No empty .Rs/.Re
[netbsd-mini2440.git] / gnu / dist / texinfo / info / footnotes.c
blobed6fcb392dd4e96920e2f46eb76c7ef5b2ae8f93
1 /* $NetBSD$ */
3 /* footnotes.c -- Some functions for manipulating footnotes.
4 Id: footnotes.c,v 1.4 2004/04/11 17:56:45 karl Exp
6 Copyright (C) 1993, 1997, 1998, 1999, 2002, 2004 Free Software
7 Foundation, Inc.
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 Originally written by Brian Fox (bfox@ai.mit.edu). */
25 #include "info.h"
27 /* Nonzero means attempt to show footnotes when displaying a new window. */
28 int auto_footnotes_p = 0;
30 static char *footnote_nodename = "*Footnotes*";
32 NODE * make_footnotes_node (NODE *node);
34 #define FOOTNOTE_HEADER_FORMAT \
35 "*** Footnotes appearing in the node `%s' ***\n"
37 /* Find the window currently showing footnotes. */
38 static WINDOW *
39 find_footnotes_window (void)
41 WINDOW *win;
43 /* Try to find an existing window first. */
44 for (win = windows; win; win = win->next)
45 if (internal_info_node_p (win->node) &&
46 (strcmp (win->node->nodename, footnote_nodename) == 0))
47 break;
49 return (win);
52 /* Manufacture a node containing the footnotes of this node, and
53 return the manufactured node. If NODE has no footnotes, return a
54 NULL pointer. */
55 NODE *
56 make_footnotes_node (NODE *node)
58 NODE *fn_node, *result = (NODE *)NULL;
59 long fn_start;
61 /* Make the initial assumption that the footnotes appear as simple
62 text within this windows node. */
63 fn_node = node;
65 /* See if this node contains the magic footnote label. */
66 fn_start =
67 info_search_in_node (FOOTNOTE_LABEL, node, 0, (WINDOW *)NULL, 1, 0);
69 /* If it doesn't, check to see if it has an associated footnotes node. */
70 if (fn_start == -1)
72 REFERENCE **refs;
74 refs = info_xrefs_of_node (node);
76 if (refs)
78 register int i;
79 char *refname;
80 int reflen = strlen ("-Footnotes") + strlen (node->nodename);
82 refname = (char *)xmalloc (reflen + 1);
84 strcpy (refname, node->nodename);
85 strcat (refname, "-Footnotes");
87 for (i = 0; refs[i]; i++)
88 if ((refs[i]->nodename != (char *)NULL) &&
89 /* Support both the older "foo-Footnotes" and the new
90 style "foo-Footnote-NN" references. */
91 (strcmp (refs[i]->nodename, refname) == 0 ||
92 (strncmp (refs[i]->nodename, refname, reflen - 1) == 0 &&
93 refs[i]->nodename[reflen - 1] == '-' &&
94 isdigit (refs[i]->nodename[reflen]))))
96 char *filename;
98 filename = node->parent;
99 if (!filename)
100 filename = node->filename;
102 fn_node = info_get_node (filename, refname);
104 if (fn_node)
105 fn_start = 0;
107 break;
110 free (refname);
111 info_free_references (refs);
115 /* If we never found the start of a footnotes area, quit now. */
116 if (fn_start == -1)
117 return ((NODE *)NULL);
119 /* Make the new node. */
120 result = (NODE *)xmalloc (sizeof (NODE));
121 result->flags = 0;
122 result->display_pos = 0;
124 /* Get the size of the footnotes appearing within this node. */
126 char *header;
127 long text_start = fn_start;
129 header = (char *)xmalloc
130 (1 + strlen (node->nodename) + strlen (FOOTNOTE_HEADER_FORMAT));
131 sprintf (header, FOOTNOTE_HEADER_FORMAT, node->nodename);
133 /* Move the start of the displayed text to right after the first line.
134 This effectively skips either "---- footno...", or "File: foo...". */
135 while (text_start < fn_node->nodelen)
136 if (fn_node->contents[text_start++] == '\n')
137 break;
139 result->nodelen = strlen (header) + fn_node->nodelen - text_start;
141 /* Set the contents of this node. */
142 result->contents = (char *)xmalloc (1 + result->nodelen);
143 sprintf (result->contents, "%s", header);
144 memcpy (result->contents + strlen (header),
145 fn_node->contents + text_start, fn_node->nodelen - text_start);
147 name_internal_node (result, footnote_nodename);
148 free (header);
151 #if defined (NOTDEF)
152 /* If the footnotes were gleaned from the node that we were called with,
153 shorten the calling node's display length. */
154 if (fn_node == node)
155 narrow_node (node, 0, fn_start);
156 #endif /* NOTDEF */
158 return (result);
161 /* Create or delete the footnotes window depending on whether footnotes
162 exist in WINDOW's node or not. Returns FN_FOUND if footnotes were found
163 and displayed. Returns FN_UNFOUND if there were no footnotes found
164 in WINDOW's node. Returns FN_UNABLE if there were footnotes, but the
165 window to show them couldn't be made. */
167 info_get_or_remove_footnotes (WINDOW *window)
169 WINDOW *fn_win;
170 NODE *new_footnotes;
172 fn_win = find_footnotes_window ();
174 /* If we are in the footnotes window, change nothing. */
175 if (fn_win == window)
176 return (FN_FOUND);
178 /* Try to find footnotes for this window's node. */
179 new_footnotes = make_footnotes_node (window->node);
181 /* If there was a window showing footnotes, and there are no footnotes
182 for the current window, delete the old footnote window. */
183 if (fn_win && !new_footnotes)
185 if (windows->next)
186 info_delete_window_internal (fn_win);
189 /* If there are footnotes for this window's node, but no window around
190 showing footnotes, try to make a new window. */
191 if (new_footnotes && !fn_win)
193 WINDOW *old_active;
194 WINDOW *last, *win;
196 /* Always make this window be the last one appearing in the list. Find
197 the last window in the chain. */
198 for (win = windows, last = windows; win; last = win, win = win->next);
200 /* Try to split this window, and make the split window the one to
201 contain the footnotes. */
202 old_active = active_window;
203 active_window = last;
204 fn_win = window_make_window (new_footnotes);
205 active_window = old_active;
207 if (!fn_win)
209 free (new_footnotes->contents);
210 free (new_footnotes);
212 /* If we are hacking automatic footnotes, and there are footnotes
213 but we couldn't display them, print a message to that effect. */
214 if (auto_footnotes_p)
215 inform_in_echo_area ((char *) _("Footnotes could not be displayed"));
216 return (FN_UNABLE);
220 /* If there are footnotes, and there is a window to display them,
221 make that window be the number of lines appearing in the footnotes. */
222 if (new_footnotes && fn_win)
224 window_set_node_of_window (fn_win, new_footnotes);
226 window_change_window_height
227 (fn_win, fn_win->line_count - fn_win->height);
229 remember_window_and_node (fn_win, new_footnotes);
230 add_gcable_pointer (new_footnotes->contents);
233 if (!new_footnotes)
234 return (FN_UNFOUND);
235 else
236 return (FN_FOUND);
239 /* Show the footnotes associated with this node in another window. */
240 DECLARE_INFO_COMMAND (info_show_footnotes,
241 _("Show the footnotes associated with this node in another window"))
243 /* A negative argument means just make the window go away. */
244 if (count < 0)
246 WINDOW *fn_win = find_footnotes_window ();
248 /* If there is an old footnotes window, and it isn't the only window
249 on the screen, delete it. */
250 if (fn_win && windows->next)
251 info_delete_window_internal (fn_win);
253 else
255 int result;
257 result = info_get_or_remove_footnotes (window);
259 switch (result)
261 case FN_UNFOUND:
262 info_error ((char *) msg_no_foot_node, NULL, NULL);
263 break;
265 case FN_UNABLE:
266 info_error ((char *) msg_win_too_small, NULL, NULL);
267 break;