home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / OS2 / gnuinfo.zip / info / footnotes.c < prev    next >
C/C++ Source or Header  |  1997-07-24  |  8KB  |  262 lines

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