1 /* footnotes.c -- Some functions for manipulating footnotes.
2 $Id: footnotes.c,v 1.9 1999/09/25 16:10:04 karl Exp $
4 Copyright (C) 1993, 97, 98, 99 Free Software Foundation, Inc.
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)
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.
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.
20 Written by Brian Fox (bfox@ai.mit.edu). */
24 /* Non-zero means attempt to show footnotes when displaying a new window. */
25 int auto_footnotes_p = 1;
27 static char *footnote_nodename = "*Footnotes*";
29 #define FOOTNOTE_HEADER_FORMAT \
30 "*** Footnotes appearing in the node \"%s\" ***\n"
32 /* Find the window currently showing footnotes. */
34 find_footnotes_window ()
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))
47 /* Manufacture a node containing the footnotes of this node, and
48 return the manufactured node. If NODE has no footnotes, return a
51 make_footnotes_node (node)
54 NODE *fn_node, *result = (NODE *)NULL;
57 /* Make the initial assumption that the footnotes appear as simple
58 text within this windows node. */
61 /* See if this node contains the magic footnote label. */
63 info_search_in_node (FOOTNOTE_LABEL, node, 0, (WINDOW *)NULL, 1, 0);
65 /* If it doesn't, check to see if it has an associated footnotes node. */
70 refs = info_xrefs_of_node (node);
76 int reflen = strlen ("-Footnotes") + strlen (node->nodename);
78 refname = (char *)xmalloc (reflen + 1);
80 strcpy (refname, node->nodename);
81 strcat (refname, "-Footnotes");
83 for (i = 0; refs[i]; i++)
84 if ((refs[i]->nodename != (char *)NULL) &&
85 /* Support both the older "foo-Footnotes" and the new
86 style "foo-Footnote-NN" references. */
87 (strcmp (refs[i]->nodename, refname) == 0 ||
88 (strncmp (refs[i]->nodename, refname, reflen - 1) == 0 &&
89 refs[i]->nodename[reflen - 1] == '-' &&
90 isdigit (refs[i]->nodename[reflen]))))
94 filename = node->parent;
96 filename = node->filename;
98 fn_node = info_get_node (filename, refname);
107 info_free_references (refs);
111 /* If we never found the start of a footnotes area, quit now. */
113 return ((NODE *)NULL);
115 /* Make the new node. */
116 result = (NODE *)xmalloc (sizeof (NODE));
118 result->display_pos = 0;
120 /* Get the size of the footnotes appearing within this node. */
123 long text_start = fn_start;
125 header = (char *)xmalloc
126 (1 + strlen (node->nodename) + strlen (FOOTNOTE_HEADER_FORMAT));
127 sprintf (header, FOOTNOTE_HEADER_FORMAT, node->nodename);
129 /* Move the start of the displayed text to right after the first line.
130 This effectively skips either "---- footno...", or "File: foo...". */
131 while (text_start < fn_node->nodelen)
132 if (fn_node->contents[text_start++] == '\n')
135 result->nodelen = strlen (header) + fn_node->nodelen - text_start;
137 /* Set the contents of this node. */
138 result->contents = (char *)xmalloc (1 + result->nodelen);
139 sprintf (result->contents, "%s", header);
140 memcpy (result->contents + strlen (header),
141 fn_node->contents + text_start, fn_node->nodelen - text_start);
143 name_internal_node (result, footnote_nodename);
148 /* If the footnotes were gleaned from the node that we were called with,
149 shorten the calling node's display length. */
151 narrow_node (node, 0, fn_start);
157 /* Create or delete the footnotes window depending on whether footnotes
158 exist in WINDOW's node or not. Returns FN_FOUND if footnotes were found
159 and displayed. Returns FN_UNFOUND if there were no footnotes found
160 in WINDOW's node. Returns FN_UNABLE if there were footnotes, but the
161 window to show them couldn't be made. */
163 info_get_or_remove_footnotes (window)
169 fn_win = find_footnotes_window ();
171 /* If we are in the footnotes window, change nothing. */
172 if (fn_win == window)
175 /* Try to find footnotes for this window's node. */
176 new_footnotes = make_footnotes_node (window->node);
178 /* If there was a window showing footnotes, and there are no footnotes
179 for the current window, delete the old footnote window. */
180 if (fn_win && !new_footnotes)
183 info_delete_window_internal (fn_win);
186 /* If there are footnotes for this window's node, but no window around
187 showing footnotes, try to make a new window. */
188 if (new_footnotes && !fn_win)
193 /* Always make this window be the last one appearing in the list. Find
194 the last window in the chain. */
195 for (win = windows, last = windows; win; last = win, win = win->next);
197 /* Try to split this window, and make the split window the one to
198 contain the footnotes. */
199 old_active = active_window;
200 active_window = last;
201 fn_win = window_make_window (new_footnotes);
202 active_window = old_active;
206 free (new_footnotes->contents);
207 free (new_footnotes);
209 /* If we are hacking automatic footnotes, and there are footnotes
210 but we couldn't display them, print a message to that effect. */
211 if (auto_footnotes_p)
212 inform_in_echo_area (_("Footnotes could not be displayed"));
217 /* If there are footnotes, and there is a window to display them,
218 make that window be the number of lines appearing in the footnotes. */
219 if (new_footnotes && fn_win)
221 window_set_node_of_window (fn_win, new_footnotes);
223 window_change_window_height
224 (fn_win, fn_win->line_count - fn_win->height);
226 remember_window_and_node (fn_win, new_footnotes);
227 add_gcable_pointer (new_footnotes->contents);
236 /* Show the footnotes associated with this node in another window. */
237 DECLARE_INFO_COMMAND (info_show_footnotes,
238 _("Show the footnotes associated with this node in another window"))
240 /* A negative argument means just make the window go away. */
243 WINDOW *fn_win = find_footnotes_window ();
245 /* If there is an old footnotes window, and it isn't the only window
246 on the screen, delete it. */
247 if (fn_win && windows->next)
248 info_delete_window_internal (fn_win);
254 result = info_get_or_remove_footnotes (window);
259 info_error (msg_no_foot_node);
263 info_error (msg_win_too_small);