Common subdirectories: merge-TAG-tree/trunk/info/.deps and parse-node-tree/trunk/info/.deps diff -u -x 'Makefile*' -x '*.o' -x '*~' merge-TAG-tree/trunk/info/dir.c parse-node-tree/trunk/info/dir.c --- merge-TAG-tree/trunk/info/dir.c 2014-01-30 13:47:12.000000000 +0000 +++ parse-node-tree/trunk/info/dir.c 2014-01-30 15:18:47.000000000 +0000 @@ -32,7 +32,7 @@ FILE_BUFFER *fb); static void insert_text_into_fb_at_binding (FILE_BUFFER *fb, SEARCH_BINDING *binding, char *text, int textlen); -void maybe_build_dir_node (char *dirname); +FILE_BUFFER *maybe_build_dir_node (char *dirname); static char *dirs_to_add[] = { "dir", "localdir", NULL @@ -74,13 +74,26 @@ return 1; } +static FILE_BUFFER *dir_buffer = 0; -void +/* Defined in nodes.c */ +void get_nodes_of_info_file (FILE_BUFFER *file_buffer); + +/* Return dir node, building it if necessary */ +FILE_BUFFER * maybe_build_dir_node (char *dirname) { int path_index, update_tags; char *this_dir; - FILE_BUFFER *dir_buffer = info_find_file (dirname); + + /* Check if it's been built already */ + if (dir_buffer) return dir_buffer; + + /* Disabled because we don't want to parse contents of dir twice, once + * when it is loaded and again at the end once extra dir's are added. + * Try a different method where we build up dir from an empty buffer. */ +#if 0 + dir_buffer = info_find_file (dirname); /* If there is no "dir" in the current info path, we cannot build one from nothing. */ @@ -94,7 +107,18 @@ /* Initialize the list we use to avoid reading the same dir file twice with the dir file just found. */ new_dir_file_p (&dir_buffer->finfo); +#endif + dir_buffer = make_file_buffer(); + dir_buffer->filesize = 12; + dir_buffer->filename = "dir"; + /* FIXME: not the full path: does this matter? */ + /* This is used in get_nodes_of_info_file() */ + dir_buffer->fullpath = "dir"; + /* Must allocate for following because it is mutable */ + dir_buffer->contents = calloc(13,1); + strcpy(dir_buffer->contents, "\037\nNode: Top\n"); + update_tags = 0; /* Using each element of the path, check for one of the files in @@ -158,10 +182,12 @@ } if (update_tags) - build_tags_and_nodes (dir_buffer); + get_nodes_of_info_file (dir_buffer); /* Flag that the dir buffer has been built. */ dir_buffer->flags |= N_CannotGC; + + return dir_buffer; } /* Given CONTENTS and FB (a file buffer), add the menu found in CONTENTS Binary files merge-TAG-tree/trunk/info/ginfo and parse-node-tree/trunk/info/ginfo differ diff -u -x 'Makefile*' -x '*.o' -x '*~' merge-TAG-tree/trunk/info/info-utils.c parse-node-tree/trunk/info/info-utils.c --- merge-TAG-tree/trunk/info/info-utils.c 2014-01-30 13:47:12.000000000 +0000 +++ parse-node-tree/trunk/info/info-utils.c 2014-01-30 15:18:47.000000000 +0000 @@ -58,7 +58,9 @@ static REFERENCE **info_references_internal (char *label, SEARCH_BINDING *binding); -/* Parse the filename and nodename out of STRING. If STRING doesn't +/* Parse the filename and nodename out of STRING. Return length of node + specification. + If STRING doesn't contain a filename (i.e., it is NOT (FILENAME)NODENAME) then set INFO_PARSED_FILENAME to NULL. The second argument is one of the PARSE_NODE_* constants. It specifies how to parse the node name: @@ -68,10 +70,11 @@ PARSE_NODE_VERBATIM Don't parse nodename */ -void +int info_parse_node (char *string, int flag) { register int i = 0; + int length = 0; /* Return value */ /* Default the answer. */ save_filename (NULL); @@ -92,6 +95,7 @@ i = 0; /* Advance past the opening paren. */ string++; + length++; /* Find the closing paren. Handle nested parens correctly. */ for (bcnt = 0, bfirst = -1; string[i]; i++) @@ -119,13 +123,19 @@ /* Point directly at the nodename. */ string += i; + length += i; if (*string) - string++; + { + string++; + length++; + } } /* Parse out nodename. */ i = skip_node_characters (string, flag); + length += i; + length++; /* skip_node_characters() stops on terminating character */ saven_nodename (string, i); canonicalize_whitespace (info_parsed_nodename); if (info_parsed_nodename && !*info_parsed_nodename) @@ -164,6 +174,7 @@ else info_parsed_line_number = 0; } + return length; } /* Return the node addressed by LABEL in NODE (usually one of "Prev:", diff -u -x 'Makefile*' -x '*.o' -x '*~' merge-TAG-tree/trunk/info/info-utils.h parse-node-tree/trunk/info/info-utils.h --- merge-TAG-tree/trunk/info/info-utils.h 2014-01-30 13:47:12.000000000 +0000 +++ parse-node-tree/trunk/info/info-utils.h 2014-01-30 15:54:09.000000000 +0000 @@ -22,10 +22,6 @@ #ifndef INFO_UTILS_H #define INFO_UTILS_H -#include "nodes.h" -#include "window.h" -#include "search.h" - /* Structure which describes a node reference, such as a menu entry or cross reference. Arrays of such references can be built by calling info_menus_of_node () or info_xrefs_of_node (). */ @@ -35,8 +31,20 @@ char *nodename; /* Name of the node. */ int start, end; /* Offsets within the containing node of LABEL. */ int line_number; /* Specific line number a menu item points to. */ + int type; /* Whether reference is a xref or a menu item */ } REFERENCE; +/* REFERENCE is used in nodes.h */ + +#include "nodes.h" +#include "window.h" +#include "search.h" + + +/* Possible values of REFERENCE.type */ +#define REFERENCE_XREF 0 +#define REFERENCE_MENU_ITEM 1 + /* When non-zero, various display and input functions handle ISO Latin character sets correctly. */ extern int ISO_Latin_p; @@ -65,7 +73,7 @@ PARSE_NODE_START The STRING argument is retrieved from a node start line, and therefore ends in `,' only. */ -void info_parse_node (char *string, int flag); +int info_parse_node (char *string, int flag); /* Return a NULL terminated array of REFERENCE * which represents the menu found in NODE. If there is no menu in NODE, just return a NULL pointer. */ Only in parse-node-tree/trunk/info/: info-utils.h.orig Binary files merge-TAG-tree/trunk/info/infokey and parse-node-tree/trunk/info/infokey differ Binary files merge-TAG-tree/trunk/info/makedoc and parse-node-tree/trunk/info/makedoc differ diff -u -x 'Makefile*' -x '*.o' -x '*~' merge-TAG-tree/trunk/info/nodes.c parse-node-tree/trunk/info/nodes.c --- merge-TAG-tree/trunk/info/nodes.c 2014-01-30 15:06:33.000000000 +0000 +++ parse-node-tree/trunk/info/nodes.c 2014-01-30 16:02:22.000000000 +0000 @@ -37,7 +37,7 @@ static void free_info_tag (NODE *tag); static void get_nodes_of_tags_table (FILE_BUFFER *file_buffer, SEARCH_BINDING *buffer_binding); -static void get_nodes_of_info_file (FILE_BUFFER *file_buffer); +void get_nodes_of_info_file (FILE_BUFFER *file_buffer); static void get_tags_of_indirect_tags_table (FILE_BUFFER *file_buffer, SEARCH_BINDING *indirect_binding, SEARCH_BINDING *tags_binding); static void info_reload_file_buffer_contents (FILE_BUFFER *fb); @@ -72,7 +72,7 @@ /* Public functions for node manipulation. */ /* Used to build `dir' menu from `localdir' files found in INFOPATH. */ -extern void maybe_build_dir_node (char *dirname); +extern FILE_BUFFER *maybe_build_dir_node (char *dirname); /* Return a pointer to a NODE structure for the Info node (FILENAME)NODENAME. If FILENAME is NULL, `dir' is used. @@ -82,32 +82,41 @@ If the node cannot be found, return NULL. */ NODE * -info_get_node (char *filename, char *nodename, int flag) +info_get_node (char *passed_filename, char *passed_nodename, int flag) { NODE *node; FILE_BUFFER *file_buffer = NULL; + char *filename = 0, *nodename = 0; + info_recent_file_error = NULL; - info_parse_node (nodename, flag); - nodename = NULL; + info_parse_node (passed_nodename, flag); + passed_nodename = NULL; + + /* We need to duplicate info_parsed_filename because it can be rewritten + * when info_get_node_of_file_buffer is called below */ + /* strdup passed_filename as well so we can free filename in both cases. + * We don't know if we can free passed_filename or not. */ + /* FIXME: Change info_parse_node to make all this easier */ if (info_parsed_filename) - filename = info_parsed_filename; + filename = strdup(info_parsed_filename); + else if (passed_filename) + filename = strdup(passed_filename); if (info_parsed_nodename) - nodename = info_parsed_nodename; + nodename = strdup(info_parsed_nodename); + else if (passed_nodename) + nodename = strdup(passed_nodename); + /* See comment above for use of strdup() */ /* If FILENAME is not specified, it defaults to "dir". */ if (!filename) - filename = "dir"; + filename = strdup("dir"); - /* If the file to be looked up is "dir", build the contents from all of - the "dir"s and "localdir"s found in INFOPATH. */ - if (is_dir_name (filename)) - maybe_build_dir_node (filename); + file_buffer = info_find_file (filename); /* Find the correct info file, or give up. */ - file_buffer = info_find_file (filename); if (!file_buffer) { node = make_manpage_node (filename); @@ -116,6 +125,7 @@ if (filesys_error_number) info_recent_file_error = filesys_error_string (filename, filesys_error_number); + free(filename); free(nodename); return NULL; } } @@ -136,6 +146,7 @@ node = info_get_node_of_file_buffer ("TOP", file_buffer); } + free(filename); free(nodename); return node; } @@ -244,6 +255,13 @@ int i; FILE_BUFFER *file_buffer; + /* If the file to be looked up is "dir", build the contents from all of + the "dir"s and "localdir"s found in INFOPATH. */ + if (is_dir_name (filename)) + { + return maybe_build_dir_node (filename); + } + /* First try to find the file in our list of already loaded files. */ if (info_loaded_files) { @@ -466,18 +484,21 @@ file_buffer->flags |= N_HasTagsTable; tags_table_begin = position; - /* If this isn't an indirect tags table, just remember the nodes - described locally in this tags table. Note that binding.end - is pointing to just after the beginning label. */ + /* If this isn't an indirect tags table, build tag table + * ourselves and ignore the tag table in the file. Note that + * binding.end is pointing to just after the beginning label. */ binding.start = binding.end; binding.end = file_buffer->filesize; if (!looking_at (TAGS_TABLE_IS_INDIRECT_LABEL, &binding)) { + /* Tags table in non-split file */ + binding.start = tags_table_begin; binding.end = tags_table_end; get_nodes_of_tags_table (file_buffer, &binding); - return; + + break; } else { @@ -505,41 +526,286 @@ } } - /* This file doesn't contain any kind of tags table. Grovel the - file and build node entries for it. */ + /* If no tags table, build node list ourselves. */ + /* For non-split files, build node list, but keep offset information + * tags tables. We need this for meaningful anchor offsets. */ get_nodes_of_info_file (file_buffer); } +/* Based on info-utils.c:info_references_internal() */ +/* Glean cross references or menu items from ENTRY->contents. Return an array + of REFERENCE * that represents the items found. */ +/* BINDING.start must be 0 for returned offsets to be relative to start of + * node. BINDING.buffer - point to first character of node */ +/* Remove syntax from node and copy to OUTPUT. Make OUTPUT point after + * added bytes. */ +static void +parse_node (NODE *node, char **output) +{ + SEARCH_BINDING s; + REFERENCE **refs = NULL; + + char *search_string = "\\n\\* Menu:|\\*Note"; + + /* Save *output so we can tell how many bytes have been output */ + char *output_start = *output; + char *input_start = node->contents; + + char *copy_from; + char *copy_to; + + size_t refs_index = 0, refs_slots = 0; + long position; + + copy_from = node->contents; + node->contents = *output; + + /* Initialize refs to point to array of one null pointer in case + * there are no results. This way we know if refs has been initialized + * even if it is empty. */ + refs = calloc (1, sizeof *refs); + refs_slots = 1; + + s.buffer = copy_from; + s.start = 0; + s.end = node->nodelen; + + s.flags = S_FoldCase | S_SkipDest; + + /* INFO_MENU_ENTRY_LABEL "|" INFO_XREF_LABEL */ + //while (regexp_search ("\\n\\* |\\*Note", + while (regexp_search (search_string, + &s, &position, 0) == search_success) + { + int colon_offset; + REFERENCE *entry; + char *refdef; + int found_menu_entry = 0; + + /* Pointer to search result (after match) */ + refdef = s.buffer + position; + + /* Was "* Menu:" seen? If so, search for menu entries hereafter */ + if (*(refdef - 1) == ':') + { + search_string = "\\n\\* |\\*Note"; + s.start = position; + continue; + } + + /* Create REFERENCE entity */ + entry = xmalloc (sizeof (REFERENCE)); + entry->filename = NULL; + entry->nodename = NULL; + entry->label = NULL; + entry->line_number = 0; + + /* Check what we found based on last character of match */ + if (*(refdef - 1) == ' ') + { + found_menu_entry = 1; + entry->type = REFERENCE_MENU_ITEM; + } + else + { + entry->type = REFERENCE_XREF; + } + + /* Clean up output */ + switch (entry->type) + { + case REFERENCE_MENU_ITEM: + copy_to = refdef; + break; + case REFERENCE_XREF: + copy_to = refdef - 5; + break; + } + + /* Write out up to current reference */ + memmove (*output, copy_from, copy_to - copy_from); + *output += copy_to - copy_from; + copy_from = refdef; + + /* Point reference to where we will put the displayed reference */ + entry->start = *output - output_start; + entry->end = entry->start; /* FIXME */ + + + **output = '['; + (*output)++; + +#if 1 + /* Turn on bold */ + /* FIXME: Look up 'bold' capability from terminfo */ + /* FIXME: Control characters in buffer mess up reference offsets. + * Searching ("s") still works for unknown reasons, except when + * the match is after a reference in the same line, though. */ + /* We could fix this by keeping track of the length of control + * strings output so far, and adjusting references by this + * amount. */ + strcpy(*output, "\033[1m"); + *output += 4; +#endif + + /* Search forward to ":" to get label name */ + /* Skip whitespace */ + refdef += skip_whitespace (refdef); + colon_offset = string_in_line (":", refdef) - 1; + + /* If no colon? */ + if (colon_offset == -1 - 1) + { + int temp; + + /* No newlines in menu entries */ + if (found_menu_entry) continue; + + /* Check if a newline intervenes */ + temp = skip_line (refdef); + colon_offset = string_in_line (":", refdef + temp) - 1; + if (colon_offset == -2) + { + /* Update search to start after end of node specifier. */ + s.start = refdef - s.buffer; + continue; /* Give up. */ + } + else + colon_offset += temp; + } + + entry->label = xmalloc(colon_offset + 1); + strncpy (entry->label, refdef, colon_offset); + entry->label[colon_offset] = '\0'; + canonicalize_whitespace (entry->label); + + /* Output reference label */ + strcpy(*output, entry->label); + (*output) += strlen(entry->label); + +#if 1 + /* Turn off bold */ + /* FIXME: Look up 'sgr0' capability from terminfo */ + strcpy(*output, "\033(\033[m"); + *output += 5; + +#endif + /* Closing "]" */ + **output = ']'; (*output)++; + + + + /* Point after ':' */ + refdef += colon_offset; refdef++; + + /* If this reference entry continues with another ':' then the + * nodename is the same as the label. */ + if (*refdef == ':') + { + entry->nodename = xstrdup (entry->label); + refdef++; + } + else + { + /* This entry continues with a specific nodename. Parse the + nodename from the specification. */ + + /* Defined in info-utils.c */ + extern int info_parsed_line_number; + int length; /* Length of specification */ + + refdef += skip_whitespace_and_newlines (refdef); + + if (found_menu_entry) + length = info_parse_node (refdef, PARSE_NODE_DFLT); + else + length = info_parse_node (refdef, PARSE_NODE_SKIP_NEWLINES); + + if (info_parsed_filename) + entry->filename = xstrdup (info_parsed_filename); + + if (info_parsed_nodename) + entry->nodename = xstrdup (info_parsed_nodename); + + entry->line_number = info_parsed_line_number; + refdef += length; + } + add_pointer_to_array (entry, refs_index, refs, refs_slots, 50); + + copy_from = refdef; + + /* Update search to start after end of node specifier. */ + s.start = refdef - s.buffer; + } + /* Write out rest of node. */ + memmove (*output, copy_from, (input_start + node->nodelen) - copy_from); + *output += (input_start + node->nodelen) - copy_from; + + /* Update nodelen */ + node->nodelen = *output - output_start; + + node->references = refs; +} + /* Search through FILE_BUFFER->contents building an array of NODE *, one entry per each node present in the file. Store the tags in FILE_BUFFER->tags, and the number of allocated slots in FILE_BUFFER->tags_slots. */ -static void + /* If FILE_BUFFER already has a tags table, set contents but maintain + values of NODE.nodestart. */ +void get_nodes_of_info_file (FILE_BUFFER *file_buffer) { long nodestart; + char *nodeline, *old_nodeline; size_t tags_index = 0; SEARCH_BINDING binding; + int has_tags_table_already; + + has_tags_table_already = file_buffer->flags & N_HasTagsTable; + + /* Build up replacement for file_buffer->contents with notation + * stripped out ("*note" etc.) */ + char *new_contents = calloc(1, file_buffer->filesize * 2 + 1); + char *new_ptr = new_contents; + + old_nodeline = file_buffer->contents; + binding.buffer = file_buffer->contents; binding.start = 0; binding.end = file_buffer->filesize; binding.flags = S_FoldCase; + /* Copy file preamble (the part before the first node + * separator) */ + /* FIXME: inefficient to call twice */ + nodestart = find_node_separator (&binding); + memmove (new_ptr, file_buffer->contents, nodestart); + new_ptr += nodestart; + while ((nodestart = find_node_separator (&binding)) != -1) { int start, end; - char *nodeline; NODE *entry; int anchor = 0; + int separator_length; + int node_len; /* Length of input node */ + REFERENCE **refs; /* Reference list for node */ + + separator_length = skip_node_separator (binding.buffer + nodestart); /* Skip past the characters just found. */ binding.start = nodestart; - binding.start += skip_node_separator (binding.buffer + binding.start); + binding.start += separator_length; /* Move to the start of the line defining the node. */ nodeline = binding.buffer + binding.start; + /* Copy node separator */ + memmove (new_ptr, binding.buffer + nodestart, separator_length); + new_ptr += separator_length; + /* Find "Node:" */ start = string_in_line (INFO_NODE_LABEL, nodeline); /* No Node:. Maybe it's a Ref:. */ @@ -561,14 +827,47 @@ end = start + skip_node_characters (nodeline + start, PARSE_NODE_DFLT); - /* Okay, we have isolated the node name, and we know where the - node starts. Remember this information. */ - entry = xmalloc (sizeof (NODE)); - entry->content_cache = NULL; - entry->nodename = xmalloc (1 + (end - start)); - strncpy (entry->nodename, nodeline + start, end - start); - entry->nodename[end - start] = 0; - entry->nodestart = nodestart; + /* Set the value of entry */ + if (!has_tags_table_already) + { + entry = xmalloc (sizeof (NODE)); + /* Add this node structure to the array of node structures in this + FILE_BUFFER. */ + add_pointer_to_array (entry, tags_index, file_buffer->tags, + file_buffer->tags_slots, 100); + entry->content_cache = NULL; + + entry->filename = file_buffer->fullpath; + + /* Okay, we have isolated the node name, and we know where the + node starts. Remember this information. */ + + entry->nodename = xmalloc (1 + (end - start)); + strncpy (entry->nodename, nodeline + start, end - start); + entry->nodename[end - start] = 0; + + /* By this point new_ptr points after copied node separator */ + entry->nodestart = new_ptr - new_contents; + entry->contents = new_ptr; + } + else + { + /* Loop through tag table looking for a tag that isn't + * an anchor */ + while (file_buffer->tags[tags_index] && + file_buffer->tags[tags_index]->nodelen == 0) + tags_index++; + + if (!(entry = file_buffer->tags[tags_index])) + { + printf("Node listed in indirect tags table but" + "not found in subfile\n"); + exit (23); + } + + tags_index++; /* For next time */ + } + if (anchor) entry->nodelen = 0; else @@ -582,12 +881,15 @@ entry->nodelen = get_node_length (&node_body); } - entry->filename = file_buffer->fullpath; - - /* Add this tag to the array of tag structures in this FILE_BUFFER. */ - add_pointer_to_array (entry, tags_index, file_buffer->tags, - file_buffer->tags_slots, 100); + entry->contents = nodeline; + /* Search node body for cross-references and menu items */ + parse_node (entry, &new_ptr); } + free(file_buffer->contents); + file_buffer->contents = new_contents; + + /* Warning: new_contents may contain null characters */ + file_buffer->filesize = new_ptr - new_contents; } /* Return the length of the node which starts at BINDING. */ @@ -874,6 +1176,17 @@ free (subfiles[i]); } free (subfiles); + + /* Create reference tables for nodes in indirect tag table */ + /* Will have to wait until after subfiles are loaded */ + { + NODE **t = file_buffer->tags; + + for (; *t != 0; t++) + { + (*t)->references = 0; /* FIXME */ + } + } } @@ -952,6 +1265,10 @@ { NODE *tag; int i; + REFERENCE **node_refs; + NODE **subfile_tags, **topfile_tags; + NODE *file_node; + SEARCH_BINDING s; /* If no tags at all (possibly a misformatted info file), quit. */ if (!file_buffer->tags) @@ -961,6 +1278,7 @@ if (strcmp (nodename, tag->nodename) == 0) { NODE *node; + /* If not a split file, subfile == file_buffer */ FILE_BUFFER *subfile = info_find_file_internal (tag->filename, INFO_NO_TAGS); if (!subfile) @@ -978,14 +1296,96 @@ if (!(tag->nodestart >= 0 && tag->nodestart < subfile->filesize)) return NULL; + /* Check if refs have been loaded for subfile, and if not, + * load them */ + /* TODO: should this be in info_find_file_internal or in here? Do + * we need to change the arguments of info_find_file_internal and + * subsequent functions? */ + + /* For tags which aren't anchors, load reference table from + * subfile if not loaded already */ + if (tag->nodelen != 0 && tag->references == 0) + { + int j, first_tag_in_subfile = -1, last_tag_in_subfile = -1; + int j2; + + printf("","Asked to build reference list for file %s\n", + tag->filename); + + get_nodes_of_info_file (subfile); + subfile_tags = subfile->tags; + topfile_tags = file_buffer->tags; + + for (j = 0; file_node = file_buffer->tags[j]; j++) + { + if (!strcmp (tag->filename, file_node->filename)) + { + first_tag_in_subfile = j; + break; + } + } + + if (first_tag_in_subfile == -1) + { + printf ("Impossible!\n"); exit(23); + } + + for (; file_node = file_buffer->tags[j]; j++) + { + /* FIXME: Use subfile offsets instead for greater + * efficiency. */ + if (strcmp (tag->filename, file_node->filename)) + { + break; + } + } + last_tag_in_subfile = j - 1; + + /* FIXME: this will break if subfile is malformed */ + /* Copy data into master tag table */ + for (j = first_tag_in_subfile, j2 = 0; + j <= last_tag_in_subfile; + j++) + { + /* If it is an anchor, there will be no corresponding + * entry in the subfile node list, so skip. Set by + * get_nodes_of_tags_table(). FIXME: better way of + * knowing if it is an anchor? */ + if (file_buffer->tags[j]->nodelen == 0) + { + continue; + } + + if (strcmp (topfile_tags[j]->nodename, subfile_tags[j2]->nodename)) + { + printf("Subfile tags different from master tag table!\n"); + exit(23); + } + + topfile_tags[j]->references = subfile_tags[j2]->references; + /* Comment out - we need nodestart intact so that + * we can interpret which node an anchor is in */ + // topfile_tags[j]->nodestart = subfile_tags[j2]->nodestart; + topfile_tags[j]->contents = subfile->contents + + subfile_tags[j2]->nodestart; + topfile_tags[j]->nodelen = subfile_tags[j2]->nodelen; + j2++; + } + + /*FIXME: free subfile_tags? */ + } + node = xmalloc (sizeof (NODE)); node->filename = subfile->fullpath; node->parent = NULL; node->nodename = tag->nodename; + node->references = tag->references; if (tag->content_cache) node->contents = tag->content_cache; - else + else if (tag->contents) + node->contents = tag->contents; + else node->contents = subfile->contents + tag->nodestart; node->display_pos = 0; Only in parse-node-tree/trunk/info/: nodes.c.orig Only in merge-TAG-tree/trunk/info/: nodes.c.rej diff -u -x 'Makefile*' -x '*.o' -x '*~' merge-TAG-tree/trunk/info/nodes.h parse-node-tree/trunk/info/nodes.h --- merge-TAG-tree/trunk/info/nodes.h 2014-01-30 13:54:28.000000000 +0000 +++ parse-node-tree/trunk/info/nodes.h 2014-01-30 15:34:50.000000000 +0000 @@ -43,6 +43,9 @@ unsigned long display_pos; /* Where to display at, if nonzero. */ long body_start; /* Offset of the actual node body */ int flags; /* See immediately below. */ + REFERENCE **references; /* Cross-references or menu items in node. + references == 0 implies uninitialized, + not empty */ /* Fields merged from TAG */ long nodestart; /* The offset of the start of this node. */ char *content_cache; /* Cache of the node contents; used if the Only in parse-node-tree/trunk/info/: nodes.h.orig diff -u -x 'Makefile*' -x '*.o' -x '*~' merge-TAG-tree/trunk/info/session.c parse-node-tree/trunk/info/session.c --- merge-TAG-tree/trunk/info/session.c 2014-01-30 13:54:28.000000000 +0000 +++ parse-node-tree/trunk/info/session.c 2014-01-30 15:18:47.000000000 +0000 @@ -4774,6 +4774,7 @@ /* */ /* **************************************************************** */ +#if 0 /* Move to the next or previous cross reference in this node. */ static int info_move_to_xref (WINDOW *window, int count, unsigned char key, int dir) @@ -4890,6 +4891,59 @@ window->flags |= W_UpdateWindow; return 0; } +#endif + +/* Move to the next or previous cross reference in this node. */ +static int +info_move_to_xref (WINDOW *window, int count, unsigned char key, int dir) +{ + long firstmenu, firstxref; + long nextmenu, nextxref; + long placement = -1; + long start = 0; + NODE *node = window->node; + REFERENCE **ref; + int nextref; + + if (firstmenu == -1 && firstxref == -1) + { + if (!cursor_movement_scrolls_p) + 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. */ + + if (!node->references) + return 1; + + 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 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 */ + + window->point = placement; + window_adjust_pagetop (window); + window->flags |= W_UpdateWindow; + return 0; +} DECLARE_INFO_COMMAND (info_move_to_prev_xref, _("Move to the previous cross reference")) @@ -4930,8 +4984,10 @@ } } +#if 0 +/* have to break macro because of macro magic */ /* Select the menu item or reference that appears on this line. */ -DECLARE_INFO_COMMAND (info_select_reference_this_line, +DCLARE_INFO_COMMAND (info_select_reference_this_line, _("Select reference or menu item appearing on this line")) { char *line; @@ -4947,6 +5003,39 @@ else info_menu_or_ref_item (window, count, key, info_xrefs_of_node, 0); } +#endif + +#if 1 +/* Select the menu item or reference that appears on this line. */ +/* FIXME: This function does not do what it should - it actually picks + * the first link before the cursor */ +DECLARE_INFO_COMMAND (info_select_reference_this_line, + _("Select reference or menu item appearing on this line")) +{ + REFERENCE **ref = window->node->references; + + if (!ref || !*ref) return; /* No references in node */ + + /* Loop until we've checked all the references or the next reference + * is after the cursor. */ + for (; *ref != 0; ref++) + { + if (*(ref+1) && (*(ref + 1))->start > window->point) + { + info_select_reference(window, *ref); + return; + } + + /* If no next reference but current reference is eligible */ + if (!*(ref+1) && (*ref)->start <= window->point) + { + info_select_reference(window, *ref); + return; + } + } +} +#endif + /* **************************************************************** */ /* */