commit 2c28487caaccff33c520215bb78541314f4f5b97 Author: Gavin Smith Date: Sun Mar 9 17:17:17 2014 +0000 * echo-area.c (info_read_completing_internal) New argument exclude_func. All callers changed. (completion_exclude_func): New variable. (info_read_completing_in_echo_area_with_exclusions): New function. * footnotes.c (make_footnotes_node) * indices.c (info_indices_of_file_buffer, select_visited_node) (apropos_in_all_indices) * nodemenu.c (select_visited_node) * session.c (forward_move_node_structure, backward_move_node_structure) (info_next_node, info_prev_node, info_up_node, select_menu_digit) (info_menu_digit, info_menu_or_ref_item, info_visit_menu, info_follow_menus) (entry_in_menu, info_intuit_options_mode, info_select_reference_this_line) (info_move_to_xref, dump_node_to_stream): Use node reference list from NODE.references instead of scanning text of node using functions that were in info-utils.c. Use NODE.up, NODE.next, NODE.prev instead of scanning node. (info_handle_pointer, info_goto_description): info_goto_description split out from info_handle_pointer. Do not assume anything about WINDOW->node now. Special handling of man pages removed. (kill_node): Copy whole NODE structure at once rather than field by field. (info_menu_or_ref_item): Arguments changed. All callers updated. (last_node_p): Function deleted. diff --git a/echo-area.c b/echo-area.c index 2ce170b..6a47e90 100644 --- a/echo-area.c +++ b/echo-area.c @@ -777,8 +777,12 @@ static size_t completions_found_slots = 0; /* The lowest common denominator found while completing. */ static REFERENCE *LCD_completion; +/* Function to choose which references to offer as completion options. */ +static reference_bool_fn completion_exclude_func = 0; + /* Internal functions used by the user calls. */ -static void build_completions (void), completions_must_be_rebuilt (void); +static void build_completions (void); +static void completions_must_be_rebuilt (void); /* Variable which holds the output of completions. */ static NODE *possible_completions_output_node = NULL; @@ -799,10 +803,11 @@ completions_window_p (WINDOW *window) } /* Workhorse for completion readers. If FORCE is non-zero, the user cannot - exit unless the line read completes, or is empty. */ + exit unless the line read completes, or is empty. Use EXCLUDE_FUNC to + exclude items in COMPLETIONS. */ char * info_read_completing_internal (WINDOW *window, const char *prompt, - REFERENCE **completions, int force) + REFERENCE **completions, int force, reference_bool_fn exclude_func) { char *line; @@ -825,6 +830,7 @@ info_read_completing_internal (WINDOW *window, const char *prompt, /* Save away the list of items to complete over. */ echo_area_completion_items = completions; completions_must_be_rebuilt (); + completion_exclude_func = exclude_func; active_window = the_echo_area; echo_area_is_active++; @@ -899,7 +905,7 @@ char * info_read_completing_in_echo_area (WINDOW *window, const char *prompt, REFERENCE **completions) { - return info_read_completing_internal (window, prompt, completions, 1); + return info_read_completing_internal (window, prompt, completions, 1, 0); } /* Read a line in the echo area allowing completion over COMPLETIONS, but @@ -908,7 +914,17 @@ char * info_read_maybe_completing (WINDOW *window, const char *prompt, REFERENCE **completions) { - return info_read_completing_internal (window, prompt, completions, 0); + return info_read_completing_internal (window, prompt, completions, 0, 0); +} + +/* Read a line in the echo area with completion over COMPLETIONS, using + EXCLUDE to exclude items from the completion list. */ +char * +info_read_completing_in_echo_area_with_exclusions (WINDOW *window, + const char *prompt, REFERENCE **completions, reference_bool_fn exclude) +{ + return info_read_completing_internal + (window, prompt, completions, 1, exclude); } DECLARE_INFO_COMMAND (ea_possible_completions, _("List possible completions")) @@ -1217,6 +1233,11 @@ build_completions (void) for (i = 0; (entry = echo_area_completion_items[i]); i++) { + /* Skip certain items (for example, we might only want + a list of menu items). */ + if (completion_exclude_func && completion_exclude_func (entry)) + continue; + if (mbsncasecmp (request, entry->label, len) == 0) add_pointer_to_array (entry, completions_found_index, completions_found, completions_found_slots, diff --git a/echo-area.h b/echo-area.h index 132e1b2..eb16f26 100644 --- a/echo-area.h +++ b/echo-area.h @@ -34,8 +34,11 @@ extern void inform_in_echo_area (const char *message); extern void echo_area_inform_of_deleted_window (WINDOW *window); extern void echo_area_prep_read (void); extern VFunction *ea_last_executed_command; + +typedef int (*reference_bool_fn) (REFERENCE *); + extern char * info_read_completing_internal (WINDOW *window, const char *prompt, - REFERENCE **completions, int force); + REFERENCE **completions, int force, reference_bool_fn exclude); /* Read a line of text in the echo area. Return a malloc ()'ed string, or NULL if the user aborted out of this read. WINDOW is the currently @@ -54,6 +57,12 @@ char *info_read_completing_in_echo_area (WINDOW *window, extern char *info_read_maybe_completing (WINDOW *window, const char *prompt, REFERENCE **completions); +/* Read a line in the echo area with completion over COMPLETIONS, using + EXCLUDE to exclude items from the completion list. */ +char * +info_read_completing_in_echo_area_with_exclusions (WINDOW *window, + const char *prompt, REFERENCE **completions, reference_bool_fn exclude); + extern void ea_insert (WINDOW *window, int count, unsigned char key); extern void ea_quoted_insert (WINDOW *window, int count, unsigned char key); extern void ea_beg_of_line (WINDOW *window, int count, unsigned char key); diff --git a/footnotes.c b/footnotes.c index 451177b..113bb95 100644 --- a/footnotes.c +++ b/footnotes.c @@ -67,7 +67,7 @@ make_footnotes_node (NODE *node) { REFERENCE **refs; - refs = info_xrefs_of_node (node); + refs = node->references; if (refs) { @@ -81,10 +81,11 @@ make_footnotes_node (NODE *node) strcat (refname, "-Footnotes"); for (i = 0; refs[i]; i++) - if ((refs[i]->nodename != NULL) && + if (refs[i]->type == REFERENCE_XREF + && (refs[i]->nodename != NULL) /* Support both the older "foo-Footnotes" and the new style "foo-Footnote-NN" references. */ - (strcmp (refs[i]->nodename, refname) == 0 || + && (strcmp (refs[i]->nodename, refname) == 0 || (strncmp (refs[i]->nodename, refname, reflen - 1) == 0 && refs[i]->nodename[reflen - 1] == '-' && isdigit (refs[i]->nodename[reflen])))) @@ -104,7 +105,6 @@ make_footnotes_node (NODE *node) } free (refname); - info_free_references (refs); } } diff --git a/indices.c b/indices.c index 1bb3ea1..4e61a59 100644 --- a/indices.c +++ b/indices.c @@ -146,11 +146,11 @@ info_indices_of_file_buffer (FILE_BUFFER *file_buffer) initial_index_filename = xstrdup (file_buffer->filename); initial_index_nodename = xstrdup (tag->nodename); - menu = info_menu_of_node (node); + menu = node->references; - /* If we have a menu, add this index's nodename and range - to our list of index_nodenames. */ - if (menu) + /* If we have a non-empty menu, add this index's nodename + and range to our list of index_nodenames. */ + if (menu && menu[0]) { add_index_to_index_nodenames (menu, node); @@ -541,8 +541,12 @@ apropos_in_all_indices (char *search_string, int inform) NODE *dir_node; dir_node = info_get_node ("dir", "Top", PARSE_NODE_DFLT); + + /* It should be safe to assume that dir nodes do not contain any + cross-references, i.e., its references list only contains + menu items. */ if (dir_node) - dir_menu = info_menu_of_node (dir_node); + dir_menu = dir_node->references; if (!dir_menu) return NULL; @@ -629,8 +633,6 @@ apropos_in_all_indices (char *search_string, int inform) } } - info_free_references (dir_menu); - /* Build a list of the references which contain SEARCH_STRING. */ if (all_indices) { diff --git a/nodemenu.c b/nodemenu.c index df0fb66..452fa55 100644 --- a/nodemenu.c +++ b/nodemenu.c @@ -305,7 +305,7 @@ DECLARE_INFO_COMMAND (select_visited_node, node = get_visited_nodes (NULL); - menu = info_menu_of_node (node); + menu = node->references; free (node); line = diff --git a/session.c b/session.c index 7661d01..83af1d1 100644 --- a/session.c +++ b/session.c @@ -40,10 +40,13 @@ static void info_clear_pending_input (void); static void info_set_pending_input (unsigned char key); +static int info_goto_description (char *description, WINDOW *window); static void info_handle_pointer (char *label, WINDOW *window); static void display_info_keyseq (int expecting_future_input); char *node_printed_rep (NODE *node); +static REFERENCE *select_menu_digit (WINDOW *window, unsigned char key); + /* **************************************************************** */ /* */ /* Running an Info Session */ @@ -1127,18 +1130,6 @@ int default_scroll_size = -1; /* meaning half screen size */ (info_parsed_nodename || (info_parsed_filename \ && !is_dir_name (info_parsed_filename))) -static int -last_node_p (NODE *node) -{ - info_next_label_of_node (node); - if (!INFO_LABEL_FOUND ()) - { - info_up_label_of_node (node); - return !INFO_LABEL_FOUND () || strcmp (info_parsed_nodename, "Top") == 0; - } - return 0; -} - /* Move to 1st menu item, Next, Up/Next, or error in this window. */ static int forward_move_node_structure (WINDOW *window, int behaviour) @@ -1150,8 +1141,7 @@ forward_move_node_structure (WINDOW *window, int behaviour) return 1; case IS_NextOnly: - info_next_label_of_node (window->node); - if (!info_parsed_nodename && !info_parsed_filename) + if (!window->node->next) { info_error (msg_no_pointer, _("Next")); return 1; @@ -1164,7 +1154,9 @@ forward_move_node_structure (WINDOW *window, int behaviour) case IS_Continuous: { - if (last_node_p (window->node)) + /* If last node in file */ + if (!window->node->next && + !(window->node->up && strcmp ("Top", window->node->up))) { switch (scroll_last_node) { @@ -1184,25 +1176,22 @@ forward_move_node_structure (WINDOW *window, int behaviour) } } - /* First things first. If this node contains a menu, move down - into the menu. */ + /* If this node contains a menu, select its first entry. */ { - REFERENCE **menu; + REFERENCE *entry; - menu = info_menu_of_node (window->node); - - if (menu) - { - info_free_references (menu); - info_menu_digit (window, 1, '1'); - return 0; - } + if (entry = select_menu_digit (window, '1')) + { + info_select_reference (window, entry); + if (entry->line_number > 0) + internal_next_line (window, entry->line_number - 1, '1'); + return 0; + } } /* Okay, this node does not contain a menu. If it contains a "Next:" pointer, use that. */ - info_next_label_of_node (window->node); - if (INFO_LABEL_FOUND ()) + if (window->node->next) { info_handle_pointer ("Next", window); return 0; @@ -1224,8 +1213,7 @@ forward_move_node_structure (WINDOW *window, int behaviour) up_counter = 0; while (!info_error_was_printed) { - info_up_label_of_node (window->node); - if (INFO_LABEL_FOUND ()) + if (window->node->up) { info_handle_pointer ("Up", window); if (info_error_was_printed) @@ -1233,41 +1221,20 @@ forward_move_node_structure (WINDOW *window, int behaviour) up_counter++; - info_next_label_of_node (window->node); - /* If no "Next" pointer, keep backing up. */ - if (!INFO_LABEL_FOUND ()) + if (!window->node->next) continue; - /* If this node's first menu item is the same as this node's - Next pointer, keep backing up. */ - if (!info_parsed_filename) + /* If this node's Next pointer is the same as the + first menu item, keep backing up. */ + + REFERENCE *first_menu_item; + first_menu_item = select_menu_digit (window, '1'); + if (first_menu_item + && !strcmp(window->node->next, + first_menu_item->nodename)) { - REFERENCE **menu; - char *next_nodename; - - /* Remember the name of the Next node, since reading - the menu can overwrite the contents of the - info_parsed_xxx strings. */ - next_nodename = xstrdup (info_parsed_nodename); - - menu = info_menu_of_node (window->node); - if (menu && - (strcmp - (menu[0]->nodename, next_nodename) == 0)) - { - info_free_references (menu); - free (next_nodename); - continue; - } - else - { - /* Restore the world to where it was before - reading the menu contents. */ - info_free_references (menu); - free (next_nodename); - info_next_label_of_node (window->node); - } + continue; } /* This node has a "Next" pointer, and it is not the @@ -1315,8 +1282,7 @@ backward_move_node_structure (WINDOW *window, int behaviour) return 1; case IS_NextOnly: - info_prev_label_of_node (window->node); - if (!info_parsed_nodename && !info_parsed_filename) + if (!window->node->prev) { info_error ("%s", _("No `Prev' for this node.")); return 1; @@ -1328,70 +1294,66 @@ backward_move_node_structure (WINDOW *window, int behaviour) break; case IS_Continuous: - info_prev_label_of_node (window->node); - - if (!info_parsed_nodename && (!info_parsed_filename - || is_dir_name (info_parsed_filename))) + if (window->node->up) { - info_up_label_of_node (window->node); - if (!info_parsed_nodename && (!info_parsed_filename - || is_dir_name (info_parsed_filename))) + int traverse_menus = 0; + + /* If up is the dir node, we are at the top node. + Don't do anything. */ + if (!strcmp ("(dir)", window->node->up)) { info_error ("%s", _("No `Prev' or `Up' for this node within this document.")); return 1; } - else + /* If 'Prev' and 'Up' are the same, we are at the first node + of the 'Up' node's menu. Go to up node. */ + else if (window->node->prev + && !strcmp(window->node->prev, window->node->up)) { info_handle_pointer ("Up", window); } - } - else - { - REFERENCE **menu; - int inhibit_menu_traversing = 0; - - /* Watch out! If this node's Prev is the same as the Up, then - move Up. Otherwise, we could move Prev, and then to the last - menu item in the Prev. This would cause the user to loop - through a subsection of the info file. */ - if (!info_parsed_filename && info_parsed_nodename) + /* Otherwise, go to 'Prev' node and go down the last entry + in the menus as far as possible. */ + else if (window->node->prev) { - char *pnode; - - pnode = xstrdup (info_parsed_nodename); - info_up_label_of_node (window->node); - - if (!info_parsed_filename && info_parsed_nodename && - strcmp (info_parsed_nodename, pnode) == 0) - { - /* The nodes are the same. Inhibit moving to the last - menu item. */ - free (pnode); - inhibit_menu_traversing = 1; - } - else - { - free (pnode); - info_prev_label_of_node (window->node); - } + traverse_menus = 1; + info_handle_pointer ("Prev", window); + } + else /* 'Up' but no 'Prev' */ + { + info_handle_pointer ("Up", window); } - /* Move to the previous node. If this node now contains a menu, - and we have not inhibited movement to it, move to the node - corresponding to the last menu item. */ - info_handle_pointer ("Prev", window); - - if (!inhibit_menu_traversing) + /* Repeatedly select last item of menus */ + if (traverse_menus) { - while (!info_error_was_printed && - (menu = info_menu_of_node (window->node))) + REFERENCE *entry; + while (!info_error_was_printed) { - info_free_references (menu); - info_menu_digit (window, 1, '0'); + if (entry = select_menu_digit (window, '0')) + { + info_select_reference (window, entry); + if (entry->line_number > 0) + internal_next_line (window, entry->line_number - 1, '0'); + } + else + break; } } } + else if (window->node->prev) /* 'Prev' but no 'Up' */ + { + info_handle_pointer ("Prev", window); + } + else + { + info_error ("%s", + _("No `Prev' or `Up' for this node within this document.")); + return 1; + } + + break; } return 0; @@ -2126,13 +2088,12 @@ info_win_find_node (INFO_WINDOW *win, NODE *node) return i; } -/* Given that the values of INFO_PARSED_FILENAME and INFO_PARSED_NODENAME - are previously filled, try to get the node represented by them into - WINDOW. The node should have been pointed to by the LABEL pointer of - WINDOW->node. */ -static void -info_handle_pointer (char *label, WINDOW *window) +/* Try to get node decribed by DESCRIPTION into WINDOW. Return + 1 if DESCRIPTION was parsed successfully, otherwise return 0. */ +static int +info_goto_description (char *description, WINDOW *window) { + info_parse_node (description, PARSE_NODE_DFLT); if (info_parsed_filename || info_parsed_nodename) { char *filename, *nodename; @@ -2164,6 +2125,8 @@ info_handle_pointer (char *label, WINDOW *window) info_win = get_info_window_of_window (window); if (info_win) { +/* We don't have label any more. */ +#if 0 if (strcmp (label, "Up") == 0) { int i = info_win_find_node (info_win, node); @@ -2172,6 +2135,7 @@ info_handle_pointer (char *label, WINDOW *window) } info_win->pagetops[info_win->current] = window->pagetop; info_win->points[info_win->current] = window->point; +#endif } info_set_node_of_window (1, window, node); } @@ -2185,18 +2149,37 @@ info_handle_pointer (char *label, WINDOW *window) free (filename); free (nodename); + + return 1; } else { - info_error (msg_no_pointer, label); + return 0; } } +static void +info_handle_pointer (char *label, WINDOW *window) +{ + int ret; + + if (!strcmp (label, "Up")) + ret = info_goto_description (window->node->up, window); + else if (!strcmp (label, "Next")) + ret = info_goto_description (window->node->next, window); + else if (!strcmp (label, "Prev")) + ret = info_goto_description (window->node->prev, window); + + if (!ret) + info_error (msg_no_pointer, label); +} + /* Make WINDOW display the "Next:" node of the node currently being displayed. */ DECLARE_INFO_COMMAND (info_next_node, _("Select the Next node")) { - info_next_label_of_node (window->node); + if (!window->node->next) return; + info_handle_pointer ("Next", window); } @@ -2204,7 +2187,8 @@ DECLARE_INFO_COMMAND (info_next_node, _("Select the Next node")) displayed. */ DECLARE_INFO_COMMAND (info_prev_node, _("Select the Prev node")) { - info_prev_label_of_node (window->node); + if (!window->node->prev) return; + info_handle_pointer ("Prev", window); } @@ -2212,7 +2196,8 @@ DECLARE_INFO_COMMAND (info_prev_node, _("Select the Prev node")) displayed. */ DECLARE_INFO_COMMAND (info_up_node, _("Select the Up node")) { - info_up_label_of_node (window->node); + if (!window->node->up) return; + info_handle_pointer ("Up", window); } @@ -2291,13 +2276,14 @@ DECLARE_INFO_COMMAND (info_last_menu_item, info_menu_digit (window, 1, '0'); } -/* Use KEY (a digit) to select the Nth menu item in WINDOW->node. */ -DECLARE_INFO_COMMAND (info_menu_digit, _("Select this menu item")) +/* Return menu entry */ +static REFERENCE * +select_menu_digit (WINDOW *window, unsigned char key) { register int i, item; register REFERENCE **menu; - menu = info_menu_of_node (window->node); + menu = window->node->references; if (!menu) { @@ -2310,27 +2296,52 @@ DECLARE_INFO_COMMAND (info_menu_digit, _("Select this menu item")) /* Special case. Item "0" is the last item in this menu. */ if (item == 0) - for (i = 0; menu[i + 1]; i++); + { + i = -1; /* Not found */ + int j; + for (j = 0; menu[j]; j++) + if (menu[j]->type == REFERENCE_MENU_ITEM) + i = j; + if (i == -1) return 0; + } else { + int k = 0; for (i = 0; menu[i]; i++) - if (i == item - 1) - break; + { + if (menu[i]->type == REFERENCE_MENU_ITEM) + k++; + if (k == item) + break; + } } - if (menu[i]) + return menu[i]; +} + +/* Use KEY (a digit) to select the Nth menu item in WINDOW->node. */ +DECLARE_INFO_COMMAND (info_menu_digit, _("Select this menu item")) +{ + int item = key - '0'; + REFERENCE *entry; + if (entry = select_menu_digit (window, key)) { - info_select_reference (window, menu[i]); - if (menu[i]->line_number > 0) - internal_next_line (window, menu[i]->line_number - 1, key); + info_select_reference (window, entry); + if (entry->line_number > 0) + internal_next_line (window, entry->line_number - 1, key); + } + else if (key == '0') + { + /* Don't print "There aren't 0 items in this menu." */ + info_error ("%s", msg_no_menu_node); } else - info_error (ngettext ("There isn't %d item in this menu.", - "There aren't %d items in this menu.", - item), - item); - - info_free_references (menu); + { + info_error (ngettext ("There isn't %d item in this menu.", + "There aren't %d items in this menu.", + item), + item); + } return; } @@ -2398,117 +2409,95 @@ nearest_xref (REFERENCE **xref_list, long int pos) } } +static int exclude_cross_references (REFERENCE *r) +{ + return r->type == REFERENCE_XREF; +} + +static int exclude_menu_items (REFERENCE *r) +{ + return r->type == REFERENCE_MENU_ITEM; +} + +static int exclude_nothing (REFERENCE *r) +{ + return 1; +} /* Read a menu or followed reference from the user defaulting to the reference found on the current line, and select that node. The - reading is done with completion. BUILDER is the function used - to build the list of references. ASK_P is non-zero if the user - should be prompted, or zero to select the default item. */ + reading is done with completion. ASK_P is non-zero if the user should + be prompted, or zero to select the item on the current line. MENU_ITEM + and XREF control whether menu items and cross-references are eligible + for selection. */ static void -info_menu_or_ref_item (WINDOW *window, int count, - unsigned char key, REFERENCE **(*builder) (NODE *node), int ask_p) +info_menu_or_ref_item (WINDOW *window, unsigned char key, + int menu_item, int xref, int ask_p) { - char *line; + REFERENCE *defentry = NULL; /* Default link */ + REFERENCE **refs = window->node->references; REFERENCE *entry; - REFERENCE *defentry = NULL; - REFERENCE **menu = (*builder) (window->node); - if (!menu) + /* Name of destination */ + char *line; + + reference_bool_fn exclude; + if (menu_item && !xref) { - if (builder == info_menu_of_node) - info_error ("%s", msg_no_menu_node); - else - info_error ("%s", msg_no_xref_node); - return; + exclude = &exclude_cross_references; } + else if (!menu_item && xref) + { + exclude = &exclude_menu_items; + } + else if (menu_item && xref) + { + exclude = &exclude_nothing; + } + else /* !menu_item && !xref */ + return; - /* Default the selected reference to the one which is on the line that - point is in. */ - { - REFERENCE **refs = NULL; - int point_line = window_line_of_point (window); + int line_no; + int this_line, next_line; - if (point_line != -1) - { - SEARCH_BINDING binding; + int which, closest = -1; - binding.buffer = window->node->contents; - binding.start = window->line_starts[point_line] - binding.buffer; - if (window->line_starts[point_line + 1]) - binding.end = window->line_starts[point_line + 1] - binding.buffer; - else - binding.end = window->node->nodelen; - binding.flags = 0; + /* Default the selected reference to the one which is on the line that + point is in. */ - if (builder == info_menu_of_node) - { - if (point_line) - { - binding.start--; - refs = info_menu_items (&binding); - } - } - else - { -#if defined (HANDLE_MAN_PAGES) - if (window->node->flags & N_IsManPage) - refs = manpage_xrefs_in_binding (window->node, &binding); - else -#endif /* HANDLE_MAN_PAGES */ - refs = nearest_xref (menu, window->point); - } + line_no = window_line_of_point (window); + this_line = window->line_starts[line_no] - window->node->contents; + if (window->line_starts[line_no + 1]) + next_line = window->line_starts[line_no + 1] - window->node->contents; + else + next_line = window->node->nodelen; - if (refs && refs[0]) - { - if (strcmp (refs[0]->label, "Menu") != 0 - || builder == info_xrefs_of_node) - { - int which = 0; - - /* For xrefs, find the closest reference to point, - unless we only have one reference (as we will if - we've called nearest_xref above). It would be better - to have only one piece of code, but the conditions - when we call this are tangled. */ - if (builder == info_xrefs_of_node && refs[1]) - { - int closest = -1; + for (which = 0; refs[which]; which++) + { + /* Check the type of reference is one we are looking for. */ + if (!( (menu_item && refs[which]->type == REFERENCE_MENU_ITEM) + || (xref && refs[which]->type == REFERENCE_XREF))) + continue; - for (; refs[which]; which++) - { - if (window->point >= refs[which]->start - && window->point <= refs[which]->end) - { - closest = which; - break; - } - else if (window->point < refs[which]->start) - break; - } - if (which > 0) - { - if (closest == -1) - which--; - else - which = closest; - } - } + /* If reference starts in current line, it is eligible */ + if ( refs[which]->start >= this_line + && refs[which]->start < next_line) + closest = which; - defentry = xmalloc (sizeof (REFERENCE)); - defentry->label = xstrdup (refs[which]->label); - defentry->filename = refs[which]->filename; - defentry->nodename = refs[which]->nodename; - defentry->line_number = refs[which]->line_number; + /* If point is inside a reference, choose that one. */ + if ( window->point >= refs[which]->start + && window->point <= refs[which]->end) + { + closest = which; + break; + } - if (defentry->filename) - defentry->filename = xstrdup (defentry->filename); - if (defentry->nodename) - defentry->nodename = xstrdup (defentry->nodename); - } - info_free_references (refs); - } - } - } + /* If we got to the next line without finding an eligible reference. */ + if (refs[which]->start >= next_line) + break; + } + if (closest != -1) + defentry = refs[closest]; /* If we are going to ask the user a question, do it now. */ if (ask_p) @@ -2516,7 +2505,7 @@ info_menu_or_ref_item (WINDOW *window, int count, char *prompt; /* Build the prompt string. */ - if (builder == info_menu_of_node) + if (menu_item && !xref) { if (defentry) { @@ -2539,7 +2528,8 @@ info_menu_or_ref_item (WINDOW *window, int count, prompt = xstrdup (_("Follow xref: ")); } - line = info_read_completing_in_echo_area (window, prompt, menu); + line = info_read_completing_in_echo_area_with_exclusions + (window, prompt, refs, exclude); free (prompt); window = active_window; @@ -2547,8 +2537,6 @@ info_menu_or_ref_item (WINDOW *window, int count, /* User aborts, just quit. */ if (!line) { - free (defentry); - info_free_references (menu); info_abort_key (window, 0, 0); return; } @@ -2590,7 +2578,7 @@ info_menu_or_ref_item (WINDOW *window, int count, int best = -1, min_dist = window->node->nodelen; REFERENCE *ref; - for (i = 0; menu && (ref = menu[i]); i++) + for (i = 0; refs && (ref = refs[i]); i++) { /* Need to use mbscasecmp because LINE is downcased inside info_read_completing_in_echo_area. */ @@ -2608,7 +2596,7 @@ info_menu_or_ref_item (WINDOW *window, int count, } } if (best != -1) - entry = menu[best]; + entry = refs[best]; else entry = NULL; } @@ -2620,37 +2608,16 @@ info_menu_or_ref_item (WINDOW *window, int count, NODE *orig = window->node; info_select_reference (window, entry); - if (builder == info_xrefs_of_node && window->node != orig - && !(window->node->flags & N_FromAnchor)) - { /* Search for this reference in the node. */ - long offset; - long start; - - if (window->line_count > 0) - start = window->line_starts[1] - window->node->contents; - else - start = 0; - - offset = info_target_search_node (window->node, entry->label, - start, 0); - - window->point = (offset == -1) ? - window->node->body_start : offset; - window_adjust_pagetop (window); - } + if (entry->line_number > 0) + /* next_line starts at line 1? Anyway, the -1 makes it + move to the right line. */ + internal_next_line (window, entry->line_number - 1, key); - if (entry->line_number > 0) - /* next_line starts at line 1? Anyway, the -1 makes it - move to the right line. */ - internal_next_line (window, entry->line_number - 1, key); } free (line); - info_reference_free (defentry); } - info_free_references (menu); - if (!info_error_was_printed) window_clear_echo_area (); } @@ -2659,7 +2626,7 @@ info_menu_or_ref_item (WINDOW *window, int count, and select that item. */ DECLARE_INFO_COMMAND (info_menu_item, _("Read a menu item and select its node")) { - info_menu_or_ref_item (window, count, key, info_menu_of_node, 1); + info_menu_or_ref_item (window, key, 1, 0, 1); } /* Read a line (with completion) which is the name of a reference to @@ -2667,7 +2634,7 @@ DECLARE_INFO_COMMAND (info_menu_item, _("Read a menu item and select its node")) DECLARE_INFO_COMMAND (info_xref_item, _("Read a footnote or cross reference and select its node")) { - info_menu_or_ref_item (window, count, key, info_xrefs_of_node, 1); + info_menu_or_ref_item (window, key, 0, 1, 1); } /* Position the cursor at the start of this node's menu. */ @@ -2698,7 +2665,7 @@ DECLARE_INFO_COMMAND (info_visit_menu, register int i; REFERENCE *entry, **menu; - menu = info_menu_of_node (window->node); + menu = window->node->references; if (!menu) info_error ("%s", msg_no_menu_node); @@ -2707,6 +2674,8 @@ DECLARE_INFO_COMMAND (info_visit_menu, { WINDOW *new; + if (entry->type != REFERENCE_MENU_ITEM) continue; + new = window_make_window (window->node); window_tile_windows (TILE_INTERNALS); @@ -2833,8 +2802,8 @@ info_follow_menus (NODE *initial_node, char **menus, NODE **err_node, if (!first_arg) first_arg = arg; - /* Build and return a list of the menu items in this node. */ - menu = info_menu_of_node (initial_node); + /* FIXME: This contains cross-references as well. */ + menu = initial_node->references; /* If no menu item in this node, stop here, but let the user continue to use Info. Perhaps they wanted this node and didn't @@ -2899,7 +2868,6 @@ info_follow_menus (NODE *initial_node, char **menus, NODE **err_node, goto maybe_got_node; } - info_free_references (menu); if (err_node) *err_node = format_message_node (_("No menu item `%s' in node `%s'."), arg, @@ -2940,14 +2908,11 @@ info_follow_menus (NODE *initial_node, char **menus, NODE **err_node, _("Unable to find node referenced by `%s' in `%s'."), entry->label, node_printed_rep (initial_node)); - info_free_references (menu); return strict ? NULL : initial_node; } debug (3, ("node: %s, %s", node->filename, node->nodename)); - info_free_references (menu); - /* Success. Go round the loop again. */ free (initial_node); initial_node = node; @@ -3060,6 +3025,8 @@ entry_in_menu (char *arg, REFERENCE **menu, int exact) for (i = 0; (entry = menu[i]); i++) { + if (REFERENCE_MENU_ITEM != entry->type) continue; + if (mbscasecmp (entry->label, arg) == 0) break; else @@ -3115,8 +3082,7 @@ info_intuit_options_node (WINDOW *window, NODE *initial_node, char *program) { REFERENCE *entry = NULL; - /* Build and return a list of the menu items in this node. */ - menu = info_menu_of_node (initial_node); + menu = initial_node->references; /* If no menu item in this node, stop here. Perhaps this node is the one they need. */ @@ -3148,7 +3114,6 @@ info_intuit_options_node (WINDOW *window, NODE *initial_node, char *program) /* Try to find this node. */ node = info_get_node (entry->filename, entry->nodename, PARSE_NODE_VERBATIM); - info_free_references (menu); if (!node) break; } @@ -3394,13 +3359,7 @@ kill_node (WINDOW *window, char *nodename) point = stealer->points[which]; pagetop = stealer->pagetops[which]; - copy->filename = temp->filename; - copy->parent = temp->parent; - copy->nodename = temp->nodename; - copy->contents = temp->contents; - copy->nodelen = temp->nodelen; - copy->flags = temp->flags; - copy->display_pos = temp->display_pos; + *copy = *temp; temp = copy; } @@ -3600,12 +3559,14 @@ dump_node_to_stream (char *filename, char *nodename, /* If this node is an Index, do not dump the menu references. */ if (string_in_line ("Index", node->nodename) == -1) - menu = info_menu_of_node (node); + menu = node->references; if (menu) { for (i = 0; menu[i]; i++) { + if (REFERENCE_MENU_ITEM != menu[i]->type) continue; + /* We don't dump Info files which are different than the current one. */ if (!menu[i]->filename) @@ -3613,7 +3574,6 @@ dump_node_to_stream (char *filename, char *nodename, stream, dump_subnodes) == DUMP_SYS_ERROR) return DUMP_SYS_ERROR; } - info_free_references (menu); } } @@ -4783,85 +4743,32 @@ info_move_to_xref (WINDOW *window, int count, unsigned char key, int dir) long placement = -1; long start = 0; NODE *node = window->node; + REFERENCE **ref; + int nextref; - if (dir < 0) - start = node->nodelen; - - /* This search is only allowed to fail if there is no menu or cross - reference in the current node. Otherwise, the first menu or xref - found is moved to. */ - - firstmenu = info_search_in_node (INFO_MENU_ENTRY_LABEL, node, start, - NULL, dir, 0, 0); - - /* FIRSTMENU may point directly to the line defining the menu. Skip that - and go directly to the first item. */ - - if (firstmenu != -1) - { - char *text = node->contents + firstmenu; - - if (strncmp (text, INFO_MENU_LABEL, strlen (INFO_MENU_LABEL)) == 0) - firstmenu = info_search_in_node (INFO_MENU_ENTRY_LABEL, node, - firstmenu + dir, NULL, dir, 0, 0); - } - - firstxref = - info_search_in_node (INFO_XREF_LABEL, node, start, NULL, dir, 0, 0); - -#if defined (HANDLE_MAN_PAGES) - if ((firstxref == -1) && (node->flags & N_IsManPage)) - { - firstxref = locate_manpage_xref (node, start, dir); - } -#endif /* HANDLE_MAN_PAGES */ - - if (firstmenu == -1 && firstxref == -1) + /* Fail if there are no references in node */ + if (!node->references) { if (!cursor_movement_scrolls_p) - info_error ("%s", msg_no_xref_node); + info_error ("%s", msg_no_xref_node); return cursor_movement_scrolls_p; } - /* There is at least one cross reference or menu entry in this node. - Try hard to find the next available one. */ - - nextmenu = info_search_in_node (INFO_MENU_ENTRY_LABEL, node, - window->point + dir, NULL, dir, 0, 0); - - nextxref = info_search_in_node (INFO_XREF_LABEL, node, - window->point + dir, NULL, dir, 0, 0); - -#if defined (HANDLE_MAN_PAGES) - if ((nextxref == -1) && (node->flags & N_IsManPage) && (firstxref != -1)) - nextxref = locate_manpage_xref (node, window->point + dir, dir); -#endif /* HANDLE_MAN_PAGES */ - - /* Ignore "Menu:" as a menu item. */ - if (nextmenu != -1) - { - char *text = node->contents + nextmenu; - - if (strncmp (text, INFO_MENU_LABEL, strlen (INFO_MENU_LABEL)) == 0) - nextmenu = info_search_in_node (INFO_MENU_ENTRY_LABEL, node, - nextmenu + dir, NULL, dir, 0, 0); - } - - /* If there is both a next menu entry, and a next xref entry, choose the - one which occurs first. Otherwise, select the one which actually - appears in this node following point. */ - if (nextmenu != -1 && nextxref != -1) - { - if (((dir == 1) && (nextmenu < nextxref)) || - ((dir == -1) && (nextmenu > nextxref))) - placement = nextmenu + 1; - else - placement = nextxref; - } - else if (nextmenu != -1) - placement = nextmenu + 1; - else if (nextxref != -1) - placement = nextxref; + if (dir == 1) /* Search forwards */ + for (ref = node->references; *ref != 0; ref++) + { + if ((*ref)->start > window->point) + { + placement = (*ref)->start; + break; + } + } + else /* Search backwards */ + for (ref = node->references; *ref != 0; ref++) + { + if ((*ref)->start >= window->point) break; + placement = (*ref)->start; + } /* If there was neither a menu or xref entry appearing in this node after point, choose the first menu or xref entry appearing in this node. */ @@ -4870,21 +4777,9 @@ info_move_to_xref (WINDOW *window, int count, unsigned char key, int dir) if (cursor_movement_scrolls_p) return 1; else - { - if (firstmenu != -1 && firstxref != -1) - { - if (((dir == 1) && (firstmenu < firstxref)) || - ((dir == -1) && (firstmenu > firstxref))) - placement = firstmenu + 1; - else - placement = firstxref; - } - else if (firstmenu != -1) - placement = firstmenu + 1; - else - placement = firstxref; - } + placement = node->references[0]->start; } + window->point = placement; window_adjust_pagetop (window); window->flags |= W_UpdateWindow; @@ -4934,19 +4829,13 @@ DECLARE_INFO_COMMAND (info_move_to_next_xref, DECLARE_INFO_COMMAND (info_select_reference_this_line, _("Select reference or menu item appearing on this line")) { - char *line; + REFERENCE **ref = window->node->references; - if (window->line_starts) - line = window->line_starts[window_line_of_point (window)]; - else - line = ""; + if (!ref || !*ref) return; /* No references in node */ - /* If this line contains a menu item, select that one. */ - if (strncmp ("* ", line, 2) == 0) - info_menu_or_ref_item (window, count, key, info_menu_of_node, 0); - else - info_menu_or_ref_item (window, count, key, info_xrefs_of_node, 0); + info_menu_or_ref_item (window, key, 1, 1, 0); } + /* **************************************************************** */ /* */