home *** CD-ROM | disk | FTP | other *** search
/ RISC DISC 2 / RISC_DISC_2.iso / pd_share / utilities / cli / gnuinfo / Source / c / footnotes < prev    next >
Encoding:
Text File  |  1994-10-01  |  7.3 KB  |  266 lines

  1. #include "defines.h"
  2. /* footnotes.c -- Some functions for manipulating footnotes. */
  3.  
  4. /* This file is part of GNU Info, a program for reading online documentation
  5.    stored in Info format.
  6.  
  7.    Copyright (C) 1993 Free Software Foundation, Inc.
  8.  
  9.    This program is free software; you can redistribute it and/or modify
  10.    it under the terms of the GNU General Public License as published by
  11.    the Free Software Foundation; either version 2, or (at your option)
  12.    any later version.
  13.  
  14.    This program is distributed in the hope that it will be useful,
  15.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.    GNU General Public License for more details.
  18.  
  19.    You should have received a copy of the GNU General Public License
  20.    along with this program; if not, write to the Free Software
  21.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  
  23.    Written by Brian Fox (bfox@ai.mit.edu). */
  24.  
  25. #include "info.h"
  26.  
  27. /* Non-zero means attempt to show footnotes when displaying a new window. */
  28. int auto_footnotes_p = 1;
  29.  
  30. static char *footnote_nodename = "*Footnotes*";
  31.  
  32. #define FOOTNOTE_HEADER_FORMAT \
  33.    "*** Footnotes appearing in the node \"%s\" ***\n"
  34.  
  35. /* Find the window currently showing footnotes. */
  36. static WINDOW *
  37. find_footnotes_window ()
  38. {
  39.   WINDOW *win;
  40.  
  41.   /* Try to find an existing window first. */
  42.   for (win = windows; win; win = win->next)
  43.     if (internal_info_node_p (win->node) &&
  44.     (strcmp (win->node->nodename, footnote_nodename) == 0))
  45.       break;
  46.  
  47.   return (win);
  48. }
  49.  
  50. /* Manufacture a node containing the footnotes of this node, and
  51.    return the manufactured node.  If NODE has no footnotes, return a 
  52.    NULL pointer. */
  53. NODE *
  54. make_footnotes_node (node)
  55.      NODE *node;
  56. {
  57.   NODE *fn_node, *result = (NODE *)NULL;
  58.   long fn_start;
  59.  
  60.   /* Make the initial assumption that the footnotes appear as simple
  61.      text within this windows node. */
  62.   fn_node = node;
  63.  
  64.   /* See if this node contains the magic footnote label. */
  65.   fn_start =
  66.     info_search_in_node (FOOTNOTE_LABEL, node, 0, (WINDOW *)NULL, 1);
  67.  
  68.   /* If it doesn't, check to see if it has an associated footnotes node. */
  69.   if (fn_start == -1)
  70.     {
  71.       REFERENCE **refs;
  72.  
  73.       refs = info_xrefs_of_node (node);
  74.  
  75.       if (refs)
  76.     {
  77.       register int i;
  78.       char *refname;
  79.  
  80.       refname = (char *)xmalloc
  81.         (1 + strlen ("-Footnotes") + strlen (node->nodename));
  82.  
  83.       strcpy (refname, node->nodename);
  84.       strcat (refname, "-Footnotes");
  85.  
  86.       for (i = 0; refs[i]; i++)
  87.         if (strcmp (refs[i]->nodename, refname) == 0)
  88.           {
  89.         char *filename;
  90.  
  91.         filename = node->parent;
  92.         if (!filename)
  93.           filename = node->filename;
  94.  
  95.         fn_node = info_get_node (filename, refname);
  96.  
  97.         if (fn_node)
  98.           fn_start = 0;
  99.  
  100.         break;
  101.           }
  102.  
  103.       free (refname);
  104.       info_free_references (refs);
  105.     }
  106.     }
  107.  
  108.   /* If we never found the start of a footnotes area, quit now. */
  109.   if (fn_start == -1)
  110.     return ((NODE *)NULL);
  111.  
  112.   /* Make the new node. */
  113.   result = (NODE *)xmalloc (sizeof (NODE));
  114.   result->flags = 0;
  115.  
  116.   /* Get the size of the footnotes appearing within this node. */
  117.   {
  118.     char *header;
  119.     long text_start = fn_start;
  120.  
  121.     header = (char *)xmalloc
  122.       (1 + strlen (node->nodename) + strlen (FOOTNOTE_HEADER_FORMAT));
  123.     sprintf (header, FOOTNOTE_HEADER_FORMAT, node->nodename);
  124.  
  125.     /* Move the start of the displayed text to right after the first line.
  126.        This effectively skips either "---- footno...", or "File: foo...". */
  127.     while (text_start < fn_node->nodelen)
  128.       if (fn_node->contents[text_start++] == '\n')
  129.     break;
  130.   
  131.     result->nodelen = strlen (header) + fn_node->nodelen - text_start;
  132.  
  133.     /* Set the contents of this node. */
  134.     result->contents = (char *)xmalloc (1 + result->nodelen);
  135.     sprintf (result->contents, "%s", header);
  136.     memcpy (result->contents + strlen (header),
  137.         fn_node->contents + text_start, fn_node->nodelen - text_start);
  138.  
  139.     name_internal_node (result, footnote_nodename);
  140.     free (header);
  141.   }
  142.  
  143. #if defined (NOTDEF)
  144.   /* If the footnotes were gleaned from the node that we were called with,
  145.      shorten the calling node's display length. */
  146.   if (fn_node == node)
  147.     narrow_node (node, 0, fn_start);
  148. #endif /* NOTDEF */
  149.  
  150.   return (result);
  151. }
  152.  
  153. /* Create or delete the footnotes window depending on whether footnotes
  154.    exist in WINDOW's node or not.  Returns FN_FOUND if footnotes were found
  155.    and displayed.  Returns FN_UNFOUND if there were no footnotes found
  156.    in WINDOW's node.  Returns FN_UNABLE if there were footnotes, but the
  157.    window to show them couldn't be made. */
  158. int
  159. info_get_or_remove_footnotes (window)
  160.      WINDOW *window;
  161. {
  162.   WINDOW *fn_win;
  163.   NODE *new_footnotes;
  164.  
  165.   fn_win = find_footnotes_window ();
  166.  
  167.   /* If we are in the footnotes window, change nothing. */
  168.   if (fn_win == window)
  169.     return (FN_FOUND);
  170.  
  171.   /* Try to find footnotes for this window's node. */
  172.   new_footnotes = make_footnotes_node (window->node);
  173.  
  174.   /* If there was a window showing footnotes, and there are no footnotes
  175.      for the current window, delete the old footnote window. */
  176.   if (fn_win && !new_footnotes)
  177.     {
  178.       if (windows->next)
  179.     info_delete_window_internal (fn_win);
  180.     }
  181.  
  182.   /* If there are footnotes for this window's node, but no window around
  183.      showing footnotes, try to make a new window. */
  184.   if (new_footnotes && !fn_win)
  185.     {
  186.       WINDOW *old_active;
  187.       WINDOW *last, *win;
  188.  
  189.       /* Always make this window be the last one appearing in the list.  Find
  190.      the last window in the chain. */
  191.       for (win = windows, last = windows; win; last = win, win = win->next);
  192.  
  193.       /* Try to split this window, and make the split window the one to
  194.      contain the footnotes. */
  195.       old_active = active_window;
  196.       active_window = last;
  197.       fn_win = window_make_window (new_footnotes);
  198.       active_window = old_active;
  199.  
  200.       if (!fn_win)
  201.     {
  202.       free (new_footnotes->contents);
  203.       free (new_footnotes);
  204.  
  205.       /* If we are hacking automatic footnotes, and there are footnotes
  206.          but we couldn't display them, print a message to that effect. */
  207.       if (auto_footnotes_p)
  208.         inform_in_echo_area ("Footnotes could not be displayed");
  209.       return (FN_UNABLE);
  210.     }
  211.     }
  212.  
  213.   /* If there are footnotes, and there is a window to display them,
  214.      make that window be the number of lines appearing in the footnotes. */
  215.   if (new_footnotes && fn_win)
  216.     {
  217.       window_set_node_of_window (fn_win, new_footnotes);
  218.  
  219.       window_change_window_height
  220.     (fn_win, fn_win->line_count - fn_win->height);
  221.  
  222.       remember_window_and_node (fn_win, new_footnotes);
  223.       add_gcable_pointer (new_footnotes->contents);
  224.     }
  225.  
  226.   if (!new_footnotes)
  227.     return (FN_UNFOUND);
  228.   else
  229.     return (FN_FOUND);
  230. }
  231.  
  232. /* Show the footnotes associated with this node in another window. */
  233. DECLARE_INFO_COMMAND (info_show_footnotes,
  234.    "Show the footnotes associated with this node in another window")
  235. {
  236.   int result;
  237.  
  238.   /* A negative argument means just make the window go away. */
  239.   if (count < 0)
  240.     {
  241.       WINDOW *fn_win = find_footnotes_window ();
  242.  
  243.       /* If there is an old footnotes window, and it isn't the only window
  244.      on the screen, delete it. */
  245.       if (fn_win && windows->next)
  246.     info_delete_window_internal (fn_win);
  247.     }
  248.   else
  249.     {
  250.       int result;
  251.  
  252.       result = info_get_or_remove_footnotes (window);
  253.  
  254.       switch (result)
  255.     {
  256.     case FN_UNFOUND:
  257.       info_error (NO_FOOT_NODE);
  258.       break;
  259.  
  260.     case FN_UNABLE:
  261.       info_error (WIN_TOO_SMALL);
  262.       break;
  263.     }
  264.     }
  265. }
  266.