From 06cd36cdc90634c88636a6d09230c573078ead0e Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Wed, 23 Nov 2011 18:39:33 -0500 Subject: Readline-2.0 import: initial import --- COPYING | 257 ++++ ChangeLog | 403 +++++ INSTALL | 146 ++ MANIFEST | 52 + Makefile | 205 +++ Makefile.in | 205 +++ README | 6 + STANDALONE | 31 + acconfig.h | 28 + ansi_stdlib.h | 41 + bind.c | 1487 +++++++++++++++++++ chardefs.h | 122 ++ complete.c | 1417 ++++++++++++++++++ config.h | 71 + config.h.in | 70 + config.status | 190 +++ configure | 1240 ++++++++++++++++ configure.in | 48 + display.c | 1219 +++++++++++++++ doc/Makefile | 56 + doc/hist.texinfo | 113 ++ doc/history.dvi | Bin 0 -> 47376 bytes doc/history.info | 744 ++++++++++ doc/history.ps | 2037 +++++++++++++++++++++++++ doc/hstech.texinfo | 489 ++++++ doc/hsuser.texinfo | 198 +++ doc/readline.3 | 1210 +++++++++++++++ doc/readline.dvi | Bin 0 -> 148692 bytes doc/readline.info | 74 + doc/readline.info-1 | 1322 +++++++++++++++++ doc/readline.info-2 | 978 ++++++++++++ doc/readline.ps | 3766 +++++++++++++++++++++++++++++++++++++++++++++++ doc/rlman.texinfo | 111 ++ doc/rltech.texinfo | 1356 +++++++++++++++++ doc/rluser.texinfo | 875 +++++++++++ doc/texinfo.tex | 4003 ++++++++++++++++++++++++++++++++++++++++++++++++++ emacs_keymap.c | 885 +++++++++++ examples/Inputrc | 65 + examples/Makefile | 12 + examples/fileman.c | 425 ++++++ examples/histexamp.c | 82 ++ examples/manexamp.c | 94 ++ funmap.c | 299 ++++ history.c | 2171 +++++++++++++++++++++++++++ history.h | 180 +++ isearch.c | 378 +++++ keymaps.c | 196 +++ keymaps.h | 95 ++ memalloc.h | 56 + parens.c | 130 ++ posixstat.h | 149 ++ readline.c | 3527 ++++++++++++++++++++++++++++++++++++++++++++ readline.h | 289 ++++ rlconf.h | 57 + rldefs.h | 207 +++ rltty.c | 697 +++++++++ search.c | 367 +++++ signals.c | 303 ++++ stamp-config | 0 tilde.c | 386 +++++ tilde.h | 38 + vi_keymap.c | 877 +++++++++++ vi_mode.c | 1329 +++++++++++++++++ xmalloc.c | 78 + 64 files changed, 37942 insertions(+) create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 MANIFEST create mode 100644 Makefile create mode 100644 Makefile.in create mode 100644 README create mode 100644 STANDALONE create mode 100644 acconfig.h create mode 100644 ansi_stdlib.h create mode 100644 bind.c create mode 100644 chardefs.h create mode 100644 complete.c create mode 100644 config.h create mode 100644 config.h.in create mode 100755 config.status create mode 100755 configure create mode 100644 configure.in create mode 100644 display.c create mode 100644 doc/Makefile create mode 100644 doc/hist.texinfo create mode 100644 doc/history.dvi create mode 100644 doc/history.info create mode 100644 doc/history.ps create mode 100644 doc/hstech.texinfo create mode 100644 doc/hsuser.texinfo create mode 100644 doc/readline.3 create mode 100644 doc/readline.dvi create mode 100644 doc/readline.info create mode 100644 doc/readline.info-1 create mode 100644 doc/readline.info-2 create mode 100644 doc/readline.ps create mode 100644 doc/rlman.texinfo create mode 100644 doc/rltech.texinfo create mode 100644 doc/rluser.texinfo create mode 100644 doc/texinfo.tex create mode 100644 emacs_keymap.c create mode 100644 examples/Inputrc create mode 100644 examples/Makefile create mode 100644 examples/fileman.c create mode 100644 examples/histexamp.c create mode 100644 examples/manexamp.c create mode 100644 funmap.c create mode 100644 history.c create mode 100644 history.h create mode 100644 isearch.c create mode 100644 keymaps.c create mode 100644 keymaps.h create mode 100644 memalloc.h create mode 100644 parens.c create mode 100644 posixstat.h create mode 100644 readline.c create mode 100644 readline.h create mode 100644 rlconf.h create mode 100644 rldefs.h create mode 100644 rltty.c create mode 100644 search.c create mode 100644 signals.c create mode 100644 stamp-config create mode 100644 tilde.c create mode 100644 tilde.h create mode 100644 vi_keymap.c create mode 100644 vi_mode.c create mode 100644 xmalloc.c diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..1bb82d1 --- /dev/null +++ b/COPYING @@ -0,0 +1,257 @@ + + GNU GENERAL PUBLIC LICENSE + Version 1, February 1989 + + Copyright (C) 1989 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +The Free Software Foundation has exempted Bash from the requirement of +Paragraph 2c of the General Public License. This is to say, there is +no requirement for Bash to print a notice when it is started +interactively in the usual way. We made this exception because users +and standards expect shells not to print such messages. This +exception applies to any program that serves as a shell and that is +based primarily on Bash as opposed to other GNU software. + + Preamble + + The license agreements of most software companies try to keep users +at the mercy of those companies. By contrast, our General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. The +General Public License applies to the Free Software Foundation's +software and to any other program whose authors commit to using it. +You can use it for your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Specifically, the General Public License is designed to make +sure that you have the freedom to give away or sell copies of free +software, that you receive source code or can get it if you want it, +that you can change the software or use pieces of it in new free +programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of a such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must tell them their rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any program or other work which +contains a notice placed by the copyright holder saying it may be +distributed under the terms of this General Public License. The +"Program", below, refers to any such program or work, and a "work based +on the Program" means either the Program or any work containing the +Program or a portion of it, either verbatim or with modifications. Each +licensee is addressed as "you". + + 1. You may copy and distribute verbatim copies of the Program's source +code as you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and +disclaimer of warranty; keep intact all the notices that refer to this +General Public License and to the absence of any warranty; and give any +other recipients of the Program a copy of this General Public License +along with the Program. You may charge a fee for the physical act of +transferring a copy. + + 2. You may modify your copy or copies of the Program or any portion of +it, and copy and distribute such modifications under the terms of Paragraph +1 above, provided that you also do the following: + + a) cause the modified files to carry prominent notices stating that + you changed the files and the date of any change; and + + b) cause the whole of any work that you distribute or publish, that + in whole or in part contains the Program or any part thereof, either + with or without modifications, to be licensed at no charge to all + third parties under the terms of this General Public License (except + that you may choose to grant warranty protection to some or all + third parties, at your option). + + c) If the modified program normally reads commands interactively when + run, you must cause it, when started running for such interactive use + in the simplest and most usual way, to print or display an + announcement including an appropriate copyright notice and a notice + that there is no warranty (or else, saying that you provide a + warranty) and that users may redistribute the program under these + conditions, and telling the user how to view a copy of this General + Public License. + + d) You may charge a fee for the physical act of transferring a + copy, and you may at your option offer warranty protection in + exchange for a fee. + +Mere aggregation of another independent work with the Program (or its +derivative) on a volume of a storage or distribution medium does not bring +the other work under the scope of these terms. + + 3. You may copy and distribute the Program (or a portion or derivative of +it, under Paragraph 2) in object code or executable form under the terms of +Paragraphs 1 and 2 above provided that you also do one of the following: + + a) accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of + Paragraphs 1 and 2 above; or, + + b) accompany it with a written offer, valid for at least three + years, to give any third party free (except for a nominal charge + for the cost of distribution) a complete machine-readable copy of the + corresponding source code, to be distributed under the terms of + Paragraphs 1 and 2 above; or, + + c) accompany it with the information you received as to where the + corresponding source code may be obtained. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form alone.) + +Source code for a work means the preferred form of the work for making +modifications to it. For an executable file, complete source code means +all the source code for all modules it contains; but, as a special +exception, it need not include source code for modules which are standard +libraries that accompany the operating system on which the executable +file runs, or for standard header files or definitions files that +accompany that operating system. + + 4. You may not copy, modify, sublicense, distribute or transfer the +Program except as expressly provided under this General Public License. +Any attempt otherwise to copy, modify, sublicense, distribute or transfer +the Program is void, and will automatically terminate your rights to use +the Program under this License. However, parties who have received +copies, or rights to use copies, from you under this General Public +License will not have their licenses terminated so long as such parties +remain in full compliance. + + 5. By copying, distributing or modifying the Program (or any work based +on the Program) you indicate your acceptance of this license to do so, +and all its terms and conditions. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the original +licensor to copy, distribute or modify the Program subject to these +terms and conditions. You may not impose any further restrictions on the +recipients' exercise of the rights granted herein. + + 7. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of the license which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +the license, you may choose any version ever published by the Free Software +Foundation. + + 8. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to humanity, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + + To do so, attach the following notices to the program. It is safest to +attach them to the start of each source file to most effectively convey +the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + 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 1, 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. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19xx name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the +appropriate parts of the General Public License. Of course, the +commands you use may be called something other than `show w' and `show +c'; they could even be mouse-clicks or menu items--whatever suits your +program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + program `Gnomovision' (a program to direct compilers to make passes + at assemblers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..1cf0c00 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,403 @@ +Tue Mar 23 14:36:51 1993 Brian Fox (bfox@eos.crseo.ucsb.edu) + + * readline.c (rl_copy): Changed name to rl_copy_text. + +Mon Mar 22 19:16:05 1993 Brian Fox (bfox@eos.crseo.ucsb.edu) + + * dispose_cmd.c, several other files. Declare dispose_xxx () as + "void". + + * builtins/hashcom.h: Make declarations of hashed_filenames be + "extern" to keep the SGI compiler happy. + + * readline.c (rl_initialize_everything): Assign values to + out_stream and in_stream immediately, since + output_character_function () can be called before + readline_internal () is called. + +Tue Dec 8 09:30:56 1992 Brian Fox (bfox@cubit) + + * readline.c (rl_init_terminal) Set PC from BC, not from *buffer. + +Mon Nov 30 09:35:47 1992 Brian Fox (bfox@cubit) + + * readline.c (invoking_keyseqs_in_map, rl_parse_and_bind) Allow + backslash to quote characters, such as backslash, double quote, + and space. Backslash quotes all character indiscriminately. + + * funmap.c (vi_keymap) Fix type in "vi-replace" declaration. + +Fri Nov 20 10:55:05 1992 Brian Fox (bfox@cubit) + + * readline.c (init_terminal_io, rl_prep_terminal): FINALLY! + Declare and use termcap variable `ospeed' when setting up terminal + parameters. + +Thu Oct 8 08:53:07 1992 Brian J. Fox (bfox@helios) + + * Makefile, this directory: Include (as links to the canonical + sources), tilde.c, tilde.h, posixstat.h and xmalloc.c. + +Tue Sep 29 13:07:21 1992 Brian J. Fox (bfox@helios) + + * readline.c (init_terminal_io) Don't set arrow keys if the key + sequences that represent them are already set. + + * readline.c (rl_function_of_keyseq) New function returns the first + function (or macro) found while searching a key sequence. + +Mon Sep 28 00:34:04 1992 Brian J. Fox (bfox@helios) + + * readline.c (LibraryVersion) New static char * contains current + version number. Version is at 2.0. + + * readline.c (rl_complete_internal): Incorporated clean changes + from gilmore (gnu@cygnus.com) to support quoted substrings within + completion functions. + + * readline.c (many locations) Added support for the _GO32_, + whatever that is. Patches supplied by Cygnus, typed in by hand, + with cleanups. + +Sun Aug 16 12:46:24 1992 Brian Fox (bfox@cubit) + + * readline.c (init_terminal_io): Find out the values of the keypad + arrows and bind them to appropriate RL functions if present. + +Mon Aug 10 18:13:24 1992 Brian Fox (bfox@cubit) + + * history.c (stifle_history): A negative argument to stifle + becomes zero. + +Tue Jul 28 09:28:41 1992 Brian Fox (bfox@cubit) + + * readline.c (rl_variable_bind): New local structure describes + booleans by name and address; code in rl_variable_bind () looks at + structure to set simple variables. + + * parens.c (rl_insert_close): New variable rl_blink_matching_paren + is non-zero if we want to blink the matching open when a close is + inserted. If FD_SET is defined, rl_blink_matching_paren defaults + to 1, else 0. If FD_SET is not defined, and + rl_blink_matching_paren is non-zero, the close character(s) are/is + simply inserted. + +Wed Jul 22 20:03:59 1992 Brian Fox (bfox@cubit) + + * history.c, readline.c, vi_mode.c: Cause the functions strchr () + and strrchr () to be used instead of index () and rindex () + throughout the source. + +Mon Jul 13 11:34:07 1992 Brian Fox (bfox@cubit) + + * readline.c: (rl_variable_bind) New variable "meta-flag" if "on" + means force the use of the 8th bit as Meta bit. Internal variable + is called meta_flag. + +Thu Jul 9 10:37:56 1992 Brian Fox (bfox@cubit) + + * history.c (get_history_event) Change INDEX to LOCAL_INDEX. If + compiling for the shell, allow shell metacharacters to separate + history tokens as they would for shell tokens. + +Sat Jul 4 19:29:12 1992 Brian Fox (bfox@cubit) + + * vi_keymap.c: According to Posix, TAB self-inserts instead of + doing completion. + + * vi_mode.c: (rl_vi_yank_arg) Enter VI insert mode after yanking + an arg from the previous line. + + * search.c: New file takes over vi style searching and implements + non-incremental searching the history. + + Makefile: Add search.c and search.o. + + funmap.c: Add names for non-incremental-forward-search-history and + non-incremental-reverse-search-history. + + readline.h: Add extern definitions for non-incremental searching. + + vi_mode.c: Remove old search code; add calls to code in search.c. + +Fri Jul 3 10:36:33 1992 Brian Fox (bfox@cubit) + + * readline.c (rl_delete_horizontal_space); New function deletes + all whitespace surrounding point. + + funmap.c: Add "delete-horizontal-space". + emacs_keymap.c: Put rl_delete_horizontal_space () on M-\. + + * readline.c (rl_set_signals, rl_clear_signals); New function + rl_set_sighandler () is either defined in a Posix way (if + HAVE_POSIX_SIGNALS is defined) or in a BSD way. Function is + called from rl_set_signals () and rl_clear_signals (). + +Fri May 8 12:50:15 1992 Brian Fox (bfox@cubit) + + * readline.c: (readline_default_bindings) Do comparisons with + _POSIX_VDISABLE casted to `unsigned char'. Change tty characters + to be unsigned char. + +Thu Apr 30 12:36:35 1992 Brian Fox (bfox@cubit) + + * readline.c: (rl_getc) Handle "read would block" error on + non-blocking IO streams. + + * readline.c: (rl_signal_handler): Unblock only the signal that we + have caught, not all signals. + +Sun Feb 23 03:33:09 1992 Brian Fox (bfox at gnuwest.fsf.org) + + * readline.c: Many functions. Use only the macros META_CHAR and + UNMETA to deal with meta characters. Prior to this, we used + numeric values and tests. + + * readline.c (rl_complete_internal) Report exactly the number of + possible completions, not the number + 1. + + * vi_mode.c (rl_do_move) Do not change the cursor position when + using `cw' or `cW'. + + * vi_mode.c (rl_vi_complete) Enter insert mode after completing + with `*' or `\'. + +Fri Feb 21 05:58:18 1992 Brian Fox (bfox at gnuwest.fsf.org) + + * readline.c (rl_dispatch) Increment rl_key_sequence_length for + meta characters that map onto ESC map. + +Mon Feb 10 01:41:35 1992 Brian Fox (bfox at gnuwest.fsf.org) + + * history.c (history_do_write) Build a buffer of all of the lines + to write and write them in one fell swoop (lower overhead than + calling write () for each line). Suggested by Peter Ho. + + * readline.c: Include hbullx20 as well as hpux for determining + USGr3ness. + + * readline.c (rl_unix_word_rubout) As per the "Now REMEMBER" + comment, pass arguments to rl_kill_text () in the correct order to + preserve prepending and appending of killed text. + + * readline.c (rl_search_history) malloc (), realloc (), and free + () SEARCH_STRING so that there are no static limits on searching. + + * vi_mode.c (rl_vi_subst) Don't forget to end the undo group. + +Fri Jan 31 14:51:02 1992 Brian Fox (bfox at gnuwest.fsf.org) + + * readline.c (rl_signal_handler): Zero the current history entry's + pointer after freeing the undo_list when SIGINT received. + Reformat a couple of functions. + +Sat Jan 25 13:47:35 1992 Brian Fox (bfox at bears) + + * readline.c (parser_if): free () TNAME after use. + +Tue Jan 21 01:01:35 1992 Brian Fox (bfox at gnuwest.fsf.org) + + * readline.c (rl_redisplay) and (rl_character_len): Display + Control characters as "^c" and Meta characters as "\234", instead + of "C-C" and "M-C". + +Sun Dec 29 10:59:00 1991 Brian Fox (bfox at gnuwest.fsf.org) + + * readline.c (init_terminal_io) Default to environment variables + LINES and COLUMNS before termcap entry values. If all else fails, + then assume 80x24 terminal. + +Sat Dec 28 16:33:11 1991 Brian Fox (bfox at gnuwest.fsf.org) + + * readline.c: If this machine is USG and it is hpux, then define + USGr3. + + * history.c: Cosmetic fixes. + +Thu Nov 21 00:10:12 1991 Brian Fox (bfox at gnuwest.fsf.org) + + * vi_mode.c: (rl_do_move) Place cursor at end of line, never at + next to last character. + +Thu Nov 14 05:08:01 1991 Brian Fox (bfox at gnuwest.fsf.org) + + * history.c (get_history_event) Non-anchored searches can have a + return index of greater than zero from get_history_event (). + +Fri Nov 1 07:02:13 1991 Brian Fox (bfox at gnuwest.fsf.org) + + * readline.c (rl_translate_keyseq) Make C-? translate to RUBOUT + unconditionally. + +Mon Oct 28 11:34:52 1991 Brian Fox (bfox at gnuwest.fsf.org) + + * readline.c; Use Posix directory routines and macros. + + * funmap.c; Add entry for call-last-kbd-macro. + + * readline.c (rl_prep_term); Use system EOF character on POSIX + systems also. + +Thu Oct 3 16:19:53 1991 Brian Fox (bfox at gnuwest.fsf.org) + + * readline.c; Make a distinction between having a TERMIOS tty + driver, and having POSIX signal handling. You might one without + the other. New defines used HAVE_POSIX_SIGNALS, and + TERMIOS_TTY_DRIVER. + +Tue Jul 30 22:37:26 1991 Brian Fox (bfox at gnuwest.fsf.org) + + * readline.c: rl_getc () If a call to read () returns without an + error, but with zero characters, the file is empty, so return EOF. + +Thu Jul 11 20:58:38 1991 Brian Fox (bfox at gnuwest.fsf.org) + + * readline.c: (rl_get_next_history, rl_get_previous_history) + Reallocate the buffer space if the line being moved to is longer + the the current space allocated. Amazing that no one has found + this bug until now. + +Sun Jul 7 02:37:05 1991 Brian Fox (bfox at gnuwest.fsf.org) + + * readline.c:(rl_parse_and_bind) Allow leading whitespace. + Make sure TERMIO and TERMIOS systems treat CR and NL + disctinctly. + +Tue Jun 25 04:09:27 1991 Brian Fox (bfox at gnuwest.fsf.org) + + * readline.c: Rework parsing conditionals to pay attention to the + prior states of the conditional stack. This makes $if statements + work correctly. + +Mon Jun 24 20:45:59 1991 Brian Fox (bfox at gnuwest.fsf.org) + + * readline.c: support for displaying key binding information + includes the functions rl_list_funmap_names (), + invoking_keyseqs_in_map (), rl_invoking_keyseqs (), + rl_dump_functions (), and rl_function_dumper (). + + funmap.c: support for same includes rl_funmap_names (). + + readline.c, funmap.c: no longer define STATIC_MALLOC. However, + update both version of xrealloc () to handle a null pointer. + +Thu Apr 25 12:03:49 1991 Brian Fox (bfox at gnuwest.fsf.org) + + * vi_mode.c (rl_vi_fword, fWord, etc. All functions use + the macro `isident()'. Fixed movement bug which prevents + continious movement through the text. + +Fri Jul 27 16:47:01 1990 Brian Fox (bfox at gnuwest.fsf.org) + + * readline.c (parser_if) Allow "$if term=foo" construct. + +Wed May 23 16:10:33 1990 Brian Fox (bfox at gnuwest.fsf.org) + + * readline.c (rl_dispatch) Correctly remember the last command + executed. Fixed typo in username_completion_function (). + +Mon Apr 9 19:55:48 1990 Brian Fox (bfox at gnuwest.fsf.org) + + * readline.c: username_completion_function (); For text passed in + with a leading `~', remember that this could be a filename (after + it is completed). + +Thu Apr 5 13:44:24 1990 Brian Fox (bfox at gnuwest.fsf.org) + + * readline.c: rl_search_history (): Correctly handle case of an + unfound search string, but a graceful exit (as with ESC). + + * readline.c: rl_restart_output (); The Apollo passes the address + of the file descriptor to TIOCSTART, not the descriptor itself. + +Tue Mar 20 05:38:55 1990 Brian Fox (bfox at gnuwest.fsf.org) + + * readline.c: rl_complete (); second call in a row causes possible + completions to be listed. + + * readline.c: rl_redisplay (), added prompt_this_line variable + which is the first character character following \n in prompt. + +Sun Mar 11 04:32:03 1990 Brian Fox (bfox at gnuwest.fsf.org) + + * Signals are now supposedly handled inside of SYSV compilation. + +Wed Jan 17 19:24:09 1990 Brian Fox (bfox at sbphy.ucsb.edu) + + * history.c: history_expand (); fixed overwriting memory error, + added needed argument to call to get_history_event (). + +Thu Jan 11 10:54:04 1990 Brian Fox (bfox at sbphy.ucsb.edu) + + * readline.c: added mark_modified_lines to control the + display of an asterisk on modified history lines. Also + added a user variable called mark-modified-lines to the + `set' command. + +Thu Jan 4 10:38:05 1990 Brian Fox (bfox at sbphy.ucsb.edu) + + * readline.c: start_insert (). Only use IC if we don't have an im + capability. + +Fri Sep 8 09:00:45 1989 Brian Fox (bfox at aurel) + + * readline.c: rl_prep_terminal (). Only turn on 8th bit + as meta-bit iff the terminal is not using parity. + +Sun Sep 3 08:57:40 1989 Brian Fox (bfox at aurel) + + * readline.c: start_insert (). Uses multiple + insertion call in cases where that makes sense. + + rl_insert (). Read type-ahead buffer for additional + keys that are bound to rl_insert, and insert them + all at once. Make insertion of single keys given + with an argument much more efficient. + +Tue Aug 8 18:13:57 1989 Brian Fox (bfox at aurel) + + * readline.c: Changed handling of EOF. readline () returns + (char *)EOF or consed string. The EOF character is read from the + tty, or if the tty doesn't have one, defaults to C-d. + + * readline.c: Added support for event driven programs. + rl_event_hook is the address of a function you want called + while Readline is waiting for input. + + * readline.c: Cleanup time. Functions without type declarations + do not use return with a value. + + * history.c: history_expand () has new variable which is the + characters to ignore immediately following history_expansion_char. + +Sun Jul 16 08:14:00 1989 Brian Fox (bfox at aurel) + + * rl_prep_terminal () + BSD version turns off C-s, C-q, C-y, C-v. + + * readline.c -- rl_prep_terminal () + SYSV version hacks readline_echoing_p. + BSD version turns on passing of the 8th bit for the duration + of reading the line. + +Tue Jul 11 06:25:01 1989 Brian Fox (bfox at aurel) + + * readline.c: new variable rl_tilde_expander. + 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. + + * readline.h - new file chardefs.h + Separates things that only readline.c needs from the standard + header file publishing interesting things about readline. + + * readline.c: + readline_default_bindings () now looks at terminal chararacters + and binds those as well. + +Wed Jun 28 20:20:51 1989 Brian Fox (bfox at aurel) + + * Made readline and history into independent libraries. + diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..8a7d026 --- /dev/null +++ b/INSTALL @@ -0,0 +1,146 @@ + This is a generic INSTALL file for utilities distributions. +If this package does not come with, e.g., installable documentation or +data files, please ignore the references to them below. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation, and +creates the Makefile(s) (one in each subdirectory of the source +directory). In some packages it creates a C header file containing +system-dependent definitions. It also creates a file `config.status' +that you can run in the future to recreate the current configuration. + +To compile this package: + +1. Configure the package for your system. + + Normally, you just `cd' to the directory containing the package's +source code and type `./configure'. If you're using `csh' on an old +version of System V, you might need to type `sh configure' instead to +prevent `csh' from trying to execute `configure' itself. + + Running `configure' takes awhile. While it is running, it +prints some messages that tell what it is doing. If you don't want to +see any messages, run `configure' with its standard output redirected +to `/dev/null'; for example, `./configure >/dev/null'. + + To compile the package in a different directory from the one +containing the source code, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. If +for some reason `configure' is not in the source code directory that +you are configuring, then it will report that it can't find the source +code. In that case, run `configure' with the option `--srcdir=DIR', +where DIR is the directory that contains the source code. + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. Alternately, you can do so by consistently +giving a value for the `prefix' variable when you run `make', e.g., + make prefix=/usr/gnu + make prefix=/usr/gnu install + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH' or set the `make' +variable `exec_prefix' to PATH, the package will use PATH as the prefix +for installing programs and libraries. Data files and documentation +will still use the regular prefix. Normally, all files are installed +using the same prefix. + + Some packages pay attention to `--with-PACKAGE' options to +`configure', where PACKAGE is something like `gnu-as' or `x' (for the +X Window System). They may also pay attention to `--enable-FEATURE' +options, where FEATURE indicates an optional part of the package. The +README should mention any `--with-' and `--enable-' options that the +package recognizes. + + `configure' also recognizes the following options: + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' + Do not print messages saying which checks are being made. + +`--verbose' + Print the results of the checks. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--x-includes=DIR' + X include files are in DIR. + +`--x-libraries=DIR' + X library files are in DIR. + + `configure' also accepts and ignores some other options. + + On systems that require unusual options for compilation or linking +that the package's `configure' script does not know about, you can give +`configure' initial values for variables by setting them in the +environment. In Bourne-compatible shells, you can do that on the +command line like this: + + CC='gcc -traditional' LIBS=-lposix ./configure + +On systems that have the `env' program, you can do it like this: + + env CC='gcc -traditional' LIBS=-lposix ./configure + + Here are the `make' variables that you might want to override with +environment variables when running `configure'. + + For these variables, any value given in the environment overrides the +value that `configure' would choose: + + - Variable: CC + C compiler program. The default is `cc'. + + - Variable: INSTALL + Program to use to install files. The default is `install' if you + have it, `cp' otherwise. + + For these variables, any value given in the environment is added to +the value that `configure' chooses: + + - Variable: DEFS + Configuration options, in the form `-Dfoo -Dbar...'. Do not use + this variable in packages that create a configuration header file. + + - Variable: LIBS + Libraries to link with, in the form `-lfoo -lbar...'. + + If you need to do unusual things to compile the package, we encourage +you to figure out how `configure' could check whether to do them, and +mail diffs or instructions to the address given in the README so we +can include them in the next release. + +2. Type `make' to compile the package. If you want, you can override +the `make' variables CFLAGS and LDFLAGS like this: + + make CFLAGS=-O2 LDFLAGS=-s + +3. If the package comes with self-tests and you want to run them, +type `make check'. If you're not sure whether there are any, try it; +if `make' responds with something like + make: *** No way to make target `check'. Stop. +then the package does not come with self-tests. + +4. Type `make install' to install programs, data files, and +documentation. + +5. You can remove the program binaries and object files from the +source directory by typing `make clean'. To also remove the +Makefile(s), the header file containing system-dependent definitions +(if the package uses one), and `config.status' (all the files that +`configure' created), type `make distclean'. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need it if you want to regenerate +`configure' using a newer version of `autoconf'. diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..007a5ca --- /dev/null +++ b/MANIFEST @@ -0,0 +1,52 @@ +doc d +examples d +COPYING f +README f +STANDALONE f +MANIFEST f +INSTALL f +acconfig.h f +config.h.in f +configure f +configure.in f +Makefile.in f +ChangeLog f +ansi_stdlib.h f +chardefs.h f +keymaps.h f +memalloc.h f +posixstat.h f +history.h f +rlconf.h f +rldefs.h f +tilde.h f +bind.c f +complete.c f +display.c f +emacs_keymap.c f +funmap.c f +history.c f +isearch.c f +keymaps.c f +parens.c f +readline.c f +readline.h f +rltty.c f +search.c f +signals.c f +tilde.c f +vi_keymap.c f +vi_mode.c f +xmalloc.c f +doc/Makefile f +doc/rlman.texinfo f +doc/rltech.texinfo f +doc/rluser.texinfo f +doc/hist.texinfo f +doc/hstech.texinfo f +doc/hsuser.texinfo f +doc/readline.3 f +examples/Makefile f +examples/fileman.c f +examples/manexamp.c f +examples/Inputrc f diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..afeab8b --- /dev/null +++ b/Makefile @@ -0,0 +1,205 @@ +# Generated automatically from Makefile.in by configure. +# Master Makefile for the GNU readline library. +# Copyright (C) 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +srcdir = . + +prefix = /usr/local +exec_prefix = $(prefix) +bindir = $(exec_prefix)/bin +libdir = $(exec_prefix)/lib +mandir = $(prefix)/man/man1 + +SHELL = /bin/sh + +INSTALL = /bin/install -c +INSTALL_PROGRAM = ${INSTALL} +INSTALL_DATA = ${INSTALL} -m 644 + +RANLIB = ranlib +AR = ar +RM = rm +CP = cp +MV = mv + +DEFS = -DHAVE_CONFIG_H +CFLAGS = -g +LDFLAGS = -g + +# For libraries which include headers from other libraries. +INCLUDES = -I. -I$(srcdir) + +CPPFLAGS = $(DEFS) $(INCLUDES) + +PICFLAG= -pic # -fpic for some versions of gcc +SHLIB_OPTS= -assert pure-text -ldl # -Bshareable for some versions of gcc +MAJOR= 2 +MINOR= .0 + +.SUFFIXES: .so +.c.o: + $(CC) -c $(CPPFLAGS) $(CFLAGS) $< + +.c.so: + -mv $*.o z$*.o + $(CC) -c $(PICFLAG) $(CPPFLAGS) $(CFLAGS) $< + mv $*.o $@ + -mv z$*.o $*.o + +# The name of the main library target. +LIBRARY_NAME = libreadline.a +SHARED_READLINE = libreadline.so.$(MAJOR)$(MINOR) +SHARED_HISTORY = libhistory.so.$(MAJOR)$(MINOR) +SHARED_LIBS = $(SHARED_READLINE) $(SHARED_HISTORY) + +# The C code source files for this library. +CSOURCES = $(srcdir)readline.c $(srcdir)funmap.c $(srcdir)keymaps.c \ + $(srcdir)vi_mode.c $(srcdir)parens.c $(srcdir)rltty.c \ + $(srcdir)complete.c $(srcdir)bind.c $(srcdir)isearch.c \ + $(srcdir)display.c $(srcdir)signals.c $(srcdir)emacs_keymap.c \ + $(srcdir)vi_keymap.c $(srcdir)history.c $(srcdir)tilde.c \ + $(srcdir)xmalloc.c + +# The header files for this library. +HSOURCES = readline.h rldefs.h chardefs.h keymaps.h history.h \ + posixstat.h tilde.h rlconf.h + +INSTALLED_HEADERS = readline.h chardefs.h keymaps.h history.h tilde.h + +OBJECTS = readline.o vi_mode.o funmap.o keymaps.o parens.o search.o \ + rltty.o complete.o bind.o isearch.o display.o signals.o \ + history.o tilde.o xmalloc.o + +SHARED_OBJ = readline.so vi_mode.so funmap.so keymaps.so parens.so search.so \ + rltty.so complete.so bind.so isearch.so display.so signals.so \ + history.so tilde.so xmalloc.so + +# The texinfo files which document this library. +DOCSOURCE = doc/rlman.texinfo doc/rltech.texinfo doc/rluser.texinfo +DOCOBJECT = doc/readline.dvi +DOCSUPPORT = doc/Makefile +DOCUMENTATION = $(DOCSOURCE) $(DOCOBJECT) $(DOCSUPPORT) + +SUPPORT = Makefile ChangeLog $(DOCSUPPORT) examples/[-a-z.]* + +SOURCES = $(CSOURCES) $(HSOURCES) $(DOCSOURCE) + +THINGS_TO_TAR = $(SOURCES) $(SUPPORT) + +########################################################################## + +all: libreadline.a libhistory.a +shared: $(SHARED_LIBS) + +libreadline.a: $(OBJECTS) + $(RM) -f $@ + $(AR) cq $@ $(OBJECTS) + -$(RANLIB) $@ + +libhistory.a: history.o + $(RM) -f $@ + $(AR) cq $@ history.o + -$(RANLIB) $@ + +$(SHARED_READLINE): $(SHARED_OBJ) + $(RM) -f $@ + ld ${SHLIB_OPTS} -o $@ $(SHARED_OBJ) + +$(SHARED_HISTORY): history.so + $(RM) -f $@ + ld ${SHLIB_OPTS} -o $@ history.so + +documentation: force + [ ! -d doc ] && mkdir doc + (if [ -d doc ]; then cd doc; $(MAKE) $(MFLAGS); fi) + +force: + +install: installdirs libreadline.a + $(INSTALL_DATA) $(INSTALLED_HEADERS) $(incdir)/readline + -$(MV) $(libdir)/libreadline.a $(libdir)/libreadline.old + $(INSTALL_DATA) libreadline.a $(libdir)/libreadline.a + -$(RANLIB) -t $(libdir)/libreadline.a + +installdirs: + [ ! -d $(incdir)/readline ] && { \ + mkdir $(incdir)/readline && chmod 755 $(incdir)/readline; } + [ ! -d $(libdir) ] && mkdir $(libdir) + +uninstall: + [ -n "$(incdir)" ] && cd $(incdir)/readline && \ + ${RM} -f ${INSTALLED_HEADERS} + [ -n "$(libdir)" ] && cd $(libdir) && \ + ${RM} -f libreadline.a libreadline.old $(SHARED_LIBS) + +clean:: + rm -f $(OBJECTS) *.a $(SHARED_OBJ) $(SHARED_LIBS) + (if [ -d doc ]; then cd doc; $(MAKE) $(MFLAGS) $@; fi) + +readline: readline.h rldefs.h chardefs.h +readline: $(OBJECTS) + $(CC) $(CFLAGS) $(CPPFLAGS) $(READLINE_DEFINES) \ + $(LOCAL_INCLUDES) -DTEST -o readline readline.c vi_mode.o funmap.o \ + keymaps.o -ltermcap + +info: +install-info: +dvi: +check: +installcheck: + +tags: force + etags $(CSOURCES) $(HSOURCES) + +TAGS: force + ctags -x $(CSOURCES) $(HSOURCES) > $@ + +Makefile: config.status $(srcdir)/Makefile.in + $(SHELL) config.status + +config.status: configure + $(SHELL) config.status --recheck + +configure: configure.in ## Comment-me-out in distribution + cd $(srcdir); autoconf ## Comment-me-out in distribution +config.h.in: configure.in ## Comment-me-out in distribution + cd $(srcdir); autoheader ## Comment-me-out in distribution + +mostlyclean: clean + +distclean realclean: clean + rm -f Makefile config.status config.h stamp-config + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: + +# Dependencies +readline.o: readline.c readline.h rldefs.h rlconf.h chardefs.h +readline.o: keymaps.h history.h +vi_mode.o: rldefs.h rlconf.h readline.h history.h +funmap.o: funmap.c readline.h rlconf.h +keymaps.o: keymaps.c emacs_keymap.c vi_keymap.c keymaps.h chardefs.h rlconf.h +history.o: history.h memalloc.h +isearch.o: memalloc.h readline.h history.h +search.o: memalloc.h readline.h history.h +display.o: readline.h history.h rldefs.h rlconf.h +complete.o: readline.h rldefs.h rlconf.h +rltty.o: rldefs.h rlconf.h readline.h +bind.o: rldefs.h rlconf.h readline.h history.h +signals.o: rldefs.h rlconf.h readline.h history.h +parens.o: readline.h diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..02888bd --- /dev/null +++ b/Makefile.in @@ -0,0 +1,205 @@ +# Master Makefile for the GNU readline library. +# Copyright (C) 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +srcdir = @srcdir@ +VPATH = @srcdir@ + +prefix = /usr/local +exec_prefix = $(prefix) +bindir = $(exec_prefix)/bin +libdir = $(exec_prefix)/lib +mandir = $(prefix)/man/man1 + +SHELL = /bin/sh + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ + +RANLIB = @RANLIB@ +AR = ar +RM = rm +CP = cp +MV = mv + +DEFS = @DEFS@ +CFLAGS = -g +LDFLAGS = -g + +# For libraries which include headers from other libraries. +INCLUDES = -I. -I$(srcdir) + +CPPFLAGS = $(DEFS) $(INCLUDES) + +PICFLAG= -pic # -fpic for some versions of gcc +SHLIB_OPTS= -assert pure-text -ldl # -Bshareable for some versions of gcc +MAJOR= 2 +MINOR= .0 + +.SUFFIXES: .so +.c.o: + $(CC) -c $(CPPFLAGS) $(CFLAGS) $< + +.c.so: + -mv $*.o z$*.o + $(CC) -c $(PICFLAG) $(CPPFLAGS) $(CFLAGS) $< + mv $*.o $@ + -mv z$*.o $*.o + +# The name of the main library target. +LIBRARY_NAME = libreadline.a +SHARED_READLINE = libreadline.so.$(MAJOR)$(MINOR) +SHARED_HISTORY = libhistory.so.$(MAJOR)$(MINOR) +SHARED_LIBS = $(SHARED_READLINE) $(SHARED_HISTORY) + +# The C code source files for this library. +CSOURCES = $(srcdir)readline.c $(srcdir)funmap.c $(srcdir)keymaps.c \ + $(srcdir)vi_mode.c $(srcdir)parens.c $(srcdir)rltty.c \ + $(srcdir)complete.c $(srcdir)bind.c $(srcdir)isearch.c \ + $(srcdir)display.c $(srcdir)signals.c $(srcdir)emacs_keymap.c \ + $(srcdir)vi_keymap.c $(srcdir)history.c $(srcdir)tilde.c \ + $(srcdir)xmalloc.c + +# The header files for this library. +HSOURCES = readline.h rldefs.h chardefs.h keymaps.h history.h \ + posixstat.h tilde.h rlconf.h + +INSTALLED_HEADERS = readline.h chardefs.h keymaps.h history.h tilde.h + +OBJECTS = readline.o vi_mode.o funmap.o keymaps.o parens.o search.o \ + rltty.o complete.o bind.o isearch.o display.o signals.o \ + history.o tilde.o xmalloc.o + +SHARED_OBJ = readline.so vi_mode.so funmap.so keymaps.so parens.so search.so \ + rltty.so complete.so bind.so isearch.so display.so signals.so \ + history.so tilde.so xmalloc.so + +# The texinfo files which document this library. +DOCSOURCE = doc/rlman.texinfo doc/rltech.texinfo doc/rluser.texinfo +DOCOBJECT = doc/readline.dvi +DOCSUPPORT = doc/Makefile +DOCUMENTATION = $(DOCSOURCE) $(DOCOBJECT) $(DOCSUPPORT) + +SUPPORT = Makefile ChangeLog $(DOCSUPPORT) examples/[-a-z.]* + +SOURCES = $(CSOURCES) $(HSOURCES) $(DOCSOURCE) + +THINGS_TO_TAR = $(SOURCES) $(SUPPORT) + +########################################################################## + +all: libreadline.a libhistory.a +shared: $(SHARED_LIBS) + +libreadline.a: $(OBJECTS) + $(RM) -f $@ + $(AR) cq $@ $(OBJECTS) + -$(RANLIB) $@ + +libhistory.a: history.o + $(RM) -f $@ + $(AR) cq $@ history.o + -$(RANLIB) $@ + +$(SHARED_READLINE): $(SHARED_OBJ) + $(RM) -f $@ + ld ${SHLIB_OPTS} -o $@ $(SHARED_OBJ) + +$(SHARED_HISTORY): history.so + $(RM) -f $@ + ld ${SHLIB_OPTS} -o $@ history.so + +documentation: force + [ ! -d doc ] && mkdir doc + (if [ -d doc ]; then cd doc; $(MAKE) $(MFLAGS); fi) + +force: + +install: installdirs libreadline.a + $(INSTALL_DATA) $(INSTALLED_HEADERS) $(incdir)/readline + -$(MV) $(libdir)/libreadline.a $(libdir)/libreadline.old + $(INSTALL_DATA) libreadline.a $(libdir)/libreadline.a + -$(RANLIB) -t $(libdir)/libreadline.a + +installdirs: + [ ! -d $(incdir)/readline ] && { \ + mkdir $(incdir)/readline && chmod 755 $(incdir)/readline; } + [ ! -d $(libdir) ] && mkdir $(libdir) + +uninstall: + [ -n "$(incdir)" ] && cd $(incdir)/readline && \ + ${RM} -f ${INSTALLED_HEADERS} + [ -n "$(libdir)" ] && cd $(libdir) && \ + ${RM} -f libreadline.a libreadline.old $(SHARED_LIBS) + +clean:: + rm -f $(OBJECTS) *.a $(SHARED_OBJ) $(SHARED_LIBS) + (if [ -d doc ]; then cd doc; $(MAKE) $(MFLAGS) $@; fi) + +readline: readline.h rldefs.h chardefs.h +readline: $(OBJECTS) + $(CC) $(CFLAGS) $(CPPFLAGS) $(READLINE_DEFINES) \ + $(LOCAL_INCLUDES) -DTEST -o readline readline.c vi_mode.o funmap.o \ + keymaps.o -ltermcap + +info: +install-info: +dvi: +check: +installcheck: + +tags: force + etags $(CSOURCES) $(HSOURCES) + +TAGS: force + ctags -x $(CSOURCES) $(HSOURCES) > $@ + +Makefile: config.status $(srcdir)/Makefile.in + $(SHELL) config.status + +config.status: configure + $(SHELL) config.status --recheck + +configure: configure.in ## Comment-me-out in distribution + cd $(srcdir); autoconf ## Comment-me-out in distribution +config.h.in: configure.in ## Comment-me-out in distribution + cd $(srcdir); autoheader ## Comment-me-out in distribution + +mostlyclean: clean + +distclean realclean: clean + rm -f Makefile config.status config.h stamp-config + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: + +# Dependencies +readline.o: readline.c readline.h rldefs.h rlconf.h chardefs.h +readline.o: keymaps.h history.h +vi_mode.o: rldefs.h rlconf.h readline.h history.h +funmap.o: funmap.c readline.h rlconf.h +keymaps.o: keymaps.c emacs_keymap.c vi_keymap.c keymaps.h chardefs.h rlconf.h +history.o: history.h memalloc.h +isearch.o: memalloc.h readline.h history.h +search.o: memalloc.h readline.h history.h +display.o: readline.h history.h rldefs.h rlconf.h +complete.o: readline.h rldefs.h rlconf.h +rltty.o: rldefs.h rlconf.h readline.h +bind.o: rldefs.h rlconf.h readline.h history.h +signals.o: rldefs.h rlconf.h readline.h history.h +parens.o: readline.h diff --git a/README b/README new file mode 100644 index 0000000..131471c --- /dev/null +++ b/README @@ -0,0 +1,6 @@ +This is the distribution of the Gnu Readline library. See the file +STANDALONE for a description of the #defines that can be passed via +the makefile to build readline on different systems. + +The file rlconf.h contains defines that enable and disable certain +readline features. diff --git a/STANDALONE b/STANDALONE new file mode 100644 index 0000000..c1387f3 --- /dev/null +++ b/STANDALONE @@ -0,0 +1,31 @@ +This is a description of C preprocessor defines that readline accepts. +Most are passed in from the parent `make'; e.g. from the bash source +directory. + +NO_SYS_FILE is not present +HAVE_UNISTD_H exists +HAVE_STDLIB_H exists +HAVE_VARARGS_H exists and is usable +HAVE_STRING_H exists +HAVE_ALLOCA_H exists and is needed for alloca() +HAVE_ALLOCA alloca(3) or a define for it exists +PRAGMA_ALLOCA use of alloca() requires a #pragma, as in AIX 3.x +VOID_SIGHANDLER signal handlers are void functions +HAVE_DIRENT_H exists and is usable +HAVE_SYS_PTEM_H exists +HAVE_SYS_PTE_H exists +HAVE_SYS_STREAM_H exists + +System-specific options: + +GWINSZ_IN_SYS_IOCTL need to include for TIOCGWINSZ +HAVE_GETPW_DECLS the getpw* functions are declared in and cannot + be redeclared without compiler errors +HAVE_STRCASECMP the strcasecmp and strncasecmp functions are available + +USG Running a variant of System V +USGr3 Running System V.3 +XENIX_22 Xenix 2.2 +Linux Linux +CRAY running a recent version of Cray UNICOS +SunOS4 Running SunOS 4.x diff --git a/acconfig.h b/acconfig.h new file mode 100644 index 0000000..ebf44e9 --- /dev/null +++ b/acconfig.h @@ -0,0 +1,28 @@ +/* acconfig.h + This file is in the public domain. + + Descriptive text for the C preprocessor macros that + the distributed Autoconf macros can define. + No software package will use all of them; autoheader copies the ones + your configure.in uses into your configuration header file templates. + + The entries are in sort -df order: alphabetical, case insensitive, + ignoring punctuation (such as underscores). Although this order + can split up related entries, it makes it easier to check whether + a given entry is in the file. + + Leave the following blank line there!! Autoheader needs it. */ + + +/* Define if your system defines TIOCGWINSZ in sys/ioctl.h. */ +#undef GWINSZ_IN_SYS_IOCTL + +#undef HAVE_GETPW_DECLS + +#undef NO_SYS_FILE + + +/* Leave that blank line there!! Autoheader needs it. + If you're adding to this file, keep in mind: + The entries are in sort -df order: alphabetical, case insensitive, + ignoring punctuation (such as underscores). */ diff --git a/ansi_stdlib.h b/ansi_stdlib.h new file mode 100644 index 0000000..52339da --- /dev/null +++ b/ansi_stdlib.h @@ -0,0 +1,41 @@ +/* ansi_stdlib.h -- An ANSI Standard stdlib.h. */ +/* A minimal stdlib.h containing extern declarations for those functions + that bash uses. */ + +/* Copyright (C) 1993 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash 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. + + Bash 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 Bash; see the file COPYING. If not, write to the Free Software + Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#if !defined (_STDLIB_H_) +#define _STDLIB_H_ 1 + +/* String conversion functions. */ +extern int atoi (); +extern long int atol (); + +/* Memory allocation functions. */ +extern char *malloc (); +extern char *realloc (); +extern void free (); + +/* Other miscellaneous functions. */ +extern void abort (); +extern void exit (); +extern char *getenv (); +extern void qsort (); + +#endif /* _STDLIB_H */ diff --git a/bind.c b/bind.c new file mode 100644 index 0000000..8821599 --- /dev/null +++ b/bind.c @@ -0,0 +1,1487 @@ +/* bind.c -- key binding and startup file support for the readline library. */ + +/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library 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 1, or + (at your option) any later version. + + The GNU Readline Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define READLINE_LIBRARY + +#include +#include +#include +#if !defined (NO_SYS_FILE) +# include +#endif /* !NO_SYS_FILE */ +#include + +#if defined (HAVE_UNISTD_H) +# include +#endif /* HAVE_UNISTD_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#include +/* Not all systems declare ERRNO in errno.h... and some systems #define it! */ +#if !defined (errno) +extern int errno; +#endif /* !errno */ + +#include "posixstat.h" + +/* System-specific feature definitions and include files. */ +#include "rldefs.h" + +/* Some standard library routines. */ +#include "readline.h" +#include "history.h" + +#if !defined (strchr) && !defined (__STDC__) +extern char *strchr (), *strrchr (); +#endif /* !strchr && !__STDC__ */ + +extern int _rl_horizontal_scroll_mode; +extern int _rl_mark_modified_lines; +extern int _rl_bell_preference; +extern int _rl_meta_flag; +extern int _rl_convert_meta_chars_to_ascii; +extern int _rl_output_meta_chars; +extern int _rl_complete_show_all; +#if defined (PAREN_MATCHING) +extern int rl_blink_matching_paren; +#endif /* PAREN_MATCHING */ +#if defined (VISIBLE_STATS) +extern int rl_visible_stats; +#endif /* VISIBLE_STATS */ +extern int rl_complete_with_tilde_expansion; +extern int rl_completion_query_items; +#if defined (VI_MODE) +extern char *rl_vi_comment_begin; +#endif + +extern int rl_explicit_arg; +extern int rl_editing_mode; +extern unsigned short _rl_parsing_conditionalized_out; +extern Keymap _rl_keymap; + +extern char *possible_control_prefixes[], *possible_meta_prefixes[]; + +extern char **rl_funmap_names (); + +/* Forward declarations */ +void rl_set_keymap_from_edit_mode (); + +static int glean_key_from_name (); + +#if defined (HAVE_STRCASECMP) +#define stricmp strcasecmp +#define strnicmp strncasecmp +#else +static int stricmp (), strnicmp (); +#endif + +#if defined (STATIC_MALLOC) +static char *xmalloc (), *xrealloc (); +#else +extern char *xmalloc (), *xrealloc (); +#endif /* STATIC_MALLOC */ + +/* **************************************************************** */ +/* */ +/* Binding keys */ +/* */ +/* **************************************************************** */ + +/* rl_add_defun (char *name, Function *function, int key) + Add NAME to the list of named functions. Make FUNCTION be the function + that gets called. If KEY is not -1, then bind it. */ +rl_add_defun (name, function, key) + char *name; + Function *function; + int key; +{ + if (key != -1) + rl_bind_key (key, function); + rl_add_funmap_entry (name, function); + return 0; +} + +/* Bind KEY to FUNCTION. Returns non-zero if KEY is out of range. */ +int +rl_bind_key (key, function) + int key; + Function *function; +{ + if (key < 0) + return (key); + + if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii) + { + if (_rl_keymap[ESC].type == ISKMAP) + { + Keymap escmap; + + escmap = FUNCTION_TO_KEYMAP (_rl_keymap, ESC); + key = UNMETA (key); + escmap[key].type = ISFUNC; + escmap[key].function = function; + return (0); + } + return (key); + } + + _rl_keymap[key].type = ISFUNC; + _rl_keymap[key].function = function; + return (0); +} + +/* Bind KEY to FUNCTION in MAP. Returns non-zero in case of invalid + KEY. */ +int +rl_bind_key_in_map (key, function, map) + int key; + Function *function; + Keymap map; +{ + int result; + Keymap oldmap = _rl_keymap; + + _rl_keymap = map; + result = rl_bind_key (key, function); + _rl_keymap = oldmap; + return (result); +} + +/* Make KEY do nothing in the currently selected keymap. + Returns non-zero in case of error. */ +int +rl_unbind_key (key) + int key; +{ + return (rl_bind_key (key, (Function *)NULL)); +} + +/* Make KEY do nothing in MAP. + Returns non-zero in case of error. */ +int +rl_unbind_key_in_map (key, map) + int key; + Keymap map; +{ + return (rl_bind_key_in_map (key, (Function *)NULL, map)); +} + +/* Bind the key sequence represented by the string KEYSEQ to + FUNCTION. This makes new keymaps as necessary. The initial + place to do bindings is in MAP. */ +rl_set_key (keyseq, function, map) + char *keyseq; + Function *function; + Keymap map; +{ + return (rl_generic_bind (ISFUNC, keyseq, function, map)); +} + +/* Bind the key sequence represented by the string KEYSEQ to + the string of characters MACRO. This makes new keymaps as + necessary. The initial place to do bindings is in MAP. */ +rl_macro_bind (keyseq, macro, map) + char *keyseq, *macro; + Keymap map; +{ + char *macro_keys; + int macro_keys_len; + + macro_keys = (char *)xmalloc ((2 * strlen (macro)) + 1); + + if (rl_translate_keyseq (macro, macro_keys, ¯o_keys_len)) + { + free (macro_keys); + return -1; + } + rl_generic_bind (ISMACR, keyseq, macro_keys, map); + return 0; +} + +/* Bind the key sequence represented by the string KEYSEQ to + the arbitrary pointer DATA. TYPE says what kind of data is + pointed to by DATA, right now this can be a function (ISFUNC), + a macro (ISMACR), or a keymap (ISKMAP). This makes new keymaps + as necessary. The initial place to do bindings is in MAP. */ +rl_generic_bind (type, keyseq, data, map) + int type; + char *keyseq, *data; + Keymap map; +{ + char *keys; + int keys_len; + register int i; + + /* If no keys to bind to, exit right away. */ + if (!keyseq || !*keyseq) + { + if (type == ISMACR) + free (data); + return -1; + } + + keys = xmalloc (1 + (2 * strlen (keyseq))); + + /* Translate the ASCII representation of KEYSEQ into an array of + characters. Stuff the characters into KEYS, and the length of + KEYS into KEYS_LEN. */ + if (rl_translate_keyseq (keyseq, keys, &keys_len)) + { + free (keys); + return -1; + } + + /* Bind keys, making new keymaps as necessary. */ + for (i = 0; i < keys_len; i++) + { + int ic = (int) ((unsigned char)keys[i]); + + if (_rl_convert_meta_chars_to_ascii && META_CHAR (ic)) + { + ic = UNMETA (ic); + if (map[ESC].type == ISKMAP) + map = FUNCTION_TO_KEYMAP (map, ESC); + } + + if ((i + 1) < keys_len) + { + if (map[ic].type != ISKMAP) + { + if (map[ic].type == ISMACR) + free ((char *)map[ic].function); + + map[ic].type = ISKMAP; + map[ic].function = KEYMAP_TO_FUNCTION (rl_make_bare_keymap()); + } + map = FUNCTION_TO_KEYMAP (map, ic); + } + else + { + if (map[ic].type == ISMACR) + free ((char *)map[ic].function); + + map[ic].function = KEYMAP_TO_FUNCTION (data); + map[ic].type = type; + } + } + free (keys); + return 0; +} + +/* Translate the ASCII representation of SEQ, stuffing the values into ARRAY, + an array of characters. LEN gets the final length of ARRAY. Return + non-zero if there was an error parsing SEQ. */ +rl_translate_keyseq (seq, array, len) + char *seq, *array; + int *len; +{ + register int i, c, l = 0; + + for (i = 0; c = seq[i]; i++) + { + if (c == '\\') + { + c = seq[++i]; + + if (!c) + break; + + if (((c == 'C' || c == 'M') && seq[i + 1] == '-') || + (c == 'e')) + { + /* Handle special case of backwards define. */ + if (strncmp (&seq[i], "C-\\M-", 5) == 0) + { + array[l++] = ESC; + i += 5; + array[l++] = CTRL (to_upper (seq[i])); + if (!seq[i]) + i--; + continue; + } + + switch (c) + { + case 'M': + i++; + array[l++] = ESC; + break; + + case 'C': + i += 2; + /* Special hack for C-?... */ + if (seq[i] == '?') + array[l++] = RUBOUT; + else + array[l++] = CTRL (to_upper (seq[i])); + break; + + case 'e': + array[l++] = ESC; + } + + continue; + } + } + array[l++] = c; + } + + *len = l; + array[l] = '\0'; + return (0); +} + +/* Return a pointer to the function that STRING represents. + If STRING doesn't have a matching function, then a NULL pointer + is returned. */ +Function * +rl_named_function (string) + char *string; +{ + register int i; + + rl_initialize_funmap (); + + for (i = 0; funmap[i]; i++) + if (stricmp (funmap[i]->name, string) == 0) + return (funmap[i]->function); + return ((Function *)NULL); +} + +/* Return the function (or macro) definition which would be invoked via + KEYSEQ if executed in MAP. If MAP is NULL, then the current keymap is + used. TYPE, if non-NULL, is a pointer to an int which will receive the + type of the object pointed to. One of ISFUNC (function), ISKMAP (keymap), + or ISMACR (macro). */ +Function * +rl_function_of_keyseq (keyseq, map, type) + char *keyseq; + Keymap map; + int *type; +{ + register int i; + + if (!map) + map = _rl_keymap; + + for (i = 0; keyseq && keyseq[i]; i++) + { + int ic = keyseq[i]; + + if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii) + { + if (map[ESC].type != ISKMAP) + { + if (type) + *type = map[ESC].type; + + return (map[ESC].function); + } + else + { + map = FUNCTION_TO_KEYMAP (map, ESC); + ic = UNMETA (ic); + } + } + + if (map[ic].type == ISKMAP) + { + /* If this is the last key in the key sequence, return the + map. */ + if (!keyseq[i + 1]) + { + if (type) + *type = ISKMAP; + + return (map[ic].function); + } + else + map = FUNCTION_TO_KEYMAP (map, ic); + } + else + { + if (type) + *type = map[ic].type; + + return (map[ic].function); + } + } + return ((Function *) NULL); +} + +/* The last key bindings file read. */ +static char *last_readline_init_file = (char *)NULL; + +/* Re-read the current keybindings file. */ +rl_re_read_init_file (count, ignore) + int count, ignore; +{ + int r; + r = rl_read_init_file ((char *)NULL); + rl_set_keymap_from_edit_mode (); + return r; +} + +/* Do key bindings from a file. If FILENAME is NULL it defaults + to the first non-null filename from this list: + 1. the filename used for the previous call + 2. the value of the shell variable `INPUTRC' + 3. ~/.inputrc + If the file existed and could be opened and read, 0 is returned, + otherwise errno is returned. */ +int +rl_read_init_file (filename) + char *filename; +{ + register int i; + char *buffer, *openname, *line, *end; + struct stat finfo; + int file; + + /* Default the filename. */ + if (!filename) + { + filename = last_readline_init_file; + if (!filename) + filename = getenv ("INPUTRC"); + if (!filename) + filename = DEFAULT_INPUTRC; + } + + if (!*filename) + filename = DEFAULT_INPUTRC; + + openname = tilde_expand (filename); + + if ((stat (openname, &finfo) < 0) || + (file = open (openname, O_RDONLY, 0666)) < 0) + { + free (openname); + return (errno); + } + else + free (openname); + + if (filename != last_readline_init_file) + { + if (last_readline_init_file) + free (last_readline_init_file); + + last_readline_init_file = savestring (filename); + } + + /* Read the file into BUFFER. */ + buffer = (char *)xmalloc ((int)finfo.st_size + 1); + i = read (file, buffer, finfo.st_size); + close (file); + + if (i != finfo.st_size) + return (errno); + + /* Loop over the lines in the file. Lines that start with `#' are + comments; all other lines are commands for readline initialization. */ + line = buffer; + end = buffer + finfo.st_size; + while (line < end) + { + /* Find the end of this line. */ + for (i = 0; line + i != end && line[i] != '\n'; i++); + + /* Mark end of line. */ + line[i] = '\0'; + + /* Skip leading whitespace. */ + while (*line && whitespace (*line)) + { + line++; + i--; + } + + /* If the line is not a comment, then parse it. */ + if (*line && *line != '#') + rl_parse_and_bind (line); + + /* Move to the next line. */ + line += i + 1; + } + free (buffer); + return (0); +} + +/* **************************************************************** */ +/* */ +/* Parser Directives */ +/* */ +/* **************************************************************** */ + +/* Conditionals. */ + +/* Calling programs set this to have their argv[0]. */ +char *rl_readline_name = "other"; + +/* Stack of previous values of parsing_conditionalized_out. */ +static unsigned char *if_stack = (unsigned char *)NULL; +static int if_stack_depth = 0; +static int if_stack_size = 0; + +/* Push _rl_parsing_conditionalized_out, and set parser state based + on ARGS. */ +static int +parser_if (args) + char *args; +{ + register int i; + + /* Push parser state. */ + if (if_stack_depth + 1 >= if_stack_size) + { + if (!if_stack) + if_stack = (unsigned char *)xmalloc (if_stack_size = 20); + else + if_stack = (unsigned char *)xrealloc (if_stack, if_stack_size += 20); + } + if_stack[if_stack_depth++] = _rl_parsing_conditionalized_out; + + /* If parsing is turned off, then nothing can turn it back on except + for finding the matching endif. In that case, return right now. */ + if (_rl_parsing_conditionalized_out) + return 0; + + /* Isolate first argument. */ + for (i = 0; args[i] && !whitespace (args[i]); i++); + + if (args[i]) + args[i++] = '\0'; + + /* Handle "if term=foo" and "if mode=emacs" constructs. If this + isn't term=foo, or mode=emacs, then check to see if the first + word in ARGS is the same as the value stored in rl_readline_name. */ + if (rl_terminal_name && strnicmp (args, "term=", 5) == 0) + { + char *tem, *tname; + + /* Terminals like "aaa-60" are equivalent to "aaa". */ + tname = savestring (rl_terminal_name); + tem = strchr (tname, '-'); + if (tem) + *tem = '\0'; + + /* Test the `long' and `short' forms of the terminal name so that + if someone has a `sun-cmd' and does not want to have bindings + that will be executed if the terminal is a `sun', they can put + `$if term=sun-cmd' into their .inputrc. */ + if ((stricmp (args + 5, tname) == 0) || + (stricmp (args + 5, rl_terminal_name) == 0)) + _rl_parsing_conditionalized_out = 0; + else + _rl_parsing_conditionalized_out = 1; + + free (tname); + } +#if defined (VI_MODE) + else if (strnicmp (args, "mode=", 5) == 0) + { + int mode; + + if (stricmp (args + 5, "emacs") == 0) + mode = emacs_mode; + else if (stricmp (args + 5, "vi") == 0) + mode = vi_mode; + else + mode = no_mode; + + if (mode == rl_editing_mode) + _rl_parsing_conditionalized_out = 0; + else + _rl_parsing_conditionalized_out = 1; + } +#endif /* VI_MODE */ + /* Check to see if the first word in ARGS is the same as the + value stored in rl_readline_name. */ + else if (stricmp (args, rl_readline_name) == 0) + _rl_parsing_conditionalized_out = 0; + else + _rl_parsing_conditionalized_out = 1; + return 0; +} + +/* Invert the current parser state if there is anything on the stack. */ +static int +parser_else (args) + char *args; +{ + register int i; + + if (!if_stack_depth) + { + /* Error message? */ + return 0; + } + + /* Check the previous (n - 1) levels of the stack to make sure that + we haven't previously turned off parsing. */ + for (i = 0; i < if_stack_depth - 1; i++) + if (if_stack[i] == 1) + return 0; + + /* Invert the state of parsing if at top level. */ + _rl_parsing_conditionalized_out = !_rl_parsing_conditionalized_out; + return 0; +} + +/* Terminate a conditional, popping the value of + _rl_parsing_conditionalized_out from the stack. */ +static int +parser_endif (args) + char *args; +{ + if (if_stack_depth) + _rl_parsing_conditionalized_out = if_stack[--if_stack_depth]; + else + { + /* *** What, no error message? *** */ + } + return 0; +} + +/* Associate textual names with actual functions. */ +static struct { + char *name; + Function *function; +} parser_directives [] = { + { "if", parser_if }, + { "endif", parser_endif }, + { "else", parser_else }, + { (char *)0x0, (Function *)0x0 } +}; + +/* Handle a parser directive. STATEMENT is the line of the directive + without any leading `$'. */ +static int +handle_parser_directive (statement) + char *statement; +{ + register int i; + char *directive, *args; + + /* Isolate the actual directive. */ + + /* Skip whitespace. */ + for (i = 0; whitespace (statement[i]); i++); + + directive = &statement[i]; + + for (; statement[i] && !whitespace (statement[i]); i++); + + if (statement[i]) + statement[i++] = '\0'; + + for (; statement[i] && whitespace (statement[i]); i++); + + args = &statement[i]; + + /* Lookup the command, and act on it. */ + for (i = 0; parser_directives[i].name; i++) + if (stricmp (directive, parser_directives[i].name) == 0) + { + (*parser_directives[i].function) (args); + return (0); + } + + /* *** Should an error message be output? */ + return (1); +} + +static int substring_member_of_array (); + +/* Read the binding command from STRING and perform it. + A key binding command looks like: Keyname: function-name\0, + a variable binding command looks like: set variable value. + A new-style keybinding looks like "\C-x\C-x": exchange-point-and-mark. */ +rl_parse_and_bind (string) + char *string; +{ + char *funname, *kname; + register int c, i; + int key, equivalency; + + while (string && whitespace (*string)) + string++; + + if (!string || !*string || *string == '#') + return 0; + + /* If this is a parser directive, act on it. */ + if (*string == '$') + { + handle_parser_directive (&string[1]); + return 0; + } + + /* If we aren't supposed to be parsing right now, then we're done. */ + if (_rl_parsing_conditionalized_out) + return 0; + + i = 0; + /* If this keyname is a complex key expression surrounded by quotes, + advance to after the matching close quote. This code allows the + backslash to quote characters in the key expression. */ + if (*string == '"') + { + int passc = 0; + + for (i = 1; c = string[i]; i++) + { + if (passc) + { + passc = 0; + continue; + } + + if (c == '\\') + { + passc++; + continue; + } + + if (c == '"') + break; + } + } + + /* Advance to the colon (:) or whitespace which separates the two objects. */ + for (; (c = string[i]) && c != ':' && c != ' ' && c != '\t'; i++ ); + + equivalency = (c == ':' && string[i + 1] == '='); + + /* Mark the end of the command (or keyname). */ + if (string[i]) + string[i++] = '\0'; + + /* If doing assignment, skip the '=' sign as well. */ + if (equivalency) + string[i++] = '\0'; + + /* If this is a command to set a variable, then do that. */ + if (stricmp (string, "set") == 0) + { + char *var = string + i; + char *value; + + /* Make VAR point to start of variable name. */ + while (*var && whitespace (*var)) var++; + + /* Make value point to start of value string. */ + value = var; + while (*value && !whitespace (*value)) value++; + if (*value) + *value++ = '\0'; + while (*value && whitespace (*value)) value++; + + rl_variable_bind (var, value); + return 0; + } + + /* Skip any whitespace between keyname and funname. */ + for (; string[i] && whitespace (string[i]); i++); + funname = &string[i]; + + /* Now isolate funname. + For straight function names just look for whitespace, since + that will signify the end of the string. But this could be a + macro definition. In that case, the string is quoted, so skip + to the matching delimiter. We allow the backslash to quote the + delimiter characters in the macro body. */ + /* This code exists to allow whitespace in macro expansions, which + would otherwise be gobbled up by the next `for' loop.*/ + /* XXX - it may be desirable to allow backslash quoting only if " is + the quoted string delimiter, like the shell. */ + if (*funname == '\'' || *funname == '"') + { + int delimiter = string[i++]; + int passc = 0; + + for (; c = string[i]; i++) + { + if (passc) + { + passc = 0; + continue; + } + + if (c == '\\') + { + passc = 1; + continue; + } + + if (c == delimiter) + break; + } + if (c) + i++; + } + + /* Advance to the end of the string. */ + for (; string[i] && !whitespace (string[i]); i++); + + /* No extra whitespace at the end of the string. */ + string[i] = '\0'; + + /* Handle equivalency bindings here. Make the left-hand side be exactly + whatever the right-hand evaluates to, including keymaps. */ + if (equivalency) + { + return 0; + } + + /* If this is a new-style key-binding, then do the binding with + rl_set_key (). Otherwise, let the older code deal with it. */ + if (*string == '"') + { + char *seq = xmalloc (1 + strlen (string)); + register int j, k = 0; + int passc = 0; + + for (j = 1; string[j]; j++) + { + /* Allow backslash to quote characters, but leave them in place. + This allows a string to end with a backslash quoting another + backslash, or with a backslash quoting a double quote. The + backslashes are left in place for rl_translate_keyseq (). */ + if (passc || (string[j] == '\\')) + { + seq[k++] = string[j]; + passc = !passc; + continue; + } + + if (string[j] == '"') + break; + + seq[k++] = string[j]; + } + seq[k] = '\0'; + + /* Binding macro? */ + if (*funname == '\'' || *funname == '"') + { + j = strlen (funname); + + /* Remove the delimiting quotes from each end of FUNNAME. */ + if (j && funname[j - 1] == *funname) + funname[j - 1] = '\0'; + + rl_macro_bind (seq, &funname[1], _rl_keymap); + } + else + rl_set_key (seq, rl_named_function (funname), _rl_keymap); + + free (seq); + return 0; + } + + /* Get the actual character we want to deal with. */ + kname = strrchr (string, '-'); + if (!kname) + kname = string; + else + kname++; + + key = glean_key_from_name (kname); + + /* Add in control and meta bits. */ + if (substring_member_of_array (string, possible_control_prefixes)) + key = CTRL (to_upper (key)); + + if (substring_member_of_array (string, possible_meta_prefixes)) + key = META (key); + + /* Temporary. Handle old-style keyname with macro-binding. */ + if (*funname == '\'' || *funname == '"') + { + char seq[2]; + int fl = strlen (funname); + + seq[0] = key; seq[1] = '\0'; + if (fl && funname[fl - 1] == *funname) + funname[fl - 1] = '\0'; + + rl_macro_bind (seq, &funname[1], _rl_keymap); + } +#if defined (PREFIX_META_HACK) + /* Ugly, but working hack to keep prefix-meta around. */ + else if (stricmp (funname, "prefix-meta") == 0) + { + char seq[2]; + + seq[0] = key; + seq[1] = '\0'; + rl_generic_bind (ISKMAP, seq, (char *)emacs_meta_keymap, _rl_keymap); + } +#endif /* PREFIX_META_HACK */ + else + rl_bind_key (key, rl_named_function (funname)); + return 0; +} + +/* Simple structure for boolean readline variables (i.e., those that can + have one of two values; either "On" or 1 for truth, or "Off" or 0 for + false. */ + +static struct { + char *name; + int *value; +} boolean_varlist [] = { + { "horizontal-scroll-mode", &_rl_horizontal_scroll_mode }, + { "mark-modified-lines", &_rl_mark_modified_lines }, + { "meta-flag", &_rl_meta_flag }, +#if defined (PAREN_MATCHING) + { "blink-matching-paren", &rl_blink_matching_paren }, +#endif + { "convert-meta", &_rl_convert_meta_chars_to_ascii }, + { "show-all-if-ambiguous", &_rl_complete_show_all }, + { "output-meta", &_rl_output_meta_chars }, +#if defined (VISIBLE_STATS) + { "visible-stats", &rl_visible_stats }, +#endif /* VISIBLE_STATS */ + { "expand-tilde", &rl_complete_with_tilde_expansion }, + { (char *)NULL, (int *)NULL } +}; + +rl_variable_bind (name, value) + char *name, *value; +{ + register int i; + + /* Check for simple variables first. */ + for (i = 0; boolean_varlist[i].name; i++) + { + if (stricmp (name, boolean_varlist[i].name) == 0) + { + /* A variable is TRUE if the "value" is "on", "1" or "". */ + if ((!*value) || + (stricmp (value, "On") == 0) || + (value[0] == '1' && value[1] == '\0')) + *boolean_varlist[i].value = 1; + else + *boolean_varlist[i].value = 0; + return 0; + } + } + + /* Not a boolean variable, so check for specials. */ + + /* Editing mode change? */ + if (stricmp (name, "editing-mode") == 0) + { + if (strnicmp (value, "vi", 2) == 0) + { +#if defined (VI_MODE) + _rl_keymap = vi_insertion_keymap; + rl_editing_mode = vi_mode; +#endif /* VI_MODE */ + } + else if (strnicmp (value, "emacs", 5) == 0) + { + _rl_keymap = emacs_standard_keymap; + rl_editing_mode = emacs_mode; + } + } + + /* Comment string change? */ + else if (stricmp (name, "comment-begin") == 0) + { +#if defined (VI_MODE) + if (*value) + { + if (rl_vi_comment_begin) + free (rl_vi_comment_begin); + + rl_vi_comment_begin = savestring (value); + } +#endif /* VI_MODE */ + } + else if (stricmp (name, "completion-query-items") == 0) + { + int nval = 100; + if (*value) + { + nval = atoi (value); + if (nval < 0) + nval = 0; + } + rl_completion_query_items = nval; + } + else if (stricmp (name, "keymap") == 0) + { + Keymap kmap; + kmap = rl_get_keymap_by_name (value); + if (kmap) + rl_set_keymap (kmap); + } + else if (stricmp (name, "bell-style") == 0) + { + if (!*value) + _rl_bell_preference = AUDIBLE_BELL; + else + { + if (stricmp (value, "none") == 0 || stricmp (value, "off") == 0) + _rl_bell_preference = NO_BELL; + else if (stricmp (value, "audible") == 0 || stricmp (value, "on") == 0) + _rl_bell_preference = AUDIBLE_BELL; + else if (stricmp (value, "visible") == 0) + _rl_bell_preference = VISIBLE_BELL; + } + } + else if (stricmp (name, "prefer-visible-bell") == 0) + { + /* Backwards compatibility. */ + if (*value && (stricmp (value, "on") == 0 || + (*value == '1' && !value[1]))) + _rl_bell_preference = VISIBLE_BELL; + else + _rl_bell_preference = AUDIBLE_BELL; + } + + return 0; +} + +/* Return the character which matches NAME. + For example, `Space' returns ' '. */ + +typedef struct { + char *name; + int value; +} assoc_list; + +static assoc_list name_key_alist[] = { + { "DEL", 0x7f }, + { "ESC", '\033' }, + { "Escape", '\033' }, + { "LFD", '\n' }, + { "Newline", '\n' }, + { "RET", '\r' }, + { "Return", '\r' }, + { "Rubout", 0x7f }, + { "SPC", ' ' }, + { "Space", ' ' }, + { "Tab", 0x09 }, + { (char *)0x0, 0 } +}; + +static int +glean_key_from_name (name) + char *name; +{ + register int i; + + for (i = 0; name_key_alist[i].name; i++) + if (stricmp (name, name_key_alist[i].name) == 0) + return (name_key_alist[i].value); + + return (*(unsigned char *)name); /* XXX was return (*name) */ +} + +/* Auxiliary functions to manage keymaps. */ +static struct { + char *name; + Keymap map; +} keymap_names[] = { + { "emacs", emacs_standard_keymap }, + { "emacs-standard", emacs_standard_keymap }, + { "emacs-meta", emacs_meta_keymap }, + { "emacs-ctlx", emacs_ctlx_keymap }, +#if defined (VI_MODE) + { "vi", vi_movement_keymap }, + { "vi-move", vi_movement_keymap }, + { "vi-command", vi_movement_keymap }, + { "vi-insert", vi_insertion_keymap }, +#endif /* VI_MODE */ + { (char *)0x0, (Keymap)0x0 } +}; + +Keymap +rl_get_keymap_by_name (name) + char *name; +{ + register int i; + + for (i = 0; keymap_names[i].name; i++) + if (strcmp (name, keymap_names[i].name) == 0) + return (keymap_names[i].map); + return ((Keymap) NULL); +} + +void +rl_set_keymap (map) + Keymap map; +{ + if (map) + _rl_keymap = map; +} + +Keymap +rl_get_keymap () +{ + return (_rl_keymap); +} + +void +rl_set_keymap_from_edit_mode () +{ + if (rl_editing_mode == emacs_mode) + _rl_keymap = emacs_standard_keymap; +#if defined (VI_MODE) + else if (rl_editing_mode == vi_mode) + _rl_keymap = vi_insertion_keymap; +#endif /* VI_MODE */ +} + +/* **************************************************************** */ +/* */ +/* Key Binding and Function Information */ +/* */ +/* **************************************************************** */ + +/* Each of the following functions produces information about the + state of keybindings and functions known to Readline. The info + is always printed to rl_outstream, and in such a way that it can + be read back in (i.e., passed to rl_parse_and_bind (). */ + +/* Print the names of functions known to Readline. */ +void +rl_list_funmap_names (count, ignore) + int count, ignore; +{ + register int i; + char **funmap_names; + + funmap_names = rl_funmap_names (); + + if (!funmap_names) + return; + + for (i = 0; funmap_names[i]; i++) + fprintf (rl_outstream, "%s\n", funmap_names[i]); + + free (funmap_names); +} + +/* Return a NULL terminated array of strings which represent the key + sequences that are used to invoke FUNCTION in MAP. */ +char ** +rl_invoking_keyseqs_in_map (function, map) + Function *function; + Keymap map; +{ + register int key; + char **result; + int result_index, result_size; + + result = (char **)NULL; + result_index = result_size = 0; + + for (key = 0; key < 128; key++) + { + switch (map[key].type) + { + case ISMACR: + /* Macros match, if, and only if, the pointers are identical. + Thus, they are treated exactly like functions in here. */ + case ISFUNC: + /* If the function in the keymap is the one we are looking for, + then add the current KEY to the list of invoking keys. */ + if (map[key].function == function) + { + char *keyname = (char *)xmalloc (5); + + if (CTRL_CHAR (key)) + sprintf (keyname, "\\C-%c", to_lower (UNCTRL (key))); + else if (key == RUBOUT) + sprintf (keyname, "\\C-?"); + else if (key == '\\' || key == '"') + { + keyname[0] = '\\'; + keyname[1] = (char) key; + keyname[2] = '\0'; + } + else + { + keyname[0] = (char) key; + keyname[1] = '\0'; + } + + if (result_index + 2 > result_size) + result = (char **) xrealloc + (result, (result_size += 10) * sizeof (char *)); + + result[result_index++] = keyname; + result[result_index] = (char *)NULL; + } + break; + + case ISKMAP: + { + char **seqs = (char **)NULL; + + /* Find the list of keyseqs in this map which have FUNCTION as + their target. Add the key sequences found to RESULT. */ + if (map[key].function) + seqs = + rl_invoking_keyseqs_in_map (function, FUNCTION_TO_KEYMAP (map, key)); + + if (seqs) + { + register int i; + + for (i = 0; seqs[i]; i++) + { + char *keyname = (char *)xmalloc (6 + strlen (seqs[i])); + + if (key == ESC) + sprintf (keyname, "\\e"); + else if (CTRL_CHAR (key)) + sprintf (keyname, "\\C-%c", to_lower (UNCTRL (key))); + else if (key == RUBOUT) + sprintf (keyname, "\\C-?"); + else if (key == '\\' || key == '"') + { + keyname[0] = '\\'; + keyname[1] = (char) key; + keyname[2] = '\0'; + } + else + { + keyname[0] = (char) key; + keyname[1] = '\0'; + } + + strcat (keyname, seqs[i]); + free (seqs[i]); + + if (result_index + 2 > result_size) + result = (char **) xrealloc + (result, (result_size += 10) * sizeof (char *)); + + result[result_index++] = keyname; + result[result_index] = (char *)NULL; + } + + free (seqs); + } + } + break; + } + } + return (result); +} + +/* Return a NULL terminated array of strings which represent the key + sequences that can be used to invoke FUNCTION using the current keymap. */ +char ** +rl_invoking_keyseqs (function) + Function *function; +{ + return (rl_invoking_keyseqs_in_map (function, _rl_keymap)); +} + +/* Print all of the current functions and their bindings to + rl_outstream. If an explicit argument is given, then print + the output in such a way that it can be read back in. */ +int +rl_dump_functions (count, key) + int count, key; +{ + rl_function_dumper (rl_explicit_arg); + rl_on_new_line (); + return (0); +} + +/* Print all of the functions and their bindings to rl_outstream. If + PRINT_READABLY is non-zero, then print the output in such a way + that it can be read back in. */ +void +rl_function_dumper (print_readably) + int print_readably; +{ + register int i; + char **names; + char *name; + + names = rl_funmap_names (); + + fprintf (rl_outstream, "\n"); + + for (i = 0; name = names[i]; i++) + { + Function *function; + char **invokers; + + function = rl_named_function (name); + invokers = rl_invoking_keyseqs_in_map (function, _rl_keymap); + + if (print_readably) + { + if (!invokers) + fprintf (rl_outstream, "# %s (not bound)\n", name); + else + { + register int j; + + for (j = 0; invokers[j]; j++) + { + fprintf (rl_outstream, "\"%s\": %s\n", + invokers[j], name); + free (invokers[j]); + } + + free (invokers); + } + } + else + { + if (!invokers) + fprintf (rl_outstream, "%s is not bound to any keys\n", + name); + else + { + register int j; + + fprintf (rl_outstream, "%s can be found on ", name); + + for (j = 0; invokers[j] && j < 5; j++) + { + fprintf (rl_outstream, "\"%s\"%s", invokers[j], + invokers[j + 1] ? ", " : ".\n"); + } + + if (j == 5 && invokers[j]) + fprintf (rl_outstream, "...\n"); + + for (j = 0; invokers[j]; j++) + free (invokers[j]); + + free (invokers); + } + } + } +} + +/* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound. */ +void +_rl_bind_if_unbound (keyseq, default_func) + char *keyseq; + Function *default_func; +{ + Function *func; + + if (keyseq) + { + func = rl_function_of_keyseq (keyseq, _rl_keymap, (int *)NULL); + if (!func || func == rl_do_lowercase_version) + rl_set_key (keyseq, default_func, _rl_keymap); + } +} + +/* **************************************************************** */ +/* */ +/* String Utility Functions */ +/* */ +/* **************************************************************** */ + +static char *strindex (); + +/* Return non-zero if any members of ARRAY are a substring in STRING. */ +static int +substring_member_of_array (string, array) + char *string, **array; +{ + while (*array) + { + if (strindex (string, *array)) + return (1); + array++; + } + return (0); +} + +#if !defined (HAVE_STRCASECMP) +/* Whoops, Unix doesn't have strnicmp. */ + +/* Compare at most COUNT characters from string1 to string2. Case + doesn't matter. */ +static int +strnicmp (string1, string2, count) + char *string1, *string2; + int count; +{ + register char ch1, ch2; + + while (count) + { + ch1 = *string1++; + ch2 = *string2++; + if (to_upper(ch1) == to_upper(ch2)) + count--; + else + break; + } + return (count); +} + +/* strcmp (), but caseless. */ +static int +stricmp (string1, string2) + char *string1, *string2; +{ + register char ch1, ch2; + + while (*string1 && *string2) + { + ch1 = *string1++; + ch2 = *string2++; + if (to_upper(ch1) != to_upper(ch2)) + return (1); + } + return (*string1 - *string2); +} +#endif /* !HAVE_STRCASECMP */ + +/* Determine if s2 occurs in s1. If so, return a pointer to the + match in s1. The compare is case insensitive. */ +static char * +strindex (s1, s2) + register char *s1, *s2; +{ + register int i, l = strlen (s2); + register int len = strlen (s1); + + for (i = 0; (len - i) >= l; i++) + if (strnicmp (s1 + i, s2, l) == 0) + return (s1 + i); + return ((char *)NULL); +} diff --git a/chardefs.h b/chardefs.h new file mode 100644 index 0000000..8c92811 --- /dev/null +++ b/chardefs.h @@ -0,0 +1,122 @@ +/* chardefs.h -- Character definitions for readline. */ + +/* Copyright (C) 1994 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library 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 1, or + (at your option) any later version. + + The GNU Readline Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef _CHARDEFS_H +#define _CHARDEFS_H + +#include + +#if defined (HAVE_STRING_H) +# include +#else +# include +#endif /* HAVE_STRING_H */ + +#ifndef whitespace +#define whitespace(c) (((c) == ' ') || ((c) == '\t')) +#endif + +#ifdef CTRL +#undef CTRL +#endif + +/* Some character stuff. */ +#define control_character_threshold 0x020 /* Smaller than this is control. */ +#define control_character_mask 0x1f /* 0x20 - 1 */ +#define meta_character_threshold 0x07f /* Larger than this is Meta. */ +#define control_character_bit 0x40 /* 0x000000, must be off. */ +#define meta_character_bit 0x080 /* x0000000, must be on. */ +#define largest_char 255 /* Largest character value. */ + +#define CTRL_CHAR(c) ((c) < control_character_threshold) +#define META_CHAR(c) ((c) > meta_character_threshold && (c) <= largest_char) + +#define CTRL(c) ((c) & control_character_mask) +#define META(c) ((c) | meta_character_bit) + +#define UNMETA(c) ((c) & (~meta_character_bit)) +#define UNCTRL(c) to_upper(((c)|control_character_bit)) + +/* Old versions +#define lowercase_p(c) (((c) > ('a' - 1) && (c) < ('z' + 1))) +#define uppercase_p(c) (((c) > ('A' - 1) && (c) < ('Z' + 1))) +#define digit_p(c) ((c) >= '0' && (c) <= '9') +*/ + +#define lowercase_p(c) (islower(c)) +#define uppercase_p(c) (isupper(c)) +#define digit_p(x) (isdigit (x)) + +#define pure_alphabetic(c) (lowercase_p(c) || uppercase_p(c)) + +/* Old versions +# define to_upper(c) (lowercase_p(c) ? ((c) - 32) : (c)) +# define to_lower(c) (uppercase_p(c) ? ((c) + 32) : (c)) +*/ + +#ifndef to_upper +# define to_upper(c) (islower(c) ? toupper(c) : (c)) +# define to_lower(c) (isupper(c) ? tolower(c) : (c)) +#endif + +#ifndef digit_value +#define digit_value(x) ((x) - '0') +#endif + +#ifndef NEWLINE +#define NEWLINE '\n' +#endif + +#ifndef RETURN +#define RETURN CTRL('M') +#endif + +#ifndef RUBOUT +#define RUBOUT 0x7f +#endif + +#ifndef TAB +#define TAB '\t' +#endif + +#ifdef ABORT_CHAR +#undef ABORT_CHAR +#endif +#define ABORT_CHAR CTRL('G') + +#ifdef PAGE +#undef PAGE +#endif +#define PAGE CTRL('L') + +#ifdef SPACE +#undef SPACE +#endif +#define SPACE ' ' /* XXX - was 0x20 */ + +#ifdef ESC +#undef ESC +#endif + +#define ESC CTRL('[') + +#endif /* _CHARDEFS_H */ diff --git a/complete.c b/complete.c new file mode 100644 index 0000000..2180132 --- /dev/null +++ b/complete.c @@ -0,0 +1,1417 @@ +/* complete.c -- filename completion for readline. */ + +/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library 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 1, or + (at your option) any later version. + + The GNU Readline Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define READLINE_LIBRARY + +#include +#include +#include +#if !defined (NO_SYS_FILE) +# include +#endif /* !NO_SYS_FILE */ + +#if defined (HAVE_UNISTD_H) +# include +#endif /* HAVE_UNISTD_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#include +/* Not all systems declare ERRNO in errno.h... and some systems #define it! */ +#if !defined (errno) +extern int errno; +#endif /* !errno */ + +#include +#if defined (USG) && !defined (HAVE_GETPW_DECLS) +extern struct passwd *getpwent (); +#endif /* USG && !HAVE_GETPW_DECLS */ + +/* ISC systems don't define getpwent() if _POSIX_SOURCE is defined. */ +#if defined (isc386) && defined (_POSIX_SOURCE) +# if defined (__STDC__) +extern struct passwd *getpwent (void); +# else +extern struct passwd *getpwent (); +# endif /* !__STDC__ */ +#endif /* isc386 && _POSIX_SOURCE */ + +#include "posixstat.h" + +/* System-specific feature definitions and include files. */ +#include "rldefs.h" + +/* Some standard library routines. */ +#include "readline.h" + +/* Possible values for do_replace in rl_complete_internal. */ +#define NO_MATCH 0 +#define SINGLE_MATCH 1 +#define MULT_MATCH 2 + +#if !defined (strchr) && !defined (__STDC__) +extern char *strchr (), *strrchr (); +#endif /* !strchr && !__STDC__ */ + +extern char *tilde_expand (); +extern char *rl_copy_text (); + +extern Function *rl_last_func; +extern int rl_editing_mode; +extern int screenwidth; + +/* Forward declarations for functions defined and used in this file. */ +char *filename_completion_function (); +char **completion_matches (); + +static int compare_strings (); +static char *rl_strpbrk (); + +#if defined (STATIC_MALLOC) +static char *xmalloc (), *xrealloc (); +#else +extern char *xmalloc (), *xrealloc (); +#endif /* STATIC_MALLOC */ + +/* If non-zero, then this is the address of a function to call when + completing on a directory name. The function is called with + the address of a string (the current directory name) as an arg. */ +Function *rl_directory_completion_hook = (Function *)NULL; + +/* Non-zero means readline completion functions perform tilde expansion. */ +int rl_complete_with_tilde_expansion = 0; + +/* If non-zero, non-unique completions always show the list of matches. */ +int _rl_complete_show_all = 0; + +#if defined (VISIBLE_STATS) +# if !defined (X_OK) +# define X_OK 1 +# endif + +static int stat_char (); + +/* Non-zero means add an additional character to each filename displayed + during listing completion iff rl_filename_completion_desired which helps + to indicate the type of file being listed. */ +int rl_visible_stats = 0; +#endif /* VISIBLE_STATS */ + +/* **************************************************************** */ +/* */ +/* Completion matching, from readline's point of view. */ +/* */ +/* **************************************************************** */ + +/* Pointer to the generator function for completion_matches (). + NULL means to use filename_entry_function (), the default filename + completer. */ +Function *rl_completion_entry_function = (Function *)NULL; + +/* Pointer to alternative function to create matches. + Function is called with TEXT, START, and END. + START and END are indices in RL_LINE_BUFFER saying what the boundaries + of TEXT are. + If this function exists and returns NULL then call the value of + rl_completion_entry_function to try to match, otherwise use the + array of strings returned. */ +CPPFunction *rl_attempted_completion_function = (CPPFunction *)NULL; + +/* Non-zero means to suppress normal filename completion after the + user-specified completion function has been called. */ +int rl_attempted_completion_over = 0; + +/* Local variable states what happened during the last completion attempt. */ +static int completion_changed_buffer = 0; + +/* Complete the word at or before point. You have supplied the function + that does the initial simple matching selection algorithm (see + completion_matches ()). The default is to do filename completion. */ + +rl_complete (ignore, invoking_key) + int ignore, invoking_key; +{ + if (rl_last_func == rl_complete && !completion_changed_buffer) + return (rl_complete_internal ('?')); + else if (_rl_complete_show_all) + return (rl_complete_internal ('!')); + else + return (rl_complete_internal (TAB)); +} + +/* List the possible completions. See description of rl_complete (). */ +rl_possible_completions (ignore, invoking_key) + int ignore, invoking_key; +{ + return (rl_complete_internal ('?')); +} + +rl_insert_completions (ignore, invoking_key) + int ignore, invoking_key; +{ + return (rl_complete_internal ('*')); +} + +/* The user must press "y" or "n". Non-zero return means "y" pressed. */ +get_y_or_n () +{ + int c; + + for (;;) + { + c = rl_read_key (); + if (c == 'y' || c == 'Y' || c == ' ') + return (1); + if (c == 'n' || c == 'N' || c == RUBOUT) + return (0); + if (c == ABORT_CHAR) + rl_abort (); + ding (); + } +} + +/* Up to this many items will be displayed in response to a + possible-completions call. After that, we ask the user if + she is sure she wants to see them all. */ +int rl_completion_query_items = 100; + +/* The basic list of characters that signal a break between words for the + completer routine. The contents of this variable is what breaks words + in the shell, i.e. " \t\n\"\\'`@$><=" */ +char *rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{("; + +/* The list of characters that signal a break between words for + rl_complete_internal. The default list is the contents of + rl_basic_word_break_characters. */ +char *rl_completer_word_break_characters = (char *)NULL; + +/* List of characters which can be used to quote a substring of the line. + Completion occurs on the entire substring, and within the substring + rl_completer_word_break_characters are treated as any other character, + unless they also appear within this list. */ +char *rl_completer_quote_characters = (char *)NULL; + +/* List of characters that are word break characters, but should be left + in TEXT when it is passed to the completion function. The shell uses + this to help determine what kind of completing to do. */ +char *rl_special_prefixes = (char *)NULL; + +/* If non-zero, then disallow duplicates in the matches. */ +int rl_ignore_completion_duplicates = 1; + +/* Non-zero means that the results of the matches are to be treated + as filenames. This is ALWAYS zero on entry, and can only be changed + within a completion entry finder function. */ +int rl_filename_completion_desired = 0; + +/* Non-zero means that the results of the matches are to be quoted using + double quotes (or an application-specific quoting mechanism) if the + filename contains any characters in rl_word_break_chars. This is + ALWAYS non-zero on entry, and can only be changed within a completion + entry finder function. */ +int rl_filename_quoting_desired = 1; + +/* This function, if defined, is called by the completer when real + filename completion is done, after all the matching names have been + generated. It is passed a (char**) known as matches in the code below. + It consists of a NULL-terminated array of pointers to potential + matching strings. The 1st element (matches[0]) is the maximal + substring that is common to all matches. This function can re-arrange + the list of matches as required, but all elements of the array must be + free()'d if they are deleted. The main intent of this function is + to implement FIGNORE a la SunOS csh. */ +Function *rl_ignore_some_completions_function = (Function *)NULL; + +#if defined (SHELL) +/* A function to strip quotes that are not protected by backquotes. It + allows single quotes to appear within double quotes, and vice versa. + It should be smarter. It's fairly shell-specific, hence the SHELL + definition wrapper. */ +static char * +_delete_quotes (text) + char *text; +{ + char *ret, *p, *r; + int l, quoted; + + l = strlen (text); + ret = xmalloc (l + 1); + for (quoted = 0, p = text, r = ret; p && *p; p++) + { + /* Allow backslash-quoted characters to pass through unscathed. */ + if (*p == '\\') + continue; + /* Close quote. */ + if (quoted && *p == quoted) + { + quoted = 0; + continue; + } + /* Open quote. */ + if (quoted == 0 && (*p == '\'' || *p == '"')) + { + quoted = *p; + continue; + } + *r++ = *p; + } + *r = '\0'; + return ret; +} +#endif /* SHELL */ + +/* Return the portion of PATHNAME that should be output when listing + possible completions. If we are hacking filename completion, we + are only interested in the basename, the portion following the + final slash. Otherwise, we return what we were passed. */ +static char * +printable_part (pathname) + char *pathname; +{ + char *temp = (char *)NULL; + + if (rl_filename_completion_desired) + temp = strrchr (pathname, '/'); + + if (!temp) + return (pathname); + else + return (++temp); +} + +/* Output TO_PRINT to rl_outstream. If VISIBLE_STATS is defined and we + are using it, check for and output a single character for `special' + filenames. Return 1 if we printed an extension character, 0 if not. */ +static int +print_filename (to_print, full_pathname) + char *to_print, *full_pathname; +{ +#if !defined (VISIBLE_STATS) + fputs (to_print, rl_outstream); + return 0; +#else + char *s, c, *new_full_pathname; + int extension_char = 0, slen, tlen; + + fputs (to_print, rl_outstream); + if (rl_filename_completion_desired && rl_visible_stats) + { + /* If to_print != full_pathname, to_print is the basename of the + path passed. In this case, we try to expand the directory + name before checking for the stat character. */ + if (to_print != full_pathname) + { + /* Terminate the directory name. */ + c = to_print[-1]; + to_print[-1] = '\0'; + + s = tilde_expand (full_pathname); + if (rl_directory_completion_hook) + (*rl_directory_completion_hook) (&s); + + slen = strlen (s); + tlen = strlen (to_print); + new_full_pathname = xmalloc (slen + tlen + 2); + strcpy (new_full_pathname, s); + new_full_pathname[slen] = '/'; + strcpy (new_full_pathname + slen + 1, to_print); + + extension_char = stat_char (new_full_pathname); + + free (new_full_pathname); + to_print[-1] = c; + } + else + { + s = tilde_expand (full_pathname); + extension_char = stat_char (s); + } + + free (s); + if (extension_char) + putc (extension_char, rl_outstream); + return (extension_char != 0); + } + else + return 0; +#endif /* VISIBLE_STATS */ +} + +/* Complete the word at or before point. + WHAT_TO_DO says what to do with the completion. + `?' means list the possible completions. + TAB means do standard completion. + `*' means insert all of the possible completions. + `!' means to do standard completion, and list all possible completions if + there is more than one. */ +rl_complete_internal (what_to_do) + int what_to_do; +{ + char **matches; + Function *our_func; + int start, scan, end, delimiter = 0, pass_next; + char *text, *saved_line_buffer; + char *replacement; + char quote_char = '\0'; + int found_quote = 0; + + if (rl_line_buffer) + saved_line_buffer = savestring (rl_line_buffer); + else + saved_line_buffer = (char *)NULL; + + if (rl_completion_entry_function) + our_func = rl_completion_entry_function; + else + our_func = (Function *)filename_completion_function; + + /* Only the completion entry function can change these. */ + rl_filename_completion_desired = 0; + rl_filename_quoting_desired = 1; + + /* We now look backwards for the start of a filename/variable word. */ + end = rl_point; + + if (rl_point) + { + if (rl_completer_quote_characters) + { + /* We have a list of characters which can be used in pairs to + quote substrings for the completer. Try to find the start + of an unclosed quoted substring. */ + /* FOUND_QUOTE is set so we know what kind of quotes we found. */ + for (scan = pass_next = 0; scan < end; scan++) + { + if (pass_next) + { + pass_next = 0; + continue; + } + + if (rl_line_buffer[scan] == '\\') + { + pass_next = 1; + found_quote |= 4; + continue; + } + + if (quote_char != '\0') + { + /* Ignore everything until the matching close quote char. */ + if (rl_line_buffer[scan] == quote_char) + { + /* Found matching close. Abandon this substring. */ + quote_char = '\0'; + rl_point = end; + } + } + else if (strchr (rl_completer_quote_characters, rl_line_buffer[scan])) + { + /* Found start of a quoted substring. */ + quote_char = rl_line_buffer[scan]; + rl_point = scan + 1; + /* Shell-like quoting conventions. */ + if (quote_char == '\'') + found_quote |= 1; + else if (quote_char == '"') + found_quote |= 2; + } + } + } + + if (rl_point == end) + { + int quoted = 0; + /* We didn't find an unclosed quoted substring upon which to do + completion, so use the word break characters to find the + substring on which to complete. */ + while (--rl_point) + { + scan = rl_line_buffer[rl_point]; + + if (strchr (rl_completer_word_break_characters, scan) == 0) + continue; + +#if defined (SHELL) + /* Don't let word break characters in quoted substrings break + words for the completer. */ + if (found_quote && char_is_quoted (rl_line_buffer, rl_point)) + continue; +#endif /* SHELL */ + + /* Convoluted code, but it avoids an n^2 algorithm with calls + to char_is_quoted. */ + break; + } + } + + /* If we are at an unquoted word break, then advance past it. */ + scan = rl_line_buffer[rl_point]; +#if defined (SHELL) + if ((found_quote == 0 || char_is_quoted (rl_line_buffer, rl_point) == 0) && + strchr (rl_completer_word_break_characters, scan)) +#else + if (strchr (rl_completer_word_break_characters, scan)) +#endif + { + /* If the character that caused the word break was a quoting + character, then remember it as the delimiter. */ + if (strchr ("\"'", scan) && (end - rl_point) > 1) + delimiter = scan; + + /* If the character isn't needed to determine something special + about what kind of completion to perform, then advance past it. */ + if (!rl_special_prefixes || strchr (rl_special_prefixes, scan) == 0) + rl_point++; + } + } + + /* At this point, we know we have an open quote if quote_char != '\0'. */ + start = rl_point; + rl_point = end; + text = rl_copy_text (start, end); + + /* If the user wants to TRY to complete, but then wants to give + up and use the default completion function, they set the + variable rl_attempted_completion_function. */ + if (rl_attempted_completion_function) + { + matches = (*rl_attempted_completion_function) (text, start, end); + + if (matches || rl_attempted_completion_over) + { + rl_attempted_completion_over = 0; + our_func = (Function *)NULL; + goto after_usual_completion; + } + } + +#if defined (SHELL) + /* Beware -- we're stripping the quotes here. Do this only if we know + we are doing filename completion. */ + if (found_quote && our_func == (Function *)filename_completion_function) + { + /* delete single and double quotes */ + replacement = _delete_quotes (text); + free (text); + text = replacement; + replacement = (char *)0; + } +#endif /* SHELL */ + + matches = completion_matches (text, our_func); + + after_usual_completion: + free (text); + + if (!matches) + ding (); + else + { + register int i; + int should_quote; + + /* It seems to me that in all the cases we handle we would like + to ignore duplicate possiblilities. Scan for the text to + insert being identical to the other completions. */ + if (rl_ignore_completion_duplicates) + { + char *lowest_common; + int j, newlen = 0; + char dead_slot; + char **temp_array; + + /* Sort the items. */ + /* It is safe to sort this array, because the lowest common + denominator found in matches[0] will remain in place. */ + for (i = 0; matches[i]; i++); + qsort (matches, i, sizeof (char *), compare_strings); + + /* Remember the lowest common denominator for it may be unique. */ + lowest_common = savestring (matches[0]); + + for (i = 0; matches[i + 1]; i++) + { + if (strcmp (matches[i], matches[i + 1]) == 0) + { + free (matches[i]); + matches[i] = (char *)&dead_slot; + } + else + newlen++; + } + + /* We have marked all the dead slots with (char *)&dead_slot. + Copy all the non-dead entries into a new array. */ + temp_array = (char **)xmalloc ((3 + newlen) * sizeof (char *)); + for (i = j = 1; matches[i]; i++) + { + if (matches[i] != (char *)&dead_slot) + temp_array[j++] = matches[i]; + } + temp_array[j] = (char *)NULL; + + if (matches[0] != (char *)&dead_slot) + free (matches[0]); + free (matches); + + matches = temp_array; + + /* Place the lowest common denominator back in [0]. */ + matches[0] = lowest_common; + + /* If there is one string left, and it is identical to the + lowest common denominator, then the LCD is the string to + insert. */ + if (j == 2 && strcmp (matches[0], matches[1]) == 0) + { + free (matches[1]); + matches[1] = (char *)NULL; + } + } + + switch (what_to_do) + { + case TAB: + case '!': + /* If we are matching filenames, then here is our chance to + do clever processing by re-examining the list. Call the + ignore function with the array as a parameter. It can + munge the array, deleting matches as it desires. */ + if (rl_ignore_some_completions_function && + our_func == (Function *)filename_completion_function) + (void)(*rl_ignore_some_completions_function)(matches); + + /* If we are doing completion on quoted substrings, and any matches + contain any of the completer_word_break_characters, then auto- + matically prepend the substring with a quote character (just pick + the first one from the list of such) if it does not already begin + with a quote string. FIXME: Need to remove any such automatically + inserted quote character when it no longer is necessary, such as + if we change the string we are completing on and the new set of + matches don't require a quoted substring. */ + replacement = matches[0]; + + should_quote = matches[0] && rl_completer_quote_characters && + rl_filename_completion_desired && + rl_filename_quoting_desired; + + if (should_quote) +#if defined (SHELL) + should_quote = should_quote && (!quote_char || quote_char == '"'); +#else + should_quote = should_quote && !quote_char; +#endif + + if (should_quote) + { + int do_replace; + + do_replace = NO_MATCH; + + /* If there is a single match, see if we need to quote it. + This also checks whether the common prefix of several + matches needs to be quoted. If the common prefix should + not be checked, add !matches[1] to the if clause. */ + should_quote = rl_strpbrk (matches[0], rl_completer_word_break_characters) != 0; +#if defined (SHELL) + should_quote = should_quote || rl_strpbrk (matches[0], "#$`") != 0; +#endif + + if (should_quote) + do_replace = matches[1] ? MULT_MATCH : SINGLE_MATCH; + + if (do_replace != NO_MATCH) + { +#if defined (SHELL) + /* Quote the replacement, since we found an + embedded word break character in a potential + match. */ + char *rtext, *mtext; + int rlen; + extern char *double_quote (); /* in builtins/common.c */ + + /* If DO_REPLACE == MULT_MATCH, it means that there is + more than one match. In this case, we do not add + the closing quote or attempt to perform tilde + expansion. If DO_REPLACE == SINGLE_MATCH, we try + to perform tilde expansion, because double quotes + inhibit tilde expansion by the shell. */ + + mtext = matches[0]; + if (mtext[0] == '~' && do_replace == SINGLE_MATCH) + mtext = tilde_expand (matches[0]); + rtext = double_quote (mtext); + if (mtext != matches[0]) + free (mtext); + + rlen = strlen (rtext); + replacement = xmalloc (rlen + 1); + /* If we're completing on a quoted string where the user + has already supplied the opening quote, we don't want + the quote in the replacement text, and we reset + QUOTE_CHAR to 0 to avoid an extra closing quote. */ + if (quote_char == '"') + { + strcpy (replacement, rtext + 1); + rlen--; + quote_char = 0; + } + else + strcpy (replacement, rtext); + if (do_replace == MULT_MATCH) + replacement[rlen - 1] = '\0'; + free (rtext); +#else /* !SHELL */ + /* Found an embedded word break character in a potential + match, so we need to prepend a quote character if we + are replacing the completion string. */ + replacement = xmalloc (strlen (matches[0]) + 2); + quote_char = *rl_completer_quote_characters; + *replacement = quote_char; + strcpy (replacement + 1, matches[0]); +#endif /* SHELL */ + } + } + + if (replacement) + { + rl_begin_undo_group (); + rl_delete_text (start, rl_point); + rl_point = start; + rl_insert_text (replacement); + rl_end_undo_group (); + if (replacement != matches[0]) + free (replacement); + } + + /* If there are more matches, ring the bell to indicate. + If this was the only match, and we are hacking files, + check the file to see if it was a directory. If so, + add a '/' to the name. If not, and we are at the end + of the line, then add a space. */ + if (matches[1]) + { + if (what_to_do == '!') + goto display_matches; /* XXX */ + else if (rl_editing_mode != vi_mode) + ding (); /* There are other matches remaining. */ + } + else + { + char temp_string[4]; + int temp_string_index = 0; + + if (quote_char) + temp_string[temp_string_index++] = quote_char; + + temp_string[temp_string_index++] = delimiter ? delimiter : ' '; + temp_string[temp_string_index++] = '\0'; + + if (rl_filename_completion_desired) + { + struct stat finfo; + char *filename = tilde_expand (matches[0]); + + if ((stat (filename, &finfo) == 0) && S_ISDIR (finfo.st_mode)) + { + if (rl_line_buffer[rl_point] != '/') + rl_insert_text ("/"); + } + else + { + if (rl_point == rl_end) + rl_insert_text (temp_string); + } + free (filename); + } + else + { + if (rl_point == rl_end) + rl_insert_text (temp_string); + } + } + break; + + case '*': + { + int i = 1; + + rl_begin_undo_group (); + rl_delete_text (start, rl_point); + rl_point = start; + if (matches[1]) + { + while (matches[i]) + { + rl_insert_text (matches[i++]); + rl_insert_text (" "); + } + } + else + { + rl_insert_text (matches[0]); + rl_insert_text (" "); + } + rl_end_undo_group (); + } + break; + + case '?': + { + int len, count, limit, max; + int j, k, l; + + /* Handle simple case first. What if there is only one answer? */ + if (!matches[1]) + { + char *temp; + + temp = printable_part (matches[0]); + crlf (); + print_filename (temp, matches[0]); + crlf (); + goto restart; + } + + /* There is more than one answer. Find out how many there are, + and find out what the maximum printed length of a single entry + is. */ + display_matches: + for (max = 0, i = 1; matches[i]; i++) + { + char *temp; + int name_length; + + temp = printable_part (matches[i]); + name_length = strlen (temp); + + if (name_length > max) + max = name_length; + } + + len = i - 1; + + /* If there are many items, then ask the user if she + really wants to see them all. */ + if (len >= rl_completion_query_items) + { + crlf (); + fprintf (rl_outstream, + "There are %d possibilities. Do you really", len); + crlf (); + fprintf (rl_outstream, "wish to see them all? (y or n)"); + fflush (rl_outstream); + if (!get_y_or_n ()) + { + crlf (); + goto restart; + } + } + + /* How many items of MAX length can we fit in the screen window? */ + max += 2; + limit = screenwidth / max; + if (limit != 1 && (limit * max == screenwidth)) + limit--; + + /* Avoid a possible floating exception. If max > screenwidth, + 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 = (len + (limit - 1)) / limit; + + /* Watch out for special case. If LEN is less than LIMIT, then + just do the inner printing loop. */ + if (len < limit) + count = 1; + + /* Sort the items if they are not already sorted. */ + if (!rl_ignore_completion_duplicates) + qsort (matches, len, sizeof (char *), compare_strings); + + /* Print the sorted items, up-and-down alphabetically, like + ls might. */ + crlf (); + + for (i = 1; i < count + 1; i++) + { + for (j = 0, l = i; j < limit; j++) + { + if (l > len || !matches[l]) + break; + else + { + char *temp; + int printed_length; + + temp = printable_part (matches[l]); + printed_length = strlen (temp); + printed_length += print_filename (temp, matches[l]); + + if (j + 1 < limit) + { + for (k = 0; k < max - printed_length; k++) + putc (' ', rl_outstream); + } + } + l += count; + } + crlf (); + } + restart: + + rl_on_new_line (); + } + break; + + default: + fprintf (stderr, "\r\nreadline: bad value for what_to_do in rl_complete\n"); + abort (); + } + + for (i = 0; matches[i]; i++) + free (matches[i]); + free (matches); + } + + /* Check to see if the line has changed through all of this manipulation. */ + if (saved_line_buffer) + { + if (strcmp (rl_line_buffer, saved_line_buffer) != 0) + completion_changed_buffer = 1; + else + completion_changed_buffer = 0; + + free (saved_line_buffer); + } + return 0; +} + +#if defined (VISIBLE_STATS) +/* Return the character which best describes FILENAME. + `@' for symbolic links + `/' for directories + `*' for executables + `=' for sockets */ +static int +stat_char (filename) + char *filename; +{ + struct stat finfo; + int character, r; + +#if defined (S_ISLNK) + r = lstat (filename, &finfo); +#else + r = stat (filename, &finfo); +#endif + + if (r == -1) + return (0); + + character = 0; + if (S_ISDIR (finfo.st_mode)) + character = '/'; +#if defined (S_ISLNK) + else if (S_ISLNK (finfo.st_mode)) + character = '@'; +#endif /* S_ISLNK */ +#if defined (S_ISSOCK) + else if (S_ISSOCK (finfo.st_mode)) + character = '='; +#endif /* S_ISSOCK */ + else if (S_ISREG (finfo.st_mode)) + { + if (access (filename, X_OK) == 0) + character = '*'; + } + return (character); +} +#endif /* VISIBLE_STATS */ + +/* Stupid comparison routine for qsort () ing strings. */ +static int +compare_strings (s1, s2) + char **s1, **s2; +{ + int result; + + result = **s1 - **s2; + if (result == 0) + result = strcmp (*s1, *s2); + + return result; +} + +/* A completion function for usernames. + TEXT contains a partial username preceded by a random + character (usually `~'). */ +char * +username_completion_function (text, state) + int state; + char *text; +{ +#if defined (__GO32__) + return (char *)NULL; +#else /* !__GO32__ */ + static char *username = (char *)NULL; + static struct passwd *entry; + static int namelen, first_char, first_char_loc; + + if (!state) + { + if (username) + free (username); + + first_char = *text; + + if (first_char == '~') + first_char_loc = 1; + else + first_char_loc = 0; + + username = savestring (&text[first_char_loc]); + namelen = strlen (username); + setpwent (); + } + + while (entry = getpwent ()) + { + if ((username[0] == entry->pw_name[0]) && + (strncmp (username, entry->pw_name, namelen) == 0)) + break; + } + + if (!entry) + { + endpwent (); + return ((char *)NULL); + } + else + { + char *value = xmalloc (2 + strlen (entry->pw_name)); + + *value = *text; + + strcpy (value + first_char_loc, entry->pw_name); + + if (first_char == '~') + rl_filename_completion_desired = 1; + + return (value); + } +#endif /* !__GO32__ */ +} + +/* **************************************************************** */ +/* */ +/* Completion */ +/* */ +/* **************************************************************** */ + +/* Non-zero means that case is not significant in completion. */ +int completion_case_fold = 0; + +/* Return an array of (char *) which is a list of completions for TEXT. + If there are no completions, return a NULL pointer. + The first entry in the returned array is the substitution for TEXT. + The remaining entries are the possible completions. + The array is terminated with a NULL pointer. + + ENTRY_FUNCTION is a function of two args, and returns a (char *). + The first argument is TEXT. + The second is a state argument; it should be zero on the first call, and + non-zero on subsequent calls. It returns a NULL pointer to the caller + when there are no more matches. + */ +char ** +completion_matches (text, entry_function) + char *text; + CPFunction *entry_function; +{ + /* Number of slots in match_list. */ + int match_list_size; + + /* The list of matches. */ + char **match_list = + (char **)xmalloc (((match_list_size = 10) + 1) * sizeof (char *)); + + /* Number of matches actually found. */ + int matches = 0; + + /* Temporary string binder. */ + char *string; + + match_list[1] = (char *)NULL; + + while (string = (*entry_function) (text, matches)) + { + if (matches + 1 == match_list_size) + match_list = (char **)xrealloc + (match_list, ((match_list_size += 10) + 1) * sizeof (char *)); + + match_list[++matches] = string; + match_list[matches + 1] = (char *)NULL; + } + + /* If there were any matches, then look through them finding out the + lowest common denominator. That then becomes match_list[0]. */ + if (matches) + { + register int i = 1; + int low = 100000; /* Count of max-matched characters. */ + + /* If only one match, just use that. */ + if (matches == 1) + { + match_list[0] = match_list[1]; + match_list[1] = (char *)NULL; + } + else + { + /* Otherwise, compare each member of the list with + the next, finding out where they stop matching. */ + + while (i < matches) + { + register int c1, c2, si; + + if (completion_case_fold) + { + for (si = 0; + (c1 = to_lower(match_list[i][si])) && + (c2 = to_lower(match_list[i + 1][si])); + si++) + if (c1 != c2) break; + } + else + { + for (si = 0; + (c1 = match_list[i][si]) && + (c2 = match_list[i + 1][si]); + si++) + if (c1 != c2) break; + } + + if (low > si) low = si; + i++; + } + match_list[0] = xmalloc (low + 1); + strncpy (match_list[0], match_list[1], low); + match_list[0][low] = '\0'; + } + } + else /* There were no matches. */ + { + free (match_list); + match_list = (char **)NULL; + } + return (match_list); +} + +/* Okay, now we write the entry_function for filename completion. In the + general case. Note that completion in the shell is a little different + because of all the pathnames that must be followed when looking up the + completion for a command. */ +char * +filename_completion_function (text, state) + int state; + char *text; +{ + static DIR *directory; + static char *filename = (char *)NULL; + static char *dirname = (char *)NULL; + static char *users_dirname = (char *)NULL; + static int filename_len; + + struct dirent *entry = (struct dirent *)NULL; + + /* If we don't have any state, then do some initialization. */ + if (!state) + { + char *temp; + + if (dirname) free (dirname); + if (filename) free (filename); + if (users_dirname) free (users_dirname); + + filename = savestring (text); + if (!*text) text = "."; + dirname = savestring (text); + + temp = strrchr (dirname, '/'); + + if (temp) + { + strcpy (filename, ++temp); + *temp = '\0'; + } + else + strcpy (dirname, "."); + + /* We aren't done yet. We also support the "~user" syntax. */ + + /* Save the version of the directory that the user typed. */ + users_dirname = savestring (dirname); + { + char *temp_dirname; + int replace_dirname; + + temp_dirname = tilde_expand (dirname); + free (dirname); + dirname = temp_dirname; + + replace_dirname = 0; + if (rl_directory_completion_hook) + replace_dirname = (*rl_directory_completion_hook) (&dirname); + if (replace_dirname) + { + free (users_dirname); + users_dirname = savestring (dirname); + } + } + directory = opendir (dirname); + filename_len = strlen (filename); + + rl_filename_completion_desired = 1; + } + + /* At this point we should entertain the possibility of hacking wildcarded + filenames, like /usr/man/man/te. If the directory name + contains globbing characters, then build an array of directories, and + then map over that list while completing. */ + /* *** UNIMPLEMENTED *** */ + + /* Now that we have some state, we can read the directory. */ + + while (directory && (entry = readdir (directory))) + { + /* Special case for no filename. + All entries except "." and ".." match. */ + if (!filename_len) + { + if ((strcmp (entry->d_name, ".") != 0) && + (strcmp (entry->d_name, "..") != 0)) + break; + } + else + { + /* Otherwise, if these match up to the length of filename, then + it is a match. */ + if ((entry->d_name[0] == filename[0]) && + (((int)D_NAMLEN (entry)) >= filename_len) && + (strncmp (filename, entry->d_name, filename_len) == 0)) + break; + } + } + + if (!entry) + { + if (directory) + { + closedir (directory); + directory = (DIR *)NULL; + } + if (dirname) + { + free (dirname); + dirname = (char *)NULL; + } + if (filename) + { + free (filename); + filename = (char *)NULL; + } + if (users_dirname) + { + free (users_dirname); + users_dirname = (char *)NULL; + } + + return (char *)NULL; + } + else + { + char *temp; + + /* dirname && (strcmp (dirname, ".") != 0) */ + if (dirname && (dirname[0] != '.' || dirname[1])) + { + if (rl_complete_with_tilde_expansion && *users_dirname == '~') + { + int dirlen = strlen (dirname); + temp = xmalloc (2 + dirlen + D_NAMLEN (entry)); + strcpy (temp, dirname); + /* Canonicalization cuts off any final slash present. We need + to add it back. */ + if (dirname[dirlen - 1] != '/') + { + temp[dirlen] = '/'; + temp[dirlen + 1] = '\0'; + } + } + else + { + temp = xmalloc (1 + strlen (users_dirname) + D_NAMLEN (entry)); + strcpy (temp, users_dirname); + } + + strcat (temp, entry->d_name); + } + else + temp = (savestring (entry->d_name)); + + return (temp); + } +} + +/* A function for simple tilde expansion. */ +int +rl_tilde_expand (ignore, key) + int ignore, key; +{ + register int start, end; + char *homedir; + + end = rl_point; + start = end - 1; + + if (rl_point == rl_end && rl_line_buffer[rl_point] == '~') + { + homedir = tilde_expand ("~"); + goto insert; + } + else if (rl_line_buffer[start] != '~') + { + for (; !whitespace (rl_line_buffer[start]) && start >= 0; start--); + start++; + } + + end = start; + do + { + end++; + } + while (!whitespace (rl_line_buffer[end]) && end < rl_end); + + if (whitespace (rl_line_buffer[end]) || end >= rl_end) + end--; + + /* If the first character of the current word is a tilde, perform + tilde expansion and insert the result. If not a tilde, do + nothing. */ + if (rl_line_buffer[start] == '~') + { + char *temp; + int len; + + len = end - start + 1; + temp = xmalloc (len + 1); + strncpy (temp, rl_line_buffer + start, len); + temp[len] = '\0'; + homedir = tilde_expand (temp); + free (temp); + + insert: + rl_begin_undo_group (); + rl_delete_text (start, end + 1); + rl_point = start; + rl_insert_text (homedir); + rl_end_undo_group (); + } + + return (0); +} + +/* Find the first occurrence in STRING1 of any character from STRING2. + Return a pointer to the character in STRING1. */ +static char * +rl_strpbrk (string1, string2) + char *string1, *string2; +{ + register char *scan; + + for (; *string1; string1++) + { + for (scan = string2; *scan; scan++) + { + if (*string1 == *scan) + { + return (string1); + } + } + } + return ((char *)NULL); +} + +#if defined (STATIC_MALLOC) + +/* **************************************************************** */ +/* */ +/* xmalloc and xrealloc () */ +/* */ +/* **************************************************************** */ + +static void memory_error_and_abort (); + +static char * +xmalloc (bytes) + int bytes; +{ + char *temp = (char *)malloc (bytes); + + if (!temp) + memory_error_and_abort (); + return (temp); +} + +static char * +xrealloc (pointer, bytes) + char *pointer; + int bytes; +{ + char *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 /* STATIC_MALLOC */ diff --git a/config.h b/config.h new file mode 100644 index 0000000..045ea22 --- /dev/null +++ b/config.h @@ -0,0 +1,71 @@ +/* config.h. Generated automatically by configure. */ +/* config.h.in. Generated automatically from configure.in by autoheader. */ + +#ifndef _RL_CONFIG_H +#define _RL_CONFIG_H + +/* Define if using alloca.c. */ +/* #undef C_ALLOCA */ + +/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. + This function is required for alloca.c support on those systems. */ +/* #undef CRAY_STACKSEG_END */ + +/* Define if you have alloca.h and it should be used (not Ultrix). */ +#define HAVE_ALLOCA_H 1 + +/* If using the C implementation of alloca, define 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 + */ +/* #undef STACK_DIRECTION */ + +/* Define if you do not have strings.h, index, bzero, etc.. */ +/* #undef USG */ + +/* Define if your system defines TIOCGWINSZ in sys/ioctl.h. */ +#define GWINSZ_IN_SYS_IOCTL 1 + +/* #undef HAVE_GETPW_DECLS */ +#define NO_SYS_FILE 1 + +/* Define if you have strcasecmp. */ +#define HAVE_STRCASECMP 1 + +/* Define if you have the header file. */ +#define HAVE_ALLOCA_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_DIRENT_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_STDLIB_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_STRING_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_PTE_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_PTEM_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_STREAM_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_TERMCAP_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_TERMIO_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_UNISTD_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_VARARGS_H */ + +#endif diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..7d7525d --- /dev/null +++ b/config.h.in @@ -0,0 +1,70 @@ +/* config.h.in. Generated automatically from configure.in by autoheader. */ + +#ifndef _RL_CONFIG_H +#define _RL_CONFIG_H + +/* Define if using alloca.c. */ +#undef C_ALLOCA + +/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. + This function is required for alloca.c support on those systems. */ +#undef CRAY_STACKSEG_END + +/* Define if you have alloca.h and it should be used (not Ultrix). */ +#undef HAVE_ALLOCA_H + +/* If using the C implementation of alloca, define 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 + */ +#undef STACK_DIRECTION + +/* Define if you do not have strings.h, index, bzero, etc.. */ +#undef USG + +/* Define if your system defines TIOCGWINSZ in sys/ioctl.h. */ +#undef GWINSZ_IN_SYS_IOCTL + +#undef HAVE_GETPW_DECLS +#undef NO_SYS_FILE + +/* Define if you have strcasecmp. */ +#undef HAVE_STRCASECMP + +/* Define if you have the header file. */ +#undef HAVE_ALLOCA_H + +/* Define if you have the header file. */ +#undef HAVE_DIRENT_H + +/* Define if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define if you have the header file. */ +#undef HAVE_STRING_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_PTE_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_PTEM_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_STREAM_H + +/* Define if you have the header file. */ +#undef HAVE_TERMCAP_H + +/* Define if you have the header file. */ +#undef HAVE_TERMIO_H + +/* Define if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define if you have the header file. */ +#undef HAVE_VARARGS_H + +#endif diff --git a/config.status b/config.status new file mode 100755 index 0000000..b6bc9ee --- /dev/null +++ b/config.status @@ -0,0 +1,190 @@ +#!/bin/sh +# Generated automatically by configure. +# Run this file to recreate the current configuration. +# This directory was configured as follows, +# on host odin: +# +# ./configure --with-gcc + +ac_cs_usage="Usage: config.status [--recheck] [--version] [--help]" +for ac_option +do + case "$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo running ${CONFIG_SHELL-/bin/sh} ./configure --with-gcc --no-create + exec ${CONFIG_SHELL-/bin/sh} ./configure --with-gcc --no-create ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "config.status generated by autoconf version 1.11" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "$ac_cs_usage"; exit 0 ;; + *) echo "$ac_cs_usage"; exit 1 ;; + esac +done + +trap 'rm -fr Makefile config.h conftest*; exit 1' 1 2 15 +CC='gcc' +CFLAGS='-g -O' +LDFLAGS='' +CPP='/lib/cpp' +INSTALL='/bin/install -c' +INSTALL_PROGRAM='${INSTALL}' +INSTALL_DATA='${INSTALL} -m 644' +RANLIB='ranlib' +ALLOCA='' +LIBS='' +srcdir='.' +top_srcdir='' +prefix='/usr/local' +exec_prefix='${prefix}' +ac_prsub='' +ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +extrasub='' + +ac_given_srcdir=$srcdir + +CONFIG_FILES=${CONFIG_FILES-"Makefile"} +for ac_file in .. ${CONFIG_FILES}; do if test "x$ac_file" != x..; then + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/$ac_dir" + else + ac_dir_suffix= + fi + + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dir_suffix"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + comment_str="Generated automatically from `echo $ac_file|sed 's|.*/||'`.in by configure." + case "$ac_file" in + *.c | *.h | *.C | *.cc | *.m ) echo "/* $comment_str */" > "$ac_file" ;; + * ) echo "# $comment_str" > "$ac_file" ;; + esac + sed -e " +$ac_prsub +$ac_vpsub +$extrasub +s%@CC@%$CC%g +s%@CFLAGS@%$CFLAGS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@CPP@%$CPP%g +s%@INSTALL@%$INSTALL%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@RANLIB@%$RANLIB%g +s%@ALLOCA@%$ALLOCA%g +s%@LIBS@%$LIBS%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@prefix@%$prefix%g +s%@exec_prefix@%$exec_prefix%g +s%@DEFS@%-DHAVE_CONFIG_H%" $ac_given_srcdir/${ac_file}.in >> $ac_file +fi; done + +# These sed commands are put into ac_sed_defs when defining a macro. +# They are broken into pieces to make the sed script easier to manage. +# They are passed to sed as "A NAME B NAME C VALUE D", where NAME +# is the cpp macro being defined and VALUE is the value it is being given. +# Each defining turns into a single global substitution command. +# Hopefully no one uses "!" as a variable value. +# Other candidates for the sed separators, like , and @, do get used. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s!^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*!\1#\2' +ac_dC='\3' +ac_dD='!g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s!^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)!\1#\2define\3' +ac_uC=' ' +ac_uD='\4!g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s!^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$!\1#\2define\3' +ac_eC=' ' +ac_eD='!g' +rm -f conftest.sed +cat >> conftest.sed <> conftest.sed <> conftest.sed <<\CONFEOF +s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, +CONFEOF +rm -f conftest.h +# Break up the sed commands because old seds have small limits. +ac_max_sed_lines=20 + +CONFIG_HEADERS=${CONFIG_HEADERS-"config.h"} +for ac_file in .. ${CONFIG_HEADERS}; do if test "x$ac_file" != x..; then + echo creating $ac_file + + cp $ac_given_srcdir/$ac_file.in conftest.h1 + cp conftest.sed conftest.stm + while : + do + ac_lines=`grep -c . conftest.stm` + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + rm -f conftest.s1 conftest.s2 conftest.h2 + sed ${ac_max_sed_lines}q conftest.stm > conftest.s1 # Like head -20. + sed 1,${ac_max_sed_lines}d conftest.stm > conftest.s2 # Like tail +21. + sed -f conftest.s1 < conftest.h1 > conftest.h2 + rm -f conftest.s1 conftest.h1 conftest.stm + mv conftest.h2 conftest.h1 + mv conftest.s2 conftest.stm + done + rm -f conftest.stm conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.h1 >> conftest.h + rm -f conftest.h1 + if cmp -s $ac_file conftest.h 2>/dev/null; then + # The file exists and we would not be changing it. + echo "$ac_file is unchanged" + rm -f conftest.h + else + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done +rm -f conftest.sed + + + +# Makefile uses this timestamp file to record whether config.h is up to date. +touch stamp-config +exit 0 diff --git a/configure b/configure new file mode 100755 index 0000000..c1b0a63 --- /dev/null +++ b/configure @@ -0,0 +1,1240 @@ +#!/bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 1.11 +# Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc. + +# This configure script 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 script 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. + +# Save the original args to write them into config.status later. +configure_args="$*" + +# Only options that might do something get documented. +ac_usage="Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +--build=BUILD configure for building on BUILD [BUILD=HOST] +--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) +--enable-FEATURE[=ARG] include FEATURE [ARG=yes] +--exec-prefix=PREFIX install host dependent files in PREFIX [/usr/local] +--help print this message +--host=HOST configure for HOST [guessed] +--prefix=PREFIX install host independent files in PREFIX [/usr/local] +--quiet, --silent do not print \`checking for...' messages +--srcdir=DIR find the sources in DIR [configure dir or ..] +--target=TARGET configure for TARGET [TARGET=HOST] +--verbose print results of checks +--version print the version of autoconf that created configure +--with-PACKAGE[=ARG] use PACKAGE [ARG=yes] +--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) +--x-includes=DIR X include files are in DIR +--x-libraries=DIR X library files are in DIR" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +exec_prefix= +host=NONE +no_create= +nonopt=NONE +norecursion= +prefix= +program_prefix= +program_suffix= +program_transform_name= +silent= +srcdir= +target=NONE +verbose= +x_includes= +x_libraries= + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + # Accept (but ignore some of) the important Cygnus configure + # options, so we can diagnose typos. + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + case "$ac_option" in + + -build | --build | --buil | --bui | --bu | --b) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=* | --b=*) + build="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that aren't valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + echo "configure: $ac_feature: invalid feature name" >&2; exit 1 + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that aren't valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + echo "configure: $ac_feature: invalid feature name" >&2; exit 1 + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + # For backward compatibility, recognize -exec-prefix and --exec_prefix. + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + with_gas=yes ;; # Obsolete; use --with-gas. + + -help | --help | --hel | --he) + cat << EOF +$ac_usage +EOF + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -nfp | --nfp | --nf) + with_fp=no ;; # Obsolete; use --without-fp. + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -norecursion | --norecursion | --norecursio | --norecursi \ + | --norecurs | --norecur | --norecu | --norec | --nore | --nor) + norecursion=yes ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 1.11" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that aren't valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + echo "configure: $ac_package: invalid package name" >&2; exit 1 + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that aren't valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + echo "configure: $ac_package: invalid package name" >&2; exit 1 + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) with_x=yes ;; # Obsolete; use --with-x. + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) echo "configure: $ac_option: invalid option; use --help to show usage" >&2; exit 1 + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" >&2 + fi + if test "x$nonopt" != xNONE; then + echo "configure: can only configure for one host and one target at a time" >&2; exit 1 + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + echo "configure: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" >&2; exit 1 +fi + +trap 'rm -fr conftest* confdefs* core $ac_clean_files; exit 1' 1 2 15 +trap 'rm -fr confdefs* $ac_clean_files' 0 + +# Save the original args if we used an alternate arg parser. +ac_configure_temp="${configure_args-$*}" +# Strip out --no-create and --norecursion so they don't pile up. +configure_args= +for ac_arg in $ac_configure_temp; do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -norecursion | --norecursion | --norecursio | --norecursi \ + | --norecurs | --norecur | --norecu | --norec | --nore | --nor) ;; + *) configure_args="$configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# These must not be set unconditionally because not all systems understand +# e.g. LANG=C (notably SCO). +if test "${LC_ALL+set}" = 'set'; then LC_ALL=C; export LC_ALL; fi +if test "${LANG+set}" = 'set'; then LANG=C; export LANG; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=readline.h + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then `..'. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +fi +if test ! -r $srcdir/$ac_unique_file; then + if test x$ac_srcdir_defaulted = xyes; then + echo "configure: can not find sources in ${ac_confdir} or .." >&2; exit 1 + else + echo "configure: can not find sources in ${srcdir}" >&2; exit 1 + fi +fi +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='${CPP}' +ac_compile='${CC-cc} $CFLAGS $LDFLAGS conftest.${ac_ext} -o conftest $LIBS >/dev/null 2>&1' + + + +#!/bin/sh +# From configure.in Configure for Readline 2.0 + + +# We want these before the checks, so the checks can modify their values. +test -z "$CFLAGS" && CFLAGS=-g auto_cflags=1 + +if test -z "$CC"; then + # Extract the first word of `gcc', so it can be a program name with args. + set ac_dummy gcc; ac_word=$2 + test -n "$silent" || echo "checking for $ac_word" + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +test -z "$CC" && CC="cc" +test -n "$CC" && test -n "$verbose" && echo " setting CC to $CC" + +# Find out if we are using GNU C, under whatever name. +cat > conftest.c < conftest.out 2>&1 +if egrep yes conftest.out >/dev/null 2>&1; then + GCC=1 # For later tests. +fi +rm -f conftest* + + +# If we're using gcc and the user hasn't specified CFLAGS, add -O to CFLAGS. +test -n "$GCC" && test -n "$auto_cflags" && CFLAGS="$CFLAGS -O" + + +test -n "$silent" || echo "checking how to run the C preprocessor" +if test -z "$CPP"; then + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and ``${CC-cc}'' will simply confuse + # make. It must be expanded now. + CPP="${CC-cc} -E" + cat > conftest.${ac_ext} < +Syntax Error +EOF +# Some shells (Coherent) do redirections in the wrong order, so need +# the parens. +ac_err=`eval "($ac_cpp conftest.${ac_ext} >/dev/null) 2>&1"` +if test -z "$ac_err"; then + : +else + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.${ac_ext} < +Syntax Error +EOF +# Some shells (Coherent) do redirections in the wrong order, so need +# the parens. +ac_err=`eval "($ac_cpp conftest.${ac_ext} >/dev/null) 2>&1"` +if test -z "$ac_err"; then + : +else + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* +fi +test -n "$verbose" && echo " setting CPP to $CPP" + +if test -n "$GCC"; then + test -n "$silent" || echo "checking whether -traditional is needed" + ac_pattern="Autoconf.*'x'" + ac_prog='#include +Autoconf TIOCGETP' + cat > conftest.${ac_ext} < conftest.out 2>&1" +if egrep "$ac_pattern" conftest.out >/dev/null 2>&1; then + rm -rf conftest* + ac_need_trad=1 + +fi +rm -f conftest* + + + if test -z "$ac_need_trad"; then + ac_prog='#include +Autoconf TCGETA' + cat > conftest.${ac_ext} < conftest.out 2>&1" +if egrep "$ac_pattern" conftest.out >/dev/null 2>&1; then + rm -rf conftest* + ac_need_trad=1 + +fi +rm -f conftest* + + fi + test -n "$ac_need_trad" && CC="$CC -traditional" +fi + +# Make sure to not get the incompatible SysV /etc/install and +# /usr/sbin/install, which might be in PATH before a BSD-like install, +# or the SunOS /usr/etc/install directory, or the AIX /bin/install, +# or the AFS install, which mishandles nonexistent args, or +# /usr/ucb/install on SVR4, which tries to use the nonexistent group +# `staff', or /sbin/install on IRIX which has incompatible command-line +# syntax. Sigh. +# +# On most BSDish systems install is in /usr/bin, not /usr/ucb +# anyway. +# This turns out not to be true, so the mere pathname isn't an indication +# of whether the program works. What we really need is a set of tests for +# the install program to see if it actually works in all the required ways. +# +# Avoid using ./install, which might have been erroneously created +# by make from ./install.sh. +if test -z "${INSTALL}"; then + test -n "$silent" || echo "checking for a BSD compatible install" + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + case "$ac_dir" in + ''|.|/etc|/sbin|/usr/sbin|/usr/etc|/usr/afsws/bin|/usr/ucb) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + for ac_prog in installbsd scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + # OSF/1 installbsd also uses dspmsg, but is usable. + : + else + INSTALL="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_ifs" +fi + +if test -z "$INSTALL"; then + # As a last resort, use the slow shell script. + for ac_dir in ${srcdir} ${srcdir}/.. ${srcdir}/../..; do + if test -f $ac_dir/install.sh; then + INSTALL="$ac_dir/install.sh -c"; break + fi + done +fi +if test -z "$INSTALL"; then + echo "configure: can not find install.sh in ${srcdir} or ${srcdir}/.. or ${srcdir}/../.." >&2; exit 1 +fi +test -n "$verbose" && echo " setting INSTALL to $INSTALL" + +# Use test -z because SunOS4 sh mishandles ${INSTALL_PROGRAM-'${INSTALL}'}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' +test -n "$verbose" && echo " setting INSTALL_PROGRAM to $INSTALL_PROGRAM" + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' +test -n "$verbose" && echo " setting INSTALL_DATA to $INSTALL_DATA" + +if test -z "$RANLIB"; then + # Extract the first word of `ranlib', so it can be a program name with args. + set ac_dummy ranlib; ac_word=$2 + test -n "$silent" || echo "checking for $ac_word" + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" +fi +test -z "$RANLIB" && RANLIB=":" +test -n "$RANLIB" && test -n "$verbose" && echo " setting RANLIB to $RANLIB" + + +test -n "$silent" || echo "checking for BSD string and memory functions" +cat > conftest.${ac_ext} < +int main() { return 0; } +int t() { rindex(0, 0); bzero(0, 0);; return 0; } +EOF +if eval $ac_compile; then + : +else + rm -rf conftest* + +{ +test -n "$verbose" && \ +echo " defining USG" +echo "#define" USG "1" >> confdefs.h +DEFS="$DEFS -DUSG=1" +ac_sed_defs="${ac_sed_defs}\${ac_dA}USG\${ac_dB}USG\${ac_dC}1\${ac_dD} +\${ac_uA}USG\${ac_uB}USG\${ac_uC}1\${ac_uD} +\${ac_eA}USG\${ac_eB}USG\${ac_eC}1\${ac_eD} +" +} + +fi +rm -f conftest* + + +for ac_func in strcasecmp sighold +do +ac_tr_func=HAVE_`echo $ac_func | tr '[a-z]' '[A-Z]'` +test -n "$silent" || echo "checking for ${ac_func}" +cat > conftest.${ac_ext} < +int main() { return 0; } +int t() { +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_${ac_func}) || defined (__stub___${ac_func}) +choke me +#else +/* Override any gcc2 internal prototype to avoid an error. */ +extern char ${ac_func}(); ${ac_func}(); +#endif +; return 0; } +EOF +if eval $ac_compile; then + rm -rf conftest* + { +test -n "$verbose" && \ +echo " defining ${ac_tr_func}" +echo "#define" ${ac_tr_func} "1" >> confdefs.h +DEFS="$DEFS -D${ac_tr_func}=1" +ac_sed_defs="${ac_sed_defs}\${ac_dA}${ac_tr_func}\${ac_dB}${ac_tr_func}\${ac_dC}1\${ac_dD} +\${ac_uA}${ac_tr_func}\${ac_uB}${ac_tr_func}\${ac_uC}1\${ac_uD} +\${ac_eA}${ac_tr_func}\${ac_eB}${ac_tr_func}\${ac_eC}1\${ac_eD} +" +} + + +fi +rm -f conftest* +done + + +for ac_hdr in unistd.h stdlib.h varargs.h string.h alloca.h \ + dirent.h sys/ptem.h sys/pte.h sys/stream.h termcap.h \ + termio.h +do +ac_tr_hdr=HAVE_`echo $ac_hdr | tr '[a-z]./' '[A-Z]__'` +test -n "$silent" || echo "checking for ${ac_hdr}" +cat > conftest.${ac_ext} < +EOF +# Some shells (Coherent) do redirections in the wrong order, so need +# the parens. +ac_err=`eval "($ac_cpp conftest.${ac_ext} >/dev/null) 2>&1"` +if test -z "$ac_err"; then + rm -rf conftest* + +{ +test -n "$verbose" && \ +echo " defining ${ac_tr_hdr}" +echo "#define" ${ac_tr_hdr} "1" >> confdefs.h +DEFS="$DEFS -D${ac_tr_hdr}=1" +ac_sed_defs="${ac_sed_defs}\${ac_dA}${ac_tr_hdr}\${ac_dB}${ac_tr_hdr}\${ac_dC}1\${ac_dD} +\${ac_uA}${ac_tr_hdr}\${ac_uB}${ac_tr_hdr}\${ac_uC}1\${ac_uD} +\${ac_eA}${ac_tr_hdr}\${ac_eB}${ac_tr_hdr}\${ac_eC}1\${ac_eD} +" +} + + +fi +rm -f conftest* +done + + +test -n "$silent" || echo "checking for sys/file.h" +cat > conftest.${ac_ext} < +EOF +# Some shells (Coherent) do redirections in the wrong order, so need +# the parens. +ac_err=`eval "($ac_cpp conftest.${ac_ext} >/dev/null) 2>&1"` +if test -z "$ac_err"; then + : +else + rm -rf conftest* + +{ +test -n "$verbose" && \ +echo " defining NO_SYS_FILE" +echo "#define" NO_SYS_FILE "1" >> confdefs.h +DEFS="$DEFS -DNO_SYS_FILE=1" +ac_sed_defs="${ac_sed_defs}\${ac_dA}NO_SYS_FILE\${ac_dB}NO_SYS_FILE\${ac_dC}1\${ac_dD} +\${ac_uA}NO_SYS_FILE\${ac_uB}NO_SYS_FILE\${ac_uC}1\${ac_uD} +\${ac_eA}NO_SYS_FILE\${ac_eB}NO_SYS_FILE\${ac_eC}1\${ac_eD} +" +} + +fi +rm -f conftest* + + +if test -z "$have_tiocgwinsz"; then +test -n "$silent" || echo "checking for TIOCGWINSZ in sys/ioctl.h" +cat > conftest.${ac_ext} < +#include +int main() { return 0; } +int t() { int x = TIOCGWINSZ;; return 0; } +EOF +if eval $ac_compile; then + rm -rf conftest* + +{ +test -n "$verbose" && \ +echo " defining GWINSZ_IN_SYS_IOCTL" +echo "#define" GWINSZ_IN_SYS_IOCTL "1" >> confdefs.h +DEFS="$DEFS -DGWINSZ_IN_SYS_IOCTL=1" +ac_sed_defs="${ac_sed_defs}\${ac_dA}GWINSZ_IN_SYS_IOCTL\${ac_dB}GWINSZ_IN_SYS_IOCTL\${ac_dC}1\${ac_dD} +\${ac_uA}GWINSZ_IN_SYS_IOCTL\${ac_uB}GWINSZ_IN_SYS_IOCTL\${ac_uC}1\${ac_uD} +\${ac_eA}GWINSZ_IN_SYS_IOCTL\${ac_eB}GWINSZ_IN_SYS_IOCTL\${ac_eC}1\${ac_eD} +" +} + + +fi +rm -f conftest* + +fi + +test -n "$silent" || echo "checking for programs able to redeclare getpw functions" +cat > conftest.${ac_ext} < +#include +extern struct passwd *getpwuid(); +int main() { return 0; } +int t() { struct passwd *z; z = getpwuid(0);; return 0; } +EOF +if eval $ac_compile; then + : +else + rm -rf conftest* + +{ +test -n "$verbose" && \ +echo " defining HAVE_GETPW_DECLS" +echo "#define" HAVE_GETPW_DECLS "1" >> confdefs.h +DEFS="$DEFS -DHAVE_GETPW_DECLS=1" +ac_sed_defs="${ac_sed_defs}\${ac_dA}HAVE_GETPW_DECLS\${ac_dB}HAVE_GETPW_DECLS\${ac_dC}1\${ac_dD} +\${ac_uA}HAVE_GETPW_DECLS\${ac_uB}HAVE_GETPW_DECLS\${ac_uC}1\${ac_uD} +\${ac_eA}HAVE_GETPW_DECLS\${ac_eB}HAVE_GETPW_DECLS\${ac_eC}1\${ac_eD} +" +} + +fi +rm -f conftest* + + +# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +test -n "$silent" || echo "checking for working alloca.h" +cat > conftest.${ac_ext} < +int main() { return 0; } +int t() { char *p = alloca(2 * sizeof(int));; return 0; } +EOF +if eval $ac_compile; then + rm -rf conftest* + +{ +test -n "$verbose" && \ +echo " defining HAVE_ALLOCA_H" +echo "#define" HAVE_ALLOCA_H "1" >> confdefs.h +DEFS="$DEFS -DHAVE_ALLOCA_H=1" +ac_sed_defs="${ac_sed_defs}\${ac_dA}HAVE_ALLOCA_H\${ac_dB}HAVE_ALLOCA_H\${ac_dC}1\${ac_dD} +\${ac_uA}HAVE_ALLOCA_H\${ac_uB}HAVE_ALLOCA_H\${ac_uC}1\${ac_uD} +\${ac_eA}HAVE_ALLOCA_H\${ac_eB}HAVE_ALLOCA_H\${ac_eC}1\${ac_eD} +" +} + + +fi +rm -f conftest* + +ac_decl="#ifdef __GNUC__ +#define alloca __builtin_alloca +#else +#if HAVE_ALLOCA_H +#include +#else +#ifdef _AIX + #pragma alloca +#else +char *alloca (); +#endif +#endif +#endif +" +test -n "$silent" || echo "checking for alloca" +cat > conftest.${ac_ext} <> confdefs.h +DEFS="$DEFS -DHAVE_ALLOCA=1" +ac_sed_defs="${ac_sed_defs}\${ac_dA}HAVE_ALLOCA\${ac_dB}HAVE_ALLOCA\${ac_dC}1\${ac_dD} +\${ac_uA}HAVE_ALLOCA\${ac_uB}HAVE_ALLOCA\${ac_uC}1\${ac_uD} +\${ac_eA}HAVE_ALLOCA\${ac_eB}HAVE_ALLOCA\${ac_eC}1\${ac_eD} +" +} + + +else + rm -rf conftest* + ac_alloca_missing=1 +cat > conftest.${ac_ext} < conftest.out 2>&1" +if egrep "winnitude" conftest.out >/dev/null 2>&1; then + rm -rf conftest* + test -n "$silent" || echo "checking for _getb67" +cat > conftest.${ac_ext} < +int main() { return 0; } +int t() { +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub__getb67) || defined (__stub____getb67) +choke me +#else +/* Override any gcc2 internal prototype to avoid an error. */ +extern char _getb67(); _getb67(); +#endif +; return 0; } +EOF +if eval $ac_compile; then + rm -rf conftest* + { +test -n "$verbose" && \ +echo " defining" CRAY_STACKSEG_END to be "_getb67" +echo "#define" CRAY_STACKSEG_END "_getb67" >> confdefs.h +DEFS="$DEFS -DCRAY_STACKSEG_END=_getb67" +ac_sed_defs="${ac_sed_defs}\${ac_dA}CRAY_STACKSEG_END\${ac_dB}CRAY_STACKSEG_END\${ac_dC}_getb67\${ac_dD} +\${ac_uA}CRAY_STACKSEG_END\${ac_uB}CRAY_STACKSEG_END\${ac_uC}_getb67\${ac_uD} +\${ac_eA}CRAY_STACKSEG_END\${ac_eB}CRAY_STACKSEG_END\${ac_eC}_getb67\${ac_eD} +" +} + + +else + rm -rf conftest* + test -n "$silent" || echo "checking for GETB67" +cat > conftest.${ac_ext} < +int main() { return 0; } +int t() { +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_GETB67) || defined (__stub___GETB67) +choke me +#else +/* Override any gcc2 internal prototype to avoid an error. */ +extern char GETB67(); GETB67(); +#endif +; return 0; } +EOF +if eval $ac_compile; then + rm -rf conftest* + { +test -n "$verbose" && \ +echo " defining" CRAY_STACKSEG_END to be "GETB67" +echo "#define" CRAY_STACKSEG_END "GETB67" >> confdefs.h +DEFS="$DEFS -DCRAY_STACKSEG_END=GETB67" +ac_sed_defs="${ac_sed_defs}\${ac_dA}CRAY_STACKSEG_END\${ac_dB}CRAY_STACKSEG_END\${ac_dC}GETB67\${ac_dD} +\${ac_uA}CRAY_STACKSEG_END\${ac_uB}CRAY_STACKSEG_END\${ac_uC}GETB67\${ac_uD} +\${ac_eA}CRAY_STACKSEG_END\${ac_eB}CRAY_STACKSEG_END\${ac_eC}GETB67\${ac_eD} +" +} + + +else + rm -rf conftest* + test -n "$silent" || echo "checking for getb67" +cat > conftest.${ac_ext} < +int main() { return 0; } +int t() { +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_getb67) || defined (__stub___getb67) +choke me +#else +/* Override any gcc2 internal prototype to avoid an error. */ +extern char getb67(); getb67(); +#endif +; return 0; } +EOF +if eval $ac_compile; then + rm -rf conftest* + { +test -n "$verbose" && \ +echo " defining" CRAY_STACKSEG_END to be "getb67" +echo "#define" CRAY_STACKSEG_END "getb67" >> confdefs.h +DEFS="$DEFS -DCRAY_STACKSEG_END=getb67" +ac_sed_defs="${ac_sed_defs}\${ac_dA}CRAY_STACKSEG_END\${ac_dB}CRAY_STACKSEG_END\${ac_dC}getb67\${ac_dD} +\${ac_uA}CRAY_STACKSEG_END\${ac_uB}CRAY_STACKSEG_END\${ac_uC}getb67\${ac_uD} +\${ac_eA}CRAY_STACKSEG_END\${ac_eB}CRAY_STACKSEG_END\${ac_eC}getb67\${ac_eD} +" +} + + +fi +rm -f conftest* + +fi +rm -f conftest* + +fi +rm -f conftest* + + +fi +rm -f conftest* + + +fi +rm -f conftest* + +if test -n "$ac_alloca_missing"; then + # The SVR3 libPW and SVR4 libucb both contain incompatible functions + # that cause trouble. Some versions do not even contain alloca or + # contain a buggy version. If you still want to use their alloca, + # use ar to extract alloca.o from them instead of compiling alloca.c. + ALLOCA=alloca.o + +{ +test -n "$verbose" && \ +echo " defining C_ALLOCA" +echo "#define" C_ALLOCA "1" >> confdefs.h +DEFS="$DEFS -DC_ALLOCA=1" +ac_sed_defs="${ac_sed_defs}\${ac_dA}C_ALLOCA\${ac_dB}C_ALLOCA\${ac_dC}1\${ac_dD} +\${ac_uA}C_ALLOCA\${ac_uB}C_ALLOCA\${ac_uC}1\${ac_uD} +\${ac_eA}C_ALLOCA\${ac_eB}C_ALLOCA\${ac_eC}1\${ac_eD} +" +} + + + test -n "$silent" || echo "checking stack direction for C alloca" + test -n "$silent" || echo "checking whether cross-compiling" +# If we cannot run a trivial program, we must be cross compiling. +cat > conftest.${ac_ext} </dev/null; then + : +else + cross_compiling=1 +fi +rm -fr conftest* + +if test -n "$cross_compiling" +then + +{ +test -n "$verbose" && \ +echo " defining" STACK_DIRECTION to be "0" +echo "#define" STACK_DIRECTION "0" >> confdefs.h +DEFS="$DEFS -DSTACK_DIRECTION=0" +ac_sed_defs="${ac_sed_defs}\${ac_dA}STACK_DIRECTION\${ac_dB}STACK_DIRECTION\${ac_dC}0\${ac_dD} +\${ac_uA}STACK_DIRECTION\${ac_uB}STACK_DIRECTION\${ac_uC}0\${ac_uD} +\${ac_eA}STACK_DIRECTION\${ac_eB}STACK_DIRECTION\${ac_eC}0\${ac_eD} +" +} + +else +cat > conftest.${ac_ext} < addr) ? 1 : -1; +} +main () +{ + exit (find_stack_direction() < 0); +} +EOF +eval $ac_compile +if test -s conftest && (./conftest; exit) 2>/dev/null; then + +{ +test -n "$verbose" && \ +echo " defining" STACK_DIRECTION to be "1" +echo "#define" STACK_DIRECTION "1" >> confdefs.h +DEFS="$DEFS -DSTACK_DIRECTION=1" +ac_sed_defs="${ac_sed_defs}\${ac_dA}STACK_DIRECTION\${ac_dB}STACK_DIRECTION\${ac_dC}1\${ac_dD} +\${ac_uA}STACK_DIRECTION\${ac_uB}STACK_DIRECTION\${ac_uC}1\${ac_uD} +\${ac_eA}STACK_DIRECTION\${ac_eB}STACK_DIRECTION\${ac_eC}1\${ac_eD} +" +} + + +else + +{ +test -n "$verbose" && \ +echo " defining" STACK_DIRECTION to be "-1" +echo "#define" STACK_DIRECTION "-1" >> confdefs.h +DEFS="$DEFS -DSTACK_DIRECTION=-1" +ac_sed_defs="${ac_sed_defs}\${ac_dA}STACK_DIRECTION\${ac_dB}STACK_DIRECTION\${ac_dC}-1\${ac_dD} +\${ac_uA}STACK_DIRECTION\${ac_uB}STACK_DIRECTION\${ac_uC}-1\${ac_uD} +\${ac_eA}STACK_DIRECTION\${ac_eB}STACK_DIRECTION\${ac_eC}-1\${ac_eD} +" +} + +fi +fi +rm -fr conftest* +fi + + + +# The preferred way to propogate these variables is regular @ substitutions. +if test -n "$prefix"; then + ac_prsub="s%^prefix\\([ ]*\\)=\\([ ]*\\).*$%prefix\\1=\\2$prefix%" +else + prefix=/usr/local +fi +if test -n "$exec_prefix"; then + ac_prsub="$ac_prsub +s%^exec_prefix\\([ ]*\\)=\\([ ]*\\).*$%exec_prefix\\1=\\2$exec_prefix%" +else + exec_prefix='${prefix}' # Let make expand it. +fi + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +# Quote sed substitution magic chars in DEFS. +cat >conftest.def < config.status </dev/null | sed 1q`: +# +# $0 $configure_args + +ac_cs_usage="Usage: config.status [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo running \${CONFIG_SHELL-/bin/sh} $0 $configure_args --no-create + exec \${CONFIG_SHELL-/bin/sh} $0 $configure_args --no-create ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "config.status generated by autoconf version 1.11" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +trap 'rm -fr Makefile config.h conftest*; exit 1' 1 2 15 +CC='$CC' +CFLAGS='$CFLAGS' +LDFLAGS='$LDFLAGS' +CPP='$CPP' +INSTALL='$INSTALL' +INSTALL_PROGRAM='$INSTALL_PROGRAM' +INSTALL_DATA='$INSTALL_DATA' +RANLIB='$RANLIB' +ALLOCA='$ALLOCA' +LIBS='$LIBS' +srcdir='$srcdir' +top_srcdir='$top_srcdir' +prefix='$prefix' +exec_prefix='$exec_prefix' +ac_prsub='$ac_prsub' +ac_vpsub='$ac_vpsub' +extrasub='$extrasub' +EOF +cat >> config.status <<\EOF + +ac_given_srcdir=$srcdir + +CONFIG_FILES=${CONFIG_FILES-"Makefile"} +for ac_file in .. ${CONFIG_FILES}; do if test "x$ac_file" != x..; then + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/$ac_dir" + else + ac_dir_suffix= + fi + + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dir_suffix"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + comment_str="Generated automatically from `echo $ac_file|sed 's|.*/||'`.in by configure." + case "$ac_file" in + *.c | *.h | *.C | *.cc | *.m ) echo "/* $comment_str */" > "$ac_file" ;; + * ) echo "# $comment_str" > "$ac_file" ;; + esac + sed -e " +$ac_prsub +$ac_vpsub +$extrasub +s%@CC@%$CC%g +s%@CFLAGS@%$CFLAGS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@CPP@%$CPP%g +s%@INSTALL@%$INSTALL%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@RANLIB@%$RANLIB%g +s%@ALLOCA@%$ALLOCA%g +s%@LIBS@%$LIBS%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@prefix@%$prefix%g +s%@exec_prefix@%$exec_prefix%g +s%@DEFS@%-DHAVE_CONFIG_H%" $ac_given_srcdir/${ac_file}.in >> $ac_file +fi; done + +# These sed commands are put into ac_sed_defs when defining a macro. +# They are broken into pieces to make the sed script easier to manage. +# They are passed to sed as "A NAME B NAME C VALUE D", where NAME +# is the cpp macro being defined and VALUE is the value it is being given. +# Each defining turns into a single global substitution command. +# Hopefully no one uses "!" as a variable value. +# Other candidates for the sed separators, like , and @, do get used. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s!^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*!\1#\2' +ac_dC='\3' +ac_dD='!g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s!^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)!\1#\2define\3' +ac_uC=' ' +ac_uD='\4!g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s!^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$!\1#\2define\3' +ac_eC=' ' +ac_eD='!g' +rm -f conftest.sed +EOF +# Turn off quoting long enough to insert the sed commands. +rm -f conftest.sh +cat > conftest.sh < conftest.s1 # Like head -9. + sed 1,${ac_max_sh_lines}d conftest.sh > conftest.s2 # Like tail +10. + # Write a limited-size here document to append to conftest.sed. + echo 'cat >> conftest.sed <> config.status + cat conftest.s1 >> config.status + echo 'CONFEOF' >> config.status + rm -f conftest.s1 conftest.sh + mv conftest.s2 conftest.sh +done +rm -f conftest.sh + +# Now back to your regularly scheduled config.status. +cat >> config.status <<\EOF +# This sed command replaces #undef's with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it in +# config.h. +cat >> conftest.sed <<\CONFEOF +s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, +CONFEOF +rm -f conftest.h +# Break up the sed commands because old seds have small limits. +ac_max_sed_lines=20 + +CONFIG_HEADERS=${CONFIG_HEADERS-"config.h"} +for ac_file in .. ${CONFIG_HEADERS}; do if test "x$ac_file" != x..; then + echo creating $ac_file + + cp $ac_given_srcdir/$ac_file.in conftest.h1 + cp conftest.sed conftest.stm + while : + do + ac_lines=`grep -c . conftest.stm` + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + rm -f conftest.s1 conftest.s2 conftest.h2 + sed ${ac_max_sed_lines}q conftest.stm > conftest.s1 # Like head -20. + sed 1,${ac_max_sed_lines}d conftest.stm > conftest.s2 # Like tail +21. + sed -f conftest.s1 < conftest.h1 > conftest.h2 + rm -f conftest.s1 conftest.h1 conftest.stm + mv conftest.h2 conftest.h1 + mv conftest.s2 conftest.stm + done + rm -f conftest.stm conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.h1 >> conftest.h + rm -f conftest.h1 + if cmp -s $ac_file conftest.h 2>/dev/null; then + # The file exists and we would not be changing it. + echo "$ac_file is unchanged" + rm -f conftest.h + else + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done +rm -f conftest.sed + + + +# Makefile uses this timestamp file to record whether config.h is up to date. +touch stamp-config +exit 0 +EOF +chmod +x config.status +# Some shells look in PATH for config.status without the "./". +test -n "$no_create" || ${CONFIG_SHELL-/bin/sh} ./config.status + diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..febcbab --- /dev/null +++ b/configure.in @@ -0,0 +1,48 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(readline.h) +AC_CONFIG_HEADER(config.h) +AC_REVISION(Configure for Readline 2.0) + +# We want these before the checks, so the checks can modify their values. +test -z "$CFLAGS" && CFLAGS=-g auto_cflags=1 + +AC_PROG_CC + +# If we're using gcc and the user hasn't specified CFLAGS, add -O to CFLAGS. +test -n "$GCC" && test -n "$auto_cflags" && CFLAGS="$CFLAGS -O" + +AC_SUBST(CFLAGS)dnl +AC_SUBST(LDFLAGS)dnl + +AC_GCC_TRADITIONAL +AC_PROG_INSTALL +AC_PROG_RANLIB + +AC_USG + +AC_HAVE_FUNCS(strcasecmp sighold) + +AC_HAVE_HEADERS(unistd.h stdlib.h varargs.h string.h alloca.h \ + dirent.h sys/ptem.h sys/pte.h sys/stream.h termcap.h \ + termio.h) + +AC_HEADER_CHECK(sys/file.h, ,AC_DEFINE(NO_SYS_FILE)) + +if test -z "$have_tiocgwinsz"; then +AC_COMPILE_CHECK(TIOCGWINSZ in sys/ioctl.h, +[#include +#include ], [int x = TIOCGWINSZ;], +AC_DEFINE(GWINSZ_IN_SYS_IOCTL)) +fi + +AC_COMPILE_CHECK(programs able to redeclare getpw functions, +[#include +#include +extern struct passwd *getpwuid();], [struct passwd *z; z = getpwuid(0);], , +AC_DEFINE(HAVE_GETPW_DECLS)) + +AC_ALLOCA + +AC_OUTPUT(Makefile, [ +# Makefile uses this timestamp file to record whether config.h is up to date. +touch stamp-config]) diff --git a/display.c b/display.c new file mode 100644 index 0000000..8204570 --- /dev/null +++ b/display.c @@ -0,0 +1,1219 @@ +/* display.c -- readline redisplay facility. */ + +/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library 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 1, or + (at your option) any later version. + + The GNU Readline Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define READLINE_LIBRARY + +#include +#include + +#if defined (HAVE_UNISTD_H) +# include +#endif /* HAVE_UNISTD_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#include "posixstat.h" + +/* System-specific feature definitions and include files. */ +#include "rldefs.h" + +/* Some standard library routines. */ +#include "readline.h" +#include "history.h" + +#if !defined (strchr) && !defined (__STDC__) +extern char *strchr (), *strrchr (); +#endif /* !strchr && !__STDC__ */ + +/* Global and pseudo-global variables and functions + imported from readline.c. */ +extern char *rl_prompt; +extern int readline_echoing_p; +extern char *term_clreol, *term_im, *term_ic, *term_ei, *term_DC; +/* Termcap variables. */ +extern char *term_up, *term_dc, *term_cr, *term_IC; +extern int screenheight, screenwidth, screenchars; +extern int terminal_can_insert, term_xn; + +extern void _rl_output_some_chars (); +extern int _rl_output_character_function (); + +extern int _rl_output_meta_chars; +extern int _rl_horizontal_scroll_mode; +extern int _rl_mark_modified_lines; +extern int _rl_prefer_visible_bell; + +/* Pseudo-global functions (local to the readline library) exported + by this file. */ +void _rl_move_cursor_relative (), _rl_output_some_chars (); +void _rl_move_vert (); + +static void update_line (), clear_to_eol (), space_to_eol (); +static void delete_chars (), insert_some_chars (); + +extern char *xmalloc (), *xrealloc (); + +/* Heuristic used to decide whether it is faster to move from CUR to NEW + by backing up or outputting a carriage return and moving forward. */ +#define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new))) + +/* **************************************************************** */ +/* */ +/* Display stuff */ +/* */ +/* **************************************************************** */ + +/* This is the stuff that is hard for me. I never seem to write good + display routines in C. Let's see how I do this time. */ + +/* (PWP) Well... Good for a simple line updater, but totally ignores + the problems of input lines longer than the screen width. + + update_line and the code that calls it makes a multiple line, + automatically wrapping line update. Careful attention needs + to be paid to the vertical position variables. */ + +/* Keep two buffers; one which reflects the current contents of the + screen, and the other to draw what we think the new contents should + be. Then compare the buffers, and make whatever changes to the + screen itself that we should. Finally, make the buffer that we + just drew into be the one which reflects the current contents of the + screen, and place the cursor where it belongs. + + Commands that want to can fix the display themselves, and then let + this function know that the display has been fixed by setting the + RL_DISPLAY_FIXED variable. This is good for efficiency. */ + +/* Global variables declared here. */ +/* What YOU turn on when you have handled all redisplay yourself. */ +int rl_display_fixed = 0; + +/* The stuff that gets printed out before the actual text of the line. + This is usually pointing to rl_prompt. */ +char *rl_display_prompt = (char *)NULL; + +/* Pseudo-global variables declared here. */ +/* The visible cursor position. If you print some text, adjust this. */ +int _rl_last_c_pos = 0; +int _rl_last_v_pos = 0; + +/* Number of lines currently on screen minus 1. */ +int _rl_vis_botlin = 0; + +/* Variables used only in this file. */ +/* The last left edge of text that was displayed. This is used when + doing horizontal scrolling. It shifts in thirds of a screenwidth. */ +static int last_lmargin = 0; + +/* The line display buffers. One is the line currently displayed on + the screen. The other is the line about to be displayed. */ +static char *visible_line = (char *)NULL; +static char *invisible_line = (char *)NULL; + +/* A buffer for `modeline' messages. */ +static char msg_buf[128]; + +/* Non-zero forces the redisplay even if we thought it was unnecessary. */ +static int forced_display = 0; + +/* Default and initial buffer size. Can grow. */ +static int line_size = 1024; + +static char *last_prompt_string = (char *)NULL; +static char *local_prompt, *local_prompt_prefix; +static int visible_length, prefix_length; + +/* The number of invisible characters in the line currently being + displayed on the screen. */ +static int visible_wrap_offset = 0; + +/* The length (buffer offset) of the first line of the last (possibly + multi-line) buffer displayed on the screen. */ +static int visible_first_line_len = 0; + +/* Expand the prompt string S and return the number of visible + characters in *LP, if LP is not null. This is currently more-or-less + a placeholder for expansion. */ + +/* Current implementation: + \001 (^A) start non-visible characters + \002 (^B) end non-visible characters + all characters except \001 and \002 (following a \001) are copied to + the returned string; all characters except those between \001 and + \002 are assumed to be `visible'. */ + +static char * +expand_prompt (pmt, lp) + char *pmt; + int *lp; +{ + char *r, *ret, *p; + int l, rl, ignoring; + + /* Short-circuit if we can. */ + if (strchr (pmt, RL_PROMPT_START_IGNORE) == 0) + { + r = savestring (pmt); + if (lp) + *lp = strlen (r); + return r; + } + + l = strlen (pmt); + r = ret = xmalloc (l + 1); + + for (rl = ignoring = 0, p = pmt; p && *p; p++) + { + /* This code strips the invisible character string markers + RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */ + if (*p == RL_PROMPT_START_IGNORE) + { + ignoring++; + continue; + } + else if (ignoring && *p == RL_PROMPT_END_IGNORE) + { + ignoring = 0; + continue; + } + else + { + *r++ = *p; + if (!ignoring) + rl++; + } + } + + *r = '\0'; + if (lp) + *lp = rl; + return ret; +} + +/* + * Expand the prompt string into the various display components, if + * necessary. + * + * local_prompt = expanded last line of string in rl_display_prompt + * (portion after the final newline) + * local_prompt_prefix = portion before last newline of rl_display_prompt, + * expanded via expand_prompt + * visible_length = number of visible characters in local_prompt + * prefix_length = number of visible characters in local_prompt_prefix + * + * This function is called once per call to readline(). It may also be + * called arbitrarily to expand the primary prompt. + * + * The return value is the number of visible characters on the last line + * of the (possibly multi-line) prompt. + */ +int +rl_expand_prompt (prompt) + char *prompt; +{ + char *p, *t; + int c; + + /* Clear out any saved values. */ + if (local_prompt) + free (local_prompt); + if (local_prompt_prefix) + free (local_prompt_prefix); + local_prompt = local_prompt_prefix = (char *)0; + + p = strrchr (prompt, '\n'); + if (!p) + { + /* The prompt is only one line. */ + local_prompt = expand_prompt (prompt, &visible_length); + local_prompt_prefix = (char *)0; + return (visible_length); + } + else + { + /* The prompt spans multiple lines. */ + t = ++p; + local_prompt = expand_prompt (p, &visible_length); + c = *t; *t = '\0'; + /* The portion of the prompt string up to and including the + final newline is now null-terminated. */ + local_prompt_prefix = expand_prompt (prompt, &prefix_length); + *t = c; + return (prefix_length); + } +} + +/* Basic redisplay algorithm. */ +void +rl_redisplay () +{ + register int in, out, c, linenum; + register char *line = invisible_line; + int c_pos = 0, inv_botlin = 0, wrap_offset, wrap_column; + char *prompt_this_line; + + if (!readline_echoing_p) + return; + + if (!rl_display_prompt) + rl_display_prompt = ""; + + if (!invisible_line) + { + visible_line = xmalloc (line_size); + invisible_line = xmalloc (line_size); + line = invisible_line; + for (in = 0; in < line_size; in++) + { + visible_line[in] = 0; + invisible_line[in] = 1; + } + rl_on_new_line (); + } + + /* Draw the line into the buffer. */ + c_pos = -1; + + /* Mark the line as modified or not. We only do this for history + lines. */ + out = 0; + if (_rl_mark_modified_lines && current_history () && rl_undo_list) + { + line[out++] = '*'; + line[out] = '\0'; + } + + /* If someone thought that the redisplay was handled, but the currently + visible line has a different modification state than the one about + to become visible, then correct the caller's misconception. */ + if (visible_line[0] != invisible_line[0]) + rl_display_fixed = 0; + + /* If the prompt to be displayed is the `primary' readline prompt (the + one passed to readline()), use the values we have already expanded. + If not, use what's already in rl_display_prompt. WRAP_OFFSET is the + number of non-visible characters in the prompt string. */ + if (rl_display_prompt == rl_prompt) + { + int local_len = local_prompt ? strlen (local_prompt) : 0; + if (local_prompt_prefix && forced_display) + _rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix)); + + if (local_len > 0) + strncpy (line + out, local_prompt, local_len); + out += local_len; + line[out] = '\0'; + wrap_offset = local_len - visible_length; + } + else + { + int pmtlen; + prompt_this_line = strrchr (rl_display_prompt, '\n'); + if (!prompt_this_line) + prompt_this_line = rl_display_prompt; + else + { + prompt_this_line++; + if (forced_display) + _rl_output_some_chars (rl_display_prompt, prompt_this_line - rl_display_prompt); + } + + pmtlen = strlen (prompt_this_line); + strncpy (line + out, prompt_this_line, pmtlen); + out += pmtlen; + line[out] = '\0'; + wrap_offset = 0; + } + + for (in = 0; in < rl_end; in++) + { + c = (unsigned char)rl_line_buffer[in]; + + if (out + 8 >= line_size) /* XXX - 8 for \t */ + { + line_size *= 2; + visible_line = xrealloc (visible_line, line_size); + invisible_line = xrealloc (invisible_line, line_size); + line = invisible_line; + } + + if (in == rl_point) + c_pos = out; + + if (META_CHAR (c)) + { + if (_rl_output_meta_chars == 0) + { + sprintf (line + out, "\\%o", c); + out += 4; + } + else + line[out++] = c; + } +#if defined (DISPLAY_TABS) + else if (c == '\t') + { + register int newout = (out | (int)7) + 1; + while (out < newout) + line[out++] = ' '; + } +#endif + else if (c < ' ') + { + line[out++] = '^'; + line[out++] = UNCTRL (c); /* XXX was c ^ 0x40 */ + } + else if (c == 127) + { + line[out++] = '^'; + line[out++] = '?'; + } + else + line[out++] = c; + } + line[out] = '\0'; + if (c_pos < 0) + c_pos = out; + + /* C_POS == position in buffer where cursor should be placed. */ + + /* PWP: now is when things get a bit hairy. The visible and invisible + line buffers are really multiple lines, which would wrap every + (screenwidth - 1) characters. Go through each in turn, finding + the changed region and updating it. The line order is top to bottom. */ + + /* If we can move the cursor up and down, then use multiple lines, + otherwise, let long lines display in a single terminal line, and + horizontally scroll it. */ + + if (!_rl_horizontal_scroll_mode && term_up && *term_up) + { + int total_screen_chars = screenchars; + int nleft, cursor_linenum, pos, changed_screen_line; + + if (!rl_display_fixed || forced_display) + { + forced_display = 0; + + /* If we have more than a screenful of material to display, then + only display a screenful. We should display the last screen, + not the first. I'll fix this in a minute. */ + if (out >= total_screen_chars) + out = total_screen_chars - 1; + + /* Number of screen lines to display. The first line wraps at + (screenwidth + wrap_offset) chars, the rest of the lines have + screenwidth chars. */ + nleft = out - wrap_offset + term_xn - 1; + inv_botlin = (nleft > 0) ? nleft / screenwidth : 0; + + /* The first line is at character position 0 in the buffer. The + second and subsequent lines start at N * screenwidth, offset by + OFFSET. OFFSET is wrap_offset for the invisible line and + visible_wrap_offset for the line currently displayed. */ + +#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0) +#define L_OFFSET(n, offset) ((n) > 0 ? ((n) * screenwidth) + (offset) : 0) +#define VIS_CHARS(line) &visible_line[L_OFFSET((line), visible_wrap_offset)] +#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line) +#define INV_LINE(line) &invisible_line[L_OFFSET((line), wrap_offset)] + + /* For each line in the buffer, do the updating display. */ + for (linenum = 0; linenum <= inv_botlin; linenum++) + { + update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum, + screenwidth + W_OFFSET(linenum, visible_wrap_offset), + screenwidth + W_OFFSET(linenum, wrap_offset), + inv_botlin); + + /* If this is the line with the prompt, we might need to + compensate for invisible characters in the new line. Do + this only if there is not more than one new line (which + implies that we completely overwrite the old visible line) + and the new line is shorter than the old. */ + if (linenum == 0 && + inv_botlin == 0 && + (wrap_offset > visible_wrap_offset) && + (_rl_last_c_pos < visible_first_line_len)) + { + nleft = screenwidth + wrap_offset - _rl_last_c_pos; + clear_to_eol (nleft); + } + + /* Since the new first line is now visible, save its length. */ + if (linenum == 0) + visible_first_line_len = (inv_botlin > 0) ? screenwidth : out - wrap_offset; + } + + /* We may have deleted some lines. If so, clear the left over + blank ones at the bottom out. */ + if (_rl_vis_botlin > inv_botlin) + { + char *tt; + for (; linenum <= _rl_vis_botlin; linenum++) + { + tt = VIS_CHARS (linenum); + _rl_move_vert (linenum); + _rl_move_cursor_relative (0, tt); + clear_to_eol + ((linenum == _rl_vis_botlin) ? strlen (tt) : screenwidth); + } + } + _rl_vis_botlin = inv_botlin; + + /* Move the cursor where it should be. */ + /* Which line? */ + nleft = c_pos - wrap_offset - term_xn + 1; + cursor_linenum = (nleft > 0) ? nleft / screenwidth : 0; + + /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a + different screen line during this redisplay. */ + changed_screen_line = _rl_last_v_pos != cursor_linenum; + if (changed_screen_line) + { + _rl_move_vert (cursor_linenum); + /* If we moved up to the line with the prompt using term_up, + the physical cursor position on the screen stays the same, + but the buffer position needs to be adjusted to account + for invisible characters. */ + if (cursor_linenum == 0 && wrap_offset) + _rl_last_c_pos += wrap_offset; + } + + /* We have to reprint the prompt if it contains invisible + characters, since it's not generally OK to just reprint + the characters from the current cursor position. */ + nleft = visible_length + wrap_offset; + if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 && + _rl_last_c_pos <= nleft && local_prompt) + { + if (term_cr) + tputs (term_cr, 1, _rl_output_character_function); + _rl_output_some_chars (local_prompt, nleft); + _rl_last_c_pos = nleft; + } + + /* Where on that line? And where does that line start + in the buffer? */ + pos = L_OFFSET(cursor_linenum, wrap_offset); + /* nleft == number of characters in the line buffer between the + start of the line and the cursor position. */ + nleft = c_pos - pos; + + /* Since backspace() doesn't know about invisible characters in the + prompt, and there's no good way to tell it, we compensate for + those characters here and call backspace() directly. */ + if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos) + { + backspace (_rl_last_c_pos - nleft); + _rl_last_c_pos = nleft; + } + + if (nleft != _rl_last_c_pos) + _rl_move_cursor_relative (nleft, &invisible_line[pos]); + } + } + else /* Do horizontal scrolling. */ + { +#define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0) + int lmargin, ndisp, nleft, phys_c_pos, t; + + /* Always at top line. */ + _rl_last_v_pos = 0; + + /* Compute where in the buffer the displayed line should start. This + will be LMARGIN. */ + + /* The number of characters that will be displayed before the cursor. */ + ndisp = c_pos - wrap_offset; + nleft = visible_length + wrap_offset; + /* Where the new cursor position will be on the screen. This can be + longer than SCREENWIDTH; if it is, lmargin will be adjusted. */ + phys_c_pos = c_pos - (last_lmargin ? last_lmargin : wrap_offset); + t = screenwidth / 3; + + /* If the number of characters had already exceeded the screenwidth, + last_lmargin will be > 0. */ + + /* If the number of characters to be displayed is more than the screen + width, compute the starting offset so that the cursor is about + two-thirds of the way across the screen. */ + if (phys_c_pos > screenwidth - 2) + { + lmargin = c_pos - (2 * t); + if (lmargin < 0) + lmargin = 0; + /* If the left margin would be in the middle of a prompt with + invisible characters, don't display the prompt at all. */ + if (wrap_offset && lmargin > 0 && lmargin < nleft) + lmargin = nleft; + } + else if (ndisp < screenwidth - 2) /* XXX - was -1 */ + lmargin = 0; + else if (phys_c_pos < 1) + { + /* If we are moving back towards the beginning of the line and + the last margin is no longer correct, compute a new one. */ + lmargin = ((c_pos - 1) / t) * t; /* XXX */ + if (wrap_offset && lmargin > 0 && lmargin < nleft) + lmargin = nleft; + } + else + lmargin = last_lmargin; + + /* If the first character on the screen isn't the first character + in the display line, indicate this with a special character. */ + if (lmargin > 0) + line[lmargin] = '<'; + + /* If SCREENWIDTH characters starting at LMARGIN do not encompass + the whole line, indicate that with a special characters at the + right edge of the screen. If LMARGIN is 0, we need to take the + wrap offset into account. */ + t = lmargin + M_OFFSET (lmargin, wrap_offset) + screenwidth; + if (t < out) + line[t - 1] = '>'; + + if (!rl_display_fixed || forced_display || lmargin != last_lmargin) + { + forced_display = 0; + update_line (&visible_line[last_lmargin], + &invisible_line[lmargin], + 0, + screenwidth + visible_wrap_offset, + screenwidth + (lmargin ? 0 : wrap_offset), + 0); + + /* If the visible new line is shorter than the old, but the number + of invisible characters is greater, and we are at the end of + the new line, we need to clear to eol. */ + t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset); + if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) && + (_rl_last_c_pos == out) && + t < visible_first_line_len) + { + nleft = screenwidth - t; + clear_to_eol (nleft); + } + visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset); + if (visible_first_line_len > screenwidth) + visible_first_line_len = screenwidth; + + _rl_move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]); + last_lmargin = lmargin; + } + } + fflush (rl_outstream); + + /* Swap visible and non-visible lines. */ + { + char *temp = visible_line; + visible_line = invisible_line; + invisible_line = temp; + rl_display_fixed = 0; + /* If we are displaying on a single line, and last_lmargin is > 0, we + are not displaying any invisible characters, so set visible_wrap_offset + to 0. */ + if (_rl_horizontal_scroll_mode && last_lmargin) + visible_wrap_offset = 0; + else + visible_wrap_offset = wrap_offset; + } +} + +/* PWP: update_line() is based on finding the middle difference of each + line on the screen; vis: + + /old first difference + /beginning of line | /old last same /old EOL + v v v v +old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as +new: eddie> Oh, my little buggy says to me, as lurgid as + ^ ^ ^ ^ + \beginning of line | \new last same \new end of line + \new first difference + + All are character pointers for the sake of speed. Special cases for + no differences, as well as for end of line additions must be handeled. + + Could be made even smarter, but this works well enough */ +static void +update_line (old, new, current_line, omax, nmax, inv_botlin) + register char *old, *new; + int current_line, omax, nmax; +{ + register char *ofd, *ols, *oe, *nfd, *nls, *ne; + int temp, lendiff, wsatend, od, nd; + + /* If we're at the right edge of a terminal that supports xn, we're + ready to wrap around, so do so. This fixes problems with knowing + the exact cursor position and cut-and-paste with certain terminal + emulators. In this calculation, TEMP is the physical screen + position of the cursor. */ + temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset); + if (temp == screenwidth && term_xn && !_rl_horizontal_scroll_mode + && _rl_last_v_pos == current_line - 1) + { + if (new[0]) + putc (new[0], rl_outstream); + else + putc (' ', rl_outstream); + _rl_last_c_pos = 1; /* XXX */ + _rl_last_v_pos++; + if (old[0]) + old[0] = new[0]; + } + + /* Find first difference. */ + for (ofd = old, nfd = new; + (ofd - old < omax) && *ofd && (*ofd == *nfd); + ofd++, nfd++) + ; + + /* Move to the end of the screen line. ND and OD are used to keep track + of the distance between ne and new and oe and old, respectively, to + move a subtraction out of each loop. */ + for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++); + for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++); + + /* If no difference, continue to next line. */ + if (ofd == oe && nfd == ne) + return; + + wsatend = 1; /* flag for trailing whitespace */ + ols = oe - 1; /* find last same */ + nls = ne - 1; + while ((ols > ofd) && (nls > nfd) && (*ols == *nls)) + { + if (*ols != ' ') + wsatend = 0; + ols--; + nls--; + } + + if (wsatend) + { + ols = oe; + nls = ne; + } + else if (*ols != *nls) + { + if (*ols) /* don't step past the NUL */ + ols++; + if (*nls) + nls++; + } + + _rl_move_vert (current_line); + + /* If this is the first line and there are invisible characters in the + prompt string, and the prompt string has not changed, then redraw + the entire prompt string. We can only do this reliably if the + terminal supports a `cr' capability. + + This is more than just an efficiency hack -- there is a problem with + redrawing portions of the prompt string if they contain terminal + escape sequences (like drawing the `unbold' sequence without a + corresponding `bold') that manifests itself on certain terminals. */ + + lendiff = strlen (local_prompt); + if (current_line == 0 && !_rl_horizontal_scroll_mode && + lendiff > visible_length && + _rl_last_c_pos > 0 && (ofd - old) >= lendiff && term_cr) + { + tputs (term_cr, 1, _rl_output_character_function); + _rl_output_some_chars (local_prompt, lendiff); + _rl_last_c_pos = lendiff; + } + + _rl_move_cursor_relative (ofd - old, old); + + /* if (len (new) > len (old)) */ + lendiff = (nls - nfd) - (ols - ofd); + + /* Insert (diff (len (old), len (new)) ch. */ + temp = ne - nfd; + if (lendiff > 0) + { + /* Non-zero if we're increasing the number of lines. */ + int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin; + /* Sometimes it is cheaper to print the characters rather than + use the terminal's capabilities. If we're growing the number + of lines, make sure we actually cause the new line to wrap + around on auto-wrapping terminals. */ + if (terminal_can_insert && ((2 * temp) >= lendiff || term_IC) && (!term_xn || !gl)) + { + /* If lendiff > visible_length and _rl_last_c_pos == 0 and + _rl_horizontal_scroll_mode == 1, inserting the characters with + term_IC or term_ic will screw up the screen because of the + invisible characters. We need to just draw them. */ + if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 || + lendiff <= visible_length)) + { + insert_some_chars (nfd, lendiff); + _rl_last_c_pos += lendiff; + } + else + { + /* At the end of a line the characters do not have to + be "inserted". They can just be placed on the screen. */ + _rl_output_some_chars (nfd, lendiff); + _rl_last_c_pos += lendiff; + } + /* Copy (new) chars to screen from first diff to last match. */ + temp = nls - nfd; + if ((temp - lendiff) > 0) + { + _rl_output_some_chars (nfd + lendiff, temp - lendiff); + _rl_last_c_pos += temp - lendiff; + } + } + else + { + /* cannot insert chars, write to EOL */ + _rl_output_some_chars (nfd, temp); + _rl_last_c_pos += temp; + } + } + else /* Delete characters from line. */ + { + /* If possible and inexpensive to use terminal deletion, then do so. */ + if (term_dc && (2 * temp) >= -lendiff) + { + /* If all we're doing is erasing the invisible characters in the + prompt string, don't bother. It screws up the assumptions + about what's on the screen. */ + if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 && + -lendiff == visible_wrap_offset) + lendiff = 0; + + if (lendiff) + delete_chars (-lendiff); /* delete (diff) characters */ + + /* Copy (new) chars to screen from first diff to last match */ + temp = nls - nfd; + if (temp > 0) + { + _rl_output_some_chars (nfd, temp); + _rl_last_c_pos += temp; + } + } + /* Otherwise, print over the existing material. */ + else + { + if (temp > 0) + { + _rl_output_some_chars (nfd, temp); + _rl_last_c_pos += temp; + } + lendiff = (oe - old) - (ne - new); + if (term_xn && current_line < inv_botlin) + space_to_eol (lendiff); + else + clear_to_eol (lendiff); + } + } +} + +/* Tell the update routines that we have moved onto a new (empty) line. */ +rl_on_new_line () +{ + if (visible_line) + visible_line[0] = '\0'; + + _rl_last_c_pos = _rl_last_v_pos = 0; + _rl_vis_botlin = last_lmargin = 0; + return 0; +} + +/* Actually update the display, period. */ +rl_forced_update_display () +{ + if (visible_line) + { + register char *temp = visible_line; + + while (*temp) *temp++ = '\0'; + } + rl_on_new_line (); + forced_display++; + rl_redisplay (); + return 0; +} + +/* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices. + DATA is the contents of the screen line of interest; i.e., where + the movement is being done. */ +void +_rl_move_cursor_relative (new, data) + int new; + char *data; +{ + register int i; + + /* If we don't have to do anything, then return. */ + if (_rl_last_c_pos == new) return; + + /* It may be faster to output a CR, and then move forwards instead + of moving backwards. */ + /* i == current physical cursor position. */ + i = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset); + if (CR_FASTER (new, _rl_last_c_pos) || (term_xn && i == screenwidth)) + { +#if defined (__MSDOS__) + putc ('\r', rl_outstream); +#else + tputs (term_cr, 1, _rl_output_character_function); +#endif /* !__MSDOS__ */ + _rl_last_c_pos = 0; + } + + if (_rl_last_c_pos < new) + { + /* Move the cursor forward. We do it by printing the command + to move the cursor forward if there is one, else print that + portion of the output buffer again. Which is cheaper? */ + + /* The above comment is left here for posterity. It is faster + to print one character (non-control) than to print a control + sequence telling the terminal to move forward one character. + That kind of control is for people who don't know what the + data is underneath the cursor. */ +#if defined (HACK_TERMCAP_MOTION) + extern char *term_forward_char; + + if (term_forward_char) + for (i = _rl_last_c_pos; i < new; i++) + tputs (term_forward_char, 1, _rl_output_character_function); + else + for (i = _rl_last_c_pos; i < new; i++) + putc (data[i], rl_outstream); +#else + for (i = _rl_last_c_pos; i < new; i++) + putc (data[i], rl_outstream); +#endif /* HACK_TERMCAP_MOTION */ + } + else if (_rl_last_c_pos != new) + backspace (_rl_last_c_pos - new); + _rl_last_c_pos = new; +} + +/* PWP: move the cursor up or down. */ +void +_rl_move_vert (to) + int to; +{ + register int delta, i; + + if (_rl_last_v_pos == to || to > screenheight) + return; + +#if defined (__GO32__) + { + int row, col; + + ScreenGetCursor (&row, &col); + ScreenSetCursor ((row + to - _rl_last_v_pos), col); + } +#else /* !__GO32__ */ + + if ((delta = to - _rl_last_v_pos) > 0) + { + for (i = 0; i < delta; i++) + putc ('\n', rl_outstream); + tputs (term_cr, 1, _rl_output_character_function); + _rl_last_c_pos = 0; + } + else + { /* delta < 0 */ + if (term_up && *term_up) + for (i = 0; i < -delta; i++) + tputs (term_up, 1, _rl_output_character_function); + } +#endif /* !__GO32__ */ + _rl_last_v_pos = to; /* Now TO is here */ +} + +/* Physically print C on rl_outstream. This is for functions which know + how to optimize the display. Return the number of characters output. */ +rl_show_char (c) + int c; +{ + int n = 1; + if (META_CHAR (c) && (_rl_output_meta_chars == 0)) + { + fprintf (rl_outstream, "M-"); + n += 2; + c = UNMETA (c); + } + +#if defined (DISPLAY_TABS) + if (c < 32 && c != '\t') +#else + if (c < 32) +#endif /* !DISPLAY_TABS */ + { + fprintf (rl_outstream, "C-"); + n += 2; + c += 64; + } + + putc (c, rl_outstream); + fflush (rl_outstream); + return n; +} + +int +rl_character_len (c, pos) + register int c, pos; +{ + unsigned char uc; + + uc = (unsigned char)c; + + if (META_CHAR (uc)) + return ((_rl_output_meta_chars == 0) ? 4 : 1); + + if (uc == '\t') + { +#if defined (DISPLAY_TABS) + return (((pos | 7) + 1) - pos); +#else + return (2); +#endif /* !DISPLAY_TABS */ + } + + return ((isprint (uc)) ? 1 : 2); +} + +/* How to print things in the "echo-area". The prompt is treated as a + mini-modeline. */ + +#if defined (HAVE_VARARGS_H) +rl_message (va_alist) + va_dcl +{ + char *format; + va_list args; + + va_start (args); + format = va_arg (args, char *); + vsprintf (msg_buf, format, args); + va_end (args); + + rl_display_prompt = msg_buf; + rl_redisplay (); + return 0; +} +#else /* !HAVE_VARARGS_H */ +rl_message (format, arg1, arg2) + char *format; +{ + sprintf (msg_buf, format, arg1, arg2); + rl_display_prompt = msg_buf; + rl_redisplay (); + return 0; +} +#endif /* !HAVE_VARARGS_H */ + +/* How to clear things from the "echo-area". */ +rl_clear_message () +{ + rl_display_prompt = rl_prompt; + rl_redisplay (); + return 0; +} + +rl_reset_line_state () +{ + rl_on_new_line (); + + rl_display_prompt = rl_prompt ? rl_prompt : ""; + forced_display = 1; + return 0; +} + +/* Quick redisplay hack when erasing characters at the end of the line. */ +void +_rl_erase_at_end_of_line (l) + int l; +{ + register int i; + + backspace (l); + for (i = 0; i < l; i++) + putc (' ', rl_outstream); + backspace (l); + for (i = 0; i < l; i++) + visible_line[--_rl_last_c_pos] = '\0'; + rl_display_fixed++; +} + +/* Clear to the end of the line. COUNT is the minimum + number of character spaces to clear, */ +static void +clear_to_eol (count) + int count; +{ +#if !defined (__GO32__) + if (term_clreol) + { + tputs (term_clreol, 1, _rl_output_character_function); + } + else +#endif /* !__GO32__ */ + space_to_eol (count); +} + +/* Clear to the end of the line using spaces. COUNT is the minimum + number of character spaces to clear, */ +static void +space_to_eol (count) + int count; +{ + register int i; + + for (i = 0; i < count; i++) + putc (' ', rl_outstream); + + _rl_last_c_pos += count; +} + +/* Insert COUNT characters from STRING to the output stream. */ +static void +insert_some_chars (string, count) + char *string; + int count; +{ +#if defined (__GO32__) + int row, col, width; + char *row_start; + + ScreenGetCursor (&row, &col); + width = ScreenCols (); + row_start = ScreenPrimary + (row * width); + + memcpy (row_start + col + count, row_start + col, width - col - count); + + /* Place the text on the screen. */ + _rl_output_some_chars (string, count); +#else /* !_GO32 */ + + /* If IC is defined, then we do not have to "enter" insert mode. */ + if (term_IC) + { + char *tgoto (), *buffer; + buffer = tgoto (term_IC, 0, count); + tputs (buffer, 1, _rl_output_character_function); + _rl_output_some_chars (string, count); + } + else + { + register int i; + + /* If we have to turn on insert-mode, then do so. */ + if (term_im && *term_im) + tputs (term_im, 1, _rl_output_character_function); + + /* If there is a special command for inserting characters, then + use that first to open up the space. */ + if (term_ic && *term_ic) + { + for (i = count; i--; ) + tputs (term_ic, 1, _rl_output_character_function); + } + + /* Print the text. */ + _rl_output_some_chars (string, count); + + /* If there is a string to turn off insert mode, we had best use + it now. */ + if (term_ei && *term_ei) + tputs (term_ei, 1, _rl_output_character_function); + } +#endif /* !__GO32__ */ +} + +/* Delete COUNT characters from the display line. */ +static void +delete_chars (count) + int count; +{ +#if defined (__GO32__) + int row, col, width; + char *row_start; + + ScreenGetCursor (&row, &col); + width = ScreenCols (); + row_start = ScreenPrimary + (row * width); + + memcpy (row_start + col, row_start + col + count, width - col - count); + memset (row_start + width - count, 0, count * 2); +#else /* !_GO32 */ + + if (count > screenwidth) /* XXX */ + return; + + if (term_DC && *term_DC) + { + char *tgoto (), *buffer; + buffer = tgoto (term_DC, count, count); + tputs (buffer, count, _rl_output_character_function); + } + else + { + if (term_dc && *term_dc) + while (count--) + tputs (term_dc, 1, _rl_output_character_function); + } +#endif /* !__GO32__ */ +} + +void +_rl_update_final () +{ + int full_lines; + + full_lines = 0; + if (_rl_vis_botlin && visible_line[screenwidth * _rl_vis_botlin] == 0) + { + _rl_vis_botlin--; + full_lines = 1; + } + _rl_move_vert (_rl_vis_botlin); + if (full_lines && term_xn) + { + /* Remove final line-wrap flag in xterm. */ + char *last_line; + last_line = &visible_line[screenwidth * _rl_vis_botlin]; + _rl_move_cursor_relative (screenwidth - 1, last_line); + clear_to_eol (0); + putc (last_line[screenwidth - 1], rl_outstream); + } + _rl_vis_botlin = 0; + crlf (); + fflush (rl_outstream); + rl_display_fixed++; +} diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000..ad5ef70 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,56 @@ +# This makefile for History library documentation is in -*- text -*- mode. +# Emacs likes it that way. + +DOC_SUPPORT = ../../doc-support/ +TEXINDEX = $(DOC_SUPPORT)/texindex + +TEX = tex + +DVIOBJ = readline.dvi history.dvi +INFOBJ = readline.info history.info +PSOBJ = readline.ps history.ps + +all: info dvi + +readline.dvi: rlman.texinfo rluser.texinfo rltech.texinfo + $(TEX) rlman.texinfo + $(TEXINDEX) rlman.?? + $(TEX) rlman.texinfo + mv rlman.dvi readline.dvi + +readline.info: rlman.texinfo rluser.texinfo rltech.texinfo + makeinfo rlman.texinfo + +history.dvi: hist.texinfo hsuser.texinfo hstech.texinfo + $(TEX) hist.texinfo + $(TEXINDEX) hist.?? + $(TEX) hist.texinfo + mv hist.dvi history.dvi + +history.info: hist.texinfo hsuser.texinfo hstech.texinfo + makeinfo hist.texinfo + +readline.ps: readline.dvi + dvips -D 300 -o $@ readline.dvi + +history.ps: history.dvi + dvips -D 300 -o $@ history.dvi + +info: $(INFOOBJ) +dvi: $(DVIOBJ) +ps: $(PSOBJ) + + +$(TEXINDEX): + (cd $(DOC_SUPPORT); $(MAKE) $(MFLAGS) CFLAGS='$(CFLAGS)' texindex) + +clean: + rm -f *.aux *.cp *.fn *.ky *.log *.pg *.toc *.tp *.vr *.cps *.pgs \ + *.fns *.kys *.tps *.vrs *.o core + +squeaky-clean: + rm -f *.aux *.cp *.fn *.ky *.log *.pg *.toc *.tp *.vr *.cps *.pgs \ + *.dvi *.info *.info-* *.fns *.kys *.tps *.vrs *.o core + +distclean: clean +realclean: clean diff --git a/doc/hist.texinfo b/doc/hist.texinfo new file mode 100644 index 0000000..cc80efa --- /dev/null +++ b/doc/hist.texinfo @@ -0,0 +1,113 @@ +\input texinfo @c -*-texinfo-*- +@c %**start of header (This is for running Texinfo on a region.) +@setfilename history.info +@settitle GNU History Library +@c %**end of header (This is for running Texinfo on a region.) + +@setchapternewpage odd + +@ignore +last change: Wed Jul 20 09:57:17 EDT 1994 +@end ignore + +@set EDITION 2.0 +@set VERSION 2.0 +@set UPDATED 20 July 1994 +@set UPDATE-MONTH July 1994 + +@ifinfo +This document describes the GNU History library, a programming tool that +provides a consistent user interface for recalling lines of previously +typed input. + +Copyright (C) 1988, 1991 Free Software Foundation, Inc. + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +pare 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 Foundation. +@end ifinfo + +@titlepage +@sp 10 +@title GNU History Library +@subtitle Edition @value{EDITION}, for @code{History Library} Version @value{VERSION}. +@subtitle @value{UPDATE-MONTH} +@author Brian Fox, Free Software Foundation +@author Chet Ramey, Case Western Reserve University + +@page +This document describes the GNU History library, a programming tool that +provides a consistent user interface for recalling lines of previously +typed input. + +Published by the Free Software Foundation @* +675 Massachusetts Avenue, @* +Cambridge, MA 02139 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 Foundation. + +@vskip 0pt plus 1filll +Copyright @copyright{} 1989, 1991 Free Software Foundation, Inc. +@end titlepage + +@ifinfo +@node Top +@top GNU History Library + +This document describes the GNU History library, a programming tool that +provides a consistent user interface for recalling lines of previously +typed input. + +@menu +* Using History Interactively:: GNU History User's Manual. +* Programming with GNU History:: GNU History Programmer's Manual. +* Concept Index:: Index of concepts described in this manual. +* Function and Variable Index:: Index of externally visible functions + and variables. +@end menu +@end ifinfo + +@syncodeindex fn vr + +@include hsuser.texinfo +@include hstech.texinfo + +@node Concept Index +@appendix Concept Index +@printindex cp + +@node Function and Variable Index +@appendix Function and Variable Index +@printindex vr + +@contents +@bye diff --git a/doc/history.dvi b/doc/history.dvi new file mode 100644 index 0000000..60d7376 Binary files /dev/null and b/doc/history.dvi differ diff --git a/doc/history.info b/doc/history.info new file mode 100644 index 0000000..6df0bd9 --- /dev/null +++ b/doc/history.info @@ -0,0 +1,744 @@ +This is Info file history.info, produced by Makeinfo-1.55 from the +input file hist.texinfo. + + This document describes the GNU History library, a programming tool +that provides a consistent user interface for recalling lines of +previously typed input. + + Copyright (C) 1988, 1991 Free Software Foundation, Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice pare +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 Foundation. + + +File: history.info, Node: Top, Next: Using History Interactively, Prev: (DIR), Up: (DIR) + +GNU History Library +******************* + + This document describes the GNU History library, a programming tool +that provides a consistent user interface for recalling lines of +previously typed input. + +* Menu: + +* Using History Interactively:: GNU History User's Manual. +* Programming with GNU History:: GNU History Programmer's Manual. +* Concept Index:: Index of concepts described in this manual. +* Function and Variable Index:: Index of externally visible functions + and variables. + + +File: history.info, Node: Using History Interactively, Next: Programming with GNU History, Prev: Top, Up: Top + +Using History Interactively +*************************** + + This chapter describes how to use the GNU History Library +interactively, from a user's standpoint. It should be considered a +user's guide. For information on using the GNU History Library in your +own programs, *note Programming with GNU History::.. + +* Menu: + +* History Interaction:: What it feels like using History as a user. + + +File: history.info, Node: History Interaction, Up: Using History Interactively + +History Interaction +=================== + + The History library provides a history expansion feature that is +similar to the history expansion provided by `csh'. The following text +describes the syntax used to manipulate the history information. + + History expansion takes place in two parts. The first is to +determine which line from the previous history should be used during +substitution. The second is to select portions of that line for +inclusion into the current one. The line selected from the previous +history is called the "event", and the portions of that line that are +acted upon are called "words". The line is broken into words in the +same fashion that Bash does, so that several English (or Unix) words +surrounded by quotes are considered as one word. + +* Menu: + +* Event Designators:: How to specify which history line to use. +* Word Designators:: Specifying which words are of interest. +* Modifiers:: Modifying the results of substitution. + + +File: history.info, Node: Event Designators, Next: Word Designators, Up: History Interaction + +Event Designators +----------------- + + An event designator is a reference to a command line entry in the +history list. + +`!' + Start a history substitution, except when followed by a space, tab, + the end of the line, = or (. + +`!!' + Refer to the previous command. This is a synonym for `!-1'. + +`!n' + Refer to command line N. + +`!-n' + Refer to the command N lines back. + +`!string' + Refer to the most recent command starting with STRING. + +`!?string'[`?'] + Refer to the most recent command containing STRING. + +`!#' + The entire command line typed so far. + +`^string1^string2^' + Quick Substitution. Repeat the last command, replacing STRING1 + with STRING2. Equivalent to `!!:s/string1/string2/'. + + +File: history.info, Node: Word Designators, Next: Modifiers, Prev: Event Designators, Up: History Interaction + +Word Designators +---------------- + + A : separates the event specification from the word designator. It +can be omitted if the word designator begins with a ^, $, * or %. +Words are numbered from the beginning of the line, with the first word +being denoted by a 0 (zero). + +`0 (zero)' + The `0'th word. For many applications, this is the command word. + +`n' + The Nth word. + +`^' + The first argument; that is, word 1. + +`$' + The last argument. + +`%' + The word matched by the most recent `?string?' search. + +`x-y' + A range of words; `-Y' abbreviates `0-Y'. + +`*' + All of the words, except the `0'th. This is a synonym for `1-$'. + It is not an error to use * if there is just one word in the event; + the empty string is returned in that case. + +`x*' + Abbreviates `x-$' + +`x-' + Abbreviates `x-$' like `x*', but omits the last word. + + +File: history.info, Node: Modifiers, Prev: Word Designators, Up: History Interaction + +Modifiers +--------- + + After the optional word designator, you can add a sequence of one or +more of the following modifiers, each preceded by a :. + +`h' + Remove a trailing pathname component, leaving only the head. + +`r' + Remove a trailing suffix of the form `.'SUFFIX, leaving the + basename. + +`e' + Remove all but the trailing suffix. + +`t' + Remove all leading pathname components, leaving the tail. + +`p' + Print the new command but do not execute it. + +`s/old/new/' + Substitute NEW for the first occurrence of OLD in the event line. + Any delimiter may be used in place of /. The delimiter may be + quoted in OLD and NEW with a single backslash. If & appears in + NEW, it is replaced by OLD. A single backslash will quote the &. + The final delimiter is optional if it is the last character on the + input line. + +`&' + Repeat the previous substitution. + +`g' + Cause changes to be applied over the entire event line. Used in + conjunction with `s', as in `gs/old/new/', or with `&'. + + +File: history.info, Node: Programming with GNU History, Next: Concept Index, Prev: Using History Interactively, Up: Top + +Programming with GNU History +**************************** + + This chapter describes how to interface programs that you write with +the GNU History Library. It should be considered a technical guide. +For information on the interactive use of GNU History, *note Using +History Interactively::.. + +* Menu: + +* Introduction to History:: What is the GNU History library for? +* History Storage:: How information is stored. +* History Functions:: Functions that you can use. +* History Variables:: Variables that control behaviour. +* History Programming Example:: Example of using the GNU History Library. + + +File: history.info, Node: Introduction to History, Next: History Storage, Up: Programming with GNU History + +Introduction to History +======================= + + Many programs read input from the user a line at a time. The GNU +History library is able to keep track of those lines, associate +arbitrary data with each line, and utilize information from previous +lines in composing new ones. + + The programmer using the History library has available functions for +remembering lines on a history list, associating arbitrary data with a +line, removing lines from the list, searching through the list for a +line containing an arbitrary text string, and referencing any line in +the list directly. In addition, a history "expansion" function is +available which provides for a consistent user interface across +different programs. + + The user using programs written with the History library has the +benefit of a consistent user interface with a set of well-known +commands for manipulating the text of previous lines and using that text +in new commands. The basic history manipulation commands are similar to +the history substitution provided by `csh'. + + If the programmer desires, he can use the Readline library, which +includes some history manipulation by default, and has the added +advantage of command line editing. + + +File: history.info, Node: History Storage, Next: History Functions, Prev: Introduction to History, Up: Programming with GNU History + +History Storage +=============== + + The history list is an array of history entries. A history entry is +declared as follows: + + typedef struct _hist_entry { + char *line; + char *data; + } HIST_ENTRY; + + The history list itself might therefore be declared as + + HIST_ENTRY **the_history_list; + + The state of the History library is encapsulated into a single +structure: + + /* A structure used to pass the current state of the history stuff around. */ + typedef struct _hist_state { + HIST_ENTRY **entries; /* Pointer to the entries themselves. */ + int offset; /* The location pointer within this array. */ + int length; /* Number of elements within this array. */ + int size; /* Number of slots allocated to this array. */ + int flags; + } HISTORY_STATE; + + If the flags member includes `HS_STIFLED', the history has been +stifled. + + +File: history.info, Node: History Functions, Next: History Variables, Prev: History Storage, Up: Programming with GNU History + +History Functions +================= + + This section describes the calling sequence for the various functions +present in GNU History. + +* Menu: + +* Initializing History and State Management:: Functions to call when you + want to use history in a + program. +* History List Management:: Functions used to manage the list + of history entries. +* Information About the History List:: Functions returning information about + the history list. +* Moving Around the History List:: Functions used to change the position + in the history list. +* Searching the History List:: Functions to search the history list + for entries containing a string. +* Managing the History File:: Functions that read and write a file + containing the history list. +* History Expansion:: Functions to perform csh-like history + expansion. + + +File: history.info, Node: Initializing History and State Management, Next: History List Management, Up: History Functions + +Initializing History and State Management +----------------------------------------- + + This section describes functions used to initialize and manage the +state of the History library when you want to use the history functions +in your program. + + - Function: void using_history () + Begin a session in which the history functions might be used. This + initializes the interactive variables. + + - Function: HISTORY_STATE * history_get_history_state () + Return a structure describing the current state of the input + history. + + - Function: void history_set_history_state (HISTORY_STATE *state) + Set the state of the history list according to STATE. + + +File: history.info, Node: History List Management, Next: Information About the History List, Prev: Initializing History and State Management, Up: History Functions + +History List Management +----------------------- + + These functions manage individual entries on the history list, or set +parameters managing the list itself. + + - Function: void add_history (char *string) + Place STRING at the end of the history list. The associated data + field (if any) is set to `NULL'. + + - Function: HIST_ENTRY * remove_history (int which) + Remove history entry at offset WHICH from the history. The + removed element is returned so you can free the line, data, and + containing structure. + + - Function: HIST_ENTRY * replace_history_entry (int which, char *line, + char *data) + Make the history entry at offset WHICH have LINE and DATA. This + returns the old entry so you can dispose of the data. In the case + of an invalid WHICH, a `NULL' pointer is returned. + + - Function: void stifle_history (int max) + Stifle the history list, remembering only the last MAX entries. + + - Function: int unstifle_history () + Stop stifling the history. This returns the previous amount the + history was stifled. The value is positive if the history was + stifled, negative if it wasn't. + + - Function: int history_is_stifled () + Returns non-zero if the history is stifled, zero if it is not. + + +File: history.info, Node: Information About the History List, Next: Moving Around the History List, Prev: History List Management, Up: History Functions + +Information About the History List +---------------------------------- + + These functions return information about the entire history list or +individual list entries. + + - Function: HIST_ENTRY ** history_list () + Return a `NULL' terminated array of `HIST_ENTRY' which is the + current input history. Element 0 of this list is the beginning of + time. If there is no history, return `NULL'. + + - Function: int where_history () + Returns the offset of the current history element. + + - Function: HIST_ENTRY * current_history () + Return the history entry at the current position, as determined by + `where_history ()'. If there is no entry there, return a `NULL' + pointer. + + - Function: HIST_ENTRY * history_get (int offset) + Return the history entry at position OFFSET, starting from + `history_base'. If there is no entry there, or if OFFSET is + greater than the history length, return a `NULL' pointer. + + - Function: int history_total_bytes () + Return the number of bytes that the primary history entries are + using. This function returns the sum of the lengths of all the + lines in the history. + + +File: history.info, Node: Moving Around the History List, Next: Searching the History List, Prev: Information About the History List, Up: History Functions + +Moving Around the History List +------------------------------ + + These functions allow the current index into the history list to be +set or changed. + + - Function: int history_set_pos (int pos) + Set the position in the history list to POS, an absolute index + into the list. + + - Function: HIST_ENTRY * previous_history () + Back up the current history offset to the previous history entry, + and return a pointer to that entry. If there is no previous + entry, return a `NULL' pointer. + + - Function: HIST_ENTRY * next_history () + Move the current history offset forward to the next history entry, + and return the a pointer to that entry. If there is no next + entry, return a `NULL' pointer. + + +File: history.info, Node: Searching the History List, Next: Managing the History File, Prev: Moving Around the History List, Up: History Functions + +Searching the History List +-------------------------- + + These functions allow searching of the history list for entries +containing a specific string. Searching may be performed both forward +and backward from the current history position. The search may be +"anchored", meaning that the string must match at the beginning of the +history entry. + + - Function: int history_search (char *string, int direction) + Search the history for STRING, starting at the current history + offset. If DIRECTION < 0, then the search is through previous + entries, else through subsequent. If STRING is found, then the + current history index is set to that history entry, and the value + returned is the offset in the line of the entry where STRING was + found. Otherwise, nothing is changed, and a -1 is returned. + + - Function: int history_search_prefix (char *string, int direction) + Search the history for STRING, starting at the current history + offset. The search is anchored: matching lines must begin with + STRING. If DIRECTION < 0, then the search is through previous + entries, else through subsequent. If STRING is found, then the + current history index is set to that entry, and the return value + is 0. Otherwise, nothing is changed, and a -1 is returned. + + - Function: int history_search_pos (char *string, int direction, int + pos) + Search for STRING in the history list, starting at POS, an + absolute index into the list. If DIRECTION is negative, the search + proceeds backward from POS, otherwise forward. Returns the + absolute index of the history element where STRING was found, or + -1 otherwise. + + +File: history.info, Node: Managing the History File, Next: History Expansion, Prev: Searching the History List, Up: History Functions + +Managing the History File +------------------------- + + The History library can read the history from and write it to a file. +This section documents the functions for managing a history file. + + - Function: int read_history (char *filename) + Add the contents of FILENAME to the history list, a line at a + time. If FILENAME is `NULL', then read from `~/.history'. + Returns 0 if successful, or errno if not. + + - Function: int read_history_range (char *filename, int from, int to) + Read a range of lines from FILENAME, adding them to the history + list. Start reading at line FROM and end at TO. If FROM is zero, + start at the beginning. If TO is less than FROM, then read until + the end of the file. If FILENAME is `NULL', then read from + `~/.history'. Returns 0 if successful, or `errno' if not. + + - Function: int write_history (char *filename) + Write the current history to FILENAME, overwriting FILENAME if + necessary. If FILENAME is `NULL', then write the history list to + `~/.history'. Values returned are as in `read_history ()'. + + - Function: int append_history (int nelements, char *filename) + Append the last NELEMENTS of the history list to FILENAME. + + - Function: int history_truncate_file (char *filename, int nlines) + Truncate the history file FILENAME, leaving only the last NLINES + lines. + + +File: history.info, Node: History Expansion, Prev: Managing the History File, Up: History Functions + +History Expansion +----------------- + + These functions implement `csh'-like history expansion. + + - Function: int history_expand (char *string, char **output) + Expand STRING, placing the result into OUTPUT, a pointer to a + string (*note History Interaction::.). Returns: + `0' + If no expansions took place (or, if the only change in the + text was the de-slashifying of the history expansion + character); + + `1' + if expansions did take place; + + `-1' + if there was an error in expansion; + + `2' + if the returned line should only be displayed, but not + executed, as with the `:p' modifier (*note Modifiers::.). + + If an error ocurred in expansion, then OUTPUT contains a + descriptive error message. + + - Function: char * history_arg_extract (int first, int last, char + *string) + Extract a string segment consisting of the FIRST through LAST + arguments present in STRING. Arguments are broken up as in Bash. + + - Function: char * get_history_event (char *string, int *cindex, int + qchar) + Returns the text of the history event beginning at STRING + + *CINDEX. *CINDEX is modified to point to after the event + specifier. At function entry, CINDEX points to the index into + STRING where the history event specification begins. QCHAR is a + character that is allowed to end the event specification in + addition to the "normal" terminating characters. + + - Function: char ** history_tokenize (char *string) + Return an array of tokens parsed out of STRING, much as the shell + might. The tokens are split on white space and on the characters + `()<>;&|$', and shell quoting conventions are obeyed. + + +File: history.info, Node: History Variables, Next: History Programming Example, Prev: History Functions, Up: Programming with GNU History + +History Variables +================= + + This section describes the externally visible variables exported by +the GNU History Library. + + - Variable: int history_base + The logical offset of the first entry in the history list. + + - Variable: int history_length + The number of entries currently stored in the history list. + + - Variable: int max_input_history + The maximum number of history entries. This must be changed using + `stifle_history ()'. + + - Variable: char history_expansion_char + The character that starts a history event. The default is `!'. + + - Variable: char history_subst_char + The character that invokes word substitution if found at the start + of a line. The default is `^'. + + - Variable: char history_comment_char + During tokenization, if this character is seen as the first + character of a word, then it and all subsequent characters up to a + newline are ignored, suppressing history expansion for the + remainder of the line. This is disabled by default. + + - Variable: char * history_no_expand_chars + The list of characters which inhibit history expansion if found + immediately following HISTORY_EXPANSION_CHAR. The default is + whitespace and `='. + + +File: history.info, Node: History Programming Example, Prev: History Variables, Up: Programming with GNU History + +History Programming Example +=========================== + + The following program demonstrates simple use of the GNU History +Library. + + main () + { + char line[1024], *t; + int len, done = 0; + + line[0] = 0; + + using_history (); + while (!done) + { + printf ("history$ "); + fflush (stdout); + t = fgets (line, sizeof (line) - 1, stdin); + if (t && *t) + { + len = strlen (t); + if (t[len - 1] == '\n') + t[len - 1] = '\0'; + } + + if (!t) + strcpy (line, "quit"); + + if (line[0]) + { + char *expansion; + int result; + + result = history_expand (line, &expansion); + if (result) + fprintf (stderr, "%s\n", expansion); + + if (result < 0 || result == 2) + { + free (expansion); + continue; + } + + add_history (expansion); + strncpy (line, expansion, sizeof (line) - 1); + free (expansion); + } + + if (strcmp (line, "quit") == 0) + done = 1; + else if (strcmp (line, "save") == 0) + write_history ("history_file"); + else if (strcmp (line, "read") == 0) + read_history ("history_file"); + else if (strcmp (line, "list") == 0) + { + register HIST_ENTRY **the_list; + register int i; + + the_list = history_list (); + if (the_list) + for (i = 0; the_list[i]; i++) + printf ("%d: %s\n", i + history_base, the_list[i]->line); + } + else if (strncmp (line, "delete", 6) == 0) + { + int which; + if ((sscanf (line + 6, "%d", &which)) == 1) + { + HIST_ENTRY *entry = remove_history (which); + if (!entry) + fprintf (stderr, "No such entry %d\n", which); + else + { + free (entry->line); + free (entry); + } + } + else + { + fprintf (stderr, "non-numeric arg given to `delete'\n"); + } + } + } + } + + +File: history.info, Node: Concept Index, Next: Function and Variable Index, Prev: Programming with GNU History, Up: Top + +Concept Index +************* + +* Menu: + +* anchored search: Searching the History List. +* event designators: Event Designators. +* expansion: History Interaction. +* history events: Event Designators. +* History Searching: Searching the History List. + + +File: history.info, Node: Function and Variable Index, Prev: Concept Index, Up: Top + +Function and Variable Index +*************************** + +* Menu: + +* add_history: History List Management. +* append_history: Managing the History File. +* current_history: Information About the History List. +* get_history_event: History Expansion. +* history_arg_extract: History Expansion. +* history_base: History Variables. +* history_comment_char: History Variables. +* history_expand: History Expansion. +* history_expansion_char: History Variables. +* history_get: Information About the History List. +* history_get_history_state: Initializing History and State Management. +* history_is_stifled: History List Management. +* history_length: History Variables. +* history_list: Information About the History List. +* history_no_expand_chars: History Variables. +* history_search: Searching the History List. +* history_search_pos: Searching the History List. +* history_search_prefix: Searching the History List. +* history_set_history_state: Initializing History and State Management. +* history_set_pos: Moving Around the History List. +* history_subst_char: History Variables. +* history_tokenize: History Expansion. +* history_total_bytes: Information About the History List. +* history_truncate_file: Managing the History File. +* max_input_history: History Variables. +* next_history: Moving Around the History List. +* previous_history: Moving Around the History List. +* read_history: Managing the History File. +* read_history_range: Managing the History File. +* remove_history: History List Management. +* replace_history_entry: History List Management. +* stifle_history: History List Management. +* unstifle_history: History List Management. +* using_history: Initializing History and State Management. +* where_history: Information About the History List. +* write_history: Managing the History File. + + + +Tag Table: +Node: Top975 +Node: Using History Interactively1569 +Node: History Interaction2077 +Node: Event Designators3122 +Node: Word Designators3952 +Node: Modifiers4936 +Node: Programming with GNU History6065 +Node: Introduction to History6791 +Node: History Storage8112 +Node: History Functions9205 +Node: Initializing History and State Management10176 +Node: History List Management10968 +Node: Information About the History List12396 +Node: Moving Around the History List13702 +Node: Searching the History List14587 +Node: Managing the History File16419 +Node: History Expansion17925 +Node: History Variables19769 +Node: History Programming Example21138 +Node: Concept Index23742 +Node: Function and Variable Index24223 + +End Tag Table diff --git a/doc/history.ps b/doc/history.ps new file mode 100644 index 0000000..839598f --- /dev/null +++ b/doc/history.ps @@ -0,0 +1,2037 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.490s Copyright 1986, 1992 Radical Eye Software +%%Title: history.dvi +%%Pages: 22 1 +%%BoundingBox: 0 0 612 792 +%%EndComments +%DVIPSCommandLine: dvips -D 300 -o history.ps history.dvi +%%BeginProcSet: tex.pro +%! +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N /X{S N} +B /TR{translate}N /isls false N /vsize 11 72 mul N /@rigin{isls{[0 -1 1 0 0 0] +concat}if 72 Resolution div 72 VResolution div neg scale isls{Resolution hsize +-72 div mul 0 TR}if Resolution VResolution vsize -72 div 1 add mul TR matrix +currentmatrix dup dup 4 get round 4 exch put dup dup 5 get round 5 exch put +setmatrix}N /@landscape{/isls true N}B /@manualfeed{statusdict /manualfeed +true put}B /@copies{/#copies X}B /FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N +/IE 0 N /ctr 0 N /df-tail{/nn 8 dict N nn begin /FontType 3 N /FontMatrix +fntrx N /FontBBox FBB N string /base X array /BitMaps X /BuildChar{ +CharBuilder}N /Encoding IE N end dup{/foo setfont}2 array copy cvx N load 0 nn +put /ctr 0 N[}B /df{/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 +0 sf neg 0 0]N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data +dup length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{128 +ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub get 127 +sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data dup type +/stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N /rc 0 N /gp 0 N +/cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup /base get 2 index get +S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx 0 ch-xoff ch-yoff ch-height +sub ch-xoff ch-width add ch-yoff setcachedevice ch-width ch-height true[1 0 0 +-1 -.1 ch-xoff sub ch-yoff .1 add]{ch-image}imagemask restore}B /D{/cc X dup +type /stringtype ne{]}if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 +ne{dup dup length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N} +B /I{cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul add +.99 lt{/FV}{/RV}ifelse load def pop}N /eop{SI restore showpage userdict +/eop-hook known{eop-hook}if}N /@start{userdict /start-hook known{start-hook} +if /VResolution X /Resolution X 1000 div /DVImag X /IE 256 array N 0 1 255{IE +S 1 string dup 0 3 index put cvn put}for 65781.76 div /vsize X 65781.76 div +/hsize X}N /p{show}N /RMat[1 0 0 -1 0 0]N /BDot 260 string N /rulex 0 N /ruley +0 N /v{/ruley X /rulex X V}B /V{}B /RV statusdict begin /product where{pop +product dup length 7 ge{0 7 getinterval dup(Display)eq exch 0 4 getinterval +(NeXT)eq or}{pop false}ifelse}{false}ifelse end{{gsave TR -.1 -.1 TR 1 1 scale +rulex ruley false RMat{BDot}imagemask grestore}}{{gsave TR -.1 -.1 TR rulex +ruley scale 1 1 false RMat{BDot}imagemask grestore}}ifelse B /FV{gsave +transform round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail{dup +/delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M}B /d{-3 M} +B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{4 M}B /w{0 +rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{p 1 w}B /r{p 2 w} +B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p a}B /bos{/SS save N}B +/eos{SS restore}B end +%%EndProcSet +TeXDict begin 40258431 52099146 1000 300 300 @start /Fa 1 59 +df<70F8F8F87005057C840D>58 D E /Fb 1 59 df<78FCFCFCFC7806067B8510>58 +D E /Fc 24 123 df<1FC0007FF000707800201800001C00001C0007FC001FFC003C1C00701C00 +E01C00E01C00E01C00707C003FFF800F8F8011107E8F14>97 DI<03F80FFC1C1C380870006000E000E0 +00E000E00060007000380E1C1E0FFC03F00F107E8F14>I<007E00007E00000E00000E00000E00 +000E00000E0007CE000FFE001C3E00301E00700E00E00E00E00E00E00E00E00E00E00E00E00E00 +700E00301E00383E001FEFC007CFC012177F9614>I<07E00FF01C38301C700CE00EE00EFFFEFF +FEE00060007000380E1C1E0FFC03F00F107E8F14>I<007C00FE01CE03840380038003807FFEFF +FE0380038003800380038003800380038003800380038003807FFC7FFC0F177F9614>I<07CF00 +1FFF80383B80301800701C00701C00701C003018003838003FF00037C0007000007000003FF800 +1FFC003FFE00700F00E00380E00380E00380E003807007003C1E001FFC0007F00011197F8F14> +II<03 +0007800780030000000000000000007F807F800380038003800380038003800380038003800380 +03800380FFFCFFFC0E187D9714>I107 DIII<07C01FF03C78701C701CE00EE00EE00EE0 +0EE00EE00E701C783C3C781FF007C00F107E8F14>II +114 D<0FD83FF86038C038C038F0007F803FF007F8001C6006E006F006F81CFFF8CFE00F107E8F +14>I<030007000700070007007FFCFFFC07000700070007000700070007000700070E070E070E +070C03FC00F00F157F9414>IIII<7E3F007E3F001E38000E780007700007E0 +0003E00001C00003C00003E0000770000E78000E38001C1C00FE3F80FE3F8011107F8F14>II< +3FFF7FFF700E701C7038007000E001C0038007000E001C0738077007FFFFFFFF10107F8F14>I +E /Fd 1 59 df<60F0F06004047D830B>58 D E /Fe 25 122 df<078018603030303060186018 +E01CE01CE01CE01CE01CE01CE01CE01CE01CE01CE01CE01C6018601870383030186007800E187E +9713>48 D<03000700FF0007000700070007000700070007000700070007000700070007000700 +070007000700070007000700FFF00C187D9713>I<0F80106020304038803CC01CE01C401C003C +003800380070006000C001800100020004040804100430083FF87FF8FFF80E187E9713>I<01E0 +06100C1818383038300070006000E000E7C0E860F030F018E018E01CE01CE01C601C601C701830 +183030186007C00E187E9713>54 D<40007FFE7FFC7FFC40088010801080200040004000800180 +01800100030003000300030007000700070007000700070002000F197E9813>I<078018603030 +201860186018601870103C303E600F8007C019F030F86038401CC00CC00CC00CC00C6008201018 +600FC00E187E9713>I<07801860303070306018E018E018E01CE01CE01C601C603C303C185C0F +9C001C00180018003870307060604021801F000E187E9713>I72 +D<0FC21836200E6006C006C002C002C002E00070007E003FE01FF807FC003E000E000700038003 +80038003C002C006E004D81887E0101A7E9915>83 D<3F8070C070E020700070007007F01C7030 +707070E070E071E071E0F171FB1E3C10107E8F13>97 D<07F80C1C381C30087000E000E000E000 +E000E000E0007000300438080C1807E00E107F8F11>99 D<007E00000E00000E00000E00000E00 +000E00000E00000E00000E00000E0003CE000C3E00380E00300E00700E00E00E00E00E00E00E00 +E00E00E00E00E00E00600E00700E00381E001C2E0007CFC0121A7F9915>I<07C01C3030187018 +600CE00CFFFCE000E000E000E0006000300438080C1807E00E107F8F11>I<0FCE187330307038 +703870387038303018602FC02000600070003FF03FFC1FFE600FC003C003C003C0036006381C07 +E010187F8F13>103 DI<18003C003C001800000000000000000000000000FC00 +1C001C001C001C001C001C001C001C001C001C001C001C001C001C00FF80091A80990A>I110 D<07E01C38300C700E6006E007E007E007E007E007E00760 +06700E381C1C3807E010107F8F13>II114 D<1F2060E04020C020C020F0007F003FC01FE000F0807080 +30C030C020F0408F800C107F8F0F>I<0400040004000C000C001C003C00FFC01C001C001C001C +001C001C001C001C001C201C201C201C201C200E4003800B177F960F>I118 D120 DI E /Ff 2 42 +df<007000E001C00380078007000E001E001E003C003C003C0078007800780078007000F000F0 +00F000F000F000F000F000F000F000F000F000F000700078007800780078003C003C003C001E00 +1E000E0007000780038001C000E000700C2E7EA112>40 DI E /Fg 25 123 df<0007F800007FFC0001FC0E0003F01F0007E03F000FC03F000F +C03F000FC03F000FC01E000FC00C000FC000000FC000000FC0FF80FFFFFF80FFFFFF800FC01F80 +0FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F +800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F807FF8FFF07FF8FFF01C23 +7FA220>12 D<000FFF80007FFF8001FC1F8003F03F8007E03F800FC03F800FC01F800FC01F800F +C01F800FC01F800FC01F800FC01F800FC01F80FFFFFF80FFFFFF800FC01F800FC01F800FC01F80 +0FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F +800FC01F800FC01F800FC01F800FC01F800FC01F807FF8FFF07FF8FFF01C237FA220>I<07FE00 +001FFF80003F07E0003F03F0003F01F0003F01F8001E01F8000001F8000001F800003FF80003FD +F8001F81F8003E01F8007C01F800F801F800F801F800F801F800F801F8007C02F8007E0CF8001F +F87F8007E03F8019167E951C>97 DI<00FF8007FFE00F83F01F03F03E03F07E03F07C01E07C0000FC0000FC0000FC0000 +FC0000FC0000FC00007C00007E00007E00003F00301F00600FC0E007FF8000FE0014167E9519> +I<0001FF000001FF0000003F0000003F0000003F0000003F0000003F0000003F0000003F000000 +3F0000003F0000003F0000003F0000FE3F0007FFBF000FC1FF001F007F003E003F007E003F007C +003F007C003F00FC003F00FC003F00FC003F00FC003F00FC003F00FC003F00FC003F007C003F00 +7E003F003E003F001F007F000F81FF0007FF3FE001FC3FE01B237EA220>I<00FE0007FF800F83 +C01F01E03E00F07E00F07C00F87C0078FC0078FFFFF8FFFFF8FC0000FC0000FC00007C00007C00 +003E00183E00181F00300F80E003FFC000FF0015167E951A>I<00FE0F8003FF9FC00F83E3C01F +01F3C01E00F0003E00F8003E00F8003E00F8003E00F8003E00F8001E00F0001F01F0000F83E000 +0BFF800008FE000018000000180000001C0000001FFFE0001FFFFC000FFFFF0007FFFF001FFFFF +807C001FC078000FC0F80007C0F80007C0F80007C07C000F803E001F001F807E000FFFFC0001FF +E0001A217F951D>103 DI<1E003F007F807F807F807F803F001E00000000000000000000000000FF80FF801F801F801F +801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F80FFF0FFF00C247EA3 +0F>I107 +DI< +FF03F803F800FF0FFE0FFE001F183F183F001F201F201F001F401FC01F801F401FC01F801F801F +801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F80 +1F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F +801F80FFF0FFF0FFF0FFF0FFF0FFF02C167D9531>II< +00FF0007FFE00F81F01F00F83E007C7C003E7C003E7C003EFC003FFC003FFC003FFC003FFC003F +FC003FFC003F7C003E7E007E3E007C1F00F80F81F007FFE000FF0018167E951D>II114 D<07F9801FFF80380780700380F00180F00180F80000FF0000FFF8007FFE +003FFF001FFF8007FF80003FC0C007C0C003C0E003C0E003C0F00380FC0F00EFFE00C3F8001216 +7E9517>I<00C00000C00000C00000C00001C00001C00003C00007C0000FC0001FC000FFFF00FF +FF000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC1800F +C1800FC1800FC1800FC18007C18007E30003FE0000FC0011207F9F16>IIIIII<7FFFE07FFFE0780FC0701FC0601F80E03F00 +C07F00C07E00C0FC0001FC0001F80003F00007F03007E0300FC0301FC0701F80703F00607F00E0 +7E03E0FFFFE0FFFFE014167E9519>I E /Fh 22 119 df<00E00000E00000E00000E00040E040 +F0E1E0F8E3E07EEFC01FFF0007FC0003F80007FC001FFF007EEFC0F8E3E0F0E1E040E04000E000 +00E00000E00000E00013157D991A>42 D<003800007C00007C00006C0000EE0000EE0000EE0000 +EE0000C60001C70001C70001C70001C7000383800383800383800383800783C00701C007FFC007 +FFC007FFC00E00E00E00E00E00E00E00E01C00707F83FCFF83FE7F83FC171E7F9D1A>65 +D<7FFFFCFFFFFC7FFFFC0E001C0E001C0E001C0E001C0E001C0E00000E00000E07000E07000E07 +000FFF000FFF000FFF000E07000E07000E07000E00000E00000E00000E000E0E000E0E000E0E00 +0E0E000E7FFFFEFFFFFE7FFFFE171E7F9D1A>69 D +72 DI78 D<0FFE003FFF807FFFC07C07C07001C0F001E0E000E0E000E0E000E0E000E0E000E0E000E0 +E000E0E000E0E000E0E000E0E000E0E000E0E000E0E000E0E000E0E000E0E000E0F001E0F001E0 +7001C07C07C07FFFC03FFF800FFE00131E7D9D1A>I82 D<03F1C00FFDC03FFFC07C0FC07003C0E003C0E001C0E001C0E001C0E00000700000780000 +3F00001FF00007FE0000FF00000F800003C00001C00000E00000E06000E0E000E0E000E0E001C0 +F001C0FC0780FFFF80EFFE00E3F800131E7D9D1A>I<7FFFFEFFFFFEFFFFFEE0380EE0380EE038 +0EE0380EE0380E0038000038000038000038000038000038000038000038000038000038000038 +0000380000380000380000380000380000380000380000380003FF8007FFC003FF80171E7F9D1A +>I89 D<7FFFC0FFFFE0FFFFE07FFFC013047D7E1A +>95 D<1FF0003FFC007FFE00780F00300700000380000380007F8007FF801FFF803F8380780380 +700380E00380E00380E00380700780780F803FFFFC1FFDFC07F0FC16157D941A>97 +D<00FF8003FFC00FFFE01F01E03C00C0780000700000700000E00000E00000E00000E00000E000 +007000007000007800703C00701F01F00FFFE003FFC000FE0014157D941A>99 +D<001FC0001FC0001FC00001C00001C00001C00001C00001C00001C001F1C007FDC00FFFC01E0F +C03C07C07803C07001C0E001C0E001C0E001C0E001C0E001C0E001C0E001C07003C07003C03807 +C03E0FC01FFFFC07FDFC01F1FC161E7E9D1A>I +104 D<01C00003E00003E00003E00001C0000000000000000000000000000000007FE000FFE000 +7FE00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E000 +00E00000E00000E000FFFFC0FFFFC0FFFFC0121F7C9E1A>I110 D<01F00007FC001FFF003E0F803C07807803C07001 +C0E000E0E000E0E000E0E000E0E000E0E000E0F001E07001C07803C03C07803E0F801FFF0007FC +0001F00013157D941A>I114 D<00C00001C00001C00001C00001C00001C00001C0007FFFE0FFFFE0FFFFE001C00001 +C00001C00001C00001C00001C00001C00001C00001C00001C00001C07001C07001C07001C07000 +E0E000FFE0007FC0001F00141C7F9B1A>116 D<7FC7FCFFC7FE7FC7FC0E00E00E00E00F01E007 +01C00701C00783C003838003838003838001C70001C70001C70000EE0000EE0000EE00007C0000 +7C0000380017157F941A>118 D E /Fi 41 123 df<0003FC00003FFE00007E070001F80F8003 +F01F8003E01F8007E01F8007E01F8007E01F8007E0060007E0000007E0000007E0000007E0FFC0 +FFFFFFC0FFFFFFC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00F +C007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC007E0 +0FC007E00FC007E00FC07FFC7FFC7FFC7FFC1E267FA522>12 D<3C7EFFFFFFFF7E3C08087C8711 +>46 D<001C00003C0000FC00FFFC00FFFC0000FC0000FC0000FC0000FC0000FC0000FC0000FC00 +00FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC00 +00FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC007FFFFC7FFFFC16237CA21F>49 +D<01FF0007FFC01E07F03803F86001FC7C00FEFE00FEFE00FFFE007FFE007F7C007F3800FF0000 +FF0000FE0000FE0001FC0001F80003F00007E0000780000F00001E00003C0000700000E00301C0 +030380070700060600060FFFFE1FFFFE3FFFFE7FFFFCFFFFFCFFFFFC18237DA21F>I<01FF0007 +FFE01E03F03801F83C01FC7E00FE7E00FE7E00FE3E00FE1C01FE0001FC0001FC0003F80007F000 +0FC001FF0001FF000007E00001F00001F80000FC0000FE0000FF0000FF1000FF7C00FFFE00FFFE +00FFFE00FEFE00FE7C01FC7001F83E07F00FFFC001FF0018237DA21F>I<000038000000780000 +0078000000F8000001F8000003F8000007F8000006F800000CF800001CF8000038F8000030F800 +0060F80000E0F80001C0F8000180F8000300F8000700F8000E00F8001C00F8001800F8003000F8 +007000F800E000F800FFFFFFC0FFFFFFC00001F8000001F8000001F8000001F8000001F8000001 +F8000001F800007FFFC0007FFFC01A237EA21F>I<18000C1F007C1FFFF81FFFF01FFFE01FFFC0 +1FFF801FFE0018000018000018000018000018000018FF001BFFE01F01F01C00F80800FC00007E +00007E00007E00007F00007F78007FFC007FFC007FFC007FFC007EF8007E6000FC7000FC3801F8 +1E07E007FFC001FE0018237DA21F>I<001FC0007FF001F83803E00C07803E0F807E1F007E3F00 +7E3F007E7E003C7E00007E00007E0000FE3FC0FE7FF0FE80F8FF80FCFF007CFF007EFE007EFE00 +7FFE007FFE007FFE007F7E007F7E007F7E007F7E007F3E007E3F007E1F007C0F80F807C1F003FF +C0007F0018237DA21F>I<300000003C0000003FFFFFC03FFFFFC03FFFFF807FFFFF007FFFFE00 +7FFFFC006000180060001800E0003000C0006000C000C000000180000001800000030000000700 +0000060000000E0000001E0000001E0000001E0000003C0000003C0000007C0000007C0000007C +0000007C000000FC000000FC000000FC000000FC000000FC000000FC000000FC00000078000000 +3000001A257DA41F>I<00001C00000000001C00000000003E00000000003E00000000003E0000 +0000007F00000000007F0000000000FF8000000000FF8000000000FF80000000019FC000000001 +9FC0000000031FE0000000030FE0000000030FE00000000607F00000000607F00000000C07F800 +00000C03F80000001C03FC0000001801FC0000001801FC0000003001FE0000003000FE0000007F +FFFF0000007FFFFF00000060007F000000C0007F800000C0003F800001C0003FC0000180001FC0 +000180001FC0000300000FE0000300000FE0000780000FF000FFF801FFFF80FFF801FFFF802925 +7EA42E>65 D +68 DI< +FFFFFFFE00FFFFFFFE0003F800FE0003F8001F0003F8000F0003F800070003F800070003F80003 +0003F800030003F800030003F800018003F806018003F806018003F806000003F806000003F80E +000003F81E000003FFFE000003FFFE000003F81E000003F80E000003F806000003F806000003F8 +06000003F806000003F800000003F800000003F800000003F800000003F800000003F800000003 +F800000003F800000003F800000003F8000000FFFFF00000FFFFF0000021257EA427>I72 +DI +76 DI<00FF0080 +07FFE3800F80F7801E001F803C000F807800078078000380F8000380F8000180F8000180FC0001 +80FC000000FF0000007FE000007FFF00003FFFE0003FFFF8001FFFFE0007FFFF0003FFFF80007F +FF800003FFC000003FC000000FE0000007E0000007E0C00003E0C00003E0C00003E0C00003C0E0 +0003C0F00007C0F8000780FC000F00FFC03E00E3FFF800803FE0001B257DA422>83 +D87 +D<07FF00001FFFC0003E03E0003F01F0003F01F8003F00FC001E00FC000000FC000000FC000000 +FC00003FFC0003FCFC000FC0FC003F00FC007E00FC007E00FC00FC00FC00FC00FC00FC00FC00FC +017C007E017C003F067C001FFC3FE007F01FE01B187E971E>97 DI<007FE003FFF807C07C +1F80FC1F00FC3F00FC7E00787E0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000 +7E00007F00003F000C1F800C1FC01807E07003FFE0007F0016187E971B>I<0001FF800001FF80 +00001F8000001F8000001F8000001F8000001F8000001F8000001F8000001F8000001F8000001F +8000001F8000001F80007F1F8003FFDF8007E0FF801F803F803F001F803F001F807E001F807E00 +1F80FE001F80FE001F80FE001F80FE001F80FE001F80FE001F80FE001F80FE001F807E001F807E +001F803F001F803F003F801F807F800FC0FF8003FF9FF800FE1FF81D267EA522>I<007F0003FF +C007C1F00F80F81F00F83F007C7E007C7E007EFE007EFE007EFFFFFEFFFFFEFE0000FE0000FE00 +007E00007E00007E00063F00061F000C0F801807E07003FFE0007F8017187E971C>I<000FC000 +7FF000F8F001F1F803F1F803E1F807E0F007E00007E00007E00007E00007E00007E00007E000FF +FF00FFFF0007E00007E00007E00007E00007E00007E00007E00007E00007E00007E00007E00007 +E00007E00007E00007E00007E00007E00007E00007E00007E0007FFF007FFF0015267EA513>I< +01FF07C007FFDFE00F83F1E01F01F1E03E00F8007E00FC007E00FC007E00FC007E00FC007E00FC +007E00FC003E00F8001F01F0000F83E0000FFFC00011FF00003000000030000000380000003C00 +00003FFFE0001FFFFC001FFFFE000FFFFF001FFFFF803C003F8078000FC0F80007C0F80007C0F8 +0007C0F80007C07C000F803E001F001F807E0007FFF80000FFC0001B247E971F>II<0F00 +1F803FC03FC03FC03FC01F800F000000000000000000000000000000FFC0FFC00FC00FC00FC00F +C00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC0FFF8FFF80D27 +7EA611>I108 DII<007F800003FFF0 +0007C0F8001F807E003F003F003F003F007E001F807E001F80FE001FC0FE001FC0FE001FC0FE00 +1FC0FE001FC0FE001FC0FE001FC0FE001FC07E001F807E001F803F003F003F003F001F807E000F +C0FC0003FFF000007F80001A187E971F>II114 D<07F9801FFF803C0F80700380F00180F00180F00180FC0000FF8000 +7FFC007FFE003FFF800FFFC003FFC0001FE00003E0C001E0C001E0E001E0E001C0F003C0FC0780 +EFFF00C3FC0013187E9718>I<00600000600000600000600000E00000E00001E00001E00003E0 +0007E0001FE000FFFFC0FFFFC007E00007E00007E00007E00007E00007E00007E00007E00007E0 +0007E00007E00007E00007E06007E06007E06007E06007E06007E06003E0C003F0C001FF80007E +0013237FA218>III120 DI<3FFF +F83FFFF83E03F03807F0300FE0700FC0701F80603F80603F00607E0000FE0000FC0001F80003F8 +1803F01807E0180FE0180FC0381F80303F80707F00707E01F0FFFFF0FFFFF015187E971B>I +E /Fj 29 122 df<0003F07C001E0DC600380F0F00701E0F00E01E0E00E00C0001C01C0001C01C +0001C01C0001C01C0001C01C00038038007FFFFFC0038038000380380003803800038038000700 +700007007000070070000700700007007000070070000E00E0000E00E0000E00E0000E00E0000E +00E0000E00E0001C01C0001E01E000FF8FFE0020207E9F1B>11 D<0003E0001C1800381800703C +00E03C00E03801C00001C00001C00001C00001C0000380007FFFF0038070038070038070038070 +0700E00700E00700E00700E00700E00700E00E01C00E01C00E01C00E01C00E01C00E01C01C0380 +1E03C0FF0FF816207E9F19>I<0003F03F00001E09E08000380F80C000701F01E000E03E01E000 +E01E01C001C01C000001C01C000001C01C000001C01C000001C01C000003803800007FFFFFFF80 +038038038003803803800380380380038038038007007007000700700700070070070007007007 +00070070070007007007000E00E00E000E00E00E000E00E00E000E00E00E000E00E00E000E00E0 +0E001C01C01C001E01E01E00FF8FF8FFC023207E9F26>14 D<0020000060000060000060000060 +007061C03843800E4E0007580001E00001E00006B8001C9C00708700E083800180000180000180 +0001800001000012147AA117>42 D45 D<000C001C00FC0F3800380038 +00380038003800700070007000700070007000E000E000E000E000E000E001C001C001C001C001 +C001C0038003C0FFFE0F1E7C9D17>49 D<003F8000C1E00100F00200780400780400780F007C0F +807C0F807C0F00780600780000F80000F00001E00001C0000380000700000E00001C0000380000 +600000C0000180000300200600200800401000403FFFC07FFF80FFFF80161E7E9D17>I<07F800 +0C0C001E06001E07001C070000070000070000070000FF0007C7001E07003C0E00780E00F00E10 +F00E10F00E10F01E10F02E20784F401F878014147D9317>97 D<01FC07060E0F1C0F380E780070 +00F000F000F000F000E000E000E000E000F0027004300818300FC010147C9314>99 +D<0000700003F00000F00000700000700000E00000E00000E00000E00000E00000E00001C000F9 +C00305C00E03C01C03C03801C0780380700380F00380F00380F00380F00380E00700E00700E007 +00E00700E00700700F00301E00186F000F8FE014207C9F19>I<00F800070E000E07001C070038 +0380780380700380F00380F00380FFFF80F00000E00000E00000E00000E00000F0010070020030 +04001C180007E00011147D9314>I<0007800018C00031E00061E000E1C000C00001C00001C000 +01C00001C00001C0000380007FF800038000038000038000038000070000070000070000070000 +0700000700000E00000E00000E00000E00000E00000E00001C00001E0000FFE00013207E9F0E> +I<00000E003E1100E1A301C1C20381E00780E00701E00F01E00F01E00F01E00703C00703800787 +0004FC000800000800001800001C00000FFF000FFFC007FFE01800F0300030600030C00030C000 +30C000306000603000C01C070007FC00181F809417>I<00E00007E00001E00000E00000E00001 +C00001C00001C00001C00001C00001C000038000038F800390E003A0E003C0600380600780E007 +00E00700E00700E00700E00700E00E01C00E01C00E01C00E01C00E01C00E01C01C03801E03C0FF +CFF815207E9F19>I<01C003E003E003C0018000000000000000000000000003801F8007800380 +03800700070007000700070007000E000E000E000E000E000E001C001E00FF800B1F7F9E0C>I< +00E007E001E000E000E001C001C001C001C001C001C00380038003800380038003800700070007 +000700070007000E000E000E000E000E000E001C001E00FFC00B207F9F0C>108 +D<0387C07C001F9861860007A072070003C0340300038038030007807807000700700700070070 +07000700700700070070070007007007000E00E00E000E00E00E000E00E00E000E00E00E000E00 +E00E000E00E00E001C01C01C001E01E01E00FFCFFCFFC022147E9326>I<038F801F90E007A0E0 +03C0600380600780E00700E00700E00700E00700E00700E00E01C00E01C00E01C00E01C00E01C0 +0E01C01C03801E03C0FFCFF815147E9319>I<00FC000387000E01801C00C03800E03800E07000 +F0F000F0F000F0F000F0F000F0E001E0E001E0E001C0E003C0F00380700700380E001C1C0007E0 +0014147D9317>I<00E3E007EC3800F01C00E01E00E00E01C00E01C00F01C00F01C00F01C00F01 +C00F03801E03801E03801C03803C0380380380700740E00721C0071F000700000700000700000E +00000E00000E00000E00001E0000FFC000181D809319>I<00F040038CC00E04C01C03C03C03C0 +780380780380F00380F00380F00380F00380E00700E00700E00700F00700F00F00700F00301E00 +186E000F8E00000E00000E00000E00001C00001C00001C00001C00003C0001FF80121D7C9318> +I<038E001FB38007C78003C7800383000780000700000700000700000700000700000E00000E00 +000E00000E00000E00000E00001C00001E0000FFE00011147E9312>I<01F2060E080618061802 +380438001E001FE00FF003F8003C401C400C400C600C6018E010D0608FC00F147E9312>I<0080 +010001000100030007000F001E00FFF80E000E000E000E001C001C001C001C001C001C00380038 +203820382038203840384018800F000D1C7C9B12>I<1C0380FC1F803C07801C03801C03803807 +00380700380700380700380700380700700E00700E00700E00700E00701E00701E00703C00305E +001F9FC012147B9319>II< +FF9FE1FC3E0780701C0300601C0300401C0380401C0380800E0780800E0581000E0981000E09C2 +000E11C2000731C4000721C4000760C8000740C8000780F0000780F0000300E000030060000200 +40001E147C9321>I<1FF0FF03C07801C06001C04000E08000E180007300007600003C00003C00 +001C00002E00004E000087000107000203800603800C01C03E03E0FF07FC18147F9318>I<0FF8 +3F8001E00E0001C00C0001C0080000E0180000E0100000E0200000E0200000F040000070400000 +708000007080000071000000390000003A0000003E0000003C0000003800000018000000100000 +0010000000200000002000000040000070C00000F0800000F1000000E20000007C000000191D80 +9318>I E /Fk 36 122 df<0001C0000003C000000FC000007FC0001FFFC000FFFFC000FFBFC0 +00E03FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003F +C000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC00000 +3FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000 +003FC000003FC000003FC000003FC000003FC000003FC000003FC0007FFFFFE07FFFFFE07FFFFF +E01B2E7AAD28>49 D<003FE00001FFFE0007FFFF800F80FFC01E003FE038001FF07C000FF87E00 +07FCFF0007FCFF8007FEFF8007FEFF8003FEFF8003FE7F0003FE3E0007FE000007FE000007FC00 +0007FC00000FF800000FF800000FF000001FE000001FC000003F8000007F0000007E000000F800 +0001F0000003E0000007C000000F0000001E000E003C000E0038000E0070001E00E0001C01C000 +1C0300003C07FFFFFC0FFFFFFC1FFFFFFC3FFFFFFC7FFFFFF8FFFFFFF8FFFFFFF8FFFFFFF81F2E +7CAD28>I<0000007800000000000078000000000000FC000000000000FC000000000000FC0000 +00000001FE000000000001FE000000000003FF000000000003FF000000000007FF800000000007 +FF800000000007FF80000000000FFFC0000000000E7FC0000000001E7FE0000000001C3FE00000 +00001C3FE000000000383FF000000000381FF000000000781FF800000000700FF800000000700F +F800000000E00FFC00000000E007FC00000001E007FE00000001C003FE00000001C003FE000000 +038003FF000000038001FF000000078001FF800000070000FF800000070000FF8000000FFFFFFF +C000000FFFFFFFC000001FFFFFFFE000001C00003FE000003C00003FF000003800001FF0000038 +00001FF000007000001FF800007000000FF80000F000000FFC0000E0000007FC0000E0000007FC +0001C0000007FE0003E0000003FE00FFFF8001FFFFFCFFFF8001FFFFFCFFFF8001FFFFFC36317D +B03D>65 DI<000003FF80018000003FFFF003800001FFFFFC07800007FF003F0F80001FF800079F80 +003FC00001FF8000FF800000FF8001FE0000007F8003FC0000003F8007FC0000001F8007F80000 +000F800FF00000000F801FF000000007801FF000000007803FE000000007803FE000000003807F +E000000003807FE000000003807FC000000000007FC00000000000FFC00000000000FFC0000000 +0000FFC00000000000FFC00000000000FFC00000000000FFC00000000000FFC00000000000FFC0 +0000000000FFC000000000007FC000000000007FC000000000007FE000000000007FE000000003 +803FE000000003803FE000000003801FF000000003801FF000000007800FF0000000070007F800 +0000070007FC0000000E0003FC0000001E0001FE0000001C0000FF8000007800003FC00000F000 +001FF80003E0000007FF003F80000001FFFFFE000000003FFFF80000000003FF80000031317CB0 +3A>I70 +D<000003FF00030000007FFFF007000001FFFFFC0F000007FF007E1F00001FF0000FBF00007FC0 +0003FF0000FF800001FF0001FE0000007F0003FC0000007F0007FC0000003F000FF80000001F00 +0FF00000001F001FF00000000F001FF00000000F003FE000000007003FE000000007007FE00000 +0007007FE000000007007FC00000000000FFC00000000000FFC00000000000FFC00000000000FF +C00000000000FFC00000000000FFC00000000000FFC00000000000FFC00000000000FFC0000000 +0000FFC00000000000FFC00007FFFFFC7FC00007FFFFFC7FE00007FFFFFC7FE0000001FF003FE0 +000001FF003FE0000001FF001FF0000001FF001FF0000001FF000FF0000001FF000FF8000001FF +0007FC000001FF0003FC000001FF0001FE000001FF0000FF800001FF00007FC00003FF00001FF8 +00077F000007FF003E3F000001FFFFFC1F0000007FFFF00F00000003FF80030036317CB03F>I< +FFFFFF807FFFFFC0FFFFFF807FFFFFC0FFFFFF807FFFFFC000FF8000007FC00000FF8000007FC0 +0000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007F +C00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF800000 +7FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000 +007FC00000FF8000007FC00000FF8000007FC00000FFFFFFFFFFC00000FFFFFFFFFFC00000FFFF +FFFFFFC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF +8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000 +FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC000 +00FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC00000FF8000007FC0 +0000FF8000007FC00000FF8000007FC000FFFFFF807FFFFFC0FFFFFF807FFFFFC0FFFFFF807FFF +FFC03A317EB03F>II78 D80 D<7FFFFFFFFFFF007FFFFFFFFFFF007FFFFFFFFFFF007F +C00FF801FF007E000FF8003F007C000FF8001F0078000FF8000F0078000FF8000F0070000FF800 +0700F0000FF8000780F0000FF8000780F0000FF8000780E0000FF8000380E0000FF8000380E000 +0FF8000380E0000FF8000380E0000FF800038000000FF800000000000FF800000000000FF80000 +0000000FF800000000000FF800000000000FF800000000000FF800000000000FF800000000000F +F800000000000FF800000000000FF800000000000FF800000000000FF800000000000FF8000000 +00000FF800000000000FF800000000000FF800000000000FF800000000000FF800000000000FF8 +00000000000FF800000000000FF800000000000FF800000000000FF800000000000FF800000000 +000FF800000000000FF800000000000FF8000000007FFFFFFF0000007FFFFFFF0000007FFFFFFF +000031307DAF38>84 DII<00FFF0000003FFFE00000F803F80000FC00FE0001F +E007F0001FE007F0001FE003F8000FC003FC00078003FC00000003FC00000003FC00000003FC00 +000003FC000000FFFC00001FFFFC0000FFE3FC0003FC03FC000FF003FC001FC003FC003FC003FC +007F8003FC007F8003FC00FF0003FC00FF0003FC00FF0003FC00FF0007FC00FF0007FC007F800D +FC003FC019FE001FE070FFF007FFE07FF000FF803FF024207E9F27>97 D<01F8000000FFF80000 +00FFF8000000FFF80000000FF800000007F800000007F800000007F800000007F800000007F800 +000007F800000007F800000007F800000007F800000007F800000007F800000007F800000007F8 +00000007F83FE00007F8FFFC0007FBE07F0007FF001F8007FE000FC007FC000FE007F80007F007 +F80007F807F80007F807F80003FC07F80003FC07F80003FC07F80003FE07F80003FE07F80003FE +07F80003FE07F80003FE07F80003FE07F80003FE07F80003FE07F80003FC07F80003FC07F80003 +FC07F80007F807F80007F807F80007F007FC000FE007FE000FC007E7003F8007C3C0FE000780FF +F80007003FC00027327EB12D>I<000FFF00007FFFC001FC01F003F003F007E007F80FE007F81F +C007F83FC003F03FC001E07F8000007F8000007F800000FF800000FF800000FF800000FF800000 +FF800000FF800000FF800000FF8000007F8000007F8000007F8000003FC0001C3FC0001C1FC000 +380FE0003807E0007003F001E001FC07C0007FFF00000FF8001E207D9F24>I<0000000FC00000 +07FFC0000007FFC0000007FFC00000007FC00000003FC00000003FC00000003FC00000003FC000 +00003FC00000003FC00000003FC00000003FC00000003FC00000003FC00000003FC00000003FC0 +0000003FC00007F83FC0003FFF3FC000FE07BFC003F801FFC007E0007FC00FE0007FC01FC0003F +C03FC0003FC03FC0003FC07F80003FC07F80003FC07F80003FC0FF80003FC0FF80003FC0FF8000 +3FC0FF80003FC0FF80003FC0FF80003FC0FF80003FC0FF80003FC07F80003FC07F80003FC07F80 +003FC03FC0003FC03FC0003FC01FC0003FC00FE0007FC007E000FFC003F003FFE001FC0F3FFE00 +7FFE3FFE000FF03FFE27327DB12D>I<000FFC00007FFF8001FC0FC003F003E007E001F00FE001 +F81FC000FC3FC000FE3FC000FE7F80007E7F80007F7F80007FFF80007FFF80007FFFFFFFFFFFFF +FFFFFF800000FF800000FF800000FF8000007F8000007F8000007F8000003FC000071FC000071F +C0000E0FE0000E07F0001C03F8007800FE03E0003FFFC00007FE0020207E9F25>I<0001FE0000 +0FFF80001FC3C0007F07E000FE0FF001FE0FF001FC0FF003FC0FF003FC07E003FC018003FC0000 +03FC000003FC000003FC000003FC000003FC000003FC000003FC0000FFFFFC00FFFFFC00FFFFFC +0003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC +000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003 +FC000003FC000003FC000003FC000003FC000003FC000003FC00007FFFF0007FFFF0007FFFF000 +1C327EB119>I<001FF007C000FFFE3FE001F83F79F007E00FC3F00FE00FE1F00FC007E0E01FC0 +07F0001FC007F0003FC007F8003FC007F8003FC007F8003FC007F8003FC007F8001FC007F0001F +C007F0000FC007E0000FE00FE00007E00FC00003F83F000006FFFE00000E1FF000000E00000000 +1E000000001E000000001F000000001F800000001FFFFF80000FFFFFF0000FFFFFFC0007FFFFFE +0003FFFFFF0003FFFFFF800FFFFFFFC01F00007FC07E00001FE07C00000FE0FC000007E0FC0000 +07E0FC000007E0FC000007E07E00000FC03E00000F803F00001F800FC0007E0007F803FC0001FF +FFF000001FFF0000242F7E9F28>I<01F8000000FFF8000000FFF8000000FFF80000000FF80000 +0007F800000007F800000007F800000007F800000007F800000007F800000007F800000007F800 +000007F800000007F800000007F800000007F800000007F800000007F807F80007F83FFE0007F8 +783F0007F8C03F8007F9801FC007FB001FC007FE001FE007FC001FE007FC001FE007FC001FE007 +F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE0 +07F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001F +E007F8001FE007F8001FE007F8001FE0FFFFC3FFFFFFFFC3FFFFFFFFC3FFFF28327DB12D>I<03 +C00007E0000FF0001FF8001FF8001FF8001FF8000FF00007E00003C00000000000000000000000 +000000000000000000000000000000000001F800FFF800FFF800FFF8000FF80007F80007F80007 +F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007 +F80007F80007F80007F80007F80007F80007F80007F80007F800FFFF80FFFF80FFFF8011337DB2 +17>I<01F800FFF800FFF800FFF8000FF80007F80007F80007F80007F80007F80007F80007F800 +07F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F800 +07F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F800 +07F80007F80007F80007F80007F80007F80007F80007F80007F800FFFFC0FFFFC0FFFFC012327D +B117>108 D<03F007F8001FE000FFF03FFE00FFF800FFF0783F01E0FC00FFF0C03F8300FE000F +F1801FC6007F0007F3001FCC007F0007F6001FF8007F8007FC001FF0007F8007FC001FF0007F80 +07FC001FF0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F +8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE000 +7F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0 +007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001F +E0007F80FFFFC3FFFF0FFFFCFFFFC3FFFF0FFFFCFFFFC3FFFF0FFFFC3E207D9F43>I<03F007F8 +00FFF03FFE00FFF0783F00FFF0C03F800FF1801FC007F3001FC007F6001FE007FC001FE007FC00 +1FE007FC001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8 +001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007 +F8001FE007F8001FE007F8001FE007F8001FE007F8001FE0FFFFC3FFFFFFFFC3FFFFFFFFC3FFFF +28207D9F2D>I<0007FC0000007FFFC00001FC07F00003F001F80007E000FC000FC0007E001FC0 +007F003FC0007F803F80003F807F80003FC07F80003FC07F80003FC0FF80003FE0FF80003FE0FF +80003FE0FF80003FE0FF80003FE0FF80003FE0FF80003FE0FF80003FE07F80003FC07F80003FC0 +7F80003FC03FC0007F803FC0007F801FC0007F000FE000FE0007E000FC0003F803F80001FE0FF0 +00007FFFC0000007FC000023207E9F28>I<01F83FE000FFF8FFFC00FFFBE07F00FFFF003F8007 +FE001FC007FC000FE007F8000FF007F80007F807F80007F807F80007FC07F80003FC07F80003FC +07F80003FE07F80003FE07F80003FE07F80003FE07F80003FE07F80003FE07F80003FE07F80003 +FE07F80003FC07F80007FC07F80007FC07F80007F807F80007F807F8000FF007FC000FE007FE00 +1FC007FF003F8007FBC0FE0007F8FFF80007F83FC00007F800000007F800000007F800000007F8 +00000007F800000007F800000007F800000007F800000007F800000007F800000007F8000000FF +FFC00000FFFFC00000FFFFC00000272E7E9F2D>I<03F03F00FFF07FC0FFF1C3E0FFF187E00FF3 +0FF007F60FF007F60FF007FC07E007FC03C007FC000007FC000007F8000007F8000007F8000007 +F8000007F8000007F8000007F8000007F8000007F8000007F8000007F8000007F8000007F80000 +07F8000007F8000007F8000007F8000007F80000FFFFE000FFFFE000FFFFE0001C207E9F21> +114 D<01FF860007FFFE001F00FE003C003E0078001E0078000E00F8000E00F8000E00F8000E00 +FC000000FF800000FFFC00007FFFC0007FFFF0003FFFF8001FFFFC0007FFFE0001FFFF00003FFF +000000FF8000003F8060001F80E0000F80E0000F80F0000F80F0000F00F8000F00FC001E00FE00 +1C00FF807800F3FFF000C07F800019207D9F20>I<001C0000001C0000001C0000001C0000001C +0000003C0000003C0000003C0000007C0000007C000000FC000001FC000003FC000007FC00001F +FFFE00FFFFFE00FFFFFE0003FC000003FC000003FC000003FC000003FC000003FC000003FC0000 +03FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC03 +8003FC038003FC038003FC038003FC038003FC038003FC038001FC038001FC070000FE0700007F +0E00003FFC000007F000192E7FAD1F>I<01F80007E0FFF803FFE0FFF803FFE0FFF803FFE00FF8 +003FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007 +F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE0 +07F8001FE007F8001FE007F8001FE007F8001FE007F8003FE007F8003FE003F8007FE003F8007F +E001FC00DFF000FE039FFF007FFF1FFF000FFC1FFF28207D9F2D>II< +FFFF1FFFE07FF8FFFF1FFFE07FF8FFFF1FFFE07FF80FF000FE0007800FF800FE00078007F800FE +00070007F8007F00070003FC007F000E0003FC00FF800E0003FE00FF801E0001FE00FF801C0001 +FE01DFC01C0001FF01DFC03C0000FF03DFE0380000FF838FE07800007F838FE07000007F8707F0 +7000007FC707F0F000003FCF07F8E000003FCE03F8E000001FEE03F9C000001FFC01FDC000001F +FC01FFC000000FFC01FF8000000FF800FF80000007F800FF00000007F0007F00000007F0007F00 +000003F0007E00000003E0003E00000001E0003C00000001C0001C000035207E9F3A>I<7FFF80 +7FFC7FFF807FFC7FFF807FFC03FE000F0001FE001E0000FF003C0000FF807800007FC07800003F +E0F000001FE1E000000FF3C000000FFF80000007FF00000003FE00000001FE00000000FF000000 +00FF80000000FFC0000001FFC0000003DFE00000078FF00000078FF800000F07FC00001E03FC00 +003C01FE00007800FF0000F000FF8000E0007FC001E0003FC0FFFC01FFFFFFFC01FFFFFFFC01FF +FF28207F9F2B>II E /Fl 1 14 df<0001FE00000007FF8000001E01E000007800780000 +E0001C000180000600030000030006000001800C000000C00C000000C018000000603000000030 +30000000303000000030600000001860000000186000000018C00000000CC00000000CC0000000 +0CC00000000CC00000000CC00000000CC00000000CC00000000CC00000000C6000000018600000 +0018600000001830000000303000000030300000003018000000600C000000C00C000000C00600 +0001800300000300018000060000E0001C000078007800001E01E0000007FF80000001FE000026 +2B7DA02D>13 D E /Fm 46 122 df<3C007F00FF80FF80FFC0FFC0FFC07FC03EC000C000C00180 +018001800300030006000E001C00380030000A157B8813>44 D<1C007F007F00FF80FF80FF807F +007F001C0009097B8813>46 D<000E00001E00007E0007FE00FFFE00FFFE00F8FE0000FE0000FE +0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE +0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE +0000FE007FFFFE7FFFFE7FFFFE17277BA622>49 D<00FF800007FFF0000FFFFC001E03FE003800 +FF807C003F80FE003FC0FF001FC0FF001FE0FF000FE0FF000FE07E000FE03C001FE000001FE000 +001FC000001FC000003F8000003F0000007E000000FC000000F8000001F0000003E00000078000 +000F0000001E0000003C00E0007000E000E000E001C001C0038001C0060001C00FFFFFC01FFFFF +C03FFFFFC07FFFFFC0FFFFFF80FFFFFF80FFFFFF801B277DA622>I<007F800003FFF00007FFFC +000F80FE001F007F003F807F003F803F803F803F803F803F801F803F801F003F8000007F000000 +7F0000007E000000FC000001F8000007F00000FFC00000FFC0000001F80000007E0000003F0000 +003F8000001FC000001FC000001FE000001FE03C001FE07E001FE0FF001FE0FF001FE0FF001FC0 +FF003FC0FE003F807C007F003F00FE001FFFFC0007FFF00000FF80001B277DA622>I<00000E00 +00001E0000003E0000007E000000FE000000FE000001FE000003FE0000077E00000E7E00000E7E +00001C7E0000387E0000707E0000E07E0000E07E0001C07E0003807E0007007E000E007E000E00 +7E001C007E0038007E0070007E00E0007E00FFFFFFF8FFFFFFF8FFFFFFF80000FE000000FE0000 +00FE000000FE000000FE000000FE000000FE000000FE00007FFFF8007FFFF8007FFFF81D277EA6 +22>I<180003001F801F001FFFFE001FFFFC001FFFF8001FFFF0001FFFC0001FFF00001C000000 +1C0000001C0000001C0000001C0000001C0000001C0000001C7FC0001DFFF8001F80FC001E003F +0008003F0000001F8000001FC000001FC000001FE000001FE018001FE07C001FE0FE001FE0FE00 +1FE0FE001FE0FE001FC0FC001FC078003F8078003F803C007F001F01FE000FFFFC0003FFF00000 +FF80001B277DA622>I<380000003E0000003FFFFFF03FFFFFF03FFFFFF07FFFFFE07FFFFFC07F +FFFF807FFFFF0070000E0070000E0070001C00E0003800E0007000E000E0000001E0000001C000 +000380000007800000070000000F0000001F0000001E0000003E0000003E0000007E0000007C00 +00007C000000FC000000FC000000FC000000FC000001FC000001FC000001FC000001FC000001FC +000001FC000001FC000000F80000007000001C297CA822>55 D<00000780000000000780000000 +000FC0000000000FC0000000000FC0000000001FE0000000001FE0000000003FF0000000003FF0 +000000003FF00000000077F80000000077F800000000F7FC00000000E3FC00000000E3FC000000 +01C1FE00000001C1FE00000003C1FF0000000380FF0000000380FF00000007007F80000007007F +8000000F007FC000000E003FC000000E003FC000001C001FE000001C001FE000003FFFFFF00000 +3FFFFFF000003FFFFFF00000700007F80000700007F80000F00007FC0000E00003FC0000E00003 +FC0001C00001FE0001C00001FE0003C00001FF00FFFE003FFFFCFFFE003FFFFCFFFE003FFFFC2E +297EA833>65 DI<00007FE0030007FFFC07001FFFFF0F +007FF00F9F00FF0001FF01FC0000FF03F800007F07F000003F0FE000001F1FC000001F1FC00000 +0F3F8000000F3F800000077F800000077F800000077F00000000FF00000000FF00000000FF0000 +0000FF00000000FF00000000FF00000000FF00000000FF00000000FF000000007F000000007F80 +0000007F800000073F800000073F800000071FC00000071FC000000E0FE000000E07F000001C03 +F800003C01FC00007800FF0001F0007FF007C0001FFFFF800007FFFE0000007FF00028297CA831 +>I69 DI<0000 +7FE003000007FFFC0700001FFFFF0F00007FF00F9F0000FF0001FF0001FC0000FF0003F800007F +0007F000003F000FE000001F001FC000001F001FC000000F003F8000000F003F80000007007F80 +000007007F80000007007F0000000000FF0000000000FF0000000000FF0000000000FF00000000 +00FF0000000000FF0000000000FF0000000000FF0000000000FF0000FFFFF87F0000FFFFF87F80 +00FFFFF87F800000FF003F800000FF003F800000FF001FC00000FF001FC00000FF000FE00000FF +0007F00000FF0003F80000FF0001FC0000FF0000FF0001FF00007FF007FF00001FFFFF9F000007 +FFFE0F0000007FF003002D297CA835>III77 +DI80 +D82 D<00FF00C003FFE1C00FFFF9C01F80FFC03F00 +3FC03E000FC07C0007C07C0007C0FC0003C0FC0003C0FC0001C0FE0001C0FE0001C0FF000000FF +C000007FFC00007FFFE0003FFFF8001FFFFE001FFFFF0007FFFF8003FFFFC000FFFFC0000FFFE0 +00007FE000001FF000000FF0000007F0E00003F0E00003F0E00003F0E00003F0F00003E0F00003 +E0F80007E0FC0007C0FF000F80FFE01F80E3FFFF00E1FFFC00C01FF0001C297CA825>I85 DII<03FF80000FFFF0001F01FC003F80FE003F +807F003F803F003F803F801F003F8000003F8000003F8000003F8000003F80003FFF8001FC3F80 +0FE03F801F803F803F003F807E003F80FC003F80FC003F80FC003F80FC003F80FC005F807E00DF +803F839FFC1FFE0FFC03F803FC1E1B7E9A21>97 D +I<003FF00001FFFC0003F03E000FC07F001F807F003F007F003F007F007F003E007E0000007E00 +0000FE000000FE000000FE000000FE000000FE000000FE000000FE0000007E0000007E0000007F +0000003F0003803F8003801F8007000FE00E0003F83C0001FFF800003FC000191B7E9A1E>I<00 +007FF000007FF000007FF0000007F0000007F0000007F0000007F0000007F0000007F0000007F0 +000007F0000007F0000007F0000007F0000007F0003F87F001FFF7F007F03FF00FC00FF01F8007 +F03F0007F03F0007F07E0007F07E0007F07E0007F0FE0007F0FE0007F0FE0007F0FE0007F0FE00 +07F0FE0007F0FE0007F0FE0007F07E0007F07E0007F03F0007F03F0007F01F800FF00FC01FF007 +E07FFF01FFE7FF007F87FF202A7EA925>I<003FC00001FFF00003E07C000F803E001F801F001F +001F003F000F807E000F807E000FC07E000FC0FE0007C0FE0007C0FFFFFFC0FFFFFFC0FE000000 +FE000000FE0000007E0000007E0000007F0000003F0001C01F0001C00F80038007C0070003F01E +0000FFFC00003FE0001A1B7E9A1F>I<0007F8003FFC007E3E01FC7F03F87F03F07F07F07F07F0 +3E07F00007F00007F00007F00007F00007F00007F000FFFFC0FFFFC0FFFFC007F00007F00007F0 +0007F00007F00007F00007F00007F00007F00007F00007F00007F00007F00007F00007F00007F0 +0007F00007F00007F00007F00007F0007FFF807FFF807FFF80182A7EA915>I<007F80F001FFE3 +F807C0FE1C0F807C7C1F003E7C1F003E103F003F003F003F003F003F003F003F003F003F003F00 +3F001F003E001F003E000F807C0007C0F80005FFE0000C7F8000180000001C0000001C0000001E +0000001FFFF8001FFFFF000FFFFFC007FFFFE003FFFFF00FFFFFF03E0007F07C0001F8F80000F8 +F80000F8F80000F8F80000F87C0001F07C0001F03F0007E00FC01F8007FFFF00007FF0001E287E +9A22>II<07000F801FC03FE03FE03FE01FC00F80 +07000000000000000000000000000000FFE0FFE0FFE00FE00FE00FE00FE00FE00FE00FE00FE00F +E00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE0FFFEFFFEFFFE0F2B7EAA12>I108 DII<003FE00001FFFC0003F07E000FC01F801F800FC03F0007E03F00 +07E07E0003F07E0003F07E0003F0FE0003F8FE0003F8FE0003F8FE0003F8FE0003F8FE0003F8FE +0003F8FE0003F87E0003F07E0003F03F0007E03F0007E01F800FC00FC01F8007F07F0001FFFC00 +003FE0001D1B7E9A22>II114 D<03FE300FFFF03E03F0 +7800F07000F0F00070F00070F80070FE0000FFE0007FFF007FFFC03FFFE01FFFF007FFF800FFF8 +0007FC0000FCE0007CE0003CF0003CF00038F80038FC0070FF01E0E7FFC0C1FF00161B7E9A1B> +I<00700000700000700000700000F00000F00000F00001F00003F00003F00007F0001FFFE0FFFF +E0FFFFE007F00007F00007F00007F00007F00007F00007F00007F00007F00007F00007F00007F0 +0007F00007F07007F07007F07007F07007F07007F07007F07003F0E001F8C000FFC0003F001426 +7FA51A>II +IIII E /Fn 75 127 df<70F8F8F8F8F8F8F8F8F8F8F8 +F8F8F8F8F870000000000070F8F8F870051C779B18>33 D<4010E038F078E038E038E038E038E0 +38E038E038E038E038E03860300D0E7B9C18>I<030600078F00078F00078F00078F00078F0007 +8F007FFFC0FFFFE0FFFFE07FFFC00F1E000F1E000F1E000F1E000F1E000F1E007FFFC0FFFFE0FF +FFE07FFFC01E3C001E3C001E3C001E3C001E3C001E3C000C1800131C7E9B18>I<00C00001C000 +01C00001C00003F0000FFC003FFE007DCF0071C700E1C380E1C780E1C780E1C780F1C00079C000 +3DC0001FE0000FF80003FC0001DE0001CF0001C70061C380F1C380F1C380E1C380E1C70071C700 +79DE003FFE001FF80007E00001C00001C00001C00000C00011247D9F18>I<3803007C07807C07 +80EE0F80EE0F00EE0F00EE1F00EE1E00EE1E00EE3E007C3C007C3C00387C0000780000780000F8 +0000F00001F00001E00001E00003E00003C00003C00007C0000783800787C00F87C00F0EE00F0E +E01F0EE01E0EE01E0EE03E0EE03C07C03C07C018038013247E9F18>I<01C00007E0000FF0000E +70001C38001C38001C38001C38001C73F01C73F01CE3F00FE3800FC7000F87000F07001F0E003F +0E007B8E0073DC00E1DC00E0F800E0F800E07070E0787070FC707FFFE03FCFE00F03C0141C7F9B +18>I<387C7C7E3E0E0E0E1C1C38F8F0C0070E789B18>I<007000F001E003C007800F001E001C00 +380038007000700070007000E000E000E000E000E000E000E000E0007000700070007000380038 +001C001E000F00078003C001F000F000700C24799F18>I<6000F00078003C001E000F00078003 +8001C001C000E000E000E000E00070007000700070007000700070007000E000E000E000E001C0 +01C0038007800F001E003C007800F00060000C247C9F18>I<01C00001C00001C00001C000C1C1 +80F1C780F9CF807FFF001FFC0007F00007F0001FFC007FFF00F9CF80F1C780C1C18001C00001C0 +0001C00001C00011147D9718>I<00600000F00000F00000F00000F00000F00000F00000F0007F +FFC0FFFFE0FFFFE07FFFC000F00000F00000F00000F00000F00000F00000F00000600013147E97 +18>I<1C3E7E7F3F1F070E1E7CF860080C788518>I<7FFF00FFFF80FFFF807FFF0011047D8F18> +I<3078FCFC78300606778518>I<000300000780000780000F80000F00001F00001E00001E0000 +3E00003C00007C0000780000780000F80000F00001F00001E00003E00003C00003C00007C00007 +80000F80000F00000F00001F00001E00003E00003C00003C00007C0000780000F80000F00000F0 +000060000011247D9F18>I<01F00007FC000FFE001F1F001C07003803807803C07001C07001C0 +E000E0E000E0E000E0E000E0E000E0E000E0E000E0E000E0E000E0F001E07001C07001C07803C0 +3803801C07001F1F000FFE0007FC0001F000131C7E9B18>I<01800380038007800F803F80FF80 +FB80438003800380038003800380038003800380038003800380038003800380038003807FFCFF +FE7FFC0F1C7B9B18>I<03F0000FFE003FFF007C0F807003C0E001C0F000E0F000E06000E00000 +E00000E00001C00001C00003C0000780000F00001E00003C0000780000F00001E00007C0000F80 +001E00E03C00E07FFFE0FFFFE07FFFE0131C7E9B18>I<001F00003F0000770000770000E70001 +E70001C7000387000787000707000E07001E07003C0700380700780700F00700FFFFF8FFFFF8FF +FFF8000700000700000700000700000700000700007FF000FFF8007FF0151C7F9B18>52 +D<007E0001FF0007FF800F83C01E03C01C03C0380180380000700000700000E1F800E7FE00FFFF +00FE0780F803C0F001C0F000E0E000E0F000E07000E07000E07000E03801C03C03C01E07800FFF +0007FE0001F800131C7E9B18>54 D<3078FCFC783000000000000000003078FCFC783006147793 +18>58 D<183C7E7E3C180000000000000000183C7E7E3E1E0E1C3C78F060071A789318>I<0003 +00000780001F80003F00007E0001FC0003F00007E0001FC0003F00007E0000FC0000FC00007E00 +003F00001FC00007E00003F00001FC00007E00003F00001F8000078000030011187D9918>I<7F +FFC0FFFFE0FFFFE0FFFFE0000000000000000000000000FFFFE0FFFFE0FFFFE07FFFC0130C7E93 +18>I<600000F00000FC00007E00003F00001FC00007E00003F00001FC00007E00003F00001F80 +001F80003F00007E0001FC0003F00007E0001FC0003F00007E0000FC0000F0000060000011187D +9918>I<0FF0003FFC007FFF00700F00F00380F00380600780000F00003E00007C0001F00001E0 +0003C00003C00003C00003C00003C00003800000000000000000000000000000000003800007C0 +0007C00007C000038000111C7D9B18>I<00700000F80000F80000D80000D80001DC0001DC0001 +DC00018C00038E00038E00038E00038E000306000707000707000707000707000FFF800FFF800F +FF800E03800E03801C01C01C01C07F07F0FF8FF87F07F0151C7F9B18>65 +D<7FF800FFFE007FFF001C0F801C03C01C03C01C01E01C00E01C00E01C00F01C00701C00701C00 +701C00701C00701C00701C00701C00701C00F01C00E01C00E01C01E01C01C01C03C01C0F807FFF +00FFFE007FF800141C7F9B18>68 DII<7F07F0FF8FF87F07F01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01F +FFC01FFFC01FFFC01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C01C07F +07F0FF8FF87F07F0151C7F9B18>72 D<7FFF00FFFF807FFF0001C00001C00001C00001C00001C0 +0001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C0 +0001C00001C00001C00001C0007FFF00FFFF807FFF00111C7D9B18>I<7FE000FFE0007FE0000E +00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E +00000E00000E00000E00000E00700E00700E00700E00700E00707FFFF0FFFFF07FFFF0141C7F9B +18>76 D<7E07F0FF0FF87F07F01D81C01D81C01D81C01DC1C01CC1C01CC1C01CE1C01CE1C01CE1 +C01C61C01C71C01C71C01C31C01C39C01C39C01C39C01C19C01C19C01C1DC01C0DC01C0DC01C0D +C07F07C0FF87C07F03C0151C7F9B18>78 D<0FF8003FFE007FFF00780F00700700F00780E00380 +E00380E00380E00380E00380E00380E00380E00380E00380E00380E00380E00380E00380E00380 +E00380E00380F00780700700780F007FFF003FFE000FF800111C7D9B18>II<7FF800FFFE007FFF001C0F801C03801C03C01C01C01C01C01C01C01C03C01C03801C +0F801FFF001FFE001FFE001C0F001C07001C03801C03801C03801C03801C03801C039C1C039C1C +039C7F01F8FF81F87F00F0161C7F9B18>82 D<03F3801FFF803FFF807C0F80700780E00380E003 +80E00380E000007000007800003F00001FF00007FE0000FF00000F800003C00001C00000E00000 +E06000E0E000E0E001E0F001C0F80780FFFF80FFFE00E7F800131C7E9B18>I<7FFFF8FFFFF8FF +FFF8E07038E07038E07038E0703800700000700000700000700000700000700000700000700000 +700000700000700000700000700000700000700000700000700000700007FF0007FF0007FF0015 +1C7F9B18>II89 +D91 D<600000F00000F00000F800007800007C00003C00003C00003E00001E00001F00000F0000 +0F00000F800007800007C00003C00003C00003E00001E00001F00000F00000F800007800007800 +007C00003C00003E00001E00001E00001F00000F00000F8000078000078000030011247D9F18> +II<018007C01FF07EFCF83EE00E0F067C9B18>I<7FFF00FFFF80FFFF807FFF0011047D7F18>I< +061E3E387070E0E0E0F8FC7C7C38070E789E18>I<1FE0003FF8007FFC00781E00300E00000700 +00070000FF0007FF001FFF007F0700780700E00700E00700E00700F00F00781F003FFFF01FFBF0 +07E1F014147D9318>I<7E0000FE00007E00000E00000E00000E00000E00000E00000E3E000EFF +800FFFC00FC1E00F80E00F00700E00700E00380E00380E00380E00380E00380E00380F00700F00 +700F80E00FC1E00FFFC00EFF80063E00151C809B18>I<01FE0007FF001FFF803E078038030070 +0000700000E00000E00000E00000E00000E00000E000007000007001C03801C03E03C01FFF8007 +FF0001FC0012147D9318>I<001F80003F80001F8000038000038000038000038000038003E380 +0FFB801FFF803C1F80380F80700780700380E00380E00380E00380E00380E00380E00380700780 +700780380F803C1F801FFFF00FFBF803E3F0151C7E9B18>I<01F00007FC001FFE003E0F003807 +80700380700380E001C0E001C0FFFFC0FFFFC0FFFFC0E000007000007001C03801C03E03C01FFF +8007FF0001FC0012147D9318>I<001F80007FC000FFE000E1E001C0C001C00001C00001C0007F +FFC0FFFFC0FFFFC001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001 +C00001C00001C00001C0007FFF007FFF007FFF00131C7F9B18>I<01E1F007FFF80FFFF81E1E30 +1C0E003807003807003807003807003807001C0E001E1E001FFC001FF80039E0003800001C0000 +1FFE001FFFC03FFFE07801F0700070E00038E00038E00038E000387800F07E03F01FFFC00FFF80 +01FC00151F7F9318>I<7E0000FE00007E00000E00000E00000E00000E00000E00000E3E000EFF +800FFFC00FC1C00F80E00F00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00 +E00E00E00E00E07FC3FCFFE7FE7FC3FC171C809B18>I<03800007C00007C00007C00003800000 +00000000000000000000007FC000FFC0007FC00001C00001C00001C00001C00001C00001C00001 +C00001C00001C00001C00001C00001C00001C00001C000FFFF00FFFF80FFFF00111D7C9C18>I< +7FE000FFE0007FE00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E000 +00E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E0007FFFC0 +FFFFE07FFFC0131C7E9B18>108 D<7CE0E000FFFBF8007FFFF8001F1F1C001E1E1C001E1E1C00 +1C1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C +001C1C1C007F1F1F00FFBFBF807F1F1F001914819318>I<7E3E00FEFF807FFFC00FC1C00F80E0 +0F00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E07FC3FC +FFE7FE7FC3FC1714809318>I<01F0000FFE001FFF003E0F803803807001C07001C0E000E0E000 +E0E000E0E000E0E000E0F001E07001C07803C03C07803E0F801FFF000FFE0001F00013147E9318 +>I<7E3E00FEFF807FFFC00FC1E00F80E00F00700E00700E00380E00380E00380E00380E00380E +00380F00700F00700F80E00FC1E00FFFC00EFF800E3E000E00000E00000E00000E00000E00000E +00000E00007FC000FFE0007FC000151E809318>I<01E38007FB801FFF803E1F80380F80700780 +700780E00380E00380E00380E00380E00380E00380700780700780380F803C1F801FFF800FFB80 +03E380000380000380000380000380000380000380000380003FF8003FF8003FF8151E7E9318> +I<7F87E0FF9FF07FBFF803F87803F03003E00003C00003C0000380000380000380000380000380 +000380000380000380000380007FFE00FFFF007FFE0015147F9318>I<07F7003FFF007FFF0078 +0F00E00700E00700E007007C00007FE0001FFC0003FE00001F00600780E00380E00380F00380F8 +0F00FFFF00FFFC00E7F00011147D9318>I<0180000380000380000380000380007FFFC0FFFFC0 +FFFFC00380000380000380000380000380000380000380000380000380000380400380E00380E0 +0380E001C1C001FFC000FF80003E0013197F9818>I<7E07E0FE0FE07E07E00E00E00E00E00E00 +E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E01E00F03E007FFFC03FF +FE01FCFC1714809318>I<7F8FF0FF8FF87F8FF01E03C00E03800E03800E038007070007070007 +0700038E00038E00038E00038E0001DC0001DC0001DC0000F80000F80000700015147F9318>I< +FF8FF8FF8FF8FF8FF83800E03800E03800E01C01C01C01C01C71C01CF9C01CF9C01CD9C01CD9C0 +0DDD800DDD800DDD800D8D800F8F800F8F8007070015147F9318>I<7F8FF07F9FF07F8FF00707 +00078E00039E0001DC0001F80000F80000700000F00000F80001DC00039E00038E000707000F07 +807F8FF0FF8FF87F8FF015147F9318>I<7F8FF0FF8FF87F8FF00E01C00E03800E038007038007 +0700070700038700038600038E0001CE0001CE0000CC0000CC0000DC0000780000780000780000 +700000700000700000F00000E00079E0007BC0007F80003F00001E0000151E7F9318>I<3FFFF0 +7FFFF07FFFF07001E07003C0700780000F00001E00003C0000F80001F00003C0000780000F0070 +1E00703C0070780070FFFFF0FFFFF0FFFFF014147F9318>I<0007E0001FE0007FE000780000E0 +0000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00001E0007FC000FF80 +00FF80007FC00001E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E0 +0000E000007800007FE0001FE00007E013247E9F18>I<60F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0600424769F18>I<7C0000FF0000FFC00003C000 +00E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000F000007FC0 +003FE0003FE0007FC000F00000E00000E00000E00000E00000E00000E00000E00000E00000E000 +00E00000E00003C000FFC000FF00007C000013247E9F18>I<060C1F1E3FBEFBF8F1F060C00F06 +7C9B18>I E /Fo 75 123 df<001F83E000F06E3001C078780380F8780300F030070070000700 +70000700700007007000070070000700700007007000FFFFFF8007007000070070000700700007 +007000070070000700700007007000070070000700700007007000070070000700700007007000 +07007000070070000700700007007000070070007FE3FF001D20809F1B>11 +D<003F0000E0C001C0C00381E00701E00701E0070000070000070000070000070000070000FFFF +E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700 +E00700E00700E00700E00700E00700E07FC3FE1720809F19>I<003FE000E0E001C1E00381E007 +00E00700E00700E00700E00700E00700E00700E00700E0FFFFE00700E00700E00700E00700E007 +00E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E007 +00E07FE7FE1720809F19>I<001F81F80000F04F040001C07C06000380F80F000300F00F000700 +F00F00070070000007007000000700700000070070000007007000000700700000FFFFFFFF0007 +007007000700700700070070070007007007000700700700070070070007007007000700700700 +070070070007007007000700700700070070070007007007000700700700070070070007007007 +00070070070007007007007FE3FE3FF02420809F26>I<7038F87CFC7EFC7E743A040204020402 +0804080410081008201040200F0E7E9F17>34 D<70F8FCFC74040404080810102040060E7C9F0D +>39 D<0020004000800100020006000C000C00180018003000300030007000600060006000E000 +E000E000E000E000E000E000E000E000E000E000E0006000600060007000300030003000180018 +000C000C000600020001000080004000200B2E7DA112>I<800040002000100008000C00060006 +000300030001800180018001C000C000C000C000E000E000E000E000E000E000E000E000E000E0 +00E000E000C000C000C001C001800180018003000300060006000C00080010002000400080000B +2E7DA112>I<70F8FCFC74040404080810102040060E7C840D>44 DI<70 +F8F8F87005057C840D>I<03F0000E1C001C0E00180600380700700380700380700380700380F0 +03C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C070 +03807003807003807807803807001806001C0E000E1C0003F000121F7E9D17>48 +D<018003800F80F380038003800380038003800380038003800380038003800380038003800380 +03800380038003800380038003800380038007C0FFFE0F1E7C9D17>I<03F0000C1C00100E0020 +0700400780800780F007C0F803C0F803C0F803C02007C00007C0000780000780000F00000E0000 +1C0000380000700000600000C0000180000300000600400C00401800401000803FFF807FFF80FF +FF80121E7E9D17>I<03F0000C1C00100E00200F00780F80780780780780380F80000F80000F00 +000F00000E00001C0000380003F000003C00000E00000F000007800007800007C02007C0F807C0 +F807C0F807C0F00780400780400F00200E001C3C0003F000121F7E9D17>I<000600000600000E +00000E00001E00002E00002E00004E00008E00008E00010E00020E00020E00040E00080E00080E +00100E00200E00200E00400E00C00E00FFFFF0000E00000E00000E00000E00000E00000E00000E +0000FFE0141E7F9D17>I<1803001FFE001FFC001FF8001FE00010000010000010000010000010 +000010000011F000161C00180E001007001007800003800003800003C00003C00003C07003C0F0 +03C0F003C0E00380400380400700200600100E000C380003E000121F7E9D17>I<007C00018200 +0701000E03800C07801C0780380300380000780000700000700000F1F000F21C00F40600F80700 +F80380F80380F003C0F003C0F003C0F003C0F003C07003C07003C0700380380380380700180700 +0C0E00061C0001F000121F7E9D17>I<4000007FFFC07FFF807FFF804001008002008002008004 +0000080000080000100000200000200000400000400000C00000C00001C0000180000380000380 +00038000038000078000078000078000078000078000078000078000030000121F7D9D17>I<03 +F0000C0C001006003003002001806001806001806001807001807803003E03003F06001FC8000F +F00003F80007FC000C7E00103F00300F806003804001C0C001C0C000C0C000C0C000C0C0008060 +01802001001002000C0C0003F000121F7E9D17>I<03F0000E18001C0C00380600380700700700 +700380F00380F00380F003C0F003C0F003C0F003C0F003C07007C07007C03807C0180BC00E13C0 +03E3C0000380000380000380000700300700780600780E00700C002018001070000FC000121F7E +9D17>I<70F8F8F8700000000000000000000070F8F8F87005147C930D>I<70F8F8F87000000000 +00000000000070F0F8F878080808101010202040051D7C930D>I<000100000003800000038000 +000380000007C0000007C0000007C0000009E0000009E0000009E0000010F0000010F0000010F0 +0000207800002078000020780000403C0000403C0000403C0000801E0000801E0000FFFE000100 +0F0001000F0001000F00020007800200078002000780040003C00E0003C01F0007E0FFC03FFE1F +207F9F22>65 DI<000FC040007030C001C009C0038005C00700 +03C00E0001C01E0000C01C0000C03C0000C07C0000407C00004078000040F8000000F8000000F8 +000000F8000000F8000000F8000000F8000000F8000000F8000000780000007C0000407C000040 +3C0000401C0000401E0000800E000080070001000380020001C0040000703800000FC0001A217D +9F21>IIII<000FE0200078186000E004E0038002E0070001E00F0000E01E0000601E000060 +3C0000603C0000207C00002078000020F8000000F8000000F8000000F8000000F8000000F80000 +00F8000000F8007FFCF80003E0780001E07C0001E03C0001E03C0001E01E0001E01E0001E00F00 +01E0070001E0038002E000E0046000781820000FE0001E217D9F24>III<0FFFC0007C +00003C00003C00003C00003C00003C00003C00003C00003C00003C00003C00003C00003C00003C +00003C00003C00003C00003C00003C00003C00003C00003C00203C00F83C00F83C00F83C00F038 +0040780040700030E0000F800012207E9E17>I76 DII<001F800000F0F00001C0380007801E +000F000F000E0007001E0007803C0003C03C0003C07C0003E0780001E0780001E0F80001F0F800 +01F0F80001F0F80001F0F80001F0F80001F0F80001F0F80001F0F80001F0780001E07C0003E07C +0003E03C0003C03C0003C01E0007800E0007000F000F0007801E0001C0380000F0F000001F8000 +1C217D9F23>II<001F800000F0F00001C0380007801E000F00 +0F000E0007001E0007803C0003C03C0003C07C0003E07C0003E0780001E0F80001F0F80001F0F8 +0001F0F80001F0F80001F0F80001F0F80001F0F80001F0F80001F0780001E0780001E07C0003E0 +3C0003C03C0F03C01E1087800E2047000F204F0007A03E0001E0380000F0F010001FB010000030 +10000038300000387000003FF000001FE000001FE000000FC0000007801C297D9F23>II<07E0800C1980100780300380600180600180E00180E00080 +E00080E00080F00000F000007800007F00003FF0001FFC000FFE0003FF00001F800007800003C0 +0003C00001C08001C08001C08001C08001C0C00180C00380E00300F00600CE0C0081F80012217D +9F19>I<7FFFFFE0780F01E0600F0060400F0020400F0020C00F0030800F0010800F0010800F00 +10800F0010000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F +0000000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F000000 +0F0000001F800007FFFE001C1F7E9E21>IIII91 +D<080410082010201040204020804080408040B85CFC7EFC7E7C3E381C0F0E7B9F17>II<081020204040808080B8FCFC7C38060E7D9F0D>96 +D<1FE000303000781800781C00300E00000E00000E00000E0000FE00078E001E0E00380E00780E +00F00E10F00E10F00E10F01E10781E103867200F83C014147E9317>I<0E0000FE00000E00000E +00000E00000E00000E00000E00000E00000E00000E00000E00000E3E000EC3800F01C00F00E00E +00E00E00700E00700E00780E00780E00780E00780E00780E00780E00700E00700E00E00F00E00D +01C00CC300083E0015207F9F19>I<03F80E0C1C1E381E380C70007000F000F000F000F000F000 +F00070007000380138011C020E0C03F010147E9314>I<000380003F8000038000038000038000 +038000038000038000038000038000038000038003E380061B801C078038038038038070038070 +0380F00380F00380F00380F00380F00380F003807003807003803803803807801C07800E1B8003 +E3F815207E9F19>I<03F0000E1C001C0E00380700380700700700700380F00380F00380FFFF80 +F00000F00000F000007000007000003800801800800C010007060001F80011147F9314>I<007C +00C6018F038F07060700070007000700070007000700FFF0070007000700070007000700070007 +0007000700070007000700070007000700070007007FF01020809F0E>I<0000E003E3300E3C30 +1C1C30380E00780F00780F00780F00780F00780F00380E001C1C001E380033E000200000200000 +3000003000003FFE001FFF800FFFC03001E0600070C00030C00030C00030C000306000603000C0 +1C038003FC00141F7F9417>I<0E0000FE00000E00000E00000E00000E00000E00000E00000E00 +000E00000E00000E00000E3E000E43000E81800F01C00F01C00E01C00E01C00E01C00E01C00E01 +C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C0FFE7FC16207F9F19>I<1C +003E003E003E001C000000000000000000000000000E007E000E000E000E000E000E000E000E00 +0E000E000E000E000E000E000E000E000E000E00FFC00A1F809E0C>I<00E001F001F001F000E0 +000000000000000000000000007007F000F0007000700070007000700070007000700070007000 +7000700070007000700070007000700070007000706070F060F0C061803F000C28829E0E>I<0E +0000FE00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E0FF00E +03C00E03000E02000E04000E08000E10000E30000E70000EF8000F38000E1C000E1E000E0E000E +07000E07800E03800E03C00E03E0FFCFF815207F9F18>I<0E00FE000E000E000E000E000E000E +000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E00 +0E000E000E000E00FFE00B20809F0C>I<0E1F01F000FE618618000E81C81C000F00F00E000F00 +F00E000E00E00E000E00E00E000E00E00E000E00E00E000E00E00E000E00E00E000E00E00E000E +00E00E000E00E00E000E00E00E000E00E00E000E00E00E000E00E00E000E00E00E00FFE7FE7FE0 +23147F9326>I<0E3E00FE43000E81800F01C00F01C00E01C00E01C00E01C00E01C00E01C00E01 +C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C0FFE7FC16147F9319>I<01F80007 +0E001C03803801C03801C07000E07000E0F000F0F000F0F000F0F000F0F000F0F000F07000E070 +00E03801C03801C01C0380070E0001F80014147F9317>I<0E3E00FEC3800F01C00F00E00E00E0 +0E00F00E00700E00780E00780E00780E00780E00780E00780E00700E00F00E00E00F01E00F01C0 +0EC3000E3E000E00000E00000E00000E00000E00000E00000E00000E0000FFE000151D7F9319> +I<03E0800619801C05803C0780380380780380700380F00380F00380F00380F00380F00380F003 +807003807803803803803807801C0B800E138003E3800003800003800003800003800003800003 +80000380000380003FF8151D7E9318>I<0E78FE8C0F1E0F1E0F0C0E000E000E000E000E000E00 +0E000E000E000E000E000E000E000E00FFE00F147F9312>I<1F9030704030C010C010C010E000 +78007F803FE00FF00070803880188018C018C018E030D0608F800D147E9312>I<020002000200 +060006000E000E003E00FFF80E000E000E000E000E000E000E000E000E000E000E000E080E080E +080E080E080610031001E00D1C7F9B12>I<0E01C0FE1FC00E01C00E01C00E01C00E01C00E01C0 +0E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E03C00603C0030DC001F1FC +16147F9319>III<7FC3FC0F01E00701C007018003810001C20000E40000EC00007800003800003C0000 +7C00004E000087000107000303800201C00601E01E01E0FF07FE1714809318>II<3FFF380E200E201C40384078407000E001E001C00380078007010E011E +011C0338027006700EFFFE10147F9314>I E /Fp 13 122 df<0000001FFC0000C000000003FF +FFC001C00000001FFFFFF003C00000007FFFFFFC07C0000001FFFC00FE0FC0000007FFC0001F9F +C000000FFE000007FFC000003FF8000003FFC000007FF0000000FFC00000FFE00000007FC00001 +FFC00000007FC00001FF800000003FC00003FF000000001FC00007FE000000001FC0000FFE0000 +00000FC0000FFC000000000FC0001FFC0000000007C0001FFC0000000007C0003FF80000000007 +C0003FF80000000003C0003FF80000000003C0007FF80000000003C0007FF80000000003C0007F +F0000000000000007FF000000000000000FFF000000000000000FFF000000000000000FFF00000 +0000000000FFF000000000000000FFF000000000000000FFF000000000000000FFF00000000000 +0000FFF000000000000000FFF000000000000000FFF000000000000000FFF000001FFFFFFF807F +F000001FFFFFFF807FF000001FFFFFFF807FF800001FFFFFFF807FF800000001FFC0003FF80000 +0001FFC0003FF800000001FFC0003FF800000001FFC0001FFC00000001FFC0001FFC00000001FF +C0000FFE00000001FFC0000FFE00000001FFC00007FF00000001FFC00003FF00000001FFC00001 +FF80000001FFC00001FFC0000001FFC00000FFE0000001FFC000007FF0000003FFC000003FFC00 +0003FFC000000FFF000007FFC0000007FFC0001FBFC0000001FFFC00FF1FC00000007FFFFFFE0F +C00000001FFFFFF803C000000003FFFFE000C0000000001FFE00000000413D7BBB4C>71 +DI76 D78 D85 D<003FFE00000001FFFFE0000007FFFFF800000FE0 +07FC00000FF001FE00001FF800FF00001FF8007F80001FF8007FC0001FF8003FC0000FF0003FE0 +0007E0003FE00003C0003FE0000000003FE0000000003FE0000000003FE0000000003FE0000000 +FFFFE000001FFFFFE000007FF83FE00003FF803FE00007FC003FE0000FF0003FE0001FE0003FE0 +003FE0003FE0007FC0003FE0007FC0003FE000FF80003FE000FF80003FE000FF80003FE000FF80 +003FE000FF80007FE0007FC0007FE0007FC000DFE0003FE0039FF0001FF80F0FFFE007FFFE0FFF +E001FFF807FFE0003FE000FFE02B267DA52F>97 D<00FE00000000FFFE00000000FFFE00000000 +FFFE00000000FFFE0000000007FE0000000003FE0000000003FE0000000003FE0000000003FE00 +00000003FE0000000003FE0000000003FE0000000003FE0000000003FE0000000003FE00000000 +03FE0000000003FE0000000003FE0000000003FE0000000003FE0000000003FE0000000003FE01 +FF000003FE1FFFF00003FE7FFFFC0003FEFC03FE0003FFF000FF0003FFC0003F8003FF00001FC0 +03FE00001FE003FE00000FF003FE00000FF803FE00000FF803FE000007FC03FE000007FC03FE00 +0007FC03FE000007FE03FE000007FE03FE000007FE03FE000007FE03FE000007FE03FE000007FE +03FE000007FE03FE000007FE03FE000007FE03FE000007FC03FE000007FC03FE000007FC03FE00 +000FFC03FE00000FF803FE00000FF003FE00001FF003FF00001FE003FF80003FC003FFC0007F80 +03F9E000FF0003F0FC07FE0003F07FFFF80003E01FFFE00003C003FE00002F3C7DBB36>I<01E0 +0007F8000FFC000FFC001FFE001FFE001FFE001FFE000FFC000FFC0007F80001E0000000000000 +0000000000000000000000000000000000000000000000000000000000FE00FFFE00FFFE00FFFE +00FFFE0007FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE +0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE +0003FE0003FE0003FE0003FE00FFFFF0FFFFF0FFFFF0FFFFF0143D7DBC1A>105 +D<0001FFC00000000FFFF80000007FFFFF000000FF80FF800003FE003FE00007F8000FF0000FF0 +0007F8000FF00007F8001FE00003FC003FE00003FE003FE00003FE007FC00001FF007FC00001FF +007FC00001FF007FC00001FF00FFC00001FF80FFC00001FF80FFC00001FF80FFC00001FF80FFC0 +0001FF80FFC00001FF80FFC00001FF80FFC00001FF80FFC00001FF807FC00001FF007FC00001FF +007FC00001FF003FE00003FE003FE00003FE001FE00003FC001FF00007FC000FF00007F80007F8 +000FF00003FE003FE00000FF80FF8000007FFFFF0000000FFFF800000001FFC0000029267DA530 +>111 D<01FC03F000FFFC0FFC00FFFC1FFF00FFFC3C3F80FFFC707F8007FCE0FFC003FCC0FFC0 +03FD80FFC003FD80FFC003FF807F8003FF003F0003FF001E0003FF00000003FE00000003FE0000 +0003FE00000003FE00000003FE00000003FE00000003FE00000003FE00000003FE00000003FE00 +000003FE00000003FE00000003FE00000003FE00000003FE00000003FE00000003FE00000003FE +00000003FE00000003FE00000003FE000000FFFFFC0000FFFFFC0000FFFFFC0000FFFFFC000022 +267DA528>114 D<003FF07003FFFEF007FFFFF01FC01FF03F0003F03E0001F07C0001F07C0000 +F0FC0000F0FC0000F0FE0000F0FF000000FFC00000FFFC00007FFFF0003FFFFE003FFFFF801FFF +FFC00FFFFFE003FFFFF000FFFFF8001FFFFC00007FFC000007FE700001FEF00000FEF000007EF8 +00007EF800007EFC00007EFC00007CFE0000FCFF0000F8FF8001F0FFF00FE0F9FFFFC0F07FFF00 +C01FF8001F267DA526>I<000F0000000F0000000F0000000F0000000F0000001F0000001F0000 +001F0000001F0000003F0000003F0000007F0000007F000000FF000001FF000003FF000007FF00 +001FFFFFF0FFFFFFF0FFFFFFF0FFFFFFF001FF000001FF000001FF000001FF000001FF000001FF +000001FF000001FF000001FF000001FF000001FF000001FF000001FF000001FF000001FF000001 +FF000001FF000001FF000001FF000001FF003C01FF003C01FF003C01FF003C01FF003C01FF003C +01FF003C01FF003C00FF007800FF8078007F80F0003FC1E0001FFFC0000FFF800001FE001E377E +B626>I121 +D E end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 300dpi +TeXDict begin + +%%EndSetup +%%Page: 1 1 +0 bop 0 1152 a Fp(GNU)33 b(History)f(Library)p 0 1201 1950 +17 v 1035 1250 a Fo(Edition)16 b(2.0,)e(for)h Fn(History)f(Library)g +Fo(V)l(ersion)i(2.0.)1759 1304 y(July)g(1994)0 2443 y Fm(Brian)23 +b(F)-6 b(o)n(x,)23 b(F)-6 b(ree)23 b(Soft)n(w)n(are)f(F)-6 +b(oundation)0 2509 y(Chet)22 b(Ramey)-6 b(,)23 b(Case)e(W)-6 +b(estern)23 b(Reserv)n(e)f(Univ)n(ersit)n(y)p 0 2545 1950 9 +v eop +%%Page: 2 2 +1 bop 0 295 a Fo(This)16 b(do)q(cumen)o(t)g(describ)q(es)h(the)f(GNU)f +(History)g(library)l(,)h(a)g(programming)e(to)q(ol)i(that)f(pro)o(vides)h(a)f +(consisten)o(t)0 358 y(user)g(in)o(terface)h(for)e(recalling)j(lines)g(of)e +(previously)h(t)o(yp)q(ed)g(input.)0 495 y(Published)h(b)o(y)f(the)f(F)l(ree) +g(Soft)o(w)o(are)f(F)l(oundation)0 557 y(675)g(Massac)o(h)o(usetts)g(Av)o(en) +o(ue,)0 619 y(Cam)o(bridge,)h(MA)g(02139)f(USA)0 756 y(P)o(ermission)f(is)g +(gran)o(ted)f(to)f(mak)o(e)h(and)h(distribute)h(v)o(erbatim)e(copies)h(of)f +(this)h(man)o(ual)g(pro)o(vided)g(the)f(cop)o(yrigh)o(t)0 818 +y(notice)k(and)f(this)h(p)q(ermission)h(notice)e(are)g(preserv)o(ed)h(on)f +(all)h(copies.)0 955 y(P)o(ermission)f(is)f(gran)o(ted)f(to)h(cop)o(y)g(and)g +(distribute)h(mo)q(di\014ed)h(v)o(ersions)e(of)f(this)i(man)o(ual)f(under)h +(the)f(conditions)0 1018 y(for)e(v)o(erbatim)g(cop)o(ying,)h(pro)o(vided)h +(that)d(the)i(en)o(tire)g(resulting)h(deriv)o(ed)f(w)o(ork)f(is)h +(distributed)h(under)f(the)g(terms)0 1080 y(of)i(a)g(p)q(ermission)h(notice)g +(iden)o(tical)h(to)e(this)g(one.)0 1217 y(P)o(ermission)20 +b(is)g(gran)o(ted)f(to)g(cop)o(y)h(and)f(distribute)i(translations)f(of)f +(this)h(man)o(ual)f(in)o(to)h(another)f(language,)0 1279 y(under)c(the)f(ab)q +(o)o(v)o(e)g(conditions)h(for)e(mo)q(di\014ed)j(v)o(ersions,)e(except)g(that) +g(this)g(p)q(ermission)i(notice)e(ma)o(y)g(b)q(e)h(stated)0 +1341 y(in)h(a)f(translation)g(appro)o(v)o(ed)g(b)o(y)g(the)g(F)l(oundation.)0 +2636 y(Cop)o(yrigh)o(t)226 2635 y(c)214 2636 y Fl(\015)g Fo(1989,)f(1991)g(F) +l(ree)h(Soft)o(w)o(are)f(F)l(oundation,)h(Inc.)p eop +%%Page: 1 3 +2 bop 0 -83 a Fo(Chapter)15 b(1:)k(Using)d(History)f(In)o(teractiv)o(ely)1157 +b(1)0 158 y Fk(1)41 b(Using)14 b(History)h(In)n(teractiv)n(ely)62 +330 y Fo(This)i(c)o(hapter)e(describ)q(es)j(ho)o(w)d(to)h(use)g(the)g(GNU)g +(History)f(Library)i(in)o(teractiv)o(ely)l(,)g(from)e(a)g(user's)h(stand-)0 +392 y(p)q(oin)o(t.)23 b(It)16 b(should)h(b)q(e)f(considered)i(a)d(user's)h +(guide.)23 b(F)l(or)15 b(information)h(on)g(using)h(the)f(GNU)g(History)f +(Library)0 454 y(in)h(y)o(our)f(o)o(wn)f(programs,)g(see)i(Chapter)e(2)h +([Programming)f(with)i(GNU)f(History],)f(page)h(5.)0 663 y +Fm(1.1)33 b(History)15 b(In)n(teraction)62 800 y Fo(The)j(History)g(library)g +(pro)o(vides)h(a)e(history)h(expansion)h(feature)e(that)g(is)i(similar)g(to)e +(the)h(history)f(expan-)0 862 y(sion)k(pro)o(vided)h(b)o(y)f +Fn(csh)p Fo(.)36 b(The)22 b(follo)o(wing)f(text)g(describ)q(es)h(the)f(syn)o +(tax)f(used)i(to)e(manipulate)i(the)f(history)0 924 y(information.)62 +1061 y(History)11 b(expansion)i(tak)o(es)d(place)i(in)h(t)o(w)o(o)d(parts.)18 +b(The)11 b(\014rst)g(is)h(to)f(determine)h(whic)o(h)g(line)h(from)e(the)g +(previous)0 1124 y(history)h(should)h(b)q(e)f(used)h(during)f(substitution.) +20 b(The)12 b(second)g(is)h(to)e(select)h(p)q(ortions)g(of)g(that)f(line)i +(for)f(inclusion)0 1186 y(in)o(to)f(the)h(curren)o(t)f(one.)18 +b(The)12 b(line)h(selected)f(from)f(the)g(previous)h(history)g(is)f(called)i +(the)e Fj(ev)o(en)o(t)p Fo(,)h(and)f(the)h(p)q(ortions)0 1248 +y(of)h(that)g(line)i(that)e(are)g(acted)g(up)q(on)h(are)g(called)h +Fj(w)o(ords)p Fo(.)j(The)c(line)h(is)f(brok)o(en)f(in)o(to)h(w)o(ords)f(in)h +(the)f(same)h(fashion)0 1310 y(that)j(Bash)h(do)q(es,)h(so)e(that)g(sev)o +(eral)h(English)i(\(or)d(Unix\))h(w)o(ords)f(surrounded)i(b)o(y)f(quotes)f +(are)h(considered)h(as)0 1373 y(one)c(w)o(ord.)0 1565 y Fi(1.1.1)30 +b(Ev)n(en)n(t)16 b(Designators)62 1702 y Fo(An)g(ev)o(en)o(t)f(designator)g +(is)g(a)g(reference)h(to)f(a)g(command)g(line)i(en)o(try)d(in)i(the)g +(history)f(list.)0 1847 y Fn(!)216 b Fo(Start)14 b(a)g(history)h +(substitution,)g(except)h(when)f(follo)o(w)o(ed)g(b)o(y)g(a)f(space,)h(tab,)f +(the)h(end)g(of)g(the)g(line,)240 1909 y Fn(=)g Fo(or)g Fn(\()p +Fo(.)0 1989 y Fn(!!)192 b Fo(Refer)16 b(to)e(the)i(previous)f(command.)20 +b(This)c(is)g(a)f(synon)o(ym)g(for)f Fn(!-1)p Fo(.)0 2068 y +Fn(!n)192 b Fo(Refer)16 b(to)e(command)h(line)i Fj(n)p Fo(.)0 +2148 y Fn(!-n)168 b Fo(Refer)16 b(to)e(the)i(command)f Fj(n)g +Fo(lines)i(bac)o(k.)0 2227 y Fn(!string)72 b Fo(Refer)16 b(to)e(the)i(most)e +(recen)o(t)h(command)g(starting)g(with)g Fj(string)p Fo(.)0 +2298 y Fn(!?string)p Fo([)p Fn(?)p Fo(])240 2360 y(Refer)h(to)e(the)i(most)e +(recen)o(t)h(command)g(con)o(taining)h Fj(string)p Fo(.)0 2440 +y Fn(!#)192 b Fo(The)15 b(en)o(tire)h(command)f(line)i(t)o(yp)q(ed)f(so)e +(far.)0 2510 y Fn(^string1^string2^)240 2573 y Fo(Quic)o(k)j(Substitution.)22 +b(Rep)q(eat)16 b(the)g(last)f(command,)h(replacing)h Fj(string1)h +Fo(with)e Fj(string2)p Fo(.)21 b(Equiv-)240 2635 y(alen)o(t)15 +b(to)g Fn(!!:s/string1/string2/)p Fo(.)p eop +%%Page: 2 4 +3 bop 0 -83 a Fo(2)1497 b(GNU)15 b(History)g(Library)0 158 +y Fi(1.1.2)30 b(W)-5 b(ord)15 b(Designators)62 295 y Fo(A)i +Fn(:)g Fo(separates)f(the)h(ev)o(en)o(t)f(sp)q(eci\014cation)j(from)d(the)g +(w)o(ord)g(designator.)25 b(It)17 b(can)g(b)q(e)g(omitted)g(if)g(the)g(w)o +(ord)0 358 y(designator)d(b)q(egins)h(with)f(a)f Fn(^)p Fo(,)h +Fn($)p Fo(,)f Fn(*)h Fo(or)f Fn(\045)p Fo(.)20 b(W)l(ords)13 +b(are)h(n)o(um)o(b)q(ered)g(from)f(the)h(b)q(eginning)i(of)d(the)h(line,)i +(with)e(the)0 420 y(\014rst)h(w)o(ord)f(b)q(eing)j(denoted)f(b)o(y)f(a)g(0)f +(\(zero\).)0 569 y Fn(0)h(\(zero\))57 b Fo(The)15 b Fn(0)p +Fo(th)g(w)o(ord.)20 b(F)l(or)14 b(man)o(y)h(applications,)h(this)g(is)g(the)f +(command)g(w)o(ord.)0 656 y Fn(n)216 b Fo(The)15 b Fj(n)p Fo(th)h(w)o(ord.)0 +744 y Fn(^)216 b Fo(The)15 b(\014rst)g(argumen)o(t;)f(that)h(is,)g(w)o(ord)g +(1.)0 831 y Fn($)216 b Fo(The)15 b(last)h(argumen)o(t.)0 918 +y Fn(\045)216 b Fo(The)15 b(w)o(ord)g(matc)o(hed)g(b)o(y)g(the)g(most)g +(recen)o(t)g Fn(?string?)f Fo(searc)o(h.)0 1005 y Fn(x-y)168 +b Fo(A)15 b(range)g(of)g(w)o(ords;)f Fn(-)p Fj(y)19 b Fo(abbreviates)c +Fn(0-)p Fj(y)t Fo(.)0 1092 y Fn(*)216 b Fo(All)17 b(of)f(the)g(w)o(ords,)f +(except)i(the)f Fn(0)p Fo(th.)22 b(This)17 b(is)f(a)g(synon)o(ym)g(for)f +Fn(1-$)p Fo(.)22 b(It)17 b(is)f(not)g(an)g(error)f(to)h(use)240 +1155 y Fn(*)f Fo(if)h(there)f(is)h(just)f(one)g(w)o(ord)f(in)i(the)g(ev)o(en) +o(t;)e(the)i(empt)o(y)e(string)i(is)f(returned)h(in)g(that)e(case.)0 +1242 y Fn(x*)192 b Fo(Abbreviates)16 b Fn(x-$)0 1329 y(x-)192 +b Fo(Abbreviates)16 b Fn(x-$)f Fo(lik)o(e)h Fn(x*)p Fo(,)e(but)i(omits)f(the) +g(last)g(w)o(ord.)0 1537 y Fi(1.1.3)30 b(Mo)r(di\014ers)62 +1674 y Fo(After)20 b(the)f(optional)i(w)o(ord)e(designator,)h(y)o(ou)f(can)h +(add)g(a)g(sequence)h(of)e(one)h(or)f(more)g(of)g(the)h(follo)o(wing)0 +1736 y(mo)q(di\014ers,)c(eac)o(h)f(preceded)i(b)o(y)e(a)g Fn(:)p +Fo(.)0 1885 y Fn(h)216 b Fo(Remo)o(v)o(e)15 b(a)g(trailing)h(pathname)f(comp) +q(onen)o(t,)g(lea)o(ving)h(only)g(the)f(head.)0 1973 y Fn(r)216 +b Fo(Remo)o(v)o(e)15 b(a)g(trailing)h(su\016x)f(of)g(the)g(form)g(`)p +Fn(.)p Fo(')p Fj(su\016x)p Fo(,)f(lea)o(ving)i(the)f(basename.)0 +2060 y Fn(e)216 b Fo(Remo)o(v)o(e)15 b(all)h(but)g(the)f(trailing)h(su\016x.) +0 2147 y Fn(t)216 b Fo(Remo)o(v)o(e)15 b(all)h(leading)h(pathname)e(comp)q +(onen)o(ts,)g(lea)o(ving)h(the)f(tail.)0 2234 y Fn(p)216 b +Fo(Prin)o(t)15 b(the)g(new)h(command)f(but)g(do)g(not)g(execute)h(it.)0 +2309 y Fn(s/old/new/)240 2371 y Fo(Substitute)g Fj(new)k Fo(for)15 +b(the)h(\014rst)f(o)q(ccurrence)h(of)g Fj(old)h Fo(in)g(the)e(ev)o(en)o(t)h +(line.)22 b(An)o(y)16 b(delimiter)h(ma)o(y)e(b)q(e)240 2433 +y(used)e(in)f(place)h(of)f Fn(/)p Fo(.)19 b(The)12 b(delimiter)i(ma)o(y)d(b)q +(e)i(quoted)f(in)h Fj(old)h Fo(and)e Fj(new)17 b Fo(with)12 +b(a)g(single)h(bac)o(kslash.)240 2496 y(If)g Fn(&)h Fo(app)q(ears)f(in)h +Fj(new)p Fo(,)f(it)h(is)g(replaced)g(b)o(y)f Fj(old)p Fo(.)20 +b(A)13 b(single)i(bac)o(kslash)e(will)i(quote)e(the)h Fn(&)p +Fo(.)19 b(The)13 b(\014nal)240 2558 y(delimiter)k(is)f(optional)g(if)f(it)h +(is)f(the)h(last)f(c)o(haracter)f(on)h(the)h(input)g(line.)0 +2645 y Fn(&)216 b Fo(Rep)q(eat)16 b(the)f(previous)h(substitution.)p +eop +%%Page: 3 5 +4 bop 0 -83 a Fo(Chapter)15 b(1:)k(Using)d(History)f(In)o(teractiv)o(ely)1157 +b(3)0 158 y Fn(g)216 b Fo(Cause)15 b(c)o(hanges)g(to)f(b)q(e)i(applied)h(o)o +(v)o(er)d(the)h(en)o(tire)g(ev)o(en)o(t)g(line.)21 b(Used)16 +b(in)g(conjunction)g(with)f Fn(s)p Fo(,)f(as)240 221 y(in)i +Fn(gs/old/new/)p Fo(,)d(or)i(with)h Fn(&)p Fo(.)p eop +%%Page: 4 6 +5 bop 0 -83 a Fo(4)1497 b(GNU)15 b(History)g(Library)p eop +%%Page: 5 7 +6 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(History)1039 +b(5)0 158 y Fk(2)41 b(Programming)16 b(with)f(GNU)h(History)62 +347 y Fo(This)e(c)o(hapter)f(describ)q(es)i(ho)o(w)d(to)h(in)o(terface)g +(programs)f(that)h(y)o(ou)g(write)g(with)g(the)h(GNU)f(History)g(Library)l(.) +0 409 y(It)j(should)g(b)q(e)g(considered)h(a)f(tec)o(hnical)h(guide.)22 +b(F)l(or)15 b(information)h(on)f(the)h(in)o(teractiv)o(e)g(use)g(of)f(GNU)g +(History)l(,)0 471 y(see)g(Chapter)g(1)g([Using)h(History)f(In)o(teractiv)o +(ely],)g(page)g(1.)0 698 y Fm(2.1)33 b(In)n(tro)r(duction)17 +b(to)e(History)62 835 y Fo(Man)o(y)j(programs)g(read)h(input)h(from)e(the)g +(user)h(a)g(line)h(at)f(a)f(time.)31 b(The)19 b(GNU)g(History)f(library)i(is) +f(able)0 897 y(to)e(k)o(eep)g(trac)o(k)f(of)h(those)g(lines,)i(asso)q(ciate)e +(arbitrary)g(data)g(with)g(eac)o(h)g(line,)j(and)d(utilize)i(information)f +(from)0 960 y(previous)e(lines)h(in)f(comp)q(osing)f(new)h(ones.)62 +1097 y(The)i(programmer)f(using)h(the)g(History)g(library)g(has)g(a)o(v)m +(ailable)h(functions)g(for)e(remem)o(b)q(ering)h(lines)i(on)d(a)0 +1159 y(history)f(list,)g(asso)q(ciating)g(arbitrary)g(data)f(with)h(a)f +(line,)j(remo)o(ving)d(lines)j(from)d(the)h(list,)g(searc)o(hing)g(through)0 +1221 y(the)h(list)h(for)e(a)h(line)h(con)o(taining)g(an)f(arbitrary)f(text)h +(string,)g(and)g(referencing)h(an)o(y)f(line)h(in)g(the)f(list)h(directly)l +(.)0 1284 y(In)d(addition,)h(a)e(history)h Fj(expansion)h Fo(function)g(is)f +(a)o(v)m(ailable)h(whic)o(h)g(pro)o(vides)f(for)f(a)h(consisten)o(t)g(user)g +(in)o(terface)0 1346 y(across)f(di\013eren)o(t)i(programs.)62 +1483 y(The)i(user)g(using)g(programs)f(written)g(with)h(the)g(History)f +(library)i(has)e(the)h(b)q(ene\014t)h(of)e(a)g(consisten)o(t)h(user)0 +1545 y(in)o(terface)d(with)g(a)f(set)h(of)f(w)o(ell-kno)o(wn)h(commands)g +(for)f(manipulating)i(the)f(text)f(of)g(previous)h(lines)h(and)f(using)0 +1608 y(that)g(text)g(in)i(new)e(commands.)22 b(The)15 b(basic)i(history)e +(manipulation)j(commands)d(are)g(similar)i(to)e(the)h(history)0 +1670 y(substitution)g(pro)o(vided)g(b)o(y)f Fn(csh)p Fo(.)62 +1807 y(If)g(the)g(programmer)e(desires,)i(he)g(can)g(use)g(the)f(Readline)j +(library)l(,)e(whic)o(h)h(includes)g(some)f(history)f(manip-)0 +1870 y(ulation)i(b)o(y)f(default,)h(and)f(has)g(the)g(added)h(adv)m(an)o +(tage)f(of)g(command)g(line)h(editing.)0 2096 y Fm(2.2)33 b(History)15 +b(Storage)62 2234 y Fo(The)h(history)f(list)h(is)g(an)f(arra)o(y)f(of)g +(history)i(en)o(tries.)k(A)15 b(history)g(en)o(try)g(is)h(declared)g(as)f +(follo)o(ws:)120 2358 y Fn(typedef)23 b(struct)g(_hist_entry)f({)168 +2408 y(char)h(*line;)168 2458 y(char)g(*data;)120 2508 y(})h(HIST_ENTRY;)62 +2645 y Fo(The)16 b(history)f(list)h(itself)g(migh)o(t)f(therefore)g(b)q(e)h +(declared)g(as)p eop +%%Page: 6 8 +7 bop 0 -83 a Fo(6)1497 b(GNU)15 b(History)g(Library)120 158 +y Fn(HIST_ENTRY)22 b(**the_history_list;)62 302 y Fo(The)16 +b(state)e(of)h(the)g(History)g(library)h(is)g(encapsulated)g(in)o(to)f(a)g +(single)i(structure:)120 434 y Fn(/*)24 b(A)f(structure)g(used)g(to)h(pass)f +(the)h(current)f(state)g(of)g(the)h(history)f(stuff)g(around.)g(*/)120 +484 y(typedef)g(struct)g(_hist_state)f({)168 534 y(HIST_ENTRY)g(**entries;) +214 b(/*)23 b(Pointer)g(to)h(the)f(entries)g(themselves.)f(*/)168 +584 y(int)h(offset;)453 b(/*)23 b(The)h(location)e(pointer)h(within)g(this)h +(array.)f(*/)168 633 y(int)g(length;)453 b(/*)23 b(Number)g(of)h(elements)f +(within)g(this)g(array.)g(*/)168 683 y(int)g(size;)501 b(/*)23 +b(Number)g(of)h(slots)f(allocated)g(to)g(this)h(array.)f(*/)168 +733 y(int)g(flags;)120 783 y(})h(HISTORY_STATE;)62 927 y Fo(If)16 +b(the)f(\015ags)g(mem)o(b)q(er)g(includes)j Fn(HS_STIFLED)p +Fo(,)13 b(the)i(history)h(has)f(b)q(een)h(sti\015ed.)0 1215 +y Fm(2.3)33 b(History)15 b(F)-6 b(unctions)62 1359 y Fo(This)16 +b(section)g(describ)q(es)h(the)e(calling)i(sequence)f(for)f(the)g(v)m(arious) +h(functions)g(presen)o(t)f(in)h(GNU)f(History)l(.)0 1631 y +Fi(2.3.1)30 b(Initializing)15 b(History)g(and)g(State)g(Managemen)n(t)62 +1775 y Fo(This)j(section)g(describ)q(es)h(functions)f(used)g(to)e(initialize) +21 b(and)c(manage)g(the)g(state)g(of)g(the)g(History)g(library)0 +1837 y(when)f(y)o(ou)f(w)o(an)o(t)f(to)g(use)i(the)f(history)g(functions)h +(in)g(y)o(our)f(program.)1725 2021 y(F)l(unction)-1899 b Fh(void)20 +b Fg(using)p 258 2021 18 3 v 20 w(history)j Ff(\(\))120 2083 +y Fo(Begin)g(a)f(session)g(in)h(whic)o(h)g(the)f(history)g(functions)g(migh)o +(t)g(b)q(e)h(used.)40 b(This)23 b(initializes)i(the)120 2145 +y(in)o(teractiv)o(e)16 b(v)m(ariables.)1725 2328 y(F)l(unction)-1899 +b Fh(HISTORY_STATE)21 b(*)e Fg(history)p 582 2328 V 21 w(get)p +680 2328 V 21 w(history)p 876 2328 V 21 w(state)j Ff(\(\))120 +2391 y Fo(Return)16 b(a)f(structure)g(describing)i(the)e(curren)o(t)g(state)f +(of)h(the)g(input)i(history)l(.)1725 2574 y(F)l(unction)-1899 +b Fh(void)20 b Fg(history)p 302 2574 V 20 w(set)p 393 2574 +V 21 w(history)p 589 2574 V 21 w(state)j Ff(\()p Fn(HISTORY_STATE)13 +b(*state)p Ff(\))120 2636 y Fo(Set)i(the)h(state)e(of)h(the)g(history)g(list) +h(according)g(to)e Fj(state)p Fo(.)p eop +%%Page: 7 9 +8 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(History)1039 +b(7)0 158 y Fi(2.3.2)30 b(History)15 b(List)g(Managemen)n(t)62 +295 y Fo(These)i(functions)h(manage)e(individual)k(en)o(tries)d(on)f(the)h +(history)g(list,)g(or)f(set)h(parameters)e(managing)i(the)0 +358 y(list)f(itself.)1725 520 y(F)l(unction)-1899 b Fh(void)20 +b Fg(add)p 219 520 18 3 v 20 w(history)j Ff(\()p Fn(char)14 +b(*string)p Ff(\))120 582 y Fo(Place)j Fj(string)k Fo(at)16 +b(the)g(end)i(of)e(the)g(history)h(list.)25 b(The)17 b(asso)q(ciated)g(data)f +(\014eld)h(\(if)g(an)o(y\))f(is)h(set)g(to)120 644 y Fn(NULL)p +Fo(.)1725 806 y(F)l(unction)-1899 b Fh(HIST_ENTRY)21 b(*)e +Fg(remo)n(v)n(e)p 509 806 V 20 w(history)k Ff(\()p Fn(int)14 +b(which)p Ff(\))120 868 y Fo(Remo)o(v)o(e)d(history)g(en)o(try)g(at)g +(o\013set)f Fj(whic)o(h)i Fo(from)f(the)g(history)l(.)19 b(The)11 +b(remo)o(v)o(ed)g(elemen)o(t)h(is)g(returned)120 930 y(so)j(y)o(ou)g(can)g +(free)g(the)h(line,)g(data,)e(and)i(con)o(taining)g(structure.)1725 +1092 y(F)l(unction)-1899 b Fh(HIST_ENTRY)21 b(*)e Fg(replace)p +505 1092 V 22 w(history)p 702 1092 V 20 w(en)n(try)24 b Ff(\()p +Fn(int)14 b(which,)g(char)h(*line,)f(char)208 1155 y(*data)p +Ff(\))120 1217 y Fo(Mak)o(e)d(the)i(history)f(en)o(try)g(at)f(o\013set)h +Fj(whic)o(h)h Fo(ha)o(v)o(e)e Fj(line)17 b Fo(and)12 b Fj(data)p +Fo(.)19 b(This)12 b(returns)g(the)h(old)g(en)o(try)e(so)120 +1279 y(y)o(ou)i(can)g(disp)q(ose)h(of)e(the)h(data.)19 b(In)13 +b(the)g(case)g(of)f(an)h(in)o(v)m(alid)i Fj(whic)o(h)p Fo(,)f(a)f +Fn(NULL)f Fo(p)q(oin)o(ter)i(is)f(returned.)1725 1441 y(F)l(unction)-1899 +b Fh(void)20 b Fg(sti\015e)p 245 1441 V 21 w(history)j Ff(\()p +Fn(int)14 b(max)p Ff(\))120 1503 y Fo(Sti\015e)i(the)f(history)h(list,)f +(remem)o(b)q(ering)h(only)g(the)f(last)g Fj(max)j Fo(en)o(tries.)1725 +1665 y(F)l(unction)-1899 b Fh(int)20 b Fg(unsti\015e)p 283 +1665 V 21 w(history)i Ff(\(\))120 1728 y Fo(Stop)13 b(sti\015ing)h(the)f +(history)l(.)19 b(This)14 b(returns)f(the)g(previous)h(amoun)o(t)e(the)h +(history)g(w)o(as)g(sti\015ed.)20 b(The)120 1790 y(v)m(alue)c(is)g(p)q +(ositiv)o(e)g(if)g(the)f(history)g(w)o(as)g(sti\015ed,)h(negativ)o(e)f(if)g +(it)h(w)o(asn't.)1725 1952 y(F)l(unction)-1899 b Fh(int)20 +b Fg(history)p 276 1952 V 20 w(is)p 334 1952 V 21 w(sti\015ed)k +Ff(\(\))120 2014 y Fo(Returns)16 b(non-zero)f(if)h(the)f(history)g(is)h +(sti\015ed,)g(zero)f(if)g(it)h(is)g(not.)0 2222 y Fi(2.3.3)30 +b(Information)14 b(Ab)r(out)h(the)g(History)g(List)62 2359 +y Fo(These)h(functions)g(return)f(information)g(ab)q(out)g(the)h(en)o(tire)f +(history)g(list)h(or)f(individual)j(list)f(en)o(tries.)1725 +2521 y(F)l(unction)-1899 b Fh(HIST_ENTRY)21 b(**)e Fg(history)p +530 2521 V 21 w(list)24 b Ff(\(\))120 2583 y Fo(Return)e(a)e +Fn(NULL)h Fo(terminated)g(arra)o(y)f(of)g Fn(HIST_ENTRY)g Fo(whic)o(h)i(is)f +(the)g(curren)o(t)g(input)h(history)l(.)120 2645 y(Elemen)o(t)16 +b(0)f(of)f(this)i(list)g(is)g(the)f(b)q(eginning)i(of)e(time.)20 +b(If)c(there)f(is)h(no)f(history)l(,)g(return)g Fn(NULL)p Fo(.)p +eop +%%Page: 8 10 +9 bop 0 -83 a Fo(8)1497 b(GNU)15 b(History)g(Library)1725 158 +y(F)l(unction)-1899 b Fh(int)20 b Fg(where)p 250 158 18 3 v +20 w(history)j Ff(\(\))120 221 y Fo(Returns)16 b(the)f(o\013set)f(of)h(the)g +(curren)o(t)g(history)g(elemen)o(t.)1725 378 y(F)l(unction)-1899 +b Fh(HIST_ENTRY)21 b(*)e Fg(curren)n(t)p 512 378 V 21 w(history)k +Ff(\(\))120 440 y Fo(Return)14 b(the)g(history)g(en)o(try)f(at)h(the)g +(curren)o(t)f(p)q(osition,)i(as)e(determined)j(b)o(y)d Fn(where_history)h +(\(\))p Fo(.)120 502 y(If)h(there)h(is)f(no)h(en)o(try)e(there,)h(return)g(a) +g Fn(NULL)g Fo(p)q(oin)o(ter.)1725 660 y(F)l(unction)-1899 +b Fh(HIST_ENTRY)21 b(*)e Fg(history)p 504 660 V 21 w(get)j +Ff(\()p Fn(int)15 b(offset)p Ff(\))120 722 y Fo(Return)g(the)g(history)f(en)o +(try)g(at)g(p)q(osition)i Fj(o\013set)p Fo(,)d(starting)h(from)g +Fn(history_base)p Fo(.)k(If)c(there)h(is)g(no)120 784 y(en)o(try)g(there,)g +(or)f(if)i Fj(o\013set)f Fo(is)h(greater)e(than)h(the)h(history)f(length,)g +(return)g(a)g Fn(NULL)g Fo(p)q(oin)o(ter.)1725 942 y(F)l(unction)-1899 +b Fh(int)20 b Fg(history)p 276 942 V 20 w(total)p 412 942 V +22 w(b)n(ytes)j Ff(\(\))120 1004 y Fo(Return)17 b(the)f(n)o(um)o(b)q(er)g(of) +g(b)o(ytes)g(that)f(the)h(primary)g(history)g(en)o(tries)h(are)e(using.)23 +b(This)17 b(function)120 1066 y(returns)e(the)g(sum)h(of)e(the)i(lengths)f +(of)g(all)h(the)g(lines)g(in)g(the)g(history)l(.)0 1265 y Fi(2.3.4)30 +b(Mo)n(ving)15 b(Around)h(the)f(History)g(List)62 1402 y Fo(These)h +(functions)g(allo)o(w)f(the)g(curren)o(t)h(index)g(in)o(to)f(the)h(history)f +(list)h(to)e(b)q(e)i(set)f(or)g(c)o(hanged.)1725 1559 y(F)l(unction)-1899 +b Fh(int)20 b Fg(history)p 276 1559 V 20 w(set)p 367 1559 V +21 w(p)r(os)h Ff(\()p Fn(int)15 b(pos)p Ff(\))120 1621 y Fo(Set)g(the)h(p)q +(osition)g(in)g(the)f(history)g(list)h(to)f Fj(p)q(os)p Fo(,)g(an)g(absolute) +g(index)i(in)o(to)e(the)g(list.)1725 1779 y(F)l(unction)-1899 +b Fh(HIST_ENTRY)21 b(*)e Fg(previous)p 540 1779 V 20 w(history)k +Ff(\(\))120 1841 y Fo(Bac)o(k)16 b(up)h(the)g(curren)o(t)f(history)h +(o\013set)e(to)h(the)h(previous)g(history)g(en)o(try)l(,)f(and)h(return)f(a)g +(p)q(oin)o(ter)120 1903 y(to)f(that)f(en)o(try)l(.)20 b(If)15 +b(there)g(is)h(no)f(previous)h(en)o(try)l(,)f(return)g(a)g +Fn(NULL)g Fo(p)q(oin)o(ter.)1725 2061 y(F)l(unction)-1899 b +Fh(HIST_ENTRY)21 b(*)e Fg(next)p 439 2061 V 21 w(history)k +Ff(\(\))120 2123 y Fo(Mo)o(v)o(e)c(the)h(curren)o(t)g(history)f(o\013set)g +(forw)o(ard)g(to)g(the)h(next)g(history)g(en)o(try)l(,)g(and)g(return)g(the)g +(a)120 2185 y(p)q(oin)o(ter)c(to)e(that)h(en)o(try)l(.)k(If)d(there)f(is)h +(no)f(next)g(en)o(try)l(,)g(return)g(a)g Fn(NULL)g Fo(p)q(oin)o(ter.)0 +2384 y Fi(2.3.5)30 b(Searc)n(hing)15 b(the)h(History)f(List)62 +2521 y Fo(These)e(functions)g(allo)o(w)f(searc)o(hing)h(of)f(the)g(history)g +(list)h(for)f(en)o(tries)h(con)o(taining)g(a)f(sp)q(eci\014c)i(string.)19 +b(Searc)o(h-)0 2583 y(ing)e(ma)o(y)g(b)q(e)g(p)q(erformed)g(b)q(oth)g(forw)o +(ard)f(and)h(bac)o(kw)o(ard)f(from)g(the)h(curren)o(t)f(history)h(p)q +(osition.)26 b(The)17 b(searc)o(h)0 2645 y(ma)o(y)d(b)q(e)i +Fj(anc)o(hored)p Fo(,)f(meaning)h(that)f(the)g(string)g(m)o(ust)g(matc)o(h)f +(at)h(the)g(b)q(eginning)i(of)e(the)h(history)f(en)o(try)l(.)p +eop +%%Page: 9 11 +10 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(History)1039 +b(9)1725 158 y(F)l(unction)-1899 b Fh(int)20 b Fg(history)p +276 158 18 3 v 20 w(searc)n(h)j Ff(\()p Fn(char)14 b(*string,)g(int)h +(direction)p Ff(\))120 221 y Fo(Searc)o(h)k(the)g(history)g(for)f +Fj(string)p Fo(,)i(starting)e(at)g(the)h(curren)o(t)g(history)g(o\013set.)30 +b(If)19 b Fj(direction)h Fn(<)f Fo(0,)120 283 y(then)14 b(the)f(searc)o(h)g +(is)h(through)e(previous)i(en)o(tries,)g(else)g(through)f(subsequen)o(t.)20 +b(If)13 b Fj(string)k Fo(is)d(found,)120 345 y(then)f(the)g(curren)o(t)g +(history)g(index)i(is)e(set)g(to)f(that)h(history)g(en)o(try)l(,)f(and)i(the) +f(v)m(alue)h(returned)f(is)h(the)120 407 y(o\013set)h(in)i(the)f(line)i(of)d +(the)h(en)o(try)g(where)g Fj(string)k Fo(w)o(as)c(found.)22 +b(Otherwise,)17 b(nothing)f(is)h(c)o(hanged,)120 470 y(and)e(a)g(-1)g(is)h +(returned.)1725 659 y(F)l(unction)-1899 b Fh(int)20 b Fg(history)p +276 659 V 20 w(searc)n(h)p 452 659 V 21 w(pre\014x)i Ff(\()p +Fn(char)15 b(*string,)f(int)g(direction)p Ff(\))120 721 y Fo(Searc)o(h)22 +b(the)h(history)f(for)f Fj(string)p Fo(,)j(starting)e(at)f(the)i(curren)o(t)f +(history)g(o\013set.)40 b(The)22 b(searc)o(h)g(is)120 783 y(anc)o(hored:)i +(matc)o(hing)18 b(lines)h(m)o(ust)d(b)q(egin)j(with)f Fj(string)p +Fo(.)26 b(If)17 b Fj(direction)i Fn(<)e Fo(0,)g(then)h(the)f(searc)o(h)g(is) +120 845 y(through)e(previous)h(en)o(tries,)f(else)i(through)d(subsequen)o(t.) +21 b(If)16 b Fj(string)j Fo(is)d(found,)f(then)h(the)f(curren)o(t)120 +908 y(history)20 b(index)i(is)e(set)g(to)g(that)f(en)o(try)l(,)i(and)f(the)g +(return)h(v)m(alue)g(is)g(0.)34 b(Otherwise,)22 b(nothing)e(is)120 +970 y(c)o(hanged,)15 b(and)h(a)e(-1)h(is)h(returned.)1725 1159 +y(F)l(unction)-1899 b Fh(int)20 b Fg(history)p 276 1159 V 20 +w(searc)n(h)p 452 1159 V 21 w(p)r(os)h Ff(\()p Fn(char)15 b(*string,)f(int)g +(direction,)g(int)h(pos)p Ff(\))120 1221 y Fo(Searc)o(h)d(for)f +Fj(string)k Fo(in)d(the)g(history)f(list,)i(starting)e(at)g +Fj(p)q(os)p Fo(,)h(an)f(absolute)h(index)h(in)o(to)e(the)h(list.)19 +b(If)12 b Fj(di-)120 1283 y(rection)g Fo(is)h(negativ)o(e,)f(the)g(searc)o(h) +g(pro)q(ceeds)h(bac)o(kw)o(ard)e(from)g Fj(p)q(os)p Fo(,)i(otherwise)f(forw)o +(ard.)17 b(Returns)120 1345 y(the)e(absolute)h(index)g(of)f(the)g(history)h +(elemen)o(t)f(where)h Fj(string)j Fo(w)o(as)14 b(found,)h(or)g(-1)g +(otherwise.)0 1634 y Fi(2.3.6)30 b(Managing)14 b(the)i(History)f(File)62 +1780 y Fo(The)f(History)g(library)h(can)f(read)g(the)g(history)g(from)f(and)i +(write)f(it)g(to)f(a)h(\014le.)20 b(This)15 b(section)g(do)q(cumen)o(ts)f +(the)0 1842 y(functions)i(for)f(managing)g(a)f(history)i(\014le.)1725 +2031 y(F)l(unction)-1899 b Fh(int)20 b Fg(read)p 211 2031 V +20 w(history)i Ff(\()p Fn(char)15 b(*filename)p Ff(\))120 2093 +y Fo(Add)i(the)f(con)o(ten)o(ts)g(of)g Fj(\014lename)k Fo(to)c(the)h(history) +f(list,)h(a)f(line)i(at)e(a)g(time.)24 b(If)17 b Fj(\014lename)j +Fo(is)d Fn(NULL)p Fo(,)120 2155 y(then)f(read)f(from)f(`)p +Fn(~/.history)p Fo('.)k(Returns)e(0)e(if)i(successful,)g(or)f(errno)g(if)h +(not.)1725 2344 y(F)l(unction)-1899 b Fh(int)20 b Fg(read)p +211 2344 V 20 w(history)p 406 2344 V 20 w(range)i Ff(\()p Fn(char)15 +b(*filename,)e(int)i(from,)g(int)f(to)p Ff(\))120 2407 y Fo(Read)j(a)e(range) +h(of)f(lines)j(from)d Fj(\014lename)p Fo(,)i(adding)f(them)g(to)f(the)h +(history)g(list.)23 b(Start)15 b(reading)i(at)120 2469 y(line)f +Fj(from)f Fo(and)g(end)g(at)f Fj(to)p Fo(.)19 b(If)d Fj(from)e +Fo(is)h(zero,)f(start)g(at)g(the)h(b)q(eginning.)22 b(If)15 +b Fj(to)i Fo(is)e(less)g(than)g Fj(from)p Fo(,)120 2531 y(then)i(read)g(un)o +(til)h(the)f(end)g(of)g(the)g(\014le.)25 b(If)17 b Fj(\014lename)k +Fo(is)c Fn(NULL)p Fo(,)f(then)i(read)e(from)g(`)p Fn(~/.history)p +Fo('.)120 2593 y(Returns)g(0)f(if)g(successful,)h(or)f Fn(errno)g +Fo(if)g(not.)p eop +%%Page: 10 12 +11 bop 0 -83 a Fo(10)1474 b(GNU)15 b(History)g(Library)1725 +158 y(F)l(unction)-1899 b Fh(int)20 b Fg(write)p 229 158 18 +3 v 22 w(history)i Ff(\()p Fn(char)15 b(*filename)p Ff(\))120 +221 y Fo(W)l(rite)20 b(the)g(curren)o(t)f(history)h(to)f Fj(\014lename)p +Fo(,)i(o)o(v)o(erwriting)f Fj(\014lename)j Fo(if)d(necessary)l(.)34 +b(If)20 b Fj(\014lename)120 283 y Fo(is)d Fn(NULL)p Fo(,)g(then)g(write)g +(the)g(history)g(list)h(to)e(`)p Fn(~/.history)p Fo('.)23 b(V)l(alues)18 +b(returned)g(are)e(as)h(in)h Fn(read_)120 345 y(history)c(\(\))p +Fo(.)1725 504 y(F)l(unction)-1899 b Fh(int)20 b Fg(app)r(end)p +285 504 V 19 w(history)j Ff(\()p Fn(int)14 b(nelements,)g(char)h(*filename)p +Ff(\))120 566 y Fo(App)q(end)i(the)e(last)g Fj(nelemen)o(ts)j +Fo(of)d(the)g(history)g(list)h(to)f Fj(\014lename)p Fo(.)1725 +724 y(F)l(unction)-1899 b Fh(int)20 b Fg(history)p 276 724 +V 20 w(truncate)p 507 724 V 21 w(\014le)k Ff(\()p Fn(char)14 +b(*filename,)g(int)h(nlines)p Ff(\))120 787 y Fo(T)l(runcate)g(the)h(history) +f(\014le)h Fj(\014lename)p Fo(,)g(lea)o(ving)g(only)g(the)f(last)g +Fj(nlines)k Fo(lines.)0 988 y Fi(2.3.7)30 b(History)15 b(Expansion)62 +1125 y Fo(These)h(functions)g(implemen)o(t)g Fn(csh)p Fo(-lik)o(e)g(history)g +(expansion.)1725 1283 y(F)l(unction)-1899 b Fh(int)20 b Fg(history)p +276 1283 V 20 w(expand)j Ff(\()p Fn(char)14 b(*string,)g(char)h(**output)p +Ff(\))120 1345 y Fo(Expand)20 b Fj(string)p Fo(,)f(placing)i(the)e(result)h +(in)o(to)f Fj(output)p Fo(,)h(a)f(p)q(oin)o(ter)h(to)e(a)h(string)h(\(see)f +(Section)h(1.1)120 1408 y([History)15 b(In)o(teraction],)f(page)h(1\).)20 +b(Returns:)120 1555 y Fn(0)216 b Fo(If)21 b(no)g(expansions)h(to)q(ok)e +(place)h(\(or,)g(if)h(the)f(only)g(c)o(hange)g(in)h(the)f(text)f(w)o(as)g +(the)360 1618 y(de-slashifying)d(of)e(the)g(history)h(expansion)g(c)o +(haracter\);)120 1701 y Fn(1)216 b Fo(if)16 b(expansions)g(did)g(tak)o(e)e +(place;)120 1785 y Fn(-1)192 b Fo(if)16 b(there)f(w)o(as)f(an)h(error)g(in)h +(expansion;)120 1869 y Fn(2)216 b Fo(if)14 b(the)f(returned)h(line)h(should)f +(only)g(b)q(e)f(displa)o(y)o(ed,)i(but)e(not)g(executed,)h(as)f(with)h(the) +360 1931 y Fn(:p)h Fo(mo)q(di\014er)h(\(see)f(Section)h(1.1.3)e([Mo)q +(di\014ers],)h(page)g(2\).)120 2079 y(If)g(an)h(error)e(o)q(curred)i(in)g +(expansion,)f(then)h Fj(output)g Fo(con)o(tains)f(a)g(descriptiv)o(e)i(error) +d(message.)1725 2238 y(F)l(unction)-1899 b Fh(char)20 b(*)f +Fg(history)p 347 2238 V 21 w(arg)p 449 2238 V 19 w(extract)24 +b Ff(\()p Fn(int)14 b(first,)h(int)g(last,)f(char)h(*string)p +Ff(\))120 2300 y Fo(Extract)10 b(a)h(string)g(segmen)o(t)g(consisting)h(of)f +(the)g Fj(\014rst)h Fo(through)f Fj(last)h Fo(argumen)o(ts)e(presen)o(t)h(in) +h Fj(string)p Fo(.)120 2362 y(Argumen)o(ts)j(are)g(brok)o(en)g(up)g(as)g(in)h +(Bash.)1725 2521 y(F)l(unction)-1899 b Fh(char)20 b(*)f Fg(get)p +249 2521 V 21 w(history)p 445 2521 V 20 w(ev)n(en)n(t)25 b +Ff(\()p Fn(char)14 b(*string,)g(int)h(*cindex,)f(int)h(qchar)p +Ff(\))120 2583 y Fo(Returns)e(the)f(text)f(of)h(the)g(history)g(ev)o(en)o(t)f +(b)q(eginning)k(at)c Fj(string)16 b Fn(+)c Fj(*cindex)p Fo(.)20 +b Fj(*cindex)c Fo(is)d(mo)q(di\014ed)120 2645 y(to)h(p)q(oin)o(t)h(to)f +(after)h(the)f(ev)o(en)o(t)h(sp)q(eci\014er.)21 b(A)o(t)15 +b(function)g(en)o(try)l(,)f Fj(cindex)20 b Fo(p)q(oin)o(ts)15 +b(to)f(the)h(index)h(in)o(to)p eop +%%Page: 11 13 +12 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(History)1017 +b(11)120 158 y Fj(string)17 b Fo(where)d(the)f(history)h(ev)o(en)o(t)f(sp)q +(eci\014cation)i(b)q(egins.)20 b Fj(qc)o(har)d Fo(is)c(a)g(c)o(haracter)g +(that)g(is)h(allo)o(w)o(ed)120 221 y(to)h(end)g(the)h(ev)o(en)o(t)f(sp)q +(eci\014cation)i(in)f(addition)g(to)f(the)g(\\normal")g(terminating)g(c)o +(haracters.)1725 394 y(F)l(unction)-1899 b Fh(char)20 b(**)f +Fg(history)p 373 394 18 3 v 21 w(tok)n(enize)25 b Ff(\()p Fn(char)14 +b(*string)p Ff(\))120 456 y Fo(Return)k(an)f(arra)o(y)f(of)h(tok)o(ens)f +(parsed)i(out)e(of)h Fj(string)p Fo(,)g(m)o(uc)o(h)h(as)e(the)i(shell)g(migh) +o(t.)26 b(The)17 b(tok)o(ens)120 519 y(are)c(split)h(on)f(white)g(space)h +(and)f(on)g(the)g(c)o(haracters)f Fn(\(\)<>;&|$)p Fo(,)g(and)h(shell)i +(quoting)e(con)o(v)o(en)o(tions)120 581 y(are)i(ob)q(ey)o(ed.)0 +840 y Fm(2.4)33 b(History)15 b(V)-6 b(ariables)62 981 y Fo(This)16 +b(section)g(describ)q(es)h(the)e(externally)h(visible)i(v)m(ariables)e(exp)q +(orted)g(b)o(y)f(the)g(GNU)g(History)g(Library)l(.)1736 1155 +y(V)l(ariable)-1899 b Fh(int)20 b Fg(history)p 276 1155 V 20 +w(base)120 1217 y Fo(The)15 b(logical)i(o\013set)d(of)h(the)g(\014rst)g(en)o +(try)g(in)h(the)f(history)g(list.)1736 1390 y(V)l(ariable)-1899 +b Fh(int)20 b Fg(history)p 276 1390 V 20 w(length)120 1453 +y Fo(The)15 b(n)o(um)o(b)q(er)h(of)f(en)o(tries)g(curren)o(tly)h(stored)f(in) +h(the)f(history)g(list.)1736 1626 y(V)l(ariable)-1899 b Fh(int)20 +b Fg(max)p 208 1626 V 19 w(input)p 360 1626 V 21 w(history)120 +1689 y Fo(The)12 b(maxim)o(um)g(n)o(um)o(b)q(er)g(of)f(history)h(en)o(tries.) +19 b(This)12 b(m)o(ust)f(b)q(e)h(c)o(hanged)g(using)h Fn(stifle_history)120 +1751 y(\(\))p Fo(.)1736 1924 y(V)l(ariable)-1899 b Fh(char)20 +b Fg(history)p 302 1924 V 20 w(expansion)p 569 1924 V 21 w(c)n(har)120 +1987 y Fo(The)15 b(c)o(haracter)g(that)f(starts)g(a)h(history)g(ev)o(en)o(t.) +20 b(The)15 b(default)h(is)g(`)p Fn(!)p Fo('.)1736 2160 y(V)l(ariable)-1899 +b Fh(char)20 b Fg(history)p 302 2160 V 20 w(subst)p 454 2160 +V 20 w(c)n(har)120 2222 y Fo(The)13 b(c)o(haracter)e(that)h(in)o(v)o(ok)o(es) +g(w)o(ord)g(substitution)h(if)g(found)g(at)e(the)i(start)e(of)h(a)g(line.)21 +b(The)12 b(default)120 2285 y(is)k(`)p Fn(^)p Fo('.)1736 2458 +y(V)l(ariable)-1899 b Fh(char)20 b Fg(history)p 302 2458 V +20 w(commen)n(t)p 552 2458 V 19 w(c)n(har)120 2521 y Fo(During)12 +b(tok)o(enization,)h(if)f(this)h(c)o(haracter)e(is)i(seen)f(as)g(the)g +(\014rst)f(c)o(haracter)g(of)h(a)g(w)o(ord,)f(then)i(it)f(and)120 +2583 y(all)19 b(subsequen)o(t)g(c)o(haracters)e(up)h(to)g(a)f(newline)j(are)e +(ignored,)h(suppressing)g(history)f(expansion)120 2645 y(for)d(the)g +(remainder)h(of)f(the)g(line.)21 b(This)16 b(is)g(disabled)h(b)o(y)e +(default.)p eop +%%Page: 12 14 +13 bop 0 -83 a Fo(12)1474 b(GNU)15 b(History)g(Library)1736 +158 y(V)l(ariable)-1899 b Fh(char)20 b(*)f Fg(history)p 347 +158 18 3 v 21 w(no)p 429 158 V 20 w(expand)p 629 158 V 20 w(c)n(hars)120 +221 y Fo(The)f(list)g(of)g(c)o(haracters)e(whic)o(h)j(inhibit)h(history)d +(expansion)i(if)f(found)g(immediately)h(follo)o(wing)120 283 +y Fj(history)p 261 283 14 2 v 16 w(expansion)p 472 283 V 18 +w(c)o(har)p Fo(.)g(The)d(default)f(is)h(whitespace)g(and)g(`)p +Fn(=)p Fo('.)0 575 y Fm(2.5)33 b(History)15 b(Programming)h(Example)62 +720 y Fo(The)g(follo)o(wing)g(program)e(demonstrates)g(simple)j(use)e(of)g +(the)g(GNU)g(History)g(Library)l(.)120 852 y Fn(main)23 b(\(\))120 +902 y({)168 951 y(char)g(line[1024],)f(*t;)168 1001 y(int)h(len,)g(done)h(=)g +(0;)168 1101 y(line[0])f(=)g(0;)168 1201 y(using_history)f(\(\);)168 +1250 y(while)h(\(!done\))215 1300 y({)263 1350 y(printf)g(\("history$)g("\);) +263 1400 y(fflush)g(\(stdout\);)263 1450 y(t)h(=)g(fgets)f(\(line,)g(sizeof)g +(\(line\))g(-)h(1,)f(stdin\);)263 1499 y(if)h(\(t)f(&&)h(*t\))311 +1549 y({)359 1599 y(len)f(=)h(strlen)f(\(t\);)359 1649 y(if)g(\(t[len)g(-)h +(1])g(==)f('\\n'\))406 1699 y(t[len)h(-)f(1])h(=)g('\\0';)311 +1748 y(})263 1848 y(if)g(\(!t\))311 1898 y(strcpy)f(\(line,)g("quit"\);)263 +1998 y(if)h(\(line[0]\))311 2047 y({)359 2097 y(char)f(*expansion;)359 +2147 y(int)g(result;)359 2247 y(result)g(=)g(history_expand)f(\(line,)h +(&expansion\);)359 2296 y(if)g(\(result\))406 2346 y(fprintf)g(\(stderr,)g +("\045s\\n",)g(expansion\);)359 2446 y(if)g(\(result)g(<)h(0)g(||)f(result)g +(==)h(2\))406 2496 y({)454 2545 y(free)f(\(expansion\);)454 +2595 y(continue;)406 2645 y(})p eop +%%Page: 13 15 +14 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(History)1017 +b(13)359 208 y Fn(add_history)22 b(\(expansion\);)359 258 y(strncpy)h +(\(line,)g(expansion,)f(sizeof)h(\(line\))g(-)h(1\);)359 308 +y(free)f(\(expansion\);)311 358 y(})263 457 y(if)h(\(strcmp)f(\(line,)g +("quit"\))g(==)g(0\))311 507 y(done)g(=)h(1;)263 557 y(else)f(if)h(\(strcmp)f +(\(line,)g("save"\))g(==)h(0\))311 607 y(write_history)e(\("history_file"\);) +263 656 y(else)h(if)h(\(strcmp)f(\(line,)g("read"\))g(==)h(0\))311 +706 y(read_history)e(\("history_file"\);)263 756 y(else)h(if)h(\(strcmp)f +(\(line,)g("list"\))g(==)h(0\))311 806 y({)359 856 y(register)e(HIST_ENTRY)h +(**the_list;)359 906 y(register)f(int)i(i;)359 1005 y(the_list)e(=)i +(history_list)e(\(\);)359 1055 y(if)h(\(the_list\))406 1105 +y(for)h(\(i)f(=)h(0;)g(the_list[i];)e(i++\))454 1155 y(printf)h(\("\045d:)g +(\045s\\n",)g(i)h(+)g(history_base,)e(the_list[i]->line\);)311 +1204 y(})263 1254 y(else)h(if)h(\(strncmp)f(\(line,)g("delete",)g(6\))g(==)h +(0\))311 1304 y({)359 1354 y(int)f(which;)359 1404 y(if)g(\(\(sscanf)g +(\(line)g(+)h(6,)f("\045d",)h(&which\)\))e(==)i(1\))406 1453 +y({)454 1503 y(HIST_ENTRY)f(*entry)g(=)g(remove_history)f(\(which\);)454 +1553 y(if)i(\(!entry\))502 1603 y(fprintf)f(\(stderr,)f("No)i(such)f(entry)g +(\045d\\n",)g(which\);)454 1653 y(else)502 1703 y({)550 1752 +y(free)g(\(entry->line\);)550 1802 y(free)g(\(entry\);)502 +1852 y(})406 1902 y(})359 1952 y(else)406 2001 y({)454 2051 +y(fprintf)g(\(stderr,)g("non-numeric)f(arg)h(given)h(to)f(`delete'\\n"\);)406 +2101 y(})311 2151 y(})215 2201 y(})120 2250 y(})p eop +%%Page: 14 16 +15 bop 0 -83 a Fo(14)1474 b(GNU)15 b(History)g(Library)p eop +%%Page: 15 17 +16 bop 0 -83 a Fo(App)q(endix)17 b(A:)e(Concept)g(Index)1346 +b(15)0 158 y Fk(App)r(endix)13 b(A)41 b(Concept)15 b(Index)0 +405 y Fm(A)0 471 y Fe(anc)o(hored)f(searc)o(h)5 b Fd(:)i(:)f(:)g(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b Fe(8)0 +579 y Fm(E)0 646 y Fe(ev)o(en)o(t)13 b(designators)g Fd(:)6 +b(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)23 +b Fe(1)1015 405 y(expansion)5 b Fd(:)k(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:) +g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b Fe(1)1015 +521 y Fm(H)1015 587 y Fe(history)d(ev)o(en)o(ts)5 b Fd(:)i(:)f(:)g(:)g(:)g(:) +g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b +Fe(1)1015 646 y(History)c(Searc)o(hing)7 b Fd(:)h(:)e(:)g(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fe(8)p eop +%%Page: 16 18 +17 bop 0 -83 a Fo(16)1474 b(GNU)15 b(History)g(Library)p eop +%%Page: 17 19 +18 bop 0 -83 a Fo(App)q(endix)17 b(B:)e(F)l(unction)h(and)g(V)l(ariable)g +(Index)1069 b(17)0 158 y Fk(App)r(endix)13 b(B)41 b(F)-7 b(unction)15 +b(and)g(V)-7 b(ariable)14 b(Index)0 405 y Fm(A)0 471 y Fc(add)p +62 471 12 2 v 13 w(history)8 b Fd(:)s(:)e(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)20 b Fe(7)0 529 y Fc(append)p +122 529 V 12 w(history)9 b Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)24 b Fe(10)0 654 y Fm(C)0 720 y Fc(current)p +142 720 V 11 w(history)9 b Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)24 b Fe(8)0 845 y Fm(G)0 911 y Fc(get)p 62 911 +V 13 w(history)p 215 911 V 11 w(event)9 b Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)g(:)23 b Fe(10)0 1036 y Fm(H)0 1102 y Fc(history)p +142 1102 V 11 w(arg)p 213 1102 V 13 w(extract)8 b Fd(:)t(:)e(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)21 b Fe(10)0 1160 y Fc(history)p 142 1160 +V 11 w(base)e Fd(:)6 b(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:) +g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h +(:)f(:)g(:)20 b Fe(11)0 1218 y Fc(history)p 142 1218 V 11 w(comment)p +293 1218 V 12 w(char)g Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)21 +b Fe(11)0 1276 y Fc(history)p 142 1276 V 11 w(expand)10 b Fd(:)c(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)24 b Fe(10)0 +1335 y Fc(history)p 142 1335 V 11 w(expansion)p 333 1335 V +11 w(char)17 b Fd(:)7 b(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b Fe(11)0 +1393 y Fc(history)p 142 1393 V 11 w(get)8 b Fd(:)d(:)h(:)g(:)g(:)g(:)g(:)h(:) +f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)20 b Fe(8)0 +1451 y Fc(history)p 142 1451 V 11 w(get)p 213 1451 V 13 w(history)p +366 1451 V 12 w(state)t Fd(:)t(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17 b Fe(6)0 +1509 y Fc(history)p 142 1509 V 11 w(is)p 193 1509 V 14 w(stifled)7 +b Fd(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)23 b +Fe(7)0 1567 y Fc(history)p 142 1567 V 11 w(length)16 b Fd(:)6 +b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18 +b Fe(11)0 1625 y Fc(history)p 142 1625 V 11 w(list)7 b Fd(:)t(:)g(:)f(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)19 +b Fe(7)0 1683 y Fc(history)p 142 1683 V 11 w(no)p 193 1683 +V 14 w(expand)p 327 1683 V 12 w(chars)f Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)20 +b Fe(12)0 1741 y Fc(history)p 142 1741 V 11 w(search)t Fd(:)t(:)6 +b(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17 +b Fe(9)0 1800 y Fc(history)p 142 1800 V 11 w(search)p 273 1800 +V 12 w(pos)9 b Fd(:)d(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)23 +b Fe(9)0 1858 y Fc(history)p 142 1858 V 11 w(search)p 273 1858 +V 12 w(prefix)6 b Fd(:)t(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 +b Fe(9)0 1916 y Fc(history)p 142 1916 V 11 w(set)p 213 1916 +V 13 w(history)p 366 1916 V 12 w(state)t Fd(:)t(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17 +b Fe(6)0 1974 y Fc(history)p 142 1974 V 11 w(set)p 213 1974 +V 13 w(pos)5 b Fd(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g +(:)g(:)18 b Fe(8)0 2032 y Fc(history)p 142 2032 V 11 w(subst)p +253 2032 V 13 w(char)k Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)24 +b Fe(11)1015 405 y Fc(history)p 1157 405 V 12 w(tokenize)9 +b Fd(:)s(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)22 +b Fe(11)1015 463 y Fc(history)p 1157 463 V 12 w(total)p 1269 +463 V 12 w(bytes)9 b Fd(:)t(:)d(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22 +b Fe(8)1015 521 y Fc(history)p 1157 521 V 12 w(truncate)p 1329 +521 V 11 w(file)5 b Fd(:)g(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:) +f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 +b Fe(10)1015 629 y Fm(M)1015 695 y Fc(max)p 1077 695 V 13 w(input)p +1190 695 V 13 w(history)14 b Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)17 b Fe(11)1015 803 y Fm(N)1015 870 y Fc(next)p 1097 +870 V 13 w(history)7 b Fd(:)s(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fe(8)1015 978 y Fm(P)1015 1044 +y Fc(previous)p 1177 1044 V 12 w(history)7 b Fd(:)f(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h +(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)23 b Fe(8)1015 1152 y Fm(R)1015 +1218 y Fc(read)p 1097 1218 V 13 w(history)7 b Fd(:)s(:)f(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fe(9)1015 +1276 y Fc(read)p 1097 1276 V 13 w(history)p 1250 1276 V 11 +w(range)9 b Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:) +g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)23 +b Fe(9)1015 1335 y Fc(remove)p 1137 1335 V 12 w(history)t Fd(:)t(:)6 +b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)17 +b Fe(7)1015 1393 y Fc(replace)p 1157 1393 V 12 w(history)p +1309 1393 V 11 w(entry)6 b Fd(:)f(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h +(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)19 +b Fe(7)1015 1501 y Fm(S)1015 1567 y Fc(stifle)p 1137 1567 V +12 w(history)t Fd(:)t(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h +(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g +(:)g(:)g(:)g(:)17 b Fe(7)1015 1675 y Fm(U)1015 1741 y Fc(unstifle)p +1177 1741 V 12 w(history)7 b Fd(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h +(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)g(:)g(:)g(:)23 b Fe(7)1015 1800 y Fc(using)p 1117 1800 V +13 w(history)5 b Fd(:)s(:)h(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)h(:)f(:)g(:)18 b Fe(6)1015 1907 y Fm(W)1015 1974 y Fc(where)p +1117 1974 V 13 w(history)5 b Fd(:)s(:)h(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)18 b Fe(8)1015 2032 y Fc(write)p +1117 2032 V 13 w(history)5 b Fd(:)s(:)h(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)18 b Fe(9)p eop +%%Page: 18 20 +19 bop 0 -83 a Fo(18)1474 b(GNU)15 b(History)g(Library)p eop +%%Page: -1 21 +20 bop 1937 -83 a Fo(i)0 158 y Fk(T)-7 b(able)15 b(of)g(Con)n(ten)n(ts)0 +333 y Fm(1)67 b(Using)22 b(History)h(In)n(teractiv)n(ely)9 +b Fb(:)k(:)d(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)31 b Fm(1)149 411 y Fo(1.1)45 +b(History)15 b(In)o(teraction)9 b Fa(:)f(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)23 +b Fo(1)299 473 y(1.1.1)44 b(Ev)o(en)o(t)14 b(Designators)6 +b Fa(:)h(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)20 b Fo(1)299 535 y(1.1.2)44 b(W)l(ord)15 b(Designators)9 +b Fa(:)d(:)h(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h +(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)h(:)f(:)23 b Fo(2)299 597 y(1.1.3)44 b(Mo)q(di\014ers)14 +b Fa(:)8 b(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:) +g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)28 b Fo(2)0 722 +y Fm(2)67 b(Programming)23 b(with)g(GNU)f(History)13 b Fb(:)e(:)f(:)g(:)g(:)h +(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)36 b +Fm(5)149 800 y Fo(2.1)45 b(In)o(tro)q(duction)16 b(to)f(History)6 +b Fa(:)h(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)h(:)f(:)g(:)20 b Fo(5)149 862 y(2.2)45 b(History)15 +b(Storage)d Fa(:)7 b(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)27 +b Fo(5)149 924 y(2.3)45 b(History)15 b(F)l(unctions)c Fa(:)d(:)f(:)h(:)f(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h +(:)f(:)g(:)g(:)g(:)h(:)25 b Fo(6)299 986 y(2.3.1)44 b(Initializing)18 +b(History)d(and)h(State)e(Managemen)o(t)f Fa(:)7 b(:)g(:)g(:)h(:)f(:)g(:)g(:) +g(:)h(:)f(:)g(:)g(:)g(:)h(:)27 b Fo(6)299 1049 y(2.3.2)44 b(History)15 +b(List)h(Managemen)o(t)c Fa(:)7 b(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h +(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)28 b Fo(7)299 1111 y(2.3.3)44 b(Information)15 b(Ab)q(out)g(the)h(History) +f(List)5 b Fa(:)i(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)19 b Fo(7)299 1173 y(2.3.4)44 b(Mo)o(ving)15 +b(Around)g(the)g(History)g(List)6 b Fa(:)i(:)f(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:) +g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)20 +b Fo(8)299 1236 y(2.3.5)44 b(Searc)o(hing)16 b(the)f(History)g(List)7 +b Fa(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)21 b +Fo(8)299 1298 y(2.3.6)44 b(Managing)15 b(the)g(History)g(File)5 +b Fa(:)j(:)f(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)19 b +Fo(9)299 1360 y(2.3.7)44 b(History)15 b(Expansion)d Fa(:)7 +b(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)26 +b Fo(10)149 1422 y(2.4)45 b(History)15 b(V)l(ariables)5 b Fa(:)k(:)e(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)h(:)f(:)g(:)20 b Fo(11)149 1485 y(2.5)45 b(History)15 +b(Programming)f(Example)8 b Fa(:)g(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:) +g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)23 b Fo(12)0 1609 y Fm(App)r(endix)h(A)67 b(Concept)22 +b(Index)15 b Fb(:)c(:)f(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)37 b Fm(15)0 1749 +y(App)r(endix)24 b(B)67 b(F)-6 b(unction)25 b(and)e(V)-6 b(ariable)24 +b(Index)8 b Fb(:)j(:)f(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)31 +b Fm(17)p eop +%%Page: -2 22 +21 bop 0 -83 a Fo(ii)1496 b(GNU)15 b(History)g(Library)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/hstech.texinfo b/doc/hstech.texinfo new file mode 100644 index 0000000..5f0f600 --- /dev/null +++ b/doc/hstech.texinfo @@ -0,0 +1,489 @@ +@ignore +This file documents the user interface to the GNU History library. + +Copyright (C) 1988, 1991 Free Software Foundation, Inc. +Authored by Brian Fox and Chet Ramey. + +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 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). + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided also that the +GNU Copyright statement is available to the distributee, 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. +@end ignore + +@node Programming with GNU History +@chapter Programming with GNU History + +This chapter describes how to interface programs that you write +with the GNU History Library. +It should be considered a technical guide. +For information on the interactive use of GNU History, @pxref{Using +History Interactively}. + +@menu +* Introduction to History:: What is the GNU History library for? +* History Storage:: How information is stored. +* History Functions:: Functions that you can use. +* History Variables:: Variables that control behaviour. +* History Programming Example:: Example of using the GNU History Library. +@end menu + +@node Introduction to History +@section Introduction to History + +Many programs read input from the user a line at a time. The GNU History +library is able to keep track of those lines, associate arbitrary data with +each line, and utilize information from previous lines in composing new +ones. + +The programmer using the History library has available functions +for remembering lines on a history list, associating arbitrary data +with a line, removing lines from the list, searching through the list +for a line containing an arbitrary text string, and referencing any line +in the list directly. In addition, a history @dfn{expansion} function +is available which provides for a consistent user interface across +different programs. + +The user using programs written with the History library has the +benefit of a consistent user interface with a set of well-known +commands for manipulating the text of previous lines and using that text +in new commands. The basic history manipulation commands are similar to +the history substitution provided by @code{csh}. + +If the programmer desires, he can use the Readline library, which +includes some history manipulation by default, and has the added +advantage of command line editing. + +@node History Storage +@section History Storage + +The history list is an array of history entries. A history entry is +declared as follows: + +@example +typedef struct _hist_entry @{ + char *line; + char *data; +@} HIST_ENTRY; +@end example + +The history list itself might therefore be declared as + +@example +HIST_ENTRY **the_history_list; +@end example + +The state of the History library is encapsulated into a single structure: + +@example +/* A structure used to pass the current state of the history stuff around. */ +typedef struct _hist_state @{ + HIST_ENTRY **entries; /* Pointer to the entries themselves. */ + int offset; /* The location pointer within this array. */ + int length; /* Number of elements within this array. */ + int size; /* Number of slots allocated to this array. */ + int flags; +@} HISTORY_STATE; +@end example + +If the flags member includes @code{HS_STIFLED}, the history has been +stifled. + +@node History Functions +@section History Functions + +This section describes the calling sequence for the various functions +present in GNU History. + +@menu +* Initializing History and State Management:: Functions to call when you + want to use history in a + program. +* History List Management:: Functions used to manage the list + of history entries. +* Information About the History List:: Functions returning information about + the history list. +* Moving Around the History List:: Functions used to change the position + in the history list. +* Searching the History List:: Functions to search the history list + for entries containing a string. +* Managing the History File:: Functions that read and write a file + containing the history list. +* History Expansion:: Functions to perform csh-like history + expansion. +@end menu + +@node Initializing History and State Management +@subsection Initializing History and State Management + +This section describes functions used to initialize and manage +the state of the History library when you want to use the history +functions in your program. + +@deftypefun void using_history () +Begin a session in which the history functions might be used. This +initializes the interactive variables. +@end deftypefun + +@deftypefun {HISTORY_STATE *} history_get_history_state () +Return a structure describing the current state of the input history. +@end deftypefun + +@deftypefun void history_set_history_state (HISTORY_STATE *state) +Set the state of the history list according to @var{state}. +@end deftypefun + +@node History List Management +@subsection History List Management + +These functions manage individual entries on the history list, or set +parameters managing the list itself. + +@deftypefun void add_history (char *string) +Place @var{string} at the end of the history list. The associated data +field (if any) is set to @code{NULL}. +@end deftypefun + +@deftypefun {HIST_ENTRY *} remove_history (int which) +Remove history entry at offset @var{which} from the history. The +removed element is returned so you can free the line, data, +and containing structure. +@end deftypefun + +@deftypefun {HIST_ENTRY *} replace_history_entry (int which, char *line, char *data) +Make the history entry at offset @var{which} have @var{line} and @var{data}. +This returns the old entry so you can dispose of the data. In the case +of an invalid @var{which}, a @code{NULL} pointer is returned. +@end deftypefun + +@deftypefun void stifle_history (int max) +Stifle the history list, remembering only the last @var{max} entries. +@end deftypefun + +@deftypefun int unstifle_history () +Stop stifling the history. This returns the previous amount the +history was stifled. The value is positive if the history was +stifled, negative if it wasn't. +@end deftypefun + +@deftypefun int history_is_stifled () +Returns non-zero if the history is stifled, zero if it is not. +@end deftypefun + +@node Information About the History List +@subsection Information About the History List + +These functions return information about the entire history list or +individual list entries. + +@deftypefun {HIST_ENTRY **} history_list () +Return a @code{NULL} terminated array of @code{HIST_ENTRY} which is the +current input history. Element 0 of this list is the beginning of time. +If there is no history, return @code{NULL}. +@end deftypefun + +@deftypefun int where_history () +Returns the offset of the current history element. +@end deftypefun + +@deftypefun {HIST_ENTRY *} current_history () +Return the history entry at the current position, as determined by +@code{where_history ()}. If there is no entry there, return a @code{NULL} +pointer. +@end deftypefun + +@deftypefun {HIST_ENTRY *} history_get (int offset) +Return the history entry at position @var{offset}, starting from +@code{history_base}. If there is no entry there, or if @var{offset} +is greater than the history length, return a @code{NULL} pointer. +@end deftypefun + +@deftypefun int history_total_bytes () +Return the number of bytes that the primary history entries are using. +This function returns the sum of the lengths of all the lines in the +history. +@end deftypefun + +@node Moving Around the History List +@subsection Moving Around the History List + +These functions allow the current index into the history list to be +set or changed. + +@deftypefun int history_set_pos (int pos) +Set the position in the history list to @var{pos}, an absolute index +into the list. +@end deftypefun + +@deftypefun {HIST_ENTRY *} previous_history () +Back up the current history offset to the previous history entry, and +return a pointer to that entry. If there is no previous entry, return +a @code{NULL} pointer. +@end deftypefun + +@deftypefun {HIST_ENTRY *} next_history () +Move the current history offset forward to the next history entry, and +return the a pointer to that entry. If there is no next entry, return +a @code{NULL} pointer. +@end deftypefun + +@node Searching the History List +@subsection Searching the History List +@cindex History Searching + +These functions allow searching of the history list for entries containing +a specific string. Searching may be performed both forward and backward +from the current history position. The search may be @dfn{anchored}, +meaning that the string must match at the beginning of the history entry. +@cindex anchored search + +@deftypefun int history_search (char *string, int direction) +Search the history for @var{string}, starting at the current history +offset. If @var{direction} < 0, then the search is through previous entries, +else through subsequent. If @var{string} is found, then +the current history index is set to that history entry, and the value +returned is the offset in the line of the entry where +@var{string} was found. Otherwise, nothing is changed, and a -1 is +returned. +@end deftypefun + +@deftypefun int history_search_prefix (char *string, int direction) +Search the history for @var{string}, starting at the current history +offset. The search is anchored: matching lines must begin with +@var{string}. If @var{direction} < 0, then the search is through previous +entries, else through subsequent. If @var{string} is found, then the +current history index is set to that entry, and the return value is 0. +Otherwise, nothing is changed, and a -1 is returned. +@end deftypefun + +@deftypefun int history_search_pos (char *string, int direction, int pos) +Search for @var{string} in the history list, starting at @var{pos}, an +absolute index into the list. If @var{direction} is negative, the search +proceeds backward from @var{pos}, otherwise forward. Returns the absolute +index of the history element where @var{string} was found, or -1 otherwise. +@end deftypefun + +@node Managing the History File +@subsection Managing the History File + +The History library can read the history from and write it to a file. +This section documents the functions for managing a history file. + +@deftypefun int read_history (char *filename) +Add the contents of @var{filename} to the history list, a line at a +time. If @var{filename} is @code{NULL}, then read from +@file{~/.history}. Returns 0 if successful, or errno if not. +@end deftypefun + +@deftypefun int read_history_range (char *filename, int from, int to) +Read a range of lines from @var{filename}, adding them to the history list. +Start reading at line @var{from} and end at @var{to}. If +@var{from} is zero, start at the beginning. If @var{to} is less than +@var{from}, then read until the end of the file. If @var{filename} is +@code{NULL}, then read from @file{~/.history}. Returns 0 if successful, +or @code{errno} if not. +@end deftypefun + +@deftypefun int write_history (char *filename) +Write the current history to @var{filename}, overwriting @var{filename} +if necessary. If @var{filename} is +@code{NULL}, then write the history list to @file{~/.history}. Values +returned are as in @code{read_history ()}. +@end deftypefun + +@deftypefun int append_history (int nelements, char *filename) +Append the last @var{nelements} of the history list to @var{filename}. +@end deftypefun + +@deftypefun int history_truncate_file (char *filename, int nlines) +Truncate the history file @var{filename}, leaving only the last +@var{nlines} lines. +@end deftypefun + +@node History Expansion +@subsection History Expansion + +These functions implement @code{csh}-like history expansion. + +@deftypefun int history_expand (char *string, char **output) +Expand @var{string}, placing the result into @var{output}, a pointer +to a string (@pxref{History Interaction}). Returns: +@table @code +@item 0 +If no expansions took place (or, if the only change in +the text was the de-slashifying of the history expansion +character); +@item 1 +if expansions did take place; +@item -1 +if there was an error in expansion; +@item 2 +if the returned line should only be displayed, but not executed, +as with the @code{:p} modifier (@pxref{Modifiers}). +@end table + +If an error ocurred in expansion, then @var{output} contains a descriptive +error message. +@end deftypefun + +@deftypefun {char *} history_arg_extract (int first, int last, char *string) +Extract a string segment consisting of the @var{first} through @var{last} +arguments present in @var{string}. Arguments are broken up as in Bash. +@end deftypefun + +@deftypefun {char *} get_history_event (char *string, int *cindex, int qchar) +Returns the text of the history event beginning at @var{string} + +@var{*cindex}. @var{*cindex} is modified to point to after the event +specifier. At function entry, @var{cindex} points to the index into +@var{string} where the history event specification begins. @var{qchar} +is a character that is allowed to end the event specification in addition +to the ``normal'' terminating characters. +@end deftypefun + +@deftypefun {char **} history_tokenize (char *string) +Return an array of tokens parsed out of @var{string}, much as the +shell might. The tokens are split on white space and on the +characters @code{()<>;&|$}, and shell quoting conventions are +obeyed. +@end deftypefun + +@node History Variables +@section History Variables + +This section describes the externally visible variables exported by +the GNU History Library. + +@deftypevar int history_base +The logical offset of the first entry in the history list. +@end deftypevar + +@deftypevar int history_length +The number of entries currently stored in the history list. +@end deftypevar + +@deftypevar int max_input_history +The maximum number of history entries. This must be changed using +@code{stifle_history ()}. +@end deftypevar + +@deftypevar char history_expansion_char +The character that starts a history event. The default is @samp{!}. +@end deftypevar + +@deftypevar char history_subst_char +The character that invokes word substitution if found at the start of +a line. The default is @samp{^}. +@end deftypevar + +@deftypevar char history_comment_char +During tokenization, if this character is seen as the first character +of a word, then it and all subsequent characters up to a newline are +ignored, suppressing history expansion for the remainder of the line. +This is disabled by default. +@end deftypevar + +@deftypevar {char *} history_no_expand_chars +The list of characters which inhibit history expansion if found immediately +following @var{history_expansion_char}. The default is whitespace and +@samp{=}. +@end deftypevar + +@node History Programming Example +@section History Programming Example + +The following program demonstrates simple use of the GNU History Library. + +@smallexample +main () +@{ + char line[1024], *t; + int len, done = 0; + + line[0] = 0; + + using_history (); + while (!done) + @{ + printf ("history$ "); + fflush (stdout); + t = fgets (line, sizeof (line) - 1, stdin); + if (t && *t) + @{ + len = strlen (t); + if (t[len - 1] == '\n') + t[len - 1] = '\0'; + @} + + if (!t) + strcpy (line, "quit"); + + if (line[0]) + @{ + char *expansion; + int result; + + result = history_expand (line, &expansion); + if (result) + fprintf (stderr, "%s\n", expansion); + + if (result < 0 || result == 2) + @{ + free (expansion); + continue; + @} + + add_history (expansion); + strncpy (line, expansion, sizeof (line) - 1); + free (expansion); + @} + + if (strcmp (line, "quit") == 0) + done = 1; + else if (strcmp (line, "save") == 0) + write_history ("history_file"); + else if (strcmp (line, "read") == 0) + read_history ("history_file"); + else if (strcmp (line, "list") == 0) + @{ + register HIST_ENTRY **the_list; + register int i; + + the_list = history_list (); + if (the_list) + for (i = 0; the_list[i]; i++) + printf ("%d: %s\n", i + history_base, the_list[i]->line); + @} + else if (strncmp (line, "delete", 6) == 0) + @{ + int which; + if ((sscanf (line + 6, "%d", &which)) == 1) + @{ + HIST_ENTRY *entry = remove_history (which); + if (!entry) + fprintf (stderr, "No such entry %d\n", which); + else + @{ + free (entry->line); + free (entry); + @} + @} + else + @{ + fprintf (stderr, "non-numeric arg given to `delete'\n"); + @} + @} + @} +@} +@end smallexample diff --git a/doc/hsuser.texinfo b/doc/hsuser.texinfo new file mode 100644 index 0000000..51327a3 --- /dev/null +++ b/doc/hsuser.texinfo @@ -0,0 +1,198 @@ +@ignore +This file documents the user interface to the GNU History library. + +Copyright (C) 1988, 1991 Free Software Foundation, Inc. +Authored by Brian Fox and Chet Ramey. + +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 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). + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided also that the +GNU Copyright statement is available to the distributee, 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. +@end ignore + +@node Using History Interactively +@chapter Using History Interactively + +@ifset BashFeatures +This chapter describes how to use the GNU History Library interactively, +from a user's standpoint. It should be considered a user's guide. For +information on using the GNU History Library in your own programs, +see the GNU Readline Library Manual. +@end ifset +@ifclear BashFeatures +This chapter describes how to use the GNU History Library interactively, +from a user's standpoint. It should be considered a user's guide. For +information on using the GNU History Library in your own programs, +@pxref{Programming with GNU History}. +@end ifclear + +@menu +* History Interaction:: What it feels like using History as a user. +@end menu + +@node History Interaction +@section History Interaction +@cindex expansion + +The History library provides a history expansion feature that is similar +to the history expansion provided by @code{csh}. The following text +describes the syntax used to manipulate the history information. + +History expansion takes place in two parts. The first is to determine +which line from the previous history should be used during substitution. +The second is to select portions of that line for inclusion into the +current one. The line selected from the previous history is called the +@dfn{event}, and the portions of that line that are acted upon are +called @dfn{words}. The line is broken into words in the same fashion +that Bash does, so that several English (or Unix) words +surrounded by quotes are considered as one word. + +@menu +* Event Designators:: How to specify which history line to use. +* Word Designators:: Specifying which words are of interest. +* Modifiers:: Modifying the results of substitution. +@end menu + +@node Event Designators +@subsection Event Designators +@cindex event designators + +An event designator is a reference to a command line entry in the +history list. +@cindex history events + +@table @asis + +@item @code{!} +Start a history substitution, except when followed by a space, tab, +the end of the line, @key{=} or @key{(}. + +@item @code{!!} +Refer to the previous command. This is a synonym for @code{!-1}. + +@item @code{!n} +Refer to command line @var{n}. + +@item @code{!-n} +Refer to the command @var{n} lines back. + +@item @code{!string} +Refer to the most recent command starting with @var{string}. + +@item @code{!?string}[@code{?}] +Refer to the most recent command containing @var{string}. + +@item @code{!#} +The entire command line typed so far. + +@item @code{^string1^string2^} +Quick Substitution. Repeat the last command, replacing @var{string1} +with @var{string2}. Equivalent to +@code{!!:s/string1/string2/}. + +@end table + +@node Word Designators +@subsection Word Designators + +A @key{:} separates the event specification from the word designator. It +can be omitted if the word designator begins with a @key{^}, @key{$}, +@key{*} or @key{%}. Words are numbered from the beginning of the line, +with the first word being denoted by a 0 (zero). + +@table @code + +@item 0 (zero) +The @code{0}th word. For many applications, this is the command word. + +@item n +The @var{n}th word. + +@item ^ +The first argument; that is, word 1. + +@item $ +The last argument. + +@item % +The word matched by the most recent @code{?string?} search. + +@item x-y +A range of words; @code{-@var{y}} abbreviates @code{0-@var{y}}. + +@item * +All of the words, except the @code{0}th. This is a synonym for @code{1-$}. +It is not an error to use @key{*} if there is just one word in the event; +the empty string is returned in that case. + +@item x* +Abbreviates @code{x-$} + +@item x- +Abbreviates @code{x-$} like @code{x*}, but omits the last word. + +@end table + +@node Modifiers +@subsection Modifiers + +After the optional word designator, you can add a sequence of one or more +of the following modifiers, each preceded by a @key{:}. + +@table @code + +@item h +Remove a trailing pathname component, leaving only the head. + +@item r +Remove a trailing suffix of the form @samp{.}@var{suffix}, leaving the basename. + +@item e +Remove all but the trailing suffix. + +@item t +Remove all leading pathname components, leaving the tail. + +@item p +Print the new command but do not execute it. + +@ifset BashFeatures +@item q +Quote the substituted words, escaping further substitutions. + +@item x +Quote the substituted words as with @code{q}, +but break into words at spaces, tabs, and newlines. +@end ifset + +@item s/old/new/ +Substitute @var{new} for the first occurrence of @var{old} in the +event line. Any delimiter may be used in place of @key{/}. +The delimiter may be quoted in @var{old} and @var{new} +with a single backslash. If @key{&} appears in @var{new}, +it is replaced by @var{old}. A single backslash will quote +the @key{&}. The final delimiter is optional if it is the last +character on the input line. + +@item & +Repeat the previous substitution. + +@item g +Cause changes to be applied over the entire event line. Used in +conjunction with @code{s}, as in @code{gs/old/new/}, or with +@code{&}. + +@end table diff --git a/doc/readline.3 b/doc/readline.3 new file mode 100644 index 0000000..e3da7cc --- /dev/null +++ b/doc/readline.3 @@ -0,0 +1,1210 @@ +.\" +.\" MAN PAGE COMMENTS to +.\" +.\" Chet Ramey +.\" Information Network Services +.\" Case Western Reserve University +.\" chet@ins.CWRU.Edu +.\" +.\" Last Change: Mon Jun 13 20:06:14 EDT 1994 +.\" +.TH READLINE 3 "1994 June 13" GNU +.\" +.\" File Name macro. This used to be `.PN', for Path Name, +.\" but Sun doesn't seem to like that very much. +.\" +.de FN +\fI\|\\$1\|\fP +.. +.SH NAME +readline \- get a line from a user with editing +.SH SYNOPSIS +.LP +.nf +.ft B +#include +#include +.ft +.fi +.LP +.nf +.ft B +typedef int Function (); +.LP +.nf +.ft B +char *readline (prompt) +char *prompt; +.ft +.fi +.LP +.nf +.ft B +int rl_add_defun (name, function, key) +char *name; +Function *function; +int key; +.ft +.fi +.LP +.nf +.ft B +int rl_bind_key (key, function) +int key; +Function *function; +.ft +.fi +.LP +.nf +.ft B +int rl_unbind_key (key) +int key; +.ft +.fi +.LP +.nf +.ft B +int rl_bind_key_in_map (key, function, keymap) +int key; +Function *function; +Keymap keymap; +.ft +.fi +.LP +.nf +.ft B +int rl_unbind_key_in_map (key, keymap) +int key; +Keymap keymap; +.ft +.fi +.ft B +int rl_macro_bind (keyseq, macro, keymap) +char *keyseq, *macro; +Keymap keymap; +.ft +.fi +.LP +.nf +.ft B +int rl_variable_bind (variable, value) +char *variable, *value; +.ft +.fi +.LP +.nf +.LP +.nf +.ft B +int rl_parse_and_bind (line) +char *line; +.ft +.fi +.LP +.nf +.ft B +int rl_translate_keyseq (keyseq, array, len) +char *keyseq, *array; +int *len; +.ft +.fi +.LP +.nf +.ft B +Function *rl_named_function (command) +char *command; +.ft +.fi +.LP +.nf +.ft B +Function *rl_function_of_keyseq (keyseq, keymap, type) +char *keyseq; +Keymap keymap; +int *type; +.ft +.fi +.LP +.nf +.ft B +char **rl_invoking_keyseqs (function) +Function *function; +.ft +.fi +.LP +.nf +.ft B +char **rl_invoking_keyseqs_in_map (function, keymap) +Function *function; +Keymap keymap; +.ft +.fi +.LP +.nf +.ft B +void rl_function_dumper (readable) +int readable; +.ft +.fi +.LP +.nf +.ft B +char **rl_funmap_names () +.ft +.fi +.SH COPYRIGHT +.if n Readline is Copyright (C) 1989, 1991 by the Free Software Foundation, Inc. +.if t Readline is Copyright \(co 1989, 1991 by the Free Software Foundation, Inc. +.SH DESCRIPTION +.LP +.B readline +will read a line from the terminal +and return it, using +.B prompt +as a prompt. If +.B prompt +is null, no prompt is issued. The line returned is allocated with +.IR malloc (3), +so the caller must free it when finished. The line returned +has the final newline removed, so only the text of the line +remains. +.LP +.B readline +offers editing capabilities while the user is entering the +line. +By default, the line editing commands +are similar to those of emacs. +A vi\-style line editing interface is also available. +.LP +In the following descriptions, +.B keymap +can be one of \fIemacs_keymap, emacs_meta_keymap, emacs_ctlx_keymap, +vi_insertion_keymap, or vi_movement_keymap\fP. +.LP +.B rl_add_defun +makes +.B name +appear as a bindable readline command, and makes +.B function +be the function called when that command is invoked. If +.B key +is not \-1, it is bound to +.B function +in the current keymap. +.LP +.B rl_bind_key +causes +.B key +to invoke +.BR function . +The binding is made in the current keymap. +.LP +.B rl_unbind_key +removes the binding for +.B key +in the current keymap. +.LP +.B rl_bind_key_in_map +makes the +.B key +entry in +.B keymap +invoke +.BR function . +.LP +.B rl_unbind_key_in_map +removes the binding for +.B key +in keymap +.BR keymap . +.LP +.B rl_macro_bind +makes +.B keyseq +insert the string +.BR macro . +The binding is performed in +.BR keymap . +.LP +.B rl_variable_bind +sets the value of the readline variable +.B variable +to +.BR value . +.LP +.B rl_parse_and_bind +takes as an argument a line of the same form as the readline startup +file (see +.SM +.B INITIALIZATION FILE +below) and executes the commands therein. +.LP +.B rl_translate_keyseq +converts +.B keyseq +into a new string, storing the result in +.BR array . +This translates control and meta prefixes and the readline +character escape sequences (see +.SM +.B Key Bindings +below). The length of the translated sequence is returned in +.BR *len . +.LP +.B rl_named_function +returns the function that is executed when the readline +command +.B command +is invoked. +.LP +.B rl_function_of_keyseq +returns the function that is executed when +.B keyseq +is read and +.B keymap +is the current keymap. +.B type +is set to indicate whether the return value corresponds to a +function, macro, or auxiliary keymap. +.LP +.B rl_invoking_keyseqs +returns all of the key sequences in the current keymap that +invoke +.BR function . +.LP +.B rl_invoking_keyseqs_in_map +returns all of the key sequences in +.B keymap +that invoke +.BR function . +.LP +.B rl_function_dumper +prints all of the readline functions and their bindings to the +readline output stream. If +.B readable +is non\-zero, the output is formattted so that it can be read +back in to restore the bindings. +.LP +.B rl_funmap_names +returns an array of all known readline bindable function names. +The array is sorted. +.SH RETURN VALUE +.LP +.B readline +returns the text of the line read. A blank line +returns the empty string. If +.B EOF +is encountered while reading a line, and the line is empty, +.B NULL +is returned. If an +.B EOF +is read with a non\-empty line, it is +treated as a newline. +.LP +Unless otherwise stated, +the other functions return 0 on success and non\-zero on failure. +.SH NOTATION +.LP +An emacs\-style notation is used to denote +keystrokes. Control keys are denoted by C\-\fIkey\fR, e.g., C\-n +means Control\-N. Similarly, +.I meta +keys are denoted by M\-\fIkey\fR, so M\-x means Meta\-X. (On keyboards +without a +.I meta +key, M\-\fIx\fP means ESC \fIx\fP, i.e., press the Escape key +then the +.I x +key. This makes ESC the \fImeta prefix\fP. +The combination M\-C\-\fIx\fP means ESC\-Control\-\fIx\fP, +or press the Escape key +then hold the Control key while pressing the +.I x +key.) +.PP +Readline commands may be given numeric +.IR arguments , +which normally act as a repeat count. Sometimes, however, it is the +sign of the argument that is significant. Passing a negative argument +to a command that acts in the forward direction (e.g., \fBkill\-line\fP) +causes that command to act in a backward direction. Commands whose +behavior with arguments deviates from this are noted. +.PP +When a command is described as \fIkilling\fP text, the text +deleted is saved for possible future retrieval +(\fIyanking\fP). The killed text is saved in a +\fIkill\-ring\fP. Consecutive kills cause the text to be +accumulated into one unit, which can be yanked all at once. +Commands which do not kill text separate the chunks of text +on the kill\-ring. +.SH INITIALIZATION FILE +.LP +Readline is customized by putting commands in an initialization +file. The name of this file is taken from the value of the +.B INPUTRC +variable. If that variable is unset, the default is +.IR ~/.inputrc . +When a program which uses the readline library starts up, the +init file is read, and the key bindings and variables are set. +There are only a few basic constructs allowed in the +readline init file. Blank lines are ignored. +Lines beginning with a \fB#\fP are comments. +Lines beginning with a \fB$\fP indicate conditional +constructs. Other lines +denote key bindings and variable settings. +Each program using this library may add its own commands +and bindings. +.PP +For example, placing +.RS +.PP +M\-Control\-u: universal\-argument +.RE +or +.RS +C\-Meta\-u: universal\-argument +.RE +into the +.FN ~/.inputrc +would make M\-C\-u execute the readline command +.IR universal\-argument . +.PP +The following symbolic character names are recognized while +processing key bindings: +.IR RUBOUT , +.IR DEL , +.IR ESC , +.IR LFD , +.IR NEWLINE , +.IR RET , +.IR RETURN , +.IR SPC , +.IR SPACE , +and +.IR TAB . +In addition to command names, readline allows keys to be bound +to a string that is inserted when the key is pressed (a \fImacro\fP). +.PP +.SS Key Bindings +.PP +The syntax for controlling key bindings in the +.I ~/.inputrc +file is simple. All that is required is the name of the +command or the text of a macro and a key sequence to which +it should be bound. The name may be specified in one of two ways: +as a symbolic key name, possibly with \fIMeta\-\fP or \fIControl\-\fP +prefixes, or as a key sequence. +When using the form \fBkeyname\fP:\fIfunction-name\fP or \fImacro\fP, +.I keyname +is the name of a key spelled out in English. For example: +.sp +.RS +Control\-u: universal\-argument +.br +Meta\-Rubout: backward\-kill\-word +.br +Control\-o: ">&output" +.RE +.LP +In the above example, +.I C\-u +is bound to the function +.BR universal\-argument , +.I M-DEL +is bound to the function +.BR backward\-kill\-word , +and +.I C\-o +is bound to run the macro +expressed on the right hand side (that is, to insert the text +.I >&output +into the line). +.PP +In the second form, \fB"keyseq"\fP:\fIfunction\-name\fP or \fImacro\fP, +.B keyseq +differs from +.B keyname +above in that strings denoting +an entire key sequence may be specified by placing the sequence +within double quotes. Some GNU Emacs style key escapes can be +used, as in the following example. +.sp +.RS +"\eC\-u": universal\-argument +.br +"\eC\-x\eC\-r": re\-read\-init\-file +.br +"\ee[11~": "Function Key 1" +.RE +.PP +In this example, +.I C-u +is again bound to the function +.BR universal\-argument . +.I "C-x C-r" +is bound to the function +.BR re\-read\-init\-file , +and +.I "ESC [ 1 1 ~" +is bound to insert the text +.BR "Function Key 1" . +The full set of escape sequences is +.RS +.TP +.B \eC- +control prefix +.TP +.B \eM- +meta prefix +.TP +.B \ee +an escape character +.TP +.B \e\e +backslash +.TP +.B \e" +literal " +.TP +.B \e' +literal ' +.RE +.PP +When entering the text of a macro, single or double quotes should +be used to indicate a macro definition. Unquoted text +is assumed to be a function name. Backslash +will quote any character in the macro text, including " and '. +.PP +.B Bash +allows the current readline key bindings to be displayed or modified +with the +.B bind +builtin command. The editing mode may be switched during interactive +use by using the +.B \-o +option to the +.B set +builtin command. Other programs using this library provide +similar mechanisms. The +.I inputrc +file may be edited and re\-read if a program does not provide +any other means to incorporate new bindings. +.SS Variables +.PP +Readline has variables that can be used to further customize its +behavior. A variable may be set in the +.I inputrc +file with a statement of the form +.RS +.PP +\fBset\fP \fIvariable\-name\fP \fIvalue\fP +.RE +.PP +Except where noted, readline variables can take the values +.B On +or +.BR Off . +The variables and their default values are: +.PP +.PD 0 +.TP +.B horizontal\-scroll\-mode (Off) +When set to \fBOn\fP, makes readline use a single line for display, +scrolling the input horizontally on a single screen line when it +becomes longer than the screen width rather than wrapping to a new line. +.TP +.B editing\-mode (emacs) +Controls whether readline begins with a set of key bindings similar +to \fIemacs\fP or \fIvi\fP. +.B editing\-mode +can be set to either +.B emacs +or +.BR vi . +.TP +.B mark\-modified\-lines (Off) +If set to \fBOn\fP, history lines that have been modified are displayed +with a preceding asterisk (\fB*\fP). +.TP +.B bell\-style (audible) +Controls what happens when readline wants to ring the terminal bell. +If set to \fBnone\fP, readline never rings the bell. If set to +\fBvisible\fP, readline uses a visible bell if one is available. +If set to \fBaudible\fP, readline attempts to ring the terminal's bell. +.TP +.B comment\-begin (``#'') +The string that is inserted in \fBvi\fP mode when the +.B vi\-comment +command is executed. +.TP +.B meta\-flag (Off) +If set to \fBOn\fP, readline will enable eight-bit input (that is, +it will not strip the high bit from the characters it reads), +regardless of what the terminal claims it can support. +.TP +.B convert\-meta (On) +If set to \fBOn\fP, readline will convert characters with the +eighth bit set to an ASCII key sequence +by stripping the eighth bit and prepending an +escape character (in effect, using escape as the \fImeta prefix\fP). +.TP +.B output\-meta (Off) +If set to \fBOn\fP, readline will display characters with the +eighth bit set directly rather than as a meta-prefixed escape +sequence. +.TP +.B completion\-query\-items (100) +This determines when the user is queried about viewing +the number of possible completions +generated by the \fBpossible\-completions\fP command. +It may be set to any integer value greater than or equal to +zero. If the number of possible completions is greater than +or equal to the value of this variable, the user is asked whether +or not he wishes to view them; otherwise they are simply listed +on the terminal. +.TP +.B keymap (emacs) +Set the current readline keymap. The set of legal keymap names is +\fIemacs, emacs-standard, emacs-meta, emacs-ctlx, vi, vi-move, +vi-command\fP, and +.IR vi-insert . +\fIvi\fP is equivalent to \fIvi-command\fP; \fIemacs\fP is +equivalent to \fIemacs-standard\fP. The default value is +.IR emacs ; +the value of +.B editing\-mode +also affects the default keymap. +.TP +.B show\-all\-if\-ambiguous (Off) +This alters the default behavior of the completion functions. If +set to +.BR on , +words which have more than one possible completion cause the +matches to be listed immediately instead of ringing the bell. +.TP +.B expand\-tilde (Off) +If set to \fBon\fP, tilde expansion is performed when readline +attempts word completion. +.PD +.SS Conditional Constructs +.PP +Readline implements a facility similar in spirit to the conditional +compilation features of the C preprocessor which allows key +bindings and variable settings to be performed as the result +of tests. There are three parser directives used. +.IP \fB$if\fP +The +.B $if +construct allows bindings to be made based on the +editing mode, the terminal being used, or the application using +readline. The text of the test extends to the end of the line; +no characters are required to isolate it. +.RS +.IP \fBmode\fP +The \fBmode=\fP form of the \fB$if\fP directive is used to test +whether readline is in emacs or vi mode. +This may be used in conjunction +with the \fBset keymap\fP command, for instance, to set bindings in +the \fIemacs-standard\fP and \fIemacs-ctlx\fP keymaps only if +readline is starting out in emacs mode. +.IP \fBterm\fP +The \fBterm=\fP form may be used to include terminal-specific +key bindings, perhaps to bind the key sequences output by the +terminal's function keys. The word on the right side of the +.B = +is tested against the full name of the terminal and the portion +of the terminal name before the first \fB\-\fP. This allows +.I sun +to match both +.I sun +and +.IR sun\-cmd , +for instance. +.IP \fBapplication\fP +The \fBapplication\fP construct is used to include +application\-specific settings. Each program using the readline +library sets the \fIapplication name\fP, and an initialization +file can test for a particular value. +This could be used to bind key sequences to functions useful for +a specific program. For instance, the following command adds a +key sequence that quotes the current or previous word in Bash: +.RS +.nf +\fB$if\fP bash +# Quote the current or previous word +"\eC-xq": "\eeb\e"\eef\e"" +\fB$endif\fP +.fi +.RE +.RE +.IP \fB$endif\fP +This command, as you saw in the previous example, terminates an +\fB$if\fP command. +.IP \fB$else\fP +Commands in this branch of the \fB$if\fP directive are executed if +the test fails. +.SH EDITING COMMANDS +.PP +The following is a list of the names of the commands and the default +key sequences to which they are bound. +.SS Commands for Moving +.PP +.PD 0 +.TP +.B beginning\-of\-line (C\-a) +Move to the start of the current line. +.TP +.B end\-of\-line (C\-e) +Move to the end of the line. +.TP +.B forward\-char (C\-f) +Move forward a character. +.TP +.B backward\-char (C\-b) +Move back a character. +.TP +.B forward\-word (M\-f) +Move forward to the end of the next word. Words are composed of +alphanumeric characters (letters and digits). +.TP +.B backward\-word (M\-b) +Move back to the start of this, or the previous, word. Words are +composed of alphanumeric characters (letters and digits). +.TP +.B clear\-screen (C\-l) +Clear the screen leaving the current line at the top of the screen. +With an argument, refresh the current line without clearing the +screen. +.TP +.B redraw\-current\-line +Refresh the current line. By default, this is unbound. +.PD +.SS Commands for Manipulating the History +.PP +.PD 0 +.TP +.B accept\-line (Newline, Return) +Accept the line regardless of where the cursor is. If this line is +non\-empty, add it to the history list. If the line is a modified +history line, then restore the history line to its original state. +.TP +.B previous\-history (C\-p) +Fetch the previous command from the history list, moving back in +the list. +.TP +.B next\-history (C\-n) +Fetch the next command from the history list, moving forward in the +list. +.TP +.B beginning\-of\-history (M\-<) +Move to the first line in the history. +.TP +.B end\-of\-history (M\->) +Move to the end of the input history, i.e., the line currently being +entered. +.TP +.B reverse\-search\-history (C\-r) +Search backward starting at the current line and moving `up' through +the history as necessary. This is an incremental search. +.TP +.B forward\-search\-history (C\-s) +Search forward starting at the current line and moving `down' through +the history as necessary. This is an incremental search. +.TP +.B non\-incremental\-reverse\-search\-history (M\-p) +Search backward through the history starting at the current line +using a non\-incremental search for a string supplied by the user. +.TP +.B non\-incremental\-forward\-search\-history (M\-n) +Search forward through the history using a non\-incremental search +for a string supplied by the user. +.TP +.B history\-search\-forward +Search forward through the history for the string of characters +between the start of the current line and the current point. This +is a non-incremental search. By default, this command is unbound. +.TP +.B history\-search\-backward +Search backward through the history for the string of characters +between the start of the current line and the current point. This +is a non-incremental search. By default, this command is unbound. +.TP +.B yank\-nth\-arg (M\-C\-y) +Insert the first argument to the previous command (usually +the second word on the previous line) at point (the current +cursor position). With an argument +.IR n , +insert the \fIn\fPth word from the previous command (the words +in the previous command begin with word 0). A negative argument +inserts the \fIn\fPth word from the end of the previous command. +.PD +.SS Commands for Changing Text +.PP +.PD 0 +.TP +.B delete\-char (C\-d) +Delete the character under the cursor. If point is at the +beginning of the line, there are no characters in the line, and +the last character typed was not +.BR C\-d , +then return +.SM +.BR EOF . +.TP +.B backward\-delete\-char (Rubout) +Delete the character behind the cursor. When given a numeric argument, +save the deleted text on the kill\-ring. +.TP +.B quoted\-insert (C\-q, C\-v) +Add the next character that you type to the line verbatim. This is +how to insert characters like \fBC\-q\fP, for example. +.TP +.B tab\-insert (M-TAB) +Insert a tab character. +.TP +.B self\-insert (a,\ b,\ A,\ 1,\ !,\ ...) +Insert the character typed. +.TP +.B transpose\-chars (C\-t) +Drag the character before point forward over the character at point. +Point moves forward as well. If point is at the end of the line, then +transpose the two characters before point. Negative arguments don't work. +.TP +.B transpose\-words (M\-t) +Drag the word behind the cursor past the word in front of the cursor +moving the cursor over that word as well. +.TP +.B upcase\-word (M\-u) +Uppercase the current (or following) word. With a negative argument, +do the previous word, but do not move point. +.TP +.B downcase\-word (M\-l) +Lowercase the current (or following) word. With a negative argument, +do the previous word, but do not move point. +.TP +.B capitalize\-word (M\-c) +Capitalize the current (or following) word. With a negative argument, +do the previous word, but do not move point. +.PD +.SS Killing and Yanking +.PP +.PD 0 +.TP +.B kill\-line (C\-k) +Kill the text from the current cursor position to the end of the line. +.TP +.B backward\-kill\-line (C\-x Rubout) +Kill backward to the beginning of the line. +.TP +.B unix\-line\-discard (C\-u) +Kill backward from point to the beginning of the line. +.\" There is no real difference between this and backward-kill-line +.TP +.B kill\-whole\-line +Kill all characters on the current line, no matter where the +cursor is. By default, this is unbound. +.TP +.B kill\-word (M\-d) +Kill from the cursor to the end of the current word, or if between +words, to the end of the next word. Word boundaries are the same as +those used by \fBforward\-word\fP. +.TP +.B backward\-kill\-word (M\-Rubout) +Kill the word behind the cursor. Word boundaries are the same as +those used by \fBbackward\-word\fP. +.TP +.B unix\-word\-rubout (C\-w) +Kill the word behind the cursor, using white space as a word boundary. +The word boundaries are different from +.BR backward\-kill\-word . +.TP +.B delete\-horizontal\-space +Delete all spaces and tabs around point. By default, this is unbound. +.TP +.B yank (C\-y) +Yank the top of the kill ring into the buffer at the cursor. +.TP +.B yank\-pop (M\-y) +Rotate the kill\-ring, and yank the new top. Only works following +.B yank +or +.BR yank\-pop . +.PD +.SS Numeric Arguments +.PP +.PD 0 +.TP +.B digit\-argument (M\-0, M\-1, ..., M\-\-) +Add this digit to the argument already accumulating, or start a new +argument. M\-\- starts a negative argument. +.TP +.B universal\-argument +Each time this is executed, the argument count is multiplied by four. +The argument count is initially one, so executing this function the +first time makes the argument count four. By default, this is not +bound to a key. +.PD +.SS Completing +.PP +.PD 0 +.TP +.B complete (TAB) +Attempt to perform completion on the text before point. +The actual completion performed is application-specific. +.BR Bash , +for instance, attempts completion treating the text as a variable +(if the text begins with \fB$\fP), username (if the text begins with +\fB~\fP), hostname (if the text begins with \fB@\fP), or +command (including aliases and functions) in turn. If none +of these produces a match, filename completion is attempted. +.BR Gdb , +on the other hand, +allows completion of program functions and variables, and +only attempts filename completion under certain circumstances. +.TP +.B possible\-completions (M-?) +List the possible completions of the text before point. +.TP +.B insert\-completions +Insert all completions of the text before point +that would have been generated by +\fBpossible\-completions\fP. By default, this +is not bound to a key. +.PD +.SS Keyboard Macros +.PP +.PD 0 +.TP +.B start\-kbd\-macro (C-x (\^) +Begin saving the characters typed into the current keyboard macro. +.TP +.B end\-kbd\-macro (C-x )\^) +Stop saving the characters typed into the current keyboard macro +and save the definition. +.TP +.B call\-last\-kbd\-macro (C-x e) +Re-execute the last keyboard macro defined, by making the characters +in the macro appear as if typed at the keyboard. +.PD +.SS Miscellaneous +.PP +.PD 0 +.TP +.B re-read-init-file (C\-x C\-r) +Read in the contents of your init file, and incorporate +any bindings or variable assignments found there. +.TP +.B abort (C\-g) +Abort the current editing command and +ring the terminal's bell (subject to the setting of +.BR bell\-style ). +.TP +.B do\-uppercase\-version (M\-a, M\-b, ...) +Run the command that is bound to the corresponding uppercase +character. +.TP +.B prefix\-meta (ESC) +Metafy the next character typed. +.SM +.B ESC +.B f +is equivalent to +.BR Meta\-f . +.TP +.B undo (C\-_, C\-x C\-u) +Incremental undo, separately remembered for each line. +.TP +.B revert\-line (M\-r) +Undo all changes made to this line. This is like typing the +.B undo +command enough times to return the line to its initial state. +.TP +.B tilde\-expand (M\-~) +Perform tilde expansion on the current word. +.TP +.B dump\-functions +Print all of the functions and their key bindings to the +readline output stream. If a numeric argument is supplied, +the output is formatted in such a way that it can be made part +of an \fIinputrc\fP file. +.TP +.B emacs\-editing\-mode (C\-e) +When in +.B vi +editing mode, this causes a switch to +.B emacs +editing mode. +.TP +.B vi\-editing\-mode (M\-C\-j) +When in +.B emacs +editing mode, this causes a switch to +.B vi +editing mode. +.PD +.SH DEFAULT KEY BINDINGS +.LP +The following is a list of the default emacs and vi bindings. +Characters with the 8th bit set are written as M-, and +are referred to as +.I metafied +characters. +The printable ASCII characters not mentioned in the list of emacs +standard bindings are bound to the +.I self\-insert +function, which just inserts the given character into the input line. +In vi insertion mode, all characters not specifically mentioned are +bound to +.IR self\-insert . +Characters assigned to signal generation by +.IR stty (1) +or the terminal driver, such as C-Z or C-C, +retain that function. +Upper and lower case +.I metafied +characters are bound to the same function in the emacs mode +meta keymap. +The remaining characters are unbound, which causes readline +to ring the bell (subject to the setting of the +.B bell\-style +variable). +.SS Emacs Mode +.RS +.6i +.nf +.ta 2.5i +.sp +Emacs Standard bindings +.sp +"C-A" -> beginning-of-line +"C-B" -> backward-char +"C-D" -> delete-char +"C-E" -> end-of-line +"C-F" -> forward-char +"C-G" -> abort +"C-H" -> backward-delete-char +"C-I" -> complete +"C-J" -> accept-line +"C-K" -> kill-line +"C-L" -> clear-screen +"C-M" -> accept-line +"C-N" -> next-history +"C-P" -> previous-history +"C-Q" -> quoted-insert +"C-R" -> reverse-search-history +"C-S" -> forward-search-history +"C-T" -> transpose-chars +"C-U" -> unix-line-discard +"C-V" -> quoted-insert +"C-W" -> unix-word-rubout +"C-Y" -> yank +"C-_" -> undo +"\^ " to "/" -> self-insert +"0" to "9" -> self-insert +":" to "~" -> self-insert +"C-?" -> backward-delete-char +.PP +Emacs Meta bindings +.sp +"M-C-H" -> backward-kill-word +"M-C-I" -> tab-insert +"M-C-J" -> vi-editing-mode +"M-C-M" -> vi-editing-mode +"M-C-R" -> revert-line +"M-C-Y" -> yank-nth-arg +"M-C-[" -> complete +"M-&" -> tilde-expand +"M--" -> digit-argument +"M-0" -> digit-argument +"M-1" -> digit-argument +"M-2" -> digit-argument +"M-3" -> digit-argument +"M-4" -> digit-argument +"M-5" -> digit-argument +"M-6" -> digit-argument +"M-7" -> digit-argument +"M-8" -> digit-argument +"M-9" -> digit-argument +"M-<" -> beginning-of-history +"M->" -> end-of-history +"M-?" -> possible-completions +"M-B" -> backward-word +"M-C" -> capitalize-word +"M-D" -> kill-word +"M-F" -> forward-word +"M-L" -> downcase-word +"M-N" -> non-incremental-forward-search-history +"M-O" -> arrow-key-prefix +"M-P" -> non-incremental-reverse-search-history +"M-R" -> revert-line +"M-T" -> transpose-words +"M-U" -> upcase-word +"M-Y" -> yank-pop +"M-C-Y" -> yank-nth-arg +"M-C-?" -> backward-delete-word +.PP +Emacs Control-X bindings +.sp +"C-XC-G" -> abort +"C-XC-R" -> re-read-init-file +"C-XC-U" -> undo +"C-X(" -> start-kbd-macro +"C-X)" -> end-kbd-macro +"C-Xe" -> call-last-kbd-macro +"C-XC-?" -> backward-kill-line +.sp +.RE +.SS VI Mode bindings +.RS +.6i +.nf +.ta 2.5i +.sp +.PP +VI Insert Mode functions +.sp +"C-D" -> vi-eof-maybe +"C-H" -> backward-delete-char +"C-I" -> complete +"C-J" -> accept-line +"C-K" -> kill-line +"C-L" -> clear-screen +"C-M" -> accept-line +"C-N" -> next-history +"C-P" -> previous-history +"C-Q" -> quoted-insert +"C-R" -> reverse-search-history +"C-S" -> forward-search-history +"C-T" -> transpose-chars +"C-U" -> unix-line-discard +"C-V" -> quoted-insert +"C-W" -> unix-word-rubout +"C-Y" -> yank +"C-[" -> vi-movement-mode +"\^ " to "~" -> self-insert +"C-?" -> backward-delete-char +.PP +VI Command Mode functions +.sp +"C-D" -> vi-eof-maybe +"C-E" -> emacs-editing-mode +"C-G" -> abort +"C-H" -> backward-char +"C-J" -> accept-line +"C-K" -> kill-line +"C-L" -> clear-screen +"C-M" -> accept-line +"C-N" -> next-history +"C-P" -> previous-history +"C-Q" -> quoted-insert +"C-R" -> reverse-search-history +"C-S" -> forward-search-history +"C-T" -> transpose-chars +"C-U" -> unix-line-discard +"C-V" -> quoted-insert +"C-W" -> unix-word-rubout +"C-Y" -> yank +"C-[" -> abort +"\^ " -> forward-char +"#" -> vi-comment +"$" -> end-of-line +"%" -> vi-match +"&" -> vi-tilde-expand +"*" -> vi-complete +"+" -> down-history +"," -> vi-char-search +"-" -> previous-history +"." -> vi-redo +"/" -> vi-search +"0" -> beginning-of-line +"1" to "9" -> vi-arg-digit +";" -> vi-char-search +"=" -> vi-complete +"?" -> vi-search +"@" -> is undefined +"A" -> vi-append-eol +"B" -> vi-prev-word +"C" -> vi-change-to +"D" -> vi-delete-to +"E" -> vi-end-word +"F" -> vi-char-search +"I" -> vi-insert-beg +"N" -> vi-search-again +"P" -> vi-put +"R" -> vi-replace +"S" -> vi-subst +"T" -> vi-char-search +"U" -> revert-line +"W" -> vi-next-word +"X" -> backward-delete-char +"Y" -> vi-yank-to +"\e" -> vi-complete +"^" -> vi-first-print +"_" -> vi-yank-arg +"a" -> vi-append-mode +"b" -> vi-prev-word +"c" -> vi-change-to +"d" -> vi-delete-to +"e" -> vi-end-word +"f" -> vi-char-search +"h" -> backward-char +"i" -> vi-insertion-mode +"j" -> next-history +"k" -> prev-history +"l" -> forward-char +"n" -> vi-search-again +"r" -> vi-change-char +"s" -> vi-subst +"t" -> vi-char-search +"u" -> undo +"w" -> vi-next-word +"x" -> vi-delete +"y" -> vi-yank-to +"|" -> vi-column +"~" -> vi-change-case +.RE +.SH "SEE ALSO" +.PD 0 +.TP +\fIThe Gnu Readline Library\fP, Brian Fox +.TP +\fIThe Gnu History Library\fP, Brian Fox +.TP +\fIbash\fP(1) +.PD +.SH FILES +.PD 0 +.TP +.FN ~/.inputrc +Individual \fBreadline\fP initialization file +.PD +.SH AUTHORS +.RS +Brian Fox, Free Software Foundation (primary author) +.br +bfox@ai.MIT.Edu +.PP +Chet Ramey, Case Western Reserve University +.br +chet@ins.CWRU.Edu +.SH BUG REPORTS +If you find a bug in +.B readline, +you should report it. But first, you should +make sure that it really is a bug, and that it appears in the latest +version of the +.B readline +library that you have. +.PP +Once you have determined that a bug actually exists, mail a +bug report to \fIbash\-maintainers\fP@\fIprep.ai.MIT.Edu\fP. +If you have a fix, you are welcome to mail that +as well! Suggestions and `philosophical' bug reports may be mailed +to \fPbug-bash\fP@\fIprep.ai.MIT.Edu\fP or posted to the Usenet +newsgroup +.BR gnu.bash.bug . +.PP +Comments and bug reports concerning +this manual page should be directed to +.IR chet@ins.CWRU.Edu . +.SH BUGS +.PP +It's too big and too slow. diff --git a/doc/readline.dvi b/doc/readline.dvi new file mode 100644 index 0000000..a967128 Binary files /dev/null and b/doc/readline.dvi differ diff --git a/doc/readline.info b/doc/readline.info new file mode 100644 index 0000000..f4882e9 --- /dev/null +++ b/doc/readline.info @@ -0,0 +1,74 @@ +This is Info file readline.info, produced by Makeinfo-1.55 from the +input file rlman.texinfo. + + This document describes the GNU Readline Library, a utility which +aids in the consistency of user interface across discrete programs that +need to provide a command line interface. + + Copyright (C) 1988, 1991 Free Software Foundation, Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice pare +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 Foundation. + + +Indirect: +readline.info-1: 1000 +readline.info-2: 50467 + +Tag Table: +(Indirect) +Node: Top1000 +Node: Command Line Editing1613 +Node: Introduction and Notation2264 +Node: Readline Interaction3284 +Node: Readline Bare Essentials4423 +Node: Readline Movement Commands5953 +Node: Readline Killing Commands6844 +Node: Readline Arguments8547 +Node: Readline Init File9498 +Node: Readline Init Syntax10502 +Node: Conditional Init Constructs17435 +Node: Bindable Readline Commands19681 +Node: Commands For Moving20351 +Node: Commands For History21199 +Node: Commands For Text23783 +Node: Commands For Killing25522 +Node: Numeric Arguments26971 +Node: Commands For Completion27598 +Node: Keyboard Macros28525 +Node: Miscellaneous Commands29084 +Node: Readline vi Mode30372 +Node: Programming with GNU Readline32122 +Node: Basic Behavior32919 +Node: Custom Functions36232 +Node: The Function Type36845 +Node: Function Writing37690 +Node: Readline Convenience Functions40453 +Node: Function Naming41118 +Node: Keymaps42345 +Node: Binding Keys43856 +Node: Associating Function Names and Bindings45650 +Node: Allowing Undoing46812 +Node: Redisplay49397 +Node: Modifying Text50467 +Node: Utility Functions51378 +Node: Custom Completers54444 +Node: How Completing Works55165 +Node: Completion Functions58156 +Node: Completion Variables61171 +Node: A Short Completion Example64996 +Node: Concept Index77230 +Node: Function and Variable Index77717 + +End Tag Table diff --git a/doc/readline.info-1 b/doc/readline.info-1 new file mode 100644 index 0000000..78bbd05 --- /dev/null +++ b/doc/readline.info-1 @@ -0,0 +1,1322 @@ +This is Info file readline.info, produced by Makeinfo-1.55 from the +input file rlman.texinfo. + + This document describes the GNU Readline Library, a utility which +aids in the consistency of user interface across discrete programs that +need to provide a command line interface. + + Copyright (C) 1988, 1991 Free Software Foundation, Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice pare +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 Foundation. + + +File: readline.info, Node: Top, Next: Command Line Editing, Prev: (DIR), Up: (DIR) + +GNU Readline Library +******************** + + This document describes the GNU Readline Library, a utility which +aids in the consistency of user interface across discrete programs that +need to provide a command line interface. + +* Menu: + +* Command Line Editing:: GNU Readline User's Manual. +* Programming with GNU Readline:: GNU Readline Programmer's Manual. +* Concept Index:: Index of concepts described in this manual. +* Function and Variable Index:: Index of externally visible functions + and variables. + + +File: readline.info, Node: Command Line Editing, Next: Programming with GNU Readline, Prev: Top, Up: Top + +Command Line Editing +******************** + + This chapter describes the basic features of the GNU command line +editing interface. + +* Menu: + +* Introduction and Notation:: Notation used in this text. +* Readline Interaction:: The minimum set of commands for editing a line. +* Readline Init File:: Customizing Readline from a user's view. +* Bindable Readline Commands:: A description of most of the Readline commands + available for binding +* Readline vi Mode:: A short description of how to make Readline + behave like the vi editor. + + +File: readline.info, Node: Introduction and Notation, Next: Readline Interaction, Up: Command Line Editing + +Introduction to Line Editing +============================ + + The following paragraphs describe the notation used to represent +keystrokes. + + The text C-k is read as `Control-K' and describes the character +produced when the Control key is depressed and the k key is struck. + + The text M-k is read as `Meta-K' and describes the character +produced when the meta key (if you have one) is depressed, and the k +key is struck. If you do not have a meta key, the identical keystroke +can be generated by typing ESC first, and then typing k. Either +process is known as "metafying" the k key. + + The text M-C-k is read as `Meta-Control-k' and describes the +character produced by "metafying" C-k. + + In addition, several keys have their own names. Specifically, DEL, +ESC, LFD, SPC, RET, and TAB all stand for themselves when seen in this +text, or in an init file (*note Readline Init File::., for more info). + + +File: readline.info, Node: Readline Interaction, Next: Readline Init File, Prev: Introduction and Notation, Up: Command Line Editing + +Readline Interaction +==================== + + Often during an interactive session you type in a long line of text, +only to notice that the first word on the line is misspelled. The +Readline library gives you a set of commands for manipulating the text +as you type it in, allowing you to just fix your typo, and not forcing +you to retype the majority of the line. Using these editing commands, +you move the cursor to the place that needs correction, and delete or +insert the text of the corrections. Then, when you are satisfied with +the line, you simply press RETURN. You do not have to be at the end of +the line to press RETURN; the entire line is accepted regardless of the +location of the cursor within the line. + +* Menu: + +* Readline Bare Essentials:: The least you need to know about Readline. +* Readline Movement Commands:: Moving about the input line. +* Readline Killing Commands:: How to delete text, and how to get it back! +* Readline Arguments:: Giving numeric arguments to commands. + + +File: readline.info, Node: Readline Bare Essentials, Next: Readline Movement Commands, Up: Readline Interaction + +Readline Bare Essentials +------------------------ + + In order to enter characters into the line, simply type them. The +typed character appears where the cursor was, and then the cursor moves +one space to the right. If you mistype a character, you can use your +erase character to back up and delete the mistyped character. + + Sometimes you may miss typing a character that you wanted to type, +and not notice your error until you have typed several other +characters. In that case, you can type C-b to move the cursor to the +left, and then correct your mistake. Afterwards, you can move the +cursor to the right with C-f. + + When you add text in the middle of a line, you will notice that +characters to the right of the cursor are `pushed over' to make room +for the text that you have inserted. Likewise, when you delete text +behind the cursor, characters to the right of the cursor are `pulled +back' to fill in the blank space created by the removal of the text. A +list of the basic bare essentials for editing the text of an input line +follows. + +C-b + Move back one character. + +C-f + Move forward one character. + +DEL + Delete the character to the left of the cursor. + +C-d + Delete the character underneath the cursor. + +Printing characters + Insert the character into the line at the cursor. + +C-_ + Undo the last thing that you did. You can undo all the way back + to an empty line. + + +File: readline.info, Node: Readline Movement Commands, Next: Readline Killing Commands, Prev: Readline Bare Essentials, Up: Readline Interaction + +Readline Movement Commands +-------------------------- + + The above table describes the most basic possible keystrokes that +you need in order to do editing of the input line. For your +convenience, many other commands have been added in addition to C-b, +C-f, C-d, and DEL. Here are some commands for moving more rapidly +about the line. + +C-a + Move to the start of the line. + +C-e + Move to the end of the line. + +M-f + Move forward a word. + +M-b + Move backward a word. + +C-l + Clear the screen, reprinting the current line at the top. + + Notice how C-f moves forward a character, while M-f moves forward a +word. It is a loose convention that control keystrokes operate on +characters while meta keystrokes operate on words. + + +File: readline.info, Node: Readline Killing Commands, Next: Readline Arguments, Prev: Readline Movement Commands, Up: Readline Interaction + +Readline Killing Commands +------------------------- + + "Killing" text means to delete the text from the line, but to save +it away for later use, usually by "yanking" (re-inserting) it back into +the line. If the description for a command says that it `kills' text, +then you can be sure that you can get the text back in a different (or +the same) place later. + + When you use a kill command, the text is saved in a "kill-ring". +Any number of consecutive kills save all of the killed text together, so +that when you yank it back, you get it all. The kill ring is not line +specific; the text that you killed on a previously typed line is +available to be yanked back later, when you are typing another line. + + Here is the list of commands for killing text. + +C-k + Kill the text from the current cursor position to the end of the + line. + +M-d + Kill from the cursor to the end of the current word, or if between + words, to the end of the next word. + +M-DEL + Kill from the cursor the start of the previous word, or if between + words, to the start of the previous word. + +C-w + Kill from the cursor to the previous whitespace. This is + different than M-DEL because the word boundaries differ. + + And, here is how to "yank" the text back into the line. Yanking +means to copy the most-recently-killed text from the kill buffer. + +C-y + Yank the most recently killed text back into the buffer at the + cursor. + +M-y + Rotate the kill-ring, and yank the new top. You can only do this + if the prior command is C-y or M-y. + + +File: readline.info, Node: Readline Arguments, Prev: Readline Killing Commands, Up: Readline Interaction + +Readline Arguments +------------------ + + You can pass numeric arguments to Readline commands. Sometimes the +argument acts as a repeat count, other times it is the sign of the +argument that is significant. If you pass a negative argument to a +command which normally acts in a forward direction, that command will +act in a backward direction. For example, to kill text back to the +start of the line, you might type M- C-k. + + The general way to pass numeric arguments to a command is to type +meta digits before the command. If the first `digit' you type is a +minus sign (-), then the sign of the argument will be negative. Once +you have typed one meta digit to get the argument started, you can type +the remainder of the digits, and then the command. For example, to give +the C-d command an argument of 10, you could type M-1 0 C-d. + + +File: readline.info, Node: Readline Init File, Next: Bindable Readline Commands, Prev: Readline Interaction, Up: Command Line Editing + +Readline Init File +================== + + Although the Readline library comes with a set of Emacs-like +keybindings installed by default, it is possible that you would like to +use a different set of keybindings. You can customize programs that +use Readline by putting commands in an "init" file in your home +directory. The name of this file is taken from the value of the +environment variable `INPUTRC'. If that variable is unset, the default +is `~/.inputrc'. + + When a program which uses the Readline library starts up, the init +file is read, and the key bindings are set. + + In addition, the `C-x C-r' command re-reads this init file, thus +incorporating any changes that you might have made to it. + +* Menu: + +* Readline Init Syntax:: Syntax for the commands in the inputrc file. +* Conditional Init Constructs:: Conditional key bindings in the inputrc file. + + +File: readline.info, Node: Readline Init Syntax, Next: Conditional Init Constructs, Up: Readline Init File + +Readline Init Syntax +-------------------- + + There are only a few basic constructs allowed in the Readline init +file. Blank lines are ignored. Lines beginning with a # are comments. +Lines beginning with a $ indicate conditional constructs (*note +Conditional Init Constructs::.). Other lines denote variable settings +and key bindings. + +Variable Settings + You can change the state of a few variables in Readline by using + the `set' command within the init file. Here is how you would + specify that you wish to use `vi' line editing commands: + + set editing-mode vi + + Right now, there are only a few variables which can be set; so + few, in fact, that we just list them here: + + `editing-mode' + The `editing-mode' variable controls which editing mode you + are using. By default, Readline starts up in Emacs editing + mode, where the keystrokes are most similar to Emacs. This + variable can be set to either `emacs' or `vi'. + + `horizontal-scroll-mode' + This variable can be set to either `On' or `Off'. Setting it + to `On' means that the text of the lines that you edit will + scroll horizontally on a single screen line when they are + longer than the width of the screen, instead of wrapping onto + a new screen line. By default, this variable is set to `Off'. + + `mark-modified-lines' + This variable, when set to `On', says to display an asterisk + (`*') at the start of history lines which have been modified. + This variable is `off' by default. + + `bell-style' + Controls what happens when Readline wants to ring the + terminal bell. If set to `none', Readline never rings the + bell. If set to `visible', Readline uses a visible bell if + one is available. If set to `audible' (the default), + Readline attempts to ring the terminal's bell. + + `comment-begin' + The string to insert at the beginning of the line when the + `vi-comment' command is executed. The default value is `"#"'. + + `meta-flag' + If set to `on', Readline will enable eight-bit input (it will + not strip the eighth bit from the characters it reads), + regardless of what the terminal claims it can support. The + default value is `off'. + + `convert-meta' + If set to `on', Readline will convert characters with the + eigth bit set to an ASCII key sequence by stripping the eigth + bit and prepending an ESC character, converting them to a + meta-prefixed key sequence. The default value is `on'. + + `output-meta' + If set to `on', Readline will display characters with the + eighth bit set directly rather than as a meta-prefixed escape + sequence. The default is `off'. + + `completion-query-items' + The number of possible completions that determines when the + user is asked whether he wants to see the list of + possibilities. If the number of possible completions is + greater than this value, Readline will ask the user whether + or not he wishes to view them; otherwise, they are simply + listed. The default limit is `100'. + + `keymap' + Sets Readline's idea of the current keymap for key binding + commands. Acceptable `keymap' names are `emacs', + `emacs-standard', `emacs-meta', `emacs-ctlx', `vi', `vi-move', + `vi-command', and `vi-insert'. `vi' is equivalent to + `vi-command'; `emacs' is equivalent to `emacs-standard'. The + default value is `emacs'. The value of the `editing-mode' + variable also affects the default keymap. + + `show-all-if-ambiguous' + This alters the default behavior of the completion functions. + If set to `on', words which have more than one possible + completion cause the matches to be listed immediately instead + of ringing the bell. The default value is `off'. + + `expand-tilde' + If set to `on', tilde expansion is performed when Readline + attempts word completion. The default is `off'. + +Key Bindings + The syntax for controlling key bindings in the init file is + simple. First you have to know the name of the command that you + want to change. The following pages contain tables of the command + name, the default keybinding, and a short description of what the + command does. + + Once you know the name of the command, simply place the name of + the key you wish to bind the command to, a colon, and then the + name of the command on a line in the init file. The name of the + key can be expressed in different ways, depending on which is most + comfortable for you. + + KEYNAME: FUNCTION-NAME or MACRO + KEYNAME is the name of a key spelled out in English. For + example: + Control-u: universal-argument + Meta-Rubout: backward-kill-word + Control-o: ">&output" + + In the above example, `C-u' is bound to the function + `universal-argument', and `C-o' is bound to run the macro + expressed on the right hand side (that is, to insert the text + `>&output' into the line). + + "KEYSEQ": FUNCTION-NAME or MACRO + KEYSEQ differs from KEYNAME above in that strings denoting an + entire key sequence can be specified, by placing the key + sequence in double quotes. Some GNU Emacs style key escapes + can be used, as in the following example, but the special + character names are not recognized. + + "\C-u": universal-argument + "\C-x\C-r": re-read-init-file + "\e[11~": "Function Key 1" + + In the above example, `C-u' is bound to the function + `universal-argument' (just as it was in the first example), + `C-x C-r' is bound to the function `re-read-init-file', and + `ESC [ 1 1 ~' is bound to insert the text `Function Key 1'. + The following escape sequences are available when specifying + key sequences: + + ``\C-'' + control prefix + + ``\M-'' + meta prefix + + ``\e'' + an escape character + + ``\\'' + backslash + + ``\"'' + " + + ``\''' + ' + + When entering the text of a macro, single or double quotes + should be used to indicate a macro definition. Unquoted text + is assumed to be a function name. Backslash will quote any + character in the macro text, including " and '. For example, + the following binding will make `C-x \' insert a single \ + into the line: + "\C-x\\": "\\" + + +File: readline.info, Node: Conditional Init Constructs, Prev: Readline Init Syntax, Up: Readline Init File + +Conditional Init Constructs +--------------------------- + + Readline implements a facility similar in spirit to the conditional +compilation features of the C preprocessor which allows key bindings +and variable settings to be performed as the result of tests. There +are three parser directives used. + +`$if' + The `$if' construct allows bindings to be made based on the + editing mode, the terminal being used, or the application using + Readline. The text of the test extends to the end of the line; no + characters are required to isolate it. + + `mode' + The `mode=' form of the `$if' directive is used to test + whether Readline is in `emacs' or `vi' mode. This may be + used in conjunction with the `set keymap' command, for + instance, to set bindings in the `emacs-standard' and + `emacs-ctlx' keymaps only if Readline is starting out in + `emacs' mode. + + `term' + The `term=' form may be used to include terminal-specific key + bindings, perhaps to bind the key sequences output by the + terminal's function keys. The word on the right side of the + `=' is tested against the full name of the terminal and the + portion of the terminal name before the first `-'. This + allows SUN to match both SUN and SUN-CMD, for instance. + + `application' + The APPLICATION construct is used to include + application-specific settings. Each program using the + Readline library sets the APPLICATION NAME, and you can test + for it. This could be used to bind key sequences to + functions useful for a specific program. For instance, the + following command adds a key sequence that quotes the current + or previous word in Bash: + $if bash + # Quote the current or previous word + "\C-xq": "\eb\"\ef\"" + $endif + +`$endif' + This command, as you saw in the previous example, terminates an + `$if' command. + +`$else' + Commands in this branch of the `$if' directive are executed if the + test fails. + + +File: readline.info, Node: Bindable Readline Commands, Next: Readline vi Mode, Prev: Readline Init File, Up: Command Line Editing + +Bindable Readline Commands +========================== + +* Menu: + +* Commands For Moving:: Moving about the line. +* Commands For History:: Getting at previous lines. +* Commands For Text:: Commands for changing text. +* Commands For Killing:: Commands for killing and yanking. +* Numeric Arguments:: Specifying numeric arguments, repeat counts. +* Commands For Completion:: Getting Readline to do the typing for you. +* Keyboard Macros:: Saving and re-executing typed characters +* Miscellaneous Commands:: Other miscellaneous commands. + + +File: readline.info, Node: Commands For Moving, Next: Commands For History, Up: Bindable Readline Commands + +Commands For Moving +------------------- + +`beginning-of-line (C-a)' + Move to the start of the current line. + +`end-of-line (C-e)' + Move to the end of the line. + +`forward-char (C-f)' + Move forward a character. + +`backward-char (C-b)' + Move back a character. + +`forward-word (M-f)' + Move forward to the end of the next word. Words are composed of + letters and digits. + +`backward-word (M-b)' + Move back to the start of this, or the previous, word. Words are + composed of letters and digits. + +`clear-screen (C-l)' + Clear the screen and redraw the current line, leaving the current + line at the top of the screen. + +`redraw-current-line ()' + Refresh the current line. By default, this is unbound. + + +File: readline.info, Node: Commands For History, Next: Commands For Text, Prev: Commands For Moving, Up: Bindable Readline Commands + +Commands For Manipulating The History +------------------------------------- + +`accept-line (Newline, Return)' + Accept the line regardless of where the cursor is. If this line is + non-empty, add it to the history list. If this line was a history + line, then restore the history line to its original state. + +`previous-history (C-p)' + Move `up' through the history list. + +`next-history (C-n)' + Move `down' through the history list. + +`beginning-of-history (M-<)' + Move to the first line in the history. + +`end-of-history (M->)' + Move to the end of the input history, i.e., the line you are + entering. + +`reverse-search-history (C-r)' + Search backward starting at the current line and moving `up' + through the history as necessary. This is an incremental search. + +`forward-search-history (C-s)' + Search forward starting at the current line and moving `down' + through the the history as necessary. This is an incremental + search. + +`non-incremental-reverse-search-history (M-p)' + Search backward starting at the current line and moving `up' + through the history as necessary using a non-incremental search + for a string supplied by the user. + +`non-incremental-forward-search-history (M-n)' + Search forward starting at the current line and moving `down' + through the the history as necessary using a non-incremental search + for a string supplied by the user. + +`history-search-forward ()' + Search forward through the history for the string of characters + between the start of the current line and the current point. This + is a non-incremental search. By default, this command is unbound. + +`history-search-backward ()' + Search backward through the history for the string of characters + between the start of the current line and the current point. This + is a non-incremental search. By default, this command is unbound. + +`yank-nth-arg (M-C-y)' + Insert the first argument to the previous command (usually the + second word on the previous line). With an argument N, insert the + Nth word from the previous command (the words in the previous + command begin with word 0). A negative argument inserts the Nth + word from the end of the previous command. + +`yank-last-arg (M-., M-_)' + Insert last argument to the previous command (the last word on the + previous line). With an argument, behave exactly like + `yank-nth-arg'. + + +File: readline.info, Node: Commands For Text, Next: Commands For Killing, Prev: Commands For History, Up: Bindable Readline Commands + +Commands For Changing Text +-------------------------- + +`delete-char (C-d)' + Delete the character under the cursor. If the cursor is at the + beginning of the line, there are no characters in the line, and + the last character typed was not C-d, then return EOF. + +`backward-delete-char (Rubout)' + Delete the character behind the cursor. A numeric arg says to kill + the characters instead of deleting them. + +`quoted-insert (C-q, C-v)' + Add the next character that you type to the line verbatim. This is + how to insert key sequences like C-q, for example. + +`tab-insert (M-TAB)' + Insert a tab character. + +`self-insert (a, b, A, 1, !, ...)' + Insert yourself. + +`transpose-chars (C-t)' + Drag the character before the cursor forward over the character at + the cursor, moving the cursor forward as well. If the insertion + point is at the end of the line, then this transposes the last two + characters of the line. Negative argumentss don't work. + +`transpose-words (M-t)' + Drag the word behind the cursor past the word in front of the + cursor moving the cursor over that word as well. + +`upcase-word (M-u)' + Uppercase the current (or following) word. With a negative + argument, do the previous word, but do not move the cursor. + +`downcase-word (M-l)' + Lowercase the current (or following) word. With a negative + argument, do the previous word, but do not move the cursor. + +`capitalize-word (M-c)' + Capitalize the current (or following) word. With a negative + argument, do the previous word, but do not move the cursor. + + +File: readline.info, Node: Commands For Killing, Next: Numeric Arguments, Prev: Commands For Text, Up: Bindable Readline Commands + +Killing And Yanking +------------------- + +`kill-line (C-k)' + Kill the text from the current cursor position to the end of the + line. + +`backward-kill-line (C-x Rubout)' + Kill backward to the beginning of the line. + +`unix-line-discard (C-u)' + Kill backward from the cursor to the beginning of the current line. + Save the killed text on the kill-ring. + +`kill-whole-line ()' + Kill all characters on the current line, no matter where the + cursor is. By default, this is unbound. + +`kill-word (M-d)' + Kill from the cursor to the end of the current word, or if between + words, to the end of the next word. Word boundaries are the same + as `forward-word'. + +`backward-kill-word (M-DEL)' + Kill the word behind the cursor. Word boundaries are the same as + `backward-word'. + +`unix-word-rubout (C-w)' + Kill the word behind the cursor, using white space as a word + boundary. The killed text is saved on the kill-ring. + +`delete-horizontal-space ()' + Delete all spaces and tabs around point. By default, this is + unbound. + +`yank (C-y)' + Yank the top of the kill ring into the buffer at the current + cursor position. + +`yank-pop (M-y)' + Rotate the kill-ring, and yank the new top. You can only do this + if the prior command is yank or yank-pop. + + +File: readline.info, Node: Numeric Arguments, Next: Commands For Completion, Prev: Commands For Killing, Up: Bindable Readline Commands + +Specifying Numeric Arguments +---------------------------- + +`digit-argument (M-0, M-1, ... M--)' + Add this digit to the argument already accumulating, or start a new + argument. M- starts a negative argument. + +`universal-argument ()' + Each time this is executed, the argument count is multiplied by + four. The argument count is initially one, so executing this + function the first time makes the argument count four. By + default, this is not bound to a key. + + +File: readline.info, Node: Commands For Completion, Next: Keyboard Macros, Prev: Numeric Arguments, Up: Bindable Readline Commands + +Letting Readline Type For You +----------------------------- + +`complete (TAB)' + Attempt to do completion on the text before the cursor. This is + application-specific. Generally, if you are typing a filename + argument, you can do filename completion; if you are typing a + command, you can do command completion, if you are typing in a + symbol to GDB, you can do symbol name completion, if you are + typing in a variable to Bash, you can do variable name completion, + and so on. + +`possible-completions (M-?)' + List the possible completions of the text before the cursor. + +`insert-completions ()' + Insert all completions of the text before point that would have + been generated by `possible-completions'. By default, this is not + bound to a key. + + +File: readline.info, Node: Keyboard Macros, Next: Miscellaneous Commands, Prev: Commands For Completion, Up: Bindable Readline Commands + +Keyboard Macros +--------------- + +`start-kbd-macro (C-x ()' + Begin saving the characters typed into the current keyboard macro. + +`end-kbd-macro (C-x ))' + Stop saving the characters typed into the current keyboard macro + and save the definition. + +`call-last-kbd-macro (C-x e)' + Re-execute the last keyboard macro defined, by making the + characters in the macro appear as if typed at the keyboard. + + +File: readline.info, Node: Miscellaneous Commands, Prev: Keyboard Macros, Up: Bindable Readline Commands + +Some Miscellaneous Commands +--------------------------- + +`re-read-init-file (C-x C-r)' + Read in the contents of your init file, and incorporate any + bindings or variable assignments found there. + +`abort (C-g)' + Abort the current editing command and ring the terminal's bell + (subject to the setting of `bell-style'). + +`do-uppercase-version (M-a, M-b, ...)' + Run the command that is bound to the corresoponding uppercase + character. + +`prefix-meta (ESC)' + Make the next character that you type be metafied. This is for + people without a meta key. Typing `ESC f' is equivalent to typing + `M-f'. + +`undo (C-_, C-x C-u)' + Incremental undo, separately remembered for each line. + +`revert-line (M-r)' + Undo all changes made to this line. This is like typing the `undo' + command enough times to get back to the beginning. + +`tilde-expand (M-~)' + Perform tilde expansion on the current word. + +`dump-functions ()' + Print all of the functions and their key bindings to the readline + output stream. If a numeric argument is supplied, the output is + formatted in such a way that it can be made part of an INPUTRC + file. + + +File: readline.info, Node: Readline vi Mode, Prev: Bindable Readline Commands, Up: Command Line Editing + +Readline vi Mode +================ + + While the Readline library does not have a full set of `vi' editing +functions, it does contain enough to allow simple editing of the line. +The Readline `vi' mode behaves as specified in the Posix 1003.2 +standard. + + In order to switch interactively between `Emacs' and `Vi' editing +modes, use the command M-C-j (toggle-editing-mode). The Readline +default is `emacs' mode. + + When you enter a line in `vi' mode, you are already placed in +`insertion' mode, as if you had typed an `i'. Pressing ESC switches +you into `command' mode, where you can edit the text of the line with +the standard `vi' movement keys, move to previous history lines with +`k', and following lines with `j', and so forth. + + This document describes the GNU Readline Library, a utility for +aiding in the consitency of user interface across discrete programs +that need to provide a command line interface. + + Copyright (C) 1988, 1994 Free Software Foundation, Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice pare +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 Foundation. + + +File: readline.info, Node: Programming with GNU Readline, Next: Concept Index, Prev: Command Line Editing, Up: Top + +Programming with GNU Readline +***************************** + + This chapter describes the interface between the GNU Readline +Library and other programs. If you are a programmer, and you wish to +include the features found in GNU Readline such as completion, line +editing, and interactive history manipulation in your own programs, +this section is for you. + +* Menu: + +* Basic Behavior:: Using the default behavior of Readline. +* Custom Functions:: Adding your own functions to Readline. +* Readline Convenience Functions:: Functions which Readline supplies to + aid in writing your own +* Custom Completers:: Supplanting or supplementing Readline's + completion functions. + + +File: readline.info, Node: Basic Behavior, Next: Custom Functions, Up: Programming with GNU Readline + +Basic Behavior +============== + + Many programs provide a command line interface, such as `mail', +`ftp', and `sh'. For such programs, the default behaviour of Readline +is sufficient. This section describes how to use Readline in the +simplest way possible, perhaps to replace calls in your code to +`gets()' or `fgets ()'. + + The function `readline ()' prints a prompt and then reads and returns +a single line of text from the user. The line `readline' returns is +allocated with `malloc ()'; you should `free ()' the line when you are +done with it. The declaration for `readline' in ANSI C is + + `char *readline (char *PROMPT);' + +So, one might say + `char *line = readline ("Enter a line: ");' + +in order to read a line of text from the user. The line returned has +the final newline removed, so only the text remains. + + If `readline' encounters an `EOF' while reading the line, and the +line is empty at that point, then `(char *)NULL' is returned. +Otherwise, the line is ended just as if a newline had been typed. + + If you want the user to be able to get at the line later, (with C-p +for example), you must call `add_history ()' to save the line away in a +"history" list of such lines. + + `add_history (line)'; + +For full details on the GNU History Library, see the associated manual. + + It is preferable to avoid saving empty lines on the history list, +since users rarely have a burning need to reuse a blank line. Here is +a function which usefully replaces the standard `gets ()' library +function, and has the advantage of no static buffer to overflow: + + /* A static variable for holding the line. */ + static char *line_read = (char *)NULL; + + /* Read a string, and return a pointer to it. Returns NULL on EOF. */ + char * + rl_gets () + { + /* If the buffer has already been allocated, return the memory + to the free pool. */ + if (line_read) + { + free (line_read); + line_read = (char *)NULL; + } + + /* Get a line from the user. */ + line_read = readline (""); + + /* If the line has any text in it, save it on the history. */ + if (line_read && *line_read) + add_history (line_read); + + return (line_read); + } + + This function gives the user the default behaviour of TAB +completion: completion on file names. If you do not want Readline to +complete on filenames, you can change the binding of the TAB key with +`rl_bind_key ()'. + + `int rl_bind_key (int KEY, int (*FUNCTION)());' + + `rl_bind_key ()' takes two arguments: KEY is the character that you +want to bind, and FUNCTION is the address of the function to call when +KEY is pressed. Binding TAB to `rl_insert ()' makes TAB insert itself. +`rl_bind_key ()' returns non-zero if KEY is not a valid ASCII character +code (between 0 and 255). + + Thus, to disable the default TAB behavior, the following suffices: + `rl_bind_key ('\t', rl_insert);' + + This code should be executed once at the start of your program; you +might write a function called `initialize_readline ()' which performs +this and other desired initializations, such as installing custom +completers (*note Custom Completers::.). + + +File: readline.info, Node: Custom Functions, Next: Readline Convenience Functions, Prev: Basic Behavior, Up: Programming with GNU Readline + +Custom Functions +================ + + Readline provides many functions for manipulating the text of the +line, but it isn't possible to anticipate the needs of all programs. +This section describes the various functions and variables defined +within the Readline library which allow a user program to add +customized functionality to Readline. + +* Menu: + +* The Function Type:: C declarations to make code readable. +* Function Writing:: Variables and calling conventions. + + +File: readline.info, Node: The Function Type, Next: Function Writing, Up: Custom Functions + +The Function Type +----------------- + + For readabilty, we declare a new type of object, called "Function". +A `Function' is a C function which returns an `int'. The type +declaration for `Function' is: + +`typedef int Function ();' + + The reason for declaring this new type is to make it easier to write +code describing pointers to C functions. Let us say we had a variable +called FUNC which was a pointer to a function. Instead of the classic +C declaration + + `int (*)()func;' + +we may write + + `Function *func;' + +Similarly, there are + + typedef void VFunction (); + typedef char *CPFunction (); and + typedef char **CPPFunction (); + +for functions returning no value, `pointer to char', and `pointer to +pointer to char', respectively. + + +File: readline.info, Node: Function Writing, Prev: The Function Type, Up: Custom Functions + +Writing a New Function +---------------------- + + In order to write new functions for Readline, you need to know the +calling conventions for keyboard-invoked functions, and the names of the +variables that describe the current state of the line read so far. + + The calling sequence for a command `foo' looks like + + `foo (int count, int key)' + +where COUNT is the numeric argument (or 1 if defaulted) and KEY is the +key that invoked this function. + + It is completely up to the function as to what should be done with +the numeric argument. Some functions use it as a repeat count, some as +a flag, and others to choose alternate behavior (refreshing the current +line as opposed to refreshing the screen, for example). Some choose to +ignore it. In general, if a function uses the numeric argument as a +repeat count, it should be able to do something useful with both +negative and positive arguments. At the very least, it should be aware +that it can be passed a negative argument. + + - Variable: char * rl_line_buffer + This is the line gathered so far. You are welcome to modify the + contents of the line, but see *Note Allowing Undoing::. + + - Variable: int rl_point + The offset of the current cursor position in `rl_line_buffer' (the + *point*). + + - Variable: int rl_end + The number of characters present in `rl_line_buffer'. When + `rl_point' is at the end of the line, `rl_point' and `rl_end' are + equal. + + - Variable: int rl_mark + The mark (saved position) in the current line. If set, the mark + and point define a *region*. + + - Variable: int rl_done + Setting this to a non-zero value causes Readline to return the + current line immediately. + + - Variable: int rl_pending_input + Setting this to a value makes it the next keystroke read. This is + a way to stuff a single character into the input stream. + + - Variable: char * rl_prompt + The prompt Readline uses. This is set from the argument to + `readline ()', and should not be assigned to directly. + + - Variable: char * rl_terminal_name + The terminal type, used for initialization. + + - Variable: char * rl_readline_name + This variable is set to a unique name by each application using + Readline. The value allows conditional parsing of the inputrc file + (*note Conditional Init Constructs::.). + + - Variable: FILE * rl_instream + The stdio stream from which Readline reads input. + + - Variable: FILE * rl_outstream + The stdio stream to which Readline performs output. + + - Variable: Function * rl_startup_hook + If non-zero, this is the address of a function to call just before + `readline' prints the first prompt. + + +File: readline.info, Node: Readline Convenience Functions, Next: Custom Completers, Prev: Custom Functions, Up: Programming with GNU Readline + +Readline Convenience Functions +============================== + +* Menu: + +* Function Naming:: How to give a function you write a name. +* Keymaps:: Making keymaps. +* Binding Keys:: Changing Keymaps. +* Associating Function Names and Bindings:: Translate function names to + key sequences. +* Allowing Undoing:: How to make your functions undoable. +* Redisplay:: Functions to control line display. +* Modifying Text:: Functions to modify `rl_line_buffer'. +* Utility Functions:: Generally useful functions and hooks. + + +File: readline.info, Node: Function Naming, Next: Keymaps, Up: Readline Convenience Functions + +Naming a Function +----------------- + + The user can dynamically change the bindings of keys while using +Readline. This is done by representing the function with a descriptive +name. The user is able to type the descriptive name when referring to +the function. Thus, in an init file, one might find + + Meta-Rubout: backward-kill-word + + This binds the keystroke Meta-Rubout to the function *descriptively* +named `backward-kill-word'. You, as the programmer, should bind the +functions you write to descriptive names as well. Readline provides a +function for doing that: + + - Function: int rl_add_defun (char *name, Function *function, int key) + Add NAME to the list of named functions. Make FUNCTION be the + function that gets called. If KEY is not -1, then bind it to + FUNCTION using `rl_bind_key ()'. + + Using this function alone is sufficient for most applications. It is +the recommended way to add a few functions to the default functions that +Readline has built in. If you need to do something other than adding a +function to Readline, you may need to use the underlying functions +described below. + + +File: readline.info, Node: Keymaps, Next: Binding Keys, Prev: Function Naming, Up: Readline Convenience Functions + +Selecting a Keymap +------------------ + + Key bindings take place on a "keymap". The keymap is the +association between the keys that the user types and the functions that +get run. You can make your own keymaps, copy existing keymaps, and tell +Readline which keymap to use. + + - Function: Keymap rl_make_bare_keymap () + Returns a new, empty keymap. The space for the keymap is + allocated with `malloc ()'; you should `free ()' it when you are + done. + + - Function: Keymap rl_copy_keymap (Keymap map) + Return a new keymap which is a copy of MAP. + + - Function: Keymap rl_make_keymap () + Return a new keymap with the printing characters bound to + rl_insert, the lowercase Meta characters bound to run their + equivalents, and the Meta digits bound to produce numeric + arguments. + + - Function: void rl_discard_keymap (Keymap keymap) + Free the storage associated with KEYMAP. + + Readline has several internal keymaps. These functions allow you to +change which keymap is active. + + - Function: Keymap rl_get_keymap () + Returns the currently active keymap. + + - Function: void rl_set_keymap (Keymap keymap) + Makes KEYMAP the currently active keymap. + + - Function: Keymap rl_get_keymap_by_name (char *name) + Return the keymap matching NAME. NAME is one which would be + supplied in a `set keymap' inputrc line (*note Readline Init + File::.). + + +File: readline.info, Node: Binding Keys, Next: Associating Function Names and Bindings, Prev: Keymaps, Up: Readline Convenience Functions + +Binding Keys +------------ + + You associate keys with functions through the keymap. Readline has +several internal keymaps: `emacs_standard_keymap', `emacs_meta_keymap', +`emacs_ctlx_keymap', `vi_movement_keymap', and `vi_insertion_keymap'. +`emacs_standard_keymap' is the default, and the examples in this manual +assume that. + + These functions manage key bindings. + + - Function: int rl_bind_key (int key, Function *function) + Binds KEY to FUNCTION in the currently active keymap. Returns + non-zero in the case of an invalid KEY. + + - Function: int rl_bind_key_in_map (int key, Function *function, + Keymap map) + Bind KEY to FUNCTION in MAP. Returns non-zero in the case of an + invalid KEY. + + - Function: int rl_unbind_key (int key) + Bind KEY to the null function in the currently active keymap. + Returns non-zero in case of error. + + - Function: int rl_unbind_key_in_map (int key, Keymap map) + Bind KEY to the null function in MAP. Returns non-zero in case of + error. + + - Function: int rl_generic_bind (int type, char *keyseq, char *data, + Keymap map) + Bind the key sequence represented by the string KEYSEQ to the + arbitrary pointer DATA. TYPE says what kind of data is pointed to + by DATA; this can be a function (`ISFUNC'), a macro (`ISMACR'), or + a keymap (`ISKMAP'). This makes new keymaps as necessary. The + initial keymap in which to do bindings is MAP. + + - Function: int rl_parse_and_bind (char *line) + Parse LINE as if it had been read from the `inputrc' file and + perform any key bindings and variable assignments found (*note + Readline Init File::.). + + +File: readline.info, Node: Associating Function Names and Bindings, Next: Allowing Undoing, Prev: Binding Keys, Up: Readline Convenience Functions + +Associating Function Names and Bindings +--------------------------------------- + + These functions allow you to find out what keys invoke named +functions and the functions invoked by a particular key sequence. + + - Function: Function * rl_named_function (char *name) + Return the function with name NAME. + + - Function: Function * rl_function_of_keyseq (char *keyseq, Keymap + map, int *type) + Return the function invoked by KEYSEQ in keymap MAP. If MAP is + NULL, the current keymap is used. If TYPE is not NULL, the type + of the object is returned in it (one of `ISFUNC', `ISKMAP', or + `ISMACR'). + + - Function: char ** rl_invoking_keyseqs (Function *function) + Return an array of strings representing the key sequences used to + invoke FUNCTION in the current keymap. + + - Function: char ** rl_invoking_keyseqs_in_map (Function *function, + Keymap map) + Return an array of strings representing the key sequences used to + invoke FUNCTION in the keymap MAP. + + +File: readline.info, Node: Allowing Undoing, Next: Redisplay, Prev: Associating Function Names and Bindings, Up: Readline Convenience Functions + +Allowing Undoing +---------------- + + Supporting the undo command is a painless thing, and makes your +functions much more useful. It is certainly easy to try something if +you know you can undo it. I could use an undo function for the stock +market. + + If your function simply inserts text once, or deletes text once, and +uses `rl_insert_text ()' or `rl_delete_text ()' to do it, then undoing +is already done for you automatically. + + If you do multiple insertions or multiple deletions, or any +combination of these operations, you should group them together into +one operation. This is done with `rl_begin_undo_group ()' and +`rl_end_undo_group ()'. + + The types of events that can be undone are: + + enum undo_code { UNDO_DELETE, UNDO_INSERT, UNDO_BEGIN, UNDO_END }; + + Notice that `UNDO_DELETE' means to insert some text, and +`UNDO_INSERT' means to delete some text. That is, the undo code tells +undo what to undo, not how to undo it. `UNDO_BEGIN' and `UNDO_END' are +tags added by `rl_begin_undo_group ()' and `rl_end_undo_group ()'. + + - Function: int rl_begin_undo_group () + Begins saving undo information in a group construct. The undo + information usually comes from calls to `rl_insert_text ()' and + `rl_delete_text ()', but could be the result of calls to + `rl_add_undo ()'. + + - Function: int rl_end_undo_group () + Closes the current undo group started with `rl_begin_undo_group + ()'. There should be one call to `rl_end_undo_group ()' for each + call to `rl_begin_undo_group ()'. + + - Function: void rl_add_undo (enum undo_code what, int start, int end, + char *text) + Remember how to undo an event (according to WHAT). The affected + text runs from START to END, and encompasses TEXT. + + - Function: void free_undo_list () + Free the existing undo list. + + - Function: int rl_do_undo () + Undo the first thing on the undo list. Returns `0' if there was + nothing to undo, non-zero if something was undone. + + Finally, if you neither insert nor delete text, but directly modify +the existing text (e.g., change its case), call `rl_modifying ()' once, +just before you modify the text. You must supply the indices of the +text range that you are going to modify. + + - Function: int rl_modifying (int start, int end) + Tell Readline to save the text between START and END as a single + undo unit. It is assumed that you will subsequently modify that + text. + + +File: readline.info, Node: Redisplay, Next: Modifying Text, Prev: Allowing Undoing, Up: Readline Convenience Functions + +Redisplay +--------- + + - Function: int rl_redisplay () + Change what's displayed on the screen to reflect the current + contents of `rl_line_buffer'. + + - Function: int rl_forced_update_display () + Force the line to be updated and redisplayed, whether or not + Readline thinks the screen display is correct. + + - Function: int rl_on_new_line () + Tell the update routines that we have moved onto a new (empty) + line, usually after ouputting a newline. + + - Function: int rl_reset_line_state () + Reset the display state to a clean state and redisplay the current + line starting on a new line. + + - Function: int rl_message (va_alist) + The arguments are a string as would be supplied to `printf'. The + resulting string is displayed in the "echo area". The echo area + is also used to display numeric arguments and search strings. + + - Function: int rl_clear_message () + Clear the message in the echo area. + diff --git a/doc/readline.info-2 b/doc/readline.info-2 new file mode 100644 index 0000000..35681aa --- /dev/null +++ b/doc/readline.info-2 @@ -0,0 +1,978 @@ +This is Info file readline.info, produced by Makeinfo-1.55 from the +input file rlman.texinfo. + + This document describes the GNU Readline Library, a utility which +aids in the consistency of user interface across discrete programs that +need to provide a command line interface. + + Copyright (C) 1988, 1991 Free Software Foundation, Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice pare +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 Foundation. + + +File: readline.info, Node: Modifying Text, Next: Utility Functions, Prev: Redisplay, Up: Readline Convenience Functions + +Modifying Text +-------------- + + - Function: int rl_insert_text (char *text) + Insert TEXT into the line at the current cursor position. + + - Function: int rl_delete_text (int start, int end) + Delete the text between START and END in the current line. + + - Function: char * rl_copy_text (int start, int end) + Return a copy of the text between START and END in the current + line. + + - Function: int rl_kill_text (int start, int end) + Copy the text between START and END in the current line to the + kill ring, appending or prepending to the last kill if the last + command was a kill command. The text is deleted. If START is + less than END, the text is appended, otherwise prepended. If the + last command was not a kill, a new kill ring slot is used. + + +File: readline.info, Node: Utility Functions, Prev: Modifying Text, Up: Readline Convenience Functions + +Utility Functions +----------------- + + - Function: int rl_reset_terminal (char *terminal_name) + Reinitialize Readline's idea of the terminal settings using + TERMINAL_NAME as the terminal type (e.g., `vt100'). + + - Function: int alphabetic (int c) + Return 1 if C is an alphabetic character. + + - Function: int numeric (int c) + Return 1 if C is a numeric character. + + - Function: int ding () + Ring the terminal bell, obeying the setting of `bell-style'. + + The following are implemented as macros, defined in `chartypes.h'. + + - Function: int uppercase_p (int c) + Return 1 if C is an uppercase alphabetic character. + + - Function: int lowercase_p (int c) + Return 1 if C is a lowercase alphabetic character. + + - Function: int digit_p (int c) + Return 1 if C is a numeric character. + + - Function: int to_upper (int c) + If C is a lowercase alphabetic character, return the corresponding + uppercase character. + + - Function: int to_lower (int c) + If C is an uppercase alphabetic character, return the corresponding + lowercase character. + + - Function: int digit_value (int c) + If C is a number, return the value it represents. + +An Example +---------- + + Here is a function which changes lowercase characters to their +uppercase equivalents, and uppercase characters to lowercase. If this +function was bound to `M-c', then typing `M-c' would change the case of +the character under point. Typing `M-1 0 M-c' would change the case of +the following 10 characters, leaving the cursor on the last character +changed. + + /* Invert the case of the COUNT following characters. */ + int + invert_case_line (count, key) + int count, key; + { + register int start, end, i; + + start = rl_point; + + if (rl_point >= rl_end) + return (0); + + if (count < 0) + { + direction = -1; + count = -count; + } + else + direction = 1; + + /* Find the end of the range to modify. */ + end = start + (count * direction); + + /* Force it to be within range. */ + if (end > rl_end) + end = rl_end; + else if (end < 0) + end = 0; + + if (start == end) + return (0); + + if (start > end) + { + int temp = start; + start = end; + end = temp; + } + + /* Tell readline that we are modifying the line, so it will save + the undo information. */ + rl_modifying (start, end); + + for (i = start; i != end; i++) + { + if (uppercase_p (rl_line_buffer[i])) + rl_line_buffer[i] = to_lower (rl_line_buffer[i]); + else if (lowercase_p (rl_line_buffer[i])) + rl_line_buffer[i] = to_upper (rl_line_buffer[i]); + } + /* Move point to on top of the last character changed. */ + rl_point = (direction == 1) ? end - 1 : start; + return (0); + } + + +File: readline.info, Node: Custom Completers, Prev: Readline Convenience Functions, Up: Programming with GNU Readline + +Custom Completers +================= + + Typically, a program that reads commands from the user has a way of +disambiguating commands and data. If your program is one of these, then +it can provide completion for commands, data, or both. The following +sections describe how your program and Readline cooperate to provide +this service. + +* Menu: + +* How Completing Works:: The logic used to do completion. +* Completion Functions:: Functions provided by Readline. +* Completion Variables:: Variables which control completion. +* A Short Completion Example:: An example of writing completer subroutines. + + +File: readline.info, Node: How Completing Works, Next: Completion Functions, Up: Custom Completers + +How Completing Works +-------------------- + + In order to complete some text, the full list of possible completions +must be available. That is, it is not possible to accurately expand a +partial word without knowing all of the possible words which make sense +in that context. The Readline library provides the user interface to +completion, and two of the most common completion functions: filename +and username. For completing other types of text, you must write your +own completion function. This section describes exactly what such +functions must do, and provides an example. + + There are three major functions used to perform completion: + + 1. The user-interface function `rl_complete ()'. This function is + called with the same arguments as other Readline functions + intended for interactive use: COUNT and INVOKING_KEY. It + isolates the word to be completed and calls `completion_matches + ()' to generate a list of possible completions. It then either + lists the possible completions, inserts the possible completions, + or actually performs the completion, depending on which behavior + is desired. + + 2. The internal function `completion_matches ()' uses your + "generator" function to generate the list of possible matches, and + then returns the array of these matches. You should place the + address of your generator function in + `rl_completion_entry_function'. + + 3. The generator function is called repeatedly from + `completion_matches ()', returning a string each time. The + arguments to the generator function are TEXT and STATE. TEXT is + the partial word to be completed. STATE is zero the first time + the function is called, allowing the generator to perform any + necessary initialization, and a positive non-zero integer for each + subsequent call. When the generator function returns `(char + *)NULL' this signals `completion_matches ()' that there are no + more possibilities left. Usually the generator function computes + the list of possible completions when STATE is zero, and returns + them one at a time on subsequent calls. Each string the generator + function returns as a match must be allocated with `malloc()'; + Readline frees the strings when it has finished with them. + + + - Function: int rl_complete (int ignore, int invoking_key) + Complete the word at or before point. You have supplied the + function that does the initial simple matching selection algorithm + (see `completion_matches ()'). The default is to do filename + completion. + + - Variable: Function * rl_completion_entry_function + This is a pointer to the generator function for `completion_matches + ()'. If the value of `rl_completion_entry_function' is `(Function + *)NULL' then the default filename generator function, + `filename_entry_function ()', is used. + + +File: readline.info, Node: Completion Functions, Next: Completion Variables, Prev: How Completing Works, Up: Custom Completers + +Completion Functions +-------------------- + + Here is the complete list of callable completion functions present in +Readline. + + - Function: int rl_complete_internal (int what_to_do) + Complete the word at or before point. WHAT_TO_DO says what to do + with the completion. A value of `?' means list the possible + completions. `TAB' means do standard completion. `*' means + insert all of the possible completions. `!' means to display all + of the possible completions, if there is more than one, as well as + performing partial completion. + + - Function: int rl_complete (int ignore, int invoking_key) + Complete the word at or before point. You have supplied the + function that does the initial simple matching selection algorithm + (see `completion_matches ()' and `rl_completion_entry_function'). + The default is to do filename completion. This calls + `rl_complete_internal ()' with an argument depending on + INVOKING_KEY. + + - Function: int rl_possible_completions (int count, int invoking_key)) + List the possible completions. See description of `rl_complete + ()'. This calls `rl_complete_internal ()' with an argument of `?'. + + - Function: int rl_insert_completions (int count, int invoking_key)) + Insert the list of possible completions into the line, deleting the + partially-completed word. See description of `rl_complete ()'. + This calls `rl_complete_internal ()' with an argument of `*'. + + - Function: char ** completion_matches (char *text, CPFunction + *entry_func) + Returns an array of `(char *)' which is a list of completions for + TEXT. If there are no completions, returns `(char **)NULL'. The + first entry in the returned array is the substitution for TEXT. + The remaining entries are the possible completions. The array is + terminated with a `NULL' pointer. + + ENTRY_FUNC is a function of two args, and returns a `(char *)'. + The first argument is TEXT. The second is a state argument; it is + zero on the first call, and non-zero on subsequent calls. + eNTRY_FUNC returns a `NULL' pointer to the caller when there are + no more matches. + + - Function: char * filename_completion_function (char *text, int state) + A generator function for filename completion in the general case. + Note that completion in Bash is a little different because of all + the pathnames that must be followed when looking up completions + for a command. The Bash source is a useful reference for writing + custom completion functions. + + - Function: char * username_completion_function (char *text, int state) + A completion generator for usernames. TEXT contains a partial + username preceded by a random character (usually `~'). As with all + completion generators, STATE is zero on the first call and non-zero + for subsequent calls. + + +File: readline.info, Node: Completion Variables, Next: A Short Completion Example, Prev: Completion Functions, Up: Custom Completers + +Completion Variables +-------------------- + + - Variable: Function * rl_completion_entry_function + A pointer to the generator function for `completion_matches ()'. + `NULL' means to use `filename_entry_function ()', the default + filename completer. + + - Variable: CPPFunction * rl_attempted_completion_function + A pointer to an alternative function to create matches. The + function is called with TEXT, START, and END. START and END are + indices in `rl_line_buffer' saying what the boundaries of TEXT + are. If this function exists and returns `NULL', or if this + variable is set to `NULL', then `rl_complete ()' will call the + value of `rl_completion_entry_function' to generate matches, + otherwise the array of strings returned will be used. + + - Variable: int rl_completion_query_items + Up to this many items will be displayed in response to a + possible-completions call. After that, we ask the user if she is + sure she wants to see them all. The default value is 100. + + - Variable: char * rl_basic_word_break_characters + The basic list of characters that signal a break between words for + the completer routine. The default value of this variable is the + characters which break words for completion in Bash, i.e., `" + \t\n\"\\'`@$><=;|&{("'. + + - Variable: char * rl_completer_word_break_characters + The list of characters that signal a break between words for + `rl_complete_internal ()'. The default list is the value of + `rl_basic_word_break_characters'. + + - Variable: char * rl_special_prefixes + The list of characters that are word break characters, but should + be left in TEXT when it is passed to the completion function. + Programs can use this to help determine what kind of completing to + do. For instance, Bash sets this variable to "$@" so that it can + complete shell variables and hostnames. + + - Variable: int rl_ignore_completion_duplicates + If non-zero, then disallow duplicates in the matches. Default is + 1. + + - Variable: int rl_filename_completion_desired + Non-zero means that the results of the matches are to be treated as + filenames. This is *always* zero on entry, and can only be changed + within a completion entry generator function. If it is set to a + non-zero value, directory names have a slash appended and Readline + attempts to quote completed filenames if they contain any embedded + word break characters. + + - Variable: int rl_filename_quoting_desired + Non-zero means that the results of the matches are to be quoted + using double quotes (or an application-specific quoting mechanism) + if the completed filename contains any characters in + `rl_completer_word_break_chars'. This is *always* non-zero on + entry, and can only be changed within a completion entry generator + function. + + - Variable: Function * rl_ignore_some_completions_function + This function, if defined, is called by the completer when real + filename completion is done, after all the matching names have + been generated. It is passed a `NULL' terminated array of matches. + The first element (`matches[0]') is the maximal substring common + to all matches. This function can re-arrange the list of matches + as required, but each element deleted from the array must be freed. + + - Variable: char * rl_completer_quote_characters + List of characters which can be used to quote a substring of the + line. Completion occurs on the entire substring, and within the + substring `rl_completer_word_break_characters' are treated as any + other character, unless they also appear within this list. + + +File: readline.info, Node: A Short Completion Example, Prev: Completion Variables, Up: Custom Completers + +A Short Completion Example +-------------------------- + + Here is a small application demonstrating the use of the GNU Readline +library. It is called `fileman', and the source code resides in +`examples/fileman.c'. This sample application provides completion of +command names, line editing features, and access to the history list. + + /* fileman.c -- A tiny application which demonstrates how to use the + GNU Readline library. This application interactively allows users + to manipulate files and their modes. */ + + #include + #include + #include + #include + #include + + #include + #include + + extern char *getwd (); + extern char *xmalloc (); + + /* The names of functions that actually do the manipulation. */ + int com_list (), com_view (), com_rename (), com_stat (), com_pwd (); + int com_delete (), com_help (), com_cd (), com_quit (); + + /* A structure which contains information on the commands this program + can understand. */ + + typedef struct { + char *name; /* User printable name of the function. */ + Function *func; /* Function to call to do the job. */ + char *doc; /* Documentation for this function. */ + } COMMAND; + + COMMAND commands[] = { + { "cd", com_cd, "Change to directory DIR" }, + { "delete", com_delete, "Delete FILE" }, + { "help", com_help, "Display this text" }, + { "?", com_help, "Synonym for `help'" }, + { "list", com_list, "List files in DIR" }, + { "ls", com_list, "Synonym for `list'" }, + { "pwd", com_pwd, "Print the current working directory" }, + { "quit", com_quit, "Quit using Fileman" }, + { "rename", com_rename, "Rename FILE to NEWNAME" }, + { "stat", com_stat, "Print out statistics on FILE" }, + { "view", com_view, "View the contents of FILE" }, + { (char *)NULL, (Function *)NULL, (char *)NULL } + }; + + /* Forward declarations. */ + char *stripwhite (); + COMMAND *find_command (); + + /* The name of this program, as taken from argv[0]. */ + char *progname; + + /* When non-zero, this global means the user is done using this program. */ + int done; + + char * + dupstr (s) + int s; + { + char *r; + + r = xmalloc (strlen (s) + 1); + strcpy (r, s); + return (r); + } + + main (argc, argv) + int argc; + char **argv; + { + char *line, *s; + + progname = argv[0]; + + initialize_readline (); /* Bind our completer. */ + + /* Loop reading and executing lines until the user quits. */ + for ( ; done == 0; ) + { + line = readline ("FileMan: "); + + if (!line) + break; + + /* Remove leading and trailing whitespace from the line. + Then, if there is anything left, add it to the history list + and execute it. */ + s = stripwhite (line); + + if (*s) + { + add_history (s); + execute_line (s); + } + + free (line); + } + exit (0); + } + + /* Execute a command line. */ + int + execute_line (line) + char *line; + { + register int i; + COMMAND *command; + char *word; + + /* Isolate the command word. */ + i = 0; + while (line[i] && whitespace (line[i])) + i++; + word = line + i; + + while (line[i] && !whitespace (line[i])) + i++; + + if (line[i]) + line[i++] = '\0'; + + command = find_command (word); + + if (!command) + { + fprintf (stderr, "%s: No such command for FileMan.\n", word); + return (-1); + } + + /* Get argument to command, if any. */ + while (whitespace (line[i])) + i++; + + word = line + i; + + /* Call the function. */ + return ((*(command->func)) (word)); + } + + /* Look up NAME as the name of a command, and return a pointer to that + command. Return a NULL pointer if NAME isn't a command name. */ + COMMAND * + find_command (name) + char *name; + { + register int i; + + for (i = 0; commands[i].name; i++) + if (strcmp (name, commands[i].name) == 0) + return (&commands[i]); + + return ((COMMAND *)NULL); + } + + /* Strip whitespace from the start and end of STRING. Return a pointer + into STRING. */ + char * + stripwhite (string) + char *string; + { + register char *s, *t; + + for (s = string; whitespace (*s); s++) + ; + + if (*s == 0) + return (s); + + t = s + strlen (s) - 1; + while (t > s && whitespace (*t)) + t--; + *++t = '\0'; + + return s; + } + + /* **************************************************************** */ + /* */ + /* Interface to Readline Completion */ + /* */ + /* **************************************************************** */ + + char *command_generator (); + char **fileman_completion (); + + /* Tell the GNU Readline library how to complete. We want to try to complete + on command names if this is the first word in the line, or on filenames + if not. */ + initialize_readline () + { + /* Allow conditional parsing of the ~/.inputrc file. */ + rl_readline_name = "FileMan"; + + /* Tell the completer that we want a crack first. */ + rl_attempted_completion_function = (CPPFunction *)fileman_completion; + } + + /* Attempt to complete on the contents of TEXT. START and END show the + region of TEXT that contains the word to complete. We can use the + entire line in case we want to do some simple parsing. Return the + array of matches, or NULL if there aren't any. */ + char ** + fileman_completion (text, start, end) + char *text; + int start, end; + { + char **matches; + + matches = (char **)NULL; + + /* If this word is at the start of the line, then it is a command + to complete. Otherwise it is the name of a file in the current + directory. */ + if (start == 0) + matches = completion_matches (text, command_generator); + + return (matches); + } + + /* Generator function for command completion. STATE lets us know whether + to start from scratch; without any state (i.e. STATE == 0), then we + start at the top of the list. */ + char * + command_generator (text, state) + char *text; + int state; + { + static int list_index, len; + char *name; + + /* If this is a new word to complete, initialize now. This includes + saving the length of TEXT for efficiency, and initializing the index + variable to 0. */ + if (!state) + { + list_index = 0; + len = strlen (text); + } + + /* Return the next name which partially matches from the command list. */ + while (name = commands[list_index].name) + { + list_index++; + + if (strncmp (name, text, len) == 0) + return (dupstr(name)); + } + + /* If no names matched, then return NULL. */ + return ((char *)NULL); + } + + /* **************************************************************** */ + /* */ + /* FileMan Commands */ + /* */ + /* **************************************************************** */ + + /* String to pass to system (). This is for the LIST, VIEW and RENAME + commands. */ + static char syscom[1024]; + + /* List the file(s) named in arg. */ + com_list (arg) + char *arg; + { + if (!arg) + arg = ""; + + sprintf (syscom, "ls -FClg %s", arg); + return (system (syscom)); + } + + com_view (arg) + char *arg; + { + if (!valid_argument ("view", arg)) + return 1; + + sprintf (syscom, "more %s", arg); + return (system (syscom)); + } + + com_rename (arg) + char *arg; + { + too_dangerous ("rename"); + return (1); + } + + com_stat (arg) + char *arg; + { + struct stat finfo; + + if (!valid_argument ("stat", arg)) + return (1); + + if (stat (arg, &finfo) == -1) + { + perror (arg); + return (1); + } + + printf ("Statistics for `%s':\n", arg); + + printf ("%s has %d link%s, and is %d byte%s in length.\n", arg, + finfo.st_nlink, + (finfo.st_nlink == 1) ? "" : "s", + finfo.st_size, + (finfo.st_size == 1) ? "" : "s"); + printf ("Inode Last Change at: %s", ctime (&finfo.st_ctime)); + printf (" Last access at: %s", ctime (&finfo.st_atime)); + printf (" Last modified at: %s", ctime (&finfo.st_mtime)); + return (0); + } + + com_delete (arg) + char *arg; + { + too_dangerous ("delete"); + return (1); + } + + /* Print out help for ARG, or for all of the commands if ARG is + not present. */ + com_help (arg) + char *arg; + { + register int i; + int printed = 0; + + for (i = 0; commands[i].name; i++) + { + if (!*arg || (strcmp (arg, commands[i].name) == 0)) + { + printf ("%s\t\t%s.\n", commands[i].name, commands[i].doc); + printed++; + } + } + + if (!printed) + { + printf ("No commands match `%s'. Possibilties are:\n", arg); + + for (i = 0; commands[i].name; i++) + { + /* Print in six columns. */ + if (printed == 6) + { + printed = 0; + printf ("\n"); + } + + printf ("%s\t", commands[i].name); + printed++; + } + + if (printed) + printf ("\n"); + } + return (0); + } + + /* Change to the directory ARG. */ + com_cd (arg) + char *arg; + { + if (chdir (arg) == -1) + { + perror (arg); + return 1; + } + + com_pwd (""); + return (0); + } + + /* Print out the current working directory. */ + com_pwd (ignore) + char *ignore; + { + char dir[1024], *s; + + s = getwd (dir); + if (s == 0) + { + printf ("Error getting pwd: %s\n", dir); + return 1; + } + + printf ("Current directory is %s\n", dir); + return 0; + } + + /* The user wishes to quit using this program. Just set DONE non-zero. */ + com_quit (arg) + char *arg; + { + done = 1; + return (0); + } + + /* Function which tells you that you can't do this. */ + too_dangerous (caller) + char *caller; + { + fprintf (stderr, + "%s: Too dangerous for me to distribute. Write it yourself.\n", + caller); + } + + /* Return non-zero if ARG is a valid argument for CALLER, else print + an error message and return zero. */ + int + valid_argument (caller, arg) + char *caller, *arg; + { + if (!arg || !*arg) + { + fprintf (stderr, "%s: Argument required.\n", caller); + return (0); + } + + return (1); + } + + +File: readline.info, Node: Concept Index, Next: Function and Variable Index, Prev: Programming with GNU Readline, Up: Top + +Concept Index +************* + +* Menu: + +* interaction, readline: Readline Interaction. +* Kill ring: Readline Killing Commands. +* Killing text: Readline Killing Commands. +* readline, function: Basic Behavior. +* Yanking text: Readline Killing Commands. + + +File: readline.info, Node: Function and Variable Index, Prev: Concept Index, Up: Top + +Function and Variable Index +*************************** + +* Menu: + +* $else: Conditional Init Constructs. +* $endif: Conditional Init Constructs. +* $if: Conditional Init Constructs. +* abort (C-g): Miscellaneous Commands. +* accept-line (Newline, Return): Commands For History. +* alphabetic: Utility Functions. +* backward-char (C-b): Commands For Moving. +* backward-delete-char (Rubout): Commands For Text. +* backward-kill-line (C-x Rubout): Commands For Killing. +* backward-kill-word (M-DEL): Commands For Killing. +* backward-word (M-b): Commands For Moving. +* beginning-of-history (M-<): Commands For History. +* beginning-of-line (C-a): Commands For Moving. +* bell-style: Readline Init Syntax. +* call-last-kbd-macro (C-x e): Keyboard Macros. +* capitalize-word (M-c): Commands For Text. +* clear-screen (C-l): Commands For Moving. +* comment-begin: Readline Init Syntax. +* complete (TAB): Commands For Completion. +* completion-query-items: Readline Init Syntax. +* completion_matches: Completion Functions. +* convert-meta: Readline Init Syntax. +* delete-char (C-d): Commands For Text. +* delete-horizontal-space (): Commands For Killing. +* digit-argument (M-0, M-1, ... M-): Numeric Arguments. +* digit_p: Utility Functions. +* digit_value: Utility Functions. +* ding: Utility Functions. +* do-uppercase-version (M-a, M-b, ...): Miscellaneous Commands. +* downcase-word (M-l): Commands For Text. +* dump-functions (): Miscellaneous Commands. +* editing-mode: Readline Init Syntax. +* end-kbd-macro (C-x )): Keyboard Macros. +* end-of-history (M->): Commands For History. +* end-of-line (C-e): Commands For Moving. +* expand-tilde: Readline Init Syntax. +* filename_completion_function: Completion Functions. +* forward-char (C-f): Commands For Moving. +* forward-search-history (C-s): Commands For History. +* forward-word (M-f): Commands For Moving. +* free_undo_list: Allowing Undoing. +* history-search-backward (): Commands For History. +* history-search-forward (): Commands For History. +* horizontal-scroll-mode: Readline Init Syntax. +* insert-completions (): Commands For Completion. +* keymap: Readline Init Syntax. +* kill-line (C-k): Commands For Killing. +* kill-whole-line (): Commands For Killing. +* kill-word (M-d): Commands For Killing. +* lowercase_p: Utility Functions. +* mark-modified-lines: Readline Init Syntax. +* meta-flag: Readline Init Syntax. +* next-history (C-n): Commands For History. +* non-incremental-forward-search-history (M-n): Commands For History. +* non-incremental-reverse-search-history (M-p): Commands For History. +* numeric: Utility Functions. +* output-meta: Readline Init Syntax. +* possible-completions (M-?): Commands For Completion. +* prefix-meta (ESC): Miscellaneous Commands. +* previous-history (C-p): Commands For History. +* quoted-insert (C-q, C-v): Commands For Text. +* re-read-init-file (C-x C-r): Miscellaneous Commands. +* readline: Basic Behavior. +* redraw-current-line (): Commands For Moving. +* reverse-search-history (C-r): Commands For History. +* revert-line (M-r): Miscellaneous Commands. +* rl_add_defun: Function Naming. +* rl_add_undo: Allowing Undoing. +* rl_attempted_completion_function: Completion Variables. +* rl_basic_word_break_characters: Completion Variables. +* rl_begin_undo_group: Allowing Undoing. +* rl_bind_key: Binding Keys. +* rl_bind_key_in_map: Binding Keys. +* rl_clear_message: Redisplay. +* rl_complete: How Completing Works. +* rl_complete: Completion Functions. +* rl_completer_quote_characters: Completion Variables. +* rl_completer_word_break_characters: Completion Variables. +* rl_complete_internal: Completion Functions. +* rl_completion_entry_function: Completion Variables. +* rl_completion_entry_function: How Completing Works. +* rl_completion_query_items: Completion Variables. +* rl_copy_keymap: Keymaps. +* rl_copy_text: Modifying Text. +* rl_delete_text: Modifying Text. +* rl_discard_keymap: Keymaps. +* rl_done: Function Writing. +* rl_do_undo: Allowing Undoing. +* rl_end: Function Writing. +* rl_end_undo_group: Allowing Undoing. +* rl_filename_completion_desired: Completion Variables. +* rl_filename_quoting_desired: Completion Variables. +* rl_forced_update_display: Redisplay. +* rl_function_of_keyseq: Associating Function Names and Bindings. +* rl_generic_bind: Binding Keys. +* rl_get_keymap: Keymaps. +* rl_get_keymap_by_name: Keymaps. +* rl_ignore_completion_duplicates: Completion Variables. +* rl_ignore_some_completions_function: Completion Variables. +* rl_insert_completions: Completion Functions. +* rl_insert_text: Modifying Text. +* rl_instream: Function Writing. +* rl_invoking_keyseqs: Associating Function Names and Bindings. +* rl_invoking_keyseqs_in_map: Associating Function Names and Bindings. +* rl_kill_text: Modifying Text. +* rl_line_buffer: Function Writing. +* rl_make_bare_keymap: Keymaps. +* rl_make_keymap: Keymaps. +* rl_mark: Function Writing. +* rl_message: Redisplay. +* rl_modifying: Allowing Undoing. +* rl_named_function: Associating Function Names and Bindings. +* rl_on_new_line: Redisplay. +* rl_outstream: Function Writing. +* rl_parse_and_bind: Binding Keys. +* rl_pending_input: Function Writing. +* rl_point: Function Writing. +* rl_possible_completions: Completion Functions. +* rl_prompt: Function Writing. +* rl_readline_name: Function Writing. +* rl_redisplay: Redisplay. +* rl_reset_line_state: Redisplay. +* rl_reset_terminal: Utility Functions. +* rl_set_keymap: Keymaps. +* rl_special_prefixes: Completion Variables. +* rl_startup_hook: Function Writing. +* rl_terminal_name: Function Writing. +* rl_unbind_key: Binding Keys. +* rl_unbind_key_in_map: Binding Keys. +* self-insert (a, b, A, 1, !, ...): Commands For Text. +* show-all-if-ambiguous: Readline Init Syntax. +* start-kbd-macro (C-x (): Keyboard Macros. +* tab-insert (M-TAB): Commands For Text. +* tilde-expand (M-~): Miscellaneous Commands. +* to_lower: Utility Functions. +* to_upper: Utility Functions. +* transpose-chars (C-t): Commands For Text. +* transpose-words (M-t): Commands For Text. +* undo (C-_, C-x C-u): Miscellaneous Commands. +* universal-argument (): Numeric Arguments. +* unix-line-discard (C-u): Commands For Killing. +* unix-word-rubout (C-w): Commands For Killing. +* upcase-word (M-u): Commands For Text. +* uppercase_p: Utility Functions. +* username_completion_function: Completion Functions. +* yank (C-y): Commands For Killing. +* yank-last-arg (M-., M-_): Commands For History. +* yank-nth-arg (M-C-y): Commands For History. +* yank-pop (M-y): Commands For Killing. + + diff --git a/doc/readline.ps b/doc/readline.ps new file mode 100644 index 0000000..e96ac47 --- /dev/null +++ b/doc/readline.ps @@ -0,0 +1,3766 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.490s Copyright 1986, 1992 Radical Eye Software +%%Title: readline.dvi +%%Pages: 52 1 +%%BoundingBox: 0 0 612 792 +%%EndComments +%DVIPSCommandLine: dvips -D 300 -o readline.ps readline.dvi +%%BeginProcSet: tex.pro +%! +/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N /X{S N} +B /TR{translate}N /isls false N /vsize 11 72 mul N /@rigin{isls{[0 -1 1 0 0 0] +concat}if 72 Resolution div 72 VResolution div neg scale isls{Resolution hsize +-72 div mul 0 TR}if Resolution VResolution vsize -72 div 1 add mul TR matrix +currentmatrix dup dup 4 get round 4 exch put dup dup 5 get round 5 exch put +setmatrix}N /@landscape{/isls true N}B /@manualfeed{statusdict /manualfeed +true put}B /@copies{/#copies X}B /FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N +/IE 0 N /ctr 0 N /df-tail{/nn 8 dict N nn begin /FontType 3 N /FontMatrix +fntrx N /FontBBox FBB N string /base X array /BitMaps X /BuildChar{ +CharBuilder}N /Encoding IE N end dup{/foo setfont}2 array copy cvx N load 0 nn +put /ctr 0 N[}B /df{/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 +0 sf neg 0 0]N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data +dup length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{128 +ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub get 127 +sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data dup type +/stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N /rc 0 N /gp 0 N +/cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup /base get 2 index get +S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx 0 ch-xoff ch-yoff ch-height +sub ch-xoff ch-width add ch-yoff setcachedevice ch-width ch-height true[1 0 0 +-1 -.1 ch-xoff sub ch-yoff .1 add]{ch-image}imagemask restore}B /D{/cc X dup +type /stringtype ne{]}if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 +ne{dup dup length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N} +B /I{cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul add +.99 lt{/FV}{/RV}ifelse load def pop}N /eop{SI restore showpage userdict +/eop-hook known{eop-hook}if}N /@start{userdict /start-hook known{start-hook} +if /VResolution X /Resolution X 1000 div /DVImag X /IE 256 array N 0 1 255{IE +S 1 string dup 0 3 index put cvn put}for 65781.76 div /vsize X 65781.76 div +/hsize X}N /p{show}N /RMat[1 0 0 -1 0 0]N /BDot 260 string N /rulex 0 N /ruley +0 N /v{/ruley X /rulex X V}B /V{}B /RV statusdict begin /product where{pop +product dup length 7 ge{0 7 getinterval dup(Display)eq exch 0 4 getinterval +(NeXT)eq or}{pop false}ifelse}{false}ifelse end{{gsave TR -.1 -.1 TR 1 1 scale +rulex ruley false RMat{BDot}imagemask grestore}}{{gsave TR -.1 -.1 TR rulex +ruley scale 1 1 false RMat{BDot}imagemask grestore}}ifelse B /FV{gsave +transform round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail{dup +/delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M}B /d{-3 M} +B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{4 M}B /w{0 +rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{p 1 w}B /r{p 2 w} +B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p a}B /bos{/SS save N}B +/eos{SS restore}B end +%%EndProcSet +TeXDict begin 40258431 52099146 1000 300 300 @start /Fa 1 59 +df<70F8F8F87005057C840D>58 D E /Fb 1 59 df<78FCFCFCFC7806067B8510>58 +D E /Fc 49 127 df<60F0F0F0F0F0F0F0F0F0F0F0F0F0600000000060F0F0600417789614>33 +D<00800180018007E01FF039BC619CC18EC18EC18EC18471807F803FE00FF001F8019C018E4186 +E186E186E186718C39B81FF00FC00180018000800F1D7E9914>36 D<00C001C0030006000C001C +0038003000700070006000E000E000E000E000E000E000E000600070007000300038001C000C00 +0600030001C000C00A1D7A9914>40 D<8000C0006000300018001C000E00060007000700030003 +8003800380038003800380038003000700070006000E001C00180030006000C0008000091D7C99 +14>I<70F8FCFC7C0C1830E0C0060A798414>44 DI<70F8F8F87005 +05798414>I<07C00FE01C7038383018701C701CE00EE00EE00EE00EE00EE00EE00EE00EE00E70 +1C701C383838381C700FE007C00F177E9614>48 D<0300030007000F003F00F700470007000700 +0700070007000700070007000700070007000700070007007FF07FF00C177C9614>I<000E003E +007C00F003E007C01F003E00F800F000F8003E001F0007C003E000F0007C003E000E0F137E9414 +>60 D<4000E000F8007C001E000F8007C001F000F8003E001E003E00F801F007C00F801E007C00 +F800E00040000F157E9514>62 D<1FE03FF8701CE00EE00E400E003C007000E001C00380038003 +8003800300000000000000000003000780078003000F177E9614>I<01C00003E00003E0000360 +000360000770000770000770000770000630000E38000E38000E38000E38000E38001FFC001FFC +001C1C001C1C003C1E00380E00FE3F80FE3F8011177F9614>65 DI<03C60FFE1C3E181E381E700E700E600EE000E000E000E000E000E000E000600E700E700E38 +0C181C1C380FF003C00F177E9614>III76 DII82 D<0FCC1FFC307C603CE01CE01CE01CE00070 +007E003FE00FF001F8001C001E000E600EE00EE00EF01CF838FFF0C7E00F177E9614>I<7FFF80 +FFFF80E1C380E1C380E1C380E1C38001C00001C00001C00001C00001C00001C00001C00001C000 +01C00001C00001C00001C00001C00001C00001C0000FF8000FF80011177F9614>I<1FC0007FF0 +00707800201800001C00001C0007FC001FFC003C1C00701C00E01C00E01C00E01C00707C003FFF +800F8F8011107E8F14>97 DI<03F80FFC1C1C380870006000E000E000E000E00060007000380E1C1E0F +FC03F00F107E8F14>I<007E00007E00000E00000E00000E00000E00000E0007CE000FFE001C3E +00301E00700E00E00E00E00E00E00E00E00E00E00E00E00E00700E00301E00383E001FEFC007CF +C012177F9614>I<07E00FF01C38301C700CE00EE00EFFFEFFFEE00060007000380E1C1E0FFC03 +F00F107E8F14>I<007C00FE01CE03840380038003807FFEFFFE03800380038003800380038003 +80038003800380038003807FFC7FFC0F177F9614>I<07CF001FFF80383B80301800701C00701C +00701C003018003838003FF00037C0007000007000003FF8001FFC003FFE00700F00E00380E003 +80E00380E003807007003C1E001FFC0007F00011197F8F14>II<030007800780030000000000000000 +007F807F80038003800380038003800380038003800380038003800380FFFCFFFC0E187D9714> +I107 +DIII<07C01FF03C78701C701CE00EE00EE00EE00EE00EE00E701C783C3C781FF007 +C00F107E8F14>II<03CE000FFE001C3E00301E00700E00E00E00E00E00E00E00E00E00E00E00 +E00E00700E00301E001C3E000FEE0007CE00000E00000E00000E00000E00000E00000E00007FC0 +007FC012187F8F14>II<0FD83FF86038C038C038F0007F +803FF007F8001C6006E006F006F81CFFF8CFE00F107E8F14>I<030007000700070007007FFCFF +FC07000700070007000700070007000700070E070E070E070C03FC00F00F157F9414>IIII<7E3F007E3F001E38000E780007700007E00003E00001C00003C00003E000077000 +0E78000E38001C1C00FE3F80FE3F8011107F8F14>II<3FFF7FFF700E701C7038007000E001C0 +038007000E001C0738077007FFFFFFFF10107F8F14>I<1C103F38E7E041C00D047D9614>126 +D E /Fd 1 59 df<60F0F06004047D830B>58 D E /Fe 41 123 df<00FC000182000703000607 +000E02000E00000E00000E00000E00000E0000FFFF000E07000E07000E07000E07000E07000E07 +000E07000E07000E07000E07000E07000E07000E07000E07007F0FE0131A809915>12 +D<00FF000387000707000607000E07000E07000E07000E07000E07000E0700FFFF000E07000E07 +000E07000E07000E07000E07000E07000E07000E07000E07000E07000E07000E07000E07007F9F +E0131A809915>I<60F0F07010101020204080040B7D830B>44 DI<0780 +18603030303060186018E01CE01CE01CE01CE01CE01CE01CE01CE01CE01CE01CE01C6018601870 +383030186007800E187E9713>48 D<03000700FF00070007000700070007000700070007000700 +07000700070007000700070007000700070007000700FFF00C187D9713>I<0F80106020304038 +803CC01CE01C401C003C003800380070006000C001800100020004040804100430083FF87FF8FF +F80E187E9713>I<0F8010E02070607870382038007800700070006000C00F8000E00070003800 +3C003CE03CE03CC03C4038407030E00F800E187E9713>I<00300030007000F000F00170037002 +7004700C7008701070307020704070C070FFFF00700070007000700070007007FF10187F9713> +I<30183FF03FE03FC02000200020002000200027C03860203000380018001C001C401CE01CE01C +80184038403030E00F800E187E9713>I<01E006100C1818383038300070006000E000E7C0E860 +F030F018E018E01CE01CE01C601C601C701830183030186007C00E187E9713>I<40007FFE7FFC +7FFC40088010801080200040004000800180018001000300030003000300070007000700070007 +00070002000F197E9813>I<078018603030201860186018601870103C303E600F8007C019F030 +F86038401CC00CC00CC00CC00C6008201018600FC00E187E9713>I<07801860303070306018E0 +18E018E01CE01CE01C601C603C303C185C0F9C001C00180018003870307060604021801F000E18 +7E9713>I75 +D89 +D<3F8070C070E020700070007007F01C7030707070E070E071E071E0F171FB1E3C10107E8F13> +97 DI<07F80C1C381C30087000E000E000E000E000E000E0007000300438080C +1807E00E107F8F11>I<007E00000E00000E00000E00000E00000E00000E00000E00000E00000E +0003CE000C3E00380E00300E00700E00E00E00E00E00E00E00E00E00E00E00E00E00600E00700E +00381E001C2E0007CFC0121A7F9915>I<07C01C3030187018600CE00CFFFCE000E000E000E000 +6000300438080C1807E00E107F8F11>I<01F0031807380E100E000E000E000E000E000E00FFC0 +0E000E000E000E000E000E000E000E000E000E000E000E000E000E007FE00D1A80990C>I<0FCE +187330307038703870387038303018602FC02000600070003FF03FFC1FFE600FC003C003C003C0 +036006381C07E010187F8F13>II<18003C003C00180000000000000000000000 +0000FC001C001C001C001C001C001C001C001C001C001C001C001C001C001C00FF80091A80990A +>I107 DII +I<07E01C38300C700E6006E007E007E007E007E007E0076006700E381C1C3807E010107F8F13> +II<03 +C2000C2600381E00300E00700E00E00E00E00E00E00E00E00E00E00E00E00E00700E00700E0038 +1E001C2E0007CE00000E00000E00000E00000E00000E00000E00007FC012177F8F14>II<1F2060 +E04020C020C020F0007F003FC01FE000F080708030C030C020F0408F800C107F8F0F>I<040004 +0004000C000C001C003C00FFC01C001C001C001C001C001C001C001C001C201C201C201C201C20 +0E4003800B177F960F>IIIIII<7FF86070407040E041C041C00380070007000E081C081C0838107010 +7030FFF00D107F8F11>I E /Ff 2 42 df<007000E001C00380078007000E001E001E003C003C +003C0078007800780078007000F000F000F000F000F000F000F000F000F000F000F000F0007000 +78007800780078003C003C003C001E001E000E0007000780038001C000E000700C2E7EA112>40 +DI E /Fg 26 122 df<000FF07F00007FFBFF +C001F83FE3C003F07F87E007E07F87E00FC07F07E00FC07F03C00FC03F00000FC03F00000FC03F +00000FC03F00000FC03F00000FC03F0000FFFFFFFC00FFFFFFFC000FC03F00000FC03F00000FC0 +3F00000FC03F00000FC03F00000FC03F00000FC03F00000FC03F00000FC03F00000FC03F00000F +C03F00000FC03F00000FC03F00000FC03F00000FC03F00000FC03F00000FC03F00000FC03F0000 +7FF9FFF0007FF9FFF00023237FA221>11 D<0007F800007FFC0001FC0E0003F01F0007E03F000F +C03F000FC03F000FC03F000FC01E000FC00C000FC000000FC000000FC0FF80FFFFFF80FFFFFF80 +0FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F +800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F800FC01F807FF8FFF07FF8 +FFF01C237FA220>I<07FE00001FFF80003F07E0003F03F0003F01F0003F01F8001E01F8000001 +F8000001F800003FF80003FDF8001F81F8003E01F8007C01F800F801F800F801F800F801F800F8 +01F8007C02F8007E0CF8001FF87F8007E03F8019167E951C>97 DI<00FF8007FFE00F83F01F03F03E03F07E03F07C01E0 +7C0000FC0000FC0000FC0000FC0000FC0000FC00007C00007E00007E00003F00301F00600FC0E0 +07FF8000FE0014167E9519>I<0001FF000001FF0000003F0000003F0000003F0000003F000000 +3F0000003F0000003F0000003F0000003F0000003F0000003F0000FE3F0007FFBF000FC1FF001F +007F003E003F007E003F007C003F007C003F00FC003F00FC003F00FC003F00FC003F00FC003F00 +FC003F00FC003F007C003F007E003F003E003F001F007F000F81FF0007FF3FE001FC3FE01B237E +A220>I<00FE0007FF800F83C01F01E03E00F07E00F07C00F87C0078FC0078FFFFF8FFFFF8FC00 +00FC0000FC00007C00007C00003E00183E00181F00300F80E003FFC000FF0015167E951A>I<00 +1F8000FFE001F1F003E3F007E3F00FC3F00FC1E00FC0000FC0000FC0000FC0000FC0000FC000FF +FE00FFFE000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000F +C0000FC0000FC0000FC0000FC0000FC0000FC0007FFC007FFC0014237EA212>I<00FE0F8003FF +9FC00F83E3C01F01F3C01E00F0003E00F8003E00F8003E00F8003E00F8003E00F8001E00F0001F +01F0000F83E0000BFF800008FE000018000000180000001C0000001FFFE0001FFFFC000FFFFF00 +07FFFF001FFFFF807C001FC078000FC0F80007C0F80007C0F80007C07C000F803E001F001F807E +000FFFFC0001FFE0001A217F951D>II<1E003F007F807F807F807F803F001E00000000000000000000000000FF80FF80 +1F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F80FFF0FF +F00C247EA30F>I107 +DI< +FF03F803F800FF0FFE0FFE001F183F183F001F201F201F001F401FC01F801F401FC01F801F801F +801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F80 +1F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F801F +801F80FFF0FFF0FFF0FFF0FFF0FFF02C167D9531>II< +00FF0007FFE00F81F01F00F83E007C7C003E7C003E7C003EFC003FFC003FFC003FFC003FFC003F +FC003FFC003F7C003E7E007E3E007C1F00F80F81F007FFE000FF0018167E951D>II<00FE030007FF07000FC1CF001F00DF003F007F007E003F007E00 +3F007C003F00FC003F00FC003F00FC003F00FC003F00FC003F00FC003F00FC003F007E003F007E +003F003E007F001F00FF000FC1FF0007FF3F0001FC3F0000003F0000003F0000003F0000003F00 +00003F0000003F0000003F0000003F000001FFE00001FFE01B207E951E>II<07F9801FFF80380780700380F0 +0180F00180F80000FF0000FFF8007FFE003FFF001FFF8007FF80003FC0C007C0C003C0E003C0E0 +03C0F00380FC0F00EFFE00C3F80012167E9517>I<00C00000C00000C00000C00001C00001C000 +03C00007C0000FC0001FC000FFFF00FFFF000FC0000FC0000FC0000FC0000FC0000FC0000FC000 +0FC0000FC0000FC0000FC0000FC1800FC1800FC1800FC1800FC18007C18007E30003FE0000FC00 +11207F9F16>IIIIII +E /Fh 23 122 df<00E00000E00000E00000E00040E040F0E1E0F8E3E07EEFC01FFF0007FC0003 +F80007FC001FFF007EEFC0F8E3E0F0E1E040E04000E00000E00000E00000E00013157D991A>42 +D<007C3801FF3807FFF80F83F81E00F81C0078380078380038700038700038700000E00000E000 +00E00000E00000E00000E00000E00000E000007000007000387000383800383800381C00701E00 +F00F83E007FFC001FF80007C00151E7E9D1A>67 D<7FFFFCFFFFFC7FFFFC0E001C0E001C0E001C +0E001C0E001C0E00000E00000E07000E07000E07000FFF000FFF000FFF000E07000E07000E0700 +0E00000E00000E00000E000E0E000E0E000E0E000E0E000E7FFFFEFFFFFE7FFFFE171E7F9D1A> +69 D<7FFFFCFFFFFC7FFFFC0E001C0E001C0E001C0E001C0E001C0E00000E00000E07000E0700 +0E07000FFF000FFF000FFF000E07000E07000E07000E00000E00000E00000E00000E00000E0000 +0E00000E00007FE000FFF0007FE000161E7F9D1A>I73 D75 D<7FE000FFF0007FE0000E00000E00000E +00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E +00000E00000E00000E00000E00380E00380E00380E00380E00387FFFF8FFFFF87FFFF8151E7E9D +1A>I<7FFF00FFFFC07FFFE00E01F00E00780E00380E003C0E001C0E001C0E001C0E001C0E003C +0E00380E00780E01F00FFFE00FFFC00FFF000E00000E00000E00000E00000E00000E00000E0000 +0E00000E00007FC000FFE0007FC000161E7F9D1A>80 D<1FF0003FFC007FFE00780F0030070000 +0380000380007F8007FF801FFF803F8380780380700380E00380E00380E00380700780780F803F +FFFC1FFDFC07F0FC16157D941A>97 D<00FF8003FFC00FFFE01F01E03C00C07800007000007000 +00E00000E00000E00000E00000E000007000007000007800703C00701F01F00FFFE003FFC000FE +0014157D941A>99 D<001FC0001FC0001FC00001C00001C00001C00001C00001C00001C001F1C0 +07FDC00FFFC01E0FC03C07C07803C07001C0E001C0E001C0E001C0E001C0E001C0E001C0E001C0 +7003C07003C03807C03E0FC01FFFFC07FDFC01F1FC161E7E9D1A>I<01F80007FF000FFF801E07 +C03C01C07800E07000E0E00070E00070FFFFF0FFFFF0FFFFF0E000007000007000007800703C00 +701F01F00FFFE003FFC000FE0014157D941A>I +104 D<01C00003E00003E00003E00001C0000000000000000000000000000000007FE000FFE000 +7FE00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E000 +00E00000E00000E000FFFFC0FFFFC0FFFFC0121F7C9E1A>I<7CE0E000FFFBF8007FFFF8001F1F +1C001E1E1C001E1E1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C +1C1C001C1C1C001C1C1C001C1C1C001C1C1C007F1F1F00FF9F9F807F1F1F00191580941A>109 +DI<01F00007FC001F +FF003E0F803C07807803C07001C0E000E0E000E0E000E0E000E0E000E0E000E0F001E07001C078 +03C03C07803E0F801FFF0007FC0001F00013157D941A>II114 D<00C00001C00001C00001C00001C00001C00001C0007FFFE0FFFFE0FFFFE001C00001C0 +0001C00001C00001C00001C00001C00001C00001C00001C00001C07001C07001C07001C07000E0 +E000FFE0007FC0001F00141C7F9B1A>116 DI<7FC7FCFFC7FE7FC7FC0E00E00E00E00F01E00701C00701C00783C003 +838003838003838001C70001C70001C70000EE0000EE0000EE00007C00007C0000380017157F94 +1A>I<7FC7FCFFC7FE7FC7FC0E00E00F00E00701E00701C00781C00381C003838001C38001C380 +01C70000E70000E70000E600006600006E00003C00003C00003C00003C00003800003800007800 +00700030700078E00079E0007FC0003F80001E000017207F941A>121 D +E /Fi 51 122 df<3C7EFFFFFFFF7E3C08087C8711>46 D<001C00003C0000FC00FFFC00FFFC00 +00FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC00 +00FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC00 +00FC0000FC007FFFFC7FFFFC16237CA21F>49 D<01FF0007FFC01E07F03803F86001FC7C00FEFE +00FEFE00FFFE007FFE007F7C007F3800FF0000FF0000FE0000FE0001FC0001F80003F00007E000 +0780000F00001E00003C0000700000E00301C0030380070700060600060FFFFE1FFFFE3FFFFE7F +FFFCFFFFFCFFFFFC18237DA21F>I<01FF0007FFE01E03F03801F83C01FC7E00FE7E00FE7E00FE +3E00FE1C01FE0001FC0001FC0003F80007F0000FC001FF0001FF000007E00001F00001F80000FC +0000FE0000FF0000FF1000FF7C00FFFE00FFFE00FFFE00FEFE00FE7C01FC7001F83E07F00FFFC0 +01FF0018237DA21F>I<0000380000007800000078000000F8000001F8000003F8000007F80000 +06F800000CF800001CF8000038F8000030F8000060F80000E0F80001C0F8000180F8000300F800 +0700F8000E00F8001C00F8001800F8003000F8007000F800E000F800FFFFFFC0FFFFFFC00001F8 +000001F8000001F8000001F8000001F8000001F8000001F800007FFFC0007FFFC01A237EA21F> +I<18000C1F007C1FFFF81FFFF01FFFE01FFFC01FFF801FFE001800001800001800001800001800 +0018FF001BFFE01F01F01C00F80800FC00007E00007E00007E00007F00007F78007FFC007FFC00 +7FFC007FFC007EF8007E6000FC7000FC3801F81E07E007FFC001FE0018237DA21F>I<001FC000 +7FF001F83803E00C07803E0F807E1F007E3F007E3F007E7E003C7E00007E00007E0000FE3FC0FE +7FF0FE80F8FF80FCFF007CFF007EFE007EFE007FFE007FFE007FFE007F7E007F7E007F7E007F7E +007F3E007E3F007E1F007C0F80F807C1F003FFC0007F0018237DA21F>I<300000003C0000003F +FFFFC03FFFFFC03FFFFF807FFFFF007FFFFE007FFFFC006000180060001800E0003000C0006000 +C000C0000001800000018000000300000007000000060000000E0000001E0000001E0000001E00 +00003C0000003C0000007C0000007C0000007C0000007C000000FC000000FC000000FC000000FC +000000FC000000FC000000FC000000780000003000001A257DA41F>I<00FF8003FFE00F01F81C +007C38003C38001E78001E78001E7C001E7E001E7F803C7FE03C3FF8781FFCF01FFFC00FFFC003 +FFE003FFF80FFFFC1E1FFC3C07FE7801FE7800FFF0003FF0001FF0000FF0000FF0000FF0000E78 +000E78001C3E00381F80F007FFE000FF0018237DA21F>I<00FF0003FFC00F83E01F00F03F00F8 +7E007C7E007C7E007EFE007EFE007EFE007EFE007FFE007FFE007FFE007F7E007F7E00FF3E00FF +3F01FF1F017F0FFE7F03FC7F00007F00007E00007E3C007E7E00FC7E00FC7E00F87E00F07C01F0 +3003E01C0F800FFF0003F80018237DA21F>I<00001C00000000001C00000000003E0000000000 +3E00000000003E00000000007F00000000007F0000000000FF8000000000FF8000000000FF8000 +0000019FC0000000019FC0000000031FE0000000030FE0000000030FE00000000607F000000006 +07F00000000C07F80000000C03F80000001C03FC0000001801FC0000001801FC0000003001FE00 +00003000FE0000007FFFFF0000007FFFFF00000060007F000000C0007F800000C0003F800001C0 +003FC0000180001FC0000180001FC0000300000FE0000300000FE0000780000FF000FFF801FFFF +80FFF801FFFF8029257EA42E>65 DI<0000FF8008000FFFF018003FC03C7800FE0006F801F80003F803F0 +0001F807E00000F80FC00000781FC00000783F800000383F800000387F800000187F000000187F +00000018FF00000000FF00000000FF00000000FF00000000FF00000000FF00000000FF00000000 +FF00000000FF000000007F000000007F000000187F800000183F800000183F800000181FC00000 +300FC000003007E000006003F00000C001F800018000FE000700003FC01E00000FFFF8000000FF +C00025257DA42C>I69 DI72 +DI75 +DI< +FFF8000000FFF8FFFC000001FFF803FC000001FE00037E0000037E00037E0000037E00037E0000 +037E00033F0000067E00033F0000067E00031F80000C7E00031F80000C7E00030FC000187E0003 +0FC000187E000307E000307E000307E000307E000307E000307E000303F000607E000303F00060 +7E000301F800C07E000301F800C07E000300FC01807E000300FC01807E0003007E03007E000300 +7E03007E0003007E03007E0003003F06007E0003003F06007E0003001F8C007E0003001F8C007E +0003000FD8007E0003000FD8007E00030007F0007E00030007F0007E00030007F0007E00030003 +E0007E00078003E0007E00FFFC01C01FFFF8FFFC01C01FFFF835257EA43A>II82 D<00FF008007FFE3800F80F7801E001F80 +3C000F807800078078000380F8000380F8000180F8000180FC000180FC000000FF0000007FE000 +007FFF00003FFFE0003FFFF8001FFFFE0007FFFF0003FFFF80007FFF800003FFC000003FC00000 +0FE0000007E0000007E0C00003E0C00003E0C00003E0C00003C0E00003C0F00007C0F8000780FC +000F00FFC03E00E3FFF800803FE0001B257DA422>I<7FFFFFFFF87FFFFFFFF87E00FE01F87800 +FE00787000FE00386000FE00186000FE0018E000FE001CE000FE000CC000FE000CC000FE000CC0 +00FE000CC000FE000C0000FE00000000FE00000000FE00000000FE00000000FE00000000FE0000 +0000FE00000000FE00000000FE00000000FE00000000FE00000000FE00000000FE00000000FE00 +000000FE00000000FE00000000FE00000000FE00000000FE00000000FE00000000FE000000FFFF +FE0000FFFFFE0026247EA32B>IIII89 D<07FF00001FFFC0003E +03E0003F01F0003F01F8003F00FC001E00FC000000FC000000FC000000FC00003FFC0003FCFC00 +0FC0FC003F00FC007E00FC007E00FC00FC00FC00FC00FC00FC00FC00FC017C007E017C003F067C +001FFC3FE007F01FE01B187E971E>97 DI<007FE003FFF807C07C1F80FC1F00FC3F00FC7E +00787E0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE00007E00007F00003F000C1F +800C1FC01807E07003FFE0007F0016187E971B>I<0001FF800001FF8000001F8000001F800000 +1F8000001F8000001F8000001F8000001F8000001F8000001F8000001F8000001F8000001F8000 +7F1F8003FFDF8007E0FF801F803F803F001F803F001F807E001F807E001F80FE001F80FE001F80 +FE001F80FE001F80FE001F80FE001F80FE001F80FE001F807E001F807E001F803F001F803F003F +801F807F800FC0FF8003FF9FF800FE1FF81D267EA522>I<007F0003FFC007C1F00F80F81F00F8 +3F007C7E007C7E007EFE007EFE007EFFFFFEFFFFFEFE0000FE0000FE00007E00007E00007E0006 +3F00061F000C0F801807E07003FFE0007F8017187E971C>I<000FC0007FF000F8F001F1F803F1 +F803E1F807E0F007E00007E00007E00007E00007E00007E00007E000FFFF00FFFF0007E00007E0 +0007E00007E00007E00007E00007E00007E00007E00007E00007E00007E00007E00007E00007E0 +0007E00007E00007E00007E00007E0007FFF007FFF0015267EA513>I<01FF07C007FFDFE00F83 +F1E01F01F1E03E00F8007E00FC007E00FC007E00FC007E00FC007E00FC007E00FC003E00F8001F +01F0000F83E0000FFFC00011FF00003000000030000000380000003C0000003FFFE0001FFFFC00 +1FFFFE000FFFFF001FFFFF803C003F8078000FC0F80007C0F80007C0F80007C0F80007C07C000F +803E001F001F807E0007FFF80000FFC0001B247E971F>II<0F001F803FC03FC03FC03FC0 +1F800F000000000000000000000000000000FFC0FFC00FC00FC00FC00FC00FC00FC00FC00FC00F +C00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC00FC0FFF8FFF80D277EA611>I107 +DI +II<007F800003FFF00007C0F8001F +807E003F003F003F003F007E001F807E001F80FE001FC0FE001FC0FE001FC0FE001FC0FE001FC0 +FE001FC0FE001FC0FE001FC07E001F807E001F803F003F003F003F001F807E000FC0FC0003FFF0 +00007F80001A187E971F>II114 D<07F9801FFF803C0F80700380F00180F00180F00180FC0000FF80007FFC007FFE00 +3FFF800FFFC003FFC0001FE00003E0C001E0C001E0E001E0E001C0F003C0FC0780EFFF00C3FC00 +13187E9718>I<00600000600000600000600000E00000E00001E00001E00003E00007E0001FE0 +00FFFFC0FFFFC007E00007E00007E00007E00007E00007E00007E00007E00007E00007E00007E0 +0007E00007E06007E06007E06007E06007E06007E06003E0C003F0C001FF80007E0013237FA218 +>IIIIII E /Fj 27 122 +df<0003E0001C1800381800703C00E03C00E03801C00001C00001C00001C00001C0000380007F +FFF00380700380700380700380700700E00700E00700E00700E00700E00700E00E01C00E01C00E +01C00E01C00E01C00E01C01C03801E03C0FF0FF816207E9F19>12 D45 +D<07FFFFF8007C0078003C0038003C001800780018007800080078000800780008007800080078 +000800F0100000F0100000F0100000F0300000F0700000FFF00001E0600001E0200001E0200001 +E0200001E0200001E0000003C0000003C0000003C0000003C0000003C0000003C0000007800000 +07C00000FFFE00001D1F7E9E1E>70 D<07FFE07FE0007C001F00003C000C00003C001800007800 +10000078004000007800800000780100000078020000007804000000F008000000F010000000F0 +60000000F0F0000000F1F0000000F278000001E478000001E878000001F03C000001E03C000001 +E01E000001E01E000003C00F000003C00F000003C00F000003C007800003C007800003C003C000 +078003C00007C007E000FFFC3FFC00231F7E9E23>75 D<07F8000C0C001E06001E07001C070000 +070000070000070000FF0007C7001E07003C0E00780E00F00E10F00E10F00E10F01E10F02E2078 +4F401F878014147D9317>97 D<01FC07060E0F1C0F380E78007000F000F000F000F000E000E000 +E000E000F0027004300818300FC010147C9314>99 D<0000700003F00000F00000700000700000 +E00000E00000E00000E00000E00000E00001C000F9C00305C00E03C01C03C03801C07803807003 +80F00380F00380F00380F00380E00700E00700E00700E00700E00700700F00301E00186F000F8F +E014207C9F19>I<00F800070E000E07001C0700380380780380700380F00380F00380FFFF80F0 +0000E00000E00000E00000E00000F001007002003004001C180007E00011147D9314>I<000780 +0018C00031E00061E000E1C000C00001C00001C00001C00001C00001C0000380007FF800038000 +0380000380000380000700000700000700000700000700000700000E00000E00000E00000E0000 +0E00000E00001C00001E0000FFE00013207E9F0E>I<00000E003E1100E1A301C1C20381E00780 +E00701E00F01E00F01E00F01E00703C007038007870004FC000800000800001800001C00000FFF +000FFFC007FFE01800F0300030600030C00030C00030C000306000603000C01C070007FC00181F +809417>I<00E00007E00001E00000E00000E00001C00001C00001C00001C00001C00001C00003 +8000038F800390E003A0E003C0600380600780E00700E00700E00700E00700E00700E00E01C00E +01C00E01C00E01C00E01C00E01C01C03801E03C0FFCFF815207E9F19>I<01C003E003E003C001 +8000000000000000000000000003801F800780038003800700070007000700070007000E000E00 +0E000E000E000E001C001E00FF800B1F7F9E0C>I<00E00007E00001E00000E00000E00001C000 +01C00001C00001C00001C00001C0000380000383FC0380F00380C0038180038100070400070800 +071800073800077C00071C000E1C000E0E000E0E000E0F000E07000E07801C03801E07C0FF8FF0 +16207E9F18>107 D<00E007E001E000E000E001C001C001C001C001C001C00380038003800380 +038003800700070007000700070007000E000E000E000E000E000E001C001E00FFC00B207F9F0C +>I<0387C07C001F9861860007A072070003C03403000380380300078078070007007007000700 +7007000700700700070070070007007007000E00E00E000E00E00E000E00E00E000E00E00E000E +00E00E000E00E00E001C01C01C001E01E01E00FFCFFCFFC022147E9326>I<038F801F90E007A0 +E003C0600380600780E00700E00700E00700E00700E00700E00E01C00E01C00E01C00E01C00E01 +C00E01C01C03801E03C0FFCFF815147E9319>I<00FC000387000E01801C00C03800E03800E070 +00F0F000F0F000F0F000F0F000F0E001E0E001E0E001C0E003C0F00380700700380E001C1C0007 +E00014147D9317>I<00E3E007EC3800F01C00E01E00E00E01C00E01C00F01C00F01C00F01C00F +01C00F03801E03801E03801C03803C0380380380700740E00721C0071F00070000070000070000 +0E00000E00000E00000E00001E0000FFC000181D809319>I<00F040038CC00E04C01C03C03C03 +C0780380780380F00380F00380F00380F00380E00700E00700E00700F00700F00F00700F00301E +00186E000F8E00000E00000E00000E00001C00001C00001C00001C00003C0001FF80121D7C9318 +>I<038E001FB38007C78003C7800383000780000700000700000700000700000700000E00000E +00000E00000E00000E00000E00001C00001E0000FFE00011147E9312>I<01F2060E0806180618 +02380438001E001FE00FF003F8003C401C400C400C600C6018E010D0608FC00F147E9312>I<00 +80010001000100030007000F001E00FFF80E000E000E000E001C001C001C001C001C001C003800 +38203820382038203840384018800F000D1C7C9B12>I<1C0380FC1F803C07801C03801C038038 +0700380700380700380700380700380700700E00700E00700E00700E00701E00701E00703C0030 +5E001F9FC012147B9319>I +II<1FF0FF03C07801C06001C04000E08000E180007300007600003C00003C +00001C00002E00004E000087000107000203800603800C01C03E03E0FF07FC18147F9318>I<0F +F83F8001E00E0001C00C0001C0080000E0180000E0100000E0200000E0200000F0400000704000 +00708000007080000071000000390000003A0000003E0000003C00000038000000180000001000 +000010000000200000002000000040000070C00000F0800000F1000000E20000007C000000191D +809318>I E /Fk 34 121 df<0001C0000003C000000FC000007FC0001FFFC000FFFFC000FFBF +C000E03FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC00000 +3FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000 +003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC0 +00003FC000003FC000003FC000003FC000003FC000003FC000003FC0007FFFFFE07FFFFFE07FFF +FFE01B2E7AAD28>49 D<003FE00001FFFE0007FFFF800F80FFC01E003FE038001FF07C000FF87E +0007FCFF0007FCFF8007FEFF8007FEFF8003FEFF8003FE7F0003FE3E0007FE000007FE000007FC +000007FC00000FF800000FF800000FF000001FE000001FC000003F8000007F0000007E000000F8 +000001F0000003E0000007C000000F0000001E000E003C000E0038000E0070001E00E0001C01C0 +001C0300003C07FFFFFC0FFFFFFC1FFFFFFC3FFFFFFC7FFFFFF8FFFFFFF8FFFFFFF8FFFFFFF81F +2E7CAD28>I<000003FF80018000003FFFF003800001FFFFFC07800007FF003F0F80001FF80007 +9F80003FC00001FF8000FF800000FF8001FE0000007F8003FC0000003F8007FC0000001F8007F8 +0000000F800FF00000000F801FF000000007801FF000000007803FE000000007803FE000000003 +807FE000000003807FE000000003807FC000000000007FC00000000000FFC00000000000FFC000 +00000000FFC00000000000FFC00000000000FFC00000000000FFC00000000000FFC00000000000 +FFC00000000000FFC000000000007FC000000000007FC000000000007FE000000000007FE00000 +0003803FE000000003803FE000000003801FF000000003801FF000000007800FF0000000070007 +F8000000070007FC0000000E0003FC0000001E0001FE0000001C0000FF8000007800003FC00000 +F000001FF80003E0000007FF003F80000001FFFFFE000000003FFFF80000000003FF8000003131 +7CB03A>67 D69 +DI<000003FF00030000007F +FFF007000001FFFFFC0F000007FF007E1F00001FF0000FBF00007FC00003FF0000FF800001FF00 +01FE0000007F0003FC0000007F0007FC0000003F000FF80000001F000FF00000001F001FF00000 +000F001FF00000000F003FE000000007003FE000000007007FE000000007007FE000000007007F +C00000000000FFC00000000000FFC00000000000FFC00000000000FFC00000000000FFC0000000 +0000FFC00000000000FFC00000000000FFC00000000000FFC00000000000FFC00000000000FFC0 +0007FFFFFC7FC00007FFFFFC7FE00007FFFFFC7FE0000001FF003FE0000001FF003FE0000001FF +001FF0000001FF001FF0000001FF000FF0000001FF000FF8000001FF0007FC000001FF0003FC00 +0001FF0001FE000001FF0000FF800001FF00007FC00003FF00001FF800077F000007FF003E3F00 +0001FFFFFC1F0000007FFFF00F00000003FF80030036317CB03F>I73 +D76 D78 +D80 D82 +D<7FFFFFFFFFFF007FFFFFFFFFFF007FFFFFFFFFFF007FC00FF801FF007E000FF8003F007C000F +F8001F0078000FF8000F0078000FF8000F0070000FF8000700F0000FF8000780F0000FF8000780 +F0000FF8000780E0000FF8000380E0000FF8000380E0000FF8000380E0000FF8000380E0000FF8 +00038000000FF800000000000FF800000000000FF800000000000FF800000000000FF800000000 +000FF800000000000FF800000000000FF800000000000FF800000000000FF800000000000FF800 +000000000FF800000000000FF800000000000FF800000000000FF800000000000FF80000000000 +0FF800000000000FF800000000000FF800000000000FF800000000000FF800000000000FF80000 +0000000FF800000000000FF800000000000FF800000000000FF800000000000FF800000000000F +F8000000007FFFFFFF0000007FFFFFFF0000007FFFFFFF000031307DAF38>84 +DII<00FFF0000003FFFE00000F803F80000FC00FE0001FE007F0001FE007F000 +1FE003F8000FC003FC00078003FC00000003FC00000003FC00000003FC00000003FC000000FFFC +00001FFFFC0000FFE3FC0003FC03FC000FF003FC001FC003FC003FC003FC007F8003FC007F8003 +FC00FF0003FC00FF0003FC00FF0003FC00FF0007FC00FF0007FC007F800DFC003FC019FE001FE0 +70FFF007FFE07FF000FF803FF024207E9F27>97 D<01F8000000FFF8000000FFF8000000FFF800 +00000FF800000007F800000007F800000007F800000007F800000007F800000007F800000007F8 +00000007F800000007F800000007F800000007F800000007F800000007F800000007F83FE00007 +F8FFFC0007FBE07F0007FF001F8007FE000FC007FC000FE007F80007F007F80007F807F80007F8 +07F80003FC07F80003FC07F80003FC07F80003FE07F80003FE07F80003FE07F80003FE07F80003 +FE07F80003FE07F80003FE07F80003FE07F80003FC07F80003FC07F80003FC07F80007F807F800 +07F807F80007F007FC000FE007FE000FC007E7003F8007C3C0FE000780FFF80007003FC0002732 +7EB12D>I<000FFF00007FFFC001FC01F003F003F007E007F80FE007F81FC007F83FC003F03FC0 +01E07F8000007F8000007F800000FF800000FF800000FF800000FF800000FF800000FF800000FF +800000FF8000007F8000007F8000007F8000003FC0001C3FC0001C1FC000380FE0003807E00070 +03F001E001FC07C0007FFF00000FF8001E207D9F24>I<0000000FC0000007FFC0000007FFC000 +0007FFC00000007FC00000003FC00000003FC00000003FC00000003FC00000003FC00000003FC0 +0000003FC00000003FC00000003FC00000003FC00000003FC00000003FC00000003FC00007F83F +C0003FFF3FC000FE07BFC003F801FFC007E0007FC00FE0007FC01FC0003FC03FC0003FC03FC000 +3FC07F80003FC07F80003FC07F80003FC0FF80003FC0FF80003FC0FF80003FC0FF80003FC0FF80 +003FC0FF80003FC0FF80003FC0FF80003FC07F80003FC07F80003FC07F80003FC03FC0003FC03F +C0003FC01FC0003FC00FE0007FC007E000FFC003F003FFE001FC0F3FFE007FFE3FFE000FF03FFE +27327DB12D>I<000FFC00007FFF8001FC0FC003F003E007E001F00FE001F81FC000FC3FC000FE +3FC000FE7F80007E7F80007F7F80007FFF80007FFF80007FFFFFFFFFFFFFFFFFFF800000FF8000 +00FF800000FF8000007F8000007F8000007F8000003FC000071FC000071FC0000E0FE0000E07F0 +001C03F8007800FE03E0003FFFC00007FE0020207E9F25>I<0001FE00000FFF80001FC3C0007F +07E000FE0FF001FE0FF001FC0FF003FC0FF003FC07E003FC018003FC000003FC000003FC000003 +FC000003FC000003FC000003FC000003FC0000FFFFFC00FFFFFC00FFFFFC0003FC000003FC0000 +03FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC00 +0003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC +000003FC000003FC000003FC000003FC00007FFFF0007FFFF0007FFFF0001C327EB119>I<001F +F007C000FFFE3FE001F83F79F007E00FC3F00FE00FE1F00FC007E0E01FC007F0001FC007F0003F +C007F8003FC007F8003FC007F8003FC007F8003FC007F8001FC007F0001FC007F0000FC007E000 +0FE00FE00007E00FC00003F83F000006FFFE00000E1FF000000E000000001E000000001E000000 +001F000000001F800000001FFFFF80000FFFFFF0000FFFFFFC0007FFFFFE0003FFFFFF0003FFFF +FF800FFFFFFFC01F00007FC07E00001FE07C00000FE0FC000007E0FC000007E0FC000007E0FC00 +0007E07E00000FC03E00000F803F00001F800FC0007E0007F803FC0001FFFFF000001FFF000024 +2F7E9F28>I<01F8000000FFF8000000FFF8000000FFF80000000FF800000007F800000007F800 +000007F800000007F800000007F800000007F800000007F800000007F800000007F800000007F8 +00000007F800000007F800000007F800000007F807F80007F83FFE0007F8783F0007F8C03F8007 +F9801FC007FB001FC007FE001FE007FC001FE007FC001FE007FC001FE007F8001FE007F8001FE0 +07F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001F +E007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F800 +1FE007F8001FE0FFFFC3FFFFFFFFC3FFFFFFFFC3FFFF28327DB12D>I<03C00007E0000FF0001F +F8001FF8001FF8001FF8000FF00007E00003C00000000000000000000000000000000000000000 +000000000000000001F800FFF800FFF800FFF8000FF80007F80007F80007F80007F80007F80007 +F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007 +F80007F80007F80007F80007F80007F800FFFF80FFFF80FFFF8011337DB217>I<01F800FFF800 +FFF800FFF8000FF80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F800 +07F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F800 +07F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F80007F800 +07F80007F80007F80007F80007F80007F800FFFFC0FFFFC0FFFFC012327DB117>108 +D<03F007F8001FE000FFF03FFE00FFF800FFF0783F01E0FC00FFF0C03F8300FE000FF1801FC600 +7F0007F3001FCC007F0007F6001FF8007F8007FC001FF0007F8007FC001FF0007F8007FC001FF0 +007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001F +E0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F800 +1FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8 +001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F8007F8001FE0007F80FF +FFC3FFFF0FFFFCFFFFC3FFFF0FFFFCFFFFC3FFFF0FFFFC3E207D9F43>I<03F007F800FFF03FFE +00FFF0783F00FFF0C03F800FF1801FC007F3001FC007F6001FE007FC001FE007FC001FE007FC00 +1FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8 +001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007 +F8001FE007F8001FE007F8001FE007F8001FE0FFFFC3FFFFFFFFC3FFFFFFFFC3FFFF28207D9F2D +>I<0007FC0000007FFFC00001FC07F00003F001F80007E000FC000FC0007E001FC0007F003FC0 +007F803F80003F807F80003FC07F80003FC07F80003FC0FF80003FE0FF80003FE0FF80003FE0FF +80003FE0FF80003FE0FF80003FE0FF80003FE0FF80003FE07F80003FC07F80003FC07F80003FC0 +3FC0007F803FC0007F801FC0007F000FE000FE0007E000FC0003F803F80001FE0FF000007FFFC0 +000007FC000023207E9F28>I<01F83FE000FFF8FFFC00FFFBE07F00FFFF003F8007FE001FC007 +FC000FE007F8000FF007F80007F807F80007F807F80007FC07F80003FC07F80003FC07F80003FE +07F80003FE07F80003FE07F80003FE07F80003FE07F80003FE07F80003FE07F80003FE07F80003 +FC07F80007FC07F80007FC07F80007F807F80007F807F8000FF007FC000FE007FE001FC007FF00 +3F8007FBC0FE0007F8FFF80007F83FC00007F800000007F800000007F800000007F800000007F8 +00000007F800000007F800000007F800000007F800000007F800000007F8000000FFFFC00000FF +FFC00000FFFFC00000272E7E9F2D>I<03F03F00FFF07FC0FFF1C3E0FFF187E00FF30FF007F60F +F007F60FF007FC07E007FC03C007FC000007FC000007F8000007F8000007F8000007F8000007F8 +000007F8000007F8000007F8000007F8000007F8000007F8000007F8000007F8000007F8000007 +F8000007F8000007F8000007F80000FFFFE000FFFFE000FFFFE0001C207E9F21>114 +D<01FF860007FFFE001F00FE003C003E0078001E0078000E00F8000E00F8000E00F8000E00FC00 +0000FF800000FFFC00007FFFC0007FFFF0003FFFF8001FFFFC0007FFFE0001FFFF00003FFF0000 +00FF8000003F8060001F80E0000F80E0000F80F0000F80F0000F00F8000F00FC001E00FE001C00 +FF807800F3FFF000C07F800019207D9F20>I<001C0000001C0000001C0000001C0000001C0000 +003C0000003C0000003C0000007C0000007C000000FC000001FC000003FC000007FC00001FFFFE +00FFFFFE00FFFFFE0003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC +000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC000003FC038003 +FC038003FC038003FC038003FC038003FC038003FC038001FC038001FC070000FE0700007F0E00 +003FFC000007F000192E7FAD1F>I<01F80007E0FFF803FFE0FFF803FFE0FFF803FFE00FF8003F +E007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F800 +1FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8001FE007F8 +001FE007F8001FE007F8001FE007F8001FE007F8003FE007F8003FE003F8007FE003F8007FE001 +FC00DFF000FE039FFF007FFF1FFF000FFC1FFF28207D9F2D>I119 D<7FFF807FFC7FFF807FFC7FFF807F +FC03FE000F0001FE001E0000FF003C0000FF807800007FC07800003FE0F000001FE1E000000FF3 +C000000FFF80000007FF00000003FE00000001FE00000000FF00000000FF80000000FFC0000001 +FFC0000003DFE00000078FF00000078FF800000F07FC00001E03FC00003C01FE00007800FF0000 +F000FF8000E0007FC001E0003FC0FFFC01FFFFFFFC01FFFFFFFC01FFFF28207F9F2B>I +E /Fl 1 14 df<0001FE00000007FF8000001E01E000007800780000E0001C0001800006000300 +00030006000001800C000000C00C000000C0180000006030000000303000000030300000003060 +0000001860000000186000000018C00000000CC00000000CC00000000CC00000000CC00000000C +C00000000CC00000000CC00000000CC00000000C60000000186000000018600000001830000000 +303000000030300000003018000000600C000000C00C000000C006000001800300000300018000 +060000E0001C000078007800001E01E0000007FF80000001FE0000262B7DA02D>13 +D E /Fm 53 122 df<001C0000001C0000001C0000007F800003FFE0000FFFF8001F9CFC003E1C +1E003C1C0F007C1C0700781C0F80F81C1F80F81C3F80F81C3F80F81C3F80FC1C3F80FE1C1F00FF +1C00007FDC00007FFC00007FFFC0003FFFE0001FFFF8000FFFFC0007FFFC0001FFFE00007FFF00 +001FFF00001C7F00001C3F80381C1F807C1C1F80FE1C0F80FE1C0F80FE1C0F80FC1C0F80F81C0F +00701C0F00701C1F00381C1E003C1C3C001F9CF8000FFFF00003FFE00000FF0000001C0000001C +0000001C000019307CAC22>36 D<3C007F00FF80FF80FFC0FFC0FFC07FC03EC000C000C0018001 +8001800300030006000E001C00380030000A157B8813>44 D<1C007F007F00FF80FF80FF807F00 +7F001C0009097B8813>46 D<000E00001E00007E0007FE00FFFE00FFFE00F8FE0000FE0000FE00 +00FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE00 +00FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE0000FE00 +00FE007FFFFE7FFFFE7FFFFE17277BA622>49 D<00FF800007FFF0000FFFFC001E03FE003800FF +807C003F80FE003FC0FF001FC0FF001FE0FF000FE0FF000FE07E000FE03C001FE000001FE00000 +1FC000001FC000003F8000003F0000007E000000FC000000F8000001F0000003E0000007800000 +0F0000001E0000003C00E0007000E000E000E001C001C0038001C0060001C00FFFFFC01FFFFFC0 +3FFFFFC07FFFFFC0FFFFFF80FFFFFF80FFFFFF801B277DA622>I<007F800003FFF00007FFFC00 +0F80FE001F007F003F807F003F803F803F803F803F803F801F803F801F003F8000007F0000007F +0000007E000000FC000001F8000007F00000FFC00000FFC0000001F80000007E0000003F000000 +3F8000001FC000001FC000001FE000001FE03C001FE07E001FE0FF001FE0FF001FE0FF001FC0FF +003FC0FE003F807C007F003F00FE001FFFFC0007FFF00000FF80001B277DA622>I<00000E0000 +001E0000003E0000007E000000FE000000FE000001FE000003FE0000077E00000E7E00000E7E00 +001C7E0000387E0000707E0000E07E0000E07E0001C07E0003807E0007007E000E007E000E007E +001C007E0038007E0070007E00E0007E00FFFFFFF8FFFFFFF8FFFFFFF80000FE000000FE000000 +FE000000FE000000FE000000FE000000FE000000FE00007FFFF8007FFFF8007FFFF81D277EA622 +>I<180003001F801F001FFFFE001FFFFC001FFFF8001FFFF0001FFFC0001FFF00001C0000001C +0000001C0000001C0000001C0000001C0000001C0000001C7FC0001DFFF8001F80FC001E003F00 +08003F0000001F8000001FC000001FC000001FE000001FE018001FE07C001FE0FE001FE0FE001F +E0FE001FE0FE001FC0FC001FC078003F8078003F803C007F001F01FE000FFFFC0003FFF00000FF +80001B277DA622>I<00000780000000000780000000000FC0000000000FC0000000000FC00000 +00001FE0000000001FE0000000003FF0000000003FF0000000003FF00000000077F80000000077 +F800000000F7FC00000000E3FC00000000E3FC00000001C1FE00000001C1FE00000003C1FF0000 +000380FF0000000380FF00000007007F80000007007F8000000F007FC000000E003FC000000E00 +3FC000001C001FE000001C001FE000003FFFFFF000003FFFFFF000003FFFFFF00000700007F800 +00700007F80000F00007FC0000E00003FC0000E00003FC0001C00001FE0001C00001FE0003C000 +01FF00FFFE003FFFFCFFFE003FFFFCFFFE003FFFFC2E297EA833>65 DI<00007FE0030007FFFC07001FFFFF0F007FF00F9F00FF0001FF01FC0000FF03F8 +00007F07F000003F0FE000001F1FC000001F1FC000000F3F8000000F3F800000077F800000077F +800000077F00000000FF00000000FF00000000FF00000000FF00000000FF00000000FF00000000 +FF00000000FF00000000FF000000007F000000007F800000007F800000073F800000073F800000 +071FC00000071FC000000E0FE000000E07F000001C03F800003C01FC00007800FF0001F0007FF0 +07C0001FFFFF800007FFFE0000007FF00028297CA831>IIII<00 +007FE003000007FFFC0700001FFFFF0F00007FF00F9F0000FF0001FF0001FC0000FF0003F80000 +7F0007F000003F000FE000001F001FC000001F001FC000000F003F8000000F003F80000007007F +80000007007F80000007007F0000000000FF0000000000FF0000000000FF0000000000FF000000 +0000FF0000000000FF0000000000FF0000000000FF0000000000FF0000FFFFF87F0000FFFFF87F +8000FFFFF87F800000FF003F800000FF003F800000FF001FC00000FF001FC00000FF000FE00000 +FF0007F00000FF0003F80000FF0001FC0000FF0000FF0001FF00007FF007FF00001FFFFF9F0000 +07FFFE0F0000007FF003002D297CA835>III75 +DIII<0000FFC00000000FFFFC0000003F807F0000 +00FE001FC00001F80007E00003F00003F00007E00001F8000FE00001FC001FC00000FE001FC000 +00FE003F8000007F003F8000007F007F8000007F807F0000003F807F0000003F807F0000003F80 +FF0000003FC0FF0000003FC0FF0000003FC0FF0000003FC0FF0000003FC0FF0000003FC0FF0000 +003FC0FF0000003FC0FF0000003FC0FF0000003FC07F0000003F807F8000007F807F8000007F80 +3F8000007F003F8000007F001FC00000FE001FC00000FE000FE00001FC0007F00003F80003F800 +07F00001FC000FE00000FE001FC000003FC0FF0000000FFFFC00000000FFC000002A297CA833> +II<0000FFC00000000FFFFC0000003FC0FF000000FE00 +1FC00001FC000FE00003F00003F00007F00003F8000FE00001FC001FC00000FE001FC00000FE00 +3F8000007F003F8000007F007F8000007F807F8000007F807F0000003F807F0000003F80FF0000 +003FC0FF0000003FC0FF0000003FC0FF0000003FC0FF0000003FC0FF0000003FC0FF0000003FC0 +FF0000003FC0FF0000003FC0FF0000003FC07F0000003F807F8000007F807F8000007F803F8000 +007F003F8000007F001FC00000FE001FC03E00FE000FE07F81FC0007E0C1C1F80003F18063F000 +01F98067E00000FF803FC000003FC07F0000000FFFFC00000000FFF800C00000003C00C0000000 +1E00C00000001E01C00000001F83C00000001FFFC00000000FFF800000000FFF800000000FFF00 +00000007FF0000000003FE0000000001FC0000000000F8002A357CA833>II<00FF00C003FFE1C00FFFF9C01F80FFC03F003FC03E000FC07C0007C0 +7C0007C0FC0003C0FC0003C0FC0001C0FE0001C0FE0001C0FF000000FFC000007FFC00007FFFE0 +003FFFF8001FFFFE001FFFFF0007FFFF8003FFFFC000FFFFC0000FFFE000007FE000001FF00000 +0FF0000007F0E00003F0E00003F0E00003F0E00003F0F00003E0F00003E0F80007E0FC0007C0FF +000F80FFE01F80E3FFFF00E1FFFC00C01FF0001C297CA825>I<7FFFFFFFFF807FFFFFFFFF807F +FFFFFFFF807F807F807F807C007F800F8078007F80078078007F80078070007F800380F0007F80 +03C0F0007F8003C0E0007F8001C0E0007F8001C0E0007F8001C0E0007F8001C0E0007F8001C000 +007F80000000007F80000000007F80000000007F80000000007F80000000007F80000000007F80 +000000007F80000000007F80000000007F80000000007F80000000007F80000000007F80000000 +007F80000000007F80000000007F80000000007F80000000007F80000000007F80000000007F80 +000000007F80000000007F80000000FFFFFFC00000FFFFFFC00000FFFFFFC0002A287EA72F>I< +FFFFF000FFFEFFFFF000FFFEFFFFF000FFFE03FC0000038003FC0000038003FC0000038003FC00 +00038003FC0000038003FC0000038003FC0000038003FC0000038003FC0000038003FC00000380 +03FC0000038003FC0000038003FC0000038003FC0000038003FC0000038003FC0000038003FC00 +00038003FC0000038003FC0000038003FC0000038003FC0000038003FC0000038003FC00000380 +03FC0000038003FC0000038003FC0000038003FC0000038003FC0000038001FC0000070001FE00 +00070000FE00000E00007F00000E00003F00003C00001FC0007800000FF003F0000007FFFFE000 +0000FFFF800000001FFC00002F297EA834>III89 D<03FF80000FFFF0001F01FC003F80FE003F807F003F803F003F803F801F003F800000 +3F8000003F8000003F8000003F80003FFF8001FC3F800FE03F801F803F803F003F807E003F80FC +003F80FC003F80FC003F80FC003F80FC005F807E00DF803F839FFC1FFE0FFC03F803FC1E1B7E9A +21>97 DI<003FF00001FFFC0003F03E000FC07F00 +1F807F003F007F003F007F007F003E007E0000007E000000FE000000FE000000FE000000FE0000 +00FE000000FE000000FE0000007E0000007E0000007F0000003F0003803F8003801F8007000FE0 +0E0003F83C0001FFF800003FC000191B7E9A1E>I<00007FF000007FF000007FF0000007F00000 +07F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F000 +0007F0003F87F001FFF7F007F03FF00FC00FF01F8007F03F0007F03F0007F07E0007F07E0007F0 +7E0007F0FE0007F0FE0007F0FE0007F0FE0007F0FE0007F0FE0007F0FE0007F0FE0007F07E0007 +F07E0007F03F0007F03F0007F01F800FF00FC01FF007E07FFF01FFE7FF007F87FF202A7EA925> +I<003FC00001FFF00003E07C000F803E001F801F001F001F003F000F807E000F807E000FC07E00 +0FC0FE0007C0FE0007C0FFFFFFC0FFFFFFC0FE000000FE000000FE0000007E0000007E0000007F +0000003F0001C01F0001C00F80038007C0070003F01E0000FFFC00003FE0001A1B7E9A1F>I<00 +07F8003FFC007E3E01FC7F03F87F03F07F07F07F07F03E07F00007F00007F00007F00007F00007 +F00007F000FFFFC0FFFFC0FFFFC007F00007F00007F00007F00007F00007F00007F00007F00007 +F00007F00007F00007F00007F00007F00007F00007F00007F00007F00007F00007F00007F0007F +FF807FFF807FFF80182A7EA915>I<007F80F001FFE3F807C0FE1C0F807C7C1F003E7C1F003E10 +3F003F003F003F003F003F003F003F003F003F003F003F001F003E001F003E000F807C0007C0F8 +0005FFE0000C7F8000180000001C0000001C0000001E0000001FFFF8001FFFFF000FFFFFC007FF +FFE003FFFFF00FFFFFF03E0007F07C0001F8F80000F8F80000F8F80000F8F80000F87C0001F07C +0001F03F0007E00FC01F8007FFFF00007FF0001E287E9A22>II<07000F801FC03FE03FE03FE01FC00F8007000000000000000000000000000000FF +E0FFE0FFE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE00FE0 +0FE00FE00FE00FE0FFFEFFFEFFFE0F2B7EAA12>I108 +DII< +003FE00001FFFC0003F07E000FC01F801F800FC03F0007E03F0007E07E0003F07E0003F07E0003 +F0FE0003F8FE0003F8FE0003F8FE0003F8FE0003F8FE0003F8FE0003F8FE0003F87E0003F07E00 +03F03F0007E03F0007E01F800FC00FC01F8007F07F0001FFFC00003FE0001D1B7E9A22>II114 D<03FE300FFFF03E03F07800F07000F0F00070F00070F8 +0070FE0000FFE0007FFF007FFFC03FFFE01FFFF007FFF800FFF80007FC0000FCE0007CE0003CF0 +003CF00038F80038FC0070FF01E0E7FFC0C1FF00161B7E9A1B>I<007000007000007000007000 +00F00000F00000F00001F00003F00003F00007F0001FFFE0FFFFE0FFFFE007F00007F00007F000 +07F00007F00007F00007F00007F00007F00007F00007F00007F00007F00007F07007F07007F070 +07F07007F07007F07007F07003F0E001F8C000FFC0003F0014267FA51A>III +III E /Fn 86 127 df<70F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F870000000000070F8 +F8F870051C779B18>33 D<4010E038F078E038E038E038E038E038E038E038E038E038E0386030 +0D0E7B9C18>I<030600078F00078F00078F00078F00078F00078F007FFFC0FFFFE0FFFFE07FFF +C00F1E000F1E000F1E000F1E000F1E000F1E007FFFC0FFFFE0FFFFE07FFFC01E3C001E3C001E3C +001E3C001E3C001E3C000C1800131C7E9B18>I<00C00001C00001C00001C00003F0000FFC003F +FE007DCF0071C700E1C380E1C780E1C780E1C780F1C00079C0003DC0001FE0000FF80003FC0001 +DE0001CF0001C70061C380F1C380F1C380E1C380E1C70071C70079DE003FFE001FF80007E00001 +C00001C00001C00000C00011247D9F18>I<3803007C07807C0780EE0F80EE0F00EE0F00EE1F00 +EE1E00EE1E00EE3E007C3C007C3C00387C0000780000780000F80000F00001F00001E00001E000 +03E00003C00003C00007C0000783800787C00F87C00F0EE00F0EE01F0EE01E0EE01E0EE03E0EE0 +3C07C03C07C018038013247E9F18>I<01C00007E0000FF0000E70001C38001C38001C38001C38 +001C73F01C73F01CE3F00FE3800FC7000F87000F07001F0E003F0E007B8E0073DC00E1DC00E0F8 +00E0F800E07070E0787070FC707FFFE03FCFE00F03C0141C7F9B18>I<387C7C7E3E0E0E0E1C1C +38F8F0C0070E789B18>I<007000F001E003C007800F001E001C00380038007000700070007000 +E000E000E000E000E000E000E000E0007000700070007000380038001C001E000F00078003C001 +F000F000700C24799F18>I<6000F00078003C001E000F000780038001C001C000E000E000E000 +E00070007000700070007000700070007000E000E000E000E001C001C0038007800F001E003C00 +7800F00060000C247C9F18>I<01C00001C00001C00001C000C1C180F1C780F9CF807FFF001FFC +0007F00007F0001FFC007FFF00F9CF80F1C780C1C18001C00001C00001C00001C00011147D9718 +>I<00600000F00000F00000F00000F00000F00000F00000F0007FFFC0FFFFE0FFFFE07FFFC000 +F00000F00000F00000F00000F00000F00000F00000600013147E9718>I<1C3E7E7F3F1F070E1E +7CF860080C788518>I<7FFF00FFFF80FFFF807FFF0011047D8F18>I<3078FCFC78300606778518 +>I<000300000780000780000F80000F00001F00001E00001E00003E00003C00007C0000780000 +780000F80000F00001F00001E00003E00003C00003C00007C0000780000F80000F00000F00001F +00001E00003E00003C00003C00007C0000780000F80000F00000F0000060000011247D9F18>I< +01F00007FC000FFE001F1F001C07003803807803C07001C07001C0E000E0E000E0E000E0E000E0 +E000E0E000E0E000E0E000E0E000E0F001E07001C07001C07803C03803801C07001F1F000FFE00 +07FC0001F000131C7E9B18>I<01800380038007800F803F80FF80FB8043800380038003800380 +0380038003800380038003800380038003800380038003807FFCFFFE7FFC0F1C7B9B18>I<03F0 +000FFE003FFF007C0F807003C0E001C0F000E0F000E06000E00000E00000E00001C00001C00003 +C0000780000F00001E00003C0000780000F00001E00007C0000F80001E00E03C00E07FFFE0FFFF +E07FFFE0131C7E9B18>I<001F00003F0000770000770000E70001E70001C70003870007870007 +07000E07001E07003C0700380700780700F00700FFFFF8FFFFF8FFFFF800070000070000070000 +0700000700000700007FF000FFF8007FF0151C7F9B18>52 D<007E0001FF0007FF800F83C01E03 +C01C03C0380180380000700000700000E1F800E7FE00FFFF00FE0780F803C0F001C0F000E0E000 +E0F000E07000E07000E07000E03801C03C03C01E07800FFF0007FE0001F800131C7E9B18>54 +D<3078FCFC783000000000000000003078FCFC78300614779318>58 D<183C7E7E3C1800000000 +00000000183C7E7E3E1E0E1C3C78F060071A789318>I<000300000780001F80003F00007E0001 +FC0003F00007E0001FC0003F00007E0000FC0000FC00007E00003F00001FC00007E00003F00001 +FC00007E00003F00001F8000078000030011187D9918>I<7FFFC0FFFFE0FFFFE0FFFFE0000000 +000000000000000000FFFFE0FFFFE0FFFFE07FFFC0130C7E9318>I<600000F00000FC00007E00 +003F00001FC00007E00003F00001FC00007E00003F00001F80001F80003F00007E0001FC0003F0 +0007E0001FC0003F00007E0000FC0000F0000060000011187D9918>I<0FF0003FFC007FFF0070 +0F00F00380F00380600780000F00003E00007C0001F00001E00003C00003C00003C00003C00003 +C00003800000000000000000000000000000000003800007C00007C00007C000038000111C7D9B +18>I<007C0001FE0007FF000F87801E03C03C1DC0387FC070FFE071E3E071C1E0E1C1E0E380E0 +E380E0E380E0E380E0E380E0E380E0E1C1C071C1C071E3C070FF80387F003C1C001E00E00F83E0 +07FFC001FF80007E00131C7E9B18>I<00700000F80000F80000D80000D80001DC0001DC0001DC +00018C00038E00038E00038E00038E000306000707000707000707000707000FFF800FFF800FFF +800E03800E03801C01C01C01C07F07F0FF8FF87F07F0151C7F9B18>II<00F8E003FEE007FFE00F07E01E03E03C01E03800E07000E07000E0700000E00000E00000 +E00000E00000E00000E00000E00000E000007000007000E07000E03800E03C00E01E01C00F07C0 +07FF8003FE0000F800131C7E9B18>I<7FF800FFFE007FFF001C0F801C03C01C03C01C01E01C00 +E01C00E01C00F01C00701C00701C00701C00701C00701C00701C00701C00701C00F01C00E01C00 +E01C01E01C01C01C03C01C0F807FFF00FFFE007FF800141C7F9B18>III<01F1C003FDC00FFFC01F0FC01C03C03803C03801C07001 +C07001C0700000E00000E00000E00000E00000E00000E00FF0E01FF0E00FF07001C07001C07003 +C03803C03803C01C07C01F0FC00FFFC003FDC001F1C0141C7E9B18>I<7FFF00FFFF807FFF0001 +C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001 +C00001C00001C00001C00001C00001C00001C00001C00001C0007FFF00FFFF807FFF00111C7D9B +18>73 D<01FFC003FFC001FFC0000E00000E00000E00000E00000E00000E00000E00000E00000E +00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00F00E00F00E00F03C +007FFC003FF0000FC000121C7D9B18>I<7F07F0FF87F87F07F01C03C01C07801C07001C0E001C +1E001C3C001C38001C70001CF0001DF0001DF0001FB8001FB8001F1C001E1C001C0E001C0E001C +07001C07001C03801C03801C01C07F03F0FF87F87F03F0151C7F9B18>I<7FE000FFE0007FE000 +0E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E0000 +0E00000E00000E00000E00000E00700E00700E00700E00700E00707FFFF0FFFFF07FFFF0141C7F +9B18>II<7E07F0FF0FF87F07F01D81C01D81C01D81C01DC1C01C +C1C01CC1C01CE1C01CE1C01CE1C01C61C01C71C01C71C01C31C01C39C01C39C01C39C01C19C01C +19C01C1DC01C0DC01C0DC01C0DC07F07C0FF87C07F03C0151C7F9B18>I<0FF8003FFE007FFF00 +780F00700700F00780E00380E00380E00380E00380E00380E00380E00380E00380E00380E00380 +E00380E00380E00380E00380E00380E00380F00780700700780F007FFF003FFE000FF800111C7D +9B18>II<0FF8003FFE007FFF00780F00700700F00780E00380E0 +0380E00380E00380E00380E00380E00380E00380E00380E00380E00380E00380E00380E00380E1 +E380E1E380F0E78070F700787F007FFF003FFE000FFC00001C00001E00000E00000F0000070000 +070011227D9B18>I<7FF800FFFE007FFF001C0F801C03801C03C01C01C01C01C01C01C01C03C0 +1C03801C0F801FFF001FFE001FFE001C0F001C07001C03801C03801C03801C03801C03801C039C +1C039C1C039C7F01F8FF81F87F00F0161C7F9B18>I<03F3801FFF803FFF807C0F80700780E003 +80E00380E00380E000007000007800003F00001FF00007FE0000FF00000F800003C00001C00000 +E00000E06000E0E000E0E001E0F001C0F80780FFFF80FFFE00E7F800131C7E9B18>I<7FFFF8FF +FFF8FFFFF8E07038E07038E07038E0703800700000700000700000700000700000700000700000 +700000700000700000700000700000700000700000700000700000700000700007FF0007FF0007 +FF00151C7F9B18>IIII<7F8FE07F9FE07F8FE00E07000F0700070E00078E00039C0003DC0001F800 +01F80000F00000F00000700000F00000F80001F80001DC00039E00038E00070F000707000E0780 +0E03801E03C07F07F0FF8FF87F07F0151C7F9B18>II91 +D<600000F00000F00000F800007800007C00003C00003C00003E00001E00001F00000F00000F00 +000F800007800007C00003C00003C00003E00001E00001F00000F00000F800007800007800007C +00003C00003E00001E00001E00001F00000F00000F8000078000078000030011247D9F18>II< +7FFF00FFFF80FFFF807FFF0011047D7F18>95 D<061E3E387070E0E0E0F8FC7C7C38070E789E18 +>I<1FE0003FF8007FFC00781E00300E0000070000070000FF0007FF001FFF007F0700780700E0 +0700E00700E00700F00F00781F003FFFF01FFBF007E1F014147D9318>I<7E0000FE00007E0000 +0E00000E00000E00000E00000E00000E3E000EFF800FFFC00FC1E00F80E00F00700E00700E0038 +0E00380E00380E00380E00380E00380F00700F00700F80E00FC1E00FFFC00EFF80063E00151C80 +9B18>I<01FE0007FF001FFF803E0780380300700000700000E00000E00000E00000E00000E000 +00E000007000007001C03801C03E03C01FFF8007FF0001FC0012147D9318>I<001F80003F8000 +1F8000038000038000038000038000038003E3800FFB801FFF803C1F80380F80700780700380E0 +0380E00380E00380E00380E00380E00380700780700780380F803C1F801FFFF00FFBF803E3F015 +1C7E9B18>I<01F00007FC001FFE003E0F00380780700380700380E001C0E001C0FFFFC0FFFFC0 +FFFFC0E000007000007001C03801C03E03C01FFF8007FF0001FC0012147D9318>I<001F80007F +C000FFE000E1E001C0C001C00001C00001C0007FFFC0FFFFC0FFFFC001C00001C00001C00001C0 +0001C00001C00001C00001C00001C00001C00001C00001C00001C00001C0007FFF007FFF007FFF +00131C7F9B18>I<01E1F007FFF80FFFF81E1E301C0E003807003807003807003807003807001C +0E001E1E001FFC001FF80039E0003800001C00001FFE001FFFC03FFFE07801F0700070E00038E0 +0038E00038E000387800F07E03F01FFFC00FFF8001FC00151F7F9318>I<7E0000FE00007E0000 +0E00000E00000E00000E00000E00000E3E000EFF800FFFC00FC1C00F80E00F00E00E00E00E00E0 +0E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E07FC3FCFFE7FE7FC3FC171C80 +9B18>I<03800007C00007C00007C0000380000000000000000000000000007FC000FFC0007FC0 +0001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C0 +0001C000FFFF00FFFF80FFFF00111D7C9C18>I<0038007C007C007C003800000000000000000F +FC1FFC0FFC001C001C001C001C001C001C001C001C001C001C001C001C001C001C001C001C001C +001C001C001C001C001C6038F078FFF07FE03F800E277E9C18>I +I<7FE000FFE0007FE00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E0 +0000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E0007FFF +C0FFFFE07FFFC0131C7E9B18>I<7CE0E000FFFBF8007FFFF8001F1F1C001E1E1C001E1E1C001C +1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C00 +1C1C1C007F1F1F00FFBFBF807F1F1F001914819318>I<7E3E00FEFF807FFFC00FC1C00F80E00F +00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E07FC3FCFF +E7FE7FC3FC1714809318>I<01F0000FFE001FFF003E0F803803807001C07001C0E000E0E000E0 +E000E0E000E0E000E0F001E07001C07803C03C07803E0F801FFF000FFE0001F00013147E9318> +I<7E3E00FEFF807FFFC00FC1E00F80E00F00700E00700E00380E00380E00380E00380E00380E00 +380F00700F00700F80E00FC1E00FFFC00EFF800E3E000E00000E00000E00000E00000E00000E00 +000E00007FC000FFE0007FC000151E809318>I<01E38007FB801FFF803E1F80380F8070078070 +0780E00380E00380E00380E00380E00380E00380700780700780380F803C1F801FFF800FFB8003 +E380000380000380000380000380000380000380000380003FF8003FF8003FF8151E7E9318>I< +7F87E0FF9FF07FBFF803F87803F03003E00003C00003C000038000038000038000038000038000 +0380000380000380000380007FFE00FFFF007FFE0015147F9318>I<07F7003FFF007FFF00780F +00E00700E00700E007007C00007FE0001FFC0003FE00001F00600780E00380E00380F00380F80F +00FFFF00FFFC00E7F00011147D9318>I<0180000380000380000380000380007FFFC0FFFFC0FF +FFC00380000380000380000380000380000380000380000380000380000380400380E00380E003 +80E001C1C001FFC000FF80003E0013197F9818>I<7E07E0FE0FE07E07E00E00E00E00E00E00E0 +0E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E00E01E00F03E007FFFC03FFFE +01FCFC1714809318>I<7F8FF0FF8FF87F8FF01E03C00E03800E03800E03800707000707000707 +00038E00038E00038E00038E0001DC0001DC0001DC0000F80000F80000700015147F9318>II<7F8FF07F9FF07F8FF0070700 +078E00039E0001DC0001F80000F80000700000F00000F80001DC00039E00038E000707000F0780 +7F8FF0FF8FF87F8FF015147F9318>I<7F8FF0FF8FF87F8FF00E01C00E03800E03800703800707 +00070700038700038600038E0001CE0001CE0000CC0000CC0000DC000078000078000078000070 +0000700000700000F00000E00079E0007BC0007F80003F00001E0000151E7F9318>I<3FFFF07F +FFF07FFFF07001E07003C0700780000F00001E00003C0000F80001F00003C0000780000F00701E +00703C0070780070FFFFF0FFFFF0FFFFF014147F9318>I<0007E0001FE0007FE000780000E000 +00E00000E00000E00000E00000E00000E00000E00000E00000E00000E00001E0007FC000FF8000 +FF80007FC00001E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E000 +00E000007800007FE0001FE00007E013247E9F18>I<60F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0600424769F18>I<7C0000FF0000FFC00003C00000 +E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000F000007FC000 +3FE0003FE0007FC000F00000E00000E00000E00000E00000E00000E00000E00000E00000E00000 +E00000E00003C000FFC000FF00007C000013247E9F18>I<060C1F1E3FBEFBF8F1F060C00F067C +9B18>I E /Fo 76 124 df<001F83E000F06E3001C078780380F8780300F03007007000070070 +000700700007007000070070000700700007007000FFFFFF800700700007007000070070000700 +700007007000070070000700700007007000070070000700700007007000070070000700700007 +007000070070000700700007007000070070007FE3FF001D20809F1B>11 +D<003F0000E0C001C0C00381E00701E00701E0070000070000070000070000070000070000FFFF +E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700 +E00700E00700E00700E00700E00700E07FC3FE1720809F19>I<003FE000E0E001C1E00381E007 +00E00700E00700E00700E00700E00700E00700E00700E0FFFFE00700E00700E00700E00700E007 +00E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E00700E007 +00E07FE7FE1720809F19>I<001F81F80000F04F040001C07C06000380F80F000300F00F000700 +F00F00070070000007007000000700700000070070000007007000000700700000FFFFFFFF0007 +007007000700700700070070070007007007000700700700070070070007007007000700700700 +070070070007007007000700700700070070070007007007000700700700070070070007007007 +00070070070007007007007FE3FE3FF02420809F26>I<0080008007E00C981084208260824081 +C087C08FC08FC086E080F08078803F803FE01FF807FC00FE009E008E00870087F083F083F08380 +83808240864084208818B007C000800080008010257DA117>36 D<70F8FCFC7404040408081010 +2040060E7C9F0D>39 D<0020004000800100020006000C000C0018001800300030003000700060 +0060006000E000E000E000E000E000E000E000E000E000E000E000E00060006000600070003000 +30003000180018000C000C000600020001000080004000200B2E7DA112>I<8000400020001000 +08000C00060006000300030001800180018001C000C000C000C000E000E000E000E000E000E000 +E000E000E000E000E000E000C000C000C001C001800180018003000300060006000C0008001000 +2000400080000B2E7DA112>I<70F8FCFC74040404080810102040060E7C840D>44 +DI<70F8F8F87005057C840D>I<03F0000E1C001C0E0018060038070070 +0380700380700380700380F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F003C0F0 +03C0F003C0F003C0F003C07003807003807003807807803807001806001C0E000E1C0003F00012 +1F7E9D17>48 D<018003800F80F380038003800380038003800380038003800380038003800380 +03800380038003800380038003800380038003800380038007C0FFFE0F1E7C9D17>I<03F0000C +1C00100E00200700400780800780F007C0F803C0F803C0F803C02007C00007C000078000078000 +0F00000E00001C0000380000700000600000C0000180000300000600400C00401800401000803F +FF807FFF80FFFF80121E7E9D17>I<03F0000C1C00100E00200F00780F80780780780780380F80 +000F80000F00000F00000E00001C0000380003F000003C00000E00000F000007800007800007C0 +2007C0F807C0F807C0F807C0F00780400780400F00200E001C3C0003F000121F7E9D17>I<0006 +00000600000E00000E00001E00002E00002E00004E00008E00008E00010E00020E00020E00040E +00080E00080E00100E00200E00200E00400E00C00E00FFFFF0000E00000E00000E00000E00000E +00000E00000E0000FFE0141E7F9D17>I<1803001FFE001FFC001FF8001FE00010000010000010 +000010000010000010000011F000161C00180E001007001007800003800003800003C00003C000 +03C07003C0F003C0F003C0E00380400380400700200600100E000C380003E000121F7E9D17>I< +007C000182000701000E03800C07801C0780380300380000780000700000700000F1F000F21C00 +F40600F80700F80380F80380F003C0F003C0F003C0F003C0F003C07003C07003C0700380380380 +3807001807000C0E00061C0001F000121F7E9D17>I<4000007FFFC07FFF807FFF804001008002 +0080020080040000080000080000100000200000200000400000400000C00000C00001C0000180 +00038000038000038000038000078000078000078000078000078000078000078000030000121F +7D9D17>I<03F0000C0C001006003003002001806001806001806001807001807803003E03003F +06001FC8000FF00003F80007FC000C7E00103F00300F806003804001C0C001C0C000C0C000C0C0 +00C0C000806001802001001002000C0C0003F000121F7E9D17>I<03F0000E18001C0C00380600 +380700700700700380F00380F00380F003C0F003C0F003C0F003C0F003C07007C07007C03807C0 +180BC00E13C003E3C0000380000380000380000700300700780600780E00700C00201800107000 +0FC000121F7E9D17>I<70F8F8F8700000000000000000000070F8F8F87005147C930D>I<70F8F8 +F8700000000000000000000070F0F8F878080808101010202040051D7C930D>I<000100000003 +800000038000000380000007C0000007C0000007C0000009E0000009E0000009E0000010F00000 +10F0000010F00000207800002078000020780000403C0000403C0000403C0000801E0000801E00 +00FFFE0001000F0001000F0001000F00020007800200078002000780040003C00E0003C01F0007 +E0FFC03FFE1F207F9F22>65 DI<000FC040007030C001C009C0 +038005C0070003C00E0001C01E0000C01C0000C03C0000C07C0000407C00004078000040F80000 +00F8000000F8000000F8000000F8000000F8000000F8000000F8000000F8000000780000007C00 +00407C0000403C0000401C0000401E0000800E000080070001000380020001C004000070380000 +0FC0001A217D9F21>IIII<000FE0200078186000E004E0038002E0070001E00F0000E01E00 +00601E0000603C0000603C0000207C00002078000020F8000000F8000000F8000000F8000000F8 +000000F8000000F8000000F8007FFCF80003E0780001E07C0001E03C0001E03C0001E01E0001E0 +1E0001E00F0001E0070001E0038002E000E0046000781820000FE0001E217D9F24>II +I<0FFFC0007C00003C00003C00003C00003C00003C00003C00003C00003C00003C00003C00003C +00003C00003C00003C00003C00003C00003C00003C00003C00003C00003C00203C00F83C00F83C +00F83C00F0380040780040700030E0000F800012207E9E17>I +IIII<001F800000F0F00001C0380007801E000F000F000E0007001E0007803C0003C03C0003 +C07C0003E0780001E0780001E0F80001F0F80001F0F80001F0F80001F0F80001F0F80001F0F800 +01F0F80001F0F80001F0780001E07C0003E07C0003E03C0003C03C0003C01E0007800E0007000F +000F0007801E0001C0380000F0F000001F80001C217D9F23>I +I82 D<07E0800C1980100780300380600180600180E0 +0180E00080E00080E00080F00000F000007800007F00003FF0001FFC000FFE0003FF00001F8000 +07800003C00003C00001C08001C08001C08001C08001C0C00180C00380E00300F00600CE0C0081 +F80012217D9F19>I<7FFFFFE0780F01E0600F0060400F0020400F0020C00F0030800F0010800F +0010800F0010800F0010000F0000000F0000000F0000000F0000000F0000000F0000000F000000 +0F0000000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F0000 +000F0000000F0000001F800007FFFE001C1F7E9E21>IIII89 +D91 D93 D<081020204040808080B8 +FCFC7C38060E7D9F0D>96 D<1FE000303000781800781C00300E00000E00000E00000E0000FE00 +078E001E0E00380E00780E00F00E10F00E10F00E10F01E10781E103867200F83C014147E9317> +I<0E0000FE00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E00000E3E +000EC3800F01C00F00E00E00E00E00700E00700E00780E00780E00780E00780E00780E00780E00 +700E00700E00E00F00E00D01C00CC300083E0015207F9F19>I<03F80E0C1C1E381E380C700070 +00F000F000F000F000F000F00070007000380138011C020E0C03F010147E9314>I<000380003F +8000038000038000038000038000038000038000038000038000038000038003E380061B801C07 +80380380380380700380700380F00380F00380F00380F00380F00380F003807003807003803803 +803807801C07800E1B8003E3F815207E9F19>I<03F0000E1C001C0E0038070038070070070070 +0380F00380F00380FFFF80F00000F00000F000007000007000003800801800800C010007060001 +F80011147F9314>I<007C00C6018F038F07060700070007000700070007000700FFF007000700 +07000700070007000700070007000700070007000700070007000700070007007FF01020809F0E +>I<0000E003E3300E3C301C1C30380E00780F00780F00780F00780F00780F00380E001C1C001E +380033E0002000002000003000003000003FFE001FFF800FFFC03001E0600070C00030C00030C0 +0030C000306000603000C01C038003FC00141F7F9417>I<0E0000FE00000E00000E00000E0000 +0E00000E00000E00000E00000E00000E00000E00000E3E000E43000E81800F01C00F01C00E01C0 +0E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C0 +FFE7FC16207F9F19>I<1C003E003E003E001C000000000000000000000000000E007E000E000E +000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E00FFC00A1F809E0C> +I<00E001F001F001F000E0000000000000000000000000007007F000F000700070007000700070 +00700070007000700070007000700070007000700070007000700070007000706070F060F0C061 +803F000C28829E0E>I<0E0000FE00000E00000E00000E00000E00000E00000E00000E00000E00 +000E00000E00000E0FF00E03C00E03000E02000E04000E08000E10000E30000E70000EF8000F38 +000E1C000E1E000E0E000E07000E07800E03800E03C00E03E0FFCFF815207F9F18>I<0E00FE00 +0E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E000E +000E000E000E000E000E000E000E000E000E00FFE00B20809F0C>I<0E1F01F000FE618618000E +81C81C000F00F00E000F00F00E000E00E00E000E00E00E000E00E00E000E00E00E000E00E00E00 +0E00E00E000E00E00E000E00E00E000E00E00E000E00E00E000E00E00E000E00E00E000E00E00E +000E00E00E00FFE7FE7FE023147F9326>I<0E3E00FE43000E81800F01C00F01C00E01C00E01C0 +0E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C0FFE7FC +16147F9319>I<01F800070E001C03803801C03801C07000E07000E0F000F0F000F0F000F0F000 +F0F000F0F000F07000E07000E03801C03801C01C0380070E0001F80014147F9317>I<0E3E00FE +C3800F01C00F00E00E00E00E00F00E00700E00780E00780E00780E00780E00780E00780E00700E +00F00E00E00F01E00F01C00EC3000E3E000E00000E00000E00000E00000E00000E00000E00000E +0000FFE000151D7F9319>I<03E0800619801C05803C0780380380780380700380F00380F00380 +F00380F00380F00380F003807003807803803803803807801C0B800E138003E380000380000380 +000380000380000380000380000380000380003FF8151D7E9318>I<0E78FE8C0F1E0F1E0F0C0E +000E000E000E000E000E000E000E000E000E000E000E000E000E00FFE00F147F9312>I<1F9030 +704030C010C010C010E00078007F803FE00FF00070803880188018C018C018E030D0608F800D14 +7E9312>I<020002000200060006000E000E003E00FFF80E000E000E000E000E000E000E000E00 +0E000E000E000E080E080E080E080E080610031001E00D1C7F9B12>I<0E01C0FE1FC00E01C00E +01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E01C00E +03C00603C0030DC001F1FC16147F9319>III<7FC3FC0F01E00701C007018003810001C20000E40000EC +00007800003800003C00007C00004E000087000107000303800201C00601E01E01E0FF07FE1714 +809318>II<3FFF380E200E201C40384078407000E001E0 +01C00380078007010E011E011C0338027006700EFFFE10147F9314>II +E /Fp 14 122 df<0000001FFC0000C000000003FFFFC001C00000001FFFFFF003C00000007FFF +FFFC07C0000001FFFC00FE0FC0000007FFC0001F9FC000000FFE000007FFC000003FF8000003FF +C000007FF0000000FFC00000FFE00000007FC00001FFC00000007FC00001FF800000003FC00003 +FF000000001FC00007FE000000001FC0000FFE000000000FC0000FFC000000000FC0001FFC0000 +000007C0001FFC0000000007C0003FF80000000007C0003FF80000000003C0003FF80000000003 +C0007FF80000000003C0007FF80000000003C0007FF0000000000000007FF000000000000000FF +F000000000000000FFF000000000000000FFF000000000000000FFF000000000000000FFF00000 +0000000000FFF000000000000000FFF000000000000000FFF000000000000000FFF00000000000 +0000FFF000000000000000FFF000001FFFFFFF807FF000001FFFFFFF807FF000001FFFFFFF807F +F800001FFFFFFF807FF800000001FFC0003FF800000001FFC0003FF800000001FFC0003FF80000 +0001FFC0001FFC00000001FFC0001FFC00000001FFC0000FFE00000001FFC0000FFE00000001FF +C00007FF00000001FFC00003FF00000001FFC00001FF80000001FFC00001FFC0000001FFC00000 +FFE0000001FFC000007FF0000003FFC000003FFC000003FFC000000FFF000007FFC0000007FFC0 +001FBFC0000001FFFC00FF1FC00000007FFFFFFE0FC00000001FFFFFF803C000000003FFFFE000 +C0000000001FFE00000000413D7BBB4C>71 D76 D78 D82 D85 D<003FFE00000001FFFFE0000007FFFFF800000FE007FC00000FF001FE00001F +F800FF00001FF8007F80001FF8007FC0001FF8003FC0000FF0003FE00007E0003FE00003C0003F +E0000000003FE0000000003FE0000000003FE0000000003FE0000000FFFFE000001FFFFFE00000 +7FF83FE00003FF803FE00007FC003FE0000FF0003FE0001FE0003FE0003FE0003FE0007FC0003F +E0007FC0003FE000FF80003FE000FF80003FE000FF80003FE000FF80003FE000FF80007FE0007F +C0007FE0007FC000DFE0003FE0039FF0001FF80F0FFFE007FFFE0FFFE001FFF807FFE0003FE000 +FFE02B267DA52F>97 D<00FE00000000FFFE00000000FFFE00000000FFFE00000000FFFE000000 +0007FE0000000003FE0000000003FE0000000003FE0000000003FE0000000003FE0000000003FE +0000000003FE0000000003FE0000000003FE0000000003FE0000000003FE0000000003FE000000 +0003FE0000000003FE0000000003FE0000000003FE0000000003FE01FF000003FE1FFFF00003FE +7FFFFC0003FEFC03FE0003FFF000FF0003FFC0003F8003FF00001FC003FE00001FE003FE00000F +F003FE00000FF803FE00000FF803FE000007FC03FE000007FC03FE000007FC03FE000007FE03FE +000007FE03FE000007FE03FE000007FE03FE000007FE03FE000007FE03FE000007FE03FE000007 +FE03FE000007FE03FE000007FC03FE000007FC03FE000007FC03FE00000FFC03FE00000FF803FE +00000FF003FE00001FF003FF00001FE003FF80003FC003FFC0007F8003F9E000FF0003F0FC07FE +0003F07FFFF80003E01FFFE00003C003FE00002F3C7DBB36>I<000000003F800000003FFF8000 +00003FFF800000003FFF800000003FFF8000000001FF8000000000FF8000000000FF8000000000 +FF8000000000FF8000000000FF8000000000FF8000000000FF8000000000FF8000000000FF8000 +000000FF8000000000FF8000000000FF8000000000FF8000000000FF8000000000FF8000000000 +FF800000FF80FF80000FFFF0FF80003FFFFCFF8000FFC03FFF8001FE000FFF8003FC0003FF8007 +F80001FF800FF00000FF801FF00000FF803FE00000FF803FE00000FF807FE00000FF807FC00000 +FF807FC00000FF807FC00000FF80FFC00000FF80FFC00000FF80FFC00000FF80FFC00000FF80FF +C00000FF80FFC00000FF80FFC00000FF80FFC00000FF80FFC00000FF807FC00000FF807FC00000 +FF807FC00000FF803FE00000FF803FE00000FF801FE00000FF800FF00001FF8007F00003FF8003 +F80007FF8001FE001FFFC000FF807EFFFE007FFFF8FFFE000FFFE0FFFE0001FF00FFFE2F3C7DBB +36>100 D<0001FF8000000FFFF000003FFFFC0000FF81FE0003FE007F8007F8003F800FF8001F +C00FF0000FE01FE0000FE03FE0000FF03FE00007F07FC00007F07FC00007F87FC00007F8FFC000 +07F8FFC00007F8FFFFFFFFF8FFFFFFFFF8FFFFFFFFF8FFC0000000FFC0000000FFC0000000FFC0 +0000007FC00000007FC00000007FC00000003FE00000003FE00000781FE00000781FF00000780F +F00000F007F80001F003FC0003E001FE000FC000FFC07F80003FFFFE00000FFFF8000000FFC000 +25267DA52C>I<01E00007F8000FFC000FFC001FFE001FFE001FFE001FFE000FFC000FFC0007F8 +0001E00000000000000000000000000000000000000000000000000000000000000000000000FE +00FFFE00FFFE00FFFE00FFFE0007FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE +0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE +0003FE0003FE0003FE0003FE0003FE0003FE0003FE00FFFFF0FFFFF0FFFFF0FFFFF0143D7DBC1A +>105 D<00FE00FFFE00FFFE00FFFE00FFFE0007FE0003FE0003FE0003FE0003FE0003FE0003FE +0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE +0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE +0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE0003FE +0003FE0003FE0003FE0003FE0003FE00FFFFF8FFFFF8FFFFF8FFFFF8153C7DBB1A>108 +D<01FC00FF8000FFFC03FFF000FFFC0FFFF800FFFC1E03FC00FFFC3801FE0007FC6001FF0003FC +C000FF0003FDC000FF8003FD8000FF8003FF0000FF8003FF0000FF8003FF0000FF8003FE0000FF +8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE +0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF +8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE0000FF8003FE +0000FF8003FE0000FF80FFFFF83FFFFEFFFFF83FFFFEFFFFF83FFFFEFFFFF83FFFFE2F267CA536 +>110 D<01FC03F000FFFC0FFC00FFFC1FFF00FFFC3C3F80FFFC707F8007FCE0FFC003FCC0FFC0 +03FD80FFC003FD80FFC003FF807F8003FF003F0003FF001E0003FF00000003FE00000003FE0000 +0003FE00000003FE00000003FE00000003FE00000003FE00000003FE00000003FE00000003FE00 +000003FE00000003FE00000003FE00000003FE00000003FE00000003FE00000003FE00000003FE +00000003FE00000003FE00000003FE000000FFFFFC0000FFFFFC0000FFFFFC0000FFFFFC000022 +267DA528>114 D121 +D E end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 300dpi +TeXDict begin + +%%EndSetup +%%Page: 1 1 +0 bop 0 1152 a Fp(GNU)33 b(Readline)h(Library)p 0 1201 1950 +17 v 1011 1250 a Fo(Edition)17 b(2.0,)c(for)i Fn(Readline)f(Library)g +Fo(V)l(ersion)i(2.0.)1759 1304 y(July)g(1994)0 2443 y Fm(Brian)23 +b(F)-6 b(o)n(x,)23 b(F)-6 b(ree)23 b(Soft)n(w)n(are)f(F)-6 +b(oundation)0 2509 y(Chet)22 b(Ramey)-6 b(,)23 b(Case)e(W)-6 +b(estern)23 b(Reserv)n(e)f(Univ)n(ersit)n(y)p 0 2545 1950 9 +v eop +%%Page: 2 2 +1 bop 0 295 a Fo(This)15 b(do)q(cumen)o(t)f(describ)q(es)i(the)e(GNU)g +(Readline)j(Library)l(,)d(a)g(utilit)o(y)h(whic)o(h)g(aids)g(in)g(the)f +(consistency)h(of)f(user)0 358 y(in)o(terface)h(across)g(discrete)h(programs) +e(that)g(need)j(to)d(pro)o(vide)i(a)f(command)g(line)i(in)o(terface.)0 +495 y(Published)g(b)o(y)f(the)f(F)l(ree)g(Soft)o(w)o(are)f(F)l(oundation)0 +557 y(675)g(Massac)o(h)o(usetts)g(Av)o(en)o(ue,)0 619 y(Cam)o(bridge,)h(MA)g +(02139)f(USA)0 756 y(P)o(ermission)f(is)g(gran)o(ted)f(to)f(mak)o(e)h(and)h +(distribute)h(v)o(erbatim)e(copies)h(of)f(this)h(man)o(ual)g(pro)o(vided)g +(the)f(cop)o(yrigh)o(t)0 818 y(notice)k(and)f(this)h(p)q(ermission)h(notice)e +(are)g(preserv)o(ed)h(on)f(all)h(copies.)0 955 y(P)o(ermission)f(is)f(gran)o +(ted)f(to)h(cop)o(y)g(and)g(distribute)h(mo)q(di\014ed)h(v)o(ersions)e(of)f +(this)i(man)o(ual)f(under)h(the)f(conditions)0 1018 y(for)e(v)o(erbatim)g +(cop)o(ying,)h(pro)o(vided)h(that)d(the)i(en)o(tire)g(resulting)h(deriv)o(ed) +f(w)o(ork)f(is)h(distributed)h(under)f(the)g(terms)0 1080 y(of)i(a)g(p)q +(ermission)h(notice)g(iden)o(tical)h(to)e(this)g(one.)0 1217 +y(P)o(ermission)20 b(is)g(gran)o(ted)f(to)g(cop)o(y)h(and)f(distribute)i +(translations)f(of)f(this)h(man)o(ual)f(in)o(to)h(another)f(language,)0 +1279 y(under)c(the)f(ab)q(o)o(v)o(e)g(conditions)h(for)e(mo)q(di\014ed)j(v)o +(ersions,)e(except)g(that)g(this)g(p)q(ermission)i(notice)e(ma)o(y)g(b)q(e)h +(stated)0 1341 y(in)h(a)f(translation)g(appro)o(v)o(ed)g(b)o(y)g(the)g(F)l +(oundation.)0 2636 y(Cop)o(yrigh)o(t)226 2635 y(c)214 2636 +y Fl(\015)g Fo(1989,)f(1991)g(F)l(ree)h(Soft)o(w)o(are)f(F)l(oundation,)h +(Inc.)p eop +%%Page: 1 3 +2 bop 0 -83 a Fo(Chapter)15 b(1:)k(Command)c(Line)i(Editing)1227 +b(1)0 158 y Fk(1)41 b(Command)16 b(Line)f(Editing)62 383 y +Fo(This)h(c)o(hapter)f(describ)q(es)i(the)e(basic)h(features)f(of)g(the)g +(GNU)g(command)g(line)i(editing)f(in)o(terface.)0 676 y Fm(1.1)33 +b(In)n(tro)r(duction)17 b(to)e(Line)h(Editing)62 820 y Fo(The)g(follo)o(wing) +g(paragraphs)e(describ)q(e)j(the)e(notation)g(used)h(to)e(represen)o(t)i(k)o +(eystrok)o(es.)62 965 y(The)f(text)e Fn(C-K)h Fo(is)g(read)g(as)g(`Con)o +(trol-K')f(and)h(describ)q(es)i(the)e(c)o(haracter)f(pro)q(duced)i(when)g +(the)f(Con)o(trol)f(k)o(ey)0 1027 y(is)j(depressed)g(and)f(the)h +Fn(K)f Fo(k)o(ey)g(is)g(struc)o(k.)62 1172 y(The)i(text)f Fn(M-K)g +Fo(is)i(read)e(as)g(`Meta-K')g(and)h(describ)q(es)h(the)f(c)o(haracter)f(pro) +q(duced)h(when)h(the)e(meta)g(k)o(ey)h(\(if)0 1234 y(y)o(ou)g(ha)o(v)o(e)f +(one\))h(is)g(depressed,)h(and)f(the)g Fn(K)g Fo(k)o(ey)g(is)g(struc)o(k.)25 +b(If)17 b(y)o(ou)f(do)h(not)g(ha)o(v)o(e)f(a)h(meta)f(k)o(ey)l(,)h(the)g +(iden)o(tical)0 1296 y(k)o(eystrok)o(e)i(can)g(b)q(e)i(generated)e(b)o(y)h(t) +o(yping)f Fn(ESC)h Fj(\014rst)p Fo(,)g(and)f(then)h(t)o(yping)g +Fn(K)p Fo(.)33 b(Either)20 b(pro)q(cess)g(is)g(kno)o(wn)f(as)0 +1358 y Fj(metafying)g Fo(the)c Fn(K)g Fo(k)o(ey)l(.)62 1503 +y(The)h(text)e Fn(M-C-K)g Fo(is)i(read)f(as)f(`Meta-Con)o(trol-k')g(and)h +(describ)q(es)h(the)g(c)o(haracter)e(pro)q(duced)i(b)o(y)f +Fj(metafying)0 1565 y Fn(C-K)p Fo(.)62 1710 y(In)i(addition,)h(sev)o(eral)e +(k)o(eys)g(ha)o(v)o(e)g(their)h(o)o(wn)f(names.)23 b(Sp)q(eci\014cally)m(,)c +Fn(DEL)p Fo(,)d Fn(ESC)p Fo(,)f Fn(LFD)p Fo(,)h Fn(SPC)p Fo(,)g +Fn(RET)p Fo(,)g(and)g Fn(TAB)0 1772 y Fo(all)e(stand)f(for)f(themselv)o(es)i +(when)f(seen)h(in)g(this)f(text,)g(or)g(in)g(an)g(init)i(\014le)f(\(see)f +(Section)h(1.3)e([Readline)j(Init)f(File],)0 1834 y(page)h(4,)g(for)f(more)h +(info\).)0 2127 y Fm(1.2)33 b(Readline)16 b(In)n(teraction)62 +2271 y Fo(Often)g(during)h(an)f(in)o(teractiv)o(e)g(session)h(y)o(ou)e(t)o +(yp)q(e)h(in)h(a)f(long)g(line)h(of)f(text,)f(only)h(to)g(notice)g(that)f +(the)h(\014rst)0 2334 y(w)o(ord)d(on)i(the)f(line)i(is)e(missp)q(elled.)23 +b(The)14 b(Readline)i(library)f(giv)o(es)g(y)o(ou)e(a)h(set)g(of)g(commands)g +(for)f(manipulating)0 2396 y(the)18 b(text)g(as)g(y)o(ou)g(t)o(yp)q(e)g(it)h +(in,)g(allo)o(wing)g(y)o(ou)f(to)g(just)g(\014x)g(y)o(our)g(t)o(yp)q(o,)g +(and)h(not)f(forcing)g(y)o(ou)g(to)g(ret)o(yp)q(e)g(the)0 2458 +y(ma)s(jorit)o(y)d(of)h(the)g(line.)25 b(Using)17 b(these)g(editing)h +(commands,)e(y)o(ou)g(mo)o(v)o(e)f(the)i(cursor)f(to)g(the)g(place)h(that)f +(needs)0 2521 y(correction,)g(and)h(delete)g(or)f(insert)g(the)h(text)e(of)h +(the)g(corrections.)23 b(Then,)17 b(when)g(y)o(ou)f(are)g(satis\014ed)g(with) +h(the)0 2583 y(line,)h(y)o(ou)e(simply)i(press)f Fn(RETURN)p +Fo(.)23 b(Y)l(ou)17 b(do)f(not)g(ha)o(v)o(e)g(to)g(b)q(e)i(at)e(the)g(end)h +(of)f(the)h(line)h(to)e(press)h Fn(RETURN)p Fo(;)f(the)0 2645 +y(en)o(tire)g(line)h(is)e(accepted)h(regardless)f(of)g(the)g(lo)q(cation)h +(of)f(the)h(cursor)e(within)j(the)e(line.)p eop +%%Page: 2 4 +3 bop 0 -83 a Fo(2)1472 b(GNU)15 b(Readline)i(Library)0 158 +y Fi(1.2.1)30 b(Readline)15 b(Bare)g(Essen)n(tials)62 295 y +Fo(In)f(order)f(to)f(en)o(ter)h(c)o(haracters)g(in)o(to)g(the)g(line,)i +(simply)f(t)o(yp)q(e)f(them.)19 b(The)14 b(t)o(yp)q(ed)f(c)o(haracter)f(app)q +(ears)i(where)0 358 y(the)h(cursor)h(w)o(as,)e(and)h(then)h(the)g(cursor)f +(mo)o(v)o(es)f(one)i(space)g(to)e(the)i(righ)o(t.)k(If)c(y)o(ou)f(mist)o(yp)q +(e)h(a)f(c)o(haracter,)f(y)o(ou)0 420 y(can)h(use)h(y)o(our)f(erase)g(c)o +(haracter)f(to)h(bac)o(k)g(up)g(and)h(delete)g(the)f(mist)o(yp)q(ed)h(c)o +(haracter.)62 557 y(Sometimes)f(y)o(ou)e(ma)o(y)h(miss)g(t)o(yping)g(a)g(c)o +(haracter)g(that)f(y)o(ou)h(w)o(an)o(ted)f(to)g(t)o(yp)q(e,)h(and)h(not)e +(notice)i(y)o(our)f(error)0 619 y(un)o(til)k(y)o(ou)e(ha)o(v)o(e)g(t)o(yp)q +(ed)h(sev)o(eral)g(other)f(c)o(haracters.)23 b(In)18 b(that)d(case,)i(y)o(ou) +f(can)h(t)o(yp)q(e)g Fn(C-B)f Fo(to)g(mo)o(v)o(e)g(the)g(cursor)0 +681 y(to)f(the)h(left,)g(and)g(then)g(correct)f(y)o(our)h(mistak)o(e.)21 +b(Afterw)o(ards,)14 b(y)o(ou)i(can)g(mo)o(v)o(e)f(the)h(cursor)f(to)g(the)h +(righ)o(t)g(with)0 744 y Fn(C-F)p Fo(.)62 881 y(When)i(y)o(ou)f(add)g(text)g +(in)h(the)f(middle)i(of)e(a)g(line,)i(y)o(ou)e(will)i(notice)e(that)g(c)o +(haracters)f(to)h(the)g(righ)o(t)g(of)g(the)0 943 y(cursor)h(are)h(`pushed)g +(o)o(v)o(er')e(to)h(mak)o(e)g(ro)q(om)g(for)g(the)h(text)f(that)g(y)o(ou)g +(ha)o(v)o(e)h(inserted.)31 b(Lik)o(ewise,)20 b(when)f(y)o(ou)0 +1005 y(delete)f(text)f(b)q(ehind)i(the)f(cursor,)f(c)o(haracters)f(to)h(the)g +(righ)o(t)g(of)g(the)h(cursor)f(are)g(`pulled)i(bac)o(k')d(to)h(\014ll)i(in)f +(the)0 1067 y(blank)g(space)f(created)g(b)o(y)g(the)h(remo)o(v)m(al)f(of)f +(the)i(text.)25 b(A)17 b(list)h(of)e(the)h(basic)h(bare)f(essen)o(tials)h +(for)e(editing)j(the)0 1130 y(text)c(of)f(an)i(input)g(line)h(follo)o(ws.)0 +1279 y Fn(C-B)168 b Fo(Mo)o(v)o(e)14 b(bac)o(k)h(one)h(c)o(haracter.)0 +1366 y Fn(C-F)168 b Fo(Mo)o(v)o(e)14 b(forw)o(ard)g(one)h(c)o(haracter.)0 +1454 y Fn(DEL)168 b Fo(Delete)16 b(the)f(c)o(haracter)g(to)f(the)h(left)h(of) +f(the)g(cursor.)0 1541 y Fn(C-D)168 b Fo(Delete)16 b(the)f(c)o(haracter)g +(underneath)h(the)f(cursor.)0 1615 y(Prin)o(ting)h(c)o(haracters)240 +1678 y(Insert)f(the)h(c)o(haracter)e(in)o(to)h(the)h(line)h(at)d(the)h +(cursor.)0 1765 y Fn(C-_)168 b Fo(Undo)15 b(the)h(last)f(thing)h(that)e(y)o +(ou)h(did.)21 b(Y)l(ou)15 b(can)h(undo)f(all)h(the)g(w)o(a)o(y)e(bac)o(k)h +(to)f(an)i(empt)o(y)e(line.)0 1973 y Fi(1.2.2)30 b(Readline)15 +b(Mo)n(v)n(emen)n(t)h(Commands)62 2110 y Fo(The)c(ab)q(o)o(v)o(e)g(table)g +(describ)q(es)i(the)e(most)f(basic)h(p)q(ossible)i(k)o(eystrok)o(es)d(that)g +(y)o(ou)g(need)i(in)g(order)f(to)f(do)h(editing)0 2172 y(of)g(the)h(input)h +(line.)21 b(F)l(or)12 b(y)o(our)g(con)o(v)o(enience,)i(man)o(y)f(other)f +(commands)h(ha)o(v)o(e)f(b)q(een)i(added)f(in)h(addition)g(to)e +Fn(C-B)p Fo(,)0 2234 y Fn(C-F)p Fo(,)i Fn(C-D)p Fo(,)h(and)g +Fn(DEL)p Fo(.)20 b(Here)15 b(are)g(some)g(commands)g(for)f(mo)o(ving)h(more)g +(rapidly)i(ab)q(out)e(the)g(line.)0 2384 y Fn(C-A)168 b Fo(Mo)o(v)o(e)14 +b(to)h(the)g(start)f(of)h(the)g(line.)0 2471 y Fn(C-E)168 b +Fo(Mo)o(v)o(e)14 b(to)h(the)g(end)h(of)f(the)g(line.)0 2558 +y Fn(M-F)168 b Fo(Mo)o(v)o(e)14 b(forw)o(ard)g(a)h(w)o(ord.)0 +2645 y Fn(M-B)168 b Fo(Mo)o(v)o(e)14 b(bac)o(kw)o(ard)h(a)g(w)o(ord.)p +eop +%%Page: 3 5 +4 bop 0 -83 a Fo(Chapter)15 b(1:)k(Command)c(Line)i(Editing)1227 +b(3)0 158 y Fn(C-L)168 b Fo(Clear)15 b(the)h(screen,)f(reprin)o(ting)h(the)f +(curren)o(t)g(line)i(at)e(the)g(top.)62 325 y(Notice)22 b(ho)o(w)e +Fn(C-F)h Fo(mo)o(v)o(es)f(forw)o(ard)g(a)g(c)o(haracter,)i(while)g +Fn(M-F)f Fo(mo)o(v)o(es)f(forw)o(ard)g(a)h(w)o(ord.)36 b(It)21 +b(is)h(a)f(lo)q(ose)0 387 y(con)o(v)o(en)o(tion)15 b(that)g(con)o(trol)g(k)o +(eystrok)o(es)f(op)q(erate)h(on)g(c)o(haracters)f(while)j(meta)e(k)o(eystrok) +o(es)f(op)q(erate)h(on)g(w)o(ords.)0 671 y Fi(1.2.3)30 b(Readline)15 +b(Killing)g(Commands)62 816 y Fj(Killing)25 b Fo(text)18 b(means)g(to)f +(delete)i(the)g(text)e(from)h(the)g(line,)i(but)e(to)g(sa)o(v)o(e)f(it)i(a)o +(w)o(a)o(y)d(for)i(later)g(use,)h(usually)0 878 y(b)o(y)c Fj(y)o(anking)k +Fo(\(re-inserting\))c(it)g(bac)o(k)g(in)o(to)g(the)g(line.)21 +b(If)16 b(the)f(description)h(for)e(a)h(command)f(sa)o(ys)h(that)f(it)h +(`kills')0 941 y(text,)f(then)i(y)o(ou)f(can)g(b)q(e)h(sure)f(that)g(y)o(ou)g +(can)g(get)g(the)g(text)g(bac)o(k)g(in)h(a)f(di\013eren)o(t)g(\(or)f(the)i +(same\))e(place)i(later.)62 1086 y(When)g(y)o(ou)f(use)g(a)g(kill)i(command,) +e(the)h(text)e(is)i(sa)o(v)o(ed)f(in)h(a)f Fj(kill-ring)p Fo(.)22 +b(An)o(y)16 b(n)o(um)o(b)q(er)f(of)g(consecutiv)o(e)h(kills)0 +1148 y(sa)o(v)o(e)g(all)i(of)e(the)h(killed)i(text)d(together,)g(so)g(that)g +(when)h(y)o(ou)f(y)o(ank)h(it)g(bac)o(k,)f(y)o(ou)h(get)f(it)h(all.)25 +b(The)17 b(kill)h(ring)f(is)0 1211 y(not)e(line)i(sp)q(eci\014c;)g(the)f +(text)f(that)g(y)o(ou)g(killed)j(on)d(a)h(previously)g(t)o(yp)q(ed)g(line)h +(is)f(a)o(v)m(ailable)i(to)d(b)q(e)h(y)o(ank)o(ed)f(bac)o(k)0 +1273 y(later,)g(when)h(y)o(ou)e(are)h(t)o(yping)h(another)e(line.)62 +1418 y(Here)i(is)f(the)h(list)g(of)e(commands)h(for)g(killing)j(text.)0 +1585 y Fn(C-K)168 b Fo(Kill)17 b(the)f(text)e(from)h(the)g(curren)o(t)g +(cursor)g(p)q(osition)h(to)f(the)g(end)h(of)f(the)g(line.)0 +1689 y Fn(M-D)168 b Fo(Kill)17 b(from)d(the)h(cursor)g(to)f(the)h(end)g(of)g +(the)g(curren)o(t)f(w)o(ord,)g(or)g(if)i(b)q(et)o(w)o(een)f(w)o(ords,)f(to)g +(the)h(end)g(of)240 1751 y(the)g(next)h(w)o(ord.)0 1855 y Fn(M-DEL)120 +b Fo(Kill)16 b(from)d(the)i(cursor)e(the)h(start)f(of)h(the)g(previous)h(w)o +(ord,)e(or)g(if)i(b)q(et)o(w)o(een)f(w)o(ords,)f(to)h(the)g(start)e(of)240 +1917 y(the)j(previous)h(w)o(ord.)0 2021 y Fn(C-W)168 b Fo(Kill)18 +b(from)e(the)g(cursor)g(to)f(the)h(previous)h(whitespace.)24 +b(This)17 b(is)f(di\013eren)o(t)h(than)f Fn(M-DEL)f Fo(b)q(ecause)240 +2084 y(the)g(w)o(ord)g(b)q(oundaries)h(di\013er.)62 2250 y(And,)e(here)g(is)h +(ho)o(w)e(to)g Fj(y)o(ank)j Fo(the)e(text)f(bac)o(k)g(in)o(to)h(the)f(line.) +22 b(Y)l(anking)14 b(means)g(to)f(cop)o(y)g(the)h(most-recen)o(tly-)0 +2312 y(killed)j(text)e(from)g(the)g(kill)i(bu\013er.)0 2479 +y Fn(C-Y)168 b Fo(Y)l(ank)15 b(the)h(most)e(recen)o(tly)i(killed)h(text)e +(bac)o(k)g(in)o(to)g(the)h(bu\013er)f(at)f(the)i(cursor.)0 +2583 y Fn(M-Y)168 b Fo(Rotate)13 b(the)h(kill-ring,)i(and)e(y)o(ank)g(the)g +(new)g(top.)19 b(Y)l(ou)14 b(can)g(only)g(do)g(this)g(if)g(the)g(prior)g +(command)240 2645 y(is)i Fn(C-Y)e Fo(or)h Fn(M-Y)p Fo(.)p eop +%%Page: 4 6 +5 bop 0 -83 a Fo(4)1472 b(GNU)15 b(Readline)i(Library)0 158 +y Fi(1.2.4)30 b(Readline)15 b(Argumen)n(ts)62 305 y Fo(Y)l(ou)k(can)g(pass)f +(n)o(umeric)i(argumen)o(ts)d(to)h(Readline)j(commands.)30 b(Sometimes)19 +b(the)f(argumen)o(t)g(acts)g(as)g(a)0 367 y(rep)q(eat)f(coun)o(t,)f(other)g +(times)g(it)h(is)g(the)g Fj(sign)f Fo(of)g(the)h(argumen)o(t)f(that)f(is)i +(signi\014can)o(t.)25 b(If)16 b(y)o(ou)h(pass)f(a)g(negativ)o(e)0 +430 y(argumen)o(t)g(to)g(a)h(command)g(whic)o(h)h(normally)f(acts)g(in)h(a)e +(forw)o(ard)g(direction,)i(that)f(command)f(will)j(act)d(in)i(a)0 +492 y(bac)o(kw)o(ard)13 b(direction.)21 b(F)l(or)13 b(example,)h(to)f(kill)i +(text)e(bac)o(k)h(to)f(the)h(start)e(of)h(the)h(line,)h(y)o(ou)e(migh)o(t)h +(t)o(yp)q(e)g Fn(M--)f(C-K)p Fo(.)62 639 y(The)19 b(general)g(w)o(a)o(y)f(to) +g(pass)g(n)o(umeric)i(argumen)o(ts)e(to)g(a)g(command)h(is)g(to)f(t)o(yp)q(e) +g(meta)g(digits)i(b)q(efore)f(the)0 701 y(command.)36 b(If)21 +b(the)g(\014rst)f(`digit')h(y)o(ou)g(t)o(yp)q(e)f(is)i(a)e(min)o(us)h(sign)g +(\()p Fn(-)p Fo(\),)g(then)g(the)g(sign)g(of)g(the)f(argumen)o(t)g(will)0 +763 y(b)q(e)i(negativ)o(e.)40 b(Once)22 b(y)o(ou)f(ha)o(v)o(e)h(t)o(yp)q(ed)g +(one)f(meta)g(digit)i(to)e(get)g(the)h(argumen)o(t)f(started,)h(y)o(ou)f(can) +h(t)o(yp)q(e)0 826 y(the)c(remainder)h(of)f(the)g(digits,)h(and)f(then)h(the) +f(command.)29 b(F)l(or)17 b(example,)i(to)f(giv)o(e)g(the)g +Fn(C-D)g Fo(command)g(an)0 888 y(argumen)o(t)c(of)h(10,)f(y)o(ou)h(could)h(t) +o(yp)q(e)g Fn(M-1)23 b(0)h(C-D)p Fo(.)0 1201 y Fm(1.3)33 b(Readline)16 +b(Init)g(File)62 1348 y Fo(Although)g(the)g(Readline)h(library)g(comes)e +(with)h(a)f(set)g(of)g(Emacs-lik)o(e)h(k)o(eybindings)h(installed)g(b)o(y)f +(default,)0 1410 y(it)e(is)g(p)q(ossible)i(that)d(y)o(ou)g(w)o(ould)h(lik)o +(e)h(to)e(use)h(a)f(di\013eren)o(t)h(set)g(of)f(k)o(eybindings.)21 +b(Y)l(ou)14 b(can)g(customize)g(programs)0 1472 y(that)e(use)i(Readline)h(b)o +(y)e(putting)h(commands)f(in)h(an)f Fj(init)i Fo(\014le)f(in)g(y)o(our)f +(home)g(directory)l(.)19 b(The)14 b(name)f(of)f(this)i(\014le)0 +1535 y(is)i(tak)o(en)f(from)g(the)g(v)m(alue)i(of)e(the)h(en)o(vironmen)o(t)f +(v)m(ariable)i Fn(INPUTRC)p Fo(.)j(If)c(that)f(v)m(ariable)h(is)g(unset,)g +(the)f(default)0 1597 y(is)h(`)p Fn(~/.inputrc)p Fo('.)62 1744 +y(When)j(a)g(program)e(whic)o(h)j(uses)f(the)g(Readline)i(library)e(starts)f +(up,)h(the)g(init)h(\014le)g(is)f(read,)g(and)g(the)g(k)o(ey)0 +1806 y(bindings)e(are)e(set.)62 1953 y(In)j(addition,)h(the)f +Fn(C-x)c(C-r)k Fo(command)f(re-reads)g(this)h(init)h(\014le,)g(th)o(us)e +(incorp)q(orating)h(an)o(y)f(c)o(hanges)h(that)0 2015 y(y)o(ou)d(migh)o(t)g +(ha)o(v)o(e)g(made)g(to)f(it.)0 2311 y Fi(1.3.1)30 b(Readline)15 +b(Init)g(Syn)n(tax)62 2458 y Fo(There)h(are)f(only)h(a)f(few)g(basic)h +(constructs)f(allo)o(w)o(ed)h(in)g(the)g(Readline)i(init)e(\014le.)22 +b(Blank)16 b(lines)h(are)e(ignored.)0 2521 y(Lines)j(b)q(eginning)g(with)f(a) +f Fn(#)g Fo(are)g(commen)o(ts.)22 b(Lines)c(b)q(eginning)g(with)f(a)f +Fn($)g Fo(indicate)h(conditional)h(constructs)0 2583 y(\(see)e(Section)h +(1.3.2)e([Conditional)i(Init)g(Constructs],)e(page)i(7\).)22 +b(Other)16 b(lines)i(denote)f(v)m(ariable)h(settings)e(and)0 +2645 y(k)o(ey)f(bindings.)p eop +%%Page: 5 7 +6 bop 0 -83 a Fo(Chapter)15 b(1:)k(Command)c(Line)i(Editing)1227 +b(5)0 158 y(V)l(ariable)16 b(Settings)240 221 y(Y)l(ou)j(can)g(c)o(hange)g +(the)g(state)f(of)g(a)g(few)h(v)m(ariables)h(in)g(Readline)h(b)o(y)d(using)i +(the)f Fn(set)f Fo(command)240 283 y(within)e(the)f(init)h(\014le.)k(Here)15 +b(is)g(ho)o(w)g(y)o(ou)f(w)o(ould)h(sp)q(ecify)h(that)e(y)o(ou)g(wish)i(to)e +(use)h Fn(vi)f Fo(line)j(editing)240 345 y(commands:)360 408 +y Fn(set)23 b(editing-mode)g(vi)240 484 y Fo(Righ)o(t)14 b(no)o(w,)f(there)h +(are)f(only)h(a)f(few)h(v)m(ariables)g(whic)o(h)h(can)f(b)q(e)g(set;)f(so)g +(few,)h(in)g(fact,)f(that)g(w)o(e)g(just)240 546 y(list)j(them)f(here:)240 +622 y Fn(editing-mode)480 684 y Fo(The)e Fn(editing-mode)e +Fo(v)m(ariable)j(con)o(trols)e(whic)o(h)h(editing)h(mo)q(de)f(y)o(ou)f(are)g +(using.)20 b(By)480 746 y(default,)f(Readline)h(starts)c(up)i(in)h(Emacs)e +(editing)i(mo)q(de,)f(where)g(the)g(k)o(eystrok)o(es)480 808 +y(are)c(most)g(similar)h(to)f(Emacs.)19 b(This)c(v)m(ariable)h(can)f(b)q(e)g +(set)f(to)g(either)h Fn(emacs)f Fo(or)g Fn(vi)p Fo(.)240 884 +y Fn(horizontal-scroll-mode)480 946 y Fo(This)k(v)m(ariable)g(can)f(b)q(e)g +(set)g(to)f(either)i Fn(On)f Fo(or)f Fn(Off)p Fo(.)25 b(Setting)17 +b(it)g(to)f Fn(On)h Fo(means)g(that)480 1009 y(the)d(text)g(of)f(the)h(lines) +i(that)d(y)o(ou)h(edit)h(will)g(scroll)g(horizon)o(tally)g(on)f(a)g(single)h +(screen)480 1071 y(line)f(when)f(they)g(are)f(longer)h(than)f(the)h(width)g +(of)f(the)g(screen,)h(instead)g(of)g(wrapping)480 1133 y(on)o(to)h(a)h(new)h +(screen)f(line.)22 b(By)15 b(default,)h(this)f(v)m(ariable)i(is)f(set)e(to)h +Fn(Off)p Fo(.)240 1209 y Fn(mark-modified-lines)480 1271 y +Fo(This)h(v)m(ariable,)g(when)g(set)f(to)f Fn(On)p Fo(,)h(sa)o(ys)f(to)g +(displa)o(y)j(an)e(asterisk)g(\(`)p Fn(*)p Fo('\))e(at)i(the)g(start)480 +1333 y(of)f(history)h(lines)i(whic)o(h)e(ha)o(v)o(e)g(b)q(een)h(mo)q +(di\014ed.)21 b(This)15 b(v)m(ariable)h(is)g Fn(off)e Fo(b)o(y)h(default.)240 +1409 y Fn(bell-style)480 1471 y Fo(Con)o(trols)h(what)f(happ)q(ens)j(when)f +(Readline)h(w)o(an)o(ts)e(to)f(ring)i(the)f(terminal)h(b)q(ell.)26 +b(If)480 1533 y(set)13 b(to)g Fn(none)p Fo(,)g(Readline)j(nev)o(er)e(rings)g +(the)g(b)q(ell.)21 b(If)14 b(set)f(to)g Fn(visible)p Fo(,)g(Readline)j(uses) +480 1596 y(a)g(visible)j(b)q(ell)g(if)e(one)g(is)g(a)o(v)m(ailable.)27 +b(If)17 b(set)f(to)g Fn(audible)g Fo(\(the)h(default\),)g(Readline)480 +1658 y(attempts)d(to)h(ring)g(the)h(terminal's)f(b)q(ell.)240 +1733 y Fn(comment-begin)480 1796 y Fo(The)21 b(string)h(to)e(insert)i(at)e +(the)h(b)q(eginning)j(of)c(the)i(line)g(when)g(the)f Fn(vi-comment)480 +1858 y Fo(command)15 b(is)h(executed.)21 b(The)15 b(default)h(v)m(alue)g(is)g +Fn("#")p Fo(.)240 1934 y Fn(meta-flag)480 1996 y Fo(If)d(set)g(to)f +Fn(on)p Fo(,)g(Readline)j(will)g(enable)f(eigh)o(t-bit)f(input)h(\(it)f(will) +h(not)f(strip)g(the)g(eigh)o(th)480 2058 y(bit)i(from)g(the)g(c)o(haracters)f +(it)h(reads\),)f(regardless)h(of)g(what)f(the)h(terminal)h(claims)g(it)480 +2120 y(can)f(supp)q(ort.)20 b(The)c(default)g(v)m(alue)g(is)g +Fn(off)p Fo(.)240 2196 y Fn(convert-meta)480 2258 y Fo(If)23 +b(set)f(to)f Fn(on)p Fo(,)j(Readline)h(will)f(con)o(v)o(ert)d(c)o(haracters)h +(with)g(the)h(eigth)g(bit)f(set)h(to)480 2320 y(an)17 b(ASCI)q(I)g(k)o(ey)g +(sequence)h(b)o(y)e(stripping)i(the)f(eigth)g(bit)g(and)g(prep)q(ending)i(an) +d Fn(ESC)480 2383 y Fo(c)o(haracter,)h(con)o(v)o(erting)g(them)g(to)f(a)h +(meta-pre\014xed)h(k)o(ey)f(sequence.)27 b(The)17 b(default)480 +2445 y(v)m(alue)f(is)g Fn(on)p Fo(.)240 2521 y Fn(output-meta)480 +2583 y Fo(If)d(set)f(to)g Fn(on)p Fo(,)h(Readline)i(will)f(displa)o(y)g(c)o +(haracters)d(with)i(the)g(eigh)o(th)g(bit)g(set)g(directly)480 +2645 y(rather)i(than)g(as)f(a)h(meta-pre\014xed)h(escap)q(e)g(sequence.)21 +b(The)16 b(default)f(is)h Fn(off)p Fo(.)p eop +%%Page: 6 8 +7 bop 0 -83 a Fo(6)1472 b(GNU)15 b(Readline)i(Library)240 158 +y Fn(completion-query-items)480 221 y Fo(The)12 b(n)o(um)o(b)q(er)g(of)f(p)q +(ossible)j(completions)e(that)f(determines)i(when)f(the)g(user)g(is)g(ask)o +(ed)480 283 y(whether)k(he)h(w)o(an)o(ts)d(to)i(see)g(the)g(list)h(of)e(p)q +(ossibiliti)q(es.)25 b(If)16 b(the)g(n)o(um)o(b)q(er)h(of)e(p)q(ossible)480 +345 y(completions)i(is)f(greater)f(than)h(this)h(v)m(alue,)f(Readline)j(will) +e(ask)f(the)g(user)g(whether)480 407 y(or)k(not)h(he)h(wishes)f(to)g(view)g +(them;)j(otherwise,)e(they)f(are)g(simply)h(listed.)39 b(The)480 +470 y(default)16 b(limit)g(is)g Fn(100)p Fo(.)240 564 y Fn(keymap)96 +b Fo(Sets)13 b(Readline's)i(idea)e(of)g(the)g(curren)o(t)f(k)o(eymap)h(for)f +(k)o(ey)h(binding)i(commands.)k(Ac-)480 626 y(ceptable)d Fn(keymap)e +Fo(names)h(are)g Fn(emacs)p Fo(,)f Fn(emacs-standard)p Fo(,)f +Fn(emacs-meta)p Fo(,)g Fn(emacs-)480 688 y(ctlx)p Fo(,)j Fn(vi)p +Fo(,)h Fn(vi-move)p Fo(,)f Fn(vi-command)p Fo(,)g(and)h Fn(vi-insert)p +Fo(.)23 b Fn(vi)17 b Fo(is)g(equiv)m(alen)o(t)i(to)d Fn(vi-)480 +750 y(command)p Fo(;)22 b Fn(emacs)e Fo(is)h(equiv)m(alen)o(t)h(to)e +Fn(emacs-standard)p Fo(.)35 b(The)20 b(default)i(v)m(alue)f(is)480 +813 y Fn(emacs)p Fo(.)33 b(The)21 b(v)m(alue)g(of)e(the)i Fn(editing-mode)d +Fo(v)m(ariable)j(also)f(a\013ects)f(the)h(default)480 875 y(k)o(eymap.)240 +953 y Fn(show-all-if-ambiguous)480 1015 y Fo(This)d(alters)f(the)h(default)g +(b)q(eha)o(vior)g(of)f(the)g(completion)i(functions.)24 b(If)17 +b(set)f(to)g Fn(on)p Fo(,)480 1077 y(w)o(ords)d(whic)o(h)h(ha)o(v)o(e)f(more) +h(than)f(one)h(p)q(ossible)h(completion)g(cause)f(the)f(matc)o(hes)h(to)480 +1140 y(b)q(e)h(listed)g(immediately)h(instead)f(of)f(ringing)h(the)f(b)q +(ell.)22 b(The)14 b(default)h(v)m(alue)g(is)g Fn(off)p Fo(.)240 +1218 y Fn(expand-tilde)480 1280 y Fo(If)20 b(set)f(to)g Fn(on)p +Fo(,)h(tilde)h(expansion)f(is)g(p)q(erformed)g(when)g(Readline)i(attempts)d +(w)o(ord)480 1342 y(completion.)i(The)15 b(default)h(is)g Fn(off)p +Fo(.)0 1420 y(Key)g(Bindings)240 1483 y(The)k(syn)o(tax)f(for)g(con)o +(trolling)i(k)o(ey)e(bindings)j(in)e(the)g(init)h(\014le)g(is)f(simple.)35 +b(First)19 b(y)o(ou)g(ha)o(v)o(e)h(to)240 1545 y(kno)o(w)13 +b(the)h(name)g(of)f(the)h(command)g(that)f(y)o(ou)g(w)o(an)o(t)g(to)g(c)o +(hange.)20 b(The)14 b(follo)o(wing)g(pages)g(con)o(tain)240 +1607 y(tables)i(of)f(the)h(command)g(name,)f(the)h(default)g(k)o(eybinding,)i +(and)e(a)f(short)g(description)i(of)f(what)240 1669 y(the)f(command)g(do)q +(es.)240 1748 y(Once)h(y)o(ou)e(kno)o(w)g(the)h(name)g(of)f(the)h(command,)f +(simply)i(place)g(the)f(name)f(of)h(the)f(k)o(ey)h(y)o(ou)f(wish)240 +1810 y(to)g(bind)j(the)e(command)g(to,)f(a)g(colon,)i(and)f(then)g(the)g +(name)g(of)g(the)g(command)g(on)g(a)f(line)j(in)f(the)240 1872 +y(init)h(\014le.)22 b(The)16 b(name)g(of)f(the)h(k)o(ey)f(can)h(b)q(e)g +(expressed)h(in)f(di\013eren)o(t)g(w)o(a)o(ys,)f(dep)q(ending)i(on)f(whic)o +(h)240 1934 y(is)g(most)e(comfortable)h(for)g(y)o(ou.)240 2012 +y Fj(k)o(eyname)s Fo(:)k Fj(function-name)g Fo(or)c Fj(macro)480 +2075 y(k)o(eyname)j Fo(is)d(the)h(name)f(of)g(a)g(k)o(ey)g(sp)q(elled)i(out)e +(in)h(English.)21 b(F)l(or)15 b(example:)600 2140 y Fn(Control-u:)22 +b(universal-argument)600 2190 y(Meta-Rubout:)g(backward-kill-word)600 +2240 y(Control-o:)g(">&output")480 2318 y Fo(In)12 b(the)g(ab)q(o)o(v)o(e)f +(example,)h(`)p Fn(C-u)p Fo(')f(is)h(b)q(ound)g(to)f(the)h(function)g +Fn(universal-argument)p Fo(,)480 2380 y(and)h(`)p Fn(C-o)p +Fo(')f(is)h(b)q(ound)h(to)f(run)g(the)g(macro)f(expressed)i(on)f(the)g(righ)o +(t)g(hand)g(side)h(\(that)480 2442 y(is,)h(to)g(insert)h(the)f(text)g(`)p +Fn(>&output)p Fo(')e(in)o(to)i(the)g(line\).)240 2521 y Fn(")p +Fj(k)o(eyseq)q Fn(")p Fo(:)20 b Fj(function-name)e Fo(or)d +Fj(macro)480 2583 y(k)o(eyseq)j Fo(di\013ers)f(from)f Fj(k)o(eyname)k +Fo(ab)q(o)o(v)o(e)c(in)i(that)e(strings)h(denoting)h(an)f(en)o(tire)g(k)o(ey) +480 2645 y(sequence)i(can)f(b)q(e)h(sp)q(eci\014ed,)i(b)o(y)d(placing)h(the)f +(k)o(ey)g(sequence)h(in)g(double)h(quotes.)p eop +%%Page: 7 9 +8 bop 0 -83 a Fo(Chapter)15 b(1:)k(Command)c(Line)i(Editing)1227 +b(7)480 158 y(Some)18 b(GNU)g(Emacs)f(st)o(yle)h(k)o(ey)g(escap)q(es)g(can)g +(b)q(e)h(used,)g(as)e(in)i(the)f(follo)o(wing)h(ex-)480 221 +y(ample,)c(but)h(the)f(sp)q(ecial)i(c)o(haracter)e(names)g(are)g(not)f +(recognized.)600 283 y Fn("\\C-u":)23 b(universal-argument)600 +333 y("\\C-x\\C-r":)f(re-read-init-file)600 383 y("\\e[11~":)h("Function)f +(Key)i(1")480 457 y Fo(In)13 b(the)g(ab)q(o)o(v)o(e)g(example,)g(`)p +Fn(C-u)p Fo(')f(is)h(b)q(ound)h(to)e(the)h(function)g Fn(universal-argument) +480 519 y Fo(\(just)g(as)f(it)i(w)o(as)e(in)i(the)f(\014rst)g(example\),)h(`) +p Fn(C-x)g(C-r)p Fo(')f(is)g(b)q(ound)i(to)d(the)h(function)h +Fn(re-)480 582 y(read-init-file)p Fo(,)g(and)i(`)p Fn(ESC)e([)h(1)g(1)g(~)p +Fo(')h(is)g(b)q(ound)h(to)f(insert)g(the)g(text)f(`)p Fn(Function)480 +644 y(Key)g(1)p Fo('.)24 b(The)18 b(follo)o(wing)f(escap)q(e)h(sequences)g +(are)f(a)o(v)m(ailable)i(when)e(sp)q(ecifying)i(k)o(ey)480 +706 y(sequences:)480 793 y Fn(\\C-)168 b Fo(con)o(trol)15 b(pre\014x)480 +881 y Fn(\\M-)168 b Fo(meta)15 b(pre\014x)480 968 y Fn(\\e)192 +b Fo(an)15 b(escap)q(e)h(c)o(haracter)480 1055 y Fn(\\\\)192 +b Fo(bac)o(kslash)480 1142 y Fn(\\")g(")480 1229 y(\\')g(')480 +1317 y Fo(When)14 b(en)o(tering)h(the)f(text)f(of)h(a)f(macro,)g(single)j(or) +d(double)i(quotes)f(should)h(b)q(e)f(used)480 1379 y(to)g(indicate)j(a)e +(macro)f(de\014nition.)22 b(Unquoted)15 b(text)g(is)g(assumed)g(to)g(b)q(e)g +(a)g(function)480 1441 y(name.)27 b(Bac)o(kslash)18 b(will)h(quote)e(an)o(y)g +(c)o(haracter)g(in)h(the)g(macro)f(text,)g(including)j Fn(")480 +1503 y Fo(and)c Fn(')p Fo(.)22 b(F)l(or)16 b(example,)h(the)f(follo)o(wing)h +(binding)h(will)f(mak)o(e)f Fn(C-x)f(\\)g Fo(insert)i(a)f(single)480 +1566 y Fn(\\)f Fo(in)o(to)g(the)g(line:)600 1628 y Fn("\\C-x\\\\":)23 +b("\\\\")0 1836 y Fi(1.3.2)30 b(Conditional)15 b(Init)g(Constructs)62 +1973 y Fo(Readline)j(implemen)o(ts)e(a)f(facilit)o(y)h(similar)g(in)g(spirit) +g(to)f(the)g(conditional)i(compilation)f(features)f(of)g(the)g(C)0 +2035 y(prepro)q(cessor)f(whic)o(h)h(allo)o(ws)f(k)o(ey)g(bindings)h(and)f(v)m +(ariable)i(settings)e(to)f(b)q(e)h(p)q(erformed)h(as)e(the)h(result)g(of)g +(tests.)0 2097 y(There)h(are)g(three)h(parser)e(directiv)o(es)j(used.)0 +2247 y Fn($if)168 b Fo(The)14 b Fn($if)e Fo(construct)h(allo)o(ws)h(bindings) +h(to)e(b)q(e)h(made)f(based)h(on)f(the)h(editing)g(mo)q(de,)g(the)f(terminal) +240 2309 y(b)q(eing)k(used,)e(or)g(the)g(application)i(using)f(Readline.)22 +b(The)16 b(text)f(of)g(the)g(test)g(extends)g(to)g(the)g(end)240 +2371 y(of)g(the)g(line;)i(no)e(c)o(haracters)f(are)h(required)h(to)f(isolate) +g(it.)240 2458 y Fn(mode)144 b Fo(The)19 b Fn(mode=)f Fo(form)g(of)h(the)g +Fn($if)f Fo(directiv)o(e)i(is)f(used)h(to)e(test)g(whether)h(Readline)i(is) +480 2521 y(in)h Fn(emacs)f Fo(or)f Fn(vi)h Fo(mo)q(de.)38 b(This)22 +b(ma)o(y)f(b)q(e)h(used)g(in)g(conjunction)g(with)f(the)h(`)p +Fn(set)480 2583 y(keymap)p Fo(')d(command,)i(for)e(instance,)j(to)d(set)h +(bindings)i(in)f(the)f Fn(emacs-standard)480 2645 y Fo(and)15 +b Fn(emacs-ctlx)f Fo(k)o(eymaps)h(only)h(if)f(Readline)j(is)e(starting)e(out) +h(in)h Fn(emacs)f Fo(mo)q(de.)p eop +%%Page: 8 10 +9 bop 0 -83 a Fo(8)1472 b(GNU)15 b(Readline)i(Library)240 158 +y Fn(term)144 b Fo(The)21 b Fn(term=)f Fo(form)g(ma)o(y)h(b)q(e)g(used)h(to)e +(include)j(terminal-sp)q(eci\014c)h(k)o(ey)c(bindings,)480 +221 y(p)q(erhaps)15 b(to)f(bind)j(the)d(k)o(ey)h(sequences)h(output)e(b)o(y)h +(the)g(terminal's)g(function)h(k)o(eys.)480 283 y(The)f(w)o(ord)g(on)f(the)i +(righ)o(t)e(side)i(of)f(the)g(`)p Fn(=)p Fo(')f(is)h(tested)g(against)g(the)g +(full)h(name)f(of)g(the)480 345 y(terminal)k(and)g(the)g(p)q(ortion)g(of)f +(the)h(terminal)g(name)g(b)q(efore)g(the)g(\014rst)f(`)p Fn(-)p +Fo('.)29 b(This)480 407 y(allo)o(ws)15 b Fj(sun)h Fo(to)e(matc)o(h)h(b)q(oth) +g Fj(sun)h Fo(and)f Fj(sun-cmd)p Fo(,)h(for)f(instance.)240 +485 y Fn(application)480 547 y Fo(The)j Fj(application)i Fo(construct)e(is)g +(used)h(to)e(include)k(application-sp)q(eci\014c)g(settings.)480 +610 y(Eac)o(h)d(program)g(using)h(the)f(Readline)j(library)e(sets)f(the)h +Fj(application)h(name)p Fo(,)f(and)480 672 y(y)o(ou)c(can)h(test)f(for)g(it.) +21 b(This)16 b(could)g(b)q(e)h(used)f(to)e(bind)j(k)o(ey)f(sequences)g(to)f +(functions)480 734 y(useful)h(for)e(a)h(sp)q(eci\014c)i(program.)h(F)l(or)d +(instance,)g(the)g(follo)o(wing)h(command)e(adds)h(a)480 796 +y(k)o(ey)g(sequence)h(that)f(quotes)g(the)g(curren)o(t)g(or)g(previous)h(w)o +(ord)e(in)i(Bash:)600 862 y Fn($if)23 b(bash)600 911 y(#)h(Quote)f(the)g +(current)g(or)h(previous)f(word)600 961 y("\\C-xq":)g("\\eb\\"\\ef\\"")600 +1011 y($endif)0 1104 y($endif)96 b Fo(This)16 b(command,)e(as)h(y)o(ou)g(sa)o +(w)g(in)h(the)f(previous)h(example,)f(terminates)h(an)f Fn($if)f +Fo(command.)0 1197 y Fn($else)120 b Fo(Commands)15 b(in)h(this)f(branc)o(h)h +(of)e(the)i Fn($if)e Fo(directiv)o(e)j(are)e(executed)h(if)g(the)f(test)g +(fails.)0 1447 y Fm(1.4)33 b(Bindable)16 b(Readline)h(Commands)0 +1681 y Fi(1.4.1)30 b(Commands)15 b(F)-5 b(or)15 b(Mo)n(ving)0 +1821 y Fn(beginning-of-line)e(\(C-a\))240 1883 y Fo(Mo)o(v)o(e)h(to)h(the)g +(start)f(of)h(the)g(curren)o(t)g(line.)0 1961 y Fn(end-of-line)f(\(C-e\))240 +2023 y Fo(Mo)o(v)o(e)g(to)h(the)g(end)h(of)f(the)g(line.)0 +2101 y Fn(forward-char)f(\(C-f\))240 2163 y Fo(Mo)o(v)o(e)g(forw)o(ard)g(a)h +(c)o(haracter.)0 2241 y Fn(backward-char)e(\(C-b\))240 2303 +y Fo(Mo)o(v)o(e)h(bac)o(k)h(a)g(c)o(haracter.)0 2381 y Fn(forward-word)f +(\(M-f\))240 2443 y Fo(Mo)o(v)o(e)g(forw)o(ard)g(to)h(the)g(end)h(of)f(the)g +(next)g(w)o(ord.)k(W)l(ords)c(are)g(comp)q(osed)h(of)e(letters)i(and)f +(digits.)0 2521 y Fn(backward-word)e(\(M-b\))240 2583 y Fo(Mo)o(v)o(e)j(bac)o +(k)g(to)g(the)h(start)f(of)g(this,)h(or)g(the)f(previous,)i(w)o(ord.)24 +b(W)l(ords)16 b(are)g(comp)q(osed)i(of)e(letters)240 2645 y(and)f(digits.)p +eop +%%Page: 9 11 +10 bop 0 -83 a Fo(Chapter)15 b(1:)k(Command)c(Line)i(Editing)1227 +b(9)0 158 y Fn(clear-screen)14 b(\(C-l\))240 221 y Fo(Clear)h(the)g(screen)g +(and)g(redra)o(w)f(the)h(curren)o(t)g(line,)h(lea)o(ving)g(the)f(curren)o(t)f +(line)j(at)d(the)h(top)f(of)h(the)240 283 y(screen.)0 361 y +Fn(redraw-current-line)e(\(\))240 423 y Fo(Refresh)j(the)f(curren)o(t)g +(line.)22 b(By)15 b(default,)h(this)f(is)h(un)o(b)q(ound.)0 +663 y Fi(1.4.2)30 b(Commands)15 b(F)-5 b(or)15 b(Manipulating)g(The)g +(History)0 804 y Fn(accept-line)f(\(Newline,)g(Return\))240 +866 y Fo(Accept)g(the)f(line)i(regardless)e(of)g(where)g(the)g(cursor)g(is.) +20 b(If)13 b(this)h(line)h(is)e(non-empt)o(y)l(,)h(add)f(it)g(to)g(the)240 +928 y(history)k(list.)25 b(If)17 b(this)g(line)i(w)o(as)c(a)i(history)g +(line,)h(then)f(restore)f(the)h(history)f(line)j(to)d(its)h(original)240 +990 y(state.)0 1069 y Fn(previous-history)c(\(C-p\))240 1131 +y Fo(Mo)o(v)o(e)h(`up')h(through)g(the)g(history)g(list.)0 +1209 y Fn(next-history)f(\(C-n\))240 1272 y Fo(Mo)o(v)o(e)g(`do)o(wn')g +(through)h(the)h(history)f(list.)0 1350 y Fn(beginning-of-history)d(\(M-<\)) +240 1412 y Fo(Mo)o(v)o(e)i(to)h(the)g(\014rst)g(line)i(in)f(the)f(history)l +(.)0 1490 y Fn(end-of-history)e(\(M->\))240 1553 y Fo(Mo)o(v)o(e)h(to)h(the)g +(end)h(of)f(the)g(input)h(history)l(,)f(i.e.,)g(the)g(line)i(y)o(ou)e(are)g +(en)o(tering.)0 1631 y Fn(reverse-search-history)d(\(C-r\))240 +1693 y Fo(Searc)o(h)18 b(bac)o(kw)o(ard)f(starting)g(at)g(the)g(curren)o(t)h +(line)h(and)f(mo)o(ving)f(`up')h(through)f(the)h(history)f(as)240 +1756 y(necessary)l(.)j(This)c(is)g(an)f(incremen)o(tal)h(searc)o(h.)0 +1834 y Fn(forward-search-history)c(\(C-s\))240 1896 y Fo(Searc)o(h)j(forw)o +(ard)e(starting)h(at)g(the)g(curren)o(t)h(line)h(and)f(mo)o(ving)f(`do)o(wn') +g(through)g(the)g(the)h(history)240 1958 y(as)g(necessary)l(.)20 +b(This)c(is)g(an)f(incremen)o(tal)h(searc)o(h.)0 2037 y Fn +(non-incremental-reverse-se)o(arch-hi)o(story)c(\(M-p\))240 +2099 y Fo(Searc)o(h)18 b(bac)o(kw)o(ard)f(starting)g(at)g(the)g(curren)o(t)h +(line)h(and)f(mo)o(ving)f(`up')h(through)f(the)h(history)f(as)240 +2161 y(necessary)e(using)h(a)f(non-incremen)o(tal)i(searc)o(h)e(for)g(a)f +(string)i(supplied)h(b)o(y)e(the)h(user.)0 2239 y Fn +(non-incremental-forward-se)o(arch-hi)o(story)c(\(M-n\))240 +2302 y Fo(Searc)o(h)j(forw)o(ard)e(starting)h(at)g(the)g(curren)o(t)h(line)h +(and)f(mo)o(ving)f(`do)o(wn')g(through)g(the)g(the)h(history)240 +2364 y(as)g(necessary)g(using)h(a)f(non-incremen)o(tal)i(searc)o(h)e(for)f(a) +h(string)g(supplied)j(b)o(y)d(the)g(user.)0 2442 y Fn(history-search-forward) +d(\(\))240 2505 y Fo(Searc)o(h)h(forw)o(ard)f(through)h(the)g(history)g(for)g +(the)g(string)g(of)g(c)o(haracters)f(b)q(et)o(w)o(een)i(the)f(start)f(of)h +(the)240 2567 y(curren)o(t)j(line)i(and)e(the)h(curren)o(t)f(p)q(oin)o(t.)23 +b(This)17 b(is)f(a)g(non-incremen)o(tal)i(searc)o(h.)23 b(By)16 +b(default,)h(this)240 2629 y(command)e(is)h(un)o(b)q(ound.)p +eop +%%Page: 10 12 +11 bop 0 -83 a Fo(10)1449 b(GNU)15 b(Readline)i(Library)0 158 +y Fn(history-search-backward)12 b(\(\))240 221 y Fo(Searc)o(h)k(bac)o(kw)o +(ard)g(through)g(the)g(history)g(for)g(the)g(string)g(of)g(c)o(haracters)g(b) +q(et)o(w)o(een)g(the)g(start)f(of)240 283 y(the)i(curren)o(t)g(line)h(and)f +(the)g(curren)o(t)g(p)q(oin)o(t.)25 b(This)17 b(is)g(a)g(non-incremen)o(tal)h +(searc)o(h.)25 b(By)17 b(default,)240 345 y(this)f(command)f(is)g(un)o(b)q +(ound.)0 425 y Fn(yank-nth-arg)f(\(M-C-y\))240 487 y Fo(Insert)19 +b(the)g(\014rst)f(argumen)o(t)g(to)g(the)h(previous)g(command)g(\(usually)g +(the)g(second)g(w)o(ord)f(on)h(the)240 550 y(previous)e(line\).)23 +b(With)16 b(an)g(argumen)o(t)f Fj(n)p Fo(,)h(insert)h(the)f +Fj(n)p Fo(th)g(w)o(ord)f(from)g(the)h(previous)h(command)240 +612 y(\(the)d(w)o(ords)g(in)h(the)g(previous)g(command)f(b)q(egin)i(with)f(w) +o(ord)f(0\).)19 b(A)14 b(negativ)o(e)h(argumen)o(t)f(inserts)240 +674 y(the)h Fj(n)p Fo(th)h(w)o(ord)e(from)h(the)g(end)h(of)e(the)i(previous)g +(command.)0 754 y Fn(yank-last-arg)d(\(M-.,)i(M-_\))240 816 +y Fo(Insert)k(last)g(argumen)o(t)g(to)f(the)h(previous)h(command)f(\(the)g +(last)g(w)o(ord)f(on)h(the)g(previous)h(line\).)240 879 y(With)15 +b(an)h(argumen)o(t,)e(b)q(eha)o(v)o(e)h(exactly)h(lik)o(e)g +Fn(yank-nth-arg)p Fo(.)0 1134 y Fi(1.4.3)30 b(Commands)15 b(F)-5 +b(or)15 b(Changing)g(T)-5 b(ext)0 1276 y Fn(delete-char)14 +b(\(C-d\))240 1338 y Fo(Delete)f(the)f(c)o(haracter)f(under)i(the)f(cursor.) +19 b(If)12 b(the)g(cursor)g(is)g(at)g(the)g(b)q(eginning)i(of)e(the)g(line,)i +(there)240 1400 y(are)k(no)g(c)o(haracters)g(in)h(the)g(line,)h(and)f(the)f +(last)g(c)o(haracter)g(t)o(yp)q(ed)h(w)o(as)e(not)h(C-d,)h(then)g(return)240 +1463 y(EOF.)0 1543 y Fn(backward-delete-char)12 b(\(Rubout\))240 +1605 y Fo(Delete)g(the)f(c)o(haracter)f(b)q(ehind)j(the)e(cursor.)18 +b(A)11 b(n)o(umeric)h(arg)e(sa)o(ys)g(to)g(kill)j(the)e(c)o(haracters)f +(instead)240 1667 y(of)15 b(deleting)h(them.)0 1747 y Fn(quoted-insert)d +(\(C-q,)i(C-v\))240 1809 y Fo(Add)i(the)f(next)h(c)o(haracter)f(that)f(y)o +(ou)h(t)o(yp)q(e)h(to)f(the)g(line)i(v)o(erbatim.)24 b(This)17 +b(is)g(ho)o(w)e(to)h(insert)h(k)o(ey)240 1872 y(sequences)f(lik)o(e)h +Fn(C-Q)p Fo(,)d(for)h(example.)0 1952 y Fn(tab-insert)f(\(M-TAB\))240 +2014 y Fo(Insert)h(a)g(tab)g(c)o(haracter.)0 2094 y Fn(self-insert)f(\(a,)g +(b,)h(A,)g(1,)g(!,)g(...\))240 2156 y Fo(Insert)g(y)o(ourself.)0 +2236 y Fn(transpose-chars)e(\(C-t\))240 2298 y Fo(Drag)h(the)h(c)o(haracter)g +(b)q(efore)g(the)h(cursor)f(forw)o(ard)f(o)o(v)o(er)g(the)h(c)o(haracter)g +(at)f(the)i(cursor,)e(mo)o(ving)240 2361 y(the)k(cursor)h(forw)o(ard)e(as)h +(w)o(ell.)30 b(If)19 b(the)f(insertion)i(p)q(oin)o(t)f(is)g(at)e(the)i(end)g +(of)f(the)g(line,)j(then)e(this)240 2423 y(transp)q(oses)c(the)g(last)g(t)o +(w)o(o)f(c)o(haracters)h(of)f(the)i(line.)21 b(Negativ)o(e)15 +b(argumen)o(tss)f(don't)h(w)o(ork.)0 2503 y Fn(transpose-words)e(\(M-t\))240 +2565 y Fo(Drag)f(the)h(w)o(ord)f(b)q(ehind)i(the)f(cursor)g(past)f(the)h(w)o +(ord)f(in)h(fron)o(t)f(of)h(the)f(cursor)h(mo)o(ving)f(the)h(cursor)240 +2627 y(o)o(v)o(er)h(that)h(w)o(ord)f(as)h(w)o(ell.)p eop +%%Page: 11 13 +12 bop 0 -83 a Fo(Chapter)15 b(1:)k(Command)c(Line)i(Editing)1205 +b(11)0 158 y Fn(upcase-word)14 b(\(M-u\))240 221 y Fo(Upp)q(ercase)h(the)e +(curren)o(t)h(\(or)f(follo)o(wing\))h(w)o(ord.)k(With)c(a)f(negativ)o(e)h +(argumen)o(t,)f(do)g(the)h(previous)240 283 y(w)o(ord,)g(but)h(do)h(not)e(mo) +o(v)o(e)h(the)g(cursor.)0 358 y Fn(downcase-word)e(\(M-l\))240 +420 y Fo(Lo)o(w)o(ercase)g(the)i(curren)o(t)f(\(or)f(follo)o(wing\))h(w)o +(ord.)19 b(With)14 b(a)g(negativ)o(e)g(argumen)o(t,)f(do)h(the)g(previous)240 +482 y(w)o(ord,)g(but)h(do)h(not)e(mo)o(v)o(e)h(the)g(cursor.)0 +557 y Fn(capitalize-word)e(\(M-c\))240 619 y Fo(Capitalize)j(the)e(curren)o +(t)g(\(or)f(follo)o(wing\))i(w)o(ord.)j(With)d(a)f(negativ)o(e)g(argumen)o +(t,)f(do)h(the)g(previous)240 682 y(w)o(ord,)g(but)h(do)h(not)e(mo)o(v)o(e)h +(the)g(cursor.)0 891 y Fi(1.4.4)30 b(Killing)15 b(And)h(Y)-5 +b(anking)0 1028 y Fn(kill-line)14 b(\(C-k\))240 1090 y Fo(Kill)j(the)f(text)e +(from)h(the)g(curren)o(t)g(cursor)g(p)q(osition)h(to)f(the)g(end)h(of)f(the)g +(line.)0 1165 y Fn(backward-kill-line)e(\(C-x)h(Rubout\))240 +1228 y Fo(Kill)j(bac)o(kw)o(ard)e(to)f(the)i(b)q(eginning)h(of)e(the)g(line.) +0 1302 y Fn(unix-line-discard)e(\(C-u\))240 1365 y Fo(Kill)j(bac)o(kw)o(ard)d +(from)f(the)i(cursor)f(to)g(the)h(b)q(eginning)i(of)d(the)g(curren)o(t)h +(line.)21 b(Sa)o(v)o(e)13 b(the)h(killed)h(text)240 1427 y(on)g(the)g +(kill-ring.)0 1502 y Fn(kill-whole-line)e(\(\))240 1564 y Fo(Kill)18 +b(all)f(c)o(haracters)e(on)h(the)g(curren)o(t)f(line,)j(no)e(matter)e(where)i +(the)g(cursor)g(is.)22 b(By)16 b(default,)h(this)240 1626 y(is)f(un)o(b)q +(ound.)0 1701 y Fn(kill-word)e(\(M-d\))240 1764 y Fo(Kill)j(from)d(the)h +(cursor)g(to)f(the)h(end)g(of)g(the)g(curren)o(t)f(w)o(ord,)g(or)g(if)i(b)q +(et)o(w)o(een)f(w)o(ords,)f(to)g(the)h(end)g(of)240 1826 y(the)g(next)h(w)o +(ord.)j(W)l(ord)c(b)q(oundaries)h(are)f(the)g(same)g(as)g Fn(forward-word)p +Fo(.)0 1901 y Fn(backward-kill-word)e(\(M-DEL\))240 1963 y +Fo(Kill)k(the)f(w)o(ord)e(b)q(ehind)j(the)f(cursor.)j(W)l(ord)c(b)q +(oundaries)i(are)d(the)i(same)f(as)f Fn(backward-word)p Fo(.)0 +2038 y Fn(unix-word-rubout)f(\(C-w\))240 2100 y Fo(Kill)i(the)e(w)o(ord)f(b)q +(ehind)j(the)f(cursor,)e(using)i(white)f(space)h(as)e(a)h(w)o(ord)f(b)q +(oundary)l(.)20 b(The)13 b(killed)i(text)240 2162 y(is)h(sa)o(v)o(ed)e(on)i +(the)f(kill-ring.)0 2237 y Fn(delete-horizontal-space)d(\(\))240 +2300 y Fo(Delete)k(all)g(spaces)f(and)h(tabs)e(around)i(p)q(oin)o(t.)k(By)15 +b(default,)h(this)f(is)h(un)o(b)q(ound.)0 2375 y Fn(yank)f(\(C-y\))240 +2437 y Fo(Y)l(ank)g(the)h(top)f(of)f(the)i(kill)h(ring)e(in)o(to)g(the)h +(bu\013er)f(at)f(the)i(curren)o(t)f(cursor)g(p)q(osition.)0 +2512 y Fn(yank-pop)f(\(M-y\))240 2574 y Fo(Rotate)f(the)h(kill-ring,)i(and)e +(y)o(ank)g(the)g(new)g(top.)19 b(Y)l(ou)14 b(can)g(only)g(do)g(this)g(if)g +(the)g(prior)g(command)240 2636 y(is)i(y)o(ank)f(or)f(y)o(ank-p)q(op.)p +eop +%%Page: 12 14 +13 bop 0 -83 a Fo(12)1449 b(GNU)15 b(Readline)i(Library)0 158 +y Fi(1.4.5)30 b(Sp)r(ecifying)15 b(Numeric)h(Argumen)n(ts)0 +301 y Fn(digit-argument)d(\(M-0,)i(M-1,)f(...)h(M--\))240 364 +y Fo(Add)k(this)f(digit)h(to)f(the)g(argumen)o(t)f(already)i(accum)o +(ulating,)g(or)f(start)f(a)g(new)i(argumen)o(t.)28 b(M{)240 +426 y(starts)14 b(a)h(negativ)o(e)g(argumen)o(t.)0 507 y Fn +(universal-argument)e(\(\))240 569 y Fo(Eac)o(h)k(time)h(this)g(is)f +(executed,)i(the)e(argumen)o(t)g(coun)o(t)g(is)h(m)o(ultiplied)i(b)o(y)d +(four.)26 b(The)18 b(argumen)o(t)240 631 y(coun)o(t)i(is)h(initially)j(one,)d +(so)f(executing)i(this)f(function)g(the)g(\014rst)f(time)h(mak)o(es)f(the)h +(argumen)o(t)240 693 y(coun)o(t)15 b(four.)20 b(By)15 b(default,)g(this)h(is) +g(not)e(b)q(ound)j(to)d(a)h(k)o(ey)l(.)0 956 y Fi(1.4.6)30 +b(Letting)14 b(Readline)h(T)n(yp)r(e)h(F)-5 b(or)14 b(Y)-5 +b(ou)0 1099 y Fn(complete)14 b(\(TAB\))240 1161 y Fo(A)o(ttempt)i(to)h(do)g +(completion)i(on)e(the)g(text)g(b)q(efore)h(the)f(cursor.)26 +b(This)18 b(is)g(application-sp)q(eci\014c.)240 1223 y(Generally)l(,)h(if)f +(y)o(ou)f(are)h(t)o(yping)g(a)f(\014lename)i(argumen)o(t,)e(y)o(ou)g(can)h +(do)f(\014lename)i(completion;)g(if)240 1285 y(y)o(ou)f(are)f(t)o(yping)i(a)e +(command,)i(y)o(ou)e(can)i(do)f(command)g(completion,)h(if)g(y)o(ou)e(are)h +(t)o(yping)g(in)h(a)240 1348 y(sym)o(b)q(ol)e(to)f(GDB,)g(y)o(ou)g(can)h(do)g +(sym)o(b)q(ol)g(name)g(completion,)h(if)f(y)o(ou)f(are)h(t)o(yping)g(in)g(a)g +(v)m(ariable)240 1410 y(to)e(Bash,)f(y)o(ou)h(can)h(do)f(v)m(ariable)h(name)g +(completion,)g(and)f(so)g(on.)0 1491 y Fn(possible-completions)d(\(M-?\))240 +1553 y Fo(List)k(the)f(p)q(ossible)i(completions)f(of)f(the)g(text)g(b)q +(efore)h(the)f(cursor.)0 1634 y Fn(insert-completions)e(\(\))240 +1696 y Fo(Insert)22 b(all)h(completions)g(of)f(the)g(text)f(b)q(efore)h(p)q +(oin)o(t)h(that)e(w)o(ould)h(ha)o(v)o(e)g(b)q(een)h(generated)f(b)o(y)240 +1758 y Fn(possible-completions)p Fo(.)17 b(By)e(default,)h(this)f(is)h(not)f +(b)q(ound)h(to)f(a)g(k)o(ey)l(.)0 2020 y Fi(1.4.7)30 b(Keyb)r(oard)15 +b(Macros)0 2163 y Fn(start-kbd-macro)e(\(C-x)i(\(\))240 2226 +y Fo(Begin)h(sa)o(ving)f(the)h(c)o(haracters)e(t)o(yp)q(ed)i(in)o(to)f(the)g +(curren)o(t)g(k)o(eyb)q(oard)g(macro.)0 2306 y Fn(end-kbd-macro)e(\(C-x)i +(\)\))240 2369 y Fo(Stop)f(sa)o(ving)h(the)g(c)o(haracters)f(t)o(yp)q(ed)h +(in)o(to)f(the)h(curren)o(t)f(k)o(eyb)q(oard)h(macro)f(and)h(sa)o(v)o(e)f +(the)g(de\014ni-)240 2431 y(tion.)0 2512 y Fn(call-last-kbd-macro)f(\(C-x)h +(e\))240 2574 y Fo(Re-execute)20 b(the)f(last)f(k)o(eyb)q(oard)g(macro)g +(de\014ned,)i(b)o(y)f(making)f(the)h(c)o(haracters)f(in)h(the)g(macro)240 +2636 y(app)q(ear)c(as)g(if)h(t)o(yp)q(ed)f(at)g(the)g(k)o(eyb)q(oard.)p +eop +%%Page: 13 15 +14 bop 0 -83 a Fo(Chapter)15 b(1:)k(Command)c(Line)i(Editing)1205 +b(13)0 158 y Fi(1.4.8)30 b(Some)15 b(Miscellaneous)h(Commands)0 +299 y Fn(re-read-init-file)d(\(C-x)h(C-r\))240 361 y Fo(Read)i(in)g(the)f +(con)o(ten)o(ts)f(of)h(y)o(our)g(init)h(\014le,)g(and)f(incorp)q(orate)h(an)o +(y)e(bindings)j(or)e(v)m(ariable)i(assign-)240 423 y(men)o(ts)e(found)g +(there.)0 502 y Fn(abort)f(\(C-g\))240 564 y Fo(Ab)q(ort)f(the)h(curren)o(t)f +(editing)i(command)e(and)h(ring)g(the)f(terminal's)h(b)q(ell)h(\(sub)s(ject)f +(to)e(the)i(setting)240 626 y(of)h Fn(bell-style)p Fo(\).)0 +704 y Fn(do-uppercase-version)d(\(M-a,)j(M-b,)f(...\))240 767 +y Fo(Run)i(the)f(command)g(that)g(is)h(b)q(ound)g(to)e(the)i(corresop)q +(onding)g(upp)q(ercase)g(c)o(haracter.)0 845 y Fn(prefix-meta)e(\(ESC\))240 +907 y Fo(Mak)o(e)g(the)g(next)h(c)o(haracter)f(that)g(y)o(ou)g(t)o(yp)q(e)h +(b)q(e)g(meta\014ed.)20 b(This)15 b(is)g(for)f(p)q(eople)i(without)e(a)h +(meta)240 970 y(k)o(ey)l(.)20 b(T)o(yping)c(`)p Fn(ESC)e(f)p +Fo(')h(is)g(equiv)m(alen)o(t)i(to)e(t)o(yping)g(`)p Fn(M-f)p +Fo('.)0 1048 y Fn(undo)g(\(C-_,)f(C-x)h(C-u\))240 1110 y Fo(Incremen)o(tal)h +(undo,)f(separately)h(remem)o(b)q(ered)g(for)e(eac)o(h)h(line.)0 +1188 y Fn(revert-line)f(\(M-r\))240 1251 y Fo(Undo)20 b(all)h(c)o(hanges)f +(made)g(to)f(this)i(line.)35 b(This)21 b(is)f(lik)o(e)h(t)o(yping)f(the)g +Fn(undo)g Fo(command)g(enough)240 1313 y(times)15 b(to)g(get)g(bac)o(k)g(to)f +(the)i(b)q(eginning.)0 1391 y Fn(tilde-expand)e(\(M-~\))240 +1453 y Fo(P)o(erform)g(tilde)j(expansion)f(on)f(the)g(curren)o(t)g(w)o(ord.)0 +1532 y Fn(dump-functions)e(\(\))240 1594 y Fo(Prin)o(t)18 b(all)h(of)f(the)g +(functions)h(and)g(their)g(k)o(ey)f(bindings)i(to)d(the)i(readline)h(output)e +(stream.)28 b(If)18 b(a)240 1656 y(n)o(umeric)i(argumen)o(t)d(is)i(supplied,) +j(the)d(output)f(is)h(formatted)f(in)h(suc)o(h)g(a)f(w)o(a)o(y)g(that)g(it)h +(can)f(b)q(e)240 1718 y(made)d(part)g(of)g(an)g Fj(inputrc)k +Fo(\014le.)0 1974 y Fm(1.5)33 b(Readline)16 b(vi)g(Mo)r(de)62 +2115 y Fo(While)d(the)f(Readline)i(library)e(do)q(es)g(not)g(ha)o(v)o(e)f(a)g +(full)i(set)f(of)f Fn(vi)g Fo(editing)i(functions,)g(it)f(do)q(es)g(con)o +(tain)g(enough)0 2177 y(to)i(allo)o(w)h(simple)i(editing)f(of)f(the)g(line.) +21 b(The)15 b(Readline)i Fn(vi)e Fo(mo)q(de)g(b)q(eha)o(v)o(es)h(as)e(sp)q +(eci\014ed)j(in)f(the)f(P)o(osix)g(1003.2)0 2240 y(standard.)62 +2380 y(In)i(order)e(to)g(switc)o(h)h(in)o(teractiv)o(ely)h(b)q(et)o(w)o(een)f +Fn(Emacs)f Fo(and)h Fn(Vi)f Fo(editing)i(mo)q(des,)f(use)g(the)g(command)f +(M-C-j)0 2442 y(\(toggle-editing-mo)q(de\).)21 b(The)15 b(Readline)j(default) +e(is)f Fn(emacs)g Fo(mo)q(de.)62 2583 y(When)k(y)o(ou)f(en)o(ter)g(a)g(line)i +(in)g Fn(vi)e Fo(mo)q(de,)h(y)o(ou)f(are)g(already)g(placed)i(in)f +(`insertion')g(mo)q(de,)g(as)f(if)h(y)o(ou)f(had)0 2645 y(t)o(yp)q(ed)e(an)f +(`)p Fn(i)p Fo('.)20 b(Pressing)c Fn(ESC)f Fo(switc)o(hes)h(y)o(ou)f(in)o(to) +h(`command')f(mo)q(de,)g(where)h(y)o(ou)f(can)h(edit)g(the)g(text)f(of)g(the) +p eop +%%Page: 14 16 +15 bop 0 -83 a Fo(14)1449 b(GNU)15 b(Readline)i(Library)0 158 +y(line)j(with)e(the)g(standard)g Fn(vi)f Fo(mo)o(v)o(emen)o(t)g(k)o(eys,)h +(mo)o(v)o(e)g(to)f(previous)i(history)f(lines)h(with)g(`)p +Fn(k)p Fo(',)e(and)h(follo)o(wing)0 221 y(lines)f(with)e(`)p +Fn(j)p Fo(',)f(and)i(so)e(forth.)p eop +%%Page: 15 17 +16 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(Readline)994 +b(15)0 158 y Fk(2)41 b(Programming)16 b(with)f(GNU)h(Readline)62 +370 y Fo(This)j(c)o(hapter)f(describ)q(es)i(the)e(in)o(terface)g(b)q(et)o(w)o +(een)h(the)f(GNU)g(Readline)j(Library)d(and)h(other)f(programs.)0 +433 y(If)h(y)o(ou)g(are)f(a)h(programmer,)f(and)i(y)o(ou)e(wish)i(to)e +(include)j(the)e(features)g(found)g(in)h(GNU)f(Readline)i(suc)o(h)e(as)0 +495 y(completion,)f(line)h(editing,)f(and)f(in)o(teractiv)o(e)h(history)f +(manipulation)h(in)g(y)o(our)f(o)o(wn)f(programs,)g(this)h(section)0 +557 y(is)f(for)e(y)o(ou.)0 826 y Fm(2.1)33 b(Basic)14 b(Beha)n(vior)62 +968 y Fo(Man)o(y)c(programs)g(pro)o(vide)h(a)g(command)f(line)j(in)o +(terface,)e(suc)o(h)g(as)g Fn(mail)p Fo(,)f Fn(ftp)p Fo(,)h(and)g +Fn(sh)p Fo(.)18 b(F)l(or)10 b(suc)o(h)i(programs,)0 1031 y(the)17 +b(default)h(b)q(eha)o(viour)g(of)e(Readline)k(is)e(su\016cien)o(t.)26 +b(This)18 b(section)f(describ)q(es)i(ho)o(w)e(to)f(use)i(Readline)h(in)f(the) +0 1093 y(simplest)e(w)o(a)o(y)e(p)q(ossible,)j(p)q(erhaps)f(to)e(replace)j +(calls)f(in)g(y)o(our)f(co)q(de)g(to)g Fn(gets\(\))f Fo(or)h +Fn(fgets)f(\(\))p Fo(.)62 1235 y(The)g(function)g Fn(readline)g(\(\))f +Fo(prin)o(ts)h(a)f(prompt)g(and)h(then)g(reads)f(and)g(returns)h(a)f(single)i +(line)g(of)e(text)g(from)0 1297 y(the)g(user.)19 b(The)13 b(line)i +Fn(readline)d Fo(returns)g(is)i(allo)q(cated)g(with)f Fn(malloc)h(\(\))p +Fo(;)f(y)o(ou)g(should)h Fn(free)g(\(\))f Fo(the)g(line)h(when)0 +1360 y(y)o(ou)h(are)g(done)g(with)h(it.)k(The)15 b(declaration)h(for)f +Fn(readline)f Fo(in)i(ANSI)g(C)f(is)120 1489 y Fn(char)23 b(*readline)g +(\(char)g(*)p Fj(prompt)q Fn(\);)0 1631 y Fo(So,)15 b(one)g(migh)o(t)g(sa)o +(y)120 1761 y Fn(char)23 b(*line)g(=)h(readline)f(\("Enter)g(a)h(line:)f +("\);)0 1903 y Fo(in)17 b(order)g(to)f(read)g(a)g(line)j(of)d(text)g(from)g +(the)g(user.)24 b(The)17 b(line)h(returned)f(has)g(the)f(\014nal)i(newline)g +(remo)o(v)o(ed,)e(so)0 1965 y(only)g(the)f(text)g(remains.)62 +2107 y(If)g Fn(readline)f Fo(encoun)o(ters)h(an)f Fn(EOF)h +Fo(while)h(reading)f(the)g(line,)h(and)f(the)g(line)h(is)f(empt)o(y)g(at)f +(that)g(p)q(oin)o(t,)h(then)0 2169 y Fn(\(char)f(*\)NULL)h +Fo(is)h(returned.)k(Otherwise,)15 b(the)h(line)h(is)e(ended)i(just)d(as)h(if) +h(a)f(newline)i(had)e(b)q(een)i(t)o(yp)q(ed.)62 2311 y(If)g(y)o(ou)g(w)o(an)o +(t)f(the)h(user)g(to)f(b)q(e)i(able)f(to)g(get)f(at)g(the)h(line)i(later,)e +(\(with)g Fn(C-P)f Fo(for)g(example\),)i(y)o(ou)e(m)o(ust)h(call)0 +2374 y Fn(add_history)d(\(\))h Fo(to)f(sa)o(v)o(e)h(the)g(line)i(a)o(w)o(a)o +(y)c(in)j(a)f Fj(history)k Fo(list)d(of)f(suc)o(h)h(lines.)120 +2503 y Fn(add_history)22 b(\(line\);)0 2645 y Fo(F)l(or)15 +b(full)h(details)g(on)f(the)h(GNU)f(History)g(Library)l(,)g(see)h(the)f(asso) +q(ciated)g(man)o(ual.)p eop +%%Page: 16 18 +17 bop 0 -83 a Fo(16)1449 b(GNU)15 b(Readline)i(Library)62 +158 y(It)e(is)g(preferable)g(to)f(a)o(v)o(oid)g(sa)o(ving)h(empt)o(y)f(lines) +i(on)f(the)f(history)h(list,)g(since)g(users)g(rarely)g(ha)o(v)o(e)f(a)g +(burning)0 221 y(need)i(to)e(reuse)h(a)f(blank)i(line.)21 b(Here)15 +b(is)g(a)g(function)g(whic)o(h)h(usefully)g(replaces)g(the)f(standard)f +Fn(gets)h(\(\))f Fo(library)0 283 y(function,)i(and)f(has)g(the)g(adv)m(an)o +(tage)g(of)g(no)g(static)g(bu\013er)g(to)g(o)o(v)o(er\015o)o(w:)120 +428 y Fn(/*)24 b(A)f(static)g(variable)g(for)h(holding)e(the)i(line.)f(*/)120 +477 y(static)g(char)g(*line_read)g(=)h(\(char)f(*\)NULL;)120 +577 y(/*)h(Read)f(a)h(string,)f(and)g(return)g(a)h(pointer)f(to)g(it.)48 +b(Returns)22 b(NULL)i(on)f(EOF.)h(*/)120 627 y(char)f(*)120 +677 y(rl_gets)g(\(\))120 726 y({)168 776 y(/*)g(If)h(the)f(buffer)g(has)h +(already)f(been)g(allocated,)g(return)g(the)g(memory)239 826 +y(to)h(the)f(free)h(pool.)f(*/)168 876 y(if)g(\(line_read\))215 +926 y({)263 975 y(free)g(\(line_read\);)263 1025 y(line_read)g(=)h(\(char)f +(*\)NULL;)215 1075 y(})168 1175 y(/*)g(Get)h(a)f(line)h(from)f(the)h(user.)f +(*/)168 1225 y(line_read)f(=)i(readline)f(\(""\);)168 1324 +y(/*)g(If)h(the)f(line)h(has)f(any)h(text)f(in)g(it,)h(save)f(it)h(on)f(the)h +(history.)f(*/)168 1374 y(if)g(\(line_read)g(&&)g(*line_read\))215 +1424 y(add_history)g(\(line_read\);)168 1523 y(return)g(\(line_read\);)120 +1573 y(})62 1730 y Fo(This)15 b(function)g(giv)o(es)f(the)g(user)g(the)g +(default)h(b)q(eha)o(viour)g(of)e Fn(TAB)h Fo(completion:)20 +b(completion)15 b(on)f(\014le)h(names.)0 1793 y(If)h(y)o(ou)f(do)h(not)f(w)o +(an)o(t)g(Readline)j(to)d(complete)i(on)e(\014lenames,)i(y)o(ou)e(can)h(c)o +(hange)g(the)g(binding)i(of)d(the)h Fn(TAB)f Fo(k)o(ey)0 1855 +y(with)h Fn(rl_bind_key)d(\(\))p Fo(.)120 1999 y Fn(int)23 +b(rl_bind_key)g(\(int)g Fj(k)o(ey)p Fn(,)h(int)f(\(*)p Fj(function)p +Fn(\)\(\)\);)62 2157 y(rl_bind_key)14 b(\(\))f Fo(tak)o(es)g(t)o(w)o(o)f +(argumen)o(ts:)19 b Fj(k)o(ey)e Fo(is)d(the)g(c)o(haracter)f(that)g(y)o(ou)g +(w)o(an)o(t)f(to)h(bind,)i(and)f Fj(function)0 2219 y Fo(is)g(the)g(address)g +(of)f(the)h(function)g(to)f(call)i(when)f Fj(k)o(ey)j Fo(is)d(pressed.)20 +b(Binding)c Fn(TAB)d Fo(to)g Fn(rl_insert)h(\(\))f Fo(mak)o(es)g +Fn(TAB)0 2281 y Fo(insert)i(itself.)20 b Fn(rl_bind_key)14 +b(\(\))g Fo(returns)g(non-zero)h(if)g Fj(k)o(ey)j Fo(is)d(not)f(a)g(v)m(alid) +i(ASCI)q(I)f(c)o(haracter)f(co)q(de)h(\(b)q(et)o(w)o(een)0 +2343 y(0)g(and)g(255\).)62 2500 y(Th)o(us,)g(to)g(disable)h(the)g(default)f +Fn(TAB)g Fo(b)q(eha)o(vior,)h(the)f(follo)o(wing)h(su\016ces:)120 +2645 y Fn(rl_bind_key)22 b(\('\\t',)h(rl_insert\);)p eop +%%Page: 17 19 +18 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(Readline)994 +b(17)62 158 y(This)12 b(co)q(de)f(should)h(b)q(e)f(executed)h(once)f(at)f +(the)h(start)f(of)g(y)o(our)g(program;)h(y)o(ou)g(migh)o(t)f(write)h(a)g +(function)g(called)0 221 y Fn(initialize_readline)i(\(\))j +Fo(whic)o(h)h(p)q(erforms)f(this)h(and)f(other)g(desired)i(initializations,)h +(suc)o(h)e(as)f(installing)0 283 y(custom)f(completers)g(\(see)h(Section)g +(2.4)e([Custom)g(Completers],)h(page)g(28\).)0 539 y Fm(2.2)33 +b(Custom)14 b(F)-6 b(unctions)62 680 y Fo(Readline)18 b(pro)o(vides)f(man)o +(y)e(functions)i(for)e(manipulating)j(the)e(text)f(of)g(the)h(line,)i(but)e +(it)g(isn't)g(p)q(ossible)i(to)0 742 y(an)o(ticipate)i(the)g(needs)g(of)f +(all)h(programs.)31 b(This)20 b(section)g(describ)q(es)h(the)f(v)m(arious)g +(functions)g(and)g(v)m(ariables)0 804 y(de\014ned)c(within)f(the)g(Readline)i +(library)e(whic)o(h)g(allo)o(w)g(a)f(user)g(program)f(to)h(add)h(customized)g +(functionalit)o(y)h(to)0 866 y(Readline.)0 1106 y Fi(2.2.1)30 +b(The)15 b(F)-5 b(unction)14 b(T)n(yp)r(e)62 1247 y Fo(F)l(or)j(readabilt)o +(y)l(,)h(w)o(e)f(declare)i(a)e(new)g(t)o(yp)q(e)h(of)f(ob)s(ject,)f(called)j +Fj(F)l(unction)p Fo(.)28 b(A)17 b Fn(Function)f Fo(is)i(a)f(C)g(function)0 +1309 y(whic)o(h)f(returns)f(an)g Fn(int)p Fo(.)20 b(The)15 +b(t)o(yp)q(e)g(declaration)h(for)f Fn(Function)f Fo(is:)0 1450 +y Fn(typedef)g(int)h(Function)f(\(\);)62 1590 y Fo(The)i(reason)f(for)g +(declaring)i(this)f(new)g(t)o(yp)q(e)f(is)h(to)f(mak)o(e)g(it)h(easier)g(to)f +(write)g(co)q(de)h(describing)i(p)q(oin)o(ters)e(to)0 1652 +y(C)g(functions.)25 b(Let)17 b(us)f(sa)o(y)g(w)o(e)g(had)h(a)f(v)m(ariable)i +(called)g Fj(func)i Fo(whic)o(h)d(w)o(as)f(a)g(p)q(oin)o(ter)h(to)f(a)g +(function.)25 b(Instead)0 1715 y(of)15 b(the)g(classic)h(C)f(declaration)62 +1855 y Fn(int)g(\(*\)\(\)func;)0 1996 y Fo(w)o(e)g(ma)o(y)f(write)62 +2136 y Fn(Function)g(*func;)0 2277 y Fo(Similarly)l(,)j(there)e(are)120 +2405 y Fn(typedef)23 b(void)g(VFunction)g(\(\);)120 2455 y(typedef)g(char)g +(*CPFunction)g(\(\);)g Fo(and)120 2505 y Fn(typedef)g(char)g(**CPPFunction)f +(\(\);)0 2645 y Fo(for)12 b(functions)h(returning)g(no)g(v)m(alue,)g +Fn(pointer)i(to)g(char)p Fo(,)d(and)g Fn(pointer)i(to)h(pointer)g(to)f(char)p +Fo(,)e(resp)q(ectiv)o(ely)l(.)p eop +%%Page: 18 20 +19 bop 0 -83 a Fo(18)1449 b(GNU)15 b(Readline)i(Library)0 158 +y Fi(2.2.2)30 b(W)-5 b(riting)15 b(a)g(New)g(F)-5 b(unction)62 +296 y Fo(In)22 b(order)f(to)g(write)g(new)h(functions)g(for)f(Readline,)j(y)o +(ou)d(need)h(to)f(kno)o(w)g(the)g(calling)i(con)o(v)o(en)o(tions)f(for)0 +358 y(k)o(eyb)q(oard-in)o(v)o(ok)o(ed)17 b(functions,)g(and)f(the)h(names)f +(of)g(the)h(v)m(ariables)h(that)d(describ)q(e)j(the)f(curren)o(t)f(state)g +(of)g(the)0 420 y(line)h(read)e(so)g(far.)62 558 y(The)h(calling)h(sequence)f +(for)f(a)f(command)i Fn(foo)e Fo(lo)q(oks)i(lik)o(e)120 683 +y Fn(foo)23 b(\(int)h(count,)f(int)g(key\))0 820 y Fo(where)f +Fj(coun)o(t)g Fo(is)g(the)f(n)o(umeric)i(argumen)o(t)d(\(or)h(1)g(if)h +(defaulted\))g(and)f Fj(k)o(ey)26 b Fo(is)21 b(the)h(k)o(ey)f(that)g(in)o(v)o +(ok)o(ed)h(this)0 882 y(function.)62 1020 y(It)f(is)h(completely)g(up)f(to)f +(the)h(function)h(as)f(to)f(what)g(should)i(b)q(e)g(done)f(with)g(the)g(n)o +(umeric)h(argumen)o(t.)0 1082 y(Some)c(functions)g(use)g(it)g(as)f(a)h(rep)q +(eat)g(coun)o(t,)f(some)h(as)f(a)g(\015ag,)h(and)g(others)f(to)g(c)o(ho)q +(ose)h(alternate)f(b)q(eha)o(vior)0 1144 y(\(refreshing)12 +b(the)g(curren)o(t)g(line)h(as)f(opp)q(osed)g(to)f(refreshing)i(the)f +(screen,)g(for)g(example\).)19 b(Some)12 b(c)o(ho)q(ose)f(to)h(ignore)0 +1207 y(it.)24 b(In)17 b(general,)g(if)g(a)g(function)g(uses)g(the)g(n)o +(umeric)g(argumen)o(t)f(as)g(a)g(rep)q(eat)h(coun)o(t,)f(it)h(should)h(b)q(e) +f(able)g(to)f(do)0 1269 y(something)f(useful)g(with)g(b)q(oth)f(negativ)o(e)h +(and)f(p)q(ositiv)o(e)i(argumen)o(ts.)i(A)o(t)c(the)h(v)o(ery)f(least,)g(it)h +(should)g(b)q(e)g(a)o(w)o(are)0 1331 y(that)f(it)i(can)f(b)q(e)h(passed)g(a)e +(negativ)o(e)i(argumen)o(t.)1736 1494 y(V)l(ariable)-1899 b +Fh(char)20 b(*)f Fg(rl)p 211 1494 18 3 v 21 w(line)p 320 1494 +V 23 w(bu\013er)120 1557 y Fo(This)f(is)g(the)f(line)i(gathered)e(so)g(far.) +25 b(Y)l(ou)18 b(are)f(w)o(elcome)g(to)g(mo)q(dify)h(the)f(con)o(ten)o(ts)g +(of)f(the)i(line,)120 1619 y(but)d(see)h(Section)g(2.3.5)d([Allo)o(wing)k +(Undoing],)e(page)g(23.)1736 1782 y(V)l(ariable)-1899 b Fh(int)20 +b Fg(rl)p 140 1782 V 21 w(p)r(oin)n(t)120 1844 y Fo(The)15 +b(o\013set)g(of)f(the)i(curren)o(t)f(cursor)g(p)q(osition)h(in)g +Fn(rl_line_buffer)d Fo(\(the)i Fj(p)q(oin)o(t)q Fo(\).)1736 +2007 y(V)l(ariable)-1899 b Fh(int)20 b Fg(rl)p 140 2007 V 21 +w(end)120 2070 y Fo(The)d(n)o(um)o(b)q(er)f(of)g(c)o(haracters)g(presen)o(t)g +(in)h Fn(rl_line_buffer)p Fo(.)k(When)c Fn(rl_point)e Fo(is)i(at)f(the)g(end) +120 2132 y(of)f(the)g(line,)i Fn(rl_point)d Fo(and)h Fn(rl_end)f +Fo(are)h(equal.)1736 2295 y(V)l(ariable)-1899 b Fh(int)20 b +Fg(rl)p 140 2295 V 21 w(mark)120 2357 y Fo(The)h(mark)e(\(sa)o(v)o(ed)h(p)q +(osition\))h(in)g(the)f(curren)o(t)h(line.)37 b(If)20 b(set,)h(the)g(mark)e +(and)i(p)q(oin)o(t)g(de\014ne)g(a)120 2420 y Fj(region)p Fo(.)1736 +2583 y(V)l(ariable)-1899 b Fh(int)20 b Fg(rl)p 140 2583 V 21 +w(done)120 2645 y Fo(Setting)13 b(this)h(to)f(a)f(non-zero)i(v)m(alue)g +(causes)f(Readline)j(to)c(return)h(the)h(curren)o(t)f(line)h(immediately)l(.) +p eop +%%Page: 19 21 +20 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(Readline)994 +b(19)1736 158 y(V)l(ariable)-1899 b Fh(int)20 b Fg(rl)p 140 +158 18 3 v 21 w(p)r(ending)p 361 158 V 20 w(input)120 221 y +Fo(Setting)15 b(this)f(to)g(a)g(v)m(alue)i(mak)o(es)d(it)i(the)f(next)h(k)o +(eystrok)o(e)e(read.)19 b(This)c(is)g(a)f(w)o(a)o(y)f(to)h(stu\013)g(a)g +(single)120 283 y(c)o(haracter)g(in)o(to)i(the)f(input)h(stream.)1736 +451 y(V)l(ariable)-1899 b Fh(char)20 b(*)f Fg(rl)p 211 451 +V 21 w(prompt)120 513 y Fo(The)c(prompt)e(Readline)k(uses.)j(This)15 +b(is)f(set)h(from)e(the)h(argumen)o(t)g(to)g Fn(readline)g(\(\))p +Fo(,)f(and)i(should)120 575 y(not)g(b)q(e)h(assigned)f(to)g(directly)l(.)1736 +743 y(V)l(ariable)-1899 b Fh(char)20 b(*)f Fg(rl)p 211 743 +V 21 w(terminal)p 443 743 V 21 w(name)120 806 y Fo(The)c(terminal)h(t)o(yp)q +(e,)f(used)h(for)f(initialization.)1736 974 y(V)l(ariable)-1899 +b Fh(char)20 b(*)f Fg(rl)p 211 974 V 21 w(readline)p 430 974 +V 22 w(name)120 1036 y Fo(This)f(v)m(ariable)h(is)f(set)f(to)g(a)g(unique)i +(name)f(b)o(y)f(eac)o(h)h(application)h(using)f(Readline.)29 +b(The)18 b(v)m(alue)120 1098 y(allo)o(ws)f(conditional)h(parsing)f(of)f(the)g +(inputrc)i(\014le)f(\(see)g(Section)g(1.3.2)e([Conditional)j(Init)f(Con-)120 +1160 y(structs],)d(page)h(7\).)1736 1328 y(V)l(ariable)-1899 +b Fh(FILE)20 b(*)f Fg(rl)p 211 1328 V 21 w(instream)120 1391 +y Fo(The)c(stdio)h(stream)e(from)h(whic)o(h)h(Readline)h(reads)e(input.)1736 +1559 y(V)l(ariable)-1899 b Fh(FILE)20 b(*)f Fg(rl)p 211 1559 +V 21 w(outstream)120 1621 y Fo(The)c(stdio)h(stream)e(to)h(whic)o(h)h +(Readline)h(p)q(erforms)e(output.)1736 1789 y(V)l(ariable)-1899 +b Fh(Function)20 b(*)g Fg(rl)p 316 1789 V 21 w(startup)p 520 +1789 V 20 w(ho)r(ok)120 1851 y Fo(If)13 b(non-zero,)h(this)f(is)h(the)f +(address)g(of)g(a)f(function)i(to)f(call)h(just)f(b)q(efore)g +Fn(readline)f Fo(prin)o(ts)h(the)g(\014rst)120 1913 y(prompt.)0 +2156 y Fm(2.3)33 b(Readline)16 b(Con)n(v)n(enience)g(F)-6 b(unctions)0 +2382 y Fi(2.3.1)30 b(Naming)15 b(a)g(F)-5 b(unction)62 2521 +y Fo(The)19 b(user)f(can)g(dynamically)i(c)o(hange)e(the)g(bindings)i(of)e(k) +o(eys)f(while)j(using)f(Readline.)30 b(This)19 b(is)g(done)f(b)o(y)0 +2583 y(represen)o(ting)f(the)g(function)h(with)f(a)g(descriptiv)o(e)h(name.) +25 b(The)17 b(user)g(is)g(able)h(to)e(t)o(yp)q(e)h(the)g(descriptiv)o(e)h +(name)0 2645 y(when)e(referring)f(to)g(the)g(function.)21 b(Th)o(us,)14 +b(in)j(an)e(init)h(\014le,)g(one)f(migh)o(t)g(\014nd)p eop +%%Page: 20 22 +21 bop 0 -83 a Fo(20)1449 b(GNU)15 b(Readline)i(Library)120 +158 y Fn(Meta-Rubout:)46 b(backward-kill-word)62 297 y Fo(This)21 +b(binds)f(the)g(k)o(eystrok)o(e)f Fn(META-RUBOUT)f Fo(to)h(the)h(function)g +Fj(descriptiv)o(ely)26 b Fo(named)20 b Fn(backward-kill-)0 +359 y(word)p Fo(.)j(Y)l(ou,)16 b(as)g(the)g(programmer,)f(should)i(bind)h +(the)e(functions)i(y)o(ou)d(write)i(to)e(descriptiv)o(e)j(names)e(as)g(w)o +(ell.)0 421 y(Readline)i(pro)o(vides)d(a)g(function)h(for)f(doing)g(that:) +1725 587 y(F)l(unction)-1899 b Fh(int)20 b Fg(rl)p 140 587 +18 3 v 21 w(add)p 253 587 V 20 w(defun)i Ff(\()p Fn(char)14 +b(*name,)g(Function)g(*function,)g(int)h(key)p Ff(\))120 649 +y Fo(Add)20 b Fj(name)i Fo(to)d(the)h(list)g(of)f(named)h(functions.)33 +b(Mak)o(e)19 b Fj(function)i Fo(b)q(e)f(the)f(function)i(that)d(gets)120 +711 y(called.)j(If)16 b Fj(k)o(ey)j Fo(is)d(not)e(-1,)h(then)h(bind)g(it)g +(to)e Fj(function)i Fo(using)g Fn(rl_bind_key)e(\(\))p Fo(.)62 +877 y(Using)i(this)g(function)g(alone)g(is)g(su\016cien)o(t)h(for)d(most)h +(applications.)22 b(It)16 b(is)g(the)f(recommended)i(w)o(a)o(y)d(to)h(add)0 +940 y(a)i(few)h(functions)g(to)f(the)h(default)g(functions)h(that)e(Readline) +j(has)d(built)i(in.)28 b(If)18 b(y)o(ou)g(need)g(to)f(do)h(something)0 +1002 y(other)c(than)h(adding)h(a)e(function)i(to)e(Readline,)j(y)o(ou)d(ma)o +(y)g(need)i(to)e(use)h(the)g(underlying)h(functions)g(describ)q(ed)0 +1064 y(b)q(elo)o(w.)0 1283 y Fi(2.3.2)30 b(Selecting)15 b(a)g(Keymap)62 +1422 y Fo(Key)k(bindings)i(tak)o(e)c(place)j(on)e(a)g Fj(k)o(eymap)p +Fo(.)30 b(The)18 b(k)o(eymap)h(is)g(the)f(asso)q(ciation)h(b)q(et)o(w)o(een)g +(the)f(k)o(eys)h(that)0 1484 y(the)g(user)g(t)o(yp)q(es)g(and)g(the)g +(functions)g(that)f(get)h(run.)30 b(Y)l(ou)20 b(can)e(mak)o(e)h(y)o(our)f(o)o +(wn)g(k)o(eymaps,)h(cop)o(y)g(existing)0 1546 y(k)o(eymaps,)14 +b(and)i(tell)g(Readline)i(whic)o(h)e(k)o(eymap)f(to)f(use.)1725 +1712 y(F)l(unction)-1899 b Fh(Keymap)20 b Fg(rl)p 218 1712 +V 21 w(mak)n(e)p 370 1712 V 20 w(bare)p 500 1712 V 20 w(k)n(eymap)j +Ff(\(\))120 1774 y Fo(Returns)14 b(a)f(new,)g(empt)o(y)g(k)o(eymap.)19 +b(The)14 b(space)f(for)g(the)h(k)o(eymap)f(is)g(allo)q(cated)i(with)e +Fn(malloc)i(\(\))p Fo(;)120 1836 y(y)o(ou)g(should)h Fn(free)f(\(\))g +Fo(it)g(when)h(y)o(ou)f(are)f(done.)1725 2002 y(F)l(unction)-1899 +b Fh(Keymap)20 b Fg(rl)p 218 2002 V 21 w(cop)n(y)p 353 2002 +V 21 w(k)n(eymap)j Ff(\()p Fn(Keymap)14 b(map)p Ff(\))120 2064 +y Fo(Return)i(a)f(new)g(k)o(eymap)g(whic)o(h)h(is)g(a)f(cop)o(y)g(of)g +Fj(map)p Fo(.)1725 2230 y(F)l(unction)-1899 b Fh(Keymap)20 +b Fg(rl)p 218 2230 V 21 w(mak)n(e)p 370 2230 V 20 w(k)n(eymap)j +Ff(\(\))120 2293 y Fo(Return)c(a)f(new)h(k)o(eymap)f(with)h(the)f(prin)o +(ting)i(c)o(haracters)d(b)q(ound)j(to)e(rl)p 1407 2293 14 2 +v 16 w(insert,)i(the)e(lo)o(w)o(ercase)120 2355 y(Meta)13 b(c)o(haracters)g +(b)q(ound)h(to)f(run)h(their)g(equiv)m(alen)o(ts,)i(and)d(the)h(Meta)f +(digits)h(b)q(ound)h(to)e(pro)q(duce)120 2417 y(n)o(umeric)j(argumen)o(ts.) +1725 2583 y(F)l(unction)-1899 b Fh(void)20 b Fg(rl)p 166 2583 +18 3 v 21 w(discard)p 366 2583 V 21 w(k)n(eymap)i Ff(\()p Fn(Keymap)14 +b(keymap)p Ff(\))120 2645 y Fo(F)l(ree)h(the)h(storage)d(asso)q(ciated)j +(with)f Fj(k)o(eymap)p Fo(.)p eop +%%Page: 21 23 +22 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(Readline)994 +b(21)62 158 y(Readline)20 b(has)d(sev)o(eral)h(in)o(ternal)g(k)o(eymaps.)26 +b(These)18 b(functions)g(allo)o(w)g(y)o(ou)f(to)g(c)o(hange)g(whic)o(h)h(k)o +(eymap)f(is)0 221 y(activ)o(e.)1725 383 y(F)l(unction)-1899 +b Fh(Keymap)20 b Fg(rl)p 218 383 18 3 v 21 w(get)p 316 383 +V 21 w(k)n(eymap)i Ff(\(\))120 445 y Fo(Returns)16 b(the)f(curren)o(tly)h +(activ)o(e)f(k)o(eymap.)1725 607 y(F)l(unction)-1899 b Fh(void)20 +b Fg(rl)p 166 607 V 21 w(set)p 258 607 V 21 w(k)n(eymap)i Ff(\()p +Fn(Keymap)14 b(keymap)p Ff(\))120 669 y Fo(Mak)o(es)g Fj(k)o(eymap)j +Fo(the)e(curren)o(tly)h(activ)o(e)f(k)o(eymap.)1725 831 y(F)l(unction)-1899 +b Fh(Keymap)20 b Fg(rl)p 218 831 V 21 w(get)p 316 831 V 21 +w(k)n(eymap)p 530 831 V 20 w(b)n(y)p 610 831 V 21 w(name)i +Ff(\()p Fn(char)14 b(*name)p Ff(\))120 893 y Fo(Return)19 b(the)g(k)o(eymap)f +(matc)o(hing)g Fj(name)p Fo(.)30 b Fj(name)21 b Fo(is)e(one)g(whic)o(h)g(w)o +(ould)g(b)q(e)g(supplied)i(in)e(a)f Fn(set)120 955 y(keymap)c +Fo(inputrc)j(line)f(\(see)g(Section)g(1.3)e([Readline)j(Init)f(File],)g(page) +f(4\).)0 1163 y Fi(2.3.3)30 b(Binding)15 b(Keys)62 1300 y Fo(Y)l(ou)h(asso)q +(ciate)f(k)o(eys)f(with)i(functions)g(through)e(the)i(k)o(eymap.)j(Readline)f +(has)c(sev)o(eral)i(in)o(ternal)g(k)o(eymaps:)0 1362 y Fn +(emacs_standard_keymap)p Fo(,)i Fn(emacs_meta_keymap)p Fo(,)g +Fn(emacs_ctlx_keymap)p Fo(,)h Fn(vi_movement_keymap)p Fo(,)f(and)0 +1425 y Fn(vi_insertion_keymap)p Fo(.)h Fn(emacs_standard_keymap)13 +b Fo(is)k(the)f(default,)g(and)g(the)g(examples)h(in)f(this)h(man)o(ual)0 +1487 y(assume)e(that.)62 1624 y(These)h(functions)g(manage)e(k)o(ey)i +(bindings.)1725 1786 y(F)l(unction)-1899 b Fh(int)20 b Fg(rl)p +140 1786 V 21 w(bind)p 272 1786 V 21 w(k)n(ey)k Ff(\()p Fn(int)14 +b(key,)h(Function)f(*function)p Ff(\))120 1848 y Fo(Binds)i +Fj(k)o(ey)j Fo(to)14 b Fj(function)i Fo(in)g(the)f(curren)o(tly)h(activ)o(e)f +(k)o(eymap.)k(Returns)d(non-zero)f(in)h(the)f(case)g(of)120 +1910 y(an)g(in)o(v)m(alid)j Fj(k)o(ey)p Fo(.)1725 2072 y(F)l(unction)-1899 +b Fh(int)19 b Fg(rl)p 139 2072 V 21 w(bind)p 271 2072 V 21 +w(k)n(ey)p 376 2072 V 21 w(in)p 444 2072 V 22 w(map)i Ff(\()p +Fn(int)14 b(key,)h(Function)f(*function,)g(Keymap)g(map)p Ff(\))120 +2134 y Fo(Bind)i Fj(k)o(ey)j Fo(to)c Fj(function)h Fo(in)g +Fj(map)p Fo(.)k(Returns)15 b(non-zero)h(in)g(the)f(case)g(of)g(an)g(in)o(v)m +(alid)j Fj(k)o(ey)p Fo(.)1725 2296 y(F)l(unction)-1899 b Fh(int)20 +b Fg(rl)p 140 2296 V 21 w(un)n(bind)p 334 2296 V 21 w(k)n(ey)k +Ff(\()p Fn(int)14 b(key)p Ff(\))120 2359 y Fo(Bind)h Fj(k)o(ey)i +Fo(to)c(the)h(n)o(ull)h(function)f(in)g(the)g(curren)o(tly)g(activ)o(e)g(k)o +(eymap.)19 b(Returns)14 b(non-zero)g(in)g(case)120 2421 y(of)h(error.)1725 +2583 y(F)l(unction)-1899 b Fh(int)20 b Fg(rl)p 140 2583 V 21 +w(un)n(bind)p 334 2583 V 21 w(k)n(ey)p 439 2583 V 21 w(in)p +507 2583 V 22 w(map)h Ff(\()p Fn(int)14 b(key,)h(Keymap)f(map)p +Ff(\))120 2645 y Fo(Bind)i Fj(k)o(ey)j Fo(to)c(the)g(n)o(ull)i(function)f(in) +g Fj(map)p Fo(.)k(Returns)15 b(non-zero)h(in)g(case)f(of)g(error.)p +eop +%%Page: 22 24 +23 bop 0 -83 a Fo(22)1449 b(GNU)15 b(Readline)i(Library)1725 +158 y(F)l(unction)-1899 b Fh(int)20 b Fg(rl)p 140 158 18 3 +v 21 w(generic)p 338 158 V 21 w(bind)j Ff(\()p Fn(int)15 b(type,)f(char)h +(*keyseq,)f(char)h(*data,)f(Keymap)208 221 y(map)p Ff(\))120 +283 y Fo(Bind)j(the)f(k)o(ey)g(sequence)h(represen)o(ted)f(b)o(y)g(the)g +(string)g Fj(k)o(eyseq)g Fo(to)g(the)f(arbitrary)h(p)q(oin)o(ter)g +Fj(data)p Fo(.)120 345 y Fj(t)o(yp)q(e)j Fo(sa)o(ys)c(what)g(kind)i(of)f +(data)f(is)i(p)q(oin)o(ted)g(to)e(b)o(y)h Fj(data)p Fo(;)f(this)i(can)f(b)q +(e)g(a)g(function)h(\()p Fn(ISFUNC)p Fo(\),)d(a)120 407 y(macro)i(\()p +Fn(ISMACR)p Fo(\),)f(or)i(a)f(k)o(eymap)g(\()p Fn(ISKMAP)p +Fo(\).)23 b(This)18 b(mak)o(es)e(new)h(k)o(eymaps)f(as)h(necessary)l(.)25 +b(The)120 470 y(initial)17 b(k)o(eymap)e(in)h(whic)o(h)g(to)f(do)g(bindings)i +(is)f Fj(map)p Fo(.)1725 656 y(F)l(unction)-1899 b Fh(int)20 +b Fg(rl)p 140 656 V 21 w(parse)p 294 656 V 19 w(and)p 405 656 +V 21 w(bind)j Ff(\()p Fn(char)14 b(*line)p Ff(\))120 718 y +Fo(P)o(arse)i Fj(line)21 b Fo(as)16 b(if)h(it)g(had)f(b)q(een)i(read)f(from)e +(the)i Fn(inputrc)f Fo(\014le)h(and)g(p)q(erform)f(an)o(y)h(k)o(ey)f +(bindings)120 780 y(and)f(v)m(ariable)i(assignmen)o(ts)e(found)h(\(see)f +(Section)h(1.3)e([Readline)j(Init)f(File],)g(page)f(4\).)0 +1061 y Fi(2.3.4)30 b(Asso)r(ciating)15 b(F)-5 b(unction)15 +b(Names)g(and)g(Bindings)62 1206 y Fo(These)22 b(functions)g(allo)o(w)g(y)o +(ou)f(to)f(\014nd)i(out)f(what)g(k)o(eys)g(in)o(v)o(ok)o(e)h(named)f +(functions)h(and)g(the)f(functions)0 1269 y(in)o(v)o(ok)o(ed)15 +b(b)o(y)h(a)e(particular)i(k)o(ey)f(sequence.)1725 1455 y(F)l(unction)-1899 +b Fh(Function)20 b(*)g Fg(rl)p 316 1455 V 21 w(named)p 504 +1455 V 19 w(function)j Ff(\()p Fn(char)14 b(*name)p Ff(\))120 +1517 y Fo(Return)i(the)f(function)h(with)g(name)f Fj(name)p +Fo(.)1725 1703 y(F)l(unction)-1899 b Fh(Function)20 b(*)g Fg(rl)p +316 1703 V 21 w(function)p 542 1703 V 21 w(of)p 610 1703 V +19 w(k)n(eyseq)k Ff(\()p Fn(char)15 b(*keyseq,)f(Keymap)g(map,)h(int)208 +1766 y(*type)p Ff(\))120 1828 y Fo(Return)i(the)f(function)h(in)o(v)o(ok)o +(ed)g(b)o(y)f Fj(k)o(eyseq)i Fo(in)f(k)o(eymap)f Fj(map)p Fo(.)23 +b(If)16 b Fj(map)i Fo(is)f(NULL,)g(the)f(curren)o(t)120 1890 +y(k)o(eymap)g(is)i(used.)25 b(If)17 b Fj(t)o(yp)q(e)i Fo(is)e(not)g(NULL,)g +(the)g(t)o(yp)q(e)g(of)f(the)h(ob)s(ject)f(is)h(returned)g(in)h(it)f(\(one)f +(of)120 1952 y Fn(ISFUNC)p Fo(,)e Fn(ISKMAP)p Fo(,)g(or)h Fn(ISMACR)p +Fo(\).)1725 2139 y(F)l(unction)-1899 b Fh(char)20 b(**)f Fg(rl)p +237 2139 V 21 w(in)n(v)n(oking)p 466 2139 V 23 w(k)n(eyseqs)k +Ff(\()p Fn(Function)14 b(*function)p Ff(\))120 2201 y Fo(Return)19 +b(an)e(arra)o(y)g(of)h(strings)f(represen)o(ting)i(the)f(k)o(ey)g(sequences)h +(used)f(to)f(in)o(v)o(ok)o(e)h Fj(function)h Fo(in)120 2263 +y(the)c(curren)o(t)g(k)o(eymap.)1725 2449 y(F)l(unction)-1899 +b Fh(char)20 b(**)f Fg(rl)p 237 2449 V 21 w(in)n(v)n(oking)p +466 2449 V 23 w(k)n(eyseqs)p 675 2449 V 21 w(in)p 743 2449 +V 22 w(map)i Ff(\()p Fn(Function)14 b(*function,)f(Keymap)208 +2512 y(map)p Ff(\))120 2574 y Fo(Return)19 b(an)e(arra)o(y)g(of)h(strings)f +(represen)o(ting)i(the)f(k)o(ey)g(sequences)h(used)f(to)f(in)o(v)o(ok)o(e)h +Fj(function)h Fo(in)120 2636 y(the)c(k)o(eymap)g Fj(map)p Fo(.)p +eop +%%Page: 23 25 +24 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(Readline)994 +b(23)0 158 y Fi(2.3.5)30 b(Allo)n(wing)16 b(Undoing)62 297 +y Fo(Supp)q(orting)f(the)f(undo)g(command)g(is)g(a)g(painless)h(thing,)f(and) +g(mak)o(es)f(y)o(our)h(functions)g(m)o(uc)o(h)g(more)f(useful.)0 +359 y(It)i(is)g(certainly)g(easy)f(to)g(try)g(something)h(if)g(y)o(ou)f(kno)o +(w)g(y)o(ou)g(can)h(undo)g(it.)20 b(I)15 b(could)g(use)g(an)f(undo)h +(function)h(for)0 422 y(the)f(sto)q(c)o(k)g(mark)o(et.)62 561 +y(If)h(y)o(our)f(function)i(simply)g(inserts)f(text)f(once,)h(or)f(deletes)h +(text)f(once,)h(and)g(uses)g Fn(rl_insert_text)d(\(\))i Fo(or)0 +623 y Fn(rl_delete_text)e(\(\))i Fo(to)g(do)g(it,)g(then)g(undoing)i(is)e +(already)h(done)f(for)g(y)o(ou)g(automatically)l(.)62 762 y(If)h(y)o(ou)f(do) +g(m)o(ultiple)i(insertions)f(or)f(m)o(ultiple)i(deletions,)f(or)f(an)o(y)g +(com)o(bination)h(of)f(these)g(op)q(erations,)g(y)o(ou)0 824 +y(should)j(group)e(them)g(together)g(in)o(to)g(one)h(op)q(eration.)24 +b(This)17 b(is)g(done)g(with)g Fn(rl_begin_undo_group)c(\(\))j +Fo(and)0 886 y Fn(rl_end_undo_group)d(\(\))p Fo(.)62 1025 y(The)j(t)o(yp)q +(es)f(of)g(ev)o(en)o(ts)g(that)f(can)h(b)q(e)h(undone)g(are:)120 +1151 y Fn(enum)23 b(undo_code)g({)h(UNDO_DELETE,)e(UNDO_INSERT,)g +(UNDO_BEGIN,)g(UNDO_END)h(};)62 1290 y Fo(Notice)c(that)e Fn(UNDO_DELETE)f +Fo(means)i(to)f(insert)i(some)e(text,)h(and)g Fn(UNDO_INSERT)e +Fo(means)i(to)f(delete)i(some)0 1353 y(text.)37 b(That)21 b(is,)i(the)e(undo) +h(co)q(de)f(tells)i(undo)e(what)g(to)f(undo,)j(not)e(ho)o(w)g(to)f(undo)i +(it.)38 b Fn(UNDO_BEGIN)20 b Fo(and)0 1415 y Fn(UNDO_END)14 +b Fo(are)h(tags)f(added)i(b)o(y)f Fn(rl_begin_undo_group)e(\(\))i +Fo(and)g Fn(rl_end_undo_group)e(\(\))p Fo(.)1725 1582 y(F)l(unction)-1899 +b Fh(int)20 b Fg(rl)p 140 1582 18 3 v 21 w(b)r(egin)p 297 1582 +V 20 w(undo)p 442 1582 V 20 w(group)h Ff(\(\))120 1645 y Fo(Begins)e(sa)o +(ving)e(undo)i(information)f(in)g(a)g(group)f(construct.)27 +b(The)18 b(undo)h(information)f(usually)120 1707 y(comes)j(from)f(calls)h(to) +g Fn(rl_insert_text)13 b(\(\))20 b Fo(and)h Fn(rl_delete_text)13 +b(\(\))p Fo(,)22 b(but)f(could)g(b)q(e)h(the)120 1769 y(result)16 +b(of)e(calls)j(to)d Fn(rl_add_undo)g(\(\))p Fo(.)1725 1937 +y(F)l(unction)-1899 b Fh(int)20 b Fg(rl)p 140 1937 V 21 w(end)p +251 1937 V 20 w(undo)p 396 1937 V 20 w(group)h Ff(\(\))120 +1999 y Fo(Closes)d(the)f(curren)o(t)g(undo)h(group)f(started)g(with)h +Fn(rl_begin_undo_group)12 b(\(\))p Fo(.)26 b(There)18 b(should)120 +2061 y(b)q(e)e(one)f(call)i(to)d Fn(rl_end_undo_group)f(\(\))i +Fo(for)f(eac)o(h)i(call)g(to)f Fn(rl_begin_undo_group)d(\(\))p +Fo(.)1725 2229 y(F)l(unction)-1899 b Fh(void)20 b Fg(rl)p 166 +2229 V 21 w(add)p 279 2229 V 20 w(undo)i Ff(\()p Fn(enum)14 +b(undo_code)g(what,)g(int)h(start,)g(int)f(end,)h(char)208 +2291 y(*text)p Ff(\))120 2353 y Fo(Remem)o(b)q(er)20 b(ho)o(w)e(to)h(undo)g +(an)g(ev)o(en)o(t)g(\(according)g(to)g Fj(what)q Fo(\).)30 +b(The)19 b(a\013ected)g(text)f(runs)i(from)120 2415 y Fj(start)15 +b Fo(to)g Fj(end)p Fo(,)g(and)g(encompasses)h Fj(text)p Fo(.)1725 +2583 y(F)l(unction)-1899 b Fh(void)20 b Fg(free)p 221 2583 +V 20 w(undo)p 366 2583 V 20 w(list)k Ff(\(\))120 2645 y Fo(F)l(ree)15 +b(the)h(existing)g(undo)f(list.)p eop +%%Page: 24 26 +25 bop 0 -83 a Fo(24)1449 b(GNU)15 b(Readline)i(Library)1725 +158 y(F)l(unction)-1899 b Fh(int)20 b Fg(rl)p 140 158 18 3 +v 21 w(do)p 222 158 V 20 w(undo)i Ff(\(\))120 221 y Fo(Undo)14 +b(the)f(\014rst)g(thing)h(on)g(the)f(undo)h(list.)20 b(Returns)14 +b Fn(0)f Fo(if)h(there)g(w)o(as)e(nothing)i(to)f(undo,)h(non-zero)120 +283 y(if)i(something)f(w)o(as)f(undone.)62 454 y(Finally)l(,)j(if)f(y)o(ou)f +(neither)i(insert)f(nor)f(delete)i(text,)d(but)i(directly)h(mo)q(dify)f(the)f +(existing)i(text)e(\(e.g.,)f(c)o(hange)0 516 y(its)g(case\),)f(call)i +Fn(rl_modifying)e(\(\))g Fo(once,)h(just)f(b)q(efore)h(y)o(ou)f(mo)q(dify)h +(the)g(text.)19 b(Y)l(ou)14 b(m)o(ust)f(supply)h(the)g(indices)0 +578 y(of)h(the)g(text)g(range)g(that)f(y)o(ou)h(are)g(going)g(to)g(mo)q(dify) +l(.)1725 749 y(F)l(unction)-1899 b Fh(int)20 b Fg(rl)p 140 +749 V 21 w(mo)r(difying)h Ff(\()p Fn(int)15 b(start,)f(int)h(end)p +Ff(\))120 811 y Fo(T)l(ell)e(Readline)g(to)e(sa)o(v)o(e)f(the)i(text)f(b)q +(et)o(w)o(een)g Fj(start)g Fo(and)h Fj(end)h Fo(as)e(a)g(single)i(undo)e +(unit.)20 b(It)11 b(is)h(assumed)120 873 y(that)i(y)o(ou)h(will)i(subsequen)o +(tly)g(mo)q(dify)e(that)g(text.)0 1107 y Fi(2.3.6)30 b(Redispla)n(y)1725 +1278 y Fo(F)l(unction)-1899 b Fh(int)20 b Fg(rl)p 140 1278 +V 21 w(redispla)n(y)k Ff(\(\))120 1340 y Fo(Change)d(what's)g(displa)o(y)o +(ed)h(on)g(the)f(screen)h(to)f(re\015ect)h(the)f(curren)o(t)g(con)o(ten)o(ts) +g(of)g Fn(rl_line_)120 1402 y(buffer)p Fo(.)1725 1573 y(F)l(unction)-1899 +b Fh(int)20 b Fg(rl)p 140 1573 V 21 w(forced)p 315 1573 V 20 +w(up)r(date)p 509 1573 V 20 w(displa)n(y)k Ff(\(\))120 1635 +y Fo(F)l(orce)12 b(the)g(line)h(to)f(b)q(e)g(up)q(dated)h(and)f(redispla)o(y) +o(ed,)i(whether)e(or)f(not)h(Readline)i(thinks)e(the)g(screen)120 +1697 y(displa)o(y)k(is)g(correct.)1725 1868 y(F)l(unction)-1899 +b Fh(int)20 b Fg(rl)p 140 1868 V 21 w(on)p 222 1868 V 20 w(new)p +341 1868 V 21 w(line)k Ff(\(\))120 1930 y Fo(T)l(ell)c(the)f(up)q(date)g +(routines)g(that)f(w)o(e)g(ha)o(v)o(e)g(mo)o(v)o(ed)g(on)o(to)g(a)g(new)h +(\(empt)o(y\))e(line,)k(usually)f(after)120 1992 y(ouputting)c(a)e(newline.) +1725 2163 y(F)l(unction)-1899 b Fh(int)20 b Fg(rl)p 140 2163 +V 21 w(reset)p 282 2163 V 20 w(line)p 390 2163 V 23 w(state)j +Ff(\(\))120 2225 y Fo(Reset)14 b(the)f(displa)o(y)h(state)f(to)f(a)h(clean)h +(state)f(and)g(redispla)o(y)i(the)e(curren)o(t)g(line)i(starting)e(on)g(a)g +(new)120 2288 y(line.)1725 2458 y(F)l(unction)-1899 b Fh(int)20 +b Fg(rl)p 140 2458 V 21 w(message)g Ff(\()p Fn(va_alist)p Ff(\))120 +2521 y Fo(The)f(argumen)o(ts)e(are)h(a)g(string)g(as)g(w)o(ould)h(b)q(e)g +(supplied)i(to)d Fn(printf)p Fo(.)28 b(The)19 b(resulting)g(string)f(is)120 +2583 y(displa)o(y)o(ed)h(in)f(the)g Fj(ec)o(ho)f(area)p Fo(.)27 +b(The)18 b(ec)o(ho)f(area)g(is)h(also)g(used)g(to)f(displa)o(y)h(n)o(umeric)h +(argumen)o(ts)120 2645 y(and)c(searc)o(h)g(strings.)p eop +%%Page: 25 27 +26 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(Readline)994 +b(25)1725 158 y(F)l(unction)-1899 b Fh(int)20 b Fg(rl)p 140 +158 18 3 v 21 w(clear)p 279 158 V 21 w(message)h Ff(\(\))120 +221 y Fo(Clear)15 b(the)h(message)e(in)i(the)g(ec)o(ho)f(area.)0 +423 y Fi(2.3.7)30 b(Mo)r(difying)15 b(T)-5 b(ext)1725 582 y +Fo(F)l(unction)-1899 b Fh(int)20 b Fg(rl)p 140 582 V 21 w(insert)p +303 582 V 21 w(text)k Ff(\()p Fn(char)14 b(*text)p Ff(\))120 +644 y Fo(Insert)h Fj(text)h Fo(in)o(to)f(the)h(line)g(at)f(the)g(curren)o(t)g +(cursor)g(p)q(osition.)1725 803 y(F)l(unction)-1899 b Fh(int)20 +b Fg(rl)p 140 803 V 21 w(delete)p 308 803 V 22 w(text)k Ff(\()p +Fn(int)14 b(start,)h(int)f(end)p Ff(\))120 865 y Fo(Delete)i(the)f(text)g(b)q +(et)o(w)o(een)g Fj(start)g Fo(and)h Fj(end)h Fo(in)f(the)g(curren)o(t)f +(line.)1725 1025 y(F)l(unction)-1899 b Fh(char)20 b(*)f Fg(rl)p +211 1025 V 21 w(cop)n(y)p 346 1025 V 21 w(text)24 b Ff(\()p +Fn(int)14 b(start,)h(int)g(end)p Ff(\))120 1087 y Fo(Return)h(a)f(cop)o(y)g +(of)g(the)g(text)f(b)q(et)o(w)o(een)i Fj(start)f Fo(and)g Fj(end)j +Fo(in)e(the)f(curren)o(t)g(line.)1725 1246 y(F)l(unction)-1899 +b Fh(int)20 b Fg(rl)p 140 1246 V 21 w(kill)p 236 1246 V 23 +w(text)k Ff(\()p Fn(int)14 b(start,)h(int)g(end)p Ff(\))120 +1308 y Fo(Cop)o(y)k(the)g(text)f(b)q(et)o(w)o(een)i Fj(start)e +Fo(and)i Fj(end)h Fo(in)f(the)f(curren)o(t)g(line)i(to)d(the)h(kill)i(ring,)f +(app)q(ending)120 1371 y(or)e(prep)q(ending)j(to)d(the)h(last)f(kill)j(if)e +(the)g(last)f(command)h(w)o(as)e(a)i(kill)h(command.)30 b(The)19 +b(text)f(is)120 1433 y(deleted.)j(If)13 b Fj(start)g Fo(is)h(less)f(than)h +Fj(end)p Fo(,)f(the)h(text)e(is)i(app)q(ended,)h(otherwise)e(prep)q(ended.)21 +b(If)14 b(the)f(last)120 1495 y(command)i(w)o(as)f(not)h(a)g(kill,)i(a)e(new) +g(kill)i(ring)f(slot)f(is)g(used.)0 1697 y Fi(2.3.8)30 b(Utilit)n(y)16 +b(F)-5 b(unctions)1725 1856 y Fo(F)l(unction)-1899 b Fh(int)20 +b Fg(rl)p 140 1856 V 21 w(reset)p 282 1856 V 20 w(terminal)j +Ff(\()p Fn(char)15 b(*terminal_name)p Ff(\))120 1919 y Fo(Reinitializ)q(e)f +(Readline's)e(idea)g(of)e(the)h(terminal)h(settings)f(using)g +Fj(terminal)p 1404 1919 14 2 v 17 w(name)j Fo(as)c(the)h(terminal)120 +1981 y(t)o(yp)q(e)k(\(e.g.,)f Fn(vt100)p Fo(\).)1725 2140 y(F)l(unction)-1899 +b Fh(int)20 b Fg(alphab)r(etic)k Ff(\()p Fn(int)14 b(c)p Ff(\))120 +2202 y Fo(Return)i(1)f(if)g Fj(c)j Fo(is)e(an)f(alphab)q(etic)i(c)o +(haracter.)1725 2361 y(F)l(unction)-1899 b Fh(int)20 b Fg(n)n(umeric)i +Ff(\()p Fn(int)15 b(c)p Ff(\))120 2424 y Fo(Return)h(1)f(if)g +Fj(c)j Fo(is)e(a)f(n)o(umeric)h(c)o(haracter.)1725 2583 y(F)l(unction)-1899 +b Fh(int)20 b Fg(ding)i Ff(\(\))120 2645 y Fo(Ring)16 b(the)f(terminal)h(b)q +(ell,)h(ob)q(eying)f(the)g(setting)f(of)g Fn(bell-style)p Fo(.)p +eop +%%Page: 26 28 +27 bop 0 -83 a Fo(26)1449 b(GNU)15 b(Readline)i(Library)62 +158 y(The)f(follo)o(wing)g(are)f(implemen)o(ted)h(as)f(macros,)f(de\014ned)j +(in)f Fn(chartypes.h)p Fo(.)1725 319 y(F)l(unction)-1899 b +Fh(int)20 b Fg(upp)r(ercase)p 351 319 18 3 v 19 w(p)j Ff(\()p +Fn(int)14 b(c)p Ff(\))120 381 y Fo(Return)i(1)f(if)g Fj(c)j +Fo(is)e(an)f(upp)q(ercase)i(alphab)q(etic)f(c)o(haracter.)1725 +541 y(F)l(unction)-1899 b Fh(int)20 b Fg(lo)n(w)n(ercase)p +334 541 V 22 w(p)i Ff(\()p Fn(int)15 b(c)p Ff(\))120 604 y +Fo(Return)h(1)f(if)g Fj(c)j Fo(is)e(a)f(lo)o(w)o(ercase)g(alphab)q(etic)i(c)o +(haracter.)1725 764 y(F)l(unction)-1899 b Fh(int)20 b Fg(digit)p +214 764 V 22 w(p)i Ff(\()p Fn(int)15 b(c)p Ff(\))120 826 y +Fo(Return)h(1)f(if)g Fj(c)j Fo(is)e(a)f(n)o(umeric)h(c)o(haracter.)1725 +987 y(F)l(unction)-1899 b Fh(int)20 b Fg(to)p 152 987 V 20 +w(upp)r(er)i Ff(\()p Fn(int)14 b(c)p Ff(\))120 1049 y Fo(If)h +Fj(c)i Fo(is)f(a)e(lo)o(w)o(ercase)g(alphab)q(etic)j(c)o(haracter,)c(return)i +(the)g(corresp)q(onding)g(upp)q(ercase)h(c)o(haracter.)1725 +1209 y(F)l(unction)-1899 b Fh(int)20 b Fg(to)p 152 1209 V 20 +w(lo)n(w)n(er)k Ff(\()p Fn(int)15 b(c)p Ff(\))120 1272 y Fo(If)e +Fj(c)i Fo(is)e(an)f(upp)q(ercase)h(alphab)q(etic)h(c)o(haracter,)e(return)g +(the)h(corresp)q(onding)g(lo)o(w)o(ercase)f(c)o(haracter.)1725 +1432 y(F)l(unction)-1899 b Fh(int)20 b Fg(digit)p 214 1432 +V 22 w(v)m(alue)j Ff(\()p Fn(int)15 b(c)p Ff(\))120 1494 y +Fo(If)g Fj(c)k Fo(is)c(a)g(n)o(um)o(b)q(er,)g(return)g(the)h(v)m(alue)g(it)g +(represen)o(ts.)0 1699 y Fi(2.3.9)30 b(An)15 b(Example)62 1836 +y Fo(Here)e(is)g(a)f(function)h(whic)o(h)g(c)o(hanges)g(lo)o(w)o(ercase)f(c)o +(haracters)f(to)h(their)h(upp)q(ercase)g(equiv)m(alen)o(ts,)h(and)f(upp)q +(er-)0 1898 y(case)j(c)o(haracters)g(to)g(lo)o(w)o(ercase.)23 +b(If)16 b(this)h(function)g(w)o(as)f(b)q(ound)h(to)f(`)p Fn(M-c)p +Fo(',)f(then)h(t)o(yping)h(`)p Fn(M-c)p Fo(')e(w)o(ould)i(c)o(hange)0 +1960 y(the)g(case)f(of)g(the)h(c)o(haracter)f(under)h(p)q(oin)o(t.)25 +b(T)o(yping)17 b(`)p Fn(M-1)d(0)h(M-c)p Fo(')h(w)o(ould)h(c)o(hange)f(the)h +(case)f(of)h(the)f(follo)o(wing)0 2022 y(10)f(c)o(haracters,)f(lea)o(ving)i +(the)f(cursor)g(on)g(the)g(last)g(c)o(haracter)g(c)o(hanged.)120 +2147 y Fn(/*)24 b(Invert)f(the)g(case)g(of)h(the)f(COUNT)h(following)e +(characters.)h(*/)120 2197 y(int)120 2247 y(invert_case_line)f(\(count,)h +(key\))239 2296 y(int)h(count,)f(key;)120 2346 y({)168 2396 +y(register)f(int)i(start,)f(end,)g(i;)168 2496 y(start)g(=)h(rl_point;)168 +2595 y(if)f(\(rl_point)g(>=)h(rl_end\))215 2645 y(return)f(\(0\);)p +eop +%%Page: 27 29 +28 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(Readline)994 +b(27)168 208 y Fn(if)23 b(\(count)g(<)h(0\))215 258 y({)263 +308 y(direction)f(=)h(-1;)263 358 y(count)f(=)h(-count;)215 +407 y(})168 457 y(else)215 507 y(direction)f(=)h(1;)168 607 +y(/*)f(Find)h(the)f(end)h(of)f(the)h(range)f(to)g(modify.)g(*/)168 +656 y(end)g(=)h(start)f(+)h(\(count)f(*)h(direction\);)168 +756 y(/*)f(Force)g(it)h(to)g(be)f(within)g(range.)g(*/)168 +806 y(if)g(\(end)h(>)f(rl_end\))215 856 y(end)h(=)g(rl_end;)168 +906 y(else)f(if)h(\(end)f(<)h(0\))215 955 y(end)g(=)g(0;)168 +1055 y(if)f(\(start)g(==)h(end\))215 1105 y(return)f(\(0\);)168 +1204 y(if)g(\(start)g(>)h(end\))215 1254 y({)263 1304 y(int)g(temp)f(=)h +(start;)263 1354 y(start)f(=)h(end;)263 1404 y(end)g(=)f(temp;)215 +1453 y(})168 1553 y(/*)g(Tell)h(readline)e(that)i(we)f(are)h(modifying)e(the) +i(line,)f(so)h(it)f(will)h(save)239 1603 y(the)g(undo)f(information.)f(*/)168 +1653 y(rl_modifying)g(\(start,)h(end\);)168 1752 y(for)g(\(i)h(=)f(start;)h +(i)f(!=)h(end;)f(i++\))215 1802 y({)263 1852 y(if)h(\(uppercase_p)e +(\(rl_line_buffer[i]\)\))311 1902 y(rl_line_buffer[i])f(=)j(to_lower)f +(\(rl_line_buffer[i]\);)263 1952 y(else)g(if)h(\(lowercase_p)e +(\(rl_line_buffer[i]\)\))311 2001 y(rl_line_buffer[i])f(=)j(to_upper)f +(\(rl_line_buffer[i]\);)215 2051 y(})168 2101 y(/*)g(Move)h(point)f(to)g(on)h +(top)f(of)h(the)f(last)h(character)e(changed.)h(*/)168 2151 +y(rl_point)f(=)i(\(direction)f(==)g(1\))h(?)g(end)f(-)h(1)g(:)f(start;)168 +2201 y(return)g(\(0\);)120 2250 y(})p eop +%%Page: 28 30 +29 bop 0 -83 a Fo(28)1449 b(GNU)15 b(Readline)i(Library)0 158 +y Fm(2.4)33 b(Custom)14 b(Completers)62 306 y Fo(T)o(ypically)l(,)g(a)c +(program)g(that)h(reads)g(commands)g(from)f(the)h(user)h(has)e(a)h(w)o(a)o(y) +f(of)h(disam)o(biguating)h(commands)0 368 y(and)k(data.)k(If)c(y)o(our)f +(program)g(is)h(one)g(of)f(these,)h(then)g(it)g(can)g(pro)o(vide)g +(completion)g(for)g(commands,)f(data,)f(or)0 430 y(b)q(oth.)28 +b(The)18 b(follo)o(wing)h(sections)f(describ)q(e)h(ho)o(w)f(y)o(our)f +(program)g(and)h(Readline)i(co)q(op)q(erate)e(to)f(pro)o(vide)i(this)0 +493 y(service.)0 795 y Fi(2.4.1)30 b(Ho)n(w)15 b(Completing)g(W)-5 +b(orks)62 942 y Fo(In)16 b(order)f(to)g(complete)h(some)f(text,)f(the)h(full) +i(list)f(of)f(p)q(ossible)i(completions)f(m)o(ust)f(b)q(e)h(a)o(v)m(ailable.) +21 b(That)15 b(is,)0 1004 y(it)k(is)f(not)g(p)q(ossible)i(to)e(accurately)h +(expand)g(a)f(partial)h(w)o(ord)e(without)i(kno)o(wing)f(all)h(of)f(the)h(p)q +(ossible)h(w)o(ords)0 1067 y(whic)o(h)c(mak)o(e)f(sense)h(in)g(that)e(con)o +(text.)20 b(The)15 b(Readline)j(library)e(pro)o(vides)f(the)h(user)f(in)o +(terface)h(to)e(completion,)0 1129 y(and)h(t)o(w)o(o)f(of)h(the)h(most)e +(common)h(completion)h(functions:)21 b(\014lename)c(and)e(username.)20 +b(F)l(or)15 b(completing)h(other)0 1191 y(t)o(yp)q(es)h(of)f(text,)g(y)o(ou)h +(m)o(ust)f(write)h(y)o(our)f(o)o(wn)g(completion)i(function.)25 +b(This)18 b(section)f(describ)q(es)h(exactly)g(what)0 1253 +y(suc)o(h)e(functions)f(m)o(ust)g(do,)g(and)g(pro)o(vides)h(an)f(example.)62 +1401 y(There)h(are)f(three)g(ma)s(jor)f(functions)i(used)f(to)g(p)q(erform)g +(completion:)25 1548 y(1.)29 b(The)15 b(user-in)o(terface)g(function)g +Fn(rl_complete)e(\(\))p Fo(.)20 b(This)15 b(function)g(is)g(called)h(with)e +(the)h(same)f(argumen)o(ts)90 1611 y(as)j(other)g(Readline)j(functions)f(in)o +(tended)g(for)e(in)o(teractiv)o(e)h(use:)25 b Fj(coun)o(t)18 +b Fo(and)g Fj(in)o(v)o(oking)p 1633 1611 14 2 v 17 w(k)o(ey)p +Fo(.)27 b(It)18 b(isolates)90 1673 y(the)j(w)o(ord)g(to)f(b)q(e)i(completed)h +(and)e(calls)h Fn(completion_matches)13 b(\(\))21 b Fo(to)f(generate)h(a)g +(list)h(of)f(p)q(ossible)90 1735 y(completions.)h(It)16 b(then)g(either)h +(lists)f(the)g(p)q(ossible)h(completions,)g(inserts)f(the)g(p)q(ossible)h +(completions,)f(or)90 1797 y(actually)g(p)q(erforms)f(the)g(completion,)h +(dep)q(ending)i(on)d(whic)o(h)h(b)q(eha)o(vior)f(is)h(desired.)25 +1883 y(2.)29 b(The)18 b(in)o(ternal)h(function)g Fn(completion_matches)13 +b(\(\))18 b Fo(uses)g(y)o(our)f Fj(generator)k Fo(function)e(to)e(generate)h +(the)90 1945 y(list)h(of)e(p)q(ossible)j(matc)o(hes,)e(and)g(then)g(returns)g +(the)g(arra)o(y)f(of)h(these)g(matc)o(hes.)28 b(Y)l(ou)18 b(should)h(place)g +(the)90 2007 y(address)c(of)g(y)o(our)g(generator)f(function)i(in)g +Fn(rl_completion_entry_functi)o(on)p Fo(.)25 2092 y(3.)29 b(The)16 +b(generator)g(function)h(is)f(called)i(rep)q(eatedly)g(from)d +Fn(completion_matches)e(\(\))p Fo(,)i(returning)i(a)f(string)90 +2155 y(eac)o(h)j(time.)31 b(The)19 b(argumen)o(ts)f(to)g(the)h(generator)e +(function)j(are)e Fj(text)i Fo(and)f Fj(state)p Fo(.)29 b Fj(text)19 +b Fo(is)h(the)f(partial)90 2217 y(w)o(ord)13 b(to)g(b)q(e)h(completed.)21 +b Fj(state)15 b Fo(is)f(zero)g(the)g(\014rst)f(time)h(the)g(function)g(is)g +(called,)i(allo)o(wing)e(the)g(generator)90 2279 y(to)19 b(p)q(erform)f(an)o +(y)h(necessary)h(initialization,)i(and)e(a)f(p)q(ositiv)o(e)h(non-zero)f(in)o +(teger)h(for)e(eac)o(h)h(subsequen)o(t)90 2341 y(call.)35 b(When)21 +b(the)f(generator)f(function)i(returns)f Fn(\(char)14 b(*\)NULL)19 +b Fo(this)i(signals)f Fn(completion_matches)90 2404 y(\(\))c +Fo(that)g(there)h(are)f(no)h(more)f(p)q(ossibilitie)q(s)j(left.)25 +b(Usually)18 b(the)e(generator)g(function)i(computes)e(the)h(list)90 +2466 y(of)j(p)q(ossible)i(completions)f(when)g Fj(state)h Fo(is)f(zero,)g +(and)f(returns)g(them)h(one)f(at)g(a)g(time)g(on)g(subsequen)o(t)90 +2528 y(calls.)g(Eac)o(h)14 b(string)f(the)h(generator)e(function)j(returns)e +(as)g(a)g(matc)o(h)g(m)o(ust)g(b)q(e)h(allo)q(cated)h(with)e +Fn(malloc\(\))p Fo(;)90 2590 y(Readline)18 b(frees)d(the)g(strings)g(when)h +(it)f(has)g(\014nished)i(with)f(them.)p eop +%%Page: 29 31 +30 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(Readline)994 +b(29)1725 158 y(F)l(unction)-1899 b Fh(int)20 b Fg(rl)p 140 +158 18 3 v 21 w(complete)j Ff(\()p Fn(int)14 b(ignore,)g(int)h(invoking_key)p +Ff(\))120 221 y Fo(Complete)j(the)f(w)o(ord)f(at)h(or)g(b)q(efore)g(p)q(oin)o +(t.)27 b(Y)l(ou)17 b(ha)o(v)o(e)g(supplied)i(the)f(function)g(that)e(do)q(es) +i(the)120 283 y(initial)d(simple)f(matc)o(hing)f(selection)h(algorithm)f +(\(see)f Fn(completion_matches)h(\(\))p Fo(\).)18 b(The)13 +b(default)120 345 y(is)j(to)e(do)h(\014lename)i(completion.)1736 +520 y(V)l(ariable)-1899 b Fh(Function)20 b(*)g Fg(rl)p 316 +520 V 21 w(completion)p 611 520 V 21 w(en)n(try)p 764 520 V +21 w(function)120 582 y Fo(This)e(is)g(a)f(p)q(oin)o(ter)h(to)f(the)g +(generator)g(function)h(for)f Fn(completion_matches)12 b(\(\))p +Fo(.)27 b(If)17 b(the)h(v)m(alue)120 644 y(of)j Fn(rl_completion_entry_funct) +o(ion)d Fo(is)k Fn(\(Function)14 b(*\)NULL)20 b Fo(then)i(the)f(default)h +(\014lename)120 707 y(generator)14 b(function,)i Fn(filename_entry_function)c +(\(\))p Fo(,)i(is)i(used.)0 953 y Fi(2.4.2)30 b(Completion)15 +b(F)-5 b(unctions)62 1094 y Fo(Here)16 b(is)f(the)h(complete)g(list)g(of)e +(callable)k(completion)e(functions)g(presen)o(t)f(in)h(Readline.)1725 +1269 y(F)l(unction)-1899 b Fh(int)20 b Fg(rl)p 140 1269 V 21 +w(complete)p 385 1269 V 21 w(in)n(ternal)k Ff(\()p Fn(int)15 +b(what_to_do)p Ff(\))120 1331 y Fo(Complete)d(the)g(w)o(ord)f(at)g(or)g(b)q +(efore)h(p)q(oin)o(t.)19 b Fj(what)p 979 1331 14 2 v 16 w(to)p +1036 1331 V 16 w(do)14 b Fo(sa)o(ys)d(what)g(to)g(do)g(with)h(the)g +(completion.)120 1394 y(A)g(v)m(alue)h(of)f(`)p Fn(?)p Fo(')f(means)h(list)h +(the)f(p)q(ossible)i(completions.)20 b(`)p Fn(TAB)p Fo(')11 +b(means)h(do)g(standard)f(completion.)120 1456 y(`)p Fn(*)p +Fo(')i(means)h(insert)h(all)g(of)f(the)g(p)q(ossible)i(completions.)21 +b(`)p Fn(!)p Fo(')13 b(means)h(to)g(displa)o(y)h(all)g(of)f(the)g(p)q +(ossible)120 1518 y(completions,)i(if)g(there)f(is)h(more)e(than)h(one,)g(as) +g(w)o(ell)h(as)f(p)q(erforming)h(partial)f(completion.)1725 +1693 y(F)l(unction)-1899 b Fh(int)20 b Fg(rl)p 140 1693 18 +3 v 21 w(complete)j Ff(\()p Fn(int)14 b(ignore,)g(int)h(invoking_key)p +Ff(\))120 1755 y Fo(Complete)23 b(the)g(w)o(ord)e(at)h(or)g(b)q(efore)h(p)q +(oin)o(t.)43 b(Y)l(ou)23 b(ha)o(v)o(e)f(supplied)j(the)d(function)i(that)e +(do)q(es)120 1817 y(the)16 b(initial)j(simple)f(matc)o(hing)e(selection)i +(algorithm)e(\(see)g Fn(completion_matches)d(\(\))j Fo(and)g +Fn(rl_)120 1880 y(completion_entry_function)p Fo(\))o(.)25 +b(The)18 b(default)g(is)g(to)f(do)h(\014lename)h(completion.)29 +b(This)18 b(calls)120 1942 y Fn(rl_complete_internal)12 b(\(\))j +Fo(with)h(an)f(argumen)o(t)f(dep)q(ending)k(on)d Fj(in)o(v)o(oking)p +1496 1942 14 2 v 17 w(k)o(ey)p Fo(.)1725 2117 y(F)l(unction)-1899 +b Fh(int)20 b Fg(rl)p 140 2117 18 3 v 21 w(p)r(ossible)p 358 +2117 V 20 w(completions)j Ff(\()p Fn(int)15 b(count,)f(int)h(invoking_key)p +Ff(\)\))120 2179 y Fo(List)23 b(the)f(p)q(ossible)j(completions.)42 +b(See)23 b(description)h(of)e Fn(rl_complete)14 b(\(\))p Fo(.)41 +b(This)23 b(calls)g Fn(rl_)120 2241 y(complete_internal)13 +b(\(\))i Fo(with)g(an)g(argumen)o(t)g(of)g(`)p Fn(?)p Fo('.)1725 +2416 y(F)l(unction)-1899 b Fh(int)20 b Fg(rl)p 140 2416 V 21 +w(insert)p 303 2416 V 21 w(completions)j Ff(\()p Fn(int)14 +b(count,)g(int)h(invoking_key)p Ff(\)\))120 2478 y Fo(Insert)20 +b(the)f(list)i(of)e(p)q(ossible)i(completions)f(in)o(to)g(the)f(line,)j +(deleting)f(the)f(partially-completed)120 2540 y(w)o(ord.)h(See)c +(description)g(of)e Fn(rl_complete)f(\(\))p Fo(.)21 b(This)c(calls)g +Fn(rl_complete_internal)12 b(\(\))k Fo(with)120 2603 y(an)f(argumen)o(t)g(of) +f(`)p Fn(*)p Fo('.)p eop +%%Page: 30 32 +31 bop 0 -83 a Fo(30)1449 b(GNU)15 b(Readline)i(Library)1725 +158 y(F)l(unction)-1899 b Fh(char)20 b(**)f Fg(completion)p +472 158 18 3 v 21 w(matc)n(hes)j Ff(\()p Fn(char)15 b(*text,)f(CPFunction)208 +221 y(*entry_func)p Ff(\))120 283 y Fo(Returns)22 b(an)g(arra)o(y)e(of)h +Fn(\(char)15 b(*\))21 b Fo(whic)o(h)i(is)f(a)f(list)i(of)e(completions)i(for) +e Fj(text)p Fo(.)39 b(If)22 b(there)f(are)120 345 y(no)d(completions,)i +(returns)e Fn(\(char)c(**\)NULL)p Fo(.)28 b(The)19 b(\014rst)e(en)o(try)h(in) +h(the)g(returned)f(arra)o(y)f(is)i(the)120 407 y(substitution)c(for)e +Fj(text)p Fo(.)19 b(The)c(remaining)g(en)o(tries)f(are)g(the)g(p)q(ossible)i +(completions.)k(The)15 b(arra)o(y)d(is)120 470 y(terminated)j(with)h(a)f +Fn(NULL)f Fo(p)q(oin)o(ter.)120 613 y Fj(en)o(try)p 227 613 +14 2 v 16 w(func)h Fo(is)d(a)g(function)h(of)e(t)o(w)o(o)g(args,)g(and)h +(returns)g(a)f Fn(\(char)k(*\))p Fo(.)j(The)12 b(\014rst)f(argumen)o(t)g(is)i +Fj(text)p Fo(.)120 675 y(The)i(second)f(is)h(a)f(state)g(argumen)o(t;)f(it)i +(is)g(zero)f(on)g(the)h(\014rst)f(call,)h(and)f(non-zero)h(on)f(subsequen)o +(t)120 738 y(calls.)21 b Fj(en)o(try)p 346 738 V 16 w(func)c +Fo(returns)e(a)f Fn(NULL)g Fo(p)q(oin)o(ter)h(to)f(the)g(caller)i(when)f +(there)f(are)g(no)h(more)f(matc)o(hes.)1725 919 y(F)l(unction)-1899 +b Fh(char)20 b(*)f Fg(\014lename)p 380 919 18 3 v 20 w(completion)p +674 919 V 21 w(function)k Ff(\()p Fn(char)15 b(*text,)f(int)h(state)p +Ff(\))120 981 y Fo(A)e(generator)f(function)h(for)f(\014lename)i(completion)g +(in)f(the)g(general)g(case.)19 b(Note)13 b(that)f(completion)120 +1043 y(in)18 b(Bash)f(is)h(a)f(little)h(di\013eren)o(t)f(b)q(ecause)h(of)f +(all)h(the)f(pathnames)g(that)g(m)o(ust)f(b)q(e)i(follo)o(w)o(ed)f(when)120 +1105 y(lo)q(oking)23 b(up)f(completions)h(for)e(a)g(command.)39 +b(The)22 b(Bash)g(source)g(is)g(a)f(useful)i(reference)g(for)120 +1168 y(writing)16 b(custom)f(completion)h(functions.)1725 1349 +y(F)l(unction)-1899 b Fh(char)20 b(*)f Fg(username)p 412 1349 +V 19 w(completion)p 705 1349 V 21 w(function)k Ff(\()p Fn(char)14 +b(*text,)g(int)h(state)p Ff(\))120 1411 y Fo(A)i(completion)h(generator)e +(for)g(usernames.)24 b Fj(text)18 b Fo(con)o(tains)e(a)h(partial)g(username)g +(preceded)h(b)o(y)120 1473 y(a)f(random)g(c)o(haracter)f(\(usually)j(`)p +Fn(~)p Fo('\).)24 b(As)18 b(with)f(all)h(completion)h(generators,)d +Fj(state)j Fo(is)f(zero)f(on)120 1536 y(the)e(\014rst)g(call)h(and)g +(non-zero)f(for)g(subsequen)o(t)h(calls.)0 1801 y Fi(2.4.3)30 +b(Completion)15 b(V)-5 b(ariables)1736 1982 y Fo(V)l(ariable)-1899 +b Fh(Function)20 b(*)g Fg(rl)p 316 1982 V 21 w(completion)p +611 1982 V 21 w(en)n(try)p 764 1982 V 21 w(function)120 2044 +y Fo(A)d(p)q(oin)o(ter)h(to)f(the)g(generator)f(function)i(for)f +Fn(completion_matches)c(\(\))p Fo(.)25 b Fn(NULL)17 b Fo(means)g(to)g(use)120 +2106 y Fn(filename_entry_function)12 b(\(\))p Fo(,)j(the)g(default)h +(\014lename)g(completer.)1736 2287 y(V)l(ariable)-1899 b Fh(CPPFunction)21 +b(*)e Fg(rl)p 394 2287 V 21 w(attempted)p 674 2287 V 20 w(completion)p +968 2287 V 21 w(function)120 2350 y Fo(A)g(p)q(oin)o(ter)h(to)f(an)g +(alternativ)o(e)h(function)g(to)f(create)g(matc)o(hes.)32 b(The)20 +b(function)g(is)g(called)h(with)120 2412 y Fj(text)p Fo(,)e +Fj(start)p Fo(,)g(and)g Fj(end)p Fo(.)32 b Fj(start)19 b Fo(and)g +Fj(end)j Fo(are)c(indices)j(in)f Fn(rl_line_buffer)d Fo(sa)o(ying)i(what)g +(the)120 2474 y(b)q(oundaries)c(of)e Fj(text)h Fo(are.)19 b(If)13 +b(this)h(function)g(exists)g(and)g(returns)f Fn(NULL)p Fo(,)g(or)g(if)h(this) +f(v)m(ariable)i(is)f(set)120 2536 y(to)h Fn(NULL)p Fo(,)f(then)i +Fn(rl_complete)e(\(\))h Fo(will)i(call)g(the)e(v)m(alue)i(of)e +Fn(rl_completion_entry_funct)o(ion)120 2599 y Fo(to)g(generate)f(matc)o(hes,) +h(otherwise)g(the)h(arra)o(y)e(of)g(strings)h(returned)h(will)h(b)q(e)f +(used.)p eop +%%Page: 31 33 +32 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(Readline)994 +b(31)1736 158 y(V)l(ariable)-1899 b Fh(int)20 b Fg(rl)p 140 +158 18 3 v 21 w(completion)p 435 158 V 21 w(query)p 598 158 +V 21 w(items)120 221 y Fo(Up)h(to)e(this)i(man)o(y)f(items)h(will)h(b)q(e)f +(displa)o(y)o(ed)h(in)f(resp)q(onse)g(to)f(a)g(p)q(ossible-completions)j +(call.)120 283 y(After)16 b(that,)f(w)o(e)g(ask)h(the)g(user)g(if)g(she)g(is) +h(sure)f(she)g(w)o(an)o(ts)f(to)g(see)h(them)g(all.)23 b(The)16 +b(default)h(v)m(alue)120 345 y(is)f(100.)1736 524 y(V)l(ariable)-1899 +b Fh(char)20 b(*)f Fg(rl)p 211 524 V 21 w(basic)p 355 524 V +21 w(w)n(ord)p 500 524 V 21 w(break)p 661 524 V 20 w(c)n(haracters)120 +586 y Fo(The)12 b(basic)g(list)h(of)e(c)o(haracters)g(that)g(signal)h(a)g +(break)f(b)q(et)o(w)o(een)h(w)o(ords)f(for)g(the)h(completer)g(routine.)120 +648 y(The)17 b(default)h(v)m(alue)g(of)e(this)i(v)m(ariable)g(is)g(the)f(c)o +(haracters)f(whic)o(h)h(break)g(w)o(ords)g(for)f(completion)120 +711 y(in)g(Bash,)f(i.e.,)g Fn(")g(\\t\\n\\"\\\\'`@$><=;|&{\(")p +Fo(.)1736 889 y(V)l(ariable)-1899 b Fh(char)20 b(*)f Fg(rl)p +211 889 V 21 w(completer)p 480 889 V 21 w(w)n(ord)p 625 889 +V 20 w(break)p 785 889 V 20 w(c)n(haracters)120 952 y Fo(The)f(list)h(of)e(c) +o(haracters)g(that)g(signal)i(a)f(break)f(b)q(et)o(w)o(een)h(w)o(ords)g(for)f +Fn(rl_complete_internal)120 1014 y(\(\))p Fo(.)j(The)15 b(default)h(list)g +(is)f(the)h(v)m(alue)g(of)f Fn(rl_basic_word_break_charac)o(ters)p +Fo(.)1736 1192 y(V)l(ariable)-1899 b Fh(char)20 b(*)f Fg(rl)p +211 1192 V 21 w(sp)r(ecial)p 398 1192 V 22 w(pre\014xes)120 +1255 y Fo(The)d(list)h(of)e(c)o(haracters)g(that)g(are)h(w)o(ord)f(break)h(c) +o(haracters,)f(but)h(should)h(b)q(e)f(left)g(in)h Fj(text)f +Fo(when)120 1317 y(it)f(is)g(passed)g(to)f(the)g(completion)i(function.)k +(Programs)14 b(can)g(use)h(this)g(to)f(help)i(determine)g(what)120 +1379 y(kind)h(of)f(completing)i(to)e(do.)23 b(F)l(or)16 b(instance,)h(Bash)f +(sets)g(this)h(v)m(ariable)h(to)e Fn(")p Fo($)p Fn(@")f Fo(so)h(that)g(it)h +(can)120 1442 y(complete)f(shell)h(v)m(ariables)f(and)g(hostnames.)1736 +1620 y(V)l(ariable)-1899 b Fh(int)20 b Fg(rl)p 140 1620 V 21 +w(ignore)p 316 1620 V 20 w(completion)p 610 1620 V 21 w(duplicates)120 +1682 y Fo(If)15 b(non-zero,)h(then)f(disallo)o(w)h(duplicates)h(in)f(the)g +(matc)o(hes.)j(Default)c(is)h(1.)1736 1861 y(V)l(ariable)-1899 +b Fh(int)20 b Fg(rl)p 140 1861 V 21 w(\014lename)p 369 1861 +V 20 w(completion)p 663 1861 V 21 w(desired)120 1923 y Fo(Non-zero)e(means)g +(that)f(the)g(results)i(of)e(the)h(matc)o(hes)f(are)h(to)f(b)q(e)h(treated)f +(as)h(\014lenames.)28 b(This)120 1986 y(is)16 b Fj(alw)o(a)o(ys)h +Fo(zero)e(on)g(en)o(try)l(,)g(and)h(can)g(only)g(b)q(e)g(c)o(hanged)f(within) +i(a)e(completion)i(en)o(try)e(generator)120 2048 y(function.)26 +b(If)18 b(it)f(is)h(set)f(to)f(a)h(non-zero)g(v)m(alue,)i(directory)e(names)g +(ha)o(v)o(e)g(a)g(slash)g(app)q(ended)i(and)120 2110 y(Readline)i(attempts)c +(to)g(quote)h(completed)i(\014lenames)f(if)f(they)h(con)o(tain)f(an)o(y)g(em) +o(b)q(edded)i(w)o(ord)120 2172 y(break)15 b(c)o(haracters.)1736 +2351 y(V)l(ariable)-1899 b Fh(int)20 b Fg(rl)p 140 2351 V 21 +w(\014lename)p 369 2351 V 20 w(quoting)p 578 2351 V 21 w(desired)120 +2413 y Fo(Non-zero)c(means)g(that)g(the)g(results)h(of)e(the)i(matc)o(hes)e +(are)h(to)g(b)q(e)h(quoted)f(using)h(double)g(quotes)120 2476 +y(\(or)d(an)h(application-sp)q(eci\014)q(c)j(quoting)d(mec)o(hanism\))g(if)h +(the)f(completed)h(\014lename)g(con)o(tains)f(an)o(y)120 2538 +y(c)o(haracters)c(in)h Fn(rl_completer_word_break_cha)o(rs)p +Fo(.)k(This)c(is)g Fj(alw)o(a)o(ys)h Fo(non-zero)f(on)f(en)o(try)l(,)h(and) +120 2600 y(can)j(only)h(b)q(e)g(c)o(hanged)f(within)i(a)e(completion)h(en)o +(try)f(generator)f(function.)p eop +%%Page: 32 34 +33 bop 0 -83 a Fo(32)1449 b(GNU)15 b(Readline)i(Library)1736 +158 y(V)l(ariable)-1899 b Fh(Function)20 b(*)g Fg(rl)p 316 +158 18 3 v 21 w(ignore)p 492 158 V 20 w(some)p 639 158 V 19 +w(completions)p 955 158 V 21 w(function)120 221 y Fo(This)e(function,)g(if)g +(de\014ned,)h(is)f(called)h(b)o(y)e(the)h(completer)g(when)g(real)f +(\014lename)i(completion)f(is)120 283 y(done,)13 b(after)e(all)i(the)g(matc)o +(hing)f(names)g(ha)o(v)o(e)g(b)q(een)h(generated.)19 b(It)12 +b(is)h(passed)f(a)g Fn(NULL)g Fo(terminated)120 345 y(arra)o(y)k(of)h(matc)o +(hes.)26 b(The)17 b(\014rst)g(elemen)o(t)h(\()p Fn(matches[0])p +Fo(\))e(is)h(the)h(maximal)g(substring)f(common)120 407 y(to)f(all)h(matc)o +(hes.)22 b(This)17 b(function)g(can)f(re-arrange)g(the)g(list)h(of)f(matc)o +(hes)g(as)f(required,)j(but)e(eac)o(h)120 470 y(elemen)o(t)g(deleted)g(from)f +(the)g(arra)o(y)f(m)o(ust)h(b)q(e)h(freed.)1736 632 y(V)l(ariable)-1899 +b Fh(char)20 b(*)f Fg(rl)p 211 632 V 21 w(completer)p 480 632 +V 21 w(quote)p 640 632 V 21 w(c)n(haracters)120 694 y Fo(List)j(of)e(c)o +(haracters)g(whic)o(h)i(can)f(b)q(e)h(used)f(to)f(quote)h(a)g(substring)g(of) +f(the)h(line.)39 b(Completion)120 756 y(o)q(ccurs)17 b(on)f(the)h(en)o(tire)g +(substring,)g(and)f(within)i(the)e(substring)h Fn(rl_completer_word_break_) +120 818 y(characters)i Fo(are)g(treated)h(as)f(an)o(y)h(other)g(c)o +(haracter,)g(unless)h(they)f(also)g(app)q(ear)g(within)i(this)120 +881 y(list.)0 1088 y Fi(2.4.4)30 b(A)15 b(Short)g(Completion)g(Example)62 +1225 y Fo(Here)20 b(is)h(a)e(small)i(application)g(demonstrating)f(the)f(use) +i(of)e(the)h(GNU)f(Readline)k(library)l(.)34 b(It)20 b(is)g(called)0 +1287 y Fn(fileman)p Fo(,)14 b(and)i(the)f(source)g(co)q(de)h(resides)g(in)h +(`)p Fn(examples/fileman.c)p Fo(')o(.)h(This)e(sample)f(application)i(pro)o +(vides)0 1350 y(completion)f(of)f(command)g(names,)g(line)i(editing)f +(features,)f(and)g(access)g(to)g(the)g(history)g(list.)p eop +%%Page: 33 35 +34 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(Readline)994 +b(33)120 158 y Fn(/*)24 b(fileman.c)e(--)i(A)g(tiny)f(application)f(which)h +(demonstrates)g(how)g(to)h(use)f(the)192 208 y(GNU)g(Readline)g(library.)46 +b(This)24 b(application)e(interactively)g(allows)h(users)192 +258 y(to)g(manipulate)g(files)g(and)g(their)g(modes.)h(*/)120 +358 y(#include)f()120 407 y(#include)g()120 +457 y(#include)g()120 507 y(#include)g()120 +557 y(#include)g()120 656 y(#include)g()120 +706 y(#include)g()120 806 y(extern)g(char)g(*getwd)g +(\(\);)120 856 y(extern)g(char)g(*xmalloc)g(\(\);)120 955 y(/*)h(The)f(names) +g(of)h(functions)e(that)i(actually)f(do)g(the)h(manipulation.)e(*/)120 +1005 y(int)h(com_list)g(\(\),)h(com_view)e(\(\),)i(com_rename)e(\(\),)i +(com_stat)f(\(\),)g(com_pwd)g(\(\);)120 1055 y(int)g(com_delete)g(\(\),)g +(com_help)g(\(\),)h(com_cd)f(\(\),)g(com_quit)g(\(\);)120 1155 +y(/*)h(A)f(structure)g(which)g(contains)g(information)f(on)i(the)f(commands)g +(this)g(program)192 1204 y(can)g(understand.)f(*/)120 1304 +y(typedef)h(struct)g({)168 1354 y(char)g(*name;)g(/*)h(User)f(printable)g +(name)g(of)h(the)f(function.)g(*/)168 1404 y(Function)f(*func;)i(/*)f +(Function)g(to)g(call)h(to)f(do)h(the)f(job.)h(*/)168 1453 +y(char)f(*doc;)g(/*)h(Documentation)e(for)h(this)h(function.)46 +b(*/)120 1503 y(})24 b(COMMAND;)120 1603 y(COMMAND)f(commands[])f(=)i({)168 +1653 y({)f("cd",)h(com_cd,)f("Change)f(to)i(directory)f(DIR")g(},)168 +1703 y({)g("delete",)g(com_delete,)f("Delete)h(FILE")h(},)168 +1752 y({)f("help",)g(com_help,)g("Display)g(this)g(text")g(},)168 +1802 y({)g("?",)h(com_help,)e("Synonym)h(for)h(`help'")f(},)168 +1852 y({)g("list",)g(com_list,)g("List)g(files)g(in)h(DIR")f(},)168 +1902 y({)g("ls",)h(com_list,)e("Synonym)h(for)g(`list'")g(},)168 +1952 y({)g("pwd",)g(com_pwd,)g("Print)g(the)h(current)f(working)g(directory") +f(},)168 2001 y({)h("quit",)g(com_quit,)g("Quit)g(using)g(Fileman")g(},)168 +2051 y({)g("rename",)g(com_rename,)f("Rename)h(FILE)h(to)f(NEWNAME")g(},)168 +2101 y({)g("stat",)g(com_stat,)g("Print)g(out)g(statistics)g(on)h(FILE")f(},) +168 2151 y({)g("view",)g(com_view,)g("View)g(the)h(contents)e(of)i(FILE")f +(},)168 2201 y({)g(\(char)h(*\)NULL,)f(\(Function)f(*\)NULL,)h(\(char)g +(*\)NULL)g(})120 2250 y(};)120 2350 y(/*)h(Forward)e(declarations.)h(*/)120 +2400 y(char)g(*stripwhite)g(\(\);)120 2450 y(COMMAND)g(*find_command)f(\(\);) +120 2549 y(/*)i(The)f(name)g(of)h(this)f(program,)g(as)h(taken)f(from)g +(argv[0].)g(*/)120 2599 y(char)g(*progname;)p eop +%%Page: 34 36 +35 bop 0 -83 a Fo(34)1449 b(GNU)15 b(Readline)i(Library)120 +208 y Fn(/*)24 b(When)f(non-zero,)g(this)g(global)g(means)g(the)h(user)f(is)g +(done)h(using)f(this)g(program.)g(*/)120 258 y(int)g(done;)120 +358 y(char)g(*)120 407 y(dupstr)g(\(s\))239 457 y(int)h(s;)120 +507 y({)168 557 y(char)f(*r;)168 656 y(r)g(=)h(xmalloc)f(\(strlen)g(\(s\))g +(+)h(1\);)168 706 y(strcpy)f(\(r,)g(s\);)168 756 y(return)g(\(r\);)120 +806 y(})120 906 y(main)g(\(argc,)g(argv\))239 955 y(int)h(argc;)239 +1005 y(char)g(**argv;)120 1055 y({)168 1105 y(char)f(*line,)g(*s;)168 +1204 y(progname)f(=)i(argv[0];)168 1304 y(initialize_readline)d(\(\);)i(/*)h +(Bind)f(our)h(completer.)e(*/)168 1404 y(/*)h(Loop)h(reading)f(and)g +(executing)g(lines)g(until)g(the)g(user)h(quits.)f(*/)168 1453 +y(for)g(\()h(;)g(done)f(==)h(0;)f(\))215 1503 y({)263 1553 +y(line)g(=)h(readline)f(\("FileMan:)f("\);)263 1653 y(if)i(\(!line\))311 +1703 y(break;)263 1802 y(/*)g(Remove)f(leading)g(and)g(trailing)g(whitespace) +f(from)i(the)f(line.)335 1852 y(Then,)g(if)h(there)f(is)g(anything)g(left,)g +(add)h(it)f(to)h(the)f(history)g(list)335 1902 y(and)g(execute)g(it.)h(*/)263 +1952 y(s)g(=)g(stripwhite)e(\(line\);)263 2051 y(if)i(\(*s\))311 +2101 y({)359 2151 y(add_history)e(\(s\);)359 2201 y(execute_line)g(\(s\);)311 +2250 y(})263 2350 y(free)h(\(line\);)215 2400 y(})168 2450 +y(exit)g(\(0\);)120 2500 y(})120 2599 y(/*)h(Execute)e(a)i(command)f(line.)g +(*/)p eop +%%Page: 35 37 +36 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(Readline)994 +b(35)120 158 y Fn(int)120 208 y(execute_line)22 b(\(line\))239 +258 y(char)i(*line;)120 308 y({)168 358 y(register)e(int)i(i;)168 +407 y(COMMAND)f(*command;)168 457 y(char)g(*word;)168 557 y(/*)g(Isolate)g +(the)h(command)f(word.)g(*/)168 607 y(i)g(=)h(0;)168 656 y(while)f(\(line[i]) +g(&&)g(whitespace)g(\(line[i]\)\))215 706 y(i++;)168 756 y(word)g(=)h(line)f +(+)h(i;)168 856 y(while)f(\(line[i])g(&&)g(!whitespace)g(\(line[i]\)\))215 +906 y(i++;)168 1005 y(if)g(\(line[i]\))215 1055 y(line[i++])g(=)h('\\0';)168 +1155 y(command)f(=)g(find_command)g(\(word\);)168 1254 y(if)g(\(!command\)) +215 1304 y({)263 1354 y(fprintf)g(\(stderr,)g("\045s:)g(No)h(such)f(command)g +(for)g(FileMan.\\n",)g(word\);)263 1404 y(return)g(\(-1\);)215 +1453 y(})168 1553 y(/*)g(Get)h(argument)f(to)g(command,)g(if)g(any.)h(*/)168 +1603 y(while)f(\(whitespace)f(\(line[i]\)\))215 1653 y(i++;)168 +1752 y(word)h(=)h(line)f(+)h(i;)168 1852 y(/*)f(Call)h(the)f(function.)g(*/) +168 1902 y(return)g(\(\(*\(command->func\)\))e(\(word\)\);)120 +1952 y(})120 2051 y(/*)j(Look)f(up)g(NAME)h(as)f(the)h(name)f(of)h(a)f +(command,)g(and)h(return)f(a)g(pointer)g(to)h(that)192 2101 +y(command.)46 b(Return)23 b(a)h(NULL)f(pointer)g(if)h(NAME)f(isn't)g(a)h +(command)f(name.)g(*/)120 2151 y(COMMAND)g(*)120 2201 y(find_command)f +(\(name\))239 2250 y(char)i(*name;)120 2300 y({)168 2350 y(register)e(int)i +(i;)168 2450 y(for)f(\(i)h(=)f(0;)h(commands[i].name;)e(i++\))215 +2500 y(if)i(\(strcmp)f(\(name,)g(commands[i].name\))f(==)h(0\))263 +2549 y(return)g(\(&commands[i]\);)p eop +%%Page: 36 38 +37 bop 0 -83 a Fo(36)1449 b(GNU)15 b(Readline)i(Library)168 +208 y Fn(return)23 b(\(\(COMMAND)f(*\)NULL\);)120 258 y(})120 +358 y(/*)i(Strip)f(whitespace)f(from)i(the)f(start)g(and)h(end)f(of)h +(STRING.)46 b(Return)24 b(a)f(pointer)192 407 y(into)g(STRING.)g(*/)120 +457 y(char)g(*)120 507 y(stripwhite)f(\(string\))239 557 y(char)i(*string;) +120 607 y({)168 656 y(register)e(char)i(*s,)f(*t;)168 756 y(for)g(\(s)h(=)f +(string;)g(whitespace)g(\(*s\);)g(s++\))215 806 y(;)168 906 +y(if)g(\(*s)h(==)f(0\))215 955 y(return)g(\(s\);)168 1055 y(t)g(=)h(s)g(+)g +(strlen)f(\(s\))g(-)h(1;)168 1105 y(while)f(\(t)g(>)h(s)g(&&)g(whitespace)e +(\(*t\)\))215 1155 y(t--;)168 1204 y(*++t)h(=)h('\\0';)168 +1304 y(return)f(s;)120 1354 y(})120 1453 y(/*)h(***********************)o +(*******)o(********)o(*******)o(*******)o(********)o(****)d(*/)120 +1503 y(/*)1575 b(*/)120 1553 y(/*)429 b(Interface)23 b(to)g(Readline)g +(Completion)381 b(*/)120 1603 y(/*)1575 b(*/)120 1653 y(/*)24 +b(***********************)o(*******)o(********)o(*******)o(*******)o +(********)o(****)d(*/)120 1752 y(char)i(*command_generator)f(\(\);)120 +1802 y(char)h(**fileman_completion)e(\(\);)120 1902 y(/*)j(Tell)f(the)g(GNU)h +(Readline)f(library)f(how)i(to)g(complete.)46 b(We)24 b(want)f(to)h(try)f(to) +h(complete)192 1952 y(on)f(command)g(names)g(if)h(this)f(is)h(the)f(first)g +(word)h(in)f(the)h(line,)f(or)h(on)f(filenames)192 2001 y(if)g(not.)g(*/)120 +2051 y(initialize_readline)e(\(\))120 2101 y({)168 2151 y(/*)i(Allow)g +(conditional)g(parsing)g(of)g(the)h(~/.inputrc)e(file.)h(*/)168 +2201 y(rl_readline_name)e(=)j("FileMan";)168 2300 y(/*)f(Tell)h(the)f +(completer)g(that)g(we)h(want)f(a)h(crack)f(first.)g(*/)168 +2350 y(rl_attempted_completion_)o(functio)o(n)e(=)j(\(CPPFunction)e +(*\)fileman_completion;)120 2400 y(})p eop +%%Page: 37 39 +38 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(Readline)994 +b(37)120 158 y Fn(/*)24 b(Attempt)e(to)i(complete)f(on)g(the)h(contents)f(of) +g(TEXT.)47 b(START)23 b(and)h(END)f(show)h(the)192 208 y(region)f(of)g(TEXT)h +(that)f(contains)g(the)g(word)g(to)h(complete.)46 b(We)24 b(can)g(use)f(the) +192 258 y(entire)g(line)g(in)h(case)f(we)g(want)h(to)f(do)h(some)f(simple)g +(parsing.)47 b(Return)23 b(the)192 308 y(array)g(of)g(matches,)g(or)h(NULL)f +(if)h(there)f(aren't)g(any.)g(*/)120 358 y(char)g(**)120 407 +y(fileman_completion)e(\(text,)i(start,)g(end\))239 457 y(char)h(*text;)239 +507 y(int)g(start,)f(end;)120 557 y({)168 607 y(char)g(**matches;)168 +706 y(matches)g(=)g(\(char)h(**\)NULL;)168 806 y(/*)f(If)h(this)f(word)h(is)f +(at)h(the)f(start)g(of)h(the)f(line,)h(then)f(it)g(is)h(a)g(command)239 +856 y(to)g(complete.)46 b(Otherwise)23 b(it)h(is)f(the)h(name)f(of)h(a)f +(file)h(in)f(the)h(current)239 906 y(directory.)f(*/)168 955 +y(if)g(\(start)g(==)h(0\))215 1005 y(matches)f(=)h(completion_matches)d +(\(text,)j(command_generator\);)168 1105 y(return)f(\(matches\);)120 +1155 y(})120 1254 y(/*)h(Generator)e(function)h(for)g(command)g(completion.) +47 b(STATE)23 b(lets)g(us)h(know)f(whether)192 1304 y(to)g(start)g(from)h +(scratch;)e(without)h(any)h(state)f(\(i.e.)g(STATE)g(==)h(0\),)f(then)h(we) +192 1354 y(start)f(at)g(the)h(top)f(of)h(the)f(list.)g(*/)120 +1404 y(char)g(*)120 1453 y(command_generator)f(\(text,)h(state\))239 +1503 y(char)h(*text;)239 1553 y(int)g(state;)120 1603 y({)168 +1653 y(static)f(int)g(list_index,)g(len;)168 1703 y(char)g(*name;)168 +1802 y(/*)g(If)h(this)f(is)h(a)g(new)f(word)g(to)h(complete,)f(initialize)f +(now.)47 b(This)24 b(includes)239 1852 y(saving)f(the)h(length)f(of)g(TEXT)h +(for)f(efficiency,)g(and)g(initializing)f(the)i(index)239 1902 +y(variable)f(to)h(0.)f(*/)168 1952 y(if)g(\(!state\))215 2001 +y({)263 2051 y(list_index)g(=)g(0;)263 2101 y(len)h(=)f(strlen)g(\(text\);) +215 2151 y(})168 2250 y(/*)g(Return)g(the)h(next)f(name)g(which)h(partially)e +(matches)h(from)g(the)h(command)f(list.)g(*/)168 2300 y(while)g(\(name)g(=)h +(commands[list_index].name)o(\))215 2350 y({)263 2400 y(list_index++;)263 +2500 y(if)g(\(strncmp)f(\(name,)g(text,)g(len\))g(==)h(0\))311 +2549 y(return)f(\(dupstr\(name\)\);)215 2599 y(})p eop +%%Page: 38 40 +39 bop 0 -83 a Fo(38)1449 b(GNU)15 b(Readline)i(Library)168 +208 y Fn(/*)23 b(If)h(no)f(names)h(matched,)e(then)i(return)f(NULL.)g(*/)168 +258 y(return)g(\(\(char)g(*\)NULL\);)120 308 y(})120 407 y(/*)h +(***********************)o(*******)o(********)o(*******)o(*******)o(********) +o(****)d(*/)120 457 y(/*)1575 b(*/)120 507 y(/*)549 b(FileMan)22 +b(Commands)644 b(*/)120 557 y(/*)1575 b(*/)120 607 y(/*)24 +b(***********************)o(*******)o(********)o(*******)o(*******)o +(********)o(****)d(*/)120 706 y(/*)j(String)f(to)g(pass)h(to)f(system)g +(\(\).)47 b(This)24 b(is)f(for)h(the)f(LIST,)g(VIEW)h(and)f(RENAME)192 +756 y(commands.)f(*/)120 806 y(static)h(char)g(syscom[1024];)120 +906 y(/*)h(List)f(the)g(file\(s\))g(named)g(in)h(arg.)f(*/)120 +955 y(com_list)g(\(arg\))239 1005 y(char)h(*arg;)120 1055 y({)168 +1105 y(if)f(\(!arg\))215 1155 y(arg)h(=)g("";)168 1254 y(sprintf)f(\(syscom,) +f("ls)i(-FClg)f(\045s",)g(arg\);)168 1304 y(return)g(\(system)g +(\(syscom\)\);)120 1354 y(})120 1453 y(com_view)g(\(arg\))239 +1503 y(char)h(*arg;)120 1553 y({)168 1603 y(if)f(\(!valid_argument)f +(\("view",)h(arg\)\))215 1653 y(return)g(1;)168 1752 y(sprintf)g(\(syscom,)f +("more)i(\045s",)f(arg\);)168 1802 y(return)g(\(system)g(\(syscom\)\);)120 +1852 y(})120 1952 y(com_rename)f(\(arg\))239 2001 y(char)i(*arg;)120 +2051 y({)168 2101 y(too_dangerous)e(\("rename"\);)168 2151 +y(return)h(\(1\);)120 2201 y(})120 2300 y(com_stat)g(\(arg\))239 +2350 y(char)h(*arg;)120 2400 y({)168 2450 y(struct)f(stat)g(finfo;)168 +2549 y(if)g(\(!valid_argument)f(\("stat",)h(arg\)\))215 2599 +y(return)g(\(1\);)p eop +%%Page: 39 41 +40 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(Readline)994 +b(39)168 208 y Fn(if)23 b(\(stat)g(\(arg,)h(&finfo\))f(==)g(-1\))215 +258 y({)263 308 y(perror)g(\(arg\);)263 358 y(return)g(\(1\);)215 +407 y(})168 507 y(printf)g(\("Statistics)f(for)h(`\045s':\\n",)g(arg\);)168 +607 y(printf)g(\("\045s)g(has)h(\045d)f(link\045s,)g(and)g(is)h(\045d)g +(byte\045s)f(in)g(length.\\n",)g(arg,)359 656 y(finfo.st_nlink,)359 +706 y(\(finfo.st_nlink)e(==)j(1\))g(?)f("")h(:)g("s",)359 756 +y(finfo.st_size,)359 806 y(\(finfo.st_size)e(==)h(1\))h(?)f("")h(:)g("s"\);) +168 856 y(printf)f(\("Inode)g(Last)g(Change)g(at:)g(\045s",)h(ctime)f +(\(&finfo.st_ctime\)\);)168 906 y(printf)g(\(")143 b(Last)23 +b(access)g(at:)g(\045s",)h(ctime)f(\(&finfo.st_atime\)\);)168 +955 y(printf)g(\(")95 b(Last)23 b(modified)g(at:)g(\045s",)h(ctime)f +(\(&finfo.st_mtime\)\);)168 1005 y(return)g(\(0\);)120 1055 +y(})120 1155 y(com_delete)f(\(arg\))239 1204 y(char)i(*arg;)120 +1254 y({)168 1304 y(too_dangerous)e(\("delete"\);)168 1354 +y(return)h(\(1\);)120 1404 y(})120 1503 y(/*)h(Print)f(out)g(help)h(for)f +(ARG,)g(or)h(for)f(all)h(of)f(the)h(commands)f(if)g(ARG)h(is)192 +1553 y(not)f(present.)g(*/)120 1603 y(com_help)g(\(arg\))239 +1653 y(char)h(*arg;)120 1703 y({)168 1752 y(register)e(int)i(i;)168 +1802 y(int)f(printed)g(=)h(0;)168 1902 y(for)f(\(i)h(=)f(0;)h +(commands[i].name;)e(i++\))215 1952 y({)263 2001 y(if)i(\(!*arg)f(||)g +(\(strcmp)g(\(arg,)g(commands[i].name\))f(==)i(0\)\))311 2051 +y({)359 2101 y(printf)f(\("\045s\\t\\t\045s.\\n",)e(commands[i].name,)h +(commands[i].doc\);)359 2151 y(printed++;)311 2201 y(})215 +2250 y(})168 2350 y(if)h(\(!printed\))215 2400 y({)263 2450 +y(printf)g(\("No)h(commands)e(match)h(`\045s'.)48 b(Possibilties)22 +b(are:\\n",)h(arg\);)p eop +%%Page: 40 42 +41 bop 0 -83 a Fo(40)1449 b(GNU)15 b(Readline)i(Library)263 +208 y Fn(for)24 b(\(i)f(=)h(0;)g(commands[i].name;)d(i++\))311 +258 y({)359 308 y(/*)i(Print)g(in)h(six)f(columns.)g(*/)359 +358 y(if)g(\(printed)g(==)h(6\))406 407 y({)454 457 y(printed)f(=)h(0;)454 +507 y(printf)f(\("\\n"\);)406 557 y(})359 656 y(printf)g(\("\045s\\t",)f +(commands[i].name\);)359 706 y(printed++;)311 756 y(})263 856 +y(if)i(\(printed\))311 906 y(printf)f(\("\\n"\);)215 955 y(})168 +1005 y(return)g(\(0\);)120 1055 y(})120 1155 y(/*)h(Change)f(to)g(the)h +(directory)e(ARG.)i(*/)120 1204 y(com_cd)f(\(arg\))239 1254 +y(char)h(*arg;)120 1304 y({)168 1354 y(if)f(\(chdir)g(\(arg\))h(==)f(-1\))215 +1404 y({)263 1453 y(perror)g(\(arg\);)263 1503 y(return)g(1;)215 +1553 y(})168 1653 y(com_pwd)g(\(""\);)168 1703 y(return)g(\(0\);)120 +1752 y(})120 1852 y(/*)h(Print)f(out)g(the)h(current)f(working)f(directory.)h +(*/)120 1902 y(com_pwd)g(\(ignore\))239 1952 y(char)h(*ignore;)120 +2001 y({)168 2051 y(char)f(dir[1024],)g(*s;)168 2151 y(s)g(=)h(getwd)f +(\(dir\);)168 2201 y(if)g(\(s)h(==)f(0\))215 2250 y({)263 2300 +y(printf)g(\("Error)g(getting)g(pwd:)g(\045s\\n",)g(dir\);)263 +2350 y(return)g(1;)215 2400 y(})168 2500 y(printf)g(\("Current)f(directory)h +(is)h(\045s\\n",)f(dir\);)168 2549 y(return)g(0;)120 2599 y(})p +eop +%%Page: 41 43 +42 bop 0 -83 a Fo(Chapter)15 b(2:)k(Programming)c(with)g(GNU)g(Readline)994 +b(41)120 208 y Fn(/*)24 b(The)f(user)g(wishes)g(to)h(quit)f(using)g(this)h +(program.)46 b(Just)24 b(set)f(DONE)h(non-zero.)e(*/)120 258 +y(com_quit)h(\(arg\))239 308 y(char)h(*arg;)120 358 y({)168 +407 y(done)f(=)h(1;)168 457 y(return)f(\(0\);)120 507 y(})120 +607 y(/*)h(Function)e(which)i(tells)f(you)g(that)g(you)h(can't)f(do)h(this.)f +(*/)120 656 y(too_dangerous)f(\(caller\))239 706 y(char)i(*caller;)120 +756 y({)168 806 y(fprintf)f(\(stderr,)382 856 y("\045s:)h(Too)f(dangerous)g +(for)g(me)h(to)g(distribute.)46 b(Write)23 b(it)h(yourself.\\n",)382 +906 y(caller\);)120 955 y(})120 1055 y(/*)g(Return)f(non-zero)f(if)i(ARG)f +(is)h(a)g(valid)f(argument)g(for)g(CALLER,)g(else)g(print)192 +1105 y(an)g(error)g(message)g(and)h(return)f(zero.)g(*/)120 +1155 y(int)120 1204 y(valid_argument)f(\(caller,)h(arg\))239 +1254 y(char)h(*caller,)e(*arg;)120 1304 y({)168 1354 y(if)h(\(!arg)g(||)h +(!*arg\))215 1404 y({)263 1453 y(fprintf)f(\(stderr,)g("\045s:)g(Argument)g +(required.\\n",)f(caller\);)263 1503 y(return)h(\(0\);)215 +1553 y(})168 1653 y(return)g(\(1\);)120 1703 y(})p eop +%%Page: 42 44 +43 bop 0 -83 a Fo(42)1449 b(GNU)15 b(Readline)i(Library)p eop +%%Page: 43 45 +44 bop 0 -83 a Fo(Concept)15 b(Index)1616 b(43)0 158 y Fk(Concept)16 +b(Index)0 405 y Fm(I)0 471 y Fe(in)o(teraction,)f(readline)5 +b Fd(:)j(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)17 +b Fe(1)0 579 y Fm(K)0 646 y Fe(Kill)e(ring)8 b Fd(:)f(:)f(:)g(:)h(:)f(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)21 +b Fe(3)0 704 y(Killing)16 b(text)8 b Fd(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h +(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)20 b Fe(3)1015 +405 y Fm(R)1015 471 y Fe(readline,)15 b(function)8 b Fd(:)g(:)e(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)21 b Fe(15)1015 637 +y Fm(Y)1015 704 y Fe(Y)m(anking)15 b(text)t Fd(:)6 b(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)17 b +Fe(3)p eop +%%Page: 44 46 +45 bop 0 -83 a Fo(44)1449 b(GNU)15 b(Readline)i(Library)p eop +%%Page: 45 47 +46 bop 0 -83 a Fo(F)l(unction)16 b(and)f(V)l(ariable)i(Index)1337 +b(45)0 158 y Fk(F)-7 b(unction)15 b(and)g(V)-7 b(ariable)14 +b(Index)0 399 y Fm($)0 466 y Fc($else)t Fd(:)t(:)6 b(:)g(:)h(:)f(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)17 b Fe(8)0 524 y Fc($endif)9 b Fd(:)d(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)24 +b Fe(8)0 582 y Fc($if)7 b Fd(:)e(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)19 +b Fe(7)0 699 y Fm(A)0 765 y Fc(abort)11 b(\(C-g\))c Fd(:)t(:)f(:)h(:)f(:)g(:) +g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)20 b +Fe(13)0 824 y Fc(accept-lin)o(e)10 b(\(Newline)o(,)g(Return\))c +Fd(:)s(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:) +g(:)19 b Fe(9)0 882 y Fc(alphabetic)t Fd(:)s(:)7 b(:)f(:)g(:)g(:)g(:)g(:)g(:) +g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b Fe(25)0 +999 y Fm(B)0 1065 y Fc(backward-c)o(ha)o(r)10 b(\(C-b\))d Fd(:)t(:)f(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)19 b Fe(8)0 1124 y Fc(backward-d)o(el)o(ete)o +(-c)o(har)9 b(\(Rubout\))e Fd(:)f(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)23 b Fe(10)0 1182 y Fc(backward-k)o(il)o(l-l)o(in)o(e) +10 b(\(C-x)h(Rubout\))d Fd(:)e(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:) +g(:)g(:)g(:)24 b Fe(11)0 1240 y Fc(backward-k)o(il)o(l-w)o(or)o(d)10 +b(\(M-DEL\))5 b Fd(:)t(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:) +g(:)h(:)f(:)g(:)g(:)g(:)g(:)18 b Fe(11)0 1298 y Fc(backward-w)o(or)o(d)10 +b(\(M-b\))d Fd(:)t(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:) +g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)19 +b Fe(8)0 1356 y Fc(beginning-)o(of)o(-hi)o(st)o(ory)9 b(\(M-<\))d +Fd(:)f(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:) +g(:)g(:)g(:)g(:)19 b Fe(9)0 1414 y Fc(beginning-)o(of)o(-li)o(ne)9 +b(\(C-a\))g Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:) +f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)23 b Fe(8)0 1472 y(b)q(ell-st)o(yle)s +Fd(:)9 b(:)d(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h +(:)f(:)g(:)g(:)g(:)g(:)g(:)16 b Fe(5)0 1590 y Fm(C)0 1656 y +Fc(call-last-)o(kb)o(d-m)o(ac)o(ro)9 b(\(C-x)j(e\))7 b Fd(:)f(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)20 +b Fe(12)0 1714 y Fc(capitalize)o(-w)o(ord)9 b(\(M-c\))s Fd(:)t(:)d(:)g(:)h(:) +f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)16 b Fe(11)0 1772 y Fc(clear-scre)o(en)9 b(\(C-l\))f +Fd(:)t(:)e(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:) +f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)21 b Fe(9)0 +1830 y(commen)o(t-b)q(egin)13 b Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)23 b Fe(5)0 1888 y Fc(complete)10 +b(\(TAB\))t Fd(:)s(:)c(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:) +g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g +(:)16 b Fe(12)0 1947 y(completion-query-i)q(tems)d Fd(:)6 b(:)g(:)g(:)g(:)h +(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)23 b Fe(6)0 2005 y Fc(completion)p 201 2005 +12 2 v 10 w(matches)6 b Fd(:)t(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:) +g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)19 +b Fe(29)0 2063 y(con)o(v)o(ert-meta)t Fd(:)6 b(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:) +g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)16 b Fe(5)0 +2180 y Fm(D)0 2247 y Fc(delete-cha)o(r)10 b(\(C-d\))e Fd(:)t(:)e(:)g(:)g(:)g +(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)21 b Fe(10)0 2305 y Fc(delete-hor)o(iz)o(ont)o +(al)o(-sp)o(ace)9 b(\(\))c Fd(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)18 b Fe(11)0 2363 y +Fc(digit-argu)o(me)o(nt)9 b(\(M-0,)i(M-1,)h(...)f(M--\))5 b +Fd(:)g(:)h(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)18 +b Fe(12)0 2421 y Fc(digit)p 102 2421 V 12 w(p)s Fd(:)6 b(:)g(:)g(:)g(:)g(:)h +(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)16 +b Fe(26)0 2479 y Fc(digit)p 102 2479 V 12 w(value)7 b Fd(:)t(:)f(:)g(:)g(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 +b Fe(26)0 2537 y Fc(ding)t Fd(:)5 b(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h +(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)17 +b Fe(25)0 2595 y Fc(do-upperca)o(se)o(-ve)o(rs)o(ion)9 b(\(M-a,)i(M-b,)g +(...\))d Fd(:)d(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)21 b +Fe(13)0 2653 y Fc(downcase-w)o(or)o(d)10 b(\(M-l\))c Fd(:)t(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)19 b Fe(11)1015 399 y Fc(dump-functi)o(on)o(s)10 +b(\(\))e Fd(:)d(:)i(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22 +b Fe(13)1015 513 y Fm(E)1015 579 y Fe(editing-mo)q(de)t Fd(:)9 +b(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)17 b Fe(5)1015 637 y Fc(end-kbd-mac)o(ro)9 b(\(C-x)j(\)\))7 +b Fd(:)t(:)f(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h +(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fe(12)1015 695 +y Fc(end-of-hist)o(or)o(y)10 b(\(M->\))c Fd(:)t(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)19 b Fe(9)1015 754 y Fc(end-of-line)9 b(\(C-e\))e +Fd(:)g(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:) +g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)22 +b Fe(8)1015 812 y(expand-tilde)10 b Fd(:)f(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:) +g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)22 b Fe(6)1015 925 +y Fm(F)1015 992 y Fc(filename)p 1177 992 V 12 w(completi)o(on)p +1388 992 V 11 w(function)5 b Fd(:)s(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)18 b Fe(30)1015 1050 y Fc(forward-cha)o(r) +10 b(\(C-f\))e Fd(:)t(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)21 +b Fe(8)1015 1108 y Fc(forward-sea)o(rc)o(h-h)o(ist)o(or)o(y)10 +b(\(C-s\))t Fd(:)t(:)c(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:) +g(:)g(:)g(:)g(:)g(:)17 b Fe(9)1015 1166 y Fc(forward-wor)o(d)10 +b(\(M-f\))e Fd(:)t(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:) +g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)21 +b Fe(8)1015 1224 y Fc(free)p 1097 1224 V 13 w(undo)p 1190 1224 +V 13 w(list)6 b Fd(:)t(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:) +g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)19 b Fe(23)1015 1338 y Fm(H)1015 1404 y Fc(history-sea)o(rc)o(h-b)o +(ack)o(wa)o(rd)9 b(\(\))d Fd(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)19 b Fe(9)1015 1462 +y Fc(history-sea)o(rc)o(h-f)o(orw)o(ar)o(d)10 b(\(\))e Fd(:)d(:)h(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)21 +b Fe(9)1015 1521 y(horizon)o(tal-scrol)q(l)q(-mo)q(de)t Fd(:)9 +b(:)d(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)17 b Fe(5)1015 1634 +y Fm(I)1015 1701 y Fc(insert-comp)o(le)o(tio)o(ns)9 b(\(\))s +Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:) +g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)16 b Fe(12)1015 1814 y +Fm(K)1015 1881 y Fe(k)o(eymap)6 b Fd(:)h(:)f(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 +b Fe(6)1015 1939 y Fc(kill-line)10 b(\(C-k\))f Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)24 b Fe(11)1015 1997 y Fc(kill-whole-)o(li)o +(ne)10 b(\(\))d Fd(:)e(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:) +g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)20 +b Fe(11)1015 2055 y Fc(kill-word)10 b(\(M-d\))f Fd(:)d(:)g(:)g(:)g(:)g(:)g(:) +g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)24 b Fe(11)1015 2169 y Fm(L)1015 +2235 y Fc(lowercase)p 1197 2235 V 11 w(p)7 b Fd(:)f(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)20 b Fe(26)1015 +2349 y Fm(M)1015 2415 y Fe(mark-mo)q(di\014ed-li)q(nes)8 b +Fd(:)h(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:) +g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)20 +b Fe(5)1015 2473 y(meta-\015ag)11 b Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h +(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)23 +b Fe(5)1015 2587 y Fm(N)1015 2653 y Fc(next-histor)o(y)10 b(\(C-n\))e +Fd(:)t(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:) +g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)21 b Fe(9)p +eop +%%Page: 46 48 +47 bop 0 -83 a Fo(46)1449 b(GNU)15 b(Readline)i(Library)0 158 +y Fc(non-increm)o(en)o(tal)o(-f)o(orw)o(ard)o(-s)o(ear)o(ch)o(-hi)o(st)o(ory) +9 b(\(M-n\))g Fd(:)t(:)22 b Fe(9)0 216 y Fc(non-increm)o(en)o(tal)o(-r)o(eve) +o(rse)o(-s)o(ear)o(ch)o(-hi)o(st)o(ory)9 b(\(M-p\))g Fd(:)t(:)22 +b Fe(9)0 275 y Fc(numeric)9 b Fd(:)s(:)e(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22 b Fe(25)0 +394 y Fm(O)0 460 y Fe(output-meta)8 b Fd(:)g(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)21 b Fe(5)0 +580 y Fm(P)0 646 y Fc(possible-c)o(om)o(ple)o(ti)o(ons)9 b(\(M-?\))c +Fd(:)g(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:) +g(:)g(:)g(:)18 b Fe(12)0 704 y Fc(prefix-met)o(a)10 b(\(ESC\))e +Fd(:)t(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:) +g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)21 b Fe(13)0 +762 y Fc(previous-h)o(is)o(tor)o(y)10 b(\(C-p\))f Fd(:)d(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g +(:)g(:)24 b Fe(9)0 882 y Fm(Q)0 948 y Fc(quoted-ins)o(er)o(t)10 +b(\(C-q,)h(C-v\))e Fd(:)d(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)24 b Fe(10)0 1068 y +Fm(R)0 1134 y Fc(re-read-in)o(it)o(-fi)o(le)9 b(\(C-x)i(C-r\))c +Fd(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:) +g(:)g(:)20 b Fe(13)0 1192 y Fc(readline)8 b Fd(:)s(:)e(:)g(:)g(:)g(:)g(:)g(:) +g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h +(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)21 +b Fe(15)0 1250 y Fc(redraw-cur)o(re)o(nt-)o(li)o(ne)9 b(\(\))i +Fd(:)6 b(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)24 b Fe(9)0 1308 y Fc(reverse-se)o(ar)o +(ch-)o(hi)o(sto)o(ry)9 b(\(C-r\))t Fd(:)t(:)d(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)16 b Fe(9)0 1367 +y Fc(revert-lin)o(e)10 b(\(M-r\))e Fd(:)t(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)g(:)g(:)21 b Fe(13)0 1425 y Fc(rl)p 42 1425 12 2 v 13 w(add)p +115 1425 V 13 w(defun)8 b Fd(:)d(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)g(:)g(:)g(:)21 b Fe(20)0 1483 y Fc(rl)p 42 1483 +V 13 w(add)p 115 1483 V 13 w(undo)8 b Fd(:)e(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)22 b Fe(23)0 1541 +y Fc(rl)p 42 1541 V 13 w(attempted)p 235 1541 V 11 w(completion)p +445 1541 V 10 w(function)15 b Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:) +g(:)g(:)g(:)h(:)17 b Fe(30)0 1599 y Fc(rl)p 42 1599 V 13 w(basic)p +155 1599 V 13 w(word)p 248 1599 V 12 w(break)p 360 1599 V 12 +w(characters)i Fd(:)6 b(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)23 b Fe(31)0 1657 y Fc(rl)p 42 1657 V 13 w(begin)p +155 1657 V 13 w(undo)p 248 1657 V 12 w(group)9 b Fd(:)d(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)h(:)f(:)g(:)23 b Fe(23)0 1715 y Fc(rl)p 42 1715 V 13 +w(bind)p 135 1715 V 13 w(key)8 b Fd(:)e(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)22 b Fe(21)0 1773 y +Fc(rl)p 42 1773 V 13 w(bind)p 135 1773 V 13 w(key)p 208 1773 +V 13 w(in)p 261 1773 V 13 w(map)6 b Fd(:)f(:)h(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:) +g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)19 b Fe(21)0 1831 y Fc(rl)p 42 1831 V 13 w(clear)p +155 1831 V 13 w(message)s Fd(:)s(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:) +g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)16 b Fe(25)0 1890 y Fc(rl)p 42 1890 V 13 w(complete)7 +b Fd(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)23 +b Fe(28,)13 b(29)0 1948 y Fc(rl)p 42 1948 V 13 w(complete)p +215 1948 V 11 w(internal)7 b Fd(:)s(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)19 +b Fe(29)0 2006 y Fc(rl)p 42 2006 V 13 w(completer)p 235 2006 +V 11 w(quote)p 346 2006 V 12 w(characters)f Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)21 b Fe(32)0 2064 +y Fc(rl)p 42 2064 V 13 w(completer)p 235 2064 V 11 w(word)p +326 2064 V 13 w(break)p 439 2064 V 12 w(character)o(s)15 b +Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b +Fe(31)0 2122 y Fc(rl)p 42 2122 V 13 w(completion)p 254 2122 +V 11 w(entry)p 366 2122 V 12 w(function)c Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:) +g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)17 b Fe(29,)c(30)0 2180 y Fc(rl)p +42 2180 V 13 w(completion)p 254 2180 V 11 w(query)p 366 2180 +V 12 w(items)j Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b Fe(30)0 2238 y Fc(rl)p +42 2238 V 13 w(copy)p 135 2238 V 13 w(keymap)6 b Fd(:)s(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)18 b Fe(20)0 2296 +y Fc(rl)p 42 2296 V 13 w(copy)p 135 2296 V 13 w(text)8 b Fd(:)d(:)h(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)21 +b Fe(25)0 2355 y Fc(rl)p 42 2355 V 13 w(delete)p 175 2355 V +12 w(text)6 b Fd(:)t(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h +(:)f(:)18 b Fe(25)0 2413 y Fc(rl)p 42 2413 V 13 w(discard)p +195 2413 V 12 w(keymap)8 b Fd(:)e(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g +(:)23 b Fe(20)0 2471 y Fc(rl)p 42 2471 V 13 w(do)p 95 2471 +V 14 w(undo)9 b Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:) +g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)24 b Fe(24)0 2529 y Fc(rl)p 42 2529 +V 13 w(done)17 b Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)18 b Fe(18)0 2587 y +Fc(rl)p 42 2587 V 13 w(end)h Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)19 b +Fe(18)0 2645 y Fc(rl)p 42 2645 V 13 w(end)p 115 2645 V 13 w(undo)p +208 2645 V 13 w(group)5 b Fd(:)t(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f +(:)g(:)17 b Fe(23)1015 158 y Fc(rl)p 1057 158 V 14 w(filename)p +1231 158 V 11 w(completio)o(n)p 1441 158 V 11 w(desired)g Fd(:)7 +b(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)20 +b Fe(31)1015 216 y Fc(rl)p 1057 216 V 14 w(filename)p 1231 +216 V 11 w(quoting)p 1382 216 V 11 w(desired)h Fd(:)7 b(:)f(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)24 b +Fe(31)1015 275 y Fc(rl)p 1057 275 V 14 w(forced)p 1191 275 +V 12 w(update)p 1323 275 V 11 w(display)t Fd(:)t(:)6 b(:)g(:)g(:)g(:)g(:)g(:) +g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)17 +b Fe(24)1015 333 y Fc(rl)p 1057 333 V 14 w(function)p 1231 +333 V 11 w(of)p 1282 333 V 13 w(keyseq)8 b Fd(:)t(:)e(:)g(:)g(:)g(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g +(:)21 b Fe(22)1015 391 y Fc(rl)p 1057 391 V 14 w(generic)p +1211 391 V 11 w(bind)t Fd(:)5 b(:)h(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)18 b Fe(22)1015 449 y Fc(rl)p 1057 449 V 14 +w(get)p 1131 449 V 13 w(keymap)7 b Fd(:)t(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)20 b Fe(21)1015 507 y Fc(rl)p +1057 507 V 14 w(get)p 1131 507 V 13 w(keymap)p 1264 507 V 12 +w(by)p 1316 507 V 13 w(name)9 b Fd(:)d(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:) +g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)24 +b Fe(21)1015 565 y Fc(rl)p 1057 565 V 14 w(ignore)p 1191 565 +V 12 w(completio)o(n)p 1402 565 V 11 w(duplicate)o(s)16 b Fd(:)6 +b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)19 +b Fe(31)1015 623 y Fc(rl)p 1057 623 V 14 w(ignore)p 1191 623 +V 12 w(some)p 1283 623 V 12 w(completion)o(s)p 1514 623 V 11 +w(function)13 b Fd(:)6 b(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17 +b Fe(31)1015 681 y Fc(rl)p 1057 681 V 14 w(insert)p 1191 681 +V 12 w(completio)o(ns)t Fd(:)t(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 +b Fe(29)1015 739 y Fc(rl)p 1057 739 V 14 w(insert)p 1191 739 +V 12 w(text)6 b Fd(:)t(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:) +g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)19 b Fe(25)1015 798 y Fc(rl)p 1057 798 V 14 w(instream)f +Fd(:)6 b(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g +(:)22 b Fe(19)1015 856 y Fc(rl)p 1057 856 V 14 w(invoking)p +1231 856 V 11 w(keyseqs)8 b Fd(:)s(:)e(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:) +g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)21 +b Fe(22)1015 914 y Fc(rl)p 1057 914 V 14 w(invoking)p 1231 +914 V 11 w(keyseqs)p 1382 914 V 11 w(in)p 1433 914 V 14 w(map)t +Fd(:)5 b(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)18 b Fe(22)1015 972 y Fc(rl)p 1057 972 V +14 w(kill)p 1151 972 V 12 w(text)8 b Fd(:)d(:)h(:)g(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)21 b Fe(25)1015 1030 +y Fc(rl)p 1057 1030 V 14 w(line)p 1151 1030 V 12 w(buffer)e +Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)21 +b Fe(18)1015 1088 y Fc(rl)p 1057 1088 V 14 w(make)p 1151 1088 +V 12 w(bare)p 1243 1088 V 13 w(keymap)8 b Fd(:)e(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)24 b Fe(20)1015 1146 y Fc(rl)p 1057 1146 V 14 w(make)p +1151 1146 V 12 w(keymap)6 b Fd(:)t(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:) +h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)19 b Fe(20)1015 1204 y Fc(rl)p 1057 1204 +V 14 w(mark)e Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:) +h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b Fe(18)1015 1263 y Fc(rl)p +1057 1263 V 14 w(message)8 b Fd(:)s(:)e(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)21 b Fe(24)1015 1321 +y Fc(rl)p 1057 1321 V 14 w(modifying)t Fd(:)t(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b Fe(24)1015 +1379 y Fc(rl)p 1057 1379 V 14 w(named)p 1171 1379 V 12 w(function)7 +b Fd(:)f(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h +(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)24 b +Fe(22)1015 1437 y Fc(rl)p 1057 1437 V 14 w(on)p 1111 1437 V +13 w(new)p 1184 1437 V 13 w(line)8 b Fd(:)d(:)h(:)g(:)g(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22 b Fe(24)1015 1495 y Fc(rl)p +1057 1495 V 14 w(outstream)17 b Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)21 b Fe(19)1015 1553 y Fc(rl)p +1057 1553 V 14 w(parse)p 1171 1553 V 12 w(and)p 1243 1553 V +13 w(bind)5 b Fd(:)t(:)h(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18 +b Fe(22)1015 1611 y Fc(rl)p 1057 1611 V 14 w(pending)p 1211 +1611 V 11 w(input)e Fd(:)6 b(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)19 b Fe(19)1015 1669 y Fc(rl)p 1057 1669 V 14 w(point)c +Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)h(:)f(:)17 b Fe(18)1015 1727 y Fc(rl)p 1057 1727 +V 14 w(possible)p 1231 1727 V 11 w(completio)o(ns)8 b Fd(:)e(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)25 b Fe(29)1015 1786 y Fc(rl)p 1057 1786 V 14 w(prompt)d +Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)25 b Fe(19)1015 1844 y Fc(rl)p 1057 1844 V 14 w(readline)p +1231 1844 V 11 w(name)16 b Fd(:)6 b(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)19 b Fe(19)1015 1902 y Fc(rl)p 1057 1902 V 14 w(redisplay)t +Fd(:)t(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)19 b Fe(24)1015 1960 y Fc(rl)p 1057 1960 V 14 w(reset)p +1171 1960 V 12 w(line)p 1263 1960 V 13 w(state)8 b Fd(:)e(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)24 b Fe(24)1015 2018 y Fc(rl)p 1057 2018 +V 14 w(reset)p 1171 2018 V 12 w(terminal)7 b Fd(:)f(:)g(:)h(:)f(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)24 b Fe(25)1015 2076 y Fc(rl)p 1057 +2076 V 14 w(set)p 1131 2076 V 13 w(keymap)7 b Fd(:)t(:)f(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)20 b Fe(21)1015 +2134 y Fc(rl)p 1057 2134 V 14 w(special)p 1211 2134 V 11 w(prefixes)g +Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)23 b Fe(31)1015 +2192 y Fc(rl)p 1057 2192 V 14 w(startup)p 1211 2192 V 11 w(hook)18 +b Fd(:)6 b(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:) +g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 +b Fe(19)1015 2250 y Fc(rl)p 1057 2250 V 14 w(terminal)p 1231 +2250 V 11 w(name)c Fd(:)6 b(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)19 b Fe(19)1015 2309 y Fc(rl)p 1057 2309 V 14 w(unbind)p +1191 2309 V 12 w(key)7 b Fd(:)e(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)20 b Fe(21)1015 2367 y Fc(rl)p 1057 +2367 V 14 w(unbind)p 1191 2367 V 12 w(key)p 1263 2367 V 13 +w(in)p 1316 2367 V 13 w(map)t Fd(:)t(:)6 b(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:) +g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:) +17 b Fe(21)1015 2521 y Fm(S)1015 2587 y Fc(self-insert)9 b(\(a,)j(b,)g(A,)g +(1,)g(!,)g(...\))6 b Fd(:)f(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)h(:)19 b Fe(10)1015 2645 y(sho)o(w-all-if-am)o(bigu)q(ous)9 +b Fd(:)g(:)d(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22 b Fe(6)p +eop +%%Page: 47 49 +48 bop 0 -83 a Fo(F)l(unction)16 b(and)f(V)l(ariable)i(Index)1337 +b(47)0 158 y Fc(start-kbd-)o(ma)o(cro)9 b(\(C-x)i(\(\))t Fd(:)6 +b(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)17 b Fe(12)0 266 y Fm(T)0 333 y Fc(tab-insert)9 +b(\(M-TAB\))e Fd(:)s(:)f(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)20 +b Fe(10)0 391 y Fc(tilde-expa)o(nd)9 b(\(M-~\))e Fd(:)t(:)f(:)g(:)h(:)f(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)20 b Fe(13)0 449 y Fc(to)p 42 449 12 +2 v 13 w(lower)9 b Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)23 b Fe(26)0 507 y Fc(to)p +42 507 V 13 w(upper)9 b Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:) +g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)23 b Fe(26)0 565 y Fc(transpose-)o(ch) +o(ars)9 b(\(C-t\))s Fd(:)t(:)d(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:) +g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)16 +b Fe(10)0 623 y Fc(transpose-)o(wo)o(rds)9 b(\(M-t\))s Fd(:)t(:)d(:)g(:)h(:)f +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)16 b Fe(10)0 731 y Fm(U)0 798 y Fc(undo)11 b(\(C-)p +153 798 V 13 w(,)i(C-x)e(C-u\))c Fd(:)e(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)20 b Fe(13)1015 158 y Fc(universal-a)o(rg)o(ume)o(nt)9 +b(\(\))s Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)16 b Fe(12)1015 +216 y Fc(unix-line-d)o(is)o(car)o(d)10 b(\(C-u\))f Fd(:)t(:)d(:)g(:)g(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)22 +b Fe(11)1015 275 y Fc(unix-word-r)o(ub)o(out)9 b(\(C-w\))g +Fd(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:) +g(:)g(:)g(:)g(:)g(:)g(:)g(:)24 b Fe(11)1015 333 y Fc(upcase-word)9 +b(\(M-u\))f Fd(:)t(:)f(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:) +g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22 +b Fe(10)1015 391 y Fc(uppercase)p 1197 391 V 11 w(p)7 b Fd(:)f(:)g(:)g(:)g(:) +g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)20 +b Fe(26)1015 449 y Fc(username)p 1177 449 V 12 w(completi)o(on)p +1388 449 V 11 w(function)5 b Fd(:)s(:)h(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)18 b Fe(30)1015 557 y Fm(Y)1015 +623 y Fc(yank)12 b(\(C-y\))d Fd(:)t(:)d(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)22 b Fe(11)1015 681 +y Fc(yank-last-a)o(rg)9 b(\(M-.,)i(M-)p 1436 681 V 13 w(\))6 +b Fd(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)g(:)g(:)g(:)g(:)g(:)g(:)19 b Fe(10)1015 739 y Fc(yank-nth-ar)o(g)10 +b(\(M-C-y\))t Fd(:)s(:)d(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)18 b +Fe(10)1015 798 y Fc(yank-pop)10 b(\(M-y\))t Fd(:)t(:)c(:)g(:)g(:)g(:)g(:)g(:) +g(:)g(:)h(:)f(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)g(:)17 b Fe(11)p eop +%%Page: 48 50 +49 bop 0 -83 a Fo(48)1449 b(GNU)15 b(Readline)i(Library)p eop +%%Page: -1 51 +50 bop 1937 -83 a Fo(i)0 158 y Fk(T)-7 b(able)15 b(of)g(Con)n(ten)n(ts)0 +333 y Fm(1)67 b(Command)22 b(Line)i(Editing)13 b Fb(:)f(:)e(:)h(:)f(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)36 b Fm(1)149 411 y Fo(1.1)45 b(In)o(tro)q(duction)16 +b(to)f(Line)h(Editing)5 b Fa(:)k(:)e(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)20 b Fo(1)149 473 y(1.2)45 b(Readline)17 +b(In)o(teraction)6 b Fa(:)i(:)g(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h +(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)21 +b Fo(1)299 535 y(1.2.1)44 b(Readline)17 b(Bare)e(Essen)o(tials)f +Fa(:)7 b(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)27 +b Fo(2)299 597 y(1.2.2)44 b(Readline)17 b(Mo)o(v)o(emen)o(t)d(Commands)f +Fa(:)7 b(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)27 b Fo(2)299 660 y(1.2.3)44 +b(Readline)17 b(Killing)h(Commands)9 b Fa(:)e(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)23 b Fo(3)299 722 y(1.2.4)44 b(Readline)17 b(Argumen)o(ts)5 +b Fa(:)i(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g +(:)19 b Fo(4)149 784 y(1.3)45 b(Readline)17 b(Init)g(File)d +Fa(:)8 b(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)28 b Fo(4)299 +846 y(1.3.1)44 b(Readline)17 b(Init)f(Syn)o(tax)11 b Fa(:)d(:)f(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)25 b Fo(4)299 +909 y(1.3.2)44 b(Conditional)16 b(Init)g(Constructs)d Fa(:)7 +b(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)27 b Fo(7)149 971 y(1.4)45 +b(Bindable)17 b(Readline)h(Commands)9 b Fa(:)e(:)g(:)g(:)g(:)g(:)h(:)f(:)g(:) +g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)23 b Fo(8)299 1033 y(1.4.1)44 +b(Commands)14 b(F)l(or)h(Mo)o(ving)t Fa(:)7 b(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h +(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h +(:)f(:)g(:)g(:)g(:)h(:)f(:)18 b Fo(8)299 1095 y(1.4.2)44 b(Commands)14 +b(F)l(or)h(Manipulating)i(The)e(History)9 b Fa(:)e(:)g(:)g(:)h(:)f(:)g(:)g(:) +g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)23 b Fo(9)299 1158 y(1.4.3)44 +b(Commands)14 b(F)l(or)h(Changing)h(T)l(ext)10 b Fa(:)c(:)i(:)f(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)25 b Fo(10)299 1220 y(1.4.4)44 b(Killing)18 b(And)e(Y)l(anking)10 +b Fa(:)e(:)f(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)25 +b Fo(11)299 1282 y(1.4.5)44 b(Sp)q(ecifying)17 b(Numeric)f(Argumen)o(ts)8 +b Fa(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)22 b Fo(12)299 1345 y(1.4.6)44 +b(Letting)15 b(Readline)j(T)o(yp)q(e)d(F)l(or)g(Y)l(ou)5 b +Fa(:)i(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:) +g(:)g(:)g(:)h(:)f(:)g(:)g(:)20 b Fo(12)299 1407 y(1.4.7)44 +b(Keyb)q(oard)15 b(Macros)9 b Fa(:)e(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)24 b Fo(12)299 1469 y(1.4.8)44 +b(Some)15 b(Miscellaneous)i(Commands)11 b Fa(:)d(:)f(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)27 +b Fo(13)149 1531 y(1.5)45 b(Readline)17 b(vi)f(Mo)q(de)d Fa(:)7 +b(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h +(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)27 b Fo(13)0 1656 y Fm(2)67 +b(Programming)23 b(with)g(GNU)f(Readline)d Fb(:)10 b(:)g(:)g(:)h(:)f(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)41 b Fm(15)149 1734 y Fo(2.1)k(Basic)16 +b(Beha)o(vior)9 b Fa(:)e(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)23 +b Fo(15)149 1796 y(2.2)45 b(Custom)14 b(F)l(unctions)6 b Fa(:)j(:)e(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)h(:)f(:)g(:)21 b Fo(17)299 1858 y(2.2.1)44 b(The)15 +b(F)l(unction)h(T)o(yp)q(e)e Fa(:)7 b(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)h(:)f(:)g(:)28 b Fo(17)299 1920 y(2.2.2)44 b(W)l(riting)16 +b(a)e(New)i(F)l(unction)6 b Fa(:)h(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:) +h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)h(:)20 b Fo(18)149 1983 y(2.3)45 b(Readline)17 b(Con)o(v)o(enience)g(F)l +(unctions)8 b Fa(:)g(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h +(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)23 +b Fo(19)299 2045 y(2.3.1)44 b(Naming)15 b(a)g(F)l(unction)t +Fa(:)9 b(:)e(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f +(:)19 b Fo(19)299 2107 y(2.3.2)44 b(Selecting)17 b(a)e(Keymap)8 +b Fa(:)g(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)23 +b Fo(20)299 2170 y(2.3.3)44 b(Binding)17 b(Keys)11 b Fa(:)d(:)f(:)g(:)g(:)h +(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)26 +b Fo(21)299 2232 y(2.3.4)44 b(Asso)q(ciating)16 b(F)l(unction)g(Names)f(and)g +(Bindings)7 b Fa(:)i(:)e(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)22 +b Fo(22)299 2294 y(2.3.5)44 b(Allo)o(wing)16 b(Undoing)7 b +Fa(:)i(:)e(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:) +g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g +(:)22 b Fo(23)299 2356 y(2.3.6)44 b(Redispla)o(y)9 b Fa(:)f(:)g(:)f(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)h(:)23 b Fo(24)299 2419 y(2.3.7)44 b(Mo)q(difying)16 +b(T)l(ext)11 b Fa(:)d(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h +(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)h(:)26 b Fo(25)299 2481 y(2.3.8)44 b(Utilit)o(y)16 +b(F)l(unctions)7 b Fa(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)22 b Fo(25)299 2543 y(2.3.9)44 b(An)15 +b(Example)c Fa(:)d(:)g(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:) +g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)26 b Fo(26)149 2605 y(2.4)45 +b(Custom)14 b(Completers)c Fa(:)e(:)f(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)25 +b Fo(28)p eop +%%Page: -2 52 +51 bop 0 -83 a Fo(ii)1471 b(GNU)15 b(Readline)i(Library)299 +17 y(2.4.1)44 b(Ho)o(w)14 b(Completing)i(W)l(orks)10 b Fa(:)c(:)i(:)f(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)24 b Fo(28)299 79 y(2.4.2)44 +b(Completion)16 b(F)l(unctions)7 b Fa(:)h(:)f(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g +(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)h(:)f(:)22 b Fo(29)299 141 y(2.4.3)44 b(Completion)16 +b(V)l(ariables)e Fa(:)7 b(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g +(:)g(:)28 b Fo(30)299 203 y(2.4.4)44 b(A)15 b(Short)g(Completion)h(Example)11 +b Fa(:)d(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)26 b Fo(32)0 328 y Fm(Concept)c(Index)5 +b Fb(:)12 b(:)e(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g +(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g +(:)h(:)f(:)g(:)g(:)g(:)h(:)28 b Fm(43)0 468 y(F)-6 b(unction)25 +b(and)d(V)-6 b(ariable)24 b(Index)11 b Fb(:)g(:)f(:)g(:)h(:)f(:)g(:)g(:)h(:)f +(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)h(:)f(:)g(:)g(:)h(:)f(:)g(:)g(:)g(:)34 +b Fm(45)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/doc/rlman.texinfo b/doc/rlman.texinfo new file mode 100644 index 0000000..ec14066 --- /dev/null +++ b/doc/rlman.texinfo @@ -0,0 +1,111 @@ +\input texinfo @c -*-texinfo-*- +@comment %**start of header (This is for running Texinfo on a region.) +@setfilename readline.info +@settitle GNU Readline Library +@comment %**end of header (This is for running Texinfo on a region.) +@synindex vr fn +@setchapternewpage odd + +@ignore +last change: Thu Jul 21 16:02:40 EDT 1994 +@end ignore + +@set EDITION 2.0 +@set VERSION 2.0 +@set UPDATED 21 July 1994 +@set UPDATE-MONTH July 1994 + +@ifinfo +This document describes the GNU Readline Library, a utility which aids +in the consistency of user interface across discrete programs that need +to provide a command line interface. + +Copyright (C) 1988, 1991 Free Software Foundation, Inc. + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +pare 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 Foundation. +@end ifinfo + +@titlepage +@sp 10 +@title GNU Readline Library +@subtitle Edition @value{EDITION}, for @code{Readline Library} Version @value{VERSION}. +@subtitle @value{UPDATE-MONTH} +@author Brian Fox, Free Software Foundation +@author Chet Ramey, Case Western Reserve University + +@page +This document describes the GNU Readline Library, a utility which aids +in the consistency of user interface across discrete programs that need +to provide a command line interface. + +Published by the Free Software Foundation @* +675 Massachusetts Avenue, @* +Cambridge, MA 02139 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 Foundation. + +@vskip 0pt plus 1filll +Copyright @copyright{} 1989, 1991 Free Software Foundation, Inc. +@end titlepage + +@ifinfo +@node Top +@top GNU Readline Library + +This document describes the GNU Readline Library, a utility which aids +in the consistency of user interface across discrete programs that need +to provide a command line interface. + +@menu +* Command Line Editing:: GNU Readline User's Manual. +* Programming with GNU Readline:: GNU Readline Programmer's Manual. +* Concept Index:: Index of concepts described in this manual. +* Function and Variable Index:: Index of externally visible functions + and variables. +@end menu +@end ifinfo + +@include rluser.texinfo +@include rltech.texinfo + +@node Concept Index +@unnumbered Concept Index +@printindex cp + +@node Function and Variable Index +@unnumbered Function and Variable Index +@printindex fn + +@contents +@bye diff --git a/doc/rltech.texinfo b/doc/rltech.texinfo new file mode 100644 index 0000000..f24ac1f --- /dev/null +++ b/doc/rltech.texinfo @@ -0,0 +1,1356 @@ +@comment %**start of header (This is for running Texinfo on a region.) +@setfilename rltech.info +@comment %**end of header (This is for running Texinfo on a region.) +@setchapternewpage odd + +@ifinfo +This document describes the GNU Readline Library, a utility for aiding +in the consitency of user interface across discrete programs that need +to provide a command line interface. + +Copyright (C) 1988, 1994 Free Software Foundation, Inc. + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +pare 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 Foundation. +@end ifinfo + +@node Programming with GNU Readline +@chapter Programming with GNU Readline + +This chapter describes the interface between the GNU Readline Library and +other programs. If you are a programmer, and you wish to include the +features found in GNU Readline +such as completion, line editing, and interactive history manipulation +in your own programs, this section is for you. + +@menu +* Basic Behavior:: Using the default behavior of Readline. +* Custom Functions:: Adding your own functions to Readline. +* Readline Convenience Functions:: Functions which Readline supplies to + aid in writing your own +* Custom Completers:: Supplanting or supplementing Readline's + completion functions. +@end menu + +@node Basic Behavior +@section Basic Behavior + +Many programs provide a command line interface, such as @code{mail}, +@code{ftp}, and @code{sh}. For such programs, the default behaviour of +Readline is sufficient. This section describes how to use Readline in +the simplest way possible, perhaps to replace calls in your code to +@code{gets()} or @code{fgets ()}. + +@findex readline +@cindex readline, function +The function @code{readline ()} prints a prompt and then reads and returns +a single line of text from the user. The line @code{readline} +returns is allocated with @code{malloc ()}; you should @code{free ()} +the line when you are done with it. The declaration for @code{readline} +in ANSI C is + +@example +@code{char *readline (char *@var{prompt});} +@end example + +@noindent +So, one might say +@example +@code{char *line = readline ("Enter a line: ");} +@end example +@noindent +in order to read a line of text from the user. +The line returned has the final newline removed, so only the +text remains. + +If @code{readline} encounters an @code{EOF} while reading the line, and the +line is empty at that point, then @code{(char *)NULL} is returned. +Otherwise, the line is ended just as if a newline had been typed. + +If you want the user to be able to get at the line later, (with +@key{C-p} for example), you must call @code{add_history ()} to save the +line away in a @dfn{history} list of such lines. + +@example +@code{add_history (line)}; +@end example + +@noindent +For full details on the GNU History Library, see the associated manual. + +It is preferable to avoid saving empty lines on the history list, since +users rarely have a burning need to reuse a blank line. Here is +a function which usefully replaces the standard @code{gets ()} library +function, and has the advantage of no static buffer to overflow: + +@example +/* A static variable for holding the line. */ +static char *line_read = (char *)NULL; + +/* Read a string, and return a pointer to it. Returns NULL on EOF. */ +char * +rl_gets () +@{ + /* If the buffer has already been allocated, return the memory + to the free pool. */ + if (line_read) + @{ + free (line_read); + line_read = (char *)NULL; + @} + + /* Get a line from the user. */ + line_read = readline (""); + + /* If the line has any text in it, save it on the history. */ + if (line_read && *line_read) + add_history (line_read); + + return (line_read); +@} +@end example + +This function gives the user the default behaviour of @key{TAB} +completion: completion on file names. If you do not want Readline to +complete on filenames, you can change the binding of the @key{TAB} key +with @code{rl_bind_key ()}. + +@example +@code{int rl_bind_key (int @var{key}, int (*@var{function})());} +@end example + +@code{rl_bind_key ()} takes two arguments: @var{key} is the character that +you want to bind, and @var{function} is the address of the function to +call when @var{key} is pressed. Binding @key{TAB} to @code{rl_insert ()} +makes @key{TAB} insert itself. +@code{rl_bind_key ()} returns non-zero if @var{key} is not a valid +ASCII character code (between 0 and 255). + +Thus, to disable the default @key{TAB} behavior, the following suffices: +@example +@code{rl_bind_key ('\t', rl_insert);} +@end example + +This code should be executed once at the start of your program; you +might write a function called @code{initialize_readline ()} which +performs this and other desired initializations, such as installing +custom completers (@pxref{Custom Completers}). + +@node Custom Functions +@section Custom Functions + +Readline provides many functions for manipulating the text of +the line, but it isn't possible to anticipate the needs of all +programs. This section describes the various functions and variables +defined within the Readline library which allow a user program to add +customized functionality to Readline. + +@menu +* The Function Type:: C declarations to make code readable. +* Function Writing:: Variables and calling conventions. +@end menu + +@node The Function Type +@subsection The Function Type + +For readabilty, we declare a new type of object, called +@dfn{Function}. A @code{Function} is a C function which +returns an @code{int}. The type declaration for @code{Function} is: + +@noindent +@code{typedef int Function ();} + +The reason for declaring this new type is to make it easier to write +code describing pointers to C functions. Let us say we had a variable +called @var{func} which was a pointer to a function. Instead of the +classic C declaration + +@code{int (*)()func;} + +@noindent +we may write + +@code{Function *func;} + +@noindent +Similarly, there are + +@example +typedef void VFunction (); +typedef char *CPFunction (); @r{and} +typedef char **CPPFunction (); +@end example + +@noindent +for functions returning no value, @code{pointer to char}, and +@code{pointer to pointer to char}, respectively. + +@node Function Writing +@subsection Writing a New Function + +In order to write new functions for Readline, you need to know the +calling conventions for keyboard-invoked functions, and the names of the +variables that describe the current state of the line read so far. + +The calling sequence for a command @code{foo} looks like + +@example +@code{foo (int count, int key)} +@end example + +@noindent +where @var{count} is the numeric argument (or 1 if defaulted) and +@var{key} is the key that invoked this function. + +It is completely up to the function as to what should be done with the +numeric argument. Some functions use it as a repeat count, some +as a flag, and others to choose alternate behavior (refreshing the current +line as opposed to refreshing the screen, for example). Some choose to +ignore it. In general, if a +function uses the numeric argument as a repeat count, it should be able +to do something useful with both negative and positive arguments. +At the very least, it should be aware that it can be passed a +negative argument. + +@deftypevar {char *} rl_line_buffer +This is the line gathered so far. You are welcome to modify the +contents of the line, but see @ref{Allowing Undoing}. +@end deftypevar + +@deftypevar int rl_point +The offset of the current cursor position in @code{rl_line_buffer} +(the @emph{point}). +@end deftypevar + +@deftypevar int rl_end +The number of characters present in @code{rl_line_buffer}. When +@code{rl_point} is at the end of the line, @code{rl_point} and +@code{rl_end} are equal. +@end deftypevar + +@deftypevar int rl_mark +The mark (saved position) in the current line. If set, the mark +and point define a @emph{region}. +@end deftypevar + +@deftypevar int rl_done +Setting this to a non-zero value causes Readline to return the current +line immediately. +@end deftypevar + +@deftypevar int rl_pending_input +Setting this to a value makes it the next keystroke read. This is a +way to stuff a single character into the input stream. +@end deftypevar + +@deftypevar {char *} rl_prompt +The prompt Readline uses. This is set from the argument to +@code{readline ()}, and should not be assigned to directly. +@end deftypevar + +@deftypevar {char *} rl_terminal_name +The terminal type, used for initialization. +@end deftypevar + +@deftypevar {char *} rl_readline_name +This variable is set to a unique name by each application using Readline. +The value allows conditional parsing of the inputrc file +(@pxref{Conditional Init Constructs}). +@end deftypevar + +@deftypevar {FILE *} rl_instream +The stdio stream from which Readline reads input. +@end deftypevar + +@deftypevar {FILE *} rl_outstream +The stdio stream to which Readline performs output. +@end deftypevar + +@deftypevar {Function *} rl_startup_hook +If non-zero, this is the address of a function to call just +before @code{readline} prints the first prompt. +@end deftypevar + +@node Readline Convenience Functions +@section Readline Convenience Functions + +@menu +* Function Naming:: How to give a function you write a name. +* Keymaps:: Making keymaps. +* Binding Keys:: Changing Keymaps. +* Associating Function Names and Bindings:: Translate function names to + key sequences. +* Allowing Undoing:: How to make your functions undoable. +* Redisplay:: Functions to control line display. +* Modifying Text:: Functions to modify @code{rl_line_buffer}. +* Utility Functions:: Generally useful functions and hooks. +@end menu + +@node Function Naming +@subsection Naming a Function + +The user can dynamically change the bindings of keys while using +Readline. This is done by representing the function with a descriptive +name. The user is able to type the descriptive name when referring to +the function. Thus, in an init file, one might find + +@example +Meta-Rubout: backward-kill-word +@end example + +This binds the keystroke @key{Meta-Rubout} to the function +@emph{descriptively} named @code{backward-kill-word}. You, as the +programmer, should bind the functions you write to descriptive names as +well. Readline provides a function for doing that: + +@deftypefun int rl_add_defun (char *name, Function *function, int key) +Add @var{name} to the list of named functions. Make @var{function} be +the function that gets called. If @var{key} is not -1, then bind it to +@var{function} using @code{rl_bind_key ()}. +@end deftypefun + +Using this function alone is sufficient for most applications. It is +the recommended way to add a few functions to the default functions that +Readline has built in. If you need to do something other +than adding a function to Readline, you may need to use the +underlying functions described below. + +@node Keymaps +@subsection Selecting a Keymap + +Key bindings take place on a @dfn{keymap}. The keymap is the +association between the keys that the user types and the functions that +get run. You can make your own keymaps, copy existing keymaps, and tell +Readline which keymap to use. + +@deftypefun Keymap rl_make_bare_keymap () +Returns a new, empty keymap. The space for the keymap is allocated with +@code{malloc ()}; you should @code{free ()} it when you are done. +@end deftypefun + +@deftypefun Keymap rl_copy_keymap (Keymap map) +Return a new keymap which is a copy of @var{map}. +@end deftypefun + +@deftypefun Keymap rl_make_keymap () +Return a new keymap with the printing characters bound to rl_insert, +the lowercase Meta characters bound to run their equivalents, and +the Meta digits bound to produce numeric arguments. +@end deftypefun + +@deftypefun void rl_discard_keymap (Keymap keymap) +Free the storage associated with @var{keymap}. +@end deftypefun + +Readline has several internal keymaps. These functions allow you to +change which keymap is active. + +@deftypefun Keymap rl_get_keymap () +Returns the currently active keymap. +@end deftypefun + +@deftypefun void rl_set_keymap (Keymap keymap) +Makes @var{keymap} the currently active keymap. +@end deftypefun + +@deftypefun Keymap rl_get_keymap_by_name (char *name) +Return the keymap matching @var{name}. @var{name} is one which would +be supplied in a @code{set keymap} inputrc line (@pxref{Readline Init File}). +@end deftypefun + +@node Binding Keys +@subsection Binding Keys + +You associate keys with functions through the keymap. Readline has +several internal keymaps: @code{emacs_standard_keymap}, +@code{emacs_meta_keymap}, @code{emacs_ctlx_keymap}, +@code{vi_movement_keymap}, and @code{vi_insertion_keymap}. +@code{emacs_standard_keymap} is the default, and the examples in +this manual assume that. + +These functions manage key bindings. + +@deftypefun int rl_bind_key (int key, Function *function) +Binds @var{key} to @var{function} in the currently active keymap. +Returns non-zero in the case of an invalid @var{key}. +@end deftypefun + +@deftypefun int rl_bind_key_in_map (int key, Function *function, Keymap map) +Bind @var{key} to @var{function} in @var{map}. Returns non-zero in the case +of an invalid @var{key}. +@end deftypefun + +@deftypefun int rl_unbind_key (int key) +Bind @var{key} to the null function in the currently active keymap. +Returns non-zero in case of error. +@end deftypefun + +@deftypefun int rl_unbind_key_in_map (int key, Keymap map) +Bind @var{key} to the null function in @var{map}. +Returns non-zero in case of error. +@end deftypefun + +@deftypefun int rl_generic_bind (int type, char *keyseq, char *data, Keymap map) +Bind the key sequence represented by the string @var{keyseq} to the arbitrary +pointer @var{data}. @var{type} says what kind of data is pointed to by +@var{data}; this can be a function (@code{ISFUNC}), a macro +(@code{ISMACR}), or a keymap (@code{ISKMAP}). This makes new keymaps as +necessary. The initial keymap in which to do bindings is @var{map}. +@end deftypefun + +@deftypefun int rl_parse_and_bind (char *line) +Parse @var{line} as if it had been read from the @code{inputrc} file and +perform any key bindings and variable assignments found +(@pxref{Readline Init File}). +@end deftypefun + +@node Associating Function Names and Bindings +@subsection Associating Function Names and Bindings + +These functions allow you to find out what keys invoke named functions +and the functions invoked by a particular key sequence. + +@deftypefun {Function *} rl_named_function (char *name) +Return the function with name @var{name}. +@end deftypefun + +@deftypefun {Function *} rl_function_of_keyseq (char *keyseq, Keymap map, int *type) +Return the function invoked by @var{keyseq} in keymap @var{map}. +If @var{map} is NULL, the current keymap is used. If @var{type} is +not NULL, the type of the object is returned in it (one of @code{ISFUNC}, +@code{ISKMAP}, or @code{ISMACR}). +@end deftypefun + +@deftypefun {char **} rl_invoking_keyseqs (Function *function) +Return an array of strings representing the key sequences used to +invoke @var{function} in the current keymap. +@end deftypefun + +@deftypefun {char **} rl_invoking_keyseqs_in_map (Function *function, Keymap map) +Return an array of strings representing the key sequences used to +invoke @var{function} in the keymap @var{map}. +@end deftypefun + +@node Allowing Undoing +@subsection Allowing Undoing + +Supporting the undo command is a painless thing, and makes your +functions much more useful. It is certainly easy to try +something if you know you can undo it. I could use an undo function for +the stock market. + +If your function simply inserts text once, or deletes text once, and +uses @code{rl_insert_text ()} or @code{rl_delete_text ()} to do it, then +undoing is already done for you automatically. + +If you do multiple insertions or multiple deletions, or any combination +of these operations, you should group them together into one operation. +This is done with @code{rl_begin_undo_group ()} and +@code{rl_end_undo_group ()}. + +The types of events that can be undone are: + +@example +enum undo_code @{ UNDO_DELETE, UNDO_INSERT, UNDO_BEGIN, UNDO_END @}; +@end example + +Notice that @code{UNDO_DELETE} means to insert some text, and +@code{UNDO_INSERT} means to delete some text. That is, the undo code +tells undo what to undo, not how to undo it. @code{UNDO_BEGIN} and +@code{UNDO_END} are tags added by @code{rl_begin_undo_group ()} and +@code{rl_end_undo_group ()}. + +@deftypefun int rl_begin_undo_group () +Begins saving undo information in a group construct. The undo +information usually comes from calls to @code{rl_insert_text ()} and +@code{rl_delete_text ()}, but could be the result of calls to +@code{rl_add_undo ()}. +@end deftypefun + +@deftypefun int rl_end_undo_group () +Closes the current undo group started with @code{rl_begin_undo_group +()}. There should be one call to @code{rl_end_undo_group ()} +for each call to @code{rl_begin_undo_group ()}. +@end deftypefun + +@deftypefun void rl_add_undo (enum undo_code what, int start, int end, char *text) +Remember how to undo an event (according to @var{what}). The affected +text runs from @var{start} to @var{end}, and encompasses @var{text}. +@end deftypefun + +@deftypefun void free_undo_list () +Free the existing undo list. +@end deftypefun + +@deftypefun int rl_do_undo () +Undo the first thing on the undo list. Returns @code{0} if there was +nothing to undo, non-zero if something was undone. +@end deftypefun + +Finally, if you neither insert nor delete text, but directly modify the +existing text (e.g., change its case), call @code{rl_modifying ()} +once, just before you modify the text. You must supply the indices of +the text range that you are going to modify. + +@deftypefun int rl_modifying (int start, int end) +Tell Readline to save the text between @var{start} and @var{end} as a +single undo unit. It is assumed that you will subsequently modify +that text. +@end deftypefun + +@node Redisplay +@subsection Redisplay + +@deftypefun int rl_redisplay () +Change what's displayed on the screen to reflect the current contents +of @code{rl_line_buffer}. +@end deftypefun + +@deftypefun int rl_forced_update_display () +Force the line to be updated and redisplayed, whether or not +Readline thinks the screen display is correct. +@end deftypefun + +@deftypefun int rl_on_new_line () +Tell the update routines that we have moved onto a new (empty) line, +usually after ouputting a newline. +@end deftypefun + +@deftypefun int rl_reset_line_state () +Reset the display state to a clean state and redisplay the current line +starting on a new line. +@end deftypefun + +@deftypefun int rl_message (va_alist) +The arguments are a string as would be supplied to @code{printf}. The +resulting string is displayed in the @dfn{echo area}. The echo area +is also used to display numeric arguments and search strings. +@end deftypefun + +@deftypefun int rl_clear_message () +Clear the message in the echo area. +@end deftypefun + +@node Modifying Text +@subsection Modifying Text + +@deftypefun int rl_insert_text (char *text) +Insert @var{text} into the line at the current cursor position. +@end deftypefun + +@deftypefun int rl_delete_text (int start, int end) +Delete the text between @var{start} and @var{end} in the current line. +@end deftypefun + +@deftypefun {char *} rl_copy_text (int start, int end) +Return a copy of the text between @var{start} and @var{end} in +the current line. +@end deftypefun + +@deftypefun int rl_kill_text (int start, int end) +Copy the text between @var{start} and @var{end} in the current line +to the kill ring, appending or prepending to the last kill if the +last command was a kill command. The text is deleted. +If @var{start} is less than @var{end}, +the text is appended, otherwise prepended. If the last command was +not a kill, a new kill ring slot is used. +@end deftypefun + +@node Utility Functions +@subsection Utility Functions + +@deftypefun int rl_reset_terminal (char *terminal_name) +Reinitialize Readline's idea of the terminal settings using +@var{terminal_name} as the terminal type (e.g., @code{vt100}). +@end deftypefun + +@deftypefun int alphabetic (int c) +Return 1 if @var{c} is an alphabetic character. +@end deftypefun + +@deftypefun int numeric (int c) +Return 1 if @var{c} is a numeric character. +@end deftypefun + +@deftypefun int ding () +Ring the terminal bell, obeying the setting of @code{bell-style}. +@end deftypefun + +The following are implemented as macros, defined in @code{chartypes.h}. + +@deftypefun int uppercase_p (int c) +Return 1 if @var{c} is an uppercase alphabetic character. +@end deftypefun + +@deftypefun int lowercase_p (int c) +Return 1 if @var{c} is a lowercase alphabetic character. +@end deftypefun + +@deftypefun int digit_p (int c) +Return 1 if @var{c} is a numeric character. +@deftypefun + +@deftypefun int to_upper (int c) +If @var{c} is a lowercase alphabetic character, return the corresponding +uppercase character. +@end deftypefun + +@deftypefun int to_lower (int c) +If @var{c} is an uppercase alphabetic character, return the corresponding +lowercase character. +@end deftypefun + +@deftypefun int digit_value (int c) +If @var{c} is a number, return the value it represents. +@end deftypefun + +@subsection An Example + +Here is a function which changes lowercase characters to their uppercase +equivalents, and uppercase characters to lowercase. If +this function was bound to @samp{M-c}, then typing @samp{M-c} would +change the case of the character under point. Typing @samp{M-1 0 M-c} +would change the case of the following 10 characters, leaving the cursor on +the last character changed. + +@example +/* Invert the case of the COUNT following characters. */ +int +invert_case_line (count, key) + int count, key; +@{ + register int start, end, i; + + start = rl_point; + + if (rl_point >= rl_end) + return (0); + + if (count < 0) + @{ + direction = -1; + count = -count; + @} + else + direction = 1; + + /* Find the end of the range to modify. */ + end = start + (count * direction); + + /* Force it to be within range. */ + if (end > rl_end) + end = rl_end; + else if (end < 0) + end = 0; + + if (start == end) + return (0); + + if (start > end) + @{ + int temp = start; + start = end; + end = temp; + @} + + /* Tell readline that we are modifying the line, so it will save + the undo information. */ + rl_modifying (start, end); + + for (i = start; i != end; i++) + @{ + if (uppercase_p (rl_line_buffer[i])) + rl_line_buffer[i] = to_lower (rl_line_buffer[i]); + else if (lowercase_p (rl_line_buffer[i])) + rl_line_buffer[i] = to_upper (rl_line_buffer[i]); + @} + /* Move point to on top of the last character changed. */ + rl_point = (direction == 1) ? end - 1 : start; + return (0); +@} +@end example + +@node Custom Completers +@section Custom Completers + +Typically, a program that reads commands from the user has a way of +disambiguating commands and data. If your program is one of these, then +it can provide completion for commands, data, or both. +The following sections describe how your program and Readline +cooperate to provide this service. + +@menu +* How Completing Works:: The logic used to do completion. +* Completion Functions:: Functions provided by Readline. +* Completion Variables:: Variables which control completion. +* A Short Completion Example:: An example of writing completer subroutines. +@end menu + +@node How Completing Works +@subsection How Completing Works + +In order to complete some text, the full list of possible completions +must be available. That is, it is not possible to accurately +expand a partial word without knowing all of the possible words +which make sense in that context. The Readline library provides +the user interface to completion, and two of the most common +completion functions: filename and username. For completing other types +of text, you must write your own completion function. This section +describes exactly what such functions must do, and provides an example. + +There are three major functions used to perform completion: + +@enumerate +@item +The user-interface function @code{rl_complete ()}. This function is +called with the same arguments as other Readline +functions intended for interactive use: @var{count} and +@var{invoking_key}. It isolates the word to be completed and calls +@code{completion_matches ()} to generate a list of possible completions. +It then either lists the possible completions, inserts the possible +completions, or actually performs the +completion, depending on which behavior is desired. + +@item +The internal function @code{completion_matches ()} uses your +@dfn{generator} function to generate the list of possible matches, and +then returns the array of these matches. You should place the address +of your generator function in @code{rl_completion_entry_function}. + +@item +The generator function is called repeatedly from +@code{completion_matches ()}, returning a string each time. The +arguments to the generator function are @var{text} and @var{state}. +@var{text} is the partial word to be completed. @var{state} is zero the +first time the function is called, allowing the generator to perform +any necessary initialization, and a positive non-zero integer for +each subsequent call. When the generator function returns +@code{(char *)NULL} this signals @code{completion_matches ()} that there are +no more possibilities left. Usually the generator function computes the +list of possible completions when @var{state} is zero, and returns them +one at a time on subsequent calls. Each string the generator function +returns as a match must be allocated with @code{malloc()}; Readline +frees the strings when it has finished with them. + +@end enumerate + +@deftypefun int rl_complete (int ignore, int invoking_key) +Complete the word at or before point. You have supplied the function +that does the initial simple matching selection algorithm (see +@code{completion_matches ()}). The default is to do filename completion. +@end deftypefun + +@deftypevar {Function *} rl_completion_entry_function +This is a pointer to the generator function for @code{completion_matches +()}. If the value of @code{rl_completion_entry_function} is +@code{(Function *)NULL} then the default filename generator function, +@code{filename_entry_function ()}, is used. +@end deftypevar + +@node Completion Functions +@subsection Completion Functions + +Here is the complete list of callable completion functions present in +Readline. + +@deftypefun int rl_complete_internal (int what_to_do) +Complete the word at or before point. @var{what_to_do} says what to do +with the completion. A value of @samp{?} means list the possible +completions. @samp{TAB} means do standard completion. @samp{*} means +insert all of the possible completions. @samp{!} means to display +all of the possible completions, if there is more than one, as well as +performing partial completion. +@end deftypefun + +@deftypefun int rl_complete (int ignore, int invoking_key) +Complete the word at or before point. You have supplied the function +that does the initial simple matching selection algorithm (see +@code{completion_matches ()} and @code{rl_completion_entry_function}). +The default is to do filename +completion. This calls @code{rl_complete_internal ()} with an +argument depending on @var{invoking_key}. +@end deftypefun + +@deftypefun int rl_possible_completions (int count, int invoking_key)) +List the possible completions. See description of @code{rl_complete +()}. This calls @code{rl_complete_internal ()} with an argument of +@samp{?}. +@end deftypefun + +@deftypefun int rl_insert_completions (int count, int invoking_key)) +Insert the list of possible completions into the line, deleting the +partially-completed word. See description of @code{rl_complete ()}. +This calls @code{rl_complete_internal ()} with an argument of @samp{*}. +@end deftypefun + +@deftypefun {char **} completion_matches (char *text, CPFunction *entry_func) +Returns an array of @code{(char *)} which is a list of completions for +@var{text}. If there are no completions, returns @code{(char **)NULL}. +The first entry in the returned array is the substitution for @var{text}. +The remaining entries are the possible completions. The array is +terminated with a @code{NULL} pointer. + +@var{entry_func} is a function of two args, and returns a +@code{(char *)}. The first argument is @var{text}. The second is a +state argument; it is zero on the first call, and non-zero on subsequent +calls. @var{entry_func} returns a @code{NULL} pointer to the caller +when there are no more matches. +@end deftypefun + +@deftypefun {char *} filename_completion_function (char *text, int state) +A generator function for filename completion in the general case. Note +that completion in Bash is a little different because of all +the pathnames that must be followed when looking up completions for a +command. The Bash source is a useful reference for writing custom +completion functions. +@end deftypefun + +@deftypefun {char *} username_completion_function (char *text, int state) +A completion generator for usernames. @var{text} contains a partial +username preceded by a random character (usually @samp{~}). As with all +completion generators, @var{state} is zero on the first call and non-zero +for subsequent calls. +@end deftypefun + +@node Completion Variables +@subsection Completion Variables + +@deftypevar {Function *} rl_completion_entry_function +A pointer to the generator function for @code{completion_matches ()}. +@code{NULL} means to use @code{filename_entry_function ()}, the default +filename completer. +@end deftypevar + +@deftypevar {CPPFunction *} rl_attempted_completion_function +A pointer to an alternative function to create matches. +The function is called with @var{text}, @var{start}, and @var{end}. +@var{start} and @var{end} are indices in @code{rl_line_buffer} saying +what the boundaries of @var{text} are. If this function exists and +returns @code{NULL}, or if this variable is set to @code{NULL}, then +@code{rl_complete ()} will call the value of +@code{rl_completion_entry_function} to generate matches, otherwise the +array of strings returned will be used. +@end deftypevar + +@deftypevar int rl_completion_query_items +Up to this many items will be displayed in response to a +possible-completions call. After that, we ask the user if she is sure +she wants to see them all. The default value is 100. +@end deftypevar + +@deftypevar {char *} rl_basic_word_break_characters +The basic list of characters that signal a break between words for the +completer routine. The default value of this variable is the characters +which break words for completion in Bash, i.e., +@code{" \t\n\"\\'`@@$><=;|&@{("}. +@end deftypevar + +@deftypevar {char *} rl_completer_word_break_characters +The list of characters that signal a break between words for +@code{rl_complete_internal ()}. The default list is the value of +@code{rl_basic_word_break_characters}. +@end deftypevar + +@deftypevar {char *} rl_special_prefixes +The list of characters that are word break characters, but should be +left in @var{text} when it is passed to the completion function. +Programs can use this to help determine what kind of completing to do. +For instance, Bash sets this variable to "$@@" so that it can complete +shell variables and hostnames. +@end deftypevar + +@deftypevar int rl_ignore_completion_duplicates +If non-zero, then disallow duplicates in the matches. Default is 1. +@end deftypevar + +@deftypevar int rl_filename_completion_desired +Non-zero means that the results of the matches are to be treated as +filenames. This is @emph{always} zero on entry, and can only be changed +within a completion entry generator function. If it is set to a non-zero +value, directory names have a slash appended and Readline attempts to +quote completed filenames if they contain any embedded word break +characters. +@end deftypevar + +@deftypevar int rl_filename_quoting_desired +Non-zero means that the results of the matches are to be quoted using +double quotes (or an application-specific quoting mechanism) if the +completed filename contains any characters in +@code{rl_completer_word_break_chars}. This is @emph{always} non-zero +on entry, and can only be changed within a completion entry generator +function. +@end deftypevar + +@deftypevar {Function *} rl_ignore_some_completions_function +This function, if defined, is called by the completer when real filename +completion is done, after all the matching names have been generated. +It is passed a @code{NULL} terminated array of matches. +The first element (@code{matches[0]}) is the +maximal substring common to all matches. This function can +re-arrange the list of matches as required, but each element deleted +from the array must be freed. +@end deftypevar + +@deftypevar {char *} rl_completer_quote_characters +List of characters which can be used to quote a substring of the line. +Completion occurs on the entire substring, and within the substring +@code{rl_completer_word_break_characters} are treated as any other character, +unless they also appear within this list. +@end deftypevar + + +@node A Short Completion Example +@subsection A Short Completion Example + +Here is a small application demonstrating the use of the GNU Readline +library. It is called @code{fileman}, and the source code resides in +@file{examples/fileman.c}. This sample application provides +completion of command names, line editing features, and access to the +history list. + +@page +@smallexample +/* fileman.c -- A tiny application which demonstrates how to use the + GNU Readline library. This application interactively allows users + to manipulate files and their modes. */ + +#include +#include +#include +#include +#include + +#include +#include + +extern char *getwd (); +extern char *xmalloc (); + +/* The names of functions that actually do the manipulation. */ +int com_list (), com_view (), com_rename (), com_stat (), com_pwd (); +int com_delete (), com_help (), com_cd (), com_quit (); + +/* A structure which contains information on the commands this program + can understand. */ + +typedef struct @{ + char *name; /* User printable name of the function. */ + Function *func; /* Function to call to do the job. */ + char *doc; /* Documentation for this function. */ +@} COMMAND; + +COMMAND commands[] = @{ + @{ "cd", com_cd, "Change to directory DIR" @}, + @{ "delete", com_delete, "Delete FILE" @}, + @{ "help", com_help, "Display this text" @}, + @{ "?", com_help, "Synonym for `help'" @}, + @{ "list", com_list, "List files in DIR" @}, + @{ "ls", com_list, "Synonym for `list'" @}, + @{ "pwd", com_pwd, "Print the current working directory" @}, + @{ "quit", com_quit, "Quit using Fileman" @}, + @{ "rename", com_rename, "Rename FILE to NEWNAME" @}, + @{ "stat", com_stat, "Print out statistics on FILE" @}, + @{ "view", com_view, "View the contents of FILE" @}, + @{ (char *)NULL, (Function *)NULL, (char *)NULL @} +@}; + +/* Forward declarations. */ +char *stripwhite (); +COMMAND *find_command (); + +/* The name of this program, as taken from argv[0]. */ +char *progname; + +/* When non-zero, this global means the user is done using this program. */ +int done; + +char * +dupstr (s) + int s; +@{ + char *r; + + r = xmalloc (strlen (s) + 1); + strcpy (r, s); + return (r); +@} + +main (argc, argv) + int argc; + char **argv; +@{ + char *line, *s; + + progname = argv[0]; + + initialize_readline (); /* Bind our completer. */ + + /* Loop reading and executing lines until the user quits. */ + for ( ; done == 0; ) + @{ + line = readline ("FileMan: "); + + if (!line) + break; + + /* Remove leading and trailing whitespace from the line. + Then, if there is anything left, add it to the history list + and execute it. */ + s = stripwhite (line); + + if (*s) + @{ + add_history (s); + execute_line (s); + @} + + free (line); + @} + exit (0); +@} + +/* Execute a command line. */ +int +execute_line (line) + char *line; +@{ + register int i; + COMMAND *command; + char *word; + + /* Isolate the command word. */ + i = 0; + while (line[i] && whitespace (line[i])) + i++; + word = line + i; + + while (line[i] && !whitespace (line[i])) + i++; + + if (line[i]) + line[i++] = '\0'; + + command = find_command (word); + + if (!command) + @{ + fprintf (stderr, "%s: No such command for FileMan.\n", word); + return (-1); + @} + + /* Get argument to command, if any. */ + while (whitespace (line[i])) + i++; + + word = line + i; + + /* Call the function. */ + return ((*(command->func)) (word)); +@} + +/* Look up NAME as the name of a command, and return a pointer to that + command. Return a NULL pointer if NAME isn't a command name. */ +COMMAND * +find_command (name) + char *name; +@{ + register int i; + + for (i = 0; commands[i].name; i++) + if (strcmp (name, commands[i].name) == 0) + return (&commands[i]); + + return ((COMMAND *)NULL); +@} + +/* Strip whitespace from the start and end of STRING. Return a pointer + into STRING. */ +char * +stripwhite (string) + char *string; +@{ + register char *s, *t; + + for (s = string; whitespace (*s); s++) + ; + + if (*s == 0) + return (s); + + t = s + strlen (s) - 1; + while (t > s && whitespace (*t)) + t--; + *++t = '\0'; + + return s; +@} + +/* **************************************************************** */ +/* */ +/* Interface to Readline Completion */ +/* */ +/* **************************************************************** */ + +char *command_generator (); +char **fileman_completion (); + +/* Tell the GNU Readline library how to complete. We want to try to complete + on command names if this is the first word in the line, or on filenames + if not. */ +initialize_readline () +@{ + /* Allow conditional parsing of the ~/.inputrc file. */ + rl_readline_name = "FileMan"; + + /* Tell the completer that we want a crack first. */ + rl_attempted_completion_function = (CPPFunction *)fileman_completion; +@} + +/* Attempt to complete on the contents of TEXT. START and END show the + region of TEXT that contains the word to complete. We can use the + entire line in case we want to do some simple parsing. Return the + array of matches, or NULL if there aren't any. */ +char ** +fileman_completion (text, start, end) + char *text; + int start, end; +@{ + char **matches; + + matches = (char **)NULL; + + /* If this word is at the start of the line, then it is a command + to complete. Otherwise it is the name of a file in the current + directory. */ + if (start == 0) + matches = completion_matches (text, command_generator); + + return (matches); +@} + +/* Generator function for command completion. STATE lets us know whether + to start from scratch; without any state (i.e. STATE == 0), then we + start at the top of the list. */ +char * +command_generator (text, state) + char *text; + int state; +@{ + static int list_index, len; + char *name; + + /* If this is a new word to complete, initialize now. This includes + saving the length of TEXT for efficiency, and initializing the index + variable to 0. */ + if (!state) + @{ + list_index = 0; + len = strlen (text); + @} + + /* Return the next name which partially matches from the command list. */ + while (name = commands[list_index].name) + @{ + list_index++; + + if (strncmp (name, text, len) == 0) + return (dupstr(name)); + @} + + /* If no names matched, then return NULL. */ + return ((char *)NULL); +@} + +/* **************************************************************** */ +/* */ +/* FileMan Commands */ +/* */ +/* **************************************************************** */ + +/* String to pass to system (). This is for the LIST, VIEW and RENAME + commands. */ +static char syscom[1024]; + +/* List the file(s) named in arg. */ +com_list (arg) + char *arg; +@{ + if (!arg) + arg = ""; + + sprintf (syscom, "ls -FClg %s", arg); + return (system (syscom)); +@} + +com_view (arg) + char *arg; +@{ + if (!valid_argument ("view", arg)) + return 1; + + sprintf (syscom, "more %s", arg); + return (system (syscom)); +@} + +com_rename (arg) + char *arg; +@{ + too_dangerous ("rename"); + return (1); +@} + +com_stat (arg) + char *arg; +@{ + struct stat finfo; + + if (!valid_argument ("stat", arg)) + return (1); + + if (stat (arg, &finfo) == -1) + @{ + perror (arg); + return (1); + @} + + printf ("Statistics for `%s':\n", arg); + + printf ("%s has %d link%s, and is %d byte%s in length.\n", arg, + finfo.st_nlink, + (finfo.st_nlink == 1) ? "" : "s", + finfo.st_size, + (finfo.st_size == 1) ? "" : "s"); + printf ("Inode Last Change at: %s", ctime (&finfo.st_ctime)); + printf (" Last access at: %s", ctime (&finfo.st_atime)); + printf (" Last modified at: %s", ctime (&finfo.st_mtime)); + return (0); +@} + +com_delete (arg) + char *arg; +@{ + too_dangerous ("delete"); + return (1); +@} + +/* Print out help for ARG, or for all of the commands if ARG is + not present. */ +com_help (arg) + char *arg; +@{ + register int i; + int printed = 0; + + for (i = 0; commands[i].name; i++) + @{ + if (!*arg || (strcmp (arg, commands[i].name) == 0)) + @{ + printf ("%s\t\t%s.\n", commands[i].name, commands[i].doc); + printed++; + @} + @} + + if (!printed) + @{ + printf ("No commands match `%s'. Possibilties are:\n", arg); + + for (i = 0; commands[i].name; i++) + @{ + /* Print in six columns. */ + if (printed == 6) + @{ + printed = 0; + printf ("\n"); + @} + + printf ("%s\t", commands[i].name); + printed++; + @} + + if (printed) + printf ("\n"); + @} + return (0); +@} + +/* Change to the directory ARG. */ +com_cd (arg) + char *arg; +@{ + if (chdir (arg) == -1) + @{ + perror (arg); + return 1; + @} + + com_pwd (""); + return (0); +@} + +/* Print out the current working directory. */ +com_pwd (ignore) + char *ignore; +@{ + char dir[1024], *s; + + s = getwd (dir); + if (s == 0) + @{ + printf ("Error getting pwd: %s\n", dir); + return 1; + @} + + printf ("Current directory is %s\n", dir); + return 0; +@} + +/* The user wishes to quit using this program. Just set DONE non-zero. */ +com_quit (arg) + char *arg; +@{ + done = 1; + return (0); +@} + +/* Function which tells you that you can't do this. */ +too_dangerous (caller) + char *caller; +@{ + fprintf (stderr, + "%s: Too dangerous for me to distribute. Write it yourself.\n", + caller); +@} + +/* Return non-zero if ARG is a valid argument for CALLER, else print + an error message and return zero. */ +int +valid_argument (caller, arg) + char *caller, *arg; +@{ + if (!arg || !*arg) + @{ + fprintf (stderr, "%s: Argument required.\n", caller); + return (0); + @} + + return (1); +@} +@end smallexample diff --git a/doc/rluser.texinfo b/doc/rluser.texinfo new file mode 100644 index 0000000..3567549 --- /dev/null +++ b/doc/rluser.texinfo @@ -0,0 +1,875 @@ +@comment %**start of header (This is for running Texinfo on a region.) +@setfilename rluser.info +@comment %**end of header (This is for running Texinfo on a region.) +@setchapternewpage odd + +@ignore +This file documents the end user interface to the GNU command line +editing features. It is to be an appendix to manuals for programs which +use these features. There is a document entitled "readline.texinfo" +which contains both end-user and programmer documentation for the GNU +Readline Library. + +Copyright (C) 1988 Free Software Foundation, Inc. + +Authored by Brian Fox and Chet Ramey. + +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). + +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 +GNU Copyright statement is available to the distributee, 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. +@end ignore + +@comment If you are including this manual as an appendix, then set the +@comment variable readline-appendix. + +@node Command Line Editing +@chapter Command Line Editing + +This chapter describes the basic features of the GNU +command line editing interface. + +@menu +* Introduction and Notation:: Notation used in this text. +* Readline Interaction:: The minimum set of commands for editing a line. +* Readline Init File:: Customizing Readline from a user's view. +* Bindable Readline Commands:: A description of most of the Readline commands + available for binding +* Readline vi Mode:: A short description of how to make Readline + behave like the vi editor. +@end menu + +@node Introduction and Notation +@section Introduction to Line Editing + +The following paragraphs describe the notation used to represent +keystrokes. + +The text @key{C-k} is read as `Control-K' and describes the character +produced when the Control key is depressed and the @key{k} key is struck. + +The text @key{M-k} is read as `Meta-K' and describes the character +produced when the meta key (if you have one) is depressed, and the @key{k} +key is struck. If you do not have a meta key, the identical keystroke +can be generated by typing @key{ESC} @i{first}, and then typing @key{k}. +Either process is known as @dfn{metafying} the @key{k} key. + +The text @key{M-C-k} is read as `Meta-Control-k' and describes the +character produced by @dfn{metafying} @key{C-k}. + +In addition, several keys have their own names. Specifically, +@key{DEL}, @key{ESC}, @key{LFD}, @key{SPC}, @key{RET}, and @key{TAB} all +stand for themselves when seen in this text, or in an init file +(@pxref{Readline Init File}, for more info). + +@node Readline Interaction +@section Readline Interaction +@cindex interaction, readline + +Often during an interactive session you type in a long line of text, +only to notice that the first word on the line is misspelled. The +Readline library gives you a set of commands for manipulating the text +as you type it in, allowing you to just fix your typo, and not forcing +you to retype the majority of the line. Using these editing commands, +you move the cursor to the place that needs correction, and delete or +insert the text of the corrections. Then, when you are satisfied with +the line, you simply press @key{RETURN}. You do not have to be at the +end of the line to press @key{RETURN}; the entire line is accepted +regardless of the location of the cursor within the line. + +@menu +* Readline Bare Essentials:: The least you need to know about Readline. +* Readline Movement Commands:: Moving about the input line. +* Readline Killing Commands:: How to delete text, and how to get it back! +* Readline Arguments:: Giving numeric arguments to commands. +@end menu + +@node Readline Bare Essentials +@subsection Readline Bare Essentials + +In order to enter characters into the line, simply type them. The typed +character appears where the cursor was, and then the cursor moves one +space to the right. If you mistype a character, you can use your +erase character to back up and delete the mistyped character. + +Sometimes you may miss typing a character that you wanted to type, and +not notice your error until you have typed several other characters. In +that case, you can type @key{C-b} to move the cursor to the left, and then +correct your mistake. Afterwards, you can move the cursor to the right +with @key{C-f}. + +When you add text in the middle of a line, you will notice that characters +to the right of the cursor are `pushed over' to make room for the text +that you have inserted. Likewise, when you delete text behind the cursor, +characters to the right of the cursor are `pulled back' to fill in the +blank space created by the removal of the text. A list of the basic bare +essentials for editing the text of an input line follows. + +@table @asis +@item @key{C-b} +Move back one character. +@item @key{C-f} +Move forward one character. +@item @key{DEL} +Delete the character to the left of the cursor. +@item @key{C-d} +Delete the character underneath the cursor. +@item @w{Printing characters} +Insert the character into the line at the cursor. +@item @key{C-_} +Undo the last thing that you did. You can undo all the way back to an +empty line. +@end table + +@node Readline Movement Commands +@subsection Readline Movement Commands + + +The above table describes the most basic possible keystrokes that you need +in order to do editing of the input line. For your convenience, many +other commands have been added in addition to @key{C-b}, @key{C-f}, +@key{C-d}, and @key{DEL}. Here are some commands for moving more rapidly +about the line. + +@table @key +@item C-a +Move to the start of the line. +@item C-e +Move to the end of the line. +@item M-f +Move forward a word. +@item M-b +Move backward a word. +@item C-l +Clear the screen, reprinting the current line at the top. +@end table + +Notice how @key{C-f} moves forward a character, while @key{M-f} moves +forward a word. It is a loose convention that control keystrokes +operate on characters while meta keystrokes operate on words. + +@node Readline Killing Commands +@subsection Readline Killing Commands + +@cindex Killing text +@cindex Yanking text + +@dfn{Killing} text means to delete the text from the line, but to save +it away for later use, usually by @dfn{yanking} (re-inserting) +it back into the line. +If the description for a command says that it `kills' text, then you can +be sure that you can get the text back in a different (or the same) +place later. + +When you use a kill command, the text is saved in a @dfn{kill-ring}. +Any number of consecutive kills save all of the killed text together, so +that when you yank it back, you get it all. The kill +ring is not line specific; the text that you killed on a previously +typed line is available to be yanked back later, when you are typing +another line. +@cindex Kill ring + +Here is the list of commands for killing text. + +@table @key +@item C-k +Kill the text from the current cursor position to the end of the line. + +@item M-d +Kill from the cursor to the end of the current word, or if between +words, to the end of the next word. + +@item M-DEL +Kill from the cursor the start of the previous word, or if between +words, to the start of the previous word. + +@item C-w +Kill from the cursor to the previous whitespace. This is different than +@key{M-DEL} because the word boundaries differ. + +@end table + +And, here is how to @dfn{yank} the text back into the line. Yanking +means to copy the most-recently-killed text from the kill buffer. + +@table @key +@item C-y +Yank the most recently killed text back into the buffer at the cursor. + +@item M-y +Rotate the kill-ring, and yank the new top. You can only do this if +the prior command is @key{C-y} or @key{M-y}. +@end table + +@node Readline Arguments +@subsection Readline Arguments + +You can pass numeric arguments to Readline commands. Sometimes the +argument acts as a repeat count, other times it is the @i{sign} of the +argument that is significant. If you pass a negative argument to a +command which normally acts in a forward direction, that command will +act in a backward direction. For example, to kill text back to the +start of the line, you might type @key{M--} @key{C-k}. + +The general way to pass numeric arguments to a command is to type meta +digits before the command. If the first `digit' you type is a minus +sign (@key{-}), then the sign of the argument will be negative. Once +you have typed one meta digit to get the argument started, you can type +the remainder of the digits, and then the command. For example, to give +the @key{C-d} command an argument of 10, you could type @key{M-1 0 C-d}. + + +@node Readline Init File +@section Readline Init File + +Although the Readline library comes with a set of Emacs-like +keybindings installed by default, +it is possible that you would like to use a different set +of keybindings. You can customize programs that use Readline by putting +commands in an @dfn{init} file in your home directory. The name of this +@ifset BashFeatures +file is taken from the value of the shell variable @code{INPUTRC}. If +@end ifset +@ifclear BashFeatures +file is taken from the value of the environment variable @code{INPUTRC}. If +@end ifclear +that variable is unset, the default is @file{~/.inputrc}. + +When a program which uses the Readline library starts up, the +init file is read, and the key bindings are set. + +In addition, the @code{C-x C-r} command re-reads this init file, thus +incorporating any changes that you might have made to it. + +@menu +* Readline Init Syntax:: Syntax for the commands in the inputrc file. +* Conditional Init Constructs:: Conditional key bindings in the inputrc file. +@end menu + +@node Readline Init Syntax +@subsection Readline Init Syntax + +There are only a few basic constructs allowed in the +Readline init file. Blank lines are ignored. +Lines beginning with a @key{#} are comments. +Lines beginning with a @key{$} indicate conditional +constructs (@pxref{Conditional Init Constructs}). Other lines +denote variable settings and key bindings. + +@table @asis +@item Variable Settings +You can change the state of a few variables in Readline by +using the @code{set} command within the init file. Here is how you +would specify that you wish to use @code{vi} line editing commands: + +@example +set editing-mode vi +@end example + +Right now, there are only a few variables which can be set; +so few, in fact, that we just list them here: + +@table @code + +@item editing-mode +@vindex editing-mode +The @code{editing-mode} variable controls which editing mode you are +using. By default, Readline starts up in Emacs editing mode, where +the keystrokes are most similar to Emacs. This variable can be +set to either @code{emacs} or @code{vi}. + +@item horizontal-scroll-mode +@vindex horizontal-scroll-mode +This variable can be set to either @code{On} or @code{Off}. Setting it +to @code{On} means that the text of the lines that you edit will scroll +horizontally on a single screen line when they are longer than the width +of the screen, instead of wrapping onto a new screen line. By default, +this variable is set to @code{Off}. + +@item mark-modified-lines +@vindex mark-modified-lines +This variable, when set to @code{On}, says to display an asterisk +(@samp{*}) at the start of history lines which have been modified. +This variable is @code{off} by default. + +@item bell-style +@vindex bell-style +Controls what happens when Readline wants to ring the terminal bell. +If set to @code{none}, Readline never rings the bell. If set to +@code{visible}, Readline uses a visible bell if one is available. +If set to @code{audible} (the default), Readline attempts to ring +the terminal's bell. + +@item comment-begin +@vindex comment-begin +The string to insert at the beginning of the line when the +@code{vi-comment} command is executed. The default value +is @code{"#"}. + +@item meta-flag +@vindex meta-flag +If set to @code{on}, Readline will enable eight-bit input (it +will not strip the eighth bit from the characters it reads), +regardless of what the terminal claims it can support. The +default value is @code{off}. + +@item convert-meta +@vindex convert-meta +If set to @code{on}, Readline will convert characters with the +eigth bit set to an ASCII key sequence by stripping the eigth +bit and prepending an @key{ESC} character, converting them to a +meta-prefixed key sequence. The default value is @code{on}. + +@item output-meta +@vindex output-meta +If set to @code{on}, Readline will display characters with the +eighth bit set directly rather than as a meta-prefixed escape +sequence. The default is @code{off}. + +@item completion-query-items +@vindex completion-query-items +The number of possible completions that determines when the user is +asked whether he wants to see the list of possibilities. If the +number of possible completions is greater than this value, +Readline will ask the user whether or not he wishes to view +them; otherwise, they are simply listed. The default limit is +@code{100}. + +@item keymap +@vindex keymap +Sets Readline's idea of the current keymap for key binding commands. +Acceptable @code{keymap} names are +@code{emacs}, +@code{emacs-standard}, +@code{emacs-meta}, +@code{emacs-ctlx}, +@code{vi}, +@code{vi-move}, +@code{vi-command}, and +@code{vi-insert}. +@code{vi} is equivalent to @code{vi-command}; @code{emacs} is +equivalent to @code{emacs-standard}. The default value is @code{emacs}. +The value of the @code{editing-mode} variable also affects the +default keymap. + +@item show-all-if-ambiguous +@vindex show-all-if-ambiguous +This alters the default behavior of the completion functions. If +set to @code{on}, +words which have more than one possible completion cause the +matches to be listed immediately instead of ringing the bell. +The default value is @code{off}. + +@item expand-tilde +@vindex expand-tilde +If set to @code{on}, tilde expansion is performed when Readline +attempts word completion. The default is @code{off}. + +@end table + +@item Key Bindings +The syntax for controlling key bindings in the init file is +simple. First you have to know the name of the command that you +want to change. The following pages contain tables of the command name, +the default keybinding, and a short description of what the command +does. + +Once you know the name of the command, simply place the name of the key +you wish to bind the command to, a colon, and then the name of the +command on a line in the init file. The name of the key +can be expressed in different ways, depending on which is most +comfortable for you. + +@table @asis +@item @w{@var{keyname}: @var{function-name} or @var{macro}} +@var{keyname} is the name of a key spelled out in English. For example: +@example +Control-u: universal-argument +Meta-Rubout: backward-kill-word +Control-o: ">&output" +@end example + +In the above example, @samp{C-u} is bound to the function +@code{universal-argument}, and @samp{C-o} is bound to run the macro +expressed on the right hand side (that is, to insert the text +@samp{>&output} into the line). + +@item @w{"@var{keyseq}": @var{function-name} or @var{macro}} +@var{keyseq} differs from @var{keyname} above in that strings +denoting an entire key sequence can be specified, by placing +the key sequence in double quotes. Some GNU Emacs style key +escapes can be used, as in the following example, but the +special character names are not recognized. + +@example +"\C-u": universal-argument +"\C-x\C-r": re-read-init-file +"\e[11~": "Function Key 1" +@end example + +In the above example, @samp{C-u} is bound to the function +@code{universal-argument} (just as it was in the first example), +@samp{C-x C-r} is bound to the function @code{re-read-init-file}, and +@samp{ESC [ 1 1 ~} is bound to insert the text @samp{Function Key 1}. +The following escape sequences are available when specifying key +sequences: + +@table @code +@item @kbd{\C-} +control prefix +@item @kbd{\M-} +meta prefix +@item @kbd{\e} +an escape character +@item @kbd{\\} +backslash +@item @kbd{\"} +@key{"} +@item @kbd{\'} +@key{'} +@end table + +When entering the text of a macro, single or double quotes should +be used to indicate a macro definition. Unquoted text +is assumed to be a function name. Backslash +will quote any character in the macro text, including @key{"} +and @key{'}. +For example, the following binding will make @kbd{C-x \} +insert a single @key{\} into the line: +@example +"\C-x\\": "\\" +@end example + +@end table +@end table + +@node Conditional Init Constructs +@subsection Conditional Init Constructs + +Readline implements a facility similar in spirit to the conditional +compilation features of the C preprocessor which allows key +bindings and variable settings to be performed as the result +of tests. There are three parser directives used. + +@ftable @code +@item $if +The @code{$if} construct allows bindings to be made based on the +editing mode, the terminal being used, or the application using +Readline. The text of the test extends to the end of the line; +no characters are required to isolate it. + +@table @code +@item mode +The @code{mode=} form of the @code{$if} directive is used to test +whether Readline is in @code{emacs} or @code{vi} mode. +This may be used in conjunction +with the @samp{set keymap} command, for instance, to set bindings in +the @code{emacs-standard} and @code{emacs-ctlx} keymaps only if +Readline is starting out in @code{emacs} mode. + +@item term +The @code{term=} form may be used to include terminal-specific +key bindings, perhaps to bind the key sequences output by the +terminal's function keys. The word on the right side of the +@samp{=} is tested against the full name of the terminal and the +portion of the terminal name before the first @samp{-}. This +allows @var{sun} to match both @var{sun} and @var{sun-cmd}, +for instance. + +@item application +The @var{application} construct is used to include +application-specific settings. Each program using the Readline +library sets the @var{application name}, and you can test for it. +This could be used to bind key sequences to functions useful for +a specific program. For instance, the following command adds a +key sequence that quotes the current or previous word in Bash: +@example +$if bash +# Quote the current or previous word +"\C-xq": "\eb\"\ef\"" +$endif +@end example +@end table + +@item $endif +This command, as you saw in the previous example, terminates an +@code{$if} command. + +@item $else +Commands in this branch of the @code{$if} directive are executed if +the test fails. +@end ftable + +@node Bindable Readline Commands +@section Bindable Readline Commands + +@menu +* Commands For Moving:: Moving about the line. +* Commands For History:: Getting at previous lines. +* Commands For Text:: Commands for changing text. +* Commands For Killing:: Commands for killing and yanking. +* Numeric Arguments:: Specifying numeric arguments, repeat counts. +* Commands For Completion:: Getting Readline to do the typing for you. +* Keyboard Macros:: Saving and re-executing typed characters +* Miscellaneous Commands:: Other miscellaneous commands. +@end menu + +@node Commands For Moving +@subsection Commands For Moving +@ftable @code +@item beginning-of-line (C-a) +Move to the start of the current line. + +@item end-of-line (C-e) +Move to the end of the line. + +@item forward-char (C-f) +Move forward a character. + +@item backward-char (C-b) +Move back a character. + +@item forward-word (M-f) +Move forward to the end of the next word. Words are composed of +letters and digits. + +@item backward-word (M-b) +Move back to the start of this, or the previous, word. Words are +composed of letters and digits. + +@item clear-screen (C-l) +Clear the screen and redraw the current line, +leaving the current line at the top of the screen. + +@item redraw-current-line () +Refresh the current line. By default, this is unbound. + +@end ftable + +@node Commands For History +@subsection Commands For Manipulating The History + +@ftable @code +@item accept-line (Newline, Return) +@ifset BashFeatures +Accept the line regardless of where the cursor is. If this line is +non-empty, add it to the history list according to the setting of +the @code{HISTCONTROL} variable. If this line was a history +line, then restore the history line to its original state. +@end ifset +@ifclear BashFeatures +Accept the line regardless of where the cursor is. If this line is +non-empty, add it to the history list. If this line was a history +line, then restore the history line to its original state. +@end ifclear + +@item previous-history (C-p) +Move `up' through the history list. + +@item next-history (C-n) +Move `down' through the history list. + +@item beginning-of-history (M-<) +Move to the first line in the history. + +@item end-of-history (M->) +Move to the end of the input history, i.e., the line you are entering. + +@item reverse-search-history (C-r) +Search backward starting at the current line and moving `up' through +the history as necessary. This is an incremental search. + +@item forward-search-history (C-s) +Search forward starting at the current line and moving `down' through +the the history as necessary. This is an incremental search. + +@item non-incremental-reverse-search-history (M-p) +Search backward starting at the current line and moving `up' +through the history as necessary using a non-incremental search +for a string supplied by the user. + +@item non-incremental-forward-search-history (M-n) +Search forward starting at the current line and moving `down' +through the the history as necessary using a non-incremental search +for a string supplied by the user. + +@item history-search-forward () +Search forward through the history for the string of characters +between the start of the current line and the current point. This +is a non-incremental search. By default, this command is unbound. + +@item history-search-backward () +Search backward through the history for the string of characters +between the start of the current line and the current point. This +is a non-incremental search. By default, this command is unbound. + +@item yank-nth-arg (M-C-y) +Insert the first argument to the previous command (usually +the second word on the previous line). With an argument @var{n}, +insert the @var{n}th word from the previous command (the words +in the previous command begin with word 0). A negative argument +inserts the @var{n}th word from the end of the previous command. + +@item yank-last-arg (M-., M-_) +Insert last argument to the previous command (the last word on the +previous line). With an +argument, behave exactly like @code{yank-nth-arg}. + +@end ftable + +@node Commands For Text +@subsection Commands For Changing Text + +@ftable @code +@item delete-char (C-d) +Delete the character under the cursor. If the cursor is at the +beginning of the line, there are no characters in the line, and +the last character typed was not C-d, then return EOF. + +@item backward-delete-char (Rubout) +Delete the character behind the cursor. A numeric arg says to kill +the characters instead of deleting them. + +@item quoted-insert (C-q, C-v) +Add the next character that you type to the line verbatim. This is +how to insert key sequences like @key{C-q}, for example. + +@item tab-insert (M-TAB) +Insert a tab character. + +@item self-insert (a, b, A, 1, !, ...) +Insert yourself. + +@item transpose-chars (C-t) +Drag the character before the cursor forward over +the character at the cursor, moving the +cursor forward as well. If the insertion point +is at the end of the line, then this +transposes the last two characters of the line. +Negative argumentss don't work. + +@item transpose-words (M-t) +Drag the word behind the cursor past the word in front of the cursor +moving the cursor over that word as well. + +@item upcase-word (M-u) +Uppercase the current (or following) word. With a negative argument, +do the previous word, but do not move the cursor. + +@item downcase-word (M-l) +Lowercase the current (or following) word. With a negative argument, +do the previous word, but do not move the cursor. + +@item capitalize-word (M-c) +Capitalize the current (or following) word. With a negative argument, +do the previous word, but do not move the cursor. + +@end ftable + +@node Commands For Killing +@subsection Killing And Yanking + +@ftable @code + +@item kill-line (C-k) +Kill the text from the current cursor position to the end of the line. + +@item backward-kill-line (C-x Rubout) +Kill backward to the beginning of the line. + +@item unix-line-discard (C-u) +Kill backward from the cursor to the beginning of the current line. +Save the killed text on the kill-ring. + +@item kill-whole-line () +Kill all characters on the current line, no matter where the +cursor is. By default, this is unbound. + +@item kill-word (M-d) +Kill from the cursor to the end of the current word, or if between +words, to the end of the next word. Word boundaries are the same +as @code{forward-word}. + +@item backward-kill-word (M-DEL) +Kill the word behind the cursor. Word boundaries are the same +as @code{backward-word}. + +@item unix-word-rubout (C-w) +Kill the word behind the cursor, using white space as a word +boundary. The killed text is saved on the kill-ring. + +@item delete-horizontal-space () +Delete all spaces and tabs around point. By default, this is unbound. + +@item yank (C-y) +Yank the top of the kill ring into the buffer at the current +cursor position. + +@item yank-pop (M-y) +Rotate the kill-ring, and yank the new top. You can only do this if +the prior command is yank or yank-pop. +@end ftable + +@node Numeric Arguments +@subsection Specifying Numeric Arguments +@ftable @code + +@item digit-argument (M-0, M-1, ... M--) +Add this digit to the argument already accumulating, or start a new +argument. M-- starts a negative argument. + +@item universal-argument () +Each time this is executed, the argument count is multiplied by four. +The argument count is initially one, so executing this function the +first time makes the argument count four. By default, this is not +bound to a key. +@end ftable + +@node Commands For Completion +@subsection Letting Readline Type For You + +@ftable @code +@item complete (TAB) +Attempt to do completion on the text before the cursor. This is +application-specific. Generally, if you are typing a filename +argument, you can do filename completion; if you are typing a command, +you can do command completion, if you are typing in a symbol to GDB, you +can do symbol name completion, if you are typing in a variable to Bash, +you can do variable name completion, and so on. +@ifset BashFeatures +See the Bash manual page for a complete list of available completion +functions. +@end ifset + +@item possible-completions (M-?) +List the possible completions of the text before the cursor. + +@item insert-completions () +Insert all completions of the text before point that would have +been generated by @code{possible-completions}. By default, this +is not bound to a key. + +@end ftable + +@node Keyboard Macros +@subsection Keyboard Macros +@ftable @code + +@item start-kbd-macro (C-x () +Begin saving the characters typed into the current keyboard macro. + +@item end-kbd-macro (C-x )) +Stop saving the characters typed into the current keyboard macro +and save the definition. + +@item call-last-kbd-macro (C-x e) +Re-execute the last keyboard macro defined, by making the characters +in the macro appear as if typed at the keyboard. + +@end ftable + +@node Miscellaneous Commands +@subsection Some Miscellaneous Commands +@ftable @code + +@item re-read-init-file (C-x C-r) +Read in the contents of your init file, and incorporate +any bindings or variable assignments found there. + +@item abort (C-g) +Abort the current editing command and +ring the terminal's bell (subject to the setting of +@code{bell-style}). + +@item do-uppercase-version (M-a, M-b, ...) +Run the command that is bound to the corresoponding uppercase +character. + +@item prefix-meta (ESC) +Make the next character that you type be metafied. This is for people +without a meta key. Typing @samp{ESC f} is equivalent to typing +@samp{M-f}. + +@item undo (C-_, C-x C-u) +Incremental undo, separately remembered for each line. + +@item revert-line (M-r) +Undo all changes made to this line. This is like typing the @code{undo} +command enough times to get back to the beginning. + +@item tilde-expand (M-~) +Perform tilde expansion on the current word. + +@item dump-functions () +Print all of the functions and their key bindings to the +readline output stream. If a numeric argument is supplied, +the output is formatted in such a way that it can be made part +of an @var{inputrc} file. + +@ifset BashFeatures +@item display-shell-version (C-x C-v) +Display version information about the current instance of Bash. + +@item shell-expand-line (M-C-e) +Expand the line the way the shell does when it reads it. This +performs alias and history expansion as well as all of the shell +word expansions. + +@item history-expand-line (M-^) +Perform history expansion on the current line. + +@item insert-last-argument (M-., M-_) +A synonym for @code{yank-last-arg}. + +@item operate-and-get-next (C-o) +Accept the current line for execution and fetch the next line +relative to the current line from the history for editing. Any +argument is ignored. + +@item emacs-editing-mode (C-e) +When in @code{vi} editing mode, this causes a switch back to +emacs editing mode, as if the command @code{set -o emacs} had +been executed. + +@end ifset + +@end ftable + +@node Readline vi Mode +@section Readline vi Mode + +While the Readline library does not have a full set of @code{vi} +editing functions, it does contain enough to allow simple editing +of the line. The Readline @code{vi} mode behaves as specified in +the Posix 1003.2 standard. + +@ifset BashFeatures +In order to switch interactively between @code{Emacs} and @code{Vi} +editing modes, use the @code{set -o emacs} and @code{set -o vi} +commands (@pxref{The Set Builtin}). +@end ifset +@ifclear BashFeatures +In order to switch interactively between @code{Emacs} and @code{Vi} +editing modes, use the command M-C-j (toggle-editing-mode). +@end ifclear +The Readline default is @code{emacs} mode. + +When you enter a line in @code{vi} mode, you are already placed in +`insertion' mode, as if you had typed an @samp{i}. Pressing @key{ESC} +switches you into `command' mode, where you can edit the text of the +line with the standard @code{vi} movement keys, move to previous +history lines with @samp{k}, and following lines with @samp{j}, and +so forth. diff --git a/doc/texinfo.tex b/doc/texinfo.tex new file mode 100644 index 0000000..ce8124e --- /dev/null +++ b/doc/texinfo.tex @@ -0,0 +1,4003 @@ +%% TeX macros to handle texinfo files + +% Copyright (C) 1985, 86, 88, 90, 91, 92, 1993 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, 675 Mass Ave, Cambridge, MA 02139, +%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! + +\def\texinfoversion{2.108} +\message{Loading texinfo package [Version \texinfoversion]:} + +% Print the version number if in a .fmt file. +\everyjob{\message{[Texinfo version \texinfoversion]}\message{}} + +% Save some parts of plain tex whose names we will redefine. + +\let\ptexlbrace=\{ +\let\ptexrbrace=\} +\let\ptexdots=\dots +\let\ptexdot=\. +\let\ptexstar=\* +\let\ptexend=\end +\let\ptexbullet=\bullet +\let\ptexb=\b +\let\ptexc=\c +\let\ptexi=\i +\let\ptext=\t +\let\ptexl=\l +\let\ptexL=\L + +\def\tie{\penalty 10000\ } % Save plain tex definition of ~. + +\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 + +% 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 \bindingoffset=0pt +\newdimen \normaloffset \normaloffset=\hoffset +\newdimen\pagewidth \newdimen\pageheight +\pagewidth=\hsize \pageheight=\vsize + +% 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 itself, 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=`\\\relax % makes sure backslash is used in output files. +\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 } + +\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}} +{\catcode`\@ =11 +\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\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 = \baselineskip +\def\singlespace{% +% Why was this kern here? It messes up equalizing space above and below +% environments. --karl, 6may93 +%{\advance \baselineskip by -\singlespaceskip +%\kern \baselineskip}% +\baselineskip=\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 + +% @: 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 } + +% @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 + % + % We do @comment here in case 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}}}} + +%\hbox{{\rm#1}}\hfil\break}} + +% @include file insert text of that file as input. + +\def\include{\parsearg\includezzz} +%Use \input\thisfile to avoid blank after \input, which may be an active +%char (in which case the blank would become the \input argument). +%The grouping keeps the value of \thisfile correct even when @include +%is nested. +\def\includezzz #1{\begingroup +\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{\par \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 + +% 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\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\include = \relax + \let\lowersections = \relax + \let\down = \relax + \let\raisesections = \relax + \let\up = \relax + \let\set = \relax + \let\clear = \relax +} + +% Ignore @ignore ... @end ignore. +% +\def\ignore{\doignore{ignore}} + +% Also ignore @ifinfo, @menu, and @direntry text. +% +\def\ifinfo{\doignore{ifinfo}} +\def\menu{\doignore{menu}} +\def\direntry{\doignore{direntry}} + +% 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{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{} + \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 + % + % 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. +% +\def\set{\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 +} +\def\setzzz#1#2 \endsetzzz{\expandafter\xdef\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 +\let\lastnode=\relax} + +\def\unnumbnoderef{\ifx\lastnode\relax\else +\expandafter\expandafter\expandafter\unnumbsetref{\lastnode}\fi +\let\lastnode=\relax} + +\def\appendixnoderef{\ifx\lastnode\relax\else +\expandafter\expandafter\expandafter\appendixsetref{\lastnode}\fi +\let\lastnode=\relax} + +\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. +} + +\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} + +\def\inforef #1{\inforefzzz #1,,,,**} +\def\inforefzzz #1,#2,#3,#4**{See Info file \file{\ignorespaces #3{}}, + node \samp{\ignorespaces#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. + +%% Try out Computer Modern fonts at \magstephalf +\let\mainmagstep=\magstephalf + +\ifx\bigger\relax +\let\mainmagstep=\magstep1 +\font\textrm=cmr12 +\font\texttt=cmtt12 +\else +\font\textrm=cmr10 scaled \mainmagstep +\font\texttt=cmtt10 scaled \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. +\font\textbf=cmb10 scaled \mainmagstep +\font\textit=cmti10 scaled \mainmagstep +\font\textsl=cmsl10 scaled \mainmagstep +\font\textsf=cmss10 scaled \mainmagstep +\font\textsc=cmcsc10 scaled \mainmagstep +\font\texti=cmmi10 scaled \mainmagstep +\font\textsy=cmsy10 scaled \mainmagstep + +% A few fonts for @defun, etc. +\font\defbf=cmbx10 scaled \magstep1 %was 1314 +\font\deftt=cmtt10 scaled \magstep1 +\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf} + +% Fonts for indices and small examples. +% 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. +\font\ninett=cmtt9 +\font\indrm=cmr9 +\font\indit=cmsl9 +\let\indsl=\indit +\let\indtt=\ninett +\let\indsf=\indrm +\let\indbf=\indrm +\let\indsc=\indrm +\font\indi=cmmi9 +\font\indsy=cmsy9 + +% Fonts for headings +\font\chaprm=cmbx12 scaled \magstep2 +\font\chapit=cmti12 scaled \magstep2 +\font\chapsl=cmsl12 scaled \magstep2 +\font\chaptt=cmtt12 scaled \magstep2 +\font\chapsf=cmss12 scaled \magstep2 +\let\chapbf=\chaprm +\font\chapsc=cmcsc10 scaled\magstep3 +\font\chapi=cmmi12 scaled \magstep2 +\font\chapsy=cmsy10 scaled \magstep3 + +\font\secrm=cmbx12 scaled \magstep1 +\font\secit=cmti12 scaled \magstep1 +\font\secsl=cmsl12 scaled \magstep1 +\font\sectt=cmtt12 scaled \magstep1 +\font\secsf=cmss12 scaled \magstep1 +\font\secbf=cmbx12 scaled \magstep1 +\font\secsc=cmcsc10 scaled\magstep2 +\font\seci=cmmi12 scaled \magstep1 +\font\secsy=cmsy10 scaled \magstep2 + +% \font\ssecrm=cmbx10 scaled \magstep1 % This size an font looked bad. +% \font\ssecit=cmti10 scaled \magstep1 % The letters were too crowded. +% \font\ssecsl=cmsl10 scaled \magstep1 +% \font\ssectt=cmtt10 scaled \magstep1 +% \font\ssecsf=cmss10 scaled \magstep1 + +%\font\ssecrm=cmb10 scaled 1315 % Note the use of cmb rather than cmbx. +%\font\ssecit=cmti10 scaled 1315 % Also, the size is a little larger than +%\font\ssecsl=cmsl10 scaled 1315 % being scaled magstep1. +%\font\ssectt=cmtt10 scaled 1315 +%\font\ssecsf=cmss10 scaled 1315 + +%\let\ssecbf=\ssecrm + +\font\ssecrm=cmbx12 scaled \magstephalf +\font\ssecit=cmti12 scaled \magstephalf +\font\ssecsl=cmsl12 scaled \magstephalf +\font\ssectt=cmtt12 scaled \magstephalf +\font\ssecsf=cmss12 scaled \magstephalf +\font\ssecbf=cmbx12 scaled \magstephalf +\font\ssecsc=cmcsc10 scaled \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: +\font\titlerm = cmbx12 scaled \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. Plain TeX does, for example, +% \def\bf{\fam=\bffam \tenbf} 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 + \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 + \resetmathfonts} +\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 + \resetmathfonts} +\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 + \resetmathfonts} +\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 + \resetmathfonts} + +% 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. +\font\shortcontrm=cmr12 +\font\shortcontbf=cmbx12 +\font\shortcontsl=cmsl12 + +%% 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 \nohyphenation \rawbackslash \frenchspacing #1}% + \null +} +\let\ttfont = \t +%\def\samp #1{`{\tt \rawbackslash \frenchspacing #1}'\null} +\def\samp #1{`\tclose{#1}'\null} +\def\key #1{{\tt \nohyphenation \uppercase{#1}}\null} +\def\ctrl #1{{\tt \rawbackslash \hat}#1} + +\let\file=\samp + +% @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 overful 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 an a dash. +% -- rms. +{ +\catcode `\-=\active +\catcode `\_=\active +\global\def\code{\begingroup \catcode `\-=\active \let-\codedash \let_\codeunder \codex} +} +\def\codedash{-\discretionary{}{}{}} +\def\codeunder{\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{\look}\fi +\else\tclose{\look}\fi} + +% 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} + +\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 + +\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 \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 + \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. + +\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{ +%\pagealignmacro +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +} +% For single-sided printing, chapter title goes across top left of page, +% page number on top right. +\def\HEADINGSsingle{ +%\pagealignmacro +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +} +\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}} +} + +\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}} +} + +% 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). + +\def\internalBitem{\smallbreak \parsearg\itemzzz} +\def\internalBitemx{\par \parsearg\itemzzz} + +\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz} +\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \par \parsearg\xitemzzz} + +\def\internalBkitem{\smallbreak \parsearg\kitemzzz} +\def\internalBkitemx{\par \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 + \setbox0=\hbox{\hskip \leftskip \hskip -\tableindent \unhbox0}\box0 + % + % 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 + \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}% + \fi + \endgroup +} + +\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}% Neccessary 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} + +\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{% +\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\samp##1{\realbackslash samp {##1}}% +\def\t##1{\realbackslash r {##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}}% +} + +% \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{% +\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 +} + +% 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. + +\def\doind #1#2{% +{\count10=\lastpenalty % +{\indexdummies % Must do this here, since \bf, etc expand at this stage +\escapechar=`\\% +{\let\folio=0% 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 in the indx. +% +% 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}% +}% +% 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}}}% +\temp }% +}\penalty\count10}} + +\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{% + \tex + \dobreak \chapheadingskip {10000} + \catcode`\%=\other\catcode`\&=\other\catcode`\#=\other + \catcode`\$=\other\catcode`\_=\other + \catcode`\~=\other + % + % The following don't help, since the chars were translated + % when the raw index was written, and their fonts were discarded + % due to \indexnofonts. + %\catcode`\"=\active + %\catcode`\^=\active + %\catcode`\_=\active + %\catcode`\|=\active + %\catcode`\<=\active + %\catcode`\>=\active + % % + \def\indexbackslash{\rawbackslashxx} + \indexfonts\rm \tolerance=9500 \advance\baselineskip -1pt + \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 + \Etex +} + +% 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% + % + % 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. + \par +\endgroup} + +% Like \dotfill except takes at least 1 em. +\def\indexdotfill{\cleaders + \hbox{$\mathsurround=0pt \mkern1.5mu . \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 is used in indexes. +%% Adapted from the TeXbook, page 416. +\catcode `\@=11 + +\newbox\partialpage + +\newdimen\doublecolumnhsize + +\def\begindoublecolumns{\begingroup + % 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 + \doublecolumnpagegoal +} + +\def\enddoublecolumns{\eject \endgroup \pagegoal=\vsize \unvbox\partialpage} + +\def\doublecolumnsplit{\splittopskip=\topskip \splitmaxdepth=\maxdepth + \global\dimen@=\pageheight \global\advance\dimen@ by-\ht\partialpage + \global\setbox1=\vsplit255 to\dimen@ \global\setbox0=\vbox{\unvbox1} + \global\setbox3=\vsplit255 to\dimen@ \global\setbox2=\vbox{\unvbox3} + \ifdim\ht0>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi + \ifdim\ht2>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi +} +\def\doublecolumnpagegoal{% + \dimen@=\vsize \advance\dimen@ by-2\ht\partialpage \global\pagegoal=\dimen@ +} +\def\pagesofar{\unvbox\partialpage % + \hsize=\doublecolumnhsize % have to restore this since output routine + \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}} +\def\doublecolumnout{% + \setbox5=\copy255 + {\vbadness=10000 \doublecolumnsplit} + \ifvbox255 + \setbox0=\vtop to\dimen@{\unvbox0} + \setbox2=\vtop to\dimen@{\unvbox2} + \onepageout\pagesofar \unvbox255 \penalty\outputpenalty + \else + \setbox0=\vbox{\unvbox5} + \ifvbox0 + \dimen@=\ht0 \advance\dimen@ by\topskip \advance\dimen@ by-\baselineskip + \divide\dimen@ by2 \splittopskip=\topskip \splitmaxdepth=\maxdepth + {\vbadness=10000 + \loop \global\setbox5=\copy0 + \setbox1=\vsplit5 to\dimen@ + \setbox3=\vsplit5 to\dimen@ + \ifvbox5 \global\advance\dimen@ by1pt \repeat + \setbox0=\vbox to\dimen@{\unvbox1} + \setbox2=\vbox to\dimen@{\unvbox3} + \global\setbox\partialpage=\vbox{\pagesofar} + \doublecolumnpagegoal + } + \fi + \fi +} + +\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{Chapter \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{Chapter \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}{Appendix \appendixletter}% +\gdef\thissection{#1}% +\gdef\thischaptername{#1}% +\xdef\thischapter{Appendix \appendixletter: \noexpand\thischaptername}% +{\chapternofonts% +\edef\temp{{\realbackslash chapentry + {#1}{Appendix \appendixletter}{\noexpand\folio}}}% +\escapechar=`\\% +\write \contentsfile \temp % +\appendixnoderef % +\global\let\section = \appendixsec +\global\let\subsection = \appendixsubsec +\global\let\subsubsection = \appendixsubsubsec +}} + +\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\appenixsection{\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}% +\plainsecheading {#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}% +\plainsecheading {#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} + +\def\heading{\parsearg\secheadingi} + +\def\subheading{\parsearg\subsecheadingi} + +\def\subsubheading{\parsearg\subsubsecheadingi} + +% 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 \chapheadingskip = 30pt plus 8pt minus 4pt + +\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\pchapsepmacro=\chapbreak +\global\let\pagealignmacro=\chappager} + +\def\CHAPPAGon{ +\global\let\pchapsepmacro=\chappager +\global\let\pagealignmacro=\chappager +\global\def\HEADINGSon{\HEADINGSsingle}} + +\def\CHAPPAGodd{ +\global\let\pchapsepmacro=\chapoddpage +\global\let\pagealignmacro=\chapoddpage +\global\def\HEADINGSon{\HEADINGSdouble}} + +\CHAPPAGon + +\def\CHAPFplain{ +\global\let\chapmacro=\chfplain +\global\let\unnumbchapmacro=\unnchfplain} + +\def\chfplain #1#2{% + \pchapsepmacro + {% + \chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #2\enspace #1}% + }% + \bigskip + \penalty5000 +} + +\def\unnchfplain #1{% +\pchapsepmacro % +{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 10000 % +} +\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\CHAPFopen{ +\global\let\chapmacro=\chfopen +\global\let\unnumbchapmacro=\unnchfopen} + +% Parameter controlling skip before section headings. + +\newskip \subsecheadingskip \subsecheadingskip = 17pt plus 8pt minus 4pt +\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}} + +\newskip \secheadingskip \secheadingskip = 21pt plus 8pt minus 4pt +\def\secheadingbreak{\dobreak \secheadingskip {-1000}} + +% @paragraphindent is defined for the Info formatting commands only. +\let\paragraphindent=\comment + +% Section fonts are the base font at magstep2, which produces +% a size a bit more than 14 points in the default situation. + +\def\secheading #1#2#3{\secheadingi {#2.#3\enspace #1}} +\def\plainsecheading #1{\secheadingi {#1}} +\def\secheadingi #1{{\advance \secheadingskip by \parskip % +\secheadingbreak}% +{\secfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}% +\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 } + + +% Subsection fonts are the base font at magstep1, +% which produces a size of 12 points. + +\def\subsecheading #1#2#3#4{\subsecheadingi {#2.#3.#4\enspace #1}} +\def\subsecheadingi #1{{\advance \subsecheadingskip by \parskip % +\subsecheadingbreak}% +{\subsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}% +\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 } + +\def\subsubsecfonts{\subsecfonts} % Maybe this should change: + % Perhaps make sssec fonts scaled + % magstep half +\def\subsubsecheading #1#2#3#4#5{\subsubsecheadingi {#2.#3.#4.#5\enspace #1}} +\def\subsubsecheadingi #1{{\advance \subsecheadingskip by \parskip % +\subsecheadingbreak}% +{\subsubsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}% +\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000} + + +\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{% + \pagealignmacro + \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 + \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{Table of Contents}% + \input \jobname.toc + \endgroup + \vfill \eject +} + +% And just the chapters. +\outer\def\summarycontents{% + \startcontents{Short Contents}% + % + \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 + \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 Appendix } +\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 in \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 would want to be at chapters +% if at all possible; hence the \penalty. +\def\dochapentry#1#2{% + \penalty-300 \vskip\baselineskip + \begingroup + \chapentryfonts + \tocentry{#1}{\dopageno{#2}}% + \endgroup + \nobreak\vskip .25\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.) +% +\def\tocentry#1#2{\begingroup + \hyphenpenalty = 10000 + \entry{#1}{#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 + +\let\ptexequiv = \equiv + +%{\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} +%} + +\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 +\catcode`\"=12 +\catcode`\==12 +\catcode`\|=12 +\catcode`\<=12 +\catcode`\>=12 +\escapechar=`\\ +% +\let\{=\ptexlbrace +\let\}=\ptexrbrace +\let\.=\ptexdot +\let\*=\ptexstar +\let\dots=\ptexdots +\def\@{@}% +\let\bullet=\ptexbullet +\let\b=\ptexb \let\c=\ptexc \let\i=\ptexi \let\t=\ptext \let\l=\ptexl +\let\L=\ptexL +% +\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 interline space and fonts for small examples. + \baselineskip 10pt + \indexfonts \tt + \rawbackslash % output the \ character from the current font + \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 and narrows the margins. +% +\def\quotation{% +\begingroup\inENV %This group ends at the end of the @quotation body +{\parskip=0pt % because we will skip by \parskip too, later +\aboveenvbreak}% +\singlespace +\parindent=0pt +\let\Equotation = \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} + +% 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 % +\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} + +\def\defvrparsebody #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\spacesplit{#3{##1}}}% +\parindent=0in +\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +\exdentamount=\defbodyindent +\begingroup\obeylines\spacesplit{#3{#4}}} + +% This seems to work right in all cases. +\let\deftpparsebody=\defvrparsebody +% This fails to work. When given `@deftp {Data Type} foo_t', +% it thinks the type name is just `f'. +%%% This is the same as all the others except for the last line. We need +%%% to parse the arguments differently for @deftp, since the ``attributes'' +%%% there are optional. +%%% +%%\def\deftpparsebody #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\spacesplit{#3{##1}}}% +%%\parindent=0in +%%\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent +%%\exdentamount=\defbodyindent +%%\begingroup\obeylines\parsetpheaderline{#3{#4}}} + +%%{\obeylines % +%% % Parse the type name and any attributes (field names, etc.). +%% % #1 is the beginning of the macro call that will produce the output, +%% % i.e., \deftpheader{CLASS}; this is passed from \deftpparsebody. +%% % #2 is the type name, e.g., `struct termios'. +%% % #3 is the (possibly empty) attribute list. +%% % +%% \gdef\parsetpheaderline#1#2#3^^M{% +%% \endgroup % Started in \deftpparsebody. +%% % +%% % If the attribute list is in fact empty, there will be no space after +%% % #2; so we can't put a space in our TeX parameter list. But if it +%% % isn't empty, then #3 will begin with an unwanted space. +%% \def\theargs{\ignorespaces #3}% +%% % +%% % Call the macro to produce the output. +%% #1{#2}\theargs % +%% }% +%%} + +\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. +\functionparens +\code{#1}% +\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 {\code{#1} #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} + +% #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\defname {\code{#2} #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 {\code{#1} #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 {\code{#2} #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. + +% \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{see \xrefX[#1,,,,,,,]} +\def\xref#1{See \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% +\def\printednodename{\ignorespaces #1}% +%%% Uncommment the following line to make the actual chapter or section title +%%% appear inside the square brackets. +%\def\printednodename{#1-title}% +\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 simply give the text of +% the node name again, so it is as if TeX is seeing it for the first +% time. +\ifdim \wd1>0pt +section ``\printednodename'' in \cite{\printedmanual}% +\else% +\turnoffactive% +\refx{#1-snt}{} [\printednodename], page\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% +\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{\thischapter} + +\def\Ynothing{} + +\def\Ysectionnumberandtype{% +\ifnum\secno=0 Chapter\xreftie\the\chapno % +\else \ifnum \subsecno=0 Section\xreftie\the\chapno.\the\secno % +\else \ifnum \subsubsecno=0 % +Section\xreftie\the\chapno.\the\secno.\the\subsecno % +\else % +Section\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno % +\fi \fi \fi } + +\def\Yappendixletterandtype{% +\ifnum\secno=0 Appendix\xreftie'char\the\appendixno{}% +\else \ifnum \subsecno=0 Section\xreftie'char\the\appendixno.\the\secno % +\else \ifnum \subsubsecno=0 % +Section\xreftie'char\the\appendixno.\the\secno.\the\subsecno % +\else % +Section\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 +% 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 `\\=\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. +\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 = 6.5in +\newdimen\defaultparindent \defaultparindent = 15pt +\parindent = \defaultparindent +\parskip 18pt plus 1pt +\setleading{15pt} +\advance\topskip by 1.2cm + +% 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{ + +% These values for secheadingskip and subsecheadingskip are +% experiments. RJC 7 Aug 1992 +\global\secheadingskip = 17pt plus 6pt minus 3pt +\global\subsecheadingskip = 14pt plus 6pt minus 3pt + +\global\lispnarrowing = 0.3in +\setleading{12pt} +\advance\topskip by -1cm +\global\parskip 3pt plus 1pt +\global\hsize = 5in +\global\vsize=7.5in +\global\tolerance=700 +\global\hfuzz=1pt +\global\contentsrightmargin=0pt + +\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 +} + +% 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^{{\tt \hat}} + +\catcode`\_=\active +\def_{\ifusingtt\normalunderscore\_} +% Subroutine for the previous macro. +\def\_{\lvvmode \kern.06em \vbox{\hrule width.3em height.1ex}} + +% \lvvmode is equivalent in function to \leavevmode. +% Using \leavevmode runs into trouble when written out to +% an index file due to the expansion of \leavevmode into ``\unhbox +% \voidb@x'' ---which looks to TeX like ``\unhbox \voidb\x'' due to our +% magic tricks with @. +\def\lvvmode{\vbox to 0pt{}} + +\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$} + +% Used sometimes to turn off (effectively) the active characters +% even after parsing them. +\def\turnoffactive{\let"=\normaldoublequote +\let~=\normaltilde +\let^=\normalcaret +\let_=\normalunderscore +\let|=\normalverticalbar +\let<=\normalless +\let>=\normalgreater +\let+=\normalplus} + +% Set up an active definition for =, but don't enable it most of the time. +{\catcode`\==\active +\global\def={{\tt \char 61}}} + +\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 + +% 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. +% +@gdef@fixbackslash{@ifx\@eatinput @let\ = @normalbackslash @fi} + +%% 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/emacs_keymap.c b/emacs_keymap.c new file mode 100644 index 0000000..849d85f --- /dev/null +++ b/emacs_keymap.c @@ -0,0 +1,885 @@ +/* emacs_keymap.c -- the keymap for emacs_mode in readline (). */ + +/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library 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 1, or + (at your option) any later version. + + The GNU Readline Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#if !defined (BUFSIZ) +#include +#endif /* !BUFSIZ */ + +#include "readline.h" + +/* An array of function pointers, one for each possible key. + If the type byte is ISKMAP, then the pointer is the address of + a keymap. */ + +KEYMAP_ENTRY_ARRAY emacs_standard_keymap = { + + /* Control keys. */ + { ISFUNC, (Function *)0x0 }, /* Control-@ */ + { ISFUNC, rl_beg_of_line }, /* Control-a */ + { ISFUNC, rl_backward }, /* Control-b */ + { ISFUNC, (Function *)0x0 }, /* Control-c */ + { ISFUNC, rl_delete }, /* Control-d */ + { ISFUNC, rl_end_of_line }, /* Control-e */ + { ISFUNC, rl_forward }, /* Control-f */ + { ISFUNC, rl_abort }, /* Control-g */ + { ISFUNC, rl_rubout }, /* Control-h */ + { ISFUNC, rl_complete }, /* Control-i */ + { ISFUNC, rl_newline }, /* Control-j */ + { ISFUNC, rl_kill_line }, /* Control-k */ + { ISFUNC, rl_clear_screen }, /* Control-l */ + { ISFUNC, rl_newline }, /* Control-m */ + { ISFUNC, rl_get_next_history }, /* Control-n */ + { ISFUNC, (Function *)0x0 }, /* Control-o */ + { ISFUNC, rl_get_previous_history }, /* Control-p */ + { ISFUNC, rl_quoted_insert }, /* Control-q */ + { ISFUNC, rl_reverse_search_history }, /* Control-r */ + { ISFUNC, rl_forward_search_history }, /* Control-s */ + { ISFUNC, rl_transpose_chars }, /* Control-t */ + { ISFUNC, rl_unix_line_discard }, /* Control-u */ + { ISFUNC, rl_quoted_insert }, /* Control-v */ + { ISFUNC, rl_unix_word_rubout }, /* Control-w */ + { ISKMAP, (Function *)emacs_ctlx_keymap }, /* Control-x */ + { ISFUNC, rl_yank }, /* Control-y */ + { ISFUNC, (Function *)0x0 }, /* Control-z */ + { ISKMAP, (Function *)emacs_meta_keymap }, /* Control-[ */ + { ISFUNC, (Function *)0x0 }, /* Control-\ */ + { ISFUNC, (Function *)0x0 }, /* Control-] */ + { ISFUNC, (Function *)0x0 }, /* Control-^ */ + { ISFUNC, rl_undo_command }, /* Control-_ */ + + /* The start of printing characters. */ + { ISFUNC, rl_insert }, /* SPACE */ + { ISFUNC, rl_insert }, /* ! */ + { ISFUNC, rl_insert }, /* " */ + { ISFUNC, rl_insert }, /* # */ + { ISFUNC, rl_insert }, /* $ */ + { ISFUNC, rl_insert }, /* % */ + { ISFUNC, rl_insert }, /* & */ + { ISFUNC, rl_insert }, /* ' */ + { ISFUNC, rl_insert }, /* ( */ +#if defined (PAREN_MATCHING) + { ISFUNC, rl_insert_close }, /* ) */ +#else + { ISFUNC, rl_insert }, /* ) */ +#endif /* !PAREN_MATCHING */ + { ISFUNC, rl_insert }, /* * */ + { ISFUNC, rl_insert }, /* + */ + { ISFUNC, rl_insert }, /* , */ + { ISFUNC, rl_insert }, /* - */ + { ISFUNC, rl_insert }, /* . */ + { ISFUNC, rl_insert }, /* / */ + + /* Regular digits. */ + { ISFUNC, rl_insert }, /* 0 */ + { ISFUNC, rl_insert }, /* 1 */ + { ISFUNC, rl_insert }, /* 2 */ + { ISFUNC, rl_insert }, /* 3 */ + { ISFUNC, rl_insert }, /* 4 */ + { ISFUNC, rl_insert }, /* 5 */ + { ISFUNC, rl_insert }, /* 6 */ + { ISFUNC, rl_insert }, /* 7 */ + { ISFUNC, rl_insert }, /* 8 */ + { ISFUNC, rl_insert }, /* 9 */ + + /* A little more punctuation. */ + { ISFUNC, rl_insert }, /* : */ + { ISFUNC, rl_insert }, /* ; */ + { ISFUNC, rl_insert }, /* < */ + { ISFUNC, rl_insert }, /* = */ + { ISFUNC, rl_insert }, /* > */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* @ */ + + /* Uppercase alphabet. */ + { ISFUNC, rl_insert }, /* A */ + { ISFUNC, rl_insert }, /* B */ + { ISFUNC, rl_insert }, /* C */ + { ISFUNC, rl_insert }, /* D */ + { ISFUNC, rl_insert }, /* E */ + { ISFUNC, rl_insert }, /* F */ + { ISFUNC, rl_insert }, /* G */ + { ISFUNC, rl_insert }, /* H */ + { ISFUNC, rl_insert }, /* I */ + { ISFUNC, rl_insert }, /* J */ + { ISFUNC, rl_insert }, /* K */ + { ISFUNC, rl_insert }, /* L */ + { ISFUNC, rl_insert }, /* M */ + { ISFUNC, rl_insert }, /* N */ + { ISFUNC, rl_insert }, /* O */ + { ISFUNC, rl_insert }, /* P */ + { ISFUNC, rl_insert }, /* Q */ + { ISFUNC, rl_insert }, /* R */ + { ISFUNC, rl_insert }, /* S */ + { ISFUNC, rl_insert }, /* T */ + { ISFUNC, rl_insert }, /* U */ + { ISFUNC, rl_insert }, /* V */ + { ISFUNC, rl_insert }, /* W */ + { ISFUNC, rl_insert }, /* X */ + { ISFUNC, rl_insert }, /* Y */ + { ISFUNC, rl_insert }, /* Z */ + + /* Some more punctuation. */ + { ISFUNC, rl_insert }, /* [ */ + { ISFUNC, rl_insert }, /* \ */ +#if defined (PAREN_MATCHING) + { ISFUNC, rl_insert_close }, /* ] */ +#else + { ISFUNC, rl_insert }, /* ] */ +#endif /* !PAREN_MATCHING */ + { ISFUNC, rl_insert }, /* ^ */ + { ISFUNC, rl_insert }, /* _ */ + { ISFUNC, rl_insert }, /* ` */ + + /* Lowercase alphabet. */ + { ISFUNC, rl_insert }, /* a */ + { ISFUNC, rl_insert }, /* b */ + { ISFUNC, rl_insert }, /* c */ + { ISFUNC, rl_insert }, /* d */ + { ISFUNC, rl_insert }, /* e */ + { ISFUNC, rl_insert }, /* f */ + { ISFUNC, rl_insert }, /* g */ + { ISFUNC, rl_insert }, /* h */ + { ISFUNC, rl_insert }, /* i */ + { ISFUNC, rl_insert }, /* j */ + { ISFUNC, rl_insert }, /* k */ + { ISFUNC, rl_insert }, /* l */ + { ISFUNC, rl_insert }, /* m */ + { ISFUNC, rl_insert }, /* n */ + { ISFUNC, rl_insert }, /* o */ + { ISFUNC, rl_insert }, /* p */ + { ISFUNC, rl_insert }, /* q */ + { ISFUNC, rl_insert }, /* r */ + { ISFUNC, rl_insert }, /* s */ + { ISFUNC, rl_insert }, /* t */ + { ISFUNC, rl_insert }, /* u */ + { ISFUNC, rl_insert }, /* v */ + { ISFUNC, rl_insert }, /* w */ + { ISFUNC, rl_insert }, /* x */ + { ISFUNC, rl_insert }, /* y */ + { ISFUNC, rl_insert }, /* z */ + + /* Final punctuation. */ + { ISFUNC, rl_insert }, /* { */ + { ISFUNC, rl_insert }, /* | */ +#if defined (PAREN_MATCHING) + { ISFUNC, rl_insert_close }, /* } */ +#else + { ISFUNC, rl_insert }, /* } */ +#endif /* !PAREN_MATCHING */ + { ISFUNC, rl_insert }, /* ~ */ + { ISFUNC, rl_rubout }, /* RUBOUT */ + +#if KEYMAP_SIZE > 128 + /* Pure 8-bit characters (128 - 159). + These might be used in some + character sets. */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + + /* ISO Latin-1 characters (160 - 255) */ + { ISFUNC, rl_insert }, /* No-break space */ + { ISFUNC, rl_insert }, /* Inverted exclamation mark */ + { ISFUNC, rl_insert }, /* Cent sign */ + { ISFUNC, rl_insert }, /* Pound sign */ + { ISFUNC, rl_insert }, /* Currency sign */ + { ISFUNC, rl_insert }, /* Yen sign */ + { ISFUNC, rl_insert }, /* Broken bar */ + { ISFUNC, rl_insert }, /* Section sign */ + { ISFUNC, rl_insert }, /* Diaeresis */ + { ISFUNC, rl_insert }, /* Copyright sign */ + { ISFUNC, rl_insert }, /* Feminine ordinal indicator */ + { ISFUNC, rl_insert }, /* Left pointing double angle quotation mark */ + { ISFUNC, rl_insert }, /* Not sign */ + { ISFUNC, rl_insert }, /* Soft hyphen */ + { ISFUNC, rl_insert }, /* Registered sign */ + { ISFUNC, rl_insert }, /* Macron */ + { ISFUNC, rl_insert }, /* Degree sign */ + { ISFUNC, rl_insert }, /* Plus-minus sign */ + { ISFUNC, rl_insert }, /* Superscript two */ + { ISFUNC, rl_insert }, /* Superscript three */ + { ISFUNC, rl_insert }, /* Acute accent */ + { ISFUNC, rl_insert }, /* Micro sign */ + { ISFUNC, rl_insert }, /* Pilcrow sign */ + { ISFUNC, rl_insert }, /* Middle dot */ + { ISFUNC, rl_insert }, /* Cedilla */ + { ISFUNC, rl_insert }, /* Superscript one */ + { ISFUNC, rl_insert }, /* Masculine ordinal indicator */ + { ISFUNC, rl_insert }, /* Right pointing double angle quotation mark */ + { ISFUNC, rl_insert }, /* Vulgar fraction one quarter */ + { ISFUNC, rl_insert }, /* Vulgar fraction one half */ + { ISFUNC, rl_insert }, /* Vulgar fraction three quarters */ + { ISFUNC, rl_insert }, /* Inverted questionk mark */ + { ISFUNC, rl_insert }, /* Latin capital letter a with grave */ + { ISFUNC, rl_insert }, /* Latin capital letter a with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter a with circumflex */ + { ISFUNC, rl_insert }, /* Latin capital letter a with tilde */ + { ISFUNC, rl_insert }, /* Latin capital letter a with diaeresis */ + { ISFUNC, rl_insert }, /* Latin capital letter a with ring above */ + { ISFUNC, rl_insert }, /* Latin capital letter ae */ + { ISFUNC, rl_insert }, /* Latin capital letter c with cedilla */ + { ISFUNC, rl_insert }, /* Latin capital letter e with grave */ + { ISFUNC, rl_insert }, /* Latin capital letter e with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter e with circumflex */ + { ISFUNC, rl_insert }, /* Latin capital letter e with diaeresis */ + { ISFUNC, rl_insert }, /* Latin capital letter i with grave */ + { ISFUNC, rl_insert }, /* Latin capital letter i with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter i with circumflex */ + { ISFUNC, rl_insert }, /* Latin capital letter i with diaeresis */ + { ISFUNC, rl_insert }, /* Latin capital letter eth (Icelandic) */ + { ISFUNC, rl_insert }, /* Latin capital letter n with tilde */ + { ISFUNC, rl_insert }, /* Latin capital letter o with grave */ + { ISFUNC, rl_insert }, /* Latin capital letter o with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter o with circumflex */ + { ISFUNC, rl_insert }, /* Latin capital letter o with tilde */ + { ISFUNC, rl_insert }, /* Latin capital letter o with diaeresis */ + { ISFUNC, rl_insert }, /* Multiplication sign */ + { ISFUNC, rl_insert }, /* Latin capital letter o with stroke */ + { ISFUNC, rl_insert }, /* Latin capital letter u with grave */ + { ISFUNC, rl_insert }, /* Latin capital letter u with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter u with circumflex */ + { ISFUNC, rl_insert }, /* Latin capital letter u with diaeresis */ + { ISFUNC, rl_insert }, /* Latin capital letter Y with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter thorn (Icelandic) */ + { ISFUNC, rl_insert }, /* Latin small letter sharp s (German) */ + { ISFUNC, rl_insert }, /* Latin small letter a with grave */ + { ISFUNC, rl_insert }, /* Latin small letter a with acute */ + { ISFUNC, rl_insert }, /* Latin small letter a with circumflex */ + { ISFUNC, rl_insert }, /* Latin small letter a with tilde */ + { ISFUNC, rl_insert }, /* Latin small letter a with diaeresis */ + { ISFUNC, rl_insert }, /* Latin small letter a with ring above */ + { ISFUNC, rl_insert }, /* Latin small letter ae */ + { ISFUNC, rl_insert }, /* Latin small letter c with cedilla */ + { ISFUNC, rl_insert }, /* Latin small letter e with grave */ + { ISFUNC, rl_insert }, /* Latin small letter e with acute */ + { ISFUNC, rl_insert }, /* Latin small letter e with circumflex */ + { ISFUNC, rl_insert }, /* Latin small letter e with diaeresis */ + { ISFUNC, rl_insert }, /* Latin small letter i with grave */ + { ISFUNC, rl_insert }, /* Latin small letter i with acute */ + { ISFUNC, rl_insert }, /* Latin small letter i with circumflex */ + { ISFUNC, rl_insert }, /* Latin small letter i with diaeresis */ + { ISFUNC, rl_insert }, /* Latin small letter eth (Icelandic) */ + { ISFUNC, rl_insert }, /* Latin small letter n with tilde */ + { ISFUNC, rl_insert }, /* Latin small letter o with grave */ + { ISFUNC, rl_insert }, /* Latin small letter o with acute */ + { ISFUNC, rl_insert }, /* Latin small letter o with circumflex */ + { ISFUNC, rl_insert }, /* Latin small letter o with tilde */ + { ISFUNC, rl_insert }, /* Latin small letter o with diaeresis */ + { ISFUNC, rl_insert }, /* Division sign */ + { ISFUNC, rl_insert }, /* Latin small letter o with stroke */ + { ISFUNC, rl_insert }, /* Latin small letter u with grave */ + { ISFUNC, rl_insert }, /* Latin small letter u with acute */ + { ISFUNC, rl_insert }, /* Latin small letter u with circumflex */ + { ISFUNC, rl_insert }, /* Latin small letter u with diaeresis */ + { ISFUNC, rl_insert }, /* Latin small letter y with acute */ + { ISFUNC, rl_insert }, /* Latin small letter thorn (Icelandic) */ + { ISFUNC, rl_insert } /* Latin small letter y with diaeresis */ +#endif /* KEYMAP_SIZE > 128 */ +}; + +KEYMAP_ENTRY_ARRAY emacs_meta_keymap = { + + /* Meta keys. Just like above, but the high bit is set. */ + { ISFUNC, (Function *)0x0 }, /* Meta-Control-@ */ + { ISFUNC, (Function *)0x0 }, /* Meta-Control-a */ + { ISFUNC, (Function *)0x0 }, /* Meta-Control-b */ + { ISFUNC, (Function *)0x0 }, /* Meta-Control-c */ + { ISFUNC, (Function *)0x0 }, /* Meta-Control-d */ + { ISFUNC, (Function *)0x0 }, /* Meta-Control-e */ + { ISFUNC, (Function *)0x0 }, /* Meta-Control-f */ + { ISFUNC, rl_abort }, /* Meta-Control-g */ + { ISFUNC, rl_backward_kill_word }, /* Meta-Control-h */ + { ISFUNC, rl_tab_insert }, /* Meta-Control-i */ + { ISFUNC, rl_vi_editing_mode }, /* Meta-Control-j */ + { ISFUNC, (Function *)0x0 }, /* Meta-Control-k */ + { ISFUNC, (Function *)0x0 }, /* Meta-Control-l */ + { ISFUNC, rl_vi_editing_mode }, /* Meta-Control-m */ + { ISFUNC, (Function *)0x0 }, /* Meta-Control-n */ + { ISFUNC, (Function *)0x0 }, /* Meta-Control-o */ + { ISFUNC, (Function *)0x0 }, /* Meta-Control-p */ + { ISFUNC, (Function *)0x0 }, /* Meta-Control-q */ + { ISFUNC, rl_revert_line }, /* Meta-Control-r */ + { ISFUNC, (Function *)0x0 }, /* Meta-Control-s */ + { ISFUNC, (Function *)0x0 }, /* Meta-Control-t */ + { ISFUNC, (Function *)0x0 }, /* Meta-Control-u */ + { ISFUNC, (Function *)0x0 }, /* Meta-Control-v */ + { ISFUNC, (Function *)0x0 }, /* Meta-Control-w */ + { ISFUNC, (Function *)0x0 }, /* Meta-Control-x */ + { ISFUNC, rl_yank_nth_arg }, /* Meta-Control-y */ + { ISFUNC, (Function *)0x0 }, /* Meta-Control-z */ + + { ISFUNC, rl_complete }, /* Meta-Control-[ */ + { ISFUNC, (Function *)0x0 }, /* Meta-Control-\ */ + { ISFUNC, (Function *)0x0 }, /* Meta-Control-] */ + { ISFUNC, (Function *)0x0 }, /* Meta-Control-^ */ + { ISFUNC, (Function *)0x0 }, /* Meta-Control-_ */ + + /* The start of printing characters. */ + { ISFUNC, (Function *)0x0 }, /* Meta-SPACE */ + { ISFUNC, (Function *)0x0 }, /* Meta-! */ + { ISFUNC, (Function *)0x0 }, /* Meta-" */ + { ISFUNC, (Function *)0x0 }, /* Meta-# */ + { ISFUNC, (Function *)0x0 }, /* Meta-$ */ + { ISFUNC, (Function *)0x0 }, /* Meta-% */ + { ISFUNC, rl_tilde_expand }, /* Meta-& */ + { ISFUNC, (Function *)0x0 }, /* Meta-' */ + { ISFUNC, (Function *)0x0 }, /* Meta-( */ + { ISFUNC, (Function *)0x0 }, /* Meta-) */ + { ISFUNC, (Function *)0x0 }, /* Meta-* */ + { ISFUNC, (Function *)0x0 }, /* Meta-+ */ + { ISFUNC, (Function *)0x0 }, /* Meta-, */ + { ISFUNC, rl_digit_argument }, /* Meta-- */ + { ISFUNC, rl_yank_last_arg}, /* Meta-. */ + { ISFUNC, (Function *)0x0 }, /* Meta-/ */ + + /* Regular digits. */ + { ISFUNC, rl_digit_argument }, /* Meta-0 */ + { ISFUNC, rl_digit_argument }, /* Meta-1 */ + { ISFUNC, rl_digit_argument }, /* Meta-2 */ + { ISFUNC, rl_digit_argument }, /* Meta-3 */ + { ISFUNC, rl_digit_argument }, /* Meta-4 */ + { ISFUNC, rl_digit_argument }, /* Meta-5 */ + { ISFUNC, rl_digit_argument }, /* Meta-6 */ + { ISFUNC, rl_digit_argument }, /* Meta-7 */ + { ISFUNC, rl_digit_argument }, /* Meta-8 */ + { ISFUNC, rl_digit_argument }, /* Meta-9 */ + + /* A little more punctuation. */ + { ISFUNC, (Function *)0x0 }, /* Meta-: */ + { ISFUNC, (Function *)0x0 }, /* Meta-; */ + { ISFUNC, rl_beginning_of_history }, /* Meta-< */ + { ISFUNC, (Function *)0x0 }, /* Meta-= */ + { ISFUNC, rl_end_of_history }, /* Meta-> */ + { ISFUNC, rl_possible_completions }, /* Meta-? */ + { ISFUNC, (Function *)0x0 }, /* Meta-@ */ + + /* Uppercase alphabet. */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-A */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-B */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-C */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-D */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-E */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-F */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-G */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-H */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-I */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-J */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-K */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-L */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-M */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-N */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-O */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-P */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-Q */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-R */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-S */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-T */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-U */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-V */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-W */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-X */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-Y */ + { ISFUNC, rl_do_lowercase_version }, /* Meta-Z */ + + /* Some more punctuation. */ + { ISFUNC, (Function *)0x0 }, /* Meta-[ */ /* was rl_arrow_keys */ + { ISFUNC, rl_delete_horizontal_space }, /* Meta-\ */ + { ISFUNC, (Function *)0x0 }, /* Meta-] */ + { ISFUNC, (Function *)0x0 }, /* Meta-^ */ + { ISFUNC, rl_yank_last_arg }, /* Meta-_ */ + { ISFUNC, (Function *)0x0 }, /* Meta-` */ + + /* Lowercase alphabet. */ + { ISFUNC, (Function *)0x0 }, /* Meta-a */ + { ISFUNC, rl_backward_word }, /* Meta-b */ + { ISFUNC, rl_capitalize_word }, /* Meta-c */ + { ISFUNC, rl_kill_word }, /* Meta-d */ + { ISFUNC, (Function *)0x0 }, /* Meta-e */ + { ISFUNC, rl_forward_word }, /* Meta-f */ + { ISFUNC, (Function *)0x0 }, /* Meta-g */ + { ISFUNC, (Function *)0x0 }, /* Meta-h */ + { ISFUNC, (Function *)0x0 }, /* Meta-i */ + { ISFUNC, (Function *)0x0 }, /* Meta-j */ + { ISFUNC, (Function *)0x0 }, /* Meta-k */ + { ISFUNC, rl_downcase_word }, /* Meta-l */ + { ISFUNC, (Function *)0x0 }, /* Meta-m */ + { ISFUNC, rl_noninc_forward_search }, /* Meta-n */ + { ISFUNC, (Function *)0x0 }, /* Meta-o */ /* was rl_arrow_keys */ + { ISFUNC, rl_noninc_reverse_search }, /* Meta-p */ + { ISFUNC, (Function *)0x0 }, /* Meta-q */ + { ISFUNC, rl_revert_line }, /* Meta-r */ + { ISFUNC, (Function *)0x0 }, /* Meta-s */ + { ISFUNC, rl_transpose_words }, /* Meta-t */ + { ISFUNC, rl_upcase_word }, /* Meta-u */ + { ISFUNC, (Function *)0x0 }, /* Meta-v */ + { ISFUNC, (Function *)0x0 }, /* Meta-w */ + { ISFUNC, (Function *)0x0 }, /* Meta-x */ + { ISFUNC, rl_yank_pop }, /* Meta-y */ + { ISFUNC, (Function *)0x0 }, /* Meta-z */ + + /* Final punctuation. */ + { ISFUNC, (Function *)0x0 }, /* Meta-{ */ + { ISFUNC, (Function *)0x0 }, /* Meta-| */ + { ISFUNC, (Function *)0x0 }, /* Meta-} */ + { ISFUNC, rl_tilde_expand }, /* Meta-~ */ + { ISFUNC, rl_backward_kill_word }, /* Meta-rubout */ + +#if KEYMAP_SIZE > 128 + /* Undefined keys. */ + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 } +#endif /* KEYMAP_SIZE > 128 */ +}; + +KEYMAP_ENTRY_ARRAY emacs_ctlx_keymap = { + + /* Control keys. */ + { ISFUNC, (Function *)0x0 }, /* Control-@ */ + { ISFUNC, (Function *)0x0 }, /* Control-a */ + { ISFUNC, (Function *)0x0 }, /* Control-b */ + { ISFUNC, (Function *)0x0 }, /* Control-c */ + { ISFUNC, (Function *)0x0 }, /* Control-d */ + { ISFUNC, (Function *)0x0 }, /* Control-e */ + { ISFUNC, (Function *)0x0 }, /* Control-f */ + { ISFUNC, rl_abort }, /* Control-g */ + { ISFUNC, (Function *)0x0 }, /* Control-h */ + { ISFUNC, (Function *)0x0 }, /* Control-i */ + { ISFUNC, (Function *)0x0 }, /* Control-j */ + { ISFUNC, (Function *)0x0 }, /* Control-k */ + { ISFUNC, (Function *)0x0 }, /* Control-l */ + { ISFUNC, (Function *)0x0 }, /* Control-m */ + { ISFUNC, (Function *)0x0 }, /* Control-n */ + { ISFUNC, (Function *)0x0 }, /* Control-o */ + { ISFUNC, (Function *)0x0 }, /* Control-p */ + { ISFUNC, (Function *)0x0 }, /* Control-q */ + { ISFUNC, rl_re_read_init_file }, /* Control-r */ + { ISFUNC, (Function *)0x0 }, /* Control-s */ + { ISFUNC, (Function *)0x0 }, /* Control-t */ + { ISFUNC, rl_undo_command }, /* Control-u */ + { ISFUNC, (Function *)0x0 }, /* Control-v */ + { ISFUNC, (Function *)0x0 }, /* Control-w */ + { ISFUNC, (Function *)0x0 }, /* Control-x */ + { ISFUNC, (Function *)0x0 }, /* Control-y */ + { ISFUNC, (Function *)0x0 }, /* Control-z */ + { ISFUNC, (Function *)0x0 }, /* Control-[ */ + { ISFUNC, (Function *)0x0 }, /* Control-\ */ + { ISFUNC, (Function *)0x0 }, /* Control-] */ + { ISFUNC, (Function *)0x0 }, /* Control-^ */ + { ISFUNC, (Function *)0x0 }, /* Control-_ */ + + /* The start of printing characters. */ + { ISFUNC, (Function *)0x0 }, /* SPACE */ + { ISFUNC, (Function *)0x0 }, /* ! */ + { ISFUNC, (Function *)0x0 }, /* " */ + { ISFUNC, (Function *)0x0 }, /* # */ + { ISFUNC, (Function *)0x0 }, /* $ */ + { ISFUNC, (Function *)0x0 }, /* % */ + { ISFUNC, (Function *)0x0 }, /* & */ + { ISFUNC, (Function *)0x0 }, /* ' */ + { ISFUNC, rl_start_kbd_macro }, /* ( */ + { ISFUNC, rl_end_kbd_macro }, /* ) */ + { ISFUNC, (Function *)0x0 }, /* * */ + { ISFUNC, (Function *)0x0 }, /* + */ + { ISFUNC, (Function *)0x0 }, /* , */ + { ISFUNC, (Function *)0x0 }, /* - */ + { ISFUNC, (Function *)0x0 }, /* . */ + { ISFUNC, (Function *)0x0 }, /* / */ + + /* Regular digits. */ + { ISFUNC, (Function *)0x0 }, /* 0 */ + { ISFUNC, (Function *)0x0 }, /* 1 */ + { ISFUNC, (Function *)0x0 }, /* 2 */ + { ISFUNC, (Function *)0x0 }, /* 3 */ + { ISFUNC, (Function *)0x0 }, /* 4 */ + { ISFUNC, (Function *)0x0 }, /* 5 */ + { ISFUNC, (Function *)0x0 }, /* 6 */ + { ISFUNC, (Function *)0x0 }, /* 7 */ + { ISFUNC, (Function *)0x0 }, /* 8 */ + { ISFUNC, (Function *)0x0 }, /* 9 */ + + /* A little more punctuation. */ + { ISFUNC, (Function *)0x0 }, /* : */ + { ISFUNC, (Function *)0x0 }, /* ; */ + { ISFUNC, (Function *)0x0 }, /* < */ + { ISFUNC, (Function *)0x0 }, /* = */ + { ISFUNC, (Function *)0x0 }, /* > */ + { ISFUNC, (Function *)0x0 }, /* ? */ + { ISFUNC, (Function *)0x0 }, /* @ */ + + /* Uppercase alphabet. */ + { ISFUNC, rl_do_lowercase_version }, /* A */ + { ISFUNC, rl_do_lowercase_version }, /* B */ + { ISFUNC, rl_do_lowercase_version }, /* C */ + { ISFUNC, rl_do_lowercase_version }, /* D */ + { ISFUNC, rl_do_lowercase_version }, /* E */ + { ISFUNC, rl_do_lowercase_version }, /* F */ + { ISFUNC, rl_do_lowercase_version }, /* G */ + { ISFUNC, rl_do_lowercase_version }, /* H */ + { ISFUNC, rl_do_lowercase_version }, /* I */ + { ISFUNC, rl_do_lowercase_version }, /* J */ + { ISFUNC, rl_do_lowercase_version }, /* K */ + { ISFUNC, rl_do_lowercase_version }, /* L */ + { ISFUNC, rl_do_lowercase_version }, /* M */ + { ISFUNC, rl_do_lowercase_version }, /* N */ + { ISFUNC, rl_do_lowercase_version }, /* O */ + { ISFUNC, rl_do_lowercase_version }, /* P */ + { ISFUNC, rl_do_lowercase_version }, /* Q */ + { ISFUNC, rl_do_lowercase_version }, /* R */ + { ISFUNC, rl_do_lowercase_version }, /* S */ + { ISFUNC, rl_do_lowercase_version }, /* T */ + { ISFUNC, rl_do_lowercase_version }, /* U */ + { ISFUNC, rl_do_lowercase_version }, /* V */ + { ISFUNC, rl_do_lowercase_version }, /* W */ + { ISFUNC, rl_do_lowercase_version }, /* X */ + { ISFUNC, rl_do_lowercase_version }, /* Y */ + { ISFUNC, rl_do_lowercase_version }, /* Z */ + + /* Some more punctuation. */ + { ISFUNC, (Function *)0x0 }, /* [ */ + { ISFUNC, (Function *)0x0 }, /* \ */ + { ISFUNC, (Function *)0x0 }, /* ] */ + { ISFUNC, (Function *)0x0 }, /* ^ */ + { ISFUNC, (Function *)0x0 }, /* _ */ + { ISFUNC, (Function *)0x0 }, /* ` */ + + /* Lowercase alphabet. */ + { ISFUNC, (Function *)0x0 }, /* a */ + { ISFUNC, (Function *)0x0 }, /* b */ + { ISFUNC, (Function *)0x0 }, /* c */ + { ISFUNC, (Function *)0x0 }, /* d */ + { ISFUNC, rl_call_last_kbd_macro }, /* e */ + { ISFUNC, (Function *)0x0 }, /* f */ + { ISFUNC, (Function *)0x0 }, /* g */ + { ISFUNC, (Function *)0x0 }, /* h */ + { ISFUNC, (Function *)0x0 }, /* i */ + { ISFUNC, (Function *)0x0 }, /* j */ + { ISFUNC, (Function *)0x0 }, /* k */ + { ISFUNC, (Function *)0x0 }, /* l */ + { ISFUNC, (Function *)0x0 }, /* m */ + { ISFUNC, (Function *)0x0 }, /* n */ + { ISFUNC, (Function *)0x0 }, /* o */ + { ISFUNC, (Function *)0x0 }, /* p */ + { ISFUNC, (Function *)0x0 }, /* q */ + { ISFUNC, (Function *)0x0 }, /* r */ + { ISFUNC, (Function *)0x0 }, /* s */ + { ISFUNC, (Function *)0x0 }, /* t */ + { ISFUNC, (Function *)0x0 }, /* u */ + { ISFUNC, (Function *)0x0 }, /* v */ + { ISFUNC, (Function *)0x0 }, /* w */ + { ISFUNC, (Function *)0x0 }, /* x */ + { ISFUNC, (Function *)0x0 }, /* y */ + { ISFUNC, (Function *)0x0 }, /* z */ + + /* Final punctuation. */ + { ISFUNC, (Function *)0x0 }, /* { */ + { ISFUNC, (Function *)0x0 }, /* | */ + { ISFUNC, (Function *)0x0 }, /* } */ + { ISFUNC, (Function *)0x0 }, /* ~ */ + { ISFUNC, rl_backward_kill_line }, /* RUBOUT */ + +#if KEYMAP_SIZE > 128 + /* Undefined keys. */ + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 } +#endif /* KEYMAP_SIZE > 128 */ +}; diff --git a/examples/Inputrc b/examples/Inputrc new file mode 100644 index 0000000..5b71bd7 --- /dev/null +++ b/examples/Inputrc @@ -0,0 +1,65 @@ +# My ~/.inputrc file is in -*- text -*- for easy editing with Emacs. +# +# Notice the various bindings which are conditionalized depending +# on which program is running, or what terminal is active. +# + +# In all programs, all terminals, make sure this is bound. +"\C-x\C-r": re-read-init-file + +# Hp terminals (and some others) have ugly default behaviour for C-h. +"\C-h": backward-delete-char +"\e\C-h": backward-kill-word +"\C-xd": dump-functions + +# In xterm windows, make the arrow keys do the right thing. +$if TERM=xterm +"\e[A": previous-history +"\e[B": next-history +"\e[C": forward-char +"\e[D": backward-char + +# alternate arrow key prefix +"\eOA": previous-history +"\eOB": next-history +"\eOC": forward-char +"\eOD": backward-char + +# Under Xterm in Bash, we bind local Function keys to do something useful. +$if Bash +"\e[11~": "Function Key 1" +"\e[12~": "Function Key 2" +"\e[13~": "Function Key 3" +"\e[14~": "Function Key 4" +"\e[15~": "Function Key 5" + +# I know the following escape sequence numbers are 1 greater than +# the function key. Don't ask me why, I didn't design the xterm terminal. +"\e[17~": "Function Key 6" +"\e[18~": "Function Key 7" +"\e[19~": "Function Key 8" +"\e[20~": "Function Key 9" +"\e[21~": "Function Key 10" +$endif +$endif + +# For Bash, all terminals, add some Bash specific hacks. +$if Bash +"\C-xv": show-bash-version +"\C-x\C-e": shell-expand-line + +# Here is one for editing my path. +"\C-xp": "$PATH\C-x\C-e\C-e\"\C-aPATH=\":\C-b" + +# Make C-x r read my mail in emacs. +# "\C-xr": "emacs -f rmail\C-j" +$endif + +# For FTP, different hacks: +$if Ftp +"\C-xg": "get \M-?" +"\C-xt": "put \M-?" +"\M-.": yank-last-arg +$endif + +" ": self-insert diff --git a/examples/Makefile b/examples/Makefile new file mode 100644 index 0000000..55ebffc --- /dev/null +++ b/examples/Makefile @@ -0,0 +1,12 @@ +# This is the Makefile for the examples subdirectory of readline. -*- text -*- +# + +EXECUTABLES = fileman +CFLAGS = -g -I.. +LDFLAGS = -g -L.. + +fileman: fileman.o + $(CC) $(LDFLAGS) -o fileman fileman.o -lreadline -ltermcap + +fileman.o: fileman.c + diff --git a/examples/fileman.c b/examples/fileman.c new file mode 100644 index 0000000..3ecb9f1 --- /dev/null +++ b/examples/fileman.c @@ -0,0 +1,425 @@ +/* fileman.c -- A tiny application which demonstrates how to use the + GNU Readline library. This application interactively allows users + to manipulate files and their modes. */ + +#include +#include +#include +#include +#include + +#include +#include + +extern char *getwd (); +extern char *xmalloc (); + +/* The names of functions that actually do the manipulation. */ +int com_list (), com_view (), com_rename (), com_stat (), com_pwd (); +int com_delete (), com_help (), com_cd (), com_quit (); + +/* A structure which contains information on the commands this program + can understand. */ + +typedef struct { + char *name; /* User printable name of the function. */ + Function *func; /* Function to call to do the job. */ + char *doc; /* Documentation for this function. */ +} COMMAND; + +COMMAND commands[] = { + { "cd", com_cd, "Change to directory DIR" }, + { "delete", com_delete, "Delete FILE" }, + { "help", com_help, "Display this text" }, + { "?", com_help, "Synonym for `help'" }, + { "list", com_list, "List files in DIR" }, + { "ls", com_list, "Synonym for `list'" }, + { "pwd", com_pwd, "Print the current working directory" }, + { "quit", com_quit, "Quit using Fileman" }, + { "rename", com_rename, "Rename FILE to NEWNAME" }, + { "stat", com_stat, "Print out statistics on FILE" }, + { "view", com_view, "View the contents of FILE" }, + { (char *)NULL, (Function *)NULL, (char *)NULL } +}; + +/* Forward declarations. */ +char *stripwhite (); +COMMAND *find_command (); + +/* The name of this program, as taken from argv[0]. */ +char *progname; + +/* When non-zero, this global means the user is done using this program. */ +int done; + +char * +dupstr (s) + int s; +{ + char *r; + + r = xmalloc (strlen (s) + 1); + strcpy (r, s); + return (r); +} + +main (argc, argv) + int argc; + char **argv; +{ + char *line, *s; + + progname = argv[0]; + + initialize_readline (); /* Bind our completer. */ + + /* Loop reading and executing lines until the user quits. */ + for ( ; done == 0; ) + { + line = readline ("FileMan: "); + + if (!line) + break; + + /* Remove leading and trailing whitespace from the line. + Then, if there is anything left, add it to the history list + and execute it. */ + s = stripwhite (line); + + if (*s) + { + add_history (s); + execute_line (s); + } + + free (line); + } + exit (0); +} + +/* Execute a command line. */ +int +execute_line (line) + char *line; +{ + register int i; + COMMAND *command; + char *word; + + /* Isolate the command word. */ + i = 0; + while (line[i] && whitespace (line[i])) + i++; + word = line + i; + + while (line[i] && !whitespace (line[i])) + i++; + + if (line[i]) + line[i++] = '\0'; + + command = find_command (word); + + if (!command) + { + fprintf (stderr, "%s: No such command for FileMan.\n", word); + return (-1); + } + + /* Get argument to command, if any. */ + while (whitespace (line[i])) + i++; + + word = line + i; + + /* Call the function. */ + return ((*(command->func)) (word)); +} + +/* Look up NAME as the name of a command, and return a pointer to that + command. Return a NULL pointer if NAME isn't a command name. */ +COMMAND * +find_command (name) + char *name; +{ + register int i; + + for (i = 0; commands[i].name; i++) + if (strcmp (name, commands[i].name) == 0) + return (&commands[i]); + + return ((COMMAND *)NULL); +} + +/* Strip whitespace from the start and end of STRING. Return a pointer + into STRING. */ +char * +stripwhite (string) + char *string; +{ + register char *s, *t; + + for (s = string; whitespace (*s); s++) + ; + + if (*s == 0) + return (s); + + t = s + strlen (s) - 1; + while (t > s && whitespace (*t)) + t--; + *++t = '\0'; + + return s; +} + +/* **************************************************************** */ +/* */ +/* Interface to Readline Completion */ +/* */ +/* **************************************************************** */ + +char *command_generator (); +char **fileman_completion (); + +/* Tell the GNU Readline library how to complete. We want to try to complete + on command names if this is the first word in the line, or on filenames + if not. */ +initialize_readline () +{ + /* Allow conditional parsing of the ~/.inputrc file. */ + rl_readline_name = "FileMan"; + + /* Tell the completer that we want a crack first. */ + rl_attempted_completion_function = (CPPFunction *)fileman_completion; +} + +/* Attempt to complete on the contents of TEXT. START and END show the + region of TEXT that contains the word to complete. We can use the + entire line in case we want to do some simple parsing. Return the + array of matches, or NULL if there aren't any. */ +char ** +fileman_completion (text, start, end) + char *text; + int start, end; +{ + char **matches; + + matches = (char **)NULL; + + /* If this word is at the start of the line, then it is a command + to complete. Otherwise it is the name of a file in the current + directory. */ + if (start == 0) + matches = completion_matches (text, command_generator); + + return (matches); +} + +/* Generator function for command completion. STATE lets us know whether + to start from scratch; without any state (i.e. STATE == 0), then we + start at the top of the list. */ +char * +command_generator (text, state) + char *text; + int state; +{ + static int list_index, len; + char *name; + + /* If this is a new word to complete, initialize now. This includes + saving the length of TEXT for efficiency, and initializing the index + variable to 0. */ + if (!state) + { + list_index = 0; + len = strlen (text); + } + + /* Return the next name which partially matches from the command list. */ + while (name = commands[list_index].name) + { + list_index++; + + if (strncmp (name, text, len) == 0) + return (dupstr(name)); + } + + /* If no names matched, then return NULL. */ + return ((char *)NULL); +} + +/* **************************************************************** */ +/* */ +/* FileMan Commands */ +/* */ +/* **************************************************************** */ + +/* String to pass to system (). This is for the LIST, VIEW and RENAME + commands. */ +static char syscom[1024]; + +/* List the file(s) named in arg. */ +com_list (arg) + char *arg; +{ + if (!arg) + arg = ""; + + sprintf (syscom, "ls -FClg %s", arg); + return (system (syscom)); +} + +com_view (arg) + char *arg; +{ + if (!valid_argument ("view", arg)) + return 1; + + sprintf (syscom, "more %s", arg); + return (system (syscom)); +} + +com_rename (arg) + char *arg; +{ + too_dangerous ("rename"); + return (1); +} + +com_stat (arg) + char *arg; +{ + struct stat finfo; + + if (!valid_argument ("stat", arg)) + return (1); + + if (stat (arg, &finfo) == -1) + { + perror (arg); + return (1); + } + + printf ("Statistics for `%s':\n", arg); + + printf ("%s has %d link%s, and is %d byte%s in length.\n", arg, + finfo.st_nlink, + (finfo.st_nlink == 1) ? "" : "s", + finfo.st_size, + (finfo.st_size == 1) ? "" : "s"); + printf ("Inode Last Change at: %s", ctime (&finfo.st_ctime)); + printf (" Last access at: %s", ctime (&finfo.st_atime)); + printf (" Last modified at: %s", ctime (&finfo.st_mtime)); + return (0); +} + +com_delete (arg) + char *arg; +{ + too_dangerous ("delete"); + return (1); +} + +/* Print out help for ARG, or for all of the commands if ARG is + not present. */ +com_help (arg) + char *arg; +{ + register int i; + int printed = 0; + + for (i = 0; commands[i].name; i++) + { + if (!*arg || (strcmp (arg, commands[i].name) == 0)) + { + printf ("%s\t\t%s.\n", commands[i].name, commands[i].doc); + printed++; + } + } + + if (!printed) + { + printf ("No commands match `%s'. Possibilties are:\n", arg); + + for (i = 0; commands[i].name; i++) + { + /* Print in six columns. */ + if (printed == 6) + { + printed = 0; + printf ("\n"); + } + + printf ("%s\t", commands[i].name); + printed++; + } + + if (printed) + printf ("\n"); + } + return (0); +} + +/* Change to the directory ARG. */ +com_cd (arg) + char *arg; +{ + if (chdir (arg) == -1) + { + perror (arg); + return 1; + } + + com_pwd (""); + return (0); +} + +/* Print out the current working directory. */ +com_pwd (ignore) + char *ignore; +{ + char dir[1024], *s; + + s = getwd (dir); + if (s == 0) + { + printf ("Error getting pwd: %s\n", dir); + return 1; + } + + printf ("Current directory is %s\n", dir); + return 0; +} + +/* The user wishes to quit using this program. Just set DONE non-zero. */ +com_quit (arg) + char *arg; +{ + done = 1; + return (0); +} + +/* Function which tells you that you can't do this. */ +too_dangerous (caller) + char *caller; +{ + fprintf (stderr, + "%s: Too dangerous for me to distribute. Write it yourself.\n", + caller); +} + +/* Return non-zero if ARG is a valid argument for CALLER, else print + an error message and return zero. */ +int +valid_argument (caller, arg) + char *caller, *arg; +{ + if (!arg || !*arg) + { + fprintf (stderr, "%s: Argument required.\n", caller); + return (0); + } + + return (1); +} diff --git a/examples/histexamp.c b/examples/histexamp.c new file mode 100644 index 0000000..eceb66d --- /dev/null +++ b/examples/histexamp.c @@ -0,0 +1,82 @@ +main () +{ + char line[1024], *t; + int len, done = 0; + + line[0] = 0; + + using_history (); + while (!done) + { + printf ("history$ "); + fflush (stdout); + t = fgets (line, sizeof (line) - 1, stdin); + if (t && *t) + { + len = strlen (t); + if (t[len - 1] == '\n') + t[len - 1] = '\0'; + } + + if (!t) + strcpy (line, "quit"); + + if (line[0]) + { + char *expansion; + int result; + + using_history (); + + result = history_expand (line, &expansion); + if (result) + fprintf (stderr, "%s\n", expansion); + + if (result < 0 || result == 2) + { + free (expansion); + continue; + } + + add_history (expansion); + strncpy (line, expansion, sizeof (line) - 1); + free (expansion); + } + + if (strcmp (line, "quit") == 0) + done = 1; + else if (strcmp (line, "save") == 0) + write_history ("history_file"); + else if (strcmp (line, "read") == 0) + read_history ("history_file"); + else if (strcmp (line, "list") == 0) + { + register HIST_ENTRY **the_list; + register int i; + + the_list = history_list (); + if (the_list) + for (i = 0; the_list[i]; i++) + printf ("%d: %s\n", i + history_base, the_list[i]->line); + } + else if (strncmp (line, "delete", 6) == 0) + { + int which; + if ((sscanf (line + 6, "%d", &which)) == 1) + { + HIST_ENTRY *entry = remove_history (which); + if (!entry) + fprintf (stderr, "No such entry %d\n", which); + else + { + free (entry->line); + free (entry); + } + } + else + { + fprintf (stderr, "non-numeric arg given to `delete'\n"); + } + } + } +} diff --git a/examples/manexamp.c b/examples/manexamp.c new file mode 100644 index 0000000..3496efa --- /dev/null +++ b/examples/manexamp.c @@ -0,0 +1,94 @@ +/* manexamp.c -- The examples which appear in the documentation are here. */ + +#include +#include + + +/* **************************************************************** */ +/* */ +* How to Emulate gets () */ +/* */ +/* **************************************************************** */ + +/* A static variable for holding the line. */ +static char *line_read = (char *)NULL; + +/* Read a string, and return a pointer to it. Returns NULL on EOF. */ +char * +rl_gets () +{ + /* If the buffer has already been allocated, return the memory + to the free pool. */ + if (line_read) + { + free (line_read); + line_read = (char *)NULL; + } + + /* Get a line from the user. */ + line_read = readline (""); + + /* If the line has any text in it, save it on the history. */ + if (line_read && *line_read) + add_history (line_read); + + return (line_read); +} + +/* **************************************************************** */ +/* */ +/* Writing a Function to be Called by Readline. */ +/* */ +/* **************************************************************** */ + +/* Invert the case of the COUNT following characters. */ +invert_case_line (count, key) + int count, key; +{ + register int start, end; + + start = rl_point; + + if (count < 0) + { + direction = -1; + count = -count; + } + else + direction = 1; + + /* Find the end of the range to modify. */ + end = start + (count * direction); + + /* Force it to be within range. */ + if (end > rl_end) + end = rl_end; + else if (end < 0) + end = -1; + + if (start > end) + { + int temp = start; + start = end; + end = temp; + } + + if (start == end) + return; + + /* Tell readline that we are modifying the line, so save the undo + information. */ + rl_modifying (start, end); + + for (; start != end; start += direction) + { + if (uppercase_p (rl_line_buffer[start])) + rl_line_buffer[start] = to_lower (rl_line_buffer[start]); + else if (lowercase_p (rl_line_buffer[start])) + rl_line_buffer[start] = to_upper (rl_line_buffer[start]); + } + + /* Move point to on top of the last character changed. */ + rl_point = end - direction; +} + diff --git a/funmap.c b/funmap.c new file mode 100644 index 0000000..9255974 --- /dev/null +++ b/funmap.c @@ -0,0 +1,299 @@ +/* funmap.c -- attach names to functions. */ + +/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library 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 1, or + (at your option) any later version. + + The GNU Readline Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define READLINE_LIBRARY + +#if defined (STATIC_MALLOC) +static char *xmalloc (), *xrealloc (); +#else +extern char *xmalloc (), *xrealloc (); +#endif /* STATIC_MALLOC */ + +#if !defined (BUFSIZ) +#include +#endif /* BUFSIZ */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#include "rlconf.h" +#include "readline.h" + +static int qsort_string_compare (); + +FUNMAP **funmap = (FUNMAP **)NULL; +static int funmap_size = 0; +static int funmap_entry = 0; + +/* After initializing the function map, this is the index of the first + program specific function. */ +int funmap_program_specific_entry_start; + +static FUNMAP default_funmap[] = { + + { "abort", rl_abort }, + { "accept-line", rl_newline }, + { "arrow-key-prefix", rl_arrow_keys }, + { "backward-char", rl_backward }, + { "backward-delete-char", rl_rubout }, + { "backward-kill-line", rl_backward_kill_line }, + { "backward-kill-word", rl_backward_kill_word }, + { "backward-word", rl_backward_word }, + { "beginning-of-history", rl_beginning_of_history }, + { "beginning-of-line", rl_beg_of_line }, + { "call-last-kbd-macro", rl_call_last_kbd_macro }, + { "capitalize-word", rl_capitalize_word }, + { "clear-screen", rl_clear_screen }, + { "complete", rl_complete }, + { "delete-char", rl_delete }, + { "delete-horizontal-space", rl_delete_horizontal_space }, + { "digit-argument", rl_digit_argument }, + { "do-lowercase-version", rl_do_lowercase_version }, + { "downcase-word", rl_downcase_word }, + { "dump-functions", rl_dump_functions }, + { "emacs-editing-mode", rl_emacs_editing_mode }, + { "end-kbd-macro", rl_end_kbd_macro }, + { "end-of-history", rl_end_of_history }, + { "end-of-line", rl_end_of_line }, + { "forward-char", rl_forward }, + { "forward-search-history", rl_forward_search_history }, + { "forward-word", rl_forward_word }, + { "history-search-backward", rl_history_search_backward }, + { "history-search-forward", rl_history_search_forward }, + { "insert-completions", rl_insert_completions }, + { "kill-whole-line", rl_kill_full_line }, + { "kill-line", rl_kill_line }, + { "kill-word", rl_kill_word }, + { "next-history", rl_get_next_history }, + { "non-incremental-forward-search-history", rl_noninc_forward_search }, + { "non-incremental-reverse-search-history", rl_noninc_reverse_search }, + { "non-incremental-forward-search-history-again", rl_noninc_forward_search_again }, + { "non-incremental-reverse-search-history-again", rl_noninc_reverse_search_again }, + { "possible-completions", rl_possible_completions }, + { "previous-history", rl_get_previous_history }, + { "quoted-insert", rl_quoted_insert }, + { "re-read-init-file", rl_re_read_init_file }, + { "redraw-current-line", rl_refresh_line}, + { "reverse-search-history", rl_reverse_search_history }, + { "revert-line", rl_revert_line }, + { "self-insert", rl_insert }, + { "start-kbd-macro", rl_start_kbd_macro }, + { "tab-insert", rl_tab_insert }, + { "tilde-expand", rl_tilde_expand }, + { "transpose-chars", rl_transpose_chars }, + { "transpose-words", rl_transpose_words }, + { "tty-status", rl_tty_status }, + { "undo", rl_undo_command }, + { "universal-argument", rl_universal_argument }, + { "unix-line-discard", rl_unix_line_discard }, + { "unix-word-rubout", rl_unix_word_rubout }, + { "upcase-word", rl_upcase_word }, + { "yank", rl_yank }, + { "yank-last-arg", rl_yank_last_arg }, + { "yank-nth-arg", rl_yank_nth_arg }, + { "yank-pop", rl_yank_pop }, + +#if defined (VI_MODE) + { "vi-append-eol", rl_vi_append_eol }, + { "vi-append-mode", rl_vi_append_mode }, + { "vi-arg-digit", rl_vi_arg_digit }, + { "vi-bWord", rl_vi_bWord }, + { "vi-bracktype", rl_vi_bracktype }, + { "vi-bword", rl_vi_bword }, + { "vi-change-case", rl_vi_change_case }, + { "vi-change-char", rl_vi_change_char }, + { "vi-change-to", rl_vi_change_to }, + { "vi-char-search", rl_vi_char_search }, + { "vi-column", rl_vi_column }, + { "vi-comment", rl_vi_comment }, + { "vi-complete", rl_vi_complete }, + { "vi-delete", rl_vi_delete }, + { "vi-delete-to", rl_vi_delete_to }, + { "vi-eWord", rl_vi_eWord }, + { "vi-editing-mode", rl_vi_editing_mode }, + { "vi-end-word", rl_vi_end_word }, + { "vi-eof-maybe", rl_vi_eof_maybe }, + { "vi-eword", rl_vi_eword }, + { "vi-fWord", rl_vi_fWord }, + { "vi-first-print", rl_vi_first_print }, + { "vi-fword", rl_vi_fword }, + { "vi-insert-beg", rl_vi_insert_beg }, + { "vi-insertion-mode", rl_vi_insertion_mode }, + { "vi-match", rl_vi_match }, + { "vi-movement-mode", rl_vi_movement_mode }, + { "vi-next-word", rl_vi_next_word }, + { "vi-overstrike", rl_vi_overstrike }, + { "vi-overstrike-delete", rl_vi_overstrike_delete }, + { "vi-prev-word", rl_vi_prev_word }, + { "vi-put", rl_vi_put }, + { "vi-redo", rl_vi_redo }, + { "vi-replace", rl_vi_replace }, + { "vi-search", rl_vi_search }, + { "vi-search-again", rl_vi_search_again }, + { "vi-subst", rl_vi_subst }, + { "vi-tilde-expand", rl_vi_tilde_expand }, + { "vi-yank-arg", rl_vi_yank_arg }, + { "vi-yank-to", rl_vi_yank_to }, +#endif /* VI_MODE */ + + {(char *)NULL, (Function *)NULL } +}; + +rl_add_funmap_entry (name, function) + char *name; + Function *function; +{ + if (funmap_entry + 2 >= funmap_size) + if (!funmap) + funmap = (FUNMAP **)xmalloc ((funmap_size = 80) * sizeof (FUNMAP *)); + else + funmap = + (FUNMAP **)xrealloc (funmap, (funmap_size += 80) * sizeof (FUNMAP *)); + + funmap[funmap_entry] = (FUNMAP *)xmalloc (sizeof (FUNMAP)); + funmap[funmap_entry]->name = name; + funmap[funmap_entry]->function = function; + + funmap[++funmap_entry] = (FUNMAP *)NULL; + return funmap_entry; +} + +static int funmap_initialized = 0; + +/* Make the funmap contain all of the default entries. */ +void +rl_initialize_funmap () +{ + register int i; + + if (funmap_initialized) + return; + + for (i = 0; default_funmap[i].name; i++) + rl_add_funmap_entry (default_funmap[i].name, default_funmap[i].function); + + funmap_initialized = 1; + funmap_program_specific_entry_start = i; +} + +/* Produce a NULL terminated array of known function names. The array + is sorted. The array itself is allocated, but not the strings inside. + You should free () the array when you done, but not the pointrs. */ +char ** +rl_funmap_names () +{ + char **result = (char **)NULL; + int result_size, result_index; + + result_size = result_index = 0; + + /* Make sure that the function map has been initialized. */ + rl_initialize_funmap (); + + for (result_index = 0; funmap[result_index]; result_index++) + { + if (result_index + 2 > result_size) + { + if (!result) + result = (char **)xmalloc ((result_size = 20) * sizeof (char *)); + else + result = (char **) + xrealloc (result, (result_size += 20) * sizeof (char *)); + } + + result[result_index] = funmap[result_index]->name; + result[result_index + 1] = (char *)NULL; + } + + qsort (result, result_index, sizeof (char *), qsort_string_compare); + return (result); +} + +/* Stupid comparison routine for qsort () ing strings. */ +static int +qsort_string_compare (s1, s2) + register char **s1, **s2; +{ + int r; + + r = **s1 - **s2; + if (r == 0) + r = strcmp (*s1, *s2); + return r; +} + +/* Things that mean `Control'. */ +char *possible_control_prefixes[] = { + "Control-", "C-", "CTRL-", (char *)NULL +}; + +char *possible_meta_prefixes[] = { + "Meta", "M-", (char *)NULL +}; + +#if defined (STATIC_MALLOC) + +/* **************************************************************** */ +/* */ +/* xmalloc and xrealloc () */ +/* */ +/* **************************************************************** */ + +static void memory_error_and_abort (); + +static char * +xmalloc (bytes) + int bytes; +{ + char *temp = (char *)malloc (bytes); + + if (!temp) + memory_error_and_abort (); + return (temp); +} + +static char * +xrealloc (pointer, bytes) + char *pointer; + int bytes; +{ + char *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, "history: Out of virtual memory!\n"); + abort (); +} +#endif /* STATIC_MALLOC */ diff --git a/history.c b/history.c new file mode 100644 index 0000000..68e99cf --- /dev/null +++ b/history.c @@ -0,0 +1,2171 @@ +/* History.c -- standalone history library */ + +/* Copyright (C) 1989, 1992 Free Software Foundation, Inc. + + This file contains the GNU History Library (the Library), a set of + routines for managing the text of previously typed lines. + + The Library 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 1, or (at your option) + any later version. + + The Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* The goal is to make the implementation transparent, so that you + don't have to know what data types are used, just what functions + you can call. I think I have done that. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ +#if defined (HAVE_UNISTD_H) +# include +#endif +#if defined (HAVE_STRING_H) +# include +#else +# include +#endif /* !HAVE_STRING_H */ +#include + +/* Not all systems declare ERRNO in errno.h... and some systems #define it! */ +#if !defined (errno) +extern int errno; +#endif /* !errno */ + +#include "memalloc.h" +#include "history.h" + +#if defined (STATIC_MALLOC) +static char *xmalloc (), *xrealloc (); +#else +extern char *xmalloc (), *xrealloc (); +#endif /* STATIC_MALLOC */ + +#define STREQ(a, b) (((a)[0] == (b)[0]) && (strcmp ((a), (b)) == 0)) +#define STREQN(a, b, n) (((a)[0] == (b)[0]) && (strncmp ((a), (b), (n)) == 0)) + +#ifndef savestring +# ifndef strcpy +extern char *strcpy (); +# endif +#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x)) +#endif + +#ifndef whitespace +#define whitespace(c) (((c) == ' ') || ((c) == '\t')) +#endif + +#ifndef digit_p +#define digit_p(c) ((c) >= '0' && (c) <= '9') +#endif + +#ifndef digit_value +#define digit_value(c) ((c) - '0') +#endif + +#ifndef member +# ifndef strchr +extern char *strchr (); +# endif +#define member(c, s) ((c) ? ((char *)strchr ((s), (c)) != (char *)NULL) : 0) +#endif + +/* Possible history errors passed to hist_error. */ +#define EVENT_NOT_FOUND 0 +#define BAD_WORD_SPEC 1 +#define SUBST_FAILED 2 +#define BAD_MODIFIER 3 + +static char error_pointer; + +static char *subst_lhs; +static char *subst_rhs; +static int subst_lhs_len = 0; +static int subst_rhs_len = 0; + +static char *get_history_word_specifier (); + +#if defined (SHELL) +extern char *single_quote (); +#endif + +/* **************************************************************** */ +/* */ +/* History Functions */ +/* */ +/* **************************************************************** */ + +/* An array of HIST_ENTRY. This is where we store the history. */ +static HIST_ENTRY **the_history = (HIST_ENTRY **)NULL; + +/* Non-zero means that we have enforced a limit on the amount of + history that we save. */ +static int history_stifled = 0; + +/* If HISTORY_STIFLED is non-zero, then this is the maximum number of + entries to remember. */ +int max_input_history; + +/* The current location of the interactive history pointer. Just makes + life easier for outside callers. */ +static int history_offset = 0; + +/* The number of strings currently stored in the input_history list. */ +int history_length = 0; + +/* The current number of slots allocated to the input_history. */ +static int history_size = 0; + +/* The number of slots to increase the_history by. */ +#define DEFAULT_HISTORY_GROW_SIZE 50 + +/* The character that represents the start of a history expansion + request. This is usually `!'. */ +char history_expansion_char = '!'; + +/* The character that invokes word substitution if found at the start of + a line. This is usually `^'. */ +char history_subst_char = '^'; + +/* During tokenization, if this character is seen as the first character + of a word, then it, and all subsequent characters upto a newline are + ignored. For a Bourne shell, this should be '#'. Bash special cases + the interactive comment character to not be a comment delimiter. */ +char history_comment_char = '\0'; + +/* The list of characters which inhibit the expansion of text if found + immediately following history_expansion_char. */ +char *history_no_expand_chars = " \t\n\r="; + +/* The logical `base' of the history array. It defaults to 1. */ +int history_base = 1; + +/* Return the current HISTORY_STATE of the history. */ +HISTORY_STATE * +history_get_history_state () +{ + HISTORY_STATE *state; + + state = (HISTORY_STATE *)xmalloc (sizeof (HISTORY_STATE)); + state->entries = the_history; + state->offset = history_offset; + state->length = history_length; + state->size = history_size; + state->flags = 0; + if (history_stifled) + state->flags |= HS_STIFLED; + + return (state); +} + +/* Set the state of the current history array to STATE. */ +void +history_set_history_state (state) + HISTORY_STATE *state; +{ + the_history = state->entries; + history_offset = state->offset; + history_length = state->length; + history_size = state->size; + if (state->flags & HS_STIFLED) + history_stifled = 1; +} + +/* Begin a session in which the history functions might be used. This + initializes interactive variables. */ +void +using_history () +{ + history_offset = history_length; +} + +/* Return the number of bytes that the primary history entries are using. + This just adds up the lengths of the_history->lines. */ +int +history_total_bytes () +{ + register int i, result; + + result = 0; + + for (i = 0; the_history && the_history[i]; i++) + result += strlen (the_history[i]->line); + + return (result); +} + +/* Place STRING at the end of the history list. The data field + is set to NULL. */ +void +add_history (string) + char *string; +{ + HIST_ENTRY *temp; + + if (history_stifled && (history_length == max_input_history)) + { + register int i; + + /* If the history is stifled, and history_length is zero, + and it equals max_input_history, we don't save items. */ + if (history_length == 0) + return; + + /* If there is something in the slot, then remove it. */ + if (the_history[0]) + { + free (the_history[0]->line); + free (the_history[0]); + } + + /* Copy the rest of the entries, moving down one slot. */ + for (i = 0; i < history_length; i++) + the_history[i] = the_history[i + 1]; + + history_base++; + + } + else + { + if (!history_size) + { + history_size = DEFAULT_HISTORY_GROW_SIZE; + the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *)); + history_length = 1; + + } + else + { + if (history_length == (history_size - 1)) + { + history_size += DEFAULT_HISTORY_GROW_SIZE; + the_history = (HIST_ENTRY **) + xrealloc (the_history, history_size * sizeof (HIST_ENTRY *)); + } + history_length++; + } + } + + temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); + temp->line = savestring (string); + temp->data = (char *)NULL; + + the_history[history_length] = (HIST_ENTRY *)NULL; + the_history[history_length - 1] = temp; +} + +/* Make the history entry at WHICH have LINE and DATA. This returns + the old entry so you can dispose of the data. In the case of an + invalid WHICH, a NULL pointer is returned. */ +HIST_ENTRY * +replace_history_entry (which, line, data) + int which; + char *line; + char *data; +{ + HIST_ENTRY *temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); + HIST_ENTRY *old_value; + + if (which >= history_length) + return ((HIST_ENTRY *)NULL); + + old_value = the_history[which]; + + temp->line = savestring (line); + temp->data = data; + the_history[which] = temp; + + return (old_value); +} + +/* Returns the magic number which says what history element we are + looking at now. In this implementation, it returns history_offset. */ +int +where_history () +{ + return (history_offset); +} + +/* Search the history for STRING, starting at history_offset. + If DIRECTION < 0, then the search is through previous entries, else + through subsequent. If ANCHORED is non-zero, the string must + appear at the beginning of a history line, otherwise, the string + may appear anywhere in the line. If the string is found, then + current_history () is the history entry, and the value of this + function is the offset in the line of that history entry that the + string was found in. Otherwise, nothing is changed, and a -1 is + returned. */ + +#define ANCHORED_SEARCH 1 +#define NON_ANCHORED_SEARCH 0 + +static int +history_search_internal (string, direction, anchored) + char *string; + int direction, anchored; +{ + register int i, reverse; + register char *line; + register int line_index; + int string_len; + + i = history_offset; + reverse = (direction < 0); + + /* Take care of trivial cases first. */ + + if (!history_length || ((i == history_length) && !reverse)) + return (-1); + + if (reverse && (i == history_length)) + i--; + +#define NEXT_LINE() do { if (reverse) i--; else i++; } while (0) + + string_len = strlen (string); + while (1) + { + /* Search each line in the history list for STRING. */ + + /* At limit for direction? */ + if ((reverse && i < 0) || (!reverse && i == history_length)) + return (-1); + + line = the_history[i]->line; + line_index = strlen (line); + + /* If STRING is longer than line, no match. */ + if (string_len > line_index) + { + NEXT_LINE (); + continue; + } + + /* Handle anchored searches first. */ + if (anchored == ANCHORED_SEARCH) + { + if (STREQN (string, line, string_len)) + { + history_offset = i; + return (0); + } + + NEXT_LINE (); + continue; + } + + /* Do substring search. */ + if (reverse) + { + line_index -= string_len; + + while (line_index >= 0) + { + if (STREQN (string, line + line_index, string_len)) + { + history_offset = i; + return (line_index); + } + line_index--; + } + } + else + { + register int limit = line_index - string_len + 1; + line_index = 0; + + while (line_index < limit) + { + if (STREQN (string, line + line_index, string_len)) + { + history_offset = i; + return (line_index); + } + line_index++; + } + } + NEXT_LINE (); + } +} + +/* Do a non-anchored search for STRING through the history in DIRECTION. */ +int +history_search (string, direction) + char *string; + int direction; +{ + return (history_search_internal (string, direction, NON_ANCHORED_SEARCH)); +} + +/* Do an anchored search for string through the history in DIRECTION. */ +int +history_search_prefix (string, direction) + char *string; + int direction; +{ + return (history_search_internal (string, direction, ANCHORED_SEARCH)); +} + +/* Remove history element WHICH from the history. The removed + element is returned to you so you can free the line, data, + and containing structure. */ +HIST_ENTRY * +remove_history (which) + int which; +{ + HIST_ENTRY *return_value; + + if (which >= history_length || !history_length) + return_value = (HIST_ENTRY *)NULL; + else + { + register int i; + return_value = the_history[which]; + + for (i = which; i < history_length; i++) + the_history[i] = the_history[i + 1]; + + history_length--; + } + + return (return_value); +} + +/* Stifle the history list, remembering only MAX number of lines. */ +void +stifle_history (max) + int max; +{ + if (max < 0) + max = 0; + + if (history_length > max) + { + register int i, j; + + /* This loses because we cannot free the data. */ + for (i = 0; i < (history_length - max); i++) + { + free (the_history[i]->line); + free (the_history[i]); + } + + history_base = i; + for (j = 0, i = history_length - max; j < max; i++, j++) + the_history[j] = the_history[i]; + the_history[j] = (HIST_ENTRY *)NULL; + history_length = j; + } + + history_stifled = 1; + max_input_history = max; +} + +/* Stop stifling the history. This returns the previous amount the history + was stifled by. The value is positive if the history was stifled, negative + if it wasn't. */ +int +unstifle_history () +{ + int result = max_input_history; + + if (history_stifled) + { + result = -result; + history_stifled = 0; + } + + return (result); +} + +int +history_is_stifled () +{ + return (history_stifled); +} + +/* Return the string that should be used in the place of this + filename. This only matters when you don't specify the + filename to read_history (), or write_history (). */ +static char * +history_filename (filename) + char *filename; +{ + char *return_val = filename ? savestring (filename) : (char *)NULL; + + if (!return_val) + { + char *home; + int home_len; + + home = getenv ("HOME"); + + if (!home) + home = "."; + + home_len = strlen (home); + /* strlen(".history") == 8 */ + return_val = xmalloc (2 + home_len + 8); + + strcpy (return_val, home); + return_val[home_len] = '/'; + strcpy (return_val + home_len + 1, ".history"); + } + + return (return_val); +} + +/* Add the contents of FILENAME to the history list, a line at a time. + If FILENAME is NULL, then read from ~/.history. Returns 0 if + successful, or errno if not. */ +int +read_history (filename) + char *filename; +{ + return (read_history_range (filename, 0, -1)); +} + +/* Read a range of lines from FILENAME, adding them to the history list. + Start reading at the FROM'th line and end at the TO'th. If FROM + is zero, start at the beginning. If TO is less than FROM, read + until the end of the file. If FILENAME is NULL, then read from + ~/.history. Returns 0 if successful, or errno if not. */ +int +read_history_range (filename, from, to) + char *filename; + int from, to; +{ + register int line_start, line_end; + char *input, *buffer = (char *)NULL; + int file, current_line; + struct stat finfo; + + input = history_filename (filename); + file = open (input, O_RDONLY, 0666); + + if ((file < 0) || (fstat (file, &finfo) == -1)) + goto error_and_exit; + + buffer = xmalloc ((int)finfo.st_size + 1); + + if (read (file, buffer, finfo.st_size) != finfo.st_size) + { + error_and_exit: + if (file >= 0) + close (file); + + if (input) + free (input); + + if (buffer) + free (buffer); + + return (errno); + } + + close (file); + + /* Set TO to larger than end of file if negative. */ + if (to < 0) + to = finfo.st_size; + + /* Start at beginning of file, work to end. */ + line_start = line_end = current_line = 0; + + /* Skip lines until we are at FROM. */ + while (line_start < finfo.st_size && current_line < from) + { + for (line_end = line_start; line_end < finfo.st_size; line_end++) + if (buffer[line_end] == '\n') + { + current_line++; + line_start = line_end + 1; + if (current_line == from) + break; + } + } + + /* If there are lines left to gobble, then gobble them now. */ + for (line_end = line_start; line_end < finfo.st_size; line_end++) + if (buffer[line_end] == '\n') + { + buffer[line_end] = '\0'; + + if (buffer[line_start]) + add_history (buffer + line_start); + + current_line++; + + if (current_line >= to) + break; + + line_start = line_end + 1; + } + + if (input) + free (input); + + if (buffer) + free (buffer); + + return (0); +} + +/* Truncate the history file FNAME, leaving only LINES trailing lines. + If FNAME is NULL, then use ~/.history. */ +int +history_truncate_file (fname, lines) + char *fname; + register int lines; +{ + register int i; + int file, chars_read; + char *buffer = (char *)NULL, *filename; + struct stat finfo; + + filename = history_filename (fname); + file = open (filename, O_RDONLY, 0666); + + if (file == -1 || fstat (file, &finfo) == -1) + goto truncate_exit; + + buffer = xmalloc ((int)finfo.st_size + 1); + chars_read = read (file, buffer, finfo.st_size); + close (file); + + if (chars_read <= 0) + goto truncate_exit; + + /* Count backwards from the end of buffer until we have passed + LINES lines. */ + for (i = chars_read - 1; lines && i; i--) + { + if (buffer[i] == '\n') + lines--; + } + + /* If this is the first line, then the file contains exactly the + number of lines we want to truncate to, so we don't need to do + anything. It's the first line if we don't find a newline between + the current value of i and 0. Otherwise, write from the start of + this line until the end of the buffer. */ + for ( ; i; i--) + if (buffer[i] == '\n') + { + i++; + break; + } + + /* Write only if there are more lines in the file than we want to + truncate to. */ + if (i && ((file = open (filename, O_WRONLY|O_TRUNC, 0666)) != -1)) + { + write (file, buffer + i, finfo.st_size - i); + close (file); + } + + truncate_exit: + if (buffer) + free (buffer); + + free (filename); + return 0; +} + +#define HISTORY_APPEND 0 +#define HISTORY_OVERWRITE 1 + +/* Workhorse function for writing history. Writes NELEMENT entries + from the history list to FILENAME. OVERWRITE is non-zero if you + wish to replace FILENAME with the entries. */ +static int +history_do_write (filename, nelements, overwrite) + char *filename; + int nelements, overwrite; +{ + register int i; + char *output = history_filename (filename); + int file, mode; + + mode = overwrite ? O_WRONLY | O_CREAT | O_TRUNC : O_WRONLY | O_APPEND; + + if ((file = open (output, mode, 0666)) == -1) + { + if (output) + free (output); + + return (errno); + } + + if (nelements > history_length) + nelements = history_length; + + /* Build a buffer of all the lines to write, and write them in one syscall. + Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */ + { + register int j = 0; + int buffer_size = 0; + char *buffer; + + /* Calculate the total number of bytes to write. */ + for (i = history_length - nelements; i < history_length; i++) + buffer_size += 1 + strlen (the_history[i]->line); + + /* Allocate the buffer, and fill it. */ + buffer = xmalloc (buffer_size); + + for (i = history_length - nelements; i < history_length; i++) + { + strcpy (buffer + j, the_history[i]->line); + j += strlen (the_history[i]->line); + buffer[j++] = '\n'; + } + + write (file, buffer, buffer_size); + free (buffer); + } + + close (file); + + if (output) + free (output); + + return (0); +} + +/* Append NELEMENT entries to FILENAME. The entries appended are from + the end of the list minus NELEMENTs up to the end of the list. */ +int +append_history (nelements, filename) + int nelements; + char *filename; +{ + return (history_do_write (filename, nelements, HISTORY_APPEND)); +} + +/* Overwrite FILENAME with the current history. If FILENAME is NULL, + then write the history list to ~/.history. Values returned + are as in read_history ().*/ +int +write_history (filename) + char *filename; +{ + return (history_do_write (filename, history_length, HISTORY_OVERWRITE)); +} + +/* Return the history entry at the current position, as determined by + history_offset. If there is no entry there, return a NULL pointer. */ +HIST_ENTRY * +current_history () +{ + if ((history_offset == history_length) || !the_history) + return ((HIST_ENTRY *)NULL); + else + return (the_history[history_offset]); +} + +/* Back up history_offset to the previous history entry, and return + a pointer to that entry. If there is no previous entry then return + a NULL pointer. */ +HIST_ENTRY * +previous_history () +{ + if (!history_offset) + return ((HIST_ENTRY *)NULL); + else + return (the_history[--history_offset]); +} + +/* Move history_offset forward to the next history entry, and return + a pointer to that entry. If there is no next entry then return a + NULL pointer. */ +HIST_ENTRY * +next_history () +{ + if (history_offset == history_length) + return ((HIST_ENTRY *)NULL); + else + return (the_history[++history_offset]); +} + +/* Return the current history array. The caller has to be carefull, since this + is the actual array of data, and could be bashed or made corrupt easily. + The array is terminated with a NULL pointer. */ +HIST_ENTRY ** +history_list () +{ + return (the_history); +} + +/* Return the history entry which is logically at OFFSET in the history array. + OFFSET is relative to history_base. */ +HIST_ENTRY * +history_get (offset) + int offset; +{ + int local_index = offset - history_base; + + if (local_index >= history_length || + local_index < 0 || + !the_history) + return ((HIST_ENTRY *)NULL); + return (the_history[local_index]); +} + +/* Search for STRING in the history list. DIR is < 0 for searching + backwards. POS is an absolute index into the history list at + which point to begin searching. */ +int +history_search_pos (string, dir, pos) + char *string; + int dir, pos; +{ + int ret, old = where_history (); + history_set_pos (pos); + if (history_search (string, dir) == -1) + { + history_set_pos (old); + return (-1); + } + ret = where_history (); + history_set_pos (old); + return ret; +} + +/* Make the current history item be the one at POS, an absolute index. + Returns zero if POS is out of range, else non-zero. */ +int +history_set_pos (pos) + int pos; +{ + if (pos > history_length || pos < 0 || !the_history) + return (0); + history_offset = pos; + return (1); +} + + +/* **************************************************************** */ +/* */ +/* History Expansion */ +/* */ +/* **************************************************************** */ + +/* Hairy history expansion on text, not tokens. This is of general + use, and thus belongs in this library. */ + +/* The last string searched for in a !?string? search. */ +static char *search_string = (char *)NULL; + +/* Return the event specified at TEXT + OFFSET modifying OFFSET to + point to after the event specifier. Just a pointer to the history + line is returned; NULL is returned in the event of a bad specifier. + You pass STRING with *INDEX equal to the history_expansion_char that + begins this specification. + DELIMITING_QUOTE is a character that is allowed to end the string + specification for what to search for in addition to the normal + characters `:', ` ', `\t', `\n', and sometimes `?'. + So you might call this function like: + line = get_history_event ("!echo:p", &index, 0); */ +char * +get_history_event (string, caller_index, delimiting_quote) + char *string; + int *caller_index; + int delimiting_quote; +{ + register int i = *caller_index; + register char c; + HIST_ENTRY *entry; + int which, sign = 1; + int local_index, search_mode, substring_okay = 0; + char *temp; + + /* The event can be specified in a number of ways. + + !! the previous command + !n command line N + !-n current command-line minus N + !str the most recent command starting with STR + !?str[?] + the most recent command containing STR + + All values N are determined via HISTORY_BASE. */ + + if (string[i] != history_expansion_char) + return ((char *)NULL); + + /* Move on to the specification. */ + i++; + +#define RETURN_ENTRY(e, w) \ + return ((e = history_get (w)) ? e->line : (char *)NULL) + + /* Handle !! case. */ + if (string[i] == history_expansion_char) + { + i++; + which = history_base + (history_length - 1); + *caller_index = i; + RETURN_ENTRY (entry, which); + } + + /* Hack case of numeric line specification. */ + if (string[i] == '-') + { + sign = -1; + i++; + } + + if (digit_p (string[i])) + { + /* Get the extent of the digits and compute the value. */ + for (which = 0; digit_p (string[i]); i++) + which = (which * 10) + digit_value (string[i]); + + *caller_index = i; + + if (sign < 0) + which = (history_length + history_base) - which; + + RETURN_ENTRY (entry, which); + } + + /* This must be something to search for. If the spec begins with + a '?', then the string may be anywhere on the line. Otherwise, + the string must be found at the start of a line. */ + if (string[i] == '?') + { + substring_okay++; + i++; + } + + /* Only a closing `?' or a newline delimit a substring search string. */ + for (local_index = i; c = string[i]; i++) + if ((!substring_okay && (whitespace (c) || c == ':' || +#if defined (SHELL) + member (c, ";&()|<>") || +#endif /* SHELL */ + string[i] == delimiting_quote)) || + string[i] == '\n' || + (substring_okay && string[i] == '?')) + break; + + temp = xmalloc (1 + (i - local_index)); + strncpy (temp, &string[local_index], (i - local_index)); + temp[i - local_index] = '\0'; + + if (substring_okay && string[i] == '?') + i++; + + *caller_index = i; + +#define FAIL_SEARCH() \ + do { history_offset = history_length; free (temp) ; return (char *)NULL; } while (0) + + search_mode = substring_okay ? NON_ANCHORED_SEARCH : ANCHORED_SEARCH; + while (1) + { + local_index = history_search_internal (temp, -1, search_mode); + + if (local_index < 0) + FAIL_SEARCH (); + + if (local_index == 0 || substring_okay) + { + entry = current_history (); + history_offset = history_length; + + /* If this was a substring search, then remember the + string that we matched for word substitution. */ + if (substring_okay) + { + if (search_string) + free (search_string); + search_string = temp; + } + else + free (temp); + return (entry->line); + } + + if (history_offset) + history_offset--; + else + FAIL_SEARCH (); + } +#undef FAIL_SEARCH +#undef RETURN_ENTRY +} +#if defined (SHELL) +/* Function for extracting single-quoted strings. Used for inhibiting + history expansion within single quotes. */ + +/* Extract the contents of STRING as if it is enclosed in single quotes. + SINDEX, when passed in, is the offset of the character immediately + following the opening single quote; on exit, SINDEX is left pointing + to the closing single quote. */ +static void +rl_string_extract_single_quoted (string, sindex) + char *string; + int *sindex; +{ + register int i = *sindex; + + while (string[i] && string[i] != '\'') + i++; + + *sindex = i; +} + +static char * +quote_breaks (s) + char *s; +{ + register char *p, *r; + char *ret; + int len = 3; + + for (p = s; p && *p; p++, len++) + { + if (*p == '\'') + len += 3; + else if (whitespace (*p) || *p == '\n') + len += 2; + } + + r = ret = xmalloc (len); + *r++ = '\''; + for (p = s; p && *p; ) + { + if (*p == '\'') + { + *r++ = '\''; + *r++ = '\\'; + *r++ = '\''; + *r++ = '\''; + p++; + } + else if (whitespace (*p) || *p == '\n') + { + *r++ = '\''; + *r++ = *p++; + *r++ = '\''; + } + else + *r++ = *p++; + } + *r++ = '\''; + *r = '\0'; + return ret; +} +#endif /* SHELL */ + +static char * +hist_error(s, start, current, errtype) + char *s; + int start, current, errtype; +{ + char *temp, *emsg; + int ll, elen; + + ll = current - start; + + switch (errtype) + { + case EVENT_NOT_FOUND: + emsg = "event not found"; + elen = 15; + break; + case BAD_WORD_SPEC: + emsg = "bad word specifier"; + elen = 18; + break; + case SUBST_FAILED: + emsg = "substitution failed"; + elen = 19; + break; + case BAD_MODIFIER: + emsg = "unrecognized history modifier"; + elen = 29; + break; + default: + emsg = "unknown expansion error"; + elen = 23; + break; + } + + temp = xmalloc (ll + elen + 3); + strncpy (temp, s + start, ll); + temp[ll] = ':'; + temp[ll + 1] = ' '; + strcpy (temp + ll + 2, emsg); + return (temp); +} + +/* Get a history substitution string from STR starting at *IPTR + and return it. The length is returned in LENPTR. + + A backslash can quote the delimiter. If the string is the + empty string, the previous pattern is used. If there is + no previous pattern for the lhs, the last history search + string is used. + + If IS_RHS is 1, we ignore empty strings and set the pattern + to "" anyway. subst_lhs is not changed if the lhs is empty; + subst_rhs is allowed to be set to the empty string. */ + +static char * +get_subst_pattern (str, iptr, delimiter, is_rhs, lenptr) + char *str; + int *iptr, delimiter, is_rhs, *lenptr; +{ + register int si, i, j, k; + char *s = (char *) NULL; + + i = *iptr; + + for (si = i; str[si] && str[si] != delimiter; si++) + if (str[si] == '\\' && str[si + 1] == delimiter) + si++; + + if (si > i || is_rhs) + { + s = xmalloc (si - i + 1); + for (j = 0, k = i; k < si; j++, k++) + { + /* Remove a backslash quoting the search string delimiter. */ + if (str[k] == '\\' && str[k + 1] == delimiter) + k++; + s[j] = str[k]; + } + s[j] = '\0'; + if (lenptr) + *lenptr = j; + } + + i = si; + if (str[i]) + i++; + *iptr = i; + + return s; +} + +static void +postproc_subst_rhs () +{ + char *new; + int i, j, new_size; + + new = xmalloc (new_size = subst_rhs_len + subst_lhs_len); + for (i = j = 0; i < subst_rhs_len; i++) + { + if (subst_rhs[i] == '&') + { + if (j + subst_lhs_len >= new_size) + new = xrealloc (new, (new_size = new_size * 2 + subst_lhs_len)); + strcpy (new + j, subst_lhs); + j += subst_lhs_len; + } + else + { + /* a single backslash protects the `&' from lhs interpolation */ + if (subst_rhs[i] == '\\' && subst_rhs[i + 1] == '&') + i++; + if (j >= new_size) + new = xrealloc (new, new_size *= 2); + new[j++] = subst_rhs[i]; + } + } + new[j] = '\0'; + free (subst_rhs); + subst_rhs = new; + subst_rhs_len = j; +} + +/* Expand the bulk of a history specifier starting at STRING[START]. + Returns 0 if everything is OK, -1 if an error occurred, and 1 + if the `p' modifier was supplied and the caller should just print + the returned string. Returns the new index into string in + *END_INDEX_PTR, and the expanded specifier in *RET_STRING. */ +static int +history_expand_internal (string, start, end_index_ptr, ret_string, current_line) + char *string; + int start, *end_index_ptr; + char **ret_string; + char *current_line; /* for !# */ +{ + int i, n, starting_index; + int substitute_globally, want_quotes, print_only; + char *event, *temp, *result, *tstr, *t, c, *word_spec; + int result_len; + + result = xmalloc (result_len = 128); + + i = start; + + /* If it is followed by something that starts a word specifier, + then !! is implied as the event specifier. */ + + if (member (string[i + 1], ":$*%^")) + { + char fake_s[3]; + int fake_i = 0; + i++; + fake_s[0] = fake_s[1] = history_expansion_char; + fake_s[2] = '\0'; + event = get_history_event (fake_s, &fake_i, 0); + } + else if (string[i + 1] == '#') + { + i += 2; + event = current_line; + } + else + { + int quoted_search_delimiter = 0; + + /* If the character before this `!' is a double or single + quote, then this expansion takes place inside of the + quoted string. If we have to search for some text ("!foo"), + allow the delimiter to end the search string. */ + if (i && (string[i - 1] == '\'' || string[i - 1] == '"')) + quoted_search_delimiter = string[i - 1]; + event = get_history_event (string, &i, quoted_search_delimiter); + } + + if (!event) + { + *ret_string = hist_error (string, start, i, EVENT_NOT_FOUND); + free (result); + return (-1); + } + + /* If a word specifier is found, then do what that requires. */ + starting_index = i; + word_spec = get_history_word_specifier (string, event, &i); + + /* There is no such thing as a `malformed word specifier'. However, + it is possible for a specifier that has no match. In that case, + we complain. */ + if (word_spec == (char *)&error_pointer) + { + *ret_string = hist_error (string, starting_index, i, BAD_WORD_SPEC); + free (result); + return (-1); + } + + /* If no word specifier, than the thing of interest was the event. */ + if (!word_spec) + temp = savestring (event); + else + { + temp = savestring (word_spec); + free (word_spec); + } + + /* Perhaps there are other modifiers involved. Do what they say. */ + want_quotes = substitute_globally = print_only = 0; + starting_index = i; + + while (string[i] == ':') + { + c = string[i + 1]; + + if (c == 'g') + { + substitute_globally = 1; + i++; + c = string[i + 1]; + } + + switch (c) + { + default: + *ret_string = hist_error (string, i+1, i+2, BAD_MODIFIER); + free (result); + free (temp); + return -1; + +#if defined (SHELL) + case 'q': + want_quotes = 'q'; + break; + + case 'x': + want_quotes = 'x'; + break; +#endif /* SHELL */ + + /* :p means make this the last executed line. So we + return an error state after adding this line to the + history. */ + case 'p': + print_only++; + break; + + /* :t discards all but the last part of the pathname. */ + case 't': + tstr = strrchr (temp, '/'); + if (tstr) + { + tstr++; + t = savestring (tstr); + free (temp); + temp = t; + } + break; + + /* :h discards the last part of a pathname. */ + case 'h': + tstr = strrchr (temp, '/'); + if (tstr) + *tstr = '\0'; + break; + + /* :r discards the suffix. */ + case 'r': + tstr = strrchr (temp, '.'); + if (tstr) + *tstr = '\0'; + break; + + /* :e discards everything but the suffix. */ + case 'e': + tstr = strrchr (temp, '.'); + if (tstr) + { + t = savestring (tstr); + free (temp); + temp = t; + } + break; + + /* :s/this/that substitutes `that' for the first + occurrence of `this'. :gs/this/that substitutes `that' + for each occurrence of `this'. :& repeats the last + substitution. :g& repeats the last substitution + globally. */ + + case '&': + case 's': + { + char *new_event, *t; + int delimiter, failed, si, l_temp; + + if (c == 's') + { + if (i + 2 < (int)strlen (string)) + delimiter = string[i + 2]; + else + break; /* no search delimiter */ + + i += 3; + + t = get_subst_pattern (string, &i, delimiter, 0, &subst_lhs_len); + /* An empty substitution lhs with no previous substitution + uses the last search string as the lhs. */ + if (t) + { + if (subst_lhs) + free (subst_lhs); + subst_lhs = t; + } + else if (!subst_lhs) + { + if (search_string && *search_string) + { + subst_lhs = savestring (search_string); + subst_lhs_len = strlen (subst_lhs); + } + else + { + subst_lhs = (char *) NULL; + subst_lhs_len = 0; + } + } + + /* If there is no lhs, the substitution can't succeed. */ + if (subst_lhs_len == 0) + { + *ret_string = hist_error (string, starting_index, i, SUBST_FAILED); + free (result); + free (temp); + return -1; + } + + if (subst_rhs) + free (subst_rhs); + subst_rhs = get_subst_pattern (string, &i, delimiter, 1, &subst_rhs_len); + + /* If `&' appears in the rhs, it's supposed to be replaced + with the lhs. */ + if (member ('&', subst_rhs)) + postproc_subst_rhs (); + } + else + i += 2; + + l_temp = strlen (temp); + /* Ignore impossible cases. */ + if (subst_lhs_len > l_temp) + { + *ret_string = hist_error (string, starting_index, i, SUBST_FAILED); + free (result); + free (temp); + return (-1); + } + + /* Find the first occurrence of THIS in TEMP. */ + si = 0; + for (failed = 1; (si + subst_lhs_len) <= l_temp; si++) + if (STREQN (temp+si, subst_lhs, subst_lhs_len)) + { + int len = subst_rhs_len - subst_lhs_len + l_temp; + new_event = xmalloc (1 + len); + strncpy (new_event, temp, si); + strncpy (new_event + si, subst_rhs, subst_rhs_len); + strncpy (new_event + si + subst_rhs_len, + temp + si + subst_lhs_len, + l_temp - (si + subst_lhs_len)); + new_event[len] = '\0'; + free (temp); + temp = new_event; + + failed = 0; + + if (substitute_globally) + { + si += subst_rhs_len; + l_temp = strlen (temp); + substitute_globally++; + continue; + } + else + break; + } + + if (substitute_globally > 1) + { + substitute_globally = 0; + continue; /* don't want to increment i */ + } + + if (failed == 0) + continue; /* don't want to increment i */ + + *ret_string = hist_error (string, starting_index, i, SUBST_FAILED); + free (result); + free (temp); + return (-1); + } + } + i += 2; + } + /* Done with modfiers. */ + /* Believe it or not, we have to back the pointer up by one. */ + --i; + +#if defined (SHELL) + if (want_quotes) + { + char *x; + + if (want_quotes == 'q') + x = single_quote (temp); + else if (want_quotes == 'x') + x = quote_breaks (temp); + else + x = savestring (temp); + + free (temp); + temp = x; + } +#endif /* SHELL */ + + n = strlen (temp); + if (n > result_len) + result = xrealloc (result, n + 2); + strcpy (result, temp); + free (temp); + + *end_index_ptr = i; + *ret_string = result; + return (print_only); +} + +/* Expand the string STRING, placing the result into OUTPUT, a pointer + to a string. Returns: + + -1) If there was an error in expansion. + 0) If no expansions took place (or, if the only change in + the text was the de-slashifying of the history expansion + character) + 1) If expansions did take place + 2) If the `p' modifier was given and the caller should print the result + + If an error ocurred in expansion, then OUTPUT contains a descriptive + error message. */ + +#define ADD_STRING(s) \ + do \ + { \ + int sl = strlen (s); \ + j += sl; \ + if (j >= result_len) \ + { \ + while (j >= result_len) \ + result_len += 128; \ + result = xrealloc (result, result_len); \ + } \ + strcpy (result + j - sl, s); \ + } \ + while (0) + +#define ADD_CHAR(c) \ + do \ + { \ + if (j >= result_len - 1) \ + result = xrealloc (result, result_len += 64); \ + result[j++] = c; \ + result[j] = '\0'; \ + } \ + while (0) + +int +history_expand (hstring, output) + char *hstring; + char **output; +{ + register int j; + int i, r, l, passc, cc, modified, eindex, only_printing; + char *string; + + /* The output string, and its length. */ + int result_len; + char *result; + + /* Used when adding the string. */ + char *temp; + + /* Setting the history expansion character to 0 inhibits all + history expansion. */ + if (history_expansion_char == 0) + { + *output = savestring (hstring); + return (0); + } + + /* Prepare the buffer for printing error messages. */ + result = xmalloc (result_len = 256); + result[0] = '\0'; + + only_printing = modified = 0; + l = strlen (hstring); + + /* Grovel the string. Only backslash can quote the history escape + character. We also handle arg specifiers. */ + + /* Before we grovel forever, see if the history_expansion_char appears + anywhere within the text. */ + + /* The quick substitution character is a history expansion all right. That + is to say, "^this^that^" is equivalent to "!!:s^this^that^", and in fact, + that is the substitution that we do. */ + if (hstring[0] == history_subst_char) + { + string = xmalloc (l + 5); + + string[0] = string[1] = history_expansion_char; + string[2] = ':'; + string[3] = 's'; + strcpy (string + 4, hstring); + l += 4; + } + else + { + string = hstring; + /* If not quick substitution, still maybe have to do expansion. */ + + /* `!' followed by one of the characters in history_no_expand_chars + is NOT an expansion. */ + for (i = 0; string[i]; i++) + { + cc = string[i + 1]; + if (string[i] == history_expansion_char) + { + if (!cc || member (cc, history_no_expand_chars)) + continue; +#if defined (SHELL) + /* The shell uses ! as a pattern negation character + in globbing [...] expressions, so let those pass + without expansion. */ + else if (i > 0 && (string[i - 1] == '[') && + member (']', string + i + 1)) + continue; +#endif /* SHELL */ + else + break; + } +#if defined (SHELL) + else if (string[i] == '\'') + { + /* If this is bash, single quotes inhibit history expansion. */ + i++; + rl_string_extract_single_quoted (string, &i); + } + else if (string[i] == '\\') + { + /* If this is bash, allow backslashes to quote single + quotes and + the history expansion character. */ + if (cc == '\'' || cc == history_expansion_char) + i++; + } +#endif /* SHELL */ + } + + if (string[i] != history_expansion_char) + { + free (result); + *output = savestring (string); + return (0); + } + } + + /* Extract and perform the substitution. */ + for (passc = i = j = 0; i < l; i++) + { + int tchar = string[i]; + + if (passc) + { + passc = 0; + ADD_CHAR (tchar); + continue; + } + + if (tchar == history_expansion_char) + tchar = -3; + + switch (tchar) + { + default: + ADD_CHAR (string[i]); + break; + + case '\\': + passc++; + ADD_CHAR (tchar); + break; + +#if defined (SHELL) + case '\'': + { + /* If this is bash, single quotes inhibit history expansion. */ + int quote, slen; + + quote = i++; + rl_string_extract_single_quoted (string, &i); + + slen = i - quote + 2; + temp = xmalloc (slen); + strncpy (temp, string + quote, slen); + temp[slen - 1] = '\0'; + ADD_STRING (temp); + free (temp); + break; + } +#endif /* SHELL */ + + case -3: /* history_expansion_char */ + cc = string[i + 1]; + + /* If the history_expansion_char is followed by one of the + characters in history_no_expand_chars, then it is not a + candidate for expansion of any kind. */ + if (member (cc, history_no_expand_chars)) + { + ADD_CHAR (string[i]); + break; + } + +#if defined (NO_BANG_HASH_MODIFIERS) + /* There is something that is listed as a `word specifier' in csh + documentation which means `the expanded text to this point'. + That is not a word specifier, it is an event specifier. If we + don't want to allow modifiers with `!#', just stick the current + output line in again. */ + if (cc == '#') + { + if (result) + { + temp = xmalloc (1 + strlen (result)); + strcpy (temp, result); + ADD_STRING (temp); + free (temp); + } + i++; + break; + } +#endif + + r = history_expand_internal (string, i, &eindex, &temp, result); + if (r < 0) + { + *output = temp; + free (result); + if (string != hstring) + free (string); + return -1; + } + else + { + if (temp) + { + modified++; + if (*temp) + ADD_STRING (temp); + free (temp); + } + only_printing = r == 1; + i = eindex; + } + break; + } + } + + *output = result; + if (string != hstring) + free (string); + + if (only_printing) + { + add_history (result); + return (2); + } + + return (modified != 0); +} + +/* Return a consed string which is the word specified in SPEC, and found + in FROM. NULL is returned if there is no spec. The address of + ERROR_POINTER is returned if the word specified cannot be found. + CALLER_INDEX is the offset in SPEC to start looking; it is updated + to point to just after the last character parsed. */ +static char * +get_history_word_specifier (spec, from, caller_index) + char *spec, *from; + int *caller_index; +{ + register int i = *caller_index; + int first, last; + int expecting_word_spec = 0; + char *result; + + /* The range of words to return doesn't exist yet. */ + first = last = 0; + result = (char *)NULL; + + /* If we found a colon, then this *must* be a word specification. If + it isn't, then it is an error. */ + if (spec[i] == ':') + { + i++; + expecting_word_spec++; + } + + /* Handle special cases first. */ + + /* `%' is the word last searched for. */ + if (spec[i] == '%') + { + *caller_index = i + 1; + return (search_string ? savestring (search_string) : savestring ("")); + } + + /* `*' matches all of the arguments, but not the command. */ + if (spec[i] == '*') + { + *caller_index = i + 1; + result = history_arg_extract (1, '$', from); + return (result ? result : savestring ("")); + } + + /* `$' is last arg. */ + if (spec[i] == '$') + { + *caller_index = i + 1; + return (history_arg_extract ('$', '$', from)); + } + + /* Try to get FIRST and LAST figured out. */ + + if (spec[i] == '-') + first = 0; + else if (spec[i] == '^') + first = 1; + else if (digit_p (spec[i]) && expecting_word_spec) + { + for (first = 0; digit_p (spec[i]); i++) + first = (first * 10) + digit_value (spec[i]); + } + else + return ((char *)NULL); /* no valid `first' for word specifier */ + + if (spec[i] == '^' || spec[i] == '*') + { + last = (spec[i] == '^') ? 1 : '$'; /* x* abbreviates x-$ */ + i++; + } + else if (spec[i] != '-') + last = first; + else + { + i++; + + if (digit_p (spec[i])) + { + for (last = 0; digit_p (spec[i]); i++) + last = (last * 10) + digit_value (spec[i]); + } + else if (spec[i] == '$') + { + i++; + last = '$'; + } + else if (!spec[i] || spec[i] == ':') /* could be modifier separator */ + last = -1; /* x- abbreviates x-$ omitting word `$' */ + } + + *caller_index = i; + + if (last >= first || last == '$' || last < 0) + result = history_arg_extract (first, last, from); + + return (result ? result : (char *)&error_pointer); +} + +/* Extract the args specified, starting at FIRST, and ending at LAST. + The args are taken from STRING. If either FIRST or LAST is < 0, + then make that arg count from the right (subtract from the number of + tokens, so that FIRST = -1 means the next to last token on the line). + If LAST is `$' the last arg from STRING is used. */ +char * +history_arg_extract (first, last, string) + int first, last; + char *string; +{ + register int i, len; + char *result = (char *)NULL; + int size = 0, offset = 0; + char **list; + + /* XXX - think about making history_tokenize return a struct array, + each struct in array being a string and a length to avoid the + calls to strlen below. */ + if ((list = history_tokenize (string)) == NULL) + return ((char *)NULL); + + for (len = 0; list[len]; len++) + ; + + if (last < 0) + last = len + last - 1; + + if (first < 0) + first = len + first - 1; + + if (last == '$') + last = len - 1; + + if (first == '$') + first = len - 1; + + last++; + + if (first > len || last > len || first < 0 || last < 0) + result = ((char *)NULL); + else + { + for (size = 0, i = first; i < last; i++) + size += strlen (list[i]) + 1; + result = xmalloc (size + 1); + + for (i = first; i < last; i++) + { + strcpy (result + offset, list[i]); + offset += strlen (list[i]); + if (i + 1 < last) + { + result[offset++] = ' '; + result[offset] = 0; + } + } + } + + for (i = 0; i < len; i++) + free (list[i]); + free (list); + + return (result); +} + +#define slashify_in_quotes "\\`\"$" + +/* Return an array of tokens, much as the shell might. The tokens are + parsed out of STRING. */ +char ** +history_tokenize (string) + char *string; +{ + char **result = (char **)NULL; + register int i, start, result_index, size; + int len; + + i = result_index = size = 0; + + /* Get a token, and stuff it into RESULT. The tokens are split + exactly where the shell would split them. */ + while (string[i]) + { + int delimiter = 0; + + /* Skip leading whitespace. */ + for (; string[i] && whitespace (string[i]); i++) + ; + if (!string[i] || string[i] == history_comment_char) + return (result); + + start = i; + + if (member (string[i], "()\n")) + { + i++; + goto got_token; + } + + if (member (string[i], "<>;&|$")) + { + int peek = string[i + 1]; + + if (peek == string[i] && peek != '$') + { + if (peek == '<' && string[i + 2] == '-') + i++; + i += 2; + goto got_token; + } + else + { + if ((peek == '&' && (string[i] == '>' || string[i] == '<')) || + ((peek == '>') && (string[i] == '&')) || + ((peek == '(') && (string[i] == '$'))) + { + i += 2; + goto got_token; + } + } + if (string[i] != '$') + { + i++; + goto got_token; + } + } + + /* Get word from string + i; */ + + if (member (string[i], "\"'`")) + delimiter = string[i++]; + + for (; string[i]; i++) + { + if (string[i] == '\\' && string[i + 1] == '\n') + { + i++; + continue; + } + + if (string[i] == '\\' && delimiter != '\'' && + (delimiter != '"' || member (string[i], slashify_in_quotes))) + { + i++; + continue; + } + + if (delimiter && string[i] == delimiter) + { + delimiter = 0; + continue; + } + + if (!delimiter && (member (string[i], " \t\n;&()|<>"))) + break; + + if (!delimiter && member (string[i], "\"'`")) + delimiter = string[i]; + } + got_token: + + len = i - start; + if (result_index + 2 >= size) + result = (char **)xrealloc (result, ((size += 10) * sizeof (char *))); + result[result_index] = xmalloc (1 + len); + strncpy (result[result_index], string + start, len); + result[result_index][len] = '\0'; + result[++result_index] = (char *)NULL; + } + + return (result); +} + +#if defined (STATIC_MALLOC) + +/* **************************************************************** */ +/* */ +/* xmalloc and xrealloc () */ +/* */ +/* **************************************************************** */ + +static void memory_error_and_abort (); + +static char * +xmalloc (bytes) + int bytes; +{ + char *temp = (char *)malloc (bytes); + + if (!temp) + memory_error_and_abort (); + return (temp); +} + +static char * +xrealloc (pointer, bytes) + char *pointer; + int bytes; +{ + char *temp; + + if (!pointer) + temp = (char *)xmalloc (bytes); + else + temp = (char *)realloc (pointer, bytes); + + if (!temp) + memory_error_and_abort (); + + return (temp); +} + +static void +memory_error_and_abort () +{ + fprintf (stderr, "history: Out of virtual memory!\n"); + abort (); +} +#endif /* STATIC_MALLOC */ + +/* **************************************************************** */ +/* */ +/* Test Code */ +/* */ +/* **************************************************************** */ +#ifdef TEST +main () +{ + char line[1024], *t; + int done = 0; + + line[0] = 0; + + while (!done) + { + fprintf (stdout, "history%% "); + t = gets (line); + + if (!t) + strcpy (line, "quit"); + + if (line[0]) + { + char *expansion; + int result; + + using_history (); + + result = history_expand (line, &expansion); + strcpy (line, expansion); + free (expansion); + if (result) + fprintf (stderr, "%s\n", line); + + if (result < 0) + continue; + + add_history (line); + } + + if (strcmp (line, "quit") == 0) done = 1; + if (strcmp (line, "save") == 0) write_history (0); + if (strcmp (line, "read") == 0) read_history (0); + if (strcmp (line, "list") == 0) + { + register HIST_ENTRY **the_list = history_list (); + register int i; + + if (the_list) + for (i = 0; the_list[i]; i++) + fprintf (stdout, "%d: %s\n", i + history_base, the_list[i]->line); + } + if (strncmp (line, "delete", strlen ("delete")) == 0) + { + int which; + if ((sscanf (line + strlen ("delete"), "%d", &which)) == 1) + { + HIST_ENTRY *entry = remove_history (which); + if (!entry) + fprintf (stderr, "No such entry %d\n", which); + else + { + free (entry->line); + free (entry); + } + } + else + { + fprintf (stderr, "non-numeric arg given to `delete'\n"); + } + } + } +} + +#endif /* TEST */ + +/* +* Local variables: +* compile-command: "gcc -g -DTEST -o history history.c" +* end: +*/ diff --git a/history.h b/history.h new file mode 100644 index 0000000..745e61c --- /dev/null +++ b/history.h @@ -0,0 +1,180 @@ +/* History.h -- the names of functions that you can call in history. */ + +/* The structure used to store a history entry. */ +typedef struct _hist_entry { + char *line; + char *data; +} HIST_ENTRY; + +/* A structure used to pass the current state of the history stuff around. */ +typedef struct _hist_state { + HIST_ENTRY **entries; /* Pointer to the entries themselves. */ + int offset; /* The location pointer within this array. */ + int length; /* Number of elements within this array. */ + int size; /* Number of slots allocated to this array. */ + int flags; +} HISTORY_STATE; + +/* Flag values for the `flags' member of HISTORY_STATE. */ +#define HS_STIFLED 0x01 + +/* Initialization and state management. */ + +/* Begin a session in which the history functions might be used. This + just initializes the interactive variables. */ +extern void using_history (); + +/* Return the current HISTORY_STATE of the history. */ +extern HISTORY_STATE *history_get_history_state (); + +/* Set the state of the current history array to STATE. */ +extern void history_set_history_state (); + +/* Manage the history list. */ + +/* Place STRING at the end of the history list. + The associated data field (if any) is set to NULL. */ +extern void add_history (); + +/* A reasonably useless function, only here for completeness. WHICH + is the magic number that tells us which element to delete. The + elements are numbered from 0. */ +extern HIST_ENTRY *remove_history (); + +/* Make the history entry at WHICH have LINE and DATA. This returns + the old entry so you can dispose of the data. In the case of an + invalid WHICH, a NULL pointer is returned. */ +extern HIST_ENTRY *replace_history_entry (); + +/* Stifle the history list, remembering only MAX number of entries. */ +extern void stifle_history (); + +/* Stop stifling the history. This returns the previous amount the + history was stifled by. The value is positive if the history was + stifled, negative if it wasn't. */ +extern int unstifle_history (); + +/* Return 1 if the history is stifled, 0 if it is not. */ +extern int history_is_stifled (); + +/* Information about the history list. */ + +/* Return a NULL terminated array of HIST_ENTRY which is the current input + history. Element 0 of this list is the beginning of time. If there + is no history, return NULL. */ +extern HIST_ENTRY **history_list (); + +/* Returns the number which says what history element we are now + looking at. */ +extern int where_history (); + +/* Return the history entry at the current position, as determined by + history_offset. If there is no entry there, return a NULL pointer. */ +HIST_ENTRY *current_history (); + +/* Return the history entry which is logically at OFFSET in the history + array. OFFSET is relative to history_base. */ +extern HIST_ENTRY *history_get (); + +/* Return the number of bytes that the primary history entries are using. + This just adds up the lengths of the_history->lines. */ +extern int history_total_bytes (); + +/* Moving around the history list. */ + +/* Set the position in the history list to POS. */ +int history_set_pos (); + +/* Back up history_offset to the previous history entry, and return + a pointer to that entry. If there is no previous entry, return + a NULL pointer. */ +extern HIST_ENTRY *previous_history (); + +/* Move history_offset forward to the next item in the input_history, + and return the a pointer to that entry. If there is no next entry, + return a NULL pointer. */ +extern HIST_ENTRY *next_history (); + +/* Searching the history list. */ + +/* Search the history for STRING, starting at history_offset. + If DIRECTION < 0, then the search is through previous entries, + else through subsequent. If the string is found, then + current_history () is the history entry, and the value of this function + is the offset in the line of that history entry that the string was + found in. Otherwise, nothing is changed, and a -1 is returned. */ +extern int history_search (); + +extern int history_search_prefix (); +/* Search the history for @var{string}, starting at history_offset. + The search is anchored: matching lines must begin with string. */ +/* Search for STRING in the history list, starting at POS, an + absolute index into the list. DIR, if negative, says to search + backwards from POS, else forwards. + Returns the absolute index of the history element where STRING + was found, or -1 otherwise. */ +extern int history_search_pos (); + +/* Managing the history file. */ + +/* Add the contents of FILENAME to the history list, a line at a time. + If FILENAME is NULL, then read from ~/.history. Returns 0 if + successful, or errno if not. */ +extern int read_history (); + +/* Read a range of lines from FILENAME, adding them to the history list. + Start reading at the FROM'th line and end at the TO'th. If FROM + is zero, start at the beginning. If TO is less than FROM, read + until the end of the file. If FILENAME is NULL, then read from + ~/.history. Returns 0 if successful, or errno if not. */ +extern int read_history_range (); + +/* Write the current history to FILENAME. If FILENAME is NULL, + then write the history list to ~/.history. Values returned + are as in read_history (). */ +extern int write_history (); + +/* Append NELEMENT entries to FILENAME. The entries appended are from + the end of the list minus NELEMENTs up to the end of the list. */ +int append_history (); + +/* Truncate the history file, leaving only the last NLINES lines. */ +extern int history_truncate_file (); + +/* History expansion. */ + +/* Expand the string STRING, placing the result into OUTPUT, a pointer + to a string. Returns: + + 0) If no expansions took place (or, if the only change in + the text was the de-slashifying of the history expansion + character) + 1) If expansions did take place + -1) If there was an error in expansion. + 2) If the returned line should just be printed. + + If an error ocurred in expansion, then OUTPUT contains a descriptive + error message. */ +extern int history_expand (); + +/* Extract a string segment consisting of the FIRST through LAST + arguments present in STRING. Arguments are broken up as in + the shell. */ +extern char *history_arg_extract (); + +/* Return the text of the history event beginning at the current + offset into STRING. */ +extern char *get_history_event (); + +/* Return an array of tokens, much as the shell might. The tokens are + parsed out of STRING. */ +extern char **history_tokenize (); + +/* Exported history variables. */ +extern int history_base; +extern int history_length; +extern int max_input_history; +extern char history_expansion_char; +extern char history_subst_char; +extern char history_comment_char; +extern char *history_no_expand_chars; diff --git a/isearch.c b/isearch.c new file mode 100644 index 0000000..1a0193f --- /dev/null +++ b/isearch.c @@ -0,0 +1,378 @@ +/* **************************************************************** */ +/* */ +/* I-Search and Searching */ +/* */ +/* **************************************************************** */ + +/* Copyright (C) 1987,1989 Free Software Foundation, Inc. + + This file contains the Readline Library (the Library), a set of + routines for providing Emacs style line input to programs that ask + for it. + + The Library 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 1, or (at your option) + any later version. + + The Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define READLINE_LIBRARY + +#include + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#include "memalloc.h" +#include "readline.h" +#include "history.h" + +#define STREQ(a, b) (((a)[0] == (b)[0]) && (strcmp ((a), (b)) == 0)) +#define STREQN(a, b, n) (((a)[0] == (b)[0]) && (strncmp ((a), (b), (n)) == 0)) + +/* Variables imported from other files in the readline library. */ +extern Keymap _rl_keymap; +extern HIST_ENTRY *saved_line_for_history; +extern int rl_line_buffer_len; +extern int rl_point, rl_end; +extern char *rl_line_buffer; + +extern char *xmalloc (), *xrealloc (); + +static int rl_search_history (); + +/* Last line found by the current incremental search, so we don't `find' + identical lines many times in a row. */ +static char *prev_line_found; + +/* Search backwards through the history looking for a string which is typed + interactively. Start with the current line. */ +rl_reverse_search_history (sign, key) + int sign; + int key; +{ + return (rl_search_history (-sign, key)); +} + +/* Search forwards through the history looking for a string which is typed + interactively. Start with the current line. */ +rl_forward_search_history (sign, key) + int sign; + int key; +{ + return (rl_search_history (sign, key)); +} + +/* Display the current state of the search in the echo-area. + SEARCH_STRING contains the string that is being searched for, + DIRECTION is zero for forward, or 1 for reverse, + WHERE is the history list number of the current line. If it is + -1, then this line is the starting one. */ +static void +rl_display_search (search_string, reverse_p, where) + char *search_string; + int reverse_p, where; +{ + char *message; + + message = xmalloc (1 + (search_string ? strlen (search_string) : 0) + 30); + *message = '\0'; + +#if defined (NOTDEF) + if (where != -1) + sprintf (message, "[%d]", where + history_base); +#endif /* NOTDEF */ + + strcat (message, "("); + + if (reverse_p) + strcat (message, "reverse-"); + + strcat (message, "i-search)`"); + + if (search_string) + strcat (message, search_string); + + strcat (message, "': "); + rl_message ("%s", message, 0); + free (message); + rl_redisplay (); +} + +/* Search through the history looking for an interactively typed string. + This is analogous to i-search. We start the search in the current line. + DIRECTION is which direction to search; >= 0 means forward, < 0 means + backwards. */ +static int +rl_search_history (direction, invoking_key) + int direction; + int invoking_key; +{ + /* The string that the user types in to search for. */ + char *search_string; + + /* The current length of SEARCH_STRING. */ + int search_string_index; + + /* The amount of space that SEARCH_STRING has allocated to it. */ + int search_string_size; + + /* The list of lines to search through. */ + char **lines, *allocated_line = (char *)NULL; + + /* The length of LINES. */ + int hlen; + + /* Where we get LINES from. */ + HIST_ENTRY **hlist = history_list (); + + register int i = 0; + int orig_point = rl_point; + int orig_line = where_history (); + int last_found_line = orig_line; + int c, done = 0, found, failed, sline_len; + + /* The line currently being searched. */ + char *sline; + + /* Offset in that line. */ + int line_index; + + /* Non-zero if we are doing a reverse search. */ + int reverse = (direction < 0); + + /* Create an arrary of pointers to the lines that we want to search. */ + maybe_replace_line (); + if (hlist) + for (i = 0; hlist[i]; i++); + + /* Allocate space for this many lines, +1 for the current input line, + and remember those lines. */ + lines = (char **)xmalloc ((1 + (hlen = i)) * sizeof (char *)); + for (i = 0; i < hlen; i++) + lines[i] = hlist[i]->line; + + if (saved_line_for_history) + lines[i] = saved_line_for_history->line; + else + { + /* Keep track of this so we can free it. */ + allocated_line = xmalloc (1 + strlen (rl_line_buffer)); + strcpy (allocated_line, &rl_line_buffer[0]); + lines[i] = allocated_line; + } + + hlen++; + + /* The line where we start the search. */ + i = orig_line; + + /* Initialize search parameters. */ + search_string = xmalloc (search_string_size = 128); + *search_string = '\0'; + search_string_index = 0; + prev_line_found = (char *)0; /* XXX */ + + /* Normalize DIRECTION into 1 or -1. */ + direction = (direction >= 0) ? 1 : -1; + + rl_display_search (search_string, reverse, -1); + + sline = rl_line_buffer; + sline_len = strlen (sline); + line_index = rl_point; + + found = failed = 0; + while (!done) + { + Function *f = (Function *)NULL; + + /* Read a key and decide how to proceed. */ + c = rl_read_key (); + + /* Hack C to Do What I Mean. */ + if (_rl_keymap[c].type == ISFUNC) + { + f = _rl_keymap[c].function; + + if (f == rl_reverse_search_history) + c = reverse ? -1 : -2; + else if (f == rl_forward_search_history) + c = !reverse ? -1 : -2; + } + + switch (c) + { + case ESC: + done = 1; + continue; + + case -1: + if (!search_string_index) + continue; + else + { + if (reverse) + --line_index; + else + { + if (line_index != sline_len) + ++line_index; + else + ding (); + } + } + break; + + /* switch directions */ + case -2: + direction = -direction; + reverse = (direction < 0); + break; + + case CTRL ('G'): + strcpy (rl_line_buffer, lines[orig_line]); + rl_point = orig_point; + rl_end = strlen (rl_line_buffer); + rl_clear_message (); + free (allocated_line); + free (lines); + return 0; + + default: + if (CTRL_CHAR (c) || META_CHAR (c) || c == RUBOUT) + { + rl_execute_next (c); + done = 1; + continue; + } + else + { + /* Add character to search string and continue search. */ + if (search_string_index + 2 >= search_string_size) + { + search_string_size += 128; + search_string = xrealloc (search_string, search_string_size); + } + search_string[search_string_index++] = c; + search_string[search_string_index] = '\0'; + break; + } + } + + found = failed = 0; + while (1) + { + int limit = sline_len - search_string_index + 1; + + /* Search the current line. */ + while (reverse ? (line_index >= 0) : (line_index < limit)) + { + if (STREQN(search_string, sline + line_index, search_string_index)) + { + found++; + break; + } + else + line_index += direction; + } + if (found) + break; + + /* Move to the next line, but skip new copies of the line + we just found and lines shorter than the string we're + searching for. */ + do + { + /* Move to the next line. */ + i += direction; + + /* At limit for direction? */ + if (reverse ? (i < 0) : (i == hlen)) + { + failed++; + break; + } + + /* We will need these later. */ + sline = lines[i]; + sline_len = strlen (sline); + } + while ((prev_line_found && STREQ (prev_line_found, lines[i])) || + (search_string_index > sline_len)); + + if (failed) + break; + + /* Now set up the line for searching... */ + if (reverse) + line_index = sline_len - search_string_index; + else + line_index = 0; + } + + if (failed) + { + /* We cannot find the search string. Ding the bell. */ + ding (); + i = last_found_line; + continue; /* XXX - was break */ + } + + /* We have found the search string. Just display it. But don't + actually move there in the history list until the user accepts + the location. */ + if (found) + { + int line_len; + + prev_line_found = lines[i]; + line_len = strlen (lines[i]); + + if (line_len >= rl_line_buffer_len) + rl_extend_line_buffer (line_len); + + strcpy (rl_line_buffer, lines[i]); + rl_point = line_index; + rl_end = line_len; + last_found_line = i; + rl_display_search (search_string, reverse, (i == orig_line) ? -1 : i); + } + } + + /* The searching is over. The user may have found the string that she + was looking for, or else she may have exited a failing search. If + LINE_INDEX is -1, then that shows that the string searched for was + not found. We use this to determine where to place rl_point. */ + + /* First put back the original state. */ + strcpy (rl_line_buffer, lines[orig_line]); + + /* Free the search string. */ + free (search_string); + + if (last_found_line < orig_line) + rl_get_previous_history (orig_line - last_found_line); + else + rl_get_next_history (last_found_line - orig_line); + + /* If the string was not found, put point at the end of the line. */ + if (line_index < 0) + line_index = strlen (rl_line_buffer); + rl_point = line_index; + rl_clear_message (); + + free (allocated_line); + free (lines); + + return 0; +} diff --git a/keymaps.c b/keymaps.c new file mode 100644 index 0000000..da59b69 --- /dev/null +++ b/keymaps.c @@ -0,0 +1,196 @@ +/* keymaps.c -- Functions and keymaps for the GNU Readline library. */ + +/* Copyright (C) 1988,1989 Free Software Foundation, Inc. + + This file is part of GNU Readline, a library for reading lines + of text with interactive input and history editing. + + Readline 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 1, or (at your option) any + later version. + + Readline 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 Readline; see the file COPYING. If not, write to the Free + Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define READLINE_LIBRARY + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#include "rlconf.h" +#include "keymaps.h" +#include "emacs_keymap.c" + +#if defined (VI_MODE) +#include "vi_keymap.c" +#endif + +extern int rl_do_lowercase_version (); +extern int rl_rubout (), rl_insert (); + +#if defined (STATIC_MALLOC) +static char *xmalloc (), *xrealloc (); +#else +extern char *xmalloc (), *xrealloc (); +#endif /* STATIC_MALLOC */ + +/* **************************************************************** */ +/* */ +/* Functions for manipulating Keymaps. */ +/* */ +/* **************************************************************** */ + + +/* Return a new, empty keymap. + Free it with free() when you are done. */ +Keymap +rl_make_bare_keymap () +{ + register int i; + Keymap keymap = (Keymap)xmalloc (KEYMAP_SIZE * sizeof (KEYMAP_ENTRY)); + + for (i = 0; i < KEYMAP_SIZE; i++) + { + keymap[i].type = ISFUNC; + keymap[i].function = (Function *)NULL; + } + + for (i = 'A'; i < ('Z' + 1); i++) + { + keymap[i].type = ISFUNC; + keymap[i].function = rl_do_lowercase_version; + } + + return (keymap); +} + +/* Return a new keymap which is a copy of MAP. */ +Keymap +rl_copy_keymap (map) + Keymap map; +{ + register int i; + Keymap temp = rl_make_bare_keymap (); + + for (i = 0; i < KEYMAP_SIZE; i++) + { + temp[i].type = map[i].type; + temp[i].function = map[i].function; + } + return (temp); +} + +/* Return a new keymap with the printing characters bound to rl_insert, + the uppercase Meta characters bound to run their lowercase equivalents, + and the Meta digits bound to produce numeric arguments. */ +Keymap +rl_make_keymap () +{ + register int i; + Keymap newmap; + + newmap = rl_make_bare_keymap (); + + /* All ASCII printing characters are self-inserting. */ + for (i = ' '; i < 126; i++) + newmap[i].function = rl_insert; + + newmap[TAB].function = rl_insert; + newmap[RUBOUT].function = rl_rubout; + newmap[CTRL('H')].function = rl_rubout; + +#if KEYMAP_SIZE > 128 + /* Printing characters in some 8-bit character sets. */ + for (i = 128; i < 160; i++) + newmap[i].function = rl_insert; + + /* ISO Latin-1 printing characters should self-insert. */ + for (i = 160; i < 256; i++) + newmap[i].function = rl_insert; +#endif /* KEYMAP_SIZE > 128 */ + + return (newmap); +} + +/* Free the storage associated with MAP. */ +void +rl_discard_keymap (map) + Keymap (map); +{ + int i; + + if (!map) + return; + + for (i = 0; i < KEYMAP_SIZE; i++) + { + switch (map[i].type) + { + case ISFUNC: + break; + + case ISKMAP: + rl_discard_keymap ((Keymap)map[i].function); + break; + + case ISMACR: + free ((char *)map[i].function); + break; + } + } +} + +#if defined (STATIC_MALLOC) + +/* **************************************************************** */ +/* */ +/* xmalloc and xrealloc () */ +/* */ +/* **************************************************************** */ + +static void memory_error_and_abort (); + +static char * +xmalloc (bytes) + int bytes; +{ + char *temp = (char *)malloc (bytes); + + if (!temp) + memory_error_and_abort (); + return (temp); +} + +static char * +xrealloc (pointer, bytes) + char *pointer; + int bytes; +{ + char *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 /* STATIC_MALLOC */ diff --git a/keymaps.h b/keymaps.h new file mode 100644 index 0000000..f0eda3d --- /dev/null +++ b/keymaps.h @@ -0,0 +1,95 @@ +/* keymaps.h -- Manipulation of readline keymaps. */ + +/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library 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 1, or + (at your option) any later version. + + The GNU Readline Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef _KEYMAPS_H_ +#define _KEYMAPS_H_ + +#if defined (READLINE_LIBRARY) +# include "chardefs.h" +#else +# include +#endif + +#if !defined (__FUNCTION_DEF) +# define __FUNCTION_DEF +typedef int Function (); +typedef void VFunction (); +typedef char *CPFunction (); +typedef char **CPPFunction (); +#endif + +/* A keymap contains one entry for each key in the ASCII set. + Each entry consists of a type and a pointer. + POINTER is the address of a function to run, or the + address of a keymap to indirect through. + TYPE says which kind of thing POINTER is. */ +typedef struct _keymap_entry { + char type; + Function *function; +} KEYMAP_ENTRY; + +/* This must be large enough to hold bindings for all of the characters + in a desired character set (e.g, 128 for ASCII, 256 for ISO Latin-x, + and so on). */ +#define KEYMAP_SIZE 256 + +/* I wanted to make the above structure contain a union of: + union { Function *function; struct _keymap_entry *keymap; } value; + but this made it impossible for me to create a static array. + Maybe I need C lessons. */ + +typedef KEYMAP_ENTRY KEYMAP_ENTRY_ARRAY[KEYMAP_SIZE]; +typedef KEYMAP_ENTRY *Keymap; + +/* The values that TYPE can have in a keymap entry. */ +#define ISFUNC 0 +#define ISKMAP 1 +#define ISMACR 2 + +extern KEYMAP_ENTRY_ARRAY emacs_standard_keymap, emacs_meta_keymap, emacs_ctlx_keymap; +extern KEYMAP_ENTRY_ARRAY vi_insertion_keymap, vi_movement_keymap; + +/* Return a new, empty keymap. + Free it with free() when you are done. */ +extern Keymap rl_make_bare_keymap (); + +/* Return a new keymap which is a copy of MAP. */ +extern Keymap rl_copy_keymap (); + +/* Return a new keymap with the printing characters bound to rl_insert, + the lowercase Meta characters bound to run their equivalents, and + the Meta digits bound to produce numeric arguments. */ +extern Keymap rl_make_keymap (); + +extern void rl_discard_keymap (); + +/* Return the keymap corresponding to a given name. Names look like + `emacs' or `emacs-meta' or `vi-insert'. */ +extern Keymap rl_get_keymap_by_name (); + +/* Return the current keymap. */ +extern Keymap rl_get_keymap (); + +/* Set the current keymap to MAP. */ +extern void rl_set_keymap (); + +#endif /* _KEYMAPS_H_ */ diff --git a/memalloc.h b/memalloc.h new file mode 100644 index 0000000..750d53d --- /dev/null +++ b/memalloc.h @@ -0,0 +1,56 @@ +/* memalloc.h -- consolidate code for including alloca.h or malloc.h and + defining alloca. */ + +/* Copyright (C) 1993 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash 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. + + Bash 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 Bash; see the file COPYING. If not, write to the Free Software + Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#if !defined (__MEMALLOC_H__) +# define __MEMALLOC_H__ + +#if defined (sparc) && defined (sun) && !defined (HAVE_ALLOCA_H) +# define HAVE_ALLOCA_H +#endif + +#if defined (__GNUC__) && !defined (HAVE_ALLOCA) +# define HAVE_ALLOCA +#endif + +#if defined (HAVE_ALLOCA_H) && !defined (HAVE_ALLOCA) +# define HAVE_ALLOCA +#endif /* HAVE_ALLOCA_H && !HAVE_ALLOCA */ + +#if !defined (BUILDING_MAKEFILE) + +#if defined (__GNUC__) +# undef alloca +# define alloca __builtin_alloca +#else /* !__GNUC__ */ +# if defined (HAVE_ALLOCA_H) +# if defined (IBMESA) +# include +# else /* !IBMESA */ +# include +# endif /* !IBMESA */ +# else +extern char *alloca (); +# endif /* !HAVE_ALLOCA_H */ +#endif /* !__GNUC__ */ + +#endif /* !BUILDING_MAKEFILE */ + +#endif /* __MEMALLOC_H__ */ diff --git a/parens.c b/parens.c new file mode 100644 index 0000000..57a9777 --- /dev/null +++ b/parens.c @@ -0,0 +1,130 @@ +/* parens.c -- Implemenation of matching parenthesis feature. */ + +/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library 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 1, or + (at your option) any later version. + + The GNU Readline Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define READLINE_LIBRARY + +#include "rlconf.h" + +#if !defined (PAREN_MATCHING) + +rl_insert_close (count, invoking_key) + int count, invoking_key; +{ + return (rl_insert (count, invoking_key)); +} + +#else /* PAREN_MATCHING */ + +#include +#include +#if defined (FD_SET) +# include +#endif /* FD_SET */ +#include "readline.h" + +extern int rl_explicit_arg; + +/* Non-zero means try to blink the matching open parenthesis when the + close parenthesis is inserted. */ +#if defined (FD_SET) +int rl_blink_matching_paren = 1; +#else /* !FD_SET */ +int rl_blink_matching_paren = 0; +#endif /* !FD_SET */ + +static int find_matching_open (); + +rl_insert_close (count, invoking_key) + int count, invoking_key; +{ + if (rl_explicit_arg || !rl_blink_matching_paren) + rl_insert (count, invoking_key); + else + { +#if defined (FD_SET) + int orig_point, match_point, ready; + struct timeval timer; + fd_set readfds; + + rl_insert (1, invoking_key); + rl_redisplay (); + match_point = + find_matching_open (rl_line_buffer, rl_point - 2, invoking_key); + + /* Emacs might message or ring the bell here, but I don't. */ + if (match_point < 0) + return -1; + + FD_ZERO (&readfds); + FD_SET (fileno (rl_instream), &readfds); + timer.tv_sec = 1; + timer.tv_usec = 500; + + orig_point = rl_point; + rl_point = match_point; + rl_redisplay (); + ready = select (1, &readfds, (fd_set *)NULL, (fd_set *)NULL, &timer); + rl_point = orig_point; +#else /* !FD_SET */ + rl_insert (count, invoking_key); +#endif /* !FD_SET */ + } + return 0; +} + +static int +find_matching_open (string, from, closer) + char *string; + int from, closer; +{ + register int i; + int opener, level, delimiter; + + switch (closer) + { + case ']': opener = '['; break; + case '}': opener = '{'; break; + case ')': opener = '('; break; + default: + return (-1); + } + + level = 1; /* The closer passed in counts as 1. */ + delimiter = 0; /* Delimited state unknown. */ + + for (i = from; i > -1; i--) + { + if (delimiter && (string[i] == delimiter)) + delimiter = 0; + else if ((string[i] == '\'') || (string[i] == '"')) + delimiter = rl_line_buffer[i]; + else if (!delimiter && (string[i] == closer)) + level++; + else if (!delimiter && (string[i] == opener)) + level--; + + if (!level) + break; + } + return (i); +} + +#endif /* PAREN_MATCHING */ diff --git a/posixstat.h b/posixstat.h new file mode 100644 index 0000000..7d1cece --- /dev/null +++ b/posixstat.h @@ -0,0 +1,149 @@ +/* posixstat.h -- Posix stat(2) definitions for systems that + don't have them. */ + +/* Copyright (C) 1987,1991 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash 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 1, or (at your option) + any later version. + + Bash 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 Bash; see the file COPYING. If not, write to the Free + Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* This file should be included instead of . + It relies on the local sys/stat.h to work though. */ +#if !defined (_POSIXSTAT_H) +#define _POSIXSTAT_H + +#include + +#if defined (isc386) +# if !defined (S_IFDIR) +# define S_IFDIR 0040000 +# endif /* !S_IFDIR */ +# if !defined (S_IFMT) +# define S_IFMT 0170000 +# endif /* !S_IFMT */ +#endif /* isc386 */ + +/* This text is taken directly from the Cadmus I was trying to + compile on: + the following MACROs are defined for X/OPEN compatibility + however, is the param correct ?? + #define S_ISBLK(s) ((s.st_mode & S_IFMT) == S_IFBLK) + + Well, the answer is no. Thus... */ +#if defined (BrainDeath) +# undef S_ISBLK +# undef S_ISCHR +# undef S_ISDIR +# undef S_ISFIFO +# undef S_ISREG +#endif /* BrainDeath */ + +/* Posix 1003.1 5.6.1.1 file types */ + +/* Some Posix-wannabe systems define _S_IF* macros instead of S_IF*, but + do not provide the S_IS* macros that Posix requires. */ + +#if defined (_S_IFMT) && !defined (S_IFMT) +#define S_IFMT _S_IFMT +#endif +#if defined (_S_IFIFO) && !defined (S_IFIFO) +#define S_IFIFO _S_IFIFO +#endif +#if defined (_S_IFCHR) && !defined (S_IFCHR) +#define S_IFCHR _S_IFCHR +#endif +#if defined (_S_IFDIR) && !defined (S_IFDIR) +#define S_IFDIR _S_IFDIR +#endif +#if defined (_S_IFBLK) && !defined (S_IFBLK) +#define S_IFBLK _S_IFBLK +#endif +#if defined (_S_IFREG) && !defined (S_IFREG) +#define S_IFREG _S_IFREG +#endif +#if defined (_S_IFLNK) && !defined (S_IFLNK) +#define S_IFLNK _S_IFLNK +#endif +#if defined (_S_IFSOCK) && !defined (S_IFSOCK) +#define S_IFSOCK _S_IFSOCK +#endif + +/* Test for each symbol individually and define the ones necessary (some + systems claiming Posix compatibility define some but not all). */ + +#if defined (S_IFBLK) && !defined (S_ISBLK) +#define S_ISBLK(m) (((m)&S_IFMT) == S_IFBLK) /* block device */ +#endif + +#if defined (S_IFCHR) && !defined (S_ISCHR) +#define S_ISCHR(m) (((m)&S_IFMT) == S_IFCHR) /* character device */ +#endif + +#if defined (S_IFDIR) && !defined (S_ISDIR) +#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR) /* directory */ +#endif + +#if defined (S_IFREG) && !defined (S_ISREG) +#define S_ISREG(m) (((m)&S_IFMT) == S_IFREG) /* file */ +#endif + +#if defined (S_IFIFO) && !defined (S_ISFIFO) +#define S_ISFIFO(m) (((m)&S_IFMT) == S_IFIFO) /* fifo - named pipe */ +#endif + +#if defined (S_IFLNK) && !defined (S_ISLNK) +#define S_ISLNK(m) (((m)&S_IFMT) == S_IFLNK) /* symbolic link */ +#endif + +#if defined (S_IFSOCK) && !defined (S_ISSOCK) +#define S_ISSOCK(m) (((m)&S_IFMT) == S_IFSOCK) /* socket */ +#endif + +/* + * POSIX 1003.1 5.6.1.2 File Modes + */ + +#if !defined (S_IRWXU) +# if !defined (S_IREAD) +# define S_IREAD 00400 +# define S_IWRITE 00200 +# define S_IEXEC 00100 +# endif /* S_IREAD */ + +# if !defined (S_IRUSR) +# define S_IRUSR S_IREAD /* read, owner */ +# define S_IWUSR S_IWRITE /* write, owner */ +# define S_IXUSR S_IEXEC /* execute, owner */ + +# define S_IRGRP (S_IREAD >> 3) /* read, group */ +# define S_IWGRP (S_IWRITE >> 3) /* write, group */ +# define S_IXGRP (S_IEXEC >> 3) /* execute, group */ + +# define S_IROTH (S_IREAD >> 6) /* read, other */ +# define S_IWOTH (S_IWRITE >> 6) /* write, other */ +# define S_IXOTH (S_IEXEC >> 6) /* execute, other */ +# endif /* !S_IRUSR */ + +# define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR) +# define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) +# define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) +#endif /* !S_IRWXU */ + +/* These are non-standard, but are used in builtins.c$symbolic_umask() */ +#define S_IRUGO (S_IRUSR | S_IRGRP | S_IROTH) +#define S_IWUGO (S_IWUSR | S_IWGRP | S_IWOTH) +#define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH) + +#endif /* _POSIXSTAT_H */ diff --git a/readline.c b/readline.c new file mode 100644 index 0000000..e15a037 --- /dev/null +++ b/readline.c @@ -0,0 +1,3527 @@ +/* readline.c -- a general facility for reading lines of input + with emacs style editing and completion. */ + +/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library 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 1, or + (at your option) any later version. + + The GNU Readline Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define READLINE_LIBRARY + +#include +#include +#include +#if !defined (NO_SYS_FILE) +# include +#endif /* !NO_SYS_FILE */ +#include + +#if defined (HAVE_UNISTD_H) +# include +#endif /* HAVE_UNISTD_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#include +/* Not all systems declare ERRNO in errno.h... and some systems #define it! */ +#if !defined (errno) +extern int errno; +#endif /* !errno */ + +#include + +#include "posixstat.h" + +/* System-specific feature definitions and include files. */ +#include "rldefs.h" + +#if defined (GWINSZ_IN_SYS_IOCTL) || (defined (VSTATUS) && !defined (SunOS4)) +# include +#endif /* GWINSZ_IN_SYS_IOCTL || VSTATUS */ + +/* Some standard library routines. */ +#include "readline.h" +#include "history.h" + +/* NOTE: Functions and variables prefixed with `_rl_' are + pseudo-global: they are global so they can be shared + between files in the readline library, but are not intended + to be visible to readline callers. */ + +/* Functions imported from other files in the library. */ +extern char *tgetstr (); +extern void rl_prep_terminal (), rl_deprep_terminal (); + +extern void _rl_bind_if_unbound (); + +/* External redisplay functions and variables from display.c */ +extern void _rl_move_vert (); +extern void _rl_update_final (); + +extern void _rl_erase_at_end_of_line (); +extern void _rl_move_cursor_relative (); + +extern int _rl_vis_botlin; +extern int _rl_last_c_pos; +extern int _rl_horizontal_scroll_mode; +extern int rl_display_fixed; +extern char *rl_display_prompt; + +/* Variables imported from complete.c. */ +extern char *rl_completer_word_break_characters; +extern char *rl_basic_word_break_characters; +extern int rl_completion_query_items; +extern int rl_complete_with_tilde_expansion; + +#if defined (VI_MODE) +extern void _rl_vi_set_last (); +extern void _rl_vi_reset_last (); +extern void _rl_vi_done_inserting (); +#endif /* VI_MODE */ + +/* Forward declarations used in this file. */ +void _rl_free_history_entry (); + +int _rl_dispatch (); +void _rl_set_screen_size (); +int _rl_output_character_function (); + +static char *readline_internal (); +static void readline_initialize_everything (); +static int init_terminal_io (); +static void start_using_history (); +static void bind_arrow_keys (); + +#if !defined (__GO32__) +static void readline_default_bindings (); +#endif /* !__GO32__ */ + +#if defined (__GO32__) +# include +# undef HANDLE_SIGNALS +#endif /* __GO32__ */ + +#if defined (STATIC_MALLOC) +static char *xmalloc (), *xrealloc (); +#else +extern char *xmalloc (), *xrealloc (); +#endif /* STATIC_MALLOC */ + + +/* **************************************************************** */ +/* */ +/* Line editing input utility */ +/* */ +/* **************************************************************** */ + +static char *LibraryVersion = "2.0"; + +/* A pointer to the keymap that is currently in use. + By default, it is the standard emacs keymap. */ +Keymap _rl_keymap = emacs_standard_keymap; + +/* The current style of editing. */ +int rl_editing_mode = emacs_mode; + +/* Non-zero if the previous command was a kill command. */ +static int last_command_was_kill = 0; + +/* The current value of the numeric argument specified by the user. */ +int rl_numeric_arg = 1; + +/* Non-zero if an argument was typed. */ +int rl_explicit_arg = 0; + +/* Temporary value used while generating the argument. */ +int rl_arg_sign = 1; + +/* Non-zero means we have been called at least once before. */ +static int rl_initialized = 0; + +/* If non-zero, this program is running in an EMACS buffer. */ +static int running_in_emacs = 0; + +/* The current offset in the current input line. */ +int rl_point; + +/* Mark in the current input line. */ +int rl_mark; + +/* Length of the current input line. */ +int rl_end; + +/* Make this non-zero to return the current input_line. */ +int rl_done; + +/* The last function executed by readline. */ +Function *rl_last_func = (Function *)NULL; + +/* Top level environment for readline_internal (). */ +static jmp_buf readline_top_level; + +/* The streams we interact with. */ +static FILE *in_stream, *out_stream; + +/* The names of the streams that we do input and output to. */ +FILE *rl_instream = (FILE *)NULL; +FILE *rl_outstream = (FILE *)NULL; + +/* Non-zero means echo characters as they are read. */ +int readline_echoing_p = 1; + +/* Current prompt. */ +char *rl_prompt; +int rl_visible_prompt_length = 0; + +/* The number of characters read in order to type this complete command. */ +int rl_key_sequence_length = 0; + +/* If non-zero, then this is the address of a function to call just + before readline_internal () prints the first prompt. */ +Function *rl_startup_hook = (Function *)NULL; + +/* What we use internally. You should always refer to RL_LINE_BUFFER. */ +static char *the_line; + +/* The character that can generate an EOF. Really read from + the terminal driver... just defaulted here. */ +int _rl_eof_char = CTRL ('D'); + +/* Non-zero makes this the next keystroke to read. */ +int rl_pending_input = 0; + +/* Pointer to a useful terminal name. */ +char *rl_terminal_name = (char *)NULL; + +/* Non-zero means to always use horizontal scrolling in line display. */ +int _rl_horizontal_scroll_mode = 0; + +/* Non-zero means to display an asterisk at the starts of history lines + which have been modified. */ +int _rl_mark_modified_lines = 0; + +/* The style of `bell' notification preferred. This can be set to NO_BELL, + AUDIBLE_BELL, or VISIBLE_BELL. */ +int _rl_bell_preference = AUDIBLE_BELL; + +/* Line buffer and maintenence. */ +char *rl_line_buffer = (char *)NULL; +int rl_line_buffer_len = 0; +#define DEFAULT_BUFFER_SIZE 256 + +/* Forward declarations used by the display and termcap code. */ +int term_xn; +int screenwidth, screenheight, screenchars; + + +/* **************************************************************** */ +/* */ +/* `Forward' declarations */ +/* */ +/* **************************************************************** */ + +/* Non-zero means do not parse any lines other than comments and + parser directives. */ +unsigned char _rl_parsing_conditionalized_out = 0; + +/* Non-zero means to save keys that we dispatch on in a kbd macro. */ +static int defining_kbd_macro = 0; + +/* Non-zero means to convert characters with the meta bit set to + escape-prefixed characters so we can indirect through + emacs_meta_keymap or vi_escape_keymap. */ +int _rl_convert_meta_chars_to_ascii = 1; + +/* Non-zero means to output characters with the meta bit set directly + rather than as a meta-prefixed escape sequence. */ +int _rl_output_meta_chars = 0; + +/* Non-zero tells rl_delete_text and rl_insert_text to not add to + the undo list. */ +static int doing_an_undo = 0; + +/* **************************************************************** */ +/* */ +/* Top Level Functions */ +/* */ +/* **************************************************************** */ + +/* Non-zero means treat 0200 bit in terminal input as Meta bit. */ +int _rl_meta_flag = 0; /* Forward declaration */ + +/* Read a line of input. Prompt with PROMPT. A NULL PROMPT means + none. A return value of NULL means that EOF was encountered. */ +char * +readline (prompt) + char *prompt; +{ + char *value; + + rl_prompt = prompt; + + /* If we are at EOF return a NULL string. */ + if (rl_pending_input == EOF) + { + rl_pending_input = 0; + return ((char *)NULL); + } + + rl_visible_prompt_length = rl_expand_prompt (rl_prompt); + + rl_initialize (); + rl_prep_terminal (_rl_meta_flag); + +#if defined (HANDLE_SIGNALS) + rl_set_signals (); +#endif + + value = readline_internal (); + rl_deprep_terminal (); + +#if defined (HANDLE_SIGNALS) + rl_clear_signals (); +#endif + + return (value); +} + +/* Read a line of input from the global rl_instream, doing output on + the global rl_outstream. + If rl_prompt is non-null, then that is our prompt. */ +static char * +readline_internal () +{ + int lastc, c, eof_found; + + in_stream = rl_instream; + out_stream = rl_outstream; + + lastc = -1; + eof_found = 0; + + if (rl_startup_hook) + (*rl_startup_hook) (); + + if (!readline_echoing_p) + { + if (rl_prompt) + { + fprintf (out_stream, "%s", rl_prompt); + fflush (out_stream); + } + } + else + { + rl_on_new_line (); + rl_redisplay (); +#if defined (VI_MODE) + if (rl_editing_mode == vi_mode) + rl_vi_insertion_mode (); +#endif /* VI_MODE */ + } + + while (!rl_done) + { + int lk = last_command_was_kill; + int code; + + code = setjmp (readline_top_level); + + if (code) + rl_redisplay (); + + if (!rl_pending_input) + { + /* Then initialize the argument and number of keys read. */ + rl_init_argument (); + rl_key_sequence_length = 0; + } + + c = rl_read_key (); + + /* EOF typed to a non-blank line is a . */ + if (c == EOF && rl_end) + c = NEWLINE; + + /* The character _rl_eof_char typed to blank line, and not as the + previous character is interpreted as EOF. */ + if (((c == _rl_eof_char && lastc != c) || c == EOF) && !rl_end) + { + eof_found = 1; + break; + } + + lastc = c; + _rl_dispatch (c, _rl_keymap); + + /* If there was no change in last_command_was_kill, then no kill + has taken place. Note that if input is pending we are reading + a prefix command, so nothing has changed yet. */ + if (!rl_pending_input) + { + if (lk == last_command_was_kill) + last_command_was_kill = 0; + } + +#if defined (VI_MODE) + /* In vi mode, when you exit insert mode, the cursor moves back + over the previous character. We explicitly check for that here. */ + if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap) + rl_vi_check (); +#endif /* VI_MODE */ + + if (!rl_done) + rl_redisplay (); + } + + /* Restore the original of this history line, iff the line that we + are editing was originally in the history, AND the line has changed. */ + { + HIST_ENTRY *entry = current_history (); + + if (entry && rl_undo_list) + { + char *temp = savestring (the_line); + rl_revert_line (); + entry = replace_history_entry (where_history (), the_line, + (HIST_ENTRY *)NULL); + _rl_free_history_entry (entry); + + strcpy (the_line, temp); + free (temp); + } + } + + /* At any rate, it is highly likely that this line has an undo list. Get + rid of it now. */ + if (rl_undo_list) + free_undo_list (); + + if (eof_found) + return (char *)NULL; + else + return (savestring (the_line)); +} + +/* **************************************************************** */ +/* */ +/* Character Input Buffering */ +/* */ +/* **************************************************************** */ + +static int pop_index = 0, push_index = 0, ibuffer_len = 511; +static unsigned char ibuffer[512]; + +/* Non-null means it is a pointer to a function to run while waiting for + character input. */ +Function *rl_event_hook = (Function *)NULL; + +#define any_typein (push_index != pop_index) + +/* Add KEY to the buffer of characters to be read. */ +rl_stuff_char (key) + int key; +{ + if (key == EOF) + { + key = NEWLINE; + rl_pending_input = EOF; + } + ibuffer[push_index++] = key; + if (push_index >= ibuffer_len) + push_index = 0; + return push_index; +} + +/* Return the amount of space available in the + buffer for stuffing characters. */ +int +ibuffer_space () +{ + if (pop_index > push_index) + return (pop_index - push_index); + else + return (ibuffer_len - (push_index - pop_index)); +} + +/* Get a key from the buffer of characters to be read. + Return the key in KEY. + Result is KEY if there was a key, or 0 if there wasn't. */ +int +rl_get_char (key) + int *key; +{ + if (push_index == pop_index) + return (0); + + *key = ibuffer[pop_index++]; + + if (pop_index >= ibuffer_len) + pop_index = 0; + + return (1); +} + +/* Stuff KEY into the *front* of the input buffer. + Returns non-zero if successful, zero if there is + no space left in the buffer. */ +int +rl_unget_char (key) + int key; +{ + if (ibuffer_space ()) + { + pop_index--; + if (pop_index < 0) + pop_index = ibuffer_len - 1; + ibuffer[pop_index] = key; + return (1); + } + return (0); +} + +/* If a character is available to be read, then read it + and stuff it into IBUFFER. Otherwise, just return. */ +void +rl_gather_tyi () +{ +#if defined (__GO32__) + char input; + + if (isatty (0)) + { + int i = rl_getc (); + + if (i != EOF) + rl_stuff_char (i); + } + else if (kbhit () && ibuffer_space ()) + rl_stuff_char (getkey ()); +#else /* !__GO32__ */ + + int tty = fileno (in_stream); + register int tem, result = -1; + int chars_avail; + char input; + +#if defined (FIONREAD) + result = ioctl (tty, FIONREAD, &chars_avail); +#endif + +#if defined (O_NDELAY) + if (result == -1) + { + int flags; + + flags = fcntl (tty, F_GETFL, 0); + + fcntl (tty, F_SETFL, (flags | O_NDELAY)); + chars_avail = read (tty, &input, 1); + + fcntl (tty, F_SETFL, flags); + if (chars_avail == -1 && errno == EAGAIN) + return; + } +#endif /* O_NDELAY */ + + /* If there's nothing available, don't waste time trying to read + something. */ + if (chars_avail == 0) + return; + + tem = ibuffer_space (); + + if (chars_avail > tem) + chars_avail = tem; + + /* One cannot read all of the available input. I can only read a single + character at a time, or else programs which require input can be + thwarted. If the buffer is larger than one character, I lose. + Damn! */ + if (tem < ibuffer_len) + chars_avail = 0; + + if (result != -1) + { + while (chars_avail--) + rl_stuff_char (rl_getc (in_stream)); + } + else + { + if (chars_avail) + rl_stuff_char (input); + } +#endif /* !__GO32__ */ +} + +static int next_macro_key (); +/* Read a key, including pending input. */ +int +rl_read_key () +{ + int c; + + rl_key_sequence_length++; + + if (rl_pending_input) + { + c = rl_pending_input; + rl_pending_input = 0; + } + else + { + /* If input is coming from a macro, then use that. */ + if (c = next_macro_key ()) + return (c); + + /* If the user has an event function, then call it periodically. */ + if (rl_event_hook) + { + while (rl_event_hook && !rl_get_char (&c)) + { + (*rl_event_hook) (); + rl_gather_tyi (); + } + } + else + { + if (!rl_get_char (&c)) + c = rl_getc (in_stream); + } + } + + return (c); +} + +/* Found later in this file. */ +static void add_macro_char (), with_macro_input (); + +/* 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. */ +int +_rl_dispatch (key, map) + register int key; + Keymap map; +{ + int r = 0; + + if (defining_kbd_macro) + add_macro_char (key); + + if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii) + { + if (map[ESC].type == ISKMAP) + { + map = FUNCTION_TO_KEYMAP (map, ESC); + key = UNMETA (key); + rl_key_sequence_length += 2; + return (_rl_dispatch (key, map)); + } + else + ding (); + return 0; + } + + switch (map[key].type) + { + case ISFUNC: + { + Function *func = map[key].function; + + if (func != (Function *)NULL) + { + /* Special case rl_do_lowercase_version (). */ + if (func == rl_do_lowercase_version) + return (_rl_dispatch (to_lower (key), map)); + + r = (*map[key].function)(rl_numeric_arg * rl_arg_sign, key); + + /* If we have input pending, then the last command was a prefix + command. Don't change the state of rl_last_func. Otherwise, + remember the last command executed in this variable. */ + if (!rl_pending_input) + rl_last_func = map[key].function; + } + else + { + rl_abort (); + return -1; + } + } + break; + + case ISKMAP: + if (map[key].function != (Function *)NULL) + { + int newkey; + + rl_key_sequence_length++; + newkey = rl_read_key (); + r = _rl_dispatch (newkey, FUNCTION_TO_KEYMAP (map, key)); + } + else + { + rl_abort (); + return -1; + } + break; + + case ISMACR: + if (map[key].function != (Function *)NULL) + { + char *macro; + + macro = savestring ((char *)map[key].function); + with_macro_input (macro); + return 0; + } + break; + } +#if defined (VI_MODE) + if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap && + rl_vi_textmod_command (key)) + _rl_vi_set_last (key, rl_numeric_arg, rl_arg_sign); +#endif + return (r); +} + + +/* **************************************************************** */ +/* */ +/* Hacking Keyboard Macros */ +/* */ +/* **************************************************************** */ + +/* The currently executing macro string. If this is non-zero, + then it is a malloc ()'ed string where input is coming from. */ +static char *executing_macro = (char *)NULL; + +/* The offset in the above string to the next character to be read. */ +static int executing_macro_index = 0; + +/* The current macro string being built. Characters get stuffed + in here by add_macro_char (). */ +static char *current_macro = (char *)NULL; + +/* The size of the buffer allocated to current_macro. */ +static int current_macro_size = 0; + +/* The index at which characters are being added to current_macro. */ +static int current_macro_index = 0; + +/* A structure used to save nested macro strings. + It is a linked list of string/index for each saved macro. */ +struct saved_macro { + struct saved_macro *next; + char *string; + int sindex; +}; + +/* The list of saved macros. */ +struct saved_macro *macro_list = (struct saved_macro *)NULL; + +/* Forward declarations of static functions. Thank you C. */ +static void push_executing_macro (), pop_executing_macro (); + +/* This one has to be declared earlier in the file. */ +/* static void add_macro_char (); */ + +/* Set up to read subsequent input from STRING. + STRING is free ()'ed when we are done with it. */ +static void +with_macro_input (string) + char *string; +{ + push_executing_macro (); + executing_macro = string; + executing_macro_index = 0; +} + +/* Return the next character available from a macro, or 0 if + there are no macro characters. */ +static int +next_macro_key () +{ + if (!executing_macro) + return (0); + + if (!executing_macro[executing_macro_index]) + { + pop_executing_macro (); + return (next_macro_key ()); + } + + return (executing_macro[executing_macro_index++]); +} + +/* Save the currently executing macro on a stack of saved macros. */ +static void +push_executing_macro () +{ + struct saved_macro *saver; + + saver = (struct saved_macro *)xmalloc (sizeof (struct saved_macro)); + saver->next = macro_list; + saver->sindex = executing_macro_index; + saver->string = executing_macro; + + macro_list = saver; +} + +/* Discard the current macro, replacing it with the one + on the top of the stack of saved macros. */ +static void +pop_executing_macro () +{ + if (executing_macro) + free (executing_macro); + + executing_macro = (char *)NULL; + executing_macro_index = 0; + + if (macro_list) + { + struct saved_macro *disposer = macro_list; + executing_macro = macro_list->string; + executing_macro_index = macro_list->sindex; + macro_list = macro_list->next; + free (disposer); + } +} + +/* Add a character to the macro being built. */ +static void +add_macro_char (c) + int c; +{ + if (current_macro_index + 1 >= current_macro_size) + { + if (!current_macro) + current_macro = xmalloc (current_macro_size = 25); + else + current_macro = xrealloc (current_macro, current_macro_size += 25); + } + + current_macro[current_macro_index++] = c; + current_macro[current_macro_index] = '\0'; +} + +/* Begin defining a keyboard macro. + Keystrokes are recorded as they are executed. + End the definition with rl_end_kbd_macro (). + If a numeric argument was explicitly typed, then append this + definition to the end of the existing macro, and start by + re-executing the existing macro. */ +rl_start_kbd_macro (ignore1, ignore2) + int ignore1, ignore2; +{ + if (defining_kbd_macro) + { + rl_abort (); + return -1; + } + + if (rl_explicit_arg) + { + if (current_macro) + with_macro_input (savestring (current_macro)); + } + else + current_macro_index = 0; + + defining_kbd_macro = 1; + return 0; +} + +/* Stop defining a keyboard macro. + A numeric argument says to execute the macro right now, + that many times, counting the definition as the first time. */ +rl_end_kbd_macro (count, ignore) + int count, ignore; +{ + if (!defining_kbd_macro) + { + rl_abort (); + return -1; + } + + current_macro_index -= (rl_key_sequence_length - 1); + current_macro[current_macro_index] = '\0'; + + defining_kbd_macro = 0; + + return (rl_call_last_kbd_macro (--count, 0)); +} + +/* Execute the most recently defined keyboard macro. + COUNT says how many times to execute it. */ +rl_call_last_kbd_macro (count, ignore) + int count, ignore; +{ + if (!current_macro) + rl_abort (); + + if (defining_kbd_macro) + { + ding (); /* no recursive macros */ + current_macro[--current_macro_index] = '\0'; /* erase this char */ + return 0; + } + + while (count--) + with_macro_input (savestring (current_macro)); + return 0; +} + +void +_rl_kill_kbd_macro () +{ + if (current_macro) + { + free (current_macro); + current_macro = (char *) NULL; + } + current_macro_size = current_macro_index = 0; + + if (executing_macro) + { + free (executing_macro); + executing_macro = (char *) NULL; + } + executing_macro_index = 0; + + defining_kbd_macro = 0; +} + +/* **************************************************************** */ +/* */ +/* Initializations */ +/* */ +/* **************************************************************** */ + +/* Initliaze readline (and terminal if not already). */ +rl_initialize () +{ + char *t; + + /* If we have never been called before, initialize the + terminal and data structures. */ + if (!rl_initialized) + { + readline_initialize_everything (); + rl_initialized++; + } + + /* Initalize the current line information. */ + rl_point = rl_end = 0; + the_line = rl_line_buffer; + the_line[0] = 0; + + /* We aren't done yet. We haven't even gotten started yet! */ + rl_done = 0; + + /* Check for LC_CTYPE and use its value to decide the defaults for + 8-bit character input and output. */ + t = getenv ("LC_CTYPE"); + if (t && (strcmp (t, "iso-8859-1") == 0 || strcmp (t, "iso_8859_1") == 0)) + { + _rl_meta_flag = 1; + _rl_convert_meta_chars_to_ascii = 0; + _rl_output_meta_chars = 1; + } + + /* Tell the history routines what is going on. */ + start_using_history (); + + /* Make the display buffer match the state of the line. */ + rl_reset_line_state (); + + /* No such function typed yet. */ + rl_last_func = (Function *)NULL; + + /* Parsing of key-bindings begins in an enabled state. */ + _rl_parsing_conditionalized_out = 0; + + return 0; +} + +/* Initialize the entire state of the world. */ +static void +readline_initialize_everything () +{ + /* Find out if we are running in Emacs. */ + running_in_emacs = getenv ("EMACS") != (char *)0; + + /* Set up input and output if they are not already set up. */ + if (!rl_instream) + rl_instream = stdin; + + if (!rl_outstream) + rl_outstream = stdout; + + /* Bind in_stream and out_stream immediately. These values may change, + but they may also be used before readline_internal () is called. */ + in_stream = rl_instream; + out_stream = rl_outstream; + + /* Allocate data structures. */ + if (!rl_line_buffer) + rl_line_buffer = xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE); + + /* Initialize the terminal interface. */ + init_terminal_io ((char *)NULL); + +#if !defined (__GO32__) + /* Bind tty characters to readline functions. */ + readline_default_bindings (); +#endif /* !__GO32__ */ + + /* Initialize the function names. */ + rl_initialize_funmap (); + + /* Read in the init file. */ + rl_read_init_file ((char *)NULL); + + /* XXX */ + if (_rl_horizontal_scroll_mode && term_xn) + { + screenwidth--; + screenchars -= screenheight; + } + + /* Override the effect of any `set keymap' assignments in the + inputrc file. */ + rl_set_keymap_from_edit_mode (); + + /* Try to bind a common arrow key prefix, if not already bound. */ + bind_arrow_keys (); + + /* If the completion parser's default word break characters haven't + been set yet, then do so now. */ + if (rl_completer_word_break_characters == (char *)NULL) + rl_completer_word_break_characters = rl_basic_word_break_characters; +} + +/* If this system allows us to look at the values of the regular + input editing characters, then bind them to their readline + equivalents, iff the characters are not bound to keymaps. */ +static void +readline_default_bindings () +{ + rltty_set_default_bindings (_rl_keymap); +} + +static void +bind_arrow_keys_internal () +{ + Function *f; + + f = rl_function_of_keyseq ("\033[A", _rl_keymap, (int *)NULL); + if (!f || f == rl_do_lowercase_version) + { + _rl_bind_if_unbound ("\033[A", rl_get_previous_history); + _rl_bind_if_unbound ("\033[B", rl_get_next_history); + _rl_bind_if_unbound ("\033[C", rl_forward); + _rl_bind_if_unbound ("\033[D", rl_backward); + } + + f = rl_function_of_keyseq ("\033OA", _rl_keymap, (int *)NULL); + if (!f || f == rl_do_lowercase_version) + { + _rl_bind_if_unbound ("\033OA", rl_get_previous_history); + _rl_bind_if_unbound ("\033OB", rl_get_next_history); + _rl_bind_if_unbound ("\033OC", rl_forward); + _rl_bind_if_unbound ("\033OD", rl_backward); + } +} + +/* Try and bind the common arrow key prefix after giving termcap and + the inputrc file a chance to bind them and create `real' keymaps + for the arrow key prefix. */ +static void +bind_arrow_keys () +{ + Keymap xkeymap; + + xkeymap = _rl_keymap; + + _rl_keymap = emacs_standard_keymap; + bind_arrow_keys_internal (); + +#if defined (VI_MODE) + _rl_keymap = vi_movement_keymap; + bind_arrow_keys_internal (); +#endif + + _rl_keymap = xkeymap; +} + + +/* **************************************************************** */ +/* */ +/* Numeric Arguments */ +/* */ +/* **************************************************************** */ + +/* Handle C-u style numeric args, as well as M--, and M-digits. */ +static int +rl_digit_loop () +{ + int key, c; + + while (1) + { + rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); + key = c = rl_read_key (); + + if (_rl_keymap[c].type == ISFUNC && + _rl_keymap[c].function == rl_universal_argument) + { + rl_numeric_arg *= 4; + continue; + } + c = UNMETA (c); + if (digit_p (c)) + { + if (rl_explicit_arg) + rl_numeric_arg = (rl_numeric_arg * 10) + (c - '0'); + else + rl_numeric_arg = (c - '0'); + rl_explicit_arg = 1; + } + else + { + if (c == '-' && !rl_explicit_arg) + { + rl_numeric_arg = 1; + rl_arg_sign = -1; + } + else + { + rl_clear_message (); + return (_rl_dispatch (key, _rl_keymap)); + } + } + } + return 0; +} + +/* Add the current digit to the argument in progress. */ +rl_digit_argument (ignore, key) + int ignore, key; +{ + rl_pending_input = key; + return (rl_digit_loop ()); +} + +/* What to do when you abort reading an argument. */ +rl_discard_argument () +{ + ding (); + rl_clear_message (); + rl_init_argument (); + return 0; +} + +/* Create a default argument. */ +rl_init_argument () +{ + rl_numeric_arg = rl_arg_sign = 1; + rl_explicit_arg = 0; + return 0; +} + +/* 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. */ +rl_universal_argument () +{ + rl_numeric_arg *= 4; + return (rl_digit_loop ()); +} + +/* **************************************************************** */ +/* */ +/* Terminal and Termcap */ +/* */ +/* **************************************************************** */ + +static char *term_buffer = (char *)NULL; +static char *term_string_buffer = (char *)NULL; + +static int tcap_initialized = 0; + +/* Non-zero means this terminal can't really do anything. */ +int dumb_term = 0; +/* 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 + +#if !defined (__linux__) +/* If this causes problems, remove the `extern'. */ +extern char PC, *BC, *UP; +#endif /* __linux__ */ + +/* Some strings to control terminal actions. These are output by tputs (). */ +char *term_goto, *term_clreol, *term_cr, *term_clrpag, *term_backspace; +char *term_pc; + +/* Non-zero if we determine that the terminal can do character insertion. */ +int terminal_can_insert = 0; + +/* How to insert characters. */ +char *term_im, *term_ei, *term_ic, *term_ip, *term_IC; + +/* How to delete characters. */ +char *term_dc, *term_DC; + +#if defined (HACK_TERMCAP_MOTION) +char *term_forward_char; +#endif /* HACK_TERMCAP_MOTION */ + +/* How to go up a line. */ +char *term_up; + +/* A visible bell, if the terminal can be made to flash the screen. */ +char *visible_bell; + +/* Non-zero means that this terminal has a meta key. */ +int term_has_meta; + +/* The string to write to turn on the meta key, if this term has one. */ +char *term_mm; + +/* The string to write to turn off the meta key, if this term has one. */ +char *term_mo; + +/* The key sequences output by the arrow keys, if this terminal has any. */ +char *term_ku, *term_kd, *term_kr, *term_kl; + +/* How to initialize and reset the arrow keys, if this terminal has any. */ +char *term_ks, *term_ke; + +/* Re-initialize the terminal considering that the TERM/TERMCAP variable + has changed. */ +rl_reset_terminal (terminal_name) + char *terminal_name; +{ + init_terminal_io (terminal_name); + return 0; +} + +/* Set readline's idea of the screen size. TTY is a file descriptor open + to the terminal. If IGNORE_ENV is true, we do not pay attention to the + values of $LINES and $COLUMNS. The tests for TERM_STRING_BUFFER being + non-null serve to check whether or not we have initialized termcap. */ +void +_rl_set_screen_size (tty, ignore_env) + int tty, ignore_env; +{ +#if defined (TIOCGWINSZ) + struct winsize window_size; +#endif /* TIOCGWINSZ */ + +#if defined (TIOCGWINSZ) + if (ioctl (tty, 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 IGNORE_ENV + is unset. */ + if (screenwidth <= 0) + { + char *sw; + + if (!ignore_env && (sw = getenv ("COLUMNS"))) + screenwidth = atoi (sw); + + if (screenwidth <= 0 && term_string_buffer) + screenwidth = tgetnum ("co"); + } + + /* Environment variable LINES overrides setting of "li" if IGNORE_ENV + is unset. */ + if (screenheight <= 0) + { + char *sh; + + if (!ignore_env && (sh = getenv ("LINES"))) + screenheight = atoi (sh); + + if (screenheight <= 0 && term_string_buffer) + screenheight = tgetnum ("li"); + } + + /* If all else fails, default to 80x24 terminal. */ + if (screenwidth <= 1) + screenwidth = 80; + + if (screenheight <= 0) + screenheight = 24; + +#if defined (SHELL) + /* If we're being compiled as part of bash, set the environment + variables $LINES and $COLUMNS to new values. */ + set_lines_and_columns (screenheight, screenwidth); +#endif + + if (!term_xn) + screenwidth--; + + screenchars = screenwidth * screenheight; +} + +struct _tc_string { + char *tc_var; + char **tc_value; +}; + +/* This should be kept sorted, just in case we decide to change the + search algorithm to something smarter. */ +static struct _tc_string tc_strings[] = +{ + "DC", &term_DC, + "IC", &term_IC, + "ce", &term_clreol, + "cl", &term_clrpag, + "cr", &term_cr, + "dc", &term_dc, + "ei", &term_ei, + "ic", &term_ic, + "im", &term_im, + "kd", &term_kd, + "kl", &term_kl, + "kr", &term_kr, + "ku", &term_ku, + "ks", &term_ks, + "ke", &term_ke, + "le", &term_backspace, + "mm", &term_mm, + "mo", &term_mo, +#if defined (HACK_TERMCAP_MOTION) + "nd", &term_forward_char, +#endif + "pc", &term_pc, + "up", &term_up, + "vb", &visible_bell, +}; + +#define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string)) + +/* Read the desired terminal capability strings into BP. The capabilities + are described in the TC_STRINGS table. */ +static void +get_term_capabilities (bp) + char **bp; +{ + register int i; + + for (i = 0; i < NUM_TC_STRINGS; i++) + *(tc_strings[i].tc_value) = tgetstr (tc_strings[i].tc_var, bp); + tcap_initialized = 1; +} + +static int +init_terminal_io (terminal_name) + char *terminal_name; +{ +#if defined (__GO32__) + screenwidth = ScreenCols (); + screenheight = ScreenRows (); + screenchars = screenwidth * screenheight; + term_cr = "\r"; + term_im = term_ei = term_ic = term_IC = (char *)NULL; + term_up = term_dc = term_DC = visible_bell = (char *)NULL; + + /* Does the __GO32__ have a meta key? I don't know. */ + term_has_meta = 0; + term_mm = term_mo = (char *)NULL; + + /* It probably has arrow keys, but I don't know what they are. */ + term_ku = term_kd = term_kr = term_kl = (char *)NULL; + +#if defined (HACK_TERMCAP_MOTION) + term_forward_char = (char *)NULL; +#endif /* HACK_TERMCAP_MOTION */ + terminal_can_insert = term_xn = 0; + return; +#else /* !__GO32__ */ + + char *term, *buffer; + int tty; + Keymap xkeymap; + + term = terminal_name ? terminal_name : getenv ("TERM"); + + if (!term_string_buffer) + term_string_buffer = xmalloc (2048); + + if (!term_buffer) + term_buffer = xmalloc (2048); + + buffer = term_string_buffer; + + term_clrpag = term_cr = term_clreol = (char *)NULL; + + if (!term) + term = "dumb"; + + if (tgetent (term_buffer, term) <= 0) + { + dumb_term = 1; + screenwidth = 79; + screenheight = 24; + screenchars = 79 * 24; + term_cr = "\r"; + term_im = term_ei = term_ic = term_IC = (char *)NULL; + term_up = term_dc = term_DC = visible_bell = (char *)NULL; + term_ku = term_kd = term_kl = term_kr = (char *)NULL; +#if defined (HACK_TERMCAP_MOTION) + term_forward_char = (char *)NULL; +#endif + terminal_can_insert = 0; + return 0; + } + + get_term_capabilities (&buffer); + + /* Set up the variables that the termcap library expects the application + to provide. */ + PC = term_pc ? *term_pc : 0; + BC = term_backspace; + UP = term_up; + + if (!term_cr) + term_cr = "\r"; + + if (rl_instream) + tty = fileno (rl_instream); + else + tty = 0; + + screenwidth = screenheight = 0; + + term_xn = tgetflag ("am") && tgetflag ("xn"); + + _rl_set_screen_size (tty, 0); + + /* "An application program can assume that the terminal can do + character insertion if *any one of* the capabilities `IC', + `im', `ic' or `ip' is provided." But we can't do anything if + only `ip' is provided, so... */ + terminal_can_insert = (term_IC || term_im || term_ic); + + /* Check to see if this terminal has a meta key and clear the capability + variables if there is none. */ + term_has_meta = (tgetflag ("km") || tgetflag ("MT")); + if (!term_has_meta) + { + term_mm = (char *)NULL; + term_mo = (char *)NULL; + } + + /* Attempt to find and bind the arrow keys. Do not override already + bound keys in an overzealous attempt, however. */ + xkeymap = _rl_keymap; + + _rl_keymap = emacs_standard_keymap; + _rl_bind_if_unbound (term_ku, rl_get_previous_history); + _rl_bind_if_unbound (term_kd, rl_get_next_history); + _rl_bind_if_unbound (term_kr, rl_forward); + _rl_bind_if_unbound (term_kl, rl_backward); + +#if defined (VI_MODE) + _rl_keymap = vi_movement_keymap; + _rl_bind_if_unbound (term_ku, rl_get_previous_history); + _rl_bind_if_unbound (term_kd, rl_get_next_history); + _rl_bind_if_unbound (term_kr, rl_forward); + _rl_bind_if_unbound (term_kl, rl_backward); +#endif /* VI_MODE */ + + _rl_keymap = xkeymap; + +#endif /* !__GO32__ */ + return 0; +} + +char * +rl_get_termcap (cap) + char *cap; +{ + register int i; + + if (tcap_initialized == 0) + return ((char *)NULL); + for (i = 0; i < NUM_TC_STRINGS; i++) + { + if (tc_strings[i].tc_var[0] == cap[0] && strcmp (tc_strings[i].tc_var, cap) == 0) + return *(tc_strings[i].tc_value); + } + return ((char *)NULL); +} + +/* A function for the use of tputs () */ +int +_rl_output_character_function (c) + int c; +{ + return putc (c, out_stream); +} + +/* Write COUNT characters from STRING to the output stream. */ +void +_rl_output_some_chars (string, count) + char *string; + int count; +{ + fwrite (string, 1, count, out_stream); +} + +/* Move the cursor back. */ +backspace (count) + int count; +{ + register int i; + +#if !defined (__GO32__) + if (term_backspace) + for (i = 0; i < count; i++) + tputs (term_backspace, 1, _rl_output_character_function); + else +#endif /* !__GO32__ */ + for (i = 0; i < count; i++) + putc ('\b', out_stream); + return 0; +} + +/* Move to the start of the next line. */ +crlf () +{ +#if defined (NEW_TTY_DRIVER) + tputs (term_cr, 1, _rl_output_character_function); +#endif /* NEW_TTY_DRIVER */ + putc ('\n', out_stream); + return 0; +} + +rl_tty_status (count, key) + int count, key; +{ +#if defined (TIOCSTAT) + ioctl (1, TIOCSTAT, (char *)0); + rl_refresh_line (); +#else + ding (); +#endif + return 0; +} + + +/* **************************************************************** */ +/* */ +/* Utility Functions */ +/* */ +/* **************************************************************** */ + +/* Return 0 if C is not a member of the class of characters that belong + in words, or 1 if it is. */ + +int allow_pathname_alphabetic_chars = 0; +char *pathname_alphabetic_chars = "/-_=~.#$"; + +int +alphabetic (c) + int c; +{ + if (pure_alphabetic (c) || (digit_p (c))) + return (1); + + if (allow_pathname_alphabetic_chars) + return (strchr (pathname_alphabetic_chars, c) != NULL); + else + return (0); +} + +/* Ring the terminal bell. */ +int +ding () +{ + if (readline_echoing_p) + { +#if !defined (__GO32__) + switch (_rl_bell_preference) + { + case NO_BELL: + default: + break; + case VISIBLE_BELL: + if (visible_bell) + { + tputs (visible_bell, 1, _rl_output_character_function); + break; + } + /* FALLTHROUGH */ + case AUDIBLE_BELL: + fprintf (stderr, "\007"); + fflush (stderr); + break; + } +#else /* __GO32__ */ + fprintf (stderr, "\007"); + fflush (stderr); +#endif /* __GO32__ */ + return (0); + } + return (-1); +} + +/* How to abort things. */ +rl_abort (count, key) + int count, key; +{ + ding (); + rl_clear_message (); + rl_init_argument (); + rl_pending_input = 0; + + defining_kbd_macro = 0; + while (executing_macro) + pop_executing_macro (); + + rl_last_func = (Function *)NULL; + longjmp (readline_top_level, 1); +} + +/* Return a copy of the string between FROM and TO. + FROM is inclusive, TO is not. */ +char * +rl_copy_text (from, to) + int from, to; +{ + register int length; + char *copy; + + /* Fix it if the caller is confused. */ + if (from > to) + { + int t = from; + from = to; + to = t; + } + + length = to - from; + copy = xmalloc (1 + length); + strncpy (copy, the_line + from, length); + copy[length] = '\0'; + return (copy); +} + +/* Increase the size of RL_LINE_BUFFER until it has enough space to hold + LEN characters. */ +void +rl_extend_line_buffer (len) + int len; +{ + while (len >= rl_line_buffer_len) + { + rl_line_buffer_len += DEFAULT_BUFFER_SIZE; + rl_line_buffer = xrealloc (rl_line_buffer, rl_line_buffer_len); + } + + the_line = rl_line_buffer; +} + + +/* **************************************************************** */ +/* */ +/* Insert and Delete */ +/* */ +/* **************************************************************** */ + +/* Insert a string of text into the line at point. This is the only + way that you should do insertion. rl_insert () calls this + function. */ +rl_insert_text (string) + char *string; +{ + register int i, l = strlen (string); + + if (rl_end + l >= rl_line_buffer_len) + rl_extend_line_buffer (rl_end + l); + + for (i = rl_end; i >= rl_point; i--) + the_line[i + l] = the_line[i]; + strncpy (the_line + rl_point, string, l); + + /* Remember how to undo this if we aren't undoing something. */ + if (!doing_an_undo) + { + /* If possible and desirable, concatenate the undos. */ + if ((l == 1) && + rl_undo_list && + (rl_undo_list->what == UNDO_INSERT) && + (rl_undo_list->end == rl_point) && + (rl_undo_list->end - rl_undo_list->start < 20)) + rl_undo_list->end++; + else + rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL); + } + rl_point += l; + rl_end += l; + the_line[rl_end] = '\0'; + return l; +} + +/* Delete the string between FROM and TO. FROM is + inclusive, TO is not. */ +rl_delete_text (from, to) + int from, to; +{ + register char *text; + register int diff, i; + + /* Fix it if the caller is confused. */ + if (from > to) + { + int t = from; + from = to; + to = t; + } + text = rl_copy_text (from, to); + + /* Some versions of strncpy() can't handle overlapping arguments. */ + diff = to - from; + for (i = from; i < rl_end - diff; i++) + the_line[i] = the_line[i + diff]; + + /* Remember how to undo this delete. */ + if (!doing_an_undo) + rl_add_undo (UNDO_DELETE, from, to, text); + else + free (text); + + rl_end -= diff; + the_line[rl_end] = '\0'; + return (diff); +} + + +/* **************************************************************** */ +/* */ +/* Readline character functions */ +/* */ +/* **************************************************************** */ + +/* This is not a gap editor, just a stupid line input routine. No hair + is involved in writing any of the functions, and none should be. */ + +/* Note that: + + rl_end is the place in the string that we would place '\0'; + i.e., it is always safe to place '\0' there. + + rl_point is the place in the string where the cursor is. Sometimes + this is the same as rl_end. + + Any command that is called interactively receives two arguments. + The first is a count: the numeric arg pased to this command. + The second is the key which invoked this command. +*/ + + +/* **************************************************************** */ +/* */ +/* Movement Commands */ +/* */ +/* **************************************************************** */ + +/* Note that if you `optimize' the display for these functions, you cannot + use said functions in other functions which do not do optimizing display. + I.e., you will have to update the data base for rl_redisplay, and you + might as well let rl_redisplay do that job. */ + +/* Move forward COUNT characters. */ +rl_forward (count, key) + int count, key; +{ + if (count < 0) + rl_backward (-count); + else if (count > 0) + { + int end = rl_point + count; +#if defined (VI_MODE) + int lend = rl_end - (rl_editing_mode == vi_mode); +#else + int lend = rl_end; +#endif + + if (end > lend) + { + rl_point = lend; + ding (); + } + else + rl_point = end; + } + return 0; +} + +/* Move backward COUNT characters. */ +rl_backward (count, key) + int count, key; +{ + if (count < 0) + rl_forward (-count); + else if (count > 0) + { + if (rl_point < count) + { + rl_point = 0; + ding (); + } + else + rl_point -= count; + } + return 0; +} + +/* Move to the beginning of the line. */ +rl_beg_of_line (count, key) + int count, key; +{ + rl_point = 0; + return 0; +} + +/* Move to the end of the line. */ +rl_end_of_line (count, key) + int count, key; +{ + rl_point = rl_end; + return 0; +} + +/* Move forward a word. We do what Emacs does. */ +rl_forward_word (count, key) + int count, key; +{ + int c; + + if (count < 0) + { + rl_backward_word (-count); + return 0; + } + + while (count) + { + if (rl_point == rl_end) + return 0; + + /* 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 = the_line[rl_point]; + if (!alphabetic (c)) + { + while (++rl_point < rl_end) + { + c = the_line[rl_point]; + if (alphabetic (c)) + break; + } + } + if (rl_point == rl_end) + return 0; + while (++rl_point < rl_end) + { + c = the_line[rl_point]; + if (!alphabetic (c)) + break; + } + --count; + } + return 0; +} + +/* Move backward a word. We do what Emacs does. */ +rl_backward_word (count, key) + int count, key; +{ + int c; + + if (count < 0) + { + rl_forward_word (-count); + return 0; + } + + while (count) + { + if (!rl_point) + return 0; + + /* Like rl_forward_word (), except that we look at the characters + just before point. */ + + c = the_line[rl_point - 1]; + if (!alphabetic (c)) + { + while (--rl_point) + { + c = the_line[rl_point - 1]; + if (alphabetic (c)) + break; + } + } + + while (rl_point) + { + c = the_line[rl_point - 1]; + if (!alphabetic (c)) + break; + else + --rl_point; + } + --count; + } + return 0; +} + +/* Clear the current line. Numeric argument to C-l does this. */ +rl_refresh_line () +{ + int curr_line, nleft; + + /* Find out whether or not there might be invisible characters in the + editing buffer. */ + if (rl_display_prompt == rl_prompt) + nleft = _rl_last_c_pos - screenwidth - rl_visible_prompt_length; + else + nleft = _rl_last_c_pos - screenwidth; + + if (nleft > 0) + curr_line = 1 + nleft / screenwidth; + else + curr_line = 0; + + _rl_move_vert (curr_line); + _rl_move_cursor_relative (0, the_line); /* XXX is this right */ + +#if defined (__GO32__) + { + int row, col, width, row_start; + + ScreenGetCursor (&row, &col); + width = ScreenCols (); + row_start = ScreenPrimary + (row * width); + memset (row_start + col, 0, (width - col) * 2); + } +#else /* !__GO32__ */ + if (term_clreol) + tputs (term_clreol, 1, _rl_output_character_function); +#endif /* !__GO32__ */ + + rl_forced_update_display (); + rl_display_fixed = 1; + + return 0; +} + +/* C-l typed to a line without quoting clears the screen, and then reprints + the prompt and the current input line. Given a numeric arg, redraw only + the current line. */ +rl_clear_screen (count, key) + int count, key; +{ + if (rl_explicit_arg) + { + rl_refresh_line (); + return 0; + } + +#if !defined (__GO32__) + if (term_clrpag) + tputs (term_clrpag, 1, _rl_output_character_function); + else +#endif /* !__GO32__ */ + crlf (); + + rl_forced_update_display (); + rl_display_fixed = 1; + + return 0; +} + +rl_arrow_keys (count, c) + int count, c; +{ + int ch; + + ch = rl_read_key (); + + switch (to_upper (ch)) + { + case 'A': + rl_get_previous_history (count); + break; + + case 'B': + rl_get_next_history (count); + break; + + case 'C': + rl_forward (count); + break; + + case 'D': + rl_backward (count); + break; + + default: + ding (); + } + return 0; +} + + +/* **************************************************************** */ +/* */ +/* Text commands */ +/* */ +/* **************************************************************** */ + +/* Insert the character C at the current location, moving point forward. */ +rl_insert (count, c) + int count, c; +{ + register int i; + char *string; + + if (count <= 0) + return 0; + + /* If we can optimize, then do it. But don't let people crash + readline because of extra large arguments. */ + if (count > 1 && count < 1024) + { + string = xmalloc (1 + count); + + for (i = 0; i < count; i++) + string[i] = c; + + string[i] = '\0'; + rl_insert_text (string); + free (string); + + return 0; + } + + if (count > 1024) + { + int decreaser; + char str[1024+1]; + + for (i = 0; i < 1024; i++) + str[i] = c; + + while (count) + { + decreaser = (count > 1024 ? 1024 : count); + str[decreaser] = '\0'; + rl_insert_text (str); + count -= decreaser; + } + + return 0; + } + + /* We are inserting a single character. + If there is pending input, then make a string of all of the + pending characters that are bound to rl_insert, and insert + them all. */ + if (any_typein) + { + int key = 0, t; + + i = 0; + string = xmalloc (ibuffer_len + 1); + string[i++] = c; + + while ((t = rl_get_char (&key)) && + (_rl_keymap[key].type == ISFUNC && + _rl_keymap[key].function == rl_insert)) + string[i++] = key; + + if (t) + rl_unget_char (key); + + string[i] = '\0'; + rl_insert_text (string); + free (string); + } + else + { + /* Inserting a single character. */ + char str[2]; + + str[1] = '\0'; + str[0] = c; + rl_insert_text (str); + } + return 0; +} + +/* Insert the next typed character verbatim. */ +rl_quoted_insert (count, key) + int count, key; +{ + int c; + + c = rl_read_key (); + return (rl_insert (count, c)); +} + +/* Insert a tab character. */ +rl_tab_insert (count, key) + int count, key; +{ + return (rl_insert (count, '\t')); +} + +/* What to do when a NEWLINE is pressed. We accept the whole line. + KEY is the key that invoked this command. I guess it could have + meaning in the future. */ +rl_newline (count, key) + int count, key; +{ + rl_done = 1; + +#if defined (VI_MODE) + _rl_vi_done_inserting (); + _rl_vi_reset_last (); + +#endif /* VI_MODE */ + + if (readline_echoing_p) + _rl_update_final (); + return 0; +} + +rl_clean_up_for_exit () +{ + if (readline_echoing_p) + { + _rl_move_vert (_rl_vis_botlin); + _rl_vis_botlin = 0; + fflush (out_stream); + rl_restart_output (); + } + return 0; +} + +/* What to do for some uppercase characters, like meta characters, + and some characters appearing in emacs_ctlx_keymap. This function + is just a stub, you bind keys to it and the code in _rl_dispatch () + is special cased. */ +rl_do_lowercase_version (ignore1, ignore2) + int ignore1, ignore2; +{ + return 0; +} + +/* Rubout the character behind point. */ +rl_rubout (count, key) + int count, key; +{ + if (count < 0) + { + rl_delete (-count); + return 0; + } + + if (!rl_point) + { + ding (); + return -1; + } + + if (count > 1 || rl_explicit_arg) + { + int orig_point = rl_point; + rl_backward (count); + rl_kill_text (orig_point, rl_point); + } + else + { + int c = the_line[--rl_point]; + rl_delete_text (rl_point, rl_point + 1); + + if (rl_point == rl_end && isprint (c) && _rl_last_c_pos) + { + int l; + l = rl_character_len (c, rl_point); + _rl_erase_at_end_of_line (l); + } + } + return 0; +} + +/* Delete the character under the cursor. Given a numeric argument, + kill that many characters instead. */ +rl_delete (count, invoking_key) + int count, invoking_key; +{ + if (count < 0) + { + return (rl_rubout (-count)); + } + + if (rl_point == rl_end) + { + ding (); + return -1; + } + + if (count > 1 || rl_explicit_arg) + { + int orig_point = rl_point; + rl_forward (count); + rl_kill_text (orig_point, rl_point); + rl_point = orig_point; + return 0; + } + else + return (rl_delete_text (rl_point, rl_point + 1)); + +} + +/* Delete all spaces and tabs around point. */ +rl_delete_horizontal_space (count, ignore) + int count, ignore; +{ + int start = rl_point; + + while (rl_point && whitespace (the_line[rl_point - 1])) + rl_point--; + + start = rl_point; + + while (rl_point < rl_end && whitespace (the_line[rl_point])) + rl_point++; + + if (start != rl_point) + { + rl_delete_text (start, rl_point); + rl_point = start; + } + return 0; +} + + +/* **************************************************************** */ +/* */ +/* Kill commands */ +/* */ +/* **************************************************************** */ + +/* The next two functions mimic unix line editing behaviour, except they + save the deleted text on the kill ring. This is safer than not saving + it, and since we have a ring, nobody should get screwed. */ + +/* This does what C-w does in Unix. We can't prevent people from + using behaviour that they expect. */ +rl_unix_word_rubout (count, key) + int count, key; +{ + if (!rl_point) + ding (); + else + { + int orig_point = rl_point; + + while (rl_point && whitespace (the_line[rl_point - 1])) + rl_point--; + + while (rl_point && !whitespace (the_line[rl_point - 1])) + rl_point--; + + rl_kill_text (orig_point, rl_point); + } + return 0; +} + +/* Here is C-u doing what Unix does. You don't *have* to use these + key-bindings. We have a choice of killing the entire line, or + killing from where we are to the start of the line. We choose the + latter, because if you are a Unix weenie, then you haven't backspaced + into the line at all, and if you aren't, then you know what you are + doing. */ +rl_unix_line_discard (count, key) + int count, key; +{ + if (!rl_point) + ding (); + else + { + rl_kill_text (rl_point, 0); + rl_point = 0; + } + return 0; +} + + +/* **************************************************************** */ +/* */ +/* Commands For Typos */ +/* */ +/* **************************************************************** */ + +/* Random and interesting things in here. */ + +/* **************************************************************** */ +/* */ +/* Changing Case */ +/* */ +/* **************************************************************** */ + +/* The three kinds of things that we know how to do. */ +#define UpCase 1 +#define DownCase 2 +#define CapCase 3 + +static int rl_change_case (); + +/* Uppercase the word at point. */ +rl_upcase_word (count, key) + int count, key; +{ + return (rl_change_case (count, UpCase)); +} + +/* Lowercase the word at point. */ +rl_downcase_word (count, key) + int count, key; +{ + return (rl_change_case (count, DownCase)); +} + +/* Upcase the first letter, downcase the rest. */ +rl_capitalize_word (count, key) + int count, key; +{ + return (rl_change_case (count, CapCase)); +} + +/* The meaty function. + Change the case of COUNT words, performing OP on them. + OP is one of UpCase, DownCase, or CapCase. + If a negative argument is given, leave point where it started, + otherwise, leave it where it moves to. */ +static int +rl_change_case (count, op) + int count, op; +{ + register int start = rl_point, end; + int state = 0; + + rl_forward_word (count); + end = rl_point; + + if (count < 0) + { + int temp = start; + start = end; + end = temp; + } + + /* We are going to modify some text, so let's prepare to undo it. */ + rl_modifying (start, end); + + for (; start < end; start++) + { + switch (op) + { + case UpCase: + the_line[start] = to_upper (the_line[start]); + break; + + case DownCase: + the_line[start] = to_lower (the_line[start]); + break; + + case CapCase: + if (state == 0) + { + the_line[start] = to_upper (the_line[start]); + state = 1; + } + else + { + the_line[start] = to_lower (the_line[start]); + } + if (!pure_alphabetic (the_line[start])) + state = 0; + break; + + default: + abort (); + return -1; + } + } + rl_point = end; + return 0; +} + +/* **************************************************************** */ +/* */ +/* Transposition */ +/* */ +/* **************************************************************** */ + +/* Transpose the words at point. */ +rl_transpose_words (count, key) + int count, key; +{ + char *word1, *word2; + int w1_beg, w1_end, w2_beg, w2_end; + int orig_point = rl_point; + + if (!count) + return 0; + + /* Find the two words. */ + rl_forward_word (count); + w2_end = rl_point; + rl_backward_word (1); + w2_beg = rl_point; + rl_backward_word (count); + w1_beg = rl_point; + rl_forward_word (1); + w1_end = rl_point; + + /* Do some check to make sure that there really are two words. */ + if ((w1_beg == w2_beg) || (w2_beg < w1_end)) + { + ding (); + rl_point = orig_point; + return -1; + } + + /* Get the text of the words. */ + word1 = rl_copy_text (w1_beg, w1_end); + word2 = rl_copy_text (w2_beg, w2_end); + + /* We are about to do many insertions and deletions. Remember them + as one operation. */ + rl_begin_undo_group (); + + /* Do the stuff at word2 first, so that we don't have to worry + about word1 moving. */ + rl_point = w2_beg; + rl_delete_text (w2_beg, w2_end); + rl_insert_text (word1); + + rl_point = w1_beg; + rl_delete_text (w1_beg, w1_end); + rl_insert_text (word2); + + /* This is exactly correct since the text before this point has not + changed in length. */ + rl_point = w2_end; + + /* I think that does it. */ + rl_end_undo_group (); + free (word1); + free (word2); + + return 0; +} + +/* Transpose the characters at point. If point is at the end of the line, + then transpose the characters before point. */ +rl_transpose_chars (count, key) + int count, key; +{ + char dummy[2]; + + if (!count) + return 0; + + if (!rl_point || rl_end < 2) + { + ding (); + return -1; + } + + rl_begin_undo_group (); + + if (rl_point == rl_end) + { + --rl_point; + count = 1; + } + rl_point--; + + dummy[0] = the_line[rl_point]; + dummy[1] = '\0'; + + rl_delete_text (rl_point, rl_point + 1); + + rl_point += count; + if (rl_point > rl_end) + rl_point = rl_end; + else if (rl_point < 0) + rl_point = 0; + rl_insert_text (dummy); + + rl_end_undo_group (); + return 0; +} + +/* **************************************************************** */ +/* */ +/* Undo, and Undoing */ +/* */ +/* **************************************************************** */ + +/* The current undo list for THE_LINE. */ +UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL; + +/* Remember how to undo something. Concatenate some undos if that + seems right. */ +void +rl_add_undo (what, start, end, text) + enum undo_code what; + int start, end; + char *text; +{ + UNDO_LIST *temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST)); + temp->what = what; + temp->start = start; + temp->end = end; + temp->text = text; + temp->next = rl_undo_list; + rl_undo_list = temp; +} + +/* Free the existing undo list. */ +void +free_undo_list () +{ + while (rl_undo_list) + { + UNDO_LIST *release = rl_undo_list; + rl_undo_list = rl_undo_list->next; + + if (release->what == UNDO_DELETE) + free (release->text); + + free (release); + } + rl_undo_list = (UNDO_LIST *)NULL; +} + +/* Undo the next thing in the list. Return 0 if there + is nothing to undo, or non-zero if there was. */ +int +rl_do_undo () +{ + UNDO_LIST *release; + int waiting_for_begin = 0; + +undo_thing: + if (!rl_undo_list) + return (0); + + doing_an_undo = 1; + + switch (rl_undo_list->what) { + + /* Undoing deletes means inserting some text. */ + case UNDO_DELETE: + rl_point = rl_undo_list->start; + rl_insert_text (rl_undo_list->text); + free (rl_undo_list->text); + break; + + /* Undoing inserts means deleting some text. */ + case UNDO_INSERT: + rl_delete_text (rl_undo_list->start, rl_undo_list->end); + rl_point = rl_undo_list->start; + break; + + /* Undoing an END means undoing everything 'til we get to + a BEGIN. */ + case UNDO_END: + waiting_for_begin++; + break; + + /* Undoing a BEGIN means that we are done with this group. */ + case UNDO_BEGIN: + if (waiting_for_begin) + waiting_for_begin--; + else + ding (); + break; + } + + doing_an_undo = 0; + + release = rl_undo_list; + rl_undo_list = rl_undo_list->next; + free (release); + + if (waiting_for_begin) + goto undo_thing; + + return (1); +} + +/* Begin a group. Subsequent undos are undone as an atomic operation. */ +int +rl_begin_undo_group () +{ + rl_add_undo (UNDO_BEGIN, 0, 0, 0); + return 0; +} + +/* End an undo group started with rl_begin_undo_group (). */ +int +rl_end_undo_group () +{ + rl_add_undo (UNDO_END, 0, 0, 0); + return 0; +} + +/* Save an undo entry for the text from START to END. */ +rl_modifying (start, end) + int start, end; +{ + if (start > end) + { + int t = start; + start = end; + end = t; + } + + if (start != end) + { + char *temp = rl_copy_text (start, end); + rl_begin_undo_group (); + rl_add_undo (UNDO_DELETE, start, end, temp); + rl_add_undo (UNDO_INSERT, start, end, (char *)NULL); + rl_end_undo_group (); + } + return 0; +} + +/* Revert the current line to its previous state. */ +int +rl_revert_line (count, key) + int count, key; +{ + if (!rl_undo_list) + ding (); + else + { + while (rl_undo_list) + rl_do_undo (); + } + return 0; +} + +/* Do some undoing of things that were done. */ +int +rl_undo_command (count, key) + int count, key; +{ + if (count < 0) + return 0; /* Nothing to do. */ + + while (count) + { + if (rl_do_undo ()) + count--; + else + { + ding (); + break; + } + } + return 0; +} + +/* **************************************************************** */ +/* */ +/* History Utilities */ +/* */ +/* **************************************************************** */ + +/* We already have a history library, and that is what we use to control + the history features of readline. However, this is our local interface + to the history mechanism. */ + +/* While we are editing the history, this is the saved + version of the original line. */ +HIST_ENTRY *saved_line_for_history = (HIST_ENTRY *)NULL; + +/* Set the history pointer back to the last entry in the history. */ +static void +start_using_history () +{ + using_history (); + if (saved_line_for_history) + _rl_free_history_entry (saved_line_for_history); + + saved_line_for_history = (HIST_ENTRY *)NULL; +} + +/* Free the contents (and containing structure) of a HIST_ENTRY. */ +void +_rl_free_history_entry (entry) + HIST_ENTRY *entry; +{ + if (!entry) + return; + if (entry->line) + free (entry->line); + free (entry); +} + +/* Perhaps put back the current line if it has changed. */ +maybe_replace_line () +{ + HIST_ENTRY *temp = current_history (); + + /* If the current line has changed, save the changes. */ + if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list)) + { + temp = replace_history_entry (where_history (), the_line, rl_undo_list); + free (temp->line); + free (temp); + } + return 0; +} + +/* Put back the saved_line_for_history if there is one. */ +maybe_unsave_line () +{ + if (saved_line_for_history) + { + int line_len; + + line_len = strlen (saved_line_for_history->line); + + if (line_len >= rl_line_buffer_len) + rl_extend_line_buffer (line_len); + + strcpy (the_line, saved_line_for_history->line); + rl_undo_list = (UNDO_LIST *)saved_line_for_history->data; + _rl_free_history_entry (saved_line_for_history); + saved_line_for_history = (HIST_ENTRY *)NULL; + rl_end = rl_point = strlen (the_line); + } + else + ding (); + return 0; +} + +/* Save the current line in saved_line_for_history. */ +maybe_save_line () +{ + if (!saved_line_for_history) + { + saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); + saved_line_for_history->line = savestring (the_line); + saved_line_for_history->data = (char *)rl_undo_list; + } + return 0; +} + +/* **************************************************************** */ +/* */ +/* History Commands */ +/* */ +/* **************************************************************** */ + +/* Meta-< goes to the start of the history. */ +rl_beginning_of_history (count, key) + int count, key; +{ + return (rl_get_previous_history (1 + where_history ())); +} + +/* Meta-> goes to the end of the history. (The current line). */ +rl_end_of_history (count, key) + int count, key; +{ + maybe_replace_line (); + using_history (); + maybe_unsave_line (); + return 0; +} + +/* Move down to the next history line. */ +rl_get_next_history (count, key) + int count, key; +{ + HIST_ENTRY *temp = (HIST_ENTRY *)NULL; + + if (count < 0) + return (rl_get_previous_history (-count)); + + if (!count) + return 0; + + maybe_replace_line (); + + while (count) + { + temp = next_history (); + if (!temp) + break; + --count; + } + + if (!temp) + maybe_unsave_line (); + else + { + int line_len; + + line_len = strlen (temp->line); + + if (line_len >= rl_line_buffer_len) + rl_extend_line_buffer (line_len); + + strcpy (the_line, temp->line); + rl_undo_list = (UNDO_LIST *)temp->data; + rl_end = rl_point = strlen (the_line); +#if defined (VI_MODE) + if (rl_editing_mode == vi_mode) + rl_point = 0; +#endif /* VI_MODE */ + } + return 0; +} + +/* Get the previous item out of our interactive history, making it the current + line. If there is no previous history, just ding. */ +rl_get_previous_history (count, key) + int count, key; +{ + HIST_ENTRY *old_temp = (HIST_ENTRY *)NULL; + HIST_ENTRY *temp = (HIST_ENTRY *)NULL; + + if (count < 0) + return (rl_get_next_history (-count)); + + if (!count) + return 0; + + /* If we don't have a line saved, then save this one. */ + maybe_save_line (); + + /* If the current line has changed, save the changes. */ + maybe_replace_line (); + + while (count) + { + temp = previous_history (); + if (!temp) + break; + else + old_temp = temp; + --count; + } + + /* If there was a large argument, and we moved back to the start of the + history, that is not an error. So use the last value found. */ + if (!temp && old_temp) + temp = old_temp; + + if (!temp) + ding (); + else + { + int line_len; + + line_len = strlen (temp->line); + + if (line_len >= rl_line_buffer_len) + rl_extend_line_buffer (line_len); + + strcpy (the_line, temp->line); + rl_undo_list = (UNDO_LIST *)temp->data; + rl_end = rl_point = line_len; + +#if defined (VI_MODE) + if (rl_editing_mode == vi_mode) + rl_point = 0; +#endif /* VI_MODE */ + } + return 0; +} + +/* Make C be the next command to be executed. */ +rl_execute_next (c) + int c; +{ + rl_pending_input = c; + return 0; +} + +/* **************************************************************** */ +/* */ +/* The Mark and the Region. */ +/* */ +/* **************************************************************** */ + +/* Set the mark at POSITION. */ +rl_set_mark (position) + int position; +{ + if (position > rl_end) + return -1; + + rl_mark = position; + return 0; +} + +/* Exchange the position of mark and point. */ +rl_exchange_mark_and_point (count, key) + int count, key; +{ + if (rl_mark > rl_end) + rl_mark = -1; + + if (rl_mark == -1) + { + ding (); + return -1; + } + else + { + int temp = rl_point; + + rl_point = rl_mark; + rl_mark = temp; + } + return 0; +} + + +/* **************************************************************** */ +/* */ +/* Killing Mechanism */ +/* */ +/* **************************************************************** */ + +/* What we assume for a max number of kills. */ +#define DEFAULT_MAX_KILLS 10 + +/* The real variable to look at to find out when to flush kills. */ +int rl_max_kills = DEFAULT_MAX_KILLS; + +/* Where to store killed text. */ +char **rl_kill_ring = (char **)NULL; + +/* Where we are in the kill ring. */ +int rl_kill_index = 0; + +/* How many slots we have in the kill ring. */ +int rl_kill_ring_length = 0; + +/* How to say that you only want to save a certain amount + of kill material. */ +rl_set_retained_kills (num) + int num; +{ + return 0; +} + +/* 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 text is appended, otherwise prepended. If the + last command was not a kill command, then a new slot is made for + this kill. */ +rl_kill_text (from, to) + int from, to; +{ + int slot; + char *text; + + /* Is there anything to kill? */ + if (from == to) + { + last_command_was_kill++; + return 0; + } + + text = rl_copy_text (from, to); + + /* Delete the copied text from the line. */ + rl_delete_text (from, to); + + /* First, find the slot to work with. */ + if (!last_command_was_kill) + { + /* Get a new slot. */ + if (!rl_kill_ring) + { + /* If we don't have any defined, then make one. */ + rl_kill_ring = (char **) + xmalloc (((rl_kill_ring_length = 1) + 1) * sizeof (char *)); + rl_kill_ring[slot = 0] = (char *)NULL; + } + else + { + /* We have to add a new slot on the end, unless we have + exceeded the max limit for remembering kills. */ + slot = rl_kill_ring_length; + if (slot == rl_max_kills) + { + register int i; + free (rl_kill_ring[0]); + for (i = 0; i < slot; i++) + rl_kill_ring[i] = rl_kill_ring[i + 1]; + } + else + { + slot = rl_kill_ring_length += 1; + rl_kill_ring = (char **)xrealloc (rl_kill_ring, slot * sizeof (char *)); + } + rl_kill_ring[--slot] = (char *)NULL; + } + } + else + slot = rl_kill_ring_length - 1; + + /* If the last command was a kill, prepend or append. */ + if (last_command_was_kill && rl_editing_mode != vi_mode) + { + char *old = rl_kill_ring[slot]; + char *new = xmalloc (1 + strlen (old) + strlen (text)); + + if (from < to) + { + strcpy (new, old); + strcat (new, text); + } + else + { + strcpy (new, text); + strcat (new, old); + } + free (old); + free (text); + rl_kill_ring[slot] = new; + } + else + { + rl_kill_ring[slot] = text; + } + rl_kill_index = slot; + last_command_was_kill++; + return 0; +} + +/* Now REMEMBER! In order to do prepending or appending correctly, kill + commands always make rl_point's original position be the FROM argument, + and rl_point's extent be the TO argument. */ + +/* **************************************************************** */ +/* */ +/* Killing Commands */ +/* */ +/* **************************************************************** */ + +/* Delete the word at point, saving the text in the kill ring. */ +rl_kill_word (count, key) + int count, key; +{ + int orig_point = rl_point; + + if (count < 0) + return (rl_backward_kill_word (-count)); + else + { + rl_forward_word (count); + + if (rl_point != orig_point) + rl_kill_text (orig_point, rl_point); + + rl_point = orig_point; + } + return 0; +} + +/* Rubout the word before point, placing it on the kill ring. */ +rl_backward_kill_word (count, ignore) + int count, ignore; +{ + int orig_point = rl_point; + + if (count < 0) + return (rl_kill_word (-count)); + else + { + rl_backward_word (count); + + if (rl_point != orig_point) + rl_kill_text (orig_point, rl_point); + } + return 0; +} + +/* Kill from here to the end of the line. If DIRECTION is negative, kill + back to the line start instead. */ +rl_kill_line (direction, ignore) + int direction, ignore; +{ + int orig_point = rl_point; + + if (direction < 0) + return (rl_backward_kill_line (1)); + else + { + rl_end_of_line (); + if (orig_point != rl_point) + rl_kill_text (orig_point, rl_point); + rl_point = orig_point; + } + return 0; +} + +/* Kill backwards to the start of the line. If DIRECTION is negative, kill + forwards to the line end instead. */ +rl_backward_kill_line (direction, ignore) + int direction, ignore; +{ + int orig_point = rl_point; + + if (direction < 0) + return (rl_kill_line (1)); + else + { + if (!rl_point) + ding (); + else + { + rl_beg_of_line (); + rl_kill_text (orig_point, rl_point); + } + } + return 0; +} + +/* Kill the whole line, no matter where point is. */ +rl_kill_full_line (count, ignore) + int count, ignore; +{ + rl_begin_undo_group (); + rl_point = 0; + rl_kill_text (rl_point, rl_end); + rl_end_undo_group (); + return 0; +} + +/* Yank back the last killed text. This ignores arguments. */ +rl_yank (count, ignore) + int count, ignore; +{ + if (!rl_kill_ring) + { + rl_abort (); + return -1; + } + + rl_set_mark (rl_point); + rl_insert_text (rl_kill_ring[rl_kill_index]); + return 0; +} + +/* 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. */ +rl_yank_pop (count, key) + int count, key; +{ + int l; + + if (((rl_last_func != rl_yank_pop) && (rl_last_func != rl_yank)) || + !rl_kill_ring) + { + rl_abort (); + return -1; + } + + l = strlen (rl_kill_ring[rl_kill_index]); + if (((rl_point - l) >= 0) && + (strncmp (the_line + (rl_point - l), + rl_kill_ring[rl_kill_index], l) == 0)) + { + rl_delete_text ((rl_point - l), rl_point); + rl_point -= l; + rl_kill_index--; + if (rl_kill_index < 0) + rl_kill_index = rl_kill_ring_length - 1; + rl_yank (1, 0); + return 0; + } + else + { + rl_abort (); + return -1; + } +} + +/* Yank the COUNTth argument from the previous history line. */ +rl_yank_nth_arg (count, ignore) + int count, ignore; +{ + register HIST_ENTRY *entry = previous_history (); + char *arg; + + if (entry) + next_history (); + else + { + ding (); + return -1; + } + + arg = history_arg_extract (count, count, entry->line); + if (!arg || !*arg) + { + ding (); + return -1; + } + + rl_begin_undo_group (); + +#if defined (VI_MODE) + /* Vi mode always inserts a space before yanking the argument, and it + inserts it right *after* rl_point. */ + if (rl_editing_mode == vi_mode) + { + rl_vi_append_mode (); + rl_insert_text (" "); + } +#endif /* VI_MODE */ + + rl_insert_text (arg); + free (arg); + + rl_end_undo_group (); + return 0; +} + +/* Yank the last argument from the previous history line. This `knows' + how rl_yank_nth_arg treats a count of `$'. With an argument, this + behaves the same as rl_yank_nth_arg. */ +int +rl_yank_last_arg (count, key) + int count, key; +{ + if (rl_explicit_arg) + return (rl_yank_nth_arg (count, key)); + else + return (rl_yank_nth_arg ('$', key)); +} + +/* How to toggle back and forth between editing modes. */ +rl_vi_editing_mode (count, key) + int count, key; +{ +#if defined (VI_MODE) + rl_editing_mode = vi_mode; + rl_vi_insertion_mode (); + return 0; +#endif /* VI_MODE */ +} + +rl_emacs_editing_mode (count, key) + int count, key; +{ + rl_editing_mode = emacs_mode; + _rl_keymap = emacs_standard_keymap; + return 0; +} + + +/* **************************************************************** */ +/* */ +/* USG (System V) Support */ +/* */ +/* **************************************************************** */ + +int +rl_getc (stream) + FILE *stream; +{ + int result; + unsigned char c; + +#if defined (__GO32__) + if (isatty (0)) + return (getkey () & 0x7F); +#endif /* __GO32__ */ + + while (1) + { + result = read (fileno (stream), &c, sizeof (unsigned char)); + + if (result == sizeof (unsigned char)) + return (c); + + /* If zero characters are returned, then the file that we are + reading from is empty! Return EOF in that case. */ + if (result == 0) + return (EOF); + +#if defined (EWOULDBLOCK) + if (errno == EWOULDBLOCK) + { + int flags; + + if ((flags = fcntl (fileno (stream), F_GETFL, 0)) < 0) + return (EOF); + if (flags & O_NDELAY) + { + flags &= ~O_NDELAY; + fcntl (fileno (stream), F_SETFL, flags); + continue; + } + continue; + } +#endif /* EWOULDBLOCK */ + +#if defined (_POSIX_VERSION) && defined (EAGAIN) && defined (O_NONBLOCK) + if (errno == EAGAIN) + { + int flags; + + if ((flags = fcntl (fileno (stream), F_GETFL, 0)) < 0) + return (EOF); + if (flags & O_NONBLOCK) + { + flags &= ~O_NONBLOCK; + fcntl (fileno (stream), F_SETFL, flags); + continue; + } + } +#endif /* _POSIX_VERSION && EAGAIN && O_NONBLOCK */ + +#if !defined (__GO32__) + /* If the error that we received was SIGINT, then try again, + this is simply an interrupted system call to read (). + Otherwise, some error ocurred, also signifying EOF. */ + if (errno != EINTR) + return (EOF); +#endif /* !__GO32__ */ + } +} + +#if !defined (SHELL) +#ifdef savestring +#undef savestring +#endif +/* Backwards compatibilty, now that savestring has been removed from + all `public' readline header files. */ +char * +savestring (s) + char *s; +{ + return ((char *)strcpy (xmalloc (1 + (int)strlen (s)), (s))); +} +#endif + +/* Function equivalents for the macros defined in chartypes.h. */ +#undef uppercase_p +int +uppercase_p (c) + int c; +{ + return (isupper (c)); +} + +#undef lowercase_p +int +lowercase_p (c) + int c; +{ + return (islower (c)); +} + +#undef pure_alphabetic +int +pure_alphabetic (c) + int c; +{ + return (isupper (c) || islower (c)); +} + +#undef digit_p +int +digit_p (c) + int c; +{ + return (isdigit (c)); +} + +#undef to_lower +int +to_lower (c) + int c; +{ + return (isupper (c) ? tolower (c) : c); +} + +#undef to_upper +int +to_upper (c) + int c; +{ + return (islower (c) ? toupper (c) : c); +} + +#undef digit_value +int +digit_value (c) + int c; +{ + return (isdigit (c) ? c - '0' : c); +} + +#if defined (STATIC_MALLOC) + +/* **************************************************************** */ +/* */ +/* xmalloc and xrealloc () */ +/* */ +/* **************************************************************** */ + +static void memory_error_and_abort (); + +static char * +xmalloc (bytes) + int bytes; +{ + char *temp = (char *)malloc (bytes); + + if (!temp) + memory_error_and_abort (); + return (temp); +} + +static char * +xrealloc (pointer, bytes) + char *pointer; + int bytes; +{ + char *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 /* STATIC_MALLOC */ + + +/* **************************************************************** */ +/* */ +/* Testing Readline */ +/* */ +/* **************************************************************** */ + +#if defined (TEST) + +main () +{ + HIST_ENTRY **history_list (); + char *temp = (char *)NULL; + char *prompt = "readline% "; + int done = 0; + + while (!done) + { + temp = readline (prompt); + + /* Test for EOF. */ + if (!temp) + exit (1); + + /* If there is anything on the line, print it and remember it. */ + if (*temp) + { + fprintf (stderr, "%s\r\n", temp); + add_history (temp); + } + + /* Check for `command' that we handle. */ + if (strcmp (temp, "quit") == 0) + done = 1; + + if (strcmp (temp, "list") == 0) + { + HIST_ENTRY **list = history_list (); + register int i; + if (list) + { + for (i = 0; list[i]; i++) + { + fprintf (stderr, "%d: %s\r\n", i, list[i]->line); + free (list[i]->line); + } + free (list); + } + } + free (temp); + } +} + +#endif /* TEST */ + + +/* + * Local variables: + * compile-command: "gcc -g -traditional -I. -I.. -DTEST -o readline readline.c keymaps.o funmap.o history.o -ltermcap" + * end: + */ diff --git a/readline.h b/readline.h new file mode 100644 index 0000000..b397177 --- /dev/null +++ b/readline.h @@ -0,0 +1,289 @@ +/* Readline.h -- the names of functions callable from within readline. */ + +/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library 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 1, or + (at your option) any later version. + + The GNU Readline Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#if !defined (_READLINE_H_) +#define _READLINE_H_ + +#if defined (READLINE_LIBRARY) +# include "keymaps.h" +# include "tilde.h" +#else +# include +# include +#endif + +/* The functions for manipulating the text of the line within readline. +Most of these functions are bound to keys by default. */ +extern int + rl_tilde_expand (), + rl_beg_of_line (), rl_backward (), rl_delete (), rl_end_of_line (), + rl_forward (), ding (), rl_backward (), rl_newline (), rl_kill_line (), + rl_clear_screen (), rl_get_next_history (), rl_get_previous_history (), + rl_quoted_insert (), rl_reverse_search_history (), rl_transpose_chars (), + rl_unix_line_discard (), rl_quoted_insert (), rl_unix_word_rubout (), + rl_yank (), rl_rubout (), rl_backward_word (), rl_kill_word (), + rl_forward_word (), rl_tab_insert (), rl_yank_pop (), rl_yank_nth_arg (), + rl_backward_kill_word (), rl_backward_kill_line (), rl_transpose_words (), + rl_complete (), rl_possible_completions (), rl_insert_completions (), + rl_do_lowercase_version (), rl_kill_full_line (), + rl_digit_argument (), rl_universal_argument (), rl_abort (), + rl_undo_command (), rl_revert_line (), rl_beginning_of_history (), + rl_end_of_history (), rl_forward_search_history (), rl_insert (), + rl_upcase_word (), rl_downcase_word (), rl_capitalize_word (), + rl_restart_output (), rl_re_read_init_file (), rl_dump_functions (), + rl_delete_horizontal_space (), rl_history_search_forward (), + rl_history_search_backward (), rl_tty_status (), rl_yank_last_arg (); + +/* `Public' utility functions. */ +extern int rl_insert_text (), rl_delete_text (), rl_kill_text (); +extern int rl_complete_internal (); +extern int rl_expand_prompt (); +extern int rl_initialize (); +extern int rl_set_signals (), rl_clear_signals (); +extern int rl_init_argument (), rl_digit_argument (); +extern int rl_read_key (), rl_getc (), rl_stuff_char (); +extern int maybe_save_line (), maybe_unsave_line (), maybe_replace_line (); +extern int rl_modifying (); + +extern int rl_begin_undo_group (), rl_end_undo_group (); +extern void rl_add_undo (), free_undo_list (); +extern int rl_do_undo (); + +/* Not available unless readline is compiled -DPAREN_MATCHING. */ +extern int rl_insert_close (); + +/* These are *both* defined even when VI_MODE is not. */ +extern int rl_vi_editing_mode (), rl_emacs_editing_mode (); + +/* Non incremental history searching. */ +extern int + rl_noninc_forward_search (), rl_noninc_reverse_search (), + rl_noninc_forward_search_again (), rl_noninc_reverse_search_again (); + +/* Things for vi mode. Not available unless readline is compiled -DVI_MODE. */ +extern int rl_vi_check (), rl_vi_textmod_command (); +extern int + rl_vi_redo (), rl_vi_tilde_expand (), + rl_vi_movement_mode (), rl_vi_insertion_mode (), rl_vi_arg_digit (), + rl_vi_prev_word (), rl_vi_next_word (), rl_vi_char_search (), + rl_vi_eof_maybe (), rl_vi_append_mode (), rl_vi_put (), + rl_vi_append_eol (), rl_vi_insert_beg (), rl_vi_delete (), rl_vi_comment (), + rl_vi_first_print (), rl_vi_fword (), rl_vi_fWord (), rl_vi_bword (), + rl_vi_bWord (), rl_vi_eword (), rl_vi_eWord (), rl_vi_end_word (), + rl_vi_change_case (), rl_vi_match (), rl_vi_bracktype (), + rl_vi_change_char (), rl_vi_yank_arg (), rl_vi_search (), + rl_vi_search_again (), rl_vi_subst (), rl_vi_overstrike (), + rl_vi_overstrike_delete (), rl_vi_replace(), rl_vi_column (), + rl_vi_delete_to (), rl_vi_change_to (), rl_vi_yank_to (), + rl_vi_complete (), rl_vi_fetch_history (); + +/* Keyboard macro commands. */ +extern int rl_start_kbd_macro (), rl_end_kbd_macro (); +extern int rl_call_last_kbd_macro (); + +extern int rl_arrow_keys(), rl_refresh_line (); + +/* Maintaining the state of undo. We remember individual deletes and inserts + on a chain of things to do. */ + +/* The actions that undo knows how to undo. Notice that UNDO_DELETE means + to insert some text, and UNDO_INSERT means to delete some text. I.e., + the code tells undo what to undo, not how to undo it. */ +enum undo_code { UNDO_DELETE, UNDO_INSERT, UNDO_BEGIN, UNDO_END }; + +/* What an element of THE_UNDO_LIST looks like. */ +typedef struct undo_list { + struct undo_list *next; + int start, end; /* Where the change took place. */ + char *text; /* The text to insert, if undoing a delete. */ + enum undo_code what; /* Delete, Insert, Begin, End. */ +} UNDO_LIST; + +/* The current undo list for RL_LINE_BUFFER. */ +extern UNDO_LIST *rl_undo_list; + +/* The data structure for mapping textual names to code addresses. */ +typedef struct { + char *name; + Function *function; +} FUNMAP; + +extern FUNMAP **funmap; + +/* **************************************************************** */ +/* */ +/* Well Published Variables */ +/* */ +/* **************************************************************** */ + +/* The name of the calling program. You should initialize this to + whatever was in argv[0]. It is used when parsing conditionals. */ +extern char *rl_readline_name; + +/* The line buffer that is in use. */ +extern char *rl_line_buffer; + +/* The location of point, and end. */ +extern int rl_point, rl_end; + +/* The name of the terminal to use. */ +extern char *rl_terminal_name; + +/* The input and output streams. */ +extern FILE *rl_instream, *rl_outstream; + +/* The basic list of characters that signal a break between words for the + completer routine. The initial contents of this variable is what + breaks words in the shell, i.e. "n\"\\'`@$>". */ +extern char *rl_basic_word_break_characters; + +/* The list of characters that signal a break between words for + rl_complete_internal. The default list is the contents of + rl_basic_word_break_characters. */ +extern char *rl_completer_word_break_characters; + +/* List of characters which can be used to quote a substring of the line. + Completion occurs on the entire substring, and within the substring + rl_completer_word_break_characters are treated as any other character, + unless they also appear within this list. */ +extern char *rl_completer_quote_characters; + +/* List of characters that are word break characters, but should be left + in TEXT when it is passed to the completion function. The shell uses + this to help determine what kind of completing to do. */ +extern char *rl_special_prefixes; + +/* Pointer to the generator function for completion_matches (). + NULL means to use filename_entry_function (), the default filename + completer. */ +extern Function *rl_completion_entry_function; + +/* If rl_ignore_some_completions_function is non-NULL it is the address + of a function to call after all of the possible matches have been + generated, but before the actual completion is done to the input line. + The function is called with one argument; a NULL terminated array + of (char *). If your function removes any of the elements, they + must be free()'ed. */ +extern Function *rl_ignore_some_completions_function; + +/* Pointer to alternative function to create matches. + Function is called with TEXT, START, and END. + START and END are indices in RL_LINE_BUFFER saying what the boundaries + of TEXT are. + If this function exists and returns NULL then call the value of + rl_completion_entry_function to try to match, otherwise use the + array of strings returned. */ +extern CPPFunction *rl_attempted_completion_function; + +/* If non-zero, then this is the address of a function to call just + before readline_internal () prints the first prompt. */ +extern Function *rl_startup_hook; + +/* If non-zero, then this is the address of a function to call when + completing on a directory name. The function is called with + the address of a string (the current directory name) as an arg. */ +extern Function *rl_directory_completion_hook; + +/* Backwards compatibility with previous versions of readline. */ +#define rl_symbolic_link_hook rl_directory_completion_hook + +/* The address of a function to call periodically while Readline is + awaiting character input, or NULL, for no event handling. */ +extern Function *rl_event_hook; + +/* Non-zero means that modified history lines are preceded + with an asterisk. */ +extern int rl_show_star; + +/* Non-zero means that the results of the matches are to be treated + as filenames. This is ALWAYS zero on entry, and can only be changed + within a completion entry finder function. */ +extern int rl_filename_completion_desired; + +/* Non-zero means that the results of the matches are to be quoted using + double quotes (or an application-specific quoting mechanism) if the + filename contains any characters in rl_word_break_chars. This is + ALWAYS non-zero on entry, and can only be changed within a completion + entry finder function. */ +extern int rl_filename_quoting_desired; + +/* Non-zero means to suppress normal filename completion after the + user-specified completion function has been called. */ +extern int rl_attempted_completion_over; + +/* **************************************************************** */ +/* */ +/* Well Published Functions */ +/* */ +/* **************************************************************** */ + +/* Read a line of input. Prompt with PROMPT. A NULL PROMPT means none. */ +extern char *readline (); + +/* These functions are from complete.c. */ +/* Return an array of strings which are the result of repeatadly calling + FUNC with TEXT. */ +extern char **completion_matches (); +extern char *username_completion_function (); +extern char *filename_completion_function (); + +/* These functions are from bind.c. */ +/* rl_add_defun (char *name, Function *function, int key) + Add NAME to the list of named functions. Make FUNCTION + be the function that gets called. + If KEY is not -1, then bind it. */ +extern int rl_add_defun (); +extern int rl_bind_key (), rl_bind_key_in_map (); +extern int rl_unbind_key (), rl_unbind_key_in_map (); +extern int rl_set_key (); +extern int rl_macro_bind (), rl_generic_bind (), rl_variable_bind (); +extern int rl_translate_keyseq (); +extern Function *rl_named_function (), *rl_function_of_keyseq (); +extern int rl_parse_and_bind (); +extern Keymap rl_get_keymap (), rl_get_keymap_by_name (); +extern void rl_set_keymap (); +extern char **rl_invoking_keyseqs (), **rl_invoking_keyseqs_in_map (); +extern void rl_function_dumper (); +extern int rl_read_init_file (); + +/* Functions in funmap.c */ +extern void rl_list_funmap_names (); +extern void rl_initialize_funmap (); + +/* Functions in display.c */ +extern void rl_redisplay (); +extern int rl_message (), rl_clear_message (); +extern int rl_reset_line_state (); +extern int rl_character_len (); +extern int rl_show_char (); +extern int crlf (), rl_on_new_line (); +extern int rl_forced_update_display (); + +/* Definitions available for use by readline clients. */ +#define RL_PROMPT_START_IGNORE '\001' +#define RL_PROMPT_END_IGNORE '\002' + +#if !defined (savestring) +extern char *savestring (); /* XXX backwards compatibility */ +#endif + +#endif /* _READLINE_H_ */ diff --git a/rlconf.h b/rlconf.h new file mode 100644 index 0000000..0035b93 --- /dev/null +++ b/rlconf.h @@ -0,0 +1,57 @@ +/* rlconf.h -- readline configuration definitions */ + +/* Copyright (C) 1994 Free Software Foundation, Inc. + + This file contains the Readline Library (the Library), a set of + routines for providing Emacs style line input to programs that ask + for it. + + The Library 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 1, or (at your option) + any later version. + + The Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#if !defined (_RLCONF_H_) +#define _RLCONF_H_ + +/* Define this if you want the vi-mode editing available. */ +#define VI_MODE + +/* Define this to get an indication of file type when listing completions. */ +#define VISIBLE_STATS + +/* If defined, readline shows opening parens and braces when closing + paren or brace entered. */ +/* #define PAREN_MATCHING */ + +/* This definition is needed by readline.c, rltty.c, and signals.c. */ +/* If on, then readline handles signals in a way that doesn't screw. */ +#define HANDLE_SIGNALS + +/* Ugly but working hack for binding prefix meta. */ +#define PREFIX_META_HACK + +/* The final, last-ditch effort file name for an init file. */ +#define DEFAULT_INPUTRC "~/.inputrc" + +/* If defined, expand tabs to spaces. */ +#define DISPLAY_TABS + +/* If defined, use the terminal escape sequence to move the cursor forward + over a character when updating the line rather than rewriting it. */ +/* #define HACK_TERMCAP_MOTION */ + +/* The string inserted by the vi-mode `insert comment' command. */ +#define VI_COMMENT_BEGIN_DEFAULT "#" + +#endif /* _RLCONF_H_ */ diff --git a/rldefs.h b/rldefs.h new file mode 100644 index 0000000..249c927 --- /dev/null +++ b/rldefs.h @@ -0,0 +1,207 @@ +/* rldefs.h -- an attempt to isolate some of the system-specific defines + for readline. This should be included after any files that define + system-specific constants like _POSIX_VERSION or USG. */ + +/* Copyright (C) 1987,1989 Free Software Foundation, Inc. + + This file contains the Readline Library (the Library), a set of + routines for providing Emacs style line input to programs that ask + for it. + + The Library 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 1, or (at your option) + any later version. + + The Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#if !defined (_RLDEFS_H) +#define _RLDEFS_H + +#if defined (HAVE_CONFIG_H) +# include "config.h" +#endif + +#if !defined (PRAGMA_ALLOCA) +# include "memalloc.h" +#endif + +#define NEW_TTY_DRIVER +#define HAVE_BSD_SIGNALS +/* #define USE_XON_XOFF */ + +#if defined (__linux__) || defined (HAVE_TERMCAP_H) +# include +#endif /* __linux__ || HAVE_TERMCAP_H */ + +/* Some USG machines have BSD signal handling (sigblock, sigsetmask, etc.) */ +#if defined (USG) && !defined (hpux) +# undef HAVE_BSD_SIGNALS +#endif + +/* System V machines use termio. */ +#if !defined (_POSIX_VERSION) +# if defined (USG) || defined (hpux) || defined (Xenix) || defined (sgi) || \ + defined (DGUX) || defined (HAVE_TERMIO_H) +# undef NEW_TTY_DRIVER +# define TERMIO_TTY_DRIVER +# include +# if !defined (TCOON) +# define TCOON 1 +# endif +# endif /* USG || hpux || Xenix || sgi || DUGX || HAVE_TERMIO_H */ +#endif /* !_POSIX_VERSION */ + +/* Posix systems use termios and the Posix signal functions. */ +#if defined (_POSIX_VERSION) +# if !defined (TERMIOS_MISSING) +# undef NEW_TTY_DRIVER +# define TERMIOS_TTY_DRIVER +# include +# endif /* !TERMIOS_MISSING */ +# define HAVE_POSIX_SIGNALS +# if !defined (O_NDELAY) +# define O_NDELAY O_NONBLOCK /* Posix-style non-blocking i/o */ +# endif /* O_NDELAY */ +#endif /* _POSIX_VERSION */ + +/* System V.3 machines have the old 4.1 BSD `reliable' signal interface. */ +#if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS) +# if defined (USGr3) && !defined (XENIX_22) +# if !defined (HAVE_USG_SIGHOLD) +# define HAVE_USG_SIGHOLD +# endif /* !HAVE_USG_SIGHOLD */ +# endif /* USGr3 && !XENIX_22 */ +#endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */ + +/* Other (BSD) machines use sgtty. */ +#if defined (NEW_TTY_DRIVER) +# include +#endif + +/* Define _POSIX_VDISABLE if we are not using the `new' tty driver and + it is not already defined. It is used both to determine if a + special character is disabled and to disable certain special + characters. Posix systems should set to 0, USG systems to -1. */ +#if !defined (NEW_TTY_DRIVER) && !defined (_POSIX_VDISABLE) +# if defined (_POSIX_VERSION) +# define _POSIX_VDISABLE 0 +# else /* !_POSIX_VERSION */ +# define _POSIX_VDISABLE -1 +# endif /* !_POSIX_VERSION */ +#endif /* !NEW_TTY_DRIVER && !_POSIX_VDISABLE */ + +#if !defined (SHELL) && (defined (_POSIX_VERSION) || defined (USGr3)) +# if !defined (HAVE_DIRENT_H) +# define HAVE_DIRENT_H +# endif /* !HAVE_DIRENT_H */ +#endif /* !SHELL && (_POSIX_VERSION || USGr3) */ + +#if defined (HAVE_DIRENT_H) +# include +# define D_NAMLEN(d) strlen ((d)->d_name) +#else /* !HAVE_DIRENT_H */ +# define D_NAMLEN(d) ((d)->d_namlen) +# if defined (USG) +# if defined (Xenix) +# include +# else /* !Xenix (but USG...) */ +# include "ndir.h" +# endif /* !Xenix */ +# else /* !USG */ +# include +# endif /* !USG */ +# if !defined (dirent) +# define dirent direct +# endif /* !dirent */ +#endif /* !HAVE_DIRENT_H */ + +#if defined (USG) && defined (TIOCGWINSZ) && !defined (Linux) +# if defined (HAVE_SYS_STREAM_H) +# include +# endif /* HAVE_SYS_STREAM_H */ +# if defined (HAVE_SYS_PTEM_H) +# include +# endif /* HAVE_SYS_PTEM_H */ +# if defined (HAVE_SYS_PTE_H) +# include +# endif /* HAVE_SYS_PTE_H */ +#endif /* USG && TIOCGWINSZ && !Linux */ + +/* Posix macro to check file in statbuf for directory-ness. + This requires that be included before this test. */ +#if defined (S_IFDIR) && !defined (S_ISDIR) +# define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR) +#endif + +/* Decide which flavor of the header file describing the C library + string functions to include and include it. */ + +#if defined (USG) || defined (NeXT) +# if !defined (HAVE_STRING_H) +# define HAVE_STRING_H +# endif /* !HAVE_STRING_H */ +#endif /* USG || NeXT */ + +#if defined (HAVE_STRING_H) +# include +#else /* !HAVE_STRING_H */ +# include +#endif /* !HAVE_STRING_H */ + +#if !defined (strchr) && !defined (__STDC__) +extern char *strchr (), *strrchr (); +#endif /* !strchr && !__STDC__ */ + +#if defined (HAVE_VARARGS_H) +# include +#endif /* HAVE_VARARGS_H */ + +/* This is needed to include support for TIOCGWINSZ and window resizing. */ +#if defined (OSF1) || defined (BSD386) || defined (NetBSD) || \ + defined (__BSD_4_4__) || defined (FreeBSD) || defined (_386BSD) || \ + defined (AIX) +# define GWINSZ_IN_SYS_IOCTL +#endif + +#if !defined (emacs_mode) +# define no_mode -1 +# define vi_mode 0 +# define emacs_mode 1 +#endif + +/* If you cast map[key].function to type (Keymap) on a Cray, + the compiler takes the value of map[key].function and + divides it by 4 to convert between pointer types (pointers + to functions and pointers to structs are different sizes). + This is not what is wanted. */ +#if defined (CRAY) +# define FUNCTION_TO_KEYMAP(map, key) (Keymap)((int)map[key].function) +# define KEYMAP_TO_FUNCTION(data) (Function *)((int)(data)) +#else +# define FUNCTION_TO_KEYMAP(map, key) (Keymap)(map[key].function) +# define KEYMAP_TO_FUNCTION(data) (Function *)(data) +#endif + +#ifndef savestring +extern char *xmalloc (); +#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x)) +#endif + +/* Possible values for _rl_bell_preference. */ +#define NO_BELL 0 +#define AUDIBLE_BELL 1 +#define VISIBLE_BELL 2 + +/* CONFIGURATION SECTION */ +#include "rlconf.h" + +#endif /* !_RLDEFS_H */ diff --git a/rltty.c b/rltty.c new file mode 100644 index 0000000..ebb8413 --- /dev/null +++ b/rltty.c @@ -0,0 +1,697 @@ +/* rltty.c -- functions to prepare and restore the terminal for readline's + use. */ + +/* Copyright (C) 1992 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library 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 1, or + (at your option) any later version. + + The GNU Readline Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define READLINE_LIBRARY + +#include +#include +#include +#include + +#if defined (HAVE_UNISTD_H) +# include +#endif /* HAVE_UNISTD_H */ + +#include "rldefs.h" +#include "readline.h" + +#if !defined (errno) +extern int errno; +#endif /* !errno */ + +extern int readline_echoing_p; +extern int _rl_eof_char; + +#if defined (__GO32__) +# include +# undef HANDLE_SIGNALS +#endif /* __GO32__ */ + +static int output_was_flushed; + +/* **************************************************************** */ +/* */ +/* Signal Management */ +/* */ +/* **************************************************************** */ + +#if defined (HAVE_POSIX_SIGNALS) +static sigset_t sigint_set, sigint_oset; +#else /* !HAVE_POSIX_SIGNALS */ +# if defined (HAVE_BSD_SIGNALS) +static int sigint_oldmask; +# endif /* HAVE_BSD_SIGNALS */ +#endif /* !HAVE_POSIX_SIGNALS */ + +static int sigint_blocked = 0; + +/* Cause SIGINT to not be delivered until the corresponding call to + release_sigint(). */ +static void +block_sigint () +{ + if (sigint_blocked) + return; + +#if defined (HAVE_POSIX_SIGNALS) + sigemptyset (&sigint_set); + sigemptyset (&sigint_oset); + sigaddset (&sigint_set, SIGINT); + sigprocmask (SIG_BLOCK, &sigint_set, &sigint_oset); +#else /* !HAVE_POSIX_SIGNALS */ +# if defined (HAVE_BSD_SIGNALS) + sigint_oldmask = sigblock (sigmask (SIGINT)); +# else /* !HAVE_BSD_SIGNALS */ +# if defined (HAVE_USG_SIGHOLD) + sighold (SIGINT); +# endif /* HAVE_USG_SIGHOLD */ +# endif /* !HAVE_BSD_SIGNALS */ +#endif /* !HAVE_POSIX_SIGNALS */ + sigint_blocked = 1; +} + +/* Allow SIGINT to be delivered. */ +static void +release_sigint () +{ + if (!sigint_blocked) + return; + +#if defined (HAVE_POSIX_SIGNALS) + sigprocmask (SIG_SETMASK, &sigint_oset, (sigset_t *)NULL); +#else +# if defined (HAVE_BSD_SIGNALS) + sigsetmask (sigint_oldmask); +# else /* !HAVE_BSD_SIGNALS */ +# if defined (HAVE_USG_SIGHOLD) + sigrelse (SIGINT); +# endif /* HAVE_USG_SIGHOLD */ +# endif /* !HAVE_BSD_SIGNALS */ +#endif /* !HAVE_POSIX_SIGNALS */ + + sigint_blocked = 0; +} + +/* **************************************************************** */ +/* */ +/* Controlling the Meta Key and Keypad */ +/* */ +/* **************************************************************** */ + +extern int term_has_meta; +extern char *term_mm; +extern char *term_mo; + +extern char *term_ks; +extern char *term_ke; + +static int +outchar (c) + int c; +{ + return putc (c, rl_outstream); +} + +/* Turn on/off the meta key depending on ON. */ +static void +control_meta_key (on) + int on; +{ + if (term_has_meta) + { + if (on && term_mm) + tputs (term_mm, 1, outchar); + else if (!on && term_mo) + tputs (term_mo, 1, outchar); + } +} + +static void +control_keypad (on) + int on; +{ + if (on && term_ks) + tputs (term_ks, 1, outchar); + else if (!on && term_ke) + tputs (term_ke, 1, outchar); +} + +/* **************************************************************** */ +/* */ +/* Saving and Restoring the TTY */ +/* */ +/* **************************************************************** */ + +/* Non-zero means that the terminal is in a prepped state. */ +static int terminal_prepped = 0; + +/* If non-zero, means that this process has called tcflow(fd, TCOOFF) + and output is suspended. */ +#if defined (__ksr1__) +static int ksrflow = 0; +#endif +#if defined (NEW_TTY_DRIVER) + +/* Values for the `flags' field of a struct bsdtty. This tells which + elements of the struct bsdtty have been fetched from the system and + are valid. */ +#define SGTTY_SET 0x01 +#define LFLAG_SET 0x02 +#define TCHARS_SET 0x04 +#define LTCHARS_SET 0x08 + +struct bsdtty { + struct sgttyb sgttyb; /* Basic BSD tty driver information. */ + int lflag; /* Local mode flags, like LPASS8. */ +#if defined (TIOCGETC) + struct tchars tchars; /* Terminal special characters, including ^S and ^Q. */ +#endif +#if defined (TIOCGLTC) + struct ltchars ltchars; /* 4.2 BSD editing characters */ +#endif + int flags; /* Bitmap saying which parts of the struct are valid. */ +}; + +#define TIOTYPE struct bsdtty + +static TIOTYPE otio; + +static int +get_tty_settings (tty, tiop) + int tty; + TIOTYPE *tiop; +{ +#if !defined (SHELL) && defined (TIOCGWINSZ) + struct winsize w; + + if (ioctl (tty, TIOCGWINSZ, &w) == 0) + (void) ioctl (tty, TIOCSWINSZ, &w); +#endif + + tiop->flags = tiop->lflag = 0; + + ioctl (tty, TIOCGETP, &(tiop->sgttyb)); + tiop->flags |= SGTTY_SET; + +#if defined (TIOCLGET) + ioctl (tty, TIOCLGET, &(tiop->lflag)); + tiop->flags |= LFLAG_SET; +#endif + +#if defined (TIOCGETC) + ioctl (tty, TIOCGETC, &(tiop->tchars)); + tiop->flags |= TCHARS_SET; +#endif + +#if defined (TIOCGLTC) + ioctl (tty, TIOCGLTC, &(tiop->ltchars)); + tiop->flags |= LTCHARS_SET; +#endif + + return 0; +} + +set_tty_settings (tty, tiop) + int tty; + TIOTYPE *tiop; +{ + if (tiop->flags & SGTTY_SET) + { + ioctl (tty, TIOCSETN, &(tiop->sgttyb)); + tiop->flags &= ~SGTTY_SET; + } + readline_echoing_p = 1; + +#if defined (TIOCLSET) + if (tiop->flags & LFLAG_SET) + { + ioctl (tty, TIOCLSET, &(tiop->lflag)); + tiop->flags &= ~LFLAG_SET; + } +#endif + +#if defined (TIOCSETC) + if (tiop->flags & TCHARS_SET) + { + ioctl (tty, TIOCSETC, &(tiop->tchars)); + tiop->flags &= ~TCHARS_SET; + } +#endif + +#if defined (TIOCSLTC) + if (tiop->flags & LTCHARS_SET) + { + ioctl (tty, TIOCSLTC, &(tiop->ltchars)); + tiop->flags &= ~LTCHARS_SET; + } +#endif + + return 0; +} + +static void +prepare_terminal_settings (meta_flag, otio, tiop) + int meta_flag; + TIOTYPE otio, *tiop; +{ +#if !defined (__GO32__) + readline_echoing_p = (otio.sgttyb.sg_flags & ECHO); + + /* Copy the original settings to the structure we're going to use for + our settings. */ + tiop->sgttyb = otio.sgttyb; + tiop->lflag = otio.lflag; +#if defined (TIOCGETC) + tiop->tchars = otio.tchars; +#endif +#if defined (TIOCGLTC) + tiop->ltchars = otio.ltchars; +#endif + tiop->flags = otio.flags; + + /* First, the basic settings to put us into character-at-a-time, no-echo + input mode. */ + tiop->sgttyb.sg_flags &= ~(ECHO | CRMOD); + tiop->sgttyb.sg_flags |= CBREAK; + + /* If this terminal doesn't care how the 8th bit is used, then we can + use it for the meta-key. If only one of even or odd parity is + specified, then the terminal is using parity, and we cannot. */ +#if !defined (ANYP) +# define ANYP (EVENP | ODDP) +#endif + if (((otio.sgttyb.sg_flags & ANYP) == ANYP) || + ((otio.sgttyb.sg_flags & ANYP) == 0)) + { + tiop->sgttyb.sg_flags |= ANYP; + + /* Hack on local mode flags if we can. */ +#if defined (TIOCLGET) +# if defined (LPASS8) + tiop->lflag |= LPASS8; +# endif /* LPASS8 */ +#endif /* TIOCLGET */ + } + +#if defined (TIOCGETC) +# if defined (USE_XON_XOFF) + /* Get rid of terminal output start and stop characters. */ + tiop->tchars.t_stopc = -1; /* C-s */ + tiop->tchars.t_startc = -1; /* C-q */ + + /* If there is an XON character, bind it to restart the output. */ + if (otio.tchars.t_startc != -1) + rl_bind_key (otio.tchars.t_startc, rl_restart_output); +# endif /* USE_XON_XOFF */ + + /* If there is an EOF char, bind _rl_eof_char to it. */ + if (otio.tchars.t_eofc != -1) + _rl_eof_char = otio.tchars.t_eofc; + +# if defined (NO_KILL_INTR) + /* Get rid of terminal-generated SIGQUIT and SIGINT. */ + tiop->tchars.t_quitc = -1; /* C-\ */ + tiop->tchars.t_intrc = -1; /* C-c */ +# endif /* NO_KILL_INTR */ +#endif /* TIOCGETC */ + +#if defined (TIOCGLTC) + /* Make the interrupt keys go away. Just enough to make people happy. */ + tiop->ltchars.t_dsuspc = -1; /* C-y */ + tiop->ltchars.t_lnextc = -1; /* C-v */ +#endif /* TIOCGLTC */ +#endif /* !__GO32__ */ +} + +#else /* !defined (NEW_TTY_DRIVER) */ + +#if !defined (VMIN) +# define VMIN VEOF +#endif + +#if !defined (VTIME) +# define VTIME VEOL +#endif + +#if defined (TERMIOS_TTY_DRIVER) +# define TIOTYPE struct termios +# define DRAIN_OUTPUT(fd) tcdrain (fd) +# define GETATTR(tty, tiop) (tcgetattr (tty, tiop)) +# define SETATTR(tty, tiop) (tcsetattr (tty, TCSANOW, tiop)) +#else +# define TIOTYPE struct termio +# define DRAIN_OUTPUT(fd) +# define GETATTR(tty, tiop) (ioctl (tty, TCGETA, tiop)) +# define SETATTR(tty, tiop) (ioctl (tty, TCSETA, tiop)) +#endif /* !TERMIOS_TTY_DRIVER */ + +static TIOTYPE otio; + +#if defined (FLUSHO) +# define OUTPUT_BEING_FLUSHED(tp) (tp->c_lflag & FLUSHO) +#else +# define OUTPUT_BEING_FLUSHED(tp) 0 +#endif + +static int +get_tty_settings (tty, tiop) + int tty; + TIOTYPE *tiop; +{ +#if !defined (SHELL) && defined (TIOCGWINSZ) + struct winsize w; + + if (ioctl (tty, TIOCGWINSZ, &w) == 0) + (void) ioctl (tty, TIOCSWINSZ, &w); +#endif + + /* Keep looping if output is being flushed after a ^O (or whatever + the flush character is). */ + while (GETATTR (tty, tiop) < 0 || OUTPUT_BEING_FLUSHED (tiop)) + { + if (OUTPUT_BEING_FLUSHED (tiop)) + continue; + if (errno != EINTR) + return -1; + errno = 0; + } + return 0; +} + +static int +set_tty_settings (tty, tiop) + int tty; + TIOTYPE *tiop; +{ + while (SETATTR (tty, tiop) < 0) + { + if (errno != EINTR) + return -1; + errno = 0; + } + +#if 0 + +#if defined (TERMIOS_TTY_DRIVER) +# if defined (__ksr1__) + if (ksrflow) + { + ksrflow = 0; + tcflow (tty, TCOON); + } +# else /* !ksr1 */ + tcflow (tty, TCOON); /* Simulate a ^Q. */ +# endif /* !ksr1 */ +#else + ioctl (tty, TCXONC, 1); /* Simulate a ^Q. */ +#endif /* !TERMIOS_TTY_DRIVER */ + +#endif + + return 0; +} + +static void +prepare_terminal_settings (meta_flag, otio, tiop) + int meta_flag; + TIOTYPE otio, *tiop; +{ + readline_echoing_p = (otio.c_lflag & ECHO); + + tiop->c_lflag &= ~(ICANON | ECHO); + + if ((unsigned char) otio.c_cc[VEOF] != (unsigned char) _POSIX_VDISABLE) + _rl_eof_char = otio.c_cc[VEOF]; + +#if defined (USE_XON_XOFF) +#if defined (IXANY) + tiop->c_iflag &= ~(IXON | IXOFF | IXANY); +#else + /* `strict' Posix systems do not define IXANY. */ + tiop->c_iflag &= ~(IXON | IXOFF); +#endif /* IXANY */ +#endif /* USE_XON_XOFF */ + + /* Only turn this off if we are using all 8 bits. */ + if (((tiop->c_cflag & CSIZE) == CS8) || meta_flag) + tiop->c_iflag &= ~(ISTRIP | INPCK); + + /* Make sure we differentiate between CR and NL on input. */ + tiop->c_iflag &= ~(ICRNL | INLCR); + +#if !defined (HANDLE_SIGNALS) + tiop->c_lflag &= ~ISIG; +#else + tiop->c_lflag |= ISIG; +#endif + + tiop->c_cc[VMIN] = 1; + tiop->c_cc[VTIME] = 0; + + if (tiop->c_lflag & FLUSHO) + { + output_was_flushed = 1; + tiop->c_lflag &= ~FLUSHO; + otio.c_lflag &= ~FLUSHO; + } + + /* Turn off characters that we need on Posix systems with job control, + just to be sure. This includes ^Y and ^V. This should not really + be necessary. */ +#if defined (TERMIOS_TTY_DRIVER) && defined (_POSIX_VDISABLE) + +#if defined (VLNEXT) + tiop->c_cc[VLNEXT] = _POSIX_VDISABLE; +#endif + +#if defined (VDSUSP) + tiop->c_cc[VDSUSP] = _POSIX_VDISABLE; +#endif + +#endif /* TERMIOS_TTY_DRIVER && _POSIX_VDISABLE */ +} +#endif /* NEW_TTY_DRIVER */ + +/* Put the terminal in CBREAK mode so that we can detect key presses. */ +void +rl_prep_terminal (meta_flag) + int meta_flag; +{ +#if !defined (__GO32__) + int tty = fileno (rl_instream); + TIOTYPE tio; + + if (terminal_prepped) + return; + + /* Try to keep this function from being INTerrupted. */ + block_sigint (); + + if (get_tty_settings (tty, &tio) < 0) + { + release_sigint (); + return; + } + + otio = tio; + + prepare_terminal_settings (meta_flag, otio, &tio); + + if (set_tty_settings (tty, &tio) < 0) + { + release_sigint (); + return; + } + + if (output_was_flushed) + output_was_flushed = 0; + + control_meta_key (1); + control_keypad (1); + fflush (rl_outstream); + terminal_prepped = 1; + + release_sigint (); +#endif /* !__GO32__ */ +} + +/* Restore the terminal's normal settings and modes. */ +void +rl_deprep_terminal () +{ +#if !defined (__GO32__) + int tty = fileno (rl_instream); + + if (!terminal_prepped) + return; + + /* Try to keep this function from being INTerrupted. */ + block_sigint (); + + if (set_tty_settings (tty, &otio) < 0) + { + release_sigint (); + return; + } + + control_meta_key (0); + control_keypad (0); + fflush (rl_outstream); + terminal_prepped = 0; + + release_sigint (); +#endif /* !__GO32__ */ +} + +/* **************************************************************** */ +/* */ +/* Bogus Flow Control */ +/* */ +/* **************************************************************** */ + +rl_restart_output (count, key) + int count, key; +{ + int fildes = fileno (rl_outstream); +#if defined (TIOCSTART) +#if defined (apollo) + ioctl (&fildes, TIOCSTART, 0); +#else + ioctl (fildes, TIOCSTART, 0); +#endif /* apollo */ + +#else /* !TIOCSTART */ +# if defined (TERMIOS_TTY_DRIVER) +# if defined (__ksr1__) + if (ksrflow) + { + ksrflow = 0; + tcflow (fildes, TCOON); + } +# else /* !ksr1 */ + tcflow (fildes, TCOON); /* Simulate a ^Q. */ +# endif /* !ksr1 */ +# else /* !TERMIOS_TTY_DRIVER */ +# if defined (TCXONC) + ioctl (fildes, TCXONC, TCOON); +# endif /* TCXONC */ +# endif /* !TERMIOS_TTY_DRIVER */ +#endif /* !TIOCSTART */ + + return 0; +} + +rl_stop_output (count, key) + int count, key; +{ + int fildes = fileno (rl_instream); + +#if defined (TIOCSTOP) +# if defined (apollo) + ioctl (&fildes, TIOCSTOP, 0); +# else + ioctl (fildes, TIOCSTOP, 0); +# endif /* apollo */ +#else /* !TIOCSTOP */ +# if defined (TERMIOS_TTY_DRIVER) +# if defined (__ksr1__) + ksrflow = 1; +# endif /* ksr1 */ + tcflow (fildes, TCOOFF); +# else +# if defined (TCXONC) + ioctl (fildes, TCXONC, TCOON); +# endif /* TCXONC */ +# endif /* !TERMIOS_TTY_DRIVER */ +#endif /* !TIOCSTOP */ + + return 0; +} + +/* **************************************************************** */ +/* */ +/* Default Key Bindings */ +/* */ +/* **************************************************************** */ +void +rltty_set_default_bindings (kmap) + Keymap kmap; +{ + TIOTYPE ttybuff; + int tty = fileno (rl_instream); + +#if defined (NEW_TTY_DRIVER) + +#define SET_SPECIAL(sc, func) \ + do \ + { \ + int ic; \ + ic = sc; \ + if (ic != -1 && kmap[ic].type == ISFUNC) \ + kmap[ic].function = func; \ + } \ + while (0) + + if (get_tty_settings (tty, &ttybuff) == 0) + { + if (ttybuff.flags & SGTTY_SET) + { + SET_SPECIAL (ttybuff.sgttyb.sg_erase, rl_rubout); + SET_SPECIAL (ttybuff.sgttyb.sg_kill, rl_unix_line_discard); + } + +# if defined (TIOCGLTC) + if (ttybuff.flags & LTCHARS_SET) + { + SET_SPECIAL (ttybuff.ltchars.t_werasc, rl_unix_word_rubout); + SET_SPECIAL (ttybuff.ltchars.t_lnextc, rl_quoted_insert); + } +# endif /* TIOCGLTC */ + } + +#else /* !NEW_TTY_DRIVER */ + +#define SET_SPECIAL(sc, func) \ + do \ + { \ + unsigned char uc; \ + uc = ttybuff.c_cc[sc]; \ + if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC) \ + kmap[uc].function = func; \ + } \ + while (0) + + if (get_tty_settings (tty, &ttybuff) == 0) + { + SET_SPECIAL (VERASE, rl_rubout); + SET_SPECIAL (VKILL, rl_unix_line_discard); + +# if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER) + SET_SPECIAL (VLNEXT, rl_quoted_insert); +# endif /* VLNEXT && TERMIOS_TTY_DRIVER */ + +# if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER) + SET_SPECIAL (VWERASE, rl_unix_word_rubout); +# endif /* VWERASE && TERMIOS_TTY_DRIVER */ + } +#endif /* !NEW_TTY_DRIVER */ +} diff --git a/search.c b/search.c new file mode 100644 index 0000000..a2b8c5e --- /dev/null +++ b/search.c @@ -0,0 +1,367 @@ +/* search.c - code for non-incremental searching in emacs and vi modes. */ + +/* Copyright (C) 1992 Free Software Foundation, Inc. + + This file is part of the Readline Library (the Library), a set of + routines for providing Emacs style line input to programs that ask + for it. + + The Library 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 1, or (at your option) + any later version. + + The Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define READLINE_LIBRARY + +#include +#include + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#include "memalloc.h" +#include "rldefs.h" +#include "readline.h" +#include "history.h" + +#define STREQ(a, b) (((a)[0] == (b)[0]) && (strcmp ((a), (b)) == 0)) +#define STREQN(a, b, n) (((a)[0] == (b)[0]) && (strncmp ((a), (b), (n)) == 0)) + +#define abs(x) (((x) > 0) ? (x) : -(x)) + +extern char *xmalloc (), *xrealloc (); + +/* Variables imported from readline.c */ +extern int rl_point, rl_end, rl_line_buffer_len; +extern Keymap _rl_keymap; +extern char *rl_prompt; +extern char *rl_line_buffer; +extern HIST_ENTRY *saved_line_for_history; +extern Function *rl_last_func; + +/* Functions imported from the rest of the library. */ +extern int _rl_free_history_entry (); + +static char *noninc_search_string = (char *) NULL; +static int noninc_history_pos = 0; +static char *prev_line_found = (char *) NULL; + +/* Search the history list for STRING starting at absolute history position + POS. If STRING begins with `^', the search must match STRING at the + beginning of a history line, otherwise a full substring match is performed + for STRING. DIR < 0 means to search backwards through the history list, + DIR >= 0 means to search forward. */ +static int +noninc_search_from_pos (string, pos, dir) + char *string; + int pos, dir; +{ + int ret, old; + + old = where_history (); + history_set_pos (pos); + + if (*string == '^') + ret = history_search_prefix (string + 1, dir); + else + ret = history_search (string, dir); + + if (ret != -1) + ret = where_history (); + + history_set_pos (old); + return (ret); +} + +/* Search for a line in the history containing STRING. If DIR is < 0, the + search is backwards through previous entries, else through subsequent + entries. */ +static void +noninc_dosearch (string, dir) + char *string; + int dir; +{ + int oldpos, pos; + HIST_ENTRY *entry; + + if (string == 0 || *string == 0 || noninc_history_pos < 0) + { + ding (); + return; + } + + pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir); + if (pos == -1) + { + /* Search failed, current history position unchanged. */ + maybe_unsave_line (); + rl_clear_message (); + rl_point = 0; + ding (); + return; + } + + noninc_history_pos = pos; + + oldpos = where_history (); + history_set_pos (noninc_history_pos); + entry = current_history (); + history_set_pos (oldpos); + + { + int line_len; + + line_len = strlen (entry->line); + if (line_len >= rl_line_buffer_len) + rl_extend_line_buffer (line_len); + strcpy (rl_line_buffer, entry->line); + } + + rl_undo_list = (UNDO_LIST *)entry->data; + rl_end = strlen (rl_line_buffer); + rl_point = 0; + rl_clear_message (); + + if (saved_line_for_history) + _rl_free_history_entry (saved_line_for_history); + saved_line_for_history = (HIST_ENTRY *)NULL; +} + +/* Search non-interactively through the history list. DIR < 0 means to + search backwards through the history of previous commands; otherwise + the search is for commands subsequent to the current position in the + history list. PCHAR is the character to use for prompting when reading + the search string; if not specified (0), it defaults to `:'. */ +static void +noninc_search (dir, pchar) + int dir; + int pchar; +{ + int saved_point, c, pmtlen; + char *p; + + maybe_save_line (); + saved_point = rl_point; + + /* Use the line buffer to read the search string. */ + rl_line_buffer[0] = 0; + rl_end = rl_point = 0; + + /* XXX - this needs fixing to work with the prompt expansion stuff - XXX */ + pmtlen = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0; + p = xmalloc (2 + pmtlen); + if (pmtlen) + strcpy (p, rl_prompt); + p[pmtlen] = pchar ? pchar : ':'; + p[pmtlen + 1] = '\0'; + + rl_message (p, 0, 0); + free (p); + + /* Read the search string. */ + while (c = rl_read_key ()) + { + switch (c) + { + case CTRL('H'): + case RUBOUT: + if (rl_point == 0) + { + maybe_unsave_line (); + rl_clear_message (); + rl_point = saved_point; + return; + } + rl_rubout (1); + break; + + case CTRL('W'): + rl_unix_word_rubout (); + break; + + case CTRL('U'): + rl_unix_line_discard (); + break; + + case RETURN: + case NEWLINE: + goto dosearch; + /* NOTREACHED */ + break; + + case CTRL('C'): + case CTRL('G'): + maybe_unsave_line (); + rl_clear_message (); + rl_point = saved_point; + ding (); + return; + + default: + rl_insert (1, c); + break; + } + rl_redisplay (); + } + + dosearch: + /* If rl_point == 0, we want to re-use the previous search string and + start from the saved history position. If there's no previous search + string, punt. */ + if (rl_point == 0) + { + if (!noninc_search_string) + { + ding (); + return; + } + } + else + { + /* We want to start the search from the current history position. */ + noninc_history_pos = where_history (); + if (noninc_search_string) + free (noninc_search_string); + noninc_search_string = savestring (rl_line_buffer); + } + + noninc_dosearch (noninc_search_string, dir); +} + +/* Search forward through the history list for a string. If the vi-mode + code calls this, KEY will be `?'. */ +rl_noninc_forward_search (count, key) + int count, key; +{ + if (key == '?') + noninc_search (1, '?'); + else + noninc_search (1, 0); + return 0; +} + +/* Reverse search the history list for a string. If the vi-mode code + calls this, KEY will be `/'. */ +rl_noninc_reverse_search (count, key) + int count, key; +{ + if (key == '/') + noninc_search (-1, '/'); + else + noninc_search (-1, 0); + return 0; +} + +/* Search forward through the history list for the last string searched + for. If there is no saved search string, abort. */ +rl_noninc_forward_search_again (count, key) + int count, key; +{ + if (!noninc_search_string) + { + ding (); + return (-1); + } + noninc_dosearch (noninc_search_string, 1); + return 0; +} + +/* Reverse search in the history list for the last string searched + for. If there is no saved search string, abort. */ +rl_noninc_reverse_search_again (count, key) + int count, key; +{ + if (!noninc_search_string) + { + ding (); + return (-1); + } + noninc_dosearch (noninc_search_string, -1); + return 0; +} + +static int +rl_history_search_internal (count, direction) + int count, direction; +{ + HIST_ENTRY *temp, *old_temp; + int line_len; + + maybe_save_line (); + + temp = old_temp = (HIST_ENTRY *)NULL; + while (count) + { + temp = (direction < 0) ? previous_history () : next_history (); + if (!temp) + break; + if (STREQN (rl_line_buffer, temp->line, rl_point)) + { + /* Don't find multiple instances of the same line. */ + if (prev_line_found && STREQ (prev_line_found, temp->line)) + continue; + if (direction < 0) + old_temp = temp; + prev_line_found = temp->line; + count--; + } + } + + if (!temp) + { + if (direction < 0 && old_temp) + temp = old_temp; + else + { + maybe_unsave_line (); + ding (); + return 1; + } + } + + line_len = strlen (temp->line); + if (line_len >= rl_line_buffer_len) + rl_extend_line_buffer (line_len); + strcpy (rl_line_buffer, temp->line); + rl_undo_list = (UNDO_LIST *)temp->data; + rl_end = line_len; + return 0; +} + +/* Search forward in the history for the string of characters + from the start of the line to rl_point. This is a non-incremental + search. */ +int +rl_history_search_forward (count, ignore) + int count, ignore; +{ + if (count == 0) + return (0); + if (rl_last_func != rl_history_search_forward) + prev_line_found = (char *)NULL; + return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1)); +} + +/* Search backward through the history for the string of characters + from the start of the line to rl_point. This is a non-incremental + search. */ +int +rl_history_search_backward (count, ignore) + int count, ignore; +{ + if (count == 0) + return (0); + if (rl_last_func != rl_history_search_backward) + prev_line_found = (char *)NULL; + return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1)); +} diff --git a/signals.c b/signals.c new file mode 100644 index 0000000..a9fda5c --- /dev/null +++ b/signals.c @@ -0,0 +1,303 @@ +/* signals.c -- signal handling support for readline. */ + +/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library 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 1, or + (at your option) any later version. + + The GNU Readline Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define READLINE_LIBRARY + +#include +#include +#include +#if !defined (NO_SYS_FILE) +# include +#endif /* !NO_SYS_FILE */ +#include + +#if defined (HAVE_UNISTD_H) +# include +#endif /* HAVE_UNISTD_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#include +/* Not all systems declare ERRNO in errno.h... and some systems #define it! */ +#if !defined (errno) +extern int errno; +#endif /* !errno */ + +#include "posixstat.h" + +/* System-specific feature definitions and include files. */ +#include "rldefs.h" + +#if defined (GWINSZ_IN_SYS_IOCTL) +# include +#endif /* GWINSZ_IN_SYS_IOCTL */ + +/* Some standard library routines. */ +#include "readline.h" +#include "history.h" + +static void cr (); + +extern int readline_echoing_p; +extern int rl_pending_input; +extern char *term_cr; + +extern int _rl_meta_flag; + +extern int _rl_output_character_function (); + +extern void free_undo_list (); + +#if defined (VOID_SIGHANDLER) +# define sighandler void +#else +# define sighandler int +#endif /* VOID_SIGHANDLER */ + +/* This typedef is equivalant to the one for Function; it allows us + to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */ +typedef sighandler SigHandler (); + +#if defined (__GO32__) +# undef HANDLE_SIGNALS +#endif /* __GO32__ */ + +#if defined (STATIC_MALLOC) +static char *xmalloc (), *xrealloc (); +#else +extern char *xmalloc (), *xrealloc (); +#endif /* STATIC_MALLOC */ + + +/* **************************************************************** */ +/* */ +/* Signal Handling */ +/* */ +/* **************************************************************** */ + +#if defined (SIGWINCH) +static SigHandler *old_sigwinch = (SigHandler *)NULL; + +static sighandler +rl_handle_sigwinch (sig) + int sig; +{ + if (readline_echoing_p) + { + _rl_set_screen_size (fileno (rl_instream), 1); + + cr (); /* was crlf () */ + rl_forced_update_display (); + } + + if (old_sigwinch && + old_sigwinch != (SigHandler *)SIG_IGN && + old_sigwinch != (SigHandler *)SIG_DFL) + (*old_sigwinch) (sig); +#if !defined (VOID_SIGHANDLER) + return (0); +#endif /* VOID_SIGHANDLER */ +} +#endif /* SIGWINCH */ + +#if defined (HANDLE_SIGNALS) +/* Interrupt handling. */ +static SigHandler + *old_int = (SigHandler *)NULL, + *old_alrm = (SigHandler *)NULL; +#if !defined (SHELL) +static SigHandler + *old_tstp = (SigHandler *)NULL, + *old_ttou = (SigHandler *)NULL, + *old_ttin = (SigHandler *)NULL, + *old_cont = (SigHandler *)NULL; +#endif /* !SHELL */ + +/* Handle an interrupt character. */ +static sighandler +rl_signal_handler (sig) + int sig; +{ +#if defined (HAVE_POSIX_SIGNALS) + sigset_t set; +#else /* !HAVE_POSIX_SIGNALS */ +# if defined (HAVE_BSD_SIGNALS) + long omask; +# endif /* HAVE_BSD_SIGNALS */ +#endif /* !HAVE_POSIX_SIGNALS */ + +#if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS) + /* Since the signal will not be blocked while we are in the signal + handler, ignore it until rl_clear_signals resets the catcher. */ + if (sig == SIGINT) + signal (sig, SIG_IGN); +#endif /* !HAVE_BSD_SIGNALS */ + + switch (sig) + { + case SIGINT: + { + register HIST_ENTRY *entry; + + free_undo_list (); + + entry = current_history (); + if (entry) + entry->data = (char *)NULL; + } + _rl_kill_kbd_macro (); + rl_clear_message (); + rl_init_argument (); + +#if defined (SIGTSTP) + case SIGTSTP: + case SIGTTOU: + case SIGTTIN: +#endif /* SIGTSTP */ + case SIGALRM: + rl_clean_up_for_exit (); + rl_deprep_terminal (); + rl_clear_signals (); + rl_pending_input = 0; + +#if defined (HAVE_POSIX_SIGNALS) + sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set); + sigdelset (&set, sig); +#else /* !HAVE_POSIX_SIGNALS */ +# if defined (HAVE_BSD_SIGNALS) + omask = sigblock (0); +# endif /* HAVE_BSD_SIGNALS */ +#endif /* !HAVE_POSIX_SIGNALS */ + + kill (getpid (), sig); + + /* Let the signal that we just sent through. */ +#if defined (HAVE_POSIX_SIGNALS) + sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL); +#else /* !HAVE_POSIX_SIGNALS */ +# if defined (HAVE_BSD_SIGNALS) + sigsetmask (omask & ~(sigmask (sig))); +# endif /* HAVE_BSD_SIGNALS */ +#endif /* !HAVE_POSIX_SIGNALS */ + + rl_prep_terminal (_rl_meta_flag); + rl_set_signals (); + } + +#if !defined (VOID_SIGHANDLER) + return (0); +#endif /* !VOID_SIGHANDLER */ +} + +#if defined (HAVE_POSIX_SIGNALS) +static SigHandler * +rl_set_sighandler (sig, handler) + int sig; + SigHandler *handler; +{ + struct sigaction act, oact; + + act.sa_handler = handler; + act.sa_flags = 0; + sigemptyset (&act.sa_mask); + sigemptyset (&oact.sa_mask); + sigaction (sig, &act, &oact); + return (oact.sa_handler); +} + +#else /* !HAVE_POSIX_SIGNALS */ +# define rl_set_sighandler(sig, handler) (SigHandler *)signal (sig, handler) +#endif /* !HAVE_POSIX_SIGNALS */ + +rl_set_signals () +{ + old_int = (SigHandler *)rl_set_sighandler (SIGINT, rl_signal_handler); + if (old_int == (SigHandler *)SIG_IGN) + signal (SIGINT, SIG_IGN); + + old_alrm = (SigHandler *)rl_set_sighandler (SIGALRM, rl_signal_handler); + if (old_alrm == (SigHandler *)SIG_IGN) + signal (SIGALRM, SIG_IGN); + +#if !defined (SHELL) + +#if defined (SIGTSTP) + old_tstp = (SigHandler *)rl_set_sighandler (SIGTSTP, rl_signal_handler); + if (old_tstp == (SigHandler *)SIG_IGN) + signal (SIGTSTP, SIG_IGN); +#endif /* SIGTSTP */ +#if defined (SIGTTOU) + old_ttou = (SigHandler *)rl_set_sighandler (SIGTTOU, rl_signal_handler); + old_ttin = (SigHandler *)rl_set_sighandler (SIGTTIN, rl_signal_handler); + + if (old_tstp == (SigHandler *)SIG_IGN) + { + signal (SIGTTOU, SIG_IGN); + signal (SIGTTIN, SIG_IGN); + } +#endif /* SIGTTOU */ + +#endif /* !SHELL */ + +#if defined (SIGWINCH) + old_sigwinch = + (SigHandler *) rl_set_sighandler (SIGWINCH, rl_handle_sigwinch); +#endif /* SIGWINCH */ + return 0; +} + +rl_clear_signals () +{ + rl_set_sighandler (SIGINT, old_int); + rl_set_sighandler (SIGALRM, old_alrm); + +#if !defined (SHELL) + +#if defined (SIGTSTP) + signal (SIGTSTP, old_tstp); +#endif + +#if defined (SIGTTOU) + signal (SIGTTOU, old_ttou); + signal (SIGTTIN, old_ttin); +#endif /* SIGTTOU */ + +#endif /* !SHELL */ + +#if defined (SIGWINCH) + signal (SIGWINCH, old_sigwinch); +#endif + + return 0; +} + +/* Move to the start of the current line. */ +static void +cr () +{ + if (term_cr) + tputs (term_cr, 1, _rl_output_character_function); +} +#endif /* HANDLE_SIGNALS */ diff --git a/stamp-config b/stamp-config new file mode 100644 index 0000000..e69de29 diff --git a/tilde.c b/tilde.c new file mode 100644 index 0000000..89168a0 --- /dev/null +++ b/tilde.c @@ -0,0 +1,386 @@ +/* tilde.c -- Tilde expansion code (~/foo := $HOME/foo). */ + +/* Copyright (C) 1988,1989 Free Software Foundation, Inc. + + This file is part of GNU Readline, a library for reading lines + of text with interactive input and history editing. + + Readline 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 1, or (at your option) any + later version. + + Readline 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 Readline; see the file COPYING. If not, write to the Free + Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "memalloc.h" + +#if defined (HAVE_STRING_H) +# include +#else /* !HAVE_STRING_H */ +# include +#endif /* !HAVE_STRING_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#include "tilde.h" +#include + +#if defined (USG) && !defined (HAVE_GETPW_DECLS) +extern struct passwd *getpwuid (), *getpwnam (); +#endif /* USG && !defined (HAVE_GETPW_DECLS) */ + +#if !defined (savestring) +extern char *xmalloc (); +# ifndef strcpy +extern char *strcpy (); +# endif +#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x)) +#endif /* !savestring */ + +#if !defined (NULL) +# if defined (__STDC__) +# define NULL ((void *) 0) +# else +# define NULL 0x0 +# endif /* !__STDC__ */ +#endif /* !NULL */ + +#if defined (TEST) || defined (STATIC_MALLOC) +static char *xmalloc (), *xrealloc (); +#else +extern char *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. */ +CPFunction *tilde_expansion_failure_hook = (CPFunction *)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 ? savestring (filename) : (char *)NULL; + + if (dirname && *dirname == '~') + { + char *temp_name; + if (!dirname[1] || dirname[1] == '/') + { + /* Prepend $HOME to the rest of the string. */ + char *temp_home = (char *)getenv ("HOME"); + + /* If there is no HOME variable, look up the directory in + the password database. */ + if (!temp_home) + { + struct passwd *entry; + + entry = getpwuid (getuid ()); + if (entry) + temp_home = entry->pw_dir; + } + + temp_name = xmalloc (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 = temp_name; + } + else + { + char u_name[257]; + struct passwd *user_entry; + char *username; + int i, c; + + username = u_name; + for (i = 1; c = dirname[i]; i++) + { + if (c == '/') + break; + else + username[i - 1] = c; + } + username[i - 1] = '\0'; + + if (!(user_entry = 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 = xmalloc (1 + strlen (expansion) + + strlen (&dirname[i])); + strcpy (temp_name, expansion); + strcat (temp_name, &dirname[i]); + free (expansion); + free (dirname); + dirname = temp_name; + } + } + /* We shouldn't report errors. */ + } + else + { + temp_name = xmalloc (1 + strlen (user_entry->pw_dir) + + strlen (&dirname[i])); + strcpy (temp_name, user_entry->pw_dir); + strcat (temp_name, &dirname[i]); + free (dirname); + dirname = 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 char * +xmalloc (bytes) + int bytes; +{ + char *temp = (char *)malloc (bytes); + + if (!temp) + memory_error_and_abort (); + return (temp); +} + +static char * +xrealloc (pointer, bytes) + char *pointer; + int bytes; +{ + char *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 (); +} + +/* + * Local variables: + * compile-command: "gcc -g -DTEST -o tilde tilde.c" + * end: + */ +#endif /* TEST */ diff --git a/tilde.h b/tilde.h new file mode 100644 index 0000000..726d081 --- /dev/null +++ b/tilde.h @@ -0,0 +1,38 @@ +/* tilde.h: Externally available variables and function in libtilde.a. */ + +#if !defined (__TILDE_H__) +# define __TILDE_H__ + +/* Function pointers can be declared as (Function *)foo. */ +#if !defined (__FUNCTION_DEF) +# define __FUNCTION_DEF +typedef int Function (); +typedef void VFunction (); +typedef char *CPFunction (); +typedef char **CPPFunction (); +#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 CPFunction *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 (); + +#endif /* __TILDE_H__ */ diff --git a/vi_keymap.c b/vi_keymap.c new file mode 100644 index 0000000..b8b3123 --- /dev/null +++ b/vi_keymap.c @@ -0,0 +1,877 @@ +/* vi_keymap.c -- the keymap for vi_mode in readline (). */ + +/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library 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 1, or + (at your option) any later version. + + The GNU Readline Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#if !defined (BUFSIZ) +#include +#endif /* !BUFSIZ */ + +#include "readline.h" + +#if 0 +extern KEYMAP_ENTRY_ARRAY vi_escape_keymap; +#endif + +/* The keymap arrays for handling vi mode. */ +KEYMAP_ENTRY_ARRAY vi_movement_keymap = { + /* The regular control keys come first. */ + { ISFUNC, (Function *)0x0 }, /* Control-@ */ + { ISFUNC, (Function *)0x0 }, /* Control-a */ + { ISFUNC, (Function *)0x0 }, /* Control-b */ + { ISFUNC, (Function *)0x0 }, /* Control-c */ + { ISFUNC, rl_vi_eof_maybe }, /* Control-d */ + { ISFUNC, rl_emacs_editing_mode }, /* Control-e */ + { ISFUNC, (Function *)0x0 }, /* Control-f */ + { ISFUNC, rl_abort }, /* Control-g */ + { ISFUNC, rl_backward }, /* Control-h */ + { ISFUNC, (Function *)0x0 }, /* Control-i */ + { ISFUNC, rl_newline }, /* Control-j */ + { ISFUNC, rl_kill_line }, /* Control-k */ + { ISFUNC, rl_clear_screen }, /* Control-l */ + { ISFUNC, rl_newline }, /* Control-m */ + { ISFUNC, rl_get_next_history }, /* Control-n */ + { ISFUNC, (Function *)0x0 }, /* Control-o */ + { ISFUNC, rl_get_previous_history }, /* Control-p */ + { ISFUNC, rl_quoted_insert }, /* Control-q */ + { ISFUNC, rl_reverse_search_history }, /* Control-r */ + { ISFUNC, rl_forward_search_history }, /* Control-s */ + { ISFUNC, rl_transpose_chars }, /* Control-t */ + { ISFUNC, rl_unix_line_discard }, /* Control-u */ + { ISFUNC, rl_quoted_insert }, /* Control-v */ + { ISFUNC, rl_unix_word_rubout }, /* Control-w */ + { ISFUNC, (Function *)0x0 }, /* Control-x */ + { ISFUNC, rl_yank }, /* Control-y */ + { ISFUNC, (Function *)0x0 }, /* Control-z */ + + { ISFUNC, (Function *)0x0 }, /* Control-[ */ /* vi_escape_keymap */ + { ISFUNC, (Function *)0x0 }, /* Control-\ */ + { ISFUNC, (Function *)0x0 }, /* Control-] */ + { ISFUNC, (Function *)0x0 }, /* Control-^ */ + { ISFUNC, rl_undo_command }, /* Control-_ */ + + /* The start of printing characters. */ + { ISFUNC, rl_forward }, /* SPACE */ + { ISFUNC, (Function *)0x0 }, /* ! */ + { ISFUNC, (Function *)0x0 }, /* " */ + { ISFUNC, rl_vi_comment }, /* # */ + { ISFUNC, rl_end_of_line }, /* $ */ + { ISFUNC, rl_vi_match }, /* % */ + { ISFUNC, rl_vi_tilde_expand }, /* & */ + { ISFUNC, (Function *)0x0 }, /* ' */ + { ISFUNC, (Function *)0x0 }, /* ( */ + { ISFUNC, (Function *)0x0 }, /* ) */ + { ISFUNC, rl_vi_complete }, /* * */ + { ISFUNC, rl_get_next_history}, /* + */ + { ISFUNC, rl_vi_char_search }, /* , */ + { ISFUNC, rl_get_previous_history }, /* - */ + { ISFUNC, rl_vi_redo }, /* . */ + { ISFUNC, rl_vi_search }, /* / */ + + /* Regular digits. */ + { ISFUNC, rl_beg_of_line }, /* 0 */ + { ISFUNC, rl_vi_arg_digit }, /* 1 */ + { ISFUNC, rl_vi_arg_digit }, /* 2 */ + { ISFUNC, rl_vi_arg_digit }, /* 3 */ + { ISFUNC, rl_vi_arg_digit }, /* 4 */ + { ISFUNC, rl_vi_arg_digit }, /* 5 */ + { ISFUNC, rl_vi_arg_digit }, /* 6 */ + { ISFUNC, rl_vi_arg_digit }, /* 7 */ + { ISFUNC, rl_vi_arg_digit }, /* 8 */ + { ISFUNC, rl_vi_arg_digit }, /* 9 */ + + /* A little more punctuation. */ + { ISFUNC, (Function *)0x0 }, /* : */ + { ISFUNC, rl_vi_char_search }, /* ; */ + { ISFUNC, (Function *)0x0 }, /* < */ + { ISFUNC, rl_vi_complete }, /* = */ + { ISFUNC, (Function *)0x0 }, /* > */ + { ISFUNC, rl_vi_search }, /* ? */ + { ISFUNC, (Function *)0x0 }, /* @ */ + + /* Uppercase alphabet. */ + { ISFUNC, rl_vi_append_eol }, /* A */ + { ISFUNC, rl_vi_prev_word}, /* B */ + { ISFUNC, rl_vi_change_to }, /* C */ + { ISFUNC, rl_vi_delete_to }, /* D */ + { ISFUNC, rl_vi_end_word }, /* E */ + { ISFUNC, rl_vi_char_search }, /* F */ + { ISFUNC, rl_vi_fetch_history }, /* G */ + { ISFUNC, (Function *)0x0 }, /* H */ + { ISFUNC, rl_vi_insert_beg }, /* I */ + { ISFUNC, (Function *)0x0 }, /* J */ + { ISFUNC, (Function *)0x0 }, /* K */ + { ISFUNC, (Function *)0x0 }, /* L */ + { ISFUNC, (Function *)0x0 }, /* M */ + { ISFUNC, rl_vi_search_again }, /* N */ + { ISFUNC, (Function *)0x0 }, /* O */ + { ISFUNC, rl_vi_put }, /* P */ + { ISFUNC, (Function *)0x0 }, /* Q */ + { ISFUNC, rl_vi_replace }, /* R */ + { ISFUNC, rl_vi_subst }, /* S */ + { ISFUNC, rl_vi_char_search }, /* T */ + { ISFUNC, rl_revert_line }, /* U */ + { ISFUNC, (Function *)0x0 }, /* V */ + { ISFUNC, rl_vi_next_word }, /* W */ + { ISFUNC, rl_rubout }, /* X */ + { ISFUNC, rl_vi_yank_to }, /* Y */ + { ISFUNC, (Function *)0x0 }, /* Z */ + + /* Some more punctuation. */ + { ISFUNC, (Function *)0x0 }, /* [ */ + { ISFUNC, rl_vi_complete }, /* \ */ + { ISFUNC, (Function *)0x0 }, /* ] */ + { ISFUNC, rl_vi_first_print }, /* ^ */ + { ISFUNC, rl_vi_yank_arg }, /* _ */ + { ISFUNC, (Function *)0x0 }, /* ` */ + + /* Lowercase alphabet. */ + { ISFUNC, rl_vi_append_mode }, /* a */ + { ISFUNC, rl_vi_prev_word }, /* b */ + { ISFUNC, rl_vi_change_to }, /* c */ + { ISFUNC, rl_vi_delete_to }, /* d */ + { ISFUNC, rl_vi_end_word }, /* e */ + { ISFUNC, rl_vi_char_search }, /* f */ + { ISFUNC, (Function *)0x0 }, /* g */ + { ISFUNC, rl_backward }, /* h */ + { ISFUNC, rl_vi_insertion_mode }, /* i */ + { ISFUNC, rl_get_next_history }, /* j */ + { ISFUNC, rl_get_previous_history }, /* k */ + { ISFUNC, rl_forward }, /* l */ + { ISFUNC, (Function *)0x0 }, /* m */ + { ISFUNC, rl_vi_search_again }, /* n */ + { ISFUNC, (Function *)0x0 }, /* o */ + { ISFUNC, rl_vi_put }, /* p */ + { ISFUNC, (Function *)0x0 }, /* q */ + { ISFUNC, rl_vi_change_char }, /* r */ + { ISFUNC, rl_vi_subst }, /* s */ + { ISFUNC, rl_vi_char_search }, /* t */ + { ISFUNC, rl_undo_command }, /* u */ + { ISFUNC, (Function *)0x0 }, /* v */ + { ISFUNC, rl_vi_next_word }, /* w */ + { ISFUNC, rl_vi_delete }, /* x */ + { ISFUNC, rl_vi_yank_to }, /* y */ + { ISFUNC, (Function *)0x0 }, /* z */ + + /* Final punctuation. */ + { ISFUNC, (Function *)0x0 }, /* { */ + { ISFUNC, rl_vi_column }, /* | */ + { ISFUNC, (Function *)0x0 }, /* } */ + { ISFUNC, rl_vi_change_case }, /* ~ */ + { ISFUNC, (Function *)0x0 }, /* RUBOUT */ + +#if KEYMAP_SIZE > 128 + /* Undefined keys. */ + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 } +#endif /* KEYMAP_SIZE > 128 */ +}; + + +KEYMAP_ENTRY_ARRAY vi_insertion_keymap = { + /* The regular control keys come first. */ + { ISFUNC, (Function *)0x0 }, /* Control-@ */ + { ISFUNC, rl_insert }, /* Control-a */ + { ISFUNC, rl_insert }, /* Control-b */ + { ISFUNC, rl_insert }, /* Control-c */ + { ISFUNC, rl_vi_eof_maybe }, /* Control-d */ + { ISFUNC, rl_insert }, /* Control-e */ + { ISFUNC, rl_insert }, /* Control-f */ + { ISFUNC, rl_insert }, /* Control-g */ + { ISFUNC, rl_rubout }, /* Control-h */ + { ISFUNC, rl_complete }, /* Control-i */ + { ISFUNC, rl_newline }, /* Control-j */ + { ISFUNC, rl_insert }, /* Control-k */ + { ISFUNC, rl_insert }, /* Control-l */ + { ISFUNC, rl_newline }, /* Control-m */ + { ISFUNC, rl_insert }, /* Control-n */ + { ISFUNC, rl_insert }, /* Control-o */ + { ISFUNC, rl_insert }, /* Control-p */ + { ISFUNC, rl_insert }, /* Control-q */ + { ISFUNC, rl_reverse_search_history }, /* Control-r */ + { ISFUNC, rl_forward_search_history }, /* Control-s */ + { ISFUNC, rl_transpose_chars }, /* Control-t */ + { ISFUNC, rl_unix_line_discard }, /* Control-u */ + { ISFUNC, rl_quoted_insert }, /* Control-v */ + { ISFUNC, rl_unix_word_rubout }, /* Control-w */ + { ISFUNC, rl_insert }, /* Control-x */ + { ISFUNC, rl_yank }, /* Control-y */ + { ISFUNC, rl_insert }, /* Control-z */ + + { ISFUNC, rl_vi_movement_mode }, /* Control-[ */ + { ISFUNC, rl_insert }, /* Control-\ */ + { ISFUNC, rl_insert }, /* Control-] */ + { ISFUNC, rl_insert }, /* Control-^ */ + { ISFUNC, rl_undo_command }, /* Control-_ */ + + /* The start of printing characters. */ + { ISFUNC, rl_insert }, /* SPACE */ + { ISFUNC, rl_insert }, /* ! */ + { ISFUNC, rl_insert }, /* " */ + { ISFUNC, rl_insert }, /* # */ + { ISFUNC, rl_insert }, /* $ */ + { ISFUNC, rl_insert }, /* % */ + { ISFUNC, rl_insert }, /* & */ + { ISFUNC, rl_insert }, /* ' */ + { ISFUNC, rl_insert }, /* ( */ + { ISFUNC, rl_insert }, /* ) */ + { ISFUNC, rl_insert }, /* * */ + { ISFUNC, rl_insert }, /* + */ + { ISFUNC, rl_insert }, /* , */ + { ISFUNC, rl_insert }, /* - */ + { ISFUNC, rl_insert }, /* . */ + { ISFUNC, rl_insert }, /* / */ + + /* Regular digits. */ + { ISFUNC, rl_insert }, /* 0 */ + { ISFUNC, rl_insert }, /* 1 */ + { ISFUNC, rl_insert }, /* 2 */ + { ISFUNC, rl_insert }, /* 3 */ + { ISFUNC, rl_insert }, /* 4 */ + { ISFUNC, rl_insert }, /* 5 */ + { ISFUNC, rl_insert }, /* 6 */ + { ISFUNC, rl_insert }, /* 7 */ + { ISFUNC, rl_insert }, /* 8 */ + { ISFUNC, rl_insert }, /* 9 */ + + /* A little more punctuation. */ + { ISFUNC, rl_insert }, /* : */ + { ISFUNC, rl_insert }, /* ; */ + { ISFUNC, rl_insert }, /* < */ + { ISFUNC, rl_insert }, /* = */ + { ISFUNC, rl_insert }, /* > */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* @ */ + + /* Uppercase alphabet. */ + { ISFUNC, rl_insert }, /* A */ + { ISFUNC, rl_insert }, /* B */ + { ISFUNC, rl_insert }, /* C */ + { ISFUNC, rl_insert }, /* D */ + { ISFUNC, rl_insert }, /* E */ + { ISFUNC, rl_insert }, /* F */ + { ISFUNC, rl_insert }, /* G */ + { ISFUNC, rl_insert }, /* H */ + { ISFUNC, rl_insert }, /* I */ + { ISFUNC, rl_insert }, /* J */ + { ISFUNC, rl_insert }, /* K */ + { ISFUNC, rl_insert }, /* L */ + { ISFUNC, rl_insert }, /* M */ + { ISFUNC, rl_insert }, /* N */ + { ISFUNC, rl_insert }, /* O */ + { ISFUNC, rl_insert }, /* P */ + { ISFUNC, rl_insert }, /* Q */ + { ISFUNC, rl_insert }, /* R */ + { ISFUNC, rl_insert }, /* S */ + { ISFUNC, rl_insert }, /* T */ + { ISFUNC, rl_insert }, /* U */ + { ISFUNC, rl_insert }, /* V */ + { ISFUNC, rl_insert }, /* W */ + { ISFUNC, rl_insert }, /* X */ + { ISFUNC, rl_insert }, /* Y */ + { ISFUNC, rl_insert }, /* Z */ + + /* Some more punctuation. */ + { ISFUNC, rl_insert }, /* [ */ + { ISFUNC, rl_insert }, /* \ */ + { ISFUNC, rl_insert }, /* ] */ + { ISFUNC, rl_insert }, /* ^ */ + { ISFUNC, rl_insert }, /* _ */ + { ISFUNC, rl_insert }, /* ` */ + + /* Lowercase alphabet. */ + { ISFUNC, rl_insert }, /* a */ + { ISFUNC, rl_insert }, /* b */ + { ISFUNC, rl_insert }, /* c */ + { ISFUNC, rl_insert }, /* d */ + { ISFUNC, rl_insert }, /* e */ + { ISFUNC, rl_insert }, /* f */ + { ISFUNC, rl_insert }, /* g */ + { ISFUNC, rl_insert }, /* h */ + { ISFUNC, rl_insert }, /* i */ + { ISFUNC, rl_insert }, /* j */ + { ISFUNC, rl_insert }, /* k */ + { ISFUNC, rl_insert }, /* l */ + { ISFUNC, rl_insert }, /* m */ + { ISFUNC, rl_insert }, /* n */ + { ISFUNC, rl_insert }, /* o */ + { ISFUNC, rl_insert }, /* p */ + { ISFUNC, rl_insert }, /* q */ + { ISFUNC, rl_insert }, /* r */ + { ISFUNC, rl_insert }, /* s */ + { ISFUNC, rl_insert }, /* t */ + { ISFUNC, rl_insert }, /* u */ + { ISFUNC, rl_insert }, /* v */ + { ISFUNC, rl_insert }, /* w */ + { ISFUNC, rl_insert }, /* x */ + { ISFUNC, rl_insert }, /* y */ + { ISFUNC, rl_insert }, /* z */ + + /* Final punctuation. */ + { ISFUNC, rl_insert }, /* { */ + { ISFUNC, rl_insert }, /* | */ + { ISFUNC, rl_insert }, /* } */ + { ISFUNC, rl_insert }, /* ~ */ + { ISFUNC, rl_rubout }, /* RUBOUT */ + +#if KEYMAP_SIZE > 128 + /* Pure 8-bit characters (128 - 159). + These might be used in some + character sets. */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + { ISFUNC, rl_insert }, /* ? */ + + /* ISO Latin-1 characters (160 - 255) */ + { ISFUNC, rl_insert }, /* No-break space */ + { ISFUNC, rl_insert }, /* Inverted exclamation mark */ + { ISFUNC, rl_insert }, /* Cent sign */ + { ISFUNC, rl_insert }, /* Pound sign */ + { ISFUNC, rl_insert }, /* Currency sign */ + { ISFUNC, rl_insert }, /* Yen sign */ + { ISFUNC, rl_insert }, /* Broken bar */ + { ISFUNC, rl_insert }, /* Section sign */ + { ISFUNC, rl_insert }, /* Diaeresis */ + { ISFUNC, rl_insert }, /* Copyright sign */ + { ISFUNC, rl_insert }, /* Feminine ordinal indicator */ + { ISFUNC, rl_insert }, /* Left pointing double angle quotation mark */ + { ISFUNC, rl_insert }, /* Not sign */ + { ISFUNC, rl_insert }, /* Soft hyphen */ + { ISFUNC, rl_insert }, /* Registered sign */ + { ISFUNC, rl_insert }, /* Macron */ + { ISFUNC, rl_insert }, /* Degree sign */ + { ISFUNC, rl_insert }, /* Plus-minus sign */ + { ISFUNC, rl_insert }, /* Superscript two */ + { ISFUNC, rl_insert }, /* Superscript three */ + { ISFUNC, rl_insert }, /* Acute accent */ + { ISFUNC, rl_insert }, /* Micro sign */ + { ISFUNC, rl_insert }, /* Pilcrow sign */ + { ISFUNC, rl_insert }, /* Middle dot */ + { ISFUNC, rl_insert }, /* Cedilla */ + { ISFUNC, rl_insert }, /* Superscript one */ + { ISFUNC, rl_insert }, /* Masculine ordinal indicator */ + { ISFUNC, rl_insert }, /* Right pointing double angle quotation mark */ + { ISFUNC, rl_insert }, /* Vulgar fraction one quarter */ + { ISFUNC, rl_insert }, /* Vulgar fraction one half */ + { ISFUNC, rl_insert }, /* Vulgar fraction three quarters */ + { ISFUNC, rl_insert }, /* Inverted questionk mark */ + { ISFUNC, rl_insert }, /* Latin capital letter a with grave */ + { ISFUNC, rl_insert }, /* Latin capital letter a with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter a with circumflex */ + { ISFUNC, rl_insert }, /* Latin capital letter a with tilde */ + { ISFUNC, rl_insert }, /* Latin capital letter a with diaeresis */ + { ISFUNC, rl_insert }, /* Latin capital letter a with ring above */ + { ISFUNC, rl_insert }, /* Latin capital letter ae */ + { ISFUNC, rl_insert }, /* Latin capital letter c with cedilla */ + { ISFUNC, rl_insert }, /* Latin capital letter e with grave */ + { ISFUNC, rl_insert }, /* Latin capital letter e with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter e with circumflex */ + { ISFUNC, rl_insert }, /* Latin capital letter e with diaeresis */ + { ISFUNC, rl_insert }, /* Latin capital letter i with grave */ + { ISFUNC, rl_insert }, /* Latin capital letter i with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter i with circumflex */ + { ISFUNC, rl_insert }, /* Latin capital letter i with diaeresis */ + { ISFUNC, rl_insert }, /* Latin capital letter eth (Icelandic) */ + { ISFUNC, rl_insert }, /* Latin capital letter n with tilde */ + { ISFUNC, rl_insert }, /* Latin capital letter o with grave */ + { ISFUNC, rl_insert }, /* Latin capital letter o with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter o with circumflex */ + { ISFUNC, rl_insert }, /* Latin capital letter o with tilde */ + { ISFUNC, rl_insert }, /* Latin capital letter o with diaeresis */ + { ISFUNC, rl_insert }, /* Multiplication sign */ + { ISFUNC, rl_insert }, /* Latin capital letter o with stroke */ + { ISFUNC, rl_insert }, /* Latin capital letter u with grave */ + { ISFUNC, rl_insert }, /* Latin capital letter u with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter u with circumflex */ + { ISFUNC, rl_insert }, /* Latin capital letter u with diaeresis */ + { ISFUNC, rl_insert }, /* Latin capital letter Y with acute */ + { ISFUNC, rl_insert }, /* Latin capital letter thorn (Icelandic) */ + { ISFUNC, rl_insert }, /* Latin small letter sharp s (German) */ + { ISFUNC, rl_insert }, /* Latin small letter a with grave */ + { ISFUNC, rl_insert }, /* Latin small letter a with acute */ + { ISFUNC, rl_insert }, /* Latin small letter a with circumflex */ + { ISFUNC, rl_insert }, /* Latin small letter a with tilde */ + { ISFUNC, rl_insert }, /* Latin small letter a with diaeresis */ + { ISFUNC, rl_insert }, /* Latin small letter a with ring above */ + { ISFUNC, rl_insert }, /* Latin small letter ae */ + { ISFUNC, rl_insert }, /* Latin small letter c with cedilla */ + { ISFUNC, rl_insert }, /* Latin small letter e with grave */ + { ISFUNC, rl_insert }, /* Latin small letter e with acute */ + { ISFUNC, rl_insert }, /* Latin small letter e with circumflex */ + { ISFUNC, rl_insert }, /* Latin small letter e with diaeresis */ + { ISFUNC, rl_insert }, /* Latin small letter i with grave */ + { ISFUNC, rl_insert }, /* Latin small letter i with acute */ + { ISFUNC, rl_insert }, /* Latin small letter i with circumflex */ + { ISFUNC, rl_insert }, /* Latin small letter i with diaeresis */ + { ISFUNC, rl_insert }, /* Latin small letter eth (Icelandic) */ + { ISFUNC, rl_insert }, /* Latin small letter n with tilde */ + { ISFUNC, rl_insert }, /* Latin small letter o with grave */ + { ISFUNC, rl_insert }, /* Latin small letter o with acute */ + { ISFUNC, rl_insert }, /* Latin small letter o with circumflex */ + { ISFUNC, rl_insert }, /* Latin small letter o with tilde */ + { ISFUNC, rl_insert }, /* Latin small letter o with diaeresis */ + { ISFUNC, rl_insert }, /* Division sign */ + { ISFUNC, rl_insert }, /* Latin small letter o with stroke */ + { ISFUNC, rl_insert }, /* Latin small letter u with grave */ + { ISFUNC, rl_insert }, /* Latin small letter u with acute */ + { ISFUNC, rl_insert }, /* Latin small letter u with circumflex */ + { ISFUNC, rl_insert }, /* Latin small letter u with diaeresis */ + { ISFUNC, rl_insert }, /* Latin small letter y with acute */ + { ISFUNC, rl_insert }, /* Latin small letter thorn (Icelandic) */ + { ISFUNC, rl_insert } /* Latin small letter y with diaeresis */ +#endif /* KEYMAP_SIZE > 128 */ +}; + +/* Unused for the time being. */ +#if 0 +KEYMAP_ENTRY_ARRAY vi_escape_keymap = { + /* The regular control keys come first. */ + { ISFUNC, (Function *)0x0 }, /* Control-@ */ + { ISFUNC, (Function *)0x0 }, /* Control-a */ + { ISFUNC, (Function *)0x0 }, /* Control-b */ + { ISFUNC, (Function *)0x0 }, /* Control-c */ + { ISFUNC, (Function *)0x0 }, /* Control-d */ + { ISFUNC, (Function *)0x0 }, /* Control-e */ + { ISFUNC, (Function *)0x0 }, /* Control-f */ + { ISFUNC, (Function *)0x0 }, /* Control-g */ + { ISFUNC, (Function *)0x0 }, /* Control-h */ + { ISFUNC, rl_tab_insert}, /* Control-i */ + { ISFUNC, rl_emacs_editing_mode}, /* Control-j */ + { ISFUNC, rl_kill_line }, /* Control-k */ + { ISFUNC, (Function *)0x0 }, /* Control-l */ + { ISFUNC, rl_emacs_editing_mode}, /* Control-m */ + { ISFUNC, (Function *)0x0 }, /* Control-n */ + { ISFUNC, (Function *)0x0 }, /* Control-o */ + { ISFUNC, (Function *)0x0 }, /* Control-p */ + { ISFUNC, (Function *)0x0 }, /* Control-q */ + { ISFUNC, (Function *)0x0 }, /* Control-r */ + { ISFUNC, (Function *)0x0 }, /* Control-s */ + { ISFUNC, (Function *)0x0 }, /* Control-t */ + { ISFUNC, (Function *)0x0 }, /* Control-u */ + { ISFUNC, (Function *)0x0 }, /* Control-v */ + { ISFUNC, (Function *)0x0 }, /* Control-w */ + { ISFUNC, (Function *)0x0 }, /* Control-x */ + { ISFUNC, (Function *)0x0 }, /* Control-y */ + { ISFUNC, (Function *)0x0 }, /* Control-z */ + + { ISFUNC, rl_vi_movement_mode }, /* Control-[ */ + { ISFUNC, (Function *)0x0 }, /* Control-\ */ + { ISFUNC, (Function *)0x0 }, /* Control-] */ + { ISFUNC, (Function *)0x0 }, /* Control-^ */ + { ISFUNC, rl_undo_command }, /* Control-_ */ + + /* The start of printing characters. */ + { ISFUNC, (Function *)0x0 }, /* SPACE */ + { ISFUNC, (Function *)0x0 }, /* ! */ + { ISFUNC, (Function *)0x0 }, /* " */ + { ISFUNC, (Function *)0x0 }, /* # */ + { ISFUNC, (Function *)0x0 }, /* $ */ + { ISFUNC, (Function *)0x0 }, /* % */ + { ISFUNC, (Function *)0x0 }, /* & */ + { ISFUNC, (Function *)0x0 }, /* ' */ + { ISFUNC, (Function *)0x0 }, /* ( */ + { ISFUNC, (Function *)0x0 }, /* ) */ + { ISFUNC, (Function *)0x0 }, /* * */ + { ISFUNC, (Function *)0x0 }, /* + */ + { ISFUNC, (Function *)0x0 }, /* , */ + { ISFUNC, (Function *)0x0 }, /* - */ + { ISFUNC, (Function *)0x0 }, /* . */ + { ISFUNC, (Function *)0x0 }, /* / */ + + /* Regular digits. */ + { ISFUNC, rl_vi_arg_digit }, /* 0 */ + { ISFUNC, rl_vi_arg_digit }, /* 1 */ + { ISFUNC, rl_vi_arg_digit }, /* 2 */ + { ISFUNC, rl_vi_arg_digit }, /* 3 */ + { ISFUNC, rl_vi_arg_digit }, /* 4 */ + { ISFUNC, rl_vi_arg_digit }, /* 5 */ + { ISFUNC, rl_vi_arg_digit }, /* 6 */ + { ISFUNC, rl_vi_arg_digit }, /* 7 */ + { ISFUNC, rl_vi_arg_digit }, /* 8 */ + { ISFUNC, rl_vi_arg_digit }, /* 9 */ + + /* A little more punctuation. */ + { ISFUNC, (Function *)0x0 }, /* : */ + { ISFUNC, (Function *)0x0 }, /* ; */ + { ISFUNC, (Function *)0x0 }, /* < */ + { ISFUNC, (Function *)0x0 }, /* = */ + { ISFUNC, (Function *)0x0 }, /* > */ + { ISFUNC, (Function *)0x0 }, /* ? */ + { ISFUNC, (Function *)0x0 }, /* @ */ + + /* Uppercase alphabet. */ + { ISFUNC, rl_do_lowercase_version }, /* A */ + { ISFUNC, rl_do_lowercase_version }, /* B */ + { ISFUNC, rl_do_lowercase_version }, /* C */ + { ISFUNC, rl_do_lowercase_version }, /* D */ + { ISFUNC, rl_do_lowercase_version }, /* E */ + { ISFUNC, rl_do_lowercase_version }, /* F */ + { ISFUNC, rl_do_lowercase_version }, /* G */ + { ISFUNC, rl_do_lowercase_version }, /* H */ + { ISFUNC, rl_do_lowercase_version }, /* I */ + { ISFUNC, rl_do_lowercase_version }, /* J */ + { ISFUNC, rl_do_lowercase_version }, /* K */ + { ISFUNC, rl_do_lowercase_version }, /* L */ + { ISFUNC, rl_do_lowercase_version }, /* M */ + { ISFUNC, rl_do_lowercase_version }, /* N */ + { ISFUNC, rl_do_lowercase_version }, /* O */ + { ISFUNC, rl_do_lowercase_version }, /* P */ + { ISFUNC, rl_do_lowercase_version }, /* Q */ + { ISFUNC, rl_do_lowercase_version }, /* R */ + { ISFUNC, rl_do_lowercase_version }, /* S */ + { ISFUNC, rl_do_lowercase_version }, /* T */ + { ISFUNC, rl_do_lowercase_version }, /* U */ + { ISFUNC, rl_do_lowercase_version }, /* V */ + { ISFUNC, rl_do_lowercase_version }, /* W */ + { ISFUNC, rl_do_lowercase_version }, /* X */ + { ISFUNC, rl_do_lowercase_version }, /* Y */ + { ISFUNC, rl_do_lowercase_version }, /* Z */ + + /* Some more punctuation. */ + { ISFUNC, rl_arrow_keys }, /* [ */ + { ISFUNC, (Function *)0x0 }, /* \ */ + { ISFUNC, (Function *)0x0 }, /* ] */ + { ISFUNC, (Function *)0x0 }, /* ^ */ + { ISFUNC, (Function *)0x0 }, /* _ */ + { ISFUNC, (Function *)0x0 }, /* ` */ + + /* Lowercase alphabet. */ + { ISFUNC, (Function *)0x0 }, /* a */ + { ISFUNC, (Function *)0x0 }, /* b */ + { ISFUNC, (Function *)0x0 }, /* c */ + { ISFUNC, (Function *)0x0 }, /* d */ + { ISFUNC, (Function *)0x0 }, /* e */ + { ISFUNC, (Function *)0x0 }, /* f */ + { ISFUNC, (Function *)0x0 }, /* g */ + { ISFUNC, (Function *)0x0 }, /* h */ + { ISFUNC, (Function *)0x0 }, /* i */ + { ISFUNC, (Function *)0x0 }, /* j */ + { ISFUNC, (Function *)0x0 }, /* k */ + { ISFUNC, (Function *)0x0 }, /* l */ + { ISFUNC, (Function *)0x0 }, /* m */ + { ISFUNC, (Function *)0x0 }, /* n */ + { ISFUNC, rl_arrow_keys }, /* o */ + { ISFUNC, (Function *)0x0 }, /* p */ + { ISFUNC, (Function *)0x0 }, /* q */ + { ISFUNC, (Function *)0x0 }, /* r */ + { ISFUNC, (Function *)0x0 }, /* s */ + { ISFUNC, (Function *)0x0 }, /* t */ + { ISFUNC, (Function *)0x0 }, /* u */ + { ISFUNC, (Function *)0x0 }, /* v */ + { ISFUNC, (Function *)0x0 }, /* w */ + { ISFUNC, (Function *)0x0 }, /* x */ + { ISFUNC, (Function *)0x0 }, /* y */ + { ISFUNC, (Function *)0x0 }, /* z */ + + /* Final punctuation. */ + { ISFUNC, (Function *)0x0 }, /* { */ + { ISFUNC, (Function *)0x0 }, /* | */ + { ISFUNC, (Function *)0x0 }, /* } */ + { ISFUNC, (Function *)0x0 }, /* ~ */ + { ISFUNC, rl_backward_kill_word }, /* RUBOUT */ + +#if KEYMAP_SIZE > 128 + /* Undefined keys. */ + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 }, + { ISFUNC, (Function *)0x0 } +#endif /* KEYMAP_SIZE > 128 */ +}; +#endif diff --git a/vi_mode.c b/vi_mode.c new file mode 100644 index 0000000..f8975f7 --- /dev/null +++ b/vi_mode.c @@ -0,0 +1,1329 @@ +/* vi_mode.c -- A vi emulation mode for Bash. + Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */ + +/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library 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 1, or + (at your option) any later version. + + The GNU Readline Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define READLINE_LIBRARY + +/* **************************************************************** */ +/* */ +/* VI Emulation Mode */ +/* */ +/* **************************************************************** */ +#include "rlconf.h" + +#if defined (VI_MODE) + +#include + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#include + +/* Some standard library routines. */ +#include "rldefs.h" +#include "readline.h" +#include "history.h" + +#ifndef digit_p +#define digit_p(c) ((c) >= '0' && (c) <= '9') +#endif + +#ifndef digit_value +#define digit_value(c) ((c) - '0') +#endif + +#ifndef member +#define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0) +#endif + +#ifndef isident +#define isident(c) ((pure_alphabetic (c) || digit_p (c) || c == '_')) +#endif + +#ifndef exchange +#define exchange(x, y) do {int temp = x; x = y; y = temp;} while (0) +#endif + +#ifndef VI_COMMENT_BEGIN_DEFAULT +#define VI_COMMENT_BEGIN_DEFAULT "#" +#endif + +#if defined (STATIC_MALLOC) +static char *xmalloc (), *xrealloc (); +#else +extern char *xmalloc (), *xrealloc (); +#endif /* STATIC_MALLOC */ + +/* Variables imported from readline.c */ +extern int rl_point, rl_end, rl_mark, rl_done; +extern FILE *rl_instream; +extern int rl_line_buffer_len, rl_explicit_arg, rl_numeric_arg; +extern Keymap _rl_keymap; +extern char *rl_prompt; +extern char *rl_line_buffer; +extern int rl_arg_sign; + +extern void _rl_dispatch (); + +extern void rl_extend_line_buffer (); +extern int rl_vi_check (); + +/* Non-zero means enter insertion mode. */ +static int _rl_vi_doing_insert = 0; + +/* String inserted into the line by rl_vi_comment (). */ +char *rl_vi_comment_begin = (char *)NULL; + +/* *** UNCLEAN *** */ +/* Command keys which do movement for xxx_to commands. */ +static char *vi_motion = " hl^$0ftFt;,%wbeWBE|"; + +/* Keymap used for vi replace characters. Created dynamically since + rarely used. */ +static Keymap vi_replace_map = (Keymap)NULL; + +/* The number of characters inserted in the last replace operation. */ +static int vi_replace_count = 0; + +/* If non-zero, we have text inserted after a c[motion] command that put + us implicitly into insert mode. Some people want this text to be + attached to the command so that it is `redoable' with `.'. */ +static int vi_continued_command = 0; + +static int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */ +static int _rl_vi_last_repeat = 1; +static int _rl_vi_last_arg_sign = 1; +static int _rl_vi_last_motion = 0; +static int _rl_vi_last_search_char = 0; +static int _rl_vi_last_replacement = 0; + +static int vi_redoing = 0; + +/* Text modification commands. These are the `redoable' commands. */ +static char *vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~"; + +static int rl_digit_loop1 (); + +void +_rl_vi_reset_last () +{ + _rl_vi_last_command = 'i'; + _rl_vi_last_repeat = 1; + _rl_vi_last_arg_sign = 1; + _rl_vi_last_motion = 0; +} + +void +_rl_vi_set_last (key, repeat, sign) + int key, repeat, sign; +{ + _rl_vi_last_command = key; + _rl_vi_last_repeat = repeat; + _rl_vi_last_arg_sign = sign; +} + +/* Is the command C a VI mode text modification command? */ +int +rl_vi_textmod_command (c) + int c; +{ + return (member (c, vi_textmod)); +} + +/* Bound to `.'. Called from command mode, so we know that we have to + redo a text modification command. The default for _rl_vi_last_command + puts you back into insert mode. */ +rl_vi_redo (count, c) + int count, c; +{ + if (!rl_explicit_arg) + { + rl_numeric_arg = _rl_vi_last_repeat; + rl_arg_sign = _rl_vi_last_arg_sign; + } + + vi_redoing = 1; + _rl_dispatch (_rl_vi_last_command, _rl_keymap); + vi_redoing = 0; + + return (0); +} + +/* Yank the nth arg from the previous line into this line at point. */ +rl_vi_yank_arg (count, key) + int count, key; +{ + /* Readline thinks that the first word on a line is the 0th, while vi + thinks the first word on a line is the 1st. Compensate. */ + if (rl_explicit_arg) + rl_yank_nth_arg (count - 1, 0); + else + rl_yank_nth_arg ('$', 0); + + return (0); +} + +/* With an argument, move back that many history lines, else move to the + beginning of history. */ +rl_vi_fetch_history (count, c) + int count, c; +{ + int current = where_history (); + + /* Giving an argument of n means we want the nth command in the history + file. The command number is interpreted the same way that the bash + `history' command does it -- that is, giving an argument count of 450 + to this command would get the command listed as number 450 in the + output of `history'. */ + if (rl_explicit_arg) + { + int wanted = history_base + current - count; + if (wanted <= 0) + rl_beginning_of_history (0, 0); + else + rl_get_previous_history (wanted); + } + else + rl_beginning_of_history (count, 0); + return (0); +} + +/* Search again for the last thing searched for. */ +rl_vi_search_again (count, key) + int count, key; +{ + switch (key) + { + case 'n': + rl_noninc_reverse_search_again (count, key); + break; + + case 'N': + rl_noninc_forward_search_again (count, key); + break; + } + return (0); +} + +/* Do a vi style search. */ +rl_vi_search (count, key) + int count, key; +{ + switch (key) + { + case '?': + rl_noninc_forward_search (count, key); + break; + + case '/': + rl_noninc_reverse_search (count, key); + break; + + default: + ding (); + break; + } + return (0); +} + +/* Completion, from vi's point of view. */ +rl_vi_complete (ignore, key) + int ignore, key; +{ + if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point]))) + { + if (!whitespace (rl_line_buffer[rl_point + 1])) + rl_vi_end_word (1, 'E'); + rl_point++; + } + + if (key == '*') + rl_complete_internal ('*'); /* Expansion and replacement. */ + else if (key == '=') + rl_complete_internal ('?'); /* List possible completions. */ + else if (key == '\\') + rl_complete_internal (TAB); /* Standard Readline completion. */ + else + rl_complete (0, key); + + if (key == '*' || key == '\\') + { + _rl_vi_set_last (key, 1, rl_arg_sign); + rl_vi_insertion_mode (); + } + return (0); +} + +/* Tilde expansion for vi mode. */ +rl_vi_tilde_expand (ignore, key) + int ignore, key; +{ + rl_tilde_expand (0, key); + _rl_vi_set_last (key, 1, rl_arg_sign); /* XXX */ + rl_vi_insertion_mode (); + return (0); +} + +/* Previous word in vi mode. */ +rl_vi_prev_word (count, key) + int count, key; +{ + if (count < 0) + return (rl_vi_next_word (-count, key)); + + if (rl_point == 0) + { + ding (); + return (0); + } + + if (uppercase_p (key)) + rl_vi_bWord (count); + else + rl_vi_bword (count); + + return (0); +} + +/* Next word in vi mode. */ +rl_vi_next_word (count, key) + int count, key; +{ + if (count < 0) + return (rl_vi_prev_word (-count, key)); + + if (rl_point >= (rl_end - 1)) + { + ding (); + return (0); + } + + if (uppercase_p (key)) + rl_vi_fWord (count); + else + rl_vi_fword (count); + return (0); +} + +/* Move to the end of the ?next? word. */ +rl_vi_end_word (count, key) + int count, key; +{ + if (count < 0) + { + ding (); + return -1; + } + + if (uppercase_p (key)) + rl_vi_eWord (count); + else + rl_vi_eword (count); + return (0); +} + +/* Move forward a word the way that 'W' does. */ +rl_vi_fWord (count) + int count; +{ + while (count-- && rl_point < (rl_end - 1)) + { + /* Skip until whitespace. */ + while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) + rl_point++; + + /* Now skip whitespace. */ + while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) + rl_point++; + } + return (0); +} + +rl_vi_bWord (count) + int count; +{ + while (count-- && rl_point > 0) + { + /* If we are at the start of a word, move back to whitespace so + we will go back to the start of the previous word. */ + if (!whitespace (rl_line_buffer[rl_point]) && + whitespace (rl_line_buffer[rl_point - 1])) + rl_point--; + + while (rl_point > 0 && whitespace (rl_line_buffer[rl_point])) + rl_point--; + + if (rl_point > 0) + { + while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point])); + rl_point++; + } + } + return (0); +} + +rl_vi_eWord (count) + int count; +{ + while (count-- && rl_point < (rl_end - 1)) + { + if (!whitespace (rl_line_buffer[rl_point])) + rl_point++; + + /* Move to the next non-whitespace character (to the start of the + next word). */ + while (++rl_point < rl_end && whitespace (rl_line_buffer[rl_point])); + + if (rl_point && rl_point < rl_end) + { + /* Skip whitespace. */ + while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) + rl_point++; + + /* Skip until whitespace. */ + while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point])) + rl_point++; + + /* Move back to the last character of the word. */ + rl_point--; + } + } + return (0); +} + +rl_vi_fword (count) + int count; +{ + while (count-- && rl_point < (rl_end - 1)) + { + /* Move to white space (really non-identifer). */ + if (isident (rl_line_buffer[rl_point])) + { + while (isident (rl_line_buffer[rl_point]) && rl_point < rl_end) + rl_point++; + } + else /* if (!whitespace (rl_line_buffer[rl_point])) */ + { + while (!isident (rl_line_buffer[rl_point]) && + !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) + rl_point++; + } + + /* Move past whitespace. */ + while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) + rl_point++; + } + return (0); +} + +rl_vi_bword (count) + int count; +{ + while (count-- && rl_point > 0) + { + int last_is_ident; + + /* If we are at the start of a word, move back to whitespace + so we will go back to the start of the previous word. */ + if (!whitespace (rl_line_buffer[rl_point]) && + whitespace (rl_line_buffer[rl_point - 1])) + rl_point--; + + /* If this character and the previous character are `opposite', move + back so we don't get messed up by the rl_point++ down there in + the while loop. Without this code, words like `l;' screw up the + function. */ + last_is_ident = isident (rl_line_buffer[rl_point - 1]); + if ((isident (rl_line_buffer[rl_point]) && !last_is_ident) || + (!isident (rl_line_buffer[rl_point]) && last_is_ident)) + rl_point--; + + while (rl_point > 0 && whitespace (rl_line_buffer[rl_point])) + rl_point--; + + if (rl_point > 0) + { + if (isident (rl_line_buffer[rl_point])) + while (--rl_point >= 0 && isident (rl_line_buffer[rl_point])); + else + while (--rl_point >= 0 && !isident (rl_line_buffer[rl_point]) && + !whitespace (rl_line_buffer[rl_point])); + rl_point++; + } + } + return (0); +} + +rl_vi_eword (count) + int count; +{ + while (count-- && rl_point < rl_end - 1) + { + if (!whitespace (rl_line_buffer[rl_point])) + rl_point++; + + while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) + rl_point++; + + if (rl_point < rl_end) + { + if (isident (rl_line_buffer[rl_point])) + while (++rl_point < rl_end && isident (rl_line_buffer[rl_point])); + else + while (++rl_point < rl_end && !isident (rl_line_buffer[rl_point]) + && !whitespace (rl_line_buffer[rl_point])); + } + rl_point--; + } + return (0); +} + +rl_vi_insert_beg (count, key) + int count, key; +{ + rl_beg_of_line (); + rl_vi_insertion_mode (); + return (0); +} + +rl_vi_append_mode (count, key) + int count, key; +{ + if (rl_point < rl_end) + rl_point++; + rl_vi_insertion_mode (); + return (0); +} + +rl_vi_append_eol (count, key) + int count, key; +{ + rl_end_of_line (); + rl_vi_append_mode (); + return (0); +} + +/* What to do in the case of C-d. */ +rl_vi_eof_maybe (count, c) + int count, c; +{ + return (rl_newline (1, '\n')); +} + +/* Insertion mode stuff. */ + +/* Switching from one mode to the other really just involves + switching keymaps. */ +rl_vi_insertion_mode (count, key) + int count, key; +{ + _rl_keymap = vi_insertion_keymap; + return (0); +} + +void +_rl_vi_done_inserting () +{ + if (_rl_vi_doing_insert) + { + rl_end_undo_group (); + /* Now, the text between rl_undo_list->next->start and + rl_undo_list->next->end is what was inserted while in insert + mode. */ + _rl_vi_doing_insert = 0; + vi_continued_command = 1; + } + else + vi_continued_command = 0; +} + +rl_vi_movement_mode (count, key) + int count, key; +{ + if (rl_point > 0) + rl_backward (1); + +#if 0 + _rl_vi_reset_last (); +#endif + + _rl_keymap = vi_movement_keymap; + _rl_vi_done_inserting (); + return (0); +} + +rl_vi_arg_digit (count, c) + int count, c; +{ + if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg) + return (rl_beg_of_line ()); + else + return (rl_digit_argument (count, c)); +} + +rl_vi_change_case (count, ignore) + int count, ignore; +{ + char c = 0; + + /* Don't try this on an empty line. */ + if (rl_point >= rl_end) + return (0); + + while (count-- && rl_point < rl_end) + { + if (uppercase_p (rl_line_buffer[rl_point])) + c = to_lower (rl_line_buffer[rl_point]); + else if (lowercase_p (rl_line_buffer[rl_point])) + c = to_upper (rl_line_buffer[rl_point]); + else + { + /* Just skip over characters neither upper nor lower case. */ + rl_forward (1); + continue; + } + + /* Vi is kind of strange here. */ + if (c) + { + rl_begin_undo_group (); + rl_delete (1, c); + rl_insert (1, c); + rl_end_undo_group (); + rl_vi_check (); + } + else + rl_forward (1); + } + return (0); +} + +rl_vi_put (count, key) + int count, key; +{ + if (!uppercase_p (key) && (rl_point + 1 <= rl_end)) + rl_point++; + + rl_yank (); + rl_backward (1); + return (0); +} + +rl_vi_check () +{ + if (rl_point && rl_point == rl_end) + rl_point--; + return (0); +} + +rl_vi_column (count, key) + int count, key; +{ + if (count > rl_end) + rl_end_of_line (); + else + rl_point = count - 1; + return (0); +} + +int +rl_vi_domove (key, nextkey) + int key, *nextkey; +{ + int c, save; + int old_end; + + rl_mark = rl_point; + c = rl_read_key (); + *nextkey = c; + + if (!member (c, vi_motion)) + { + if (digit_p (c)) + { + save = rl_numeric_arg; + rl_numeric_arg = digit_value (c); + rl_digit_loop1 (); + rl_numeric_arg *= save; + c = rl_read_key (); /* real command */ + *nextkey = c; + } + else if (key == c && (key == 'd' || key == 'y' || key == 'c')) + { + rl_mark = rl_end; + rl_beg_of_line (); + _rl_vi_last_motion = c; + return (0); + } + else + return (-1); + } + + _rl_vi_last_motion = c; + + /* Append a blank character temporarily so that the motion routines + work right at the end of the line. */ + old_end = rl_end; + rl_line_buffer[rl_end++] = ' '; + rl_line_buffer[rl_end] = '\0'; + + _rl_dispatch (c, _rl_keymap); + + /* Remove the blank that we added. */ + rl_end = old_end; + rl_line_buffer[rl_end] = '\0'; + if (rl_point > rl_end) + rl_point = rl_end; + + /* No change in position means the command failed. */ + if (rl_mark == rl_point) + return (-1); + + /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next + word. If we are not at the end of the line, and we are on a + non-whitespace character, move back one (presumably to whitespace). */ + if ((to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark && + !whitespace (rl_line_buffer[rl_point])) + rl_point--; + + /* If cw or cW, back up to the end of a word, so the behaviour of ce + or cE is the actual result. Brute-force, no subtlety. */ + if (key == 'c' && rl_point >= rl_mark && (to_upper (c) == 'W')) + { + /* Don't move farther back than where we started. */ + while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point])) + rl_point--; + + /* Posix.2 says that if cw or cW moves the cursor towards the end of + the line, the character under the cursor should be deleted. */ + if (rl_point == rl_mark) + rl_point++; + else + { + /* Move past the end of the word so that the kill doesn't + remove the last letter of the previous word. Only do this + if we are not at the end of the line. */ + if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point])) + rl_point++; + } + } + + if (rl_mark < rl_point) + exchange (rl_point, rl_mark); + + return (0); +} + +/* A simplified loop for vi. Don't dispatch key at end. + Don't recognize minus sign? */ +static int +rl_digit_loop1 () +{ + int key, c; + + while (1) + { + rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg, 0); + key = c = rl_read_key (); + + if (_rl_keymap[c].type == ISFUNC && + _rl_keymap[c].function == rl_universal_argument) + { + rl_numeric_arg *= 4; + continue; + } + + c = UNMETA (c); + if (digit_p (c)) + { + if (rl_explicit_arg) + rl_numeric_arg = (rl_numeric_arg * 10) + digit_value (c); + else + rl_numeric_arg = digit_value (c); + rl_explicit_arg = 1; + } + else + { + rl_clear_message (); + rl_stuff_char (key); + break; + } + } + return (0); +} + +rl_vi_delete_to (count, key) + int count, key; +{ + int c; + + if (uppercase_p (key)) + rl_stuff_char ('$'); + else if (vi_redoing) + rl_stuff_char (_rl_vi_last_motion); + + if (rl_vi_domove (key, &c)) + { + ding (); + return -1; + } + + /* These are the motion commands that do not require adjusting the + mark. */ + if ((strchr (" l|h^0%bB", c) == 0) && (rl_mark < rl_end)) + rl_mark++; + + rl_kill_text (rl_point, rl_mark); + return (0); +} + +rl_vi_change_to (count, key) + int count, key; +{ + int c, start_pos; + + if (uppercase_p (key)) + rl_stuff_char ('$'); + else if (vi_redoing) + rl_stuff_char (_rl_vi_last_motion); + + start_pos = rl_point; + + if (rl_vi_domove (key, &c)) + { + ding (); + return -1; + } + + /* These are the motion commands that do not require adjusting the + mark. c[wW] are handled by special-case code in rl_vi_domove(), + and already leave the mark at the correct location. */ + if ((strchr (" l|hwW^0%bB", c) == 0) && (rl_mark < rl_end)) + rl_mark++; + + /* The cursor never moves with c[wW]. */ + if ((to_upper (c) == 'W') && rl_point < start_pos) + rl_point = start_pos; + + rl_kill_text (rl_point, rl_mark); + + rl_begin_undo_group (); + _rl_vi_doing_insert = 1; + _rl_vi_set_last (key, count, rl_arg_sign); + rl_vi_insertion_mode (); + + return (0); +} + +rl_vi_yank_to (count, key) + int count, key; +{ + int c, save = rl_point; + + if (uppercase_p (key)) + rl_stuff_char ('$'); + + if (rl_vi_domove (key, &c)) + { + ding (); + return -1; + } + + /* These are the motion commands that do not require adjusting the + mark. */ + if ((strchr (" l|h^0%bB", c) == 0) && (rl_mark < rl_end)) + rl_mark++; + + rl_begin_undo_group (); + rl_kill_text (rl_point, rl_mark); + rl_end_undo_group (); + rl_do_undo (); + rl_point = save; + + return (0); +} + +rl_vi_delete (count, key) + int count, key; +{ + int end; + + if (rl_end == 0) + { + ding (); + return -1; + } + + end = rl_point + count; + + if (end >= rl_end) + end = rl_end; + + rl_kill_text (rl_point, end); + + if (rl_point > 0 && rl_point == rl_end) + rl_backward (1); + return (0); +} + +/* Turn the current line into a comment in shell history. + A K*rn shell style function. */ +rl_vi_comment (count, key) + int count, key; +{ + rl_beg_of_line (); + + if (rl_vi_comment_begin != (char *)NULL) + rl_insert_text (rl_vi_comment_begin); + else + rl_insert_text (VI_COMMENT_BEGIN_DEFAULT); /* Default. */ + + rl_redisplay (); + rl_newline (1, '\010'); + return (0); +} + +rl_vi_first_print (count, key) + int count, key; +{ + return (rl_back_to_indent ()); +} + +rl_back_to_indent (ignore1, ignore2) + int ignore1, ignore2; +{ + rl_beg_of_line (); + while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) + rl_point++; + return (0); +} + +/* NOTE: it is necessary that opposite directions are inverses */ +#define FTO 1 /* forward to */ +#define BTO -1 /* backward to */ +#define FFIND 2 /* forward find */ +#define BFIND -2 /* backward find */ + +rl_vi_char_search (count, key) + int count, key; +{ + static char target; + static int orig_dir, dir; + int pos; + + if (key == ';' || key == ',') + dir = (key == ';' ? orig_dir : -orig_dir); + else + { + if (vi_redoing) + target = _rl_vi_last_search_char; + else + _rl_vi_last_search_char = target = rl_getc (rl_instream); + + switch (key) + { + case 't': + orig_dir = dir = FTO; + break; + + case 'T': + orig_dir = dir = BTO; + break; + + case 'f': + orig_dir = dir = FFIND; + break; + + case 'F': + orig_dir = dir = BFIND; + break; + } + } + + pos = rl_point; + + while (count--) + { + if (dir < 0) + { + if (pos == 0) + { + ding (); + return -1; + } + + pos--; + do + { + if (rl_line_buffer[pos] == target) + { + if (dir == BTO) + rl_point = pos + 1; + else + rl_point = pos; + break; + } + } + while (pos--); + + if (pos < 0) + { + ding (); + return -1; + } + } + else + { /* dir > 0 */ + if (pos >= rl_end) + { + ding (); + return -1; + } + + pos++; + do + { + if (rl_line_buffer[pos] == target) + { + if (dir == FTO) + rl_point = pos - 1; + else + rl_point = pos; + break; + } + } + while (++pos < rl_end); + + if (pos >= (rl_end - 1)) + { + ding (); + return -1; + } + } + } + return (0); +} + +/* Match brackets */ +rl_vi_match (ignore, key) + int ignore, key; +{ + int count = 1, brack, pos; + + pos = rl_point; + if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0) + { + while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 && + rl_point < rl_end - 1) + rl_forward (1); + + if (brack <= 0) + { + rl_point = pos; + ding (); + return -1; + } + } + + pos = rl_point; + + if (brack < 0) + { + while (count) + { + if (--pos >= 0) + { + int b = rl_vi_bracktype (rl_line_buffer[pos]); + if (b == -brack) + count--; + else if (b == brack) + count++; + } + else + { + ding (); + return -1; + } + } + } + else + { /* brack > 0 */ + while (count) + { + if (++pos < rl_end) + { + int b = rl_vi_bracktype (rl_line_buffer[pos]); + if (b == -brack) + count--; + else if (b == brack) + count++; + } + else + { + ding (); + return -1; + } + } + } + rl_point = pos; + return (0); +} + +int +rl_vi_bracktype (c) + int c; +{ + switch (c) + { + case '(': return 1; + case ')': return -1; + case '[': return 2; + case ']': return -2; + case '{': return 3; + case '}': return -3; + default: return 0; + } +} + +rl_vi_change_char (count, key) + int count, key; +{ + int c; + + if (vi_redoing) + c = _rl_vi_last_replacement; + else + _rl_vi_last_replacement = c = rl_getc (rl_instream); + + if (c == '\033' || c == CTRL ('C')) + return -1; + + while (count-- && rl_point < rl_end) + { + rl_begin_undo_group (); + + rl_delete (1, c); + rl_insert (1, c); + if (count == 0) + rl_backward (1); + + rl_end_undo_group (); + } + return (0); +} + +rl_vi_subst (count, key) + int count, key; +{ + rl_begin_undo_group (); + + if (uppercase_p (key)) + { + rl_beg_of_line (); + rl_kill_line (1); + } + else + rl_delete (count, key); + + rl_end_undo_group (); + + _rl_vi_set_last (key, count, rl_arg_sign); + + rl_begin_undo_group (); + _rl_vi_doing_insert = 1; + rl_vi_insertion_mode (); + + return (0); +} + +rl_vi_overstrike (count, key) + int count, key; +{ + int i; + + if (_rl_vi_doing_insert == 0) + { + _rl_vi_doing_insert = 1; + rl_begin_undo_group (); + } + + for (i = 0; i < count; i++) + { + vi_replace_count++; + rl_begin_undo_group (); + + if (rl_point < rl_end) + { + rl_delete (1, key); + rl_insert (1, key); + } + else + rl_insert (1, key); + + rl_end_undo_group (); + } + return (0); +} + +rl_vi_overstrike_delete (count) + int count; +{ + int i, s; + + for (i = 0; i < count; i++) + { + if (vi_replace_count == 0) + { + ding (); + break; + } + s = rl_point; + + if (rl_do_undo ()) + vi_replace_count--; + + if (rl_point == s) + rl_backward (1); + } + + if (vi_replace_count == 0 && _rl_vi_doing_insert) + { + rl_end_undo_group (); + rl_do_undo (); + _rl_vi_doing_insert = 0; + } + return (0); +} + +rl_vi_replace (count, key) + int count, key; +{ + int i; + + vi_replace_count = 0; + + if (!vi_replace_map) + { + vi_replace_map = rl_make_bare_keymap (); + + for (i = ' '; i < 127; i++) + vi_replace_map[i].function = rl_vi_overstrike; + + vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete; + vi_replace_map[ESC].function = rl_vi_movement_mode; + vi_replace_map[RETURN].function = rl_newline; + vi_replace_map[NEWLINE].function = rl_newline; + + /* If the normal vi insertion keymap has ^H bound to erase, do the + same here. Probably should remove the assignment to RUBOUT up + there, but I don't think it will make a difference in real life. */ + if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC && + vi_insertion_keymap[CTRL ('H')].function == rl_rubout) + vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete; + + } + _rl_keymap = vi_replace_map; + return (0); +} + +#if 0 +/* Try to complete the word we are standing on or the word that ends with + the previous character. A space matches everything. Word delimiters are + space and ;. */ +rl_vi_possible_completions() +{ + int save_pos = rl_point; + + if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';') + { + while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' && + rl_line_buffer[rl_point] != ';') + rl_point++; + } + else if (rl_line_buffer[rl_point - 1] == ';') + { + ding (); + return (0); + } + + rl_possible_completions (); + rl_point = save_pos; + + return (0); +} +#endif + +#if defined (STATIC_MALLOC) + +/* **************************************************************** */ +/* */ +/* xmalloc and xrealloc () */ +/* */ +/* **************************************************************** */ + +static void memory_error_and_abort (); + +static char * +xmalloc (bytes) + int bytes; +{ + char *temp = (char *)malloc (bytes); + + if (!temp) + memory_error_and_abort (); + return (temp); +} + +static char * +xrealloc (pointer, bytes) + char *pointer; + int bytes; +{ + char *temp; + + if (!pointer) + temp = (char *)xmalloc (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 /* STATIC_MALLOC */ + +#endif /* VI_MODE */ diff --git a/xmalloc.c b/xmalloc.c new file mode 100644 index 0000000..4f6dc76 --- /dev/null +++ b/xmalloc.c @@ -0,0 +1,78 @@ +/* xmalloc.c -- safe versions of malloc and realloc */ + +/* Copyright (C) 1991 Free Software Foundation, Inc. + + This file is part of GNU Readline, a library for reading lines + of text with interactive input and history editing. + + Readline 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 1, or (at your option) any + later version. + + Readline 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 Readline; see the file COPYING. If not, write to the Free + Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#if defined (ALREADY_HAVE_XMALLOC) +#else +#include + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +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. */ +char * +xmalloc (bytes) + int bytes; +{ + char *temp = (char *)malloc (bytes); + + if (!temp) + memory_error_and_abort ("xmalloc"); + return (temp); +} + +char * +xrealloc (pointer, bytes) + char *pointer; + int bytes; +{ + char *temp; + + if (!pointer) + temp = (char *)malloc (bytes); + else + temp = (char *)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 */ -- cgit v1.2.1