nodemenu.c (37313) | nodemenu.c (42664) |
---|---|
1/* nodemenu.c -- Produce a menu of all visited nodes. */ | 1/* nodemenu.c -- Produce a menu of all visited nodes. 2 $Id: nodemenu.c,v 1.7 1997/07/24 21:30:30 karl Exp $ |
2 | 3 |
3/* This file is part of GNU Info, a program for reading online documentation 4 stored in Info format. | 4 Copyright (C) 1993, 97 Free Software Foundation, Inc. |
5 | 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 --- 6 unchanged lines hidden (view full) --- 22 Written by Brian Fox (bfox@ai.mit.edu). */ 23 24#include "info.h" 25 26/* Return a line describing the format of a node information line. */ 27static char * 28nodemenu_format_info () 29{ | 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 --- 6 unchanged lines hidden (view full) --- 20 Written by Brian Fox (bfox@ai.mit.edu). */ 21 22#include "info.h" 23 24/* Return a line describing the format of a node information line. */ 25static char * 26nodemenu_format_info () 27{ |
30 return ("\n\ | 28 return (_("\n\ |
31* Menu:\n\ 32 (File)Node Lines Size Containing File\n\ | 29* Menu:\n\ 30 (File)Node Lines Size Containing File\n\ |
33 ---------- ----- ---- ---------------"); | 31 ---------- ----- ---- ---------------")); |
34} 35 36/* Produce a formatted line of information about NODE. Here is what we want 37 the output listing to look like: 38 39* Menu: 40 (File)Node Lines Size Containing File 41 ---------- ----- ---- --------------- 42* (emacs)Buffers:: 48 2230 /usr/gnu/info/emacs/emacs-1 43* (autoconf)Writing configure.in:: 123 58789 /usr/gnu/info/autoconf/autoconf-1 | 32} 33 34/* Produce a formatted line of information about NODE. Here is what we want 35 the output listing to look like: 36 37* Menu: 38 (File)Node Lines Size Containing File 39 ---------- ----- ---- --------------- 40* (emacs)Buffers:: 48 2230 /usr/gnu/info/emacs/emacs-1 41* (autoconf)Writing configure.in:: 123 58789 /usr/gnu/info/autoconf/autoconf-1 |
44* (dir)Top:: 40 589 /usr/gnu/info/dir | 42* (dir)Top:: 40 589 /usr/gnu/info/dir |
45*/ 46static char * 47format_node_info (node) 48 NODE *node; 49{ 50 register int i, len; 51 char *parent, *containing_file; 52 static char *line_buffer = (char *)NULL; 53 54 if (!line_buffer) 55 line_buffer = (char *)xmalloc (1000); 56 57 if (node->parent) 58 { 59 parent = filename_non_directory (node->parent); 60 if (!parent) | 43*/ 44static char * 45format_node_info (node) 46 NODE *node; 47{ 48 register int i, len; 49 char *parent, *containing_file; 50 static char *line_buffer = (char *)NULL; 51 52 if (!line_buffer) 53 line_buffer = (char *)xmalloc (1000); 54 55 if (node->parent) 56 { 57 parent = filename_non_directory (node->parent); 58 if (!parent) |
61 parent = node->parent; | 59 parent = node->parent; |
62 } 63 else 64 parent = (char *)NULL; 65 66 containing_file = node->filename; 67 68 if (!parent && !*containing_file) 69 sprintf (line_buffer, "* %s::", node->nodename); 70 else 71 { 72 char *file = (char *)NULL; 73 74 if (parent) | 60 } 61 else 62 parent = (char *)NULL; 63 64 containing_file = node->filename; 65 66 if (!parent && !*containing_file) 67 sprintf (line_buffer, "* %s::", node->nodename); 68 else 69 { 70 char *file = (char *)NULL; 71 72 if (parent) |
75 file = parent; | 73 file = parent; |
76 else | 74 else |
77 file = filename_non_directory (containing_file); | 75 file = filename_non_directory (containing_file); |
78 79 if (!file) | 76 77 if (!file) |
80 file = containing_file; | 78 file = containing_file; |
81 82 if (!*file) | 79 80 if (!*file) |
83 file = "dir"; | 81 file = "dir"; |
84 85 sprintf (line_buffer, "* (%s)%s::", file, node->nodename); 86 } 87 88 len = pad_to (36, line_buffer); 89 90 { 91 int lines = 1; 92 93 for (i = 0; i < node->nodelen; i++) 94 if (node->contents[i] == '\n') | 82 83 sprintf (line_buffer, "* (%s)%s::", file, node->nodename); 84 } 85 86 len = pad_to (36, line_buffer); 87 88 { 89 int lines = 1; 90 91 for (i = 0; i < node->nodelen; i++) 92 if (node->contents[i] == '\n') |
95 lines++; | 93 lines++; |
96 97 sprintf (line_buffer + len, "%d", lines); 98 } 99 100 len = pad_to (44, line_buffer); 101 sprintf (line_buffer + len, "%ld", node->nodelen); 102 103 if (node->filename && *(node->filename)) 104 { 105 len = pad_to (51, line_buffer); 106 sprintf (line_buffer + len, node->filename); 107 } 108 | 94 95 sprintf (line_buffer + len, "%d", lines); 96 } 97 98 len = pad_to (44, line_buffer); 99 sprintf (line_buffer + len, "%ld", node->nodelen); 100 101 if (node->filename && *(node->filename)) 102 { 103 len = pad_to (51, line_buffer); 104 sprintf (line_buffer + len, node->filename); 105 } 106 |
109 return (strdup (line_buffer)); | 107 return xstrdup (line_buffer); |
110} 111 112/* Little string comparison routine for qsort (). */ 113static int 114compare_strings (string1, string2) 115 char **string1, **string2; 116{ 117 return (strcasecmp (*string1, *string2)); --- 14 unchanged lines hidden (view full) --- 132 INFO_WINDOW *info_win; 133 NODE *node; 134 char **lines = (char **)NULL; 135 int lines_index = 0, lines_slots = 0; 136 137 if (!info_windows) 138 return ((NODE *)NULL); 139 | 108} 109 110/* Little string comparison routine for qsort (). */ 111static int 112compare_strings (string1, string2) 113 char **string1, **string2; 114{ 115 return (strcasecmp (*string1, *string2)); --- 14 unchanged lines hidden (view full) --- 130 INFO_WINDOW *info_win; 131 NODE *node; 132 char **lines = (char **)NULL; 133 int lines_index = 0, lines_slots = 0; 134 135 if (!info_windows) 136 return ((NODE *)NULL); 137 |
140 for (iw_index = 0; info_win = info_windows[iw_index]; iw_index++) | 138 for (iw_index = 0; (info_win = info_windows[iw_index]); iw_index++) |
141 { 142 for (i = 0; i < info_win->nodes_index; i++) | 139 { 140 for (i = 0; i < info_win->nodes_index; i++) |
143 { 144 node = info_win->nodes[i]; | 141 { 142 node = info_win->nodes[i]; |
145 | 143 |
146 /* We skip mentioning "*Node Menu*" nodes. */ 147 if (internal_info_node_p (node) && 148 (strcmp (node->nodename, nodemenu_nodename) == 0)) 149 continue; | 144 /* We skip mentioning "*Node Menu*" nodes. */ 145 if (internal_info_node_p (node) && 146 (strcmp (node->nodename, nodemenu_nodename) == 0)) 147 continue; |
150 | 148 |
151 if (node && (!filter_func || (*filter_func) (node))) 152 { 153 char *line; | 149 if (node && (!filter_func || (*filter_func) (node))) 150 { 151 char *line; |
154 | 152 |
155 line = format_node_info (node); 156 add_pointer_to_array 157 (line, lines_index, lines, lines_slots, 20, char *); 158 } 159 } | 153 line = format_node_info (node); 154 add_pointer_to_array 155 (line, lines_index, lines, lines_slots, 20, char *); 156 } 157 } |
160 } 161 162 /* Sort the array of information lines, if there are any. */ 163 if (lines) 164 { 165 register int j, newlen; 166 char **temp; 167 168 qsort (lines, lines_index, sizeof (char *), compare_strings); 169 170 /* Delete duplicates. */ 171 for (i = 0, newlen = 1; i < lines_index - 1; i++) | 158 } 159 160 /* Sort the array of information lines, if there are any. */ 161 if (lines) 162 { 163 register int j, newlen; 164 char **temp; 165 166 qsort (lines, lines_index, sizeof (char *), compare_strings); 167 168 /* Delete duplicates. */ 169 for (i = 0, newlen = 1; i < lines_index - 1; i++) |
172 { 173 if (strcmp (lines[i], lines[i + 1]) == 0) 174 { 175 free (lines[i]); 176 lines[i] = (char *)NULL; 177 } 178 else 179 newlen++; 180 } | 170 { 171 if (strcmp (lines[i], lines[i + 1]) == 0) 172 { 173 free (lines[i]); 174 lines[i] = (char *)NULL; 175 } 176 else 177 newlen++; 178 } |
181 182 /* We have free ()'d and marked all of the duplicate slots. | 179 180 /* We have free ()'d and marked all of the duplicate slots. |
183 Copy the live slots rather than pruning the dead slots. */ | 181 Copy the live slots rather than pruning the dead slots. */ |
184 temp = (char **)xmalloc ((1 + newlen) * sizeof (char *)); 185 for (i = 0, j = 0; i < lines_index; i++) | 182 temp = (char **)xmalloc ((1 + newlen) * sizeof (char *)); 183 for (i = 0, j = 0; i < lines_index; i++) |
186 if (lines[i]) 187 temp[j++] = lines[i]; | 184 if (lines[i]) 185 temp[j++] = lines[i]; |
188 189 temp[j] = (char *)NULL; 190 free (lines); 191 lines = temp; 192 lines_index = newlen; 193 } 194 195 initialize_message_buffer (); 196 197 printf_to_message_buffer 198 ("%s", replace_in_documentation | 186 187 temp[j] = (char *)NULL; 188 free (lines); 189 lines = temp; 190 lines_index = newlen; 191 } 192 193 initialize_message_buffer (); 194 195 printf_to_message_buffer 196 ("%s", replace_in_documentation |
199 ("Here is the menu of nodes you have recently visited.\n\ 200Select one from this menu, or use `\\[history-node]' in another window.\n")); | 197 (_("Here is the menu of nodes you have recently visited.\n\ 198Select one from this menu, or use `\\[history-node]' in another window.\n"))); |
201 202 printf_to_message_buffer ("%s\n", nodemenu_format_info ()); 203 204 for (i = 0; (lines != (char **)NULL) && (i < lines_index); i++) 205 { 206 printf_to_message_buffer ("%s\n", lines[i]); 207 free (lines[i]); 208 } 209 210 if (lines) 211 free (lines); 212 213 node = message_buffer_to_node (); 214 add_gcable_pointer (node->contents); 215 return (node); 216} 217 218DECLARE_INFO_COMMAND (list_visited_nodes, | 199 200 printf_to_message_buffer ("%s\n", nodemenu_format_info ()); 201 202 for (i = 0; (lines != (char **)NULL) && (i < lines_index); i++) 203 { 204 printf_to_message_buffer ("%s\n", lines[i]); 205 free (lines[i]); 206 } 207 208 if (lines) 209 free (lines); 210 211 node = message_buffer_to_node (); 212 add_gcable_pointer (node->contents); 213 return (node); 214} 215 216DECLARE_INFO_COMMAND (list_visited_nodes, |
219 "Make a window containing a menu of all of the currently visited nodes") | 217 _("Make a window containing a menu of all of the currently visited nodes")) |
220{ 221 WINDOW *new; 222 NODE *node; 223 224 set_remembered_pagetop_and_point (window); 225 226 /* If a window is visible and showing the buffer list already, re-use it. */ 227 for (new = windows; new; new = new->next) 228 { 229 node = new->node; 230 231 if (internal_info_node_p (node) && | 218{ 219 WINDOW *new; 220 NODE *node; 221 222 set_remembered_pagetop_and_point (window); 223 224 /* If a window is visible and showing the buffer list already, re-use it. */ 225 for (new = windows; new; new = new->next) 226 { 227 node = new->node; 228 229 if (internal_info_node_p (node) && |
232 (strcmp (node->nodename, nodemenu_nodename) == 0)) 233 break; | 230 (strcmp (node->nodename, nodemenu_nodename) == 0)) 231 break; |
234 } 235 236 /* If we couldn't find an existing window, try to use the next window 237 in the chain. */ | 232 } 233 234 /* If we couldn't find an existing window, try to use the next window 235 in the chain. */ |
238 if (!new && window->next) 239 new = window->next; | 236 if (!new) 237 { 238 if (window->next) 239 new = window->next; 240 /* If there is more than one window, wrap around. */ 241 else if (window != windows) 242 new = windows; 243 } |
240 241 /* If we still don't have a window, make a new one to contain the list. */ 242 if (!new) 243 { 244 WINDOW *old_active; 245 246 old_active = active_window; 247 active_window = window; --- 5 unchanged lines hidden (view full) --- 253 if (!new) 254 new = window; 255 256 /* Lines do not wrap in this window. */ 257 new->flags |= W_NoWrap; 258 node = get_visited_nodes ((Function *)NULL); 259 name_internal_node (node, nodemenu_nodename); 260 | 244 245 /* If we still don't have a window, make a new one to contain the list. */ 246 if (!new) 247 { 248 WINDOW *old_active; 249 250 old_active = active_window; 251 active_window = window; --- 5 unchanged lines hidden (view full) --- 257 if (!new) 258 new = window; 259 260 /* Lines do not wrap in this window. */ 261 new->flags |= W_NoWrap; 262 node = get_visited_nodes ((Function *)NULL); 263 name_internal_node (node, nodemenu_nodename); 264 |
265#if 0 |
|
261 /* Even if this is an internal node, we don't want the window 262 system to treat it specially. So we turn off the internalness 263 of it here. */ | 266 /* Even if this is an internal node, we don't want the window 267 system to treat it specially. So we turn off the internalness 268 of it here. */ |
269 /* Why? We depend on internal_info_node_p returning true, so we must 270 not remove the flag. Otherwise, the *Node Menu* nodes themselves 271 appear in the node menu. --Andreas Schwab 272 <schwab@issan.informatik.uni-dortmund.de>. */ |
|
264 node->flags &= ~N_IsInternal; | 273 node->flags &= ~N_IsInternal; |
274#endif |
|
265 266 /* If this window is already showing a node menu, reuse the existing node 267 slot. */ 268 { 269 int remember_me = 1; 270 271#if defined (NOTDEF) 272 if (internal_info_node_p (new->node) && | 275 276 /* If this window is already showing a node menu, reuse the existing node 277 slot. */ 278 { 279 int remember_me = 1; 280 281#if defined (NOTDEF) 282 if (internal_info_node_p (new->node) && |
273 (strcmp (new->node->nodename, nodemenu_nodename) == 0)) | 283 (strcmp (new->node->nodename, nodemenu_nodename) == 0)) |
274 remember_me = 0; 275#endif /* NOTDEF */ 276 277 window_set_node_of_window (new, node); 278 279 if (remember_me) 280 remember_window_and_node (new, node); 281 } 282 283 active_window = new; 284} 285 286DECLARE_INFO_COMMAND (select_visited_node, | 284 remember_me = 0; 285#endif /* NOTDEF */ 286 287 window_set_node_of_window (new, node); 288 289 if (remember_me) 290 remember_window_and_node (new, node); 291 } 292 293 active_window = new; 294} 295 296DECLARE_INFO_COMMAND (select_visited_node, |
287 "Select a node which has been previously visited in a visible window") | 297 _("Select a node which has been previously visited in a visible window")) |
288{ 289 char *line; 290 NODE *node; 291 REFERENCE **menu; 292 293 node = get_visited_nodes ((Function *)NULL); 294 295 menu = info_menu_of_node (node); 296 free (node); 297 298 line = | 298{ 299 char *line; 300 NODE *node; 301 REFERENCE **menu; 302 303 node = get_visited_nodes ((Function *)NULL); 304 305 menu = info_menu_of_node (node); 306 free (node); 307 308 line = |
299 info_read_completing_in_echo_area (window, "Select visited node: ", menu); | 309 info_read_completing_in_echo_area (window, _("Select visited node: "), menu); |
300 301 window = active_window; 302 303 /* User aborts, just quit. */ 304 if (!line) 305 { 306 info_abort_key (window, 0, 0); 307 info_free_references (menu); 308 return; 309 } 310 311 if (*line) 312 { 313 REFERENCE *entry; 314 315 /* Find the selected label in the references. */ 316 entry = info_get_labeled_reference (line, menu); 317 318 if (!entry) | 310 311 window = active_window; 312 313 /* User aborts, just quit. */ 314 if (!line) 315 { 316 info_abort_key (window, 0, 0); 317 info_free_references (menu); 318 return; 319 } 320 321 if (*line) 322 { 323 REFERENCE *entry; 324 325 /* Find the selected label in the references. */ 326 entry = info_get_labeled_reference (line, menu); 327 328 if (!entry) |
319 info_error ("The reference disappeared! (%s).", line); | 329 info_error (_("The reference disappeared! (%s)."), line); |
320 else | 330 else |
321 info_select_reference (window, entry); | 331 info_select_reference (window, entry); |
322 } 323 324 free (line); 325 info_free_references (menu); 326 327 if (!info_error_was_printed) 328 window_clear_echo_area (); 329} | 332 } 333 334 free (line); 335 info_free_references (menu); 336 337 if (!info_error_was_printed) 338 window_clear_echo_area (); 339} |