# HG changeset patch # User jwe # Date 870640823 0 # Node ID 5e4b19abfeb1e1068b9fc0fc4db5ea18504d4d7d # Parent bb05bfa835c97573663c513d70f15143baf86de5 [project @ 1997-08-03 20:40:16 by jwe] diff --git a/info/ChangeLog b/info/ChangeLog deleted file mode 100644 --- a/info/ChangeLog +++ /dev/null @@ -1,89 +0,0 @@ -Sun Mar 16 14:07:05 1997 John W. Eaton - - * terminal.c: Include infomap.h here. - (terminal_prep_terminal): Use DEL instead of '\177'. - Also disable Control-C as quit or interrupt character. - -Wed Mar 12 17:00:24 1997 John W. Eaton - - * Makefile.in (install-strip): New target. - -Wed Feb 26 12:30:51 1997 John W. Eaton - - * Makefile.in (maintainer-clean): New target. - -Sat Jan 25 22:33:43 1997 John W. Eaton - - * Makefile.in (bin-dist): New target. - -Sat Jan 18 15:57:49 1997 John W. Eaton - - * Makefile.in (MAKEDOC_OBJECTS): Also include $(LIBOBJS). - -Wed Jan 15 14:52:23 1997 John W. Eaton - - * Makefile.in (LIBOBJS): Allow substitution. - (SRCS): Add memcpy.c, memmove.c, and strdup.c to the list. - -Mon Jan 6 19:14:49 1997 John W. Eaton - - * terminal.c (terminal_prep_terminal): Only delete OCRNL from - ttybuff.c_oflag if it is defined. - -Mon Dec 9 14:20:01 1996 John W. Eaton - - * Makefile.in (install): Use $(EXE) suffix so that install will - find the right file on cygwin32 systems. - -Mon Dec 2 13:48:57 1996 John W. Eaton - - * configure.in: Check for gethostname in libsocket.a, for SCO. - - * termdep.h: Don't use termios.h on SCO systems. - -Sun Nov 24 21:24:39 1996 John W. Eaton - - * configure.in (TERMLIBS): Look for ncurses too. - -Tue Nov 12 14:44:00 1996 John W. Eaton - - * Makefile.in (VPATH): Don't include $(common). - (common): Don't define. - (makeinfo): Define to just be makeinfo. - (LIBS): Don't use libtxi. - (info): Don't depend on ../libtxi.a. - (info.o): Depend on getopt.h, not $(common)/getopt.h. - (.c.o): Don't add -I$(common). - (install, uninstall, dist, local-dist): Customize for Octave. - (TOPDIR, top_srcdir, DISTFILES): For Octave. - Include $(TOPDIR)/Makeconf, for Octave. - Don't add $(common) for dvi or info targets. - (Makefile): Depend on Makefile.in and config.status. - - * configure.in: Copy here from (in texinfo distribution). - - * alloca.c, bzero.c, getopt.c, getopt.h, getopt1.c, memcpy.c, - memmove.c, str - dup.c: Copy here from ../libtxi (in texinfo - distribution). - * Makefile.in: Don't link to files in libtxi. Instead, include - them in SRCS, HDRS, and OBJS. - - * session.c (initialize_info_session): New arg, - clear_screen. Change all callers. - - * info.c (main): Handle new option, --index-search STRING. - (index_search_p, index_search_string): New static variables, used - to handle --index-search option. - - * indices.h (do_info_index_search, index_intry_exists): - Provide declarations here. - - * indices.c (do_info_index_search): New function, extracted - from info_index_search. - (info_index_search): Simply call do_info_index_search() with - search_string set to NULL. - (index_entry_exists): New function. - -For a list of other changes, see the ChangeLog from the texinfo-3.9 -distribution. diff --git a/info/Makefile.in b/info/Makefile.in deleted file mode 100644 --- a/info/Makefile.in +++ /dev/null @@ -1,247 +0,0 @@ -# Makefile for texinfo/info. -*- Indented-Text -*- -# $Id: Makefile.in,v 1.43 1997-06-05 06:35:11 jwe Exp $ -# -# Copyright (C) 1993,96 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. - -#### Start of system configuration section. #### - -TOPDIR = .. - -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ -VPATH = @srcdir@ - -include $(TOPDIR)/Makeconf - -CC = @CC@ - -INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_DATA = @INSTALL_DATA@ - -LN = ln -RM = rm -f -MKDIR = mkdir -MAKEINFO= makeinfo - -DEFS = @DEFS@ - -LDEFS = -DHANDLE_MAN_PAGES -DNAMED_FUNCTIONS=1 -DDEFAULT_INFOPATH='"$(DEFAULT_INFOPATH)"' - -TERMLIBS = @TERMLIBS@ -LIBS = $(TERMLIBS) @LIBS@ -LOADLIBES = $(LIBS) - -LIBOBJS = @LIBOBJS@ - -SHELL = /bin/sh - -CFLAGS = @CFLAGS@ -LDFLAGS = @LDFLAGS@ - -prefix = @prefix@ -exec_prefix = @exec_prefix@ -bindir = $(exec_prefix)/bin -# Prefix for each installed program, normally empty or `g'. -binprefix = -# Prefix for each installed man page, normally empty or `g'. -manprefix = -mandir = $(prefix)/man/man1 -manext = 1 -infodir = $(prefix)/info -DEFAULT_INFOPATH= $(infodir):. - -#### End of system configuration section. #### - -SRCS = dir.c display.c echo_area.c filesys.c \ - info-utils.c info.c infodoc.c infomap.c \ - m-x.c nodes.c search.c session.c \ - signals.c terminal.c tilde.c window.c \ - xmalloc.c indices.c makedoc.c nodemenu.c \ - footnotes.c dribble.c variables.c gc.c man.c \ - clib.c getopt.c getopt1.c bzero.c \ - memcpy.c memmove.c strdup.c - -HDRS = display.h doc.h echo_area.h filesys.h \ - general.h getopt.h info-utils.h info.h \ - infomap.h nodes.h search.h session.h \ - signals.h termdep.h terminal.h tilde.h \ - indices.h window.h footnotes.h dribble.h \ - variables.h gc.h clib.h man.h - -OBJS = dir.o display.o doc.o echo_area.o filesys.o info-utils.o info.o \ - infodoc.o infomap.o m-x.o nodes.o search.o session.o signals.o \ - terminal.o tilde.o window.o indices.o xmalloc.o nodemenu.o \ - footnotes.o dribble.o variables.o gc.o man.o clib.o \ - getopt.o getopt1.o bzero.o $(ALLOCA) $(LIBOBJS) - -# The names of files which declare info commands. -CMDFILES = $(srcdir)/session.c $(srcdir)/echo_area.c $(srcdir)/infodoc.c \ - $(srcdir)/m-x.c $(srcdir)/indices.c $(srcdir)/nodemenu.c \ - $(srcdir)/footnotes.c $(srcdir)/variables.c - -# The name of the program which builds documentation structure from CMDFILES. -MAKEDOC_OBJECTS = makedoc.o clib.o xmalloc.o $(LIBOBJS) -MAKEDOC_SOURCE = makedoc.c clib.c xmalloc.c - -infofiles = info.info info-stnd.info - -TEXINFO = info.texi info-stnd.texi - -DVI = info.dvi info-stnd.dvi - -DISTFILES = Makefile.in ChangeLog README NEWS info.1 configure.in \ - configure mkinstalldirs $(SRCS) $(HDRS) $(infofiles) $(TEXINFO) $(DVI) - -BINDISTFILES = info - -%.o : %.c - $(CC) -c $(CPPFLAGS) $(LDEFS) $(DEFS) -I. -I$(srcdir) $(CFLAGS) $< - -all: info $(infofiles) -sub-all: all - -install: - $(top_srcdir)/mkinstalldirs $(archlibdir) - $(INSTALL_PROGRAM) info$(EXE) $(archlibdir)/info$(EXE) - -install-strip: - $(MAKE) INSTALL_PROGRAM="$(INSTALL_PROGRAM) -s" install - -uninstall: - rm -f $(archlibdir)/info - -info: $(OBJS) - $(CC) $(LDFLAGS) -o info $(OBJS) $(LOADLIBES) - -all-info: info.info info-stnd.info - -info.info: info.texi - $(MAKEINFO) --no-split -I$(srcdir) info.texi - -info-stnd.info: info-stnd.texi - $(MAKEINFO) --no-split -I$(srcdir) info-stnd.texi - -dvi all-dvi: info.dvi info-stnd.dvi -info.dvi: info.texi - PATH="$(util):$${PATH}" TEXINPUTS="$(srcdir):$${TEXINPUTS}" texi2dvi $(srcdir)/info.texi - -info-stnd.dvi: info-stnd.texi - PATH="$(util):$${PATH}" TEXINPUTS="$(srcdir):$${TEXINPUTS}" texi2dvi $(srcdir)/info-stnd.texi - -makedoc: $(MAKEDOC_OBJECTS) - $(CC) $(LDFLAGS) -o makedoc $(MAKEDOC_OBJECTS) $(LOADLIBES) - -Makefile: Makefile.in config.status - cd ..; sh config.status - -clean: - $(RM) info funs.h doc.c makedoc $(OBJS) $(MAKEDOC_OBJECTS) - -distclean: clean texclean - $(RM) Makefile config.status config.cache *~ core core.* *.core - $(RM) *.BAK makedoc-TAGS TAGS \#* *.info* - -mostlyclean: clean - -maintainer-clean realclean: distclean - $(RM) info.info info-stnd.info $(DVI) config.h configure config.h.in - -dist: all-info all-dvi - ln $(DISTFILES) ../`cat ../.fname`/info -.PHONY: dist - -bin-dist: - if [ -n "$(BINDISTFILES)" ]; then \ - ln $(BINDISTFILES) ../`cat ../.fname`/info; \ - fi -.PHONY: bin-dist - -TAGS: $(SRCS) makedoc-TAGS - etags $(SRCS) - cat makedoc-TAGS >>TAGS && $(RM) makedoc-TAGS - -makedoc-TAGS: $(CMDFILES) - ./makedoc -tags $(CMDFILES) >makedoc-TAGS - -texclean: - $(RM) *.toc *.aux *.log *.cp *.fn *.tp *.vr *.pg *.ky *.cps - $(RM) *.tps *.fns *.kys *.pgs *.vrs - -check: info - -# The files `doc.c' and `funs.h' are created by ./makedoc run over the source -# files which contain DECLARE_INFO_COMMAND. `funs.h' is a header file -# listing the functions found. `doc.c' is a structure containing pointers -# to those functions along with completable names and documentation strings. -funs.h: makedoc $(CMDFILES) - -@if test -f funs.h; then mv -f funs.h old-funs.h; fi; : - -@if test -f doc.c; then mv -f doc.c old-doc.c; fi; : - ./makedoc $(CMDFILES) - -@if cmp -s old-funs.h funs.h; then mv old-funs.h funs.h; \ - else $(RM) old-funs.h; fi; : - -@if cmp -s old-doc.c doc.c; then mv old-doc.c doc.c; \ - else $(RM) old-doc.c; fi; : - -doc.c: funs.h -dribble.o: dribble.c dribble.h -display.o: display.c -echo_area.o: echo_area.c -filesys.o: filesys.c -info-utils.o: info-utils.c -info.o: info.c filesys.h -infodoc.o: infodoc.c -infomap.o: infomap.c -m-x.o: m-x.c -nodes.o: nodes.c -search.o: search.c -session.o: session.c -signals.o: signals.c -terminal.o: terminal.c -tilde.o: tilde.c -window.o: window.c -xmalloc.o: xmalloc.c -indices.o: indices.c -makedoc.o: makedoc.c - -dir.o: dir.c -display.o: nodes.h info-utils.h search.h -display.o: terminal.h window.h display.h -echo_area.o: info.h -filesys.o: general.h tilde.h filesys.h -footnotes.o: footnotes.h -info-utils.o: info-utils.h nodes.h search.h -info.o: info.h getopt.h -infodoc.o: info.h doc.h -infomap.o: infomap.h funs.h -gc.o: info.h -m-x.o: info.h -nodes.o: search.h filesys.h -nodes.o: nodes.h info-utils.h -search.o: general.h search.h nodes.h -session.o: info.h -signals.o: info.h signals.h -terminal.o: terminal.h termdep.h -tilde.o: tilde.h -variables.c: variables.h -window.o: nodes.h window.h display.h -window.o: info-utils.h search.h infomap.h - -# Prevent GNU make v3 from overflowing arg limit on SysV. -.NOEXPORT: - -# eof diff --git a/info/NEWS b/info/NEWS deleted file mode 100644 --- a/info/NEWS +++ /dev/null @@ -1,200 +0,0 @@ -This release of Info is version 2.11. Please read the file README. - -Version 2.11, Sat Apr 1 09:15:21 1995 - -Changes since 2.7 beta: - -Although the basic code remains the same, there are numerous nits -fixed, including some display bugs, and a memory leak. Some changes -that have taken place with larger impact include the way in which the -(dir) node is built; I have added in support for "localdir" -directories among other things. Info files may be stored in -compressed formats, and in their own subdirectories; menu items which -do not explicitly name the node to which they are attached have the -menu item name looked up as an Info file if it is not found within the -current document. This means that the menu item: - -* Info:: The Info documentation reader. - -in (dir) refers to the info node "(info)Top". - -Please see the ChangeLog and documentation for details on other -changes. - -Version 2.7 beta, Wed Dec 30 02:02:38 1992 -Version 2.6 beta, Tue Dec 22 03:58:07 1992 -Version 2.5 beta, Tue Dec 8 14:50:35 1992 -Version 2.4 beta, Sat Nov 28 14:34:02 1992 -Version 2.3 beta, Fri Nov 27 01:04:13 1992 -Version 2.2 beta, Tue Nov 24 09:36:08 1992 -Version 2.1 beta, Tue Nov 17 23:29:36 1992 - -Changes since 2.5 beta: - -Note that versions 2.6 and 2.7 Beta were only released to a select group. - -* "info-" removed from the front of M-x commands. - -* Automatic footnote display. When you enter a node which contains - footnotes, and the variable "automatic-footnotes" is "On", Info pops - up a window containing the footnotes. Likewise, when you leave that - node, the window containing the footnotes goes away. - -* Cleaner built in documentation, and documentation functions. - - Use: - o `M-x describe-variable' to read a variable's documenation - o `M-x describe-key' to find out what a particular keystroke does. - o `M-x describe-function' to read a function's documentation. - o `M-x where-is' to find out what keys invoke a particular function. - -* Info can "tile" the displayed windows (via "M-x tile-windows"). If - the variable "automatic-tiling" is "On", then splitting a window or - deleting a window causes the remaining windows to be retiled. - -* You can save every keystroke you type in a "dribble file" by using the - `--dribble FILENAME' option. You can initially read keystrokes from an - alternate input stream with `--restore FILENAME', or by redirecting - input on the command line `info < old-dribble'. - -* New behaviour of menu items. If the label is the same as the - target node name, and the node couldn't be found in the current file, - treat the label as a file name. For example, a menu entry in "DIR" - might contain: - - * Emacs:: Cool text-editor. - - Info would not find the node "(dir)Emacs", so just plain "(emacs)" - would be tried. - -* New variable "ISO-Latin" allows you to use European machines with - 8-bit character sets. - -* Cleanups in echo area reading, and redisplay. Cleanups in handling the - window which shows possible completions. - -* Info can now read files that have been compressed. An array in filesys.c - maps extensions to programs that can decompress stdin, and write the results - to stdout. Currently, ".Z"/uncompress, ".z"/gunzip, and ".Y"/unyabba are - supported. The modeline for a compressed file shows "zz" in it. - -* There is a new variable "gc-compressed-files" which, if non-zero, says - it is okay to reclaim the file buffer space allocated to a file which - was compressed, if, and only if, that file's contents do not appear in - any history node. - -* New file `nodemenu.c' implements a few functions for manipulating - previously visited nodes. `C-x C-b' (list-visited-nodes) produces a - menu of the nodes that could be reached by info-history-node in some - window. `C-x b' (select-visited-node) is similar, but reads one of - the node names with completion. - -* Keystroke `M-r' (move_to_screen_line) allows the user to place the cursor at - the start of a specific screen line. Without a numeric argument, place the - cursor on the center line; with an arg, place the cursor on that line. - -* Interruptible display implemented. Basic display speedups and hacks. -* The message "*** Tags Out of Date ***" now means what it says. -* Index searching with `,' (info-index-next) has been improved. -* When scrolling with C-v, C-M-v, or M-v, only "Page Only" scrolling - will happen. - -* Continous scrolling (along with `]' (info-global-next) and `[' - (info-global-prev) works better. `]' and `[' accept numeric - arguments, moving that many nodes in that case. - -* `C-x w' (info-toggle-wrap) controls how lines wider than the width - of the screen are displayed. If a line is too long, a `$' is - displayed in the rightmost column of the window. - -* There are some new variables for controlling the behaviour of Info - interactively. The current list of variables is as follows: - - Variable Name Default Value Description - ------------- ------------- ----------- - `automatic-footnotes' On When "On", footnotes appear and - disappear automatically. - - `automatic-tiling' Off When "On", creating of deleting a - window resizes other windows. - - `visible-bell' Off If non-zero, try to use a visible bell. - - `errors-ring-bell' On If non-zero, errors cause a ring. - - `show-index-match' On If non-zero, the portion of the string - matched is highlighted by changing its - case. - - `scroll-behaviour' Continuous One of "Continuous", "Next Only", or - "Page Only". "Page Only" prevents you from - scrolling past the bottom or top of a node. - "Next Only" causes the Next or Prev node to - be selected when you scroll past the bottom - or top of a node. "Continous" moves - linearly through the files hierchichal - structure. - - `scroll-step' 0 Controls how scrolling is done for you when - the cursor moves out of the current window. - Non-zero means it is the number of lines - you would like the screen to shift. A - value of 0 means to center the line - containing the cursor in the window. - - `gc-compressed-files' Off If non-zero means it is okay to reclaim the - file buffer space allocated to a file which - was compressed, if, and only if, that - file's contents do not appear in the node - list of any window. - - `ISO-Latin' Off Non-zero means that you are using an ISO - Latin character set. By default, standard - ASCII characters are assumed. -________________________________________ -This release of Info is version 2.5 beta. - -Changes since 2.4 beta: - -* Index (i) and (,) commands fully implemented. -* "configure" script now shipped with Info. -* New function "set-variable" allows users to set various variables. -* User-settable behaviour on end or beginning of node scrolling. This - supercedes the SPC and DEL changes in 2.3 beta. - -________________________________________ -This release of Info is version 2.4 beta. - -Changes since 2.3 beta: - -* info-last-node now means move to the last node of this info file. -* info-history-node means move backwards through this window's node history. -* info-first-node moves to the first node in the Info file. This node is - not necessarily "Top"! -* SPC and DEL can select the Next or Prev node after printing an informative - message when pressed at the end/beg of a node. - ----------------------------------------- -This release of Info is version 2.3 beta. - -Changes since 2.2 beta: - -* M-x command lines if NAMED_COMMANDS is #defined. Variable in Makefile. -* Screen height changes made quite robust. -* Interactive function "set-screen-height" implements user height changes. -* Scrolling on some terminals is faster now. -* C-l with numeric arguement is fixed. - ----------------------------------------- -This release of Info is version 2.2 beta. - -Changes since 2.0: - -* C-g can now interrupt multi-file searches. -* Incremental search is fully implemented. -* Loading large tag tables is much faster now. -* makedoc.c replaces shell script, speeding incremental builds. -* Scrolling in redisplay is implemented. -* Recursive uses of the echo area made more robust. -* Garbage collection of unreferenced nodes. - diff --git a/info/README b/info/README deleted file mode 100644 --- a/info/README +++ /dev/null @@ -1,37 +0,0 @@ -The file NEWS contains information about what has changed since the last -release. - -The file ../INSTALL contains instructions on how to install Info. - - -Info 2.0 is a complete rewrite of the original standalone Info I wrote in -1987, the first program I wrote for rms. That program was something like -my second Unix program ever, and my die-hard machine language coding habits -tended to show through. I found the original Info hard to read and -maintain, and thus decided to write this one. - -The rewrite consists of about 12,000 lines of code written in about 12 -days. I believe this version of Info to be in much better shape than the -original Info, and the only reason it is in Beta test is because of its -short life span. - -Info 2.0 is substantially different from its original standalone -predecessor. It appears almost identical to the GNU Emacs version, but has -the advantages of smaller size, ease of portability, and a built in library -which can be used in other programs (to get or display documentation from -Info files, for example). - -I eagerly await responses to this newer version of Info; comments on its -portability, ease of use and user interface, code quality, and general -usefulness are all of interest to me, and I will appreciate any comments -that you would care to make. - -A full listing of the commands available in Info can be gotten by typing -`?' while within an Info window. This produces a node in a window which -can be viewed just like any Info node. - -Please send your comments, bug reports, and suggestions to - - bug-texinfo@prep.ai.mit.edu - ---Brian Fox diff --git a/info/alloca.c b/info/alloca.c deleted file mode 100644 --- a/info/alloca.c +++ /dev/null @@ -1,504 +0,0 @@ -/* alloca.c -- allocate automatically reclaimed memory - (Mostly) portable public-domain implementation -- D A Gwyn - - This implementation of the PWB library alloca function, - which is used to allocate space off the run-time stack so - that it is automatically reclaimed upon procedure exit, - was inspired by discussions with J. Q. Johnson of Cornell. - J.Otto Tennant contributed the Cray support. - - There are some preprocessor constants that can - be defined when compiling for your specific system, for - improved efficiency; however, the defaults should be okay. - - The general concept of this implementation is to keep - track of all alloca-allocated blocks, and reclaim any - that are found to be deeper in the stack than the current - invocation. This heuristic does not reclaim storage as - soon as it becomes invalid, but it will do so eventually. - - As a special case, alloca(0) reclaims storage without - allocating any. It is a good idea to use alloca(0) in - your main control loop, etc. to force garbage collection. */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif - -#ifdef emacs -#include "blockinput.h" -#endif - -/* If compiling with GCC 2, this file's not needed. */ -#if !defined (__GNUC__) || __GNUC__ < 2 - -/* If someone has defined alloca as a macro, - there must be some other way alloca is supposed to work. */ -#ifndef alloca - -#ifdef emacs -#ifdef static -/* actually, only want this if static is defined as "" - -- this is for usg, in which emacs must undefine static - in order to make unexec workable - */ -#ifndef STACK_DIRECTION -you -lose --- must know STACK_DIRECTION at compile-time -#endif /* STACK_DIRECTION undefined */ -#endif /* static */ -#endif /* emacs */ - -/* If your stack is a linked list of frames, you have to - provide an "address metric" ADDRESS_FUNCTION macro. */ - -#if defined (CRAY) && defined (CRAY_STACKSEG_END) -long i00afunc (); -#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg)) -#else -#define ADDRESS_FUNCTION(arg) &(arg) -#endif - -#if __STDC__ -typedef void *pointer; -#else -typedef char *pointer; -#endif - -#ifndef NULL -#define NULL 0 -#endif - -/* Different portions of Emacs need to call different versions of - malloc. The Emacs executable needs alloca to call xmalloc, because - ordinary malloc isn't protected from input signals. On the other - hand, the utilities in lib-src need alloca to call malloc; some of - them are very simple, and don't have an xmalloc routine. - - Non-Emacs programs expect this to call use xmalloc. - - Callers below should use malloc. */ - -#ifndef emacs -#define malloc xmalloc -#endif -extern pointer malloc (); - -/* Define STACK_DIRECTION if you know the direction of stack - growth for your system; otherwise it will be automatically - deduced at run-time. - - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown */ - -#ifndef STACK_DIRECTION -#define STACK_DIRECTION 0 /* Direction unknown. */ -#endif - -#if STACK_DIRECTION != 0 - -#define STACK_DIR STACK_DIRECTION /* Known at compile-time. */ - -#else /* STACK_DIRECTION == 0; need run-time code. */ - -static int stack_dir; /* 1 or -1 once known. */ -#define STACK_DIR stack_dir - -static void -find_stack_direction () -{ - static char *addr = NULL; /* Address of first `dummy', once known. */ - auto char dummy; /* To get stack address. */ - - if (addr == NULL) - { /* Initial entry. */ - addr = ADDRESS_FUNCTION (dummy); - - find_stack_direction (); /* Recurse once. */ - } - else - { - /* Second entry. */ - if (ADDRESS_FUNCTION (dummy) > addr) - stack_dir = 1; /* Stack grew upward. */ - else - stack_dir = -1; /* Stack grew downward. */ - } -} - -#endif /* STACK_DIRECTION == 0 */ - -/* An "alloca header" is used to: - (a) chain together all alloca'ed blocks; - (b) keep track of stack depth. - - It is very important that sizeof(header) agree with malloc - alignment chunk size. The following default should work okay. */ - -#ifndef ALIGN_SIZE -#define ALIGN_SIZE sizeof(double) -#endif - -typedef union hdr -{ - char align[ALIGN_SIZE]; /* To force sizeof(header). */ - struct - { - union hdr *next; /* For chaining headers. */ - char *deep; /* For stack depth measure. */ - } h; -} header; - -static header *last_alloca_header = NULL; /* -> last alloca header. */ - -/* Return a pointer to at least SIZE bytes of storage, - which will be automatically reclaimed upon exit from - the procedure that called alloca. Originally, this space - was supposed to be taken from the current stack frame of the - caller, but that method cannot be made to work for some - implementations of C, for example under Gould's UTX/32. */ - -pointer -alloca (size) - unsigned size; -{ - auto char probe; /* Probes stack depth: */ - register char *depth = ADDRESS_FUNCTION (probe); - -#if STACK_DIRECTION == 0 - if (STACK_DIR == 0) /* Unknown growth direction. */ - find_stack_direction (); -#endif - - /* Reclaim garbage, defined as all alloca'd storage that - was allocated from deeper in the stack than currently. */ - - { - register header *hp; /* Traverses linked list. */ - -#ifdef emacs - BLOCK_INPUT; -#endif - - for (hp = last_alloca_header; hp != NULL;) - if ((STACK_DIR > 0 && hp->h.deep > depth) - || (STACK_DIR < 0 && hp->h.deep < depth)) - { - register header *np = hp->h.next; - - free ((pointer) hp); /* Collect garbage. */ - - hp = np; /* -> next header. */ - } - else - break; /* Rest are not deeper. */ - - last_alloca_header = hp; /* -> last valid storage. */ - -#ifdef emacs - UNBLOCK_INPUT; -#endif - } - - if (size == 0) - return NULL; /* No allocation required. */ - - /* Allocate combined header + user data storage. */ - - { - register pointer new = malloc (sizeof (header) + size); - /* Address of header. */ - - if (new == 0) - abort(); - - ((header *) new)->h.next = last_alloca_header; - ((header *) new)->h.deep = depth; - - last_alloca_header = (header *) new; - - /* User storage begins just after header. */ - - return (pointer) ((char *) new + sizeof (header)); - } -} - -#if defined (CRAY) && defined (CRAY_STACKSEG_END) - -#ifdef DEBUG_I00AFUNC -#include -#endif - -#ifndef CRAY_STACK -#define CRAY_STACK -#ifndef CRAY2 -/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */ -struct stack_control_header - { - long shgrow:32; /* Number of times stack has grown. */ - long shaseg:32; /* Size of increments to stack. */ - long shhwm:32; /* High water mark of stack. */ - long shsize:32; /* Current size of stack (all segments). */ - }; - -/* The stack segment linkage control information occurs at - the high-address end of a stack segment. (The stack - grows from low addresses to high addresses.) The initial - part of the stack segment linkage control information is - 0200 (octal) words. This provides for register storage - for the routine which overflows the stack. */ - -struct stack_segment_linkage - { - long ss[0200]; /* 0200 overflow words. */ - long sssize:32; /* Number of words in this segment. */ - long ssbase:32; /* Offset to stack base. */ - long:32; - long sspseg:32; /* Offset to linkage control of previous - segment of stack. */ - long:32; - long sstcpt:32; /* Pointer to task common address block. */ - long sscsnm; /* Private control structure number for - microtasking. */ - long ssusr1; /* Reserved for user. */ - long ssusr2; /* Reserved for user. */ - long sstpid; /* Process ID for pid based multi-tasking. */ - long ssgvup; /* Pointer to multitasking thread giveup. */ - long sscray[7]; /* Reserved for Cray Research. */ - long ssa0; - long ssa1; - long ssa2; - long ssa3; - long ssa4; - long ssa5; - long ssa6; - long ssa7; - long sss0; - long sss1; - long sss2; - long sss3; - long sss4; - long sss5; - long sss6; - long sss7; - }; - -#else /* CRAY2 */ -/* The following structure defines the vector of words - returned by the STKSTAT library routine. */ -struct stk_stat - { - long now; /* Current total stack size. */ - long maxc; /* Amount of contiguous space which would - be required to satisfy the maximum - stack demand to date. */ - long high_water; /* Stack high-water mark. */ - long overflows; /* Number of stack overflow ($STKOFEN) calls. */ - long hits; /* Number of internal buffer hits. */ - long extends; /* Number of block extensions. */ - long stko_mallocs; /* Block allocations by $STKOFEN. */ - long underflows; /* Number of stack underflow calls ($STKRETN). */ - long stko_free; /* Number of deallocations by $STKRETN. */ - long stkm_free; /* Number of deallocations by $STKMRET. */ - long segments; /* Current number of stack segments. */ - long maxs; /* Maximum number of stack segments so far. */ - long pad_size; /* Stack pad size. */ - long current_address; /* Current stack segment address. */ - long current_size; /* Current stack segment size. This - number is actually corrupted by STKSTAT to - include the fifteen word trailer area. */ - long initial_address; /* Address of initial segment. */ - long initial_size; /* Size of initial segment. */ - }; - -/* The following structure describes the data structure which trails - any stack segment. I think that the description in 'asdef' is - out of date. I only describe the parts that I am sure about. */ - -struct stk_trailer - { - long this_address; /* Address of this block. */ - long this_size; /* Size of this block (does not include - this trailer). */ - long unknown2; - long unknown3; - long link; /* Address of trailer block of previous - segment. */ - long unknown5; - long unknown6; - long unknown7; - long unknown8; - long unknown9; - long unknown10; - long unknown11; - long unknown12; - long unknown13; - long unknown14; - }; - -#endif /* CRAY2 */ -#endif /* not CRAY_STACK */ - -#ifdef CRAY2 -/* Determine a "stack measure" for an arbitrary ADDRESS. - I doubt that "lint" will like this much. */ - -static long -i00afunc (long *address) -{ - struct stk_stat status; - struct stk_trailer *trailer; - long *block, size; - long result = 0; - - /* We want to iterate through all of the segments. The first - step is to get the stack status structure. We could do this - more quickly and more directly, perhaps, by referencing the - $LM00 common block, but I know that this works. */ - - STKSTAT (&status); - - /* Set up the iteration. */ - - trailer = (struct stk_trailer *) (status.current_address - + status.current_size - - 15); - - /* There must be at least one stack segment. Therefore it is - a fatal error if "trailer" is null. */ - - if (trailer == 0) - abort (); - - /* Discard segments that do not contain our argument address. */ - - while (trailer != 0) - { - block = (long *) trailer->this_address; - size = trailer->this_size; - if (block == 0 || size == 0) - abort (); - trailer = (struct stk_trailer *) trailer->link; - if ((block <= address) && (address < (block + size))) - break; - } - - /* Set the result to the offset in this segment and add the sizes - of all predecessor segments. */ - - result = address - block; - - if (trailer == 0) - { - return result; - } - - do - { - if (trailer->this_size <= 0) - abort (); - result += trailer->this_size; - trailer = (struct stk_trailer *) trailer->link; - } - while (trailer != 0); - - /* We are done. Note that if you present a bogus address (one - not in any segment), you will get a different number back, formed - from subtracting the address of the first block. This is probably - not what you want. */ - - return (result); -} - -#else /* not CRAY2 */ -/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP. - Determine the number of the cell within the stack, - given the address of the cell. The purpose of this - routine is to linearize, in some sense, stack addresses - for alloca. */ - -static long -i00afunc (long address) -{ - long stkl = 0; - - long size, pseg, this_segment, stack; - long result = 0; - - struct stack_segment_linkage *ssptr; - - /* Register B67 contains the address of the end of the - current stack segment. If you (as a subprogram) store - your registers on the stack and find that you are past - the contents of B67, you have overflowed the segment. - - B67 also points to the stack segment linkage control - area, which is what we are really interested in. */ - - stkl = CRAY_STACKSEG_END (); - ssptr = (struct stack_segment_linkage *) stkl; - - /* If one subtracts 'size' from the end of the segment, - one has the address of the first word of the segment. - - If this is not the first segment, 'pseg' will be - nonzero. */ - - pseg = ssptr->sspseg; - size = ssptr->sssize; - - this_segment = stkl - size; - - /* It is possible that calling this routine itself caused - a stack overflow. Discard stack segments which do not - contain the target address. */ - - while (!(this_segment <= address && address <= stkl)) - { -#ifdef DEBUG_I00AFUNC - fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl); -#endif - if (pseg == 0) - break; - stkl = stkl - pseg; - ssptr = (struct stack_segment_linkage *) stkl; - size = ssptr->sssize; - pseg = ssptr->sspseg; - this_segment = stkl - size; - } - - result = address - this_segment; - - /* If you subtract pseg from the current end of the stack, - you get the address of the previous stack segment's end. - This seems a little convoluted to me, but I'll bet you save - a cycle somewhere. */ - - while (pseg != 0) - { -#ifdef DEBUG_I00AFUNC - fprintf (stderr, "%011o %011o\n", pseg, size); -#endif - stkl = stkl - pseg; - ssptr = (struct stack_segment_linkage *) stkl; - size = ssptr->sssize; - pseg = ssptr->sspseg; - result += size; - } - return (result); -} - -#endif /* not CRAY2 */ -#endif /* CRAY */ - -#endif /* no alloca */ -#endif /* not GCC version 2 */ diff --git a/info/bzero.c b/info/bzero.c deleted file mode 100644 --- a/info/bzero.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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, you can either send email to this - * program's author (see below) or write to: The Free Software Foundation, - * Inc.; 59 Temple Place - Suite 330. Boston, MA 02111-1307, USA. - */ - -#if !defined (HAVE_MEMSET) && !defined (HAVE_BZERO) - -void -bzero (b, length) - register char *b; - register int length; -{ -#ifdef VMS /* but this is definitely VMS-specific */ - short zero = 0; - long max_str = 65535; - - while (length > max_str) - { - (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b); - length -= max_str; - b += max_str; - } - (void) LIB$MOVC5 (&zero, &zero, &zero, &length, b); -#else - while (length-- > 0) - *b++ = 0; -#endif /* not VMS */ -} - -#endif /* not HAVE_MEMSET && not HAVE_BZERO */ diff --git a/info/clib.c b/info/clib.c deleted file mode 100644 --- a/info/clib.c +++ /dev/null @@ -1,112 +0,0 @@ -/* clib.c: Functions which we normally expect to find in the C library. - $Id: clib.c,v 1.1 1996-11-13 03:41:37 jwe Exp $ - - This file is part of GNU Info, a program for reading online documentation - stored in Info format. - - Copyright (C) 1995 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 - -#if defined (HAVE_UNISTD_H) -#include -#endif - -#if defined (HAVE_STDLIB_H) -#include -#endif - -#if defined (HAVE_STRING_H) -#include -#endif - -#include - -extern void *xmalloc (), *xrealloc (); -#include "general.h" - -#if !defined (errno) -extern int errno; -#endif - -#if !defined (HAVE_STRERROR) -extern char *sys_errlist[]; -extern int sys_nerr; - -char * -strerror (num) - int num; -{ - if (num >= sys_nerr) - return (""); - else - return (sys_errlist[num]); -} -#endif /* !HAVE_STRERROR */ - -#if !defined (HAVE_STRCASECMP) -/* This Unix doesn't have the strcasecmp () function. */ -int -strcasecmp (string1, string2) - char *string1, *string2; -{ - char ch1, ch2; - - for (;;) - { - ch1 = *string1++; - ch2 = *string2++; - - if (!(ch1 | ch2)) - return (0); - - ch1 = info_toupper (ch1); - ch2 = info_toupper (ch2); - - if (ch1 != ch2) - return (ch1 - ch2); - } -} - -/* Compare at most COUNT characters from string1 to string2. Case - doesn't matter. */ -int -strncasecmp (string1, string2, count) - char *string1, *string2; - int count; -{ - register char ch1, ch2; - - while (count) - { - ch1 = *string1++; - ch2 = *string2++; - - ch1 = info_toupper (ch1); - ch2 = info_toupper (ch2); - - if (ch1 == ch2) - count--; - else - break; - } - return (count); -} -#endif /* !STRCASECMP */ - diff --git a/info/clib.h b/info/clib.h deleted file mode 100644 --- a/info/clib.h +++ /dev/null @@ -1,42 +0,0 @@ -/* clib.h: Declarations of functions which appear in clib.c (or libc.a). */ - -/* This file is part of GNU Info, a program for reading online documentation - stored in Info format. - - Copyright (C) 1995 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). */ - -#if !defined (_CLIB_H_) -#define _CLIB_H_ - -#if !defined (HAVE_STRDUP) -extern char *strdup (); -#endif - -#if !defined (HAVE_STRERROR) -extern char *strerror (); -#endif - -#if !defined (HAVE_STRCASECMP) -extern int strcasecmp (); -extern int strncasecmp (); -#endif - -#endif /* !_CLIB_H_ */ - - diff --git a/info/configure.in b/info/configure.in deleted file mode 100644 --- a/info/configure.in +++ /dev/null @@ -1,46 +0,0 @@ -dnl Process this file with autoconf to produce a configure script. -dnl $Id: configure.in,v 1.8 1996-12-03 17:49:39 jwe Exp $ -AC_INIT(info.c) - -dnl Checks for programs. -AC_PROG_GCC_TRADITIONAL -AC_PROG_INSTALL -AC_PROG_RANLIB - -AC_ISC_POSIX -AC_MINIX - -dnl Checks for libraries. -# Needed on sysV68 for sigblock, sigsetmask. -AC_CHECK_LIB(bsd, sigblock) - -### I am told that on some SCO systems, the only place to find some -### functions like gethostname and gettimeofday is in libsocket. -AC_CHECK_LIB(socket, gethostname) - -TERMLIBS= -for termlib in ncurses curses termcap terminfo termlib ; do - AC_CHECK_LIB(${termlib}, tputs, - [TERMLIBS="${TERMLIBS} -l${termlib}"; break]) -done -AC_SUBST(TERMLIBS) - -dnl Checks for header files. -AC_HEADER_STDC -AC_CHECK_HEADERS(unistd.h termios.h termio.h strings.h string.h varargs.h \ - sys/time.h sys/fcntl.h sys/ttold.h sys/ptem.h sys/file.h) - -dnl Checks for typedefs, structures, and compiler characteristics. -AC_TYPE_OFF_T -AC_C_CONST -AC_STRUCT_TM - -dnl Checks for library functions. -AC_FUNC_ALLOCA -AC_FUNC_SETVBUF_REVERSED -AC_CHECK_FUNCS(setvbuf getcwd memset bzero strchr strcasecmp \ - vfprintf vsprintf strerror sigprocmask sigsetmask) -dnl strcasecmp, strerror, xmalloc, xrealloc, probably others should be added. -AC_REPLACE_FUNCS(memcpy memmove strdup) - -AC_OUTPUT(Makefile) diff --git a/info/dir.c b/info/dir.c deleted file mode 100644 --- a/info/dir.c +++ /dev/null @@ -1,273 +0,0 @@ -/* dir.c -- How to build a special "dir" node from "localdir" files. */ - -/* 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 -#include -#include -#if defined (HAVE_SYS_FILE_H) -#include -#endif /* HAVE_SYS_FILE_H */ -#include -#include "info-utils.h" -#include "filesys.h" -#include "tilde.h" - -/* The "dir" node can be built from the contents of a file called "dir", - with the addition of the menus of every file named in the array - dirs_to_add which are found in INFOPATH. */ - -static void add_menu_to_file_buffer (), insert_text_into_fb_at_binding (); -static void build_dir_node_internal (); - -static char *dirs_to_add[] = { - "dir", "localdir", (char *)NULL -}; - -void -maybe_build_dir_node (dirname) - char *dirname; -{ - FILE_BUFFER *dir_buffer; - int path_index, update_tags; - char *this_dir; - - /* Check to see if the file has already been built. If so, then - do not build it again. */ - dir_buffer = info_find_file (dirname); - - /* If there is no "dir" in the current info path, we cannot build one - from nothing. */ - if (!dir_buffer) - return; - - /* If this directory has already been built, return now. */ - if (dir_buffer->flags & N_CannotGC) - return; - - path_index = update_tags = 0; - - /* Using each element of the path, check for one of the files in - DIRS_TO_ADD. Do not check for "localdir.info.Z" or anything else. - Only files explictly named are eligible. This is a design decision. - There can be an info file name "localdir.info" which contains - information on the setting up of "localdir" files. */ - while (this_dir = extract_colon_unit (infopath, &path_index)) - { - register int da_index; - char *from_file; - - /* Expand a leading tilde if one is present. */ - if (*this_dir == '~') - { - char *tilde_expanded_dirname; - - tilde_expanded_dirname = tilde_expand_word (this_dir); - if (tilde_expanded_dirname != this_dir) - { - free (this_dir); - this_dir = tilde_expanded_dirname; - } - } - - /* For every file named in DIRS_TO_ADD found in the search path, - add the contents of that file's menu to our "dir" node. */ - for (da_index = 0; from_file = dirs_to_add[da_index]; da_index++) - { - struct stat finfo; - char *fullpath; - int namelen, statable; - - namelen = strlen (from_file); - - fullpath = (char *)xmalloc (3 + strlen (this_dir) + namelen); - strcpy (fullpath, this_dir); - if (fullpath[strlen (fullpath) - 1] != '/') - strcat (fullpath, "/"); - strcat (fullpath, from_file); - - statable = (stat (fullpath, &finfo) == 0); - - /* Only add the contents of this file if it is not identical to the - file of the DIR buffer. */ - if ((statable && S_ISREG (finfo.st_mode)) && - (strcmp (dir_buffer->fullpath, fullpath) != 0)) - { - long filesize; - char *contents; - - contents = filesys_read_info_file (fullpath, &filesize, &finfo); - - if (contents) - { - update_tags++; - add_menu_to_file_buffer (contents, filesize, dir_buffer); - free (contents); - } - } - - free (fullpath); - } - free (this_dir); - } - - if (update_tags) - build_tags_and_nodes (dir_buffer); - - /* Flag that the dir buffer has been built. */ - dir_buffer->flags |= N_CannotGC; -} - -/* Given CONTENTS and FB (a file buffer), add the menu found in CONTENTS - to the menu found in FB->contents. Second argument SIZE is the total - size of CONTENTS. */ -static void -add_menu_to_file_buffer (contents, size, fb) - char *contents; - long size; - FILE_BUFFER *fb; -{ - SEARCH_BINDING contents_binding, fb_binding; - long contents_offset, fb_offset; - - contents_binding.buffer = contents; - contents_binding.start = 0; - contents_binding.end = size; - contents_binding.flags = S_FoldCase | S_SkipDest; - - fb_binding.buffer = fb->contents; - fb_binding.start = 0; - fb_binding.end = fb->filesize; - fb_binding.flags = S_FoldCase | S_SkipDest; - - /* Move to the start of the menus in CONTENTS and FB. */ - contents_offset = search_forward (INFO_MENU_LABEL, &contents_binding); - fb_offset = search_forward (INFO_MENU_LABEL, &fb_binding); - - /* If there is no menu in CONTENTS, quit now. */ - if (contents_offset == -1) - return; - - /* There is a menu in CONTENTS, and contents_offset points to the first - character following the menu starter string. Skip all whitespace - and newline characters. */ - contents_offset += skip_whitespace_and_newlines (contents + contents_offset); - - /* If there is no menu in FB, make one. */ - if (fb_offset == -1) - { - /* Find the start of the second node in this file buffer. If there - is only one node, we will be adding the contents to the end of - this node. */ - fb_offset = find_node_separator (&fb_binding); - - /* If not even a single node separator, give up. */ - if (fb_offset == -1) - return; - - fb_binding.start = fb_offset; - fb_binding.start += - skip_node_separator (fb_binding.buffer + fb_binding.start); - - /* Try to find the next node separator. */ - fb_offset = find_node_separator (&fb_binding); - - /* If found one, consider that the start of the menu. Otherwise, the - start of this menu is the end of the file buffer (i.e., fb->size). */ - if (fb_offset != -1) - fb_binding.start = fb_offset; - else - fb_binding.start = fb_binding.end; - - insert_text_into_fb_at_binding - (fb, &fb_binding, INFO_MENU_LABEL, strlen (INFO_MENU_LABEL)); - - fb_binding.buffer = fb->contents; - fb_binding.start = 0; - fb_binding.end = fb->filesize; - fb_offset = search_forward (INFO_MENU_LABEL, &fb_binding); - if (fb_offset == -1) - abort (); - } - - /* CONTENTS_OFFSET and FB_OFFSET point to the starts of the menus that - appear in their respective buffers. Add the remainder of CONTENTS - to the end of FB's menu. */ - fb_binding.start = fb_offset; - fb_offset = find_node_separator (&fb_binding); - if (fb_offset != -1) - fb_binding.start = fb_offset; - else - fb_binding.start = fb_binding.end; - - /* Leave exactly one blank line between directory entries. */ - { - int num_found = 0; - - while ((fb_binding.start > 0) && - (whitespace_or_newline (fb_binding.buffer[fb_binding.start - 1]))) - { - num_found++; - fb_binding.start--; - } - - /* Optimize if possible. */ - if (num_found >= 2) - { - fb_binding.buffer[fb_binding.start++] = '\n'; - fb_binding.buffer[fb_binding.start++] = '\n'; - } - else - { - /* Do it the hard way. */ - insert_text_into_fb_at_binding (fb, &fb_binding, "\n\n", 2); - fb_binding.start += 2; - } - } - - /* Insert the new menu. */ - insert_text_into_fb_at_binding - (fb, &fb_binding, contents + contents_offset, size - contents_offset); -} - -static void -insert_text_into_fb_at_binding (fb, binding, text, textlen) - FILE_BUFFER *fb; - SEARCH_BINDING *binding; - char *text; - int textlen; -{ - char *contents; - long start, end; - - start = binding->start; - end = fb->filesize; - - contents = (char *)xmalloc (fb->filesize + textlen + 1); - memcpy (contents, fb->contents, start); - memcpy (contents + start, text, textlen); - memcpy (contents + start + textlen, fb->contents + start, end - start); - free (fb->contents); - fb->contents = contents; - fb->filesize += textlen; - fb->finfo.st_size = fb->filesize; -} diff --git a/info/display.c b/info/display.c deleted file mode 100644 --- a/info/display.c +++ /dev/null @@ -1,561 +0,0 @@ -/* display.c -- How to display Info windows. */ - -/* 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 -#include -#include -#include -#include "display.h" - -extern int info_any_buffered_input_p (); /* Found in session.c. */ - -static void free_display (); -static DISPLAY_LINE **make_display (); - -/* An array of display lines which tell us what is currently visible on - the display. */ -DISPLAY_LINE **the_display = (DISPLAY_LINE **)NULL; - -/* Non-zero means do no output. */ -int display_inhibited = 0; - -/* Initialize THE_DISPLAY to WIDTH and HEIGHT, with nothing in it. */ -void -display_initialize_display (width, height) - int width, height; -{ - free_display (the_display); - the_display = make_display (width, height); - display_clear_display (the_display); -} - -/* Clear all of the lines in DISPLAY making the screen blank. */ -void -display_clear_display (display) - DISPLAY_LINE **display; -{ - register int i; - register DISPLAY_LINE *display_line; - - for (i = 0; display_line = display[i]; i++) - { - display[i]->text[0] = '\0'; - display[i]->textlen = 0; - display[i]->inverse = 0; - } -} - -/* Non-zero if we didn't completely redisplay a window. */ -int display_was_interrupted_p = 0; - -/* Update the windows pointed to by WINDOW in the_display. This actually - writes the text on the screen. */ -void -display_update_display (window) - WINDOW *window; -{ - register WINDOW *win; - - display_was_interrupted_p = 0; - - /* For every window in the list, check contents against the display. */ - for (win = window; win; win = win->next) - { - /* Only re-display visible windows which need updating. */ - if (((win->flags & W_WindowVisible) == 0) || - ((win->flags & W_UpdateWindow) == 0) || - (win->height == 0)) - continue; - - display_update_one_window (win); - if (display_was_interrupted_p) - break; - } - - /* Always update the echo area. */ - display_update_one_window (the_echo_area); -} - -/* Display WIN on the_display. Unlike display_update_display (), this - function only does one window. */ -void -display_update_one_window (win) - WINDOW *win; -{ - register char *nodetext; /* Current character to display. */ - register char *last_node_char; /* Position of the last character in node. */ - register int i; /* General use index. */ - char *printed_line; /* Buffer for a printed line. */ - int pl_index = 0; /* Index into PRINTED_LINE. */ - int line_index = 0; /* Number of lines done so far. */ - DISPLAY_LINE **display = the_display; - - /* If display is inhibited, that counts as an interrupted display. */ - if (display_inhibited) - display_was_interrupted_p = 1; - - /* If the window has no height, or display is inhibited, quit now. */ - if (!win->height || display_inhibited) - return; - - /* If the window's first row doesn't appear in the_screen, then it - cannot be displayed. This can happen when the_echo_area is the - window to be displayed, and the screen has shrunk to less than one - line. */ - if ((win->first_row < 0) || (win->first_row > the_screen->height)) - return; - - /* Print each line in the window into our local buffer, and then - check the contents of that buffer against the display. If they - differ, update the display. */ - printed_line = (char *)xmalloc (1 + win->width); - - if (!win->node || !win->line_starts) - goto done_with_node_display; - - nodetext = win->line_starts[win->pagetop]; - last_node_char = win->node->contents + win->node->nodelen; - - for (; nodetext < last_node_char; nodetext++) - { - char *rep, *rep_carried_over, rep_temp[2]; - int replen; - - if (isprint (*nodetext)) - { - rep_temp[0] = *nodetext; - replen = 1; - rep_temp[1] = '\0'; - rep = rep_temp; - } - else - { - if (*nodetext == '\r' || *nodetext == '\n') - { - replen = win->width - pl_index; - } - else - { - rep = printed_representation (*nodetext, pl_index); - replen = strlen (rep); - } - } - - /* If this character can be printed without passing the width of - the line, then stuff it into the line. */ - if (replen + pl_index < win->width) - { - /* Optimize if possible. */ - if (replen == 1) - { - printed_line[pl_index++] = *rep; - } - else - { - for (i = 0; i < replen; i++) - printed_line[pl_index++] = rep[i]; - } - } - else - { - DISPLAY_LINE *entry; - - /* If this character cannot be printed in this line, we have - found the end of this line as it would appear on the screen. - Carefully print the end of the line, and then compare. */ - if (*nodetext == '\n' || *nodetext == '\r' || *nodetext == '\t') - { - printed_line[pl_index] = '\0'; - rep_carried_over = (char *)NULL; - } - else - { - /* The printed representation of this character extends into - the next line. Remember the offset of the last character - printed out of REP so that we can carry the character over - to the next line. */ - for (i = 0; pl_index < (win->width - 1);) - printed_line[pl_index++] = rep[i++]; - - rep_carried_over = rep + i; - - /* If printing the last character in this window couldn't - possibly cause the screen to scroll, place a backslash - in the rightmost column. */ - if (1 + line_index + win->first_row < the_screen->height) - { - if (win->flags & W_NoWrap) - printed_line[pl_index++] = '$'; - else - printed_line[pl_index++] = '\\'; - } - printed_line[pl_index] = '\0'; - } - - /* We have the exact line as it should appear on the screen. - Check to see if this line matches the one already appearing - on the screen. */ - entry = display[line_index + win->first_row]; - - /* If the screen line is inversed, then we have to clear - the line from the screen first. Why, I don't know. */ - if (entry->inverse) - { - terminal_goto_xy (0, line_index + win->first_row); - terminal_clear_to_eol (); - entry->inverse = 0; - entry->text[0] = '\0'; - entry->textlen = 0; - } - - /* Find the offset where these lines differ. */ - for (i = 0; i < pl_index; i++) - if (printed_line[i] != entry->text[i]) - break; - - /* If the lines are not the same length, or if they differed - at all, we must do some redrawing. */ - if ((i != pl_index) || (pl_index != entry->textlen)) - { - /* Move to the proper point on the terminal. */ - terminal_goto_xy (i, line_index + win->first_row); - - /* If there is any text to print, print it. */ - if (i != pl_index) - terminal_put_text (printed_line + i); - - /* If the printed text didn't extend all the way to the edge - of the window, and text was appearing between here and the - edge of the window, clear from here to the end of the line. */ - if ((pl_index < win->width && pl_index < entry->textlen) || - (entry->inverse)) - terminal_clear_to_eol (); - - fflush (stdout); - - /* Update the display text buffer. */ - strcpy (entry->text + i, printed_line + i); - entry->textlen = pl_index; - - /* Lines showing node text are not in inverse. Only modelines - have that distinction. */ - entry->inverse = 0; - } - - /* We have done at least one line. Increment our screen line - index, and check against the bottom of the window. */ - if (++line_index == win->height) - break; - - /* A line has been displayed, and the screen reflects that state. - If there is typeahead pending, then let that typeahead be read - now, instead of continuing with the display. */ - if (info_any_buffered_input_p ()) - { - free (printed_line); - display_was_interrupted_p = 1; - return; - } - - /* Reset PL_INDEX to the start of the line. */ - pl_index = 0; - - /* If there are characters from REP left to print, stuff them - into the buffer now. */ - if (rep_carried_over) - for (; rep[pl_index]; pl_index++) - printed_line[pl_index] = rep[pl_index]; - - /* If this window has chosen not to wrap lines, skip to the end - of the physical line in the buffer, and start a new line here. */ - if (pl_index && (win->flags & W_NoWrap)) - { - char *begin; - - pl_index = 0; - printed_line[0] = '\0'; - - begin = nodetext; - - while ((nodetext < last_node_char) && (*nodetext != '\n')) - nodetext++; - } - } - } - - done_with_node_display: - /* We have reached the end of the node or the end of the window. If it - is the end of the node, then clear the lines of the window from here - to the end of the window. */ - for (; line_index < win->height; line_index++) - { - DISPLAY_LINE *entry = display[line_index + win->first_row]; - - /* If this line has text on it then make it go away. */ - if (entry && entry->textlen) - { - entry->textlen = 0; - entry->text[0] = '\0'; - - terminal_goto_xy (0, line_index + win->first_row); - terminal_clear_to_eol (); - } - } - - /* Finally, if this window has a modeline it might need to be redisplayed. - Check the window's modeline against the one in the display, and update - if necessary. */ - if ((win->flags & W_InhibitMode) == 0) - { - window_make_modeline (win); - line_index = win->first_row + win->height; - - /* This display line must both be in inverse, and have the same - contents. */ - if ((!display[line_index]->inverse) || - (strcmp (display[line_index]->text, win->modeline) != 0)) - { - terminal_goto_xy (0, line_index); - terminal_begin_inverse (); - terminal_put_text (win->modeline); - terminal_end_inverse (); - strcpy (display[line_index]->text, win->modeline); - display[line_index]->inverse = 1; - display[line_index]->textlen = strlen (win->modeline); - fflush (stdout); - } - } - - /* Okay, this window doesn't need updating anymore. */ - win->flags &= ~W_UpdateWindow; - free (printed_line); - fflush (stdout); -} - -/* Scroll the region of the_display starting at START, ending at END, and - moving the lines AMOUNT lines. If AMOUNT is less than zero, the lines - are moved up in the screen, otherwise down. Actually, it is possible - for no scrolling to take place in the case that the terminal doesn't - support it. This doesn't matter to us. */ -void -display_scroll_display (start, end, amount) - int start, end, amount; -{ - register int i, last; - DISPLAY_LINE *temp; - - /* If this terminal cannot do scrolling, give up now. */ - if (!terminal_can_scroll) - return; - - /* If there isn't anything displayed on the screen because it is too - small, quit now. */ - if (!the_display[0]) - return; - - /* If there is typeahead pending, then don't actually do any scrolling. */ - if (info_any_buffered_input_p ()) - return; - - /* Do it on the screen. */ - terminal_scroll_terminal (start, end, amount); - - /* Now do it in the display buffer so our contents match the screen. */ - if (amount > 0) - { - last = end + amount; - - /* Shift the lines to scroll right into place. */ - for (i = 0; i < (end - start); i++) - { - temp = the_display[last - i]; - the_display[last - i] = the_display[end - i]; - the_display[end - i] = temp; - } - - /* The lines have been shifted down in the buffer. Clear all of the - lines that were vacated. */ - for (i = start; i != (start + amount); i++) - { - the_display[i]->text[0] = '\0'; - the_display[i]->textlen = 0; - the_display[i]->inverse = 0; - } - } - - if (amount < 0) - { - last = start + amount; - for (i = 0; i < (end - start); i++) - { - temp = the_display[last + i]; - the_display[last + i] = the_display[start + i]; - the_display[start + i] = temp; - } - - /* The lines have been shifted up in the buffer. Clear all of the - lines that are left over. */ - for (i = end + amount; i != end; i++) - { - the_display[i]->text[0] = '\0'; - the_display[i]->textlen = 0; - the_display[i]->inverse = 0; - } - } -} - -/* Try to scroll lines in WINDOW. OLD_PAGETOP is the pagetop of WINDOW before - having had its line starts recalculated. OLD_STARTS is the list of line - starts that used to appear in this window. OLD_COUNT is the number of lines - that appear in the OLD_STARTS array. */ -void -display_scroll_line_starts (window, old_pagetop, old_starts, old_count) - WINDOW *window; - int old_pagetop, old_count; - char **old_starts; -{ - register int i, old, new; /* Indices into the line starts arrays. */ - int last_new, last_old; /* Index of the last visible line. */ - int old_first, new_first; /* Index of the first changed line. */ - int unchanged_at_top = 0; - int already_scrolled = 0; - - /* Locate the first line which was displayed on the old window. */ - old_first = old_pagetop; - new_first = window->pagetop; - - /* Find the last line currently visible in this window. */ - last_new = window->pagetop + (window->height - 1); - if (last_new > window->line_count) - last_new = window->line_count - 1; - - /* Find the last line which used to be currently visible in this window. */ - last_old = old_pagetop + (window->height - 1); - if (last_old > old_count) - last_old = old_count - 1; - - for (old = old_first, new = new_first; - old < last_old && new < last_new; - old++, new++) - if (old_starts[old] != window->line_starts[new]) - break; - else - unchanged_at_top++; - - /* Loop through the old lines looking for a match in the new lines. */ - for (old = old_first + unchanged_at_top; old < last_old; old++) - { - for (new = new_first; new < last_new; new++) - if (old_starts[old] == window->line_starts[new]) - { - /* Find the extent of the matching lines. */ - for (i = 0; (old + i) < last_old; i++) - if (old_starts[old + i] != window->line_starts[new + i]) - break; - - /* Scroll these lines if there are enough of them. */ - { - int start, end, amount; - - start = (window->first_row - + ((old + already_scrolled) - old_pagetop)); - amount = new - (old + already_scrolled); - end = window->first_row + window->height; - - /* If we are shifting the block of lines down, then the last - AMOUNT lines will become invisible. Thus, don't bother - scrolling them. */ - if (amount > 0) - end -= amount; - - if ((end - start) > 0) - { - display_scroll_display (start, end, amount); - - /* Some lines have been scrolled. Simulate the scrolling - by offsetting the value of the old index. */ - old += i; - already_scrolled += amount; - } - } - } - } -} - -/* Move the screen cursor to directly over the current character in WINDOW. */ -void -display_cursor_at_point (window) - WINDOW *window; -{ - int vpos, hpos; - - vpos = window_line_of_point (window) - window->pagetop + window->first_row; - hpos = window_get_cursor_column (window); - terminal_goto_xy (hpos, vpos); -} - -/* **************************************************************** */ -/* */ -/* Functions Static to this File */ -/* */ -/* **************************************************************** */ - -/* Make a DISPLAY_LINE ** with width and height. */ -static DISPLAY_LINE ** -make_display (width, height) - int width, height; -{ - register int i; - DISPLAY_LINE **display; - - display = (DISPLAY_LINE **)xmalloc ((1 + height) * sizeof (DISPLAY_LINE *)); - - for (i = 0; i < height; i++) - { - display[i] = (DISPLAY_LINE *)xmalloc (sizeof (DISPLAY_LINE)); - display[i]->text = (char *)xmalloc (1 + width); - display[i]->textlen = 0; - display[i]->inverse = 0; - } - display[i] = (DISPLAY_LINE *)NULL; - return (display); -} - -/* Free the storage allocated to DISPLAY. */ -static void -free_display (display) - DISPLAY_LINE **display; -{ - register int i; - register DISPLAY_LINE *display_line; - - if (!display) - return; - - for (i = 0; display_line = display[i]; i++) - { - free (display_line->text); - free (display_line); - } - free (display); -} diff --git a/info/display.h b/info/display.h deleted file mode 100644 --- a/info/display.h +++ /dev/null @@ -1,76 +0,0 @@ -/* display.h -- How the display in Info is done. */ - -/* 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). */ - -#if !defined (_DISPLAY_H_) -#define _DISPLAY_H_ - -#include "info-utils.h" -#include "terminal.h" - -typedef struct { - char *text; /* Text of the line as it appears. */ - int textlen; /* Printable Length of TEXT. */ - int inverse; /* Non-zero means this line is inverse. */ -} DISPLAY_LINE; - -/* An array of display lines which tell us what is currently visible on - the display. */ -extern DISPLAY_LINE **the_display; - -/* Non-zero means do no output. */ -extern int display_inhibited; - -/* Non-zero if we didn't completely redisplay a window. */ -extern int display_was_interrupted_p; - -/* Initialize THE_DISPLAY to WIDTH and HEIGHT, with nothing in it. */ -extern void display_initialize_display (); - -/* Clear all of the lines in DISPLAY making the screen blank. */ -extern void display_clear_display (); - -/* Update the windows pointed to by WINDOWS in THE_DISPLAY. This actually - writes the text on the screen. */ -extern void display_update_display (); - -/* Display WIN on THE_DISPLAY. Unlike display_update_display (), this - function only does one window. */ -extern void display_update_one_window (); - -/* Move the screen cursor to directly over the current character in WINDOW. */ -extern void display_cursor_at_point (); - -/* Scroll the region of the_display starting at START, ending at END, and - moving the lines AMOUNT lines. If AMOUNT is less than zero, the lines - are moved up in the screen, otherwise down. Actually, it is possible - for no scrolling to take place in the case that the terminal doesn't - support it. This doesn't matter to us. */ -extern void display_scroll_display (); - -/* Try to scroll lines in WINDOW. OLD_PAGETOP is the pagetop of WINDOW before - having had its line starts recalculated. OLD_STARTS is the list of line - starts that used to appear in this window. OLD_COUNT is the number of lines - that appear in the OLD_STARTS array. */ -extern void display_scroll_line_starts (); - -#endif /* !_DISPLAY_H_ */ diff --git a/info/doc.h b/info/doc.h deleted file mode 100644 --- a/info/doc.h +++ /dev/null @@ -1,58 +0,0 @@ -/* doc.h -- Structure associating function pointers with documentation. */ - -/* 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). */ - -#if !defined (_DOC_H_) -#define _DOC_H_ - -#if !defined (NULL) -# define NULL 0x0 -#endif /* !NULL */ - -#if !defined (__FUNCTION_DEF) -# define __FUNCTION_DEF -typedef int Function (); -typedef void VFunction (); -#endif /* _FUNCTION_DEF */ - -typedef struct { - VFunction *func; -#if defined (NAMED_FUNCTIONS) - char *func_name; -#endif /* NAMED_FUNCTIONS */ - char *doc; -} FUNCTION_DOC; - -extern FUNCTION_DOC function_doc_array[]; - -extern char *function_documentation (); -extern char *key_documentation (); -extern char *pretty_keyname (); -extern char *replace_in_documentation (); -extern void info_document_key (); -extern void dump_map_to_message_buffer (); - -#if defined (NAMED_FUNCTIONS) -extern char *function_name (); -extern VFunction *named_function (); -#endif /* NAMED_FUNCTIONS */ -#endif /* !_DOC_H_ */ diff --git a/info/dribble b/info/dribble deleted file mode 100644 --- a/info/dribble +++ /dev/null @@ -1,5 +0,0 @@ -mfoo -em -buffers - -ââ \ No newline at end of file diff --git a/info/dribble.c b/info/dribble.c deleted file mode 100644 --- a/info/dribble.c +++ /dev/null @@ -1,71 +0,0 @@ -/* dribble.c -- Dribble files for Info. */ - -/* 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 -#include "dribble.h" - -/* When non-zero, it is a stream to write all input characters to for the - duration of this info session. */ -FILE *info_dribble_file = (FILE *)NULL; - -/* Open a dribble file named NAME, perhaps closing an already open one. - This sets the global variable INFO_DRIBBLE_FILE to the open stream. */ -void -open_dribble_file (name) - char *name; -{ - /* Perhaps close existing dribble file. */ - close_dribble_file (); - - info_dribble_file = fopen (name, "w"); - -#if defined (HAVE_SETVBUF) - if (info_dribble_file) -# if defined (SETVBUF_REVERSED) - setvbuf (info_dribble_file, _IONBF, (char *)NULL, 1); -# else - setvbuf (info_dribble_file, (char *)NULL, _IONBF, 1); -# endif /* !SETVBUF_REVERSED */ -#endif /* HAVE_SETVBUF */ -} - -/* If there is a dribble file already open, close it. */ -void -close_dribble_file () -{ - if (info_dribble_file) - { - fflush (info_dribble_file); - fclose (info_dribble_file); - info_dribble_file = (FILE *)NULL; - } -} - -/* Write some output to our existing dribble file. */ -void -dribble (byte) - unsigned char byte; -{ - if (info_dribble_file) - fwrite (&byte, sizeof (unsigned char), 1, info_dribble_file); -} diff --git a/info/dribble.h b/info/dribble.h deleted file mode 100644 --- a/info/dribble.h +++ /dev/null @@ -1,41 +0,0 @@ -/* dribble.h -- Functions and vars declared in dribble.c. */ - -/* 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). */ - -#if !defined (_DRIBBLE_H_) -#define _DRIBBLE_H_ - -/* When non-zero, it is a stream to write all input characters to for the - duration of this info session. */ -extern FILE *info_dribble_file; - -/* Open a dribble file named NAME, perhaps closing an already open one. - This sets the global variable INFO_DRIBBLE_FILE to the open stream. */ -extern void open_dribble_file (); - -/* If there is a dribble file already open, close it. */ -extern void close_dribble_file (); - -/* Write some output to our existing dribble file. */ -extern void dribble (); - -#endif /* !_DRIBBLE_H_ */ diff --git a/info/echo_area.c b/info/echo_area.c deleted file mode 100644 --- a/info/echo_area.c +++ /dev/null @@ -1,1508 +0,0 @@ -/* echo_area.c -- How to read a line in the echo area. */ - -/* 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" - -#if defined (FD_SET) -# if defined (hpux) -# define fd_set_cast(x) (int *)(x) -# else -# define fd_set_cast(x) (fd_set *)(x) -# endif /* !hpux */ -#endif /* FD_SET */ - -/* Non-zero means that C-g was used to quit reading input. */ -int info_aborted_echo_area = 0; - -/* Non-zero means that the echo area is being used to read input. */ -int echo_area_is_active = 0; - -/* The address of the last command executed in the echo area. */ -VFunction *ea_last_executed_command = (VFunction *)NULL; - -/* Non-zero means that the last command executed while reading input - killed some text. */ -int echo_area_last_command_was_kill = 0; - -/* Variables which hold on to the current state of the input line. */ -static char input_line[1 + EA_MAX_INPUT]; -static char *input_line_prompt; -static int input_line_point; -static int input_line_beg; -static int input_line_end; -static NODE input_line_node = { - (char *)NULL, (char *)NULL, (char *)NULL, input_line, EA_MAX_INPUT, 0 -}; - -static void echo_area_initialize_node (); -static void push_echo_area (), pop_echo_area (); -static int echo_area_stack_depth (), echo_area_stack_contains_completions_p (); - -static void ea_kill_text (); - -/* Non-zero means we force the user to complete. */ -static int echo_area_must_complete_p = 0; -static int completions_window_p (); - -/* If non-null, this is a window which was specifically created to display - possible completions output. We remember it so we can delete it when - appropriate. */ -static WINDOW *echo_area_completions_window = (WINDOW *)NULL; - -/* Variables which keep track of the window which was active prior to - entering the echo area. */ -static WINDOW *calling_window = (WINDOW *)NULL; -static NODE *calling_window_node = (NODE *)NULL; -static long calling_window_point = 0; -static long calling_window_pagetop = 0; - -/* Remember the node and pertinent variables of the calling window. */ -static void -remember_calling_window (window) - WINDOW *window; -{ - /* Only do this if the calling window is not the completions window, or, - if it is the completions window and there is no other window. */ - if (!completions_window_p (window) || - ((window == windows) && !(window->next))) - { - calling_window = window; - calling_window_node = window->node; - calling_window_point = window->point; - calling_window_pagetop = window->pagetop; - } -} - -/* Restore the caller's window so that it shows the node that it was showing - on entry to info_read_xxx_echo_area (). */ -static void -restore_calling_window () -{ - register WINDOW *win, *compwin = (WINDOW *)NULL; - - /* If the calling window is still visible, and it is the window that - we used for completions output, then restore the calling window. */ - for (win = windows; win; win = win->next) - { - if (completions_window_p (win)) - compwin = win; - - if (win == calling_window && win == compwin) - { - window_set_node_of_window (calling_window, calling_window_node); - calling_window->point = calling_window_point; - calling_window->pagetop = calling_window_pagetop; - compwin = (WINDOW *)NULL; - break; - } - } - - /* Delete the completions window if it is still present, it isn't the - last window on the screen, and there aren't any prior echo area reads - pending which created a completions window. */ - if (compwin) - { - if ((compwin != windows || windows->next) && - !echo_area_stack_contains_completions_p ()) - { - WINDOW *next; - int pagetop, start, end, amount; - - next = compwin->next; - if (next) - { - start = next->first_row; - end = start + next->height; - amount = - (compwin->height + 1); - pagetop = next->pagetop; - } - - info_delete_window_internal (compwin); - - /* This is not necessary because info_delete_window_internal () - calls echo_area_inform_of_deleted_window (), which does the - right thing. */ -#if defined (UNNECESSARY) - echo_area_completions_window = (WINDOW *)NULL; -#endif /* UNNECESSARY */ - - if (next) - { - display_scroll_display (start, end, amount); - next->pagetop = pagetop; - display_update_display (windows); - } - } - } -} - -/* Set up a new input line with PROMPT. */ -static void -initialize_input_line (prompt) - char *prompt; -{ - input_line_prompt = prompt; - if (prompt) - strcpy (input_line, prompt); - else - input_line[0] = '\0'; - - input_line_beg = input_line_end = input_line_point = strlen (prompt); -} - -static char * -echo_area_after_read () -{ - char *return_value; - - if (info_aborted_echo_area) - { - info_aborted_echo_area = 0; - return_value = (char *)NULL; - } - else - { - if (input_line_beg == input_line_end) - return_value = strdup (""); - else - { - int line_len = input_line_end - input_line_beg; - return_value = (char *) xmalloc (1 + line_len); - strncpy (return_value, &input_line[input_line_beg], line_len); - return_value[line_len] = '\0'; - } - } - return (return_value); -} - -/* 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 - active window, so that we can restore it when we need to. PROMPT, if - non-null, is a prompt to print before reading the line. */ -char * -info_read_in_echo_area (window, prompt) - WINDOW *window; - char *prompt; -{ - char *line; - - /* If the echo area is already active, remember the current state. */ - if (echo_area_is_active) - push_echo_area (); - - /* Initialize our local variables. */ - initialize_input_line (prompt); - - /* Initialize the echo area for the first (but maybe not the last) time. */ - echo_area_initialize_node (); - - /* Save away the original node of this window, and the window itself, - so echo area commands can temporarily use this window. */ - remember_calling_window (window); - - /* Let the rest of Info know that the echo area is active. */ - echo_area_is_active++; - active_window = the_echo_area; - - /* Read characters in the echo area. */ - info_read_and_dispatch (); - - echo_area_is_active--; - - /* Restore the original active window and show point in it. */ - active_window = calling_window; - restore_calling_window (); - display_cursor_at_point (active_window); - fflush (stdout); - - /* Get the value of the line. */ - line = echo_area_after_read (); - - /* If there is a previous loop waiting for us, restore it now. */ - if (echo_area_is_active) - pop_echo_area (); - - /* Return the results to the caller. */ - return (line); -} - -/* (re) Initialize the echo area node. */ -static void -echo_area_initialize_node () -{ - register int i; - - for (i = input_line_end; i < sizeof (input_line); i++) - input_line[i] = ' '; - - input_line[i - 1] = '\n'; - window_set_node_of_window (the_echo_area, &input_line_node); - input_line[input_line_end] = '\n'; -} - -/* Prepare to read characters in the echo area. This can initialize the - echo area node, but its primary purpose is to side effect the input - line buffer contents. */ -void -echo_area_prep_read () -{ - if (the_echo_area->node != &input_line_node) - echo_area_initialize_node (); - - the_echo_area->point = input_line_point; - input_line[input_line_end] = '\n'; - display_update_one_window (the_echo_area); - display_cursor_at_point (active_window); -} - - -/* **************************************************************** */ -/* */ -/* Echo Area Movement Commands */ -/* */ -/* **************************************************************** */ - -DECLARE_INFO_COMMAND (ea_forward, "Move forward a character") -{ - if (count < 0) - ea_backward (window, -count, key); - else - { - input_line_point += count; - if (input_line_point > input_line_end) - input_line_point = input_line_end; - } -} - -DECLARE_INFO_COMMAND (ea_backward, "Move backward a character") -{ - if (count < 0) - ea_forward (window, -count, key); - else - { - input_line_point -= count; - if (input_line_point < input_line_beg) - input_line_point = input_line_beg; - } -} - -DECLARE_INFO_COMMAND (ea_beg_of_line, "Move to the start of this line") -{ - input_line_point = input_line_beg; -} - -DECLARE_INFO_COMMAND (ea_end_of_line, "Move to the end of this line") -{ - input_line_point = input_line_end; -} - -#define alphabetic(c) (islower (c) || isupper (c) || isdigit (c)) - -/* Move forward a word in the input line. */ -DECLARE_INFO_COMMAND (ea_forward_word, "Move forward a word") -{ - int c; - - if (count < 0) - ea_backward_word (window, -count, key); - else - { - while (count--) - { - if (input_line_point == input_line_end) - return; - - /* If we are not in a word, move forward until we are in one. - Then, move forward until we hit a non-alphabetic character. */ - c = input_line[input_line_point]; - - if (!alphabetic (c)) - { - while (++input_line_point < input_line_end) - { - c = input_line[input_line_point]; - if (alphabetic (c)) - break; - } - } - - if (input_line_point == input_line_end) - return; - - while (++input_line_point < input_line_end) - { - c = input_line[input_line_point]; - if (!alphabetic (c)) - break; - } - } - } -} - -DECLARE_INFO_COMMAND (ea_backward_word, "Move backward a word") -{ - int c; - - if (count < 0) - ea_forward_word (window, -count, key); - else - { - while (count--) - { - if (input_line_point == input_line_beg) - return; - - /* Like ea_forward_word (), except that we look at the - characters just before point. */ - - c = input_line[input_line_point - 1]; - - if (!alphabetic (c)) - { - while ((--input_line_point) != input_line_beg) - { - c = input_line[input_line_point - 1]; - if (alphabetic (c)) - break; - } - } - - while (input_line_point != input_line_beg) - { - c = input_line[input_line_point - 1]; - if (!alphabetic (c)) - break; - else - --input_line_point; - } - } - } -} - -DECLARE_INFO_COMMAND (ea_delete, "Delete the character under the cursor") -{ - register int i; - - if (count < 0) - ea_rubout (window, -count, key); - else - { - if (input_line_point == input_line_end) - return; - - if (info_explicit_arg || count > 1) - { - int orig_point; - - orig_point = input_line_point; - ea_forward (window, count, key); - ea_kill_text (orig_point, input_line_point); - input_line_point = orig_point; - } - else - { - for (i = input_line_point; i < input_line_end; i++) - input_line[i] = input_line[i + 1]; - - input_line_end--; - } - } -} - -DECLARE_INFO_COMMAND (ea_rubout, "Delete the character behind the cursor") -{ - if (count < 0) - ea_delete (window, -count, key); - else - { - int start; - - if (input_line_point == input_line_beg) - return; - - start = input_line_point; - ea_backward (window, count, key); - - if (info_explicit_arg || count > 1) - ea_kill_text (start, input_line_point); - else - ea_delete (window, count, key); - } -} - -DECLARE_INFO_COMMAND (ea_abort, "Cancel or quit operation") -{ - /* If any text, just discard it, and restore the calling window's node. - If no text, quit. */ - if (input_line_end != input_line_beg) - { - terminal_ring_bell (); - input_line_end = input_line_point = input_line_beg; - if (calling_window->node != calling_window_node) - restore_calling_window (); - } - else - info_aborted_echo_area = 1; -} - -DECLARE_INFO_COMMAND (ea_newline, "Accept (or force completion of) this line") -{ - /* Stub does nothing. Simply here to see if it has been executed. */ -} - -DECLARE_INFO_COMMAND (ea_quoted_insert, "Insert next character verbatim") -{ - unsigned char character; - - character = info_get_another_input_char (); - ea_insert (window, count, character); -} - -DECLARE_INFO_COMMAND (ea_insert, "Insert this character") -{ - register int i; - - if ((input_line_end + 1) == EA_MAX_INPUT) - { - terminal_ring_bell (); - return; - } - - for (i = input_line_end + 1; i != input_line_point; i--) - input_line[i] = input_line[i - 1]; - - input_line[input_line_point] = key; - input_line_point++; - input_line_end++; -} - -DECLARE_INFO_COMMAND (ea_tab_insert, "Insert a TAB character") -{ - ea_insert (window, count, '\t'); -} - -/* Transpose the characters at point. If point is at the end of the line, - then transpose the characters before point. */ -DECLARE_INFO_COMMAND (ea_transpose_chars, "Transpose characters at point") -{ - /* Handle conditions that would make it impossible to transpose - characters. */ - if (!count || !input_line_point || (input_line_end - input_line_beg) < 2) - return; - - while (count) - { - int t; - if (input_line_point == input_line_end) - { - t = input_line[input_line_point - 1]; - - input_line[input_line_point - 1] = input_line[input_line_point - 2]; - input_line[input_line_point - 2] = t; - } - else - { - t = input_line[input_line_point]; - - input_line[input_line_point] = input_line[input_line_point - 1]; - input_line[input_line_point - 1] = t; - - if (count < 0 && input_line_point != input_line_beg) - input_line_point--; - else - input_line_point++; - } - - if (count < 0) - count++; - else - count--; - } -} - -/* **************************************************************** */ -/* */ -/* Echo Area Killing and Yanking */ -/* */ -/* **************************************************************** */ - -static char **kill_ring = (char **)NULL; -static int kill_ring_index = 0; /* Number of kills appearing in KILL_RING. */ -static int kill_ring_slots = 0; /* Number of slots allocated to KILL_RING. */ -static int kill_ring_loc = 0; /* Location of current yank pointer. */ - -/* The largest number of kills that we remember at one time. */ -static int max_retained_kills = 15; - -DECLARE_INFO_COMMAND (ea_yank, "Yank back the contents of the last kill") -{ - register int i; - register char *text; - - if (!kill_ring_index) - { - inform_in_echo_area ("Kill ring is empty"); - return; - } - - text = kill_ring[kill_ring_loc]; - - for (i = 0; text[i]; i++) - ea_insert (window, 1, text[i]); -} - -/* If the last command was yank, or yank_pop, and the text just before - point is identical to the current kill item, then delete that text - from the line, rotate the index down, and yank back some other text. */ -DECLARE_INFO_COMMAND (ea_yank_pop, "Yank back a previous kill") -{ - register int len; - - if (((ea_last_executed_command != ea_yank) && - (ea_last_executed_command != ea_yank_pop)) || - (kill_ring_index == 0)) - return; - - len = strlen (kill_ring[kill_ring_loc]); - - /* Delete the last yanked item from the line. */ - { - register int i, counter; - - counter = input_line_end - input_line_point; - - for (i = input_line_point - len; counter; i++, counter--) - input_line[i] = input_line[i + len]; - - input_line_end -= len; - input_line_point -= len; - } - - /* Get a previous kill, and yank that. */ - kill_ring_loc--; - if (kill_ring_loc < 0) - kill_ring_loc = kill_ring_index - 1; - - ea_yank (window, count, key); -} - -/* Delete the text from point to end of line. */ -DECLARE_INFO_COMMAND (ea_kill_line, "Kill to the end of the line") -{ - if (count < 0) - { - ea_kill_text (input_line_point, input_line_beg); - input_line_point = input_line_beg; - } - else - ea_kill_text (input_line_point, input_line_end); -} - -/* Delete the text from point to beg of line. */ -DECLARE_INFO_COMMAND (ea_backward_kill_line, - "Kill to the beginning of the line") -{ - if (count < 0) - ea_kill_text (input_line_point, input_line_end); - else - { - ea_kill_text (input_line_point, input_line_beg); - input_line_point = input_line_beg; - } -} - -/* Delete from point to the end of the current word. */ -DECLARE_INFO_COMMAND (ea_kill_word, "Kill the word following the cursor") -{ - int orig_point = input_line_point; - - if (count < 0) - ea_backward_kill_word (window, -count, key); - else - { - ea_forward_word (window, count, key); - - if (input_line_point != orig_point) - ea_kill_text (orig_point, input_line_point); - - input_line_point = orig_point; - } -} - -/* Delete from point to the start of the current word. */ -DECLARE_INFO_COMMAND (ea_backward_kill_word, - "Kill the word preceding the cursor") -{ - int orig_point = input_line_point; - - if (count < 0) - ea_kill_word (window, -count, key); - else - { - ea_backward_word (window, count, key); - - if (input_line_point != orig_point) - ea_kill_text (orig_point, input_line_point); - } -} - -/* The way to kill something. This appends or prepends to the last - kill, if the last command was a kill command. If FROM is less - than TO, then the killed text is appended to the most recent kill, - otherwise it is prepended. If the last command was not a kill command, - then a new slot is made for this kill. */ -static void -ea_kill_text (from, to) - int from, to; -{ - register int i, counter, distance; - int killing_backwards, slot; - char *killed_text; - - killing_backwards = (from > to); - - /* If killing backwards, reverse the values of FROM and TO. */ - if (killing_backwards) - { - int temp = from; - from = to; - to = temp; - } - - /* Remember the text that we are about to delete. */ - distance = to - from; - killed_text = (char *)xmalloc (1 + distance); - strncpy (killed_text, &input_line[from], distance); - killed_text[distance] = '\0'; - - /* Actually delete the text from the line. */ - counter = input_line_end - to; - - for (i = from; counter; i++, counter--) - input_line[i] = input_line[i + distance]; - - input_line_end -= distance; - - /* If the last command was a kill, append or prepend the killed text to - the last command's killed text. */ - if (echo_area_last_command_was_kill) - { - char *old, *new; - - slot = kill_ring_loc; - old = kill_ring[slot]; - new = (char *)xmalloc (1 + strlen (old) + strlen (killed_text)); - - if (killing_backwards) - { - /* Prepend TEXT to current kill. */ - strcpy (new, killed_text); - strcat (new, old); - } - else - { - /* Append TEXT to current kill. */ - strcpy (new, old); - strcat (new, killed_text); - } - - free (old); - free (killed_text); - kill_ring[slot] = new; - } - else - { - /* Try to store the kill in a new slot, unless that would cause there - to be too many remembered kills. */ - slot = kill_ring_index; - - if (slot == max_retained_kills) - slot = 0; - - if (slot + 1 > kill_ring_slots) - kill_ring = (char **) xrealloc - (kill_ring, - (kill_ring_slots += max_retained_kills) * sizeof (char *)); - - if (slot != kill_ring_index) - free (kill_ring[slot]); - else - kill_ring_index++; - - kill_ring[slot] = killed_text; - - kill_ring_loc = slot; - } - - /* Notice that the last command was a kill. */ - echo_area_last_command_was_kill++; -} - -/* **************************************************************** */ -/* */ -/* Echo Area Completion */ -/* */ -/* **************************************************************** */ - -/* Pointer to an array of REFERENCE to complete over. */ -static REFERENCE **echo_area_completion_items = (REFERENCE **)NULL; - -/* Sorted array of REFERENCE * which is the possible completions found in - the variable echo_area_completion_items. If there is only one element, - it is the only possible completion. */ -static REFERENCE **completions_found = (REFERENCE **)NULL; -static int completions_found_index = 0; -static int completions_found_slots = 0; - -/* The lowest common denominator found while completing. */ -static REFERENCE *LCD_completion; - -/* Internal functions used by the user calls. */ -static void build_completions (), completions_must_be_rebuilt (); - -/* Variable which holds the output of completions. */ -static NODE *possible_completions_output_node = (NODE *)NULL; - -static char *compwin_name = "*Completions*"; - -/* Return non-zero if WINDOW is a window used for completions output. */ -static int -completions_window_p (window) - WINDOW *window; -{ - int result = 0; - - if (internal_info_node_p (window->node) && - (strcmp (window->node->nodename, compwin_name) == 0)) - result = 1; - - return (result); -} - -/* Workhorse for completion readers. If FORCE is non-zero, the user cannot - exit unless the line read completes, or is empty. */ -char * -info_read_completing_internal (window, prompt, completions, force) - WINDOW *window; - char *prompt; - REFERENCE **completions; - int force; -{ - char *line; - - /* If the echo area is already active, remember the current state. */ - if (echo_area_is_active) - push_echo_area (); - - echo_area_must_complete_p = force; - - /* Initialize our local variables. */ - initialize_input_line (prompt); - - /* Initialize the echo area for the first (but maybe not the last) time. */ - echo_area_initialize_node (); - - /* Save away the original node of this window, and the window itself, - so echo area commands can temporarily use this window. */ - remember_calling_window (window); - - /* Save away the list of items to complete over. */ - echo_area_completion_items = completions; - completions_must_be_rebuilt (); - - active_window = the_echo_area; - echo_area_is_active++; - - /* Read characters in the echo area. */ - while (1) - { - info_read_and_dispatch (); - - line = echo_area_after_read (); - - /* Force the completion to take place if the user hasn't accepted - a default or aborted, and if FORCE is active. */ - if (force && line && *line && completions) - { - register int i; - - build_completions (); - - /* If there is only one completion, then make the line be that - completion. */ - if (completions_found_index == 1) - { - free (line); - line = strdup (completions_found[0]->label); - break; - } - - /* If one of the completions matches exactly, then that is okay, so - return the current line. */ - for (i = 0; i < completions_found_index; i++) - if (strcasecmp (completions_found[i]->label, line) == 0) - { - free (line); - line = strdup (completions_found[i]->label); - break; - } - - /* If no match, go back and try again. */ - if (i == completions_found_index) - { - inform_in_echo_area ("Not complete"); - continue; - } - } - break; - } - echo_area_is_active--; - - /* Restore the original active window and show point in it. */ - active_window = calling_window; - restore_calling_window (); - display_cursor_at_point (active_window); - fflush (stdout); - - echo_area_completion_items = (REFERENCE **)NULL; - completions_must_be_rebuilt (); - - /* If there is a previous loop waiting for us, restore it now. */ - if (echo_area_is_active) - pop_echo_area (); - - return (line); -} - -/* Read a line in the echo area with completion over COMPLETIONS. */ -char * -info_read_completing_in_echo_area (window, prompt, completions) - WINDOW *window; - char *prompt; - REFERENCE **completions; -{ - return (info_read_completing_internal (window, prompt, completions, 1)); -} - -/* Read a line in the echo area allowing completion over COMPLETIONS, but - not requiring it. */ -char * -info_read_maybe_completing (window, prompt, completions) - WINDOW *window; - char *prompt; - REFERENCE **completions; -{ - return (info_read_completing_internal (window, prompt, completions, 0)); -} - -DECLARE_INFO_COMMAND (ea_possible_completions, "List possible completions") -{ - if (!echo_area_completion_items) - { - ea_insert (window, count, key); - return; - } - - build_completions (); - - if (!completions_found_index) - { - terminal_ring_bell (); - inform_in_echo_area ("No completions"); - } - else if ((completions_found_index == 1) && (key != '?')) - { - inform_in_echo_area ("Sole completion"); - } - else - { - register int i, l; - int limit, count, max_label = 0; - - initialize_message_buffer (); - printf_to_message_buffer - ("There %s %d ", completions_found_index == 1 ? "is" : "are", - completions_found_index); - printf_to_message_buffer - ("completion%s:\n", completions_found_index == 1 ? "" : "s"); - - /* Find the maximum length of a label. */ - for (i = 0; i < completions_found_index; i++) - { - int len = strlen (completions_found[i]->label); - if (len > max_label) - max_label = len; - } - - max_label += 4; - - /* Find out how many columns we should print in. */ - limit = calling_window->width / max_label; - if (limit != 1 && (limit * max_label == calling_window->width)) - limit--; - - /* Avoid a possible floating exception. If max_label > width then - the limit will be 0 and a divide-by-zero fault will result. */ - if (limit == 0) - limit = 1; - - /* How many iterations of the printing loop? */ - count = (completions_found_index + (limit - 1)) / limit; - - /* Watch out for special case. If the number of completions is less - than LIMIT, then just do the inner printing loop. */ - if (completions_found_index < limit) - count = 1; - - /* Print the sorted items, up-and-down alphabetically. */ - for (i = 0; i < count; i++) - { - register int j; - - for (j = 0, l = i; j < limit; j++) - { - if (l >= completions_found_index) - break; - else - { - char *label; - int printed_length, k; - - label = completions_found[l]->label; - printed_length = strlen (label); - printf_to_message_buffer ("%s", label); - - if (j + 1 < limit) - { - for (k = 0; k < max_label - printed_length; k++) - printf_to_message_buffer (" "); - } - } - l += count; - } - printf_to_message_buffer ("\n"); - } - - /* Make a new node to hold onto possible completions. Don't destroy - dangling pointers. */ - { - NODE *temp; - - temp = message_buffer_to_node (); - add_gcable_pointer (temp->contents); - name_internal_node (temp, compwin_name); - possible_completions_output_node = temp; - } - - /* Find a suitable window for displaying the completions output. - First choice is an existing window showing completions output. - If there is only one window, and it is large, make another - (smaller) window, and use that one. Otherwise, use the caller's - window. */ - { - WINDOW *compwin; - - compwin = get_internal_info_window (compwin_name); - - if (!compwin) - { - /* If we can split the window to display most of the completion - items, then do so. */ - if (calling_window->height > (count * 2)) - { - int start, end, pagetop; - - active_window = calling_window; - - /* Perhaps we can scroll this window on redisplay. */ - start = calling_window->first_row; - pagetop = calling_window->pagetop; - - compwin = - window_make_window (possible_completions_output_node); - active_window = the_echo_area; - window_change_window_height - (compwin, -(compwin->height - (count + 2))); - - window_adjust_pagetop (calling_window); - remember_calling_window (calling_window); - -#if defined (SPLIT_BEFORE_ACTIVE) - /* If the pagetop hasn't changed, scrolling the calling - window is a reasonable thing to do. */ - if (pagetop == calling_window->pagetop) - { - end = start + calling_window->height; - display_scroll_display - (start, end, calling_window->prev->height + 1); - } -#else /* !SPLIT_BEFORE_ACTIVE */ - /* If the pagetop has changed, set the new pagetop here. */ - if (pagetop != calling_window->pagetop) - { - int newtop = calling_window->pagetop; - calling_window->pagetop = pagetop; - set_window_pagetop (calling_window, newtop); - } -#endif /* !SPLIT_BEFORE_ACTIVE */ - - echo_area_completions_window = compwin; - remember_window_and_node (compwin, compwin->node); - } - else - compwin = calling_window; - } - - if (compwin->node != possible_completions_output_node) - { - window_set_node_of_window - (compwin, possible_completions_output_node); - remember_window_and_node (compwin, compwin->node); - } - - display_update_display (windows); - } - } -} - -DECLARE_INFO_COMMAND (ea_complete, "Insert completion") -{ - if (!echo_area_completion_items) - { - ea_insert (window, count, key); - return; - } - - /* If KEY is SPC, and we are not forcing completion to take place, simply - insert the key. */ - if (!echo_area_must_complete_p && key == SPC) - { - ea_insert (window, count, key); - return; - } - - if (ea_last_executed_command == ea_complete) - { - /* If the keypress is a SPC character, and we have already tried - completing once, and there are several completions, then check - the batch of completions to see if any continue with a space. - If there are some, insert the space character and continue. */ - if (key == SPC && completions_found_index > 1) - { - register int i, offset; - - offset = input_line_end - input_line_beg; - - for (i = 0; i < completions_found_index; i++) - if (completions_found[i]->label[offset] == ' ') - break; - - if (completions_found[i]) - ea_insert (window, 1, ' '); - else - { - ea_possible_completions (window, count, key); - return; - } - } - else - { - ea_possible_completions (window, count, key); - return; - } - } - - input_line_point = input_line_end; - build_completions (); - - if (!completions_found_index) - terminal_ring_bell (); - else if (LCD_completion->label[0] == '\0') - ea_possible_completions (window, count, key); - else - { - register int i; - input_line_point = input_line_end = input_line_beg; - for (i = 0; LCD_completion->label[i]; i++) - ea_insert (window, 1, LCD_completion->label[i]); - } -} - -/* Utility REFERENCE used to store possible LCD. */ -static REFERENCE LCD_reference = { (char *)NULL, (char *)NULL, (char *)NULL }; - -static void remove_completion_duplicates (); - -/* Variables which remember the state of the most recent call - to build_completions (). */ -static char *last_completion_request = (char *)NULL; -static REFERENCE **last_completion_items = (REFERENCE **)NULL; - -/* How to tell the completion builder to reset internal state. */ -static void -completions_must_be_rebuilt () -{ - maybe_free (last_completion_request); - last_completion_request = (char *)NULL; - last_completion_items = (REFERENCE **)NULL; -} - -/* Build a list of possible completions from echo_area_completion_items, - and the contents of input_line. */ -static void -build_completions () -{ - register int i, len; - register REFERENCE *entry; - char *request; - int informed_of_lengthy_job = 0; - - /* If there are no items to complete over, exit immediately. */ - if (!echo_area_completion_items) - { - completions_found_index = 0; - LCD_completion = (REFERENCE *)NULL; - return; - } - - /* Check to see if this call to build completions is the same as the last - call to build completions. */ - len = input_line_end - input_line_beg; - request = (char *)xmalloc (1 + len); - strncpy (request, &input_line[input_line_beg], len); - request[len] = '\0'; - - if (last_completion_request && last_completion_items && - last_completion_items == echo_area_completion_items && - (strcmp (last_completion_request, request) == 0)) - { - free (request); - return; - } - - maybe_free (last_completion_request); - last_completion_request = request; - last_completion_items = echo_area_completion_items; - - /* Always start at the beginning of the list. */ - completions_found_index = 0; - LCD_completion = (REFERENCE *)NULL; - - for (i = 0; entry = echo_area_completion_items[i]; i++) - { - if (strncasecmp (request, entry->label, len) == 0) - add_pointer_to_array (entry, completions_found_index, - completions_found, completions_found_slots, - 20, REFERENCE *); - - if (!informed_of_lengthy_job && completions_found_index > 100) - { - informed_of_lengthy_job = 1; - window_message_in_echo_area ("Building completions..."); - } - } - - if (!completions_found_index) - return; - - /* Sort and prune duplicate entries from the completions array. */ - remove_completion_duplicates (); - - /* If there is only one completion, just return that. */ - if (completions_found_index == 1) - { - LCD_completion = completions_found[0]; - return; - } - - /* Find the least common denominator. */ - { - long shortest = 100000; - - for (i = 1; i < completions_found_index; i++) - { - register int j; - int c1, c2; - - for (j = 0; - (c1 = info_tolower (completions_found[i - 1]->label[j])) && - (c2 = info_tolower (completions_found[i]->label[j])); - j++) - if (c1 != c2) - break; - - if (shortest > j) - shortest = j; - } - - maybe_free (LCD_reference.label); - LCD_reference.label = (char *)xmalloc (1 + shortest); - strncpy (LCD_reference.label, completions_found[0]->label, shortest); - LCD_reference.label[shortest] = '\0'; - LCD_completion = &LCD_reference; - } - - if (informed_of_lengthy_job) - echo_area_initialize_node (); -} - -/* Function called by qsort. */ -static int -compare_references (entry1, entry2) - REFERENCE **entry1, **entry2; -{ - return (strcasecmp ((*entry1)->label, (*entry2)->label)); -} - -/* Prune duplicate entries from COMPLETIONS_FOUND. */ -static void -remove_completion_duplicates () -{ - register int i, j; - REFERENCE **temp; - int newlen; - - if (!completions_found_index) - return; - - /* Sort the items. */ - qsort (completions_found, completions_found_index, sizeof (REFERENCE *), - compare_references); - - for (i = 0, newlen = 1; i < completions_found_index - 1; i++) - { - if (strcmp (completions_found[i]->label, - completions_found[i + 1]->label) == 0) - completions_found[i] = (REFERENCE *)NULL; - else - newlen++; - } - - /* We have marked all the dead slots. It is faster to copy the live slots - twice than to prune the dead slots one by one. */ - temp = (REFERENCE **)xmalloc ((1 + newlen) * sizeof (REFERENCE *)); - for (i = 0, j = 0; i < completions_found_index; i++) - if (completions_found[i]) - temp[j++] = completions_found[i]; - - for (i = 0; i < newlen; i++) - completions_found[i] = temp[i]; - - completions_found[i] = (REFERENCE *)NULL; - completions_found_index = newlen; - free (temp); -} - -/* Scroll the "other" window. If there is a window showing completions, scroll - that one, otherwise scroll the window which was active on entering the read - function. */ -DECLARE_INFO_COMMAND (ea_scroll_completions_window, "Scroll the completions window") -{ - WINDOW *compwin; - int old_pagetop; - - compwin = get_internal_info_window (compwin_name); - - if (!compwin) - compwin = calling_window; - - old_pagetop = compwin->pagetop; - - /* Let info_scroll_forward () do the work, and print any messages that - need to be displayed. */ - info_scroll_forward (compwin, count, key); -} - -/* Function which gets called when an Info window is deleted while the - echo area is active. WINDOW is the window which has just been deleted. */ -void -echo_area_inform_of_deleted_window (window) - WINDOW *window; -{ - /* If this is the calling_window, forget what we remembered about it. */ - if (window == calling_window) - { - if (active_window != the_echo_area) - remember_calling_window (active_window); - else - remember_calling_window (windows); - } - - /* If this window was the echo_area_completions_window, then notice that - the window has been deleted. */ - if (window == echo_area_completions_window) - echo_area_completions_window = (WINDOW *)NULL; -} - -/* **************************************************************** */ -/* */ -/* Pushing and Popping the Echo Area */ -/* */ -/* **************************************************************** */ - -/* Push and Pop the echo area. */ -typedef struct { - char *line; - char *prompt; - REFERENCE **comp_items; - int point, beg, end; - int must_complete; - NODE node; - WINDOW *compwin; -} PUSHED_EA; - -static PUSHED_EA **pushed_echo_areas = (PUSHED_EA **)NULL; -static int pushed_echo_areas_index = 0; -static int pushed_echo_areas_slots = 0; - -/* Pushing the echo_area has a side effect of zeroing the completion_items. */ -static void -push_echo_area () -{ - PUSHED_EA *pushed; - - pushed = (PUSHED_EA *)xmalloc (sizeof (PUSHED_EA)); - pushed->line = strdup (input_line); - pushed->prompt = input_line_prompt; - pushed->point = input_line_point; - pushed->beg = input_line_beg; - pushed->end = input_line_end; - pushed->node = input_line_node; - pushed->comp_items = echo_area_completion_items; - pushed->must_complete = echo_area_must_complete_p; - pushed->compwin = echo_area_completions_window; - - add_pointer_to_array (pushed, pushed_echo_areas_index, pushed_echo_areas, - pushed_echo_areas_slots, 4, PUSHED_EA *); - - echo_area_completion_items = (REFERENCE **)NULL; -} - -static void -pop_echo_area () -{ - PUSHED_EA *popped; - - popped = pushed_echo_areas[--pushed_echo_areas_index]; - - strcpy (input_line, popped->line); - free (popped->line); - input_line_prompt = popped->prompt; - input_line_point = popped->point; - input_line_beg = popped->beg; - input_line_end = popped->end; - input_line_node = popped->node; - echo_area_completion_items = popped->comp_items; - echo_area_must_complete_p = popped->must_complete; - echo_area_completions_window = popped->compwin; - completions_must_be_rebuilt (); - - /* If the completion window no longer exists, forget about it. */ - if (echo_area_completions_window) - { - register WINDOW *win; - - for (win = windows; win; win = win->next) - if (echo_area_completions_window == win) - break; - - /* If the window wasn't found, then it has already been deleted. */ - if (!win) - echo_area_completions_window = (WINDOW *)NULL; - } - - free (popped); -} - -static int -echo_area_stack_depth () -{ - return (pushed_echo_areas_index); -} - -/* Returns non-zero if any of the prior stacked calls to read in the echo - area produced a completions window. */ -static int -echo_area_stack_contains_completions_p () -{ - register int i; - - for (i = 0; i < pushed_echo_areas_index; i++) - if (pushed_echo_areas[i]->compwin) - return (1); - - return (0); -} - -/* **************************************************************** */ -/* */ -/* Error Messages While Reading in Echo Area */ -/* */ -/* **************************************************************** */ - -#if defined (HAVE_SYS_TIME_H) -# include -# define HAVE_STRUCT_TIMEVAL -#endif /* HAVE_SYS_TIME_H */ - -static void -pause_or_input () -{ -#if defined (FD_SET) - struct timeval timer; - fd_set readfds; - int ready; - - FD_ZERO (&readfds); - FD_SET (fileno (stdin), &readfds); - timer.tv_sec = 2; - timer.tv_usec = 750; - ready = select (1, &readfds, (fd_set *)NULL, (fd_set *)NULL, &timer); -#endif /* FD_SET */ -} - -/* Print MESSAGE right after the end of the current line, and wait - for input or 2.75 seconds, whichever comes first. Then flush the - informational message that was printed. */ -void -inform_in_echo_area (message) - char *message; -{ - register int i; - char *text; - - text = strdup (message); - for (i = 0; text[i] && text[i] != '\n'; i++); - text[i] = '\0'; - - echo_area_initialize_node (); - sprintf (&input_line[input_line_end], "%s[%s]\n", - echo_area_is_active ? " ": "", text); - free (text); - the_echo_area->point = input_line_point; - display_update_one_window (the_echo_area); - display_cursor_at_point (active_window); - fflush (stdout); - pause_or_input (); - echo_area_initialize_node (); -} diff --git a/info/echo_area.h b/info/echo_area.h deleted file mode 100644 --- a/info/echo_area.h +++ /dev/null @@ -1,63 +0,0 @@ -/* echo_area.h -- Functions used in reading information from the echo area. */ - -/* 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). */ - -#if !defined (_ECHO_AREA_H_) -#define _ECHO_AREA_H_ - -#define EA_MAX_INPUT 256 - -extern int echo_area_is_active, info_aborted_echo_area; - -/* Non-zero means that the last command executed while reading input - killed some text. */ -extern int echo_area_last_command_was_kill; - -extern void inform_in_echo_area (), echo_area_inform_of_deleted_window (); -extern void echo_area_prep_read (); -extern VFunction *ea_last_executed_command; - -/* 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 - active window, so that we can restore it when we need to. PROMPT, if - non-null, is a prompt to print before reading the line. */ -extern char *info_read_in_echo_area (); - -/* Read a line in the echo area with completion over COMPLETIONS. - Takes arguments of WINDOW, PROMPT, and COMPLETIONS, a REFERENCE **. */ -char *info_read_completing_in_echo_area (); - -/* Read a line in the echo area allowing completion over COMPLETIONS, but - not requiring it. Takes arguments of WINDOW, PROMPT, and COMPLETIONS, - a REFERENCE **. */ -extern char *info_read_maybe_completing (); - -extern void ea_insert (), ea_quoted_insert (); -extern void ea_beg_of_line (), ea_backward (), ea_delete (), ea_end_of_line (); -extern void ea_forward (), ea_abort (), ea_rubout (), ea_complete (); -extern void ea_newline (), ea_kill_line (), ea_transpose_chars (); -extern void ea_yank (), ea_tab_insert (), ea_possible_completions (); -extern void ea_backward_word (), ea_kill_word (), ea_forward_word (); -extern void ea_yank_pop (), ea_backward_kill_word (); -extern void ea_scroll_completions_window (); - -#endif /* _ECHO_AREA_H_ */ diff --git a/info/filesys.c b/info/filesys.c deleted file mode 100644 --- a/info/filesys.c +++ /dev/null @@ -1,617 +0,0 @@ -/* filesys.c -- File system specific functions for hacking this system. */ - -/* 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 -#include -#include -#if defined (HAVE_SYS_FILE_H) -#include -#endif /* HAVE_SYS_FILE_H */ -#include -#include "general.h" -#include "tilde.h" -#include "filesys.h" - -#if !defined (O_RDONLY) -#if defined (HAVE_SYS_FCNTL_H) -#include -#else /* !HAVE_SYS_FCNTL_H */ -#include -#endif /* !HAVE_SYS_FCNTL_H */ -#endif /* !O_RDONLY */ - -#if !defined (errno) -extern int errno; -#endif /* !errno */ - -/* Found in info-utils.c. */ -extern char *filename_non_directory (); - -#if !defined (BUILDING_LIBRARY) -/* Found in session.c */ -extern int info_windows_initialized_p; - -/* Found in window.c. */ -extern void message_in_echo_area (), unmessage_in_echo_area (); -#endif /* !BUILDING_LIBRARY */ - -/* Local to this file. */ -static char *info_file_in_path (), *lookup_info_filename (); -static void remember_info_filename (), maybe_initialize_infopath (); - -#if !defined (NULL) -# define NULL 0x0 -#endif /* !NULL */ - -typedef struct { - char *suffix; - char *decompressor; -} COMPRESSION_ALIST; - -static char *info_suffixes[] = { - "", - ".info", - "-info", - (char *)NULL -}; - -static COMPRESSION_ALIST compress_suffixes[] = { - { ".Z", "uncompress" }, - { ".Y", "unyabba" }, - { ".z", "gunzip" }, - { ".gz", "gunzip" }, - { (char *)NULL, (char *)NULL } -}; - -/* The path on which we look for info files. You can initialize this - from the environment variable INFOPATH if there is one, or you can - call info_add_path () to add paths to the beginning or end of it. - You can call zap_infopath () to make the path go away. */ -char *infopath = (char *)NULL; -static int infopath_size = 0; - -/* Expand the filename in PARTIAL to make a real name for this operating - system. This looks in INFO_PATHS in order to find the correct file. - If it can't find the file, it returns NULL. */ -static char *local_temp_filename = (char *)NULL; -static int local_temp_filename_size = 0; - -char * -info_find_fullpath (partial) - char *partial; -{ - int initial_character; - char *temp; - - filesys_error_number = 0; - - maybe_initialize_infopath (); - - if (partial && (initial_character = *partial)) - { - char *expansion; - - expansion = lookup_info_filename (partial); - - if (expansion) - return (expansion); - - /* If we have the full path to this file, we still may have to add - various extensions to it. I guess we have to stat this file - after all. */ - if (initial_character == '/') - temp = info_file_in_path (partial + 1, "/"); - else if (initial_character == '~') - { - expansion = tilde_expand_word (partial); - if (*expansion == '/') - { - temp = info_file_in_path (expansion + 1, "/"); - free (expansion); - } - else - temp = expansion; - } - else if (initial_character == '.' && - (partial[1] == '/' || (partial[1] == '.' && partial[2] == '/'))) - { - if (local_temp_filename_size < 1024) - local_temp_filename = (char *)xrealloc - (local_temp_filename, (local_temp_filename_size = 1024)); -#if defined (HAVE_GETCWD) - if (!getcwd (local_temp_filename, local_temp_filename_size)) -#else /* !HAVE_GETCWD */ - if (!getwd (local_temp_filename)) -#endif /* !HAVE_GETCWD */ - { - filesys_error_number = errno; - return (partial); - } - - strcat (local_temp_filename, "/"); - strcat (local_temp_filename, partial); - return (local_temp_filename); - } - else - temp = info_file_in_path (partial, infopath); - - if (temp) - { - remember_info_filename (partial, temp); - if (strlen (temp) > local_temp_filename_size) - local_temp_filename = (char *) xrealloc - (local_temp_filename, - (local_temp_filename_size = (50 + strlen (temp)))); - strcpy (local_temp_filename, temp); - free (temp); - return (local_temp_filename); - } - } - return (partial); -} - -/* Scan the list of directories in PATH looking for FILENAME. If we find - one that is a regular file, return it as a new string. Otherwise, return - a NULL pointer. */ -static char * -info_file_in_path (filename, path) - char *filename, *path; -{ - struct stat finfo; - char *temp_dirname; - int statable, dirname_index; - - dirname_index = 0; - - while (temp_dirname = extract_colon_unit (path, &dirname_index)) - { - register int i, pre_suffix_length; - char *temp; - - /* Expand a leading tilde if one is present. */ - if (*temp_dirname == '~') - { - char *expanded_dirname; - - expanded_dirname = tilde_expand_word (temp_dirname); - free (temp_dirname); - temp_dirname = expanded_dirname; - } - - temp = (char *)xmalloc (30 + strlen (temp_dirname) + strlen (filename)); - strcpy (temp, temp_dirname); - if (temp[(strlen (temp)) - 1] != '/') - strcat (temp, "/"); - strcat (temp, filename); - - pre_suffix_length = strlen (temp); - - free (temp_dirname); - - for (i = 0; info_suffixes[i]; i++) - { - strcpy (temp + pre_suffix_length, info_suffixes[i]); - - statable = (stat (temp, &finfo) == 0); - - /* If we have found a regular file, then use that. Else, if we - have found a directory, look in that directory for this file. */ - if (statable) - { - if (S_ISREG (finfo.st_mode)) - { - return (temp); - } - else if (S_ISDIR (finfo.st_mode)) - { - char *newpath, *filename_only, *newtemp; - - newpath = strdup (temp); - filename_only = filename_non_directory (filename); - newtemp = info_file_in_path (filename_only, newpath); - - free (newpath); - if (newtemp) - { - free (temp); - return (newtemp); - } - } - } - else - { - /* Add various compression suffixes to the name to see if - the file is present in compressed format. */ - register int j, pre_compress_suffix_length; - - pre_compress_suffix_length = strlen (temp); - - for (j = 0; compress_suffixes[j].suffix; j++) - { - strcpy (temp + pre_compress_suffix_length, - compress_suffixes[j].suffix); - - statable = (stat (temp, &finfo) == 0); - if (statable && (S_ISREG (finfo.st_mode))) - return (temp); - } - } - } - free (temp); - } - return ((char *)NULL); -} - -/* Given a string containing units of information separated by colons, - return the next one pointed to by IDX, or NULL if there are no more. - Advance IDX to the character after the colon. */ -char * -extract_colon_unit (string, idx) - char *string; - int *idx; -{ - register int i, start; - - i = start = *idx; - if ((i >= strlen (string)) || !string) - return ((char *) NULL); - - while (string[i] && string[i] != ':') - i++; - if (i == start) - { - return ((char *) NULL); - } - else - { - char *value; - - value = (char *) xmalloc (1 + (i - start)); - strncpy (value, &string[start], (i - start)); - value[i - start] = '\0'; - if (string[i]) - ++i; - *idx = i; - return (value); - } -} - -/* A structure which associates a filename with its expansion. */ -typedef struct { - char *filename; - char *expansion; -} FILENAME_LIST; - -/* An array of remembered arguments and results. */ -static FILENAME_LIST **names_and_files = (FILENAME_LIST **)NULL; -static int names_and_files_index = 0; -static int names_and_files_slots = 0; - -/* Find the result for having already called info_find_fullpath () with - FILENAME. */ -static char * -lookup_info_filename (filename) - char *filename; -{ - if (filename && names_and_files) - { - register int i; - for (i = 0; names_and_files[i]; i++) - { - if (strcmp (names_and_files[i]->filename, filename) == 0) - return (names_and_files[i]->expansion); - } - } - return (char *)NULL;; -} - -/* Add a filename and its expansion to our list. */ -static void -remember_info_filename (filename, expansion) - char *filename, *expansion; -{ - FILENAME_LIST *new; - - if (names_and_files_index + 2 > names_and_files_slots) - { - int alloc_size; - names_and_files_slots += 10; - - alloc_size = names_and_files_slots * sizeof (FILENAME_LIST *); - - names_and_files = - (FILENAME_LIST **) xrealloc (names_and_files, alloc_size); - } - - new = (FILENAME_LIST *)xmalloc (sizeof (FILENAME_LIST)); - new->filename = strdup (filename); - new->expansion = expansion ? strdup (expansion) : (char *)NULL; - - names_and_files[names_and_files_index++] = new; - names_and_files[names_and_files_index] = (FILENAME_LIST *)NULL; -} - -static void -maybe_initialize_infopath () -{ - if (!infopath_size) - { - infopath = (char *) - xmalloc (infopath_size = (1 + strlen (DEFAULT_INFOPATH))); - - strcpy (infopath, DEFAULT_INFOPATH); - } -} - -/* Add PATH to the list of paths found in INFOPATH. 2nd argument says - whether to put PATH at the front or end of INFOPATH. */ -void -info_add_path (path, where) - char *path; - int where; -{ - int len; - - if (!infopath) - { - infopath = (char *)xmalloc (infopath_size = 200 + strlen (path)); - infopath[0] = '\0'; - } - - len = strlen (path) + strlen (infopath); - - if (len + 2 >= infopath_size) - infopath = (char *)xrealloc (infopath, (infopath_size += (2 * len) + 2)); - - if (!*infopath) - strcpy (infopath, path); - else if (where == INFOPATH_APPEND) - { - strcat (infopath, ":"); - strcat (infopath, path); - } - else if (where == INFOPATH_PREPEND) - { - char *temp = strdup (infopath); - strcpy (infopath, path); - strcat (infopath, ":"); - strcat (infopath, temp); - free (temp); - } -} - -/* Make INFOPATH have absolutely nothing in it. */ -void -zap_infopath () -{ - if (infopath) - free (infopath); - - infopath = (char *)NULL; - infopath_size = 0; -} - -/* Read the contents of PATHNAME, returning a buffer with the contents of - that file in it, and returning the size of that buffer in FILESIZE. - FINFO is a stat struct which has already been filled in by the caller. - If the file cannot be read, return a NULL pointer. */ -char * -filesys_read_info_file (pathname, filesize, finfo) - char *pathname; - long *filesize; - struct stat *finfo; -{ - long st_size; - - *filesize = filesys_error_number = 0; - - if (compressed_filename_p (pathname)) - return (filesys_read_compressed (pathname, filesize, finfo)); - else - { - int descriptor; - char *contents; - - descriptor = open (pathname, O_RDONLY, 0666); - - /* If the file couldn't be opened, give up. */ - if (descriptor < 0) - { - filesys_error_number = errno; - return ((char *)NULL); - } - - /* Try to read the contents of this file. */ - st_size = (long) finfo->st_size; - contents = (char *)xmalloc (1 + st_size); - if ((read (descriptor, contents, st_size)) != st_size) - { - filesys_error_number = errno; - close (descriptor); - free (contents); - return ((char *)NULL); - } - - close (descriptor); - - *filesize = st_size; - return (contents); - } -} - -/* Typically, pipe buffers are 4k. */ -#define BASIC_PIPE_BUFFER (4 * 1024) - -/* We use some large multiple of that. */ -#define FILESYS_PIPE_BUFFER_SIZE (16 * BASIC_PIPE_BUFFER) - -char * -filesys_read_compressed (pathname, filesize, finfo) - char *pathname; - long *filesize; - struct stat *finfo; -{ - FILE *stream; - char *command, *decompressor; - char *contents = (char *)NULL; - - *filesize = filesys_error_number = 0; - - decompressor = filesys_decompressor_for_file (pathname); - - if (!decompressor) - return ((char *)NULL); - - command = (char *)xmalloc (10 + strlen (pathname) + strlen (decompressor)); - sprintf (command, "%s < %s", decompressor, pathname); - -#if !defined (BUILDING_LIBRARY) - if (info_windows_initialized_p) - { - char *temp; - - temp = (char *)xmalloc (5 + strlen (command)); - sprintf (temp, "%s...", command); - message_in_echo_area ("%s", temp); - free (temp); - } -#endif /* !BUILDING_LIBRARY */ - - stream = popen (command, "r"); - free (command); - - /* Read chunks from this file until there are none left to read. */ - if (stream) - { - int offset, size; - char *chunk; - - offset = size = 0; - chunk = (char *)xmalloc (FILESYS_PIPE_BUFFER_SIZE); - - while (1) - { - int bytes_read; - - bytes_read = fread (chunk, 1, FILESYS_PIPE_BUFFER_SIZE, stream); - - if (bytes_read + offset >= size) - contents = (char *)xrealloc - (contents, size += (2 * FILESYS_PIPE_BUFFER_SIZE)); - - memcpy (contents + offset, chunk, bytes_read); - offset += bytes_read; - if (bytes_read != FILESYS_PIPE_BUFFER_SIZE) - break; - } - - free (chunk); - pclose (stream); - contents = (char *)xrealloc (contents, offset + 1); - *filesize = offset; - } - else - { - filesys_error_number = errno; - } - -#if !defined (BUILDING_LIBARARY) - if (info_windows_initialized_p) - unmessage_in_echo_area (); -#endif /* !BUILDING_LIBRARY */ - return (contents); -} - -/* Return non-zero if FILENAME belongs to a compressed file. */ -int -compressed_filename_p (filename) - char *filename; -{ - char *decompressor; - - /* Find the final extension of this filename, and see if it matches one - of our known ones. */ - decompressor = filesys_decompressor_for_file (filename); - - if (decompressor) - return (1); - else - return (0); -} - -/* Return the command string that would be used to decompress FILENAME. */ -char * -filesys_decompressor_for_file (filename) - char *filename; -{ - register int i; - char *extension = (char *)NULL; - - /* Find the final extension of FILENAME, and see if it appears in our - list of known compression extensions. */ - for (i = strlen (filename) - 1; i > 0; i--) - if (filename[i] == '.') - { - extension = filename + i; - break; - } - - if (!extension) - return ((char *)NULL); - - for (i = 0; compress_suffixes[i].suffix; i++) - if (strcmp (extension, compress_suffixes[i].suffix) == 0) - return (compress_suffixes[i].decompressor); - - return ((char *)NULL); -} - -/* The number of the most recent file system error. */ -int filesys_error_number = 0; - -/* A function which returns a pointer to a static buffer containing - an error message for FILENAME and ERROR_NUM. */ -static char *errmsg_buf = (char *)NULL; -static int errmsg_buf_size = 0; - -char * -filesys_error_string (filename, error_num) - char *filename; - int error_num; -{ - int len; - char *result; - - if (error_num == 0) - return ((char *)NULL); - - result = strerror (error_num); - - len = 4 + strlen (filename) + strlen (result); - if (len >= errmsg_buf_size) - errmsg_buf = (char *)xrealloc (errmsg_buf, (errmsg_buf_size = 2 + len)); - - sprintf (errmsg_buf, "%s: %s", filename, result); - return (errmsg_buf); -} - diff --git a/info/filesys.h b/info/filesys.h deleted file mode 100644 --- a/info/filesys.h +++ /dev/null @@ -1,84 +0,0 @@ -/* filesys.h -- External declarations of functions and vars in filesys.c. */ - -/* 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). */ - -#if !defined (_FILESYS_H_) -#define _FILESYS_H_ - -/* The path on which we look for info files. You can initialize this - from the environment variable INFOPATH if there is one, or you can - call info_add_path () to add paths to the beginning or end of it. */ -extern char *infopath; - -/* Make INFOPATH have absolutely nothing in it. */ -extern void zap_infopath (); - -/* Add PATH to the list of paths found in INFOPATH. 2nd argument says - whether to put PATH at the front or end of INFOPATH. */ -extern void info_add_path (); - -/* Defines that are passed along with the pathname to info_add_path (). */ -#define INFOPATH_PREPEND 0 -#define INFOPATH_APPEND 1 - -/* Expand the filename in PARTIAL to make a real name for this operating - system. This looks in INFO_PATHS in order to find the correct file. - If it can't find the file, it returns NULL. */ -extern char *info_find_fullpath (); - -/* Read the contents of PATHNAME, returning a buffer with the contents of - that file in it, and returning the size of that buffer in FILESIZE. - FINFO is a stat struct which has already been filled in by the caller. - If the file cannot be read, return a NULL pointer. */ -extern char *filesys_read_info_file (); -extern char *filesys_read_compressed (); - -/* Return the command string that would be used to decompress FILENAME. */ -extern char *filesys_decompressor_for_file (); -extern int compressed_filename_p (); - -/* A function which returns a pointer to a static buffer containing - an error message for FILENAME and ERROR_NUM. */ -extern char *filesys_error_string (); - -/* The number of the most recent file system error. */ -extern int filesys_error_number; - -/* Given a string containing units of information separated by colons, - return the next one pointed to by IDX, or NULL if there are no more. - Advance IDX to the character after the colon. */ -extern char *extract_colon_unit (); - -/* The default value of INFOPATH. */ -#if !defined (DEFAULT_INFOPATH) -# define DEFAULT_INFOPATH "/usr/local/info:/usr/info:/usr/local/lib/info:/usr/lib/info:/usr/local/gnu/info:/usr/local/gnu/lib/info:/usr/gnu/info:/usr/gnu/lib/info:/opt/gnu/info:/usr/share/info:/usr/share/lib/info:/usr/local/share/info:/usr/local/share/lib/info:/usr/gnu/lib/emacs/info:/usr/local/gnu/lib/emacs/info:/usr/local/lib/emacs/info:/usr/local/emacs/info:." -#endif /* !DEFAULT_INFOPATH */ - -#if !defined (S_ISREG) && defined (S_IFREG) -# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) -#endif /* !S_ISREG && S_IFREG */ - -#if !defined (S_ISDIR) && defined (S_IFDIR) -# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) -#endif /* !S_ISDIR && S_IFDIR */ - -#endif /* !_FILESYS_H_ */ diff --git a/info/footnotes.c b/info/footnotes.c deleted file mode 100644 --- a/info/footnotes.c +++ /dev/null @@ -1,265 +0,0 @@ -/* footnotes.c -- Some functions for manipulating footnotes. */ - -/* 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" - -/* Non-zero means attempt to show footnotes when displaying a new window. */ -int auto_footnotes_p = 1; - -static char *footnote_nodename = "*Footnotes*"; - -#define FOOTNOTE_HEADER_FORMAT \ - "*** Footnotes appearing in the node \"%s\" ***\n" - -/* Find the window currently showing footnotes. */ -static WINDOW * -find_footnotes_window () -{ - WINDOW *win; - - /* Try to find an existing window first. */ - for (win = windows; win; win = win->next) - if (internal_info_node_p (win->node) && - (strcmp (win->node->nodename, footnote_nodename) == 0)) - break; - - return (win); -} - -/* Manufacture a node containing the footnotes of this node, and - return the manufactured node. If NODE has no footnotes, return a - NULL pointer. */ -NODE * -make_footnotes_node (node) - NODE *node; -{ - NODE *fn_node, *result = (NODE *)NULL; - long fn_start; - - /* Make the initial assumption that the footnotes appear as simple - text within this windows node. */ - fn_node = node; - - /* See if this node contains the magic footnote label. */ - fn_start = - info_search_in_node (FOOTNOTE_LABEL, node, 0, (WINDOW *)NULL, 1); - - /* If it doesn't, check to see if it has an associated footnotes node. */ - if (fn_start == -1) - { - REFERENCE **refs; - - refs = info_xrefs_of_node (node); - - if (refs) - { - register int i; - char *refname; - - refname = (char *)xmalloc - (1 + strlen ("-Footnotes") + strlen (node->nodename)); - - strcpy (refname, node->nodename); - strcat (refname, "-Footnotes"); - - for (i = 0; refs[i]; i++) - if ((refs[i]->nodename != (char *)NULL) && - (strcmp (refs[i]->nodename, refname) == 0)) - { - char *filename; - - filename = node->parent; - if (!filename) - filename = node->filename; - - fn_node = info_get_node (filename, refname); - - if (fn_node) - fn_start = 0; - - break; - } - - free (refname); - info_free_references (refs); - } - } - - /* If we never found the start of a footnotes area, quit now. */ - if (fn_start == -1) - return ((NODE *)NULL); - - /* Make the new node. */ - result = (NODE *)xmalloc (sizeof (NODE)); - result->flags = 0; - - /* Get the size of the footnotes appearing within this node. */ - { - char *header; - long text_start = fn_start; - - header = (char *)xmalloc - (1 + strlen (node->nodename) + strlen (FOOTNOTE_HEADER_FORMAT)); - sprintf (header, FOOTNOTE_HEADER_FORMAT, node->nodename); - - /* Move the start of the displayed text to right after the first line. - This effectively skips either "---- footno...", or "File: foo...". */ - while (text_start < fn_node->nodelen) - if (fn_node->contents[text_start++] == '\n') - break; - - result->nodelen = strlen (header) + fn_node->nodelen - text_start; - - /* Set the contents of this node. */ - result->contents = (char *)xmalloc (1 + result->nodelen); - sprintf (result->contents, "%s", header); - memcpy (result->contents + strlen (header), - fn_node->contents + text_start, fn_node->nodelen - text_start); - - name_internal_node (result, footnote_nodename); - free (header); - } - -#if defined (NOTDEF) - /* If the footnotes were gleaned from the node that we were called with, - shorten the calling node's display length. */ - if (fn_node == node) - narrow_node (node, 0, fn_start); -#endif /* NOTDEF */ - - return (result); -} - -/* Create or delete the footnotes window depending on whether footnotes - exist in WINDOW's node or not. Returns FN_FOUND if footnotes were found - and displayed. Returns FN_UNFOUND if there were no footnotes found - in WINDOW's node. Returns FN_UNABLE if there were footnotes, but the - window to show them couldn't be made. */ -int -info_get_or_remove_footnotes (window) - WINDOW *window; -{ - WINDOW *fn_win; - NODE *new_footnotes; - - fn_win = find_footnotes_window (); - - /* If we are in the footnotes window, change nothing. */ - if (fn_win == window) - return (FN_FOUND); - - /* Try to find footnotes for this window's node. */ - new_footnotes = make_footnotes_node (window->node); - - /* If there was a window showing footnotes, and there are no footnotes - for the current window, delete the old footnote window. */ - if (fn_win && !new_footnotes) - { - if (windows->next) - info_delete_window_internal (fn_win); - } - - /* If there are footnotes for this window's node, but no window around - showing footnotes, try to make a new window. */ - if (new_footnotes && !fn_win) - { - WINDOW *old_active; - WINDOW *last, *win; - - /* Always make this window be the last one appearing in the list. Find - the last window in the chain. */ - for (win = windows, last = windows; win; last = win, win = win->next); - - /* Try to split this window, and make the split window the one to - contain the footnotes. */ - old_active = active_window; - active_window = last; - fn_win = window_make_window (new_footnotes); - active_window = old_active; - - if (!fn_win) - { - free (new_footnotes->contents); - free (new_footnotes); - - /* If we are hacking automatic footnotes, and there are footnotes - but we couldn't display them, print a message to that effect. */ - if (auto_footnotes_p) - inform_in_echo_area ("Footnotes could not be displayed"); - return (FN_UNABLE); - } - } - - /* If there are footnotes, and there is a window to display them, - make that window be the number of lines appearing in the footnotes. */ - if (new_footnotes && fn_win) - { - window_set_node_of_window (fn_win, new_footnotes); - - window_change_window_height - (fn_win, fn_win->line_count - fn_win->height); - - remember_window_and_node (fn_win, new_footnotes); - add_gcable_pointer (new_footnotes->contents); - } - - if (!new_footnotes) - return (FN_UNFOUND); - else - return (FN_FOUND); -} - -/* Show the footnotes associated with this node in another window. */ -DECLARE_INFO_COMMAND (info_show_footnotes, - "Show the footnotes associated with this node in another window") -{ - int result; - - /* A negative argument means just make the window go away. */ - if (count < 0) - { - WINDOW *fn_win = find_footnotes_window (); - - /* If there is an old footnotes window, and it isn't the only window - on the screen, delete it. */ - if (fn_win && windows->next) - info_delete_window_internal (fn_win); - } - else - { - int result; - - result = info_get_or_remove_footnotes (window); - - switch (result) - { - case FN_UNFOUND: - info_error (NO_FOOT_NODE); - break; - - case FN_UNABLE: - info_error (WIN_TOO_SMALL); - break; - } - } -} diff --git a/info/footnotes.h b/info/footnotes.h deleted file mode 100644 --- a/info/footnotes.h +++ /dev/null @@ -1,46 +0,0 @@ -/* footnotes.h -- Some functions for manipulating footnotes. */ - -/* 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). */ - -#if !defined (_FOOTNOTES_H_) -#define _FOOTNOTES_H_ - -/* Magic string which indicates following text is footnotes. */ -#define FOOTNOTE_LABEL "---------- Footnotes ----------" - -#define FN_FOUND 0 -#define FN_UNFOUND 1 -#define FN_UNABLE 2 - - -/* Create or delete the footnotes window depending on whether footnotes - exist in WINDOW's node or not. Returns FN_FOUND if footnotes were found - and displayed. Returns FN_UNFOUND if there were no footnotes found - in WINDOW's node. Returns FN_UNABLE if there were footnotes, but the - window to show them couldn't be made. */ -extern int info_get_or_remove_footnotes (); - -/* Non-zero means attempt to show footnotes when displaying a new window. */ -extern int auto_footnotes_p; - -#endif /* !_FOOTNOTES_H_ */ - diff --git a/info/gc.c b/info/gc.c deleted file mode 100644 --- a/info/gc.c +++ /dev/null @@ -1,95 +0,0 @@ -/* gc.c -- Functions to remember and garbage collect unused node contents. */ - -/* 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" - -/* Array of pointers to the contents of gc-able nodes. A pointer on this - list can be garbage collected when no info window contains a node whose - contents member match the pointer. */ -static char **gcable_pointers = (char **)NULL; -static int gcable_pointers_index = 0; -static int gcable_pointers_slots = 0; - -/* Add POINTER to the list of garbage collectible pointers. A pointer - is not actually garbage collected until no info window contains a node - whose contents member is equal to the pointer. */ -void -add_gcable_pointer (pointer) - char *pointer; -{ - gc_pointers (); - add_pointer_to_array (pointer, gcable_pointers_index, gcable_pointers, - gcable_pointers_slots, 10, char *); -} - -/* Grovel the list of info windows and gc-able pointers finding those - node->contents which are collectible, and free them. */ -void -gc_pointers () -{ - register int i, j, k; - INFO_WINDOW *iw; - char **new = (char **)NULL; - int new_index = 0; - int new_slots = 0; - - if (!info_windows || !gcable_pointers_index) - return; - - for (i = 0; iw = info_windows[i]; i++) - { - for (j = 0; j < iw->nodes_index; j++) - { - NODE *node = iw->nodes[j]; - - /* If this node->contents appears in our list of gcable_pointers, - it is not gc-able, so save it. */ - for (k = 0; k < gcable_pointers_index; k++) - if (gcable_pointers[k] == node->contents) - { - add_pointer_to_array - (node->contents, new_index, new, new_slots, 10, char *); - break; - } - } - } - - /* We have gathered all of the pointers which need to be saved. Free any - of the original pointers which do not appear in the new list. */ - for (i = 0; i < gcable_pointers_index; i++) - { - for (j = 0; j < new_index; j++) - if (gcable_pointers[i] == new[j]) - break; - - /* If we got all the way through the new list, then the old pointer - can be garbage collected. */ - if (new && !new[j]) - free (gcable_pointers[i]); - } - - free (gcable_pointers); - gcable_pointers = new; - gcable_pointers_slots = new_slots; - gcable_pointers_index = new_index; -} diff --git a/info/gc.h b/info/gc.h deleted file mode 100644 --- a/info/gc.h +++ /dev/null @@ -1,36 +0,0 @@ -/* gc.h -- Functions for garbage collecting unused node contents. */ - -/* 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). */ - -#if !defined (_GC_H_) -#define _GC_H_ - -/* Add POINTER to the list of garbage collectible pointers. A pointer - is not actually garbage collected until no info window contains a node - whose contents member is equal to the pointer. */ -extern void add_gcable_pointer (); - -/* Grovel the list of info windows and gc-able pointers finding those - node->contents which are collectible, and free them. */ -extern void gc_pointers (); - -#endif /* !_GC_H_ */ diff --git a/info/general.h b/info/general.h deleted file mode 100644 --- a/info/general.h +++ /dev/null @@ -1,94 +0,0 @@ -/* general.h -- Some generally useful defines. */ - -/* 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). */ - -#if !defined (_GENERAL_H_) -#define _GENERAL_H_ - -extern void *xmalloc (), *xrealloc (); - -#if defined (HAVE_UNISTD_H) -# include -#endif /* HAVE_UNISTD_H */ - -#if defined (HAVE_STRING_H) -# include -#else -# include -#endif /* !HAVE_STRING_H */ - -#include "clib.h" - -#define info_toupper(x) (islower (x) ? toupper (x) : x) -#define info_tolower(x) (isupper (x) ? tolower (x) : x) - -#if !defined (whitespace) -# define whitespace(c) ((c == ' ') || (c == '\t')) -#endif /* !whitespace */ - -#if !defined (whitespace_or_newline) -# define whitespace_or_newline(c) (whitespace (c) || (c == '\n')) -#endif /* !whitespace_or_newline */ - -#if !defined (__FUNCTION_DEF) -# define __FUNCTION_DEF -typedef int Function (); -typedef void VFunction (); -typedef char *CFunction (); -#endif /* _FUNCTION_DEF */ - -/* Add POINTER to the list of pointers found in ARRAY. SLOTS is the number - of slots that have already been allocated. INDEX is the index into the - array where POINTER should be added. GROW is the number of slots to grow - ARRAY by, in the case that it needs growing. TYPE is a cast of the type - of object stored in ARRAY (e.g., NODE_ENTRY *. */ -#define add_pointer_to_array(pointer, idx, array, slots, grow, type) \ - do { \ - if (idx + 2 >= slots) \ - array = (type *)(xrealloc (array, (slots += grow) * sizeof (type))); \ - array[idx++] = (type)pointer; \ - array[idx] = (type)NULL; \ - } while (0) - -#define maybe_free(x) do { if (x) free (x); } while (0) - -#if !defined (zero_mem) && defined (HAVE_MEMSET) -# define zero_mem(mem, length) memset (mem, 0, length) -#endif /* !zero_mem && HAVE_MEMSET */ - -#if !defined (zero_mem) && defined (HAVE_BZERO) -# define zero_mem(mem, length) bzero (mem, length) -#endif /* !zero_mem && HAVE_BZERO */ - -#if !defined (zero_mem) -# define zero_mem(mem, length) \ - do { \ - register int zi; \ - register unsigned char *place; \ - \ - place = (unsigned char *)mem; \ - for (zi = 0; zi < length; zi++) \ - place[zi] = 0; \ - } while (0) -#endif /* !zero_mem */ - -#endif /* !_GENERAL_H_ */ diff --git a/info/getopt.c b/info/getopt.c deleted file mode 100644 --- a/info/getopt.c +++ /dev/null @@ -1,762 +0,0 @@ -/* Getopt for GNU. - NOTE: getopt is now part of the C library, so if you don't know what - "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu - before changing it! - - Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95 - 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -/* This tells Alpha OSF/1 not to define a getopt prototype in . - Ditto for AIX 3.2 and . */ -#ifndef _NO_PROTO -#define _NO_PROTO -#endif - -#ifdef HAVE_CONFIG_H -#include -#endif - -#if !defined (__STDC__) || !__STDC__ -/* This is a separate conditional since some stdc systems - reject `defined (const)'. */ -#ifndef const -#define const -#endif -#endif - -#include - -/* Comment out all this code if we are using the GNU C Library, and are not - actually compiling the library itself. This code is part of the GNU C - Library, but also included in many other GNU distributions. Compiling - and linking in this code is a waste when using the GNU C library - (especially if it is a shared library). Rather than having every GNU - program understand `configure --with-gnu-libc' and omit the object files, - it is simpler to just do this in the source for each such file. */ - -#if defined (_LIBC) || !defined (__GNU_LIBRARY__) - - -/* This needs to come after some library #include - to get __GNU_LIBRARY__ defined. */ -#ifdef __GNU_LIBRARY__ -/* Don't include stdlib.h for non-GNU C libraries because some of them - contain conflicting prototypes for getopt. */ -#include -#endif /* GNU C library. */ - -/* This is for other GNU distributions with internationalized messages. - The GNU C Library itself does not yet support such messages. */ -#if HAVE_LIBINTL_H -# include -#else -# define gettext(msgid) (msgid) -#endif - -/* This version of `getopt' appears to the caller like standard Unix `getopt' - but it behaves differently for the user, since it allows the user - to intersperse the options with the other arguments. - - As `getopt' works, it permutes the elements of ARGV so that, - when it is done, all the options precede everything else. Thus - all application programs are extended to handle flexible argument order. - - Setting the environment variable POSIXLY_CORRECT disables permutation. - Then the behavior is completely standard. - - GNU application programs can use a third alternative mode in which - they can distinguish the relative order of options and other arguments. */ - -#include "getopt.h" - -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - -char *optarg = NULL; - -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to `getopt'. - - On entry to `getopt', zero means this is the first call; initialize. - - When `getopt' returns EOF, this is the index of the first of the - non-option elements that the caller should itself scan. - - Otherwise, `optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ - -/* XXX 1003.2 says this must be 1 before any call. */ -int optind = 0; - -/* The next char to be scanned in the option-element - in which the last option character we returned was found. - This allows us to pick up the scan where we left off. - - If this is zero, or a null string, it means resume the scan - by advancing to the next ARGV-element. */ - -static char *nextchar; - -/* Callers store zero here to inhibit the error message - for unrecognized options. */ - -int opterr = 1; - -/* Set to an option character which was unrecognized. - This must be initialized on some systems to avoid linking in the - system's own getopt implementation. */ - -int optopt = '?'; - -/* Describe how to deal with options that follow non-option ARGV-elements. - - If the caller did not specify anything, - the default is REQUIRE_ORDER if the environment variable - POSIXLY_CORRECT is defined, PERMUTE otherwise. - - REQUIRE_ORDER means don't recognize them as options; - stop option processing when the first non-option is seen. - This is what Unix does. - This mode of operation is selected by either setting the environment - variable POSIXLY_CORRECT, or using `+' as the first character - of the list of option characters. - - PERMUTE is the default. We permute the contents of ARGV as we scan, - so that eventually all the non-options are at the end. This allows options - to be given in any order, even with programs that were not written to - expect this. - - RETURN_IN_ORDER is an option available to programs that were written - to expect options and other ARGV-elements in any order and that care about - the ordering of the two. We describe each non-option ARGV-element - as if it were the argument of an option with character code 1. - Using `-' as the first character of the list of option characters - selects this mode of operation. - - The special argument `--' forces an end of option-scanning regardless - of the value of `ordering'. In the case of RETURN_IN_ORDER, only - `--' can cause `getopt' to return EOF with `optind' != ARGC. */ - -static enum -{ - REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER -} ordering; - -/* Value of POSIXLY_CORRECT environment variable. */ -static char *posixly_correct; - -#ifdef __GNU_LIBRARY__ -/* We want to avoid inclusion of string.h with non-GNU libraries - because there are many ways it can cause trouble. - On some systems, it contains special magic macros that don't work - in GCC. */ -#include -#define my_index strchr -#else - -/* Avoid depending on library functions or files - whose names are inconsistent. */ - -char *getenv (); - -static char * -my_index (str, chr) - const char *str; - int chr; -{ - while (*str) - { - if (*str == chr) - return (char *) str; - str++; - } - return 0; -} - -/* If using GCC, we can safely declare strlen this way. - If not using GCC, it is ok not to declare it. */ -#ifdef __GNUC__ -/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. - That was relevant to code that was here before. */ -#if !defined (__STDC__) || !__STDC__ -/* gcc with -traditional declares the built-in strlen to return int, - and has done so at least since version 2.4.5. -- rms. */ -extern int strlen (const char *); -#endif /* not __STDC__ */ -#endif /* __GNUC__ */ - -#endif /* not __GNU_LIBRARY__ */ - -/* Handle permutation of arguments. */ - -/* Describe the part of ARGV that contains non-options that have - been skipped. `first_nonopt' is the index in ARGV of the first of them; - `last_nonopt' is the index after the last of them. */ - -static int first_nonopt; -static int last_nonopt; - -/* Exchange two adjacent subsequences of ARGV. - One subsequence is elements [first_nonopt,last_nonopt) - which contains all the non-options that have been skipped so far. - The other is elements [last_nonopt,optind), which contains all - the options processed since those non-options were skipped. - - `first_nonopt' and `last_nonopt' are relocated so that they describe - the new indices of the non-options in ARGV after they are moved. */ - -static void -exchange (argv) - char **argv; -{ - int bottom = first_nonopt; - int middle = last_nonopt; - int top = optind; - char *tem; - - /* Exchange the shorter segment with the far end of the longer segment. - That puts the shorter segment into the right place. - It leaves the longer segment in the right place overall, - but it consists of two parts that need to be swapped next. */ - - while (top > middle && middle > bottom) - { - if (top - middle > middle - bottom) - { - /* Bottom segment is the short one. */ - int len = middle - bottom; - register int i; - - /* Swap it with the top part of the top segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[top - (middle - bottom) + i]; - argv[top - (middle - bottom) + i] = tem; - } - /* Exclude the moved bottom segment from further swapping. */ - top -= len; - } - else - { - /* Top segment is the short one. */ - int len = top - middle; - register int i; - - /* Swap it with the bottom part of the bottom segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[middle + i]; - argv[middle + i] = tem; - } - /* Exclude the moved top segment from further swapping. */ - bottom += len; - } - } - - /* Update records for the slots the non-options now occupy. */ - - first_nonopt += (optind - last_nonopt); - last_nonopt = optind; -} - -/* Initialize the internal data when the first call is made. */ - -static const char * -_getopt_initialize (optstring) - const char *optstring; -{ - /* Start processing options with ARGV-element 1 (since ARGV-element 0 - is the program name); the sequence of previously skipped - non-option ARGV-elements is empty. */ - - first_nonopt = last_nonopt = optind = 1; - - nextchar = NULL; - - posixly_correct = getenv ("POSIXLY_CORRECT"); - - /* Determine how to handle the ordering of options and nonoptions. */ - - if (optstring[0] == '-') - { - ordering = RETURN_IN_ORDER; - ++optstring; - } - else if (optstring[0] == '+') - { - ordering = REQUIRE_ORDER; - ++optstring; - } - else if (posixly_correct != NULL) - ordering = REQUIRE_ORDER; - else - ordering = PERMUTE; - - return optstring; -} - -/* Scan elements of ARGV (whose length is ARGC) for option characters - given in OPTSTRING. - - If an element of ARGV starts with '-', and is not exactly "-" or "--", - then it is an option element. The characters of this element - (aside from the initial '-') are option characters. If `getopt' - is called repeatedly, it returns successively each of the option characters - from each of the option elements. - - If `getopt' finds another option character, it returns that character, - updating `optind' and `nextchar' so that the next call to `getopt' can - resume the scan with the following option character or ARGV-element. - - If there are no more option characters, `getopt' returns `EOF'. - Then `optind' is the index in ARGV of the first ARGV-element - that is not an option. (The ARGV-elements have been permuted - so that those that are not options now come last.) - - OPTSTRING is a string containing the legitimate option characters. - If an option character is seen that is not listed in OPTSTRING, - return '?' after printing an error message. If you set `opterr' to - zero, the error message is suppressed but we still return '?'. - - If a char in OPTSTRING is followed by a colon, that means it wants an arg, - so the following text in the same ARGV-element, or the text of the following - ARGV-element, is returned in `optarg'. Two colons mean an option that - wants an optional arg; if there is text in the current ARGV-element, - it is returned in `optarg', otherwise `optarg' is set to zero. - - If OPTSTRING starts with `-' or `+', it requests different methods of - handling the non-option ARGV-elements. - See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. - - Long-named options begin with `--' instead of `-'. - Their names may be abbreviated as long as the abbreviation is unique - or is an exact match for some defined option. If they have an - argument, it follows the option name in the same ARGV-element, separated - from the option name by a `=', or else the in next ARGV-element. - When `getopt' finds a long-named option, it returns 0 if that option's - `flag' field is nonzero, the value of the option's `val' field - if the `flag' field is zero. - - The elements of ARGV aren't really const, because we permute them. - But we pretend they're const in the prototype to be compatible - with other systems. - - LONGOPTS is a vector of `struct option' terminated by an - element containing a name which is zero. - - LONGIND returns the index in LONGOPT of the long-named option found. - It is only valid when a long-named option has been found by the most - recent call. - - If LONG_ONLY is nonzero, '-' as well as '--' can introduce - long-named options. */ - -int -_getopt_internal (argc, argv, optstring, longopts, longind, long_only) - int argc; - char *const *argv; - const char *optstring; - const struct option *longopts; - int *longind; - int long_only; -{ - optarg = NULL; - - if (optind == 0) - { - optstring = _getopt_initialize (optstring); - optind = 1; /* Don't scan ARGV[0], the program name. */ - } - - if (nextchar == NULL || *nextchar == '\0') - { - /* Advance to the next ARGV-element. */ - - if (ordering == PERMUTE) - { - /* If we have just processed some options following some non-options, - exchange them so that the options come first. */ - - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (last_nonopt != optind) - first_nonopt = optind; - - /* Skip any additional non-options - and extend the range of non-options previously skipped. */ - - while (optind < argc - && (argv[optind][0] != '-' || argv[optind][1] == '\0')) - optind++; - last_nonopt = optind; - } - - /* The special ARGV-element `--' means premature end of options. - Skip it like a null option, - then exchange with previous non-options as if it were an option, - then skip everything else like a non-option. */ - - if (optind != argc && !strcmp (argv[optind], "--")) - { - optind++; - - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (first_nonopt == last_nonopt) - first_nonopt = optind; - last_nonopt = argc; - - optind = argc; - } - - /* If we have done all the ARGV-elements, stop the scan - and back over any non-options that we skipped and permuted. */ - - if (optind == argc) - { - /* Set the next-arg-index to point at the non-options - that we previously skipped, so the caller will digest them. */ - if (first_nonopt != last_nonopt) - optind = first_nonopt; - return EOF; - } - - /* If we have come to a non-option and did not permute it, - either stop the scan or describe it to the caller and pass it by. */ - - if ((argv[optind][0] != '-' || argv[optind][1] == '\0')) - { - if (ordering == REQUIRE_ORDER) - return EOF; - optarg = argv[optind++]; - return 1; - } - - /* We have found another option-ARGV-element. - Skip the initial punctuation. */ - - nextchar = (argv[optind] + 1 - + (longopts != NULL && argv[optind][1] == '-')); - } - - /* Decode the current option-ARGV-element. */ - - /* Check whether the ARGV-element is a long option. - - If long_only and the ARGV-element has the form "-f", where f is - a valid short option, don't consider it an abbreviated form of - a long option that starts with f. Otherwise there would be no - way to give the -f short option. - - On the other hand, if there's a long option "fubar" and - the ARGV-element is "-fu", do consider that an abbreviation of - the long option, just like "--fu", and not "-f" with arg "u". - - This distinction seems to be the most useful approach. */ - - if (longopts != NULL - && (argv[optind][1] == '-' - || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) - { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound; - int option_index; - - for (nameend = nextchar; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, nextchar, nameend - nextchar)) - { - if (nameend - nextchar == strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else - /* Second or later nonexact match found. */ - ambig = 1; - } - - if (ambig && !exact) - { - if (opterr) - fprintf (stderr, gettext ("%s: option `%s' is ambiguous\n"), - argv[0], argv[optind]); - nextchar += strlen (nextchar); - optind++; - return '?'; - } - - if (pfound != NULL) - { - option_index = indfound; - optind++; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - optarg = nameend + 1; - else - { - if (opterr) - if (argv[optind - 1][1] == '-') - /* --option */ - fprintf (stderr, - gettext ("%s: option `--%s' doesn't allow an argument\n"), - argv[0], pfound->name); - else - /* +option or -option */ - fprintf (stderr, - gettext ("%s: option `%c%s' doesn't allow an argument\n"), - argv[0], argv[optind - 1][0], pfound->name); - - nextchar += strlen (nextchar); - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (optind < argc) - optarg = argv[optind++]; - else - { - if (opterr) - fprintf (stderr, - gettext ("%s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]); - nextchar += strlen (nextchar); - return optstring[0] == ':' ? ':' : '?'; - } - } - nextchar += strlen (nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - - /* Can't find it as a long option. If this is not getopt_long_only, - or the option starts with '--' or is not a valid short - option, then it's an error. - Otherwise interpret it as a short option. */ - if (!long_only || argv[optind][1] == '-' - || my_index (optstring, *nextchar) == NULL) - { - if (opterr) - { - if (argv[optind][1] == '-') - /* --option */ - fprintf (stderr, gettext ("%s: unrecognized option `--%s'\n"), - argv[0], nextchar); - else - /* +option or -option */ - fprintf (stderr, gettext ("%s: unrecognized option `%c%s'\n"), - argv[0], argv[optind][0], nextchar); - } - nextchar = (char *) ""; - optind++; - return '?'; - } - } - - /* Look at and handle the next short option-character. */ - - { - char c = *nextchar++; - char *temp = my_index (optstring, c); - - /* Increment `optind' when we start to process its last character. */ - if (*nextchar == '\0') - ++optind; - - if (temp == NULL || c == ':') - { - if (opterr) - { - if (posixly_correct) - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, gettext ("%s: illegal option -- %c\n"), - argv[0], c); - else - fprintf (stderr, gettext ("%s: invalid option -- %c\n"), - argv[0], c); - } - optopt = c; - return '?'; - } - if (temp[1] == ':') - { - if (temp[2] == ':') - { - /* This is an option that accepts an argument optionally. */ - if (*nextchar != '\0') - { - optarg = nextchar; - optind++; - } - else - optarg = NULL; - nextchar = NULL; - } - else - { - /* This is an option that requires an argument. */ - if (*nextchar != '\0') - { - optarg = nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - optind++; - } - else if (optind == argc) - { - if (opterr) - { - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, - gettext ("%s: option requires an argument -- %c\n"), - argv[0], c); - } - optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - } - else - /* We already incremented `optind' once; - increment it again when taking next ARGV-elt as argument. */ - optarg = argv[optind++]; - nextchar = NULL; - } - } - return c; - } -} - -int -getopt (argc, argv, optstring) - int argc; - char *const *argv; - const char *optstring; -{ - return _getopt_internal (argc, argv, optstring, - (const struct option *) 0, - (int *) 0, - 0); -} - -#endif /* _LIBC or not __GNU_LIBRARY__. */ - -#ifdef TEST - -/* Compile with -DTEST to make an executable for use in testing - the above definition of `getopt'. */ - -int -main (argc, argv) - int argc; - char **argv; -{ - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - - c = getopt (argc, argv, "abc:d:0123456789"); - if (c == EOF) - break; - - switch (c) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value `%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); - } - } - - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } - - exit (0); -} - -#endif /* TEST */ diff --git a/info/getopt.h b/info/getopt.h deleted file mode 100644 --- a/info/getopt.h +++ /dev/null @@ -1,129 +0,0 @@ -/* Declarations for getopt. - Copyright (C) 1989, 90, 91, 92, 93, 94 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#ifndef _GETOPT_H -#define _GETOPT_H 1 - -#ifdef __cplusplus -extern "C" { -#endif - -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - -extern char *optarg; - -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to `getopt'. - - On entry to `getopt', zero means this is the first call; initialize. - - When `getopt' returns EOF, this is the index of the first of the - non-option elements that the caller should itself scan. - - Otherwise, `optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ - -extern int optind; - -/* Callers store zero here to inhibit the error message `getopt' prints - for unrecognized options. */ - -extern int opterr; - -/* Set to an option character which was unrecognized. */ - -extern int optopt; - -/* Describe the long-named options requested by the application. - The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector - of `struct option' terminated by an element containing a name which is - zero. - - The field `has_arg' is: - no_argument (or 0) if the option does not take an argument, - required_argument (or 1) if the option requires an argument, - optional_argument (or 2) if the option takes an optional argument. - - If the field `flag' is not NULL, it points to a variable that is set - to the value given in the field `val' when the option is found, but - left unchanged if the option is not found. - - To have a long-named option do something other than set an `int' to - a compiled-in constant, such as set a value from `optarg', set the - option's `flag' field to zero and its `val' field to a nonzero - value (the equivalent single-letter option character, if there is - one). For long options that have a zero `flag' field, `getopt' - returns the contents of the `val' field. */ - -struct option -{ -#if defined (__STDC__) && __STDC__ - const char *name; -#else - char *name; -#endif - /* has_arg can't be an enum because some compilers complain about - type mismatches in all the code that assumes it is an int. */ - int has_arg; - int *flag; - int val; -}; - -/* Names for the values of the `has_arg' field of `struct option'. */ - -#define no_argument 0 -#define required_argument 1 -#define optional_argument 2 - -#if defined (__STDC__) && __STDC__ -#ifdef __GNU_LIBRARY__ -/* Many other libraries have conflicting prototypes for getopt, with - differences in the consts, in stdlib.h. To avoid compilation - errors, only prototype getopt for the GNU C library. */ -extern int getopt (int argc, char *const *argv, const char *shortopts); -#else /* not __GNU_LIBRARY__ */ -extern int getopt (); -#endif /* __GNU_LIBRARY__ */ -extern int getopt_long (int argc, char *const *argv, const char *shortopts, - const struct option *longopts, int *longind); -extern int getopt_long_only (int argc, char *const *argv, - const char *shortopts, - const struct option *longopts, int *longind); - -/* Internal only. Users should not call this directly. */ -extern int _getopt_internal (int argc, char *const *argv, - const char *shortopts, - const struct option *longopts, int *longind, - int long_only); -#else /* not __STDC__ */ -extern int getopt (); -extern int getopt_long (); -extern int getopt_long_only (); - -extern int _getopt_internal (); -#endif /* __STDC__ */ - -#ifdef __cplusplus -} -#endif - -#endif /* _GETOPT_H */ diff --git a/info/getopt1.c b/info/getopt1.c deleted file mode 100644 --- a/info/getopt1.c +++ /dev/null @@ -1,180 +0,0 @@ -/* getopt_long and getopt_long_only entry points for GNU getopt. - Copyright (C) 1987, 88, 89, 90, 91, 92, 1993, 1994 - 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "getopt.h" - -#if !defined (__STDC__) || !__STDC__ -/* This is a separate conditional since some stdc systems - reject `defined (const)'. */ -#ifndef const -#define const -#endif -#endif - -#include - -/* Comment out all this code if we are using the GNU C Library, and are not - actually compiling the library itself. This code is part of the GNU C - Library, but also included in many other GNU distributions. Compiling - and linking in this code is a waste when using the GNU C library - (especially if it is a shared library). Rather than having every GNU - program understand `configure --with-gnu-libc' and omit the object files, - it is simpler to just do this in the source for each such file. */ - -#if defined (_LIBC) || !defined (__GNU_LIBRARY__) - - -/* This needs to come after some library #include - to get __GNU_LIBRARY__ defined. */ -#ifdef __GNU_LIBRARY__ -#include -#else -char *getenv (); -#endif - -#ifndef NULL -#define NULL 0 -#endif - -int -getopt_long (argc, argv, options, long_options, opt_index) - int argc; - char *const *argv; - const char *options; - const struct option *long_options; - int *opt_index; -{ - return _getopt_internal (argc, argv, options, long_options, opt_index, 0); -} - -/* Like getopt_long, but '-' as well as '--' can indicate a long option. - If an option that starts with '-' (not '--') doesn't match a long option, - but does match a short option, it is parsed as a short option - instead. */ - -int -getopt_long_only (argc, argv, options, long_options, opt_index) - int argc; - char *const *argv; - const char *options; - const struct option *long_options; - int *opt_index; -{ - return _getopt_internal (argc, argv, options, long_options, opt_index, 1); -} - - -#endif /* _LIBC or not __GNU_LIBRARY__. */ - -#ifdef TEST - -#include - -int -main (argc, argv) - int argc; - char **argv; -{ - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - int option_index = 0; - static struct option long_options[] = - { - {"add", 1, 0, 0}, - {"append", 0, 0, 0}, - {"delete", 1, 0, 0}, - {"verbose", 0, 0, 0}, - {"create", 0, 0, 0}, - {"file", 1, 0, 0}, - {0, 0, 0, 0} - }; - - c = getopt_long (argc, argv, "abc:d:0123456789", - long_options, &option_index); - if (c == EOF) - break; - - switch (c) - { - case 0: - printf ("option %s", long_options[option_index].name); - if (optarg) - printf (" with arg %s", optarg); - printf ("\n"); - break; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value `%s'\n", optarg); - break; - - case 'd': - printf ("option d with value `%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); - } - } - - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } - - exit (0); -} - -#endif /* TEST */ diff --git a/info/indices.c b/info/indices.c deleted file mode 100644 --- a/info/indices.c +++ /dev/null @@ -1,731 +0,0 @@ -/* indices.c -- Commands for dealing with an Info file Index. */ - -/* 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 "indices.h" - -/* User-visible variable controls the output of info-index-next. */ -int show_index_match = 1; - -/* In the Info sense, an index is a menu. This variable holds the last - parsed index. */ -static REFERENCE **index_index = (REFERENCE **)NULL; - -/* The offset of the most recently selected index element. */ -static int index_offset = 0; - -/* Variable which holds the last string searched for. */ -static char *index_search = (char *)NULL; - -/* A couple of "globals" describing where the initial index was found. */ -static char *initial_index_filename = (char *)NULL; -static char *initial_index_nodename = (char *)NULL; - -/* A structure associating index names with index offset ranges. */ -typedef struct { - char *name; /* The nodename of this index. */ - int first; /* The index in our list of the first entry. */ - int last; /* The index in our list of the last entry. */ -} INDEX_NAME_ASSOC; - -/* An array associating index nodenames with index offset ranges. */ -static INDEX_NAME_ASSOC **index_nodenames = (INDEX_NAME_ASSOC **)NULL; -static int index_nodenames_index = 0; -static int index_nodenames_slots = 0; - -/* Add the name of NODE, and the range of the associated index elements - (passed in ARRAY) to index_nodenames. */ -static void -add_index_to_index_nodenames (array, node) - REFERENCE **array; - NODE *node; -{ - register int i, last; - INDEX_NAME_ASSOC *assoc; - - for (last = 0; array[last]; last++); - assoc = (INDEX_NAME_ASSOC *)xmalloc (sizeof (INDEX_NAME_ASSOC)); - assoc->name = strdup (node->nodename); - - if (!index_nodenames_index) - { - assoc->first = 0; - assoc->last = last; - } - else - { - for (i = 0; index_nodenames[i + 1]; i++); - assoc->first = 1 + index_nodenames[i]->last; - assoc->last = assoc->first + last; - } - add_pointer_to_array - (assoc, index_nodenames_index, index_nodenames, index_nodenames_slots, - 10, INDEX_NAME_ASSOC *); -} - -/* Find and return the indices of WINDOW's file. The indices are defined - as the first node in the file containing the word "Index" and any - immediately following nodes whose names also contain "Index". All such - indices are concatenated and the result returned. If WINDOW's info file - doesn't have any indices, a NULL pointer is returned. */ -REFERENCE ** -info_indices_of_window (window) - WINDOW *window; -{ - FILE_BUFFER *fb; - - fb = file_buffer_of_window (window); - - return (info_indices_of_file_buffer (fb)); -} - -REFERENCE ** -info_indices_of_file_buffer (file_buffer) - FILE_BUFFER *file_buffer; -{ - register int i; - REFERENCE **result = (REFERENCE **)NULL; - - /* No file buffer, no indices. */ - if (!file_buffer) - return ((REFERENCE **)NULL); - - /* Reset globals describing where the index was found. */ - maybe_free (initial_index_filename); - maybe_free (initial_index_nodename); - initial_index_filename = (char *)NULL; - initial_index_nodename = (char *)NULL; - - if (index_nodenames) - { - for (i = 0; index_nodenames[i]; i++) - { - free (index_nodenames[i]->name); - free (index_nodenames[i]); - } - - index_nodenames_index = 0; - index_nodenames[0] = (INDEX_NAME_ASSOC *)NULL; - } - - /* Grovel the names of the nodes found in this file. */ - if (file_buffer->tags) - { - TAG *tag; - - for (i = 0; tag = file_buffer->tags[i]; i++) - { - if (string_in_line ("Index", tag->nodename) != -1) - { - NODE *node; - REFERENCE **menu; - - /* Found one. Get its menu. */ - node = info_get_node (tag->filename, tag->nodename); - if (!node) - continue; - - /* Remember the filename and nodename of this index. */ - initial_index_filename = strdup (file_buffer->filename); - initial_index_nodename = strdup (tag->nodename); - - menu = info_menu_of_node (node); - - /* If we have a menu, add this index's nodename and range - to our list of index_nodenames. */ - if (menu) - { - add_index_to_index_nodenames (menu, node); - - /* Concatenate the references found so far. */ - result = info_concatenate_references (result, menu); - } - free (node); - } - } - } - - /* If there is a result, clean it up so that every entry has a filename. */ - for (i = 0; result && result[i]; i++) - if (!result[i]->filename) - result[i]->filename = strdup (file_buffer->filename); - - return (result); -} - -DECLARE_INFO_COMMAND (info_index_search, - "Look up a string in the index for this file") -{ - do_info_index_search (window, count, 0); -} - -/* Look up SEARCH_STRING in the index for this file. If SEARCH_STRING - is NULL, prompt user for input. */ -void -do_info_index_search (window, count, search_string) - WINDOW *window; - int count; - char *search_string; -{ - FILE_BUFFER *fb; - char *line; - - /* Reset the index offset, since this is not the info-index-next command. */ - index_offset = 0; - - /* The user is selecting a new search string, so flush the old one. */ - maybe_free (index_search); - index_search = (char *)NULL; - - /* If this window's file is not the same as the one that we last built an - index for, build and remember an index now. */ - fb = file_buffer_of_window (window); - if (!initial_index_filename || - (strcmp (initial_index_filename, fb->filename) != 0)) - { - info_free_references (index_index); - window_message_in_echo_area ("Finding index entries..."); - index_index = info_indices_of_file_buffer (fb); - } - - /* If there is no index, quit now. */ - if (!index_index) - { - info_error ("No indices found."); - return; - } - - /* Okay, there is an index. Look for SEARCH_STRING, or, if it is - empty, prompt for one. */ - if (search_string && *search_string) - line = strdup (search_string); - else - { - line = - info_read_maybe_completing (window, "Index entry: ", index_index); - - window = active_window; - - /* User aborted? */ - if (!line) - { - info_abort_key (active_window, 1, 0); - return; - } - - /* Empty line means move to the Index node. */ - if (!*line) - { - free (line); - - if (initial_index_filename && initial_index_nodename) - { - NODE *node; - - node = - info_get_node (initial_index_filename, initial_index_nodename); - set_remembered_pagetop_and_point (window); - window_set_node_of_window (window, node); - remember_window_and_node (window, node); - window_clear_echo_area (); - return; - } - } - } - - /* The user typed either a completed index label, or a partial string. - Find an exact match, or, failing that, the first index entry containing - the partial string. So, we just call info_next_index_match () with minor - manipulation of INDEX_OFFSET. */ - { - int old_offset; - - /* Start the search right after/before this index. */ - if (count < 0) - { - register int i; - for (i = 0; index_index[i]; i++); - index_offset = i; - } - else - index_offset = -1; - - old_offset = index_offset; - - /* The "last" string searched for is this one. */ - index_search = line; - - /* Find it, or error. */ - info_next_index_match (window, count, 0); - - /* If the search failed, return the index offset to where it belongs. */ - if (index_offset == old_offset) - index_offset = 0; - } -} - -int -index_entry_exists (window, string) - WINDOW *window; - char *string; -{ - register int i; - FILE_BUFFER *fb; - - /* If there is no previous search string, the user hasn't built an index - yet. */ - if (!string) - return 0; - - fb = file_buffer_of_window (window); - if (!initial_index_filename || - (strcmp (initial_index_filename, fb->filename) != 0)) - { - info_free_references (index_index); - index_index = info_indices_of_file_buffer (fb); - } - - /* If there is no index, that is an error. */ - if (!index_index) - return 0; - - for (i = 0; (i > -1) && (index_index[i]); i++) - if (strcmp (string, index_index[i]->label) == 0) - break; - - /* If that failed, look for the next substring match. */ - if ((i < 0) || (!index_index[i])) - { - for (i = 0; (i > -1) && (index_index[i]); i++) - if (string_in_line (string, index_index[i]->label) != -1) - break; - - if ((i > -1) && (index_index[i])) - string_in_line (string, index_index[i]->label); - } - - /* If that failed, return 0. */ - if ((i < 0) || (!index_index[i])) - return 0; - - return 1; -} - -DECLARE_INFO_COMMAND (info_next_index_match, - "Go to the next matching index item from the last `\\[index-search]' command") -{ - register int i; - int partial, dir; - NODE *node; - - /* If there is no previous search string, the user hasn't built an index - yet. */ - if (!index_search) - { - info_error ("No previous index search string."); - return; - } - - /* If there is no index, that is an error. */ - if (!index_index) - { - info_error ("No index entries."); - return; - } - - /* The direction of this search is controlled by the value of the - numeric argument. */ - if (count < 0) - dir = -1; - else - dir = 1; - - /* Search for the next occurence of index_search. First try to find - an exact match. */ - partial = 0; - - for (i = index_offset + dir; (i > -1) && (index_index[i]); i += dir) - if (strcmp (index_search, index_index[i]->label) == 0) - break; - - /* If that failed, look for the next substring match. */ - if ((i < 0) || (!index_index[i])) - { - for (i = index_offset + dir; (i > -1) && (index_index[i]); i += dir) - if (string_in_line (index_search, index_index[i]->label) != -1) - break; - - if ((i > -1) && (index_index[i])) - partial = string_in_line (index_search, index_index[i]->label); - } - - /* If that failed, print an error. */ - if ((i < 0) || (!index_index[i])) - { - info_error ("No %sindex entries containing \"%s\".", - index_offset > 0 ? "more " : "", index_search); - return; - } - - /* Okay, we found the next one. Move the offset to the current entry. */ - index_offset = i; - - /* Report to the user on what we have found. */ - { - register int j; - char *name = "CAN'T SEE THIS"; - char *match; - - for (j = 0; index_nodenames[j]; j++) - { - if ((i >= index_nodenames[j]->first) && - (i <= index_nodenames[j]->last)) - { - name = index_nodenames[j]->name; - break; - } - } - - /* If we had a partial match, indicate to the user which part of the - string matched. */ - match = strdup (index_index[i]->label); - - if (partial && show_index_match) - { - int j, ls, start, upper; - - ls = strlen (index_search); - start = partial - ls; - upper = isupper (match[start]) ? 1 : 0; - - for (j = 0; j < ls; j++) - if (upper) - match[j + start] = info_tolower (match[j + start]); - else - match[j + start] = info_toupper (match[j + start]); - } - - { - char *format; - - format = replace_in_documentation - ("Found \"%s\" in %s. (`\\[next-index-match]' tries to find next.)"); - - window_message_in_echo_area (format, match, name); - } - - free (match); - } - - /* Select the node corresponding to this index entry. */ - node = info_get_node (index_index[i]->filename, index_index[i]->nodename); - - if (!node) - { - info_error (CANT_FILE_NODE, - index_index[i]->filename, index_index[i]->nodename); - return; - } - - set_remembered_pagetop_and_point (window); - window_set_node_of_window (window, node); - remember_window_and_node (window, node); - - - /* Try to find an occurence of LABEL in this node. */ - { - long start, loc; - - start = window->line_starts[1] - window->node->contents; - loc = info_target_search_node (node, index_index[i]->label, start); - - if (loc != -1) - { - window->point = loc; - window_adjust_pagetop (window); - } - } -} - -/* **************************************************************** */ -/* */ -/* Info APROPOS: Search every known index. */ -/* */ -/* **************************************************************** */ - -/* For every menu item in DIR, search the indices of that file for - SEARCH_STRING. */ -REFERENCE ** -apropos_in_all_indices (search_string, inform) - char *search_string; - int inform; -{ - register int i, dir_index; - REFERENCE **all_indices = (REFERENCE **)NULL; - REFERENCE **dir_menu = (REFERENCE **)NULL; - NODE *dir_node; - int printed = 0; - - dir_node = info_get_node ("dir", "Top"); - if (dir_node) - dir_menu = info_menu_of_node (dir_node); - - if (!dir_menu) - return; - - /* For every menu item in DIR, get the associated node's file buffer and - read the indices of that file buffer. Gather all of the indices into - one large one. */ - for (dir_index = 0; dir_menu[dir_index]; dir_index++) - { - REFERENCE **this_index, *this_item; - NODE *this_node; - FILE_BUFFER *this_fb; - - this_item = dir_menu[dir_index]; - - if (!this_item->filename) - { - if (dir_node->parent) - this_item->filename = strdup (dir_node->parent); - else - this_item->filename = strdup (dir_node->filename); - } - - /* Find this node. If we cannot find it, try using the label of the - entry as a file (i.e., "(LABEL)Top"). */ - this_node = info_get_node (this_item->filename, this_item->nodename); - - if (!this_node && this_item->nodename && - (strcmp (this_item->label, this_item->nodename) == 0)) - this_node = info_get_node (this_item->label, "Top"); - - if (!this_node) - continue; - - /* Get the file buffer associated with this node. */ - { - char *files_name; - - files_name = this_node->parent; - if (!files_name) - files_name = this_node->filename; - - this_fb = info_find_file (files_name); - - if (this_fb && inform) - message_in_echo_area ("Scanning indices of \"%s\"...", files_name); - - this_index = info_indices_of_file_buffer (this_fb); - free (this_node); - - if (this_fb && inform) - unmessage_in_echo_area (); - } - - if (this_index) - { - /* Remember the filename which contains this set of references. */ - for (i = 0; this_index && this_index[i]; i++) - if (!this_index[i]->filename) - this_index[i]->filename = strdup (this_fb->filename); - - /* Concatenate with the other indices. */ - all_indices = info_concatenate_references (all_indices, this_index); - } - } - - info_free_references (dir_menu); - - /* Build a list of the references which contain SEARCH_STRING. */ - if (all_indices) - { - REFERENCE *entry, **apropos_list = (REFERENCE **)NULL; - int apropos_list_index = 0; - int apropos_list_slots = 0; - - for (i = 0; (entry = all_indices[i]); i++) - { - if (string_in_line (search_string, entry->label) != -1) - { - add_pointer_to_array - (entry, apropos_list_index, apropos_list, apropos_list_slots, - 100, REFERENCE *); - } - else - { - maybe_free (entry->label); - maybe_free (entry->filename); - maybe_free (entry->nodename); - free (entry); - } - } - - free (all_indices); - all_indices = apropos_list; - } - return (all_indices); -} - -#define APROPOS_NONE \ - "No available info files reference \"%s\" in their indices." - -void -info_apropos (string) - char *string; -{ - REFERENCE **apropos_list; - - apropos_list = apropos_in_all_indices (string, 0); - - if (!apropos_list) - { - info_error (APROPOS_NONE, string); - } - else - { - register int i; - REFERENCE *entry; - - for (i = 0; (entry = apropos_list[i]); i++) - fprintf (stderr, "\"(%s)%s\" -- %s\n", - entry->filename, entry->nodename, entry->label); - } - info_free_references (apropos_list); -} - -static char *apropos_list_nodename = "*Apropos*"; - -DECLARE_INFO_COMMAND (info_index_apropos, - "Grovel all known info file's indices for a string and build a menu") -{ - char *line; - - line = info_read_in_echo_area (window, "Index apropos: "); - - window = active_window; - - /* User aborted? */ - if (!line) - { - info_abort_key (window, 1, 1); - return; - } - - /* User typed something? */ - if (*line) - { - REFERENCE **apropos_list; - NODE *apropos_node; - - apropos_list = apropos_in_all_indices (line, 1); - - if (!apropos_list) - { - info_error (APROPOS_NONE, line); - } - else - { - register int i; - char *line_buffer; - - initialize_message_buffer (); - printf_to_message_buffer - ("\n* Menu: Nodes whoses indices contain \"%s\":\n", line); - line_buffer = (char *)xmalloc (500); - - for (i = 0; apropos_list[i]; i++) - { - int len; - sprintf (line_buffer, "* (%s)%s::", - apropos_list[i]->filename, apropos_list[i]->nodename); - len = pad_to (36, line_buffer); - sprintf (line_buffer + len, "%s", apropos_list[i]->label); - printf_to_message_buffer ("%s\n", line_buffer); - } - free (line_buffer); - } - - apropos_node = message_buffer_to_node (); - add_gcable_pointer (apropos_node->contents); - name_internal_node (apropos_node, apropos_list_nodename); - - /* Even though this is an internal node, we don't want the window - system to treat it specially. So we turn off the internalness - of it here. */ - apropos_node->flags &= ~N_IsInternal; - - /* Find/Create a window to contain this node. */ - { - WINDOW *new; - NODE *node; - - set_remembered_pagetop_and_point (window); - - /* If a window is visible and showing an apropos list already, - re-use it. */ - for (new = windows; new; new = new->next) - { - node = new->node; - - if (internal_info_node_p (node) && - (strcmp (node->nodename, apropos_list_nodename) == 0)) - break; - } - - /* If we couldn't find an existing window, try to use the next window - in the chain. */ - if (!new && window->next) - new = window->next; - - /* If we still don't have a window, make a new one to contain - the list. */ - if (!new) - { - WINDOW *old_active; - - old_active = active_window; - active_window = window; - new = window_make_window ((NODE *)NULL); - active_window = old_active; - } - - /* If we couldn't make a new window, use this one. */ - if (!new) - new = window; - - /* Lines do not wrap in this window. */ - new->flags |= W_NoWrap; - - window_set_node_of_window (new, apropos_node); - remember_window_and_node (new, apropos_node); - active_window = new; - } - info_free_references (apropos_list); - } - free (line); - - if (!info_error_was_printed) - window_clear_echo_area (); -} - diff --git a/info/indices.h b/info/indices.h deleted file mode 100644 --- a/info/indices.h +++ /dev/null @@ -1,41 +0,0 @@ -/* indices.h -- Functions defined in indices.c. */ - -/* 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). */ - -#if !defined (_INDICES_H_) -#define _INDICES_H_ - -/* User-visible variable controls the output of info-index-next. */ -extern int show_index_match; - -extern REFERENCE **info_indices_of_window (), **info_indices_of_file_buffer (); -extern void info_apropos (); - -/* For every menu item in DIR, search the indices of that file for STRING. */ -REFERENCE **apropos_in_all_indices (); - -/* User visible functions declared in indices.c. */ -extern void info_index_search (), info_next_index_match (); -extern void do_info_index_search (); -extern int index_intry_exists (); - -#endif /* !_INDICES_H_ */ diff --git a/info/info-stnd.texi b/info/info-stnd.texi deleted file mode 100644 --- a/info/info-stnd.texi +++ /dev/null @@ -1,1365 +0,0 @@ -\input texinfo @c -*-texinfo-*- -@comment %**start of header -@setfilename info-stnd.info -@settitle GNU Info -@set InfoProgVer 2.11 -@paragraphindent none -@footnotestyle end -@synindex vr cp -@synindex fn cp -@synindex ky cp -@comment %**end of header -@comment $Id: info-stnd.texi,v 1.3 1996-11-13 03:41:41 jwe Exp $ - -@dircategory Texinfo documentation system -@direntry -* info program: (info-stnd). Standalone Info-reading program. -@end direntry - -@ifinfo -This file documents GNU Info, a program for viewing the on-line formatted -versions of Texinfo files. This documentation is different from the -documentation for the Info reader that is part of GNU Emacs. If you do -not know how to use Info, but have a working Info reader, you should -read that documentation first. - -Copyright @copyright{} 1992, 93, 96 Free Software Foundation, Inc. - -Permission is granted to make and distribute verbatim copies of this -manual provided the copyright notice and this permission notice are -preserved on all copies. - -@ignore -Permission is granted to process this file through TeX and print the -results, provided the printed document carries a copying permission -notice identical to this one except for the removal of this paragraph -(this paragraph not being relevant to the printed manual). -@end ignore - -Permission is granted to copy and distribute modified versions of this -manual under the conditions for verbatim copying, provided also that the -sections entitled ``Copying'' and ``GNU General Public License'' are -included exactly as in the original, and provided that the entire -resulting derived work is distributed under the terms of a permission -notice identical to this one. - -Permission is granted to copy and distribute translations of this manual -into another language, under the above conditions for modified versions, -except that this permission notice may be stated in a translation -approved by the Free Software Foundation. -@end ifinfo - -@titlepage -@title GNU Info User's Guide -@subtitle For GNU Info version @value{InfoProgVer} -@author Brian J. Fox (bfox@@ai.mit.edu) -@page -@vskip 0pt plus 1filll -Copyright @copyright{} 1992, 1993 Free Software Foundation - -Permission is granted to make and distribute verbatim copies of this -manual provided the copyright notice and this permission notice are -preserved on all copies. - -Permission is granted to copy and distribute modified versions of this -manual under the conditions for verbatim copying, provided also that the -sections entitled ``Copying'' and ``GNU General Public License'' are -included exactly as in the original, and provided that the entire -resulting derived work is distributed under the terms of a permission -notice identical to this one. - -Permission is granted to copy and distribute translations of this manual -into another language, under the above conditions for modified versions, -except that this permission notice may be stated in a translation -approved by the Free Software Foundation. -@end titlepage - -@ifinfo -@node Top, What is Info, (dir), (dir) -@top The GNU Info Program - -This file documents GNU Info, a program for viewing the on-line -formatted versions of Texinfo files, version @value{InfoProgVer}. This -documentation is different from the documentation for the Info reader -that is part of GNU Emacs. -@end ifinfo - -@menu -* What is Info:: -* Options:: Options you can pass on the command line. -* Cursor Commands:: Commands which move the cursor within a node. -* Scrolling Commands:: Commands for moving the node around - in a window. -* Node Commands:: Commands for selecting a new node. -* Searching Commands:: Commands for searching an Info file. -* Xref Commands:: Commands for selecting cross references. -* Window Commands:: Commands which manipulate multiple windows. -* Printing Nodes:: How to print out the contents of a node. -* Miscellaneous Commands:: A few commands that defy categories. -* Variables:: How to change the default behavior of Info. -* GNU Info Global Index:: Global index containing keystrokes, - command names, variable names, - and general concepts. -@end menu - -@node What is Info, Options, Top, Top -@chapter What is Info? - -@iftex -This file documents GNU Info, a program for viewing the on-line formatted -versions of Texinfo files, version @value{InfoProgVer}. -@end iftex - -@dfn{Info} is a program which is used to view Info files on an ASCII -terminal. @dfn{Info files} are the result of processing Texinfo files -with the program @code{makeinfo} or with one of the Emacs commands, such -as @code{M-x texinfo-format-buffer}. Texinfo itself is a documentation -system that uses a single source file to produce both on-line -information and printed output. You can typeset and print the -files that you read in Info.@refill - -@node Options, Cursor Commands, What is Info, Top -@chapter Command Line Options -@cindex command line options -@cindex arguments, command line - -GNU Info accepts several options to control the initial node being -viewed, and to specify which directories to search for Info files. Here -is a template showing an invocation of GNU Info from the shell: - -@example -info [--@var{option-name} @var{option-value}] @var{menu-item}@dots{} -@end example - -The following @var{option-names} are available when invoking Info from -the shell: - -@table @code -@cindex directory path -@item --directory @var{directory-path} -@itemx -d @var{directory-path} -Add @var{directory-path} to the list of directory paths searched when -Info needs to find a file. You may issue @code{--directory} multiple -times; once for each directory which contains Info files. -Alternatively, you may specify a value for the environment variable -@code{INFOPATH}; if @code{--directory} is not given, the value of -@code{INFOPATH} is used. The value of @code{INFOPATH} is a colon -separated list of directory names. If you do not supply @code{INFOPATH} -or @code{--directory-path}, Info uses a default path. - -@item --file @var{filename} -@itemx -f @var{filename} -@cindex Info file, selecting -Specify a particular Info file to visit. By default, Info visits -the file @code{dir}; if you use this option, Info will start with -@code{(@var{filename})Top} as the first file and node. - -@item --node @var{nodename} -@itemx -n @var{nodename} -@cindex node, selecting -Specify a particular node to visit in the initial file that Info -loads. This is especially useful in conjunction with -@code{--file}@footnote{Of course, you can specify both the file and node -in a @code{--node} command; but don't forget to escape the open and -close parentheses from the shell as in: @code{info --node -"(emacs)Buffers"}}. You may specify @code{--node} multiple times; for -an interactive Info, each @var{nodename} is visited in its own window, -for a non-interactive Info (such as when @code{--output} is given) each -@var{nodename} is processed sequentially. - -@item --output @var{filename} -@itemx -o @var{filename} -@cindex file, outputting to -@cindex outputting to a file -Specify @var{filename} as the name of a file to which to direct output. -Each node that Info visits will be output to @var{filename} instead of -interactively viewed. A value of @code{-} for @var{filename} specifies -the standard output. - -@item --subnodes -@cindex @code{--subnodes}, command line option -This option only has meaning when given in conjunction with -@code{--output}. It means to recursively output the nodes appearing in -the menus of each node being output. Menu items which resolve to -external Info files are not output, and neither are menu items which are -members of an index. Each node is only output once. - -@item --help -@itemx -h -Produces a relatively brief description of the available Info options. - -@item --version -@cindex version information -Prints the version information of Info and exits. - -@item @var{menu-item} -@cindex menu, following -Info treats its remaining arguments as the names of menu items. The -first argument is a menu item in the initial node visited, while -the second argument is a menu item in the first argument's node. -You can easily move to the node of your choice by specifying the menu -names which describe the path to that node. For example, - -@example -info emacs buffers -@end example - -@noindent -first selects the menu item @samp{Emacs} in the node @samp{(dir)Top}, -and then selects the menu item @samp{Buffers} in the node -@samp{(emacs)Top}. -@end table - -@node Cursor Commands, Scrolling Commands, Options, Top -@chapter Moving the Cursor -@cindex cursor, moving - -Many people find that reading screens of text page by page is made -easier when one is able to indicate particular pieces of text with some -kind of pointing device. Since this is the case, GNU Info (both the -Emacs and standalone versions) have several commands which allow you to -move the cursor about the screen. The notation used in this manual to -describe keystrokes is identical to the notation used within the Emacs -manual, and the GNU Readline manual. @xref{Characters, , Character -Conventions, emacs, the GNU Emacs Manual}, if you are unfamiliar with the -notation. - -The following table lists the basic cursor movement commands in Info. -Each entry consists of the key sequence you should type to execute the -cursor movement, the @code{M-x}@footnote{@code{M-x} is also a command; it -invokes @code{execute-extended-command}. @xref{M-x, , Executing an -extended command, emacs, the GNU Emacs Manual}, for more detailed -information.} command name (displayed in parentheses), and a short -description of what the command does. All of the cursor motion commands -can take an @dfn{numeric} argument (@pxref{Miscellaneous Commands, -@code{universal-argument}}), to find out how to supply them. With a -numeric argument, the motion commands are simply executed that -many times; for example, a numeric argument of 4 given to -@code{next-line} causes the cursor to move down 4 lines. With a -negative numeric argument, the motion is reversed; an argument of -4 -given to the @code{next-line} command would cause the cursor to move -@emph{up} 4 lines. - -@table @asis -@item @code{C-n} (@code{next-line}) -@kindex C-n -@findex next-line -Move the cursor down to the next line. - -@item @code{C-p} (@code{prev-line}) -@kindex C-p -@findex prev-line -Move the cursor up to the previous line. - -@item @code{C-a} (@code{beginning-of-line}) -@kindex C-a, in Info windows -@findex beginning-of-line -Move the cursor to the start of the current line. - -@item @code{C-e} (@code{end-of-line}) -@kindex C-e, in Info windows -@findex end-of-line -Move the cursor to the end of the current line. - -@item @code{C-f} (@code{forward-char}) -@kindex C-f, in Info windows -@findex forward-char -Move the cursor forward a character. - -@item @code{C-b} (@code{backward-char}) -@kindex C-b, in Info windows -@findex backward-char -Move the cursor backward a character. - -@item @code{M-f} (@code{forward-word}) -@kindex M-f, in Info windows -@findex forward-word -Move the cursor forward a word. - -@item @code{M-b} (@code{backward-word}) -@kindex M-b, in Info windows -@findex backward-word -Move the cursor backward a word. - -@item @code{M-<} (@code{beginning-of-node}) -@itemx @code{b} -@kindex b, in Info windows -@kindex M-< -@findex beginning-of-node -Move the cursor to the start of the current node. - -@item @code{M->} (@code{end-of-node}) -@kindex M-> -@findex end-of-node -Move the cursor to the end of the current node. - -@item @code{M-r} (@code{move-to-window-line}) -@kindex M-r -@findex move-to-window-line -Move the cursor to a specific line of the window. Without a numeric -argument, @code{M-r} moves the cursor to the start of the line in the -center of the window. With a numeric argument of @var{n}, @code{M-r} -moves the cursor to the start of the @var{n}th line in the window. -@end table - -@node Scrolling Commands, Node Commands, Cursor Commands, Top -@chapter Moving Text Within a Window -@cindex scrolling - -Sometimes you are looking at a screenful of text, and only part of the -current paragraph you are reading is visible on the screen. The -commands detailed in this section are used to shift which part of the -current node is visible on the screen. - -@table @asis -@item @code{SPC} (@code{scroll-forward}) -@itemx @code{C-v} -@kindex SPC, in Info windows -@kindex C-v -@findex scroll-forward -Shift the text in this window up. That is, show more of the node which -is currently below the bottom of the window. With a numeric argument, -show that many more lines at the bottom of the window; a numeric -argument of 4 would shift all of the text in the window up 4 lines -(discarding the top 4 lines), and show you four new lines at the bottom -of the window. Without a numeric argument, @key{SPC} takes the bottom -two lines of the window and places them at the top of the window, -redisplaying almost a completely new screenful of lines. - -@item @code{DEL} (@code{scroll-backward}) -@itemx @code{M-v} -@kindex DEL, in Info windows -@kindex M-v -@findex scroll-backward -Shift the text in this window down. The inverse of -@code{scroll-forward}. -@end table - -@cindex scrolling through node structure -The @code{scroll-forward} and @code{scroll-backward} commands can also -move forward and backward through the node structure of the file. If -you press @key{SPC} while viewing the end of a node, or @key{DEL} while -viewing the beginning of a node, what happens is controlled by the -variable @code{scroll-behavior}. @xref{Variables, -@code{scroll-behavior}}, for more information. - -@table @asis -@item @code{C-l} (@code{redraw-display}) -@kindex C-l -@findex redraw-display -Redraw the display from scratch, or shift the line containing the cursor -to a specified location. With no numeric argument, @samp{C-l} clears -the screen, and then redraws its entire contents. Given a numeric -argument of @var{n}, the line containing the cursor is shifted so that -it is on the @var{n}th line of the window. - -@item @code{C-x w} (@code{toggle-wrap}) -@kindex C-w -@findex toggle-wrap -Toggles the state of line wrapping in the current window. Normally, -lines which are longer than the screen width @dfn{wrap}, i.e., they are -continued on the next line. Lines which wrap have a @samp{\} appearing -in the rightmost column of the screen. You can cause such lines to be -terminated at the rightmost column by changing the state of line -wrapping in the window with @code{C-x w}. When a line which needs more -space than one screen width to display is displayed, a @samp{$} appears -in the rightmost column of the screen, and the remainder of the line is -invisible. -@end table - -@node Node Commands, Searching Commands, Scrolling Commands, Top -@chapter Selecting a New Node -@cindex nodes, selection of - -This section details the numerous Info commands which select a new node -to view in the current window. - -The most basic node commands are @samp{n}, @samp{p}, @samp{u}, and -@samp{l}. - -When you are viewing a node, the top line of the node contains some Info -@dfn{pointers} which describe where the next, previous, and up nodes -are. Info uses this line to move about the node structure of the file -when you use the following commands: - -@table @asis -@item @code{n} (@code{next-node}) -@kindex n -@findex next-node -Select the `Next' node. - -@item @code{p} (@code{prev-node}) -@kindex p -@findex prev-node -Select the `Prev' node. - -@item @code{u} (@code{up-node}) -@kindex u -@findex up-node -Select the `Up' node. -@end table - -You can easily select a node that you have already viewed in this window -by using the @samp{l} command -- this name stands for "last", and -actually moves through the list of already visited nodes for this -window. @samp{l} with a negative numeric argument moves forward through -the history of nodes for this window, so you can quickly step between -two adjacent (in viewing history) nodes. - -@table @asis -@item @code{l} (@code{history-node}) -@kindex l -@findex history-node -Select the most recently selected node in this window. -@end table - -Two additional commands make it easy to select the most commonly -selected nodes; they are @samp{t} and @samp{d}. - -@table @asis -@item @code{t} (@code{top-node}) -@kindex t -@findex top-node -Select the node @samp{Top} in the current Info file. - -@item @code{d} (@code{dir-node}) -@kindex d -@findex dir-node -Select the directory node (i.e., the node @samp{(dir)}). -@end table - -Here are some other commands which immediately result in the selection -of a different node in the current window: - -@table @asis -@item @code{<} (@code{first-node}) -@kindex < -@findex first-node -Selects the first node which appears in this file. This node is most -often @samp{Top}, but it does not have to be. - -@item @code{>} (@code{last-node}) -@kindex > -@findex last-node -Select the last node which appears in this file. - -@item @code{]} (@code{global-next-node}) -@kindex ] -@findex global-next-node -Move forward or down through node structure. If the node that you are -currently viewing has a @samp{Next} pointer, that node is selected. -Otherwise, if this node has a menu, the first menu item is selected. If -there is no @samp{Next} and no menu, the same process is tried with the -@samp{Up} node of this node. - -@item @code{[} (@code{global-prev-node}) -@kindex [ -@findex global-prev-node -Move backward or up through node structure. If the node that you are -currently viewing has a @samp{Prev} pointer, that node is selected. -Otherwise, if the node has an @samp{Up} pointer, that node is selected, -and if it has a menu, the last item in the menu is selected. -@end table - -You can get the same behavior as @code{global-next-node} and -@code{global-prev-node} while simply scrolling through the file with -@key{SPC} and @key{DEL}; @xref{Variables, @code{scroll-behavior}}, for -more information. - -@table @asis -@item @code{g} (@code{goto-node}) -@kindex g -@findex goto-node -Read the name of a node and select it. No completion is done while -reading the node name, since the desired node may reside in a separate -file. The node must be typed exactly as it appears in the Info file. A -file name may be included as with any node specification, for example - -@example -@code{g(emacs)Buffers} -@end example - -finds the node @samp{Buffers} in the Info file @file{emacs}. - -@item @code{C-x k} (@code{kill-node}) -@kindex C-x k -@findex kill-node -Kill a node. The node name is prompted for in the echo area, with a -default of the current node. @dfn{Killing} a node means that Info tries -hard to forget about it, removing it from the list of history nodes kept -for the window where that node is found. Another node is selected in -the window which contained the killed node. - -@item @code{C-x C-f} (@code{view-file}) -@kindex C-x C-f -@findex view-file -Read the name of a file and selects the entire file. The command -@example -@code{C-x C-f @var{filename}} -@end example -is equivalent to typing -@example -@code{g(@var{filename})*} -@end example - -@item @code{C-x C-b} (@code{list-visited-nodes}) -@kindex C-x C-b -@findex list-visited-nodes -Make a window containing a menu of all of the currently visited nodes. -This window becomes the selected window, and you may use the standard -Info commands within it. - -@item @code{C-x b} (@code{select-visited-node}) -@kindex C-x b -@findex select-visited-node -Select a node which has been previously visited in a visible window. -This is similar to @samp{C-x C-b} followed by @samp{m}, but no window is -created. -@end table - -@node Searching Commands, Xref Commands, Node Commands, Top -@chapter Searching an Info File -@cindex searching - -GNU Info allows you to search for a sequence of characters throughout an -entire Info file, search through the indices of an Info file, or find -areas within an Info file which discuss a particular topic. - -@table @asis -@item @code{s} (@code{search}) -@kindex s -@findex search -Read a string in the echo area and search for it. - -@item @code{C-s} (@code{isearch-forward}) -@kindex C-s -@findex isearch-forward -Interactively search forward through the Info file for a string as you -type it. - -@item @code{C-r} (@code{isearch-backward}) -@kindex C-r -@findex isearch-backward -Interactively search backward through the Info file for a string as -you type it. - -@item @code{i} (@code{index-search}) -@kindex i -@findex index-search -Look up a string in the indices for this Info file, and select a node -where the found index entry points to. - -@item @code{,} (@code{next-index-match}) -@kindex , -@findex next-index-match -Move to the node containing the next matching index item from the last -@samp{i} command. -@end table - -The most basic searching command is @samp{s} (@code{search}). The -@samp{s} command prompts you for a string in the echo area, and then -searches the remainder of the Info file for an occurrence of that string. -If the string is found, the node containing it is selected, and the -cursor is left positioned at the start of the found string. Subsequent -@samp{s} commands show you the default search string within @samp{[} and -@samp{]}; pressing @key{RET} instead of typing a new string will use the -default search string. - -@dfn{Incremental searching} is similar to basic searching, but the -string is looked up while you are typing it, instead of waiting until -the entire search string has been specified. - -@node Xref Commands, Window Commands, Searching Commands, Top -@chapter Selecting Cross References - -We have already discussed the @samp{Next}, @samp{Prev}, and @samp{Up} -pointers which appear at the top of a node. In addition to these -pointers, a node may contain other pointers which refer you to a -different node, perhaps in another Info file. Such pointers are called -@dfn{cross references}, or @dfn{xrefs} for short. - -@menu -* Parts of an Xref:: What a cross reference is made of. -* Selecting Xrefs:: Commands for selecting menu or note items. -@end menu - -@node Parts of an Xref, Selecting Xrefs, , Xref Commands -@section Parts of an Xref - -Cross references have two major parts: the first part is called the -@dfn{label}; it is the name that you can use to refer to the cross -reference, and the second is the @dfn{target}; it is the full name of -the node that the cross reference points to. - -The target is separated from the label by a colon @samp{:}; first the -label appears, and then the target. For example, in the sample menu -cross reference below, the single colon separates the label from the -target. - -@example -* Foo Label: Foo Target. More information about Foo. -@end example - -Note the @samp{.} which ends the name of the target. The @samp{.} is -not part of the target; it serves only to let Info know where the target -name ends. - -A shorthand way of specifying references allows two adjacent colons to -stand for a target name which is the same as the label name: - -@example -* Foo Commands:: Commands pertaining to Foo. -@end example - -In the above example, the name of the target is the same as the name of -the label, in this case @code{Foo Commands}. - -You will normally see two types of cross reference while viewing nodes: -@dfn{menu} references, and @dfn{note} references. Menu references -appear within a node's menu; they begin with a @samp{*} at the beginning -of a line, and continue with a label, a target, and a comment which -describes what the contents of the node pointed to contains. - -Note references appear within the body of the node text; they begin with -@code{*Note}, and continue with a label and a target. - -Like @samp{Next}, @samp{Prev}, and @samp{Up} pointers, cross references -can point to any valid node. They are used to refer you to a place -where more detailed information can be found on a particular subject. -Here is a cross reference which points to a node within the Texinfo -documentation: @xref{xref, , Writing an Xref, texinfo, the Texinfo -Manual}, for more information on creating your own texinfo cross -references. - -@node Selecting Xrefs, , Parts of an Xref, Xref Commands -@section Selecting Xrefs - -The following table lists the Info commands which operate on menu items. - -@table @asis -@item @code{1} (@code{menu-digit}) -@itemx @code{2} @dots{} @code{9} -@cindex 1 @dots{} 9, in Info windows -@kindex 1 @dots{} 9, in Info windows -@findex menu-digit -Within an Info window, pressing a single digit, (such as @samp{1}), -selects that menu item, and places its node in the current window. -For convenience, there is one exception; pressing @samp{0} selects the -@emph{last} item in the node's menu. - -@item @code{0} (@code{last-menu-item}) -@kindex 0, in Info windows -@findex last-menu-item -Select the last item in the current node's menu. - -@item @code{m} (@code{menu-item}) -@kindex m -@findex menu-item -Reads the name of a menu item in the echo area and selects its node. -Completion is available while reading the menu label. - -@item @code{M-x find-menu} -@findex find-menu -Move the cursor to the start of this node's menu. -@end table - -This table lists the Info commands which operate on note cross references. - -@table @asis -@item @code{f} (@code{xref-item}) -@itemx @code{r} -@kindex f -@kindex r -@findex xref-item -Reads the name of a note cross reference in the echo area and selects -its node. Completion is available while reading the cross reference -label. -@end table - -Finally, the next few commands operate on menu or note references alike: - -@table @asis -@item @code{TAB} (@code{move-to-next-xref}) -@kindex TAB, in Info windows -@findex move-to-next-xref -Move the cursor to the start of the next nearest menu item or note -reference in this node. You can then use @key{RET} -(@code{select-reference-this-line}) to select the menu or note reference. - -@item @code{M-TAB} (@code{move-to-prev-xref}) -@kindex M-TAB, in Info windows -@findex move-to-prev-xref -Move the cursor the start of the nearest previous menu item or note -reference in this node. - -@item @code{RET} (@code{select-reference-this-line}) -@kindex RET, in Info windows -@findex select-reference-this-line -Select the menu item or note reference appearing on this line. -@end table - -@node Window Commands, Printing Nodes, Xref Commands, Top -@chapter Manipulating Multiple Windows -@cindex windows, manipulating - -A @dfn{window} is a place to show the text of a node. Windows have a -view area where the text of the node is displayed, and an associated -@dfn{mode line}, which briefly describes the node being viewed. - -GNU Info supports multiple windows appearing in a single screen; each -window is separated from the next by its modeline. At any time, there -is only one @dfn{active} window, that is, the window in which the cursor -appears. There are commands available for creating windows, changing -the size of windows, selecting which window is active, and for deleting -windows. - -@menu -* The Mode Line:: What appears in the mode line? -* Basic Windows:: Manipulating windows in Info. -* The Echo Area:: Used for displaying errors and reading input. -@end menu - -@node The Mode Line, Basic Windows, , Window Commands -@section The Mode Line - -A @dfn{mode line} is a line of inverse video which appears at the bottom -of an Info window. It describes the contents of the window just above -it; this information includes the name of the file and node appearing in -that window, the number of screen lines it takes to display the node, -and the percentage of text that is above the top of the window. It can -also tell you if the indirect tags table for this Info file needs to be -updated, and whether or not the Info file was compressed when stored on -disk. - -Here is a sample mode line for a window containing an uncompressed file -named @file{dir}, showing the node @samp{Top}. - -@example -@group ------Info: (dir)Top, 40 lines --Top--------------------------------------- - ^^ ^ ^^^ ^^ - (file)Node #lines where -@end group -@end example - -When a node comes from a file which is compressed on disk, this is -indicated in the mode line with two small @samp{z}'s. In addition, if -the Info file containing the node has been split into subfiles, the name -of the subfile containing the node appears in the modeline as well: - -@example ---zz-Info: (emacs)Top, 291 lines --Top-- Subfile: emacs-1.Z--------------- -@end example - -When Info makes a node internally, such that there is no corresponding -info file on disk, the name of the node is surrounded by asterisks -(@samp{*}). The name itself tells you what the contents of the window -are; the sample mode line below shows an internally constructed node -showing possible completions: - -@example ------Info: *Completions*, 7 lines --All----------------------------------- -@end example - -@node Basic Windows, The Echo Area, The Mode Line, Window Commands -@section Window Commands - -It can be convenient to view more than one node at a time. To allow -this, Info can display more than one @dfn{window}. Each window has its -own mode line (@pxref{The Mode Line}) and history of nodes viewed in that -window (@pxref{Node Commands, , @code{history-node}}). - -@table @asis -@item @code{C-x o} (@code{next-window}) -@cindex windows, selecting -@kindex C-x o -@findex next-window -Select the next window on the screen. Note that the echo area can only be -selected if it is already in use, and you have left it temporarily. -Normally, @samp{C-x o} simply moves the cursor into the next window on -the screen, or if you are already within the last window, into the first -window on the screen. Given a numeric argument, @samp{C-x o} moves over -that many windows. A negative argument causes @samp{C-x o} to select -the previous window on the screen. - -@item @code{M-x prev-window} -@findex prev-window -Select the previous window on the screen. This is identical to -@samp{C-x o} with a negative argument. - -@item @code{C-x 2} (@code{split-window}) -@cindex windows, creating -@kindex C-x 2 -@findex split-window -Split the current window into two windows, both showing the same node. -Each window is one half the size of the original window, and the cursor -remains in the original window. The variable @code{automatic-tiling} -can cause all of the windows on the screen to be resized for you -automatically, please @pxref{Variables, , automatic-tiling} for more -information. - -@item @code{C-x 0} (@code{delete-window}) -@cindex windows, deleting -@kindex C-x 0 -@findex delete-window -Delete the current window from the screen. If you have made too many -windows and your screen appears cluttered, this is the way to get rid of -some of them. - -@item @code{C-x 1} (@code{keep-one-window}) -@kindex C-x 1 -@findex keep-one-window -Delete all of the windows excepting the current one. - -@item @code{ESC C-v} (@code{scroll-other-window}) -@kindex ESC C-v, in Info windows -@findex scroll-other-window -Scroll the other window, in the same fashion that @samp{C-v} might -scroll the current window. Given a negative argument, scroll the -"other" window backward. - -@item @code{C-x ^} (@code{grow-window}) -@kindex C-x ^ -@findex grow-window -Grow (or shrink) the current window. Given a numeric argument, grow -the current window that many lines; with a negative numeric argument, -shrink the window instead. - -@item @code{C-x t} (@code{tile-windows}) -@cindex tiling -@kindex C-x t -@findex tile-windows -Divide the available screen space among all of the visible windows. -Each window is given an equal portion of the screen in which to display -its contents. The variable @code{automatic-tiling} can cause -@code{tile-windows} to be called when a window is created or deleted. -@xref{Variables, , @code{automatic-tiling}}. -@end table - -@node The Echo Area, , Basic Windows, Window Commands -@section The Echo Area -@cindex echo area - -The @dfn{echo area} is a one line window which appears at the bottom of -the screen. It is used to display informative or error messages, and to -read lines of input from you when that is necessary. Almost all of the -commands available in the echo area are identical to their Emacs -counterparts, so please refer to that documentation for greater depth of -discussion on the concepts of editing a line of text. The following -table briefly lists the commands that are available while input is being -read in the echo area: - -@table @asis -@item @code{C-f} (@code{echo-area-forward}) -@kindex C-f, in the echo area -@findex echo-area-forward -Move forward a character. - -@item @code{C-b} (@code{echo-area-backward}) -@kindex C-b, in the echo area -@findex echo-area-backward -Move backward a character. - -@item @code{C-a} (@code{echo-area-beg-of-line}) -@kindex C-a, in the echo area -@findex echo-area-beg-of-line -Move to the start of the input line. - -@item @code{C-e} (@code{echo-area-end-of-line}) -@kindex C-e, in the echo area -@findex echo-area-end-of-line -Move to the end of the input line. - -@item @code{M-f} (@code{echo-area-forward-word}) -@kindex M-f, in the echo area -@findex echo-area-forward-word -Move forward a word. - -@item @code{M-b} (@code{echo-area-backward-word}) -@kindex M-b, in the echo area -@findex echo-area-backward-word -Move backward a word. - -@item @code{C-d} (@code{echo-area-delete}) -@kindex C-d, in the echo area -@findex echo-area-delete -Delete the character under the cursor. - -@item @code{DEL} (@code{echo-area-rubout}) -@kindex DEL, in the echo area -@findex echo-area-rubout -Delete the character behind the cursor. - -@item @code{C-g} (@code{echo-area-abort}) -@kindex C-g, in the echo area -@findex echo-area-abort -Cancel or quit the current operation. If completion is being read, -@samp{C-g} discards the text of the input line which does not match any -completion. If the input line is empty, @samp{C-g} aborts the calling -function. - -@item @code{RET} (@code{echo-area-newline}) -@kindex RET, in the echo area -@findex echo-area-newline -Accept (or forces completion of) the current input line. - -@item @code{C-q} (@code{echo-area-quoted-insert}) -@kindex C-q, in the echo area -@findex echo-area-quoted-insert -Insert the next character verbatim. This is how you can insert control -characters into a search string, for example. - -@item @var{printing character} (@code{echo-area-insert}) -@kindex printing characters, in the echo area -@findex echo-area-insert -Insert the character. - -@item @code{M-TAB} (@code{echo-area-tab-insert}) -@kindex M-TAB, in the echo area -@findex echo-area-tab-insert -Insert a TAB character. - -@item @code{C-t} (@code{echo-area-transpose-chars}) -@kindex C-t, in the echo area -@findex echo-area-transpose-chars -Transpose the characters at the cursor. -@end table - -The next group of commands deal with @dfn{killing}, and @dfn{yanking} -text. For an in depth discussion of killing and yanking, -@pxref{Killing, , Killing and Deleting, emacs, the GNU Emacs Manual} - -@table @asis -@item @code{M-d} (@code{echo-area-kill-word}) -@kindex M-d, in the echo area -@findex echo-area-kill-word -Kill the word following the cursor. - -@item @code{M-DEL} (@code{echo-area-backward-kill-word}) -@kindex M-DEL, in the echo area -@findex echo-area-backward-kill-word -Kill the word preceding the cursor. - -@item @code{C-k} (@code{echo-area-kill-line}) -@kindex C-k, in the echo area -@findex echo-area-kill-line -Kill the text from the cursor to the end of the line. - -@item @code{C-x DEL} (@code{echo-area-backward-kill-line}) -@kindex C-x DEL, in the echo area -@findex echo-area-backward-kill-line -Kill the text from the cursor to the beginning of the line. - -@item @code{C-y} (@code{echo-area-yank}) -@kindex C-y, in the echo area -@findex echo-area-yank -Yank back the contents of the last kill. - -@item @code{M-y} (@code{echo-area-yank-pop}) -@kindex M-y, in the echo area -@findex echo-area-yank-pop -Yank back a previous kill, removing the last yanked text first. -@end table - -Sometimes when reading input in the echo area, the command that needed -input will only accept one of a list of several choices. The choices -represent the @dfn{possible completions}, and you must respond with one -of them. Since there are a limited number of responses you can make, -Info allows you to abbreviate what you type, only typing as much of the -response as is necessary to uniquely identify it. In addition, you can -request Info to fill in as much of the response as is possible; this -is called @dfn{completion}. - -The following commands are available when completing in the echo area: - -@table @asis -@item @code{TAB} (@code{echo-area-complete}) -@itemx @code{SPC} -@kindex TAB, in the echo area -@kindex SPC, in the echo area -@findex echo-area-complete -Insert as much of a completion as is possible. - -@item @code{?} (@code{echo-area-possible-completions}) -@kindex ?, in the echo area -@findex echo-area-possible-completions -Display a window containing a list of the possible completions of what -you have typed so far. For example, if the available choices are: - -@example -@group -bar -foliate -food -forget -@end group -@end example - -@noindent -and you have typed an @samp{f}, followed by @samp{?}, the possible -completions would contain: - -@example -@group -foliate -food -forget -@end group -@end example - -@noindent -i.e., all of the choices which begin with @samp{f}. Pressing @key{SPC} -or @key{TAB} would result in @samp{fo} appearing in the echo area, since -all of the choices which begin with @samp{f} continue with @samp{o}. -Now, typing @samp{l} followed by @samp{TAB} results in @samp{foliate} -appearing in the echo area, since that is the only choice which begins -with @samp{fol}. - -@item @code{ESC C-v} (@code{echo-area-scroll-completions-window}) -@kindex ESC C-v, in the echo area -@findex echo-area-scroll-completions-window -Scroll the completions window, if that is visible, or the "other" -window if not. -@end table - -@node Printing Nodes, Miscellaneous Commands, Window Commands, Top -@chapter Printing Out Nodes -@cindex printing - -You may wish to print out the contents of a node as a quick reference -document for later use. Info provides you with a command for doing -this. In general, we recommend that you use @TeX{} to format the -document and print sections of it, by running @code{tex} on the Texinfo -source file. - -@table @asis -@item @code{M-x print-node} -@findex print-node -@cindex INFO_PRINT_COMMAND, environment variable -Pipe the contents of the current node through the command in the -environment variable @code{INFO_PRINT_COMMAND}. If the variable does not -exist, the node is simply piped to @code{lpr}. -@end table - -@node Miscellaneous Commands, Variables, Printing Nodes, Top -@chapter Miscellaneous Commands - -GNU Info contains several commands which self-document GNU Info: - -@table @asis -@item @code{M-x describe-command} -@cindex functions, describing -@cindex commands, describing -@findex describe-command -Read the name of an Info command in the echo area and then display a -brief description of what that command does. - -@item @code{M-x describe-key} -@cindex keys, describing -@findex describe-key -Read a key sequence in the echo area, and then display the name and -documentation of the Info command that the key sequence invokes. - -@item @code{M-x describe-variable} -Read the name of a variable in the echo area and then display a brief -description of what the variable affects. - -@item @code{M-x where-is} -@findex where-is -Read the name of an Info command in the echo area, and then display -a key sequence which can be typed in order to invoke that command. - -@item @code{C-h} (@code{get-help-window}) -@itemx @code{?} -@kindex C-h -@kindex ?, in Info windows -@findex get-help-window -Create (or Move into) the window displaying @code{*Help*}, and place -a node containing a quick reference card into it. This window displays -the most concise information about GNU Info available. - -@item @code{h} (@code{get-info-help-node}) -@kindex h -@findex get-info-help-node -Try hard to visit the node @code{(info)Help}. The Info file -@file{info.texi} distributed with GNU Info contains this node. Of -course, the file must first be processed with @code{makeinfo}, and then -placed into the location of your Info directory. -@end table - -Here are the commands for creating a numeric argument: - -@table @asis -@item @code{C-u} (@code{universal-argument}) -@cindex numeric arguments -@kindex C-u -@findex universal-argument -Start (or multiply by 4) the current numeric argument. @samp{C-u} is -a good way to give a small numeric argument to cursor movement or -scrolling commands; @samp{C-u C-v} scrolls the screen 4 lines, while -@samp{C-u C-u C-n} moves the cursor down 16 lines. - -@item @code{M-1} (@code{add-digit-to-numeric-arg}) -@itemx @code{M-2} @dots{} @code{M-9} -@kindex M-1 @dots{} M-9 -@findex add-digit-to-numeric-arg -Add the digit value of the invoking key to the current numeric -argument. Once Info is reading a numeric argument, you may just type -the digits of the argument, without the Meta prefix. For example, you -might give @samp{C-l} a numeric argument of 32 by typing: - -@example -@kbd{C-u 3 2 C-l} -@end example - -@noindent -or - -@example -@kbd{M-3 2 C-l} -@end example -@end table - -@samp{C-g} is used to abort the reading of a multi-character key -sequence, to cancel lengthy operations (such as multi-file searches) and -to cancel reading input in the echo area. - -@table @asis -@item @code{C-g} (@code{abort-key}) -@cindex cancelling typeahead -@cindex cancelling the current operation -@kindex C-g, in Info windows -@findex abort-key -Cancel current operation. -@end table - -The @samp{q} command of Info simply quits running Info. - -@table @asis -@item @code{q} (@code{quit}) -@cindex quitting -@kindex q -@findex quit -Exit GNU Info. -@end table - -If the operating system tells GNU Info that the screen is 60 lines tall, -and it is actually only 40 lines tall, here is a way to tell Info that -the operating system is correct. - -@table @asis -@item @code{M-x set-screen-height} -@findex set-screen-height -@cindex screen, changing the height of -Read a height value in the echo area and set the height of the -displayed screen to that value. -@end table - -Finally, Info provides a convenient way to display footnotes which might -be associated with the current node that you are viewing: - -@table @asis -@item @code{ESC C-f} (@code{show-footnotes}) -@kindex ESC C-f -@findex show-footnotes -@cindex footnotes, displaying -Show the footnotes (if any) associated with the current node in another -window. You can have Info automatically display the footnotes -associated with a node when the node is selected by setting the variable -@code{automatic-footnotes}. @xref{Variables, , @code{automatic-footnotes}}. -@end table - -@node Variables, GNU Info Global Index, Miscellaneous Commands, Top -@chapter Manipulating Variables - -GNU Info contains several @dfn{variables} whose values are looked at by -various Info commands. You can change the values of these variables, -and thus change the behavior of Info to more closely match your -environment and Info file reading manner. - -@table @asis -@item @code{M-x set-variable} -@cindex variables, setting -@findex set-variable -Read the name of a variable, and the value for it, in the echo area and -then set the variable to that value. Completion is available when -reading the variable name; often, completion is available when reading -the value to give to the variable, but that depends on the variable -itself. If a variable does @emph{not} supply multiple choices to -complete over, it expects a numeric value. - -@item @code{M-x describe-variable} -@cindex variables, describing -@findex describe-variable -Read the name of a variable in the echo area and then display a brief -description of what the variable affects. -@end table - -Here is a list of the variables that you can set in Info. - -@table @code -@item automatic-footnotes -@vindex automatic-footnotes -When set to @code{On}, footnotes appear and disappear automatically. -This variable is @code{On} by default. When a node is selected, a -window containing the footnotes which appear in that node is created, -and the footnotes are displayed within the new window. The window that -Info creates to contain the footnotes is called @samp{*Footnotes*}. If -a node is selected which contains no footnotes, and a @samp{*Footnotes*} -window is on the screen, the @samp{*Footnotes*} window is deleted. -Footnote windows created in this fashion are not automatically tiled so -that they can use as little of the display as is possible. - -@item automatic-tiling -@vindex automatic-tiling -When set to @code{On}, creating or deleting a window resizes other -windows. This variable is @code{Off} by default. Normally, typing -@samp{C-x 2} divides the current window into two equal parts. When -@code{automatic-tiling} is set to @code{On}, all of the windows are -resized automatically, keeping an equal number of lines visible in each -window. There are exceptions to the automatic tiling; specifically, the -windows @samp{*Completions*} and @samp{*Footnotes*} are @emph{not} -resized through automatic tiling; they remain their original size. - -@item visible-bell -@vindex visible-bell -When set to @code{On}, GNU Info attempts to flash the screen instead of -ringing the bell. This variable is @code{Off} by default. Of course, -Info can only flash the screen if the terminal allows it; in the case -that the terminal does not allow it, the setting of this variable has no -effect. However, you can make Info perform quietly by setting the -@code{errors-ring-bell} variable to @code{Off}. - -@item errors-ring-bell -@vindex errors-ring-bell -When set to @code{On}, errors cause the bell to ring. The default -setting of this variable is @code{On}. - -@item gc-compressed-files -@vindex gc-compressed-files -When set to @code{On}, Info garbage collects files which had to be -uncompressed. The default value of this variable is @code{Off}. -Whenever a node is visited in Info, the Info file containing that node -is read into core, and Info reads information about the tags and nodes -contained in that file. Once the tags information is read by Info, it -is never forgotten. However, the actual text of the nodes does not need -to remain in core unless a particular Info window needs it. For -non-compressed files, the text of the nodes does not remain in core when -it is no longer in use. But de-compressing a file can be a time -consuming operation, and so Info tries hard not to do it twice. -@code{gc-compressed-files} tells Info it is okay to garbage collect the -text of the nodes of a file which was compressed on disk. - -@item show-index-match -@vindex show-index-match -When set to @code{On}, the portion of the matched search string is -highlighted in the message which explains where the matched search -string was found. The default value of this variable is @code{On}. -When Info displays the location where an index match was found, -(@pxref{Searching Commands, , @code{next-index-match}}), the portion of the -string that you had typed is highlighted by displaying it in the inverse -case from its surrounding characters. - -@item scroll-behavior -@vindex scroll-behavior -Control what happens when forward scrolling is requested at the end of -a node, or when backward scrolling is requested at the beginning of a -node. The default value for this variable is @code{Continuous}. There -are three possible values for this variable: - -@table @code -@item Continuous -Try to get the first item in this node's menu, or failing that, the -@samp{Next} node, or failing that, the @samp{Next} of the @samp{Up}. -This behavior is identical to using the @samp{]} -(@code{global-next-node}) and @samp{[} (@code{global-prev-node}) -commands. - -@item Next Only -Only try to get the @samp{Next} node. - -@item Page Only -Simply give up, changing nothing. If @code{scroll-behavior} is -@code{Page Only}, no scrolling command can change the node that is being -viewed. -@end table - -@item scroll-step -@vindex scroll-step -The number of lines to scroll when the cursor moves out of the window. -Scrolling happens automatically if the cursor has moved out of the -visible portion of the node text when it is time to display. Usually -the scrolling is done so as to put the cursor on the center line of the -current window. However, if the variable @code{scroll-step} has a -nonzero value, Info attempts to scroll the node text by that many lines; -if that is enough to bring the cursor back into the window, that is what -is done. The default value of this variable is 0, thus placing the -cursor (and the text it is attached to) in the center of the window. -Setting this variable to 1 causes a kind of "smooth scrolling" which -some people prefer. - -@item ISO-Latin -@cindex ISO Latin characters -@vindex ISO-Latin -When set to @code{On}, Info accepts and displays ISO Latin characters. -By default, Info assumes an ASCII character set. @code{ISO-Latin} tells -Info that it is running in an environment where the European standard -character set is in use, and allows you to input such characters to -Info, as well as display them. -@end table - - - -@c the following is incomplete -@ignore -@c node Info for Sys Admins -@c chapter Info for System Administrators - -This text describes some common ways of setting up an Info hierarchy -from scratch, and details the various options that are available when -installing Info. This text is designed for the person who is installing -GNU Info on the system; although users may find the information present -in this section interesting, none of it is vital to understanding how to -use GNU Info. - -@menu -* Setting the INFOPATH:: Where are my Info files kept? -* Editing the DIR node:: What goes in `DIR', and why? -* Storing Info files:: Alternate formats allow flexibility in setups. -* Using `localdir':: Building DIR on the fly. -* Example setups:: Some common ways to organize Info files. -@end menu - -@c node Setting the INFOPATH -@c section Setting the INFOPATH - -Where are my Info files kept? - -@c node Editing the DIR node -@c section Editing the DIR node - -What goes in `DIR', and why? - -@c node Storing Info files -@c section Storing Info files - -Alternate formats allow flexibility in setups. - -@c node Using `localdir' -@c section Using `localdir' - -Building DIR on the fly. - -@c node Example setups -@c section Example setups - -Some common ways to organize Info files. -@end ignore - -@node GNU Info Global Index, , Variables, Top -@appendix Global Index - -@printindex cp - -@contents -@bye diff --git a/info/info-utils.c b/info/info-utils.c deleted file mode 100644 --- a/info/info-utils.c +++ /dev/null @@ -1,672 +0,0 @@ -/* 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 /* For "NULL". Yechhh! */ -#include -#include -#include -#if defined (HAVE_STRING_H) -# include -#endif /* HAVE_STRING_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). */ -void -info_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. */ -void -info_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 = strdup (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 = strdup (info_parsed_filename); - - if (info_parsed_nodename) - entry->nodename = strdup (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) - return (ref2); - else if (!ref2) - return (ref1); - - /* Get the total size of the slots that we will need. */ - for (i = 0; ref1[i]; i++); - size = i; - for (i = 0; ref2[i]; i++); - size += i; - - result = (REFERENCE **)xmalloc ((1 + size) * sizeof (REFERENCE *)); - - /* Copy the contents over. */ - for (i = 0; ref1[i]; i++) - result[i] = ref1[i]; - - j = i; - for (i = 0; ref2[i]; i++) - result[j++] = ref2[i]; - - result[j] = (REFERENCE *)NULL; - free (ref1); - free (ref2); - return (result); -} - -/* Free the data associated with REFERENCES. */ -void -info_free_references (references) - REFERENCE **references; -{ - register int i; - REFERENCE *entry; - - if (references) - { - for (i = 0; references && (entry = references[i]); i++) - { - maybe_free (entry->label); - maybe_free (entry->filename); - maybe_free (entry->nodename); - - free (entry); - } - - free (references); - } -} - -/* Search for sequences of whitespace or newlines in STRING, replacing - all such sequences with just a single space. Remove whitespace from - start and end of string. */ -void -canonicalize_whitespace (string) - char *string; -{ - register int i, j; - int len, whitespace_found, whitespace_loc; - char *temp; - - if (!string) - return; - - len = strlen (string); - temp = (char *)xmalloc (1 + len); - - /* Search for sequences of whitespace or newlines. Replace all such - sequences in the string with just a single space. */ - - whitespace_found = 0; - for (i = 0, j = 0; string[i]; i++) - { - if (whitespace_or_newline (string[i])) - { - whitespace_found++; - whitespace_loc = i; - continue; - } - else - { - if (whitespace_found && whitespace_loc) - { - whitespace_found = 0; - - /* Suppress whitespace at start of string. */ - if (j) - temp[j++] = ' '; - } - - temp[j++] = string[i]; - } - } - - /* Kill trailing whitespace. */ - if (j && whitespace (temp[j - 1])) - j--; - - temp[j] = '\0'; - strcpy (string, temp); - free (temp); -} - -/* String representation of a char returned by printed_representation (). */ -static char the_rep[10]; - -/* Return a pointer to a string which is the printed representation - of CHARACTER if it were printed at HPOS. */ -char * -printed_representation (character, hpos) - unsigned char character; - int hpos; -{ - register int i = 0; - int printable_limit; - - if (ISO_Latin_p) - printable_limit = 160; - else - printable_limit = 127; - - if (character == '\177') - { - the_rep[i++] = '^'; - the_rep[i++] = '?'; - } - else if (iscntrl (character)) - { - switch (character) - { - case '\r': - case '\n': - the_rep[i++] = character; - break; - - case '\t': - { - int tw; - - tw = ((hpos + 8) & 0xf8) - hpos; - while (i < tw) - the_rep[i++] = ' '; - } - break; - - default: - the_rep[i++] = '^'; - the_rep[i++] = (character | 0x40); - } - } - else if (character > printable_limit) - { - sprintf (the_rep + i, "\\%0o", character); - i = strlen (the_rep); - } - else - the_rep[i++] = character; - - the_rep[i] = '\0'; - - return (the_rep); -} - - -/* **************************************************************** */ -/* */ -/* Functions Static To This File */ -/* */ -/* **************************************************************** */ - -/* Amount of space allocated to INFO_PARSED_FILENAME via xmalloc (). */ -static int parsed_filename_size = 0; - -/* Amount of space allocated to INFO_PARSED_NODENAME via xmalloc (). */ -static int parsed_nodename_size = 0; - -static void save_string (), saven_string (); - -/* Remember FILENAME in PARSED_FILENAME. An empty FILENAME is translated - to a NULL pointer in PARSED_FILENAME. */ -static void -save_filename (filename) - char *filename; -{ - save_string (filename, &info_parsed_filename, &parsed_filename_size); -} - -/* Just like save_filename (), but you pass the length of the string. */ -static void -saven_filename (filename, len) - char *filename; - int len; -{ - saven_string (filename, len, - &info_parsed_filename, &parsed_filename_size); -} - -/* Remember NODENAME in PARSED_NODENAME. An empty NODENAME is translated - to a NULL pointer in PARSED_NODENAME. */ -static void -save_nodename (nodename) - char *nodename; -{ - save_string (nodename, &info_parsed_nodename, &parsed_nodename_size); -} - -/* Just like save_nodename (), but you pass the length of the string. */ -static void -saven_nodename (nodename, len) - char *nodename; - int len; -{ - saven_string (nodename, len, - &info_parsed_nodename, &parsed_nodename_size); -} - -/* Remember STRING in STRING_P. STRING_P should currently have STRING_SIZE_P - bytes allocated to it. An empty STRING is translated to a NULL pointer - in STRING_P. */ -static void -save_string (string, string_p, string_size_p) - char *string; - char **string_p; - int *string_size_p; -{ - if (!string || !*string) - { - if (*string_p) - free (*string_p); - - *string_p = (char *)NULL; - *string_size_p = 0; - } - else - { - if (strlen (string) >= *string_size_p) - *string_p = (char *)xrealloc - (*string_p, (*string_size_p = 1 + strlen (string))); - - strcpy (*string_p, string); - } -} - -/* Just like save_string (), but you also pass the length of STRING. */ -static void -saven_string (string, len, string_p, string_size_p) - char *string; - int len; - char **string_p; - int *string_size_p; -{ - if (!string) - { - if (*string_p) - free (*string_p); - - *string_p = (char *)NULL; - *string_size_p = 0; - } - else - { - if (len >= *string_size_p) - *string_p = (char *)xrealloc (*string_p, (*string_size_p = 1 + len)); - - strncpy (*string_p, string, len); - (*string_p)[len] = '\0'; - } -} - -/* Return a pointer to the part of PATHNAME that simply defines the file. */ -char * -filename_non_directory (pathname) - char *pathname; -{ - char *filename; - - filename = (char *) strrchr (pathname, '/'); - - if (filename) - filename++; - else - filename = pathname; - - return (filename); -} - -/* Return non-zero if NODE is one especially created by Info. */ -int -internal_info_node_p (node) - NODE *node; -{ -#if defined (NEVER) - if (node && - (node->filename && !*node->filename) && - !node->parent && node->nodename) - return (1); - else - return (0); -#else - return ((node != (NODE *)NULL) && ((node->flags & N_IsInternal) != 0)); -#endif /* !NEVER */ -} - -/* Make NODE appear to be one especially created by Info. */ -void -name_internal_node (node, name) - NODE *node; - char *name; -{ - if (!node) - return; - - node->filename = ""; - node->parent = (char *)NULL; - node->nodename = name; - node->flags |= N_IsInternal; -} - -/* Return the window displaying NAME, the name of an internally created - Info window. */ -WINDOW * -get_internal_info_window (name) - char *name; -{ - WINDOW *win; - - for (win = windows; win; win = win->next) - if (internal_info_node_p (win->node) && - (strcmp (win->node->nodename, name) == 0)) - break; - - return (win); -} diff --git a/info/info-utils.h b/info/info-utils.h deleted file mode 100644 --- a/info/info-utils.h +++ /dev/null @@ -1,140 +0,0 @@ -/* info-utils.h -- Exported functions and variables from info-util.c. - $Id: info-utils.h,v 1.4 1996-11-13 03:41:41 jwe Exp $ - - This file is part of GNU Info, a program for reading online documentation - stored in Info format. - - Copyright (C) 1993, 96 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). */ - -#if !defined (_INFO_UTILS_H_) -#define _INFO_UTILS_H_ - -#if !defined (HAVE_STRCHR) -# undef strchr -# undef strrchr -# define strchr index -# define strrchr rindex -#endif /* !HAVE_STRCHR */ - -#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 (). */ -typedef struct { - char *label; /* User Label. */ - char *filename; /* File where this node can be found. */ - char *nodename; /* Name of the node. */ - int start, end; /* Offsets within the containing node of LABEL. */ -} REFERENCE; - -/* When non-zero, various display and input functions handle ISO Latin - character sets correctly. */ -extern int ISO_Latin_p; - -/* Variable which holds the most recent filename parsed as a result of - calling info_parse_xxx (). */ -extern char *info_parsed_filename; - -/* Variable which holds the most recent nodename parsed as a result of - calling info_parse_xxx (). */ -extern char *info_parsed_nodename; - -/* 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). */ -void info_parse_node (); - -/* 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. */ -extern REFERENCE **info_menu_of_node (); - -/* 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. */ -extern REFERENCE **info_xrefs_of_node (); - -/* Glean cross references from BINDING->buffer + BINDING->start until - BINDING->end. Return an array of REFERENCE * that represents each - cross reference in this range. */ -extern REFERENCE **info_xrefs (); - -/* Get the entry associated with LABEL in REFERENCES. Return a pointer to - the reference if found, or NULL. */ -extern REFERENCE *info_get_labeled_reference (); - -/* 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. */ -extern REFERENCE **info_menu_items (); - -/* 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 (); - -/* Free the data associated with REFERENCES. */ -extern void info_free_references (); - -/* Search for sequences of whitespace or newlines in STRING, replacing - all such sequences with just a single space. Remove whitespace from - start and end of string. */ -void canonicalize_whitespace (); - -/* Return a pointer to a string which is the printed representation - of CHARACTER if it were printed at HPOS. */ -extern char *printed_representation (); - -/* Return a pointer to the part of PATHNAME that simply defines the file. */ -extern char *filename_non_directory (); - -/* Return non-zero if NODE is one especially created by Info. */ -extern int internal_info_node_p (); - -/* Make NODE appear to be one especially created by Info, and give it NAME. */ -extern void name_internal_node (); - -/* Return the window displaying NAME, the name of an internally created - Info window. */ -extern WINDOW *get_internal_info_window (); - -/* 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. */ -extern void info_parse_label (/* label, node */); - -#define info_label_was_found \ - (info_parsed_nodename != NULL || info_parsed_filename != NULL) - -#define info_file_label_of_node(n) info_parse_label (INFO_FILE_LABEL, n) -#define info_next_label_of_node(n) info_parse_label (INFO_NEXT_LABEL, n) -#define info_up_label_of_node(n) info_parse_label (INFO_UP_LABEL, n) -#define info_prev_label_of_node(n) \ - do { \ - info_parse_label (INFO_PREV_LABEL, n); \ - if (!info_label_was_found) \ - info_parse_label (INFO_ALTPREV_LABEL, n); \ - } while (0) - -#endif /* !_INFO_UTILS_H_ */ diff --git a/info/info.1 b/info/info.1 deleted file mode 100644 --- a/info/info.1 +++ /dev/null @@ -1,229 +0,0 @@ -.TH info 1 "7th December 1990" -.SH NAME -info \- GNU's hypertext system -.SH SYNOPSIS -.B info -[ -.B \-\-option-name option-value -] -.B \menu-item... -.SH COPYRIGHT -.if n Copyright (C) 1989, 1993 Free Software Foundation, Inc. -.if t Copyright \(co 1989, 1993 Free Software Foundation, Inc. -.SH DESCRIPTION -.LP -The GNU project has a hypertext system called -.I Info -which allows the same source file to be either printed as a -paper manual, or viewed using -.B info. -It is possible to use the -.B info -program from inside Emacs, or to use the stand-alone version described here. -This manual page gives a brief summary of its capabilities. - -.SH OPTIONS -.TP -.B \-\-directory directory-path -Add -.B directory-path -to the list of directory paths searched when -.B info -needs to find a file. You may issue -.B \-\-directory -multiple times. -Alternatively, you may specify a value for the environment variable -.B INFOPATH; -if -.B \-\-directory -is not given, the value of -.B INFOPATH -is used. The value of -.B INFOPATH -is a colon separated list of directory names. If you do not supply either -.B INFOPATH -or -.B \-\-directory-path, -.B info -uses a default path. -.TP -.B \-f filename -Specify a particular -.B info -file to visit. By default, -.B info -visits -the file -.B dir; -if you use this option, -.B info -will start with -.B (FILENAME)Top -as the first file and node. -.TP -.B \-n nodename -Specify a particular node to visit in the initial file that -.B info -loads. This is especially useful in conjunction with -.B \-\-file. -You may specify -.B \-\-node -multiple times. -.TP -.B -o file -Direct output to -.B file -instead of starting an interactive -.B info -session. -.TP -.B \-h -Produce a relatively brief description of the available -.B info -options. -.TP -.B \-\-version -Print the version information of -.B info -and exit. -.TP -.B menu-item -.B info -treats its remaining arguments as the names of menu items. -The first argument is a menu item in the initial node visited, -while the second argument is a menu item in the first argument's -node. You can easily move to the node of your choice by -specifying the menu names which describe the path to that node. -For example, - -.B info emacs buffers - -first selects the menu item -.B emacs -in the node -.B (dir)Top, -and then selects the menu item -.B buffers -in the node -.B (emacs)Top. -.SH COMMANDS -When in -.B info -the following commands are available: -.TP -.B h -Invoke the Info tutorial. -.TP -.B ? -Get a short summary of -.B info -commands. -.TP -.B h -Select the -.B info -node from the main directory; this is much more complete than just -using -.B ?. -.TP -.B Ctrl-g -Abort whatever you are doing. -.TP -.B Ctrl-l -Redraw the screen. -.PP -Selecting other nodes: -.TP -.B n -Move to the "next" node of this node. -.TP -.B p -Move to the "previous" node of this node. -.TP -.B u -Move to this node's "up" node. -.TP -.B m -Pick a menu item specified by name. Picking a menu item causes another -node to be selected. You do not need to type a complete nodename; if -you type a few letters and then a space or tab -.B info -will will try to fill in the rest of the nodename. If you ask for further -completion without typing any more characters you'll be given a list -of possibilities; you can also get the list with -.B ?. -If you type a few characters and then hit return -.B info -will try to do a completion, and if it is ambigous use the first possibility. -.TP -.B f -Follow a cross reference. You are asked for the name of the reference, -using command completion as for -.B m. -.TP -.B l -Move to the last node you were at. -.PP -Moving within a node: -.TP -.B Space -Scroll forward a page. -.TP -.B DEL -Scroll backward a page. -.TP -.B b -Go to the beginning of this node. -.PP -Advanced commands: -.TP -.B q -Quit -.B info. -.TP -.B 1 -Pick first item in node's menu. -.TP -.B 2 \-\- 5 -Pick second ... fifth item in node's menu. -.TP -.B g -Move to node specified by name. You may include a filename as well, -as -.B (FILENAME)NODENAME. -.TP -.B s -Search through this -.B info -file for a specified string, and select the node in which -the next occurrence is found. -.TP -.B M-x print-node -Pipe the contents of the current node through the command in the -environment variable -.B INFO_PRINT_COMMAND. -If the variable does not exist, the node is simply piped to -.B lpr. -.SH ENVIRONMENT -.TP -.B INFOPATH -A colon-separated list of directories to search for -.B info -files. Used if -.B \-\-directory -is not given. -.TP -.B INFO_PRINT_COMMAND -The command used for printing. -.SH SEE ALSO -.BR emacs (1) -.SH AUTHOR -.RS -Brian Fox, Free Software Foundation -.br -bfox@ai.mit.edu -.SH MANUAL AUTHOR -.RS -Robert Lupton; updated by Robert J. Chassell. -.br -rhl@astro.princeton.edu; bob@gnu.ai.mit.edu diff --git a/info/info.c b/info/info.c deleted file mode 100644 --- a/info/info.c +++ /dev/null @@ -1,619 +0,0 @@ -/* info.c -- Display nodes of Info files in multiple windows. */ - -/* This file is part of GNU Info, a program for reading online documentation - stored in Info format. - - Copyright (C) 1993, 96 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 "dribble.h" -#include "getopt.h" -#if defined (HANDLE_MAN_PAGES) -# include "man.h" -#endif /* HANDLE_MAN_PAGES */ - -/* The version numbers of this version of Info. */ -int info_major_version = 2; -int info_minor_version = 16; -int info_patch_level = 0; - -/* Non-zero means search all indices for APROPOS_SEARCH_STRING. */ -static int apropos_p = 0; - -/* Variable containing the string to search for when apropos_p is non-zero. */ -static char *apropos_search_string = (char *)NULL; - -/* Non-zero means search all indices for INDEX_SEARCH_STRING. Unlike - apropos, this puts the user at the node, running info. */ -static int index_search_p = 0; - -/* Variable containing the string to search for when index_search_p is - non-zero. */ -static char *index_search_string = (char *)NULL; - -/* Non-zero means print version info only. */ -static int print_version_p = 0; - -/* Non-zero means print a short description of the options. */ -static int print_help_p = 0; - -/* Array of the names of nodes that the user specified with "--node" on the - command line. */ -static char **user_nodenames = (char **)NULL; -static int user_nodenames_index = 0; -static int user_nodenames_slots = 0; - -/* String specifying the first file to load. This string can only be set - by the user specifying "--file" on the command line. */ -static char *user_filename = (char *)NULL; - -/* String specifying the name of the file to dump nodes to. This value is - filled if the user speficies "--output" on the command line. */ -static char *user_output_filename = (char *)NULL; - -/* Non-zero indicates that when "--output" is specified, all of the menu - items of the specified nodes (and their subnodes as well) should be - dumped in the order encountered. This basically can print a book. */ -int dump_subnodes = 0; - -/* Structure describing the options that Info accepts. We pass this structure - to getopt_long (). If you add or otherwise change this structure, you must - also change the string which follows it. */ -#define APROPOS_OPTION 1 -#define DRIBBLE_OPTION 2 -#define RESTORE_OPTION 3 -#define IDXSRCH_OPTION 4 -static struct option long_options[] = { - { "apropos", 1, 0, APROPOS_OPTION }, - { "directory", 1, 0, 'd' }, - { "node", 1, 0, 'n' }, - { "file", 1, 0, 'f' }, - { "subnodes", 0, &dump_subnodes, 1 }, - { "output", 1, 0, 'o' }, - { "help", 0, &print_help_p, 1 }, - { "version", 0, &print_version_p, 1 }, - { "dribble", 1, 0, DRIBBLE_OPTION }, - { "restore", 1, 0, RESTORE_OPTION }, - { "index-search", 1, 0, IDXSRCH_OPTION }, - {NULL, 0, NULL, 0} -}; - -/* String describing the shorthand versions of the long options found above. */ -static char *short_options = "d:n:f:o:s"; - -/* When non-zero, the Info window system has been initialized. */ -int info_windows_initialized_p = 0; - -/* Some "forward" declarations. */ -static void usage (), info_short_help (), remember_info_program_name (); - - -/* **************************************************************** */ -/* */ -/* Main Entry Point to the Info Program */ -/* */ -/* **************************************************************** */ - -int -main (argc, argv) - int argc; - char **argv; -{ - int getopt_long_index; /* Index returned by getopt_long (). */ - NODE *initial_node; /* First node loaded by Info. */ - - remember_info_program_name (argv[0]); - - while (1) - { - int option_character; - - option_character = getopt_long - (argc, argv, short_options, long_options, &getopt_long_index); - - /* getopt_long () returns EOF when there are no more long options. */ - if (option_character == EOF) - break; - - /* If this is a long option, then get the short version of it. */ - if (option_character == 0 && long_options[getopt_long_index].flag == 0) - option_character = long_options[getopt_long_index].val; - - /* Case on the option that we have received. */ - switch (option_character) - { - case 0: - break; - - /* User wants to add a directory. */ - case 'd': - info_add_path (optarg, INFOPATH_PREPEND); - break; - - /* User is specifying a particular node. */ - case 'n': - add_pointer_to_array (optarg, user_nodenames_index, user_nodenames, - user_nodenames_slots, 10, char *); - break; - - /* User is specifying a particular Info file. */ - case 'f': - if (user_filename) - free (user_filename); - - user_filename = strdup (optarg); - break; - - /* User is specifying the name of a file to output to. */ - case 'o': - if (user_output_filename) - free (user_output_filename); - user_output_filename = strdup (optarg); - break; - - /* User is specifying that she wishes to dump the subnodes of - the node that she is dumping. */ - case 's': - dump_subnodes = 1; - break; - - /* User has specified a string to search all indices for. */ - case APROPOS_OPTION: - apropos_p = 1; - maybe_free (apropos_search_string); - apropos_search_string = strdup (optarg); - break; - - /* User has specified a dribble file to receive keystrokes. */ - case DRIBBLE_OPTION: - close_dribble_file (); - open_dribble_file (optarg); - break; - - /* User has specified an alternate input stream. */ - case RESTORE_OPTION: - info_set_input_from_file (optarg); - break; - - /* User has specified a string to search all indices for. */ - case IDXSRCH_OPTION: - index_search_p = 1; - maybe_free (index_search_string); - index_search_string = strdup (optarg); - break; - - default: - usage (); - } - } - - /* If the output device is not a terminal, and no output filename has been - specified, make user_output_filename be "-", so that the info is written - to stdout, and turn on the dumping of subnodes. */ - if ((!isatty (fileno (stdout))) && (user_output_filename == (char *)NULL)) - { - user_output_filename = strdup ("-"); - dump_subnodes = 1; - } - - /* If the user specified --version, then show the version and exit. */ - if (print_version_p) - { - printf ("GNU Info (Texinfo 3.9) %s\n", version_string ()); - puts ("Copyright (C) 1996 Free Software Foundation, Inc.\n\ -There is NO warranty. You may redistribute this software\n\ -under the terms of the GNU General Public License.\n\ -For more information about these matters, see the files named COPYING."); - exit (0); - } - - /* If the `--help' option was present, show the help and exit. */ - if (print_help_p) - { - info_short_help (); - exit (0); - } - - /* If the user hasn't specified a path for Info files, default that path - now. */ - if (!infopath) - { - char *path_from_env, *getenv (); - - path_from_env = getenv ("INFOPATH"); - - if (path_from_env) - info_add_path (path_from_env, INFOPATH_PREPEND); - else - info_add_path (DEFAULT_INFOPATH, INFOPATH_PREPEND); - } - - /* If the user specified a particular filename, add the path of that - file to the contents of INFOPATH. */ - if (user_filename) - { - char *directory_name, *temp; - - directory_name = strdup (user_filename); - temp = filename_non_directory (directory_name); - - if (temp != directory_name) - { - *temp = 0; - info_add_path (directory_name, INFOPATH_PREPEND); - } - - free (directory_name); - } - - /* If the user wants to search every known index for a given string, - do that now, and report the results. */ - if (apropos_p) - { - info_apropos (apropos_search_string); - exit (0); - } - - /* Get the initial Info node. It is either "(dir)Top", or what the user - specifed with values in user_filename and user_nodenames. */ - if (user_nodenames) - initial_node = info_get_node (user_filename, user_nodenames[0]); - else - initial_node = info_get_node (user_filename, (char *)NULL); - - /* If we couldn't get the initial node, this user is in trouble. */ - if (!initial_node) - { - if (info_recent_file_error) - info_error (info_recent_file_error); - else - info_error - (CANT_FIND_NODE, user_nodenames ? user_nodenames[0] : "Top"); - exit (1); - } - - /* Special cases for when the user specifies multiple nodes. If we are - dumping to an output file, dump all of the nodes specified. Otherwise, - attempt to create enough windows to handle the nodes that this user wants - displayed. */ - if (user_nodenames_index > 1) - { - free (initial_node); - - if (user_output_filename) - dump_nodes_to_file - (user_filename, user_nodenames, user_output_filename, dump_subnodes); - else - begin_multiple_window_info_session (user_filename, user_nodenames); - - exit (0); - } - - /* If the user specified `--index-search string', start the info - session in the node corresponding to the first match. */ - if (index_search_p) - { - int status = 0; - - initialize_info_session (initial_node, 0); - - if (index_entry_exists (windows, index_search_string)) - { - terminal_clear_screen (); - terminal_prep_terminal (); - display_update_display (windows); - info_last_executed_command = (VFunction *)NULL; - - do_info_index_search (windows, 0, index_search_string); - - info_read_and_dispatch (); - - terminal_unprep_terminal (); - - /* On program exit, leave the cursor at the bottom of the - window, and restore the terminal IO. */ - terminal_goto_xy (0, screenheight - 1); - terminal_clear_to_eol (); - fflush (stdout); - } - else - { - fprintf (stderr, "no entries found\n"); - status = -1; - } - - close_dribble_file (); - exit (status); - } - - /* If there are arguments remaining, they are the names of menu items - in sequential info files starting from the first one loaded. That - file name is either "dir", or the contents of user_filename if one - was specified. */ - while (optind != argc) - { - REFERENCE **menu; - REFERENCE *entry; - NODE *node; - char *arg; - static char *first_arg = (char *)NULL; - - /* Remember the name of the menu entry we want. */ - arg = argv[optind++]; - - if (first_arg == (char *)NULL) - first_arg = arg; - - /* Build and return a list of the menu items in this node. */ - menu = info_menu_of_node (initial_node); - - /* If there wasn't a menu item in this node, stop here, but let - the user continue to use Info. Perhaps they wanted this node - and didn't realize it. */ - if (!menu) - { -#if defined (HANDLE_MAN_PAGES) - if (first_arg == arg) - { - node = make_manpage_node (first_arg); - if (node) - goto maybe_got_node; - } -#endif /* HANDLE_MAN_PAGES */ - begin_info_session_with_error - (initial_node, "There is no menu in this node."); - exit (0); - } - - /* Find the specified menu item. */ - entry = info_get_labeled_reference (arg, menu); - - /* If the item wasn't found, search the list sloppily. Perhaps this - user typed "buffer" when they really meant "Buffers". */ - if (!entry) - { - register int i; - int best_guess = -1; - - for (i = 0; entry = menu[i]; i++) - { - if (strcasecmp (entry->label, arg) == 0) - break; - else - if (strncasecmp (entry->label, arg, strlen (arg)) == 0) - best_guess = i; - } - - if (!entry && best_guess != -1) - entry = menu[best_guess]; - } - - /* If we failed to find the reference, start Info with the current - node anyway. It is probably a misspelling. */ - if (!entry) - { - char *error_message = "There is no menu item \"%s\" in this node."; - -#if defined (HANDLE_MAN_PAGES) - if (first_arg == arg) - { - node = make_manpage_node (first_arg); - if (node) - goto maybe_got_node; - } -#endif /* HANDLE_MAN_PAGES */ - - info_free_references (menu); - - /* If we were supposed to dump this node, complain. */ - if (user_output_filename) - info_error (error_message, arg); - else - begin_info_session_with_error (initial_node, error_message, arg); - - exit (0); - } - - /* We have found the reference that the user specified. Clean it - up a little bit. */ - if (!entry->filename) - { - if (initial_node->parent) - entry->filename = strdup (initial_node->parent); - else - entry->filename = strdup (initial_node->filename); - } - - /* Find this node. If we can find it, then turn the initial_node - into this one. If we cannot find it, try using the label of the - entry as a file (i.e., "(LABEL)Top"). Otherwise the Info file is - malformed in some way, and we will just use the current value of - initial node. */ - node = info_get_node (entry->filename, entry->nodename); - -#if defined (HANDLE_MAN_PAGES) - if ((first_arg == arg) && !node) - { - node = make_manpage_node (first_arg); - if (node) - goto maybe_got_node; - } -#endif /* HANDLE_MAN_PAGES */ - - if (!node && entry->nodename && - (strcmp (entry->label, entry->nodename) == 0)) - node = info_get_node (entry->label, "Top"); - - maybe_got_node: - if (node) - { - free (initial_node); - initial_node = node; - info_free_references (menu); - } - else - { - char *temp = strdup (entry->label); - char *error_message; - - error_message = "Unable to find the node referenced by \"%s\"."; - - info_free_references (menu); - - /* If we were trying to dump the node, then give up. Otherwise, - start the session with an error message. */ - if (user_output_filename) - info_error (error_message, temp); - else - begin_info_session_with_error (initial_node, error_message, temp); - - exit (0); - } - } - - /* If the user specified that this node should be output, then do that - now. Otherwise, start the Info session with this node. */ - if (user_output_filename) - dump_node_to_file (initial_node, user_output_filename, dump_subnodes); - else - begin_info_session (initial_node); - - exit (0); -} - -/* Return a string describing the current version of Info. */ -char * -version_string () -{ - static char *vstring = (char *)NULL; - - if (!vstring) - { - vstring = (char *)xmalloc (50); - sprintf (vstring, "%d.%d", info_major_version, info_minor_version); - if (info_patch_level) - sprintf (vstring + strlen (vstring), "-p%d", info_patch_level); - } - return (vstring); -} - -/* **************************************************************** */ -/* */ -/* Error Handling for Info */ -/* */ -/* **************************************************************** */ - -static char *program_name = (char *)NULL; - -static void -remember_info_program_name (fullpath) - char *fullpath; -{ - char *filename; - - filename = filename_non_directory (fullpath); - program_name = strdup (filename); -} - -/* Non-zero if an error has been signalled. */ -int info_error_was_printed = 0; - -/* Non-zero means ring terminal bell on errors. */ -int info_error_rings_bell_p = 1; - -/* Print FORMAT with ARG1 and ARG2. If the window system was initialized, - then the message is printed in the echo area. Otherwise, a message is - output to stderr. */ -void -info_error (format, arg1, arg2) - char *format; - void *arg1, *arg2; -{ - info_error_was_printed = 1; - - if (!info_windows_initialized_p || display_inhibited) - { - fprintf (stderr, "%s: ", program_name); - fprintf (stderr, format, arg1, arg2); - fprintf (stderr, "\n"); - fflush (stderr); - } - else - { - if (!echo_area_is_active) - { - if (info_error_rings_bell_p) - terminal_ring_bell (); - window_message_in_echo_area (format, arg1, arg2); - } - else - { - NODE *temp; - - temp = build_message_node (format, arg1, arg2); - if (info_error_rings_bell_p) - terminal_ring_bell (); - inform_in_echo_area (temp->contents); - free (temp->contents); - free (temp); - } - } -} - -/* Produce a very brief descripton of the available options and exit with - an error. */ -static void -usage () -{ - fprintf (stderr,"%s\n%s\n%s\n%s\n%s\n", -"Usage: info [-d dir-path] [-f info-file] [-o output-file] [-n node-name]...", -" [--directory dir-path] [--file info-file] [--node node-name]...", -" [--help] [--output output-file] [--subnodes] [--version]", -" [--dribble dribble-file] [--restore from-file]", -" [menu-selection ...]"); - exit (1); -} - -/* Produce a scaled down description of the available options to Info. */ -static void -info_short_help () -{ - puts ("\ -Here is a quick description of Info's options. For a more complete\n\ -description of how to use Info, type `info info options'.\n\ -\n\ - --directory DIR Add DIR to INFOPATH.\n\ - --dribble FILENAME Remember user keystrokes in FILENAME.\n\ - --file FILENAME Specify Info file to visit.\n\ - --node NODENAME Specify nodes in first visited Info file.\n\ - --output FILENAME Output selected nodes to FILENAME.\n\ - --restore FILENAME Read initial keystrokes from FILENAME.\n\ - --subnodes Recursively output menu items.\n\ - --help Get this help message.\n\ - --version Display Info's version information.\n\ -\n\ -Remaining arguments to Info are treated as the names of menu\n\ -items in the initial node visited. You can easily move to the\n\ -node of your choice by specifying the menu names which describe\n\ -the path to that node. For example, `info emacs buffers'.\n\ -\n\ -Email bug reports to bug-texinfo@prep.ai.mit.edu."); - - exit (0); -} diff --git a/info/info.h b/info/info.h deleted file mode 100644 --- a/info/info.h +++ /dev/null @@ -1,100 +0,0 @@ -/* info.h -- Header file which includes all of the other headers. */ - -/* 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). */ - -#if !defined (_INFO_H_) -#define _INFO_H_ - -#include -#include -#include -#include -#if defined (HAVE_STRING_H) -#include -#endif /* HAVE_STRING_H */ -#include "filesys.h" -#include "display.h" -#include "session.h" -#include "echo_area.h" -#include "doc.h" -#include "footnotes.h" -#include "gc.h" - -/* A structure associating the nodes visited in a particular window. */ -typedef struct { - WINDOW *window; /* The window that this list is attached to. */ - NODE **nodes; /* Array of nodes visited in this window. */ - int *pagetops; /* For each node in NODES, the pagetop. */ - long *points; /* For each node in NODES, the point. */ - int current; /* Index in NODES of the current node. */ - int nodes_index; /* Index where to add the next node. */ - int nodes_slots; /* Number of slots allocated to NODES. */ -} INFO_WINDOW; - -/* Array of structures describing for each window which nodes have been - visited in that window. */ -extern INFO_WINDOW **info_windows; - -/* For handling errors. If you initialize the window system, you should - also set info_windows_initialized_p to non-zero. It is used by the - info_error () function to determine how to format and output errors. */ -extern int info_windows_initialized_p; - -/* Non-zero if an error message has been printed. */ -extern int info_error_was_printed; - -/* Non-zero means ring terminal bell on errors. */ -extern int info_error_rings_bell_p; - -/* Print FORMAT with ARG1 and ARG2. If the window system was initialized, - then the message is printed in the echo area. Otherwise, a message is - output to stderr. */ -extern void info_error (); - -/* The version numbers of Info. */ -extern int info_major_version, info_minor_version, info_patch_level; - -/* How to get the version string for this version of Info. Returns - something similar to "2.11". */ -extern char *version_string (); - -/* Error message defines. */ -#define CANT_FIND_NODE "Cannot find the node \"%s\"." -#define CANT_FILE_NODE "Cannot find the node \"(%s)%s\"." -#define CANT_FIND_WIND "Cannot find a window!" -#define CANT_FIND_POINT "Point doesn't appear within this window's node!" -#define CANT_KILL_LAST "Cannot delete the last window." -#define NO_MENU_NODE "No menu in this node." -#define NO_FOOT_NODE "No footnotes in this node." -#define NO_XREF_NODE "No cross references in this node." -#define NO_POINTER "No \"%s\" pointer for this node." -#define UNKNOWN_COMMAND "Unknown Info command `%c'. `?' for help." -#define TERM_TOO_DUMB "Terminal type \"%s\" is not smart enough to run Info." -#define AT_NODE_BOTTOM "You are already at the last page of this node." -#define AT_NODE_TOP "You are already at the first page of this node." -#define ONE_WINDOW "Only one window." -#define WIN_TOO_SMALL "Resulting window would be too small." -#define CANT_MAKE_HELP \ -"There isn't enough room to make a help window. Please delete a window." - -#endif /* !_INFO_H_ */ - diff --git a/info/info.texi b/info/info.texi deleted file mode 100644 --- a/info/info.texi +++ /dev/null @@ -1,916 +0,0 @@ -\input texinfo @c -*-texinfo-*- -@comment %**start of header -@setfilename info.info -@settitle Info 1.0 -@comment %**end of header -@comment $Id: info.texi,v 1.3 1996-11-13 03:41:41 jwe Exp $ - -@dircategory Texinfo documentation system -@direntry -* Info: (info). Documentation browsing system. -@end direntry - -@ifinfo -This file describes how to use Info, -the on-line, menu-driven GNU documentation system. - -Copyright (C) 1989, 92, 96 Free Software Foundation, Inc. - -Permission is granted to make and distribute verbatim copies of -this manual provided the copyright notice and this permission notice -are preserved on all copies. - -@ignore -Permission is granted to process this file through TeX and print the -results, provided the printed document carries copying permission -notice identical to this one except for the removal of this paragraph -(this paragraph not being relevant to the printed manual). - -@end ignore -Permission is granted to copy and distribute modified versions of this -manual under the conditions for verbatim copying, provided that the entire -resulting derived work is distributed under the terms of a permission -notice identical to this one. - -Permission is granted to copy and distribute translations of this manual -into another language, under the above conditions for modified versions, -except that this permission notice may be stated in a translation approved -by the Free Software Foundation. -@end ifinfo - -@titlepage -@sp 11 -@center @titlefont{Info} -@sp 2 -@center The -@sp 2 -@center On-line, Menu-driven -@sp 2 -@center GNU Documentation System - -@page -@vskip 0pt plus 1filll -Copyright @copyright{} 1989, 1992, 1993 Free Software Foundation, Inc. -@sp 2 - -Published by the Free Software Foundation @* -59 Temple Place - Suite 330 @* -Boston, MA 02111-1307, USA. - -Permission is granted to make and distribute verbatim copies of -this manual provided the copyright notice and this permission notice -are preserved on all copies. - -Permission is granted to copy and distribute modified versions of this -manual under the conditions for verbatim copying, provided that the entire -resulting derived work is distributed under the terms of a permission -notice identical to this one. - -Permission is granted to copy and distribute translations of this manual -into another language, under the above conditions for modified versions, -except that this permission notice may be stated in a translation approved -by the Free Software Foundation. -@end titlepage - -@ifinfo -@node Top, Getting Started, (dir), (dir) -@top Info: An Introduction - -Info is a program for reading documentation, which you are using now. - -To learn how to use Info, type the command @kbd{h}. It brings you -to a programmed instruction sequence. - -@c Need to make sure that `Info-help' goes to the right node, -@c which is the first node of the first chapter. (It should.) -@c (Info-find-node "info" -@c (if (< (window-height) 23) -@c "Help-Small-Screen" -@c "Help"))) - -To learn advanced Info commands, type @kbd{n} twice. This brings you to -@cite{Info for Experts}, skipping over the `Getting Started' chapter. -@end ifinfo - -@menu -* Getting Started:: Getting started using an Info reader. -* Advanced Info:: Advanced commands within Info. -* Create an Info File:: How to make your own Info file. -* The Standalone Info Program: (info-stnd.info). -@end menu - -@node Getting Started, Advanced Info, Top, Top -@comment node-name, next, previous, up -@chapter Getting Started - -This first part of the Info manual describes how to get around inside -of Info. The second part of the manual describes various advanced -Info commands, and how to write an Info as distinct from a Texinfo -file. The third part is about how to generate Info files from -Texinfo files. - -@iftex -This manual is primarily designed for use on a computer, so that you can -try Info commands while reading about them. Reading it on paper is less -effective, since you must take it on faith that the commands described -really do what the manual says. By all means go through this manual now -that you have it; but please try going through the on-line version as -well. - -There are two ways of looking at the online version of this manual: - -@enumerate -@item -Type @code{info} at your shell's command line. This approach uses a -small stand-alone program designed just to read Info files. - -@item -Type @code{emacs} at the command line; then type @kbd{C-h i} (Control -@kbd{h}, followed by @kbd{i}). This approach uses the Info mode of the -Emacs program, an editor with many other capabilities. -@end enumerate - -In either case, then type @kbd{mInfo} (just the letters), followed by -@key{RET}---the ``Return'' or ``Enter'' key. At this point, you should -be ready to follow the instructions in this manual as you read them on -the screen. -@c FIXME! (pesch@cygnus.com, 14 dec 1992) -@c Is it worth worrying about what-if the beginner goes to somebody -@c else's Emacs session, which already has an Info running in the middle -@c of something---in which case these simple instructions won't work? -@end iftex - -@menu -* Help-Small-Screen:: Starting Info on a Small Screen -* Help:: How to use Info -* Help-P:: Returning to the Previous node -* Help-^L:: The Space, Rubout, B and ^L commands. -* Help-M:: Menus -* Help-Adv:: Some advanced Info commands -* Help-Q:: Quitting Info -@end menu - -@node Help-Small-Screen, Help, , Getting Started -@comment node-name, next, previous, up -@section Starting Info on a Small Screen - -@iftex -(In Info, you only see this section if your terminal has a small -number of lines; most readers pass by it without seeing it.) -@end iftex - -Since your terminal has an unusually small number of lines on its -screen, it is necessary to give you special advice at the beginning. - -If you see the text @samp{--All----} at near the bottom right corner -of the screen, it means the entire text you are looking at fits on the -screen. If you see @samp{--Top----} instead, it means that there is -more text below that does not fit. To move forward through the text -and see another screen full, press the Space bar, @key{SPC}. To move -back up, press the key labeled @samp{Backspace} or @key{Delete}. - -@ifinfo -Here are 40 lines of junk, so you can try Spaces and Deletes and -see what they do. At the end are instructions of what you should do -next. - -This is line 17 @* -This is line 18 @* -This is line 19 @* -This is line 20 @* -This is line 21 @* -This is line 22 @* -This is line 23 @* -This is line 24 @* -This is line 25 @* -This is line 26 @* -This is line 27 @* -This is line 28 @* -This is line 29 @* -This is line 30 @* -This is line 31 @* -This is line 32 @* -This is line 33 @* -This is line 34 @* -This is line 35 @* -This is line 36 @* -This is line 37 @* -This is line 38 @* -This is line 39 @* -This is line 40 @* -This is line 41 @* -This is line 42 @* -This is line 43 @* -This is line 44 @* -This is line 45 @* -This is line 46 @* -This is line 47 @* -This is line 48 @* -This is line 49 @* -This is line 50 @* -This is line 51 @* -This is line 52 @* -This is line 53 @* -This is line 54 @* -This is line 55 @* -This is line 56 @* - -If you have managed to get here, go back to the beginning with -Delete, and come back here again, then you understand Space and -Delete. So now type an @kbd{n} ---just one character; don't type -the quotes and don't type the Return key afterward--- to -get to the normal start of the course. -@end ifinfo - -@node Help, Help-P, Help-Small-Screen, Getting Started -@comment node-name, next, previous, up -@section How to use Info - -You are talking to the program Info, for reading documentation. - - Right now you are looking at one @dfn{Node} of Information. -A node contains text describing a specific topic at a specific -level of detail. This node's topic is ``how to use Info''. - - The top line of a node is its @dfn{header}. This node's header (look at -it now) says that it is the node named @samp{Help} in the file -@file{info}. It says that the @samp{Next} node after this one is the node -called @samp{Help-P}. An advanced Info command lets you go to any node -whose name you know. - - Besides a @samp{Next}, a node can have a @samp{Previous} or an @samp{Up}. -This node has a @samp{Previous} but no @samp{Up}, as you can see. - - Now it is time to move on to the @samp{Next} node, named @samp{Help-P}. - ->> Type @samp{n} to move there. Type just one character; - do not type the quotes and do not type a @key{RET} afterward. - -@samp{>>} in the margin means it is really time to try a command. - -@node Help-P, Help-^L, Help, Getting Started -@comment node-name, next, previous, up -@section Returning to the Previous node - -This node is called @samp{Help-P}. The @samp{Previous} node, as you see, -is @samp{Help}, which is the one you just came from using the @kbd{n} -command. Another @kbd{n} command now would take you to the next -node, @samp{Help-^L}. - ->> But do not do that yet. First, try the @kbd{p} command, which takes - you to the @samp{Previous} node. When you get there, you can do an - @kbd{n} again to return here. - - This all probably seems insultingly simple so far, but @emph{do not} be -led into skimming. Things will get more complicated soon. Also, -do not try a new command until you are told it is time to. Otherwise, -you may make Info skip past an important warning that was coming up. - ->> Now do an @kbd{n} to get to the node @samp{Help-^L} and learn more. - -@node Help-^L, Help-M, Help-P, Getting Started -@comment node-name, next, previous, up -@section The Space, Delete, B and ^L commands. - - This node's header tells you that you are now at node @samp{Help-^L}, and -that @kbd{p} would get you back to @samp{Help-P}. The node's title is -underlined; it says what the node is about (most nodes have titles). - - This is a big node and it does not all fit on your display screen. -You can tell that there is more that is not visible because you -can see the string @samp{--Top-----} rather than @samp{--All----} near -the bottom right corner of the screen. - - The Space, Delete and @kbd{B} commands exist to allow you to ``move -around'' in a node that does not all fit on the screen at once. -Space moves forward, to show what was below the bottom of the screen. -Delete moves backward, to show what was above the top of the screen -(there is not anything above the top until you have typed some spaces). - ->> Now try typing a Space (afterward, type a Delete to return here). - - When you type the space, the two lines that were at the bottom of -the screen appear at the top, followed by more lines. Delete takes -the two lines from the top and moves them to the bottom, -@emph{usually}, but if there are not a full screen's worth of lines -above them they may not make it all the way to the bottom. - - If you type Space when there is no more to see, it rings the -bell and otherwise does nothing. The same goes for Delete when -the header of the node is visible. - - If your screen is ever garbaged, you can tell Info to print it out -again by typing @kbd{C-l} (@kbd{Control-L}, that is---hold down ``Control'' and -type an @key{L} or @kbd{l}). - ->> Type @kbd{C-l} now. - - To move back to the beginning of the node you are on, you can type -a lot of Deletes. You can also type simply @kbd{b} for beginning. ->> Try that now. (We have put in enough verbiage to push this past -the first screenful, but screens are so big nowadays that perhaps it -isn't enough. You may need to shrink your Emacs or Info window.) -Then come back, with Spaces. - - If your screen is very tall, all of this node might fit at once. -In that case, "b" won't do anything. Sorry; what can we do? - - You have just learned a considerable number of commands. If you -want to use one but have trouble remembering which, you should type -a @key{?} which prints out a brief list of commands. When you are -finished looking at the list, make it go away by typing a @key{SPC}. - ->> Type a @key{?} now. After it finishes, type a @key{SPC}. - - (If you are using the standalone Info reader, type `l' to return here.) - - From now on, you will encounter large nodes without warning, and -will be expected to know how to use Space and Delete to move -around in them without being told. Since not all terminals have -the same size screen, it would be impossible to warn you anyway. - ->> Now type @kbd{n} to see the description of the @kbd{m} command. - -@node Help-M, Help-Adv, Help-^L, Getting Started -@comment node-name, next, previous, up -@section Menus - -Menus and the @kbd{m} command - - With only the @kbd{n} and @kbd{p} commands for moving between nodes, nodes -are restricted to a linear sequence. Menus allow a branching -structure. A menu is a list of other nodes you can move to. It is -actually just part of the text of the node formatted specially so that -Info can interpret it. The beginning of a menu is always identified -by a line which starts with @samp{* Menu:}. A node contains a menu if and -only if it has a line in it which starts that way. The only menu you -can use at any moment is the one in the node you are in. To use a -menu in any other node, you must move to that node first. - - After the start of the menu, each line that starts with a @samp{*} -identifies one subtopic. The line usually contains a brief name -for the subtopic (followed by a @samp{:}), the name of the node that talks -about that subtopic, and optionally some further description of the -subtopic. Lines in the menu that do not start with a @samp{*} have no -special meaning---they are only for the human reader's benefit and do -not define additional subtopics. Here is an example: - -@example -* Foo: FOO's Node This tells about FOO -@end example - -The subtopic name is Foo, and the node describing it is @samp{FOO's Node}. -The rest of the line is just for the reader's Information. -[[ But this line is not a real menu item, simply because there is -no line above it which starts with @samp{* Menu:}.]] - - When you use a menu to go to another node (in a way that will be -described soon), what you specify is the subtopic name, the first -thing in the menu line. Info uses it to find the menu line, extracts -the node name from it, and goes to that node. The reason that there -is both a subtopic name and a node name is that the node name must be -meaningful to the computer and may therefore have to be ugly looking. -The subtopic name can be chosen just to be convenient for the user to -specify. Often the node name is convenient for the user to specify -and so both it and the subtopic name are the same. There is an -abbreviation for this: - -@example -* Foo:: This tells about FOO -@end example - -@noindent -This means that the subtopic name and node name are the same; they are -both @samp{Foo}. - ->> Now use Spaces to find the menu in this node, then come back to - the front with a @kbd{b} and some Spaces. As you see, a menu is - actually visible in its node. If you cannot find a menu in a node - by looking at it, then the node does not have a menu and the - @kbd{m} command is not available. - - The command to go to one of the subnodes is @kbd{m}---but @emph{do -not do it yet!} Before you use @kbd{m}, you must understand the -difference between commands and arguments. So far, you have learned -several commands that do not need arguments. When you type one, Info -processes it and is instantly ready for another command. The @kbd{m} -command is different: it is incomplete without the @dfn{name of the -subtopic}. Once you have typed @kbd{m}, Info tries to read the -subtopic name. - - Now look for the line containing many dashes near the bottom of the -screen. There is one more line beneath that one, but usually it is -blank. If it is empty, Info is ready for a command, such as @kbd{n} -or @kbd{b} or Space or @kbd{m}. If that line contains text ending -in a colon, it mean Info is trying to read the @dfn{argument} to a -command. At such times, commands do not work, because Info tries to -use them as the argument. You must either type the argument and -finish the command you started, or type @kbd{Control-g} to cancel the -command. When you have done one of those things, the line becomes -blank again. - - The command to go to a subnode via a menu is @kbd{m}. After you type -the @kbd{m}, the line at the bottom of the screen says @samp{Menu item: }. -You must then type the name of the subtopic you want, and end it with -a @key{RET}. - - You can abbreviate the subtopic name. If the abbreviation is not -unique, the first matching subtopic is chosen. Some menus put -the shortest possible abbreviation for each subtopic name in capital -letters, so you can see how much you need to type. It does not -matter whether you use upper case or lower case when you type the -subtopic. You should not put any spaces at the end, or inside of the -item name, except for one space where a space appears in the item in -the menu. - - You can also use the @dfn{completion} feature to help enter the subtopic -name. If you type the Tab key after entering part of a name, it will -magically fill in more of the name---as much as follows uniquely from -what you have entered. - - If you move the cursor to one of the menu subtopic lines, then you do -not need to type the argument: you just type a Return, and it stands for -the subtopic of the line you are on. - -Here is a menu to give you a chance to practice. - -* Menu: The menu starts here. - -This menu gives you three ways of going to one place, Help-FOO. - -* Foo: Help-FOO. A node you can visit for fun.@* -* Bar: Help-FOO. Strange! two ways to get to the same place.@* -* Help-FOO:: And yet another!@* - - ->> Now type just an @kbd{m} and see what happens: - - Now you are ``inside'' an @kbd{m} command. Commands cannot be used -now; the next thing you will type must be the name of a subtopic. - - You can change your mind about doing the @kbd{m} by typing Control-g. - ->> Try that now; notice the bottom line clear. - ->> Then type another @kbd{m}. - ->> Now type @samp{BAR} item name. Do not type Return yet. - - While you are typing the item name, you can use the Delete key to -cancel one character at a time if you make a mistake. - ->> Type one to cancel the @samp{R}. You could type another @samp{R} to - replace it. You do not have to, since @samp{BA} is a valid abbreviation. - ->> Now you are ready to go. Type a @key{RET}. - - After visiting Help-FOO, you should return here. - ->> Type @kbd{n} to see more commands. - -@c If a menu appears at the end of this node, remove it. -@c It is an accident of the menu updating command. - -Here is another way to get to Help-FOO, a menu. You can ignore this -if you want, or else try it (but then please come back to here). - -@menu -* Help-FOO:: -@end menu - -@node Help-FOO, , , Help-M -@comment node-name, next, previous, up -@subsection The @kbd{u} command - - Congratulations! This is the node @samp{Help-FOO}. Unlike the other -nodes you have seen, this one has an @samp{Up}: @samp{Help-M}, the node you -just came from via the @kbd{m} command. This is the usual -convention---the nodes you reach from a menu have @samp{Up} nodes that lead -back to the menu. Menus move Down in the tree, and @samp{Up} moves Up. -@samp{Previous}, on the other hand, is usually used to ``stay on the same -level but go backwards'' - - You can go back to the node @samp{Help-M} by typing the command -@kbd{u} for ``Up''. That puts you at the @emph{front} of the -node---to get back to where you were reading you have to type -some @key{SPC}s. - ->> Now type @kbd{u} to move back up to @samp{Help-M}. - -@node Help-Adv, Help-Q, Help-M, Getting Started -@comment node-name, next, previous, up -@section Some advanced Info commands - - The course is almost over, so please stick with it to the end. - - If you have been moving around to different nodes and wish to -retrace your steps, the @kbd{l} command (@kbd{l} for @dfn{last}) will -do that, one node-step at a time. As you move from node to node, Info -records the nodes where you have been in a special history list. The -@kbd{l} command revisits nodes in the history list; each successive -@kbd{l} command moves one step back through the history. - - If you have been following directions, ad @kbd{l} command now will get -you back to @samp{Help-M}. Another @kbd{l} command would undo the -@kbd{u} and get you back to @samp{Help-FOO}. Another @kbd{l} would undo -the @kbd{m} and get you back to @samp{Help-M}. - ->> Try typing three @kbd{l}'s, pausing in between to see what each - @kbd{l} does. - -Then follow directions again and you will end up back here. - - Note the difference between @kbd{l} and @kbd{p}: @kbd{l} moves to -where @emph{you} last were, whereas @kbd{p} always moves to the node -which the header says is the @samp{Previous} node (from this node, to -@samp{Help-M}). - - The @samp{d} command gets you instantly to the Directory node. -This node, which is the first one you saw when you entered Info, -has a menu which leads (directly, or indirectly through other menus), -to all the nodes that exist. - ->> Try doing a @samp{d}, then do an @kbd{l} to return here (yes, - @emph{do} return). - - Sometimes, in Info documentation, you will see a cross reference. -Cross references look like this: @xref{Help-Cross, Cross}. That is a -real, live cross reference which is named @samp{Cross} and points at -the node named @samp{Help-Cross}. - - If you wish to follow a cross reference, you must use the @samp{f} -command. The @samp{f} must be followed by the cross reference name -(in this case, @samp{Cross}). While you enter the name, you can use the -Delete key to edit your input. If you change your mind about following -any reference, you can use @kbd{Control-g} to cancel the command. - - Completion is available in the @samp{f} command; you can complete among -all the cross reference names in the current node by typing a Tab. - ->> Type @samp{f}, followed by @samp{Cross}, and a @key{RET}. - - To get a list of all the cross references in the current node, you can -type @kbd{?} after an @samp{f}. The @samp{f} continues to await a -cross reference name even after printing the list, so if you don't -actually want to follow a reference, you should type a @kbd{Control-g} -to cancel the @samp{f}. - ->> Type "f?" to get a list of the cross references in this node. Then - type a @kbd{Control-g} and see how the @samp{f} gives up. - ->> Now type @kbd{n} to see the last node of the course. - -@c If a menu appears at the end of this node, remove it. -@c It is an accident of the menu updating command. - -@node Help-Cross, , , Help-Adv -@comment node-name, next, previous, up -@unnumberedsubsec The node reached by the cross reference in Info - - This is the node reached by the cross reference named @samp{Cross}. - - While this node is specifically intended to be reached by a cross -reference, most cross references lead to nodes that ``belong'' -someplace else far away in the structure of Info. So you cannot expect -the footnote to have a @samp{Next}, @samp{Previous} or @samp{Up} pointing back to -where you came from. In general, the @kbd{l} (el) command is the only -way to get back there. - ->> Type @kbd{l} to return to the node where the cross reference was. - -@node Help-Q, , Help-Adv, Getting Started -@comment node-name, next, previous, up -@section Quitting Info - - To get out of Info, back to what you were doing before, type @kbd{q} -for @dfn{Quit}. - - This is the end of the course on using Info. There are some other -commands that are meant for experienced users; they are useful, and you -can find them by looking in the directory node for documentation on -Info. Finding them will be a good exercise in using Info in the usual -manner. - ->> Type @samp{d} to go to the Info directory node; then type - @samp{mInfo} and Return, to get to the node about Info and - see what other help is available. - -@node Advanced Info, Create an Info File, Getting Started, Top -@comment node-name, next, previous, up -@chapter Info for Experts - -This chapter describes various advanced Info commands, and how to write -an Info as distinct from a Texinfo file. (However, in most cases, writing a -Texinfo file is better, since you can use it @emph{both} to generate an -Info file and to make a printed manual. @xref{Top,, Overview of -Texinfo, texinfo, Texinfo: The GNU Documentation Format}.) - -@menu -* Expert:: Advanced Info commands: g, s, e, and 1 - 5. -* Add:: Describes how to add new nodes to the hierarchy. - Also tells what nodes look like. -* Menus:: How to add to or create menus in Info nodes. -* Cross-refs:: How to add cross-references to Info nodes. -* Tags:: How to make tag tables for Info files. -* Checking:: Checking an Info File -* Emacs Info Variables:: Variables modifying the behavior of Emacs Info. -@end menu - -@node Expert, Add, , Advanced Info -@comment node-name, next, previous, up -@section Advanced Info Commands - -@kbd{g}, @kbd{s}, @kbd{1}, -- @kbd{9}, and @kbd{e} - -If you know a node's name, you can go there by typing @kbd{g}, the -name, and @key{RET}. Thus, @kbd{gTop@key{RET}} would go to the node -called @samp{Top} in this file (its directory node). -@kbd{gExpert@key{RET}} would come back here. - -Unlike @kbd{m}, @kbd{g} does not allow the use of abbreviations. - -To go to a node in another file, you can include the filename in the -node name by putting it at the front, in parentheses. Thus, -@kbd{g(dir)Top@key{RET}} would go to the Info Directory node, which is -node @samp{Top} in the file @file{dir}. - -The node name @samp{*} specifies the whole file. So you can look at -all of the current file by typing @kbd{g*@key{RET}} or all of any -other file with @kbd{g(FILENAME)@key{RET}}. - -The @kbd{s} command allows you to search a whole file for a string. -It switches to the next node if and when that is necessary. You -type @kbd{s} followed by the string to search for, terminated by -@key{RET}. To search for the same string again, just @kbd{s} followed -by @key{RET} will do. The file's nodes are scanned in the order -they are in in the file, which has no necessary relationship to the -order that they may be in in the tree structure of menus and @samp{next} pointers. -But normally the two orders are not very different. In any case, -you can always do a @kbd{b} to find out what node you have reached, if -the header is not visible (this can happen, because @kbd{s} puts your -cursor at the occurrence of the string, not at the beginning of the -node). - -If you grudge the system each character of type-in it requires, you -might like to use the commands @kbd{1}, @kbd{2}, @kbd{3}, @kbd{4}, ... -@kbd{9}. They are short for the @kbd{m} command together with an -argument. @kbd{1} goes through the first item in the current node's -menu; @kbd{2} goes through the second item, etc. - -If you display supports multiple fonts, and you are using Emacs' Info -mode to read Info files, the @samp{*} for the fifth menu item is -underlines, and so is the @samp{*} for the ninth item; these underlines -make it easy to see at a glance which number to use for an item. - -On ordinary terminals, you won't have underlining. If you need to -actually count items, it is better to use @kbd{m} instead, and specify -the name. - -The Info command @kbd{e} changes from Info mode to an ordinary -Emacs editing mode, so that you can edit the text of the current node. -Type @kbd{C-c C-c} to switch back to Info. The @kbd{e} command is allowed -only if the variable @code{Info-enable-edit} is non-@code{nil}. - -@node Add, Menus, Expert, Advanced Info -@comment node-name, next, previous, up -@section Adding a new node to Info - -To add a new topic to the list in the Info directory, you must: -@enumerate -@item -Create some nodes, in some file, to document that topic. -@item -Put that topic in the menu in the directory. @xref{Menus, Menu}. -@end enumerate - -Usually, the way to create the nodes is with Texinfo @pxref{Top,, Overview of -Texinfo, texinfo, Texinfo: The GNU Documentation Format}); this has the -advantage that you can also make a printed manual from them. However, -if hyou want to edit an Info file, here is how. - - The new node can live in an existing documentation file, or in a new -one. It must have a @key{^_} character before it (invisible to the -user; this node has one but you cannot see it), and it ends with either -a @key{^_}, a @key{^L}, or the end of file. Note: If you put in a -@key{^L} to end a new node, be sure that there is a @key{^_} after it -to start the next one, since @key{^L} cannot @emph{start} a node. -Also, a nicer way to make a node boundary be a page boundary as well -is to put a @key{^L} @emph{right after} the @key{^_}. - - The @key{^_} starting a node must be followed by a newline or a -@key{^L} newline, after which comes the node's header line. The -header line must give the node's name (by which Info finds it), -and state the names of the @samp{Next}, @samp{Previous}, and @samp{Up} nodes (if -there are any). As you can see, this node's @samp{Up} node is the node -@samp{Top}, which points at all the documentation for Info. The @samp{Next} -node is @samp{Menus}. - - The keywords @dfn{Node}, @dfn{Previous}, @dfn{Up}, and @dfn{Next}, -may appear in any order, anywhere in the header line, but the -recommended order is the one in this sentence. Each keyword must be -followed by a colon, spaces and tabs, and then the appropriate name. -The name may be terminated with a tab, a comma, or a newline. A space -does not end it; node names may contain spaces. The case of letters -in the names is insignificant. - - A node name has two forms. A node in the current file is named by -what appears after the @samp{Node: } in that node's first line. For -example, this node's name is @samp{Add}. A node in another file is -named by @samp{(@var{filename})@var{node-within-file}}, as in -@samp{(info)Add} for this node. If the file name starts with ``./'', -then it is relative to the current directory; otherwise, it is relative -starting from the standard Info file directory of your site. -The name @samp{(@var{filename})Top} can be abbreviated to just -@samp{(@var{filename})}. By convention, the name @samp{Top} is used for -the ``highest'' node in any single file---the node whose @samp{Up} points -out of the file. The Directory node is @file{(dir)}. The @samp{Top} node -of a document file listed in the Directory should have an @samp{Up: -(dir)} in it. - - The node name @kbd{*} is special: it refers to the entire file. -Thus, @kbd{g*} shows you the whole current file. The use of the -node @kbd{*} is to make it possible to make old-fashioned, -unstructured files into nodes of the tree. - - The @samp{Node:} name, in which a node states its own name, must not -contain a filename, since Info when searching for a node does not -expect one to be there. The @samp{Next}, @samp{Previous} and @samp{Up} names may -contain them. In this node, since the @samp{Up} node is in the same file, -it was not necessary to use one. - - Note that the nodes in this file have a file name in the header -line. The file names are ignored by Info, but they serve as comments -to help identify the node for the user. - -@node Menus, Cross-refs, Add, Advanced Info -@comment node-name, next, previous, up -@section How to Create Menus - - Any node in the Info hierarchy may have a @dfn{menu}---a list of subnodes. -The @kbd{m} command searches the current node's menu for the topic which it -reads from the terminal. - - A menu begins with a line starting with @samp{* Menu:}. The rest of the -line is a comment. After the starting line, every line that begins -with a @samp{* } lists a single topic. The name of the topic--the -argument that the user must give to the @kbd{m} command to select this -topic---comes right after the star and space, and is followed by a -colon, spaces and tabs, and the name of the node which discusses that -topic. The node name, like node names following @samp{Next}, @samp{Previous} -and @samp{Up}, may be terminated with a tab, comma, or newline; it may also -be terminated with a period. - - If the node name and topic name are the same, then rather than -giving the name twice, the abbreviation @samp{* NAME::} may be used -(and should be used, whenever possible, as it reduces the visual -clutter in the menu). - - It is considerate to choose the topic names so that they differ -from each other very near the beginning---this allows the user to type -short abbreviations. In a long menu, it is a good idea to capitalize -the beginning of each item name which is the minimum acceptable -abbreviation for it (a long menu is more than 5 or so entries). - - The nodes listed in a node's menu are called its ``subnodes'', and -it is their ``superior''. They should each have an @samp{Up:} pointing at -the superior. It is often useful to arrange all or most of the -subnodes in a sequence of @samp{Next} and @samp{Previous} pointers so that someone who -wants to see them all need not keep revisiting the Menu. - - The Info Directory is simply the menu of the node @samp{(dir)Top}---that -is, node @samp{Top} in file @file{.../info/dir}. You can put new entries -in that menu just like any other menu. The Info Directory is @emph{not} the -same as the file directory called @file{info}. It happens that many of -Info's files live on that file directory, but they do not have to; and -files on that directory are not automatically listed in the Info -Directory node. - - Also, although the Info node graph is claimed to be a ``hierarchy'', -in fact it can be @emph{any} directed graph. Shared structures and -pointer cycles are perfectly possible, and can be used if they are -appropriate to the meaning to be expressed. There is no need for all -the nodes in a file to form a connected structure. In fact, this file -has two connected components. You are in one of them, which is under -the node @samp{Top}; the other contains the node @samp{Help} which the -@kbd{h} command goes to. In fact, since there is no garbage -collector, nothing terrible happens if a substructure is not pointed -to, but such a substructure is rather useless since nobody can -ever find out that it exists. - -@node Cross-refs, Tags, Menus, Advanced Info -@comment node-name, next, previous, up -@section Creating Cross References - - A cross reference can be placed anywhere in the text, unlike a menu -item which must go at the front of a line. A cross reference looks -like a menu item except that it has @samp{*note} instead of @kbd{*}. -It @emph{cannot} be terminated by a @samp{)}, because @samp{)}'s are -so often part of node names. If you wish to enclose a cross reference -in parentheses, terminate it with a period first. Here are two -examples of cross references pointers: - -@example -*Note details: commands. (See *note 3: Full Proof.) -@end example - -They are just examples. The places they ``lead to'' do not really exist! - -@node Tags, Checking, Cross-refs, Advanced Info -@comment node-name, next, previous, up -@section Tag Tables for Info Files - - You can speed up the access to nodes of a large Info file by giving -it a tag table. Unlike the tag table for a program, the tag table for -an Info file lives inside the file itself and is used -automatically whenever Info reads in the file. - - To make a tag table, go to a node in the file using Emacs Info mode and type -@kbd{M-x Info-tagify}. Then you must use @kbd{C-x C-s} to save the -file. - - Once the Info file has a tag table, you must make certain it is up -to date. If, as a result of deletion of text, any node moves back -more than a thousand characters in the file from the position -recorded in the tag table, Info will no longer be able to find that -node. To update the tag table, use the @code{Info-tagify} command again. - - An Info file tag table appears at the end of the file and looks like -this: - -@example -^_ -Tag Table: -File: info, Node: Cross-refs^?21419 -File: info, Node: Tags^?22145 -^_ -End Tag Table -@end example - -@noindent -Note that it contains one line per node, and this line contains -the beginning of the node's header (ending just after the node name), -a Delete character, and the character position in the file of the -beginning of the node. - -@node Checking, Emacs Info Variables, Tags, Advanced Info -@comment node-name, next, previous, up -@section Checking an Info File - - When creating an Info file, it is easy to forget the name of a node -when you are making a pointer to it from another node. If you put in -the wrong name for a node, this is not detected until someone -tries to go through the pointer using Info. Verification of the Info -file is an automatic process which checks all pointers to nodes and -reports any pointers which are invalid. Every @samp{Next}, @samp{Previous}, and -@samp{Up} is checked, as is every menu item and every cross reference. In -addition, any @samp{Next} which does not have a @samp{Previous} pointing back is -reported. Only pointers within the file are checked, because checking -pointers to other files would be terribly slow. But those are usually -few. - - To check an Info file, do @kbd{M-x Info-validate} while looking at -any node of the file with Emacs Info mode. - -@node Emacs Info Variables, , Checking, Advanced Info -@section Emacs Info-mode Variables - -The following variables may modify the behaviour of Info-mode in Emacs; -you may wish to set one or several of these variables interactively, or -in your @file{~/.emacs} init file. @xref{Examining, Examining and Setting -Variables, Examining and Setting Variables, emacs, The GNU Emacs -Manual}. - -@vtable @code -@item Info-enable-edit -Set to @code{nil}, disables the @samp{e} (@code{Info-edit}) command. A -non-@code{nil} value enables it. @xref{Add, Edit}. - -@item Info-enable-active-nodes -When set to a non-@code{nil} value, allows Info to execute Lisp code -associated with nodes. The Lisp code is executed when the node is -selected. - -@item Info-directory-list -The list of directories to search for Info files. Each element is a -string (directory name) or @code{nil} (try default directory). - -@item Info-directory -The standard directory for Info documentation files. Only used when the -function @code{Info-directory} is called. -@end vtable - -@node Create an Info File, , Advanced Info, Top -@comment node-name, next, previous, up -@chapter Creating an Info File from a Makeinfo file - -@code{makeinfo} is a utility that converts a Texinfo file into an Info -file; @code{texinfo-format-region} and @code{texinfo-format-buffer} are -GNU Emacs functions that do the same. - -@xref{Create an Info File, , Creating an Info File, texinfo, the Texinfo -Manual}, to learn how to create an Info file from a Texinfo file. - -@xref{Top,, Overview of Texinfo, texinfo, Texinfo: The GNU Documentation -Format}, to learn how to write a Texinfo file. - -@bye diff --git a/info/infodoc.c b/info/infodoc.c deleted file mode 100644 --- a/info/infodoc.c +++ /dev/null @@ -1,771 +0,0 @@ -/* infodoc.c -- Functions which build documentation nodes. */ - -/* 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" - -/* Normally we do not define HELP_NODE_GETS_REGENERATED because the - contents of the help node currently can never change once an info - session has been started. You should consider defining this in - the case that you place information about dynamic variables in the - help text. When that happens, the contents of the help node will - change dependent on the value of those variables, and the user will - expect to see those changes. */ -/* #define HELP_NODE_GETS_REGENERATED 1 */ - -/* **************************************************************** */ -/* */ -/* Info Help Windows */ -/* */ -/* **************************************************************** */ - -/* The name of the node used in the help window. */ -static char *info_help_nodename = "*Info Help*"; - -/* A node containing printed key bindings and their documentation. */ -static NODE *internal_info_help_node = (NODE *)NULL; - -/* A pointer to the contents of the help node. */ -static char *internal_info_help_node_contents = (char *)NULL; - -/* The static text which appears in the internal info help node. */ -static char *info_internal_help_text[] = { - "Basic Commands in Info Windows", - "******************************", - "", - " h Invoke the Info tutorial.", - "", - "Selecting other nodes:", - "----------------------", - " n Move to the \"next\" node of this node.", - " p Move to the \"previous\" node of this node.", - " u Move \"up\" from this node.", - " m Pick menu item specified by name.", - " Picking a menu item causes another node to be selected.", - " f Follow a cross reference. Reads name of reference.", - " l Move to the last node seen in this window.", - " d Move to the `directory' node. Equivalent to `g(DIR)'.", - "", - "Moving within a node:", - "---------------------", - " SPC Scroll forward a page.", - " DEL Scroll backward a page.", - " b Go to the beginning of this node.", - " e Go to the end of this node.", - "", - "\"Advanced\" commands:", - "--------------------", - " q Quit Info.", - " 1 Pick first item in node's menu.", - " 2-9 Pick second ... ninth item in node's menu.", - " 0 Pick last item in node's menu.", - " g Move to node specified by name.", - " You may include a filename as well, as in (FILENAME)NODENAME.", - " s Search through this Info file for a specified string,", - " and select the node in which the next occurrence is found.", - (char *)NULL -}; - -static char *where_is (), *where_is_internal (); - -void -dump_map_to_message_buffer (prefix, map) - char *prefix; - Keymap map; -{ - register int i; - - for (i = 0; i < 256; i++) - { - if (map[i].type == ISKMAP) - { - char *new_prefix, *keyname; - - keyname = pretty_keyname (i); - new_prefix = (char *) - xmalloc (3 + strlen (prefix) + strlen (keyname)); - sprintf (new_prefix, "%s%s%s ", prefix, *prefix ? " " : "", keyname); - - dump_map_to_message_buffer (new_prefix, (Keymap)map[i].function); - free (new_prefix); - } - else if (map[i].function) - { - register int last; - char *doc, *name; - - doc = function_documentation (map[i].function); - name = function_name (map[i].function); - - if (!*doc) - continue; - - /* Find out if there is a series of identical functions, as in - ea_insert (). */ - for (last = i + 1; last < 256; last++) - if ((map[last].type != ISFUNC) || - (map[last].function != map[i].function)) - break; - - if (last - 1 != i) - { - printf_to_message_buffer - ("%s%s .. ", prefix, pretty_keyname (i)); - printf_to_message_buffer - ("%s%s\t", prefix, pretty_keyname (last - 1)); - i = last - 1; - } - else - printf_to_message_buffer ("%s%s\t", prefix, pretty_keyname (i)); - -#if defined (NAMED_FUNCTIONS) - /* Print the name of the function, and some padding before the - documentation string is printed. */ - { - int length_so_far; - int desired_doc_start = 40; /* Must be multiple of 8. */ - - printf_to_message_buffer ("(%s)", name); - length_so_far = message_buffer_length_this_line (); - - if ((desired_doc_start + strlen (doc)) >= the_screen->width) - printf_to_message_buffer ("\n "); - else - { - while (length_so_far < desired_doc_start) - { - printf_to_message_buffer ("\t"); - length_so_far += character_width ('\t', length_so_far); - } - } - } -#endif /* NAMED_FUNCTIONS */ - printf_to_message_buffer ("%s\n", doc); - } - } -} - -/* How to create internal_info_help_node. */ -static void -create_internal_info_help_node () -{ - register int i; - char *contents = (char *)NULL; - NODE *node; - -#if !defined (HELP_NODE_GETS_REGENERATED) - if (internal_info_help_node_contents) - contents = internal_info_help_node_contents; -#endif /* !HELP_NODE_GETS_REGENERATED */ - - if (!contents) - { - int printed_one_mx = 0; - - initialize_message_buffer (); - - for (i = 0; info_internal_help_text[i]; i++) - printf_to_message_buffer ("%s\n", info_internal_help_text[i]); - - printf_to_message_buffer ("---------------------\n\n"); - printf_to_message_buffer ("The current search path is:\n"); - printf_to_message_buffer (" \"%s\"\n", infopath); - printf_to_message_buffer ("---------------------\n\n"); - printf_to_message_buffer ("Commands available in Info windows:\n\n"); - dump_map_to_message_buffer ("", info_keymap); - printf_to_message_buffer ("---------------------\n\n"); - printf_to_message_buffer ("Commands available in the echo area:\n\n"); - dump_map_to_message_buffer ("", echo_area_keymap); - -#if defined (NAMED_FUNCTIONS) - /* Get a list of the M-x commands which have no keystroke equivs. */ - for (i = 0; function_doc_array[i].func; i++) - { - VFunction *func = function_doc_array[i].func; - - if ((!where_is_internal (info_keymap, func)) && - (!where_is_internal (echo_area_keymap, func))) - { - if (!printed_one_mx) - { - printf_to_message_buffer ("---------------------\n\n"); - printf_to_message_buffer - ("The following commands can only be invoked via M-x:\n\n"); - printed_one_mx = 1; - } - - printf_to_message_buffer - ("M-x %s\n %s\n", - function_doc_array[i].func_name, - replace_in_documentation (function_doc_array[i].doc)); - } - } - - if (printed_one_mx) - printf_to_message_buffer ("\n"); -#endif /* NAMED_FUNCTIONS */ - - printf_to_message_buffer - ("%s", replace_in_documentation - ("--- Use `\\[history-node]' or `\\[kill-node]' to exit ---\n")); - node = message_buffer_to_node (); - internal_info_help_node_contents = node->contents; - } - else - { - /* We already had the right contents, so simply use them. */ - node = build_message_node ("", 0, 0); - free (node->contents); - node->contents = contents; - node->nodelen = 1 + strlen (contents); - } - - internal_info_help_node = node; - - /* Do not GC this node's contents. It never changes, and we never need - to delete it once it is made. If you change some things (such as - placing information about dynamic variables in the help text) then - you will need to allow the contents to be gc'd, and you will have to - arrange to always regenerate the help node. */ -#if defined (HELP_NODE_GETS_REGENERATED) - add_gcable_pointer (internal_info_help_node->contents); -#endif - - name_internal_node (internal_info_help_node, info_help_nodename); - - /* Even though this is an internal node, we don't want the window - system to treat it specially. So we turn off the internalness - of it here. */ - internal_info_help_node->flags &= ~N_IsInternal; -} - -/* Return a window which is the window showing help in this Info. */ -static WINDOW * -info_find_or_create_help_window () -{ - WINDOW *help_window, *eligible, *window; - - eligible = (WINDOW *)NULL; - help_window = get_internal_info_window (info_help_nodename); - - /* If we couldn't find the help window, then make it. */ - if (!help_window) - { - int max = 0; - - for (window = windows; window; window = window->next) - { - if (window->height > max) - { - max = window->height; - eligible = window; - } - } - - if (!eligible) - return ((WINDOW *)NULL); - } -#if !defined (HELP_NODE_GETS_REGENERATED) - else - return (help_window); -#endif /* !HELP_NODE_GETS_REGENERATED */ - - /* Make sure that we have a node containing the help text. */ - create_internal_info_help_node (); - - /* Either use the existing window to display the help node, or create - a new window if there was no existing help window. */ - if (!help_window) - { - /* Split the largest window into 2 windows, and show the help text - in that window. */ - if (eligible->height > 30) - { - active_window = eligible; - help_window = window_make_window (internal_info_help_node); - } - else - { - set_remembered_pagetop_and_point (active_window); - window_set_node_of_window (active_window, internal_info_help_node); - help_window = active_window; - } - } - else - { - /* Case where help node always gets regenerated, and we have an - existing window in which to place the node. */ - if (active_window != help_window) - { - set_remembered_pagetop_and_point (active_window); - active_window = help_window; - } - window_set_node_of_window (active_window, internal_info_help_node); - } - remember_window_and_node (help_window, help_window->node); - return (help_window); -} - -/* Create or move to the help window. */ -DECLARE_INFO_COMMAND (info_get_help_window, "Display help message") -{ - WINDOW *help_window; - - help_window = info_find_or_create_help_window (); - if (help_window) - { - active_window = help_window; - active_window->flags |= W_UpdateWindow; - } - else - { - info_error (CANT_MAKE_HELP); - } -} - -/* Show the Info help node. This means that the "info" file is installed - where it can easily be found on your system. */ -DECLARE_INFO_COMMAND (info_get_info_help_node, "Visit Info node `(info)Help'") -{ - NODE *node; - char *nodename; - - /* If there is a window on the screen showing the node "(info)Help" or - the node "(info)Help-Small-Screen", simply select that window. */ - { - WINDOW *win; - - for (win = windows; win; win = win->next) - { - if (win->node && win->node->filename && - (strcasecmp - (filename_non_directory (win->node->filename), "info") == 0) && - ((strcmp (win->node->nodename, "Help") == 0) || - (strcmp (win->node->nodename, "Help-Small-Screen") == 0))) - { - active_window = win; - return; - } - } - } - - /* If the current window is small, show the small screen help. */ - if (active_window->height < 24) - nodename = "Help-Small-Screen"; - else - nodename = "Help"; - - /* Try to get the info file for Info. */ - node = info_get_node ("Info", nodename); - - if (!node) - { - if (info_recent_file_error) - info_error (info_recent_file_error); - else - info_error (CANT_FILE_NODE, "Info", nodename); - } - else - { - /* If the current window is very large (greater than 45 lines), - then split it and show the help node in another window. - Otherwise, use the current window. */ - - if (active_window->height > 45) - active_window = window_make_window (node); - else - { - set_remembered_pagetop_and_point (active_window); - window_set_node_of_window (active_window, node); - } - - remember_window_and_node (active_window, node); - } -} - -/* **************************************************************** */ -/* */ -/* Groveling Info Keymaps and Docs */ -/* */ -/* **************************************************************** */ - -/* Return the documentation associated with the Info command FUNCTION. */ -char * -function_documentation (function) - VFunction *function; -{ - register int i; - - for (i = 0; function_doc_array[i].func; i++) - if (function == function_doc_array[i].func) - break; - - return (replace_in_documentation (function_doc_array[i].doc)); -} - -#if defined (NAMED_FUNCTIONS) -/* Return the user-visible name of the function associated with the - Info command FUNCTION. */ -char * -function_name (function) - - VFunction *function; -{ - register int i; - - for (i = 0; function_doc_array[i].func; i++) - if (function == function_doc_array[i].func) - break; - - return (function_doc_array[i].func_name); -} - -/* Return a pointer to the function named NAME. */ -VFunction * -named_function (name) - char *name; -{ - register int i; - - for (i = 0; function_doc_array[i].func; i++) - if (strcmp (function_doc_array[i].func_name, name) == 0) - break; - - return (function_doc_array[i].func); -} -#endif /* NAMED_FUNCTIONS */ - -/* Return the documentation associated with KEY in MAP. */ -char * -key_documentation (key, map) - char key; - Keymap map; -{ - VFunction *function = map[key].function; - - if (function) - return (function_documentation (function)); - else - return ((char *)NULL); -} - -DECLARE_INFO_COMMAND (describe_key, "Print documentation for KEY") -{ - char keyname[50]; - int keyname_index = 0; - unsigned char keystroke; - char *rep; - Keymap map; - - keyname[0] = '\0'; - map = window->keymap; - - while (1) - { - message_in_echo_area ("Describe key: %s", keyname); - keystroke = info_get_input_char (); - unmessage_in_echo_area (); - - if (Meta_p (keystroke) && (!ISO_Latin_p || key < 160)) - { - if (map[ESC].type != ISKMAP) - { - window_message_in_echo_area - ("ESC %s is undefined.", pretty_keyname (UnMeta (keystroke))); - return; - } - - strcpy (keyname + keyname_index, "ESC "); - keyname_index = strlen (keyname); - keystroke = UnMeta (keystroke); - map = (Keymap)map[ESC].function; - } - - /* Add the printed representation of KEYSTROKE to our keyname. */ - rep = pretty_keyname (keystroke); - strcpy (keyname + keyname_index, rep); - keyname_index = strlen (keyname); - - if (map[keystroke].function == (VFunction *)NULL) - { - message_in_echo_area ("%s is undefined.", keyname); - return; - } - else if (map[keystroke].type == ISKMAP) - { - map = (Keymap)map[keystroke].function; - strcat (keyname, " "); - keyname_index = strlen (keyname); - continue; - } - else - { - char *message, *fundoc, *funname = ""; - -#if defined (NAMED_FUNCTIONS) - funname = function_name (map[keystroke].function); -#endif /* NAMED_FUNCTIONS */ - - fundoc = function_documentation (map[keystroke].function); - - message = (char *)xmalloc - (10 + strlen (keyname) + strlen (fundoc) + strlen (funname)); - -#if defined (NAMED_FUNCTIONS) - sprintf (message, "%s (%s): %s.", keyname, funname, fundoc); -#else - sprintf (message, "%s is defined to %s.", keyname, fundoc); -#endif /* !NAMED_FUNCTIONS */ - - window_message_in_echo_area ("%s", message); - free (message); - break; - } - } -} - -/* How to get the pretty printable name of a character. */ -static char rep_buffer[30]; - -char * -pretty_keyname (key) - unsigned char key; -{ - char *rep; - - if (Meta_p (key)) - { - char temp[20]; - - rep = pretty_keyname (UnMeta (key)); - - sprintf (temp, "ESC %s", rep); - strcpy (rep_buffer, temp); - rep = rep_buffer; - } - else if (Control_p (key)) - { - switch (key) - { - case '\n': rep = "LFD"; break; - case '\t': rep = "TAB"; break; - case '\r': rep = "RET"; break; - case ESC: rep = "ESC"; break; - - default: - sprintf (rep_buffer, "C-%c", UnControl (key)); - rep = rep_buffer; - } - } - else - { - switch (key) - { - case ' ': rep = "SPC"; break; - case DEL: rep = "DEL"; break; - default: - rep_buffer[0] = key; - rep_buffer[1] = '\0'; - rep = rep_buffer; - } - } - return (rep); -} - -/* Replace the names of functions with the key that invokes them. */ -char * -replace_in_documentation (string) - char *string; -{ - register int i, start, next; - static char *result = (char *)NULL; - - maybe_free (result); - result = (char *)xmalloc (1 + strlen (string)); - - i = next = start = 0; - - /* Skip to the beginning of a replaceable function. */ - for (i = start; string[i]; i++) - { - /* Is this the start of a replaceable function name? */ - if (string[i] == '\\' && string[i + 1] == '[') - { - char *fun_name, *rep; - VFunction *function; - - /* Copy in the old text. */ - strncpy (result + next, string + start, i - start); - next += (i - start); - start = i + 2; - - /* Move to the end of the function name. */ - for (i = start; string[i] && (string[i] != ']'); i++); - - fun_name = (char *)xmalloc (1 + i - start); - strncpy (fun_name, string + start, i - start); - fun_name[i - start] = '\0'; - - /* Find a key which invokes this function in the info_keymap. */ - function = named_function (fun_name); - - /* If the internal documentation string fails, there is a - serious problem with the associated command's documentation. - We croak so that it can be fixed immediately. */ - if (!function) - abort (); - - rep = where_is (info_keymap, function); - strcpy (result + next, rep); - next = strlen (result); - - start = i; - if (string[i]) - start++; - } - } - strcpy (result + next, string + start); - return (result); -} - -/* Return a string of characters which could be typed from the keymap - MAP to invoke FUNCTION. */ -static char *where_is_rep = (char *)NULL; -static int where_is_rep_index = 0; -static int where_is_rep_size = 0; - -static char * -where_is (map, function) - Keymap map; - VFunction *function; -{ - char *rep; - - if (!where_is_rep_size) - where_is_rep = (char *)xmalloc (where_is_rep_size = 100); - where_is_rep_index = 0; - - rep = where_is_internal (map, function); - - /* If it couldn't be found, return "M-x Foo". */ - if (!rep) - { - char *name; - - name = function_name (function); - - if (name) - sprintf (where_is_rep, "M-x %s", name); - - rep = where_is_rep; - } - return (rep); -} - -/* Return the printed rep of FUNCTION as found in MAP, or NULL. */ -static char * -where_is_internal (map, function) - Keymap map; - VFunction *function; -{ - register int i; - - /* If the function is directly invokable in MAP, return the representation - of that keystroke. */ - for (i = 0; i < 256; i++) - if ((map[i].type == ISFUNC) && map[i].function == function) - { - sprintf (where_is_rep + where_is_rep_index, "%s", pretty_keyname (i)); - return (where_is_rep); - } - - /* Okay, search subsequent maps for this function. */ - for (i = 0; i < 256; i++) - { - if (map[i].type == ISKMAP) - { - int saved_index = where_is_rep_index; - char *rep; - - sprintf (where_is_rep + where_is_rep_index, "%s ", - pretty_keyname (i)); - - where_is_rep_index = strlen (where_is_rep); - rep = where_is_internal ((Keymap)map[i].function, function); - - if (rep) - return (where_is_rep); - - where_is_rep_index = saved_index; - } - } - - return ((char *)NULL); -} - -extern char *read_function_name (); - -DECLARE_INFO_COMMAND (info_where_is, - "Show what to type to execute a given command") -{ - char *command_name; - - command_name = read_function_name ("Where is command: ", window); - - if (!command_name) - { - info_abort_key (active_window, count, key); - return; - } - - if (*command_name) - { - VFunction *function; - - function = named_function (command_name); - - if (function) - { - char *location; - - location = where_is (active_window->keymap, function); - - if (!location) - { - info_error ("`%s' is not on any keys", command_name); - } - else - { - if (strncmp (location, "M-x ", 4) == 0) - window_message_in_echo_area - ("%s can only be invoked via %s.", command_name, location); - else - window_message_in_echo_area - ("%s can be invoked via %s.", command_name, location); - } - } - else - info_error ("There is no function named `%s'", command_name); - } - - free (command_name); -} diff --git a/info/infomap.c b/info/infomap.c deleted file mode 100644 --- a/info/infomap.c +++ /dev/null @@ -1,274 +0,0 @@ -/* infomap.c -- Keymaps for Info. */ - -/* 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 "stdio.h" -#include "ctype.h" -#include "infomap.h" -#include "funs.h" - -/* Return a new keymap which has all the uppercase letters mapped to run - the function info_do_lowercase_version (). */ -Keymap -keymap_make_keymap () -{ - register int i; - Keymap keymap; - - keymap = (Keymap)xmalloc (256 * sizeof (KEYMAP_ENTRY)); - - for (i = 0; i < 256; i++) - { - keymap[i].type = ISFUNC; - keymap[i].function = (VFunction *)NULL; - } - - for (i = 'A'; i < ('Z' + 1); i++) - { - keymap[i].type = ISFUNC; - keymap[i].function = info_do_lowercase_version; - } - - return (keymap); -} - -/* Return a new keymap which is a copy of MAP. */ -Keymap -keymap_copy_keymap (map) - Keymap map; -{ - register int i; - Keymap keymap; - - keymap = keymap_make_keymap (); - - for (i = 0; i < 256; i++) - { - keymap[i].type = map[i].type; - keymap[i].function = map[i].function; - } - return (keymap); -} - -/* Free the keymap and it's descendents. */ -void -keymap_discard_keymap (map) - Keymap (map); -{ - register int i; - - if (!map) - return; - - for (i = 0; i < 256; i++) - { - switch (map[i].type) - { - case ISFUNC: - break; - - case ISKMAP: - keymap_discard_keymap ((Keymap)map[i].function); - break; - - } - } -} - -/* Initialize the standard info keymaps. */ - -Keymap info_keymap = (Keymap)NULL; -Keymap echo_area_keymap = (Keymap)NULL; - -void -initialize_info_keymaps () -{ - register int i; - Keymap map; - - if (!info_keymap) - { - info_keymap = keymap_make_keymap (); - info_keymap[ESC].type = ISKMAP; - info_keymap[ESC].function = (VFunction *)keymap_make_keymap (); - info_keymap[Control ('x')].type = ISKMAP; - info_keymap[Control ('x')].function = (VFunction *)keymap_make_keymap (); - echo_area_keymap = keymap_make_keymap (); - echo_area_keymap[ESC].type = ISKMAP; - echo_area_keymap[ESC].function = (VFunction *)keymap_make_keymap (); - echo_area_keymap[Control ('x')].type = ISKMAP; - echo_area_keymap[Control ('x')].function = - (VFunction *)keymap_make_keymap (); - } - - /* Bind numeric arg functions for both echo area and info window maps. */ - for (i = '0'; i < '9' + 1; i++) - { - ((Keymap) info_keymap[ESC].function)[i].function = - ((Keymap) echo_area_keymap[ESC].function)[i].function = - info_add_digit_to_numeric_arg; - } - ((Keymap) info_keymap[ESC].function)['-'].function = - ((Keymap) echo_area_keymap[ESC].function)['-'].function = - info_add_digit_to_numeric_arg; - - /* Bind the echo area routines. */ - map = echo_area_keymap; - - /* Bind the echo area insert routines. */ - for (i = 0; i < 160; i++) - if (isprint (i)) - map[i].function = ea_insert; - - map[Control ('a')].function = ea_beg_of_line; - map[Control ('b')].function = ea_backward; - map[Control ('d')].function = ea_delete; - map[Control ('e')].function = ea_end_of_line; - map[Control ('f')].function = ea_forward; - map[Control ('g')].function = ea_abort; - map[Control ('h')].function = ea_rubout; - map[Control ('k')].function = ea_kill_line; - map[Control ('l')].function = info_redraw_display; - map[Control ('q')].function = ea_quoted_insert; - map[Control ('t')].function = ea_transpose_chars; - map[Control ('u')].function = info_universal_argument; - map[Control ('y')].function = ea_yank; - - map[LFD].function = ea_newline; - map[RET].function = ea_newline; - map[SPC].function = ea_complete; - map[TAB].function = ea_complete; - map['?'].function = ea_possible_completions; - map[DEL].function = ea_rubout; - - /* Bind the echo area ESC keymap. */ - map = (Keymap)echo_area_keymap[ESC].function; - - map[Control ('g')].function = ea_abort; - map[Control ('v')].function = ea_scroll_completions_window; - map['b'].function = ea_backward_word; - map['d'].function = ea_kill_word; - map['f'].function = ea_forward_word; -#if defined (NAMED_FUNCTIONS) - /* map['x'].function = info_execute_command; */ -#endif /* NAMED_FUNCTIONS */ - map['y'].function = ea_yank_pop; - map['?'].function = ea_possible_completions; - map[TAB].function = ea_tab_insert; - map[DEL].function = ea_backward_kill_word; - - /* Bind the echo area Control-x keymap. */ - map = (Keymap)echo_area_keymap[Control ('x')].function; - - map['o'].function = info_next_window; - map[DEL].function = ea_backward_kill_line; - - /* Bind commands for Info window keymaps. */ - map = info_keymap; - map[TAB].function = info_move_to_next_xref; - map[LFD].function = info_select_reference_this_line; - map[RET].function = info_select_reference_this_line; - map[SPC].function = info_scroll_forward; - map[Control ('a')].function = info_beginning_of_line; - map[Control ('b')].function = info_backward_char; - map[Control ('e')].function = info_end_of_line; - map[Control ('f')].function = info_forward_char; - map[Control ('g')].function = info_abort_key; - map[Control ('h')].function = info_get_help_window; - map[Control ('l')].function = info_redraw_display; - map[Control ('n')].function = info_next_line; - map[Control ('p')].function = info_prev_line; - map[Control ('r')].function = isearch_backward; - map[Control ('s')].function = isearch_forward; - map[Control ('u')].function = info_universal_argument; - map[Control ('v')].function = info_scroll_forward; - map[','].function = info_next_index_match; - - for (i = '1'; i < '9' + 1; i++) - map[i].function = info_menu_digit; - map['0'].function = info_last_menu_item; - - map['<'].function = info_first_node; - map['>'].function = info_last_node; - map['?'].function = info_get_help_window; - map['['].function = info_global_prev_node; - map[']'].function = info_global_next_node; - - map['b'].function = info_beginning_of_node; - map['d'].function = info_dir_node; - map['e'].function = info_end_of_node; - map['f'].function = info_xref_item; - map['g'].function = info_goto_node; - map['h'].function = info_get_info_help_node; - map['i'].function = info_index_search; - map['l'].function = info_history_node; - map['m'].function = info_menu_item; - map['n'].function = info_next_node; - map['p'].function = info_prev_node; - map['q'].function = info_quit; - map['r'].function = info_xref_item; - map['s'].function = info_search; - map['t'].function = info_top_node; - map['u'].function = info_up_node; - map[DEL].function = info_scroll_backward; - - /* Bind members in the ESC map for Info windows. */ - map = (Keymap)info_keymap[ESC].function; - map[Control ('f')].function = info_show_footnotes; - map[Control ('g')].function = info_abort_key; - map[TAB].function = info_move_to_prev_xref; - map[Control ('v')].function = info_scroll_other_window; - map['<'].function = info_beginning_of_node; - map['>'].function = info_end_of_node; - map['b'].function = info_backward_word; - map['f'].function = info_forward_word; - map['r'].function = info_move_to_window_line; - map['v'].function = info_scroll_backward; -#if defined (NAMED_FUNCTIONS) - map['x'].function = info_execute_command; -#endif /* NAMED_FUNCTIONS */ - - /* Bind members in the Control-X map for Info windows. */ - map = (Keymap)info_keymap[Control ('x')].function; - - map[Control ('b')].function = list_visited_nodes; - map[Control ('c')].function = info_quit; - map[Control ('f')].function = info_view_file; - map[Control ('g')].function = info_abort_key; - map[Control ('v')].function = info_view_file; - map['0'].function = info_delete_window; - map['1'].function = info_keep_one_window; - map['2'].function = info_split_window; - map['^'].function = info_grow_window; - map['b'].function = select_visited_node; - map['k'].function = info_kill_node; - map['o'].function = info_next_window; - map['t'].function = info_tile_windows; - map['w'].function = info_toggle_wrap; -} - -/* Strings which represent the sequence of characters that the arrow keys - produce. If these keys begin with ESC, and the second character of the - sequence does not conflict with an existing binding in the Meta keymap, - then bind the keys to do what C-p, C-n, C-f, and C-b do. */ -extern char *term_ku, *term_kd, *term_kr, *term_kl; - diff --git a/info/infomap.h b/info/infomap.h deleted file mode 100644 --- a/info/infomap.h +++ /dev/null @@ -1,82 +0,0 @@ -/* infomap.h -- Description of a keymap in Info and related functions. */ - -/* 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). */ - -#if !defined (_INFOMAP_H_) -#define _INFOMAP_H_ - -#include "general.h" - -#define ESC '\033' -#define DEL '\177' -#define TAB '\011' -#define RET '\r' -#define LFD '\n' -#define SPC ' ' - -#define meta_character_threshold (DEL + 1) -#define control_character_threshold (SPC) - -#define meta_character_bit 0x80 -#define control_character_bit 0x40 - -#define Meta_p(c) (((c) > meta_character_threshold)) -#define Control_p(c) ((c) < control_character_threshold) - -#define Meta(c) ((c) | (meta_character_bit)) -#define UnMeta(c) ((c) & (~meta_character_bit)) -#define Control(c) ((toupper (c)) & (~control_character_bit)) -#define UnControl(c) (tolower ((c) | control_character_bit)) - -/* A keymap contains one entry for each key in the ASCII set. - Each entry consists of a type and a pointer. - FUNCTION is the address of a function to run, or the - address of a keymap to indirect through. - TYPE says which kind of thing FUNCTION is. */ -typedef struct { - char type; - VFunction *function; -} KEYMAP_ENTRY; - -typedef KEYMAP_ENTRY *Keymap; - -/* The values that TYPE can have in a keymap entry. */ -#define ISFUNC 0 -#define ISKMAP 1 - -extern Keymap info_keymap; -extern Keymap echo_area_keymap; - -/* Return a new keymap which has all the uppercase letters mapped to run - the function info_do_lowercase_version (). */ -extern Keymap keymap_make_keymap (); - -/* Return a new keymap which is a copy of MAP. */ -extern Keymap keymap_copy_keymap (); - -/* Free MAP and it's descendents. */ -extern void keymap_discard_keymap (); - -/* Initialize the info keymaps. */ -extern void initialize_info_keymaps (); - -#endif /* !_INFOMAP_H_ */ diff --git a/info/m-x.c b/info/m-x.c deleted file mode 100644 --- a/info/m-x.c +++ /dev/null @@ -1,195 +0,0 @@ -/* m-x.c -- Meta-X minibuffer reader. */ - -/* 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" - -/* **************************************************************** */ -/* */ -/* Reading Named Commands */ -/* */ -/* **************************************************************** */ - -/* Read the name of an Info function in the echo area and return the - name. A return value of NULL indicates that no function name could - be read. */ -char * -read_function_name (prompt, window) - char *prompt; - WINDOW *window; -{ - register int i; - char *line; - REFERENCE **array = (REFERENCE **)NULL; - int array_index = 0, array_slots = 0; - - /* Make an array of REFERENCE which actually contains the names of - the functions available in Info. */ - for (i = 0; function_doc_array[i].func; i++) - { - REFERENCE *entry; - - entry = (REFERENCE *)xmalloc (sizeof (REFERENCE)); - entry->label = strdup (function_doc_array[i].func_name); - entry->nodename = (char *)NULL; - entry->filename = (char *)NULL; - - add_pointer_to_array - (entry, array_index, array, array_slots, 200, REFERENCE *); - } - - line = info_read_completing_in_echo_area (window, prompt, array); - - info_free_references (array); - - if (!echo_area_is_active) - window_clear_echo_area (); - - return (line); -} - -DECLARE_INFO_COMMAND (describe_command, - "Read the name of an Info command and describe it") -{ - char *line; - - line = read_function_name ("Describe command: ", window); - - if (!line) - { - info_abort_key (active_window, count, key); - return; - } - - /* Describe the function named in "LINE". */ - if (*line) - { - char *fundoc; - VFunction *fun; - - fun = named_function (line); - - if (!fun) - return; - - window_message_in_echo_area ("%s: %s.", - line, function_documentation (fun)); - } - free (line); -} - -DECLARE_INFO_COMMAND (info_execute_command, - "Read a command name in the echo area and execute it") -{ - char *line; - - /* Ask the completer to read a reference for us. */ - if (info_explicit_arg || count != 1) - { - char *prompt; - - prompt = (char *)xmalloc (20); - sprintf (prompt, "%d M-x ", count); - line = read_function_name (prompt, window); - } - else - line = read_function_name ("M-x ", window); - - /* User aborted? */ - if (!line) - { - info_abort_key (active_window, count, key); - return; - } - - /* User accepted "default"? (There is none.) */ - if (!*line) - { - free (line); - return; - } - - /* User wants to execute a named command. Do it. */ - { - VFunction *function; - - if ((active_window != the_echo_area) && - (strncmp (line, "echo-area-", 10) == 0)) - { - free (line); - info_error ("Cannot execute an `echo-area' command here."); - return; - } - - function = named_function (line); - free (line); - - if (!function) - return; - - (*function) (active_window, count, 0); - } -} - -/* Okay, now that we have M-x, let the user set the screen height. */ -DECLARE_INFO_COMMAND (set_screen_height, - "Set the height of the displayed window") -{ - int new_height; - - if (info_explicit_arg || count != 1) - new_height = count; - else - { - char prompt[80]; - char *line; - - new_height = screenheight; - - sprintf (prompt, "Set screen height to (%d): ", new_height); - - line = info_read_in_echo_area (window, prompt); - - /* If the user aborted, do that now. */ - if (!line) - { - info_abort_key (active_window, count, 0); - return; - } - - /* Find out what the new height is supposed to be. */ - if (*line) - new_height = atoi (line); - - /* Clear the echo area if it isn't active. */ - if (!echo_area_is_active) - window_clear_echo_area (); - - free (line); - } - - terminal_clear_screen (); - display_clear_display (the_display); - screenheight = new_height; - display_initialize_display (screenwidth, screenheight); - window_new_screen_size (screenwidth, screenheight); -} diff --git a/info/makedoc.c b/info/makedoc.c deleted file mode 100644 --- a/info/makedoc.c +++ /dev/null @@ -1,481 +0,0 @@ -/* makedoc.c -- Make DOC.C and FUNS.H from input files. */ - -/* 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). */ - -/* This program grovels the contents of the source files passed as arguments - and writes out a file of function pointers and documentation strings, and - a header file which describes the contents. This only does the functions - declared with DECLARE_INFO_COMMAND. */ - -#include -#include -#include -#if defined (HAVE_SYS_FILE_H) -#include -#endif /* HAVE_SYS_FILE_H */ -#include -#include "general.h" - -#if !defined (O_RDONLY) -#if defined (HAVE_SYS_FCNTL_H) -#include -#else /* !HAVE_SYS_FCNTL_H */ -#include -#endif /* !HAVE_SYS_FCNTL_H */ -#endif /* !O_RDONLY */ - -extern void *xmalloc (), *xrealloc (); -static void fatal_file_error (); - -/* Name of the header file which receives the declarations of functions. */ -static char *funs_filename = "funs.h"; - -/* Name of the documentation to function pointer file. */ -static char *doc_filename = "doc.c"; - -static char *doc_header[] = { - "/* doc.c -- Generated structure containing function names and doc strings.", - "", - " This file was automatically made from various source files with the", - " command \"%s\". DO NOT EDIT THIS FILE, only \"%s.c\".", - (char *)NULL -}; - -static char *doc_header_1[] = { - " An entry in the array FUNCTION_DOC_ARRAY is made for each command", - " found in the above files; each entry consists of a function pointer,", -#if defined (NAMED_FUNCTIONS) - " a string which is the user-visible name of the function,", -#endif /* NAMED_FUNCTIONS */ - " and a string which documents its purpose. */", - "", - "#include \"doc.h\"", - "#include \"funs.h\"", - "", - "FUNCTION_DOC function_doc_array[] = {", - "", - (char *)NULL -}; - -/* How to remember the locations of the functions found so that Emacs - can use the information in a tag table. */ -typedef struct { - char *name; /* Name of the tag. */ - int line; /* Line number at which it appears. */ - long char_offset; /* Character offset at which it appears. */ -} EMACS_TAG; - -typedef struct { - char *filename; /* Name of the file containing entries. */ - long entrylen; /* Total number of characters in tag block. */ - EMACS_TAG **entries; /* Entries found in FILENAME. */ - int entries_index; - int entries_slots; -} EMACS_TAG_BLOCK; - -EMACS_TAG_BLOCK **emacs_tags = (EMACS_TAG_BLOCK **)NULL; -int emacs_tags_index = 0; -int emacs_tags_slots = 0; - -#define DECLARATION_STRING "\nDECLARE_INFO_COMMAND" - -static void process_one_file (); -static void maybe_dump_tags (); -static FILE *must_fopen (); - -int -main (argc, argv) - int argc; - char **argv; -{ - register int i; - int tags_only = 0; - FILE *funs_stream, *doc_stream; - - for (i = 1; i < argc; i++) - if (strcmp (argv[i], "-tags") == 0) - { - tags_only++; - break; - } - - if (tags_only) - { - funs_filename = "/dev/null"; - doc_filename = "/dev/null"; - } - - funs_stream = must_fopen (funs_filename, "w"); - doc_stream = must_fopen (doc_filename, "w"); - - fprintf (funs_stream, - "/* %s -- Generated declarations for Info commands. */\n", - funs_filename); - - for (i = 0; doc_header[i]; i++) - { - fprintf (doc_stream, doc_header[i], argv[0], argv[0]); - fprintf (doc_stream, "\n"); - } - - fprintf (doc_stream, - " Source files groveled to make this file include:\n\n"); - - for (i = 1; i < argc; i++) - fprintf (doc_stream, "\t%s\n", argv[i]); - - fprintf (doc_stream, "\n"); - - for (i = 0; doc_header_1[i]; i++) - fprintf (doc_stream, "%s\n", doc_header_1[i]); - - - for (i = 1; i < argc; i++) - { - char *curfile; - curfile = argv[i]; - - if (*curfile == '-') - continue; - - fprintf (doc_stream, "/* Commands found in \"%s\". */\n", curfile); - fprintf (funs_stream, "\n/* Functions declared in \"%s\". */\n", - curfile); - - process_one_file (curfile, doc_stream, funs_stream); - } - - fprintf (doc_stream, - " { (VFunction *)NULL, (char *)NULL, (char *)NULL }\n};\n"); - - fclose (funs_stream); - fclose (doc_stream); - - if (tags_only) - maybe_dump_tags (stdout); - exit (0); -} - -/* Dumping out the contents of an Emacs tags table. */ -static void -maybe_dump_tags (stream) - FILE *stream; -{ - register int i; - - /* Print out the information for each block. */ - for (i = 0; i < emacs_tags_index; i++) - { - register int j; - register EMACS_TAG_BLOCK *block; - register EMACS_TAG *etag; - long block_len; - - block_len = 0; - block = emacs_tags[i]; - - /* Calculate the length of the dumped block first. */ - for (j = 0; j < block->entries_index; j++) - { - char digits[30]; - etag = block->entries[j]; - block_len += 3 + strlen (etag->name); - sprintf (digits, "%d,%d", etag->line, etag->char_offset); - block_len += strlen (digits); - } - - /* Print out the defining line. */ - fprintf (stream, "\f\n%s,%d\n", block->filename, block_len); - - /* Print out the individual tags. */ - for (j = 0; j < block->entries_index; j++) - { - etag = block->entries[j]; - - fprintf (stream, "%s,\177%d,%d\n", - etag->name, etag->line, etag->char_offset); - } - } -} - -/* Keeping track of names, line numbers and character offsets of functions - found in source files. */ -static EMACS_TAG_BLOCK * -make_emacs_tag_block (filename) - char *filename; -{ - EMACS_TAG_BLOCK *block; - - block = (EMACS_TAG_BLOCK *)xmalloc (sizeof (EMACS_TAG_BLOCK)); - block->filename = strdup (filename); - block->entrylen = 0; - block->entries = (EMACS_TAG **)NULL; - block->entries_index = 0; - block->entries_slots = 0; - return (block); -} - -static void -add_tag_to_block (block, name, line, char_offset) - EMACS_TAG_BLOCK *block; - char *name; - int line; - long char_offset; -{ - EMACS_TAG *tag; - - tag = (EMACS_TAG *)xmalloc (sizeof (EMACS_TAG)); - tag->name = name; - tag->line = line; - tag->char_offset = char_offset; - add_pointer_to_array (tag, block->entries_index, block->entries, - block->entries_slots, 50, EMACS_TAG *); -} - -/* Read the file represented by FILENAME into core, and search it for Info - function declarations. Output the declarations in various forms to the - DOC_STREAM and FUNS_STREAM. */ -static void -process_one_file (filename, doc_stream, funs_stream) - char *filename; - FILE *doc_stream, *funs_stream; -{ - int descriptor, decl_len; - char *buffer, *decl_str; - struct stat finfo; - long offset; - long file_size; - EMACS_TAG_BLOCK *block; - - if (stat (filename, &finfo) == -1) - fatal_file_error (filename); - - descriptor = open (filename, O_RDONLY, 0666); - - if (descriptor == -1) - fatal_file_error (filename); - - file_size = (long) finfo.st_size; - buffer = (char *)xmalloc (1 + file_size); - read (descriptor, buffer, file_size); - close (descriptor); - - offset = 0; - decl_str = DECLARATION_STRING; - decl_len = strlen (decl_str); - - block = make_emacs_tag_block (filename); - - while (1) - { - long point = 0; - long line_start = 0; - int line_number = 0; - - char *func, *doc; -#if defined (NAMED_FUNCTIONS) - char *func_name; -#endif /* NAMED_FUNCTIONS */ - - for (; offset < (file_size - decl_len); offset++) - { - if (buffer[offset] == '\n') - { - line_number++; - line_start = offset + 1; - } - - if (strncmp (buffer + offset, decl_str, decl_len) == 0) - { - offset += decl_len; - point = offset; - break; - } - } - - if (!point) - break; - - /* Skip forward until we find the open paren. */ - while (point < file_size) - { - if (buffer[point] == '\n') - { - line_number++; - line_start = point + 1; - } - else if (buffer[point] == '(') - break; - - point++; - } - - while (point++ < file_size) - { - if (!whitespace_or_newline (buffer[point])) - break; - else if (buffer[point] == '\n') - { - line_number++; - line_start = point + 1; - } - } - - if (point >= file_size) - break; - - /* Now looking at name of function. Get it. */ - for (offset = point; buffer[offset] != ','; offset++); - func = (char *)xmalloc (1 + (offset - point)); - strncpy (func, buffer + point, offset - point); - func[offset - point] = '\0'; - - /* Remember this tag in the current block. */ - { - char *tag_name; - - tag_name = (char *)xmalloc (1 + (offset - line_start)); - strncpy (tag_name, buffer + line_start, offset - line_start); - tag_name[offset - line_start] = '\0'; - add_tag_to_block (block, tag_name, line_number, point); - } - -#if defined (NAMED_FUNCTIONS) - /* Generate the user-visible function name from the function's name. */ - { - register int i; - char *name_start; - - name_start = func; - - if (strncmp (name_start, "info_", 5) == 0) - name_start += 5; - - func_name = strdup (name_start); - - /* Fix up "ea" commands. */ - if (strncmp (func_name, "ea_", 3) == 0) - { - char *temp_func_name; - - temp_func_name = (char *)xmalloc (10 + strlen (func_name)); - strcpy (temp_func_name, "echo_area_"); - strcat (temp_func_name, func_name + 3); - free (func_name); - func_name = temp_func_name; - } - - for (i = 0; func_name[i]; i++) - if (func_name[i] == '_') - func_name[i] = '-'; - } -#endif /* NAMED_FUNCTIONS */ - - /* Find doc string. */ - point = offset + 1; - - while (point < file_size) - { - if (buffer[point] == '\n') - { - line_number++; - line_start = point + 1; - } - - if (buffer[point] == '"') - break; - else - point++; - } - - offset = point + 1; - - while (offset < file_size) - { - if (buffer[offset] == '\n') - { - line_number++; - line_start = offset + 1; - } - - if (buffer[offset] == '\\') - offset += 2; - else if (buffer[offset] == '"') - break; - else - offset++; - } - - offset++; - if (offset >= file_size) - break; - - doc = (char *)xmalloc (1 + (offset - point)); - strncpy (doc, buffer + point, offset - point); - doc[offset - point] = '\0'; - -#if defined (NAMED_FUNCTIONS) - fprintf (doc_stream, " { %s, \"%s\", %s },\n", func, func_name, doc); - free (func_name); -#else /* !NAMED_FUNCTIONS */ - fprintf (doc_stream, " { %s, %s },\n", func, doc); -#endif /* !NAMED_FUNCTIONS */ - - fprintf (funs_stream, "extern void %s ();\n", func); - free (func); - free (doc); - } - free (buffer); - - /* If we created any tags, remember this file on our global list. Otherwise, - free the memory already allocated to it. */ - if (block->entries) - add_pointer_to_array (block, emacs_tags_index, emacs_tags, - emacs_tags_slots, 10, EMACS_TAG_BLOCK *); - else - { - free (block->filename); - free (block); - } -} - -static void -fatal_file_error (filename) - char *filename; -{ - fprintf (stderr, "Couldn't manipulate the file %s.\n", filename); - exit (2); -} - -static FILE * -must_fopen (filename, mode) - char *filename, *mode; -{ - FILE *stream; - - stream = fopen (filename, mode); - if (!stream) - fatal_file_error (filename); - - return (stream); -} - diff --git a/info/man.c b/info/man.c deleted file mode 100644 --- a/info/man.c +++ /dev/null @@ -1,643 +0,0 @@ -/* man.c: How to read and format man files. */ - -/* This file is part of GNU Info, a program for reading online documentation - stored in Info format. - - Copyright (C) 1995 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 Thu May 4 09:17:52 1995 (bfox@ai.mit.edu). */ - -#include "info.h" -#include -#include -#include "signals.h" -#if defined (HAVE_SYS_TIME_H) -#include -#endif -#if defined (HAVE_SYS_WAIT_H) -#include -#endif -#include "tilde.h" - -#include "man.h" - -#if !defined (_POSIX_VERSION) -#define pid_t int -#endif - -#if defined (FD_SET) -# if defined (hpux) -# define fd_set_cast(x) (int *)(x) -# else -# define fd_set_cast(x) (fd_set *)(x) -# endif /* !hpux */ -#endif /* FD_SET */ - -static char *read_from_fd (); -static void clean_manpage (); -static NODE *manpage_node_of_file_buffer (); -static char *get_manpage_contents (); - -NODE * -make_manpage_node (pagename) - char *pagename; -{ - return (info_get_node (MANPAGE_FILE_BUFFER_NAME, pagename)); -} - -NODE * -get_manpage_node (file_buffer, pagename) - FILE_BUFFER *file_buffer; - char *pagename; -{ - NODE *node; - - node = manpage_node_of_file_buffer (file_buffer, pagename); - - if (!node) - { - char *page; - - page = get_manpage_contents (pagename); - - if (page) - { - char header[1024]; - long oldsize, newsize; - int hlen, plen; - - sprintf (header, "\n\n%c\n%s %s, %s %s, %s (dir)\n\n", - INFO_COOKIE, - INFO_FILE_LABEL, file_buffer->filename, - INFO_NODE_LABEL, pagename, - INFO_UP_LABEL); - oldsize = file_buffer->filesize; - hlen = strlen (header); - plen = strlen (page); - newsize = (oldsize + hlen + plen); - file_buffer->contents = - (char *)xrealloc (file_buffer->contents, 1 + newsize); - memcpy (file_buffer->contents + oldsize, header, hlen); - oldsize += hlen; - memcpy (file_buffer->contents + oldsize, page, plen); - file_buffer->contents[newsize] = '\0'; - file_buffer->filesize = newsize; - file_buffer->finfo.st_size = newsize; - build_tags_and_nodes (file_buffer); - free (page); - } - - node = manpage_node_of_file_buffer (file_buffer, pagename); - } - - return (node); -} - -FILE_BUFFER * -create_manpage_file_buffer () -{ - FILE_BUFFER *file_buffer; - struct stat *finfo; - - file_buffer = make_file_buffer (); - file_buffer->filename = strdup (MANPAGE_FILE_BUFFER_NAME); - file_buffer->fullpath = strdup (MANPAGE_FILE_BUFFER_NAME); - file_buffer->finfo.st_size = 0; - file_buffer->filesize = 0; - file_buffer->contents = (char *)NULL; - file_buffer->flags = (N_IsInternal | N_CannotGC | N_IsManPage); - - return (file_buffer); -} - -/* Scan the list of directories in PATH looking for FILENAME. If we find - one that is an executable file, return it as a new string. Otherwise, - return a NULL pointer. */ -static char * -executable_file_in_path (filename, path) - char *filename, *path; -{ - struct stat finfo; - char *temp_dirname; - int statable, dirname_index; - - dirname_index = 0; - - while (temp_dirname = extract_colon_unit (path, &dirname_index)) - { - register int i; - char *temp; - - /* Expand a leading tilde if one is present. */ - if (*temp_dirname == '~') - { - char *expanded_dirname; - - expanded_dirname = tilde_expand_word (temp_dirname); - free (temp_dirname); - temp_dirname = expanded_dirname; - } - - temp = (char *)xmalloc (30 + strlen (temp_dirname) + strlen (filename)); - strcpy (temp, temp_dirname); - if (temp[(strlen (temp)) - 1] != '/') - strcat (temp, "/"); - strcat (temp, filename); - - free (temp_dirname); - - statable = (stat (temp, &finfo) == 0); - - /* If we have found a regular executable file, then use it. */ - if ((statable) && (S_ISREG (finfo.st_mode)) && - (access (temp, X_OK) == 0)) - return (temp); - else - free (temp); - } - return ((char *)NULL); -} - -/* Return the full pathname of the system man page formatter. */ -static char * -find_man_formatter () -{ - return (executable_file_in_path ("man", (char *)getenv ("PATH"))); -} - -static char *manpage_pagename = (char *)NULL; -static char *manpage_section = (char *)NULL; - -static void -get_page_and_section (pagename) - char *pagename; -{ - register int i; - - if (manpage_pagename) - free (manpage_pagename); - - if (manpage_section) - free (manpage_section); - - manpage_pagename = (char *)NULL; - manpage_section = (char *)NULL; - - for (i = 0; pagename[i] != '\0' && pagename[i] != '('; i++); - - manpage_pagename = (char *)xmalloc (1 + i); - strncpy (manpage_pagename, pagename, i); - manpage_pagename[i] = '\0'; - - if (pagename[i] == '(') - { - int start; - - start = i + 1; - - for (i = start; pagename[i] != '\0' && pagename[i] != ')'; i++); - - manpage_section = (char *)xmalloc (1 + (i - start)); - strncpy (manpage_section, pagename + start, (i - start)); - manpage_section[i - start] = '\0'; - } -} - -static void -reap_children (sig) - int sig; -{ - unsigned int status; - wait (&status); -} - -static char * -get_manpage_contents (pagename) - char *pagename; -{ - static char *formatter_args[4] = { (char *)NULL }; - int pipes[2]; - pid_t child; - char *formatted_page = (char *)NULL; - char *section = (char *)NULL; - int arg_index = 1; - - if (formatter_args[0] == (char *)NULL) - formatter_args[0] = find_man_formatter (); - - if (formatter_args[0] == (char *)NULL) - return ((char *)NULL); - - get_page_and_section (pagename); - - if (manpage_section != (char *)NULL) - formatter_args[arg_index++] = manpage_section; - - formatter_args[arg_index++] = manpage_pagename; - formatter_args[arg_index] = (char *)NULL; - - /* Open a pipe to this program, read the output, and save it away - in FORMATTED_PAGE. The reader end of the pipe is pipes[0]; the - writer end is pipes[1]. */ - pipe (pipes); - - signal (SIGCHLD, reap_children); - - child = fork (); - - if (child == -1) - return ((char *)NULL); - - if (child != 0) - { - /* In the parent, close the writing end of the pipe, and read from - the exec'd child. */ - close (pipes[1]); - formatted_page = read_from_fd (pipes[0]); - close (pipes[0]); - } - else - { - /* In the child, close the read end of the pipe, make the write end - of the pipe be stdout, and execute the man page formatter. */ - close (pipes[0]); - close (fileno (stderr)); - close (fileno (stdin)); /* Don't print errors. */ - dup2 (pipes[1], fileno (stdout)); - - execv (formatter_args[0], formatter_args); - - /* If we get here, we couldn't exec, so close out the pipe and - exit. */ - close (pipes[1]); - exit (0); - } - - /* If we have the page, then clean it up. */ - if (formatted_page) - clean_manpage (formatted_page); - - return (formatted_page); -} - -static void -clean_manpage (manpage) - char *manpage; -{ - register int i, j; - int newline_count = 0; - char *newpage; - - newpage = (char *)xmalloc (1 + strlen (manpage)); - - for (i = 0, j = 0; newpage[j] = manpage[i]; i++, j++) - { - if (manpage[i] == '\n') - newline_count++; - else - newline_count = 0; - - if (newline_count == 3) - { - j--; - newline_count--; - } - - if (manpage[i] == '\b' || manpage[i] == '\f') - j -= 2; - } - - newpage[j++] = '\0'; - - strcpy (manpage, newpage); - free (newpage); -} - -static NODE * -manpage_node_of_file_buffer (file_buffer, pagename) - FILE_BUFFER *file_buffer; - char *pagename; -{ - NODE *node = (NODE *)NULL; - TAG *tag = (TAG *)NULL; - - if (file_buffer->contents) - { - register int i; - - for (i = 0; tag = file_buffer->tags[i]; i++) - { - if (strcasecmp (pagename, tag->nodename) == 0) - break; - } - } - - if (tag) - { - node = (NODE *)xmalloc (sizeof (NODE)); - node->filename = file_buffer->filename; - node->nodename = tag->nodename; - node->contents = file_buffer->contents + tag->nodestart; - node->nodelen = tag->nodelen; - node->flags = 0; - node->parent = (char *)NULL; - node->flags = (N_HasTagsTable | N_IsManPage); - node->contents += skip_node_separator (node->contents); - } - - return (node); -} - -static char * -read_from_fd (fd) - int fd; -{ - struct timeval timeout; - char *buffer = (char *)NULL; - int bsize = 0; - int bindex = 0; - int select_result; -#if defined (FD_SET) - fd_set read_fds; - - timeout.tv_sec = 15; - timeout.tv_usec = 0; - - FD_ZERO (&read_fds); - FD_SET (fd, &read_fds); - - select_result = select (fd + 1, fd_set_cast (&read_fds), 0, 0, &timeout); -#else /* !FD_SET */ - select_result = 1; -#endif /* !FD_SET */ - - switch (select_result) - { - case 0: - case -1: - break; - - default: - { - int amount_read; - int done = 0; - - while (!done) - { - while ((bindex + 1024) > (bsize)) - buffer = (char *)xrealloc (buffer, (bsize += 1024)); - buffer[bindex] = '\0'; - - amount_read = read (fd, buffer + bindex, 1023); - - if (amount_read < 0) - { - done = 1; - } - else - { - bindex += amount_read; - buffer[bindex] = '\0'; - if (amount_read == 0) - done = 1; - } - } - } - } - - if ((buffer != (char *)NULL) && (*buffer == '\0')) - { - free (buffer); - buffer = (char *)NULL; - } - - return (buffer); -} - -static char *reference_section_starters[] = -{ - "\nRELATED INFORMATION", - "\nRELATED\tINFORMATION", - "RELATED INFORMATION\n", - "RELATED\tINFORMATION\n", - "\nSEE ALSO", - "\nSEE\tALSO", - "SEE ALSO\n", - "SEE\tALSO\n", - (char *)NULL -}; - -static SEARCH_BINDING frs_binding; - -static SEARCH_BINDING * -find_reference_section (node) - NODE *node; -{ - register int i; - long position = -1; - - frs_binding.buffer = node->contents; - frs_binding.start = 0; - frs_binding.end = node->nodelen; - frs_binding.flags = S_SkipDest; - - for (i = 0; reference_section_starters[i] != (char *)NULL; i++) - { - position = search_forward (reference_section_starters[i], &frs_binding); - if (position != -1) - break; - } - - if (position == -1) - return ((SEARCH_BINDING *)NULL); - - /* We found the start of the reference section, and point is right after - the string which starts it. The text from here to the next header - (or end of buffer) contains the only references in this manpage. */ - frs_binding.start = position; - - for (i = frs_binding.start; i < frs_binding.end - 2; i++) - { - if ((frs_binding.buffer[i] == '\n') && - (!whitespace (frs_binding.buffer[i + 1]))) - { - frs_binding.end = i; - break; - } - } - - return (&frs_binding); -} - -REFERENCE ** -xrefs_of_manpage (node) - NODE *node; -{ - SEARCH_BINDING *reference_section; - REFERENCE **refs = (REFERENCE **)NULL; - int refs_index = 0; - int refs_slots = 0; - long position; - - reference_section = find_reference_section (node); - - if (reference_section == (SEARCH_BINDING *)NULL) - return ((REFERENCE **)NULL); - - /* Grovel the reference section building a list of references found there. - A reference is alphabetic characters followed by non-whitespace text - within parenthesis. */ - reference_section->flags = 0; - - while ((position = search_forward ("(", reference_section)) != -1) - { - register int start, end; - - for (start = position; start > reference_section->start; start--) - if (whitespace (reference_section->buffer[start])) - break; - - start++; - - for (end = position; end < reference_section->end; end++) - { - if (whitespace (reference_section->buffer[end])) - { - end = start; - break; - } - - if (reference_section->buffer[end] == ')') - { - end++; - break; - } - } - - if (end != start) - { - REFERENCE *entry; - int len = end - start; - - entry = (REFERENCE *)xmalloc (sizeof (REFERENCE)); - entry->label = (char *)xmalloc (1 + len); - strncpy (entry->label, (reference_section->buffer) + start, len); - entry->label[len] = '\0'; - entry->filename = strdup (node->filename); - entry->nodename = strdup (entry->label); - entry->start = start; - entry->end = end; - - add_pointer_to_array - (entry, refs_index, refs, refs_slots, 10, REFERENCE *); - } - - reference_section->start = position + 1; - } - - return (refs); -} - -long -locate_manpage_xref (node, start, dir) - NODE *node; - long start; - int dir; -{ - register int i, count; - REFERENCE **refs; - long position = -1; - - refs = xrefs_of_manpage (node); - - if (refs) - { - register int i, count; - REFERENCE *entry; - - for (i = 0; refs[i]; i++); - count = i; - - if (dir > 0) - { - for (i = 0; entry = refs[i]; i++) - if (entry->start > start) - { - position = entry->start; - break; - } - } - else - { - for (i = count - 1; i > -1; i--) - { - entry = refs[i]; - - if (entry->start < start) - { - position = entry->start; - break; - } - } - } - - info_free_references (refs); - } - return (position); -} - -/* This one was a little tricky. The binding buffer that is passed in has - a START and END value of 0 -- strlen (window-line-containing-point). - The BUFFER is a pointer to the start of that line. */ -REFERENCE ** -manpage_xrefs_in_binding (node, binding) - NODE *node; - SEARCH_BINDING *binding; -{ - register int i; - REFERENCE **all_refs = xrefs_of_manpage (node); - REFERENCE **brefs = (REFERENCE **)NULL; - REFERENCE *entry; - int brefs_index = 0; - int brefs_slots = 0; - int start, end; - - if (!all_refs) - return ((REFERENCE **)NULL); - - start = binding->start + (binding->buffer - node->contents); - end = binding->end + (binding->buffer - node->contents); - - for (i = 0; entry = all_refs[i]; i++) - { - if ((entry->start > start) && (entry->end < end)) - { - add_pointer_to_array - (entry, brefs_index, brefs, brefs_slots, 10, REFERENCE *); - } - else - { - maybe_free (entry->label); - maybe_free (entry->filename); - maybe_free (entry->nodename); - free (entry); - } - } - - free (all_refs); - return (brefs); -} diff --git a/info/man.h b/info/man.h deleted file mode 100644 --- a/info/man.h +++ /dev/null @@ -1,36 +0,0 @@ -/* man.h: Defines and external function declarations for man.c */ - -/* 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. - - Author: Brian J. Fox (bfox@ai.mit.edu) Sat May 6 16:19:13 1995. */ - -#if !defined (_MAN_H_) -#define _MAN_H_ - -#define MANPAGE_FILE_BUFFER_NAME "*manpages*" - -extern NODE *make_manpage_node (/* char *pagename */); -extern NODE *get_manpage_node (/* FILE_BUFFER *file_buffer, char *pagename */); -extern FILE_BUFFER *create_manpage_file_buffer (/* void */); -extern long locate_manpage_xref (/* NODE *node, long start, int dir */); -extern REFERENCE **xrefs_of_manpage (/* NODE *node */); -extern REFERENCE **manpage_xrefs_in_binding (/* NODE *node, SEARCH_BINDING *binding */); - -#endif /* !_MAN_H_ */ diff --git a/info/memcpy.c b/info/memcpy.c deleted file mode 100644 --- a/info/memcpy.c +++ /dev/null @@ -1,20 +0,0 @@ -/* Copy LEN bytes starting at SRCADDR to DESTADDR. Result undefined - if the source overlaps with the destination. - Return DESTADDR. */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -char * -memcpy (destaddr, srcaddr, len) - char *destaddr; - const char *srcaddr; - int len; -{ - char *dest = destaddr; - - while (len-- > 0) - *destaddr++ = *srcaddr++; - return dest; -} diff --git a/info/memmove.c b/info/memmove.c deleted file mode 100644 --- a/info/memmove.c +++ /dev/null @@ -1,24 +0,0 @@ -/* memmove.c -- copy memory. - Copy LENGTH bytes from SOURCE to DEST. Does not null-terminate. - In the public domain. - By David MacKenzie . */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -void -memmove (dest, source, length) - char *dest; - const char *source; - unsigned length; -{ - if (source < dest) - /* Moving from low mem to hi mem; start at end. */ - for (source += length, dest += length; length; --length) - *--dest = *--source; - else if (source != dest) - /* Moving from hi mem to low mem; start at beginning. */ - for (; length; --length) - *dest++ = *source++; -} diff --git a/info/mkinstalldirs b/info/mkinstalldirs deleted file mode 100755 --- a/info/mkinstalldirs +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh -# mkinstalldirs --- make directory hierarchy -# Author: Noah Friedman -# Created: 1993-05-16 -# Last modified: Wed Jan 25 09:35:21 1995 -# Public domain - -errstatus=0 - -dirmode=0755 - -for file in ${1+"$@"} ; do - set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` - shift - - pathcomp= - for d in ${1+"$@"} ; do - pathcomp="$pathcomp$d" - case "$pathcomp" in - -* ) pathcomp=./$pathcomp ;; - esac - - if test ! -d "$pathcomp"; then - echo "mkdir $pathcomp" 1>&2 - mkdir "$pathcomp" || errstatus=$? - echo "chmod $dirmode $pathcomp" 1>&2 - chmod $dirmode "$pathcomp" || errstatus=$? - fi - - pathcomp="$pathcomp/" - done -done - -exit $errstatus - -# mkinstalldirs ends here diff --git a/info/nodemenu.c b/info/nodemenu.c deleted file mode 100644 --- a/info/nodemenu.c +++ /dev/null @@ -1,329 +0,0 @@ -/* nodemenu.c -- Produce a menu of all visited nodes. */ - -/* 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" - -/* Return a line describing the format of a node information line. */ -static char * -nodemenu_format_info () -{ - return ("\n\ -* Menu:\n\ - (File)Node Lines Size Containing File\n\ - ---------- ----- ---- ---------------"); -} - -/* Produce a formatted line of information about NODE. Here is what we want - the output listing to look like: - -* Menu: - (File)Node Lines Size Containing File - ---------- ----- ---- --------------- -* (emacs)Buffers:: 48 2230 /usr/gnu/info/emacs/emacs-1 -* (autoconf)Writing configure.in:: 123 58789 /usr/gnu/info/autoconf/autoconf-1 -* (dir)Top:: 40 589 /usr/gnu/info/dir -*/ -static char * -format_node_info (node) - NODE *node; -{ - register int i, len; - char *parent, *containing_file; - static char *line_buffer = (char *)NULL; - - if (!line_buffer) - line_buffer = (char *)xmalloc (1000); - - if (node->parent) - { - parent = filename_non_directory (node->parent); - if (!parent) - parent = node->parent; - } - else - parent = (char *)NULL; - - containing_file = node->filename; - - if (!parent && !*containing_file) - sprintf (line_buffer, "* %s::", node->nodename); - else - { - char *file = (char *)NULL; - - if (parent) - file = parent; - else - file = filename_non_directory (containing_file); - - if (!file) - file = containing_file; - - if (!*file) - file = "dir"; - - sprintf (line_buffer, "* (%s)%s::", file, node->nodename); - } - - len = pad_to (36, line_buffer); - - { - int lines = 1; - - for (i = 0; i < node->nodelen; i++) - if (node->contents[i] == '\n') - lines++; - - sprintf (line_buffer + len, "%d", lines); - } - - len = pad_to (44, line_buffer); - sprintf (line_buffer + len, "%d", node->nodelen); - - if (node->filename && *(node->filename)) - { - len = pad_to (51, line_buffer); - sprintf (line_buffer + len, node->filename); - } - - return (strdup (line_buffer)); -} - -/* Little string comparison routine for qsort (). */ -static int -compare_strings (string1, string2) - char **string1, **string2; -{ - return (strcasecmp (*string1, *string2)); -} - -/* The name of the nodemenu node. */ -static char *nodemenu_nodename = "*Node Menu*"; - -/* Produce an informative listing of all the visited nodes, and return it - in a node. If FILTER_FUNC is non-null, it is a function which filters - which nodes will appear in the listing. FILTER_FUNC takes an argument - of NODE, and returns non-zero if the node should appear in the listing. */ -NODE * -get_visited_nodes (filter_func) - Function *filter_func; -{ - register int i, iw_index; - INFO_WINDOW *info_win; - NODE *node; - char **lines = (char **)NULL; - int lines_index = 0, lines_slots = 0; - - if (!info_windows) - return ((NODE *)NULL); - - for (iw_index = 0; info_win = info_windows[iw_index]; iw_index++) - { - for (i = 0; i < info_win->nodes_index; i++) - { - node = info_win->nodes[i]; - - /* We skip mentioning "*Node Menu*" nodes. */ - if (internal_info_node_p (node) && - (strcmp (node->nodename, nodemenu_nodename) == 0)) - continue; - - if (node && (!filter_func || (*filter_func) (node))) - { - char *line; - - line = format_node_info (node); - add_pointer_to_array - (line, lines_index, lines, lines_slots, 20, char *); - } - } - } - - /* Sort the array of information lines, if there are any. */ - if (lines) - { - register int j, newlen; - char **temp; - - qsort (lines, lines_index, sizeof (char *), compare_strings); - - /* Delete duplicates. */ - for (i = 0, newlen = 1; i < lines_index - 1; i++) - { - if (strcmp (lines[i], lines[i + 1]) == 0) - { - free (lines[i]); - lines[i] = (char *)NULL; - } - else - newlen++; - } - - /* We have free ()'d and marked all of the duplicate slots. - Copy the live slots rather than pruning the dead slots. */ - temp = (char **)xmalloc ((1 + newlen) * sizeof (char *)); - for (i = 0, j = 0; i < lines_index; i++) - if (lines[i]) - temp[j++] = lines[i]; - - temp[j] = (char *)NULL; - free (lines); - lines = temp; - lines_index = newlen; - } - - initialize_message_buffer (); - - printf_to_message_buffer - ("%s", replace_in_documentation - ("Here is the menu of nodes you have recently visited.\n\ -Select one from this menu, or use `\\[history-node]' in another window.\n")); - - printf_to_message_buffer ("%s\n", nodemenu_format_info ()); - - for (i = 0; (lines != (char **)NULL) && (i < lines_index); i++) - { - printf_to_message_buffer ("%s\n", lines[i]); - free (lines[i]); - } - - if (lines) - free (lines); - - node = message_buffer_to_node (); - add_gcable_pointer (node->contents); - return (node); -} - -DECLARE_INFO_COMMAND (list_visited_nodes, - "Make a window containing a menu of all of the currently visited nodes") -{ - WINDOW *new; - NODE *node; - - set_remembered_pagetop_and_point (window); - - /* If a window is visible and showing the buffer list already, re-use it. */ - for (new = windows; new; new = new->next) - { - node = new->node; - - if (internal_info_node_p (node) && - (strcmp (node->nodename, nodemenu_nodename) == 0)) - break; - } - - /* If we couldn't find an existing window, try to use the next window - in the chain. */ - if (!new && window->next) - new = window->next; - - /* If we still don't have a window, make a new one to contain the list. */ - if (!new) - { - WINDOW *old_active; - - old_active = active_window; - active_window = window; - new = window_make_window ((NODE *)NULL); - active_window = old_active; - } - - /* If we couldn't make a new window, use this one. */ - if (!new) - new = window; - - /* Lines do not wrap in this window. */ - new->flags |= W_NoWrap; - node = get_visited_nodes ((Function *)NULL); - name_internal_node (node, nodemenu_nodename); - - /* Even if this is an internal node, we don't want the window - system to treat it specially. So we turn off the internalness - of it here. */ - node->flags &= ~N_IsInternal; - - /* If this window is already showing a node menu, reuse the existing node - slot. */ - { - int remember_me = 1; - -#if defined (NOTDEF) - if (internal_info_node_p (new->node) && - (strcmp (new->node->nodename, nodemenu_nodename) == 0)) - remember_me = 0; -#endif /* NOTDEF */ - - window_set_node_of_window (new, node); - - if (remember_me) - remember_window_and_node (new, node); - } - - active_window = new; -} - -DECLARE_INFO_COMMAND (select_visited_node, - "Select a node which has been previously visited in a visible window") -{ - char *line; - NODE *node; - REFERENCE **menu; - - node = get_visited_nodes ((Function *)NULL); - - menu = info_menu_of_node (node); - free (node); - - line = - info_read_completing_in_echo_area (window, "Select visited node: ", menu); - - window = active_window; - - /* User aborts, just quit. */ - if (!line) - { - info_abort_key (window, 0, 0); - info_free_references (menu); - return; - } - - if (*line) - { - REFERENCE *entry; - - /* Find the selected label in the references. */ - entry = info_get_labeled_reference (line, menu); - - if (!entry) - info_error ("The reference disappeared! (%s).", line); - else - info_select_reference (window, entry); - } - - free (line); - info_free_references (menu); - - if (!info_error_was_printed) - window_clear_echo_area (); -} diff --git a/info/nodes.c b/info/nodes.c deleted file mode 100644 --- a/info/nodes.c +++ /dev/null @@ -1,1207 +0,0 @@ -/* nodes.c -- How to get an Info file and node. */ - -/* 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 -#include -#include -#if defined (HAVE_SYS_FILE_H) -#include -#endif /* HAVE_SYS_FILE_H */ -#include -#include -#if defined (HAVE_STRING_H) -#include -#endif /* HAVE_STRING_H */ -#include "nodes.h" -#include "search.h" -#include "filesys.h" -#include "info-utils.h" - -#if defined (HANDLE_MAN_PAGES) -# include "man.h" -#endif /* HANDLE_MAN_PAGES */ - -#if !defined (O_RDONLY) -#if defined (HAVE_SYS_FCNTL_H) -#include -#else /* !HAVE_SYS_FCNTL_H */ -#include -#endif /* !HAVE_SYS_FCNTL_H */ -#endif /* !O_RDONLY */ - -#if !defined (errno) -extern int errno; -#endif /* !errno */ - -/* **************************************************************** */ -/* */ -/* Functions Static to this File */ -/* */ -/* **************************************************************** */ - -static void forget_info_file (), remember_info_file (); -static void free_file_buffer_tags (), free_info_tag (); -static void get_nodes_of_tags_table (), get_nodes_of_info_file (); -static void get_tags_of_indirect_tags_table (); -static void info_reload_file_buffer_contents (); -static char *adjust_nodestart (); -static FILE_BUFFER *info_load_file_internal (), *info_find_file_internal (); -static NODE *info_node_of_file_buffer_tags (); - -static long get_node_length (); - -/* Magic number that RMS used to decide how much a tags table pointer could - be off by. I feel that it should be much smaller, like on the order of - 4. */ -#define DEFAULT_INFO_FUDGE 1000 - -/* Passed to *_internal functions. INFO_GET_TAGS says to do what is - neccessary to fill in the nodes or tags arrays in FILE_BUFFER. */ -#define INFO_NO_TAGS 0 -#define INFO_GET_TAGS 1 - -/* **************************************************************** */ -/* */ -/* Global Variables */ -/* */ -/* **************************************************************** */ - -/* When non-zero, this is a string describing the recent file error. */ -char *info_recent_file_error = (char *)NULL; - -/* The list of already loaded nodes. */ -FILE_BUFFER **info_loaded_files = (FILE_BUFFER **)NULL; - -/* The number of slots currently allocated to LOADED_FILES. */ -int info_loaded_files_slots = 0; - -/* **************************************************************** */ -/* */ -/* Public Functions for Node Manipulation */ -/* */ -/* **************************************************************** */ - -/* Used to build "dir" menu from "localdir" files found in INFOPATH. */ -extern void maybe_build_dir_node (); - -/* Return a pointer to a NODE structure for the Info node (FILENAME)NODENAME. - FILENAME can be passed as NULL, in which case the filename of "dir" is used. - NODENAME can be passed as NULL, in which case the nodename of "Top" is used. - If the node cannot be found, return a NULL pointer. */ -NODE * -info_get_node (filename, nodename) - char *filename, *nodename; -{ - FILE_BUFFER *file_buffer; - NODE *node; - - file_buffer = (FILE_BUFFER *)NULL; - info_recent_file_error = (char *)NULL; - - info_parse_node (nodename, DONT_SKIP_NEWLINES); - nodename = (char *)NULL; - - if (info_parsed_filename) - filename = info_parsed_filename; - - if (info_parsed_nodename) - nodename = info_parsed_nodename; - - /* If FILENAME is not specified, it defaults to "dir". */ - if (!filename) - filename = "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 (strcasecmp (filename, "dir") == 0) - maybe_build_dir_node (filename); - - /* Find the correct info file. */ - file_buffer = info_find_file (filename); - - if (!file_buffer) - { - if (filesys_error_number) - info_recent_file_error = - filesys_error_string (filename, filesys_error_number); - return ((NODE *)NULL); - } - - node = info_get_node_of_file_buffer (nodename, file_buffer); - /* If the node looked for was "Top", try again looking for the node under - a slightly different name. */ - if (!node && (nodename == NULL || strcasecmp (nodename, "Top") == 0)) - { - node = info_get_node_of_file_buffer ("Top", file_buffer); - if (!node) - node = info_get_node_of_file_buffer ("top", file_buffer); - if (!node) - node = info_get_node_of_file_buffer ("TOP", file_buffer); - } - return (node); -} - -/* Return a pointer to a NODE structure for the Info node NODENAME in - FILE_BUFFER. NODENAME can be passed as NULL, in which case the - nodename of "Top" is used. If the node cannot be found, return a - NULL pointer. */ -NODE * -info_get_node_of_file_buffer (nodename, file_buffer) - char *nodename; - FILE_BUFFER *file_buffer; -{ - NODE *node = (NODE *)NULL; - - /* If we are unable to find the file, we have to give up. There isn't - anything else we can do. */ - if (!file_buffer) - return ((NODE *)NULL); - - /* If the file buffer was gc'ed, reload the contents now. */ - if (!file_buffer->contents) - info_reload_file_buffer_contents (file_buffer); - - /* If NODENAME is not specified, it defaults to "Top". */ - if (!nodename) - nodename = "Top"; - - /* If the name of the node that we wish to find is exactly "*", then the - node body is the contents of the entire file. Create and return such - a node. */ - if (strcmp (nodename, "*") == 0) - { - node = (NODE *)xmalloc (sizeof (NODE)); - node->filename = file_buffer->fullpath; - node->parent = (char *)NULL; - node->nodename = strdup ("*"); - node->contents = file_buffer->contents; - node->nodelen = file_buffer->filesize; - node->flags = 0; - } -#if defined (HANDLE_MAN_PAGES) - /* If the file buffer is the magic one associated with manpages, call - the manpage node finding function instead. */ - else if (file_buffer->flags & N_IsManPage) - { - node = get_manpage_node (file_buffer, nodename); - } -#endif /* HANDLE_MAN_PAGES */ - /* If this is the "main" info file, it might contain a tags table. Search - the tags table for an entry which matches the node that we want. If - there is a tags table, get the file which contains this node, but don't - bother building a node list for it. */ - else if (file_buffer->tags) - { - node = info_node_of_file_buffer_tags (file_buffer, nodename); - } - - /* Return the results of our node search. */ - return (node); -} - -/* Locate the file named by FILENAME, and return the information structure - describing this file. The file may appear in our list of loaded files - already, or it may not. If it does not already appear, find the file, - and add it to the list of loaded files. If the file cannot be found, - return a NULL FILE_BUFFER *. */ -FILE_BUFFER * -info_find_file (filename) - char *filename; -{ - return (info_find_file_internal (filename, INFO_GET_TAGS)); -} - -/* Load the info file FILENAME, remembering information about it in a - file buffer. */ -FILE_BUFFER * -info_load_file (filename) - char *filename; -{ - return (info_load_file_internal (filename, INFO_GET_TAGS)); -} - - -/* **************************************************************** */ -/* */ -/* Private Functions Implementation */ -/* */ -/* **************************************************************** */ - -/* The workhorse for info_find_file (). Non-zero 2nd argument says to - try to build a tags table (or otherwise glean the nodes) for this - file once found. By default, we build the tags table, but when this - function is called by info_get_node () when we already have a valid - tags table describing the nodes, it is unnecessary. */ -static FILE_BUFFER * -info_find_file_internal (filename, get_tags) - char *filename; - int get_tags; -{ - register int i; - register FILE_BUFFER *file_buffer; - - /* First try to find the file in our list of already loaded files. */ - if (info_loaded_files) - { - for (i = 0; file_buffer = info_loaded_files[i]; i++) - if ((strcmp (filename, file_buffer->filename) == 0) || - (strcmp (filename, file_buffer->fullpath) == 0) || - ((*filename != '/') && - strcmp (filename, - filename_non_directory (file_buffer->fullpath)) == 0)) - { - struct stat new_info, *old_info; - - /* This file is loaded. If the filename that we want is - specifically "dir", then simply return the file buffer. */ - if (strcasecmp (filename_non_directory (filename), "dir") == 0) - return (file_buffer); - -#if defined (HANDLE_MAN_PAGES) - /* Do the same for the magic MANPAGE file. */ - if (file_buffer->flags & N_IsManPage) - return (file_buffer); -#endif /* HANDLE_MAN_PAGES */ - - /* The file appears to be already loaded, and it is not "dir". - Check to see if it has changed since the last time it was - loaded. */ - if (stat (file_buffer->fullpath, &new_info) == -1) - { - filesys_error_number = errno; - return ((FILE_BUFFER *)NULL); - } - - old_info = &file_buffer->finfo; - - if ((new_info.st_size != old_info->st_size) || - (new_info.st_mtime != old_info->st_mtime)) - { - /* The file has changed. Forget that we ever had loaded it - in the first place. */ - forget_info_file (filename); - break; - } - else - { - /* The info file exists, and has not changed since the last - time it was loaded. If the caller requested a nodes list - for this file, and there isn't one here, build the nodes - for this file_buffer. In any case, return the file_buffer - object. */ - if (get_tags && !file_buffer->tags) - build_tags_and_nodes (file_buffer); - - return (file_buffer); - } - } - } - - /* The file wasn't loaded. Try to load it now. */ -#if defined (HANDLE_MAN_PAGES) - /* If the name of the file that we want is our special file buffer for - Unix manual pages, then create the file buffer, and return it now. */ - if (strcasecmp (filename, MANPAGE_FILE_BUFFER_NAME) == 0) - file_buffer = create_manpage_file_buffer (); - else -#endif /* HANDLE_MAN_PAGES */ - file_buffer = info_load_file_internal (filename, get_tags); - - /* If the file was loaded, remember the name under which it was found. */ - if (file_buffer) - remember_info_file (file_buffer); - - return (file_buffer); -} - -/* The workhorse function for info_load_file (). Non-zero second argument - says to build a list of tags (or nodes) for this file. This is the - default behaviour when info_load_file () is called, but it is not - necessary when loading a subfile for which we already have tags. */ -static FILE_BUFFER * -info_load_file_internal (filename, get_tags) - char *filename; - int get_tags; -{ - char *fullpath, *contents; - long filesize; - struct stat finfo; - int retcode; - FILE_BUFFER *file_buffer = (FILE_BUFFER *)NULL; - - /* Get the full pathname of this file, as known by the info system. - That is to say, search along INFOPATH and expand tildes, etc. */ - fullpath = info_find_fullpath (filename); - - /* Did we actually find the file? */ - retcode = stat (fullpath, &finfo); - - /* If the file referenced by the name returned from info_find_fullpath () - doesn't exist, then try again with the last part of the filename - appearing in lowercase. */ - if (retcode < 0) - { - char *lowered_name; - char *basename; - - lowered_name = strdup (filename); - basename = (char *) strrchr (lowered_name, '/'); - - if (basename) - basename++; - else - basename = lowered_name; - - while (*basename) - { - if (isupper (*basename)) - *basename = tolower (*basename); - - basename++; - } - - fullpath = info_find_fullpath (lowered_name); - free (lowered_name); - - retcode = stat (fullpath, &finfo); - } - - /* If the file wasn't found, give up, returning a NULL pointer. */ - if (retcode < 0) - { - filesys_error_number = errno; - return ((FILE_BUFFER *)NULL); - } - - /* Otherwise, try to load the file. */ - contents = filesys_read_info_file (fullpath, &filesize, &finfo); - - if (!contents) - return ((FILE_BUFFER *)NULL); - - /* The file was found, and can be read. Allocate FILE_BUFFER and fill - in the various members. */ - file_buffer = make_file_buffer (); - file_buffer->filename = strdup (filename); - file_buffer->fullpath = strdup (fullpath); - file_buffer->finfo = finfo; - file_buffer->filesize = filesize; - file_buffer->contents = contents; - if (file_buffer->filesize != file_buffer->finfo.st_size) - file_buffer->flags |= N_IsCompressed; - - /* If requested, build the tags and nodes for this file buffer. */ - if (get_tags) - build_tags_and_nodes (file_buffer); - - return (file_buffer); -} - -/* Grovel FILE_BUFFER->contents finding tags and nodes, and filling in the - various slots. This can also be used to rebuild a tag or node table. */ -void -build_tags_and_nodes (file_buffer) - FILE_BUFFER *file_buffer; -{ - SEARCH_BINDING binding; - long position; - - free_file_buffer_tags (file_buffer); - file_buffer->flags &= ~N_HasTagsTable; - - /* See if there is a tags table in this info file. */ - binding.buffer = file_buffer->contents; - binding.start = file_buffer->filesize; - binding.end = binding.start - 1000; - if (binding.end < 0) - binding.end = 0; - binding.flags = S_FoldCase; - - position = search_backward (TAGS_TABLE_END_LABEL, &binding); - - /* If there is a tag table, find the start of it, and grovel over it - extracting tag information. */ - if (position != -1) - while (1) - { - long tags_table_begin, tags_table_end; - - binding.end = position; - binding.start = binding.end - 5 - strlen (TAGS_TABLE_END_LABEL); - if (binding.start < 0) - binding.start = 0; - - position = find_node_separator (&binding); - - /* For this test, (and all others here) failure indicates a bogus - tags table. Grovel the file. */ - if (position == -1) - break; - - /* Remember the end of the tags table. */ - binding.start = position; - tags_table_end = binding.start; - binding.end = 0; - - /* Locate the start of the tags table. */ - position = search_backward (TAGS_TABLE_BEG_LABEL, &binding); - - if (position == -1) - break; - - binding.end = position; - binding.start = binding.end - 5 - strlen (TAGS_TABLE_BEG_LABEL); - position = find_node_separator (&binding); - - if (position == -1) - break; - - /* The file contains a valid tags table. Fill the FILE_BUFFER's - tags member. */ - 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. */ - binding.start = binding.end; - binding.end = file_buffer->filesize; - - if (!looking_at (TAGS_TABLE_IS_INDIRECT_LABEL, &binding)) - { - binding.start = tags_table_begin; - binding.end = tags_table_end; - get_nodes_of_tags_table (file_buffer, &binding); - return; - } - else - { - /* This is an indirect tags table. Build TAGS member. */ - SEARCH_BINDING indirect; - - indirect.start = tags_table_begin; - indirect.end = 0; - indirect.buffer = binding.buffer; - indirect.flags = S_FoldCase; - - position = search_backward (INDIRECT_TAGS_TABLE_LABEL, &indirect); - - if (position == -1) - { - /* This file is malformed. Give up. */ - return; - } - - indirect.start = position; - indirect.end = tags_table_begin; - binding.start = tags_table_begin; - binding.end = tags_table_end; - get_tags_of_indirect_tags_table (file_buffer, &indirect, &binding); - return; - } - } - - /* This file doesn't contain any kind of tags table. Grovel the - file and build node entries for it. */ - get_nodes_of_info_file (file_buffer); -} - -/* Search through FILE_BUFFER->contents building an array of TAG *, - 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 -get_nodes_of_info_file (file_buffer) - FILE_BUFFER *file_buffer; -{ - long nodestart; - int tags_index = 0; - SEARCH_BINDING binding; - - binding.buffer = file_buffer->contents; - binding.start = 0; - binding.end = file_buffer->filesize; - binding.flags = S_FoldCase; - - while ((nodestart = find_node_separator (&binding)) != -1) - { - int start, end; - char *nodeline; - TAG *entry; - - /* Skip past the characters just found. */ - binding.start = nodestart; - binding.start += skip_node_separator (binding.buffer + binding.start); - - /* Move to the start of the line defining the node. */ - nodeline = binding.buffer + binding.start; - - /* Find "Node:" */ - start = string_in_line (INFO_NODE_LABEL, nodeline); - - /* If not there, this is not the start of a node. */ - if (start == -1) - continue; - - /* Find the start of the nodename. */ - start += skip_whitespace (nodeline + start); - - /* Find the end of the nodename. */ - end = start + - skip_node_characters (nodeline + start, DONT_SKIP_NEWLINES); - - /* Okay, we have isolated the node name, and we know where the - node starts. Remember this information in a NODE structure. */ - entry = (TAG *)xmalloc (sizeof (TAG)); - entry->nodename = (char *)xmalloc (1 + (end - start)); - strncpy (entry->nodename, nodeline + start, end - start); - entry->nodename[end - start] = '\0'; - entry->nodestart = nodestart; - { - SEARCH_BINDING node_body; - - node_body.buffer = binding.buffer + binding.start; - node_body.start = 0; - node_body.end = binding.end - binding.start; - node_body.flags = S_FoldCase; - 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, TAG *); - } -} - -/* Return the length of the node which starts at BINDING. */ -static long -get_node_length (binding) - SEARCH_BINDING *binding; -{ - register int i; - char *body; - - /* From the Info-RFC file: - [A node] ends with either a ^_, a ^L, or the end of file. */ - for (i = binding->start, body = binding->buffer; i < binding->end; i++) - { - if (body[i] == INFO_FF || body[i] == INFO_COOKIE) - break; - } - return ((long) i - binding->start); -} - -/* Build and save the array of nodes in FILE_BUFFER by searching through the - contents of BUFFER_BINDING for a tags table, and groveling the contents. */ -static void -get_nodes_of_tags_table (file_buffer, buffer_binding) - FILE_BUFFER *file_buffer; - SEARCH_BINDING *buffer_binding; -{ - int offset, tags_index = 0; - SEARCH_BINDING *search; - long position; - - search = copy_binding (buffer_binding); - - /* Find the start of the tags table. */ - position = find_tags_table (search); - - /* If none, we're all done. */ - if (position == -1) - return; - - /* Move to one character before the start of the actual table. */ - search->start = position; - search->start += skip_node_separator (search->buffer + search->start); - search->start += strlen (TAGS_TABLE_BEG_LABEL); - search->start--; - - /* The tag table consists of lines containing node names and positions. - Do each line until we find one that doesn't contain a node name. */ - while ((position = search_forward ("\n", search)) != -1) - { - TAG *entry; - char *nodedef; - - /* Prepare to skip this line. */ - search->start = position; - search->start++; - - /* Skip past informative "(Indirect)" tags table line. */ - if (!tags_index && looking_at (TAGS_TABLE_IS_INDIRECT_LABEL, search)) - continue; - - /* Find the label preceding the node name. */ - offset = - string_in_line (INFO_NODE_LABEL, search->buffer + search->start); - - /* If not there, not a defining line, so we must be out of the - tags table. */ - if (offset == -1) - break; - - /* Point to the beginning of the node definition. */ - search->start += offset; - nodedef = search->buffer + search->start; - nodedef += skip_whitespace (nodedef); - - /* Move past the node's name. */ - for (offset = 0; - (nodedef[offset]) && (nodedef[offset] != INFO_TAGSEP); - offset++); - - if (nodedef[offset] != INFO_TAGSEP) - continue; - - entry = (TAG *)xmalloc (sizeof (TAG)); - entry->nodename = (char *)xmalloc (1 + offset); - strncpy (entry->nodename, nodedef, offset); - entry->nodename[offset] = '\0'; - offset++; - entry->nodestart = (long) atol (nodedef + offset); - - /* We don't know the length of this node yet. */ - entry->nodelen = -1; - - /* The filename of this node is currently known as the same as the - name of this file. */ - entry->filename = file_buffer->fullpath; - - /* 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, TAG *); - } - free (search); -} - -/* A structure used only in get_tags_of_indirect_tags_table () to hold onto - an intermediate value. */ -typedef struct { - char *filename; - long first_byte; -} SUBFILE; - -/* Remember in FILE_BUFFER the nodenames, subfilenames, and offsets within the - subfiles of every node which appears in TAGS_BINDING. The 2nd argument is - a binding surrounding the indirect files list. */ -static void -get_tags_of_indirect_tags_table (file_buffer, indirect_binding, tags_binding) - FILE_BUFFER *file_buffer; - SEARCH_BINDING *indirect_binding, *tags_binding; -{ - register int i; - SUBFILE **subfiles = (SUBFILE **)NULL; - int subfiles_index = 0, subfiles_slots = 0; - TAG *entry; - - /* First get the list of tags from the tags table. Then lookup the - associated file in the indirect list for each tag, and update it. */ - get_nodes_of_tags_table (file_buffer, tags_binding); - - /* We have the list of tags in file_buffer->tags. Get the list of - subfiles from the indirect table. */ - { - char *start, *end, *line; - SUBFILE *subfile; - - start = indirect_binding->buffer + indirect_binding->start; - end = indirect_binding->buffer + indirect_binding->end; - line = start; - - while (line < end) - { - int colon; - - colon = string_in_line (":", line); - - if (colon == -1) - break; - - subfile = (SUBFILE *)xmalloc (sizeof (SUBFILE)); - subfile->filename = (char *)xmalloc (colon); - strncpy (subfile->filename, line, colon - 1); - subfile->filename[colon - 1] = '\0'; - subfile->first_byte = (long) atol (line + colon); - - add_pointer_to_array - (subfile, subfiles_index, subfiles, subfiles_slots, 10, SUBFILE *); - - while (*line++ != '\n'); - } - } - - /* If we have successfully built the indirect files table, then - merge the information in the two tables. */ - if (!subfiles) - { - free_file_buffer_tags (file_buffer); - return; - } - else - { - register int tags_index; - long header_length; - SEARCH_BINDING binding; - - /* Find the length of the header of the file containing the indirect - tags table. This header appears at the start of every file. We - want the absolute position of each node within each subfile, so - we subtract the start of the containing subfile from the logical - position of the node, and then add the length of the header in. */ - binding.buffer = file_buffer->contents; - binding.start = 0; - binding.end = file_buffer->filesize; - binding.flags = S_FoldCase; - - header_length = find_node_separator (&binding); - if (header_length == -1) - header_length = 0; - - /* Build the file buffer's list of subfiles. */ - { - char *containing_dir, *temp; - int len_containing_dir; - - containing_dir = strdup (file_buffer->fullpath); - temp = (char *) strrchr (containing_dir, '/'); - - if (temp) - *temp = '\0'; - - len_containing_dir = strlen (containing_dir); - - for (i = 0; subfiles[i]; i++); - - file_buffer->subfiles = (char **) xmalloc ((1 + i) * sizeof (char *)); - - for (i = 0; subfiles[i]; i++) - { - char *fullpath; - - fullpath = (char *) xmalloc - (2 + strlen (subfiles[i]->filename) + len_containing_dir); - - sprintf (fullpath, "%s/%s", - containing_dir, subfiles[i]->filename); - - file_buffer->subfiles[i] = fullpath; - } - file_buffer->subfiles[i] = (char *)NULL; - free (containing_dir); - } - - /* For each node in the file's tags table, remember the starting - position. */ - for (tags_index = 0; - entry = file_buffer->tags[tags_index]; - tags_index++) - { - for (i = 0; - subfiles[i] && entry->nodestart >= subfiles[i]->first_byte; - i++); - - /* If the Info file containing the indirect tags table is - malformed, then give up. */ - if (!i) - { - /* The Info file containing the indirect tags table is - malformed. Give up. */ - for (i = 0; subfiles[i]; i++) - { - free (subfiles[i]->filename); - free (subfiles[i]); - free (file_buffer->subfiles[i]); - } - file_buffer->subfiles = (char **)NULL; - free_file_buffer_tags (file_buffer); - return; - } - - /* SUBFILES[i] is the index of the first subfile whose logical - first byte is greater than the logical offset of this node's - starting position. This means that the subfile directly - preceding this one is the one containing the node. */ - - entry->filename = file_buffer->subfiles[i - 1]; - entry->nodestart -= subfiles[i -1]->first_byte; - entry->nodestart += header_length; - entry->nodelen = -1; - } - - /* We have successfully built the tags table. Remember that it - was indirect. */ - file_buffer->flags |= N_TagsIndirect; - } - - /* Free the structures assigned to SUBFILES. Free the names as well - as the structures themselves, then finally, the array. */ - for (i = 0; subfiles[i]; i++) - { - free (subfiles[i]->filename); - free (subfiles[i]); - } - free (subfiles); -} - -/* Return the node from FILE_BUFFER which matches NODENAME by searching - the tags table in FILE_BUFFER. If the node could not be found, return - a NULL pointer. */ -static NODE * -info_node_of_file_buffer_tags (file_buffer, nodename) - FILE_BUFFER *file_buffer; - char *nodename; -{ - register int i; - TAG *tag; - - for (i = 0; tag = file_buffer->tags[i]; i++) - if (strcmp (nodename, tag->nodename) == 0) - { - FILE_BUFFER *subfile; - - subfile = info_find_file_internal (tag->filename, INFO_NO_TAGS); - - if (!subfile) - return ((NODE *)NULL); - - if (!subfile->contents) - { - info_reload_file_buffer_contents (subfile); - - if (!subfile->contents) - return ((NODE *)NULL); - } - - /* If we were able to find this file and load it, then return - the node within it. */ - { - NODE *node; - - node = (NODE *)xmalloc (sizeof (NODE)); - node->filename = (subfile->fullpath); - node->nodename = tag->nodename; - node->contents = subfile->contents + tag->nodestart; - node->flags = 0; - node->parent = (char *)NULL; - - if (file_buffer->flags & N_HasTagsTable) - { - node->flags |= N_HasTagsTable; - - if (file_buffer->flags & N_TagsIndirect) - { - node->flags |= N_TagsIndirect; - node->parent = file_buffer->fullpath; - } - } - - if (subfile->flags & N_IsCompressed) - node->flags |= N_IsCompressed; - - /* If TAG->nodelen hasn't been calculated yet, then we aren't - in a position to trust the entry pointer. Adjust things so - that ENTRY->nodestart gets the exact address of the start of - the node separator which starts this node, and NODE->contents - gets the address of the line defining this node. If we cannot - do that, the node isn't really here. */ - if (tag->nodelen == -1) - { - int min, max; - char *node_sep; - SEARCH_BINDING node_body; - char *buff_end; - - min = max = DEFAULT_INFO_FUDGE; - - if (tag->nodestart < DEFAULT_INFO_FUDGE) - min = tag->nodestart; - - if (DEFAULT_INFO_FUDGE > - (subfile->filesize - tag->nodestart)) - max = subfile->filesize - tag->nodestart; - - /* NODE_SEP gets the address of the separator which defines - this node, or (char *)NULL if the node wasn't found. - NODE->contents is side-effected to point to right after - the separator. */ - node_sep = adjust_nodestart (node, min, max); - if (node_sep == (char *)NULL) - { - free (node); - return ((NODE *)NULL); - } - /* Readjust tag->nodestart. */ - tag->nodestart = node_sep - subfile->contents; - - /* Calculate the length of the current node. */ - buff_end = subfile->contents + subfile->filesize; - - node_body.buffer = node->contents; - node_body.start = 0; - node_body.end = buff_end - node_body.buffer; - node_body.flags = 0; - tag->nodelen = get_node_length (&node_body); - } - else - { - /* Since we know the length of this node, we have already - adjusted tag->nodestart to point to the exact start of - it. Simply skip the node separator. */ - node->contents += skip_node_separator (node->contents); - } - - node->nodelen = tag->nodelen; - return (node); - } - } - - /* There was a tag table for this file, and the node wasn't found. - Return NULL, since this file doesn't contain the desired node. */ - return ((NODE *)NULL); -} - -/* **************************************************************** */ -/* */ -/* Managing file_buffers, nodes, and tags. */ -/* */ -/* **************************************************************** */ - -/* Create a new, empty file buffer. */ -FILE_BUFFER * -make_file_buffer () -{ - FILE_BUFFER *file_buffer; - - file_buffer = (FILE_BUFFER *)xmalloc (sizeof (FILE_BUFFER)); - file_buffer->filename = file_buffer->fullpath = (char *)NULL; - file_buffer->contents = (char *)NULL; - file_buffer->tags = (TAG **)NULL; - file_buffer->subfiles = (char **)NULL; - file_buffer->tags_slots = 0; - file_buffer->flags = 0; - - return (file_buffer); -} - -/* Add FILE_BUFFER to our list of already loaded info files. */ -static void -remember_info_file (file_buffer) - FILE_BUFFER *file_buffer; -{ - int i; - - for (i = 0; info_loaded_files && info_loaded_files[i]; i++) - ; - - add_pointer_to_array (file_buffer, i, info_loaded_files, - info_loaded_files_slots, 10, FILE_BUFFER *); -} - -/* Forget the contents, tags table, nodes list, and names of FILENAME. */ -static void -forget_info_file (filename) - char *filename; -{ - register int i; - FILE_BUFFER *file_buffer; - - if (!info_loaded_files) - return; - - for (i = 0; file_buffer = info_loaded_files[i]; i++) - if ((strcmp (filename, file_buffer->filename) == 0) || - (strcmp (filename, file_buffer->fullpath) == 0)) - { - free (file_buffer->filename); - free (file_buffer->fullpath); - - if (file_buffer->contents) - free (file_buffer->contents); - - /* Note that free_file_buffer_tags () also kills the subfiles - list, since the subfiles list is only of use in conjunction - with tags. */ - free_file_buffer_tags (file_buffer); - - while (info_loaded_files[i] = info_loaded_files[++i]) - ; - - break; - } -} - -/* Free the tags (if any) associated with FILE_BUFFER. */ -static void -free_file_buffer_tags (file_buffer) - FILE_BUFFER *file_buffer; -{ - register int i; - - if (file_buffer->tags) - { - register TAG *tag; - - for (i = 0; tag = file_buffer->tags[i]; i++) - free_info_tag (tag); - - free (file_buffer->tags); - file_buffer->tags = (TAG **)NULL; - file_buffer->tags_slots = 0; - } - - if (file_buffer->subfiles) - { - for (i = 0; file_buffer->subfiles[i]; i++) - free (file_buffer->subfiles[i]); - - free (file_buffer->subfiles); - file_buffer->subfiles = (char **)NULL; - } -} - -/* Free the data associated with TAG, as well as TAG itself. */ -static void -free_info_tag (tag) - TAG *tag; -{ - free (tag->nodename); - - /* We don't free tag->filename, because that filename is part of the - subfiles list for the containing FILE_BUFFER. free_info_tags () - will free the subfiles when it is appropriate. */ - - free (tag); -} - -/* Load the contents of FILE_BUFFER->contents. This function is called - when a file buffer was loaded, and then in order to conserve memory, the - file buffer's contents were freed and the pointer was zero'ed. Note that - the file was already loaded at least once successfully, so the tags and/or - nodes members are still correctly filled. */ -static void -info_reload_file_buffer_contents (fb) - FILE_BUFFER *fb; -{ - -#if defined (HANDLE_MAN_PAGES) - /* If this is the magic manpage node, don't try to reload, just give up. */ - if (fb->flags & N_IsManPage) - return; -#endif - - fb->flags &= ~N_IsCompressed; - - /* Let the filesystem do all the work for us. */ - fb->contents = - filesys_read_info_file (fb->fullpath, &(fb->filesize), &(fb->finfo)); - if (fb->filesize != (long) (fb->finfo.st_size)) - fb->flags |= N_IsCompressed; -} - -/* Return the actual starting memory location of NODE, side-effecting - NODE->contents. MIN and MAX are bounds for a search if one is necessary. - Because of the way that tags are implemented, the physical nodestart may - not actually be where the tag says it is. If that is the case, but the - node was found anyway, set N_UpdateTags in NODE->flags. If the node is - found, return non-zero. NODE->contents is returned positioned right after - the node separator that precedes this node, while the return value is - position directly on the separator that precedes this node. If the node - could not be found, return a NULL pointer. */ -static char * -adjust_nodestart (node, min, max) - NODE *node; - int min, max; -{ - long position; - SEARCH_BINDING node_body; - - /* Define the node body. */ - node_body.buffer = node->contents; - node_body.start = 0; - node_body.end = max; - node_body.flags = 0; - - /* Try the optimal case first. Who knows? This file may actually be - formatted (mostly) correctly. */ - if (node_body.buffer[0] != INFO_COOKIE && min > 2) - node_body.buffer -= 3; - - position = find_node_separator (&node_body); - - /* If we found a node start, then check it out. */ - if (position != -1) - { - int sep_len; - - sep_len = skip_node_separator (node->contents); - - /* If we managed to skip a node separator, then check for this node - being the right one. */ - if (sep_len != 0) - { - char *nodedef, *nodestart; - int offset; - - nodestart = node_body.buffer + position + sep_len; - nodedef = nodestart; - offset = string_in_line (INFO_NODE_LABEL, nodedef); - - if (offset != -1) - { - nodedef += offset; - nodedef += skip_whitespace (nodedef); - offset = skip_node_characters (nodedef, DONT_SKIP_NEWLINES); - if ((offset == strlen (node->nodename)) && - (strncmp (node->nodename, nodedef, offset) == 0)) - { - node->contents = nodestart; - return (node_body.buffer + position); - } - } - } - } - - /* Oh well, I guess we have to try to find it in a larger area. */ - node_body.buffer = node->contents - min; - node_body.start = 0; - node_body.end = min + max; - node_body.flags = 0; - - position = find_node_in_binding (node->nodename, &node_body); - - /* If the node couldn't be found, we lose big. */ - if (position == -1) - return ((char *)NULL); - - /* Otherwise, the node was found, but the tags table could need updating - (if we used a tag to get here, that is). Set the flag in NODE->flags. */ - node->contents = node_body.buffer + position; - node->contents += skip_node_separator (node->contents); - if (node->flags & N_HasTagsTable) - node->flags |= N_UpdateTags; - return (node_body.buffer + position); -} diff --git a/info/nodes.h b/info/nodes.h deleted file mode 100644 --- a/info/nodes.h +++ /dev/null @@ -1,168 +0,0 @@ -/* nodes.h -- How we represent nodes internally. */ - -/* 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). */ - -#if !defined (_NODES_H_) -#define _NODES_H_ - -#include "general.h" - -/* **************************************************************** */ -/* */ -/* User Code Interface */ -/* */ -/* **************************************************************** */ - -/* Callers generally only want the node itself. This structure is used - to pass node information around. None of the information in this - structure should ever be directly freed. The structure itself can - be passed to free (). Note that NODE->parent is non-null if this - node's file is a subfile. In that case, NODE->parent is the logical - name of the file containing this node. Both names are given as full - paths, so you might have: node->filename = "/usr/gnu/info/emacs-1", - with node->parent = "/usr/gnu/info/emacs". */ -typedef struct { - char *filename; /* The physical file containing this node. */ - char *parent; /* Non-null is the logical file name. */ - char *nodename; /* The name of this node. */ - char *contents; /* Characters appearing in this node. */ - long nodelen; /* The length of the CONTENTS member. */ - int flags; /* See immediately below. */ -} NODE; - -/* Defines that can appear in NODE->flags. All informative. */ -#define N_HasTagsTable 0x01 /* This node was found through a tags table. */ -#define N_TagsIndirect 0x02 /* The tags table was an indirect one. */ -#define N_UpdateTags 0x04 /* The tags table is out of date. */ -#define N_IsCompressed 0x08 /* The file is compressed on disk. */ -#define N_IsInternal 0x10 /* This node was made by Info. */ -#define N_CannotGC 0x20 /* File buffer cannot be gc'ed. */ -#define N_IsManPage 0x40 /* This node is a Un*x manpage. */ - -/* **************************************************************** */ -/* */ -/* Internal Data Structures */ -/* */ -/* **************************************************************** */ - -/* Some defines describing details about Info file contents. */ - -/* String Constants. */ -#define INFO_FILE_LABEL "File:" -#define INFO_NODE_LABEL "Node:" -#define INFO_PREV_LABEL "Prev:" -#define INFO_ALTPREV_LABEL "Previous:" -#define INFO_NEXT_LABEL "Next:" -#define INFO_UP_LABEL "Up:" -#define INFO_MENU_LABEL "\n* Menu:" -#define INFO_MENU_ENTRY_LABEL "\n* " -#define INFO_XREF_LABEL "*Note" -#define TAGS_TABLE_END_LABEL "\nEnd Tag Table" -#define TAGS_TABLE_BEG_LABEL "Tag Table:\n" -#define INDIRECT_TAGS_TABLE_LABEL "Indirect:\n" -#define TAGS_TABLE_IS_INDIRECT_LABEL "(Indirect)" - -/* Character Constants. */ -#define INFO_COOKIE '\037' -#define INFO_FF '\014' -#define INFO_TAGSEP '\177' - -/* For each logical file that we have loaded, we keep a list of the names - of the nodes that are found in that file. A pointer to a node in an - info file is called a "tag". For split files, the tag pointer is - "indirect"; that is, the pointer also contains the name of the split - file where the node can be found. For non-split files, the filename - member in the structure below simply contains the name of the current - file. The following structure describes a single node within a file. */ -typedef struct { - char *filename; /* The file where this node can be found. */ - char *nodename; /* The node pointed to by this tag. */ - long nodestart; /* The offset of the start of this node. */ - long nodelen; /* The length of this node. */ -} TAG; - -/* The following structure is used to remember information about the contents - of Info files that we have loaded at least once before. The FINFO member - is present so that we can reload the file if it has been modified since - last being loaded. All of the arrays appearing within this structure - are NULL terminated, and each array which can change size has a - corresponding SLOTS member which says how many slots have been allocated - (with malloc ()) for this array. */ -typedef struct { - char *filename; /* The filename used to find this file. */ - char *fullpath; /* The full pathname of this info file. */ - struct stat finfo; /* Information about this file. */ - char *contents; /* The contents of this particular file. */ - long filesize; /* The number of bytes this file expands to. */ - char **subfiles; /* If non-null, the list of subfiles. */ - TAG **tags; /* If non-null, the indirect tags table. */ - int tags_slots; /* Number of slots allocated for TAGS. */ - int flags; /* Various flags. Mimics of N_* flags. */ -} FILE_BUFFER; - -/* **************************************************************** */ -/* */ -/* Externally Visible Functions */ -/* */ -/* **************************************************************** */ - -/* Array of FILE_BUFFER * which represents the currently loaded info files. */ -extern FILE_BUFFER **info_loaded_files; - -/* The number of slots currently allocated to INFO_LOADED_FILES. */ -extern int info_loaded_files_slots; - -/* Locate the file named by FILENAME, and return the information structure - describing this file. The file may appear in our list of loaded files - already, or it may not. If it does not already appear, find the file, - and add it to the list of loaded files. If the file cannot be found, - return a NULL FILE_BUFFER *. */ -extern FILE_BUFFER *info_find_file (); - -/* Force load the file named FILENAME, and return the information structure - describing this file. Even if the file was already loaded, this loads - a new buffer, rebuilds tags and nodes, and returns a new FILE_BUFFER *. */ -extern FILE_BUFFER *info_load_file (); - -/* Return a pointer to a NODE structure for the Info node (FILENAME)NODENAME. - FILENAME can be passed as NULL, in which case the filename of "dir" is used. - NODENAME can be passed as NULL, in which case the nodename of "Top" is used. - If the node cannot be found, return a NULL pointer. */ -extern NODE *info_get_node (); - -/* Return a pointer to a NODE structure for the Info node NODENAME in - FILE_BUFFER. NODENAME can be passed as NULL, in which case the - nodename of "Top" is used. If the node cannot be found, return a - NULL pointer. */ -extern NODE *info_get_node_of_file_buffer (); - -/* Grovel FILE_BUFFER->contents finding tags and nodes, and filling in the - various slots. This can also be used to rebuild a tag or node table. */ -extern void build_tags_and_nodes (); - -/* When non-zero, this is a string describing the most recent file error. */ -extern char *info_recent_file_error; - -/* Create a new, empty file buffer. */ -extern FILE_BUFFER *make_file_buffer (); - -#endif /* !_NODES_H_ */ diff --git a/info/search.c b/info/search.c deleted file mode 100644 --- a/info/search.c +++ /dev/null @@ -1,519 +0,0 @@ -/* search.c -- How to search large bodies of text. */ - -/* 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 -#include -#include -#include "general.h" -#include "search.h" -#include "nodes.h" - -#if !defined (NULL) -# define NULL 0x0 -#endif /* !NULL */ - -/* The search functions take two arguments: - - 1) a string to search for, and - - 2) a pointer to a SEARCH_BINDING which contains the buffer, start, - and end of the search. - - They return a long, which is the offset from the start of the buffer - at which the match was found. An offset of -1 indicates failure. */ - -/* A function which makes a binding with buffer and bounds. */ -SEARCH_BINDING * -make_binding (buffer, start, end) - char *buffer; - long start, end; -{ - SEARCH_BINDING *binding; - - binding = (SEARCH_BINDING *)xmalloc (sizeof (SEARCH_BINDING)); - binding->buffer = buffer; - binding->start = start; - binding->end = end; - binding->flags = 0; - - return (binding); -} - -/* Make a copy of BINDING without duplicating the data. */ -SEARCH_BINDING * -copy_binding (binding) - SEARCH_BINDING *binding; -{ - SEARCH_BINDING *copy; - - copy = make_binding (binding->buffer, binding->start, binding->end); - copy->flags = binding->flags; - return (copy); -} - - -/* **************************************************************** */ -/* */ -/* The Actual Searching Functions */ -/* */ -/* **************************************************************** */ - -/* Search forwards or backwards for the text delimited by BINDING. - The search is forwards if BINDING->start is greater than BINDING->end. */ -long -search (string, binding) - char *string; - SEARCH_BINDING *binding; -{ - long result; - - /* If the search is backwards, then search backwards, otherwise forwards. */ - if (binding->start > binding->end) - result = search_backward (string, binding); - else - result = search_forward (string, binding); - - return (result); -} - -/* Search forwards for STRING through the text delimited in BINDING. */ -long -search_forward (string, binding) - char *string; - SEARCH_BINDING *binding; -{ - register int c, i, len; - register char *buff, *end; - char *alternate = (char *)NULL; - - len = strlen (string); - - /* We match characters in the search buffer against STRING and ALTERNATE. - ALTERNATE is a case reversed version of STRING; this is cheaper than - case folding each character before comparison. Alternate is only - used if the case folding bit is turned on in the passed BINDING. */ - - if (binding->flags & S_FoldCase) - { - alternate = strdup (string); - - for (i = 0; i < len; i++) - { - if (islower (alternate[i])) - alternate[i] = toupper (alternate[i]); - else if (isupper (alternate[i])) - alternate[i] = tolower (alternate[i]); - } - } - - buff = binding->buffer + binding->start; - end = binding->buffer + binding->end + 1; - - while (buff < (end - len)) - { - for (i = 0; i < len; i++) - { - c = buff[i]; - - if ((c != string[i]) && (!alternate || c != alternate[i])) - break; - } - - if (!string[i]) - { - if (alternate) - free (alternate); - if (binding->flags & S_SkipDest) - buff += len; - return ((long) (buff - binding->buffer)); - } - - buff++; - } - - if (alternate) - free (alternate); - - return ((long) -1); -} - -/* Search for STRING backwards through the text delimited in BINDING. */ -long -search_backward (input_string, binding) - char *input_string; - SEARCH_BINDING *binding; -{ - register int c, i, len; - register char *buff, *end; - char *string; - char *alternate = (char *)NULL; - - len = strlen (input_string); - - /* Reverse the characters in the search string. */ - string = (char *)xmalloc (1 + len); - for (c = 0, i = len - 1; input_string[c]; c++, i--) - string[i] = input_string[c]; - - string[c] = '\0'; - - /* We match characters in the search buffer against STRING and ALTERNATE. - ALTERNATE is a case reversed version of STRING; this is cheaper than - case folding each character before comparison. ALTERNATE is only - used if the case folding bit is turned on in the passed BINDING. */ - - if (binding->flags & S_FoldCase) - { - alternate = strdup (string); - - for (i = 0; i < len; i++) - { - if (islower (alternate[i])) - alternate[i] = toupper (alternate[i]); - else if (isupper (alternate[i])) - alternate[i] = tolower (alternate[i]); - } - } - - buff = binding->buffer + binding->start - 1; - end = binding->buffer + binding->end; - - while (buff > (end + len)) - { - for (i = 0; i < len; i++) - { - c = *(buff - i); - - if (c != string[i] && (alternate && c != alternate[i])) - break; - } - - if (!string[i]) - { - free (string); - if (alternate) - free (alternate); - - if (binding->flags & S_SkipDest) - buff -= len; - return ((long) (1 + (buff - binding->buffer))); - } - - buff--; - } - - free (string); - if (alternate) - free (alternate); - - return ((long) -1); -} - -/* Find STRING in LINE, returning the offset of the end of the string. - Return an offset of -1 if STRING does not appear in LINE. The search - is bound by the end of the line (i.e., either NEWLINE or 0). */ -int -string_in_line (string, line) - char *string, *line; -{ - register int end; - SEARCH_BINDING binding; - - /* Find the end of the line. */ - for (end = 0; line[end] && line[end] != '\n'; end++); - - /* Search for STRING within these confines. */ - binding.buffer = line; - binding.start = 0; - binding.end = end; - binding.flags = S_FoldCase | S_SkipDest; - - return (search_forward (string, &binding)); -} - -/* Return non-zero if STRING is the first text to appear at BINDING. */ -int -looking_at (string, binding) - char *string; - SEARCH_BINDING *binding; -{ - long search_end; - - search_end = search (string, binding); - - /* If the string was not found, SEARCH_END is -1. If the string was found, - but not right away, SEARCH_END is != binding->start. Otherwise, the - string was found at binding->start. */ - return (search_end == binding->start); -} - -/* **************************************************************** */ -/* */ -/* Small String Searches */ -/* */ -/* **************************************************************** */ - -/* Function names that start with "skip" are passed a string, and return - an offset from the start of that string. Function names that start - with "find" are passed a SEARCH_BINDING, and return an absolute position - marker of the item being searched for. "Find" functions return a value - of -1 if the item being looked for couldn't be found. */ - -/* Return the index of the first non-whitespace character in STRING. */ -int -skip_whitespace (string) - char *string; -{ - register int i; - - for (i = 0; string && whitespace (string[i]); i++); - return (i); -} - -/* Return the index of the first non-whitespace or newline character in - STRING. */ -int -skip_whitespace_and_newlines (string) - char *string; -{ - register int i; - - for (i = 0; string && (whitespace (string[i]) || string[i] == '\n'); i++); - return (i); -} - -/* Return the index of the first whitespace character in STRING. */ -int -skip_non_whitespace (string) - char *string; -{ - register int i; - - for (i = 0; string && !whitespace (string[i]); i++); - return (i); -} - -/* Return the index of the first non-node character in STRING. Note that - this function contains quite a bit of hair to ignore periods in some - special cases. This is because we here at GNU ship some info files which - contain nodenames that contain periods. No such nodename can start with - a period, or continue with whitespace, newline, or ')' immediately following - the period. If second argument NEWLINES_OKAY is non-zero, newlines should - be skipped while parsing out the nodename specification. */ -int -skip_node_characters (string, newlines_okay) - char *string; - int newlines_okay; -{ - register int c, i = 0; - int paren_seen = 0; - int paren = 0; - - /* Handle special case. This is when another function has parsed out the - filename component of the node name, and we just want to parse out the - nodename proper. In that case, a period at the start of the nodename - indicates an empty nodename. */ - if (string && *string == '.') - return (0); - - if (string && *string == '(') - { - paren++; - paren_seen++; - i++; - } - - for (; string && (c = string[i]); i++) - { - if (paren) - { - if (c == '(') - paren++; - else if (c == ')') - paren--; - - continue; - } - - /* If the character following the close paren is a space or period, - then this node name has no more characters associated with it. */ - if (c == '\t' || - c == ',' || - c == INFO_TAGSEP || - ((!newlines_okay) && (c == '\n')) || - ((paren_seen && string[i - 1] == ')') && - (c == ' ' || c == '.')) || - (c == '.' && - ((!string[i + 1]) || - (whitespace_or_newline (string[i + 1])) || - (string[i + 1] == ')')))) - break; - } - return (i); -} - - -/* **************************************************************** */ -/* */ -/* Searching FILE_BUFFER's */ -/* */ -/* **************************************************************** */ - -/* Return the absolute position of the first occurence of a node separator in - BINDING-buffer. The search starts at BINDING->start. Return -1 if no node - separator was found. */ -long -find_node_separator (binding) - SEARCH_BINDING *binding; -{ - register long i; - char *body; - - body = binding->buffer; - - /* A node is started by [^L]^_[^L]\n. That is to say, the C-l's are - optional, but the DELETE and NEWLINE are not. This separator holds - true for all separated elements in an Info file, including the tags - table (if present) and the indirect tags table (if present). */ - for (i = binding->start; i < binding->end - 1; i++) - if (((body[i] == INFO_FF && body[i + 1] == INFO_COOKIE) && - (body[i + 2] == '\n' || - (body[i + 2] == INFO_FF && body[i + 3] == '\n'))) || - ((body[i] == INFO_COOKIE) && - (body[i + 1] == '\n' || - (body[i + 1] == INFO_FF && body[i + 2] == '\n')))) - return (i); - return (-1); -} - -/* Return the length of the node separator characters that BODY is - currently pointing at. */ -int -skip_node_separator (body) - char *body; -{ - register int i; - - i = 0; - - if (body[i] == INFO_FF) - i++; - - if (body[i++] != INFO_COOKIE) - return (0); - - if (body[i] == INFO_FF) - i++; - - if (body[i++] != '\n') - return (0); - - return (i); -} - -/* Return the number of characters from STRING to the start of - the next line. */ -int -skip_line (string) - char *string; -{ - register int i; - - for (i = 0; string && string[i] && string[i] != '\n'; i++); - - if (string[i] == '\n') - i++; - - return (i); -} - -/* Return the absolute position of the beginning of a tags table in this - binding starting the search at binding->start. */ -long -find_tags_table (binding) - SEARCH_BINDING *binding; -{ - SEARCH_BINDING search; - long position; - - search.buffer = binding->buffer; - search.start = binding->start; - search.end = binding->end; - search.flags = S_FoldCase; - - while ((position = find_node_separator (&search)) != -1 ) - { - search.start = position; - search.start += skip_node_separator (search.buffer + search.start); - - if (looking_at (TAGS_TABLE_BEG_LABEL, &search)) - return (position); - } - return (-1); -} - -/* Return the absolute position of the node named NODENAME in BINDING. - This is a brute force search, and we wish to avoid it when possible. - This function is called when a tag (indirect or otherwise) doesn't - really point to the right node. It returns the absolute position of - the separator preceding the node. */ -long -find_node_in_binding (nodename, binding) - char *nodename; - SEARCH_BINDING *binding; -{ - register long position; - register int offset, namelen; - SEARCH_BINDING search; - - namelen = strlen (nodename); - - search.buffer = binding->buffer; - search.start = binding->start; - search.end = binding->end; - search.flags = 0; - - while ((position = find_node_separator (&search)) != -1) - { - search.start = position; - search.start += skip_node_separator (search.buffer + search.start); - - offset = string_in_line (INFO_NODE_LABEL, search.buffer + search.start); - - if (offset == -1) - continue; - - search.start += offset; - search.start += skip_whitespace (search.buffer + search.start); - offset = skip_node_characters - (search.buffer + search.start, DONT_SKIP_NEWLINES); - - /* Notice that this is an exact match. You cannot grovel through - the buffer with this function looking for random nodes. */ - if ((offset == namelen) && - (search.buffer[search.start] == nodename[0]) && - (strncmp (search.buffer + search.start, nodename, offset) == 0)) - return (position); - } - return (-1); -} diff --git a/info/search.h b/info/search.h deleted file mode 100644 --- a/info/search.h +++ /dev/null @@ -1,75 +0,0 @@ -/* search.h -- Structure used to search large bodies of text, with bounds. */ - -/* 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). */ - -/* The search functions take two arguments: - - 1) a string to search for, and - - 2) a pointer to a SEARCH_BINDING which contains the buffer, start, - and end of the search. - - They return a long, which is the offset from the start of the buffer - at which the match was found. An offset of -1 indicates failure. */ - -#if !defined (_SEARCH_H_) -#define _SEARCH_H_ - -typedef struct { - char *buffer; /* The buffer of text to search. */ - long start; /* Offset of the start of the search. */ - long end; /* Offset of the end of the searh. */ - int flags; /* Flags controlling the type of search. */ -} SEARCH_BINDING; - -#define S_FoldCase 0x01 /* Set means fold case in searches. */ -#define S_SkipDest 0x02 /* Set means return pointing after the dest. */ - -SEARCH_BINDING *make_binding (), *copy_binding (); -extern long search_forward (), search_backward (), search (); -extern int looking_at (); - -/* Note that STRING_IN_LINE () always returns the offset of the 1st character - after the string. */ -extern int string_in_line (); - -/* Some unixes don't have strcasecmp or strncasecmp. */ -#if !defined (HAVE_STRCASECMP) -extern int strcasecmp (), strncasecmp (); -#endif /* !HAVE_STRCASECMP */ - -/* Function names that start with "skip" are passed a string, and return - an offset from the start of that string. Function names that start - with "find" are passed a SEARCH_BINDING, and return an absolute position - marker of the item being searched for. "Find" functions return a value - of -1 if the item being looked for couldn't be found. */ -extern int skip_whitespace (), skip_non_whitespace (); -extern int skip_whitespace_and_newlines (), skip_line (); -extern int skip_node_characters (), skip_node_separator (); -#define DONT_SKIP_NEWLINES 0 -#define SKIP_NEWLINES 1 - -extern long find_node_separator (), find_tags_table (); -extern long find_node_in_binding (); - -#endif /* !_SEARCH_H_ */ - diff --git a/info/session.c b/info/session.c deleted file mode 100644 --- a/info/session.c +++ /dev/null @@ -1,4267 +0,0 @@ -/* session.c -- The user windowing interface to Info. */ - -/* This file is part of GNU Info, a program for reading online documentation - stored in Info format. - - Copyright (C) 1993, 96 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" -#if defined (HAVE_SYS_FILE_H) -#include -#endif /* HAVE_SYS_FILE_H */ -#include -#include - -#if defined (HAVE_SYS_TIME_H) -# include -# define HAVE_STRUCT_TIMEVAL -#endif /* HAVE_SYS_TIME_H */ - -#if defined (HANDLE_MAN_PAGES) -# include "man.h" -#endif - -static void info_clear_pending_input (), info_set_pending_input (); -static void info_handle_pointer (); - -/* **************************************************************** */ -/* */ -/* Running an Info Session */ -/* */ -/* **************************************************************** */ - -/* The place that we are reading input from. */ -static FILE *info_input_stream = (FILE *)NULL; - -/* The last executed command. */ -VFunction *info_last_executed_command = (VFunction *)NULL; - -/* Becomes non-zero when 'q' is typed to an Info window. */ -int quit_info_immediately = 0; - -/* Array of structures describing for each window which nodes have been - visited in that window. */ -INFO_WINDOW **info_windows = (INFO_WINDOW **)NULL; - -/* Where to add the next window, if we need to add one. */ -static int info_windows_index = 0; - -/* Number of slots allocated to INFO_WINDOWS. */ -static int info_windows_slots = 0; - -void remember_window_and_node (), forget_window_and_nodes (); -void initialize_info_session (), info_session (); -void display_startup_message_and_start (); - -/* Begin an info session finding the nodes specified by FILENAME and NODENAMES. - For each loaded node, create a new window. Always split the largest of the - available windows. */ -void -begin_multiple_window_info_session (filename, nodenames) - char *filename; - char **nodenames; -{ - register int i; - WINDOW *window = (WINDOW *)NULL; - - for (i = 0; nodenames[i]; i++) - { - NODE *node; - - node = info_get_node (filename, nodenames[i]); - - if (!node) - break; - - /* If this is the first node, initialize the info session. */ - if (!window) - { - initialize_info_session (node, 1); - window = active_window; - } - else - { - /* Find the largest window in WINDOWS, and make that be the active - one. Then split it and add our window and node to the list - of remembered windows and nodes. Then tile the windows. */ - register WINDOW *win, *largest = (WINDOW *)NULL; - int max_height = 0; - - for (win = windows; win; win = win->next) - if (win->height > max_height) - { - max_height = win->height; - largest = win; - } - - if (!largest) - { - display_update_display (windows); - info_error (CANT_FIND_WIND); - info_session (); - exit (0); - } - - active_window = largest; - window = window_make_window (node); - if (window) - { - window_tile_windows (TILE_INTERNALS); - remember_window_and_node (window, node); - } - else - { - display_update_display (windows); - info_error (WIN_TOO_SMALL); - info_session (); - exit (0); - } - } - } - display_startup_message_and_start (); -} - -/* Start an info session with INITIAL_NODE, and an error message in the echo - area made from FORMAT and ARG. */ -void -begin_info_session_with_error (initial_node, format, arg) - NODE *initial_node; - char *format; - void *arg; -{ - initialize_info_session (initial_node, 1); - info_error (format, arg, (void *)NULL); - info_session (); -} - -/* Start an info session with INITIAL_NODE. */ -void -begin_info_session (initial_node) - NODE *initial_node; -{ - initialize_info_session (initial_node, 1); - display_startup_message_and_start (); -} - -void -display_startup_message_and_start () -{ - char *format; - - format = replace_in_documentation - ("Welcome to Info version %s. \"\\[get-help-window]\" for help, \"\\[menu-item]\" for menu item."); - - window_message_in_echo_area (format, version_string ()); - info_session (); -} - -/* Run an info session with an already initialized window and node. */ -void -info_session () -{ - terminal_prep_terminal (); - display_update_display (windows); - info_last_executed_command = (VFunction *)NULL; - info_read_and_dispatch (); - /* On program exit, leave the cursor at the bottom of the window, and - restore the terminal I/O. */ - terminal_goto_xy (0, screenheight - 1); - terminal_clear_to_eol (); - fflush (stdout); - terminal_unprep_terminal (); - close_dribble_file (); -} - -/* Here is a window-location dependent event loop. Called from the - functions info_session (), and from read_xxx_in_echo_area (). */ -void -info_read_and_dispatch () -{ - unsigned char key; - int done; - done = 0; - - while (!done && !quit_info_immediately) - { - int lk; - - /* If we haven't just gone up or down a line, there is no - goal column for this window. */ - if ((info_last_executed_command != info_next_line) && - (info_last_executed_command != info_prev_line)) - active_window->goal_column = -1; - - if (echo_area_is_active) - { - lk = echo_area_last_command_was_kill; - echo_area_prep_read (); - } - - if (!info_any_buffered_input_p ()) - display_update_display (windows); - - display_cursor_at_point (active_window); - info_initialize_numeric_arg (); - - initialize_keyseq (); - key = info_get_input_char (); - - /* No errors yet. We just read a character, that's all. Only clear - the echo_area if it is not currently active. */ - if (!echo_area_is_active) - window_clear_echo_area (); - - info_error_was_printed = 0; - - /* Do the selected command. */ - info_dispatch_on_key (key, active_window->keymap); - - if (echo_area_is_active) - { - /* Echo area commands that do killing increment the value of - ECHO_AREA_LAST_COMMAND_WAS_KILL. Thus, if there is no - change in the value of this variable, the last command - executed was not a kill command. */ - if (lk == echo_area_last_command_was_kill) - echo_area_last_command_was_kill = 0; - - if (ea_last_executed_command == ea_newline || - info_aborted_echo_area) - { - ea_last_executed_command = (VFunction *)NULL; - done = 1; - } - - if (info_last_executed_command == info_quit) - quit_info_immediately = 1; - } - else if (info_last_executed_command == info_quit) - done = 1; - } -} - -/* Found in signals.c */ -extern void initialize_info_signal_handler (); - -/* Initialize the first info session by starting the terminal, window, - and display systems. If CLEAR_SCREEN is 0, don't clear the - screen. */ -void -initialize_info_session (node, clear_screen) - NODE *node; - int clear_screen; -{ - char *getenv (), *term_name; - - term_name = getenv ("TERM"); - terminal_initialize_terminal (term_name); - - if (terminal_is_dumb_p) - { - if (!term_name) - term_name = "dumb"; - - info_error (TERM_TOO_DUMB, term_name); - exit (1); - } - - if (clear_screen) - terminal_clear_screen (); - - initialize_info_keymaps (); - window_initialize_windows (screenwidth, screenheight); - initialize_info_signal_handler (); - display_initialize_display (screenwidth, screenheight); - info_set_node_of_window (active_window, node); - - /* Tell the window system how to notify us when a window needs to be - asynchronously deleted (e.g., user resizes window very small). */ - window_deletion_notifier = forget_window_and_nodes; - - /* If input has not been redirected yet, make it come from STDIN. */ - if (!info_input_stream) - info_input_stream = stdin; - - info_windows_initialized_p = 1; -} - -/* Tell Info that input is coming from the file FILENAME. */ -void -info_set_input_from_file (filename) - char *filename; -{ - FILE *stream; - - stream = fopen (filename, "r"); - - if (!stream) - return; - - if ((info_input_stream != (FILE *)NULL) && - (info_input_stream != stdin)) - fclose (info_input_stream); - - info_input_stream = stream; - - if (stream != stdin) - display_inhibited = 1; -} - -/* Return the INFO_WINDOW containing WINDOW, or NULL if there isn't one. */ -static INFO_WINDOW * -get_info_window_of_window (window) - WINDOW *window; -{ - register int i; - INFO_WINDOW *info_win = (INFO_WINDOW *)NULL; - - for (i = 0; info_windows && (info_win = info_windows[i]); i++) - if (info_win->window == window) - break; - - return (info_win); -} - -/* Reset the remembered pagetop and point of WINDOW to WINDOW's current - values if the window and node are the same as the current one being - displayed. */ -void -set_remembered_pagetop_and_point (window) - WINDOW *window; -{ - INFO_WINDOW *info_win; - - info_win = get_info_window_of_window (window); - - if (!info_win) - return; - - if (info_win->nodes_index && - (info_win->nodes[info_win->current] == window->node)) - { - info_win->pagetops[info_win->current] = window->pagetop; - info_win->points[info_win->current] = window->point; - } -} - -void -remember_window_and_node (window, node) - WINDOW *window; - NODE *node; -{ - INFO_WINDOW *info_win; - - /* See if we already have this window in our list. */ - info_win = get_info_window_of_window (window); - - /* If the window wasn't already on our list, then make a new entry. */ - if (!info_win) - { - info_win = (INFO_WINDOW *)xmalloc (sizeof (INFO_WINDOW)); - info_win->window = window; - info_win->nodes = (NODE **)NULL; - info_win->pagetops = (int *)NULL; - info_win->points = (long *)NULL; - info_win->current = 0; - info_win->nodes_index = 0; - info_win->nodes_slots = 0; - - add_pointer_to_array (info_win, info_windows_index, info_windows, - info_windows_slots, 10, INFO_WINDOW *); - } - - /* If this node, the current pagetop, and the current point are the - same as the last saved node and pagetop, don't really add this to - the list of history nodes. */ - { - int ni = info_win->nodes_index - 1; - - if ((ni != -1) && - (info_win->nodes[ni]->contents == node->contents) && - (info_win->pagetops[ni] == window->pagetop) && - (info_win->points[ni] == window->point)) - return; - } - - /* Remember this node, the currently displayed pagetop, and the current - location of point in this window. Because we are updating pagetops - and points as well as nodes, it is more efficient to avoid the - add_pointer_to_array macro here. */ - if (info_win->nodes_index + 2 >= info_win->nodes_slots) - { - info_win->nodes = (NODE **) - xrealloc (info_win->nodes, - (info_win->nodes_slots += 20) * sizeof (NODE *)); - - info_win->pagetops = (int *) - xrealloc (info_win->pagetops, info_win->nodes_slots * sizeof (int)); - - info_win->points = (long *) - xrealloc (info_win->points, info_win->nodes_slots * sizeof (long)); - } - - info_win->nodes[info_win->nodes_index] = node; - info_win->pagetops[info_win->nodes_index] = window->pagetop; - info_win->points[info_win->nodes_index] = window->point; - info_win->current = info_win->nodes_index++; - info_win->nodes[info_win->nodes_index] = (NODE *)NULL; - info_win->pagetops[info_win->nodes_index] = 0; - info_win->points[info_win->nodes_index] = 0; -} - -#define DEBUG_FORGET_WINDOW_AND_NODES -#if defined (DEBUG_FORGET_WINDOW_AND_NODES) -static void -consistency_check_info_windows () -{ - register int i; - INFO_WINDOW *info_win; - - for (i = 0; i < info_windows_index; i++) - { - WINDOW *win; - - for (win = windows; win; win = win->next) - if (win == info_windows[i]->window) - break; - - if (!win) - abort (); - } -} -#endif /* DEBUG_FORGET_WINDOW_AND_NODES */ - -/* Remove WINDOW and its associated list of nodes from INFO_WINDOWS. */ -void -forget_window_and_nodes (window) - WINDOW *window; -{ - register int i; - INFO_WINDOW *info_win = (INFO_WINDOW *)NULL; - - for (i = 0; info_windows && (info_win = info_windows[i]); i++) - if (info_win->window == window) - break; - - /* If we found the window to forget, then do so. */ - if (info_win) - { - while (i < info_windows_index) - { - info_windows[i] = info_windows[i + 1]; - i++; - } - - info_windows_index--; - info_windows[info_windows_index] = (INFO_WINDOW *)NULL; - - if (info_win->nodes) - { - /* Free the node structures which held onto internal node contents - here. This doesn't free the contents; we have a garbage collector - which does that. */ - for (i = 0; info_win->nodes[i]; i++) - if (internal_info_node_p (info_win->nodes[i])) - free (info_win->nodes[i]); - free (info_win->nodes); - - maybe_free (info_win->pagetops); - maybe_free (info_win->points); - } - - free (info_win); - } -#if defined (DEBUG_FORGET_WINDOW_AND_NODES) - consistency_check_info_windows (); -#endif /* DEBUG_FORGET_WINDOW_AND_NODES */ -} - -/* Set WINDOW to show NODE. Remember the new window in our list of Info - windows. If we are doing automatic footnote display, also try to display - the footnotes for this window. */ -void -info_set_node_of_window (window, node) - WINDOW *window; - NODE *node; -{ - /* Put this node into the window. */ - window_set_node_of_window (window, node); - - /* Remember this node and window in our list of info windows. */ - remember_window_and_node (window, node); - - /* If doing auto-footnote display/undisplay, show the footnotes belonging - to this window's node. */ - if (auto_footnotes_p) - info_get_or_remove_footnotes (window); -} - - -/* **************************************************************** */ -/* */ -/* Info Movement Commands */ -/* */ -/* **************************************************************** */ - -/* Change the pagetop of WINDOW to DESIRED_TOP, perhaps scrolling the screen - to do so. */ -void -set_window_pagetop (window, desired_top) - WINDOW *window; - int desired_top; -{ - int point_line, old_pagetop; - - if (desired_top < 0) - desired_top = 0; - else if (desired_top > window->line_count) - desired_top = window->line_count - 1; - - if (window->pagetop == desired_top) - return; - - old_pagetop = window->pagetop; - window->pagetop = desired_top; - - /* Make sure that point appears in this window. */ - point_line = window_line_of_point (window); - if ((point_line < window->pagetop) || - ((point_line - window->pagetop) > window->height - 1)) - window->point = - window->line_starts[window->pagetop] - window->node->contents; - - window->flags |= W_UpdateWindow; - - /* Find out which direction to scroll, and scroll the window in that - direction. Do this only if there would be a savings in redisplay - time. This is true if the amount to scroll is less than the height - of the window, and if the number of lines scrolled would be greater - than 10 % of the window's height. */ - if (old_pagetop < desired_top) - { - int start, end, amount; - - amount = desired_top - old_pagetop; - - if ((amount >= window->height) || - (((window->height - amount) * 10) < window->height)) - return; - - start = amount + window->first_row; - end = window->height + window->first_row; - - display_scroll_display (start, end, -amount); - } - else - { - int start, end, amount; - - amount = old_pagetop - desired_top; - - if ((amount >= window->height) || - (((window->height - amount) * 10) < window->height)) - return; - - start = window->first_row; - end = (window->first_row + window->height) - amount; - display_scroll_display (start, end, amount); - } -} - -/* Immediately make WINDOW->point visible on the screen, and move the - terminal cursor there. */ -static void -info_show_point (window) - WINDOW *window; -{ - int old_pagetop; - - old_pagetop = window->pagetop; - window_adjust_pagetop (window); - if (old_pagetop != window->pagetop) - { - int new_pagetop; - - new_pagetop = window->pagetop; - window->pagetop = old_pagetop; - set_window_pagetop (window, new_pagetop); - } - - if (window->flags & W_UpdateWindow) - display_update_one_window (window); - - display_cursor_at_point (window); -} - -/* Move WINDOW->point from OLD line index to NEW line index. */ -static void -move_to_new_line (old, new, window) - int old, new; - WINDOW *window; -{ - if (old == -1) - { - info_error (CANT_FIND_POINT); - } - else - { - int goal; - - if (new >= window->line_count || new < 0) - return; - - goal = window_get_goal_column (window); - window->goal_column = goal; - - window->point = window->line_starts[new] - window->node->contents; - window->point += window_chars_to_goal (window->line_starts[new], goal); - info_show_point (window); - } -} - -/* Move WINDOW's point down to the next line if possible. */ -DECLARE_INFO_COMMAND (info_next_line, "Move down to the next line") -{ - int old_line, new_line; - - if (count < 0) - info_prev_line (window, -count, key); - else - { - old_line = window_line_of_point (window); - new_line = old_line + count; - move_to_new_line (old_line, new_line, window); - } -} - -/* Move WINDOW's point up to the previous line if possible. */ -DECLARE_INFO_COMMAND (info_prev_line, "Move up to the previous line") -{ - int old_line, new_line; - - if (count < 0) - info_next_line (window, -count, key); - else - { - old_line = window_line_of_point (window); - new_line = old_line - count; - move_to_new_line (old_line, new_line, window); - } -} - -/* Move WINDOW's point to the end of the true line. */ -DECLARE_INFO_COMMAND (info_end_of_line, "Move to the end of the line") -{ - register int point, len; - register char *buffer; - - buffer = window->node->contents; - len = window->node->nodelen; - - for (point = window->point; - (point < len) && (buffer[point] != '\n'); - point++); - - if (point != window->point) - { - window->point = point; - info_show_point (window); - } -} - -/* Move WINDOW's point to the beginning of the true line. */ -DECLARE_INFO_COMMAND (info_beginning_of_line, "Move to the start of the line") -{ - register int point; - register char *buffer; - - buffer = window->node->contents; - point = window->point; - - for (; (point) && (buffer[point - 1] != '\n'); point--); - - /* If at a line start alreay, do nothing. */ - if (point != window->point) - { - window->point = point; - info_show_point (window); - } -} - -/* Move point forward in the node. */ -DECLARE_INFO_COMMAND (info_forward_char, "Move forward a character") -{ - if (count < 0) - info_backward_char (window, -count, key); - else - { - window->point += count; - - if (window->point >= window->node->nodelen) - window->point = window->node->nodelen - 1; - - info_show_point (window); - } -} - -/* Move point backward in the node. */ -DECLARE_INFO_COMMAND (info_backward_char, "Move backward a character") -{ - if (count < 0) - info_forward_char (window, -count, key); - else - { - window->point -= count; - - if (window->point < 0) - window->point = 0; - - info_show_point (window); - } -} - -#define alphabetic(c) (islower (c) || isupper (c) || isdigit (c)) - -/* Move forward a word in this node. */ -DECLARE_INFO_COMMAND (info_forward_word, "Move forward a word") -{ - long point; - char *buffer; - int end, c; - - if (count < 0) - { - info_backward_word (window, -count, key); - return; - } - - point = window->point; - buffer = window->node->contents; - end = window->node->nodelen; - - while (count) - { - if (point + 1 >= end) - return; - - /* If we are not in a word, move forward until we are in one. - Then, move forward until we hit a non-alphabetic character. */ - c = buffer[point]; - - if (!alphabetic (c)) - { - while (++point < end) - { - c = buffer[point]; - if (alphabetic (c)) - break; - } - } - - if (point >= end) return; - - while (++point < end) - { - c = buffer[point]; - if (!alphabetic (c)) - break; - } - --count; - } - window->point = point; - info_show_point (window); -} - -DECLARE_INFO_COMMAND (info_backward_word, "Move backward a word") -{ - long point; - char *buffer; - int c; - - if (count < 0) - { - info_forward_word (window, -count, key); - return; - } - - buffer = window->node->contents; - point = window->point; - - while (count) - { - if (point == 0) - break; - - /* Like info_forward_word (), except that we look at the - characters just before point. */ - - c = buffer[point - 1]; - - if (!alphabetic (c)) - { - while (--point) - { - c = buffer[point - 1]; - if (alphabetic (c)) - break; - } - } - - while (point) - { - c = buffer[point - 1]; - if (!alphabetic (c)) - break; - else - --point; - } - --count; - } - window->point = point; - info_show_point (window); -} - -/* Here is a list of time counter names which correspond to ordinal numbers. - It is used to print "once" instead of "1". */ -static char *counter_names[] = { - "not at all", "once", "twice", "three", "four", "five", "six", - (char *)NULL -}; - -/* Buffer used to return values from times_description (). */ -static char td_buffer[50]; - -/* Function returns a static string fully describing the number of times - present in COUNT. */ -static char * -times_description (count) - int count; -{ - register int i; - - td_buffer[0] = '\0'; - - for (i = 0; counter_names[i]; i++) - if (count == i) - break; - - if (counter_names[i]) - sprintf (td_buffer, "%s%s", counter_names[i], count > 2 ? " times" : ""); - else - sprintf (td_buffer, "%d times", count); - - return (td_buffer); -} - -/* Variable controlling the behaviour of default scrolling when you are - already at the bottom of a node. Possible values are defined in session.h. - The meanings are: - - IS_Continuous Try to get first menu item, or failing that, the - "Next:" pointer, or failing that, the "Up:" and - "Next:" of the up. - IS_NextOnly Try to get "Next:" menu item. - IS_PageOnly Simply give up at the bottom of a node. */ - -int info_scroll_behaviour = IS_Continuous; - -/* Choices used by the completer when reading a value for the user-visible - variable "scroll-behaviour". */ -char *info_scroll_choices[] = { - "Continuous", "Next Only", "Page Only", (char *)NULL -}; - -/* Move to 1st menu item, Next, Up/Next, or error in this window. */ -static void -forward_move_node_structure (window, behaviour) - WINDOW *window; - int behaviour; -{ - switch (behaviour) - { - case IS_PageOnly: - info_error (AT_NODE_BOTTOM); - break; - - case IS_NextOnly: - info_next_label_of_node (window->node); - if (!info_parsed_nodename && !info_parsed_filename) - info_error ("No \"Next\" pointer for this node."); - else - { - window_message_in_echo_area ("Following \"Next\" node..."); - info_handle_pointer ("Next", window); - } - break; - - case IS_Continuous: - { - /* First things first. If this node contains a menu, move down - into the menu. */ - { - REFERENCE **menu; - - menu = info_menu_of_node (window->node); - - if (menu) - { - info_free_references (menu); - window_message_in_echo_area ("Selecting first menu item..."); - info_menu_digit (window, 1, '1'); - return; - } - } - - /* 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_was_found) - { - window_message_in_echo_area ("Selecting \"Next\" node..."); - info_handle_pointer ("Next", window); - return; - } - - /* Okay, there wasn't a "Next:" for this node. Move "Up:" until we - can move "Next:". If that isn't possible, complain that there - are no more nodes. */ - { - int up_counter, old_current; - INFO_WINDOW *info_win; - - /* Remember the current node and location. */ - info_win = get_info_window_of_window (window); - old_current = info_win->current; - - /* Back up through the "Up:" pointers until we have found a "Next:" - that isn't the same as the first menu item found in that node. */ - up_counter = 0; - while (!info_error_was_printed) - { - info_up_label_of_node (window->node); - if (info_label_was_found) - { - info_handle_pointer ("Up", window); - if (info_error_was_printed) - continue; - - up_counter++; - - info_next_label_of_node (window->node); - - /* If no "Next" pointer, keep backing up. */ - if (!info_label_was_found) - continue; - - /* If this node's first menu item is the same as this node's - Next pointer, keep backing up. */ - if (!info_parsed_filename) - { - 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 = strdup (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); - } - } - - /* This node has a "Next" pointer, and it is not the - same as the first menu item found in this node. */ - window_message_in_echo_area - ("Moving \"Up\" %s, then \"Next\".", - times_description (up_counter)); - - info_handle_pointer ("Next", window); - return; - } - else - { - /* No more "Up" pointers. Print an error, and call it - quits. */ - register int i; - - for (i = 0; i < up_counter; i++) - { - info_win->nodes_index--; - free (info_win->nodes[info_win->nodes_index]); - info_win->nodes[info_win->nodes_index] = (NODE *)NULL; - } - info_win->current = old_current; - window->node = info_win->nodes[old_current]; - window->pagetop = info_win->pagetops[old_current]; - window->point = info_win->points[old_current]; - recalculate_line_starts (window); - window->flags |= W_UpdateWindow; - info_error ("No more nodes."); - } - } - } - break; - } - } -} - -/* Move Prev, Up or error in WINDOW depending on BEHAVIOUR. */ -static void -backward_move_node_structure (window, behaviour) - WINDOW *window; - int behaviour; -{ - switch (behaviour) - { - case IS_PageOnly: - info_error (AT_NODE_TOP); - break; - - case IS_NextOnly: - info_prev_label_of_node (window->node); - if (!info_parsed_nodename && !info_parsed_filename) - info_error ("No \"Prev\" for this node."); - else - { - window_message_in_echo_area ("Moving \"Prev\" in this window."); - info_handle_pointer ("Prev", window); - } - break; - - case IS_Continuous: - info_prev_label_of_node (window->node); - - if (!info_parsed_nodename && !info_parsed_filename) - { - info_up_label_of_node (window->node); - if (!info_parsed_nodename && !info_parsed_filename) - info_error ("No \"Prev\" or \"Up\" for this node."); - else - { - window_message_in_echo_area ("Moving \"Up\" in this window."); - 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) - { - char *pnode; - - pnode = strdup (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); - } - } - - /* 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. */ - window_message_in_echo_area ("Moving \"Prev\" in this window."); - info_handle_pointer ("Prev", window); - - if (!inhibit_menu_traversing) - { - while (!info_error_was_printed && - (menu = info_menu_of_node (window->node))) - { - info_free_references (menu); - window_message_in_echo_area - ("Moving to \"Prev\"'s last menu item."); - info_menu_digit (window, 1, '0'); - } - } - } - break; - } -} - -/* Move continuously forward through the node structure of this info file. */ -DECLARE_INFO_COMMAND (info_global_next_node, - "Move forwards or down through node structure") -{ - if (count < 0) - info_global_prev_node (window, -count, key); - else - { - while (count && !info_error_was_printed) - { - forward_move_node_structure (window, IS_Continuous); - count--; - } - } -} - -/* Move continuously backward through the node structure of this info file. */ -DECLARE_INFO_COMMAND (info_global_prev_node, - "Move backwards or up through node structure") -{ - if (count < 0) - info_global_next_node (window, -count, key); - else - { - while (count && !info_error_was_printed) - { - backward_move_node_structure (window, IS_Continuous); - count--; - } - } -} - -/* Show the next screen of WINDOW's node. */ -DECLARE_INFO_COMMAND (info_scroll_forward, "Scroll forward in this window") -{ - if (count < 0) - info_scroll_backward (window, -count, key); - else - { - int desired_top; - - /* Without an explicit numeric argument, scroll the bottom two - lines to the top of this window, Or, if at bottom of window, - and the user wishes to scroll through nodes get the "Next" node - for this window. */ - if (!info_explicit_arg && count == 1) - { - desired_top = window->pagetop + (window->height - 2); - - /* If there are no more lines to scroll here, error, or get - another node, depending on INFO_SCROLL_BEHAVIOUR. */ - if (desired_top > window->line_count) - { - int behaviour = info_scroll_behaviour; - - /* Here is a hack. If the key being used is not SPC, do the - PageOnly behaviour. */ - if (key != SPC && key != DEL) - behaviour = IS_PageOnly; - - forward_move_node_structure (window, behaviour); - return; - } - } - else - desired_top = window->pagetop + count; - - if (desired_top >= window->line_count) - desired_top = window->line_count - 2; - - if (window->pagetop > desired_top) - return; - else - set_window_pagetop (window, desired_top); - } -} - -/* Show the previous screen of WINDOW's node. */ -DECLARE_INFO_COMMAND (info_scroll_backward, "Scroll backward in this window") -{ - if (count < 0) - info_scroll_forward (window, -count, key); - else - { - int desired_top; - - /* Without an explicit numeric argument, scroll the top two lines - to the bottom of this window, or move to the previous, or Up'th - node. */ - if (!info_explicit_arg && count == 1) - { - desired_top = window->pagetop - (window->height - 2); - - if ((desired_top < 0) && (window->pagetop == 0)) - { - int behaviour = info_scroll_behaviour; - - /* Same kind of hack as in info_scroll_forward. If the key - used to invoke this command is not DEL, do only the PageOnly - behaviour. */ - if (key != DEL && key != SPC) - behaviour = IS_PageOnly; - - backward_move_node_structure (window, behaviour); - return; - } - } - else - desired_top = window->pagetop - count; - - if (desired_top < 0) - desired_top = 0; - - set_window_pagetop (window, desired_top); - } -} - -/* Move to the beginning of the node. */ -DECLARE_INFO_COMMAND (info_beginning_of_node, "Move to the start of this node") -{ - window->pagetop = window->point = 0; - window->flags |= W_UpdateWindow; -} - -/* Move to the end of the node. */ -DECLARE_INFO_COMMAND (info_end_of_node, "Move to the end of this node") -{ - window->point = window->node->nodelen - 1; - info_show_point (window); -} - -/* **************************************************************** */ -/* */ -/* Commands for Manipulating Windows */ -/* */ -/* **************************************************************** */ - -/* Make the next window in the chain be the active window. */ -DECLARE_INFO_COMMAND (info_next_window, "Select the next window") -{ - if (count < 0) - { - info_prev_window (window, -count, key); - return; - } - - /* If no other window, error now. */ - if (!windows->next && !echo_area_is_active) - { - info_error (ONE_WINDOW); - return; - } - - while (count--) - { - if (window->next) - window = window->next; - else - { - if (window == the_echo_area || !echo_area_is_active) - window = windows; - else - window = the_echo_area; - } - } - - if (active_window != window) - { - if (auto_footnotes_p) - info_get_or_remove_footnotes (window); - - window->flags |= W_UpdateWindow; - active_window = window; - } -} - -/* Make the previous window in the chain be the active window. */ -DECLARE_INFO_COMMAND (info_prev_window, "Select the previous window") -{ - if (count < 0) - { - info_next_window (window, -count, key); - return; - } - - /* Only one window? */ - - if (!windows->next && !echo_area_is_active) - { - info_error (ONE_WINDOW); - return; - } - - while (count--) - { - /* If we are in the echo area, or if the echo area isn't active and we - are in the first window, find the last window in the chain. */ - if (window == the_echo_area || - (window == windows && !echo_area_is_active)) - { - register WINDOW *win, *last; - - for (win = windows; win; win = win->next) - last = win; - - window = last; - } - else - { - if (window == windows) - window = the_echo_area; - else - window = window->prev; - } - } - - if (active_window != window) - { - if (auto_footnotes_p) - info_get_or_remove_footnotes (window); - - window->flags |= W_UpdateWindow; - active_window = window; - } -} - -/* Split WINDOW into two windows, both showing the same node. If we - are automatically tiling windows, re-tile after the split. */ -DECLARE_INFO_COMMAND (info_split_window, "Split the current window") -{ - WINDOW *split, *old_active; - int pagetop; - - /* Remember the current pagetop of the window being split. If it doesn't - change, we can scroll its contents around after the split. */ - pagetop = window->pagetop; - - /* Make the new window. */ - old_active = active_window; - active_window = window; - split = window_make_window (window->node); - active_window = old_active; - - if (!split) - { - info_error (WIN_TOO_SMALL); - } - else - { -#if defined (SPLIT_BEFORE_ACTIVE) - /* Try to scroll the old window into its new postion. */ - if (pagetop == window->pagetop) - { - int start, end, amount; - - start = split->first_row; - end = start + window->height; - amount = split->height + 1; - display_scroll_display (start, end, amount); - } -#else /* !SPLIT_BEFORE_ACTIVE */ - /* Make sure point still appears in the active window. */ - info_show_point (window); -#endif /* !SPLIT_BEFORE_ACTIVE */ - - /* If the window just split was one internal to Info, try to display - something else in it. */ - if (internal_info_node_p (split->node)) - { - register int i, j; - INFO_WINDOW *iw; - NODE *node = (NODE *)NULL; - char *filename; - - for (i = 0; iw = info_windows[i]; i++) - { - for (j = 0; j < iw->nodes_index; j++) - if (!internal_info_node_p (iw->nodes[j])) - { - if (iw->nodes[j]->parent) - filename = iw->nodes[j]->parent; - else - filename = iw->nodes[j]->filename; - - node = info_get_node (filename, iw->nodes[j]->nodename); - if (node) - { - window_set_node_of_window (split, node); - i = info_windows_index - 1; - break; - } - } - } - } - split->pagetop = window->pagetop; - - if (auto_tiling_p) - window_tile_windows (DONT_TILE_INTERNALS); - else - window_adjust_pagetop (split); - - remember_window_and_node (split, split->node); - } -} - -/* Delete WINDOW, forgetting the list of last visited nodes. If we are - automatically displaying footnotes, show or remove the footnotes - window. If we are automatically tiling windows, re-tile after the - deletion. */ -DECLARE_INFO_COMMAND (info_delete_window, "Delete the current window") -{ - if (!windows->next) - { - info_error (CANT_KILL_LAST); - } - else if (window->flags & W_WindowIsPerm) - { - info_error ("Cannot delete a permanent window"); - } - else - { - info_delete_window_internal (window); - - if (auto_footnotes_p) - info_get_or_remove_footnotes (active_window); - - if (auto_tiling_p) - window_tile_windows (DONT_TILE_INTERNALS); - } -} - -/* Do the physical deletion of WINDOW, and forget this window and - associated nodes. */ -void -info_delete_window_internal (window) - WINDOW *window; -{ - if (windows->next && ((window->flags & W_WindowIsPerm) == 0)) - { - /* We not only delete the window from the display, we forget it from - our list of remembered windows. */ - forget_window_and_nodes (window); - window_delete_window (window); - - if (echo_area_is_active) - echo_area_inform_of_deleted_window (window); - } -} - -/* Just keep WINDOW, deleting all others. */ -DECLARE_INFO_COMMAND (info_keep_one_window, "Delete all other windows") -{ - int num_deleted; /* The number of windows we deleted. */ - int pagetop, start, end; - - /* Remember a few things about this window. We may be able to speed up - redisplay later by scrolling its contents. */ - pagetop = window->pagetop; - start = window->first_row; - end = start + window->height; - - num_deleted = 0; - - while (1) - { - WINDOW *win; - - /* Find an eligible window and delete it. If no eligible windows - are found, we are done. A window is eligible for deletion if - is it not permanent, and it is not WINDOW. */ - for (win = windows; win; win = win->next) - if (win != window && ((win->flags & W_WindowIsPerm) == 0)) - break; - - if (!win) - break; - - info_delete_window_internal (win); - num_deleted++; - } - - /* Scroll the contents of this window into the right place so that the - user doesn't have to wait any longer than necessary for redisplay. */ - if (num_deleted) - { - int amount; - - amount = (window->first_row - start); - amount -= (window->pagetop - pagetop); - display_scroll_display (start, end, amount); - } - - window->flags |= W_UpdateWindow; -} - -/* Scroll the "other" window of WINDOW. */ -DECLARE_INFO_COMMAND (info_scroll_other_window, "Scroll the other window") -{ - WINDOW *other; - - /* If only one window, give up. */ - if (!windows->next) - { - info_error (ONE_WINDOW); - return; - } - - other = window->next; - - if (!other) - other = window->prev; - - info_scroll_forward (other, count, key); -} - -/* Change the size of WINDOW by AMOUNT. */ -DECLARE_INFO_COMMAND (info_grow_window, "Grow (or shrink) this window") -{ - window_change_window_height (window, count); -} - -/* When non-zero, tiling takes place automatically when info_split_window - is called. */ -int auto_tiling_p = 0; - -/* Tile all of the visible windows. */ -DECLARE_INFO_COMMAND (info_tile_windows, - "Divide the available screen space among the visible windows") -{ - window_tile_windows (TILE_INTERNALS); -} - -/* Toggle the state of this window's wrapping of lines. */ -DECLARE_INFO_COMMAND (info_toggle_wrap, - "Toggle the state of line wrapping in the current window") -{ - window_toggle_wrap (window); -} - -/* **************************************************************** */ -/* */ -/* Info Node Commands */ -/* */ -/* **************************************************************** */ - -/* Using WINDOW for various defaults, select the node referenced by ENTRY - in it. If the node is selected, the window and node are remembered. */ -void -info_select_reference (window, entry) - WINDOW *window; - REFERENCE *entry; -{ - NODE *node; - char *filename, *nodename, *file_system_error; - - file_system_error = (char *)NULL; - - filename = entry->filename; - if (!filename) - filename = window->node->parent; - if (!filename) - filename = window->node->filename; - - if (filename) - filename = strdup (filename); - - if (entry->nodename) - nodename = strdup (entry->nodename); - else - nodename = strdup ("Top"); - - node = info_get_node (filename, nodename); - - /* Try something a little weird. If the node couldn't be found, and the - reference was of the form "foo::", see if the entry->label can be found - as a file, with a node of "Top". */ - if (!node) - { - if (info_recent_file_error) - file_system_error = strdup (info_recent_file_error); - - if (entry->nodename && (strcmp (entry->nodename, entry->label) == 0)) - { - node = info_get_node (entry->label, "Top"); - if (!node && info_recent_file_error) - { - maybe_free (file_system_error); - file_system_error = strdup (info_recent_file_error); - } - } - } - - if (!node) - { - if (file_system_error) - info_error (file_system_error); - else - info_error (CANT_FIND_NODE, nodename); - } - - maybe_free (file_system_error); - maybe_free (filename); - maybe_free (nodename); - - if (node) - { - set_remembered_pagetop_and_point (window); - info_set_node_of_window (window, node); - } -} - -/* Parse the node specification in LINE using WINDOW to default the filename. - Select the parsed node in WINDOW and remember it, or error if the node - couldn't be found. */ -static void -info_parse_and_select (line, window) - char *line; - WINDOW *window; -{ - REFERENCE entry; - - info_parse_node (line, DONT_SKIP_NEWLINES); - - entry.nodename = info_parsed_nodename; - entry.filename = info_parsed_filename; - entry.label = "*info-parse-and-select*"; - - info_select_reference (window, &entry); -} - -/* 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 (label, window) - char *label; - WINDOW *window; -{ - if (info_parsed_filename || info_parsed_nodename) - { - char *filename, *nodename; - NODE *node; - - filename = nodename = (char *)NULL; - - if (info_parsed_filename) - filename = strdup (info_parsed_filename); - else - { - if (window->node->parent) - filename = strdup (window->node->parent); - else if (window->node->filename) - filename = strdup (window->node->filename); - } - - if (info_parsed_nodename) - nodename = strdup (info_parsed_nodename); - else - nodename = strdup ("Top"); - - node = info_get_node (filename, nodename); - - if (node) - { - INFO_WINDOW *info_win; - - info_win = get_info_window_of_window (window); - if (info_win) - { - info_win->pagetops[info_win->current] = window->pagetop; - info_win->points[info_win->current] = window->point; - } - set_remembered_pagetop_and_point (window); - info_set_node_of_window (window, node); - } - else - { - if (info_recent_file_error) - info_error (info_recent_file_error); - else - info_error (CANT_FILE_NODE, filename, nodename); - } - - free (filename); - free (nodename); - } - else - { - info_error (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); - info_handle_pointer ("Next", window); -} - -/* Make WINDOW display the "Prev:" node of the node currently being - displayed. */ -DECLARE_INFO_COMMAND (info_prev_node, "Select the `Prev' node") -{ - info_prev_label_of_node (window->node); - info_handle_pointer ("Prev", window); -} - -/* Make WINDOW display the "Up:" node of the node currently being - displayed. */ -DECLARE_INFO_COMMAND (info_up_node, "Select the `Up' node") -{ - info_up_label_of_node (window->node); - info_handle_pointer ("Up", window); -} - -/* Make WINDOW display the last node of this info file. */ -DECLARE_INFO_COMMAND (info_last_node, "Select the last node in this file") -{ - register int i; - FILE_BUFFER *fb = file_buffer_of_window (window); - NODE *node = (NODE *)NULL; - - if (fb && fb->tags) - { - for (i = 0; fb->tags[i]; i++); - node = info_get_node (fb->filename, fb->tags[i - 1]->nodename); - } - - if (!node) - info_error ("This window has no additional nodes"); - else - { - set_remembered_pagetop_and_point (window); - info_set_node_of_window (window, node); - } -} - -/* Make WINDOW display the first node of this info file. */ -DECLARE_INFO_COMMAND (info_first_node, "Select the first node in this file") -{ - FILE_BUFFER *fb = file_buffer_of_window (window); - NODE *node = (NODE *)NULL; - - if (fb && fb->tags) - node = info_get_node (fb->filename, fb->tags[0]->nodename); - - if (!node) - info_error ("This window has no additional nodes"); - else - { - set_remembered_pagetop_and_point (window); - info_set_node_of_window (window, node); - } -} - -/* Make WINDOW display the previous node displayed in this window. */ -DECLARE_INFO_COMMAND (info_history_node, - "Select the most recently selected node") -{ - INFO_WINDOW *info_win; - - /* Find the INFO_WINDOW which contains WINDOW. */ - info_win = get_info_window_of_window (window); - - if (!info_win) - { - info_error ("Requested window is not present!"); - return; - } - - set_remembered_pagetop_and_point (window); - if (!info_win->current) - { - if (info_win->nodes_index > 1) - { - window_message_in_echo_area - ("Now wrapped around to beginning of history."); - info_win->current = info_win->nodes_index; - } - else - { - info_error ("No earlier nodes in this window."); - return; - } - } - - info_win->current--; - window_set_node_of_window (window, info_win->nodes[info_win->current]); - window->pagetop = info_win->pagetops[info_win->current]; - window->point = info_win->points[info_win->current]; - window->flags |= W_UpdateWindow; - if (auto_footnotes_p) - info_get_or_remove_footnotes (window); -} - -/* Select the last menu item in WINDOW->node. */ -DECLARE_INFO_COMMAND (info_last_menu_item, - "Select the last item in this node's menu") -{ - 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") -{ - register int i, item; - register REFERENCE *entry, **menu; - - menu = info_menu_of_node (window->node); - - if (!menu) - { - info_error (NO_MENU_NODE); - return; - } - - /* We have the menu. See if there are this many items in it. */ - item = key - '0'; - - /* Special case. Item "0" is the last item in this menu. */ - if (item == 0) - for (i = 0; menu[i + 1]; i++); - else - { - for (i = 0; entry = menu[i]; i++) - if (i == item - 1) - break; - } - - if (menu[i]) - info_select_reference (window, menu[i]); - else - info_error ("There aren't %d items in this menu.", item); - - info_free_references (menu); - return; -} - -/* 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. */ -static void -info_menu_or_ref_item (window, count, key, builder, ask_p) - WINDOW *window; - int count; - unsigned char key; - REFERENCE **(*builder) (); - int ask_p; -{ - REFERENCE **menu, *entry, *defentry = (REFERENCE *)NULL; - char *line; - - menu = (*builder) (window->node); - - if (!menu) - { - if (builder == info_menu_of_node) - info_error (NO_MENU_NODE); - else - info_error (NO_XREF_NODE); - return; - } - - /* Default the selected reference to the one which is on the line that - point is in. */ - { - REFERENCE **refs = (REFERENCE **)NULL; - int point_line; - - point_line = window_line_of_point (window); - - if (point_line != -1) - { - SEARCH_BINDING binding; - - 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; - - 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 = info_xrefs (&binding); - } - - if (refs) - { - if ((strcmp (refs[0]->label, "Menu") != 0) || - (builder == info_xrefs_of_node)) - { - int which = 0; - - /* Find the closest reference to point. */ - if (builder == info_xrefs_of_node) - { - int closest = -1; - - 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 (closest == -1) - which--; - else - which = closest; - } - - defentry = (REFERENCE *)xmalloc (sizeof (REFERENCE)); - defentry->label = strdup (refs[which]->label); - defentry->filename = refs[which]->filename; - defentry->nodename = refs[which]->nodename; - - if (defentry->filename) - defentry->filename = strdup (defentry->filename); - if (defentry->nodename) - defentry->nodename = strdup (defentry->nodename); - } - info_free_references (refs); - } - } - } - - /* If we are going to ask the user a question, do it now. */ - if (ask_p) - { - char *prompt; - - /* Build the prompt string. */ - if (defentry) - prompt = (char *)xmalloc (20 + strlen (defentry->label)); - else - prompt = (char *)xmalloc (20); - - if (builder == info_menu_of_node) - { - if (defentry) - sprintf (prompt, "Menu item (%s): ", defentry->label); - else - sprintf (prompt, "Menu item: "); - } - else - { - if (defentry) - sprintf (prompt, "Follow xref (%s): ", defentry->label); - else - sprintf (prompt, "Follow xref: "); - } - - line = info_read_completing_in_echo_area (window, prompt, menu); - free (prompt); - - window = active_window; - - /* User aborts, just quit. */ - if (!line) - { - maybe_free (defentry); - info_free_references (menu); - info_abort_key (window, 0, 0); - return; - } - - /* If we had a default and the user accepted it, use that. */ - if (!*line) - { - free (line); - if (defentry) - line = strdup (defentry->label); - else - line = (char *)NULL; - } - } - else - { - /* Not going to ask any questions. If we have a default entry, use - that, otherwise return. */ - if (!defentry) - return; - else - line = strdup (defentry->label); - } - - if (line) - { - /* Find the selected label in the references. */ - entry = info_get_labeled_reference (line, menu); - - if (!entry && defentry) - info_error ("The reference disappeared! (%s).", line); - else - { - NODE *orig; - - orig = window->node; - info_select_reference (window, entry); - if ((builder == info_xrefs_of_node) && (window->node != orig)) - { - 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); - - if (offset != -1) - { - window->point = offset; - window_adjust_pagetop (window); - } - } - } - - free (line); - if (defentry) - { - free (defentry->label); - maybe_free (defentry->filename); - maybe_free (defentry->nodename); - free (defentry); - } - } - - info_free_references (menu); - - if (!info_error_was_printed) - window_clear_echo_area (); -} - -/* Read a line (with completion) which is the name of a menu item, - 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); -} - -/* Read a line (with completion) which is the name of a reference to - follow, and select the 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); -} - -/* Position the cursor at the start of this node's menu. */ -DECLARE_INFO_COMMAND (info_find_menu, "Move to the start of this node's menu") -{ - SEARCH_BINDING binding; - long position; - - binding.buffer = window->node->contents; - binding.start = 0; - binding.end = window->node->nodelen; - binding.flags = S_FoldCase | S_SkipDest; - - position = search (INFO_MENU_LABEL, &binding); - - if (position == -1) - info_error (NO_MENU_NODE); - else - { - window->point = position; - window_adjust_pagetop (window); - window->flags |= W_UpdateWindow; - } -} - -/* Visit as many menu items as is possible, each in a separate window. */ -DECLARE_INFO_COMMAND (info_visit_menu, - "Visit as many menu items at once as possible") -{ - register int i; - REFERENCE *entry, **menu; - - menu = info_menu_of_node (window->node); - - if (!menu) - info_error (NO_MENU_NODE); - - for (i = 0; (!info_error_was_printed) && (entry = menu[i]); i++) - { - WINDOW *new; - - new = window_make_window (window->node); - window_tile_windows (TILE_INTERNALS); - - if (!new) - info_error (WIN_TOO_SMALL); - else - { - active_window = new; - info_select_reference (new, entry); - } - } -} - -/* Read a line of input which is a node name, and go to that node. */ -DECLARE_INFO_COMMAND (info_goto_node, "Read a node name and select it") -{ - char *line; - NODE *node; - -#define GOTO_COMPLETES -#if defined (GOTO_COMPLETES) - /* Build a completion list of all of the known nodes. */ - { - register int fbi, i; - FILE_BUFFER *current; - REFERENCE **items = (REFERENCE **)NULL; - int items_index = 0; - int items_slots = 0; - - current = file_buffer_of_window (window); - - for (fbi = 0; info_loaded_files && info_loaded_files[fbi]; fbi++) - { - FILE_BUFFER *fb; - REFERENCE *entry; - int this_is_the_current_fb; - - fb = info_loaded_files[fbi]; - this_is_the_current_fb = (current == fb); - - entry = (REFERENCE *)xmalloc (sizeof (REFERENCE)); - entry->filename = entry->nodename = (char *)NULL; - entry->label = (char *)xmalloc (4 + strlen (fb->filename)); - sprintf (entry->label, "(%s)*", fb->filename); - - add_pointer_to_array - (entry, items_index, items, items_slots, 10, REFERENCE *); - - if (fb->tags) - { - for (i = 0; fb->tags[i]; i++) - { - entry = (REFERENCE *)xmalloc (sizeof (REFERENCE)); - entry->filename = entry->nodename = (char *)NULL; - entry->label = (char *) xmalloc - (4 + strlen (fb->filename) + strlen (fb->tags[i]->nodename)); - sprintf (entry->label, "(%s)%s", - fb->filename, fb->tags[i]->nodename); - - add_pointer_to_array - (entry, items_index, items, items_slots, 100, REFERENCE *); - } - - if (this_is_the_current_fb) - { - for (i = 0; fb->tags[i]; i++) - { - entry = (REFERENCE *)xmalloc (sizeof (REFERENCE)); - entry->filename = entry->nodename = (char *)NULL; - entry->label = strdup (fb->tags[i]->nodename); - add_pointer_to_array (entry, items_index, items, - items_slots, 100, REFERENCE *); - } - } - } - } - line = info_read_maybe_completing (window, "Goto Node: ", items); - info_free_references (items); - } -#else /* !GOTO_COMPLETES */ - line = info_read_in_echo_area (window, "Goto Node: "); -#endif /* !GOTO_COMPLETES */ - - /* If the user aborted, quit now. */ - if (!line) - { - info_abort_key (window, 0, 0); - return; - } - - canonicalize_whitespace (line); - - if (*line) - info_parse_and_select (line, window); - - free (line); - if (!info_error_was_printed) - window_clear_echo_area (); -} - -#if defined (HANDLE_MAN_PAGES) -DECLARE_INFO_COMMAND (info_man, "Read a manpage reference and select it") -{ - char *line; - NODE *node; - - line = info_read_in_echo_area (window, "Get Manpage: "); - - if (!line) - { - info_abort_key (window, 0, 0); - return; - } - - canonicalize_whitespace (line); - - if (*line) - { - char *goto_command; - - goto_command = (char *)xmalloc - (4 + strlen (MANPAGE_FILE_BUFFER_NAME) + strlen (line)); - - sprintf (goto_command, "(%s)%s", MANPAGE_FILE_BUFFER_NAME, line); - - info_parse_and_select (goto_command, window); - free (goto_command); - } - - free (line); - if (!info_error_was_printed) - window_clear_echo_area (); -} -#endif /* HANDLE_MAN_PAGES */ - -/* Move to the "Top" node in this file. */ -DECLARE_INFO_COMMAND (info_top_node, "Select the node `Top' in this file") -{ - info_parse_and_select ("Top", window); -} - -/* Move to the node "(dir)Top". */ -DECLARE_INFO_COMMAND (info_dir_node, "Select the node `(dir)'") -{ - info_parse_and_select ("(dir)Top", window); -} - -/* Try to delete the current node appearing in this window, showing the most - recently selected node in this window. */ -DECLARE_INFO_COMMAND (info_kill_node, "Kill this node") -{ - register int iw, i; - register INFO_WINDOW *info_win; - char *nodename = (char *)NULL; - NODE *temp = (NODE *)NULL; - - /* Read the name of a node to kill. The list of available nodes comes - from the nodes appearing in the current window configuration. */ - { - REFERENCE **menu = (REFERENCE **)NULL; - int menu_index = 0, menu_slots = 0; - char *default_nodename, *prompt; - - for (iw = 0; info_win = info_windows[iw]; iw++) - { - REFERENCE *entry; - - entry = (REFERENCE *)xmalloc (sizeof (REFERENCE)); - entry->label = strdup (info_win->window->node->nodename); - entry->filename = entry->nodename = (char *)NULL; - - add_pointer_to_array - (entry, menu_index, menu, menu_slots, 10, REFERENCE *); - } - - default_nodename = strdup (active_window->node->nodename); - prompt = (char *)xmalloc (40 + strlen (default_nodename)); - sprintf (prompt, "Kill node (%s): ", default_nodename); - - nodename = info_read_completing_in_echo_area (window, prompt, menu); - free (prompt); - info_free_references (menu); - if (nodename && !*nodename) - { - free (nodename); - nodename = default_nodename; - } - else - free (default_nodename); - } - - /* If there is no nodename to kill, quit now. */ - if (!nodename) - { - info_abort_key (window, 0, 0); - return; - } - - /* If there is a nodename, find it in our window list. */ - for (iw = 0; info_win = info_windows[iw]; iw++) - if (strcmp (nodename, info_win->nodes[info_win->current]->nodename) == 0) - break; - - if (!info_win) - { - if (*nodename) - info_error ("Cannot kill the node `%s'", nodename); - else - window_clear_echo_area (); - - return; - } - - /* If there are no more nodes left anywhere to view, complain and exit. */ - if (info_windows_index == 1 && info_windows[0]->nodes_index == 1) - { - info_error ("Cannot kill the last node"); - return; - } - - /* INFO_WIN contains the node that the user wants to stop viewing. - Delete this node from the list of nodes previously shown in this - window. */ - for (i = info_win->current; i < info_win->nodes_index; i++) - info_win->nodes[i] = info_win->nodes[i++]; - - /* There is one less node in this window's history list. */ - info_win->nodes_index--; - - /* Make this window show the most recent history node. */ - info_win->current = info_win->nodes_index - 1; - - /* If there aren't any nodes left in this window, steal one from the - next window. */ - if (info_win->current < 0) - { - INFO_WINDOW *stealer; - int which, pagetop; - long point; - - if (info_windows[iw + 1]) - stealer = info_windows[iw + 1]; - else - stealer = info_windows[0]; - - /* If the node being displayed in the next window is not the most - recently loaded one, get the most recently loaded one. */ - if ((stealer->nodes_index - 1) != stealer->current) - which = stealer->nodes_index - 1; - - /* Else, if there is another node behind the stealers current node, - use that one. */ - else if (stealer->current > 0) - which = stealer->current - 1; - - /* Else, just use the node appearing in STEALER's window. */ - else - which = stealer->current; - - /* Copy this node. */ - { - NODE *copy; - - temp = stealer->nodes[which]; - point = stealer->points[which]; - pagetop = stealer->pagetops[which]; - - copy = (NODE *)xmalloc (sizeof (NODE)); - copy->filename = temp->filename; - copy->parent = temp->parent; - copy->nodename = temp->nodename; - copy->contents = temp->contents; - copy->nodelen = temp->nodelen; - copy->flags = temp->flags; - - temp = copy; - } - - window_set_node_of_window (info_win->window, temp); - window->point = point; - window->pagetop = pagetop; - remember_window_and_node (info_win->window, temp); - } - else - { - temp = info_win->nodes[info_win->current]; - window_set_node_of_window (info_win->window, temp); - } - if (!info_error_was_printed) - window_clear_echo_area (); -} - -/* Read the name of a file and select the entire file. */ -DECLARE_INFO_COMMAND (info_view_file, "Read the name of a file and select it") -{ - char *line; - - line = info_read_in_echo_area (window, "Find file: "); - if (!line) - { - info_abort_key (active_window, 1, 0); - return; - } - - if (*line) - { - NODE *node; - - node = info_get_node (line, "*"); - if (!node) - { - if (info_recent_file_error) - info_error (info_recent_file_error); - else - info_error ("Cannot find \"%s\".", line); - } - else - { - set_remembered_pagetop_and_point (active_window); - info_set_node_of_window (window, node); - } - free (line); - } - - if (!info_error_was_printed) - window_clear_echo_area (); -} - -/* **************************************************************** */ -/* */ -/* Dumping and Printing Nodes */ -/* */ -/* **************************************************************** */ - -#define VERBOSE_NODE_DUMPING -static void write_node_to_stream (); -static void dump_node_to_stream (); -static void initialize_dumping (); - -/* Dump the nodes specified by FILENAME and NODENAMES to the file named - in OUTPUT_FILENAME. If DUMP_SUBNODES is non-zero, recursively dump - the nodes which appear in the menu of each node dumped. */ -void -dump_nodes_to_file (filename, nodenames, output_filename, dump_subnodes) - char *filename; - char **nodenames; - char *output_filename; - int dump_subnodes; -{ - register int i; - FILE *output_stream; - - /* Get the stream to print the nodes to. Special case of an output - filename of "-" means to dump the nodes to stdout. */ - if (strcmp (output_filename, "-") == 0) - output_stream = stdout; - else - output_stream = fopen (output_filename, "w"); - - if (!output_stream) - { - info_error ("Could not create output file \"%s\".", output_filename); - return; - } - - /* Print each node to stream. */ - initialize_dumping (); - for (i = 0; nodenames[i]; i++) - dump_node_to_stream (filename, nodenames[i], output_stream, dump_subnodes); - - if (output_stream != stdout) - fclose (output_stream); - -#if defined (VERBOSE_NODE_DUMPING) - info_error ("Done."); -#endif /* VERBOSE_NODE_DUMPING */ -} - -/* A place to remember already dumped nodes. */ -static char **dumped_already = (char **)NULL; -static int dumped_already_index = 0; -static int dumped_already_slots = 0; - -static void -initialize_dumping () -{ - dumped_already_index = 0; -} - -/* Get and print the node specified by FILENAME and NODENAME to STREAM. - If DUMP_SUBNODES is non-zero, recursively dump the nodes which appear - in the menu of each node dumped. */ -static void -dump_node_to_stream (filename, nodename, stream, dump_subnodes) - char *filename, *nodename; - FILE *stream; - int dump_subnodes; -{ - register int i; - NODE *node; - - node = info_get_node (filename, nodename); - - if (!node) - { - if (info_recent_file_error) - info_error (info_recent_file_error); - else - { - if (filename && *nodename != '(') - info_error - (CANT_FILE_NODE, filename_non_directory (filename), nodename); - else - info_error (CANT_FIND_NODE, nodename); - } - return; - } - - /* If we have already dumped this node, don't dump it again. */ - for (i = 0; i < dumped_already_index; i++) - if (strcmp (node->nodename, dumped_already[i]) == 0) - { - free (node); - return; - } - add_pointer_to_array (node->nodename, dumped_already_index, dumped_already, - dumped_already_slots, 50, char *); - -#if defined (VERBOSE_NODE_DUMPING) - /* Maybe we should print some information about the node being output. */ - if (node->filename) - info_error ("Writing node \"(%s)%s\"...", - filename_non_directory (node->filename), node->nodename); - else - info_error ("Writing node \"%s\"...", node->nodename); -#endif /* VERBOSE_NODE_DUMPING */ - - write_node_to_stream (node, stream); - - /* If we are dumping subnodes, get the list of menu items in this node, - and dump each one recursively. */ - if (dump_subnodes) - { - REFERENCE **menu = (REFERENCE **)NULL; - - /* 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); - - if (menu) - { - for (i = 0; menu[i]; i++) - { - /* We don't dump Info files which are different than the - current one. */ - if (!menu[i]->filename) - dump_node_to_stream - (filename, menu[i]->nodename, stream, dump_subnodes); - } - info_free_references (menu); - } - } - - free (node); -} - -/* Dump NODE to FILENAME. If DUMP_SUBNODES is non-zero, recursively dump - the nodes which appear in the menu of each node dumped. */ -void -dump_node_to_file (node, filename, dump_subnodes) - NODE *node; - char *filename; - int dump_subnodes; -{ - FILE *output_stream; - char *nodes_filename; - - /* Get the stream to print this node to. Special case of an output - filename of "-" means to dump the nodes to stdout. */ - if (strcmp (filename, "-") == 0) - output_stream = stdout; - else - output_stream = fopen (filename, "w"); - - if (!output_stream) - { - info_error ("Could not create output file \"%s\".", filename); - return; - } - - if (node->parent) - nodes_filename = node->parent; - else - nodes_filename = node->filename; - - initialize_dumping (); - dump_node_to_stream - (nodes_filename, node->nodename, output_stream, dump_subnodes); - - if (output_stream != stdout) - fclose (output_stream); - -#if defined (VERBOSE_NODE_DUMPING) - info_error ("Done."); -#endif /* VERBOSE_NODE_DUMPING */ -} - -#if !defined (DEFAULT_INFO_PRINT_COMMAND) -# define DEFAULT_INFO_PRINT_COMMAND "lpr" -#endif /* !DEFAULT_INFO_PRINT_COMMAND */ - -DECLARE_INFO_COMMAND (info_print_node, - "Pipe the contents of this node through INFO_PRINT_COMMAND") -{ - print_node (window->node); -} - -/* Print NODE on a printer piping it into INFO_PRINT_COMMAND. */ -void -print_node (node) - NODE *node; -{ - char *print_command, *getenv (); - FILE *printer_pipe; - - print_command = getenv ("INFO_PRINT_COMMAND"); - - if (!print_command || !*print_command) - print_command = DEFAULT_INFO_PRINT_COMMAND; - - printer_pipe = popen (print_command, "w"); - - if (!printer_pipe) - { - info_error ("Cannot open pipe to \"%s\".", print_command); - return; - } - -#if defined (VERBOSE_NODE_DUMPING) - /* Maybe we should print some information about the node being output. */ - if (node->filename) - info_error ("Printing node \"(%s)%s\"...", - filename_non_directory (node->filename), node->nodename); - else - info_error ("Printing node \"%s\"...", node->nodename); -#endif /* VERBOSE_NODE_DUMPING */ - - write_node_to_stream (node, printer_pipe); - pclose (printer_pipe); - -#if defined (VERBOSE_NODE_DUMPING) - info_error ("Done."); -#endif /* VERBOSE_NODE_DUMPING */ -} - -static void -write_node_to_stream (node, stream) - NODE *node; - FILE *stream; -{ - fwrite (node->contents, 1, node->nodelen, stream); -} - -/* **************************************************************** */ -/* */ -/* Info Searching Commands */ -/* */ -/* **************************************************************** */ - -/* Variable controlling the garbage collection of files briefly visited - during searches. Such files are normally gc'ed, unless they were - compressed to begin with. If this variable is non-zero, it says - to gc even those file buffer contents which had to be uncompressed. */ -int gc_compressed_files = 0; - -static void info_gc_file_buffers (); - -static char *search_string = (char *)NULL; -static int search_string_index = 0; -static int search_string_size = 0; -static int isearch_is_active = 0; - -/* Return the file buffer which belongs to WINDOW's node. */ -FILE_BUFFER * -file_buffer_of_window (window) - WINDOW *window; -{ - /* If this window has no node, then it has no file buffer. */ - if (!window->node) - return ((FILE_BUFFER *)NULL); - - if (window->node->parent) - return (info_find_file (window->node->parent)); - - if (window->node->filename) - return (info_find_file (window->node->filename)); - - return ((FILE_BUFFER *)NULL); -} - -/* Search for STRING in NODE starting at START. Return -1 if the string - was not found, or the location of the string if it was. If WINDOW is - passed as non-null, set the window's node to be NODE, its point to be - the found string, and readjust the window's pagetop. Final argument - DIR says which direction to search in. If it is positive, search - forward, else backwards. */ -long -info_search_in_node (string, node, start, window, dir) - char *string; - NODE *node; - long start; - WINDOW *window; - int dir; -{ - SEARCH_BINDING binding; - long offset; - - binding.buffer = node->contents; - binding.start = start; - binding.end = node->nodelen; - binding.flags = S_FoldCase; - - if (dir < 0) - { - binding.end = 0; - binding.flags |= S_SkipDest; - } - - if (binding.start < 0) - return (-1); - - /* For incremental searches, we always wish to skip past the string. */ - if (isearch_is_active) - binding.flags |= S_SkipDest; - - offset = search (string, &binding); - - if (offset != -1 && window) - { - set_remembered_pagetop_and_point (window); - if (window->node != node) - window_set_node_of_window (window, node); - window->point = offset; - window_adjust_pagetop (window); - } - return (offset); -} - -/* Search NODE, looking for the largest possible match of STRING. Start the - search at START. Return the absolute position of the match, or -1, if - no part of the string could be found. */ -long -info_target_search_node (node, string, start) - NODE *node; - char *string; - long start; -{ - register int i; - long offset; - char *target; - - target = strdup (string); - i = strlen (target); - - /* Try repeatedly searching for this string while removing words from - the end of it. */ - while (i) - { - target[i] = '\0'; - offset = info_search_in_node (target, node, start, (WINDOW *)NULL, 1); - - if (offset != -1) - break; - - /* Delete the last word from TARGET. */ - for (; i && (!whitespace (target[i]) && (target[i] != ',')); i--); - } - free (target); - return (offset); -} - -/* Search for STRING starting in WINDOW at point. If the string is found - in this node, set point to that position. Otherwise, get the file buffer - associated with WINDOW's node, and search through each node in that file. - If the search fails, return non-zero, else zero. Side-effect window - leaving the node and point where the string was found current. */ -static char *last_searched_for_string = (char *)NULL; -static int -info_search_internal (string, window, dir) - char *string; - WINDOW *window; - int dir; -{ - register int i; - FILE_BUFFER *file_buffer; - char *initial_nodename; - long ret, start = 0; - - file_buffer = file_buffer_of_window (window); - initial_nodename = window->node->nodename; - - if ((info_last_executed_command == info_search) && - (last_searched_for_string) && - (strcmp (last_searched_for_string, string) == 0)) - { - ret = info_search_in_node - (string, window->node, window->point + dir, window, dir); - } - else - { - ret = info_search_in_node - (string, window->node, window->point, window, dir); - } - - maybe_free (last_searched_for_string); - last_searched_for_string = strdup (string); - - if (ret != -1) - { - /* We won! */ - if (!echo_area_is_active && !isearch_is_active) - window_clear_echo_area (); - return (0); - } - - /* The string wasn't found in the current node. Search through the - window's file buffer, iff the current node is not "*". */ - if (!file_buffer || (strcmp (initial_nodename, "*") == 0)) - return (-1); - - /* If this file has tags, search through every subfile, starting at - this node's subfile and node. Otherwise, search through the - file's node list. */ - if (file_buffer->tags) - { - register int current_tag, number_of_tags; - char *last_subfile; - TAG *tag; - - /* Find number of tags and current tag. */ - last_subfile = (char *)NULL; - for (i = 0; file_buffer->tags[i]; i++) - if (strcmp (initial_nodename, file_buffer->tags[i]->nodename) == 0) - { - current_tag = i; - last_subfile = file_buffer->tags[i]->filename; - } - - number_of_tags = i; - - /* If there is no last_subfile, our tag wasn't found. */ - if (!last_subfile) - return (-1); - - /* Search through subsequent nodes, wrapping around to the top - of the info file until we find the string or return to this - window's node and point. */ - while (1) - { - NODE *node; - - /* Allow C-g to quit the search, failing it if pressed. */ - return_if_control_g (-1); - - current_tag += dir; - - if (current_tag < 0) - current_tag = number_of_tags - 1; - else if (current_tag == number_of_tags) - current_tag = 0; - - tag = file_buffer->tags[current_tag]; - - if (!echo_area_is_active && (last_subfile != tag->filename)) - { - window_message_in_echo_area - ("Searching subfile \"%s\"...", - filename_non_directory (tag->filename)); - - last_subfile = tag->filename; - } - - node = info_get_node (file_buffer->filename, tag->nodename); - - if (!node) - { - /* If not doing i-search... */ - if (!echo_area_is_active) - { - if (info_recent_file_error) - info_error (info_recent_file_error); - else - info_error (CANT_FILE_NODE, - filename_non_directory (file_buffer->filename), - tag->nodename); - } - return (-1); - } - - if (dir < 0) - start = tag->nodelen; - - ret = - info_search_in_node (string, node, start, window, dir); - - /* Did we find the string in this node? */ - if (ret != -1) - { - /* Yes! We win. */ - remember_window_and_node (window, node); - if (!echo_area_is_active) - window_clear_echo_area (); - return (0); - } - - /* No. Free this node, and make sure that we haven't passed - our starting point. */ - free (node); - - if (strcmp (initial_nodename, tag->nodename) == 0) - return (-1); - } - } - return (-1); -} - -DECLARE_INFO_COMMAND (info_search, "Read a string and search for it") -{ - char *line, *prompt; - int result, old_pagetop; - int direction; - - if (count < 0) - direction = -1; - else - direction = 1; - - /* Read a string from the user, defaulting the search to SEARCH_STRING. */ - if (!search_string) - { - search_string = (char *)xmalloc (search_string_size = 100); - search_string[0] = '\0'; - } - - prompt = (char *)xmalloc (50 + strlen (search_string)); - - sprintf (prompt, "%s for string [%s]: ", - direction < 0 ? "Search backward" : "Search", - search_string); - - line = info_read_in_echo_area (window, prompt); - free (prompt); - - if (!line) - { - info_abort_key (); - return; - } - - if (*line) - { - if (strlen (line) + 1 > search_string_size) - search_string = (char *) - xrealloc (search_string, (search_string_size += 50 + strlen (line))); - - strcpy (search_string, line); - search_string_index = strlen (line); - free (line); - } - - old_pagetop = active_window->pagetop; - result = info_search_internal (search_string, active_window, direction); - - if (result != 0 && !info_error_was_printed) - info_error ("Search failed."); - else if (old_pagetop != active_window->pagetop) - { - int new_pagetop; - - new_pagetop = active_window->pagetop; - active_window->pagetop = old_pagetop; - set_window_pagetop (active_window, new_pagetop); - if (auto_footnotes_p) - info_get_or_remove_footnotes (active_window); - } - - /* Perhaps free the unreferenced file buffers that were searched, but - not retained. */ - info_gc_file_buffers (); -} - -/* **************************************************************** */ -/* */ -/* Incremental Searching */ -/* */ -/* **************************************************************** */ - -static void incremental_search (); - -DECLARE_INFO_COMMAND (isearch_forward, - "Search interactively for a string as you type it") -{ - incremental_search (window, count, key); -} - -DECLARE_INFO_COMMAND (isearch_backward, - "Search interactively for a string as you type it") -{ - incremental_search (window, -count, key); -} - -/* Incrementally search for a string as it is typed. */ -/* The last accepted incremental search string. */ -static char *last_isearch_accepted = (char *)NULL; - -/* The current incremental search string. */ -static char *isearch_string = (char *)NULL; -static int isearch_string_index = 0; -static int isearch_string_size = 0; -static unsigned char isearch_terminate_search_key = ESC; - -/* Structure defining the current state of an incremental search. */ -typedef struct { - WINDOW_STATE_DECL; /* The node, pagetop and point. */ - int search_index; /* Offset of the last char in the search string. */ - int direction; /* The direction that this search is heading in. */ - int failing; /* Whether or not this search failed. */ -} SEARCH_STATE; - -/* Array of search states. */ -static SEARCH_STATE **isearch_states = (SEARCH_STATE **)NULL; -static int isearch_states_index = 0; -static int isearch_states_slots = 0; - -/* Push the state of this search. */ -static void -push_isearch (window, search_index, direction, failing) - WINDOW *window; - int search_index, direction, failing; -{ - SEARCH_STATE *state; - - state = (SEARCH_STATE *)xmalloc (sizeof (SEARCH_STATE)); - window_get_state (window, state); - state->search_index = search_index; - state->direction = direction; - state->failing = failing; - - add_pointer_to_array (state, isearch_states_index, isearch_states, - isearch_states_slots, 20, SEARCH_STATE *); -} - -/* Pop the state of this search to WINDOW, SEARCH_INDEX, and DIRECTION. */ -static void -pop_isearch (window, search_index, direction, failing) - WINDOW *window; - int *search_index, *direction, *failing; -{ - SEARCH_STATE *state; - - if (isearch_states_index) - { - isearch_states_index--; - state = isearch_states[isearch_states_index]; - window_set_state (window, state); - *search_index = state->search_index; - *direction = state->direction; - *failing = state->failing; - - free (state); - isearch_states[isearch_states_index] = (SEARCH_STATE *)NULL; - } -} - -/* Free the memory used by isearch_states. */ -static void -free_isearch_states () -{ - register int i; - - for (i = 0; i < isearch_states_index; i++) - { - free (isearch_states[i]); - isearch_states[i] = (SEARCH_STATE *)NULL; - } - isearch_states_index = 0; -} - -/* Display the current search in the echo area. */ -static void -show_isearch_prompt (dir, string, failing_p) - int dir; - unsigned char *string; - int failing_p; -{ - register int i; - char *prefix, *prompt, *p_rep; - int prompt_len, p_rep_index, p_rep_size; - - if (dir < 0) - prefix = "I-search backward: "; - else - prefix = "I-search: "; - - p_rep_index = p_rep_size = 0; - p_rep = (char *)NULL; - for (i = 0; string[i]; i++) - { - char *rep; - - switch (string[i]) - { - case ' ': rep = " "; break; - case LFD: rep = "\\n"; break; - case TAB: rep = "\\t"; break; - default: - rep = pretty_keyname (string[i]); - } - if ((p_rep_index + strlen (rep) + 1) >= p_rep_size) - p_rep = (char *)xrealloc (p_rep, p_rep_size += 100); - - strcpy (p_rep + p_rep_index, rep); - p_rep_index += strlen (rep); - } - - prompt_len = strlen (prefix) + p_rep_index + 20; - prompt = (char *)xmalloc (prompt_len); - sprintf (prompt, "%s%s%s", failing_p ? "Failing " : "", prefix, - p_rep ? p_rep : ""); - - window_message_in_echo_area ("%s", prompt); - maybe_free (p_rep); - free (prompt); - display_cursor_at_point (active_window); -} - -static void -incremental_search (window, count, ignore) - WINDOW *window; - int count; - unsigned char ignore; -{ - unsigned char key; - int last_search_result, search_result, dir; - SEARCH_STATE mystate, orig_state; - - if (count < 0) - dir = -1; - else - dir = 1; - - last_search_result = search_result = 0; - - window_get_state (window, &orig_state); - - isearch_string_index = 0; - if (!isearch_string_size) - isearch_string = (char *)xmalloc (isearch_string_size = 50); - - /* Show the search string in the echo area. */ - isearch_string[isearch_string_index] = '\0'; - show_isearch_prompt (dir, isearch_string, search_result); - - isearch_is_active = 1; - - while (isearch_is_active) - { - VFunction *func = (VFunction *)NULL; - int quoted = 0; - - /* If a recent display was interrupted, then do the redisplay now if - it is convenient. */ - if (!info_any_buffered_input_p () && display_was_interrupted_p) - { - display_update_one_window (window); - display_cursor_at_point (active_window); - } - - /* Read a character and dispatch on it. */ - key = info_get_input_char (); - window_get_state (window, &mystate); - - if (key == DEL) - { - /* User wants to delete one level of search? */ - if (!isearch_states_index) - { - terminal_ring_bell (); - continue; - } - else - { - pop_isearch - (window, &isearch_string_index, &dir, &search_result); - isearch_string[isearch_string_index] = '\0'; - show_isearch_prompt (dir, isearch_string, search_result); - goto after_search; - } - } - else if (key == Control ('q')) - { - key = info_get_input_char (); - quoted = 1; - } - - /* We are about to search again, or quit. Save the current search. */ - push_isearch (window, isearch_string_index, dir, search_result); - - if (quoted) - goto insert_and_search; - - if (!Meta_p (key) || (ISO_Latin_p && key < 160)) - { - func = window->keymap[key].function; - - /* If this key invokes an incremental search, then this means that - we will either search again in the same direction, search - again in the reverse direction, or insert the last search - string that was accepted through incremental searching. */ - if (func == isearch_forward || func == isearch_backward) - { - if ((func == isearch_forward && dir > 0) || - (func == isearch_backward && dir < 0)) - { - /* If the user has typed no characters, then insert the - last successful search into the current search string. */ - if (isearch_string_index == 0) - { - /* Of course, there must be something to insert. */ - if (last_isearch_accepted) - { - if (strlen (last_isearch_accepted) + 1 >= - isearch_string_size) - isearch_string = (char *) - xrealloc (isearch_string, - isearch_string_size += 10 + - strlen (last_isearch_accepted)); - strcpy (isearch_string, last_isearch_accepted); - isearch_string_index = strlen (isearch_string); - goto search_now; - } - else - continue; - } - else - { - /* Search again in the same direction. This means start - from a new place if the last search was successful. */ - if (search_result == 0) - window->point += dir; - } - } - else - { - /* Reverse the direction of the search. */ - dir = -dir; - } - } - else if (isprint (key) || func == (VFunction *)NULL) - { - insert_and_search: - - if (isearch_string_index + 2 >= isearch_string_size) - isearch_string = (char *)xrealloc - (isearch_string, isearch_string_size += 100); - - isearch_string[isearch_string_index++] = key; - isearch_string[isearch_string_index] = '\0'; - goto search_now; - } - else if (func == info_abort_key) - { - /* If C-g pressed, and the search is failing, pop the search - stack back to the last unfailed search. */ - if (isearch_states_index && (search_result != 0)) - { - terminal_ring_bell (); - while (isearch_states_index && (search_result != 0)) - pop_isearch - (window, &isearch_string_index, &dir, &search_result); - isearch_string[isearch_string_index] = '\0'; - show_isearch_prompt (dir, isearch_string, search_result); - continue; - } - else - goto exit_search; - } - else - goto exit_search; - } - else - { - exit_search: - /* The character is not printable, or it has a function which is - non-null. Exit the search, remembering the search string. If - the key is not the same as the isearch_terminate_search_key, - then push it into pending input. */ - if (isearch_string_index && func != info_abort_key) - { - maybe_free (last_isearch_accepted); - last_isearch_accepted = strdup (isearch_string); - } - - if (key != isearch_terminate_search_key) - info_set_pending_input (key); - - if (func == info_abort_key) - { - if (isearch_states_index) - window_set_state (window, &orig_state); - } - - if (!echo_area_is_active) - window_clear_echo_area (); - - if (auto_footnotes_p) - info_get_or_remove_footnotes (active_window); - - isearch_is_active = 0; - continue; - } - - /* Search for the contents of isearch_string. */ - search_now: - show_isearch_prompt (dir, isearch_string, search_result); - - if (search_result == 0) - { - /* Check to see if the current search string is right here. If - we are looking at it, then don't bother calling the search - function. */ - if (((dir < 0) && - (strncasecmp (window->node->contents + window->point, - isearch_string, isearch_string_index) == 0)) || - ((dir > 0) && - ((window->point - isearch_string_index) >= 0) && - (strncasecmp (window->node->contents + - (window->point - (isearch_string_index - 1)), - isearch_string, isearch_string_index) == 0))) - { - if (dir > 0) - window->point++; - } - else - search_result = info_search_internal (isearch_string, window, dir); - } - - /* If this search failed, and we didn't already have a failed search, - then ring the terminal bell. */ - if (search_result != 0 && last_search_result == 0) - terminal_ring_bell (); - - after_search: - show_isearch_prompt (dir, isearch_string, search_result); - - if (search_result == 0) - { - if ((mystate.node == window->node) && - (mystate.pagetop != window->pagetop)) - { - int newtop = window->pagetop; - window->pagetop = mystate.pagetop; - set_window_pagetop (window, newtop); - } - display_update_one_window (window); - display_cursor_at_point (window); - } - - last_search_result = search_result; - } - - /* Free the memory used to remember each search state. */ - free_isearch_states (); - - /* Perhaps GC some file buffers. */ - info_gc_file_buffers (); - - /* After searching, leave the window in the correct state. */ - if (!echo_area_is_active) - window_clear_echo_area (); -} - -/* GC some file buffers. A file buffer can be gc-ed if there we have - no nodes in INFO_WINDOWS that reference this file buffer's contents. - Garbage collecting a file buffer means to free the file buffers - contents. */ -static void -info_gc_file_buffers () -{ - register int fb_index, iw_index, i; - register FILE_BUFFER *fb; - register INFO_WINDOW *iw; - - if (!info_loaded_files) - return; - - for (fb_index = 0; fb = info_loaded_files[fb_index]; fb_index++) - { - int fb_referenced_p = 0; - - /* If already gc-ed, do nothing. */ - if (!fb->contents) - continue; - - /* If this file had to be uncompressed, check to see if we should - gc it. This means that the user-variable "gc-compressed-files" - is non-zero. */ - if ((fb->flags & N_IsCompressed) && !gc_compressed_files) - continue; - - /* If this file's contents are not gc-able, move on. */ - if (fb->flags & N_CannotGC) - continue; - - /* Check each INFO_WINDOW to see if it has any nodes which reference - this file. */ - for (iw_index = 0; iw = info_windows[iw_index]; iw_index++) - { - for (i = 0; iw->nodes && iw->nodes[i]; i++) - { - if ((strcmp (fb->fullpath, iw->nodes[i]->filename) == 0) || - (strcmp (fb->filename, iw->nodes[i]->filename) == 0)) - { - fb_referenced_p = 1; - break; - } - } - } - - /* If this file buffer wasn't referenced, free its contents. */ - if (!fb_referenced_p) - { - free (fb->contents); - fb->contents = (char *)NULL; - } - } -} - -/* **************************************************************** */ -/* */ -/* Traversing and Selecting References */ -/* */ -/* **************************************************************** */ - -/* Move to the next or previous cross reference in this node. */ -static void -info_move_to_xref (window, count, key, dir) - 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; - - 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, (WINDOW *)NULL, dir); - - /* 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, (WINDOW *)NULL, dir); - } - - firstxref = - info_search_in_node (INFO_XREF_LABEL, node, start, (WINDOW *)NULL, dir); - -#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) - { - info_error ("No cross references in this node."); - return; - } - - /* 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, (WINDOW *)NULL, dir); - - nextxref = info_search_in_node - (INFO_XREF_LABEL, node, window->point + dir, (WINDOW *)NULL, dir); - -#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, (WINDOW *)NULL, dir); - } - - /* 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 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. */ - if (placement == -1) - { - 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; - } - window->point = placement; - window_adjust_pagetop (window); - window->flags |= W_UpdateWindow; -} - -DECLARE_INFO_COMMAND (info_move_to_prev_xref, - "Move to the previous cross reference") -{ - if (count < 0) - info_move_to_prev_xref (window, -count, key); - else - info_move_to_xref (window, count, key, -1); -} - -DECLARE_INFO_COMMAND (info_move_to_next_xref, - "Move to the next cross reference") -{ - if (count < 0) - info_move_to_next_xref (window, -count, key); - else - info_move_to_xref (window, count, key, 1); -} - -/* Select the menu item or reference that appears on this line. */ -DECLARE_INFO_COMMAND (info_select_reference_this_line, - "Select reference or menu item appearing on this line") -{ - char *line; - NODE *orig; - - line = window->line_starts[window_line_of_point (window)]; - orig = window->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); -} - -/* **************************************************************** */ -/* */ -/* Miscellaneous Info Commands */ -/* */ -/* **************************************************************** */ - -/* What to do when C-g is pressed in a window. */ -DECLARE_INFO_COMMAND (info_abort_key, "Cancel current operation") -{ - /* If error printing doesn't oridinarily ring the bell, do it now, - since C-g always rings the bell. Otherwise, let the error printer - do it. */ - if (!info_error_rings_bell_p) - terminal_ring_bell (); - info_error ("Quit"); - - info_initialize_numeric_arg (); - info_clear_pending_input (); - info_last_executed_command = (VFunction *)NULL; -} - -/* Move the cursor to the desired line of the window. */ -DECLARE_INFO_COMMAND (info_move_to_window_line, - "Move to the cursor to a specific line of the window") -{ - int line; - - /* With no numeric argument of any kind, default to the center line. */ - if (!info_explicit_arg && count == 1) - line = (window->height / 2) + window->pagetop; - else - { - if (count < 0) - line = (window->height + count) + window->pagetop; - else - line = window->pagetop + count; - } - - /* If the line doesn't appear in this window, make it do so. */ - if ((line - window->pagetop) >= window->height) - line = window->pagetop + (window->height - 1); - - /* If the line is too small, make it fit. */ - if (line < window->pagetop) - line = window->pagetop; - - /* If the selected line is past the bottom of the node, force it back. */ - if (line >= window->line_count) - line = window->line_count - 1; - - window->point = (window->line_starts[line] - window->node->contents); -} - -/* Clear the screen and redraw its contents. Given a numeric argument, - move the line the cursor is on to the COUNT'th line of the window. */ -DECLARE_INFO_COMMAND (info_redraw_display, "Redraw the display") -{ - if ((!info_explicit_arg && count == 1) || echo_area_is_active) - { - terminal_clear_screen (); - display_clear_display (the_display); - window_mark_chain (windows, W_UpdateWindow); - display_update_display (windows); - } - else - { - int desired_line, point_line; - int new_pagetop; - - point_line = window_line_of_point (window) - window->pagetop; - - if (count < 0) - desired_line = window->height + count; - else - desired_line = count; - - if (desired_line < 0) - desired_line = 0; - - if (desired_line >= window->height) - desired_line = window->height - 1; - - if (desired_line == point_line) - return; - - new_pagetop = window->pagetop + (point_line - desired_line); - - set_window_pagetop (window, new_pagetop); - } -} -/* This command does nothing. It is the fact that a key is bound to it - that has meaning. See the code at the top of info_session (). */ -DECLARE_INFO_COMMAND (info_quit, "Quit using Info") -{} - - -/* **************************************************************** */ -/* */ -/* Reading Keys and Dispatching on Them */ -/* */ -/* **************************************************************** */ - -/* Declaration only. Special cased in info_dispatch_on_key (). */ -DECLARE_INFO_COMMAND (info_do_lowercase_version, "") -{} - -static void -dispatch_error (keyseq) - char *keyseq; -{ - char *rep; - - rep = pretty_keyseq (keyseq); - - if (!echo_area_is_active) - info_error ("Unknown command (%s).", rep); - else - { - char *temp; - - temp = (char *)xmalloc (1 + strlen (rep) + strlen ("\"\" is invalid")); - - sprintf (temp, "\"%s\" is invalid", rep); - terminal_ring_bell (); - inform_in_echo_area (temp); - free (temp); - } -} - -/* Keeping track of key sequences. */ -static char *info_keyseq = (char *)NULL; -static char keyseq_rep[100]; -static int info_keyseq_index = 0; -static int info_keyseq_size = 0; -static int info_keyseq_displayed_p = 0; - -/* Initialize the length of the current key sequence. */ -void -initialize_keyseq () -{ - info_keyseq_index = 0; - info_keyseq_displayed_p = 0; -} - -/* Add CHARACTER to the current key sequence. */ -void -add_char_to_keyseq (character) - char character; -{ - if (info_keyseq_index + 2 >= info_keyseq_size) - info_keyseq = (char *)xrealloc (info_keyseq, info_keyseq_size += 10); - - info_keyseq[info_keyseq_index++] = character; - info_keyseq[info_keyseq_index] = '\0'; -} - -/* Return the pretty printable string which represents KEYSEQ. */ -char * -pretty_keyseq (keyseq) - char *keyseq; -{ - register int i; - - keyseq_rep[0] = '\0'; - - for (i = 0; keyseq[i]; i++) - { - sprintf (keyseq_rep + strlen (keyseq_rep), "%s%s", - strlen (keyseq_rep) ? " " : "", - pretty_keyname (keyseq[i])); - } - - return (keyseq_rep); -} - -/* Display the current value of info_keyseq. If argument EXPECTING is - non-zero, input is expected to be read after the key sequence is - displayed, so add an additional prompting character to the sequence. */ -void -display_info_keyseq (expecting_future_input) - int expecting_future_input; -{ - char *rep; - - rep = pretty_keyseq (info_keyseq); - if (expecting_future_input) - strcat (rep, "-"); - - if (echo_area_is_active) - inform_in_echo_area (rep); - else - { - window_message_in_echo_area (rep); - display_cursor_at_point (active_window); - } - info_keyseq_displayed_p = 1; -} - -/* Called by interactive commands to read a keystroke. */ -unsigned char -info_get_another_input_char () -{ - int ready = 0; - - /* If there isn't any input currently available, then wait a - moment looking for input. If we don't get it fast enough, - prompt a little bit with the current key sequence. */ - if (!info_keyseq_displayed_p && - !info_any_buffered_input_p () && - !info_input_pending_p ()) - { -#if defined (FD_SET) - struct timeval timer; - fd_set readfds; - - FD_ZERO (&readfds); - FD_SET (fileno (info_input_stream), &readfds); - timer.tv_sec = 1; - timer.tv_usec = 750; - ready = select (1, &readfds, (fd_set *)NULL, (fd_set *)NULL, &timer); -#endif /* FD_SET */ - } - - if (!ready) - display_info_keyseq (1); - - return (info_get_input_char ()); -} - -/* Do the command associated with KEY in MAP. If the associated command is - really a keymap, then read another key, and dispatch into that map. */ -void -info_dispatch_on_key (key, map) - unsigned char key; - Keymap map; -{ - if (Meta_p (key) && (!ISO_Latin_p || map[key].function != ea_insert)) - { - if (map[ESC].type == ISKMAP) - { - map = (Keymap)map[ESC].function; - add_char_to_keyseq (ESC); - key = UnMeta (key); - info_dispatch_on_key (key, map); - } - else - { - dispatch_error (info_keyseq); - } - return; - } - - switch (map[key].type) - { - case ISFUNC: - { - VFunction *func; - - func = map[key].function; - if (func != (VFunction *)NULL) - { - /* Special case info_do_lowercase_version (). */ - if (func == info_do_lowercase_version) - { - info_dispatch_on_key (tolower (key), map); - return; - } - - add_char_to_keyseq (key); - - if (info_keyseq_displayed_p) - display_info_keyseq (0); - - { - WINDOW *where; - - where = active_window; - (*map[key].function) - (active_window, info_numeric_arg * info_numeric_arg_sign, key); - - /* If we have input pending, then the last command was a prefix - command. Don't change the value of the last function vars. - Otherwise, remember the last command executed in the var - appropriate to the window in which it was executed. */ - if (!info_input_pending_p ()) - { - if (where == the_echo_area) - ea_last_executed_command = map[key].function; - else - info_last_executed_command = map[key].function; - } - } - } - else - { - add_char_to_keyseq (key); - dispatch_error (info_keyseq); - return; - } - } - break; - - case ISKMAP: - add_char_to_keyseq (key); - if (map[key].function != (VFunction *)NULL) - { - unsigned char newkey; - - newkey = info_get_another_input_char (); - info_dispatch_on_key (newkey, (Keymap)map[key].function); - } - else - { - dispatch_error (info_keyseq); - return; - } - break; - } -} - -/* **************************************************************** */ -/* */ -/* Numeric Arguments */ -/* */ -/* **************************************************************** */ - -/* Handle C-u style numeric args, as well as M--, and M-digits. */ - -/* Non-zero means that an explicit argument has been passed to this - command, as in C-u C-v. */ -int info_explicit_arg = 0; - -/* The sign of the numeric argument. */ -int info_numeric_arg_sign = 1; - -/* The value of the argument itself. */ -int info_numeric_arg = 1; - -/* Add the current digit to the argument in progress. */ -DECLARE_INFO_COMMAND (info_add_digit_to_numeric_arg, - "Add this digit to the current numeric argument") -{ - info_numeric_arg_digit_loop (window, 0, key); -} - -/* C-u, universal argument. Multiply the current argument by 4. - Read a key. If the key has nothing to do with arguments, then - dispatch on it. If the key is the abort character then abort. */ -DECLARE_INFO_COMMAND (info_universal_argument, - "Start (or multiply by 4) the current numeric argument") -{ - info_numeric_arg *= 4; - info_numeric_arg_digit_loop (window, 0, 0); -} - -/* Create a default argument. */ -void -info_initialize_numeric_arg () -{ - info_numeric_arg = info_numeric_arg_sign = 1; - info_explicit_arg = 0; -} - -DECLARE_INFO_COMMAND (info_numeric_arg_digit_loop, - "Internally used by \\[universal-argument]") -{ - unsigned char pure_key; - Keymap keymap = window->keymap; - - while (1) - { - if (key) - pure_key = key; - else - { - if (display_was_interrupted_p && !info_any_buffered_input_p ()) - display_update_display (windows); - - if (active_window != the_echo_area) - display_cursor_at_point (active_window); - - pure_key = key = info_get_another_input_char (); - - if (Meta_p (key)) - add_char_to_keyseq (ESC); - - add_char_to_keyseq (UnMeta (key)); - } - - if (Meta_p (key)) - key = UnMeta (key); - - if (keymap[key].type == ISFUNC && - keymap[key].function == info_universal_argument) - { - info_numeric_arg *= 4; - key = 0; - continue; - } - - if (isdigit (key)) - { - if (info_explicit_arg) - info_numeric_arg = (info_numeric_arg * 10) + (key - '0'); - else - info_numeric_arg = (key - '0'); - info_explicit_arg = 1; - } - else - { - if (key == '-' && !info_explicit_arg) - { - info_numeric_arg_sign = -1; - info_numeric_arg = 1; - } - else - { - info_keyseq_index--; - info_dispatch_on_key (pure_key, keymap); - return; - } - } - key = 0; - } -} - -/* **************************************************************** */ -/* */ -/* Input Character Buffering */ -/* */ -/* **************************************************************** */ - -/* Character waiting to be read next. */ -static int pending_input_character = 0; - -/* How to make there be no pending input. */ -static void -info_clear_pending_input () -{ - pending_input_character = 0; -} - -/* How to set the pending input character. */ -static void -info_set_pending_input (key) - unsigned char key; -{ - pending_input_character = key; -} - -/* How to see if there is any pending input. */ -unsigned char -info_input_pending_p () -{ - return (pending_input_character); -} - -/* Largest number of characters that we can read in advance. */ -#define MAX_INFO_INPUT_BUFFERING 512 - -static int pop_index = 0, push_index = 0; -static unsigned char info_input_buffer[MAX_INFO_INPUT_BUFFERING]; - -/* Add KEY to the buffer of characters to be read. */ -static void -info_push_typeahead (key) - unsigned char key; -{ - /* Flush all pending input in the case of C-g pressed. */ - if (key == Control ('g')) - { - push_index = pop_index; - info_set_pending_input (Control ('g')); - } - else - { - info_input_buffer[push_index++] = key; - if (push_index >= sizeof (info_input_buffer)) - push_index = 0; - } -} - -/* Return the amount of space available in INFO_INPUT_BUFFER for new chars. */ -static int -info_input_buffer_space_available () -{ - if (pop_index > push_index) - return (pop_index - push_index); - else - return (sizeof (info_input_buffer) - (push_index - pop_index)); -} - -/* Get a key from the buffer of characters to be read. - Return the key in KEY. - Result is non-zero if there was a key, or 0 if there wasn't. */ -static int -info_get_key_from_typeahead (key) - unsigned char *key; -{ - if (push_index == pop_index) - return (0); - - *key = info_input_buffer[pop_index++]; - - if (pop_index >= sizeof (info_input_buffer)) - pop_index = 0; - - return (1); -} - -int -info_any_buffered_input_p () -{ - info_gather_typeahead (); - return (push_index != pop_index); -} - -/* Push KEY into the *front* of the input buffer. Returns non-zero if - successful, zero if there is no space left in the buffer. */ -static int -info_replace_key_to_typeahead (key) - unsigned char key; -{ - if (info_input_buffer_space_available ()) - { - pop_index--; - if (pop_index < 0) - pop_index = sizeof (info_input_buffer) - 1; - info_input_buffer[pop_index] = key; - return (1); - } - return (0); -} - -/* If characters are available to be read, then read them and stuff them into - info_input_buffer. Otherwise, do nothing. */ -void -info_gather_typeahead () -{ - register int i = 0; - int tty, space_avail; - long chars_avail; - unsigned char input[MAX_INFO_INPUT_BUFFERING]; - - tty = fileno (info_input_stream); - chars_avail = 0; - - space_avail = info_input_buffer_space_available (); - - /* If we can just find out how many characters there are to read, do so. */ -#if defined (FIONREAD) - { - ioctl (tty, FIONREAD, &chars_avail); - - if (chars_avail > space_avail) - chars_avail = space_avail; - - if (chars_avail) - read (tty, &input[0], chars_avail); - } -#else /* !FIONREAD */ -# if defined (O_NDELAY) - { - int flags; - - flags = fcntl (tty, F_GETFL, 0); - - fcntl (tty, F_SETFL, (flags | O_NDELAY)); - chars_avail = read (tty, &input[0], space_avail); - fcntl (tty, F_SETFL, flags); - - if (chars_avail == -1) - chars_avail = 0; - } -# endif /* O_NDELAY */ -#endif /* !FIONREAD */ - - while (i < chars_avail) - { - info_push_typeahead (input[i]); - i++; - } -} - -/* How to read a single character. */ -unsigned char -info_get_input_char () -{ - unsigned char keystroke; - - info_gather_typeahead (); - - if (pending_input_character) - { - keystroke = pending_input_character; - pending_input_character = 0; - } - else if (info_get_key_from_typeahead (&keystroke) == 0) - { - int rawkey; - - rawkey = getc (info_input_stream); - keystroke = rawkey; - - if (rawkey == EOF) - { - if (info_input_stream != stdin) - { - fclose (info_input_stream); - info_input_stream = stdin; - display_inhibited = 0; - display_update_display (windows); - display_cursor_at_point (active_window); - rawkey = getc (info_input_stream); - keystroke = rawkey; - } - - if (rawkey == EOF) - { - terminal_unprep_terminal (); - close_dribble_file (); - exit (0); - } - } - } - - if (info_dribble_file) - dribble (keystroke); - - return (keystroke); -} diff --git a/info/session.h b/info/session.h deleted file mode 100644 --- a/info/session.h +++ /dev/null @@ -1,146 +0,0 @@ -/* session.h -- Functions found in session.c. */ - -/* 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). */ - -#if !defined (_SESSION_H_) -#define _SESSION_H_ - -#include "general.h" -#include "dribble.h" - -/* All commands that can be invoked from within info_session () receive - arguments in the same way. This simple define declares the header - of a function named NAME, with associated documentation DOC. The - documentation string is groveled out of the source files by the - utility program `makedoc', which is also responsible for making - the documentation/function-pointer maps. */ -#define DECLARE_INFO_COMMAND(name, doc) \ -void name (window, count, key) WINDOW *window; int count; unsigned char key; - -/* Variables found in session.h. */ -extern VFunction *info_last_executed_command; - -/* Variable controlling the garbage collection of files briefly visited - during searches. Such files are normally gc'ed, unless they were - compressed to begin with. If this variable is non-zero, it says - to gc even those file buffer contents which had to be uncompressed. */ -extern int gc_compressed_files; - -/* When non-zero, tiling takes place automatically when info_split_window - is called. */ -extern int auto_tiling_p; - -/* Variable controlling the behaviour of default scrolling when you are - already at the bottom of a node. */ -extern int info_scroll_behaviour; -extern char *info_scroll_choices[]; - -/* Values for info_scroll_behaviour. */ -#define IS_Continuous 0 /* Try to get first menu item, or failing that, the - "Next:" pointer, or failing that, the "Up:" and - "Next:" of the up. */ -#define IS_NextOnly 1 /* Try to get "Next:" menu item. */ -#define IS_PageOnly 2 /* Simply give up at the bottom of a node. */ - -/* Utility functions found in session.c */ -extern void info_dispatch_on_key (); -extern unsigned char info_get_input_char (), info_get_another_input_char (); -extern unsigned char info_input_pending_p (); -extern void remember_window_and_node (), set_remembered_pagetop_and_point (); -extern void set_window_pagetop (), info_set_node_of_window (); -extern char *pretty_keyseq (); -extern void initialize_keyseq (), add_char_to_keyseq (); -extern void info_gather_typeahead (); -extern FILE_BUFFER *file_buffer_of_window (); -extern long info_search_in_node (), info_target_search_node (); -extern void info_select_reference (); -extern int info_any_buffered_input_p (); -extern void print_node (); -extern void dump_node_to_file (), dump_nodes_to_file (); - -/* Do the physical deletion of WINDOW, and forget this window and - associated nodes. */ -extern void info_delete_window_internal (); - -/* Tell Info that input is coming from the file FILENAME. */ -extern void info_set_input_from_file (); - -#define return_if_control_g(val) \ - do { \ - info_gather_typeahead (); \ - if (info_input_pending_p () == Control ('g')) \ - return (val); \ - } while (0) - -/* The names of the functions that run an info session. */ - -/* Starting an info session. */ -extern void begin_multiple_window_info_session (), begin_info_session (); -extern void begin_info_session_with_error (), info_session (); -extern void info_read_and_dispatch (); - -/* Moving the point within a node. */ -extern void info_next_line (), info_prev_line (); -extern void info_end_of_line (), info_beginning_of_line (); -extern void info_forward_char (), info_backward_char (); -extern void info_forward_word (), info_backward_word (); -extern void info_beginning_of_node (), info_end_of_node (); -extern void info_move_to_prev_xref (), info_move_to_next_xref (); - -/* Scrolling text within a window. */ -extern void info_scroll_forward (), info_scroll_backward (); -extern void info_redraw_display (), info_toggle_wrap (); -extern void info_move_to_window_line (); - -/* Manipulating multiple windows. */ -extern void info_split_window (), info_delete_window (); -extern void info_keep_one_window (), info_grow_window (); -extern void info_scroll_other_window (), info_tile_windows (); -extern void info_next_window (), info_prev_window (); - -/* Selecting nodes. */ -extern void info_next_node (), info_prev_node (), info_up_node (); -extern void info_last_node (), info_first_node (), info_history_node (); -extern void info_goto_node (), info_top_node (), info_dir_node (); -extern void info_global_next_node (), info_global_prev_node (); -extern void info_kill_node (), info_view_file (); - -/* Selecting cross references. */ -extern void info_menu_digit (), info_menu_item (), info_xref_item (); -extern void info_find_menu (), info_select_reference_this_line (); - -/* Hacking numeric arguments. */ -extern int info_explicit_arg, info_numeric_arg, info_numeric_arg_sign; - -extern void info_add_digit_to_numeric_arg (), info_universal_argument (); -extern void info_initialize_numeric_arg (), info_numeric_arg_digit_loop (); - -/* Searching commands. */ -extern void info_search (), isearch_forward (), isearch_backward (); - -/* Dumping and printing nodes. */ -extern void info_print_node (); - -/* Miscellaneous commands. */ -extern void info_abort_key (), info_quit (), info_do_lowercase_version (); - -#endif /* _SESSION_H_ */ diff --git a/info/signals.c b/info/signals.c deleted file mode 100644 --- a/info/signals.c +++ /dev/null @@ -1,173 +0,0 @@ -/* signals.c -- Install and maintain Info signal handlers. */ - -/* This file is part of GNU Info, a program for reading online documentation - stored in Info format. - - Copyright (C) 1993, 1994, 1995 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 "signals.h" - -/* **************************************************************** */ -/* */ -/* Pretending That We Have POSIX Signals */ -/* */ -/* **************************************************************** */ - -#if !defined (HAVE_SIGPROCMASK) && defined (HAVE_SIGSETMASK) -/* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */ -static void -sigprocmask (operation, newset, oldset) - int operation, *newset, *oldset; -{ - switch (operation) - { - case SIG_UNBLOCK: - sigsetmask (sigblock (0) & ~(*newset)); - break; - - case SIG_BLOCK: - *oldset = sigblock (*newset); - break; - - case SIG_SETMASK: - sigsetmask (*newset); - break; - - default: - abort (); - } -} -#endif /* !HAVE_SIGPROCMASK && HAVE_SIGSETMASK */ - -/* **************************************************************** */ -/* */ -/* Signal Handling for Info */ -/* */ -/* **************************************************************** */ - -typedef void SigHandlerType; -typedef SigHandlerType SigHandler (); - -static SigHandlerType info_signal_handler (); -static SigHandler *old_TSTP, *old_TTOU, *old_TTIN; -static SigHandler *old_WINCH, *old_INT; - -void -initialize_info_signal_handler () -{ -#if defined (SIGTSTP) - old_TSTP = (SigHandler *) signal (SIGTSTP, info_signal_handler); - old_TTOU = (SigHandler *) signal (SIGTTOU, info_signal_handler); - old_TTIN = (SigHandler *) signal (SIGTTIN, info_signal_handler); -#endif /* SIGTSTP */ - -#if defined (SIGWINCH) - old_WINCH = (SigHandler *) signal (SIGWINCH, info_signal_handler); -#endif - -#if defined (SIGINT) - old_INT = (SigHandler *) signal (SIGINT, info_signal_handler); -#endif -} - -static void -redisplay_after_signal () -{ - terminal_clear_screen (); - display_clear_display (the_display); - window_mark_chain (windows, W_UpdateWindow); - display_update_display (windows); - display_cursor_at_point (active_window); - fflush (stdout); -} - -static SigHandlerType -info_signal_handler (sig) - int sig; -{ - SigHandler **old_signal_handler; - - switch (sig) - { -#if defined (SIGTSTP) - case SIGTSTP: - case SIGTTOU: - case SIGTTIN: -#endif -#if defined (SIGINT) - case SIGINT: -#endif - { -#if defined (SIGTSTP) - if (sig == SIGTSTP) - old_signal_handler = &old_TSTP; - if (sig == SIGTTOU) - old_signal_handler = &old_TTOU; - if (sig == SIGTTIN) - old_signal_handler = &old_TTIN; -#endif /* SIGTSTP */ - if (sig == SIGINT) - old_signal_handler = &old_INT; - - /* For stop signals, restore the terminal IO, leave the cursor - at the bottom of the window, and stop us. */ - terminal_goto_xy (0, screenheight - 1); - terminal_clear_to_eol (); - fflush (stdout); - terminal_unprep_terminal (); - signal (sig, *old_signal_handler); - UNBLOCK_SIGNAL (sig); - kill (getpid (), sig); - - /* The program is returning now. Restore our signal handler, - turn on terminal handling, redraw the screen, and place the - cursor where it belongs. */ - terminal_prep_terminal (); - *old_signal_handler = (SigHandler *) signal (sig, info_signal_handler); - redisplay_after_signal (); - fflush (stdout); - } - break; - -#if defined (SIGWINCH) - case SIGWINCH: - { - /* Turn off terminal IO, tell our parent that the window has changed, - then reinitialize the terminal and rebuild our windows. */ - old_signal_handler = &old_WINCH; - terminal_goto_xy (0, 0); - fflush (stdout); - terminal_unprep_terminal (); - signal (sig, *old_signal_handler); - UNBLOCK_SIGNAL (sig); - kill (getpid (), sig); - - /* After our old signal handler returns... */ - terminal_get_screen_size (); - terminal_prep_terminal (); - display_initialize_display (screenwidth, screenheight); - window_new_screen_size (screenwidth, screenheight, (VFunction *)NULL); - *old_signal_handler = (SigHandler *) signal (sig, info_signal_handler); - redisplay_after_signal (); - } - break; -#endif /* SIGWINCH */ - } -} diff --git a/info/signals.h b/info/signals.h deleted file mode 100644 --- a/info/signals.h +++ /dev/null @@ -1,89 +0,0 @@ -/* signals.h -- Header to include system dependent signal definitions. */ - -/* This file is part of GNU Info, a program for reading online documentation - stored in Info format. - - Copyright (C) 1993, 1994, 1995 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). */ - -#if !defined (_SIGNALS_H_) -#define _SIGNALS_H_ - -#include - -#if !defined (HAVE_SIGPROCMASK) && !defined (sigmask) -# define sigmask(x) (1 << ((x)-1)) -#endif /* !HAVE_SIGPROCMASK && !sigmask */ - -#if !defined (HAVE_SIGPROCMASK) -# if !defined (SIG_BLOCK) -# define SIG_UNBLOCK 1 -# define SIG_BLOCK 2 -# define SIG_SETMASK 3 -# endif /* SIG_BLOCK */ - -/* Type of a signal set. */ -# define sigset_t int - -/* Make SET have no signals in it. */ -# define sigemptyset(set) (*(set) = (sigset_t)0x0) - -/* Make SET have the full range of signal specifications possible. */ -# define sigfillset(set) (*(set) = (sigset_t)0xffffffffff) - -/* Add SIG to the contents of SET. */ -# define sigaddset(set, sig) *(set) |= sigmask (sig) - -/* Delete SIG from the contents of SET. */ -# define sigdelset(set, sig) *(set) &= ~(sigmask (sig)) - -/* Tell if SET contains SIG. */ -# define sigismember(set, sig) (*(set) & (sigmask (sig))) - -/* Suspend the process until the reception of one of the signals - not present in SET. */ -# define sigsuspend(set) sigpause (*(set)) -#endif /* !HAVE_SIGPROCMASK */ - -#if defined (HAVE_SIGPROCMASK) || defined (HAVE_SIGSETMASK) -/* These definitions are used both in POSIX and non-POSIX implementations. */ - -#define BLOCK_SIGNAL(sig) \ - do { \ - sigset_t nvar, ovar; \ - sigemptyset (&nvar); \ - sigemptyset (&ovar); \ - sigaddset (&nvar, sig); \ - sigprocmask (SIG_BLOCK, &nvar, &ovar); \ - } while (0) - -#define UNBLOCK_SIGNAL(sig) \ - do { \ - sigset_t nvar, ovar; \ - sigemptyset (&ovar); \ - sigemptyset (&nvar); \ - sigaddset (&nvar, sig); \ - sigprocmask (SIG_UNBLOCK, &nvar, &ovar); \ - } while (0) - -#else /* !HAVE_SIGPROCMASK && !HAVE_SIGSETMASK */ -# define BLOCK_SIGNAL(sig) -# define UNBLOCK_SIGNAL(sig) -#endif /* !HAVE_SIGPROCMASK && !HAVE_SIGSETMASK */ - -#endif /* !_SIGNALS_H_ */ diff --git a/info/strdup.c b/info/strdup.c deleted file mode 100644 --- a/info/strdup.c +++ /dev/null @@ -1,43 +0,0 @@ -/* strdup.c -- return a newly allocated copy of a string - Copyright (C) 1990 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef STDC_HEADERS -#include -#include -#else -char *malloc (); -char *strcpy (); -#endif - -/* Return a newly allocated copy of STR, - or 0 if out of memory. */ - -char * -strdup (str) - const char *str; -{ - char *newstr; - - newstr = (char *) malloc (strlen (str) + 1); - if (newstr) - strcpy (newstr, str); - return newstr; -} diff --git a/info/termdep.h b/info/termdep.h deleted file mode 100644 --- a/info/termdep.h +++ /dev/null @@ -1,76 +0,0 @@ -/* termdep.h -- System things that terminal.c depends on. - $Id: termdep.h,v 1.6 1996-12-03 17:49:39 jwe Exp $ - - This file is part of GNU Info, a program for reading online documentation - stored in Info format. - - Copyright (C) 1993, 96 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). */ - -#if !defined (_TERMDEP_H_) -# define _TERMDEP_H_ - -#if defined (HAVE_SYS_FCNTL_H) -# include -#else -# include -#endif /* !HAVE_SYS_FCNTL_H */ - -#if defined (HAVE_SYS_FILE_H) -# include -#endif /* HAVE_SYS_FILE_H */ - -#if defined (HAVE_STRINGS_H) -# include -#else -# if defined (HAVE_STRING_H) -# include -# endif -#endif - -#if defined (HAVE_TERMIOS_H) && ! defined (SCO) -# include -#else -# if defined (HAVE_TERMIO_H) -# include -# if defined (HAVE_SYS_PTEM_H) -# if defined (M_UNIX) || !defined (M_XENIX) -# include -# include -# undef TIOCGETC -# else /* M_XENIX */ -# define tchars tc -# endif /* M_XENIX */ -# endif /* HAVE_SYS_PTEM_H */ -# else /* !HAVE_TERMIO_H */ -# include -# endif /* !HAVE_TERMIO_H */ -#endif /* !HAVE_TERMIOS_H */ - -#if defined (HAVE_SYS_TTOLD_H) -# include -#endif /* HAVE_SYS_TTOLD_H */ - -#if !defined (HAVE_STRCHR) -# undef strchr -# undef strrchr -# define strchr index -# define strrchr rindex -#endif /* !HAVE_STRCHR */ - -#endif /* _TERMDEP_H_ */ diff --git a/info/terminal.c b/info/terminal.c deleted file mode 100644 --- a/info/terminal.c +++ /dev/null @@ -1,774 +0,0 @@ -/* terminal.c -- How to handle the physical terminal for Info. */ - -/* This file is part of GNU Info, a program for reading online documentation - stored in Info format. - - This file has appeared in prior works by the Free Software Foundation; - thus it carries copyright dates from 1988 through 1993. - - Copyright (C) 1988, 89, 90, 91, 92, 93, 96 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 -#include -#include "infomap.h" -#include "terminal.h" -#include "termdep.h" - -extern void *xmalloc (), *xrealloc (); - -/* The Unix termcap interface code. */ - -extern int tgetnum (), tgetflag (), tgetent (); -extern char *tgetstr (), *tgoto (); -extern char *getenv (); -extern void tputs (); - -/* Function "hooks". If you make one of these point to a function, that - function is called when appropriate instead of its namesake. Your - function is called with exactly the same arguments that were passed - to the namesake function. */ -VFunction *terminal_begin_inverse_hook = (VFunction *)NULL; -VFunction *terminal_end_inverse_hook = (VFunction *)NULL; -VFunction *terminal_prep_terminal_hook = (VFunction *)NULL; -VFunction *terminal_unprep_terminal_hook = (VFunction *)NULL; -VFunction *terminal_up_line_hook = (VFunction *)NULL; -VFunction *terminal_down_line_hook = (VFunction *)NULL; -VFunction *terminal_clear_screen_hook = (VFunction *)NULL; -VFunction *terminal_clear_to_eol_hook = (VFunction *)NULL; -VFunction *terminal_get_screen_size_hook = (VFunction *)NULL; -VFunction *terminal_goto_xy_hook = (VFunction *)NULL; -VFunction *terminal_initialize_terminal_hook = (VFunction *)NULL; -VFunction *terminal_new_terminal_hook = (VFunction *)NULL; -VFunction *terminal_put_text_hook = (VFunction *)NULL; -VFunction *terminal_ring_bell_hook = (VFunction *)NULL; -VFunction *terminal_write_chars_hook = (VFunction *)NULL; -VFunction *terminal_scroll_terminal_hook = (VFunction *)NULL; - -/* **************************************************************** */ -/* */ -/* Terminal and Termcap */ -/* */ -/* **************************************************************** */ - -/* On Solaris2, sys/types.h #includes sys/reg.h, which #defines PC. - Unfortunately, PC is a global variable used by the termcap library. */ -#undef PC - -/* TERMCAP requires these variables, whether we access them or not. */ -char PC; -char *BC, *UP; -short ospeed; - -/* A buffer which holds onto the current terminal description, and a pointer - used to float within it. */ -static char *term_buffer = (char *)NULL; -static char *term_string_buffer = (char *)NULL; - -/* Some strings to control terminal actions. These are output by tputs (). */ -static char *term_goto, *term_clreol, *term_cr, *term_clrpag; -static char *term_begin_use, *term_end_use; -static char *term_AL, *term_DL, *term_al, *term_dl; - -/* How to go up a line. */ -static char *term_up; - -/* How to go down a line. */ -static char *term_dn; - -/* An audible bell, if the terminal can be made to make noise. */ -static char *audible_bell; - -/* A visible bell, if the terminal can be made to flash the screen. */ -static char *visible_bell; - -/* The string to write to turn on the meta key, if this term has one. */ -static char *term_mm; - -/* The string to write to turn off the meta key, if this term has one. */ -static char *term_mo; - -/* The string to turn on inverse mode, if this term has one. */ -static char *term_invbeg; - -/* The string to turn off inverse mode, if this term has one. */ -static char *term_invend; - -static void -output_character_function (c) - int c; -{ - putc (c, stdout); -} - -/* Macro to send STRING to the terminal. */ -#define send_to_terminal(string) \ - do { \ - if (string) \ - tputs (string, 1, output_character_function); \ - } while (0) - -/* Tell the terminal that we will be doing cursor addressable motion. */ -static void -terminal_begin_using_terminal () -{ - send_to_terminal (term_begin_use); -} - -/* Tell the terminal that we will not be doing any more cursor addressable - motion. */ -static void -terminal_end_using_terminal () -{ - send_to_terminal (term_end_use); -} - -/* **************************************************************** */ -/* */ -/* Necessary Terminal Functions */ -/* */ -/* **************************************************************** */ - -/* The functions and variables on this page implement the user visible - portion of the terminal interface. */ - -/* The width and height of the terminal. */ -int screenwidth, screenheight; - -/* Non-zero means this terminal can't really do anything. */ -int terminal_is_dumb_p = 0; - -/* Non-zero means that this terminal has a meta key. */ -int terminal_has_meta_p = 0; - -/* Non-zero means that this terminal can produce a visible bell. */ -int terminal_has_visible_bell_p = 0; - -/* Non-zero means to use that visible bell if at all possible. */ -int terminal_use_visible_bell_p = 0; - -/* Non-zero means that the terminal can do scrolling. */ -int terminal_can_scroll = 0; - -/* The key sequences output by the arrow keys, if this terminal has any. */ -char *term_ku = (char *)NULL; -char *term_kd = (char *)NULL; -char *term_kr = (char *)NULL; -char *term_kl = (char *)NULL; - -/* Move the cursor to the terminal location of X and Y. */ -void -terminal_goto_xy (x, y) - int x, y; -{ - if (terminal_goto_xy_hook) - (*terminal_goto_xy_hook) (x, y); - else - { - if (term_goto) - tputs (tgoto (term_goto, x, y), 1, output_character_function); - } -} - -/* Print STRING to the terminal at the current position. */ -void -terminal_put_text (string) - char *string; -{ - if (terminal_put_text_hook) - (*terminal_put_text_hook) (string); - else - { - printf ("%s", string); - } -} - -/* Print NCHARS from STRING to the terminal at the current position. */ -void -terminal_write_chars (string, nchars) - char *string; - int nchars; -{ - if (terminal_write_chars_hook) - (*terminal_write_chars_hook) (string, nchars); - else - { - if (nchars) - fwrite (string, 1, nchars, stdout); - } -} - -/* Clear from the current position of the cursor to the end of the line. */ -void -terminal_clear_to_eol () -{ - if (terminal_clear_to_eol_hook) - (*terminal_clear_to_eol_hook) (); - else - { - send_to_terminal (term_clreol); - } -} - -/* Clear the entire terminal screen. */ -void -terminal_clear_screen () -{ - if (terminal_clear_screen_hook) - (*terminal_clear_screen_hook) (); - else - { - send_to_terminal (term_clrpag); - } -} - -/* Move the cursor up one line. */ -void -terminal_up_line () -{ - if (terminal_up_line_hook) - (*terminal_up_line_hook) (); - else - { - send_to_terminal (term_up); - } -} - -/* Move the cursor down one line. */ -void -terminal_down_line () -{ - if (terminal_down_line_hook) - (*terminal_down_line_hook) (); - else - { - send_to_terminal (term_dn); - } -} - -/* Turn on reverse video if possible. */ -void -terminal_begin_inverse () -{ - if (terminal_begin_inverse_hook) - (*terminal_begin_inverse_hook) (); - else - { - send_to_terminal (term_invbeg); - } -} - -/* Turn off reverse video if possible. */ -void -terminal_end_inverse () -{ - if (terminal_end_inverse_hook) - (*terminal_end_inverse_hook) (); - else - { - send_to_terminal (term_invend); - } -} - -/* Ring the terminal bell. The bell is run visibly if it both has one and - terminal_use_visible_bell_p is non-zero. */ -void -terminal_ring_bell () -{ - if (terminal_ring_bell_hook) - (*terminal_ring_bell_hook) (); - else - { - if (terminal_has_visible_bell_p && terminal_use_visible_bell_p) - send_to_terminal (visible_bell); - else - send_to_terminal (audible_bell); - } -} - -/* At the line START, delete COUNT lines from the terminal display. */ -static void -terminal_delete_lines (start, count) - int start, count; -{ - int lines; - - /* Normalize arguments. */ - if (start < 0) - start = 0; - - lines = screenheight - start; - terminal_goto_xy (0, start); - if (term_DL) - tputs (tgoto (term_DL, 0, count), lines, output_character_function); - else - { - while (count--) - tputs (term_dl, lines, output_character_function); - } - - fflush (stdout); -} - -/* At the line START, insert COUNT lines in the terminal display. */ -static void -terminal_insert_lines (start, count) - int start, count; -{ - int lines; - - /* Normalize arguments. */ - if (start < 0) - start = 0; - - lines = screenheight - start; - terminal_goto_xy (0, start); - - if (term_AL) - tputs (tgoto (term_AL, 0, count), lines, output_character_function); - else - { - while (count--) - tputs (term_al, lines, output_character_function); - } - - fflush (stdout); -} - -/* Scroll an area of the terminal, starting with the region from START - to END, AMOUNT lines. If AMOUNT is negative, the lines are scrolled - towards the top of the screen, else they are scrolled towards the - bottom of the screen. */ -void -terminal_scroll_terminal (start, end, amount) - int start, end, amount; -{ - if (!terminal_can_scroll) - return; - - /* Any scrolling at all? */ - if (amount == 0) - return; - - if (terminal_scroll_terminal_hook) - (*terminal_scroll_terminal_hook) (start, end, amount); - else - { - /* If we are scrolling down, delete AMOUNT lines at END. Then insert - AMOUNT lines at START. */ - if (amount > 0) - { - terminal_delete_lines (end, amount); - terminal_insert_lines (start, amount); - } - - /* If we are scrolling up, delete AMOUNT lines before START. This - actually does the upwards scroll. Then, insert AMOUNT lines - after the already scrolled region (i.e., END - AMOUNT). */ - if (amount < 0) - { - int abs_amount = -amount; - terminal_delete_lines (start - abs_amount, abs_amount); - terminal_insert_lines (end - abs_amount, abs_amount); - } - } -} - -/* Re-initialize the terminal considering that the TERM/TERMCAP variable - has changed. */ -void -terminal_new_terminal (terminal_name) - char *terminal_name; -{ - if (terminal_new_terminal_hook) - (*terminal_new_terminal_hook) (terminal_name); - else - { - terminal_initialize_terminal (terminal_name); - } -} - -/* Set the global variables SCREENWIDTH and SCREENHEIGHT. */ -void -terminal_get_screen_size () -{ - if (terminal_get_screen_size_hook) - (*terminal_get_screen_size_hook) (); - else - { - screenwidth = screenheight = 0; - -#if defined (TIOCGWINSZ) - { - struct winsize window_size; - - if (ioctl (fileno (stdout), TIOCGWINSZ, &window_size) == 0) - { - screenwidth = (int) window_size.ws_col; - screenheight = (int) window_size.ws_row; - } - } -#endif /* TIOCGWINSZ */ - - /* Environment variable COLUMNS overrides setting of "co". */ - if (screenwidth <= 0) - { - char *sw = getenv ("COLUMNS"); - - if (sw) - screenwidth = atoi (sw); - - if (screenwidth <= 0) - screenwidth = tgetnum ("co"); - } - - /* Environment variable LINES overrides setting of "li". */ - if (screenheight <= 0) - { - char *sh = getenv ("LINES"); - - if (sh) - screenheight = atoi (sh); - - if (screenheight <= 0) - screenheight = tgetnum ("li"); - } - - /* If all else fails, default to 80x24 terminal. */ - if (screenwidth <= 0) - screenwidth = 80; - - if (screenheight <= 0) - screenheight = 24; - } -} - -/* Initialize the terminal which is known as TERMINAL_NAME. If this terminal - doesn't have cursor addressability, TERMINAL_IS_DUMB_P becomes non-zero. - The variables SCREENHEIGHT and SCREENWIDTH are set to the dimensions that - this terminal actually has. The variable TERMINAL_HAS_META_P becomes non- - zero if this terminal supports a Meta key. Finally, the terminal screen is - cleared. */ -void -terminal_initialize_terminal (terminal_name) - char *terminal_name; -{ - char *term, *buffer; - - terminal_is_dumb_p = 0; - - if (terminal_initialize_terminal_hook) - { - (*terminal_initialize_terminal_hook) (terminal_name); - return; - } - - term = terminal_name ? terminal_name : getenv ("TERM"); - - if (!term_string_buffer) - term_string_buffer = (char *)xmalloc (2048); - - if (!term_buffer) - term_buffer = (char *)xmalloc (2048); - - buffer = term_string_buffer; - - term_clrpag = term_cr = term_clreol = (char *)NULL; - - if (!term) - term = "dumb"; - - if (tgetent (term_buffer, term) <= 0) - { - terminal_is_dumb_p = 1; - screenwidth = 80; - screenheight = 24; - term_cr = "\r"; - term_up = term_dn = audible_bell = visible_bell = (char *)NULL; - term_ku = term_kd = term_kl = term_kr = (char *)NULL; - return; - } - - BC = tgetstr ("pc", &buffer); - PC = BC ? *BC : 0; - -#if defined (TIOCGETP) - { - struct sgttyb sg; - - if (ioctl (fileno (stdout), TIOCGETP, &sg) != -1) - ospeed = sg.sg_ospeed; - else - ospeed = B9600; - } -#else - ospeed = B9600; -#endif /* !TIOCGETP */ - - term_cr = tgetstr ("cr", &buffer); - term_clreol = tgetstr ("ce", &buffer); - term_clrpag = tgetstr ("cl", &buffer); - term_goto = tgetstr ("cm", &buffer); - - /* Find out about this terminals scrolling capability. */ - term_AL = tgetstr ("AL", &buffer); - term_DL = tgetstr ("DL", &buffer); - term_al = tgetstr ("al", &buffer); - term_dl = tgetstr ("dl", &buffer); - - terminal_can_scroll = ((term_AL || term_al) && (term_DL || term_dl)); - - term_invbeg = tgetstr ("mr", &buffer); - if (term_invbeg) - term_invend = tgetstr ("me", &buffer); - else - term_invend = (char *)NULL; - - if (!term_cr) - term_cr = "\r"; - - terminal_get_screen_size (); - - term_up = tgetstr ("up", &buffer); - term_dn = tgetstr ("dn", &buffer); - visible_bell = tgetstr ("vb", &buffer); - terminal_has_visible_bell_p = (visible_bell != (char *)NULL); - audible_bell = tgetstr ("bl", &buffer); - if (!audible_bell) - audible_bell = "\007"; - term_begin_use = tgetstr ("ti", &buffer); - term_end_use = tgetstr ("te", &buffer); - - /* Check to see if this terminal has a meta key. */ - terminal_has_meta_p = (tgetflag ("km") || tgetflag ("MT")); - if (terminal_has_meta_p) - { - term_mm = tgetstr ("mm", &buffer); - term_mo = tgetstr ("mo", &buffer); - } - else - { - term_mm = (char *)NULL; - term_mo = (char *)NULL; - } - - /* Attempt to find the arrow keys. */ - term_ku = tgetstr ("ku", &buffer); - term_kd = tgetstr ("kd", &buffer); - term_kr = tgetstr ("kr", &buffer); - term_kl = tgetstr ("kl", &buffer); - - /* If this terminal is not cursor addressable, then it is really dumb. */ - if (!term_goto) - terminal_is_dumb_p = 1; - - terminal_begin_using_terminal (); -} - -/* **************************************************************** */ -/* */ -/* How to Read Characters From the Terminal */ -/* */ -/* **************************************************************** */ - -#if defined (TIOCGETC) -/* A buffer containing the terminal interrupt characters upon entry - to Info. */ -struct tchars original_tchars; -#endif - -#if defined (TIOCGLTC) -/* A buffer containing the local terminal mode characters upon entry - to Info. */ -struct ltchars original_ltchars; -#endif - -#if defined (HAVE_TERMIOS_H) -struct termios original_termios, ttybuff; -#else -# if defined (HAVE_TERMIO_H) -/* A buffer containing the terminal mode flags upon entry to info. */ -struct termio original_termio, ttybuff; -# else /* !HAVE_TERMIO_H */ -/* Buffers containing the terminal mode flags upon entry to info. */ -int original_tty_flags = 0; -int original_lmode; -struct sgttyb ttybuff; -# endif /* !HAVE_TERMIO_H */ -#endif /* !HAVE_TERMIOS_H */ - -/* Prepare to start using the terminal to read characters singly. */ -void -terminal_prep_terminal () -{ - int tty; - - if (terminal_prep_terminal_hook) - { - (*terminal_prep_terminal_hook) (); - return; - } - - tty = fileno (stdin); - -#if defined (HAVE_TERMIOS_H) - tcgetattr (tty, &original_termios); - tcgetattr (tty, &ttybuff); -#else -# if defined (HAVE_TERMIO_H) - ioctl (tty, TCGETA, &original_termio); - ioctl (tty, TCGETA, &ttybuff); -# endif -#endif - -#if defined (HAVE_TERMIOS_H) || defined (HAVE_TERMIO_H) - ttybuff.c_iflag &= (~ISTRIP & ~INLCR & ~IGNCR & ~ICRNL & ~IXON); -#ifdef OCRNL - ttybuff.c_oflag &= ~OCRNL; -#endif - ttybuff.c_oflag &= ~ONLCR; - - ttybuff.c_lflag &= (~ICANON & ~ECHO); - - ttybuff.c_cc[VMIN] = 1; - ttybuff.c_cc[VTIME] = 0; - - if (ttybuff.c_cc[VINTR] == DEL || ttybuff.c_cc[VINTR] == Control ('c')) - ttybuff.c_cc[VINTR] = -1; - - if (ttybuff.c_cc[VQUIT] == DEL || ttybuff.c_cc[VQUIT] == Control ('c')) - ttybuff.c_cc[VQUIT] = -1; -#endif - -#if defined (HAVE_TERMIOS_H) - tcsetattr (tty, TCSANOW, &ttybuff); -#else -# if defined (HAVE_TERMIO_H) - ioctl (tty, TCSETA, &ttybuff); -# endif -#endif - -#if !defined (HAVE_TERMIOS_H) && !defined (HAVE_TERMIO_H) - ioctl (tty, TIOCGETP, &ttybuff); - - if (!original_tty_flags) - original_tty_flags = ttybuff.sg_flags; - - /* Make this terminal pass 8 bits around while we are using it. */ -# if defined (PASS8) - ttybuff.sg_flags |= PASS8; -# endif /* PASS8 */ - -# if defined (TIOCLGET) && defined (LPASS8) - { - int flags; - ioctl (tty, TIOCLGET, &flags); - original_lmode = flags; - flags |= LPASS8; - ioctl (tty, TIOCLSET, &flags); - } -# endif /* TIOCLGET && LPASS8 */ - -# if defined (TIOCGETC) - { - struct tchars temp; - - ioctl (tty, TIOCGETC, &original_tchars); - temp = original_tchars; - - /* C-s and C-q. */ - temp.t_startc = temp.t_stopc = -1; - - /* Often set to C-d. */ - temp.t_eofc = -1; - - /* If the a quit or interrupt character conflicts with one of our - commands, then make it go away. */ - if (temp.t_intrc == DEL || temp.t_intrc == Control ('c')) - temp.t_intrc = -1; - - if (temp.t_quitc == DEL || temp.t_quitc == Control ('c')) - temp.t_quitc = -1; - - ioctl (tty, TIOCSETC, &temp); - } -# endif /* TIOCGETC */ - -# if defined (TIOCGLTC) - { - struct ltchars temp; - - ioctl (tty, TIOCGLTC, &original_ltchars); - temp = original_ltchars; - - /* Make the interrupt keys go away. Just enough to make people happy. */ - temp.t_lnextc = -1; /* C-v. */ - temp.t_dsuspc = -1; /* C-y. */ - temp.t_flushc = -1; /* C-o. */ - ioctl (tty, TIOCSLTC, &temp); - } -# endif /* TIOCGLTC */ - - ttybuff.sg_flags &= ~ECHO; - ttybuff.sg_flags |= CBREAK; - ioctl (tty, TIOCSETN, &ttybuff); -#endif /* !HAVE_TERMIOS_H && !HAVE_TERMIO_H */ -} - -/* Restore the tty settings back to what they were before we started using - this terminal. */ -void -terminal_unprep_terminal () -{ - int tty; - - if (terminal_unprep_terminal_hook) - { - (*terminal_unprep_terminal_hook) (); - return; - } - - tty = fileno (stdin); - -#if defined (HAVE_TERMIOS_H) - tcsetattr (tty, TCSANOW, &original_termios); -#else -# if defined (HAVE_TERMIO_H) - ioctl (tty, TCSETA, &original_termio); -# else /* !HAVE_TERMIO_H */ - ioctl (tty, TIOCGETP, &ttybuff); - ttybuff.sg_flags = original_tty_flags; - ioctl (tty, TIOCSETN, &ttybuff); - -# if defined (TIOCGETC) - ioctl (tty, TIOCSETC, &original_tchars); -# endif /* TIOCGETC */ - -# if defined (TIOCGLTC) - ioctl (tty, TIOCSLTC, &original_ltchars); -# endif /* TIOCGLTC */ - -# if defined (TIOCLGET) && defined (LPASS8) - ioctl (tty, TIOCLSET, &original_lmode); -# endif /* TIOCLGET && LPASS8 */ - -# endif /* !HAVE_TERMIO_H */ -#endif /* !HAVE_TERMIOS_H */ - terminal_end_using_terminal (); -} - diff --git a/info/terminal.h b/info/terminal.h deleted file mode 100644 --- a/info/terminal.h +++ /dev/null @@ -1,129 +0,0 @@ -/* terminal.h -- The external interface to terminal I/O. */ - -/* This file is part of GNU Info, a program for reading online documentation - stored in Info format. - - Copyright (C) 1993, 96 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). */ - -#if !defined (_TERMINAL_H_) -#define _TERMINAL_H_ - -/* We use the following data type to talk about pointers to functions. */ -#if !defined (__FUNCTION_DEF) -# define __FUNCTION_DEF -typedef int Function (); -typedef void VFunction (); -#endif /* _FUNCTION_DEF */ - -/* For almost every function externally visible from terminal.c, there is - a corresponding "hook" function which can be bound in order to replace - the functionality of the one found in terminal.c. This is how we go - about implemented X window display. */ - -/* The width and height of the terminal. */ -extern int screenwidth, screenheight; - -/* Non-zero means this terminal can't really do anything. */ -extern int terminal_is_dumb_p; - -/* Non-zero means that this terminal has a meta key. */ -extern int terminal_has_meta_p; - -/* Non-zero means that this terminal can produce a visible bell. */ -extern int terminal_has_visible_bell_p; - -/* Non-zero means to use that visible bell if at all possible. */ -extern int terminal_use_visible_bell_p; - -/* Non-zero means that this terminal can scroll lines up and down. */ -extern int terminal_can_scroll; - -/* Initialize the terminal which is known as TERMINAL_NAME. If this terminal - doesn't have cursor addressability, TERMINAL_IS_DUMB_P becomes non-zero. - The variables SCREENHEIGHT and SCREENWIDTH are set to the dimensions that - this terminal actually has. The variable TERMINAL_HAS_META_P becomes non- - zero if this terminal supports a Meta key. */ -extern void terminal_initialize_terminal (); -extern VFunction *terminal_initialize_terminal_hook; - -/* Return the current screen width and height in the variables - SCREENWIDTH and SCREENHEIGHT. */ -extern void terminal_get_screen_size (); -extern VFunction *terminal_get_screen_size_hook; - -/* Save and restore tty settings. */ -extern void terminal_prep_terminal (), terminal_unprep_terminal (); -extern VFunction *terminal_prep_terminal_hook, *terminal_unprep_terminal_hook; - -/* Re-initialize the terminal to TERMINAL_NAME. */ -extern void terminal_new_terminal (); -extern VFunction *terminal_new_terminal_hook; - -/* Move the cursor to the terminal location of X and Y. */ -extern void terminal_goto_xy (); -extern VFunction *terminal_goto_xy_hook; - -/* Print STRING to the terminal at the current position. */ -extern void terminal_put_text (); -extern VFunction *terminal_put_text_hook; - -/* Print NCHARS from STRING to the terminal at the current position. */ -extern void terminal_write_chars (); -extern VFunction *terminal_write_chars_hook; - -/* Clear from the current position of the cursor to the end of the line. */ -extern void terminal_clear_to_eol (); -extern VFunction *terminal_clear_to_eol_hook; - -/* Clear the entire terminal screen. */ -extern void terminal_clear_screen (); -extern VFunction *terminal_clear_screen_hook; - -/* Move the cursor up one line. */ -extern void terminal_up_line (); -extern VFunction *terminal_up_line_hook; - -/* Move the cursor down one line. */ -extern void terminal_down_line (); -extern VFunction *terminal_down_line_hook; - -/* Turn on reverse video if possible. */ -extern void terminal_begin_inverse (); -extern VFunction *terminal_begin_inverse_hook; - -/* Turn off reverse video if possible. */ -extern void terminal_end_inverse (); -extern VFunction *terminal_end_inverse_hook; - -/* Scroll an area of the terminal, starting with the region from START - to END, AMOUNT lines. If AMOUNT is negative, the lines are scrolled - towards the top of the screen, else they are scrolled towards the - bottom of the screen. */ -extern void terminal_scroll_terminal (); -extern VFunction *terminal_scroll_terminal_hook; - -/* Ring the terminal bell. The bell is run visibly if it both has one and - terminal_use_visible_bell_p is non-zero. */ -extern void terminal_ring_bell (); -extern VFunction *terminal_ring_bell_hook; - -/* The key sequences output by the arrow keys, if this terminal has any. */ -extern char *term_ku, *term_kd, *term_kr, *term_kl; - -#endif /* !_TERMINAL_H_ */ diff --git a/info/texinfo.tex b/info/texinfo.tex deleted file mode 100644 --- a/info/texinfo.tex +++ /dev/null @@ -1,4692 +0,0 @@ -%% TeX macros to handle texinfo files - -% Copyright (C) 1985, 86, 88, 90, 91, 92, 93, -% 94, 95, 1996 Free Software Foundation, Inc. - -%This texinfo.tex file 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 texinfo.tex file 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 texinfo.tex file; see the file COPYING. If not, write -%to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -%Boston, MA 02111-1307, USA. - - -%In other words, you are welcome to use, share and improve this program. -%You are forbidden to forbid anyone else to use, share and improve -%what you give them. Help stamp out software-hoarding! - - -% Send bug reports to bug-texinfo@prep.ai.mit.edu. -% Please include a *precise* test case in each bug report. - - -% Make it possible to create a .fmt file just by loading this file: -% if the underlying format is not loaded, start by loading it now. -% Added by gildea November 1993. -\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi - -% This automatically updates the version number based on RCS. -\def\deftexinfoversion$#1: #2 ${\def\texinfoversion{#2}} -\deftexinfoversion$Revision: 1.1 $ -\message{Loading texinfo package [Version \texinfoversion]:} - -% If in a .fmt file, print the version number -% and turn on active characters that we couldn't do earlier because -% they might have appeared in the input file name. -\everyjob{\message{[Texinfo version \texinfoversion]}\message{} - \catcode`+=\active \catcode`\_=\active} - -% Save some parts of plain tex whose names we will redefine. - -\let\ptexb=\b -\let\ptexbullet=\bullet -\let\ptexc=\c -\let\ptexcomma=\, -\let\ptexdot=\. -\let\ptexdots=\dots -\let\ptexend=\end -\let\ptexequiv = \equiv -\let\ptexi=\i -\let\ptexlbrace=\{ -\let\ptexrbrace=\} -\let\ptexstar=\* -\let\ptext=\t -\let\ptextilde=\~ - -% Be sure we're in horizontal mode when doing a tie, since we make space -% equivalent to this in @example-like environments. Otherwise, a space -% at the beginning of a line will start with \penalty -- and -% since \penalty is valid in vertical mode, we'd end up putting the -% penalty on the vertical list instead of in the new paragraph. -{\catcode`@ = 11 - % Avoid using \@M directly, because that causes trouble - % if the definition is written into an index file. - \global\let\tiepenalty = \@M - \gdef\tie{\leavevmode\penalty\tiepenalty\ } -} -\let\~ = \tie % And make it available as @~. - - -\message{Basics,} -\chardef\other=12 - -% If this character appears in an error message or help string, it -% starts a new line in the output. -\newlinechar = `^^J - -% Set up fixed words for English. -\ifx\putwordChapter\undefined{\gdef\putwordChapter{Chapter}}\fi% -\def\putwordInfo{Info}% -\ifx\putwordSee\undefined{\gdef\putwordSee{See}}\fi% -\ifx\putwordsee\undefined{\gdef\putwordsee{see}}\fi% -\ifx\putwordfile\undefined{\gdef\putwordfile{file}}\fi% -\ifx\putwordpage\undefined{\gdef\putwordpage{page}}\fi% -\ifx\putwordsection\undefined{\gdef\putwordsection{section}}\fi% -\ifx\putwordSection\undefined{\gdef\putwordSection{Section}}\fi% -\ifx\putwordTableofContents\undefined{\gdef\putwordTableofContents{Table of Contents}}\fi% -\ifx\putwordShortContents\undefined{\gdef\putwordShortContents{Short Contents}}\fi% -\ifx\putwordAppendix\undefined{\gdef\putwordAppendix{Appendix}}\fi% - -% Ignore a token. -% -\def\gobble#1{} - -\hyphenation{ap-pen-dix} -\hyphenation{mini-buf-fer mini-buf-fers} -\hyphenation{eshell} - -% Margin to add to right of even pages, to left of odd pages. -\newdimen \bindingoffset -\newdimen \normaloffset -\newdimen\pagewidth \newdimen\pageheight - -% Sometimes it is convenient to have everything in the transcript file -% and nothing on the terminal. We don't just call \tracingall here, -% since that produces some useless output on the terminal. -% -\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}% -\def\loggingall{\tracingcommands2 \tracingstats2 - \tracingpages1 \tracingoutput1 \tracinglostchars1 - \tracingmacros2 \tracingparagraphs1 \tracingrestores1 - \showboxbreadth\maxdimen\showboxdepth\maxdimen -}% - -%---------------------Begin change----------------------- -% -%%%% For @cropmarks command. -% Dimensions to add cropmarks at corners Added by P. A. MacKay, 12 Nov. 1986 -% -\newdimen\cornerlong \newdimen\cornerthick -\newdimen \topandbottommargin -\newdimen \outerhsize \newdimen \outervsize -\cornerlong=1pc\cornerthick=.3pt % These set size of cropmarks -\outerhsize=7in -%\outervsize=9.5in -% Alternative @smallbook page size is 9.25in -\outervsize=9.25in -\topandbottommargin=.75in -% -%---------------------End change----------------------- - -% \onepageout takes a vbox as an argument. Note that \pagecontents -% does insertions, but you have to call it yourself. -\chardef\PAGE=255 \output={\onepageout{\pagecontents\PAGE}} -\def\onepageout#1{% - \hoffset=\normaloffset - \ifodd\pageno \advance\hoffset by \bindingoffset - \else \advance\hoffset by -\bindingoffset\fi - {% - \escapechar = `\\ % use backslash in output files. - \indexdummies - \shipout\vbox{% - {\let\hsize=\pagewidth \makeheadline}% - \pagebody{#1}% - {\let\hsize=\pagewidth \makefootline}% - }% - }% - \advancepageno - \ifnum\outputpenalty>-20000 \else\dosupereject\fi -} - -%%%% For @cropmarks command %%%% - -% Here is a modification of the main output routine for Near East Publications -% This provides right-angle cropmarks at all four corners. -% The contents of the page are centerlined into the cropmarks, -% and any desired binding offset is added as an \hskip on either -% site of the centerlined box. (P. A. MacKay, 12 November, 1986) -% -\def\croppageout#1{\hoffset=0pt % make sure this doesn't mess things up -{\escapechar=`\\\relax % makes sure backslash is used in output files. - \shipout - \vbox to \outervsize{\hsize=\outerhsize - \vbox{\line{\ewtop\hfill\ewtop}} - \nointerlineskip - \line{\vbox{\moveleft\cornerthick\nstop} - \hfill - \vbox{\moveright\cornerthick\nstop}} - \vskip \topandbottommargin - \centerline{\ifodd\pageno\hskip\bindingoffset\fi - \vbox{ - {\let\hsize=\pagewidth \makeheadline} - \pagebody{#1} - {\let\hsize=\pagewidth \makefootline}} - \ifodd\pageno\else\hskip\bindingoffset\fi} - \vskip \topandbottommargin plus1fill minus1fill - \boxmaxdepth\cornerthick - \line{\vbox{\moveleft\cornerthick\nsbot} - \hfill - \vbox{\moveright\cornerthick\nsbot}} - \nointerlineskip - \vbox{\line{\ewbot\hfill\ewbot}} - }} - \advancepageno - \ifnum\outputpenalty>-20000 \else\dosupereject\fi} -% -% Do @cropmarks to get crop marks -\def\cropmarks{\let\onepageout=\croppageout } - -\newinsert\margin \dimen\margin=\maxdimen - -\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}} -{\catcode`\@ =11 -\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi -% marginal hacks, juha@viisa.uucp (Juha Takala) -\ifvoid\margin\else % marginal info is present - \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi -\dimen@=\dp#1 \unvbox#1 -\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi -\ifr@ggedbottom \kern-\dimen@ \vfil \fi} -} - -% -% Here are the rules for the cropmarks. Note that they are -% offset so that the space between them is truly \outerhsize or \outervsize -% (P. A. MacKay, 12 November, 1986) -% -\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong} -\def\nstop{\vbox - {\hrule height\cornerthick depth\cornerlong width\cornerthick}} -\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong} -\def\nsbot{\vbox - {\hrule height\cornerlong depth\cornerthick width\cornerthick}} - -% Parse an argument, then pass it to #1. The argument is the rest of -% the input line (except we remove a trailing comment). #1 should be a -% macro which expects an ordinary undelimited TeX argument. -% -\def\parsearg#1{% - \let\next = #1% - \begingroup - \obeylines - \futurelet\temp\parseargx -} - -% If the next token is an obeyed space (from an @example environment or -% the like), remove it and recurse. Otherwise, we're done. -\def\parseargx{% - % \obeyedspace is defined far below, after the definition of \sepspaces. - \ifx\obeyedspace\temp - \expandafter\parseargdiscardspace - \else - \expandafter\parseargline - \fi -} - -% Remove a single space (as the delimiter token to the macro call). -{\obeyspaces % - \gdef\parseargdiscardspace {\futurelet\temp\parseargx}} - -{\obeylines % - \gdef\parseargline#1^^M{% - \endgroup % End of the group started in \parsearg. - % - % First remove any @c comment, then any @comment. - % Result of each macro is put in \toks0. - \argremovec #1\c\relax % - \expandafter\argremovecomment \the\toks0 \comment\relax % - % - % Call the caller's macro, saved as \next in \parsearg. - \expandafter\next\expandafter{\the\toks0}% - }% -} - -% Since all \c{,omment} does is throw away the argument, we can let TeX -% do that for us. The \relax here is matched by the \relax in the call -% in \parseargline; it could be more or less anything, its purpose is -% just to delimit the argument to the \c. -\def\argremovec#1\c#2\relax{\toks0 = {#1}} -\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}} - -% \argremovec{,omment} might leave us with trailing spaces, though; e.g., -% @end itemize @c foo -% will have two active spaces as part of the argument with the -% `itemize'. Here we remove all active spaces from #1, and assign the -% result to \toks0. -% -% This loses if there are any *other* active characters besides spaces -% in the argument -- _ ^ +, for example -- since they get expanded. -% Fortunately, Texinfo does not define any such commands. (If it ever -% does, the catcode of the characters in questionwill have to be changed -% here.) But this means we cannot call \removeactivespaces as part of -% \argremovec{,omment}, since @c uses \parsearg, and thus the argument -% that \parsearg gets might well have any character at all in it. -% -\def\removeactivespaces#1{% - \begingroup - \ignoreactivespaces - \edef\temp{#1}% - \global\toks0 = \expandafter{\temp}% - \endgroup -} - -% Change the active space to expand to nothing. -% -\begingroup - \obeyspaces - \gdef\ignoreactivespaces{\obeyspaces\let =\empty} -\endgroup - - -\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} - -%% These are used to keep @begin/@end levels from running away -%% Call \inENV within environments (after a \begingroup) -\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi} -\def\ENVcheck{% -\ifENV\errmessage{Still within an environment. Type Return to continue.} -\endgroup\fi} % This is not perfect, but it should reduce lossage - -% @begin foo is the same as @foo, for now. -\newhelp\EMsimple{Type to continue.} - -\outer\def\begin{\parsearg\beginxxx} - -\def\beginxxx #1{% -\expandafter\ifx\csname #1\endcsname\relax -{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else -\csname #1\endcsname\fi} - -% @end foo executes the definition of \Efoo. -% -\def\end{\parsearg\endxxx} -\def\endxxx #1{% - \removeactivespaces{#1}% - \edef\endthing{\the\toks0}% - % - \expandafter\ifx\csname E\endthing\endcsname\relax - \expandafter\ifx\csname \endthing\endcsname\relax - % There's no \foo, i.e., no ``environment'' foo. - \errhelp = \EMsimple - \errmessage{Undefined command `@end \endthing'}% - \else - \unmatchedenderror\endthing - \fi - \else - % Everything's ok; the right environment has been started. - \csname E\endthing\endcsname - \fi -} - -% There is an environment #1, but it hasn't been started. Give an error. -% -\def\unmatchedenderror#1{% - \errhelp = \EMsimple - \errmessage{This `@end #1' doesn't have a matching `@#1'}% -} - -% Define the control sequence \E#1 to give an unmatched @end error. -% -\def\defineunmatchedend#1{% - \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}% -} - - -% Single-spacing is done by various environments (specifically, in -% \nonfillstart and \quotations). -\newskip\singlespaceskip \singlespaceskip = 12.5pt -\def\singlespace{% - % Why was this kern here? It messes up equalizing space above and below - % environments. --karl, 6may93 - %{\advance \baselineskip by -\singlespaceskip - %\kern \baselineskip}% - \setleading \singlespaceskip -} - -%% Simple single-character @ commands - -% @@ prints an @ -% Kludge this until the fonts are right (grr). -\def\@{{\tt \char '100}} - -% This is turned off because it was never documented -% and you can use @w{...} around a quote to suppress ligatures. -%% Define @` and @' to be the same as ` and ' -%% but suppressing ligatures. -%\def\`{{`}} -%\def\'{{'}} - -% Used to generate quoted braces. -\def\mylbrace {{\tt \char '173}} -\def\myrbrace {{\tt \char '175}} -\let\{=\mylbrace -\let\}=\myrbrace -\begingroup - % Definitions to produce actual \{ & \} command in an index. - \catcode`\{ = 12 \catcode`\} = 12 - \catcode`\[ = 1 \catcode`\] = 2 - \catcode`\@ = 0 \catcode`\\ = 12 - @gdef@lbracecmd[\{]% - @gdef@rbracecmd[\}]% -@endgroup - -% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent -% Others are defined by plain TeX: @` @' @" @^ @~ @= @v @H. -\let\, = \c -\let\dotaccent = \. -\def\ringaccent#1{{\accent23 #1}} -\let\tieaccent = \t -\let\ubaraccent = \b -\let\udotaccent = \d - -% Other special characters: @questiondown @exclamdown -% Plain TeX defines: @AA @AE @O @OE @L (and lowercase versions) @ss. -\def\questiondown{?`} -\def\exclamdown{!`} - -% Dotless i and dotless j, used for accents. -\def\imacro{i} -\def\jmacro{j} -\def\dotless#1{% - \def\temp{#1}% - \ifx\temp\imacro \ptexi - \else\ifx\temp\jmacro \j - \else \errmessage{@dotless can be used only with i or j}% - \fi\fi -} - -% @: forces normal size whitespace following. -\def\:{\spacefactor=1000 } - -% @* forces a line break. -\def\*{\hfil\break\hbox{}\ignorespaces} - -% @. is an end-of-sentence period. -\def\.{.\spacefactor=3000 } - -% @enddots{} is an end-of-sentence ellipsis. -\gdef\enddots{$\mathinner{\ldotp\ldotp\ldotp\ldotp}$\spacefactor=3000} - -% @! is an end-of-sentence bang. -\gdef\!{!\spacefactor=3000 } - -% @? is an end-of-sentence query. -\gdef\?{?\spacefactor=3000 } - -% @w prevents a word break. Without the \leavevmode, @w at the -% beginning of a paragraph, when TeX is still in vertical mode, would -% produce a whole line of output instead of starting the paragraph. -\def\w#1{\leavevmode\hbox{#1}} - -% @group ... @end group forces ... to be all on one page, by enclosing -% it in a TeX vbox. We use \vtop instead of \vbox to construct the box -% to keep its height that of a normal line. According to the rules for -% \topskip (p.114 of the TeXbook), the glue inserted is -% max (\topskip - \ht (first item), 0). If that height is large, -% therefore, no glue is inserted, and the space between the headline and -% the text is small, which looks bad. -% -\def\group{\begingroup - \ifnum\catcode13=\active \else - \errhelp = \groupinvalidhelp - \errmessage{@group invalid in context where filling is enabled}% - \fi - % - % The \vtop we start below produces a box with normal height and large - % depth; thus, TeX puts \baselineskip glue before it, and (when the - % next line of text is done) \lineskip glue after it. (See p.82 of - % the TeXbook.) Thus, space below is not quite equal to space - % above. But it's pretty close. - \def\Egroup{% - \egroup % End the \vtop. - \endgroup % End the \group. - }% - % - \vtop\bgroup - % We have to put a strut on the last line in case the @group is in - % the midst of an example, rather than completely enclosing it. - % Otherwise, the interline space between the last line of the group - % and the first line afterwards is too small. But we can't put the - % strut in \Egroup, since there it would be on a line by itself. - % Hence this just inserts a strut at the beginning of each line. - \everypar = {\strut}% - % - % Since we have a strut on every line, we don't need any of TeX's - % normal interline spacing. - \offinterlineskip - % - % OK, but now we have to do something about blank - % lines in the input in @example-like environments, which normally - % just turn into \lisppar, which will insert no space now that we've - % turned off the interline space. Simplest is to make them be an - % empty paragraph. - \ifx\par\lisppar - \edef\par{\leavevmode \par}% - % - % Reset ^^M's definition to new definition of \par. - \obeylines - \fi - % - % Do @comment since we are called inside an environment such as - % @example, where each end-of-line in the input causes an - % end-of-line in the output. We don't want the end-of-line after - % the `@group' to put extra space in the output. Since @group - % should appear on a line by itself (according to the Texinfo - % manual), we don't worry about eating any user text. - \comment -} -% -% TeX puts in an \escapechar (i.e., `@') at the beginning of the help -% message, so this ends up printing `@group can only ...'. -% -\newhelp\groupinvalidhelp{% -group can only be used in environments such as @example,^^J% -where each line of input produces a line of output.} - -% @need space-in-mils -% forces a page break if there is not space-in-mils remaining. - -\newdimen\mil \mil=0.001in - -\def\need{\parsearg\needx} - -% Old definition--didn't work. -%\def\needx #1{\par % -%% This method tries to make TeX break the page naturally -%% if the depth of the box does not fit. -%{\baselineskip=0pt% -%\vtop to #1\mil{\vfil}\kern -#1\mil\penalty 10000 -%\prevdepth=-1000pt -%}} - -\def\needx#1{% - % Go into vertical mode, so we don't make a big box in the middle of a - % paragraph. - \par - % - % Don't add any leading before our big empty box, but allow a page - % break, since the best break might be right here. - \allowbreak - \nointerlineskip - \vtop to #1\mil{\vfil}% - % - % TeX does not even consider page breaks if a penalty added to the - % main vertical list is 10000 or more. But in order to see if the - % empty box we just added fits on the page, we must make it consider - % page breaks. On the other hand, we don't want to actually break the - % page after the empty box. So we use a penalty of 9999. - % - % There is an extremely small chance that TeX will actually break the - % page at this \penalty, if there are no other feasible breakpoints in - % sight. (If the user is using lots of big @group commands, which - % almost-but-not-quite fill up a page, TeX will have a hard time doing - % good page breaking, for example.) However, I could not construct an - % example where a page broke at this \penalty; if it happens in a real - % document, then we can reconsider our strategy. - \penalty9999 - % - % Back up by the size of the box, whether we did a page break or not. - \kern -#1\mil - % - % Do not allow a page break right after this kern. - \nobreak -} - -% @br forces paragraph break - -\let\br = \par - -% @dots{} output some dots - -\def\dots{$\ldots$} - -% @page forces the start of a new page - -\def\page{\par\vfill\supereject} - -% @exdent text.... -% outputs text on separate line in roman font, starting at standard page margin - -% This records the amount of indent in the innermost environment. -% That's how much \exdent should take out. -\newskip\exdentamount - -% This defn is used inside fill environments such as @defun. -\def\exdent{\parsearg\exdentyyy} -\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}} - -% This defn is used inside nofill environments such as @example. -\def\nofillexdent{\parsearg\nofillexdentyyy} -\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount -\leftline{\hskip\leftskip{\rm#1}}}} - -% @inmargin{TEXT} puts TEXT in the margin next to the current paragraph. - -\def\inmargin#1{% -\strut\vadjust{\nobreak\kern-\strutdepth - \vtop to \strutdepth{\baselineskip\strutdepth\vss - \llap{\rightskip=\inmarginspacing \vbox{\noindent #1}}\null}}} -\newskip\inmarginspacing \inmarginspacing=1cm -\def\strutdepth{\dp\strutbox} - -%\hbox{{\rm#1}}\hfil\break}} - -% @include file insert text of that file as input. -% Allow normal characters that we make active in the argument (a file name). -\def\include{\begingroup - \catcode`\\=12 - \catcode`~=12 - \catcode`^=12 - \catcode`_=12 - \catcode`|=12 - \catcode`<=12 - \catcode`>=12 - \catcode`+=12 - \parsearg\includezzz} -% Restore active chars for included file. -\def\includezzz#1{\endgroup\begingroup - % Read the included file in a group so nested @include's work. - \def\thisfile{#1}% - \input\thisfile -\endgroup} - -\def\thisfile{} - -% @center line outputs that line, centered - -\def\center{\parsearg\centerzzz} -\def\centerzzz #1{{\advance\hsize by -\leftskip -\advance\hsize by -\rightskip -\centerline{#1}}} - -% @sp n outputs n lines of vertical space - -\def\sp{\parsearg\spxxx} -\def\spxxx #1{\vskip #1\baselineskip} - -% @comment ...line which is ignored... -% @c is the same as @comment -% @ignore ... @end ignore is another way to write a comment - -\def\comment{\catcode 64=\other \catcode 123=\other \catcode 125=\other% -\parsearg \commentxxx} - -\def\commentxxx #1{\catcode 64=0 \catcode 123=1 \catcode 125=2 } - -\let\c=\comment - -% @paragraphindent is defined for the Info formatting commands only. -\let\paragraphindent=\comment - -% Prevent errors for section commands. -% Used in @ignore and in failing conditionals. -\def\ignoresections{% -\let\chapter=\relax -\let\unnumbered=\relax -\let\top=\relax -\let\unnumberedsec=\relax -\let\unnumberedsection=\relax -\let\unnumberedsubsec=\relax -\let\unnumberedsubsection=\relax -\let\unnumberedsubsubsec=\relax -\let\unnumberedsubsubsection=\relax -\let\section=\relax -\let\subsec=\relax -\let\subsubsec=\relax -\let\subsection=\relax -\let\subsubsection=\relax -\let\appendix=\relax -\let\appendixsec=\relax -\let\appendixsection=\relax -\let\appendixsubsec=\relax -\let\appendixsubsection=\relax -\let\appendixsubsubsec=\relax -\let\appendixsubsubsection=\relax -\let\contents=\relax -\let\smallbook=\relax -\let\titlepage=\relax -} - -% Used in nested conditionals, where we have to parse the Texinfo source -% and so want to turn off most commands, in case they are used -% incorrectly. -% -\def\ignoremorecommands{% - \let\defcodeindex = \relax - \let\defcv = \relax - \let\deffn = \relax - \let\deffnx = \relax - \let\defindex = \relax - \let\defivar = \relax - \let\defmac = \relax - \let\defmethod = \relax - \let\defop = \relax - \let\defopt = \relax - \let\defspec = \relax - \let\deftp = \relax - \let\deftypefn = \relax - \let\deftypefun = \relax - \let\deftypevar = \relax - \let\deftypevr = \relax - \let\defun = \relax - \let\defvar = \relax - \let\defvr = \relax - \let\ref = \relax - \let\xref = \relax - \let\printindex = \relax - \let\pxref = \relax - \let\settitle = \relax - \let\setchapternewpage = \relax - \let\setchapterstyle = \relax - \let\everyheading = \relax - \let\evenheading = \relax - \let\oddheading = \relax - \let\everyfooting = \relax - \let\evenfooting = \relax - \let\oddfooting = \relax - \let\headings = \relax - \let\include = \relax - \let\lowersections = \relax - \let\down = \relax - \let\raisesections = \relax - \let\up = \relax - \let\set = \relax - \let\clear = \relax - \let\item = \relax -} - -% Ignore @ignore ... @end ignore. -% -\def\ignore{\doignore{ignore}} - -% Also ignore @ifinfo, @ifhtml, @html, @menu, and @direntry text. -% -\def\ifinfo{\doignore{ifinfo}} -\def\ifhtml{\doignore{ifhtml}} -\def\html{\doignore{html}} -\def\menu{\doignore{menu}} -\def\direntry{\doignore{direntry}} - -% Also ignore @macro ... @end macro. The user must run texi2dvi, -% which runs makeinfo to do macro expansion. Ignore @unmacro, too. -\def\macro{\doignore{macro}} -\let\unmacro = \comment - - -% @dircategory CATEGORY -- specify a category of the dir file -% which this file should belong to. Ignore this in TeX. -\let\dircategory = \comment - -% Ignore text until a line `@end #1'. -% -\def\doignore#1{\begingroup - % Don't complain about control sequences we have declared \outer. - \ignoresections - % - % Define a command to swallow text until we reach `@end #1'. - \long\def\doignoretext##1\end #1{\enddoignore}% - % - % Make sure that spaces turn into tokens that match what \doignoretext wants. - \catcode32 = 10 - % - % And now expand that command. - \doignoretext -} - -% What we do to finish off ignored text. -% -\def\enddoignore{\endgroup\ignorespaces}% - -\newif\ifwarnedobs\warnedobsfalse -\def\obstexwarn{% - \ifwarnedobs\relax\else - % We need to warn folks that they may have trouble with TeX 3.0. - % This uses \immediate\write16 rather than \message to get newlines. - \immediate\write16{} - \immediate\write16{***WARNING*** for users of Unix TeX 3.0!} - \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).} - \immediate\write16{If you are running another version of TeX, relax.} - \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.} - \immediate\write16{ Then upgrade your TeX installation if you can.} - \immediate\write16{ (See ftp://ftp.gnu.ai.mit.edu/pub/gnu/TeX.README.)} - \immediate\write16{If you are stuck with version 3.0, run the} - \immediate\write16{ script ``tex3patch'' from the Texinfo distribution} - \immediate\write16{ to use a workaround.} - \immediate\write16{} - \global\warnedobstrue - \fi -} - -% **In TeX 3.0, setting text in \nullfont hangs tex. For a -% workaround (which requires the file ``dummy.tfm'' to be installed), -% uncomment the following line: -%%%%%\font\nullfont=dummy\let\obstexwarn=\relax - -% Ignore text, except that we keep track of conditional commands for -% purposes of nesting, up to an `@end #1' command. -% -\def\nestedignore#1{% - \obstexwarn - % We must actually expand the ignored text to look for the @end - % command, so that nested ignore constructs work. Thus, we put the - % text into a \vbox and then do nothing with the result. To minimize - % the change of memory overflow, we follow the approach outlined on - % page 401 of the TeXbook: make the current font be a dummy font. - % - \setbox0 = \vbox\bgroup - % Don't complain about control sequences we have declared \outer. - \ignoresections - % - % Define `@end #1' to end the box, which will in turn undefine the - % @end command again. - \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}% - % - % We are going to be parsing Texinfo commands. Most cause no - % trouble when they are used incorrectly, but some commands do - % complicated argument parsing or otherwise get confused, so we - % undefine them. - % - % We can't do anything about stray @-signs, unfortunately; - % they'll produce `undefined control sequence' errors. - \ignoremorecommands - % - % Set the current font to be \nullfont, a TeX primitive, and define - % all the font commands to also use \nullfont. We don't use - % dummy.tfm, as suggested in the TeXbook, because not all sites - % might have that installed. Therefore, math mode will still - % produce output, but that should be an extremely small amount of - % stuff compared to the main input. - % - \nullfont - \let\tenrm = \nullfont \let\tenit = \nullfont \let\tensl = \nullfont - \let\tenbf = \nullfont \let\tentt = \nullfont \let\smallcaps = \nullfont - \let\tensf = \nullfont - % Similarly for index fonts (mostly for their use in - % smallexample) - \let\indrm = \nullfont \let\indit = \nullfont \let\indsl = \nullfont - \let\indbf = \nullfont \let\indtt = \nullfont \let\indsc = \nullfont - \let\indsf = \nullfont - % - % Don't complain when characters are missing from the fonts. - \tracinglostchars = 0 - % - % Don't bother to do space factor calculations. - \frenchspacing - % - % Don't report underfull hboxes. - \hbadness = 10000 - % - % Do minimal line-breaking. - \pretolerance = 10000 - % - % Do not execute instructions in @tex - \def\tex{\doignore{tex}} -} - -% @set VAR sets the variable VAR to an empty value. -% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE. -% -% Since we want to separate VAR from REST-OF-LINE (which might be -% empty), we can't just use \parsearg; we have to insert a space of our -% own to delimit the rest of the line, and then take it out again if we -% didn't need it. Make sure the catcode of space is correct to avoid -% losing inside @example, for instance. -% -\def\set{\begingroup\catcode` =10 \parsearg\setxxx} -\def\setxxx#1{\setyyy#1 \endsetyyy} -\def\setyyy#1 #2\endsetyyy{% - \def\temp{#2}% - \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty - \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted. - \fi - \endgroup -} -% Can't use \xdef to pre-expand #2 and save some time, since \temp or -% \next or other control sequences that we've defined might get us into -% an infinite loop. Consider `@set foo @cite{bar}'. -\def\setzzz#1#2 \endsetzzz{\expandafter\gdef\csname SET#1\endcsname{#2}} - -% @clear VAR clears (i.e., unsets) the variable VAR. -% -\def\clear{\parsearg\clearxxx} -\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax} - -% @value{foo} gets the text saved in variable foo. -% -\def\value#1{\expandafter - \ifx\csname SET#1\endcsname\relax - {\{No value for ``#1''\}} - \else \csname SET#1\endcsname \fi} - -% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined -% with @set. -% -\def\ifset{\parsearg\ifsetxxx} -\def\ifsetxxx #1{% - \expandafter\ifx\csname SET#1\endcsname\relax - \expandafter\ifsetfail - \else - \expandafter\ifsetsucceed - \fi -} -\def\ifsetsucceed{\conditionalsucceed{ifset}} -\def\ifsetfail{\nestedignore{ifset}} -\defineunmatchedend{ifset} - -% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been -% defined with @set, or has been undefined with @clear. -% -\def\ifclear{\parsearg\ifclearxxx} -\def\ifclearxxx #1{% - \expandafter\ifx\csname SET#1\endcsname\relax - \expandafter\ifclearsucceed - \else - \expandafter\ifclearfail - \fi -} -\def\ifclearsucceed{\conditionalsucceed{ifclear}} -\def\ifclearfail{\nestedignore{ifclear}} -\defineunmatchedend{ifclear} - -% @iftex always succeeds; we read the text following, through @end -% iftex). But `@end iftex' should be valid only after an @iftex. -% -\def\iftex{\conditionalsucceed{iftex}} -\defineunmatchedend{iftex} - -% We can't just want to start a group at @iftex (for example) and end it -% at @end iftex, since then @set commands inside the conditional have no -% effect (they'd get reverted at the end of the group). So we must -% define \Eiftex to redefine itself to be its previous value. (We can't -% just define it to fail again with an ``unmatched end'' error, since -% the @ifset might be nested.) -% -\def\conditionalsucceed#1{% - \edef\temp{% - % Remember the current value of \E#1. - \let\nece{prevE#1} = \nece{E#1}% - % - % At the `@end #1', redefine \E#1 to be its previous value. - \def\nece{E#1}{\let\nece{E#1} = \nece{prevE#1}}% - }% - \temp -} - -% We need to expand lots of \csname's, but we don't want to expand the -% control sequences after we've constructed them. -% -\def\nece#1{\expandafter\noexpand\csname#1\endcsname} - -% @asis just yields its argument. Used with @table, for example. -% -\def\asis#1{#1} - -% @math means output in math mode. -% We don't use $'s directly in the definition of \math because control -% sequences like \math are expanded when the toc file is written. Then, -% we read the toc file back, the $'s will be normal characters (as they -% should be, according to the definition of Texinfo). So we must use a -% control sequence to switch into and out of math mode. -% -% This isn't quite enough for @math to work properly in indices, but it -% seems unlikely it will ever be needed there. -% -\let\implicitmath = $ -\def\math#1{\implicitmath #1\implicitmath} - -% @bullet and @minus need the same treatment as @math, just above. -\def\bullet{\implicitmath\ptexbullet\implicitmath} -\def\minus{\implicitmath-\implicitmath} - -\def\node{\ENVcheck\parsearg\nodezzz} -\def\nodezzz#1{\nodexxx [#1,]} -\def\nodexxx[#1,#2]{\gdef\lastnode{#1}} -\let\nwnode=\node -\let\lastnode=\relax - -\def\donoderef{\ifx\lastnode\relax\else -\expandafter\expandafter\expandafter\setref{\lastnode}\fi -\global\let\lastnode=\relax} - -\def\unnumbnoderef{\ifx\lastnode\relax\else -\expandafter\expandafter\expandafter\unnumbsetref{\lastnode}\fi -\global\let\lastnode=\relax} - -\def\appendixnoderef{\ifx\lastnode\relax\else -\expandafter\expandafter\expandafter\appendixsetref{\lastnode}\fi -\global\let\lastnode=\relax} - -% @refill is a no-op. -\let\refill=\relax - -% @setfilename is done at the beginning of every texinfo file. -% So open here the files we need to have open while reading the input. -% This makes it possible to make a .fmt file for texinfo. -\def\setfilename{% - \readauxfile - \opencontents - \openindices - \fixbackslash % Turn off hack to swallow `\input texinfo'. - \global\let\setfilename=\comment % Ignore extra @setfilename cmds. - \comment % Ignore the actual filename. -} - -% @bye. -\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} - -% \def\macro#1{\begingroup\ignoresections\catcode`\#=6\def\macrotemp{#1}\parsearg\macroxxx} -% \def\macroxxx#1#2 \end macro{% -% \expandafter\gdef\macrotemp#1{#2}% -% \endgroup} - -%\def\linemacro#1{\begingroup\ignoresections\catcode`\#=6\def\macrotemp{#1}\parsearg\linemacroxxx} -%\def\linemacroxxx#1#2 \end linemacro{% -%\let\parsearg=\relax -%\edef\macrotempx{\csname M\butfirst\expandafter\string\macrotemp\endcsname}% -%\expandafter\xdef\macrotemp{\parsearg\macrotempx}% -%\expandafter\gdef\macrotempx#1{#2}% -%\endgroup} - -%\def\butfirst#1{} - - -\message{fonts,} - -% Font-change commands. - -% Texinfo supports the sans serif font style, which plain TeX does not. -% So we set up a \sf analogous to plain's \rm, etc. -\newfam\sffam -\def\sf{\fam=\sffam \tensf} -\let\li = \sf % Sometimes we call it \li, not \sf. - -% We don't need math for this one. -\def\ttsl{\tenttsl} - -%% Try out Computer Modern fonts at \magstephalf -\let\mainmagstep=\magstephalf - -% Set the font macro #1 to the font named #2, adding on the -% specified font prefix (normally `cm'). -% #3 is the font's design size, #4 is a scale factor -\def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4} - -% Use cm as the default font prefix. -% To specify the font prefix, you must define \fontprefix -% before you read in texinfo.tex. -\ifx\fontprefix\undefined -\def\fontprefix{cm} -\fi -% Support font families that don't use the same naming scheme as CM. -\def\rmshape{r} -\def\rmbshape{bx} %where the normal face is bold -\def\bfshape{b} -\def\bxshape{bx} -\def\ttshape{tt} -\def\ttbshape{tt} -\def\ttslshape{sltt} -\def\itshape{ti} -\def\itbshape{bxti} -\def\slshape{sl} -\def\slbshape{bxsl} -\def\sfshape{ss} -\def\sfbshape{ss} -\def\scshape{csc} -\def\scbshape{csc} - -\ifx\bigger\relax -\let\mainmagstep=\magstep1 -\setfont\textrm\rmshape{12}{1000} -\setfont\texttt\ttshape{12}{1000} -\else -\setfont\textrm\rmshape{10}{\mainmagstep} -\setfont\texttt\ttshape{10}{\mainmagstep} -\fi -% Instead of cmb10, you many want to use cmbx10. -% cmbx10 is a prettier font on its own, but cmb10 -% looks better when embedded in a line with cmr10. -\setfont\textbf\bfshape{10}{\mainmagstep} -\setfont\textit\itshape{10}{\mainmagstep} -\setfont\textsl\slshape{10}{\mainmagstep} -\setfont\textsf\sfshape{10}{\mainmagstep} -\setfont\textsc\scshape{10}{\mainmagstep} -\setfont\textttsl\ttslshape{10}{\mainmagstep} -\font\texti=cmmi10 scaled \mainmagstep -\font\textsy=cmsy10 scaled \mainmagstep - -% A few fonts for @defun, etc. -\setfont\defbf\bxshape{10}{\magstep1} %was 1314 -\setfont\deftt\ttshape{10}{\magstep1} -\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf} - -% Fonts for indices and small examples (9pt). -% We actually use the slanted font rather than the italic, -% because texinfo normally uses the slanted fonts for that. -% Do not make many font distinctions in general in the index, since they -% aren't very useful. -\setfont\ninett\ttshape{9}{1000} -\setfont\indrm\rmshape{9}{1000} -\setfont\indit\slshape{9}{1000} -\let\indsl=\indit -\let\indtt=\ninett -\let\indttsl=\ninett -\let\indsf=\indrm -\let\indbf=\indrm -\setfont\indsc\scshape{10}{900} -\font\indi=cmmi9 -\font\indsy=cmsy9 - -% Chapter (and unnumbered) fonts (17.28pt). -\setfont\chaprm\rmbshape{12}{\magstep2} -\setfont\chapit\itbshape{10}{\magstep3} -\setfont\chapsl\slbshape{10}{\magstep3} -\setfont\chaptt\ttbshape{12}{\magstep2} -\setfont\chapttsl\ttslshape{10}{\magstep3} -\setfont\chapsf\sfbshape{12}{\magstep2} -\let\chapbf=\chaprm -\setfont\chapsc\scbshape{10}{\magstep3} -\font\chapi=cmmi12 scaled \magstep2 -\font\chapsy=cmsy10 scaled \magstep3 - -% Section fonts (14.4pt). -\setfont\secrm\rmbshape{12}{\magstep1} -\setfont\secit\itbshape{10}{\magstep2} -\setfont\secsl\slbshape{10}{\magstep2} -\setfont\sectt\ttbshape{12}{\magstep1} -\setfont\secttsl\ttslshape{10}{\magstep2} -\setfont\secsf\sfbshape{12}{\magstep1} -\let\secbf\secrm -\setfont\secsc\scbshape{10}{\magstep2} -\font\seci=cmmi12 scaled \magstep1 -\font\secsy=cmsy10 scaled \magstep2 - -% \setfont\ssecrm\bxshape{10}{\magstep1} % This size an font looked bad. -% \setfont\ssecit\itshape{10}{\magstep1} % The letters were too crowded. -% \setfont\ssecsl\slshape{10}{\magstep1} -% \setfont\ssectt\ttshape{10}{\magstep1} -% \setfont\ssecsf\sfshape{10}{\magstep1} - -%\setfont\ssecrm\bfshape{10}{1315} % Note the use of cmb rather than cmbx. -%\setfont\ssecit\itshape{10}{1315} % Also, the size is a little larger than -%\setfont\ssecsl\slshape{10}{1315} % being scaled magstep1. -%\setfont\ssectt\ttshape{10}{1315} -%\setfont\ssecsf\sfshape{10}{1315} - -%\let\ssecbf=\ssecrm - -% Subsection fonts (13.15pt). -\setfont\ssecrm\rmbshape{12}{\magstephalf} -\setfont\ssecit\itbshape{10}{1315} -\setfont\ssecsl\slbshape{10}{1315} -\setfont\ssectt\ttbshape{12}{\magstephalf} -\setfont\ssecttsl\ttslshape{10}{\magstep1} -\setfont\ssecsf\sfbshape{12}{\magstephalf} -\let\ssecbf\ssecrm -\setfont\ssecsc\scbshape{10}{\magstep1} -\font\sseci=cmmi12 scaled \magstephalf -\font\ssecsy=cmsy10 scaled \magstep1 -% The smallcaps and symbol fonts should actually be scaled \magstep1.5, -% but that is not a standard magnification. - -% Fonts for title page: -\setfont\titlerm\rmbshape{12}{\magstep3} -\let\authorrm = \secrm - -% In order for the font changes to affect most math symbols and letters, -% we have to define the \textfont of the standard families. Since -% texinfo doesn't allow for producing subscripts and superscripts, we -% don't bother to reset \scriptfont and \scriptscriptfont (which would -% also require loading a lot more fonts). -% -\def\resetmathfonts{% - \textfont0 = \tenrm \textfont1 = \teni \textfont2 = \tensy - \textfont\itfam = \tenit \textfont\slfam = \tensl \textfont\bffam = \tenbf - \textfont\ttfam = \tentt \textfont\sffam = \tensf -} - - -% The font-changing commands redefine the meanings of \tenSTYLE, instead -% of just \STYLE. We do this so that font changes will continue to work -% in math mode, where it is the current \fam that is relevant in most -% cases, not the current font. Plain TeX does \def\bf{\fam=\bffam -% \tenbf}, for example. By redefining \tenbf, we obviate the need to -% redefine \bf itself. -\def\textfonts{% - \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl - \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc - \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy \let\tenttsl=\textttsl - \resetmathfonts} -\def\chapfonts{% - \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl - \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc - \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy \let\tenttsl=\chapttsl - \resetmathfonts \setleading{19pt}} -\def\secfonts{% - \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl - \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc - \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy \let\tenttsl=\secttsl - \resetmathfonts \setleading{16pt}} -\def\subsecfonts{% - \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl - \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc - \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy \let\tenttsl=\ssecttsl - \resetmathfonts \setleading{15pt}} -\let\subsubsecfonts = \subsecfonts % Maybe make sssec fonts scaled magstephalf? -\def\indexfonts{% - \let\tenrm=\indrm \let\tenit=\indit \let\tensl=\indsl - \let\tenbf=\indbf \let\tentt=\indtt \let\smallcaps=\indsc - \let\tensf=\indsf \let\teni=\indi \let\tensy=\indsy \let\tenttsl=\indttsl - \resetmathfonts \setleading{12pt}} - -% Set up the default fonts, so we can use them for creating boxes. -% -\textfonts - -% Count depth in font-changes, for error checks -\newcount\fontdepth \fontdepth=0 - -% Fonts for short table of contents. -\setfont\shortcontrm\rmshape{12}{1000} -\setfont\shortcontbf\bxshape{12}{1000} -\setfont\shortcontsl\slshape{12}{1000} - -%% Add scribe-like font environments, plus @l for inline lisp (usually sans -%% serif) and @ii for TeX italic - -% \smartitalic{ARG} outputs arg in italics, followed by an italic correction -% unless the following character is such as not to need one. -\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else\/\fi\fi\fi} -\def\smartitalic#1{{\sl #1}\futurelet\next\smartitalicx} - -\let\i=\smartitalic -\let\var=\smartitalic -\let\dfn=\smartitalic -\let\emph=\smartitalic -\let\cite=\smartitalic - -\def\b#1{{\bf #1}} -\let\strong=\b - -% We can't just use \exhyphenpenalty, because that only has effect at -% the end of a paragraph. Restore normal hyphenation at the end of the -% group within which \nohyphenation is presumably called. -% -\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation} -\def\restorehyphenation{\hyphenchar\font = `- } - -\def\t#1{% - {\tt \rawbackslash \frenchspacing #1}% - \null -} -\let\ttfont=\t -\def\samp #1{`\tclose{#1}'\null} -\setfont\smallrm\rmshape{8}{1000} -\font\smallsy=cmsy9 -\def\key#1{{\smallrm\textfont2=\smallsy \leavevmode\hbox{% - \raise0.4pt\hbox{$\langle$}\kern-.08em\vtop{% - \vbox{\hrule\kern-0.4pt - \hbox{\raise0.4pt\hbox{\vphantom{$\langle$}}#1}}% - \kern-0.4pt\hrule}% - \kern-.06em\raise0.4pt\hbox{$\rangle$}}}} -% The old definition, with no lozenge: -%\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null} -\def\ctrl #1{{\tt \rawbackslash \hat}#1} - -\let\file=\samp -\let\url=\samp % perhaps include a hypertex \special eventually -\def\email#1{$\langle${\tt #1}$\rangle$} - -% @code is a modification of @t, -% which makes spaces the same size as normal in the surrounding text. -\def\tclose#1{% - {% - % Change normal interword space to be same as for the current font. - \spaceskip = \fontdimen2\font - % - % Switch to typewriter. - \tt - % - % But `\ ' produces the large typewriter interword space. - \def\ {{\spaceskip = 0pt{} }}% - % - % Turn off hyphenation. - \nohyphenation - % - \rawbackslash - \frenchspacing - #1% - }% - \null -} - -% We *must* turn on hyphenation at `-' and `_' in \code. -% Otherwise, it is too hard to avoid overfull hboxes -% in the Emacs manual, the Library manual, etc. - -% Unfortunately, TeX uses one parameter (\hyphenchar) to control -% both hyphenation at - and hyphenation within words. -% We must therefore turn them both off (\tclose does that) -% and arrange explicitly to hyphenate at a dash. -% -- rms. -{ -\catcode`\-=\active -\catcode`\_=\active -\global\def\code{\begingroup \catcode`\-=\active \let-\codedash \catcode`\_=\active \let_\codeunder \codex} -% The following is used by \doprintindex to insure that long function names -% wrap around. It is necessary for - and _ to be active before the index is -% read from the file, as \entry parses the arguments long before \code is -% ever called. -- mycroft -\global\def\indexbreaks{\catcode`\-=\active \let-\realdash \catcode`\_=\active \let_\realunder} -} - -\def\realdash{-} -\def\realunder{_} -\def\codedash{-\discretionary{}{}{}} -\def\codeunder{\ifusingtt{\normalunderscore\discretionary{}{}{}}{\_}} -\def\codex #1{\tclose{#1}\endgroup} - -%\let\exp=\tclose %Was temporary - -% @kbd is like @code, except that if the argument is just one @key command, -% then @kbd has no effect. -% -\def\xkey{\key} -\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}% -\ifx\one\xkey\ifx\threex\three \key{#2}% -\else{\tclose{\ttsl\look}}\fi -\else{\tclose{\ttsl\look}}\fi} - -% Check if we are currently using a typewriter font. Since all the -% Computer Modern typewriter fonts have zero interword stretch (and -% shrink), and it is reasonable to expect all typewriter fonts to have -% this property, we can check that font parameter. -% -\def\ifmonospace{\ifdim\fontdimen3\font=0pt } - -% Typeset a dimension, e.g., `in' or `pt'. The only reason for the -% argument is to make the input look right: @dmn{pt} instead of -% @dmn{}pt. -% -\def\dmn#1{\thinspace #1} - -\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par} - -% @l was never documented to mean ``switch to the Lisp font'', -% and it is not used as such in any manual I can find. We need it for -% Polish suppressed-l. --karl, 22sep96. -%\def\l#1{{\li #1}\null} - -\def\r#1{{\rm #1}} % roman font -% Use of \lowercase was suggested. -\def\sc#1{{\smallcaps#1}} % smallcaps font -\def\ii#1{{\it #1}} % italic font - -% @pounds{} is a sterling sign. -\def\pounds{{\it\$}} - - -\message{page headings,} - -\newskip\titlepagetopglue \titlepagetopglue = 1.5in -\newskip\titlepagebottomglue \titlepagebottomglue = 2pc - -% First the title page. Must do @settitle before @titlepage. -\def\titlefont#1{{\titlerm #1}} - -\newif\ifseenauthor -\newif\iffinishedtitlepage - -\def\shorttitlepage{\parsearg\shorttitlepagezzz} -\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}% - \endgroup\page\hbox{}\page} - -\def\titlepage{\begingroup \parindent=0pt \textfonts - \let\subtitlerm=\tenrm -% I deinstalled the following change because \cmr12 is undefined. -% This change was not in the ChangeLog anyway. --rms. -% \let\subtitlerm=\cmr12 - \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}% - % - \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}% - % - % Leave some space at the very top of the page. - \vglue\titlepagetopglue - % - % Now you can print the title using @title. - \def\title{\parsearg\titlezzz}% - \def\titlezzz##1{\leftline{\titlefont{##1}} - % print a rule at the page bottom also. - \finishedtitlepagefalse - \vskip4pt \hrule height 4pt width \hsize \vskip4pt}% - % No rule at page bottom unless we print one at the top with @title. - \finishedtitlepagetrue - % - % Now you can put text using @subtitle. - \def\subtitle{\parsearg\subtitlezzz}% - \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}% - % - % @author should come last, but may come many times. - \def\author{\parsearg\authorzzz}% - \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi - {\authorfont \leftline{##1}}}% - % - % Most title ``pages'' are actually two pages long, with space - % at the top of the second. We don't want the ragged left on the second. - \let\oldpage = \page - \def\page{% - \iffinishedtitlepage\else - \finishtitlepage - \fi - \oldpage - \let\page = \oldpage - \hbox{}}% -% \def\page{\oldpage \hbox{}} -} - -\def\Etitlepage{% - \iffinishedtitlepage\else - \finishtitlepage - \fi - % It is important to do the page break before ending the group, - % because the headline and footline are only empty inside the group. - % If we use the new definition of \page, we always get a blank page - % after the title page, which we certainly don't want. - \oldpage - \endgroup - \HEADINGSon -} - -\def\finishtitlepage{% - \vskip4pt \hrule height 2pt width \hsize - \vskip\titlepagebottomglue - \finishedtitlepagetrue -} - -%%% Set up page headings and footings. - -\let\thispage=\folio - -\newtoks \evenheadline % Token sequence for heading line of even pages -\newtoks \oddheadline % Token sequence for heading line of odd pages -\newtoks \evenfootline % Token sequence for footing line of even pages -\newtoks \oddfootline % Token sequence for footing line of odd pages - -% Now make Tex use those variables -\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline - \else \the\evenheadline \fi}} -\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline - \else \the\evenfootline \fi}\HEADINGShook} -\let\HEADINGShook=\relax - -% Commands to set those variables. -% For example, this is what @headings on does -% @evenheading @thistitle|@thispage|@thischapter -% @oddheading @thischapter|@thispage|@thistitle -% @evenfooting @thisfile|| -% @oddfooting ||@thisfile - -\def\evenheading{\parsearg\evenheadingxxx} -\def\oddheading{\parsearg\oddheadingxxx} -\def\everyheading{\parsearg\everyheadingxxx} - -\def\evenfooting{\parsearg\evenfootingxxx} -\def\oddfooting{\parsearg\oddfootingxxx} -\def\everyfooting{\parsearg\everyfootingxxx} - -{\catcode`\@=0 % - -\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish} -\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{% -\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} - -\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish} -\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{% -\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} - -\gdef\everyheadingxxx #1{\everyheadingyyy #1@|@|@|@|\finish} -\gdef\everyheadingyyy #1@|#2@|#3@|#4\finish{% -\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}} -\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} - -\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish} -\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{% -\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} - -\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish} -\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{% -\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} - -\gdef\everyfootingxxx #1{\everyfootingyyy #1@|@|@|@|\finish} -\gdef\everyfootingyyy #1@|#2@|#3@|#4\finish{% -\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}} -\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} -% -}% unbind the catcode of @. - -% @headings double turns headings on for double-sided printing. -% @headings single turns headings on for single-sided printing. -% @headings off turns them off. -% @headings on same as @headings double, retained for compatibility. -% @headings after turns on double-sided headings after this page. -% @headings doubleafter turns on double-sided headings after this page. -% @headings singleafter turns on single-sided headings after this page. -% By default, they are off at the start of a document, -% and turned `on' after @end titlepage. - -\def\headings #1 {\csname HEADINGS#1\endcsname} - -\def\HEADINGSoff{ -\global\evenheadline={\hfil} \global\evenfootline={\hfil} -\global\oddheadline={\hfil} \global\oddfootline={\hfil}} -\HEADINGSoff -% When we turn headings on, set the page number to 1. -% For double-sided printing, put current file name in lower left corner, -% chapter name on inside top of right hand pages, document -% title on inside top of left hand pages, and page numbers on outside top -% edge of all pages. -\def\HEADINGSdouble{ -\global\pageno=1 -\global\evenfootline={\hfil} -\global\oddfootline={\hfil} -\global\evenheadline={\line{\folio\hfil\thistitle}} -\global\oddheadline={\line{\thischapter\hfil\folio}} -\global\let\contentsalignmacro = \chapoddpage -} -\let\contentsalignmacro = \chappager - -% For single-sided printing, chapter title goes across top left of page, -% page number on top right. -\def\HEADINGSsingle{ -\global\pageno=1 -\global\evenfootline={\hfil} -\global\oddfootline={\hfil} -\global\evenheadline={\line{\thischapter\hfil\folio}} -\global\oddheadline={\line{\thischapter\hfil\folio}} -\global\let\contentsalignmacro = \chappager -} -\def\HEADINGSon{\HEADINGSdouble} - -\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex} -\let\HEADINGSdoubleafter=\HEADINGSafter -\def\HEADINGSdoublex{% -\global\evenfootline={\hfil} -\global\oddfootline={\hfil} -\global\evenheadline={\line{\folio\hfil\thistitle}} -\global\oddheadline={\line{\thischapter\hfil\folio}} -\global\let\contentsalignmacro = \chapoddpage -} - -\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex} -\def\HEADINGSsinglex{% -\global\evenfootline={\hfil} -\global\oddfootline={\hfil} -\global\evenheadline={\line{\thischapter\hfil\folio}} -\global\oddheadline={\line{\thischapter\hfil\folio}} -\global\let\contentsalignmacro = \chappager -} - -% Subroutines used in generating headings -% Produces Day Month Year style of output. -\def\today{\number\day\space -\ifcase\month\or -January\or February\or March\or April\or May\or June\or -July\or August\or September\or October\or November\or December\fi -\space\number\year} - -% Use this if you want the Month Day, Year style of output. -%\def\today{\ifcase\month\or -%January\or February\or March\or April\or May\or June\or -%July\or August\or September\or October\or November\or December\fi -%\space\number\day, \number\year} - -% @settitle line... specifies the title of the document, for headings -% It generates no output of its own - -\def\thistitle{No Title} -\def\settitle{\parsearg\settitlezzz} -\def\settitlezzz #1{\gdef\thistitle{#1}} - - -\message{tables,} - -% @tabs -- simple alignment - -% These don't work. For one thing, \+ is defined as outer. -% So these macros cannot even be defined. - -%\def\tabs{\parsearg\tabszzz} -%\def\tabszzz #1{\settabs\+#1\cr} -%\def\tabline{\parsearg\tablinezzz} -%\def\tablinezzz #1{\+#1\cr} -%\def\&{&} - -% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(x). - -% default indentation of table text -\newdimen\tableindent \tableindent=.8in -% default indentation of @itemize and @enumerate text -\newdimen\itemindent \itemindent=.3in -% margin between end of table item and start of table text. -\newdimen\itemmargin \itemmargin=.1in - -% used internally for \itemindent minus \itemmargin -\newdimen\itemmax - -% Note @table, @vtable, and @vtable define @item, @itemx, etc., with -% these defs. -% They also define \itemindex -% to index the item name in whatever manner is desired (perhaps none). - -\newif\ifitemxneedsnegativevskip - -\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi} - -\def\internalBitem{\smallbreak \parsearg\itemzzz} -\def\internalBitemx{\itemxpar \parsearg\itemzzz} - -\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz} -\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \itemxpar \parsearg\xitemzzz} - -\def\internalBkitem{\smallbreak \parsearg\kitemzzz} -\def\internalBkitemx{\itemxpar \parsearg\kitemzzz} - -\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}% - \itemzzz {#1}} - -\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}% - \itemzzz {#1}} - -\def\itemzzz #1{\begingroup % - \advance\hsize by -\rightskip - \advance\hsize by -\tableindent - \setbox0=\hbox{\itemfont{#1}}% - \itemindex{#1}% - \nobreak % This prevents a break before @itemx. - % - % Be sure we are not still in the middle of a paragraph. - %{\parskip = 0in - %\par - %}% - % - % If the item text does not fit in the space we have, put it on a line - % by itself, and do not allow a page break either before or after that - % line. We do not start a paragraph here because then if the next - % command is, e.g., @kindex, the whatsit would get put into the - % horizontal list on a line by itself, resulting in extra blank space. - \ifdim \wd0>\itemmax - % - % Make this a paragraph so we get the \parskip glue and wrapping, - % but leave it ragged-right. - \begingroup - \advance\leftskip by-\tableindent - \advance\hsize by\tableindent - \advance\rightskip by0pt plus1fil - \leavevmode\unhbox0\par - \endgroup - % - % We're going to be starting a paragraph, but we don't want the - % \parskip glue -- logically it's part of the @item we just started. - \nobreak \vskip-\parskip - % - % Stop a page break at the \parskip glue coming up. Unfortunately - % we can't prevent a possible page break at the following - % \baselineskip glue. - \nobreak - \endgroup - \itemxneedsnegativevskipfalse - \else - % The item text fits into the space. Start a paragraph, so that the - % following text (if any) will end up on the same line. Since that - % text will be indented by \tableindent, we make the item text be in - % a zero-width box. - \noindent - \rlap{\hskip -\tableindent\box0}\ignorespaces% - \endgroup% - \itemxneedsnegativevskiptrue% - \fi -} - -\def\item{\errmessage{@item while not in a table}} -\def\itemx{\errmessage{@itemx while not in a table}} -\def\kitem{\errmessage{@kitem while not in a table}} -\def\kitemx{\errmessage{@kitemx while not in a table}} -\def\xitem{\errmessage{@xitem while not in a table}} -\def\xitemx{\errmessage{@xitemx while not in a table}} - -%% Contains a kludge to get @end[description] to work -\def\description{\tablez{\dontindex}{1}{}{}{}{}} - -\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex} -{\obeylines\obeyspaces% -\gdef\tablex #1^^M{% -\tabley\dontindex#1 \endtabley}} - -\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex} -{\obeylines\obeyspaces% -\gdef\ftablex #1^^M{% -\tabley\fnitemindex#1 \endtabley -\def\Eftable{\endgraf\afterenvbreak\endgroup}% -\let\Etable=\relax}} - -\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex} -{\obeylines\obeyspaces% -\gdef\vtablex #1^^M{% -\tabley\vritemindex#1 \endtabley -\def\Evtable{\endgraf\afterenvbreak\endgroup}% -\let\Etable=\relax}} - -\def\dontindex #1{} -\def\fnitemindex #1{\doind {fn}{\code{#1}}}% -\def\vritemindex #1{\doind {vr}{\code{#1}}}% - -{\obeyspaces % -\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup% -\tablez{#1}{#2}{#3}{#4}{#5}{#6}}} - -\def\tablez #1#2#3#4#5#6{% -\aboveenvbreak % -\begingroup % -\def\Edescription{\Etable}% Necessary kludge. -\let\itemindex=#1% -\ifnum 0#3>0 \advance \leftskip by #3\mil \fi % -\ifnum 0#4>0 \tableindent=#4\mil \fi % -\ifnum 0#5>0 \advance \rightskip by #5\mil \fi % -\def\itemfont{#2}% -\itemmax=\tableindent % -\advance \itemmax by -\itemmargin % -\advance \leftskip by \tableindent % -\exdentamount=\tableindent -\parindent = 0pt -\parskip = \smallskipamount -\ifdim \parskip=0pt \parskip=2pt \fi% -\def\Etable{\endgraf\afterenvbreak\endgroup}% -\let\item = \internalBitem % -\let\itemx = \internalBitemx % -\let\kitem = \internalBkitem % -\let\kitemx = \internalBkitemx % -\let\xitem = \internalBxitem % -\let\xitemx = \internalBxitemx % -} - -% This is the counter used by @enumerate, which is really @itemize - -\newcount \itemno - -\def\itemize{\parsearg\itemizezzz} - -\def\itemizezzz #1{% - \begingroup % ended by the @end itemsize - \itemizey {#1}{\Eitemize} -} - -\def\itemizey #1#2{% -\aboveenvbreak % -\itemmax=\itemindent % -\advance \itemmax by -\itemmargin % -\advance \leftskip by \itemindent % -\exdentamount=\itemindent -\parindent = 0pt % -\parskip = \smallskipamount % -\ifdim \parskip=0pt \parskip=2pt \fi% -\def#2{\endgraf\afterenvbreak\endgroup}% -\def\itemcontents{#1}% -\let\item=\itemizeitem} - -% Set sfcode to normal for the chars that usually have another value. -% These are `.?!:;,' -\def\frenchspacing{\sfcode46=1000 \sfcode63=1000 \sfcode33=1000 - \sfcode58=1000 \sfcode59=1000 \sfcode44=1000 } - -% \splitoff TOKENS\endmark defines \first to be the first token in -% TOKENS, and \rest to be the remainder. -% -\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}% - -% Allow an optional argument of an uppercase letter, lowercase letter, -% or number, to specify the first label in the enumerated list. No -% argument is the same as `1'. -% -\def\enumerate{\parsearg\enumeratezzz} -\def\enumeratezzz #1{\enumeratey #1 \endenumeratey} -\def\enumeratey #1 #2\endenumeratey{% - \begingroup % ended by the @end enumerate - % - % If we were given no argument, pretend we were given `1'. - \def\thearg{#1}% - \ifx\thearg\empty \def\thearg{1}\fi - % - % Detect if the argument is a single token. If so, it might be a - % letter. Otherwise, the only valid thing it can be is a number. - % (We will always have one token, because of the test we just made. - % This is a good thing, since \splitoff doesn't work given nothing at - % all -- the first parameter is undelimited.) - \expandafter\splitoff\thearg\endmark - \ifx\rest\empty - % Only one token in the argument. It could still be anything. - % A ``lowercase letter'' is one whose \lccode is nonzero. - % An ``uppercase letter'' is one whose \lccode is both nonzero, and - % not equal to itself. - % Otherwise, we assume it's a number. - % - % We need the \relax at the end of the \ifnum lines to stop TeX from - % continuing to look for a . - % - \ifnum\lccode\expandafter`\thearg=0\relax - \numericenumerate % a number (we hope) - \else - % It's a letter. - \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax - \lowercaseenumerate % lowercase letter - \else - \uppercaseenumerate % uppercase letter - \fi - \fi - \else - % Multiple tokens in the argument. We hope it's a number. - \numericenumerate - \fi -} - -% An @enumerate whose labels are integers. The starting integer is -% given in \thearg. -% -\def\numericenumerate{% - \itemno = \thearg - \startenumeration{\the\itemno}% -} - -% The starting (lowercase) letter is in \thearg. -\def\lowercaseenumerate{% - \itemno = \expandafter`\thearg - \startenumeration{% - % Be sure we're not beyond the end of the alphabet. - \ifnum\itemno=0 - \errmessage{No more lowercase letters in @enumerate; get a bigger - alphabet}% - \fi - \char\lccode\itemno - }% -} - -% The starting (uppercase) letter is in \thearg. -\def\uppercaseenumerate{% - \itemno = \expandafter`\thearg - \startenumeration{% - % Be sure we're not beyond the end of the alphabet. - \ifnum\itemno=0 - \errmessage{No more uppercase letters in @enumerate; get a bigger - alphabet} - \fi - \char\uccode\itemno - }% -} - -% Call itemizey, adding a period to the first argument and supplying the -% common last two arguments. Also subtract one from the initial value in -% \itemno, since @item increments \itemno. -% -\def\startenumeration#1{% - \advance\itemno by -1 - \itemizey{#1.}\Eenumerate\flushcr -} - -% @alphaenumerate and @capsenumerate are abbreviations for giving an arg -% to @enumerate. -% -\def\alphaenumerate{\enumerate{a}} -\def\capsenumerate{\enumerate{A}} -\def\Ealphaenumerate{\Eenumerate} -\def\Ecapsenumerate{\Eenumerate} - -% Definition of @item while inside @itemize. - -\def\itemizeitem{% -\advance\itemno by 1 -{\let\par=\endgraf \smallbreak}% -\ifhmode \errmessage{\in hmode at itemizeitem}\fi -{\parskip=0in \hskip 0pt -\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}% -\vadjust{\penalty 1200}}% -\flushcr} - -% @multitable macros -% Amy Hendrickson, 8/18/94, 3/6/96 -% -% @multitable ... @end multitable will make as many columns as desired. -% Contents of each column will wrap at width given in preamble. Width -% can be specified either with sample text given in a template line, -% or in percent of \hsize, the current width of text on page. - -% Table can continue over pages but will only break between lines. - -% To make preamble: -% -% Either define widths of columns in terms of percent of \hsize: -% @multitable @columnfractions .25 .3 .45 -% @item ... -% -% Numbers following @columnfractions are the percent of the total -% current hsize to be used for each column. You may use as many -% columns as desired. - - -% Or use a template: -% @multitable {Column 1 template} {Column 2 template} {Column 3 template} -% @item ... -% using the widest term desired in each column. -% -% For those who want to use more than one line's worth of words in -% the preamble, break the line within one argument and it -% will parse correctly, i.e., -% -% @multitable {Column 1 template} {Column 2 template} {Column 3 -% template} -% Not: -% @multitable {Column 1 template} {Column 2 template} -% {Column 3 template} - -% Each new table line starts with @item, each subsequent new column -% starts with @tab. Empty columns may be produced by supplying @tab's -% with nothing between them for as many times as empty columns are needed, -% ie, @tab@tab@tab will produce two empty columns. - -% @item, @tab, @multitable or @end multitable do not need to be on their -% own lines, but it will not hurt if they are. - -% Sample multitable: - -% @multitable {Column 1 template} {Column 2 template} {Column 3 template} -% @item first col stuff @tab second col stuff @tab third col -% @item -% first col stuff -% @tab -% second col stuff -% @tab -% third col -% @item first col stuff @tab second col stuff -% @tab Many paragraphs of text may be used in any column. -% -% They will wrap at the width determined by the template. -% @item@tab@tab This will be in third column. -% @end multitable - -% Default dimensions may be reset by user. -% @multitableparskip is vertical space between paragraphs in table. -% @multitableparindent is paragraph indent in table. -% @multitablecolmargin is horizontal space to be left between columns. -% @multitablelinespace is space to leave between table items, baseline -% to baseline. -% 0pt means it depends on current normal line spacing. - -%%%% -% Dimensions - -\newskip\multitableparskip -\newskip\multitableparindent -\newdimen\multitablecolspace -\newskip\multitablelinespace -\multitableparskip=0pt -\multitableparindent=6pt -\multitablecolspace=12pt -\multitablelinespace=0pt - -%%%% -% Macros used to set up halign preamble: -\let\endsetuptable\relax -\def\xendsetuptable{\endsetuptable} -\let\columnfractions\relax -\def\xcolumnfractions{\columnfractions} -\newif\ifsetpercent - -%% 2/1/96, to allow fractions to be given with more than one digit. -\def\pickupwholefraction#1 {\global\advance\colcount by1 % -\expandafter\xdef\csname col\the\colcount\endcsname{.#1\hsize}% -\setuptable} - -\newcount\colcount -\def\setuptable#1{\def\firstarg{#1}% -\ifx\firstarg\xendsetuptable\let\go\relax% -\else - \ifx\firstarg\xcolumnfractions\global\setpercenttrue% - \else - \ifsetpercent - \let\go\pickupwholefraction % In this case arg of setuptable - % is the decimal point before the - % number given in percent of hsize. - % We don't need this so we don't use it. - \else - \global\advance\colcount by1 - \setbox0=\hbox{#1 }% Add a normal word space as a separator; - % typically that is always in the input, anyway. - \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}% - \fi% - \fi% -\ifx\go\pickupwholefraction\else\let\go\setuptable\fi% -\fi\go} - -%%%% -% multitable syntax -\def\tab{&\hskip1sp\relax} % 2/2/96 - % tiny skip here makes sure this column space is - % maintained, even if it is never used. - - -%%%% -% @multitable ... @end multitable definitions: - -\def\multitable{\parsearg\dotable} - -\def\dotable#1{\bgroup -\let\item\cr -\tolerance=9500 -\hbadness=9500 -\setmultitablespacing -\parskip=\multitableparskip -\parindent=\multitableparindent -\overfullrule=0pt -\global\colcount=0\relax% -\def\Emultitable{\global\setpercentfalse\global\everycr{}\cr\egroup\egroup}% - % To parse everything between @multitable and @item : -\setuptable#1 \endsetuptable - % Need to reset this to 0 after \setuptable. -\global\colcount=0\relax% - % - % This preamble sets up a generic column definition, which will - % be used as many times as user calls for columns. - % \vtop will set a single line and will also let text wrap and - % continue for many paragraphs if desired. -\halign\bgroup&\global\advance\colcount by 1\relax% -\multistrut\vtop{\hsize=\expandafter\csname col\the\colcount\endcsname - % In order to keep entries from bumping into each other - % we will add a \leftskip of \multitablecolspace to all columns after - % the first one. - % If a template has been used, we will add \multitablecolspace - % to the width of each template entry. - % If user has set preamble in terms of percent of \hsize - % we will use that dimension as the width of the column, and - % the \leftskip will keep entries from bumping into each other. - % Table will start at left margin and final column will justify at - % right margin. -\ifnum\colcount=1 -\else - \ifsetpercent - \else - % If user has set preamble in terms of percent of \hsize - % we will advance \hsize by \multitablecolspace - \advance\hsize by \multitablecolspace - \fi - % In either case we will make \leftskip=\multitablecolspace: -\leftskip=\multitablecolspace -\fi -\noindent##\multistrut}\cr% - % \everycr will reset column counter, \colcount, at the end of - % each line. Every column entry will cause \colcount to advance by one. - % The table preamble - % looks at the current \colcount to find the correct column width. -\global\everycr{\noalign{% -\filbreak%% keeps underfull box messages off when table breaks over pages. -\global\colcount=0\relax}} -} - -\def\setmultitablespacing{% test to see if user has set \multitablelinespace. -% If so, do nothing. If not, give it an appropriate dimension based on -% current baselineskip. -\ifdim\multitablelinespace=0pt -%% strut to put in table in case some entry doesn't have descenders, -%% to keep lines equally spaced -\let\multistrut = \strut -%% Test to see if parskip is larger than space between lines of -%% table. If not, do nothing. -%% If so, set to same dimension as multitablelinespace. -\else -\gdef\multistrut{\vrule height\multitablelinespace depth\dp0 -width0pt\relax} \fi -\ifdim\multitableparskip>\multitablelinespace -\global\multitableparskip=\multitablelinespace -\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller - %% than skip between lines in the table. -\fi% -\ifdim\multitableparskip=0pt -\global\multitableparskip=\multitablelinespace -\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller - %% than skip between lines in the table. -\fi} - - -\message{indexing,} -% Index generation facilities - -% Define \newwrite to be identical to plain tex's \newwrite -% except not \outer, so it can be used within \newindex. -{\catcode`\@=11 -\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}} - -% \newindex {foo} defines an index named foo. -% It automatically defines \fooindex such that -% \fooindex ...rest of line... puts an entry in the index foo. -% It also defines \fooindfile to be the number of the output channel for -% the file that accumulates this index. The file's extension is foo. -% The name of an index should be no more than 2 characters long -% for the sake of vms. - -\def\newindex #1{ -\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file -\openout \csname#1indfile\endcsname \jobname.#1 % Open the file -\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex -\noexpand\doindex {#1}} -} - -% @defindex foo == \newindex{foo} - -\def\defindex{\parsearg\newindex} - -% Define @defcodeindex, like @defindex except put all entries in @code. - -\def\newcodeindex #1{ -\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file -\openout \csname#1indfile\endcsname \jobname.#1 % Open the file -\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex -\noexpand\docodeindex {#1}} -} - -\def\defcodeindex{\parsearg\newcodeindex} - -% @synindex foo bar makes index foo feed into index bar. -% Do this instead of @defindex foo if you don't want it as a separate index. -\def\synindex #1 #2 {% -\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname -\expandafter\let\csname#1indfile\endcsname=\synindexfoo -\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex -\noexpand\doindex {#2}}% -} - -% @syncodeindex foo bar similar, but put all entries made for index foo -% inside @code. -\def\syncodeindex #1 #2 {% -\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname -\expandafter\let\csname#1indfile\endcsname=\synindexfoo -\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex -\noexpand\docodeindex {#2}}% -} - -% Define \doindex, the driver for all \fooindex macros. -% Argument #1 is generated by the calling \fooindex macro, -% and it is "foo", the name of the index. - -% \doindex just uses \parsearg; it calls \doind for the actual work. -% This is because \doind is more useful to call from other macros. - -% There is also \dosubind {index}{topic}{subtopic} -% which makes an entry in a two-level index such as the operation index. - -\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer} -\def\singleindexer #1{\doind{\indexname}{#1}} - -% like the previous two, but they put @code around the argument. -\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer} -\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}} - -\def\indexdummies{% -% Take care of the plain tex accent commands. -\def\"{\realbackslash "}% -\def\`{\realbackslash `}% -\def\'{\realbackslash '}% -\def\^{\realbackslash ^}% -\def\~{\realbackslash ~}% -\def\={\realbackslash =}% -\def\b{\realbackslash b}% -\def\c{\realbackslash c}% -\def\d{\realbackslash d}% -\def\u{\realbackslash u}% -\def\v{\realbackslash v}% -\def\H{\realbackslash H}% -% Take care of the plain tex special European modified letters. -\def\oe{\realbackslash oe}% -\def\ae{\realbackslash ae}% -\def\aa{\realbackslash aa}% -\def\OE{\realbackslash OE}% -\def\AE{\realbackslash AE}% -\def\AA{\realbackslash AA}% -\def\o{\realbackslash o}% -\def\O{\realbackslash O}% -\def\l{\realbackslash l}% -\def\L{\realbackslash L}% -\def\ss{\realbackslash ss}% -% Take care of texinfo commands likely to appear in an index entry. -% (Must be a way to avoid doing expansion at all, and thus not have to -% laboriously list every single command here.) -\def\@{@}% will be @@ when we switch to @ as escape char. -%\let\{ = \lbracecmd -%\let\} = \rbracecmd -\def\_{{\realbackslash _}}% -\def\w{\realbackslash w }% -\def\bf{\realbackslash bf }% -%\def\rm{\realbackslash rm }% -\def\sl{\realbackslash sl }% -\def\sf{\realbackslash sf}% -\def\tt{\realbackslash tt}% -\def\gtr{\realbackslash gtr}% -\def\less{\realbackslash less}% -\def\hat{\realbackslash hat}% -%\def\char{\realbackslash char}% -\def\TeX{\realbackslash TeX}% -\def\dots{\realbackslash dots }% -\def\copyright{\realbackslash copyright }% -\def\tclose##1{\realbackslash tclose {##1}}% -\def\code##1{\realbackslash code {##1}}% -\def\dotless##1{\realbackslash dotless {##1}}% -\def\samp##1{\realbackslash samp {##1}}% -\def\,##1{\realbackslash ,{##1}}% -\def\t##1{\realbackslash t {##1}}% -\def\r##1{\realbackslash r {##1}}% -\def\i##1{\realbackslash i {##1}}% -\def\b##1{\realbackslash b {##1}}% -\def\cite##1{\realbackslash cite {##1}}% -\def\key##1{\realbackslash key {##1}}% -\def\file##1{\realbackslash file {##1}}% -\def\var##1{\realbackslash var {##1}}% -\def\kbd##1{\realbackslash kbd {##1}}% -\def\dfn##1{\realbackslash dfn {##1}}% -\def\emph##1{\realbackslash emph {##1}}% -\unsepspaces -} - -% If an index command is used in an @example environment, any spaces -% therein should become regular spaces in the raw index file, not the -% expansion of \tie (\\leavevmode \penalty \@M \ ). -{\obeyspaces - \gdef\unsepspaces{\obeyspaces\let =\space}} - -% \indexnofonts no-ops all font-change commands. -% This is used when outputting the strings to sort the index by. -\def\indexdummyfont#1{#1} -\def\indexdummytex{TeX} -\def\indexdummydots{...} - -\def\indexnofonts{% -% Just ignore accents. -\let\,=\indexdummyfont -\let\"=\indexdummyfont -\let\`=\indexdummyfont -\let\'=\indexdummyfont -\let\^=\indexdummyfont -\let\~=\indexdummyfont -\let\==\indexdummyfont -\let\b=\indexdummyfont -\let\c=\indexdummyfont -\let\d=\indexdummyfont -\let\u=\indexdummyfont -\let\v=\indexdummyfont -\let\H=\indexdummyfont -\let\dotless=\indexdummyfont -% Take care of the plain tex special European modified letters. -\def\oe{oe}% -\def\ae{ae}% -\def\aa{aa}% -\def\OE{OE}% -\def\AE{AE}% -\def\AA{AA}% -\def\o{o}% -\def\O{O}% -\def\l{l}% -\def\L{L}% -\def\ss{ss}% -\let\w=\indexdummyfont -\let\t=\indexdummyfont -\let\r=\indexdummyfont -\let\i=\indexdummyfont -\let\b=\indexdummyfont -\let\emph=\indexdummyfont -\let\strong=\indexdummyfont -\let\cite=\indexdummyfont -\let\sc=\indexdummyfont -%Don't no-op \tt, since it isn't a user-level command -% and is used in the definitions of the active chars like <, >, |... -%\let\tt=\indexdummyfont -\let\tclose=\indexdummyfont -\let\code=\indexdummyfont -\let\file=\indexdummyfont -\let\samp=\indexdummyfont -\let\kbd=\indexdummyfont -\let\key=\indexdummyfont -\let\var=\indexdummyfont -\let\TeX=\indexdummytex -\let\dots=\indexdummydots -\def\@{@}% -} - -% To define \realbackslash, we must make \ not be an escape. -% We must first make another character (@) an escape -% so we do not become unable to do a definition. - -{\catcode`\@=0 \catcode`\\=\other -@gdef@realbackslash{\}} - -\let\indexbackslash=0 %overridden during \printindex. - -\let\SETmarginindex=\relax %initialize! -% workhorse for all \fooindexes -% #1 is name of index, #2 is stuff to put there -\def\doind #1#2{% - % Put the index entry in the margin if desired. - \ifx\SETmarginindex\relax\else - \insert\margin{\hbox{\vrule height8pt depth3pt width0pt #2}}% - \fi - {% - \count255=\lastpenalty - {% - \indexdummies % Must do this here, since \bf, etc expand at this stage - \escapechar=`\\ - {% - \let\folio=0 % We will expand all macros now EXCEPT \folio. - \def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now - % so it will be output as is; and it will print as backslash. - % - % First process the index-string with all font commands turned off - % to get the string to sort by. - {\indexnofonts \xdef\indexsorttmp{#2}}% - % - % Now produce the complete index entry, with both the sort key and the - % original text, including any font commands. - \toks0 = {#2}% - \edef\temp{% - \write\csname#1indfile\endcsname{% - \realbackslash entry{\indexsorttmp}{\folio}{\the\toks0}}% - }% - \temp - }% - }% - \penalty\count255 - }% -} - -\def\dosubind #1#2#3{% -{\count10=\lastpenalty % -{\indexdummies % Must do this here, since \bf, etc expand at this stage -\escapechar=`\\% -{\let\folio=0% -\def\rawbackslashxx{\indexbackslash}% -% -% Now process the index-string once, with all font commands turned off, -% to get the string to sort the index by. -{\indexnofonts -\xdef\temp1{#2 #3}% -}% -% Now produce the complete index entry. We process the index-string again, -% this time with font commands expanded, to get what to print in the index. -\edef\temp{% -\write \csname#1indfile\endcsname{% -\realbackslash entry {\temp1}{\folio}{#2}{#3}}}% -\temp }% -}\penalty\count10}} - -% The index entry written in the file actually looks like -% \entry {sortstring}{page}{topic} -% or -% \entry {sortstring}{page}{topic}{subtopic} -% The texindex program reads in these files and writes files -% containing these kinds of lines: -% \initial {c} -% before the first topic whose initial is c -% \entry {topic}{pagelist} -% for a topic that is used without subtopics -% \primary {topic} -% for the beginning of a topic that is used with subtopics -% \secondary {subtopic}{pagelist} -% for each subtopic. - -% Define the user-accessible indexing commands -% @findex, @vindex, @kindex, @cindex. - -\def\findex {\fnindex} -\def\kindex {\kyindex} -\def\cindex {\cpindex} -\def\vindex {\vrindex} -\def\tindex {\tpindex} -\def\pindex {\pgindex} - -\def\cindexsub {\begingroup\obeylines\cindexsub} -{\obeylines % -\gdef\cindexsub "#1" #2^^M{\endgroup % -\dosubind{cp}{#2}{#1}}} - -% Define the macros used in formatting output of the sorted index material. - -% This is what you call to cause a particular index to get printed. -% Write -% @unnumbered Function Index -% @printindex fn - -\def\printindex{\parsearg\doprintindex} - -\def\doprintindex#1{\begingroup - \dobreak \chapheadingskip{10000}% - % - \indexfonts \rm - \tolerance = 9500 - \indexbreaks - \def\indexbackslash{\rawbackslashxx}% - % Index files are almost Texinfo source, but we use \ as the escape - % character. It would be better to use @, but that's too big a change - % to make right now. - \catcode`\\ = 0 - \catcode`\@ = 11 - \escapechar = `\\ - \begindoublecolumns - % - % See if the index file exists and is nonempty. - \openin 1 \jobname.#1s - \ifeof 1 - % \enddoublecolumns gets confused if there is no text in the index, - % and it loses the chapter title and the aux file entries for the - % index. The easiest way to prevent this problem is to make sure - % there is some text. - (Index is nonexistent) - \else - % - % If the index file exists but is empty, then \openin leaves \ifeof - % false. We have to make TeX try to read something from the file, so - % it can discover if there is anything in it. - \read 1 to \temp - \ifeof 1 - (Index is empty) - \else - \input \jobname.#1s - \fi - \fi - \closein 1 - \enddoublecolumns -\endgroup} - -% These macros are used by the sorted index file itself. -% Change them to control the appearance of the index. - -% Same as \bigskipamount except no shrink. -% \balancecolumns gets confused if there is any shrink. -\newskip\initialskipamount \initialskipamount 12pt plus4pt - -\def\initial #1{% -{\let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt -\ifdim\lastskip<\initialskipamount -\removelastskip \penalty-200 \vskip \initialskipamount\fi -\line{\secbf#1\hfill}\kern 2pt\penalty10000}} - -% This typesets a paragraph consisting of #1, dot leaders, and then #2 -% flush to the right margin. It is used for index and table of contents -% entries. The paragraph is indented by \leftskip. -% -\def\entry #1#2{\begingroup - % - % Start a new paragraph if necessary, so our assignments below can't - % affect previous text. - \par - % - % Do not fill out the last line with white space. - \parfillskip = 0in - % - % No extra space above this paragraph. - \parskip = 0in - % - % Do not prefer a separate line ending with a hyphen to fewer lines. - \finalhyphendemerits = 0 - % - % \hangindent is only relevant when the entry text and page number - % don't both fit on one line. In that case, bob suggests starting the - % dots pretty far over on the line. Unfortunately, a large - % indentation looks wrong when the entry text itself is broken across - % lines. So we use a small indentation and put up with long leaders. - % - % \hangafter is reset to 1 (which is the value we want) at the start - % of each paragraph, so we need not do anything with that. - \hangindent=2em - % - % When the entry text needs to be broken, just fill out the first line - % with blank space. - \rightskip = 0pt plus1fil - % - % Start a ``paragraph'' for the index entry so the line breaking - % parameters we've set above will have an effect. - \noindent - % - % Insert the text of the index entry. TeX will do line-breaking on it. - #1% - % The following is kludged to not output a line of dots in the index if - % there are no page numbers. The next person who breaks this will be - % cursed by a Unix daemon. - \def\tempa{{\rm }}% - \def\tempb{#2}% - \edef\tempc{\tempa}% - \edef\tempd{\tempb}% - \ifx\tempc\tempd\ \else% - % - % If we must, put the page number on a line of its own, and fill out - % this line with blank space. (The \hfil is overwhelmed with the - % fill leaders glue in \indexdotfill if the page number does fit.) - \hfil\penalty50 - \null\nobreak\indexdotfill % Have leaders before the page number. - % - % The `\ ' here is removed by the implicit \unskip that TeX does as - % part of (the primitive) \par. Without it, a spurious underfull - % \hbox ensues. - \ #2% The page number ends the paragraph. - \fi% - \par -\endgroup} - -% Like \dotfill except takes at least 1 em. -\def\indexdotfill{\cleaders - \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \mkern1.5mu$}\hskip 1em plus 1fill} - -\def\primary #1{\line{#1\hfil}} - -\newskip\secondaryindent \secondaryindent=0.5cm - -\def\secondary #1#2{ -{\parfillskip=0in \parskip=0in -\hangindent =1in \hangafter=1 -\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\par -}} - -% Define two-column mode, which we use to typeset indexes. -% Adapted from the TeXbook, page 416, which is to say, -% the manmac.tex format used to print the TeXbook itself. -\catcode`\@=11 - -\newbox\partialpage -\newdimen\doublecolumnhsize - -\def\begindoublecolumns{\begingroup % ended by \enddoublecolumns - % Grab any single-column material above us. - \output = {\global\setbox\partialpage - =\vbox{\unvbox255\kern -\topskip \kern \baselineskip}}% - \eject - % - % Now switch to the double-column output routine. - \output={\doublecolumnout}% - % - % Change the page size parameters. We could do this once outside this - % routine, in each of @smallbook, @afourpaper, and the default 8.5x11 - % format, but then we repeat the same computation. Repeating a couple - % of assignments once per index is clearly meaningless for the - % execution time, so we may as well do it once. - % - % First we halve the line length, less a little for the gutter between - % the columns. We compute the gutter based on the line length, so it - % changes automatically with the paper format. The magic constant - % below is chosen so that the gutter has the same value (well, +- < - % 1pt) as it did when we hard-coded it. - % - % We put the result in a separate register, \doublecolumhsize, so we - % can restore it in \pagesofar, after \hsize itself has (potentially) - % been clobbered. - % - \doublecolumnhsize = \hsize - \advance\doublecolumnhsize by -.04154\hsize - \divide\doublecolumnhsize by 2 - \hsize = \doublecolumnhsize - % - % Double the \vsize as well. (We don't need a separate register here, - % since nobody clobbers \vsize.) - \vsize = 2\vsize -} -\def\doublecolumnout{% - \splittopskip=\topskip \splitmaxdepth=\maxdepth - % Get the available space for the double columns -- the normal - % (undoubled) page height minus any material left over from the - % previous page. - \dimen@=\pageheight \advance\dimen@ by-\ht\partialpage - % box0 will be the left-hand column, box1 the right. - \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@ - \onepageout\pagesofar - \unvbox255 \penalty\outputpenalty -} -\def\pagesofar{% - % The contents of the output page -- any previous material, - % followed by the two boxes we just split. - \unvbox\partialpage - \hsize = \doublecolumnhsize - \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}% -} -\def\enddoublecolumns{% - \output={\balancecolumns}\eject % split what we have - \endgroup - % Back to normal single-column typesetting, but take account of the - % fact that we just accumulated some stuff on the output page. - \pagegoal=\vsize -} -\def\balancecolumns{% - % Called on the last page of the double column material. - \setbox0=\vbox{\unvbox255}% - \dimen@ = \ht0 - \advance\dimen@ by \topskip - \advance\dimen@ by-\baselineskip - \divide\dimen@ by 2 - \splittopskip = \topskip - % Loop until we get a decent breakpoint. - {\vbadness=10000 \loop \global\setbox3=\copy0 - \global\setbox1=\vsplit3 to\dimen@ - \ifdim\ht3>\dimen@ \global\advance\dimen@ by1pt \repeat}% - \setbox0=\vbox to\dimen@{\unvbox1}% - \setbox2=\vbox to\dimen@{\unvbox3}% - \pagesofar -} -\catcode `\@=\other - - -\message{sectioning,} -% Define chapters, sections, etc. - -\newcount \chapno -\newcount \secno \secno=0 -\newcount \subsecno \subsecno=0 -\newcount \subsubsecno \subsubsecno=0 - -% This counter is funny since it counts through charcodes of letters A, B, ... -\newcount \appendixno \appendixno = `\@ -\def\appendixletter{\char\the\appendixno} - -\newwrite \contentsfile -% This is called from \setfilename. -\def\opencontents{\openout \contentsfile = \jobname.toc} - -% Each @chapter defines this as the name of the chapter. -% page headings and footings can use it. @section does likewise - -\def\thischapter{} \def\thissection{} -\def\seccheck#1{\if \pageno<0 % -\errmessage{@#1 not allowed after generating table of contents}\fi -% -} - -\def\chapternofonts{% -\let\rawbackslash=\relax% -\let\frenchspacing=\relax% -\def\result{\realbackslash result} -\def\equiv{\realbackslash equiv} -\def\expansion{\realbackslash expansion} -\def\print{\realbackslash print} -\def\TeX{\realbackslash TeX} -\def\dots{\realbackslash dots} -\def\copyright{\realbackslash copyright} -\def\tt{\realbackslash tt} -\def\bf{\realbackslash bf } -\def\w{\realbackslash w} -\def\less{\realbackslash less} -\def\gtr{\realbackslash gtr} -\def\hat{\realbackslash hat} -\def\char{\realbackslash char} -\def\tclose##1{\realbackslash tclose {##1}} -\def\code##1{\realbackslash code {##1}} -\def\samp##1{\realbackslash samp {##1}} -\def\r##1{\realbackslash r {##1}} -\def\b##1{\realbackslash b {##1}} -\def\key##1{\realbackslash key {##1}} -\def\file##1{\realbackslash file {##1}} -\def\kbd##1{\realbackslash kbd {##1}} -% These are redefined because @smartitalic wouldn't work inside xdef. -\def\i##1{\realbackslash i {##1}} -\def\cite##1{\realbackslash cite {##1}} -\def\var##1{\realbackslash var {##1}} -\def\emph##1{\realbackslash emph {##1}} -\def\dfn##1{\realbackslash dfn {##1}} -} - -\newcount\absseclevel % used to calculate proper heading level -\newcount\secbase\secbase=0 % @raise/lowersections modify this count - -% @raisesections: treat @section as chapter, @subsection as section, etc. -\def\raisesections{\global\advance\secbase by -1} -\let\up=\raisesections % original BFox name - -% @lowersections: treat @chapter as section, @section as subsection, etc. -\def\lowersections{\global\advance\secbase by 1} -\let\down=\lowersections % original BFox name - -% Choose a numbered-heading macro -% #1 is heading level if unmodified by @raisesections or @lowersections -% #2 is text for heading -\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 -\ifcase\absseclevel - \chapterzzz{#2} -\or - \seczzz{#2} -\or - \numberedsubseczzz{#2} -\or - \numberedsubsubseczzz{#2} -\else - \ifnum \absseclevel<0 - \chapterzzz{#2} - \else - \numberedsubsubseczzz{#2} - \fi -\fi -} - -% like \numhead, but chooses appendix heading levels -\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 -\ifcase\absseclevel - \appendixzzz{#2} -\or - \appendixsectionzzz{#2} -\or - \appendixsubseczzz{#2} -\or - \appendixsubsubseczzz{#2} -\else - \ifnum \absseclevel<0 - \appendixzzz{#2} - \else - \appendixsubsubseczzz{#2} - \fi -\fi -} - -% like \numhead, but chooses numberless heading levels -\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 -\ifcase\absseclevel - \unnumberedzzz{#2} -\or - \unnumberedseczzz{#2} -\or - \unnumberedsubseczzz{#2} -\or - \unnumberedsubsubseczzz{#2} -\else - \ifnum \absseclevel<0 - \unnumberedzzz{#2} - \else - \unnumberedsubsubseczzz{#2} - \fi -\fi -} - - -\def\thischaptername{No Chapter Title} -\outer\def\chapter{\parsearg\chapteryyy} -\def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz -\def\chapterzzz #1{\seccheck{chapter}% -\secno=0 \subsecno=0 \subsubsecno=0 -\global\advance \chapno by 1 \message{\putwordChapter \the\chapno}% -\chapmacro {#1}{\the\chapno}% -\gdef\thissection{#1}% -\gdef\thischaptername{#1}% -% We don't substitute the actual chapter name into \thischapter -% because we don't want its macros evaluated now. -\xdef\thischapter{\putwordChapter{} \the\chapno: \noexpand\thischaptername}% -{\chapternofonts% -\edef\temp{{\realbackslash chapentry {#1}{\the\chapno}{\noexpand\folio}}}% -\escapechar=`\\% -\write \contentsfile \temp % -\donoderef % -\global\let\section = \numberedsec -\global\let\subsection = \numberedsubsec -\global\let\subsubsection = \numberedsubsubsec -}} - -\outer\def\appendix{\parsearg\appendixyyy} -\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz -\def\appendixzzz #1{\seccheck{appendix}% -\secno=0 \subsecno=0 \subsubsecno=0 -\global\advance \appendixno by 1 \message{Appendix \appendixletter}% -\chapmacro {#1}{\putwordAppendix{} \appendixletter}% -\gdef\thissection{#1}% -\gdef\thischaptername{#1}% -\xdef\thischapter{\putwordAppendix{} \appendixletter: \noexpand\thischaptername}% -{\chapternofonts% -\edef\temp{{\realbackslash chapentry - {#1}{\putwordAppendix{} \appendixletter}{\noexpand\folio}}}% -\escapechar=`\\% -\write \contentsfile \temp % -\appendixnoderef % -\global\let\section = \appendixsec -\global\let\subsection = \appendixsubsec -\global\let\subsubsection = \appendixsubsubsec -}} - -% @centerchap is like @unnumbered, but the heading is centered. -\outer\def\centerchap{\parsearg\centerchapyyy} -\def\centerchapyyy #1{{\let\unnumbchapmacro=\centerchapmacro \unnumberedyyy{#1}}} - -\outer\def\top{\parsearg\unnumberedyyy} -\outer\def\unnumbered{\parsearg\unnumberedyyy} -\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz -\def\unnumberedzzz #1{\seccheck{unnumbered}% -\secno=0 \subsecno=0 \subsubsecno=0 -% -% This used to be simply \message{#1}, but TeX fully expands the -% argument to \message. Therefore, if #1 contained @-commands, TeX -% expanded them. For example, in `@unnumbered The @cite{Book}', TeX -% expanded @cite (which turns out to cause errors because \cite is meant -% to be executed, not expanded). -% -% Anyway, we don't want the fully-expanded definition of @cite to appear -% as a result of the \message, we just want `@cite' itself. We use -% \the to achieve this: TeX expands \the only once, -% simply yielding the contents of the . -\toks0 = {#1}\message{(\the\toks0)}% -% -\unnumbchapmacro {#1}% -\gdef\thischapter{#1}\gdef\thissection{#1}% -{\chapternofonts% -\edef\temp{{\realbackslash unnumbchapentry {#1}{\noexpand\folio}}}% -\escapechar=`\\% -\write \contentsfile \temp % -\unnumbnoderef % -\global\let\section = \unnumberedsec -\global\let\subsection = \unnumberedsubsec -\global\let\subsubsection = \unnumberedsubsubsec -}} - -\outer\def\numberedsec{\parsearg\secyyy} -\def\secyyy #1{\numhead1{#1}} % normally calls seczzz -\def\seczzz #1{\seccheck{section}% -\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 % -\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}% -{\chapternofonts% -\edef\temp{{\realbackslash secentry % -{#1}{\the\chapno}{\the\secno}{\noexpand\folio}}}% -\escapechar=`\\% -\write \contentsfile \temp % -\donoderef % -\penalty 10000 % -}} - -\outer\def\appendixsection{\parsearg\appendixsecyyy} -\outer\def\appendixsec{\parsearg\appendixsecyyy} -\def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz -\def\appendixsectionzzz #1{\seccheck{appendixsection}% -\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 % -\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}% -{\chapternofonts% -\edef\temp{{\realbackslash secentry % -{#1}{\appendixletter}{\the\secno}{\noexpand\folio}}}% -\escapechar=`\\% -\write \contentsfile \temp % -\appendixnoderef % -\penalty 10000 % -}} - -\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy} -\def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz -\def\unnumberedseczzz #1{\seccheck{unnumberedsec}% -\plainsecheading {#1}\gdef\thissection{#1}% -{\chapternofonts% -\edef\temp{{\realbackslash unnumbsecentry{#1}{\noexpand\folio}}}% -\escapechar=`\\% -\write \contentsfile \temp % -\unnumbnoderef % -\penalty 10000 % -}} - -\outer\def\numberedsubsec{\parsearg\numberedsubsecyyy} -\def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz -\def\numberedsubseczzz #1{\seccheck{subsection}% -\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 % -\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}% -{\chapternofonts% -\edef\temp{{\realbackslash subsecentry % -{#1}{\the\chapno}{\the\secno}{\the\subsecno}{\noexpand\folio}}}% -\escapechar=`\\% -\write \contentsfile \temp % -\donoderef % -\penalty 10000 % -}} - -\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy} -\def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz -\def\appendixsubseczzz #1{\seccheck{appendixsubsec}% -\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 % -\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}% -{\chapternofonts% -\edef\temp{{\realbackslash subsecentry % -{#1}{\appendixletter}{\the\secno}{\the\subsecno}{\noexpand\folio}}}% -\escapechar=`\\% -\write \contentsfile \temp % -\appendixnoderef % -\penalty 10000 % -}} - -\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy} -\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz -\def\unnumberedsubseczzz #1{\seccheck{unnumberedsubsec}% -\plainsubsecheading {#1}\gdef\thissection{#1}% -{\chapternofonts% -\edef\temp{{\realbackslash unnumbsubsecentry{#1}{\noexpand\folio}}}% -\escapechar=`\\% -\write \contentsfile \temp % -\unnumbnoderef % -\penalty 10000 % -}} - -\outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy} -\def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz -\def\numberedsubsubseczzz #1{\seccheck{subsubsection}% -\gdef\thissection{#1}\global\advance \subsubsecno by 1 % -\subsubsecheading {#1} - {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}% -{\chapternofonts% -\edef\temp{{\realbackslash subsubsecentry % - {#1} - {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno} - {\noexpand\folio}}}% -\escapechar=`\\% -\write \contentsfile \temp % -\donoderef % -\penalty 10000 % -}} - -\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy} -\def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz -\def\appendixsubsubseczzz #1{\seccheck{appendixsubsubsec}% -\gdef\thissection{#1}\global\advance \subsubsecno by 1 % -\subsubsecheading {#1} - {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}% -{\chapternofonts% -\edef\temp{{\realbackslash subsubsecentry{#1}% - {\appendixletter} - {\the\secno}{\the\subsecno}{\the\subsubsecno}{\noexpand\folio}}}% -\escapechar=`\\% -\write \contentsfile \temp % -\appendixnoderef % -\penalty 10000 % -}} - -\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy} -\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz -\def\unnumberedsubsubseczzz #1{\seccheck{unnumberedsubsubsec}% -\plainsubsubsecheading {#1}\gdef\thissection{#1}% -{\chapternofonts% -\edef\temp{{\realbackslash unnumbsubsubsecentry{#1}{\noexpand\folio}}}% -\escapechar=`\\% -\write \contentsfile \temp % -\unnumbnoderef % -\penalty 10000 % -}} - -% These are variants which are not "outer", so they can appear in @ifinfo. -% Actually, they should now be obsolete; ordinary section commands should work. -\def\infotop{\parsearg\unnumberedzzz} -\def\infounnumbered{\parsearg\unnumberedzzz} -\def\infounnumberedsec{\parsearg\unnumberedseczzz} -\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz} -\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz} - -\def\infoappendix{\parsearg\appendixzzz} -\def\infoappendixsec{\parsearg\appendixseczzz} -\def\infoappendixsubsec{\parsearg\appendixsubseczzz} -\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz} - -\def\infochapter{\parsearg\chapterzzz} -\def\infosection{\parsearg\sectionzzz} -\def\infosubsection{\parsearg\subsectionzzz} -\def\infosubsubsection{\parsearg\subsubsectionzzz} - -% These macros control what the section commands do, according -% to what kind of chapter we are in (ordinary, appendix, or unnumbered). -% Define them by default for a numbered chapter. -\global\let\section = \numberedsec -\global\let\subsection = \numberedsubsec -\global\let\subsubsection = \numberedsubsubsec - -% Define @majorheading, @heading and @subheading - -% NOTE on use of \vbox for chapter headings, section headings, and -% such: -% 1) We use \vbox rather than the earlier \line to permit -% overlong headings to fold. -% 2) \hyphenpenalty is set to 10000 because hyphenation in a -% heading is obnoxious; this forbids it. -% 3) Likewise, headings look best if no \parindent is used, and -% if justification is not attempted. Hence \raggedright. - - -\def\majorheading{\parsearg\majorheadingzzz} -\def\majorheadingzzz #1{% -{\advance\chapheadingskip by 10pt \chapbreak }% -{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 - \parindent=0pt\raggedright - \rm #1\hfill}}\bigskip \par\penalty 200} - -\def\chapheading{\parsearg\chapheadingzzz} -\def\chapheadingzzz #1{\chapbreak % -{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 - \parindent=0pt\raggedright - \rm #1\hfill}}\bigskip \par\penalty 200} - -% @heading, @subheading, @subsubheading. -\def\heading{\parsearg\plainsecheading} -\def\subheading{\parsearg\plainsubsecheading} -\def\subsubheading{\parsearg\plainsubsubsecheading} - -% These macros generate a chapter, section, etc. heading only -% (including whitespace, linebreaking, etc. around it), -% given all the information in convenient, parsed form. - -%%% Args are the skip and penalty (usually negative) -\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi} - -\def\setchapterstyle #1 {\csname CHAPF#1\endcsname} - -%%% Define plain chapter starts, and page on/off switching for it -% Parameter controlling skip before chapter headings (if needed) - -\newskip\chapheadingskip - -\def\chapbreak{\dobreak \chapheadingskip {-4000}} -\def\chappager{\par\vfill\supereject} -\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi} - -\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname} - -\def\CHAPPAGoff{ -\global\let\contentsalignmacro = \chappager -\global\let\pchapsepmacro=\chapbreak -\global\let\pagealignmacro=\chappager} - -\def\CHAPPAGon{ -\global\let\contentsalignmacro = \chappager -\global\let\pchapsepmacro=\chappager -\global\let\pagealignmacro=\chappager -\global\def\HEADINGSon{\HEADINGSsingle}} - -\def\CHAPPAGodd{ -\global\let\contentsalignmacro = \chapoddpage -\global\let\pchapsepmacro=\chapoddpage -\global\let\pagealignmacro=\chapoddpage -\global\def\HEADINGSon{\HEADINGSdouble}} - -\CHAPPAGon - -\def\CHAPFplain{ -\global\let\chapmacro=\chfplain -\global\let\unnumbchapmacro=\unnchfplain -\global\let\centerchapmacro=\centerchfplain} - -% Plain chapter opening. -% #1 is the text, #2 the chapter number or empty if unnumbered. -\def\chfplain#1#2{% - \pchapsepmacro - {% - \chapfonts \rm - \def\chapnum{#2}% - \setbox0 = \hbox{#2\ifx\chapnum\empty\else\enspace\fi}% - \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright - \hangindent = \wd0 \centerparametersmaybe - \unhbox0 #1\par}% - }% - \nobreak\bigskip % no page break after a chapter title - \nobreak -} - -% Plain opening for unnumbered. -\def\unnchfplain#1{\chfplain{#1}{}} - -% @centerchap -- centered and unnumbered. -\let\centerparametersmaybe = \relax -\def\centerchfplain#1{{% - \def\centerparametersmaybe{% - \advance\rightskip by 3\rightskip - \leftskip = \rightskip - \parfillskip = 0pt - }% - \chfplain{#1}{}% -}} - -\CHAPFplain % The default - -\def\unnchfopen #1{% -\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 - \parindent=0pt\raggedright - \rm #1\hfill}}\bigskip \par\penalty 10000 % -} - -\def\chfopen #1#2{\chapoddpage {\chapfonts -\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}% -\par\penalty 5000 % -} - -\def\centerchfopen #1{% -\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 - \parindent=0pt - \hfill {\rm #1}\hfill}}\bigskip \par\penalty 10000 % -} - -\def\CHAPFopen{ -\global\let\chapmacro=\chfopen -\global\let\unnumbchapmacro=\unnchfopen -\global\let\centerchapmacro=\centerchfopen} - - -% Section titles. -\newskip\secheadingskip -\def\secheadingbreak{\dobreak \secheadingskip {-1000}} -\def\secheading#1#2#3{\sectionheading{sec}{#2.#3}{#1}} -\def\plainsecheading#1{\sectionheading{sec}{}{#1}} - -% Subsection titles. -\newskip \subsecheadingskip -\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}} -\def\subsecheading#1#2#3#4{\sectionheading{subsec}{#2.#3.#4}{#1}} -\def\plainsubsecheading#1{\sectionheading{subsec}{}{#1}} - -% Subsubsection titles. -\let\subsubsecheadingskip = \subsecheadingskip -\let\subsubsecheadingbreak = \subsecheadingbreak -\def\subsubsecheading#1#2#3#4#5{\sectionheading{subsubsec}{#2.#3.#4.#5}{#1}} -\def\plainsubsubsecheading#1{\sectionheading{subsubsec}{}{#1}} - - -% Print any size section title. -% -% #1 is the section type (sec/subsec/subsubsec), #2 is the section -% number (maybe empty), #3 the text. -\def\sectionheading#1#2#3{% - {% - \expandafter\advance\csname #1headingskip\endcsname by \parskip - \csname #1headingbreak\endcsname - }% - {% - % Switch to the right set of fonts. - \csname #1fonts\endcsname \rm - % - % Only insert the separating space if we have a section number. - \def\secnum{#2}% - \setbox0 = \hbox{#2\ifx\secnum\empty\else\enspace\fi}% - % - \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright - \hangindent = \wd0 % zero if no section number - \unhbox0 #3}% - }% - \ifdim\parskip<10pt \nobreak\kern10pt\nobreak\kern-\parskip\fi \nobreak -} - - -\message{toc printing,} -% Finish up the main text and prepare to read what we've written -% to \contentsfile. - -\newskip\contentsrightmargin \contentsrightmargin=1in -\def\startcontents#1{% - % If @setchapternewpage on, and @headings double, the contents should - % start on an odd page, unlike chapters. Thus, we maintain - % \contentsalignmacro in parallel with \pagealignmacro. - % From: Torbjorn Granlund - \contentsalignmacro - \immediate\closeout \contentsfile - \ifnum \pageno>0 - \pageno = -1 % Request roman numbered pages. - \fi - % Don't need to put `Contents' or `Short Contents' in the headline. - % It is abundantly clear what they are. - \unnumbchapmacro{#1}\def\thischapter{}% - \begingroup % Set up to handle contents files properly. - \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11 - \catcode`\^=7 % to see ^^e4 as \"a etc. juha@piuha.ydi.vtt.fi - \raggedbottom % Worry more about breakpoints than the bottom. - \advance\hsize by -\contentsrightmargin % Don't use the full line length. -} - - -% Normal (long) toc. -\outer\def\contents{% - \startcontents{\putwordTableofContents}% - \input \jobname.toc - \endgroup - \vfill \eject -} - -% And just the chapters. -\outer\def\summarycontents{% - \startcontents{\putwordShortContents}% - % - \let\chapentry = \shortchapentry - \let\unnumbchapentry = \shortunnumberedentry - % We want a true roman here for the page numbers. - \secfonts - \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl - \rm - \hyphenpenalty = 10000 - \advance\baselineskip by 1pt % Open it up a little. - \def\secentry ##1##2##3##4{} - \def\unnumbsecentry ##1##2{} - \def\subsecentry ##1##2##3##4##5{} - \def\unnumbsubsecentry ##1##2{} - \def\subsubsecentry ##1##2##3##4##5##6{} - \def\unnumbsubsubsecentry ##1##2{} - \input \jobname.toc - \endgroup - \vfill \eject -} -\let\shortcontents = \summarycontents - -% These macros generate individual entries in the table of contents. -% The first argument is the chapter or section name. -% The last argument is the page number. -% The arguments in between are the chapter number, section number, ... - -% Chapter-level things, for both the long and short contents. -\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}} - -% See comments in \dochapentry re vbox and related settings -\def\shortchapentry#1#2#3{% - \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno{#3}}% -} - -% Typeset the label for a chapter or appendix for the short contents. -% The arg is, e.g. `Appendix A' for an appendix, or `3' for a chapter. -% We could simplify the code here by writing out an \appendixentry -% command in the toc file for appendices, instead of using \chapentry -% for both, but it doesn't seem worth it. -\setbox0 = \hbox{\shortcontrm \putwordAppendix } -\newdimen\shortappendixwidth \shortappendixwidth = \wd0 - -\def\shortchaplabel#1{% - % We typeset #1 in a box of constant width, regardless of the text of - % #1, so the chapter titles will come out aligned. - \setbox0 = \hbox{#1}% - \dimen0 = \ifdim\wd0 > \shortappendixwidth \shortappendixwidth \else 0pt \fi - % - % This space should be plenty, since a single number is .5em, and the - % widest letter (M) is 1em, at least in the Computer Modern fonts. - % (This space doesn't include the extra space that gets added after - % the label; that gets put in by \shortchapentry above.) - \advance\dimen0 by 1.1em - \hbox to \dimen0{#1\hfil}% -} - -\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}} -\def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno{#2}}} - -% Sections. -\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}} -\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}} - -% Subsections. -\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}} -\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}} - -% And subsubsections. -\def\subsubsecentry#1#2#3#4#5#6{% - \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}} -\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}} - -% This parameter controls the indentation of the various levels. -\newdimen\tocindent \tocindent = 3pc - -% Now for the actual typesetting. In all these, #1 is the text and #2 is the -% page number. -% -% If the toc has to be broken over pages, we want it to be at chapters -% if at all possible; hence the \penalty. -\def\dochapentry#1#2{% - \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip - \begingroup - \chapentryfonts - \tocentry{#1}{\dopageno{#2}}% - \endgroup - \nobreak\vskip .25\baselineskip plus.1\baselineskip -} - -\def\dosecentry#1#2{\begingroup - \secentryfonts \leftskip=\tocindent - \tocentry{#1}{\dopageno{#2}}% -\endgroup} - -\def\dosubsecentry#1#2{\begingroup - \subsecentryfonts \leftskip=2\tocindent - \tocentry{#1}{\dopageno{#2}}% -\endgroup} - -\def\dosubsubsecentry#1#2{\begingroup - \subsubsecentryfonts \leftskip=3\tocindent - \tocentry{#1}{\dopageno{#2}}% -\endgroup} - -% Final typesetting of a toc entry; we use the same \entry macro as for -% the index entries, but we want to suppress hyphenation here. (We -% can't do that in the \entry macro, since index entries might consist -% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.) -% -% \turnoffactive is for the sake of @" used for umlauts. -\def\tocentry#1#2{\begingroup - \vskip 0pt plus1pt % allow a little stretch for the sake of nice page breaks - \entry{\turnoffactive #1}{\turnoffactive #2}% -\endgroup} - -% Space between chapter (or whatever) number and the title. -\def\labelspace{\hskip1em \relax} - -\def\dopageno#1{{\rm #1}} -\def\doshortpageno#1{{\rm #1}} - -\def\chapentryfonts{\secfonts \rm} -\def\secentryfonts{\textfonts} -\let\subsecentryfonts = \textfonts -\let\subsubsecentryfonts = \textfonts - - -\message{environments,} - -% Since these characters are used in examples, it should be an even number of -% \tt widths. Each \tt character is 1en, so two makes it 1em. -% Furthermore, these definitions must come after we define our fonts. -\newbox\dblarrowbox \newbox\longdblarrowbox -\newbox\pushcharbox \newbox\bullbox -\newbox\equivbox \newbox\errorbox - -%{\tentt -%\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil} -%\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil} -%\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil} -%\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil} -% Adapted from the manmac format (p.420 of TeXbook) -%\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex -% depth .1ex\hfil} -%} - -% @point{}, @result{}, @expansion{}, @print{}, @equiv{}. -\def\point{$\star$} -\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}} -\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}} -\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}} -\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}} - -% Adapted from the TeXbook's \boxit. -{\tentt \global\dimen0 = 3em}% Width of the box. -\dimen2 = .55pt % Thickness of rules -% The text. (`r' is open on the right, `e' somewhat less so on the left.) -\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt} - -\global\setbox\errorbox=\hbox to \dimen0{\hfil - \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. - \advance\hsize by -2\dimen2 % Rules. - \vbox{ - \hrule height\dimen2 - \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. - \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. - \kern3pt\vrule width\dimen2}% Space to right. - \hrule height\dimen2} - \hfil} - -% The @error{} command. -\def\error{\leavevmode\lower.7ex\copy\errorbox} - -% @tex ... @end tex escapes into raw Tex temporarily. -% One exception: @ is still an escape character, so that @end tex works. -% But \@ or @@ will get a plain tex @ character. - -\def\tex{\begingroup -\catcode `\\=0 \catcode `\{=1 \catcode `\}=2 -\catcode `\$=3 \catcode `\&=4 \catcode `\#=6 -\catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie -\catcode `\%=14 -\catcode 43=12 % plus -\catcode`\"=12 -\catcode`\==12 -\catcode`\|=12 -\catcode`\<=12 -\catcode`\>=12 -\escapechar=`\\ -% -\let\,=\ptexcomma -\let\~=\ptextilde -\let\{=\ptexlbrace -\let\}=\ptexrbrace -\let\.=\ptexdot -\let\*=\ptexstar -\let\dots=\ptexdots -\def\endldots{\mathinner{\ldots\ldots\ldots\ldots}} -\def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi} -\def\@{@}% -\let\bullet=\ptexbullet -\let\b=\ptexb \let\c=\ptexc \let\i=\ptexi \let\t=\ptext -% -\let\Etex=\endgroup} - -% Define @lisp ... @endlisp. -% @lisp does a \begingroup so it can rebind things, -% including the definition of @endlisp (which normally is erroneous). - -% Amount to narrow the margins by for @lisp. -\newskip\lispnarrowing \lispnarrowing=0.4in - -% This is the definition that ^^M gets inside @lisp, @example, and other -% such environments. \null is better than a space, since it doesn't -% have any width. -\def\lisppar{\null\endgraf} - -% Make each space character in the input produce a normal interword -% space in the output. Don't allow a line break at this space, as this -% is used only in environments like @example, where each line of input -% should produce a line of output anyway. -% -{\obeyspaces % -\gdef\sepspaces{\obeyspaces\let =\tie}} - -% Define \obeyedspace to be our active space, whatever it is. This is -% for use in \parsearg. -{\sepspaces% -\global\let\obeyedspace= } - -% This space is always present above and below environments. -\newskip\envskipamount \envskipamount = 0pt - -% Make spacing and below environment symmetrical. We use \parskip here -% to help in doing that, since in @example-like environments \parskip -% is reset to zero; thus the \afterenvbreak inserts no space -- but the -% start of the next paragraph will insert \parskip -% -\def\aboveenvbreak{{\advance\envskipamount by \parskip -\endgraf \ifdim\lastskip<\envskipamount -\removelastskip \penalty-50 \vskip\envskipamount \fi}} - -\let\afterenvbreak = \aboveenvbreak - -% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins. -\let\nonarrowing=\relax - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% \cartouche: draw rectangle w/rounded corners around argument -\font\circle=lcircle10 -\newdimen\circthick -\newdimen\cartouter\newdimen\cartinner -\newskip\normbskip\newskip\normpskip\newskip\normlskip -\circthick=\fontdimen8\circle -% -\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth -\def\ctr{{\hskip 6pt\circle\char'010}} -\def\cbl{{\circle\char'012\hskip -6pt}} -\def\cbr{{\hskip 6pt\circle\char'011}} -\def\carttop{\hbox to \cartouter{\hskip\lskip - \ctl\leaders\hrule height\circthick\hfil\ctr - \hskip\rskip}} -\def\cartbot{\hbox to \cartouter{\hskip\lskip - \cbl\leaders\hrule height\circthick\hfil\cbr - \hskip\rskip}} -% -\newskip\lskip\newskip\rskip - -\long\def\cartouche{% -\begingroup - \lskip=\leftskip \rskip=\rightskip - \leftskip=0pt\rightskip=0pt %we want these *outside*. - \cartinner=\hsize \advance\cartinner by-\lskip - \advance\cartinner by-\rskip - \cartouter=\hsize - \advance\cartouter by 18pt % allow for 3pt kerns on either -% side, and for 6pt waste from -% each corner char - \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip - % Flag to tell @lisp, etc., not to narrow margin. - \let\nonarrowing=\comment - \vbox\bgroup - \baselineskip=0pt\parskip=0pt\lineskip=0pt - \carttop - \hbox\bgroup - \hskip\lskip - \vrule\kern3pt - \vbox\bgroup - \hsize=\cartinner - \kern3pt - \begingroup - \baselineskip=\normbskip - \lineskip=\normlskip - \parskip=\normpskip - \vskip -\parskip -\def\Ecartouche{% - \endgroup - \kern3pt - \egroup - \kern3pt\vrule - \hskip\rskip - \egroup - \cartbot - \egroup -\endgroup -}} - - -% This macro is called at the beginning of all the @example variants, -% inside a group. -\def\nonfillstart{% - \aboveenvbreak - \inENV % This group ends at the end of the body - \hfuzz = 12pt % Don't be fussy - \sepspaces % Make spaces be word-separators rather than space tokens. - \singlespace - \let\par = \lisppar % don't ignore blank lines - \obeylines % each line of input is a line of output - \parskip = 0pt - \parindent = 0pt - \emergencystretch = 0pt % don't try to avoid overfull boxes - % @cartouche defines \nonarrowing to inhibit narrowing - % at next level down. - \ifx\nonarrowing\relax - \advance \leftskip by \lispnarrowing - \exdentamount=\lispnarrowing - \let\exdent=\nofillexdent - \let\nonarrowing=\relax - \fi -} - -% To ending an @example-like environment, we first end the paragraph -% (via \afterenvbreak's vertical glue), and then the group. That way we -% keep the zero \parskip that the environments set -- \parskip glue -% will be inserted at the beginning of the next paragraph in the -% document, after the environment. -% -\def\nonfillfinish{\afterenvbreak\endgroup}% - -% This macro is -\def\lisp{\begingroup - \nonfillstart - \let\Elisp = \nonfillfinish - \tt - \rawbackslash % have \ input char produce \ char from current font - \gobble -} - -% Define the \E... control sequence only if we are inside the -% environment, so the error checking in \end will work. -% -% We must call \lisp last in the definition, since it reads the -% return following the @example (or whatever) command. -% -\def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp} -\def\smallexample{\begingroup \def\Esmallexample{\nonfillfinish\endgroup}\lisp} -\def\smalllisp{\begingroup \def\Esmalllisp{\nonfillfinish\endgroup}\lisp} - -% @smallexample and @smalllisp. This is not used unless the @smallbook -% command is given. Originally contributed by Pavel@xerox. -% -\def\smalllispx{\begingroup - \nonfillstart - \let\Esmalllisp = \nonfillfinish - \let\Esmallexample = \nonfillfinish - % - % Smaller fonts for small examples. - \indexfonts \tt - \rawbackslash % make \ output the \ character from the current font (tt) - \gobble -} - -% This is @display; same as @lisp except use roman font. -% -\def\display{\begingroup - \nonfillstart - \let\Edisplay = \nonfillfinish - \gobble -} - -% This is @format; same as @display except don't narrow margins. -% -\def\format{\begingroup - \let\nonarrowing = t - \nonfillstart - \let\Eformat = \nonfillfinish - \gobble -} - -% @flushleft (same as @format) and @flushright. -% -\def\flushleft{\begingroup - \let\nonarrowing = t - \nonfillstart - \let\Eflushleft = \nonfillfinish - \gobble -} -\def\flushright{\begingroup - \let\nonarrowing = t - \nonfillstart - \let\Eflushright = \nonfillfinish - \advance\leftskip by 0pt plus 1fill - \gobble} - -% @quotation does normal linebreaking (hence we can't use \nonfillstart) -% and narrows the margins. -% -\def\quotation{% - \begingroup\inENV %This group ends at the end of the @quotation body - {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip - \singlespace - \parindent=0pt - % We have retained a nonzero parskip for the environment, since we're - % doing normal filling. So to avoid extra space below the environment... - \def\Equotation{\parskip = 0pt \nonfillfinish}% - % - % @cartouche defines \nonarrowing to inhibit narrowing at next level down. - \ifx\nonarrowing\relax - \advance\leftskip by \lispnarrowing - \advance\rightskip by \lispnarrowing - \exdentamount = \lispnarrowing - \let\nonarrowing = \relax - \fi -} - -\message{defuns,} -% Define formatter for defuns -% First, allow user to change definition object font (\df) internally -\def\setdeffont #1 {\csname DEF#1\endcsname} - -\newskip\defbodyindent \defbodyindent=.4in -\newskip\defargsindent \defargsindent=50pt -\newskip\deftypemargin \deftypemargin=12pt -\newskip\deflastargmargin \deflastargmargin=18pt - -\newcount\parencount -% define \functionparens, which makes ( and ) and & do special things. -% \functionparens affects the group it is contained in. -\def\activeparens{% -\catcode`\(=\active \catcode`\)=\active \catcode`\&=\active -\catcode`\[=\active \catcode`\]=\active} - -% Make control sequences which act like normal parenthesis chars. -\let\lparen = ( \let\rparen = ) - -{\activeparens % Now, smart parens don't turn on until &foo (see \amprm) - -% Be sure that we always have a definition for `(', etc. For example, -% if the fn name has parens in it, \boldbrax will not be in effect yet, -% so TeX would otherwise complain about undefined control sequence. -\global\let(=\lparen \global\let)=\rparen -\global\let[=\lbrack \global\let]=\rbrack - -\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 } -\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} -% This is used to turn on special parens -% but make & act ordinary (given that it's active). -\gdef\boldbraxnoamp{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb\let&=\ampnr} - -% Definitions of (, ) and & used in args for functions. -% This is the definition of ( outside of all parentheses. -\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested % -\global\advance\parencount by 1 } -% -% This is the definition of ( when already inside a level of parens. -\gdef\opnested{\char`\(\global\advance\parencount by 1 } -% -\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0. -% also in that case restore the outer-level definition of (. -\ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi -\global\advance \parencount by -1 } -% If we encounter &foo, then turn on ()-hacking afterwards -\gdef\amprm#1 {{\rm\}\let(=\oprm \let)=\clrm\ } -% -\gdef\normalparens{\boldbrax\let&=\ampnr} -} % End of definition inside \activeparens -%% These parens (in \boldbrax) actually are a little bolder than the -%% contained text. This is especially needed for [ and ] -\def\opnr{{\sf\char`\(}} \def\clnr{{\sf\char`\)}} \def\ampnr{\&} -\def\lbrb{{\bf\char`\[}} \def\rbrb{{\bf\char`\]}} - -% First, defname, which formats the header line itself. -% #1 should be the function name. -% #2 should be the type of definition, such as "Function". - -\def\defname #1#2{% -% Get the values of \leftskip and \rightskip as they were -% outside the @def... -\dimen2=\leftskip -\advance\dimen2 by -\defbodyindent -\dimen3=\rightskip -\advance\dimen3 by -\defbodyindent -\noindent % -\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}% -\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line -\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations -\parshape 2 0in \dimen0 \defargsindent \dimen1 % -% Now output arg 2 ("Function" or some such) -% ending at \deftypemargin from the right margin, -% but stuck inside a box of width 0 so it does not interfere with linebreaking -{% Adjust \hsize to exclude the ambient margins, -% so that \rightline will obey them. -\advance \hsize by -\dimen2 \advance \hsize by -\dimen3 -\rlap{\rightline{{\rm #2}\hskip \deftypemargin}}}% -% Make all lines underfull and no complaints: -\tolerance=10000 \hbadness=10000 -\advance\leftskip by -\defbodyindent -\exdentamount=\defbodyindent -{\df #1}\enskip % Generate function name -} - -% Actually process the body of a definition -% #1 should be the terminating control sequence, such as \Edefun. -% #2 should be the "another name" control sequence, such as \defunx. -% #3 should be the control sequence that actually processes the header, -% such as \defunheader. - -\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody -\medbreak % -% Define the end token that this defining construct specifies -% so that it will exit this group. -\def#1{\endgraf\endgroup\medbreak}% -\def#2{\begingroup\obeylines\activeparens\spacesplit#3}% -\parindent=0in -\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent -\exdentamount=\defbodyindent -\begingroup % -\catcode 61=\active % 61 is `=' -\obeylines\activeparens\spacesplit#3} - -\def\defmethparsebody #1#2#3#4 {\begingroup\inENV % -\medbreak % -% Define the end token that this defining construct specifies -% so that it will exit this group. -\def#1{\endgraf\endgroup\medbreak}% -\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}% -\parindent=0in -\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent -\exdentamount=\defbodyindent -\begingroup\obeylines\activeparens\spacesplit{#3{#4}}} - -\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV % -\medbreak % -% Define the end token that this defining construct specifies -% so that it will exit this group. -\def#1{\endgraf\endgroup\medbreak}% -\def#2##1 ##2 {\def#4{##1}% -\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}% -\parindent=0in -\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent -\exdentamount=\defbodyindent -\begingroup\obeylines\activeparens\spacesplit{#3{#5}}} - -% These parsing functions are similar to the preceding ones -% except that they do not make parens into active characters. -% These are used for "variables" since they have no arguments. - -\def\defvarparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody -\medbreak % -% Define the end token that this defining construct specifies -% so that it will exit this group. -\def#1{\endgraf\endgroup\medbreak}% -\def#2{\begingroup\obeylines\spacesplit#3}% -\parindent=0in -\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent -\exdentamount=\defbodyindent -\begingroup % -\catcode 61=\active % -\obeylines\spacesplit#3} - -% This is used for \def{tp,vr}parsebody. It could probably be used for -% some of the others, too, with some judicious conditionals. -% -\def\parsebodycommon#1#2#3{% - \begingroup\inENV % - \medbreak % - % Define the end token that this defining construct specifies - % so that it will exit this group. - \def#1{\endgraf\endgroup\medbreak}% - \def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}% - \parindent=0in - \advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent - \exdentamount=\defbodyindent - \begingroup\obeylines -} - -\def\defvrparsebody#1#2#3#4 {% - \parsebodycommon{#1}{#2}{#3}% - \spacesplit{#3{#4}}% -} - -% This loses on `@deftp {Data Type} {struct termios}' -- it thinks the -% type is just `struct', because we lose the braces in `{struct -% termios}' when \spacesplit reads its undelimited argument. Sigh. -% \let\deftpparsebody=\defvrparsebody -% -% So, to get around this, we put \empty in with the type name. That -% way, TeX won't find exactly `{...}' as an undelimited argument, and -% won't strip off the braces. -% -\def\deftpparsebody #1#2#3#4 {% - \parsebodycommon{#1}{#2}{#3}% - \spacesplit{\parsetpheaderline{#3{#4}}}\empty -} - -% Fine, but then we have to eventually remove the \empty *and* the -% braces (if any). That's what this does, putting the result in \tptemp. -% -\def\removeemptybraces\empty#1\relax{\def\tptemp{#1}}% - -% After \spacesplit has done its work, this is called -- #1 is the final -% thing to call, #2 the type name (which starts with \empty), and #3 -% (which might be empty) the arguments. -% -\def\parsetpheaderline#1#2#3{% - \removeemptybraces#2\relax - #1{\tptemp}{#3}% -}% - -\def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV % -\medbreak % -% Define the end token that this defining construct specifies -% so that it will exit this group. -\def#1{\endgraf\endgroup\medbreak}% -\def#2##1 ##2 {\def#4{##1}% -\begingroup\obeylines\spacesplit{#3{##2}}}% -\parindent=0in -\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent -\exdentamount=\defbodyindent -\begingroup\obeylines\spacesplit{#3{#5}}} - -% Split up #2 at the first space token. -% call #1 with two arguments: -% the first is all of #2 before the space token, -% the second is all of #2 after that space token. -% If #2 contains no space token, all of it is passed as the first arg -% and the second is passed as empty. - -{\obeylines -\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}% -\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{% -\ifx\relax #3% -#1{#2}{}\else #1{#2}{#3#4}\fi}} - -% So much for the things common to all kinds of definitions. - -% Define @defun. - -% First, define the processing that is wanted for arguments of \defun -% Use this to expand the args and terminate the paragraph they make up - -\def\defunargs #1{\functionparens \sl -% Expand, preventing hyphenation at `-' chars. -% Note that groups don't affect changes in \hyphenchar. -\hyphenchar\tensl=0 -#1% -\hyphenchar\tensl=45 -\ifnum\parencount=0 \else \errmessage{unbalanced parens in @def arguments}\fi% -\interlinepenalty=10000 -\advance\rightskip by 0pt plus 1fil -\endgraf\penalty 10000\vskip -\parskip\penalty 10000% -} - -\def\deftypefunargs #1{% -% Expand, preventing hyphenation at `-' chars. -% Note that groups don't affect changes in \hyphenchar. -% Use \boldbraxnoamp, not \functionparens, so that & is not special. -\boldbraxnoamp -\tclose{#1}% avoid \code because of side effects on active chars -\interlinepenalty=10000 -\advance\rightskip by 0pt plus 1fil -\endgraf\penalty 10000\vskip -\parskip\penalty 10000% -} - -% Do complete processing of one @defun or @defunx line already parsed. - -% @deffn Command forward-char nchars - -\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader} - -\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}% -\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup % -\catcode 61=\other % Turn off change made in \defparsebody -} - -% @defun == @deffn Function - -\def\defun{\defparsebody\Edefun\defunx\defunheader} - -\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index -\begingroup\defname {#1}{Function}% -\defunargs {#2}\endgroup % -\catcode 61=\other % Turn off change made in \defparsebody -} - -% @deftypefun int foobar (int @var{foo}, float @var{bar}) - -\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader} - -% #1 is the data type. #2 is the name and args. -\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax} -% #1 is the data type, #2 the name, #3 the args. -\def\deftypefunheaderx #1#2 #3\relax{% -\doind {fn}{\code{#2}}% Make entry in function index -\begingroup\defname {\defheaderxcond#1\relax$$$#2}{Function}% -\deftypefunargs {#3}\endgroup % -\catcode 61=\other % Turn off change made in \defparsebody -} - -% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar}) - -\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader} - -% \defheaderxcond#1\relax$$$ -% puts #1 in @code, followed by a space, but does nothing if #1 is null. -\def\defheaderxcond#1#2$$${\ifx#1\relax\else\code{#1#2} \fi} - -% #1 is the classification. #2 is the data type. #3 is the name and args. -\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax} -% #1 is the classification, #2 the data type, #3 the name, #4 the args. -\def\deftypefnheaderx #1#2#3 #4\relax{% -\doind {fn}{\code{#3}}% Make entry in function index -\begingroup -\normalparens % notably, turn off `&' magic, which prevents -% at least some C++ text from working -\defname {\defheaderxcond#2\relax$$$#3}{#1}% -\deftypefunargs {#4}\endgroup % -\catcode 61=\other % Turn off change made in \defparsebody -} - -% @defmac == @deffn Macro - -\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader} - -\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index -\begingroup\defname {#1}{Macro}% -\defunargs {#2}\endgroup % -\catcode 61=\other % Turn off change made in \defparsebody -} - -% @defspec == @deffn Special Form - -\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader} - -\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index -\begingroup\defname {#1}{Special Form}% -\defunargs {#2}\endgroup % -\catcode 61=\other % Turn off change made in \defparsebody -} - -% This definition is run if you use @defunx -% anywhere other than immediately after a @defun or @defunx. - -\def\deffnx #1 {\errmessage{@deffnx in invalid context}} -\def\defunx #1 {\errmessage{@defunx in invalid context}} -\def\defmacx #1 {\errmessage{@defmacx in invalid context}} -\def\defspecx #1 {\errmessage{@defspecx in invalid context}} -\def\deftypefnx #1 {\errmessage{@deftypefnx in invalid context}} -\def\deftypeunx #1 {\errmessage{@deftypeunx in invalid context}} - -% @defmethod, and so on - -% @defop {Funny Method} foo-class frobnicate argument - -\def\defop #1 {\def\defoptype{#1}% -\defopparsebody\Edefop\defopx\defopheader\defoptype} - -\def\defopheader #1#2#3{% -\dosubind {fn}{\code{#2}}{on #1}% Make entry in function index -\begingroup\defname {#2}{\defoptype{} on #1}% -\defunargs {#3}\endgroup % -} - -% @defmethod == @defop Method - -\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader} - -\def\defmethodheader #1#2#3{% -\dosubind {fn}{\code{#2}}{on #1}% entry in function index -\begingroup\defname {#2}{Method on #1}% -\defunargs {#3}\endgroup % -} - -% @defcv {Class Option} foo-class foo-flag - -\def\defcv #1 {\def\defcvtype{#1}% -\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype} - -\def\defcvarheader #1#2#3{% -\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index -\begingroup\defname {#2}{\defcvtype{} of #1}% -\defvarargs {#3}\endgroup % -} - -% @defivar == @defcv {Instance Variable} - -\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader} - -\def\defivarheader #1#2#3{% -\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index -\begingroup\defname {#2}{Instance Variable of #1}% -\defvarargs {#3}\endgroup % -} - -% These definitions are run if you use @defmethodx, etc., -% anywhere other than immediately after a @defmethod, etc. - -\def\defopx #1 {\errmessage{@defopx in invalid context}} -\def\defmethodx #1 {\errmessage{@defmethodx in invalid context}} -\def\defcvx #1 {\errmessage{@defcvx in invalid context}} -\def\defivarx #1 {\errmessage{@defivarx in invalid context}} - -% Now @defvar - -% First, define the processing that is wanted for arguments of @defvar. -% This is actually simple: just print them in roman. -% This must expand the args and terminate the paragraph they make up -\def\defvarargs #1{\normalparens #1% -\interlinepenalty=10000 -\endgraf\penalty 10000\vskip -\parskip\penalty 10000} - -% @defvr Counter foo-count - -\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader} - -\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}% -\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup} - -% @defvar == @defvr Variable - -\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader} - -\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index -\begingroup\defname {#1}{Variable}% -\defvarargs {#2}\endgroup % -} - -% @defopt == @defvr {User Option} - -\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader} - -\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index -\begingroup\defname {#1}{User Option}% -\defvarargs {#2}\endgroup % -} - -% @deftypevar int foobar - -\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader} - -% #1 is the data type. #2 is the name. -\def\deftypevarheader #1#2{% -\doind {vr}{\code{#2}}% Make entry in variables index -\begingroup\defname {\defheaderxcond#1\relax$$$#2}{Variable}% -\interlinepenalty=10000 -\endgraf\penalty 10000\vskip -\parskip\penalty 10000 -\endgroup} - -% @deftypevr {Global Flag} int enable - -\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader} - -\def\deftypevrheader #1#2#3{\doind {vr}{\code{#3}}% -\begingroup\defname {\defheaderxcond#2\relax$$$#3}{#1} -\interlinepenalty=10000 -\endgraf\penalty 10000\vskip -\parskip\penalty 10000 -\endgroup} - -% This definition is run if you use @defvarx -% anywhere other than immediately after a @defvar or @defvarx. - -\def\defvrx #1 {\errmessage{@defvrx in invalid context}} -\def\defvarx #1 {\errmessage{@defvarx in invalid context}} -\def\defoptx #1 {\errmessage{@defoptx in invalid context}} -\def\deftypevarx #1 {\errmessage{@deftypevarx in invalid context}} -\def\deftypevrx #1 {\errmessage{@deftypevrx in invalid context}} - -% Now define @deftp -% Args are printed in bold, a slight difference from @defvar. - -\def\deftpargs #1{\bf \defvarargs{#1}} - -% @deftp Class window height width ... - -\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader} - -\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}% -\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup} - -% This definition is run if you use @deftpx, etc -% anywhere other than immediately after a @deftp, etc. - -\def\deftpx #1 {\errmessage{@deftpx in invalid context}} - - -\message{cross reference,} -% Define cross-reference macros -\newwrite \auxfile - -\newif\ifhavexrefs % True if xref values are known. -\newif\ifwarnedxrefs % True if we warned once that they aren't known. - -% @inforef is simple. -\def\inforef #1{\inforefzzz #1,,,,**} -\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}}, - node \samp{\ignorespaces#1{}}} - -% \setref{foo} defines a cross-reference point named foo. - -\def\setref#1{% -\dosetq{#1-title}{Ytitle}% -\dosetq{#1-pg}{Ypagenumber}% -\dosetq{#1-snt}{Ysectionnumberandtype}} - -\def\unnumbsetref#1{% -\dosetq{#1-title}{Ytitle}% -\dosetq{#1-pg}{Ypagenumber}% -\dosetq{#1-snt}{Ynothing}} - -\def\appendixsetref#1{% -\dosetq{#1-title}{Ytitle}% -\dosetq{#1-pg}{Ypagenumber}% -\dosetq{#1-snt}{Yappendixletterandtype}} - -% \xref, \pxref, and \ref generate cross-references to specified points. -% For \xrefX, #1 is the node name, #2 the name of the Info -% cross-reference, #3 the printed node name, #4 the name of the Info -% file, #5 the name of the printed manual. All but the node name can be -% omitted. -% -\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]} -\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]} -\def\ref#1{\xrefX[#1,,,,,,,]} -\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup - \def\printedmanual{\ignorespaces #5}% - \def\printednodename{\ignorespaces #3}% - \setbox1=\hbox{\printedmanual}% - \setbox0=\hbox{\printednodename}% - \ifdim \wd0 = 0pt - % No printed node name was explicitly given. - \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax - % Use the node name inside the square brackets. - \def\printednodename{\ignorespaces #1}% - \else - % Use the actual chapter/section title appear inside - % the square brackets. Use the real section title if we have it. - \ifdim \wd1>0pt% - % It is in another manual, so we don't have it. - \def\printednodename{\ignorespaces #1}% - \else - \ifhavexrefs - % We know the real title if we have the xref values. - \def\printednodename{\refx{#1-title}{}}% - \else - % Otherwise just copy the Info node name. - \def\printednodename{\ignorespaces #1}% - \fi% - \fi - \fi - \fi - % - % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not - % insert empty discretionaries after hyphens, which means that it will - % not find a line break at a hyphen in a node names. Since some manuals - % are best written with fairly long node names, containing hyphens, this - % is a loss. Therefore, we give the text of the node name again, so it - % is as if TeX is seeing it for the first time. - \ifdim \wd1 > 0pt - \putwordsection{} ``\printednodename'' in \cite{\printedmanual}% - \else - % _ (for example) has to be the character _ for the purposes of the - % control sequence corresponding to the node, but it has to expand - % into the usual \leavevmode...\vrule stuff for purposes of - % printing. So we \turnoffactive for the \refx-snt, back on for the - % printing, back off for the \refx-pg. - {\turnoffactive \refx{#1-snt}{}}% - \space [\printednodename],\space - \turnoffactive \putwordpage\tie\refx{#1-pg}{}% - \fi -\endgroup} - -% \dosetq is the interface for calls from other macros - -% Use \turnoffactive so that punctuation chars such as underscore -% work in node names. -\def\dosetq #1#2{{\let\folio=0 \turnoffactive \auxhat% -\edef\next{\write\auxfile{\internalsetq {#1}{#2}}}% -\next}} - -% \internalsetq {foo}{page} expands into -% CHARACTERS 'xrdef {foo}{...expansion of \Ypage...} -% When the aux file is read, ' is the escape character - -\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}} - -% Things to be expanded by \internalsetq - -\def\Ypagenumber{\folio} - -\def\Ytitle{\thissection} - -\def\Ynothing{} - -\def\Ysectionnumberandtype{% -\ifnum\secno=0 \putwordChapter\xreftie\the\chapno % -\else \ifnum \subsecno=0 \putwordSection\xreftie\the\chapno.\the\secno % -\else \ifnum \subsubsecno=0 % -\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno % -\else % -\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno % -\fi \fi \fi } - -\def\Yappendixletterandtype{% -\ifnum\secno=0 \putwordAppendix\xreftie'char\the\appendixno{}% -\else \ifnum \subsecno=0 \putwordSection\xreftie'char\the\appendixno.\the\secno % -\else \ifnum \subsubsecno=0 % -\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno % -\else % -\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno % -\fi \fi \fi } - -\gdef\xreftie{'tie} - -% Use TeX 3.0's \inputlineno to get the line number, for better error -% messages, but if we're using an old version of TeX, don't do anything. -% -\ifx\inputlineno\thisisundefined - \let\linenumber = \empty % Non-3.0. -\else - \def\linenumber{\the\inputlineno:\space} -\fi - -% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME. -% If its value is nonempty, SUFFIX is output afterward. - -\def\refx#1#2{% - \expandafter\ifx\csname X#1\endcsname\relax - % If not defined, say something at least. - $\langle$un\-de\-fined$\rangle$% - \ifhavexrefs - \message{\linenumber Undefined cross reference `#1'.}% - \else - \ifwarnedxrefs\else - \global\warnedxrefstrue - \message{Cross reference values unknown; you must run TeX again.}% - \fi - \fi - \else - % It's defined, so just use it. - \csname X#1\endcsname - \fi - #2% Output the suffix in any case. -} - -% Read the last existing aux file, if any. No error if none exists. - -% This is the macro invoked by entries in the aux file. -\def\xrdef #1#2{ -{\catcode`\'=\other\expandafter \gdef \csname X#1\endcsname {#2}}} - -\def\readauxfile{% -\begingroup -\catcode `\^^@=\other -\catcode `\=\other -\catcode `\=\other -\catcode `\^^C=\other -\catcode `\^^D=\other -\catcode `\^^E=\other -\catcode `\^^F=\other -\catcode `\^^G=\other -\catcode `\^^H=\other -\catcode `\ =\other -\catcode `\^^L=\other -\catcode `\=\other -\catcode `\=\other -\catcode `\=\other -\catcode `\=\other -\catcode `\=\other -\catcode `\=\other -\catcode `\=\other -\catcode `\=\other -\catcode `\=\other -\catcode `\=\other -\catcode `\=\other -\catcode `\=\other -\catcode 26=\other -\catcode `\^^[=\other -\catcode `\^^\=\other -\catcode `\^^]=\other -\catcode `\^^^=\other -\catcode `\^^_=\other -\catcode `\@=\other -\catcode `\^=\other -\catcode `\~=\other -\catcode `\[=\other -\catcode `\]=\other -\catcode`\"=\other -\catcode`\_=\other -\catcode`\|=\other -\catcode`\<=\other -\catcode`\>=\other -\catcode `\$=\other -\catcode `\#=\other -\catcode `\&=\other -% `\+ does not work, so use 43. -\catcode 43=\other -% Make the characters 128-255 be printing characters -{% - \count 1=128 - \def\loop{% - \catcode\count 1=\other - \advance\count 1 by 1 - \ifnum \count 1<256 \loop \fi - }% -}% -% the aux file uses ' as the escape. -% Turn off \ as an escape so we do not lose on -% entries which were dumped with control sequences in their names. -% For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^ -% Reference to such entries still does not work the way one would wish, -% but at least they do not bomb out when the aux file is read in. -\catcode `\{=1 \catcode `\}=2 -\catcode `\%=\other -\catcode `\'=0 -\catcode`\^=7 % to make ^^e4 etc usable in xref tags -\catcode `\\=\other -\openin 1 \jobname.aux -\ifeof 1 \else \closein 1 \input \jobname.aux \global\havexrefstrue -\global\warnedobstrue -\fi -% Open the new aux file. Tex will close it automatically at exit. -\openout \auxfile=\jobname.aux -\endgroup} - - -% Footnotes. - -\newcount \footnoteno - -% The trailing space in the following definition for supereject is -% vital for proper filling; pages come out unaligned when you do a -% pagealignmacro call if that space before the closing brace is -% removed. (Generally, numeric constants should always be followed by a -% space to prevent strange expansion errors.) -\def\supereject{\par\penalty -20000\footnoteno =0 } - -% @footnotestyle is meaningful for info output only.. -\let\footnotestyle=\comment - -\let\ptexfootnote=\footnote - -{\catcode `\@=11 -% -% Auto-number footnotes. Otherwise like plain. -\gdef\footnote{% - \global\advance\footnoteno by \@ne - \edef\thisfootno{$^{\the\footnoteno}$}% - % - % In case the footnote comes at the end of a sentence, preserve the - % extra spacing after we do the footnote number. - \let\@sf\empty - \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi - % - % Remove inadvertent blank space before typesetting the footnote number. - \unskip - \thisfootno\@sf - \footnotezzz -}% - -% Don't bother with the trickery in plain.tex to not require the -% footnote text as a parameter. Our footnotes don't need to be so general. -% -\long\gdef\footnotezzz#1{\insert\footins{% - % We want to typeset this text as a normal paragraph, even if the - % footnote reference occurs in (for example) a display environment. - % So reset some parameters. - \interlinepenalty\interfootnotelinepenalty - \splittopskip\ht\strutbox % top baseline for broken footnotes - \splitmaxdepth\dp\strutbox - \floatingpenalty\@MM - \leftskip\z@skip - \rightskip\z@skip - \spaceskip\z@skip - \xspaceskip\z@skip - \parindent\defaultparindent - % - % Hang the footnote text off the number. - \hang - \textindent{\thisfootno}% - % - % Don't crash into the line above the footnote text. Since this - % expands into a box, it must come within the paragraph, lest it - % provide a place where TeX can split the footnote. - \footstrut - #1\strut}% -} - -}%end \catcode `\@=11 - -% Set the baselineskip to #1, and the lineskip and strut size -% correspondingly. There is no deep meaning behind these magic numbers -% used as factors; they just match (closely enough) what Knuth defined. -% -\def\lineskipfactor{.08333} -\def\strutheightpercent{.70833} -\def\strutdepthpercent {.29167} -% -\def\setleading#1{% - \normalbaselineskip = #1\relax - \normallineskip = \lineskipfactor\normalbaselineskip - \normalbaselines - \setbox\strutbox =\hbox{% - \vrule width0pt height\strutheightpercent\baselineskip - depth \strutdepthpercent \baselineskip - }% -} - -% @| inserts a changebar to the left of the current line. It should -% surround any changed text. This approach does *not* work if the -% change spans more than two lines of output. To handle that, we would -% have adopt a much more difficult approach (putting marks into the main -% vertical list for the beginning and end of each change). -% -\def\|{% - % \vadjust can only be used in horizontal mode. - \leavevmode - % - % Append this vertical mode material after the current line in the output. - \vadjust{% - % We want to insert a rule with the height and depth of the current - % leading; that is exactly what \strutbox is supposed to record. - \vskip-\baselineskip - % - % \vadjust-items are inserted at the left edge of the type. So - % the \llap here moves out into the left-hand margin. - \llap{% - % - % For a thicker or thinner bar, change the `1pt'. - \vrule height\baselineskip width1pt - % - % This is the space between the bar and the text. - \hskip 12pt - }% - }% -} - -% For a final copy, take out the rectangles -% that mark overfull boxes (in case you have decided -% that the text looks ok even though it passes the margin). -% -\def\finalout{\overfullrule=0pt} - - -% End of control word definitions. - -\message{and turning on texinfo input format.} - -\def\openindices{% - \newindex{cp}% - \newcodeindex{fn}% - \newcodeindex{vr}% - \newcodeindex{tp}% - \newcodeindex{ky}% - \newcodeindex{pg}% -} - -% Set some numeric style parameters, for 8.5 x 11 format. - -\hsize = 6in -\hoffset = .25in -\newdimen\defaultparindent \defaultparindent = 15pt -\parindent = \defaultparindent -\parskip 3pt plus 2pt minus 1pt -\setleading{13.2pt} -\advance\topskip by 1.2cm - -\chapheadingskip = 15pt plus 4pt minus 2pt -\secheadingskip = 12pt plus 3pt minus 2pt -\subsecheadingskip = 9pt plus 2pt minus 2pt - -% Prevent underfull vbox error messages. -\vbadness=10000 - -% Following George Bush, just get rid of widows and orphans. -\widowpenalty=10000 -\clubpenalty=10000 - -% Use TeX 3.0's \emergencystretch to help line breaking, but if we're -% using an old version of TeX, don't do anything. We want the amount of -% stretch added to depend on the line length, hence the dependence on -% \hsize. This makes it come to about 9pt for the 8.5x11 format. -% -\ifx\emergencystretch\thisisundefined - % Allow us to assign to \emergencystretch anyway. - \def\emergencystretch{\dimen0}% -\else - \emergencystretch = \hsize - \divide\emergencystretch by 45 -\fi - -% Use @smallbook to reset parameters for 7x9.5 format (or else 7x9.25) -\def\smallbook{ - \global\chapheadingskip = 15pt plus 4pt minus 2pt - \global\secheadingskip = 12pt plus 3pt minus 2pt - \global\subsecheadingskip = 9pt plus 2pt minus 2pt - % - \global\lispnarrowing = 0.3in - \setleading{12pt} - \advance\topskip by -1cm - \global\parskip 2pt plus 1pt - \global\hsize = 5in - \global\vsize=7.5in - \global\tolerance=700 - \global\hfuzz=1pt - \global\contentsrightmargin=0pt - \global\deftypemargin=0pt - \global\defbodyindent=.5cm - % - \global\pagewidth=\hsize - \global\pageheight=\vsize - % - \global\let\smalllisp=\smalllispx - \global\let\smallexample=\smalllispx - \global\def\Esmallexample{\Esmalllisp} -} - -% Use @afourpaper to print on European A4 paper. -\def\afourpaper{ -\global\tolerance=700 -\global\hfuzz=1pt -\setleading{12pt} -\global\parskip 15pt plus 1pt - -\global\vsize= 53\baselineskip -\advance\vsize by \topskip -%\global\hsize= 5.85in % A4 wide 10pt -\global\hsize= 6.5in -\global\outerhsize=\hsize -\global\advance\outerhsize by 0.5in -\global\outervsize=\vsize -\global\advance\outervsize by 0.6in - -\global\pagewidth=\hsize -\global\pageheight=\vsize -} - -\bindingoffset=0pt -\normaloffset=\hoffset -\pagewidth=\hsize -\pageheight=\vsize - -% Allow control of the text dimensions. Parameters in order: textheight; -% textwidth; voffset; hoffset; binding offset; topskip. -% All require a dimension; -% header is additional; added length extends the bottom of the page. - -\def\changepagesizes#1#2#3#4#5#6{ - \global\vsize= #1 - \global\topskip= #6 - \advance\vsize by \topskip - \global\voffset= #3 - \global\hsize= #2 - \global\outerhsize=\hsize - \global\advance\outerhsize by 0.5in - \global\outervsize=\vsize - \global\advance\outervsize by 0.6in - \global\pagewidth=\hsize - \global\pageheight=\vsize - \global\normaloffset= #4 - \global\bindingoffset= #5} - -% A specific text layout, 24x15cm overall, intended for A4 paper. Top margin -% 29mm, hence bottom margin 28mm, nominal side margin 3cm. -\def\afourlatex - {\global\tolerance=700 - \global\hfuzz=1pt - \setleading{12pt} - \global\parskip 15pt plus 1pt - \advance\baselineskip by 1.6pt - \changepagesizes{237mm}{150mm}{3.6mm}{3.6mm}{3mm}{7mm} - } - -% Use @afourwide to print on European A4 paper in wide format. -\def\afourwide{\afourpaper -\changepagesizes{9.5in}{6.5in}{\hoffset}{\normaloffset}{\bindingoffset}{7mm}} - -% Define macros to output various characters with catcode for normal text. -\catcode`\"=\other -\catcode`\~=\other -\catcode`\^=\other -\catcode`\_=\other -\catcode`\|=\other -\catcode`\<=\other -\catcode`\>=\other -\catcode`\+=\other -\def\normaldoublequote{"} -\def\normaltilde{~} -\def\normalcaret{^} -\def\normalunderscore{_} -\def\normalverticalbar{|} -\def\normalless{<} -\def\normalgreater{>} -\def\normalplus{+} - -% This macro is used to make a character print one way in ttfont -% where it can probably just be output, and another way in other fonts, -% where something hairier probably needs to be done. -% -% #1 is what to print if we are indeed using \tt; #2 is what to print -% otherwise. Since all the Computer Modern typewriter fonts have zero -% interword stretch (and shrink), and it is reasonable to expect all -% typewriter fonts to have this, we can check that font parameter. -% -\def\ifusingtt#1#2{\ifdim \fontdimen3\the\font=0pt #1\else #2\fi} - -% Turn off all special characters except @ -% (and those which the user can use as if they were ordinary). -% Most of these we simply print from the \tt font, but for some, we can -% use math or other variants that look better in normal text. - -\catcode`\"=\active -\def\activedoublequote{{\tt \char '042}} -\let"=\activedoublequote -\catcode`\~=\active -\def~{{\tt \char '176}} -\chardef\hat=`\^ -\catcode`\^=\active -\def\auxhat{\def^{'hat}} -\def^{{\tt \hat}} - -\catcode`\_=\active -\def_{\ifusingtt\normalunderscore\_} -% Subroutine for the previous macro. -\def\_{\leavevmode \kern.06em \vbox{\hrule width.3em height.1ex}} - -\catcode`\|=\active -\def|{{\tt \char '174}} -\chardef \less=`\< -\catcode`\<=\active -\def<{{\tt \less}} -\chardef \gtr=`\> -\catcode`\>=\active -\def>{{\tt \gtr}} -\catcode`\+=\active -\def+{{\tt \char 43}} -%\catcode 27=\active -%\def^^[{$\diamondsuit$} - -% Set up an active definition for =, but don't enable it most of the time. -{\catcode`\==\active -\global\def={{\tt \char 61}}} - -\catcode`+=\active -\catcode`\_=\active - -% If a .fmt file is being used, characters that might appear in a file -% name cannot be active until we have parsed the command line. -% So turn them off again, and have \everyjob (or @setfilename) turn them on. -% \otherifyactive is called near the end of this file. -\def\otherifyactive{\catcode`+=\other \catcode`\_=\other} - -\catcode`\@=0 - -% \rawbackslashxx output one backslash character in current font -\global\chardef\rawbackslashxx=`\\ -%{\catcode`\\=\other -%@gdef@rawbackslashxx{\}} - -% \rawbackslash redefines \ as input to do \rawbackslashxx. -{\catcode`\\=\active -@gdef@rawbackslash{@let\=@rawbackslashxx }} - -% \normalbackslash outputs one backslash in fixed width font. -\def\normalbackslash{{\tt\rawbackslashxx}} - -% Say @foo, not \foo, in error messages. -\escapechar=`\@ - -% \catcode 17=0 % Define control-q -\catcode`\\=\active - -% Used sometimes to turn off (effectively) the active characters -% even after parsing them. -@def@turnoffactive{@let"=@normaldoublequote -@let\=@realbackslash -@let~=@normaltilde -@let^=@normalcaret -@let_=@normalunderscore -@let|=@normalverticalbar -@let<=@normalless -@let>=@normalgreater -@let+=@normalplus} - -@def@normalturnoffactive{@let"=@normaldoublequote -@let\=@normalbackslash -@let~=@normaltilde -@let^=@normalcaret -@let_=@normalunderscore -@let|=@normalverticalbar -@let<=@normalless -@let>=@normalgreater -@let+=@normalplus} - -% Make _ and + \other characters, temporarily. -% This is canceled by @fixbackslash. -@otherifyactive - -% If a .fmt file is being used, we don't want the `\input texinfo' to show up. -% That is what \eatinput is for; after that, the `\' should revert to printing -% a backslash. -% -@gdef@eatinput input texinfo{@fixbackslash} -@global@let\ = @eatinput - -% On the other hand, perhaps the file did not have a `\input texinfo'. Then -% the first `\{ in the file would cause an error. This macro tries to fix -% that, assuming it is called before the first `\' could plausibly occur. -% Also back turn on active characters that might appear in the input -% file name, in case not using a pre-dumped format. -% -@gdef@fixbackslash{@ifx\@eatinput @let\ = @normalbackslash @fi - @catcode`+=@active @catcode`@_=@active} - -%% These look ok in all fonts, so just make them not special. The @rm below -%% makes sure that the current font starts out as the newly loaded cmr10 -@catcode`@$=@other @catcode`@%=@other @catcode`@&=@other @catcode`@#=@other - -@textfonts -@rm - -@c Local variables: -@c page-delimiter: "^\\\\message" -@c End: diff --git a/info/tilde.c b/info/tilde.c deleted file mode 100644 --- a/info/tilde.c +++ /dev/null @@ -1,376 +0,0 @@ -/* tilde.c -- Tilde expansion code (~/foo := $HOME/foo). - $Id: tilde.c,v 1.5 1996-11-13 03:41:45 jwe Exp $ - - This file is part of GNU Info, a program for reading online documentation - stored in Info format. - - Copyright (C) 1988, 89, 90, 91, 92, 93, 96 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). */ - -#if defined (__GNUC__) -# define alloca __builtin_alloca -#else /* !__GNUC__ */ -# if defined (_AIX) - #pragma alloca -# else /* !_AIX */ -# if defined (HAVE_ALLOCA_H) -# include -# endif /* HAVE_ALLOCA_H */ -# endif /* !AIX */ -#endif /* !__GNUC__ */ - -#if defined (HAVE_STDLIB_H) -#include -#endif - -#include "tilde.h" -#include - -#if defined (HAVE_STRING_H) -#include -#endif - -#include "clib.h" - -#if !defined (NULL) -# define NULL 0x0 -#endif - -#if defined (TEST) || defined (STATIC_MALLOC) -static void *xmalloc (), *xrealloc (); -#else -extern void *xmalloc (), *xrealloc (); -#endif /* TEST || STATIC_MALLOC */ - -/* The default value of tilde_additional_prefixes. This is set to - whitespace preceding a tilde so that simple programs which do not - perform any word separation get desired behaviour. */ -static char *default_prefixes[] = - { " ~", "\t~", (char *)NULL }; - -/* The default value of tilde_additional_suffixes. This is set to - whitespace or newline so that simple programs which do not - perform any word separation get desired behaviour. */ -static char *default_suffixes[] = - { " ", "\n", (char *)NULL }; - -/* If non-null, this contains the address of a function to call if the - standard meaning for expanding a tilde fails. The function is called - with the text (sans tilde, as in "foo"), and returns a malloc()'ed string - which is the expansion, or a NULL pointer if there is no expansion. */ -CFunction *tilde_expansion_failure_hook = (CFunction *)NULL; - -/* When non-null, this is a NULL terminated array of strings which - are duplicates for a tilde prefix. Bash uses this to expand - `=~' and `:~'. */ -char **tilde_additional_prefixes = default_prefixes; - -/* When non-null, this is a NULL terminated array of strings which match - the end of a username, instead of just "/". Bash sets this to - `:' and `=~'. */ -char **tilde_additional_suffixes = default_suffixes; - -/* Find the start of a tilde expansion in STRING, and return the index of - the tilde which starts the expansion. Place the length of the text - which identified this tilde starter in LEN, excluding the tilde itself. */ -static int -tilde_find_prefix (string, len) - char *string; - int *len; -{ - register int i, j, string_len; - register char **prefixes = tilde_additional_prefixes; - - string_len = strlen (string); - *len = 0; - - if (!*string || *string == '~') - return (0); - - if (prefixes) - { - for (i = 0; i < string_len; i++) - { - for (j = 0; prefixes[j]; j++) - { - if (strncmp (string + i, prefixes[j], strlen (prefixes[j])) == 0) - { - *len = strlen (prefixes[j]) - 1; - return (i + *len); - } - } - } - } - return (string_len); -} - -/* Find the end of a tilde expansion in STRING, and return the index of - the character which ends the tilde definition. */ -static int -tilde_find_suffix (string) - char *string; -{ - register int i, j, string_len; - register char **suffixes = tilde_additional_suffixes; - - string_len = strlen (string); - - for (i = 0; i < string_len; i++) - { - if (string[i] == '/' || !string[i]) - break; - - for (j = 0; suffixes && suffixes[j]; j++) - { - if (strncmp (string + i, suffixes[j], strlen (suffixes[j])) == 0) - return (i); - } - } - return (i); -} - -/* Return a new string which is the result of tilde expanding STRING. */ -char * -tilde_expand (string) - char *string; -{ - char *result, *tilde_expand_word (); - int result_size, result_index; - - result_size = result_index = 0; - result = (char *)NULL; - - /* Scan through STRING expanding tildes as we come to them. */ - while (1) - { - register int start, end; - char *tilde_word, *expansion; - int len; - - /* Make START point to the tilde which starts the expansion. */ - start = tilde_find_prefix (string, &len); - - /* Copy the skipped text into the result. */ - if ((result_index + start + 1) > result_size) - result = (char *)xrealloc (result, 1 + (result_size += (start + 20))); - - strncpy (result + result_index, string, start); - result_index += start; - - /* Advance STRING to the starting tilde. */ - string += start; - - /* Make END be the index of one after the last character of the - username. */ - end = tilde_find_suffix (string); - - /* If both START and END are zero, we are all done. */ - if (!start && !end) - break; - - /* Expand the entire tilde word, and copy it into RESULT. */ - tilde_word = (char *)xmalloc (1 + end); - strncpy (tilde_word, string, end); - tilde_word[end] = '\0'; - string += end; - - expansion = tilde_expand_word (tilde_word); - free (tilde_word); - - len = strlen (expansion); - if ((result_index + len + 1) > result_size) - result = (char *)xrealloc (result, 1 + (result_size += (len + 20))); - - strcpy (result + result_index, expansion); - result_index += len; - free (expansion); - } - - result[result_index] = '\0'; - - return (result); -} - -/* Do the work of tilde expansion on FILENAME. FILENAME starts with a - tilde. If there is no expansion, call tilde_expansion_failure_hook. */ -char * -tilde_expand_word (filename) - char *filename; -{ - char *dirname; - - dirname = filename ? strdup (filename) : (char *)NULL; - - if (dirname && *dirname == '~') - { - char *temp_name; - if (!dirname[1] || dirname[1] == '/') - { - /* Prepend $HOME to the rest of the string. */ - extern char *getenv (); - char *temp_home = getenv ("HOME"); - - /* If there is no HOME variable, look up the directory in - the password database. */ - if (!temp_home) - { - struct passwd *entry; - - entry = (struct passwd *) getpwuid (getuid ()); - if (entry) - temp_home = entry->pw_dir; - } - - temp_name = (char *) - alloca (1 + strlen (&dirname[1]) - + (temp_home ? strlen (temp_home) : 0)); - temp_name[0] = '\0'; - if (temp_home) - strcpy (temp_name, temp_home); - strcat (temp_name, &dirname[1]); - free (dirname); - dirname = strdup (temp_name); - } - else - { - struct passwd *user_entry; - char *username = (char *)alloca (257); - int i, c; - - for (i = 1; c = dirname[i]; i++) - { - if (c == '/') - break; - else - username[i - 1] = c; - } - username[i - 1] = '\0'; - - if (!(user_entry = (struct passwd *) getpwnam (username))) - { - /* If the calling program has a special syntax for - expanding tildes, and we couldn't find a standard - expansion, then let them try. */ - if (tilde_expansion_failure_hook) - { - char *expansion; - - expansion = (*tilde_expansion_failure_hook) (username); - - if (expansion) - { - temp_name = (char *)alloca - (1 + strlen (expansion) + strlen (&dirname[i])); - strcpy (temp_name, expansion); - strcat (temp_name, &dirname[i]); - free (expansion); - goto return_name; - } - } - /* We shouldn't report errors. */ - } - else - { - temp_name = (char *)alloca - (1 + strlen (user_entry->pw_dir) + strlen (&dirname[i])); - strcpy (temp_name, user_entry->pw_dir); - strcat (temp_name, &dirname[i]); - return_name: - free (dirname); - dirname = strdup (temp_name); - } - endpwent (); - } - } - return (dirname); -} - - -#if defined (TEST) -#undef NULL -#include - -main (argc, argv) - int argc; - char **argv; -{ - char *result, line[512]; - int done = 0; - - while (!done) - { - printf ("~expand: "); - fflush (stdout); - - if (!gets (line)) - strcpy (line, "done"); - - if ((strcmp (line, "done") == 0) || - (strcmp (line, "quit") == 0) || - (strcmp (line, "exit") == 0)) - { - done = 1; - break; - } - - result = tilde_expand (line); - printf (" --> %s\n", result); - free (result); - } - exit (0); -} - -static void memory_error_and_abort (); - -static void * -xmalloc (bytes) - int bytes; -{ - void *temp = (void *)malloc (bytes); - - if (!temp) - memory_error_and_abort (); - return (temp); -} - -static void * -xrealloc (pointer, bytes) - void *pointer; - int bytes; -{ - void *temp; - - if (!pointer) - temp = (char *)malloc (bytes); - else - temp = (char *)realloc (pointer, bytes); - - if (!temp) - memory_error_and_abort (); - - return (temp); -} - -static void -memory_error_and_abort () -{ - fprintf (stderr, "readline: Out of virtual memory!\n"); - abort (); -} -#endif /* TEST */ - diff --git a/info/tilde.h b/info/tilde.h deleted file mode 100644 --- a/info/tilde.h +++ /dev/null @@ -1,58 +0,0 @@ -/* tilde.h: Externally available variables and function in libtilde.a. */ - -/* This file is part of GNU Info, a program for reading online documentation - stored in Info format. - - This file has appeared in prior works by the Free Software Foundation; - thus it carries copyright dates from 1988 through 1993. - - Copyright (C) 1988, 1989, 1990, 1991, 1992, 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). */ - -/* Function pointers can be declared as (Function *)foo. */ -#if !defined (__FUNCTION_DEF) -# define __FUNCTION_DEF -typedef int Function (); -typedef void VFunction (); -typedef char *CFunction (); -#endif /* _FUNCTION_DEF */ - -/* If non-null, this contains the address of a function to call if the - standard meaning for expanding a tilde fails. The function is called - with the text (sans tilde, as in "foo"), and returns a malloc()'ed string - which is the expansion, or a NULL pointer if there is no expansion. */ -extern CFunction *tilde_expansion_failure_hook; - -/* When non-null, this is a NULL terminated array of strings which - are duplicates for a tilde prefix. Bash uses this to expand - `=~' and `:~'. */ -extern char **tilde_additional_prefixes; - -/* When non-null, this is a NULL terminated array of strings which match - the end of a username, instead of just "/". Bash sets this to - `:' and `=~'. */ -extern char **tilde_additional_suffixes; - -/* Return a new string which is the result of tilde expanding STRING. */ -extern char *tilde_expand (); - -/* Do the work of tilde expansion on FILENAME. FILENAME starts with a - tilde. If there is no expansion, call tilde_expansion_failure_hook. */ -extern char *tilde_expand_word (); - diff --git a/info/userdoc.texi b/info/userdoc.texi deleted file mode 100644 --- a/info/userdoc.texi +++ /dev/null @@ -1,1270 +0,0 @@ -@c This file is meant to be included in any arbitrary piece of -@c documentation that wishes to describe the info program. Some day -@c info-stnd.texi should probably use this file instead of duplicating -@c its contents. -@c -@c This file documents the use of the standalone GNU Info program, -@c versions 2.7 and later. - -@ifclear InfoProgVer -@set InfoProgVer 2.11 -@end ifclear -@synindex vr cp -@synindex fn cp -@synindex ky cp - -@heading What is Info? - -This text documents the use of the GNU Info program, version -@value{InfoProgVer}. - -@dfn{Info} is a program which is used to view info files on an ASCII -terminal. @dfn{info files} are the result of processing texinfo files -with the program @code{makeinfo} or with the Emacs command @code{M-x -texinfo-format-buffer}. Finally, @dfn{texinfo} is a documentation -language which allows a printed manual and online documentation (an info -file) to be produced from a single source file. - -@menu -* Options:: Options you can pass on the command line. -* Cursor Commands:: Commands which move the cursor within a node. -* Scrolling Commands:: Commands for moving the node around in a window. -* Node Commands:: Commands for selecting a new node. -* Searching Commands:: Commands for searching an info file. -* Xref Commands:: Commands for selecting cross references. -* Window Commands:: Commands which manipulate multiple windows. -* Printing Nodes:: How to print out the contents of a node. -* Miscellaneous Commands:: A few commands that defy categories. -* Variables:: How to change the default behaviour of Info. -@ifset NOTSET -* Info for Sys Admins:: How to setup Info. Using special options. -@end ifset -@ifset STANDALONE -* GNU Info Global Index:: Global index containing keystrokes, command names, - variable names, and general concepts. -@end ifset -@end menu - -@node Options -@chapter Command Line Options -@cindex command line options -@cindex arguments, command line - -GNU Info accepts several options to control the initial node being -viewed, and to specify which directories to search for info files. Here -is a template showing an invocation of GNU Info from the shell: - -@example -info [--@var{option-name} @var{option-value}] @var{menu-item}@dots{} -@end example - -The following @var{option-names} are available when invoking Info from -the shell: - -@table @code -@cindex directory path -@item --directory @var{directory-path} -@itemx -d @var{directory-path} -Adds @var{directory-path} to the list of directory paths searched when -Info needs to find a file. You may issue @code{--directory} multiple -times; once for each directory which contains info files. -Alternatively, you may specify a value for the environment variable -@code{INFOPATH}; if @code{--directory} is not given, the value of -@code{INFOPATH} is used. The value of @code{INFOPATH} is a colon -separated list of directory names. If you do not supply -@code{INFOPATH} or @code{--directory-path} a default path is used. - -@item --file @var{filename} -@itemx -f @var{filename} -@cindex info file, selecting -Specifies a particular info file to visit. Instead of visiting the file -@code{dir}, Info will start with @code{(@var{filename})Top} as the first -file and node. - -@item --node @var{nodename} -@itemx -n @var{nodename} -@cindex node, selecting -Specifies a particular node to visit in the initial file loaded. This -is especially useful in conjunction with @code{--file}@footnote{Of -course, you can specify both the file and node in a @code{--node} -command; but don't forget to escape the open and close parentheses from -the shell as in: @code{info --node '(emacs)Buffers'}}. You may specify -@code{--node} multiple times; for an interactive Info, each -@var{nodename} is visited in its own window, for a non-interactive Info -(such as when @code{--output} is given) each @var{nodename} is processed -sequentially. - -@item --output @var{filename} -@itemx -o @var{filename} -@cindex file, outputting to -@cindex outputting to a file -Specify @var{filename} as the name of a file to output to. Each node -that Info visits will be output to @var{filename} instead of -interactively viewed. A value of @code{-} for @var{filename} specifies -the standard output. - -@item --subnodes -@cindex @code{--subnodes}, command line option -This option only has meaning when given in conjunction with -@code{--output}. It means to recursively output the nodes appearing in -the menus of each node being output. Menu items which resolve to -external info files are not output, and neither are menu items which are -members of an index. Each node is only output once. - -@item --help -@itemx -h -Produces a relatively brief description of the available Info options. - -@item --version -@cindex version information -Prints the version information of Info and exits. - -@item @var{menu-item} -@cindex menu, following -Remaining arguments to Info are treated as the names of menu items. The -first argument would be a menu item in the initial node visited, while -the second argument would be a menu item in the first argument's node. -You can easily move to the node of your choice by specifying the menu -names which describe the path to that node. For example, - -@example -info emacs buffers -@end example - -first selects the menu item @samp{Emacs} in the node @samp{(dir)Top}, -and then selects the menu item @samp{Buffers} in the node -@samp{(emacs)Top}. - -@end table - -@node Cursor Commands -@chapter Moving the Cursor -@cindex cursor, moving -Many people find that reading screens of text page by page is made -easier when one is able to indicate particular pieces of text with some -kind of pointing device. Since this is the case, GNU Info (both the -Emacs and standalone versions) have several commands which allow you to -move the cursor about the screen. The notation used in this manual to -describe keystrokes is identical to the notation used within the Emacs -manual, and the GNU Readline manual. @xref{Characters, , Character -Conventions, emacs, the GNU Emacs Manual}, if you are unfamilar with the -notation. - -The following table lists the basic cursor movement commands in Info. -Each entry consists of the key sequence you should type to execute the -cursor movement, the @code{M-x}@footnote{@code{M-x} is also a command; it -invokes @code{execute-extended-command}. @xref{M-x, , Executing an -extended command, emacs, the GNU Emacs Manual}, for more detailed -information.} command name (displayed in parentheses), and a short -description of what the command does. All of the cursor motion commands -can take an @dfn{numeric} argument (@pxref{Miscellaneous Commands, -@code{universal-argument}}), to find out how to supply them. With a -numeric argument, the motion commands are simply executed that -many times; for example, a numeric argument of 4 given to -@code{next-line} causes the cursor to move down 4 lines. With a -negative numeric argument, the motion is reversed; an argument of -4 -given to the @code{next-line} command would cause the cursor to move -@emph{up} 4 lines. - -@table @asis -@item @code{C-n} (@code{next-line}) -@kindex C-n -@findex next-line -Moves the cursor down to the next line. - -@item @code{C-p} (@code{prev-line}) -@kindex C-p -@findex prev-line -Move the cursor up to the previous line. - -@item @code{C-a} (@code{beginning-of-line}) -@kindex C-a, in Info windows -@findex beginning-of-line -Move the cursor to the start of the current line. - -@item @code{C-e} (@code{end-of-line}) -@kindex C-e, in Info windows -@findex end-of-line -Moves the cursor to the end of the current line. - -@item @code{C-f} (@code{forward-char}) -@kindex C-f, in Info windows -@findex forward-char -Move the cursor forward a character. - -@item @code{C-b} (@code{backward-char}) -@kindex C-b, in Info windows -@findex backward-char -Move the cursor backward a character. - -@item @code{M-f} (@code{forward-word}) -@kindex M-f, in Info windows -@findex forward-word -Moves the cursor forward a word. - -@item @code{M-b} (@code{backward-word}) -@kindex M-b, in Info winows -@findex backward-word -Moves the cursor backward a word. - -@item @code{M-<} (@code{beginning-of-node}) -@itemx @code{b} -@kindex b, in Info winows -@kindex M-< -@findex beginning-of-node -Moves the cursor to the start of the current node. - -@item @code{M->} (@code{end-of-node}) -@kindex M-> -@findex end-of-node -Moves the cursor to the end of the current node. - -@item @code{M-r} (@code{move-to-window-line}) -@kindex M-r -@findex move-to-window-line -Moves the cursor to a specific line of the window. Without a numeric -argument, @code{M-r} moves the cursor to the start of the line in the -center of the window. With a numeric argument of @var{n}, @code{M-r} -moves the cursor to the start of the @var{n}th line in the window. -@end table - -@node Scrolling Commands -@chapter Moving Text Within a Window -@cindex scrolling - -Sometimes you are looking at a screenful of text, and only part of the -current paragraph you are reading is visible on the screen. The -commands detailed in this section are used to shift which part of the -current node is visible on the screen. - -@table @asis -@item @code{SPC} (@code{scroll-forward}) -@itemx @code{C-v} -@kindex SPC, in Info windows -@kindex C-v -@findex scroll-forward -Shift the text in this window up. That is, show more of the node which -is currently below the bottom of the window. With a numeric argument, -show that many more lines at the bottom of the window; a numeric -argument of 4 would shift all of the text in the window up 4 lines -(discarding the top 4 lines), and show you four new lines at the bottom -of the window. Without a numeric argument, @key{SPC} takes the bottom -two lines of the window and places them at the top of the window, -redisplaying almost a completely new screenful of lines. - -@item @code{DEL} (@code{scroll-backward}) -@itemx @code{M-v} -@kindex DEL, in Info windows -@kindex M-v -@findex scroll-backward -Shift the text in this window down. The inverse of -@code{scroll-forward}. - -@end table - -@cindex scrolling through node structure -The @code{scroll-forward} and @code{scroll-backward} commands can also -move forward and backward through the node structure of the file. If -you press @key{SPC} while viewing the end of a node, or @key{DEL} while -viewing the beginning of a node, what happens is controlled by the -variable @code{scroll-behaviour}. @xref{Variables, -@code{scroll-behaviour}}, for more information. - -@table @asis -@item @code{C-l} (@code{redraw-display}) -@kindex C-l -@findex redraw-display -Redraw the display from scratch, or shift the line containing the cursor -to a specified location. With no numeric argument, @samp{C-l} clears -the screen, and then redraws its entire contents. Given a numeric -argument of @var{n}, the line containing the cursor is shifted so that -it is on the @var{n}th line of the window. - -@item @code{C-x w} (@code{toggle-wrap}) -@kindex C-w -@findex toggle-wrap -Toggles the state of line wrapping in the current window. Normally, -lines which are longer than the screen width @dfn{wrap}, i.e., they are -continued on the next line. Lines which wrap have a @samp{\} appearing -in the rightmost column of the screen. You can cause such lines to be -terminated at the rightmost column by changing the state of line -wrapping in the window with @code{C-x w}. When a line which needs more -space than one screen width to display is displayed, a @samp{$} appears -in the rightmost column of the screen, and the remainder of the line is -invisible. -@end table - -@node Node Commands -@chapter Selecting a New Node -@cindex nodes, selection of - -This section details the numerous Info commands which select a new node -to view in the current window. - -The most basic node commands are @samp{n}, @samp{p}, @samp{u}, and -@samp{l}. - -When you are viewing a node, the top line of the node contains some Info -@dfn{pointers} which describe where the next, previous, and up nodes -are. Info uses this line to move about the node structure of the file -when you use the following commands: - -@table @asis -@item @code{n} (@code{next-node}) -@kindex n -@findex next-node -Selects the `Next' node. - -@item @code{p} (@code{prev-node}) -@kindex p -@findex prev-node -Selects the `Prev' node. - -@item @code{u} (@code{up-node}) -@kindex u -@findex up-node -Selects the `Up' node. -@end table - -You can easily select a node that you have already viewed in this window -by using the @samp{l} command -- this name stands for "last", and -actually moves through the list of already visited nodes for this -window. @samp{l} with a negative numeric argument moves forward through -the history of nodes for this window, so you can quickly step between -two adjacent (in viewing history) nodes. - -@table @asis -@item @code{l} (@code{history-node}) -@kindex l -@findex history-node -Selects the most recently selected node in this window. -@end table - -Two additional commands make it easy to select the most commonly -selected nodes; they are @samp{t} and @samp{d}. - -@table @asis -@item @code{t} (@code{top-node}) -@kindex t -@findex top-node -Selects the node @samp{Top} in the current info file. - -@item @code{d} (@code{dir-node}) -@kindex d -@findex dir-node -Selects the directory node (i.e., the node @samp{(dir)}). -@end table - -Here are some other commands which immediately result in the selection -of a different node in the current window: - -@table @asis -@item @code{<} (@code{first-node}) -@kindex < -@findex first-node -Selects the first node which appears in this file. This node is most -often @samp{Top}, but it doesn't have to be. - -@item @code{>} (@code{last-node}) -@kindex > -@findex last-node -Selects the last node which appears in this file. - -@item @code{]} (@code{global-next-node}) -@kindex ] -@findex global-next-node -Moves forward or down through node structure. If the node that you are -currently viewing has a @samp{Next} pointer, that node is selected. -Otherwise, if this node has a menu, the first menu item is selected. If -there is no @samp{Next} and no menu, the same process is tried with the -@samp{Up} node of this node. - -@item @code{[} (@code{global-prev-node}) -@kindex [ -@findex global-prev-node -Moves backward or up through node structure. If the node that you are -currently viewing has a @samp{Prev} pointer, that node is selected. -Otherwise, if the node has an @samp{Up} pointer, that node is selected, -and if it has a menu, the last item in the menu is selected. -@end table - -You can get the same behaviour as @code{global-next-node} and -@code{global-prev-node} while simply scrolling through the file with -@key{SPC} and @key{DEL}; @xref{Variables, @code{scroll-behaviour}}, for -more information. - -@table @asis -@item @code{g} (@code{goto-node}) -@kindex g -@findex goto-node -Reads the name of a node and selects it. No completion is done while -reading the node name, since the desired node may reside in a separate -file. The node must be typed exactly as it appears in the info file. A -file name may be included as with any node specification, for example - -@example -@code{g(emacs)Buffers} -@end example - -finds the node @samp{Buffers} in the info file @file{emacs}. - -@item @code{C-x k} (@code{kill-node}) -@kindex C-x k -@findex kill-node -Kills a node. The node name is prompted for in the echo area, with a -default of the current node. @dfn{Killing} a node means that Info tries -hard to forget about it, removing it from the list of history nodes kept -for the window where that node is found. Another node is selected in -the window which contained the killed node. - -@item @code{C-x C-f} (@code{view-file}) -@kindex C-x C-f -@findex view-file -Reads the name of a file and selects the entire file. The command -@example -@code{C-x C-f @var{filename}} -@end example -is equivalent to typing -@example -@code{g(@var{filename})*} -@end example - -@item @code{C-x C-b} (@code{list-visited-nodes}) -@kindex C-x C-b -@findex list-visited-nodes -Makes a window containing a menu of all of the currently visited nodes. -This window becomes the selected window, and you may use the standard -Info commands within it. - -@item @code{C-x b} (@code{select-visited-node}) -@kindex C-x b -@findex select-visited-node -Selects a node which has been previously visited in a visible window. -This is similar to @samp{C-x C-b} followed by @samp{m}, but no window is -created. -@end table - -@node Searching Commands -@chapter Searching an Info File -@cindex searching - -GNU Info allows you to search for a sequence of characters throughout an -entire info file, search through the indices of an info file, or find -areas within an info file which discuss a particular topic. - -@table @asis -@item @code{s} (@code{search}) -@kindex s -@findex search -Reads a string in the echo area and searches for it. - -@item @code{C-s} (@code{isearch-forward}) -@kindex C-s -@findex isearch-forward -Interactively searches forward through the info file for a string as you -type it. - -@item @code{C-r} (@code{isearch-backward}) -@kindex C-r -@findex isearch-backward -Interactively searches backward through the info file for a string as -you type it. - -@item @code{i} (@code{index-search}) -@kindex i -@findex index-search -Looks up a string in the indices for this info file, and selects a node -where the found index entry points to. - -@item @code{,} (@code{next-index-match}) -@kindex , -@findex next-index-match -Moves to the node containing the next matching index item from the last -@samp{i} command. -@end table - -The most basic searching command is @samp{s} (@code{search}). The -@samp{s} command prompts you for a string in the echo area, and then -searches the remainder of the info file for an ocurrence of that string. -If the string is found, the node containing it is selected, and the -cursor is left positioned at the start of the found string. Subsequent -@samp{s} commands show you the default search string within @samp{[} and -@samp{]}; pressing @key{RET} instead of typing a new string will use the -default search string. - -@dfn{Incremental searching} is similar to basic searching, but the -string is looked up while you are typing it, instead of waiting until -the entire search string has been specified. - -@node Xref Commands -@chapter Selecting Cross References - -We have already discussed the @samp{Next}, @samp{Prev}, and @samp{Up} -pointers which appear at the top of a node. In addition to these -pointers, a node may contain other pointers which refer you to a -different node, perhaps in another info file. Such pointers are called -@dfn{cross references}, or @dfn{xrefs} for short. - -@menu -* Parts of an Xref:: What a cross reference is made of. -* Selecting Xrefs:: Commands for selecting menu or note items. -@end menu - -@node Parts of an Xref -@section Parts of an Xref - -Cross references have two major parts: the first part is called the -@dfn{label}; it is the name that you can use to refer to the cross -reference, and the second is the @dfn{target}; it is the full name of -the node that the cross reference points to. - -The target is separated from the label by a colon @samp{:}; first the -label appears, and then the target. For example, in the sample menu -cross reference below, the single colon separates the label from the -target. - -@example -* Foo Label: Foo Target. More information about Foo. -@end example - -Note the @samp{.} which ends the name of the target. The @samp{.} is -not part of the target; it serves only to let Info know where the target -name ends. - -A shorthand way of specifying references allows two adjacent colons to -stand for a target name which is the same as the label name: - -@example -* Foo Commands:: Commands pertaining to Foo. -@end example - -In the above example, the name of the target is the same as the name of -the label, in this case @code{Foo Commands}. - -You will normally see two types of cross references while viewing nodes: -@dfn{menu} references, and @dfn{note} references. Menu references -appear within a node's menu; they begin with a @samp{*} at the beginning -of a line, and continue with a label, a target, and a comment which -describes what the contents of the node pointed to contains. - -Note references appear within the body of the node text; they begin with -@code{*Note}, and continue with a label and a target. - -Like @samp{Next}, @samp{Prev} and @samp{Up} pointers, cross references -can point to any valid node. They are used to refer you to a place -where more detailed information can be found on a particular subject. -Here is a cross reference which points to a node within the Texinfo -documentation: @xref{xref, , Writing an Xref, texinfo, the Texinfo -Manual}, for more information on creating your own texinfo cross -references. - -@node Selecting Xrefs -@section Selecting Xrefs - -The following table lists the Info commands which operate on menu items. - -@table @asis -@item @code{1} (@code{menu-digit}) -@itemx @code{2} @dots{} @code{9} -@cindex 1 @dots{} 9, in Info windows -@kindex 1 @dots{} 9, in Info windows -@findex menu-digit -Within an Info window, pressing a single digit, (such as @samp{1}), -selects that menu item, and places its node in the current window. -For convenience, there is one exception; pressing @samp{0} selects the -@emph{last} item in the node's menu. - -@item @code{0} (@code{last-menu-item}) -@kindex 0, in Info windows -@findex last-menu-item -Select the last item in the current node's menu. - -@item @code{m} (@code{menu-item}) -@kindex m -@findex menu-item -Reads the name of a menu item in the echo area and selects its node. -Completion is available while reading the menu label. - -@item @code{M-x find-menu} -@findex find-menu -Moves the cursor to the start of this node's menu. -@end table - -This table lists the Info commands which operate on note cross references. - -@table @asis -@item @code{f} (@code{xref-item}) -@itemx @code{r} -@kindex f -@kindex r -@findex xref-item -Reads the name of a note cross reference in the echo area and selects -its node. Completion is available while reading the cross reference -label. -@end table - -Finally, the next few commands operate on menu or note references alike: - -@table @asis -@item @code{TAB} (@code{move-to-next-xref}) -@kindex TAB, in Info windows -@findex move-to-next-xref -Moves the cursor to the start of the next nearest menu item or note -reference in this node. You can then use @key{RET} -(@code{select-reference-this-line} to select the menu or note reference. - -@item @code{M-TAB} (@code{move-to-prev-xref}) -@kindex M-TAB, in Info windows -@findex move-to-prev-xref -Moves the cursor the start of the nearest previous menu item or note -reference in this node. - -@item @code{RET} (@code{select-reference-this-line}) -@kindex RET, in Info windows -@findex select-reference-this-line -Selects the menu item or note reference appearing on this line. -@end table - -@node Window Commands -@chapter Manipulating Multiple Windows -@cindex windows, manipulating - -A @dfn{window} is a place to show the text of a node. Windows have a -view area where the text of the node is displayed, and an associated -@dfn{mode line}, which briefly describes the node being viewed. - -GNU Info supports multiple windows appearing in a single screen; each -window is separated from the next by its modeline. At any time, there -is only one @dfn{active} window, that is, the window in which the cursor -appears. There are commands available for creating windows, changing -the size of windows, selecting which window is active, and for deleting -windows. - -@menu -* The Mode Line:: What appears in the mode line? -* Basic Windows:: Manipulating windows in Info. -* The Echo Area:: Used for displaying errors and reading input. -@end menu - -@node The Mode Line -@section The Mode Line - -A @dfn{mode line} is a line of inverse video which appears at the bottom -of an info window. It describes the contents of the window just above -it; this information includes the name of the file and node appearing in -that window, the number of screen lines it takes to display the node, -and the percentage of text that is above the top of the window. It can -also tell you if the indirect tags table for this info file needs to be -updated, and whether or not the info file was compressed when stored on -disk. - -Here is a sample mode line for a window containing an uncompressed file -named @file{dir}, showing the node @samp{Top}. - -@example ------Info: (dir)Top, 40 lines --Top--------------------------------------- - ^^ ^ ^^^ ^^ - (file)Node #lines where -@end example - -When a node comes from a file which is compressed on disk, this is -indicated in the mode line with two small @samp{z}'s. In addition, if -the info file containing the node has been split into subfiles, the name -of the subfile containing the node appears in the modeline as well: - -@example ---zz-Info: (emacs)Top, 291 lines --Top-- Subfile: emacs-1.Z--------------- -@end example - -When Info makes a node internally, such that there is no corresponding -info file on disk, the name of the node is surrounded by asterisks -(@samp{*}). The name itself tells you what the contents of the window -are; the sample mode line below shows an internally constructed node -showing possible completions: - -@example ------Info: *Completions*, 7 lines --All----------------------------------- -@end example - -@node Basic Windows -@section Window Commands - -It can be convenient to view more than one node at a time. To allow -this, Info can display more than one @dfn{window}. Each window has its -own mode line (@pxref{The Mode Line}) and history of nodes viewed in that -window (@pxref{Node Commands, , @code{history-node}}). - -@table @asis -@item @code{C-x o} (@code{next-window}) -@cindex windows, selecting -@kindex C-x o -@findex next-window -Selects the next window on the screen. Note that the echo area can only be -selected if it is already in use, and you have left it temporarily. -Normally, @samp{C-x o} simply moves the cursor into the next window on -the screen, or if you are already within the last window, into the first -window on the screen. Given a numeric argument, @samp{C-x o} moves over -that many windows. A negative argument causes @samp{C-x o} to select -the previous window on the screen. - -@item @code{M-x prev-window} -@findex prev-window -Selects the previous window on the screen. This is identical to -@samp{C-x o} with a negative argument. - -@item @code{C-x 2} (@code{split-window}) -@cindex windows, creating -@kindex C-x 2 -@findex split-window -Splits the current window into two windows, both showing the same node. -Each window is one half the size of the original window, and the cursor -remains in the original window. The variable @code{automatic-tiling} -can cause all of the windows on the screen to be resized for you -automatically, please @pxref{Variables, , automatic-tiling} for more -information. - -@item @code{C-x 0} (@code{delete-window}) -@cindex windows, deleting -@kindex C-x 0 -@findex delete-window -Deletes the current window from the screen. If you have made too many -windows and your screen appears cluttered, this is the way to get rid of -some of them. - -@item @code{C-x 1} (@code{keep-one-window}) -@kindex C-x 1 -@findex keep-one-window -Deletes all of the windows excepting the current one. - -@item @code{ESC C-v} (@code{scroll-other-window}) -@kindex ESC C-v, in Info windows -@findex scroll-other-window -Scrolls the other window, in the same fashion that @samp{C-v} might -scroll the current window. Given a negative argument, the "other" -window is scrolled backward. - -@item @code{C-x ^} (@code{grow-window}) -@kindex C-x ^ -@findex grow-window -Grows (or shrinks) the current window. Given a numeric argument, grows -the current window that many lines; with a negative numeric argument, -the window is shrunk instead. - -@item @code{C-x t} (@code{tile-windows}) -@cindex tiling -@kindex C-x t -@findex tile-windows -Divides the available screen space among all of the visible windows. -Each window is given an equal portion of the screen in which to display -its contents. The variable @code{automatic-tiling} can cause -@code{tile-windows} to be called when a window is created or deleted. -@xref{Variables, , @code{automatic-tiling}}. -@end table - -@node The Echo Area -@section The Echo Area -@cindex echo area - -The @dfn{echo area} is a one line window which appears at the bottom of -the screen. It is used to display informative or error messages, and to -read lines of input from you when that is necessary. Almost all of the -commands available in the echo area are identical to their Emacs -counterparts, so please refer to that documentation for greater depth of -discussion on the concepts of editing a line of text. The following -table briefly lists the commands that are available while input is being -read in the echo area: - -@table @asis -@item @code{C-f} (@code{echo-area-forward}) -@kindex C-f, in the echo area -@findex echo-area-forward -Moves forward a character. - -@item @code{C-b} (@code{echo-area-backward}) -@kindex C-b, in the echo area -@findex echo-area-backward -Moves backward a character. - -@item @code{C-a} (@code{echo-area-beg-of-line}) -@kindex C-a, in the echo area -@findex echo-area-beg-of-line -Moves to the start of the input line. - -@item @code{C-e} (@code{echo-area-end-of-line}) -@kindex C-e, in the echo area -@findex echo-area-end-of-line -Moves to the end of the input line. - -@item @code{M-f} (@code{echo-area-forward-word}) -@kindex M-f, in the echo area -@findex echo-area-forward-word -Moves forward a word. - -@item @code{M-b} (@code{echo-area-backward-word}) -@kindex M-b, in the echo area -@findex echo-area-backward-word -Moves backward a word. - -@item @code{C-d} (@code{echo-area-delete}) -@kindex C-d, in the echo area -@findex echo-area-delete -Deletes the character under the cursor. - -@item @code{DEL} (@code{echo-area-rubout}) -@kindex DEL, in the echo area -@findex echo-area-rubout -Deletes the character behind the cursor. - -@item @code{C-g} (@code{echo-area-abort}) -@kindex C-g, in the echo area -@findex echo-area-abort -Cancels or quits the current operation. If completion is being read, -@samp{C-g} discards the text of the input line which does not match any -completion. If the input line is empty, @samp{C-g} aborts the calling -function. - -@item @code{RET} (@code{echo-area-newline}) -@kindex RET, in the echo area -@findex echo-area-newline -Accepts (or forces completion of) the current input line. - -@item @code{C-q} (@code{echo-area-quoted-insert}) -@kindex C-q, in the echo area -@findex echo-area-quoted-insert -Inserts the next character verbatim. This is how you can insert control -characters into a search string, for example. - -@item @var{printing character} (@code{echo-area-insert}) -@kindex printing characters, in the echo area -@findex echo-area-insert -Inserts the character. - -@item @code{M-TAB} (@code{echo-area-tab-insert}) -@kindex M-TAB, in the echo area -@findex echo-area-tab-insert -Inserts a TAB character. - -@item @code{C-t} (@code{echo-area-transpose-chars}) -@kindex C-t, in the echo area -@findex echo-area-transpose-chars -Transposes the characters at the cursor. -@end table - -The next group of commands deal with @dfn{killing}, and @dfn{yanking} -text. For an in depth discussion of killing and yanking, -@pxref{Killing, , Killing and Deleting, emacs, the GNU Emacs Manual} - -@table @asis -@item @code{M-d} (@code{echo-area-kill-word}) -@kindex M-d, in the echo area -@findex echo-area-kill-word -Kills the word following the cursor. - -@item @code{M-DEL} (@code{echo-area-backward-kill-word}) -@kindex M-DEL, in the echo area -@findex echo-area-backward-kill-word -Kills the word preceding the cursor. - -@item @code{C-k} (@code{echo-area-kill-line}) -@kindex C-k, in the echo area -@findex echo-area-kill-line -Kills the text from the cursor to the end of the line. - -@item @code{C-x DEL} (@code{echo-area-backward-kill-line}) -@kindex C-x DEL, in the echo area -@findex echo-area-backward-kill-line -Kills the text from the cursor to the beginning of the line. - -@item @code{C-y} (@code{echo-area-yank}) -@kindex C-y, in the echo area -@findex echo-area-yank -Yanks back the contents of the last kill. - -@item @code{M-y} (@code{echo-area-yank-pop}) -@kindex M-y, in the echo area -@findex echo-area-yank-pop -Yanks back a previous kill, removing the last yanked text first. -@end table - -Sometimes when reading input in the echo area, the command that needed -input will only accept one of a list of several choices. The choices -represent the @dfn{possible completions}, and you must respond with one -of them. Since there are a limited number of responses you can make, -Info allows you to abbreviate what you type, only typing as much of the -response as is necessary to uniquely identify it. In addition, you can -request Info to fill in as much of the response as is possible; this -is called @dfn{completion}. - -The following commands are available when completing in the echo area: - -@table @asis -@item @code{TAB} (@code{echo-area-complete}) -@itemx @code{SPC} -@kindex TAB, in the echo area -@kindex SPC, in the echo area -@findex echo-area-complete -Inserts as much of a completion as is possible. - -@item @code{?} (@code{echo-area-possible-completions}) -@kindex ?, in the echo area -@findex echo-area-possible-completions -Displays a window containing a list of the possible completions of what -you have typed so far. For example, if the available choices are: -@example -bar -foliate -food -forget -@end example -and you have typed an @samp{f}, followed by @samp{?}, the possible -completions would contain: -@example -foliate -food -forget -@end example -i.e., all of the choices which begin with @samp{f}. Pressing @key{SPC} -or @key{TAB} would result in @samp{fo} appearing in the echo area, since -all of the choices which begin with @samp{f} continue with @samp{o}. -Now, typing @samp{l} followed by @samp{TAB} results in @samp{foliate} -appearing in the echo area, since that is the only choice which begins -with @samp{fol}. - -@item @code{ESC C-v} (@code{echo-area-scroll-completions-window}) -@kindex ESC C-v, in the echo area -@findex echo-area-scroll-completions-window -Scrolls the completions window, if that is visible, or the "other" -window if not. -@end table - -@node Printing Nodes -@chapter Printing Out Nodes -@cindex printing - -You may wish to print out the contents of a node as a quick reference -document for later use. Info provides you with a command for doing -this. In general, we recommend that you use @TeX{} to format the -document and print sections of it, by running @code{tex} on the texinfo -source file. - -@table @asis -@item @code{M-x print-node} -@findex print-node -@cindex INFO_PRINT_COMMAND, environment variable -Pipes the contents of the current node through the command in the -environment variable @code{INFO_PRINT_COMMAND}. If the variable doesn't -exist, the node is simply piped to @code{lpr}. -@end table - -@node Miscellaneous Commands -@chapter Miscellaneous Commands - -GNU Info contains several commands which self-document GNU Info: - -@table @asis -@item @code{M-x describe-command} -@cindex functions, describing -@cindex commands, describing -@findex describe-command -Reads the name of an Info command in the echo area and then displays a -brief description of what that command does. - -@item @code{M-x describe-key} -@cindex keys, describing -@findex describe-key -Reads a key sequence in the echo area, and then displays the name and -documentation of the Info command that the key sequence invokes. - -@item @code{M-x describe-variable} -Reads the name of a variable in the echo area and then displays a brief -description of what the variable affects. - -@item @code{M-x where-is} -@findex where-is -Reads the name of an Info command in the echo area, and then displays -a key sequence which can be typed in order to invoke that command. - -@item @code{C-h} (@code{get-help-window}) -@itemx @code{?} -@kindex C-h -@kindex ?, in Info windows -@findex get-help-window -Creates (or moves into) the window displaying @code{*Help*}, and places -a node containing a quick reference card into it. This window displays -the most concise information about GNU Info available. - -@item @code{h} (@code{get-info-help-node}) -@kindex h -@findex get-info-help-node -Tries hard to visit the node @code{(info)Help}. The info file -@file{info.texi} distributed with GNU Info contains this node. Of -course, the file must first be processed with @code{makeinfo}, and then -placed into the location of your info directory. -@end table - -Here are the commands for creating a numeric argument: - -@table @asis -@item @code{C-u} (@code{universal-argument}) -@cindex numeric arguments -@kindex C-u -@findex universal-argument -Starts (or multiplies by 4) the current numeric argument. @samp{C-u} is -a good way to give a small numeric argument to cursor movement or -scrolling commands; @samp{C-u C-v} scrolls the screen 4 lines, while -@samp{C-u C-u C-n} moves the cursor down 16 lines. - -@item @code{M-1} (@code{add-digit-to-numeric-arg}) -@itemx @code{M-2} @dots{} @code{M-9} -@kindex M-1 @dots{} M-9 -@findex add-digit-to-numeric-arg -Adds the digit value of the invoking key to the current numeric -argument. Once Info is reading a numeric argument, you may just type -the digits of the argument, without the Meta prefix. For example, you -might give @samp{C-l} a numeric argument of 32 by typing: - -@example -@kbd{C-u 3 2 C-l} -@end example -or -@example -@kbd{M-3 2 C-l} -@end example -@end table - -@samp{C-g} is used to abort the reading of a multi-character key -sequence, to cancel lengthy operations (such as multi-file searches) and -to cancel reading input in the echo area. - -@table @asis -@item @code{C-g} (@code{abort-key}) -@cindex cancelling typeahead -@cindex cancelling the current operation -@kindex C-g, in Info windows -@findex abort-key -Cancels current operation. -@end table - -The @samp{q} command of Info simply quits running Info. - -@table @asis -@item @code{q} (@code{quit}) -@cindex quitting -@kindex q -@findex quit -Exits GNU Info. -@end table - -If the operating system tells GNU Info that the screen is 60 lines tall, -and it is actually only 40 lines tall, here is a way to tell Info that -the operating system is correct. - -@table @asis -@item @code{M-x set-screen-height} -@findex set-screen-height -@cindex screen, changing the height of -Reads a height value in the echo area and sets the height of the -displayed screen to that value. -@end table - -Finally, Info provides a convenient way to display footnotes which might -be associated with the current node that you are viewing: - -@table @asis -@item @code{ESC C-f} (@code{show-footnotes}) -@kindex ESC C-f -@findex show-footnotes -@cindex footnotes, displaying -Shows the footnotes (if any) associated with the current node in another -window. You can have Info automatically display the footnotes -associated with a node when the node is selected by setting the variable -@code{automatic-footnotes}. @xref{Variables, , @code{automatic-footnotes}}. -@end table - -@node Variables -@chapter Manipulating Variables - -GNU Info contains several @dfn{variables} whose values are looked at by various -Info commands. You can change the values of these variables, and thus -change the behaviour of Info to more closely match your environment and -info file reading manner. - -@table @asis -@item @code{M-x set-variable} -@cindex variables, setting -@findex set-variable -Reads the name of a variable, and the value for it, in the echo area and -then sets the variable to that value. Completion is available when -reading the variable name; often, completion is available when reading -the value to give to the variable, but that depends on the variable -itself. If a variable does @emph{not} supply multiple choices to -complete over, it expects a numeric value. - -@item @code{M-x describe-variable} -@cindex variables, describing -@findex describe-variable -Reads the name of a variable in the echo area and then displays a brief -description of what the variable affects. -@end table - -Here is a list of the variables that you can set in Info. - -@table @code -@item automatic-footnotes -@vindex automatic-footnotes -When set to @code{On}, footnotes appear and disappear automatically. -This variable is @code{On} by default. When a node is selected, a -window containing the footnotes which appear in that node is created, -and the footnotes are displayed within the new window. The window that -Info creates to contain the footnotes is called @samp{*Footnotes*}. If -a node is selected which contains no footnotes, and a @samp{*Footnotes*} -window is on the screen, the @samp{*Footnotes*} window is deleted. -Footnote windows created in this fashion are not automatically tiled so -that they can use as little of the display as is possible. - -@item automatic-tiling -@vindex automatic-tiling -When set to @code{On}, creating or deleting a window resizes other -windows. This variable is @code{Off} by default. Normally, typing -@samp{C-x 2} divides the current window into two equal parts. When -@code{automatic-tiling} is set to @code{On}, all of the windows are -resized automatically, keeping an equal number of lines visible in each -window. There are exceptions to the automatic tiling; specifically, the -windows @samp{*Completions*} and @samp{*Footnotes*} are @emph{not} -resized through automatic tiling; they remain their original size. - -@item visible-bell -@vindex visible-bell -When set to @code{On}, GNU Info attempts to flash the screen instead of -ringing the bell. This variable is @code{Off} by default. Of course, -Info can only flash the screen if the terminal allows it; in the case -that the terminal does not allow it, the setting of this variable has no -effect. However, you can make Info perform quietly by setting the -@code{errors-ring-bell} variable to @code{Off}. - -@item errors-ring-bell -@vindex errors-ring-bell -When set to @code{On}, errors cause the bell to ring. The default -setting of this variable is @code{On}. - -@item gc-compressed-files -@vindex gc-compressed-files -When set to @code{On}, Info garbage collects files which had to be -uncompressed. The default value of this variable is @code{Off}. -Whenever a node is visited in Info, the info file containing that node -is read into core, and Info reads information about the tags and nodes -contained in that file. Once the tags information is read by Info, it -is never forgotten. However, the actual text of the nodes does not need -to remain in core unless a particular info window needs it. For -non-compressed files, the text of the nodes does not remain in core when -it is no longer in use. But de-compressing a file can be a time -consuming operation, and so Info tries hard not to do it twice. -@code{gc-compressed-files} tells Info it is okay to garbage collect the -text of the nodes of a file which was compressed on disk. - -@item show-index-match -@vindex show-index-match -When set to @code{On}, the portion of the matched search string is -highlighted in the message which explains where the matched search -string was found. The default value of this variable is @code{On}. -When Info displays the location where an index match was found, -(@pxref{Searching Commands, , @code{next-index-match}}), the portion of the -string that you had typed is highlighted by displaying it in the inverse -case from its surrounding characters. - -@item scroll-behaviour -@vindex scroll-behaviour -Controls what happens when forward scrolling is requested at the end of -a node, or when backward scrolling is requested at the beginning of a -node. The default value for this variable is @code{Continuous}. There -are three possible values for this variable: - -@table @code -@item Continuous -Tries to get the first item in this node's menu, or failing that, the -@samp{Next} node, or failing that, the @samp{Next} of the @samp{Up}. -This behaviour is identical to using the @samp{]} -(@code{global-next-node}) and @samp{[} (@code{global-prev-node}) -commands. - -@item Next Only -Only tries to get the @samp{Next} node. - -@item Page Only -Simply gives up, changing nothing. If @code{scroll-behaviour} is -@code{Page Only}, no scrolling command can change the node that is being -viewed. -@end table - -@item scroll-step -@vindex scroll-step -The number of lines to scroll when the cursor moves out of the window. -Scrolling happens automatically if the cursor has moved out of the -visible portion of the node text when it is time to display. Usually -the scrolling is done so as to put the cursor on the center line of the -current window. However, if the variable @code{scroll-step} has a -nonzero value, Info attempts to scroll the node text by that many lines; -if that is enough to bring the cursor back into the window, that is what -is done. The default value of this variable is 0, thus placing the -cursor (and the text it is attached to) in the center of the window. -Setting this variable to 1 causes a kind of "smooth scrolling" which -some people prefer. - -@item ISO-Latin -@cindex ISO Latin characters -@vindex ISO-Latin -When set to @code{On}, Info accepts and displays ISO Latin characters. -By default, Info assumes an ASCII character set. @code{ISO-Latin} tells -Info that it is running in an environment where the European standard -character set is in use, and allows you to input such characters to -Info, as well as display them. -@end table - -@c The following node and its children are currently unfinished. Please feel -@c free to finish it! - -@ifset NOTSET -@node Info for Sys Admins -@chapter Info for System Administrators - -This text describes some common ways of setting up an Info heierarchy -from scratch, and details the various options that are available when -installing Info. This text is designed for the person who is installing -GNU Info on the system; although users may find the information present -in this section interesting, none of it is vital to understanding how to -use GNU Info. - -@menu -* Setting the INFOPATH:: Where are my Info files kept? -* Editing the DIR node:: What goes in `DIR', and why? -* Storing Info files:: Alternate formats allow flexibilty in setups. -* Using `localdir':: Building DIR on the fly. -* Example setups:: Some common ways to origanize Info files. -@end menu - -@node Setting the INFOPATH -@section Setting the INFOPATH -Where are my Info files kept? - -@node Editing the DIR node -@section Editing the DIR node -What goes in `DIR', and why? - -@node Storing Info files -@section Storing Info files -Alternate formats allow flexibilty in setups. - -@node Using `localdir' -@section Using `localdir' -Building DIR on the fly. - -@node Example setups -@section Example setups -Some common ways to origanize Info files. -@end ifset - -@ifset STANDALONE -@node GNU Info Global Index -@appendix Global Index -@printindex cp -@end ifset diff --git a/info/variables.c b/info/variables.c deleted file mode 100644 --- a/info/variables.c +++ /dev/null @@ -1,272 +0,0 @@ -/* variables.c -- How to manipulate user visible variables in Info. */ - -/* 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 "variables.h" - -/* **************************************************************** */ -/* */ -/* User Visible Variables in Info */ -/* */ -/* **************************************************************** */ - -/* Choices used by the completer when reading a zero/non-zero value for - a variable. */ -static char *on_off_choices[] = { "Off", "On", (char *)NULL }; - -VARIABLE_ALIST info_variables[] = { - { "automatic-footnotes", - "When \"On\", footnotes appear and disappear automatically", - &auto_footnotes_p, (char **)on_off_choices }, - - { "automatic-tiling", - "When \"On\", creating or deleting a window resizes other windows", - &auto_tiling_p, (char **)on_off_choices }, - - { "visible-bell", - "When \"On\", flash the screen instead of ringing the bell", - &terminal_use_visible_bell_p, (char **)on_off_choices }, - - { "errors-ring-bell", - "When \"On\", errors cause the bell to ring", - &info_error_rings_bell_p, (char **)on_off_choices }, - - { "gc-compressed-files", - "When \"On\", Info garbage collects files which had to be uncompressed", - &gc_compressed_files, (char **)on_off_choices }, - { "show-index-match", - "When \"On\", the portion of the matched search string is highlighted", - &show_index_match, (char **)on_off_choices }, - - { "scroll-behaviour", - "Controls what happens when scrolling is requested at the end of a node", - &info_scroll_behaviour, (char **)info_scroll_choices }, - - { "scroll-step", - "The number lines to scroll when the cursor moves out of the window", - &window_scroll_step, (char **)NULL }, - - { "ISO-Latin", - "When \"On\", Info accepts and displays ISO Latin characters", - &ISO_Latin_p, (char **)on_off_choices }, - - { (char *)NULL, (char *)NULL, (int *)NULL, (char **)NULL } -}; - -DECLARE_INFO_COMMAND (describe_variable, "Explain the use of a variable") -{ - VARIABLE_ALIST *var; - char *description; - - /* Get the variable's name. */ - var = read_variable_name ("Describe variable: ", window); - - if (!var) - return; - - description = (char *)xmalloc (20 + strlen (var->name) + strlen (var->doc)); - - if (var->choices) - sprintf (description, "%s (%s): %s.", - var->name, var->choices[*(var->value)], var->doc); - else - sprintf (description, "%s (%d): %s.", var->name, *(var->value), var->doc); - - window_message_in_echo_area ("%s", description); - free (description); -} - -DECLARE_INFO_COMMAND (set_variable, "Set the value of an Info variable") -{ - VARIABLE_ALIST *var; - char *line; - - /* Get the variable's name and value. */ - var = read_variable_name ("Set variable: ", window); - - if (!var) - return; - - /* Read a new value for this variable. */ - { - char prompt[100]; - - if (!var->choices) - { - int potential_value; - - if (info_explicit_arg || count != 1) - potential_value = count; - else - potential_value = *(var->value); - - sprintf (prompt, "Set %s to value (%d): ", - var->name, potential_value); - line = info_read_in_echo_area (active_window, prompt); - - /* If no error was printed, clear the echo area. */ - if (!info_error_was_printed) - window_clear_echo_area (); - - /* User aborted? */ - if (!line) - return; - - /* If the user specified a value, get that, otherwise, we are done. */ - canonicalize_whitespace (line); - if (*line) - *(var->value) = atoi (line); - else - *(var->value) = potential_value; - - free (line); - } - else - { - register int i; - REFERENCE **array = (REFERENCE **)NULL; - int array_index = 0; - int array_slots = 0; - - for (i = 0; var->choices[i]; i++) - { - REFERENCE *entry; - - entry = (REFERENCE *)xmalloc (sizeof (REFERENCE)); - entry->label = strdup (var->choices[i]); - entry->nodename = (char *)NULL; - entry->filename = (char *)NULL; - - add_pointer_to_array - (entry, array_index, array, array_slots, 10, REFERENCE *); - } - - sprintf (prompt, "Set %s to value (%s): ", - var->name, var->choices[*(var->value)]); - - /* Ask the completer to read a variable value for us. */ - line = info_read_completing_in_echo_area (window, prompt, array); - - info_free_references (array); - - if (!echo_area_is_active) - window_clear_echo_area (); - - /* User aborted? */ - if (!line) - { - info_abort_key (active_window, 0, 0); - return; - } - - /* User accepted default choice? If so, no change. */ - if (!*line) - { - free (line); - return; - } - - /* Find the choice in our list of choices. */ - for (i = 0; var->choices[i]; i++) - if (strcmp (var->choices[i], line) == 0) - break; - - if (var->choices[i]) - *(var->value) = i; - } - } -} - -/* Read the name of an Info variable in the echo area and return the - address of a VARIABLE_ALIST member. A return value of NULL indicates - that no variable could be read. */ -VARIABLE_ALIST * -read_variable_name (prompt, window) - char *prompt; - WINDOW *window; -{ - register int i; - char *line; - REFERENCE **variables; - - /* Get the completion array of variable names. */ - variables = make_variable_completions_array (); - - /* Ask the completer to read a variable for us. */ - line = - info_read_completing_in_echo_area (window, prompt, variables); - - info_free_references (variables); - - if (!echo_area_is_active) - window_clear_echo_area (); - - /* User aborted? */ - if (!line) - { - info_abort_key (active_window, 0, 0); - return ((VARIABLE_ALIST *)NULL); - } - - /* User accepted "default"? (There is none.) */ - if (!*line) - { - free (line); - return ((VARIABLE_ALIST *)NULL); - } - - /* Find the variable in our list of variables. */ - for (i = 0; info_variables[i].name; i++) - if (strcmp (info_variables[i].name, line) == 0) - break; - - if (!info_variables[i].name) - return ((VARIABLE_ALIST *)NULL); - else - return (&(info_variables[i])); -} - -/* Make an array of REFERENCE which actually contains the names of the - variables available in Info. */ -REFERENCE ** -make_variable_completions_array () -{ - register int i; - REFERENCE **array = (REFERENCE **)NULL; - int array_index = 0, array_slots = 0; - - for (i = 0; info_variables[i].name; i++) - { - REFERENCE *entry; - - entry = (REFERENCE *)xmalloc (sizeof (REFERENCE)); - entry->label = strdup (info_variables[i].name); - entry->nodename = (char *)NULL; - entry->filename = (char *)NULL; - - add_pointer_to_array - (entry, array_index, array, array_slots, 200, REFERENCE *); - } - - return (array); -} diff --git a/info/variables.h b/info/variables.h deleted file mode 100644 --- a/info/variables.h +++ /dev/null @@ -1,64 +0,0 @@ -/* variables.h -- Description of user visible variables in Info. */ - -/* 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). */ - -#if !defined (_VARIABLES_H_) -#define _VARIABLES_H_ - -/* A variable (in the Info sense) is an integer value with a user-visible - name. You may supply an array of strings to complete over when the - variable is set; in that case, the variable is set to the index of the - string that the user chose. If you supply a null list, the user can - set the variable to a numeric value. */ - -/* Structure describing a user visible variable. */ -typedef struct { - char *name; /* Polite name. */ - char *doc; /* Documentation string. */ - int *value; /* Address of value. */ - char **choices; /* Array of strings or NULL if numeric only. */ -} VARIABLE_ALIST; - -/* Read the name of an Info variable in the echo area and return the - address of a VARIABLE_ALIST member. A return value of NULL indicates - that no variable could be read. */ -extern VARIABLE_ALIST *read_variable_name (); - -/* Make an array of REFERENCE which actually contains the names of the - variables available in Info. */ -extern REFERENCE **make_variable_completions_array (); - -/* Set the value of an info variable. */ -extern void set_variable (); - -/* The list of user-visible variables. */ -extern int auto_footnotes_p; -extern int auto_tiling_p; -extern int terminal_use_visible_bell_p; -extern int info_error_rings_bell_p; -extern int gc_compressed_files; -extern int show_index_match; -extern int info_scroll_behaviour; -extern int window_scroll_step; -extern int ISO_Latin_p; - -#endif /* _VARIABLES_H_ */ diff --git a/info/window.c b/info/window.c deleted file mode 100644 --- a/info/window.c +++ /dev/null @@ -1,1482 +0,0 @@ -/* window.c -- Windows in Info. */ - -/* 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 -#include -#include -#include -#include "nodes.h" -#include "window.h" -#include "display.h" -#include "info-utils.h" -#include "infomap.h" - -/* The window which describes the screen. */ -WINDOW *the_screen = (WINDOW *)NULL; - -/* The window which describes the echo area. */ -WINDOW *the_echo_area = (WINDOW *)NULL; - -/* The list of windows in Info. */ -WINDOW *windows = (WINDOW *)NULL; - -/* Pointer to the active window in WINDOW_LIST. */ -WINDOW *active_window = (WINDOW *)NULL; - -/* The size of the echo area in Info. It never changes, irregardless of the - size of the screen. */ -#define ECHO_AREA_HEIGHT 1 - -/* Macro returns the amount of space that the echo area truly requires relative - to the entire screen. */ -#define echo_area_required (1 + the_echo_area->height) - -/* Initalize the window system by creating THE_SCREEN and THE_ECHO_AREA. - Create the first window ever. - You pass the dimensions of the total screen size. */ -void -window_initialize_windows (width, height) - int width, height; -{ - the_screen = (WINDOW *)xmalloc (sizeof (WINDOW)); - the_echo_area = (WINDOW *)xmalloc (sizeof (WINDOW)); - windows = (WINDOW *)xmalloc (sizeof (WINDOW)); - active_window = windows; - - zero_mem (the_screen, sizeof (WINDOW)); - zero_mem (the_echo_area, sizeof (WINDOW)); - zero_mem (active_window, sizeof (WINDOW)); - - /* None of these windows has a goal column yet. */ - the_echo_area->goal_column = -1; - active_window->goal_column = -1; - the_screen->goal_column = -1; - - /* The active and echo_area windows are visible. - The echo_area is permanent. - The screen is permanent. */ - active_window->flags = W_WindowVisible; - the_echo_area->flags = W_WindowIsPerm | W_InhibitMode | W_WindowVisible; - the_screen->flags = W_WindowIsPerm; - - /* The height of the echo area never changes. It is statically set right - here, and it must be at least 1 line for display. The size of the - initial window cannot be the same size as the screen, since the screen - includes the echo area. So, we make the height of the initial window - equal to the screen's displayable region minus the height of the echo - area. */ - the_echo_area->height = ECHO_AREA_HEIGHT; - active_window->height = the_screen->height - 1 - the_echo_area->height; - window_new_screen_size (width, height, (VFunction *)NULL); - - /* The echo area uses a different keymap than normal info windows. */ - the_echo_area->keymap = echo_area_keymap; - active_window->keymap = info_keymap; -} - -/* Given that the size of the screen has changed to WIDTH and HEIGHT - from whatever it was before (found in the_screen->height, ->width), - change the size (and possibly location) of each window in the screen. - If a window would become too small, call the function DELETER on it, - after deleting the window from our chain of windows. If DELETER is NULL, - nothing extra is done. The last window can never be deleted, but it can - become invisible. */ - -/* If non-null, a function to call with WINDOW as argument when the function - window_new_screen_size () has deleted WINDOW. */ -VFunction *window_deletion_notifier = (VFunction *)NULL; - -void -window_new_screen_size (width, height) - int width, height; -{ - register WINDOW *win; - int delta_height, delta_each, delta_leftover; - int numwins; - - /* If no change, do nothing. */ - if (width == the_screen->width && height == the_screen->height) - return; - - /* If the new window height is too small, make it be zero. */ - if (height < (WINDOW_MIN_SIZE + the_echo_area->height)) - height = 0; - if (width < 0) - width = 0; - - /* Find out how many windows will change. */ - for (numwins = 0, win = windows; win; win = win->next, numwins++); - - /* See if some windows will need to be deleted. This is the case if - the screen is getting smaller, and the available space divided by - the number of windows is less than WINDOW_MIN_SIZE. In that case, - delete some windows and try again until there is either enough - space to divy up among the windows, or until there is only one - window left. */ - while ((height - echo_area_required) / numwins <= WINDOW_MIN_SIZE) - { - /* If only one window, make the size of it be zero, and return - immediately. */ - if (!windows->next) - { - windows->height = 0; - maybe_free (windows->line_starts); - windows->line_starts = (char **)NULL; - windows->line_count = 0; - break; - } - - /* If we have some temporary windows, delete one of them. */ - for (win = windows; win; win = win->next) - if (win->flags & W_TempWindow) - break; - - /* Otherwise, delete the first window, and try again. */ - if (!win) - win = windows; - - if (window_deletion_notifier) - (*window_deletion_notifier) (win); - - window_delete_window (win); - numwins--; - } - - /* The screen has changed height and width. */ - delta_height = height - the_screen->height; /* This is how much. */ - the_screen->height = height; /* This is the new height. */ - the_screen->width = width; /* This is the new width. */ - - /* Set the start of the echo area. */ - the_echo_area->first_row = height - the_echo_area->height; - the_echo_area->width = width; - - /* Check to see if the screen can really be changed this way. */ - if ((!windows->next) && ((windows->height == 0) && (delta_height < 0))) - return; - - /* Divide the change in height among the available windows. */ - delta_each = delta_height / numwins; - delta_leftover = delta_height - (delta_each * numwins); - - /* Change the height of each window in the chain by delta_each. Change - the height of the last window in the chain by delta_each and by the - leftover amount of change. Change the width of each window to be - WIDTH. */ - for (win = windows; win; win = win->next) - { - if ((win->width != width) && ((win->flags & W_InhibitMode) == 0)) - { - win->width = width; - maybe_free (win->modeline); - win->modeline = (char *)xmalloc (1 + width); - } - - win->height += delta_each; - - /* If the previous height of this window was zero, it was the only - window, and it was not visible. Thus we need to compensate for - the echo_area. */ - if (win->height == delta_each) - win->height -= (1 + the_echo_area->height); - - /* If this is not the first window in the chain, then change the - first row of it. We cannot just add delta_each to the first row, - since this window's first row is the sum of the collective increases - that have gone before it. So we just add one to the location of the - previous window's modeline. */ - if (win->prev) - win->first_row = (win->prev->first_row + win->prev->height) + 1; - - /* The last window in the chain gets the extra space (or shrinkage). */ - if (!win->next) - win->height += delta_leftover; - - if (win->node) - recalculate_line_starts (win); - - win->flags |= W_UpdateWindow; - } - - /* If the screen got smaller, check over the windows just shrunk to - keep them within bounds. Some of the windows may have gotten smaller - than WINDOW_MIN_HEIGHT in which case some of the other windows are - larger than the available display space in the screen. Because of our - intial test above, we know that there is enough space for all of the - windows. */ - if ((delta_each < 0) && ((windows->height != 0) && windows->next)) - { - int avail; - - avail = the_screen->height - (numwins + the_echo_area->height); - win = windows; - - while (win) - { - if ((win->height < WINDOW_MIN_HEIGHT) || - (win->height > avail)) - { - WINDOW *lastwin; - - /* Split the space among the available windows. */ - delta_each = avail / numwins; - delta_leftover = avail - (delta_each * numwins); - - for (win = windows; win; win = win->next) - { - lastwin = win; - if (win->prev) - win->first_row = - (win->prev->first_row + win->prev->height) + 1; - win->height = delta_each; - } - - /* Give the leftover space (if any) to the last window. */ - lastwin->height += delta_leftover; - break; - } - else - win= win->next; - } - } -} - -/* Make a new window showing NODE, and return that window structure. - If NODE is passed as NULL, then show the node showing in the active - window. If the window could not be made return a NULL pointer. The - active window is not changed.*/ -WINDOW * -window_make_window (node) - NODE *node; -{ - WINDOW *window; - - if (!node) - node = active_window->node; - - /* If there isn't enough room to make another window, return now. */ - if ((active_window->height / 2) < WINDOW_MIN_SIZE) - return ((WINDOW *)NULL); - - /* Make and initialize the new window. - The fudging about with -1 and +1 is because the following window in the - chain cannot start at window->height, since that is where the modeline - for the previous window is displayed. The inverse adjustment is made - in window_delete_window (). */ - window = (WINDOW *)xmalloc (sizeof (WINDOW)); - window->width = the_screen->width; - window->height = (active_window->height / 2) - 1; -#if defined (SPLIT_BEFORE_ACTIVE) - window->first_row = active_window->first_row; -#else - window->first_row = active_window->first_row + - (active_window->height - window->height); -#endif - window->keymap = info_keymap; - window->goal_column = -1; - window->modeline = (char *)xmalloc (1 + window->width); - window->line_starts = (char **)NULL; - window->flags = W_UpdateWindow | W_WindowVisible; - window_set_node_of_window (window, node); - - /* Adjust the height of the old active window. */ - active_window->height -= (window->height + 1); -#if defined (SPLIT_BEFORE_ACTIVE) - active_window->first_row += (window->height + 1); -#endif - active_window->flags |= W_UpdateWindow; - - /* Readjust the new and old windows so that their modelines and contents - will be displayed correctly. */ -#if defined (NOTDEF) - /* We don't have to do this for WINDOW since window_set_node_of_window () - already did. */ - window_adjust_pagetop (window); - window_make_modeline (window); -#endif /* NOTDEF */ - - /* We do have to readjust the existing active window. */ - window_adjust_pagetop (active_window); - window_make_modeline (active_window); - -#if defined (SPLIT_BEFORE_ACTIVE) - /* This window is just before the active one. The active window gets - bumped down one. The active window is not changed. */ - window->next = active_window; - - window->prev = active_window->prev; - active_window->prev = window; - - if (window->prev) - window->prev->next = window; - else - windows = window; -#else - /* This window is just after the active one. Which window is active is - not changed. */ - window->prev = active_window; - window->next = active_window->next; - active_window->next = window; - if (window->next) - window->next->prev = window; -#endif /* !SPLIT_BEFORE_ACTIVE */ - return (window); -} - -/* These useful macros make it possible to read the code in - window_change_window_height (). */ -#define grow_me_shrinking_next(me, next, diff) \ - do { \ - me->height += diff; \ - next->height -= diff; \ - next->first_row += diff; \ - window_adjust_pagetop (next); \ - } while (0) - -#define grow_me_shrinking_prev(me, prev, diff) \ - do { \ - me->height += diff; \ - prev->height -= diff; \ - me->first_row -=diff; \ - window_adjust_pagetop (prev); \ - } while (0) - -#define shrink_me_growing_next(me, next, diff) \ - do { \ - me->height -= diff; \ - next->height += diff; \ - next->first_row -= diff; \ - window_adjust_pagetop (next); \ - } while (0) - -#define shrink_me_growing_prev(me, prev, diff) \ - do { \ - me->height -= diff; \ - prev->height += diff; \ - me->first_row += diff; \ - window_adjust_pagetop (prev); \ - } while (0) - -/* Change the height of WINDOW by AMOUNT. This also automagically adjusts - the previous and next windows in the chain. If there is only one user - window, then no change takes place. */ -void -window_change_window_height (window, amount) - WINDOW *window; - int amount; -{ - register WINDOW *win, *prev, *next; - - /* If there is only one window, or if the amount of change is zero, - return immediately. */ - if (!windows->next || amount == 0) - return; - - /* Find this window in our chain. */ - for (win = windows; win; win = win->next) - if (win == window) - break; - - /* If the window is isolated (i.e., doesn't appear in our window list, - then quit now. */ - if (!win) - return; - - /* Change the height of this window by AMOUNT, if that is possible. - It can be impossible if there isn't enough available room on the - screen, or if the resultant window would be too small. */ - - prev = window->prev; - next = window->next; - - /* WINDOW decreasing in size? */ - if (amount < 0) - { - int abs_amount = -amount; /* It is easier to deal with this way. */ - - /* If the resultant window would be too small, stop here. */ - if ((window->height - abs_amount) < WINDOW_MIN_HEIGHT) - return; - - /* If we have two neighboring windows, choose the smaller one to get - larger. */ - if (next && prev) - { - if (prev->height < next->height) - shrink_me_growing_prev (window, prev, abs_amount); - else - shrink_me_growing_next (window, next, abs_amount); - } - else if (next) - shrink_me_growing_next (window, next, abs_amount); - else - shrink_me_growing_prev (window, prev, abs_amount); - } - - /* WINDOW increasing in size? */ - if (amount > 0) - { - int total_avail, next_avail = 0, prev_avail = 0; - - if (next) - next_avail = next->height - WINDOW_MIN_SIZE; - - if (prev) - prev_avail = prev->height - WINDOW_MIN_SIZE; - - total_avail = next_avail + prev_avail; - - /* If there isn't enough space available to grow this window, give up. */ - if (amount > total_avail) - return; - - /* If there aren't two neighboring windows, or if one of the neighbors - is larger than the other one by at least AMOUNT, grow that one. */ - if ((next && !prev) || ((next_avail - amount) >= prev_avail)) - grow_me_shrinking_next (window, next, amount); - else if ((prev && !next) || ((prev_avail - amount) >= next_avail)) - grow_me_shrinking_prev (window, prev, amount); - else - { - int change; - - /* This window has two neighbors. They both must be shrunk in to - make enough space for WINDOW to grow. Make them both the same - size. */ - if (prev_avail > next_avail) - { - change = prev_avail - next_avail; - grow_me_shrinking_prev (window, prev, change); - amount -= change; - } - else - { - change = next_avail - prev_avail; - grow_me_shrinking_next (window, next, change); - amount -= change; - } - - /* Both neighbors are the same size. Split the difference in - AMOUNT between them. */ - while (amount) - { - window->height++; - amount--; - - /* Odd numbers grow next, even grow prev. */ - if (amount & 1) - { - prev->height--; - window->first_row--; - } - else - { - next->height--; - next->first_row++; - } - } - window_adjust_pagetop (prev); - window_adjust_pagetop (next); - } - } - if (prev) - prev->flags |= W_UpdateWindow; - - if (next) - next->flags |= W_UpdateWindow; - - window->flags |= W_UpdateWindow; - window_adjust_pagetop (window); -} - -/* Tile all of the windows currently displayed in the global variable - WINDOWS. If argument STYLE is TILE_INTERNALS, tile windows displaying - internal nodes as well, otherwise do not change the height of such - windows. */ -void -window_tile_windows (style) - int style; -{ - WINDOW *win, *last_adjusted; - int numwins, avail, per_win_height, leftover; - int do_internals; - - numwins = avail = 0; - do_internals = (style == TILE_INTERNALS); - - for (win = windows; win; win = win->next) - if (do_internals || !win->node || - (win->node->flags & N_IsInternal) == 0) - { - avail += win->height; - numwins++; - } - - if (numwins <= 1 || !the_screen->height) - return; - - /* Find the size for each window. Divide the size of the usable portion - of the screen by the number of windows. */ - per_win_height = avail / numwins; - leftover = avail - (per_win_height * numwins); - - last_adjusted = (WINDOW *)NULL; - for (win = windows; win; win = win->next) - { - if (do_internals || !win->node || - (win->node->flags & N_IsInternal) == 0) - { - last_adjusted = win; - win->height = per_win_height; - } - } - - if (last_adjusted) - last_adjusted->height += leftover; - - /* Readjust the first_row of every window in the chain. */ - for (win = windows; win; win = win->next) - { - if (win->prev) - win->first_row = win->prev->first_row + win->prev->height + 1; - - window_adjust_pagetop (win); - win->flags |= W_UpdateWindow; - } -} - -/* Toggle the state of line wrapping in WINDOW. This can do a bit of fancy - redisplay. */ -void -window_toggle_wrap (window) - WINDOW *window; -{ - if (window->flags & W_NoWrap) - window->flags &= ~W_NoWrap; - else - window->flags |= W_NoWrap; - - if (window != the_echo_area) - { - char **old_starts; - int old_lines, old_pagetop; - - old_starts = window->line_starts; - old_lines = window->line_count; - old_pagetop = window->pagetop; - - calculate_line_starts (window); - - /* Make sure that point appears within this window. */ - window_adjust_pagetop (window); - - /* If the pagetop hasn't changed maybe we can do some scrolling now - to speed up the display. Many of the line starts will be the same, - so scrolling here is a very good optimization.*/ - if (old_pagetop == window->pagetop) - display_scroll_line_starts - (window, old_pagetop, old_starts, old_lines); - maybe_free (old_starts); - } - window->flags |= W_UpdateWindow; -} - -/* Set WINDOW to display NODE. */ -void -window_set_node_of_window (window, node) - WINDOW *window; - NODE *node; -{ - window->node = node; - window->pagetop = 0; - window->point = 0; - recalculate_line_starts (window); - window->flags |= W_UpdateWindow; - window_adjust_pagetop (window); - window_make_modeline (window); -} - -/* Delete WINDOW from the list of known windows. If this window was the - active window, make the next window in the chain be the active window. - If the active window is the next or previous window, choose that window - as the recipient of the extra space. Otherwise, prefer the next window. */ -void -window_delete_window (window) - WINDOW *window; -{ - WINDOW *next, *prev, *window_to_fix; - - next = window->next; - prev = window->prev; - - /* You cannot delete the only window or a permanent window. */ - if ((!next && !prev) || (window->flags & W_WindowIsPerm)) - return; - - if (next) - next->prev = prev; - - if (!prev) - windows = next; - else - prev->next = next; - - if (window->line_starts) - free (window->line_starts); - - if (window->modeline) - free (window->modeline); - - if (window == active_window) - { - /* If there isn't a next window, then there must be a previous one, - since we cannot delete the last window. If there is a next window, - prefer to use that as the active window. */ - if (next) - active_window = next; - else - active_window = prev; - } - - if (next && active_window == next) - window_to_fix = next; - else if (prev && active_window == prev) - window_to_fix = prev; - else if (next) - window_to_fix = next; - else if (prev) - window_to_fix = prev; - else - window_to_fix = windows; - - if (window_to_fix->first_row > window->first_row) - { - int diff; - - /* Try to adjust the visible part of the node so that as little - text as possible has to move. */ - diff = window_to_fix->first_row - window->first_row; - window_to_fix->first_row = window->first_row; - - window_to_fix->pagetop -= diff; - if (window_to_fix->pagetop < 0) - window_to_fix->pagetop = 0; - } - - /* The `+ 1' is to offset the difference between the first_row locations. - See the code in window_make_window (). */ - window_to_fix->height += window->height + 1; - window_to_fix->flags |= W_UpdateWindow; - - free (window); -} - -/* For every window in CHAIN, set the flags member to have FLAG set. */ -void -window_mark_chain (chain, flag) - WINDOW *chain; - int flag; -{ - register WINDOW *win; - - for (win = chain; win; win = win->next) - win->flags |= flag; -} - -/* For every window in CHAIN, clear the flags member of FLAG. */ -void -window_unmark_chain (chain, flag) - WINDOW *chain; - int flag; -{ - register WINDOW *win; - - for (win = chain; win; win = win->next) - win->flags &= ~flag; -} - -/* Return the number of characters it takes to display CHARACTER on the - screen at HPOS. */ -int -character_width (character, hpos) - int character, hpos; -{ - int printable_limit = 127; - int width = 1; - - if (ISO_Latin_p) - printable_limit = 160; - - if (character > printable_limit) - width = 3; - else if (iscntrl (character)) - { - switch (character) - { - case '\r': - case '\n': - width = the_screen->width - hpos; - break; - case '\t': - width = ((hpos + 8) & 0xf8) - hpos; - break; - default: - width = 2; - } - } - else if (character == DEL) - width = 2; - - return (width); -} - -/* Return the number of characters it takes to display STRING on the screen - at HPOS. */ -int -string_width (string, hpos) - char *string; - int hpos; -{ - register int i, width, this_char_width; - - for (width = 0, i = 0; string[i]; i++) - { - this_char_width = character_width (string[i], hpos); - width += this_char_width; - hpos += this_char_width; - } - return (width); -} - -/* Quickly guess the approximate number of lines to that NODE would - take to display. This really only counts carriage returns. */ -int -window_physical_lines (node) - NODE *node; -{ - register int i, lines; - char *contents; - - if (!node) - return (0); - - contents = node->contents; - for (i = 0, lines = 1; i < node->nodelen; i++) - if (contents[i] == '\n') - lines++; - - return (lines); -} - -/* Calculate a list of line starts for the node belonging to WINDOW. The line - starts are pointers to the actual text within WINDOW->NODE. */ -void -calculate_line_starts (window) - WINDOW *window; -{ - register int i, hpos; - char **line_starts = (char **)NULL; - int line_starts_index = 0, line_starts_slots = 0; - int bump_index; - NODE *node; - - window->line_starts = (char **)NULL; - window->line_count = 0; - node = window->node; - - if (!node) - return; - - /* Grovel the node starting at the top, and for each line calculate the - width of the characters appearing in that line. Add each line start - to our array. */ - i = 0; - hpos = 0; - bump_index = 0; - - while (i < node->nodelen) - { - char *line = node->contents + i; - unsigned int cwidth, c; - - add_pointer_to_array (line, line_starts_index, line_starts, - line_starts_slots, 100, char *); - if (bump_index) - { - i++; - bump_index = 0; - } - - while (1) - { - c = node->contents[i]; - cwidth = character_width (c, hpos); - - /* If this character fits within this line, just do the next one. */ - if ((hpos + cwidth) < window->width) - { - i++; - hpos += cwidth; - continue; - } - else - { - /* If this character would position the cursor at the start of - the next printed screen line, then do the next line. */ - if (c == '\n' || c == '\r' || c == '\t') - { - i++; - hpos = 0; - break; - } - else - { - /* This character passes the window width border. Postion - the cursor after the printed character, but remember this - line start as where this character is. A bit tricky. */ - - /* If this window doesn't wrap lines, proceed to the next - physical line here. */ - if (window->flags & W_NoWrap) - { - hpos = 0; - while (i < node->nodelen && node->contents[i] != '\n') - i++; - - if (node->contents[i] == '\n') - i++; - } - else - { - hpos = the_screen->width - hpos; - bump_index++; - } - break; - } - } - } - } - window->line_starts = line_starts; - window->line_count = line_starts_index; -} - -/* Given WINDOW, recalculate the line starts for the node it displays. */ -void -recalculate_line_starts (window) - WINDOW *window; -{ - maybe_free (window->line_starts); - calculate_line_starts (window); -} - -/* Global variable control redisplay of scrolled windows. If non-zero, it - is the desired number of lines to scroll the window in order to make - point visible. A user might set this to 1 for smooth scrolling. If - set to zero, the line containing point is centered within the window. */ -int window_scroll_step = 0; - -/* Adjust the pagetop of WINDOW such that the cursor point will be visible. */ -void -window_adjust_pagetop (window) - WINDOW *window; -{ - register int line = 0; - char *contents; - - if (!window->node) - return; - - contents = window->node->contents; - - /* Find the first printed line start which is after WINDOW->point. */ - for (line = 0; line < window->line_count; line++) - { - char *line_start; - - line_start = window->line_starts[line]; - - if ((line_start - contents) > window->point) - break; - } - - /* The line index preceding the line start which is past point is the - one containing point. */ - line--; - - /* If this line appears in the current displayable page, do nothing. - Otherwise, adjust the top of the page to make this line visible. */ - if ((line < window->pagetop) || - (line - window->pagetop > (window->height - 1))) - { - /* The user-settable variable "scroll-step" is used to attempt - to make point visible, iff it is non-zero. If that variable - is zero, then the line containing point is centered within - the window. */ - if (window_scroll_step < window->height) - { - if ((line < window->pagetop) && - ((window->pagetop - window_scroll_step) <= line)) - window->pagetop -= window_scroll_step; - else if ((line - window->pagetop > (window->height - 1)) && - ((line - (window->pagetop + window_scroll_step) - < window->height))) - window->pagetop += window_scroll_step; - else - window->pagetop = line - ((window->height - 1) / 2); - } - else - window->pagetop = line - ((window->height - 1) / 2); - - if (window->pagetop < 0) - window->pagetop = 0; - window->flags |= W_UpdateWindow; - } -} - -/* Return the index of the line containing point. */ -int -window_line_of_point (window) - WINDOW *window; -{ - register int i, start = 0; - - /* Try to optimize. Check to see if point is past the pagetop for - this window, and if so, start searching forward from there. */ - if ((window->pagetop > -1 && window->pagetop < window->line_count) && - (window->line_starts[window->pagetop] - window->node->contents) - <= window->point) - start = window->pagetop; - - for (i = start; i < window->line_count; i++) - { - if ((window->line_starts[i] - window->node->contents) > window->point) - break; - } - - return (i - 1); -} - -/* Get and return the goal column for this window. */ -int -window_get_goal_column (window) - WINDOW *window; -{ - if (!window->node) - return (-1); - - if (window->goal_column != -1) - return (window->goal_column); - - /* Okay, do the work. Find the printed offset of the cursor - in this window. */ - return (window_get_cursor_column (window)); -} - -/* Get and return the printed column offset of the cursor in this window. */ -int -window_get_cursor_column (window) - WINDOW *window; -{ - int i, hpos, end; - char *line; - - i = window_line_of_point (window); - - if (i < 0) - return (-1); - - line = window->line_starts[i]; - end = window->point - (line - window->node->contents); - - for (hpos = 0, i = 0; i < end; i++) - hpos += character_width (line[i], hpos); - - return (hpos); -} - -/* Count the number of characters in LINE that precede the printed column - offset of GOAL. */ -int -window_chars_to_goal (line, goal) - char *line; - int goal; -{ - register int i, check, hpos; - - for (hpos = 0, i = 0; line[i] != '\n'; i++) - { - - check = hpos + character_width (line[i], hpos); - - if (check > goal) - break; - - hpos = check; - } - return (i); -} - -/* Create a modeline for WINDOW, and store it in window->modeline. */ -void -window_make_modeline (window) - WINDOW *window; -{ - register int i; - char *modeline; - char location_indicator[4]; - int lines_remaining; - - /* Only make modelines for those windows which have one. */ - if (window->flags & W_InhibitMode) - return; - - /* Find the number of lines actually displayed in this window. */ - lines_remaining = window->line_count - window->pagetop; - - if (window->pagetop == 0) - { - if (lines_remaining <= window->height) - strcpy (location_indicator, "All"); - else - strcpy (location_indicator, "Top"); - } - else - { - if (lines_remaining <= window->height) - strcpy (location_indicator, "Bot"); - else - { - float pt, lc; - int percentage; - - pt = (float)window->pagetop; - lc = (float)window->line_count; - - percentage = 100 * (pt / lc); - - sprintf (location_indicator, "%2d%%", percentage); - } - } - - /* Calculate the maximum size of the information to stick in MODELINE. */ - { - int modeline_len = 0; - char *parent = (char *)NULL, *filename = "*no file*"; - char *nodename = "*no node*"; - char *update_message = (char *)NULL; - NODE *node = window->node; - - if (node) - { - if (node->nodename) - nodename = node->nodename; - - if (node->parent) - { - parent = filename_non_directory (node->parent); - modeline_len += strlen ("Subfile: ") + strlen (node->filename); - } - - if (node->filename) - filename = filename_non_directory (node->filename); - - if (node->flags & N_UpdateTags) - update_message = "--*** Tags out of Date ***"; - } - - if (update_message) - modeline_len += strlen (update_message); - modeline_len += strlen (filename); - modeline_len += strlen (nodename); - modeline_len += 4; /* strlen (location_indicator). */ - - /* 10 for the decimal representation of the number of lines in this - node, and the remainder of the text that can appear in the line. */ - modeline_len += 10 + strlen ("-----Info: (), lines ----, "); - modeline_len += window->width; - - modeline = (char *)xmalloc (1 + modeline_len); - - /* Special internal windows have no filename. */ - if (!parent && !*filename) - sprintf (modeline, "-%s---Info: %s, %d lines --%s--", - (window->flags & W_NoWrap) ? "$" : "-", - nodename, window->line_count, location_indicator); - else - sprintf (modeline, "-%s%s-Info: (%s)%s, %d lines --%s--", - (window->flags & W_NoWrap) ? "$" : "-", - (node && (node->flags & N_IsCompressed)) ? "zz" : "--", - parent ? parent : filename, - nodename, window->line_count, location_indicator); - - if (parent) - sprintf (modeline + strlen (modeline), " Subfile: %s", filename); - - if (update_message) - sprintf (modeline + strlen (modeline), "%s", update_message); - - i = strlen (modeline); - - if (i >= window->width) - modeline[window->width] = '\0'; - else - { - while (i < window->width) - modeline[i++] = '-'; - modeline[i] = '\0'; - } - - strcpy (window->modeline, modeline); - free (modeline); - } -} - -/* Make WINDOW start displaying at PERCENT percentage of its node. */ -void -window_goto_percentage (window, percent) - WINDOW *window; - int percent; -{ - int desired_line; - - if (!percent) - desired_line = 0; - else - desired_line = - (int) ((float)window->line_count * ((float)percent / 100.0)); - - window->pagetop = desired_line; - window->point = - window->line_starts[window->pagetop] - window->node->contents; - window->flags |= W_UpdateWindow; - window_make_modeline (window); -} - -/* Get the state of WINDOW, and save it in STATE. */ -void -window_get_state (window, state) - WINDOW *window; - WINDOW_STATE *state; -{ - state->node = window->node; - state->pagetop = window->pagetop; - state->point = window->point; -} - -/* Set the node, pagetop, and point of WINDOW. */ -void -window_set_state (window, state) - WINDOW *window; - WINDOW_STATE *state; -{ - if (window->node != state->node) - window_set_node_of_window (window, state->node); - window->pagetop = state->pagetop; - window->point = state->point; -} - - -/* **************************************************************** */ -/* */ -/* Manipulating Home-Made Nodes */ -/* */ -/* **************************************************************** */ - -/* A place to buffer echo area messages. */ -static NODE *echo_area_node = (NODE *)NULL; - -/* Make the node of the_echo_area be an empty one. */ -static void -free_echo_area () -{ - if (echo_area_node) - { - maybe_free (echo_area_node->contents); - free (echo_area_node); - } - - echo_area_node = (NODE *)NULL; - window_set_node_of_window (the_echo_area, echo_area_node); -} - -/* Clear the echo area, removing any message that is already present. - The echo area is cleared immediately. */ -void -window_clear_echo_area () -{ - free_echo_area (); - display_update_one_window (the_echo_area); -} - -/* Make a message appear in the echo area, built from FORMAT, ARG1 and ARG2. - The arguments are treated similar to printf () arguments, but not all of - printf () hair is present. The message appears immediately. If there was - already a message appearing in the echo area, it is removed. */ -void -window_message_in_echo_area (format, arg1, arg2) - char *format; - void *arg1, *arg2; -{ - free_echo_area (); - echo_area_node = build_message_node (format, arg1, arg2); - window_set_node_of_window (the_echo_area, echo_area_node); - display_update_one_window (the_echo_area); -} - -/* Place a temporary message in the echo area built from FORMAT, ARG1 - and ARG2. The message appears immediately, but does not destroy - any existing message. A future call to unmessage_in_echo_area () - restores the old contents. */ -static NODE **old_echo_area_nodes = (NODE **)NULL; -static int old_echo_area_nodes_index = 0; -static int old_echo_area_nodes_slots = 0; - -void -message_in_echo_area (format, arg1, arg2) - char *format; - void *arg1, *arg2; -{ - if (echo_area_node) - { - add_pointer_to_array (echo_area_node, old_echo_area_nodes_index, - old_echo_area_nodes, old_echo_area_nodes_slots, - 4, NODE *); - } - echo_area_node = (NODE *)NULL; - window_message_in_echo_area (format, arg1, arg2); -} - -void -unmessage_in_echo_area () -{ - free_echo_area (); - - if (old_echo_area_nodes_index) - echo_area_node = old_echo_area_nodes[--old_echo_area_nodes_index]; - - window_set_node_of_window (the_echo_area, echo_area_node); - display_update_one_window (the_echo_area); -} - -/* A place to build a message. */ -static char *message_buffer = (char *)NULL; -static int message_buffer_index = 0; -static int message_buffer_size = 0; - -/* Ensure that there is enough space to stuff LENGTH characters into - MESSAGE_BUFFER. */ -static void -message_buffer_resize (length) - int length; -{ - if (!message_buffer) - { - message_buffer_size = length + 1; - message_buffer = (char *)xmalloc (message_buffer_size); - message_buffer_index = 0; - } - - while (message_buffer_size <= message_buffer_index + length) - message_buffer = (char *) - xrealloc (message_buffer, - message_buffer_size += 100 + (2 * length)); -} - -/* Format MESSAGE_BUFFER with the results of printing FORMAT with ARG1 and - ARG2. */ -static void -build_message_buffer (format, arg1, arg2) - char *format; - void *arg1, *arg2; -{ - register int i, len; - void *args[2]; - int arg_index = 0; - - args[0] = arg1; - args[1] = arg2; - - len = strlen (format); - - message_buffer_resize (len); - - for (i = 0; format[i]; i++) - { - if (format[i] != '%') - { - message_buffer[message_buffer_index++] = format[i]; - len--; - } - else - { - char c; - - c = format[++i]; - - switch (c) - { - case '%': /* Insert a percent sign. */ - message_buffer_resize (len + 1); - message_buffer[message_buffer_index++] = '%'; - break; - - case 's': /* Insert the current arg as a string. */ - { - char *string; - int string_len; - - string = (char *)args[arg_index++]; - string_len = strlen (string); - - message_buffer_resize (len + string_len); - sprintf - (message_buffer + message_buffer_index, "%s", string); - message_buffer_index += string_len; - } - break; - - case 'd': /* Insert the current arg as an integer. */ - { - long long_val; - int integer; - - long_val = (long)args[arg_index++]; - integer = (int)long_val; - - message_buffer_resize (len + 32); - sprintf - (message_buffer + message_buffer_index, "%d", integer); - message_buffer_index = strlen (message_buffer); - } - break; - - case 'c': /* Insert the current arg as a character. */ - { - long long_val; - int character; - - long_val = (long)args[arg_index++]; - character = (int)long_val; - - message_buffer_resize (len + 1); - message_buffer[message_buffer_index++] = character; - } - break; - - default: - abort (); - } - } - } - message_buffer[message_buffer_index] = '\0'; -} - -/* Build a new node which has FORMAT printed with ARG1 and ARG2 as the - contents. */ -NODE * -build_message_node (format, arg1, arg2) - char *format; - void *arg1, *arg2; -{ - NODE *node; - - message_buffer_index = 0; - build_message_buffer (format, arg1, arg2); - - node = message_buffer_to_node (); - return (node); -} - -/* Convert the contents of the message buffer to a node. */ -NODE * -message_buffer_to_node () -{ - NODE *node; - - node = (NODE *)xmalloc (sizeof (NODE)); - node->filename = (char *)NULL; - node->parent = (char *)NULL; - node->nodename = (char *)NULL; - node->flags = 0; - - /* Make sure that this buffer ends with a newline. */ - node->nodelen = 1 + strlen (message_buffer); - node->contents = (char *)xmalloc (1 + node->nodelen); - strcpy (node->contents, message_buffer); - node->contents[node->nodelen - 1] = '\n'; - node->contents[node->nodelen] = '\0'; - return (node); -} - -/* Useful functions can be called from outside of window.c. */ -void -initialize_message_buffer () -{ - message_buffer_index = 0; -} - -/* Print FORMAT with ARG1,2 to the end of the current message buffer. */ -void -printf_to_message_buffer (format, arg1, arg2) - char *format; - void *arg1, *arg2; -{ - build_message_buffer (format, arg1, arg2); -} - -/* Return the current horizontal position of the "cursor" on the most - recently output message buffer line. */ -int -message_buffer_length_this_line () -{ - register int i; - - if (!message_buffer_index) - return (0); - - for (i = message_buffer_index; i && message_buffer[i - 1] != '\n'; i--); - - return (string_width (message_buffer + i, 0)); -} - -/* Pad STRING to COUNT characters by inserting blanks. */ -int -pad_to (count, string) - int count; - char *string; -{ - register int i; - - i = strlen (string); - - if (i >= count) - string[i++] = ' '; - else - { - while (i < count) - string[i++] = ' '; - } - string[i] = '\0'; - - return (i); -} diff --git a/info/window.h b/info/window.h deleted file mode 100644 --- a/info/window.h +++ /dev/null @@ -1,229 +0,0 @@ -/* window.h -- Structure and flags used in manipulating Info windows. */ - -/* 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). */ - -#if !defined (_WINDOW_H_) -#define _WINDOW_H_ - -#include "nodes.h" -#include "infomap.h" - -/* Smallest number of visible lines in a window. The actual height is - always one more than this number because each window has a modeline. */ -#define WINDOW_MIN_HEIGHT 2 - -/* Smallest number of screen lines that can be used to fully present a - window. This number includes the modeline of the window. */ -#define WINDOW_MIN_SIZE (WINDOW_MIN_HEIGHT + 1) - -/* The exact same elements are used within the WINDOW_STATE structure and a - subsection of the WINDOW structure. We could define a structure which - contains this elements, and include that structure in each of WINDOW_STATE - and WINDOW. But that would lead references in the code such as - window->state->node which we would like to avoid. Instead, we #define the - elements here, and simply include the define in both data structures. Thus, - if you need to change window state information, here is where you would - do it. NB> The last element does NOT end with a semi-colon. */ -#define WINDOW_STATE_DECL \ - NODE *node; /* The node displayed in this window. */ \ - int pagetop; /* LINE_STARTS[PAGETOP] is first line in WINDOW. */ \ - long point /* Offset within NODE of the cursor position. */ - -/* Structure which defines a window. Windows are doubly linked, next - and prev. The list of windows is kept on WINDOWS. The structure member - window->height is the total height of the window. The position location - (0, window->height + window->first_row) is the first character of this - windows modeline. The number of lines that can be displayed in a window - is equal to window->height - 1. */ -typedef struct __window__ { - struct __window__ *next; /* Next window in this chain. */ - struct __window__ *prev; /* Previous window in this chain. */ - int width; /* Width of this window. */ - int height; /* Height of this window. */ - int first_row; /* Offset of the first line in the_screen. */ - int goal_column; /* The column we would like the cursor to appear in. */ - Keymap keymap; /* Keymap used to read commands in this window. */ - WINDOW_STATE_DECL; /* Node, pagetop and point. */ - char *modeline; /* Calculated text of the modeline for this window. */ - char **line_starts; /* Array of printed line starts for this node. */ - int line_count; /* Number of lines appearing in LINE_STARTS. */ - int flags; /* See below for details. */ -} WINDOW; - -typedef struct { - WINDOW_STATE_DECL; /* What gets saved. */ -} WINDOW_STATE; - -#define W_UpdateWindow 0x01 /* WINDOW needs updating. */ -#define W_WindowIsPerm 0x02 /* This WINDOW is a permanent object. */ -#define W_WindowVisible 0x04 /* This WINDOW is currently visible. */ -#define W_InhibitMode 0x08 /* This WINDOW has no modeline. */ -#define W_NoWrap 0x10 /* Lines do not wrap in this window. */ -#define W_InputWindow 0x20 /* Window accepts input. */ -#define W_TempWindow 0x40 /* Window is less important. */ - -extern WINDOW *windows; /* List of visible Info windows. */ -extern WINDOW *active_window; /* The currently active window. */ -extern WINDOW *the_screen; /* The Info screen is just another window. */ -extern WINDOW *the_echo_area; /* THE_ECHO_AREA is a window in THE_SCREEN. */ - -/* Global variable control redisplay of scrolled windows. If non-zero, it - is the desired number of lines to scroll the window in order to make - point visible. A user might set this to 1 for smooth scrolling. If - set to zero, the line containing point is centered within the window. */ -extern int window_scroll_step; - - /* Make the modeline member for WINDOW. */ -extern void window_make_modeline (); - -/* Initalize the window system by creating THE_SCREEN and THE_ECHO_AREA. - Create the first window ever, and make it permanent. - You pass WIDTH and HEIGHT; the dimensions of the total screen size. */ -extern void window_initialize_windows (); - -/* Make a new window showing NODE, and return that window structure. - The new window is made to be the active window. If NODE is passed - as NULL, then show the node showing in the active window. If the - window could not be made return a NULL pointer. The active window - is not changed.*/ -extern WINDOW *window_make_window (); - -/* Delete WINDOW from the list of known windows. If this window was the - active window, make the next window in the chain be the active window, - or the previous window in the chain if there is no next window. */ -extern void window_delete_window (); - -/* A function to call when the screen changes size, and some windows have - to get deleted. The function is called with the window to be deleted - as an argument, and it can't do anything about the window getting deleted; - it can only clean up dangling references to that window. */ -extern VFunction *window_deletion_notifier; - -/* Set WINDOW to display NODE. */ -extern void window_set_node_of_window (); - -/* Tell the window system that the size of the screen has changed. This - causes lots of interesting things to happen. The permanent windows - are resized, as well as every visible window. You pass WIDTH and HEIGHT; - the dimensions of the total screen size. */ -extern void window_new_screen_size (); - -/* Change the height of WINDOW by AMOUNT. This also automagically adjusts - the previous and next windows in the chain. If there is only one user - window, then no change takes place. */ -extern void window_change_window_height (); - -/* Adjust the pagetop of WINDOW such that the cursor point will be visible. */ -extern void window_adjust_pagetop (); - -/* Tile all of the windows currently displayed in the global variable - WINDOWS. If argument DO_INTERNALS is non-zero, tile windows displaying - internal nodes as well. */ -#define DONT_TILE_INTERNALS 0 -#define TILE_INTERNALS 1 -extern void window_tile_windows (); - -/* Toggle the state of line wrapping in WINDOW. This can do a bit of fancy - redisplay. */ -extern void window_toggle_wrap (); - -/* For every window in CHAIN, set the flags member to have FLAG set. */ -extern void window_mark_chain (); - -/* For every window in CHAIN, clear the flags member of FLAG. */ -extern void window_unmark_chain (); - -/* Make WINDOW start displaying at PERCENT percentage of its node. */ -extern void window_goto_percentage (); - -/* Build a new node which has FORMAT printed with ARG1 and ARG2 as the - contents. */ -extern NODE *build_message_node (); - -/* Useful functions can be called from outside of window.c. */ -extern void initialize_message_buffer (); - -/* Print FORMAT with ARG1,2 to the end of the current message buffer. */ -extern void printf_to_message_buffer (); - -/* Convert the contents of the message buffer to a node. */ -extern NODE *message_buffer_to_node (); - -/* Return the length of the most recently printed line in message buffer. */ -extern int message_buffer_length_this_line (); - -/* Pad STRING to COUNT characters by inserting blanks. */ -extern int pad_to (); - -/* Make a message appear in the echo area, built from FORMAT, ARG1 and ARG2. - The arguments are treated similar to printf () arguments, but not all of - printf () hair is present. The message appears immediately. If there was - already a message appearing in the echo area, it is removed. */ -extern void window_message_in_echo_area (); - -/* Place a temporary message in the echo area built from FORMAT, ARG1 - and ARG2. The message appears immediately, but does not destroy - any existing message. A future call to unmessage_in_echo_area () - restores the old contents. */ -extern void message_in_echo_area (); -extern void unmessage_in_echo_area (); - -/* Clear the echo area, removing any message that is already present. - The echo area is cleared immediately. */ -extern void window_clear_echo_area (); - -/* Quickly guess the approximate number of lines to that NODE would - take to display. This really only counts carriage returns. */ -extern int window_physical_lines (); - -/* Calculate a list of line starts for the node belonging to WINDOW. The line - starts are pointers to the actual text within WINDOW->NODE. */ -extern void calculate_line_starts (); - -/* Given WINDOW, recalculate the line starts for the node it displays. */ -extern void recalculate_line_starts (); - -/* Return the number of characters it takes to display CHARACTER on the - screen at HPOS. */ -extern int character_width (); - -/* Return the number of characters it takes to display STRING on the - screen at HPOS. */ -extern int string_width (); - -/* Return the index of the line containing point. */ -extern int window_line_of_point (); - -/* Get and return the goal column for this window. */ -extern int window_get_goal_column (); - -/* Get and return the printed column offset of the cursor in this window. */ -extern int window_get_cursor_column (); - -/* Get and Set the node, pagetop, and point of WINDOW. */ -extern void window_get_state (), window_set_state (); - -/* Count the number of characters in LINE that precede the printed column - offset of GOAL. */ -extern int window_chars_to_goal (); - -#endif /* !_WINDOW_H_ */ diff --git a/info/xmalloc.c b/info/xmalloc.c deleted file mode 100644 --- a/info/xmalloc.c +++ /dev/null @@ -1,80 +0,0 @@ -/* xmalloc.c -- safe versions of malloc and realloc */ - -/* This file is part of GNU Info, a program for reading online documentation - stored in Info format. - - This file has appeared in prior works by the Free Software Foundation; - thus it carries copyright dates from 1988 through 1993. - - Copyright (C) 1988, 1989, 1990, 1991, 1992, 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). */ - -#if !defined (ALREADY_HAVE_XMALLOC) -#include -#include - -extern void *malloc (), *realloc (); -static void memory_error_and_abort (); - -/* **************************************************************** */ -/* */ -/* Memory Allocation and Deallocation. */ -/* */ -/* **************************************************************** */ - -/* Return a pointer to free()able block of memory large enough - to hold BYTES number of bytes. If the memory cannot be allocated, - print an error message and abort. */ -void * -xmalloc (bytes) - int bytes; -{ - void *temp = malloc (bytes); - - if (!temp) - memory_error_and_abort ("xmalloc"); - return (temp); -} - -void * -xrealloc (pointer, bytes) - void *pointer; - int bytes; -{ - void *temp; - - if (!pointer) - temp = malloc (bytes); - else - temp = realloc (pointer, bytes); - - if (!temp) - memory_error_and_abort ("xrealloc"); - - return (temp); -} - -static void -memory_error_and_abort (fname) - char *fname; -{ - fprintf (stderr, "%s: Out of virtual memory!\n", fname); - abort (); -} -#endif /* !ALREADY_HAVE_XMALLOC */