comparison info/footnotes.c @ 171:d6fae6ef3e60

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