home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume22
/
nn6.4
/
part01
next >
Wrap
Text File
|
1990-06-07
|
54KB
|
2,178 lines
Subject: v22i036: NN Newsreader, release 6.4, Part01/21
Newsgroups: comp.sources.unix
Approved: rsalz@uunet.UU.NET
X-Checksum-Snefru: d04fa928 5e29b51a 7500b5b8 47b939e6
Submitted-by: "Kim F. Storm" <storm@texas.dk>
Posting-number: Volume 22, Issue 36
Archive-name: nn6.4/part01
nn is a menu based (point and shoot) netnews reader with a complete
set of features to satisfy both the expert and the novice user. Since
its first release in Denmark in 1984 (!), in Europe in 1988, and the
global release in June 1989, it has replaced rn and other well-known
news readers at many sites.
Some of the key features of nn are:
* It is fast. It uses a dtabase, so it starts almost equally fast (in a few
seconds), no matter whether you have 100 or 10000 unread articles! On
my system nn uses less than 20 seconds to find all articles on a
specific subject among 64000 articles in all groups!
* Menu-based article selection prior to reading the articles
with the articles sorted according to subject & posting time!
* Release 6.4 uses standard .newsrc, and can leave individual
articles unread!
* Digests are automatically split and presented as ordinary articles!
You can transparently save and respond to individual subarticles.
* Full folder support: read, save, and delete individual articles.
* Online help and manual.
* Built-in unshar and patch functions.
* Built-in uudecode function which will automatically unpack,
concatenate, and decode multi-part postings.
* Easy remapping of keys with advanced macro definition features.
* Automatic kill & selection of articles based on subject or author.
* Whole classes of news groups can easily be unsubscribed
* Related groups can be merged and presented as a single group, e.g.
comp.emacs and all gnu.emacs groups.
* In a distributed environment, the database can be shared among all
hosts on the network. Only one daemon is needed on the news server
for all hosts. This works in a heterogenous environment as well.
* NNTP is also supported (using a local database for speed).
#! /bin/sh
# This is a shell archive. Remove anything before this line, then feed it
# into a shell via "sh file" or similar. To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix@uunet.uu.net if you want that tool.
# Contents: README MANIFEST conf contrib doc help inews man regexp.h
# term.c
# Wrapped by storm@texas.dk on Sun May 6 18:19:13 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo If this archive is complete, you will see the following message:
echo ' "shar: End of archive 1 (of 22)."'
if test -f 'README' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(7714 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X INTRODUCTION TO NN
X ------------------
X
X RELEASE 6.4
X
X
Xnn is a menu based (point and shoot) netnews reader with a complete
Xset of features to satisfy both the expert and the novice user. Since
Xits first release in Denmark in 1984 (!), in Europe in 1988, and the
Xglobal release in June 1989, it has replaced rn and other well-known
Xnews readers at many sites.
X
XSome of the key features of nn are:
X
X * Menu-based article selection prior to reading the articles
X with the articles sorted according to subject & posting time!
X
X This significantly reduces the time spent on news reading.
X No keystorkes are wasted on articles you don't want to read, and
X only the articles selected on the menu will be read.
X
X * Release 6.4 uses standard .newsrc, and can leave individual
X articles unread!
X
X * Digests are automatically split and presented as ordinary articles!
X You can transparently save and respond to individual subarticles.
X
X * Full folder support: read, save, and delete individual articles.
X
X * Online help and manual.
X
X * Built-in unshar and patch functions.
X
X * Built-in uudecode function which will automatically unpack,
X concatenate, and decode multi-part postings.
X
X * Easy remapping of keys with advanced macro definition features.
X
X * Automatic kill & selection of articles based on subject or author.
X
X * User specified presentation sequence of news groups based on the
X news group hierarchy.
X
X * Whole classes of news groups can easily be unsubscribed
X permanently, e.g. talk.all and all.politics
X
X * Related groups can be merged and presented as a single group, e.g.
X comp.emancs and all gnu.emacs groups.
X
X * Blindingly fast 'search for subject'. On my Texas S1500 system,
X nn uses less than 20 seconds to find all articles on a specific
X subject among 64000 articles in all groups!
X
X * News collection and presentation is extremely fast, because nn
X uses its own database on top of the standard news system.
X
X * In a distributed environment, the database can be shared among all
X hosts on the network. Only one daemon is needed on the news server
X for all hosts. This works in a heterogenous environment as well.
X
X * NNTP is also supported (using a local database for speed).
X
XBecause of the database, nn starts almost equally fast (in a few
Xseconds), no matter whether you have 100 or 10000 unread articles!
XThe database takes up some disk space, but dramatically improves speed
Xand functionality. The amount of disk space consumed is approx. 1Mb
Xper 10000 articles.
X
X
X DISTRIBUTION
X ------------
X
XThe package is posted as 22 separate shar archives on comp.sources.unix.
XIt is unpacked by applying /bin/sh to each archive in turn.
XEverything is a little more than 1 Mbyte, including documentation.
X
XIt is also available via anonymous ftp from
X
X host: dkuug.dk (129.142.96.41)
X File: /pub/nn6.4.tar.Z (compressed tar)
X
X
X COPYRIGHT
X ---------
X
XCopyright (c) 1989, 1990 by Kim Fabricius Storm. All rights reserved.
X
XNot derived from licensed software except as stated below.
X
XPermission is granted to anyone to use, modify, and reuse this
Xsoftware for any purpose on any computer system, and to redistribute
Xit freely, subject to the following restrictions:
X
X1. The author is not responsible for the consequences of use of this
X software, no matter how awful, even if they arise from defects in it.
X
X2. The origin of this software must not be misrepresented, either by
X explicit claim or by omission.
X
X3. Altered versions must be plainly marked as such, and must not be
X misrepresented as being the original software.
X
X
XThe following code modules have been incorporated into nn, and the
Xabove copyright notice does not apply to these modules; they include
Xtheir own copyright notices (or have none):
X
Xregexp.c: Copyright (c) 1986 by University of Toronto.
X Written by Henry Spencer.
X
Xunshar.c: No copyright notice.
X Written by K. Greer, S. Shafer, and M. Mauldin
X
Xdecode.c: Derived from a modified Berkeley original posted on
X USENET.
X
Xfullname.c: Copyright (c) 1986 by Rick Adams.
X Derived from the Bnews distribution.
X
Xcontrib/*: Various copyright notices.
X The software available in the contrib/ directory was sent
X to me for inclusion in the nn distribution, because
X the authors think it might be useful to other nn users.
X I have included it *as is*.
X
Xinews/*: NNTP 1.5 mini-inews. Copyrights for NNTP applies.
X The software in the inews/ directory is a stand-alone
X version of the NNTP 1.5.7 mini-inews which has been
X slightly changed to ease configuration when used with nn.
X
XVarious pieces of code which may have their own copyright notices are
Xincluded in the contrib/ and inews/ directories. This software has been
Xsent to me in the hope that it will be useful to somebody else. I
Xhave included it in this spirit, but I take no responsibilities for
Xthis software, and I have no intentions to support it.
X
X
X INSTALLATION
X ------------
X
XThe following files are contained in the `doc' subdirectory:
X
XThe installation procedure is described in the file INSTALLATION.
X
XYou may also find useful information in the files PROBLEMS and NNTP.
X
XThe file NEWS-6.3 describes the major changes from release 6.1 to 6.3.
X
XThe file NEWS-6.4 describes the major changes from release 6.3 to 6.4.
X
X
X BUG REPORTS and SUGGESTIONS
X ---------------------------
X
XPlease send bug reports (and fixes) to the following address:
X nn-bugs@dkuug.dk
X
XYou may also use nn-bugs for suggestions for improvements (missing
Xfeatures in nn are considered to be bugs :-)
X
XThe easiest way to send a bug report is by using the :bug command in nn.
X
X
X NN HAS ITS OWN NEWS GROUP
X -------------------------
X
XWe have an unmoderated news group dedicated to nn: news.software.nn
X
XThe news.software.nn group is used for discussion on all subjects
Xrelated to the nn news reader. This includes, but is not limited to,
Xquestions, answers, ideas, hints, information from the development
Xgroup, patches, etc.
X
XThe news.software.nn group was created in January 1990 after an
Xofficial vote. It may still be missing on parts of the net, so if you
Xdon't get it please check your news feed, and help propagating the
Xnews group to the entire net.
X
X
X ACKNOWLEDGEMENTS
X ----------------
X
XSince the development of nn is now on its fifth year, numerous persons
Xhave contributed to nn with ideas and critisism, have helped me debug
Xthe software by patiently using alpha and beta versions, have provided
Xbug fixes, small and big chunks of code, new configuration files, etc.
X
XMy warm thanks go to Rene Seindal and Wayne Davison for their many
Xcontributions, to Lloyd W. Taylor for his efforts counting the
Xvotes for news.software.nn, and to Paul D. Anderson for running the
Xrelease 6.3 patch server.
X
XI also thank the following persons for their help and contributions:
XPeter Andersen, Jonathan Bayer, Gardner Cohen, Bernie Cosell, P{r
XEmanuelsson, Steven Grady, Miek Grenier, Scott Hankin, Kareth, Mike
XKhaw, Edwin Kremer, Jean-Francois Lamy, Mark Moraes, A. E. Mossberg,
XMark Nagel, Rich Salz, Steve Simmons, Wietse Z. Venema, James A.
XWoods, and Pim Zandbergen.
X
XAnd of course I would like to thank the hundreds of other people who
Xhave reported bugs, given suggestions, provided information, etc.
XForgive me for not listing all your names here, but I hope you
Xunderstand, and that you will continue to contribute your
Xvaluable input to the continued developments. Let us keep nn in the
Xlead!
X
X
XKim Fabricius Storm
XTexas Instruments A/S, Denmark
X
XEmail: storm@texas.dk
XSnail: Marielundvej 46E, DK-2730 Herlev, Denmark
Xtel: +45 42 91 7400 fax: +45 42 91 8400
END_OF_FILE
if test 7714 -ne `wc -c <'README'`; then
echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'MANIFEST' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(10469 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X File Name Archive # Description
X----------------------------------------------------------
XREADME 1 Read this file first
XMANIFEST 1 Packing list
XFILES 22 Extract file names from MANIFEST
XMakefile 21 Makefile for building nn
XSPLITNN1 22 Split nn.1 in four parts.
Xaccount.c 17 Accounting routines
Xactive.c 20 Read active file
Xadmin.c 12 Administration mode (nnadmin)
Xanswer.c 14 Respond/post/mail code
Xarticles.c 17 Incore article fetching and management
Xarticles.h 21 Header file for article management
Xaux.sh 10 Auxiliary script for post/mail
Xback_act.sh 22 Backup active file once a day
Xcollect.c 16 Collect groups and articles in the database
Xconf 1 Directory for s- and m- files
Xconf/m-3b1g.h 22 For 3b1 (unix-pc) with GCC [no networking].
Xconf/m-att3b.h 22 For AT&T 3b2 (with s-usg3-1.h)
Xconf/m-convex.h 21 For Convex.
Xconf/m-dec3100.h 22 For DECstation 3100 (with s-bsd4-2.h)
Xconf/m-gould.h 22 For Gould PN6000 (with s-bsd4-3.h)
Xconf/m-hp9000.h 22 For HP9000 series 320 and 800 (at least)
Xconf/m-i80286.h 22 For Intel 80286 processors [no network support]
Xconf/m-i80386.h 22 For Intel 80386 processors [no network support]
Xconf/m-m680x0.h 22 For 68000 family processors
Xconf/m-m88000.h 22 For Motorola 88000 risc processors
Xconf/m-mips.h 22 For MIPS processors
Xconf/m-pyramid.h 22 For Pyramid (and Targon 35).
Xconf/m-rt6150.h 22 For IBM 6150
Xconf/m-sgi4D.h 22 For Silicon Graphics 4D series.
Xconf/m-sparc.h 22 For SPARC processors
Xconf/m-sun386i.h 22 For 80386 based SUNs [have network support]
Xconf/m-symmetry.h 22 For Sequent Symmetry.
Xconf/m-template.h 21 Template for new machine files.
Xconf/m-vax.h 22 For VAX family
Xconf/s-3b1g.h 22 For 3b1 (unix-pc) with GCC.
Xconf/s-aix221.h 14 For AIX 2.2.1
Xconf/s-aux1-1.h 22 For A/UX 1.1
Xconf/s-bsd4-2.h 20 For 4.2 BSD and Ultrix systems
Xconf/s-bsd4-3.h 22 For 4.3 BSD systems
Xconf/s-dnix5-2.h 22 For dnix 5.2 on DIAB DS90.
Xconf/s-dnix5-3.h 22 For dnix 5.3 on DIAB DS90.
Xconf/s-dynix3-0.h 22 For Dynix 3.0 on Symmetry.
Xconf/s-fortune.h 19 For Fortune 32:16 [read comments in the file]
Xconf/s-hpux.h 6 For HPUX (series 300)
Xconf/s-hpux2-1.h 22 For HPUX 2.1 (series 800)
Xconf/s-hpux3-0.h 22 For HPUX 3.0 (series 800)
Xconf/s-hpux6-5.h 21 For HPUX 6.5 or newer (series 300)
Xconf/s-pyramid.h 22 For Pyramid (and Targon 35).
Xconf/s-sgi4D.h 21 For IRIX 3.1/3.2 [read comments in the file]
Xconf/s-sunos3.h 22 For SunOS 3
Xconf/s-sunos4-0.h 22 For SunOS 4.0
Xconf/s-sys5-tcap.h 22 For system V using termcap.
Xconf/s-sys5.h 20 For most system V based systems.
Xconf/s-template.h 19 Template for new system files.
Xconf/s-texas1500.h 22 For Texas Instruments System 1500.
Xconf/s-tower32.h 22 For NCR tower
Xconf/s-umipsb.h 19 For Mips w/riscos 4.0 or greater
Xconf/s-uport2-2.h 22 For Microport UNIX V.2
Xconf/s-usg3-1.h 22 For most system V systems (obsolete)
Xconf/s-xenix386.h 21 For xenix386 [termcap version].
Xconf/s-xenix386ds.h 22 For Xenix386 2.3.2 w/development system.
Xconfig.h-dist 17 CONFIGURATION FILE, DISTRIBUTED VERSION
Xcontrib 1 Directory for contributed software
Xcontrib/aspell 20 Ispell front-end written in perl
Xcontrib/cn 22 Checknews w/multi-column output
Xcontrib/recmail.c 18 Sample recmail program
Xcontrib/recmail.sh 18 Sample recmail script
Xcvt-help.c 22 Convertion utility for help files
Xdata.h 15 Internal article and group information
Xdb.c 13 Database access and update routines
Xdb.h 20 External database format
Xdebug.h 22 Debugging symbols
Xdecode.c 17 UUdecode engine
Xdigest.c 17 Digest splitting
Xdir.c 19 Directory access
Xdir.h 22 Include file for directory access
Xdoc 1 Directory for documentation files
Xdoc/INSTALLATION 9 INSTALLATION AND CONFIGURATION
Xdoc/NEWS-6.3 18 What's new in release 6.3
Xdoc/NEWS-6.4 16 What's new in release 6.4
Xdoc/NNTP 16 INSTALLATION WITH NNTP or NFS
Xdoc/PROBLEMS 15 KNOWN PROBLEMS AND SOLUTIONS
Xdoc/RELEASE_NOTES 20 Known problems
Xexecute.c 19 Shell command execution
Xexpire.c 15 Database expiration
Xfolder.c 13 Folder menu and file name expansion
Xformat.awk 21 Nroff -man formatter in awk
Xfullname.c 20 Extract full name from /etc/passwd
Xglobal.c 4 Global routines
Xglobal.h 19 Global include file
Xgroup.c 10 Group menu, group overview, and goto-group
Xhelp 1 Directory for online help files
Xhelp/adm.upgrade1 22 Start-up message 1
Xhelp/adm.upgrade2 22 Start-up message 2
Xhelp/adm.upgrade3 22 Start-up message 3
Xhelp/adm.upgrade4 22 Start-up message 4
Xhelp/adm.welcome 22 New user welcome message
Xhelp/help.attr 22 Help on attributes
Xhelp/help.commands 20 Help on commands
Xhelp/help.extended 21 Help on : commands
Xhelp/help.help 22 Help on help
Xhelp/help.map 21 Help on key mapping
Xhelp/help.menu 21 ? in selection mode
Xhelp/help.more 21 ? in reading mode
Xhelp/help.read 12 Help on reading mode
Xhelp/help.set 22 Help on :set commands
Xhelp/help.show 22 Help on :show commands
Xhelp/help.sort 21 Help on menu ordering
Xhelp/help.variables 2 Help on variables
Xhostname.c 20 Generic gethostname() function
Xinews 1 Directory for NNTP 1.5.7 mini-inews
Xinews/Makefile 19 mini-inews makefile
Xinews/Manifest 22 mini-inews manifest
Xinews/README 21 mini-inews read me 2nd
Xinews/README.NN 19 mini-inews read me 1st
Xinews/clientlib.c 16 mini-inews source
Xinews/clientlib.h 22 mini-inews source
Xinews/conf.h 20 mini-inews configuration file
Xinews/inews.c 12 mini-inews source
Xinews/nntp.h 20 mini-inews source
Xinews/version.c 22 mini-inews source
Xinit.c 11 Init file and extended command parsing
Xinit.sample 20 Sample init file
Xinst.sh 18 Installation script
Xkeymap.c 6 Key mapping and command names
Xkeymap.h 19 Key and command names
Xkill.c 11 Kill compilation and processing
Xmacro.c 14 Macro compilation and execution
Xman 1 Directory for user manuals
Xman/nn.1.A 2 nn manual (for users) - part 1
Xman/nn.1.B 7 nn manual (for users) - part 2
Xman/nn.1.C 3 nn manual (for users) - part 3
Xman/nn.1.D 4 nn manual (for users) - part 4
Xman/nnacct.1m 9 nnacct manual (for sysadm)
Xman/nnadmin.1m 8 nnadmin manual (for sysadm)
Xman/nncheck.1 20 nncheck manual (for users)
Xman/nngoback.1 19 nngoback manual (for users)
Xman/nngrab.1 5 nngrab manual (for users)
Xman/nngrep.1 20 nngrep manual (for users)
Xman/nnmaster.8 13 nnmaster manual (for sysadm)
Xman/nnpost.1 21 nnpost manual (for users)
Xman/nnspew.8 21 nnspew manual (for sysadm)
Xman/nnstats.1m 21 nnstats manual (for sysadm)
Xman/nntidy.1 21 nntidy manual (for users)
Xman/nnusage.1m 21 nnusage manual (for sysadm)
Xmaster.c 7 Database manager (nnmaster)
Xmatch.c 20 String/regexp matching
Xmenu.c 6 Article selection menu
Xmenu.h 21 Return values from various modes
Xmore.c 9 Pager (reading mode)
Xnews.c 18 Parsing of news article headers
Xnews.h 21 Article header information
Xnewsrc.c 5 Access and update .newsrc
Xnn.c 14 nn main program
Xnngrab.sh 22 Quick subject search
Xnnmail.c 21 Primitive mailer w/domain addressing
Xnnspew.sh 22 Subject database generator (for nngrab)
Xnnstats.sh 20 Collection and Expiration reports
Xnntp.c 10 NNTP interface library
Xnntp.h 20 NNTP response codes
Xnnusage.sh 22 Usage statistics
Xoptions.c 19 Option parsing (much better than getopt!)
Xoptions.h 21 Header file for option parsing
Xpack_date.c 19 Timestamp generation
Xpack_name.c 3 Pack sender names
Xpack_subject.c 21 Pack subject lines
Xpatchlevel.h 8 Patch level and history
Xprefix.c 16 Generate prefix for scripts.
Xproto.c 19 Locking and message passing
Xproto.h 21 Include file for proto routines
Xregexp.c 8 Regular expression compile and exec
Xregexp.h 1 Include file for regexp usage
Xreroute.c 18 Mail address parsing and rewrite
Xroutes.sample 21 Sample configuration file for nnmail
Xsave.c 15 Article saving, unpacking, etc.
Xsequence.c 5 Group presentation sequence parser
Xsort.c 11 Article menu ordering
Xterm.c 1 Terminal interface library
Xterm.h 21 Include file for terminal interface
Xunshar.c 18 Unshar pre-processor
Xupgrade_rc.sh 22 .nn/rc to .newsrc converter
Xusercheck.c 22 Check uid during installation
Xvararg.h 21 Faked and real varargs.h encapsulation
Xvariable.c 12 Variable management
Xxmakefile 18 Skeleton for ymakefile
END_OF_FILE
if test 10469 -ne `wc -c <'MANIFEST'`; then
echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test ! -d 'conf' ; then
echo shar: Creating directory \"'conf'\"
mkdir 'conf'
fi
if test ! -d 'contrib' ; then
echo shar: Creating directory \"'contrib'\"
mkdir 'contrib'
fi
if test ! -d 'doc' ; then
echo shar: Creating directory \"'doc'\"
mkdir 'doc'
fi
if test ! -d 'help' ; then
echo shar: Creating directory \"'help'\"
mkdir 'help'
fi
if test ! -d 'inews' ; then
echo shar: Creating directory \"'inews'\"
mkdir 'inews'
fi
if test ! -d 'man' ; then
echo shar: Creating directory \"'man'\"
mkdir 'man'
fi
if test -f 'regexp.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'regexp.h'\"
else
echo shar: Extracting \"'regexp.h'\" \(731 characters\)
sed "s/^X//" >'regexp.h' <<'END_OF_FILE'
X/*
X * Definitions etc. for regexp(3) routines.
X *
X * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof],
X * not the System V one.
X */
X
X#define NSUBEXP 10
Xtypedef struct regexp {
X char *startp[NSUBEXP];
X char *endp[NSUBEXP];
X char regstart; /* Internal use only. */
X char reganch; /* Internal use only. */
X char *regmust; /* Internal use only. */
X int regmlen; /* Internal use only. */
X char program[1]; /* Unwarranted chumminess with compiler. */
X} regexp;
X
X
X/*
X * The first byte of the regexp internal "program" is actually this magic
X * number; the start node begins in the second byte.
X */
X#define MAGIC 0234
X
Xextern regexp *regcomp();
Xextern int regexec();
Xextern void regsub();
Xextern void regerror();
X
END_OF_FILE
if test 731 -ne `wc -c <'regexp.h'`; then
echo shar: \"'regexp.h'\" unpacked with wrong size!
fi
# end of 'regexp.h'
fi
if test -f 'term.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'term.c'\"
else
echo shar: Extracting \"'term.c'\" \(27619 characters\)
sed "s/^X//" >'term.c' <<'END_OF_FILE'
X/*
X * (c) Copyright 1990, Kim Fabricius Storm. All rights reserved.
X *
X * Terminal interface.
X */
X
X#include <signal.h>
X#include <errno.h>
X#include "config.h"
X#include "term.h"
X#include "keymap.h"
X
X#ifdef RESIZING
X#include <sys/ioctl.h> /* for TIOCGWINSZ */
X#ifdef SYSV_RESIZING
X#include <sys/stream.h>
X#include <sys/ptem.h>
X#endif
X
Xint s_resized;
X#endif
X
Xexport char *term_name = NULL;
Xexport int show_current_time = 1;
Xexport int conf_dont_sleep = 0;
Xexport int prompt_length;
Xexport int terminal_speed;
Xexport int slow_speed = 1200;
Xexport int any_message = 0;
Xexport int flow_control = 1;
Xexport int use_visible_bell = 1; /* if supported by terminal */
X
Xexport key_type help_key = '?';
Xexport key_type comp1_key = SP;
Xexport key_type comp2_key = TAB;
Xexport key_type erase_key, kill_key;
Xexport key_type delword_key = CONTROL_('W');
X
Xstatic char bell_str[256] = "\007";
X
X#ifdef USE_TERMINFO
X
X#include <curses.h>
X#ifndef auto_left_margin
X#include <term.h>
X#endif
X
X#define HAS_CAP(str) (str && *str)
X
Xextern char *tgoto(); /* some systems don't have this in term.h */
X
X#else
X
X#define USE_TERMCAP
X
Xchar *tgoto();
Xchar PC;
Xchar *BC, *UP;
Xshort ospeed;
X
Xstatic char XBC[64], XUP[64];
Xstatic char enter_ca_mode[64], exit_ca_mode[64];
Xstatic char cursor_home[64];
Xstatic char cursor_address[64];
Xstatic char clear_screen[64];
Xstatic char clr_eol[64];
Xstatic char clr_eos[64];
Xstatic char enter_standout_mode[64], exit_standout_mode[64];
Xstatic char enter_underline_mode[64], exit_underline_mode[64];
Xstatic char key_down[64], key_up[64], key_right[64], key_left[64];
X
Xint magic_cookie_glitch; /* magic cookie size */
X
X#define putp(str) tputs(str, 0, outc)
X
X#define HAS_CAP(str) (*str)
X
Xstatic outc(c)
X{
X putchar(c);
X}
X
X#endif /* USE_TERMCAP */
X
Xint Lines, Columns; /* screen size */
Xint cookie_size; /* size of magic cookie */
Xint two_cookies; /* space needed to enter&exit standout mode */
Xint STANDOUT; /* terminal got standout mode */
Xint WRAP; /* terminal got automatic margins */
X
X#ifdef HAVE_TERMIO
X
X#define KEY_BURST 50 /* read bursts of 50 chars (or timeout after 100 ms) */
X
X#ifdef USE_TERMCAP
X#include <termio.h>
X#endif
X
X#undef CBREAK
X
Xstatic struct termio norm_tty, raw_tty;
X
X#define IntrC norm_tty.c_cc[VINTR]
X#define EraseC norm_tty.c_cc[VERASE]
X#define KillC norm_tty.c_cc[VKILL]
X#define SuspC CONTROL_('Z') /* norm_tty.c_cc[SWTCH] */
X
X#else /* V7/BSD TTY DRIVER */
X
X#include <sgtty.h>
X
Xstatic struct sgttyb norm_tty, raw_tty;
Xstatic struct tchars norm_chars;
X
X#define IntrC norm_chars.t_intrc
X#define EraseC norm_tty.sg_erase
X#define KillC norm_tty.sg_kill
X
X#ifdef TIOCGLTC
Xstatic struct ltchars spec_chars;
X#define SuspC spec_chars.t_suspc
X#else
X#define SuspC CONTROL_('Z')
X#endif
X
X#endif
X
X#ifdef USE_TERMCAP
X
Xopt_cap(cap, buf)
Xchar *cap, *buf;
X{
X char *tgetstr();
X
X *buf = NUL;
X return tgetstr(cap, &buf) != NULL;
X}
X
Xget_cap(cap, buf)
Xchar *cap, *buf;
X{
X if (!opt_cap(cap, buf))
X user_error("TERMCAP entry for %s has no '%s' capability",
X term_name, cap);
X}
X
X#endif /* USE_TERMCAP */
X
Xstatic int multi_keys = 0;
X
Xstatic struct multi_key {
X key_type *cur_key;
X key_type *keys;
X key_type code;
X} multi_key_list[MULTI_KEYS];
X
Xenter_multi_key(code, keys)
Xint code;
Xkey_type *keys;
X{
X register i;
X
X if (strlen((char *)keys) == 1)
X /* will ignore arrow keys overlaying these keys */
X if (*keys == NL || *keys == CR ||
X *keys == erase_key || *keys == kill_key ||
X *keys == IntrC) return;
X
X /* lookup code to see if it is already defined... */
X for (i = 0; i < multi_keys; i++)
X if (multi_key_list[i].code == (key_type)code)
X goto replace_key;
X
X i = multi_keys++;
X
X /* now i points to matching or empty slot */
X if (i >= MULTI_KEYS) {
X /* should never happen */
X log_entry('E', "too many multi keys");
X return;
X }
X
X replace_key:
X
X multi_key_list[i].keys = keys;
X multi_key_list[i].code = code;
X}
X
Xdump_multi_keys()
X{
X register i;
X register key_type *cp;
X
X clrdisp();
X pg_init(0, 1);
X
X for (i = 0; i < multi_keys; i++) {
X if (pg_next() < 0) break;
X printf("%d\t%s\t", i, key_name(multi_key_list[i].code));
X for (cp = multi_key_list[i].keys; *cp; cp++) {
X putchar(SP);
X fputs(key_name(*cp), stdout);
X }
X }
X
X pg_end();
X}
X
X
X#ifdef RESIZING
X
Xsig_type catch_winch()
X{
X struct winsize winsize;
X
X (void) signal(SIGWINCH, catch_winch);
X if (ioctl(0, TIOCGWINSZ, &winsize) >= 0
X && (winsize.ws_row != Lines || winsize.ws_col != Columns)) {
X Lines = winsize.ws_row;
X Columns = winsize.ws_col;
X s_redraw = 1;
X s_resized = 1;
X }
X}
X#endif /* RESIZING */
X
X#ifdef SV_INTERRUPT
X#ifdef NO_SIGINTERRUPT
Xstatic siginterrupt(signo, on)
X{
X struct sigvec sv;
X sv.sv_handler = signal (signo, SIG_DFL);
X sv.sv_mask = 0;
X sv.sv_flags = on ? SV_INTERRUPT : 0;
X sigvec (signo, &sv, 0);
X}
X#endif
X#endif
X
Xstatic unsigned sp_table[] = {
X B9600, 960,
X#ifdef B19200
X B19200, 1920,
X#else
X#ifdef EXTA
X EXTA, 1920,
X#endif
X#endif
X#ifdef B38400
X B38400, 3840,
X#else
X#ifdef EXTB
X EXTB, 3840,
X#endif
X#endif
X B1200, 120,
X B2400, 240,
X B4800, 480,
X B300, 30,
X 0, 0
X};
X
Xstatic set_term_speed(sp)
Xregister unsigned long sp;
X{
X register unsigned *tp;
X
X for (tp = sp_table; *tp; tp += 2)
X if (*tp == sp) {
X terminal_speed = tp[1];
X return;
X }
X
X terminal_speed = 30;
X}
X
Xinit_term()
X{
X#ifdef USE_TERMCAP
X char tbuf[1024];
X#endif
X
X if ((term_name = getenv("TERM")) == NULL)
X user_error("No TERM variable in enviroment");
X
X#ifdef HAVE_TERMIO
X ioctl(0, TCGETA, &norm_tty);
X#else
X ioctl(0, TIOCGETP, &norm_tty);
X#endif
X
X#ifdef USE_TERMINFO
X setupterm((char *)NULL, 1, (int *)NULL);
X Columns = columns;
X Lines = lines;
X cookie_size = magic_cookie_glitch;
X WRAP = auto_right_margin;
X if (use_visible_bell && HAS_CAP(flash_screen))
X strcpy(bell_str, flash_screen);
X else if (HAS_CAP(bell))
X strcpy(bell_str, bell);
X if (! HAS_CAP(cursor_home))
X cursor_home = copy_str(tgoto(cursor_address, 0, 0));
X#else
X
X if (tgetent(tbuf, term_name) <= 0)
X user_error("Unknown terminal type: %s", term_name);
X
X if (opt_cap("bc", XBC)) BC = XBC;
X if (opt_cap("up", XUP)) UP = XUP;
X opt_cap("pc", cursor_address); /* temp. usage */
X PC = cursor_address[0];
X
X get_cap("cm", cursor_address);
X if (!opt_cap("ho", cursor_home))
X strcpy(cursor_home, tgoto(cursor_address, 0, 0));
X
X get_cap("cl", clear_screen);
X get_cap("ce", clr_eol);
X opt_cap("cd", clr_eos);
X
X#ifdef RESIZING
X {
X struct winsize winsize;
X
X if (ioctl(0, TIOCGWINSZ, &winsize) >= 0
X && winsize.ws_row != 0 && winsize.ws_col != 0) {
X Lines = winsize.ws_row;
X Columns = winsize.ws_col;
X (void) signal(SIGWINCH, catch_winch);
X#ifdef SV_INTERRUPT
X siginterrupt(SIGWINCH, 1); /* make read from tty interruptable */
X#endif /* SV_INTERRUPT */
X }
X }
X if (Lines == 0 || Columns == 0) {
X#endif /* RESIZING */
X Lines = tgetnum("li");
X Columns = tgetnum("co");
X#ifdef RESIZING
X }
X#endif /* RESIZING */
X
X opt_cap("so", enter_standout_mode);
X opt_cap("se", exit_standout_mode);
X
X opt_cap("us", enter_underline_mode);
X opt_cap("ue", exit_underline_mode);
X
X opt_cap("kd", key_down);
X opt_cap("ku", key_up);
X opt_cap("kr", key_right);
X opt_cap("kl", key_left);
X
X cookie_size = tgetnum("sg");
X
X WRAP = tgetflag("am");
X
X opt_cap("ti", enter_ca_mode);
X opt_cap("te", exit_ca_mode);
X
X if (!use_visible_bell || !opt_cap("vb", bell_str))
X if (!opt_cap("bl", bell_str))
X strcpy(bell_str, "\007");
X
X#endif /* !USE_TERMINFO */
X
X STANDOUT = HAS_CAP(enter_standout_mode);
X if (STANDOUT) {
X if (cookie_size < 0) cookie_size = 0;
X two_cookies = 2 * cookie_size;
X } else
X cookie_size = two_cookies = 0;
X
X
X raw_tty = norm_tty;
X
X#ifdef HAVE_TERMIO
X raw_tty.c_iflag &= ~(BRKINT|INLCR|ICRNL|IGNCR);
X raw_tty.c_iflag |= IGNBRK|IGNPAR|ISTRIP;
X raw_tty.c_oflag &= ~OPOST;
X raw_tty.c_lflag &= ~(ISIG|ICANON|XCASE|ECHO|NOFLSH);
X
X /* read a maximum of 10 characters in one burst; timeout in 1-200 ms */
X raw_tty.c_cc[VEOF] = KEY_BURST;
X raw_tty.c_cc[VEOL] = ((raw_tty.c_cflag & CBAUD) > B1200) ? 1 : 2;
X set_term_speed((unsigned long)(raw_tty.c_cflag & CBAUD));
X#else
X ioctl(0, TIOCGETC, &norm_chars);
X
X#ifdef TIOCGLTC
X ioctl(0, TIOCGLTC, &spec_chars);
X#endif
X
X ospeed = norm_tty.sg_ospeed;
X set_term_speed((unsigned long)ospeed);
X
X raw_tty.sg_flags &= ~ECHO;
X#ifdef CBREAK
X#ifdef SV_INTERRUPT /* make read from tty interruptable */
X siginterrupt(SIGTSTP, 1); /* this is necessary to redraw screen */
X#endif
X raw_tty.sg_flags |= CBREAK;
X#else
X raw_tty.sg_flags |= RAW;
X#endif
X
X#ifdef SV_INTERRUPT
X siginterrupt(SIGALRM, 1); /* make read from tty interruptable */
X#endif
X#endif
X
X erase_key = (key_type)EraseC;
X kill_key = (key_type)KillC;
X
X if (HAS_CAP(key_down))
X enter_multi_key(K_down_arrow, (key_type *)key_down);
X if (HAS_CAP(key_up))
X enter_multi_key(K_up_arrow, (key_type *)key_up);
X if (HAS_CAP(key_right))
X enter_multi_key(K_right_arrow, (key_type *)key_right);
X if (HAS_CAP(key_left))
X enter_multi_key(K_left_arrow, (key_type *)key_left);
X
X visual_on();
X}
X
Xhome()
X{
X putp(cursor_home);
X}
X
Xstatic int curxy_c = -1, curxy_l, savxy_c = -1, savxy_l;
X
Xsave_xy()
X{
X savxy_c = curxy_c; savxy_l = curxy_l;
X}
X
Xrestore_xy()
X{
X if (savxy_c < 0) return;
X gotoxy(savxy_c, savxy_l); fl;
X}
X
Xgotoxy(c, l)
Xint c, l;
X{
X curxy_c = c; curxy_l = l;
X putp(tgoto(cursor_address, c, l));
X}
X
Xclrdisp()
X{
X#ifdef USE_TERMINFO
X putp(clear_screen); /* tputs is broken on UNISYS I've been told */
X#else
X tputs(clear_screen, Lines, outc);
X#endif
X curxy_c = savxy_c = -1;
X}
X
Xclrline()
X{
X putp(clr_eol);
X fl;
X}
X
Xclrpage(lineno)
Xregister int lineno;
X{
X register int olineno= lineno;
X
X if (HAS_CAP(clr_eos)) {
X#ifdef USE_TERMINFO
X putp(clr_eos);
X#else
X tputs(clr_eos, Lines - lineno, outc);
X#endif
X } else {
X clrline();
X lineno++;
X for (; lineno < Lines; lineno++) {
X gotoxy(0, lineno);
X putp(clr_eol);
X }
X gotoxy(0, olineno);
X fl;
X }
X}
X
Xstatic char so_buf[512], *so_p;
Xstatic int so_c, so_l, so_b, so_active = 0;
X
Xso_gotoxy(c, l, blank)
X{
X if (!STANDOUT && c >= 0) {
X if (l >= 0) gotoxy(c, l);
X return 0;
X }
X
X so_active++;
X so_c = c;
X so_l = l;
X so_b = blank;
X so_p = so_buf;
X *so_p = NUL;
X
X return 1; /* not really true if not standout & c < 0 */
X}
X
X/*VARARGS*/
Xso_printf(va_alist)
Xva_dcl
X{
X use_vararg;
X
X start_vararg;
X so_vprintf(va_args1toN);
X end_vararg;
X}
X
Xso_vprintf(va_tail)
Xva_tdcl
X{
X char *fmt;
X
X fmt = va_arg1(char *);
X
X if (!so_active) {
X vprintf(fmt, va_args2toN);
X return;
X }
X
X vsprintf(so_p, fmt, va_args2toN);
X while (*so_p) so_p++;
X}
X
Xso_end()
X{
X int len;
X
X if (!so_active) return;
X
X if (so_l >= 0) {
X
X len = so_p - so_buf + two_cookies;
X
X if (so_c < 0)
X so_c = Columns - len - 2;
X if (so_c < 0) so_c = 0;
X
X if (len + so_c >= Columns) {
X len = Columns - so_c - two_cookies;
X so_buf[len] = NUL;
X }
X
X if (cookie_size) {
X gotoxy(so_c + len - cookie_size, so_l);
X putp(exit_standout_mode);
X }
X
X gotoxy(so_c, so_l);
X
X }
X
X if ((so_b & 1) && (!STANDOUT || !cookie_size)) putchar(SP);
X
X if (STANDOUT) putp(enter_standout_mode);
X
X fputs(so_buf, stdout);
X
X if (STANDOUT) putp(exit_standout_mode);
X
X if ((so_b & 2) && (!STANDOUT || !cookie_size)) putchar(SP);
X
X so_active = 0;
X}
X
X
X/*VARARGS*/
Xso_printxy(va_alist)
Xva_dcl
X{
X int k, l;
X use_vararg;
X
X start_vararg;
X
X k = va_arg1(int);
X l = va_arg2(int);
X
X so_gotoxy(k, l, 0);
X so_vprintf(va_args3toN);
X so_end();
X
X end_vararg;
X}
X
Xunderline(on)
X{
X if (cookie_size) return 0;
X if (! HAS_CAP(enter_underline_mode)) return 0;
X putp(on ? enter_underline_mode : exit_underline_mode);
X return 1;
X}
X
Xhighlight(on)
X{
X if (cookie_size) return 0;
X if (! HAS_CAP(enter_standout_mode)) return 0;
X putp(on ? enter_standout_mode : exit_standout_mode);
X return 1;
X}
X
Xstatic int is_visual = 0;
Xstatic int is_raw = 0;
X
X#ifdef HAVE_TERMIO
X#define RAW_MODE_ON ioctl(0, TCSETAF, &raw_tty)
X#define RAW_MODE_OFF ioctl(0, TCSETAF, &norm_tty)
X#else
X#define RAW_MODE_ON ioctl(0, TIOCSETP, &raw_tty)
X#define RAW_MODE_OFF ioctl(0, TIOCSETP, &norm_tty)
X#endif
X
Xvisual_on()
X{
X if (HAS_CAP(enter_ca_mode)) {
X putp(enter_ca_mode);
X is_visual = 1;
X }
X}
X
Xvisual_off()
X{
X int was_raw = is_raw;
X
X if (term_name == NULL) return 0;
X
X if (is_visual && HAS_CAP(exit_ca_mode)) putp(exit_ca_mode), fl;
X is_visual = 0;
X
X is_raw = 1;
X unset_raw();
X
X return was_raw;
X}
X
X#ifdef CBREAK
Xraw()
X{
X if (is_raw == 1)
X return;
X is_raw = 1;
X RAW_MODE_ON;
X}
X
Xno_raw()
X{
X return 0;
X}
X
Xunset_raw()
X{
X if (is_raw == 0)
X return 0;
X RAW_MODE_OFF;
X is_raw = 0;
X return 1;
X}
X
X#else /* not CBREAK */
Xstatic int must_set_raw = 1;
X
Xraw()
X{
X if (!flow_control) {
X if (!must_set_raw) return;
X must_set_raw = 0;
X }
X
X if (is_raw) return;
X
X RAW_MODE_ON;
X
X is_raw++;
X}
X
Xno_raw()
X{
X if (!flow_control) return 0;
X
X if (!is_raw) return 0;
X
X RAW_MODE_OFF;
X
X is_raw = 0;
X
X return 1;
X}
X
Xunset_raw()
X{
X int was_raw = is_raw;
X
X if (is_raw) {
X RAW_MODE_OFF;
X is_raw = 0;
X }
X
X if (!flow_control)
X must_set_raw = 1;
X return was_raw;
X}
X
X#endif /* CBREAK */
X
Xstatic int do_flush_input = 0;
X
Xflush_input()
X{
X#ifdef HAVE_TERMIO
X ioctl(0, TCFLSH, 0);
X do_flush_input = 1;
X#else
X#ifdef FREAD
X int arg = FREAD;
X ioctl(0, TIOCFLUSH, &arg);
X#else
X ioctl(0, TIOCFLUSH, 0);
X#endif
X#endif
X}
X
Xint enable_stop = 1;
X
X#ifndef KEY_BURST
X
Xstatic int alarm_on = 0;
X
Xstatic mk_timeout()
X{
X alarm_on = 0;
X}
X
X#endif
X
Xstatic int do_macro_processing = 1;
X
Xget_c()
X{
X key_type c;
X int any_multi, key_cnt, mc;
X register struct multi_key *mk;
X register int i;
X#ifdef KEY_BURST
X static char cbuf[KEY_BURST], *cp;
X static int n = 0;
X
X if (do_flush_input) {
X do_flush_input = 0;
X n = 0;
X }
X#else
X int n;
X key_type first_key;
X#endif
X
X next_key:
X if (s_hangup)
X return K_interrupt;
X
X#ifdef RESIZING
X if (s_resized) {
X s_resized = 0;
X return GETC_COMMAND | K_REDRAW;
X }
X#endif
X
X if (do_macro_processing)
X switch (m_getc(&mc)) {
X case 0:
X break;
X case 1:
X return mc;
X case 2:
X return K_interrupt;
X }
X
X for (i = multi_keys, mk = multi_key_list; --i >= 0; mk++)
X mk->cur_key = mk->keys;
X key_cnt = 0;
X
X#ifdef KEY_BURST
X if (n <= 0) {
X n = read(0, cbuf, KEY_BURST);
X if (n < 0 && errno != EINTR) s_hangup++;
X if (n <= 0) return K_interrupt;
X cp = cbuf;
X }
X
X while (--n >= 0) {
X c = (key_type)*cp++;
X#else
X
X while ((n = read(0, (char *)&c, 1)) > 0) {
X c &= 0177; /* done by ISTRIP on USG systems */
X#endif
X
X if (c == CONTROL_('Q') || c == CONTROL_('S'))
X continue;
X
X any_multi = 0;
X for (i = multi_keys, mk = multi_key_list; --i >= 0; mk++)
X if (mk->cur_key) {
X if (*(mk->cur_key)++ == c) {
X if (*(mk->cur_key) == NUL) {
X c = mk->code;
X goto got_char;
X }
X any_multi++;
X } else
X mk->cur_key = NUL;
X }
X
X if (any_multi) {
X#ifndef KEY_BURST
X if (key_cnt == 0) {
X first_key = c;
X alarm_on = 1;
X signal(SIGALRM, mk_timeout);
X MICRO_ALARM();
X }
X#endif
X key_cnt++;
X continue;
X }
X if (key_cnt == 0)
X goto got_char;
X
X ding();
X flush_input();
X goto next_key;
X }
X
X#ifdef CBREAK
X if (s_redraw) {
X s_redraw = 0;
X return GETC_COMMAND | K_REDRAW;
X }
X#endif
X
X#ifndef KEY_BURST
X if (n < 0) {
X if (errno != EINTR) s_hangup++;
X return K_interrupt;
X }
X#endif
X
X#ifdef RESIZING
X if (s_resized) {
X s_resized = 0;
X return GETC_COMMAND | K_REDRAW;
X }
X#endif
X
X#ifndef KEY_BURST
X if (n < 0 && key_cnt)
X c = first_key;
X#endif
X
Xgot_char:
X
X#ifndef KEY_BURST
X if (alarm_on) {
X alarm(0);
X alarm_on = 0;
X }
X#endif
X
X c = global_key_map[c];
X
X#ifndef CBREAK
X if (c == SuspC) {
X if (!enable_stop) goto next_key;
X if (suspend_nn())
X return GETC_COMMAND | K_REDRAW;
X else
X goto next_key;
X }
X
X if (c == IntrC) c = K_interrupt;
X#endif
X return (int)c;
X}
X
X
X/*
X * read string with completion, pre-filling, and break on first char
X *
X * dflt is a string that will be use as default value if the
X * space bar is hit as the first character.
X *
X * prefill pre-fill the buffer with .... and print it
X *
X * break_chars return immediately if one of these characters
X * is entered as the first character.
X *
X * completion is a function that will fill the buffer with a value
X * see the group_completion and file_completion routines
X * for examples.
X */
X
Xchar *get_s(dflt, prefill, break_chars, completion)
Xchar *dflt, *prefill, *break_chars;
Xfct_type completion;
X{
X static char buf[GET_S_BUFFER];
X register char *cp;
X register int i, c, lastc;
X char *ret_val = buf;
X int comp_used, comp_len;
X int ostop, max, did_help;
X int hit_count;
X
X switch (m_gets(buf)) {
X case 0:
X break;
X case 1:
X return buf;
X case 2:
X return NULL;
X }
X
X ostop = enable_stop;
X enable_stop = 0;
X do_macro_processing = 0;
X hit_count = 0;
X
X max = Columns - prompt_length;
X
X if (max >= FILENAME) max = FILENAME-1;
X
X i = comp_len = comp_used = did_help = 0;
X
X if (prefill && prefill[0]) {
X while (c = *prefill++) {
X if (i == max) break;
X
X putchar(c);
X buf[i] = c;
X i++;
X }
X fl;
X }
X
X if (dflt && *dflt == NUL)
X dflt = NULL;
X
X if (break_chars && *break_chars == NUL)
X break_chars = NULL;
X
X c = NUL;
X for(;;) {
X lastc = c;
X c = get_c();
X if (c & GETC_COMMAND) continue;
X
X kill_prefill_hack:
X
X hit_count++;
X
X if (i == 0) {
X if (c == comp1_key && dflt) {
X while ((c = *dflt++) != NUL && i < max) {
X putchar(c);
X buf[i] = c;
X i++;
X }
X fl;
X dflt = NULL;
X continue;
X }
X if (cp = break_chars) {
X while (*cp)
X if (*cp++ == c) {
X buf[0] = c;
X buf[1] = NUL;
X goto out;
X }
X }
X }
X
X if (completion != NULL_FCT) {
X if (comp_used && c == erase_key) {
X CALL(completion)(buf, -1);
X if (did_help) { clrmsg(i); did_help = 0; }
X if (comp_len) {
X i -= comp_len;
X while (--comp_len >= 0) putchar(BS);
X clrline();
X }
X comp_len = comp_used = 0;
X if (lastc == help_key) goto no_completion;
X continue;
X }
X
X if (c == comp1_key || c == comp2_key || c == help_key) {
X if (!comp_used || c == comp2_key ||
X (c == help_key && lastc != c)) {
X buf[i] = NUL;
X if ((comp_used = CALL(completion)(buf, i)) == 0) {
X ding();
X continue;
X }
X if (comp_used < 0) {
X comp_used = 0;
X goto no_completion;
X }
X comp_len = 0;
X }
X if (c == help_key) {
X if (CALL(completion)((char *)NULL, 1)) {
X gotoxy(prompt_length+i, prompt_line); fl;
X did_help = 1;
X }
X continue;
X }
X
X if (comp_len) {
X i -= comp_len;
X while (--comp_len >= 0) putchar(BS);
X clrline();
X comp_len = 0;
X }
X
X switch ( CALL(completion)((char *)NULL, 0) ) {
X
X case 0: /* no possible completion */
X comp_used = 0;
X ding();
X continue;
X
X case 2: /* whole new alternative */
X while (--i >= 0) putchar(BS);
X clrline();
X /* fall thru */
X
X case 1: /* completion */
X comp_len = i;
X while (c = buf[i]) {
X if (i == max) break;
X putchar(c);
X i++;
X }
X fl;
X comp_len = i - comp_len;
X continue;
X }
X }
X
X if (comp_used) {
X CALL(completion)(buf, -1);
X if (did_help) clrmsg(i);
X comp_len = comp_used = 0;
X }
X }
X
X no_completion:
X
X if (c == CR || c == NL) {
X buf[i] = NUL;
X break;
X }
X
X if (c == erase_key) {
X if (i <= 0) continue;
X i--;
X putchar(BS);
X putchar(' ');
X putchar(BS);
X fl;
X continue;
X }
X
X if (c == delword_key) {
X if (i <= 0) continue;
X buf[i-1] = 'X';
X while (i > 0 && isalnum(buf[i-1])) { putchar(BS); i--; }
X clrline();
X continue;
X }
X
X if (c == kill_key) {
X while (i > 0) { putchar(BS); i--; }
X clrline();
X if (hit_count == 1 && dflt) {
X c = comp1_key;
X goto kill_prefill_hack;
X }
X continue;
X }
X
X if (c == K_interrupt) {
X ret_val = NULL;
X break;
X }
X
X if (!isascii(c) || !isprint(c)) continue;
X
X if (i == max) continue;
X
X if (i > 0 && buf[i-1] == '/' && (c == '/' || c == '+')) {
X while (i > 0) { putchar(BS); i--; }
X clrline();
X }
X
X putchar(c);
X fl;
X
X buf[i] = c;
X i++;
X }
X out:
X enable_stop = ostop;
X do_macro_processing = 1;
X return ret_val;
X}
X
Xexport int list_offset = 0;
X
Xlist_completion(str)
Xchar *str;
X{
X static int cols, line;
X
X if (str == NULL) {
X cols = Columns;
X line = prompt_line + 1;
X
X gotoxy(0, line);
X clrpage(line);
X return 1;
X }
X
X str += list_offset;
X
X for (;;) {
X cols -= strlen(str);
X if (cols >= 0) {
X printf("%s%s", str, cols > 0 ? " " : "");
X cols--;
X return 1;
X }
X if (line >= Lines - 1) return 0;
X line++;
X cols = Columns;
X gotoxy(0, line);
X if (line == Lines - 1) cols--;
X }
X}
X
Xyes(must_answer)
Xint must_answer;
X{
X int c, help = 1, in_macro = 0;
X
X switch (m_yes()) {
X case 0:
X break;
X case 1:
X return 0;
X case 2:
X return 1;
X case 3:
X do_macro_processing = 0;
X in_macro++;
X break;
X }
X
X for (;;) {
X if (!is_raw) {
X raw();
X c = get_c();
X unset_raw();
X } else
X c = get_c();
X
X if (c == 'y' || c == 'Y') {
X c = 1;
X break;
X }
X
X if (must_answer == 0 && (c == SP || c == CR || c == NL)) {
X c = 1;
X break;
X }
X
X if (c == 'n' || c == 'N') {
X c = 0;
X break;
X }
X if (c == K_interrupt) {
X c = -1;
X break;
X }
X if (help) {
X fputs(" y=YES n=NO", stdout);
X prompt_length += 11;
X help = 0;
X }
X }
X
X if (in_macro) {
X if (c < 0) m_break();
X do_macro_processing = 1;
X }
X
X return c;
X}
X
X
Xding()
X{
X putp(bell_str);
X fl;
X}
X
X
Xdisplay_file(name, modes)
Xchar *name;
Xint modes;
X{
X FILE *f;
X register c, stand_on;
X int linecnt, headln_cnt, hdline, no_conf;
X char headline[128];
X import char *help_directory;
X
X headline[0] = 0;
X hdline = 0;
X no_conf = 0;
X
X headln_cnt = -1;
X
X if (modes & CLEAR_DISPLAY) {
X gotoxy(0,0);
X clrdisp();
X }
X
X linecnt = Lines - 1;
X
Xchain:
X
X f = open_file(relative(help_directory, name), OPEN_READ);
X if (f == NULL)
X printf("\r\n\nFile %s is not available\n\n", name);
X else {
X stand_on = 0;
X
X while ((c = getc(f)) != EOF) {
X#ifdef HAVE_JOBCONTROL
X if (s_redraw) {
X no_conf = 1;
X break;
X }
X#endif
X no_conf = 0;
X if (c == '\1') {
X if (STANDOUT) {
X putp(stand_on ? exit_standout_mode : enter_standout_mode);
X stand_on = !stand_on;
X }
X continue;
X }
X if (c == '\2') {
X headln_cnt = 0;
X continue;
X }
X if (c == '\3') {
X headln_cnt = 0;
X while ((c = getc(f)) != EOF && c != NL)
X headline[headln_cnt++] = c;
X headline[headln_cnt++] = NUL;
X name = headline;
X fclose(f);
X goto chain;
X }
X if (c == '\4') {
X printf("%s", version_id);
X continue;
X }
X
X if (headln_cnt >= 0)
X headline[headln_cnt++] = c;
X
X if (hdline) {
X puts(headline);
X putchar(CR);
X hdline = 0;
X linecnt--;
X }
X
X putchar(c);
X if (c == NL) {
X putchar(CR);
X if (headln_cnt >= 0) {
X headline[--headln_cnt] = 0;
X headln_cnt = -1;
X }
X if (--linecnt == 0) {
X no_conf = 1;
X if (any_key(0) == K_interrupt)
X break;
X linecnt = Lines - 1;
X if (modes & CLEAR_DISPLAY) {
X gotoxy(0,0);
X clrdisp();
X }
X hdline = headline[0];
X }
X }
X }
X
X if (stand_on) putp(exit_standout_mode);
X fclose(f);
X }
X
X prompt_line = Lines-1; /* move prompt to last line */
X
X if (!no_conf && (modes & CONFIRMATION))
X any_key(prompt_line);
X}
X
X
X/*VARARGS*/
Xuser_error(va_alist)
Xva_dcl
X{
X char *fmt;
X use_vararg;
X
X unset_raw();
X clrdisp();
X fl;
X
X start_vararg;
X fmt = va_arg1(char *);
X
X vprintf(fmt, va_args2toN);
X putchar(NL);
X
X end_vararg;
X nn_exit(1);
X}
X
X/*VARARGS*/
Xmsg(va_alist)
Xva_dcl
X{
X use_vararg;
X
X start_vararg;
X vmsg(va_args1toN);
X end_vararg;
X}
X
Xvmsg(va_tail)
Xva_tdcl
X{
X static char errmsg[512] = "";
X char *fmt;
X
X fmt = va_arg1(char *);
X
X if (fmt) vsprintf(errmsg, fmt, va_args2toN);
X
X gotoxy(0, Lines-1);
X fputs(errmsg, stdout);
X clrline();
X any_message = 1;
X
X gotoxy(prompt_length, prompt_line);
X fl;
X}
X
Xclrmsg(col)
Xint col;
X{
X gotoxy(0, prompt_line + 1);
X clrpage(prompt_line + 1);
X if (col >= 0)
X gotoxy(prompt_length + col, prompt_line);
X fl;
X any_message = 0;
X}
X
X
X/*VARARGS*/
Xprompt(va_alist)
Xva_dcl
X{
X register char *cp;
X int stand_on;
X char *fmt;
X static char cur_p[FILENAME];
X static char saved_p[FILENAME];
X use_vararg;
X
X start_vararg;
X
X fmt = va_arg1(char *);
X
X if (fmt == P_VERSION) {
X gotoxy(0, prompt_line + 1);
X printf("Release %s ", version_id);
X clrline();
X any_message++;
X
X if (prompt_line >= 0)
X gotoxy(prompt_length, prompt_line);
X goto out;
X }
X
X if (fmt == P_SAVE) {
X strcpy(saved_p, cur_p);
X goto out;
X }
X
X if (fmt == P_RESTORE)
X strcpy(cur_p, saved_p);
X
X if (prompt_line >= 0)
X gotoxy(0, prompt_line);
X
X if (fmt == P_MOVE) {
X clrline();
X goto out;
X }
X
X if (fmt != P_REDRAW && fmt != P_RESTORE)
X vsprintf(cur_p, fmt, va_args2toN);
X
X putchar(CR);
X
X for (cp = cur_p, stand_on = 0, prompt_length = 0; *cp; cp++) {
X if (*cp == '\1') {
X if (cp[1] != '\1') {
X if (STANDOUT) {
X putp(stand_on ? exit_standout_mode : enter_standout_mode);
X stand_on = !stand_on;
X prompt_length += cookie_size;
X }
X continue;
X }
X cp++;
X } else
X if (*cp == '\2') {
X time_t t, tick_usage();
X char *timestr;
X
X t = tick_usage();
X
X if (show_current_time) {
X timestr = ctime(&t) + 11;
X timestr[5] = NUL;
X
X printf("-- %s ", timestr);
X prompt_length += 9;
X }
X
X if (unread_mail(t)) {
X printf("Mail ");
X prompt_length += 5;
X }
X
X continue;
X }
X
X putchar(*cp);
X prompt_length ++;
X }
X if (stand_on) {
X putp(exit_standout_mode);
X prompt_length += cookie_size;
X }
X
X clrline();
X
X if (fmt == P_RESTORE)
X restore_xy();
X else
X curxy_c = -1;
X
X out:
X end_vararg;
X}
X
X
Xany_key(line)
Xint line;
X{
X int was_raw, c, dmp;
X
X was_raw = is_raw;
X if (!is_raw) raw();
X if (line == 0)
X line = -1;
X else
X if (line < 0)
X line = Lines + line;
X
X if (line != 10000)
X so_printxy(0, line, "Hit any key to continue");
X
X clrline();
X
X dmp = do_macro_processing;
X do_macro_processing = 0;
X c = get_c();
X if (c == 'q' || c == 'Q') c = K_interrupt;
X do_macro_processing = dmp;
X
X if (!was_raw) unset_raw();
X
X return c;
X}
X
X
Xstatic pg_fline, pg_width, pg_maxw, pg_line, pg_col, pg_quit;
X
Xpg_init(first_line, cols)
Xint first_line, cols;
X{
X pg_fline = first_line;
X pg_line = pg_fline - 1;
X pg_quit = pg_col = 0;
X pg_width = Columns / cols;
X pg_maxw = pg_width * (cols - 1);
X}
X
Xpg_scroll(n)
Xint n;
X{
X pg_line += n;
X if (pg_line >= (Lines - 1)) {
X pg_line = 0;
X if (any_key(0) == K_interrupt)
X return 1;
X putchar(CR);
X clrline();
X }
X return 0;
X}
X
Xpg_next()
X{
X int c;
X
X pg_line++;
X if (pg_line < Lines) {
X gotoxy(pg_col, pg_line);
X if (pg_line == Lines - 1 && pg_col == pg_maxw) {
X c = any_key(0);
X gotoxy(0, pg_fline);
X clrpage(pg_fline);
X pg_col = 0;
X pg_line = pg_fline;
X if (c == K_interrupt) {
X pg_quit = 1;
X return -1;
X }
X return 1;
X }
X } else {
X pg_line = pg_fline;
X pg_col += pg_width;
X gotoxy(pg_col, pg_line);
X }
X return 0;
X}
X
Xpg_indent(pos)
Xint pos;
X{
X gotoxy(pg_col + pos, pg_line);
X}
X
Xpg_end()
X{
X if (pg_quit == 0 && pg_next() == 0)
X any_key(0);
X}
X
X
Xuser_delay(ticks)
Xint ticks;
X{
X if (ticks <= 0 || conf_dont_sleep) {
X printf(" <>");
X any_key(10000);
X } else {
X fl;
X sleep((unsigned)ticks);
X }
X}
X
END_OF_FILE
if test 27619 -ne `wc -c <'term.c'`; then
echo shar: \"'term.c'\" unpacked with wrong size!
fi
# end of 'term.c'
fi
echo shar: End of archive 1 \(of 22\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 22 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still must unpack the following archives:
echo " " ${MISSING}
fi
exit 0
exit 0 # Just in case...