1
1
/* session.c -- user windowing interface to Info.
2
$Id: session.c,v 1.45 2002/03/02 15:05:04 karl Exp $
2
$Id: session.c,v 1.16 2004/12/14 00:15:36 karl Exp $
4
Copyright (C) 1993, 96, 97, 98, 99, 2000, 01, 02
4
Copyright (C) 1993, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
5
5
Free Software Foundation, Inc.
7
7
This program is free software; you can redistribute it and/or modify
36
/* SCO 3.2v5.0.2 defines but does not correctly declare strncasecmp.
37
Since we use it as a symbol, have to get it right. --gildea, 1jul99. */
38
extern int strncasecmp (const char *, const char *, size_t);
41
static void info_clear_pending_input (), info_set_pending_input ();
42
static void info_handle_pointer ();
36
static void info_clear_pending_input (void);
37
static void info_set_pending_input (unsigned char key);
38
static void info_handle_pointer (char *label, WINDOW *window);
39
static void display_info_keyseq (int expecting_future_input);
40
char *node_printed_rep (NODE *node);
44
42
/* **************************************************************** */
66
64
/* Number of slots allocated to `info_windows'. */
67
65
static int info_windows_slots = 0;
69
void remember_window_and_node (), forget_window_and_nodes ();
70
void initialize_info_session (), info_session ();
71
void display_startup_message_and_start ();
67
void remember_window_and_node (WINDOW *window, NODE *node);
68
void forget_window_and_nodes (WINDOW *window);
69
void display_startup_message_and_start (void);
73
71
/* Begin an info session finding the nodes specified by FILENAME and NODENAMES.
74
72
For each loaded node, create a new window. Always split the largest of the
75
73
available windows. */
77
begin_multiple_window_info_session (filename, nodenames)
75
begin_multiple_window_info_session (char *filename, char **nodenames)
82
78
WINDOW *window = (WINDOW *)NULL;
155
148
/* Start an info session with INITIAL_NODE. */
157
begin_info_session (initial_node)
150
begin_info_session (NODE *initial_node)
160
152
initialize_info_session (initial_node, 1);
161
153
display_startup_message_and_start ();
165
display_startup_message_and_start ()
157
display_startup_message_and_start (void)
169
161
format = replace_in_documentation
170
(_("Welcome to Info version %s. Type \\[get-help-window] for help, \\[menu-item] for menu item."));
162
((char *) _("Welcome to Info version %s. Type \\[get-help-window] for help, \\[menu-item] for menu item."),
172
window_message_in_echo_area (format, VERSION);
165
window_message_in_echo_area (format, VERSION, NULL);
176
169
/* Run an info session with an already initialized window and node. */
180
173
display_update_display (windows);
181
174
info_last_executed_command = NULL;
242
235
if (lk == echo_area_last_command_was_kill)
243
236
echo_area_last_command_was_kill = 0;
245
if (ea_last_executed_command == ea_newline ||
238
if (ea_last_executed_command == (VFunction *) ea_newline ||
246
239
info_aborted_echo_area)
248
241
ea_last_executed_command = (VFunction *)NULL;
252
if (info_last_executed_command == info_quit)
245
if (info_last_executed_command == (VFunction *) info_quit)
253
246
quit_info_immediately = 1;
255
else if (info_last_executed_command == info_quit)
248
else if (info_last_executed_command == (VFunction *) info_quit)
260
253
/* Found in signals.c */
261
extern void initialize_info_signal_handler ();
254
extern void initialize_info_signal_handler (void );
263
256
/* Initialize the first info session by starting the terminal, window,
264
257
and display systems. If CLEAR_SCREEN is 0, don't clear the screen. */
266
initialize_info_session (node, clear_screen)
259
initialize_info_session (NODE *node, int clear_screen)
270
261
char *term_name = getenv ("TERM");
271
262
terminal_initialize_terminal (term_name);
870
847
/* Move to 1st menu item, Next, Up/Next, or error in this window. */
872
forward_move_node_structure (window, behaviour)
849
forward_move_node_structure (WINDOW *window, int behaviour)
876
851
switch (behaviour)
878
853
case IS_PageOnly:
879
info_error (msg_at_node_bottom);
854
info_error ((char *) msg_at_node_bottom, NULL, NULL);
882
857
case IS_NextOnly:
883
858
info_next_label_of_node (window->node);
884
859
if (!info_parsed_nodename && !info_parsed_filename)
885
info_error (msg_no_pointer, _("Next"));
860
info_error ((char *) msg_no_pointer, (char *) _("Next"), NULL);
888
window_message_in_echo_area (_("Following Next node..."));
863
window_message_in_echo_area ((char *) _("Following Next node..."),
889
865
info_handle_pointer ("Next", window);
1019
998
/* Move Prev, Up or error in WINDOW depending on BEHAVIOUR. */
1021
backward_move_node_structure (window, behaviour)
1000
backward_move_node_structure (WINDOW *window, int behaviour)
1025
1002
switch (behaviour)
1027
1004
case IS_PageOnly:
1028
info_error (msg_at_node_top);
1005
info_error ((char *) msg_at_node_top, NULL, NULL);
1031
1008
case IS_NextOnly:
1032
1009
info_prev_label_of_node (window->node);
1033
1010
if (!info_parsed_nodename && !info_parsed_filename)
1034
info_error (_("No `Prev' for this node."));
1011
info_error ((char *) _("No `Prev' for this node."), NULL, NULL);
1037
window_message_in_echo_area (_("Moving Prev in this window."));
1014
window_message_in_echo_area ((char *) _("Moving Prev in this window."),
1038
1016
info_handle_pointer ("Prev", window);
1143
static void _scroll_forward();
1144
static void _scroll_backward();
1125
static void _scroll_forward(WINDOW *window, int count,
1126
unsigned char key, int behaviour);
1127
static void _scroll_backward(WINDOW *window, int count,
1128
unsigned char key, int behaviour);
1147
_scroll_forward(window, count, key, behaviour)
1131
_scroll_forward(WINDOW *window, int count, unsigned char key, int behaviour)
1154
1134
_scroll_backward (window, -count, key, behaviour);
1994
1962
for (i = 0; menu[i + 1]; i++);
1997
for (i = 0; (entry = menu[i]); i++)
1965
for (i = 0; menu[i]; i++)
1998
1966
if (i == item - 1)
2003
info_select_reference (window, menu[i]);
1972
info_select_reference (window, menu[i]);
1973
if (menu[i]->line_number > 0)
1974
info_next_line (window, menu[i]->line_number - 1, key);
2005
info_error (_("There aren't %d items in this menu."), item);
1977
info_error ((char *) _("There aren't %d items in this menu."),
1978
(void *) (long) item, NULL);
2007
1980
info_free_references (menu);
1986
/* Return a pointer to the xref in XREF_LIST that is nearest to POS, or
1987
NULL if XREF_LIST is empty. That is, if POS is within any of the
1988
given xrefs, return that one. Otherwise, return the one with the
1989
nearest beginning or end. If there are two that are equidistant,
1990
prefer the one forward. The return is in newly-allocated memory,
1991
since the caller frees it.
1993
This is called from info_menu_or_ref_item with XREF_LIST being all
1994
the xrefs in the node, and POS being point. The ui function that
1995
starts it all off is select-reference-this-line.
1997
This is not the same logic as in info.el. Info-get-token prefers
1998
searching backwards to searching forwards, and has a hardwired search
1999
limit of 200 chars (in Emacs 21.2). */
2002
nearest_xref (REFERENCE **xref_list, long int pos)
2006
long best_delta = -1;
2008
for (this_xref = 0; xref_list[this_xref]; this_xref++)
2011
REFERENCE *xref = xref_list[this_xref];
2012
if (xref->start <= pos && pos <= xref->end)
2013
{ /* POS is within this xref, we're done */
2014
nearest = this_xref;
2018
/* See how far POS is from this xref. Take into account the
2019
`*Note' that begins the xref, since as far as the user is
2020
concerned, that's where it starts. */
2021
delta = MIN (labs (pos - (xref->start - strlen (INFO_XREF_LABEL))),
2022
labs (pos - xref->end));
2024
/* It's the <= instead of < that makes us choose the forward xref
2025
of POS if two are equidistant. Of course, because of all the
2026
punctuation surrounding xrefs, it's not necessarily obvious
2028
if (delta <= best_delta || best_delta < 0)
2030
nearest = this_xref;
2035
/* Maybe there was no list to search through. */
2039
/* Ok, we have a nearest xref, make a list of it. */
2041
REFERENCE **ret = xmalloc (sizeof (REFERENCE *) * 2);
2042
ret[0] = info_copy_reference (xref_list[nearest]);
2011
2049
/* Read a menu or followed reference from the user defaulting to the
2012
2050
reference found on the current line, and select that node. The
2013
2051
reading is done with completion. BUILDER is the function used
2014
2052
to build the list of references. ASK_P is non-zero if the user
2015
2053
should be prompted, or zero to select the default item. */
2017
info_menu_or_ref_item (window, count, key, builder, ask_p)
2021
REFERENCE **(*builder) ();
2055
info_menu_or_ref_item (WINDOW *window, int count,
2056
unsigned char key, REFERENCE **(*builder) (NODE *node), int ask_p)
2024
REFERENCE **menu, *entry, *defentry = (REFERENCE *)NULL;
2027
menu = (*builder) (window->node);
2060
REFERENCE *defentry = NULL;
2061
REFERENCE **menu = (*builder) (window->node);
2031
2065
if (builder == info_menu_of_node)
2032
info_error (msg_no_menu_node);
2066
info_error ((char *) msg_no_menu_node, NULL, NULL);
2034
info_error (msg_no_xref_node);
2068
info_error ((char *) msg_no_xref_node, NULL, NULL);
2038
2072
/* Default the selected reference to the one which is on the line that
2039
2073
point is in. */
2041
REFERENCE **refs = (REFERENCE **)NULL;
2044
point_line = window_line_of_point (window);
2075
REFERENCE **refs = NULL;
2076
int point_line = window_line_of_point (window);
2046
2078
if (point_line != -1)
2070
2102
refs = manpage_xrefs_in_binding (window->node, &binding);
2072
2104
#endif /* HANDLE_MAN_PAGES */
2074
refs = info_xrefs (&binding);
2075
if (!refs && point_line > 0)
2077
/* People get annoyed that Info cannot find an xref
2078
which starts on a previous line and ends on this
2079
one. So if we fail to find a reference on this
2080
line, let's try the one before. */
2082
window->line_starts[point_line - 1] - binding.buffer;
2083
refs = info_xrefs (&binding);
2105
refs = nearest_xref (menu, window->point);
2108
if (refs && refs[0])
2090
if ((strcmp (refs[0]->label, "Menu") != 0) ||
2091
(builder == info_xrefs_of_node))
2110
if (strcmp (refs[0]->label, "Menu") != 0
2111
|| builder == info_xrefs_of_node)
2095
/* Find the closest reference to point. */
2096
if (builder == info_xrefs_of_node)
2115
/* For xrefs, find the closest reference to point,
2116
unless we only have one reference (as we will if
2117
we've called nearest_xref above). It would be better
2118
to have only one piece of code, but the conditions
2119
when we call this are tangled. */
2120
if (builder == info_xrefs_of_node && refs[1])
2098
2122
int closest = -1;
2100
2124
for (; refs[which]; which++)
2102
if ((window->point >= refs[which]->start) &&
2103
(window->point <= refs[which]->end))
2126
if (window->point >= refs[which]->start
2127
&& window->point <= refs[which]->end)
2105
2129
closest = which;
2108
2132
else if (window->point < refs[which]->start)
2119
2144
defentry = (REFERENCE *)xmalloc (sizeof (REFERENCE));
2120
2145
defentry->label = xstrdup (refs[which]->label);
2121
2146
defentry->filename = refs[which]->filename;
2122
2147
defentry->nodename = refs[which]->nodename;
2148
defentry->line_number = refs[which]->line_number;
2124
2150
if (defentry->filename)
2125
2151
defentry->filename = xstrdup (defentry->filename);
2139
2165
/* Build the prompt string. */
2141
prompt = (char *)xmalloc (20 + strlen (defentry->label));
2143
prompt = (char *)xmalloc (20);
2145
2166
if (builder == info_menu_of_node)
2148
sprintf (prompt, _("Menu item (%s): "), defentry->label);
2170
prompt = xmalloc (strlen (defentry->label)
2171
+ strlen (_("Menu item (%s): ")));
2172
sprintf (prompt, _("Menu item (%s): "), defentry->label);
2150
sprintf (prompt, _("Menu item: "));
2175
prompt = xstrdup (_("Menu item: "));
2155
sprintf (prompt, _("Follow xref (%s): "), defentry->label);
2181
prompt = xmalloc (strlen (defentry->label)
2182
+ strlen (_("Follow xref (%s): ")));
2183
sprintf (prompt, _("Follow xref (%s): "), defentry->label);
2157
sprintf (prompt, _("Follow xref: "));
2186
prompt = xstrdup (_("Follow xref: "));
2160
2189
line = info_read_completing_in_echo_area (window, prompt, menu);
2628
2663
/* If we still cannot find the starting point, give up.
2629
2664
We cannot allow a NULL pointer inside info_follow_menus. */
2631
info_error (msg_cant_find_node, "Top");
2666
info_error ((char *) msg_cant_find_node, "Top", NULL);
2634
= info_follow_menus (dir_node, nodes, &errstr, &errarg1, &errarg2);
2668
node = info_follow_menus (dir_node, nodes, &errstr, &errarg1, &errarg2);
2638
2672
info_set_node_of_window (1, window, node);
2640
info_error (errstr, errarg1, errarg2);
2674
info_error ((char *) errstr, errarg1, errarg2);
3098
3124
/* **************************************************************** */
3100
3126
#define VERBOSE_NODE_DUMPING
3101
static void write_node_to_stream ();
3102
static void dump_node_to_stream ();
3103
static void initialize_dumping ();
3127
static void write_node_to_stream (NODE *node, FILE *stream);
3128
static void dump_node_to_stream (char *filename, char *nodename,
3129
FILE *stream, int dump_subnodes);
3130
static void initialize_dumping (void);
3105
3132
/* Dump the nodes specified by FILENAME and NODENAMES to the file named
3106
3133
in OUTPUT_FILENAME. If DUMP_SUBNODES is non-zero, recursively dump
3107
3134
the nodes which appear in the menu of each node dumped. */
3109
dump_nodes_to_file (filename, nodenames, output_filename, dump_subnodes)
3112
char *output_filename;
3136
dump_nodes_to_file (char *filename, char **nodenames,
3137
char *output_filename, int dump_subnodes)
3115
3139
register int i;
3116
3140
FILE *output_stream;
3877
3873
p_rep_index += strlen (rep);
3880
prompt_len = strlen (prefix) + p_rep_index + 20;
3881
prompt = (char *)xmalloc (prompt_len);
3876
prompt_len = strlen (prefix) + p_rep_index + 1;
3878
prompt_len += strlen (_("Failing "));
3879
prompt = xmalloc (prompt_len);
3882
3880
sprintf (prompt, "%s%s%s", failing_p ? _("Failing ") : "", prefix,
3883
3881
p_rep ? p_rep : "");
3885
window_message_in_echo_area ("%s", prompt);
3883
window_message_in_echo_area ("%s", prompt, NULL);
3886
3884
maybe_free (p_rep);
3888
3886
display_cursor_at_point (active_window);
3892
incremental_search (window, count, ignore)
3895
unsigned char ignore;
3890
incremental_search (WINDOW *window, int count, unsigned char ignore)
3897
3892
unsigned char key;
3898
3893
int last_search_result, search_result, dir;
3981
3983
isearch_string[isearch_string_index] = '\0';
3982
3984
goto search_now;
3984
else if (func == isearch_forward || func == isearch_backward)
3986
else if (func == (VFunction *) isearch_forward
3987
|| func == (VFunction *) isearch_backward)
3986
3989
/* If this key invokes an incremental search, then this
3987
3990
means that we will either search again in the same
3988
3991
direction, search again in the reverse direction, or
3989
3992
insert the last search string that was accepted through
3990
3993
incremental searching. */
3991
if ((func == isearch_forward && dir > 0) ||
3992
(func == isearch_backward && dir < 0))
3994
if ((func == (VFunction *) isearch_forward && dir > 0) ||
3995
(func == (VFunction *) isearch_backward && dir < 0))
3994
3997
/* If the user has typed no characters, then insert the
3995
3998
last successful search into the current search string. */
4483
dispatch_error (keyseq)
4484
dispatch_error (char *keyseq)
4488
4488
rep = pretty_keyseq (keyseq);
4490
4490
if (!echo_area_is_active)
4491
info_error (_("Unknown command (%s)."), rep);
4491
info_error ((char *) _("Unknown command (%s)."), rep, NULL);
4494
char *temp = xmalloc (1 + strlen (rep) + strlen (_("\"\" is invalid")));
4495
sprintf (temp, _("\"%s\" is invalid"), rep);
4494
char *temp = xmalloc (1 + strlen (rep) + strlen (_("\"%s\" is invalid")));
4495
sprintf (temp, _("`%s' is invalid"), rep);
4496
4496
terminal_ring_bell ();
4497
4497
inform_in_echo_area (temp);