]>
git.ipfire.org Git - thirdparty/gcc.git/blob - texinfo/info/nodemenu.c
1 /* nodemenu.c -- Produce a menu of all visited nodes. */
3 /* This file is part of GNU Info, a program for reading online documentation
6 Copyright (C) 1993 Free Software Foundation, Inc.
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)
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 Written by Brian Fox (bfox@ai.mit.edu). */
26 /* Return a line describing the format of a node information line. */
28 nodemenu_format_info ()
32 (File)Node Lines Size Containing File\n\
33 ---------- ----- ---- ---------------");
36 /* Produce a formatted line of information about NODE. Here is what we want
37 the output listing to look like:
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
44 * (dir)Top:: 40 589 /usr/gnu/info/dir
47 format_node_info (node
)
51 char *parent
, *containing_file
;
52 static char *line_buffer
= (char *)NULL
;
55 line_buffer
= (char *)xmalloc (1000);
59 parent
= filename_non_directory (node
->parent
);
61 parent
= node
->parent
;
64 parent
= (char *)NULL
;
66 containing_file
= node
->filename
;
68 if (!parent
&& !*containing_file
)
69 sprintf (line_buffer
, "* %s::", node
->nodename
);
72 char *file
= (char *)NULL
;
77 file
= filename_non_directory (containing_file
);
80 file
= containing_file
;
85 sprintf (line_buffer
, "* (%s)%s::", file
, node
->nodename
);
88 len
= pad_to (36, line_buffer
);
93 for (i
= 0; i
< node
->nodelen
; i
++)
94 if (node
->contents
[i
] == '\n')
97 sprintf (line_buffer
+ len
, "%d", lines
);
100 len
= pad_to (44, line_buffer
);
101 sprintf (line_buffer
+ len
, "%d", node
->nodelen
);
103 if (node
->filename
&& *(node
->filename
))
105 len
= pad_to (51, line_buffer
);
106 sprintf (line_buffer
+ len
, node
->filename
);
109 return (strdup (line_buffer
));
112 /* Little string comparison routine for qsort (). */
114 compare_strings (string1
, string2
)
115 char **string1
, **string2
;
117 return (strcasecmp (*string1
, *string2
));
120 /* The name of the nodemenu node. */
121 static char *nodemenu_nodename
= "*Node Menu*";
123 /* Produce an informative listing of all the visited nodes, and return it
124 in a node. If FILTER_FUNC is non-null, it is a function which filters
125 which nodes will appear in the listing. FILTER_FUNC takes an argument
126 of NODE, and returns non-zero if the node should appear in the listing. */
128 get_visited_nodes (filter_func
)
129 Function
*filter_func
;
131 register int i
, iw_index
;
132 INFO_WINDOW
*info_win
;
134 char **lines
= (char **)NULL
;
135 int lines_index
= 0, lines_slots
= 0;
138 return ((NODE
*)NULL
);
140 for (iw_index
= 0; info_win
= info_windows
[iw_index
]; iw_index
++)
142 for (i
= 0; i
< info_win
->nodes_index
; i
++)
144 node
= info_win
->nodes
[i
];
146 /* We skip mentioning "*Node Menu*" nodes. */
147 if (internal_info_node_p (node
) &&
148 (strcmp (node
->nodename
, nodemenu_nodename
) == 0))
151 if (node
&& (!filter_func
|| (*filter_func
) (node
)))
155 line
= format_node_info (node
);
157 (line
, lines_index
, lines
, lines_slots
, 20, char *);
162 /* Sort the array of information lines, if there are any. */
165 register int j
, newlen
;
168 qsort (lines
, lines_index
, sizeof (char *), compare_strings
);
170 /* Delete duplicates. */
171 for (i
= 0, newlen
= 1; i
< lines_index
- 1; i
++)
173 if (strcmp (lines
[i
], lines
[i
+ 1]) == 0)
176 lines
[i
] = (char *)NULL
;
182 /* We have free ()'d and marked all of the duplicate slots.
183 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
++)
187 temp
[j
++] = lines
[i
];
189 temp
[j
] = (char *)NULL
;
192 lines_index
= newlen
;
195 initialize_message_buffer ();
197 printf_to_message_buffer
198 ("%s", replace_in_documentation
199 ("Here is the menu of nodes you have recently visited.\n\
200 Select one from this menu, or use `\\[history-node]' in another window.\n"));
202 printf_to_message_buffer ("%s\n", nodemenu_format_info ());
204 for (i
= 0; (lines
!= (char **)NULL
) && (i
< lines_index
); i
++)
206 printf_to_message_buffer ("%s\n", lines
[i
]);
213 node
= message_buffer_to_node ();
214 add_gcable_pointer (node
->contents
);
218 DECLARE_INFO_COMMAND (list_visited_nodes
,
219 "Make a window containing a menu of all of the currently visited nodes")
224 set_remembered_pagetop_and_point (window
);
226 /* If a window is visible and showing the buffer list already, re-use it. */
227 for (new = windows
; new; new = new->next
)
231 if (internal_info_node_p (node
) &&
232 (strcmp (node
->nodename
, nodemenu_nodename
) == 0))
236 /* If we couldn't find an existing window, try to use the next window
238 if (!new && window
->next
)
241 /* If we still don't have a window, make a new one to contain the list. */
246 old_active
= active_window
;
247 active_window
= window
;
248 new = window_make_window ((NODE
*)NULL
);
249 active_window
= old_active
;
252 /* If we couldn't make a new window, use this one. */
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
);
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
264 node
->flags
&= ~N_IsInternal
;
266 /* If this window is already showing a node menu, reuse the existing node
272 if (internal_info_node_p (new->node
) &&
273 (strcmp (new->node
->nodename
, nodemenu_nodename
) == 0))
277 window_set_node_of_window (new, node
);
280 remember_window_and_node (new, node
);
286 DECLARE_INFO_COMMAND (select_visited_node
,
287 "Select a node which has been previously visited in a visible window")
293 node
= get_visited_nodes ((Function
*)NULL
);
295 menu
= info_menu_of_node (node
);
299 info_read_completing_in_echo_area (window
, "Select visited node: ", menu
);
301 window
= active_window
;
303 /* User aborts, just quit. */
306 info_abort_key (window
, 0, 0);
307 info_free_references (menu
);
315 /* Find the selected label in the references. */
316 entry
= info_get_labeled_reference (line
, menu
);
319 info_error ("The reference disappeared! (%s).", line
);
321 info_select_reference (window
, entry
);
325 info_free_references (menu
);
327 if (!info_error_was_printed
)
328 window_clear_echo_area ();