1/* $NetBSD: footnotes.c,v 1.1.1.1 2016/01/14 00:11:29 christos Exp $ */ 2 3/* footnotes.c -- Some functions for manipulating footnotes. 4 Id: footnotes.c,v 1.4 2004/04/11 17:56:45 karl Exp 5 6 Copyright (C) 1993, 1997, 1998, 1999, 2002, 2004 Free Software 7 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 22 23 Originally written by Brian Fox (bfox@ai.mit.edu). */ 24 25#include "info.h" 26 27/* Nonzero means attempt to show footnotes when displaying a new window. */ 28int auto_footnotes_p = 0; 29 30static char *footnote_nodename = "*Footnotes*"; 31 32NODE * make_footnotes_node (NODE *node); 33 34#define FOOTNOTE_HEADER_FORMAT \ 35 "*** Footnotes appearing in the node `%s' ***\n" 36 37/* Find the window currently showing footnotes. */ 38static WINDOW * 39find_footnotes_window (void) 40{ 41 WINDOW *win; 42 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; 48 49 return (win); 50} 51 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. */ 55NODE * 56make_footnotes_node (NODE *node) 57{ 58 NODE *fn_node, *result = (NODE *)NULL; 59 long fn_start; 60 61 /* Make the initial assumption that the footnotes appear as simple 62 text within this windows node. */ 63 fn_node = node; 64 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); 68 69 /* If it doesn't, check to see if it has an associated footnotes node. */ 70 if (fn_start == -1) 71 { 72 REFERENCE **refs; 73 74 refs = info_xrefs_of_node (node); 75 76 if (refs) 77 { 78 register int i; 79 char *refname; 80 int reflen = strlen ("-Footnotes") + strlen (node->nodename); 81 82 refname = (char *)xmalloc (reflen + 1); 83 84 strcpy (refname, node->nodename); 85 strcat (refname, "-Footnotes"); 86 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])))) 95 { 96 char *filename; 97 98 filename = node->parent; 99 if (!filename) 100 filename = node->filename; 101 102 fn_node = info_get_node (filename, refname); 103 104 if (fn_node) 105 fn_start = 0; 106 107 break; 108 } 109 110 free (refname); 111 info_free_references (refs); 112 } 113 } 114 115 /* If we never found the start of a footnotes area, quit now. */ 116 if (fn_start == -1) 117 return ((NODE *)NULL); 118 119 /* Make the new node. */ 120 result = (NODE *)xmalloc (sizeof (NODE)); 121 result->flags = 0; 122 result->display_pos = 0; 123 124 /* Get the size of the footnotes appearing within this node. */ 125 { 126 char *header; 127 long text_start = fn_start; 128 129 header = (char *)xmalloc 130 (1 + strlen (node->nodename) + strlen (FOOTNOTE_HEADER_FORMAT)); 131 sprintf (header, FOOTNOTE_HEADER_FORMAT, node->nodename); 132 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; 138 139 result->nodelen = strlen (header) + fn_node->nodelen - text_start; 140 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); 146 147 name_internal_node (result, footnote_nodename); 148 free (header); 149 } 150 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 */ 157 158 return (result); 159} 160 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. */ 166int 167info_get_or_remove_footnotes (WINDOW *window) 168{ 169 WINDOW *fn_win; 170 NODE *new_footnotes; 171 172 fn_win = find_footnotes_window (); 173 174 /* If we are in the footnotes window, change nothing. */ 175 if (fn_win == window) 176 return (FN_FOUND); 177 178 /* Try to find footnotes for this window's node. */ 179 new_footnotes = make_footnotes_node (window->node); 180 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) 184 { 185 if (windows->next) 186 info_delete_window_internal (fn_win); 187 } 188 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) 192 { 193 WINDOW *old_active; 194 WINDOW *last, *win; 195 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); 199 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; 206 207 if (!fn_win) 208 { 209 free (new_footnotes->contents); 210 free (new_footnotes); 211 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); 217 } 218 } 219 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) 223 { 224 window_set_node_of_window (fn_win, new_footnotes); 225 226 window_change_window_height 227 (fn_win, fn_win->line_count - fn_win->height); 228 229 remember_window_and_node (fn_win, new_footnotes); 230 add_gcable_pointer (new_footnotes->contents); 231 } 232 233 if (!new_footnotes) 234 return (FN_UNFOUND); 235 else 236 return (FN_FOUND); 237} 238 239/* Show the footnotes associated with this node in another window. */ 240DECLARE_INFO_COMMAND (info_show_footnotes, 241 _("Show the footnotes associated with this node in another window")) 242{ 243 /* A negative argument means just make the window go away. */ 244 if (count < 0) 245 { 246 WINDOW *fn_win = find_footnotes_window (); 247 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); 252 } 253 else 254 { 255 int result; 256 257 result = info_get_or_remove_footnotes (window); 258 259 switch (result) 260 { 261 case FN_UNFOUND: 262 info_error ((char *) msg_no_foot_node, NULL, NULL); 263 break; 264 265 case FN_UNABLE: 266 info_error ((char *) msg_win_too_small, NULL, NULL); 267 break; 268 } 269 } 270} 271