📄 info-utils.c
字号:
/* info-utils.c -- Useful functions for manipulating Info file quirks. *//* This file is part of GNU Info, a program for reading online documentation stored in Info format. Copyright (C) 1993 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Written by Brian Fox (bfox@ai.mit.edu). */#include "info.h"#include "info-utils.h"#if defined (HANDLE_MAN_PAGES)# include "man.h"#endif /* HANDLE_MAN_PAGES *//* When non-zero, various display and input functions handle ISO Latin character sets correctly. */int ISO_Latin_p = 0;/* Variable which holds the most recent filename parsed as a result of calling info_parse_xxx (). */char *info_parsed_filename = (char *)NULL;/* Variable which holds the most recent nodename parsed as a result of calling info_parse_xxx (). */char *info_parsed_nodename = (char *)NULL;/* Functions to remember a filename or nodename for later return. */static void save_filename (), saven_filename ();static void save_nodename (), saven_nodename ();/* How to get a reference (either menu or cross). */static REFERENCE **info_references_internal ();/* Parse the filename and nodename out of STRING. If STRING doesn't contain a filename (i.e., it is NOT (FILENAME)NODENAME) then set INFO_PARSED_FILENAME to NULL. If second argument NEWLINES_OKAY is non-zero, it says to allow the nodename specification to cross a newline boundary (i.e., only `,', `.', or `TAB' can end the spec). */voidinfo_parse_node (string, newlines_okay) char *string; int newlines_okay;{ register int i = 0; /* Default the answer. */ save_filename ((char *)NULL); save_nodename ((char *)NULL); /* Special case of nothing passed. Return nothing. */ if (!string || !*string) return; string += skip_whitespace (string); /* Check for (FILENAME)NODENAME. */ if (*string == '(') { i = 0; /* Advance past the opening paren. */ string++; /* Find the closing paren. */ while (string[i] && string[i] != ')') i++; /* Remember parsed filename. */ saven_filename (string, i); /* Point directly at the nodename. */ string += i; if (*string) string++; } /* Parse out nodename. */ i = skip_node_characters (string, newlines_okay); saven_nodename (string, i); canonicalize_whitespace (info_parsed_nodename); if (info_parsed_nodename && !*info_parsed_nodename) { free (info_parsed_nodename); info_parsed_nodename = (char *)NULL; }}/* Return the node addressed by LABEL in NODE (usually one of "Prev:", "Next:", "Up:", "File:", or "Node:". After a call to this function, the global INFO_PARSED_NODENAME and INFO_PARSED_FILENAME contain the information. */voidinfo_parse_label (label, node) char *label; NODE *node;{ register int i; char *nodeline; /* Default answer to failure. */ save_nodename ((char *)NULL); save_filename ((char *)NULL); /* Find the label in the first line of this node. */ nodeline = node->contents; i = string_in_line (label, nodeline); if (i == -1) return; nodeline += i; nodeline += skip_whitespace (nodeline); info_parse_node (nodeline, DONT_SKIP_NEWLINES);}/* **************************************************************** *//* *//* Finding and Building Menus *//* *//* **************************************************************** *//* 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. */REFERENCE **info_menu_of_node (node) NODE *node;{ long position; SEARCH_BINDING search; REFERENCE **menu = (REFERENCE **)NULL; search.buffer = node->contents; search.start = 0; search.end = node->nodelen; search.flags = S_FoldCase; /* Find the start of the menu. */ position = search_forward (INFO_MENU_LABEL, &search); if (position == -1) return ((REFERENCE **) NULL); /* We have the start of the menu now. Glean menu items from the rest of the node. */ search.start = position + strlen (INFO_MENU_LABEL); search.start += skip_line (search.buffer + search.start); search.start--; menu = info_menu_items (&search); return (menu);}/* Return a NULL terminated array of REFERENCE * which represents the cross refrences found in NODE. If there are no cross references in NODE, just return a NULL pointer. */REFERENCE **info_xrefs_of_node (node) NODE *node;{ SEARCH_BINDING search;#if defined (HANDLE_MAN_PAGES) if (node->flags & N_IsManPage) return (xrefs_of_manpage (node));#endif search.buffer = node->contents; search.start = 0; search.end = node->nodelen; search.flags = S_FoldCase; return (info_xrefs (&search));}/* Glean menu entries from BINDING->buffer + BINDING->start until we have looked at the entire contents of BINDING. Return an array of REFERENCE * that represents each menu item in this range. */REFERENCE **info_menu_items (binding) SEARCH_BINDING *binding;{ return (info_references_internal (INFO_MENU_ENTRY_LABEL, binding));}/* Glean cross references from BINDING->buffer + BINDING->start until BINDING->end. Return an array of REFERENCE * that represents each cross reference in this range. */REFERENCE **info_xrefs (binding) SEARCH_BINDING *binding;{ return (info_references_internal (INFO_XREF_LABEL, binding));}/* Glean cross references or menu items from BINDING. Return an array of REFERENCE * that represents the items found. */static REFERENCE **info_references_internal (label, binding) char *label; SEARCH_BINDING *binding;{ SEARCH_BINDING search; REFERENCE **refs = (REFERENCE **)NULL; int refs_index = 0, refs_slots = 0; int searching_for_menu_items = 0; long position; search.buffer = binding->buffer; search.start = binding->start; search.end = binding->end; search.flags = S_FoldCase | S_SkipDest; searching_for_menu_items = (strcasecmp (label, INFO_MENU_ENTRY_LABEL) == 0); while ((position = search_forward (label, &search)) != -1) { int offset, start; char *refdef; REFERENCE *entry; search.start = position; search.start += skip_whitespace (search.buffer + search.start); start = search.start - binding->start; refdef = search.buffer + search.start; offset = string_in_line (":", refdef); /* When searching for menu items, if no colon, there is no menu item on this line. */ if (offset == -1) { if (searching_for_menu_items) continue; else { int temp; temp = skip_line (refdef); offset = string_in_line (":", refdef + temp); if (offset == -1) continue; /* Give up? */ else offset += temp; } } entry = (REFERENCE *)xmalloc (sizeof (REFERENCE)); entry->filename = (char *)NULL; entry->nodename = (char *)NULL; entry->label = (char *)xmalloc (offset); strncpy (entry->label, refdef, offset - 1); entry->label[offset - 1] = '\0'; canonicalize_whitespace (entry->label); refdef += offset; entry->start = start; entry->end = refdef - binding->buffer; /* If this reference entry continues with another ':' then the nodename is the same as the label. */ if (*refdef == ':') { entry->nodename = xstrdup (entry->label); } else { /* This entry continues with a specific nodename. Parse the nodename from the specification. */ refdef += skip_whitespace_and_newlines (refdef); if (searching_for_menu_items) info_parse_node (refdef, DONT_SKIP_NEWLINES); else info_parse_node (refdef, SKIP_NEWLINES); if (info_parsed_filename) entry->filename = xstrdup (info_parsed_filename); if (info_parsed_nodename) entry->nodename = xstrdup (info_parsed_nodename); } add_pointer_to_array (entry, refs_index, refs, refs_slots, 50, REFERENCE *); } return (refs);}/* Get the entry associated with LABEL in MENU. Return a pointer to the REFERENCE if found, or NULL. */REFERENCE *info_get_labeled_reference (label, references) char *label; REFERENCE **references;{ register int i; REFERENCE *entry; for (i = 0; references && (entry = references[i]); i++) { if (strcmp (label, entry->label) == 0) return (entry); } return ((REFERENCE *)NULL);}/* A utility function for concatenating REFERENCE **. Returns a new REFERENCE ** which is the concatenation of REF1 and REF2. The REF1 and REF2 arrays are freed, but their contents are not. */REFERENCE **info_concatenate_references (ref1, ref2) REFERENCE **ref1, **ref2;{ register int i, j; REFERENCE **result; int size; /* With one argument passed as NULL, simply return the other arg. */ if (!ref1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -