This commit was generated by cvs2svn to compensate for changes in r174996,

which included commits to RCS files with non-trunk default branches.
This commit is contained in:
Rong-En Fan 2007-12-30 11:10:17 +00:00
parent ca7562e9c2
commit 45ed6d05ba
24 changed files with 0 additions and 13039 deletions

View File

@ -1,38 +0,0 @@
#! /bin/sh
# mkinstalldirs --- make directory hierarchy
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
# Created: 1993-05-16
# Last modified: 1994-03-25
# Public domain
#
errstatus=0
umask 022
for file in ${1+"$@"} ; do
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
shift
pathcomp=
for d in ${1+"$@"} ; do
pathcomp="$pathcomp$d"
case "$pathcomp" in
-* ) pathcomp=./$pathcomp ;;
esac
if test ! -d "$pathcomp"; then
echo "mkdir $pathcomp" 1>&2
case "$pathcomp" in
[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]: )
;; # DOSISH systems
* ) mkdir "$pathcomp" || errstatus=$? ;;
esac
fi
pathcomp="$pathcomp/"
done
done
exit $errstatus
# mkinstalldirs ends here

View File

@ -1,340 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU 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. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), 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 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 show them these terms so they know 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.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
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 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 derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
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 License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
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.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary 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
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 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 Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing 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 for copying, distributing or modifying
the Program or works based on it.
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.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. 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 this 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
this License, you may choose any version ever published by the Free Software
Foundation.
10. 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
11. 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.
12. 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
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 the public, 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.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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 of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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) year 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 is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@ -1,49 +0,0 @@
Current history:
2006/11/25 Fixes for ncurses tparm() prototype.
2006/06/24 1.02 Modify to support ncurses extended string capabilities.
2003/10/18 1.01 Fix some logic in pad.c, improve bce test.
2003/09/20 Modified to allow running from compiled-in terminfo.
2001/10/20 Make menu titles agree with descriptions.
2000/03/04 Fix a few spelling errors
1999/09/04 Minor fix to build/link on BeOS
1999/05/16 Minor fix to build/link on CLIX
1999/05/09 Update to build/link on NeXT
1999/04/17 Update to work with ncurses 5.0 beta1 (TERMTYPE struct)
1999/02/07 Build with ncurses 4.2 981219 (renamed function)
1998/01/09 1.00 First release under GPL
1997/12/24 0.02 First version that requires ncurses
1997/10/29 0.01 Second beta release to the ncurses mailing list.
1997/10/06 0.00 First beta release to the ncurses mailing list.
Ancient history: TACK -- the terminfo action checker
The purpose of this program is to verify the correctness of
terminfos and to calculate the pads needed for each capability.
This program is not designed to test curses and therefore uses
as little of curses as possible.
This program was originally called TED. In 1991 it was
released to USENET in comp.sources. TED was originally written to
test both terminfos and termcaps. The original intent was to
create a terminfo editor. This code fell quite short of its goal.
Tests were controlled by command line switches and editing was done
with pen and paper.
In 1995 Eric S. Raymond got interested in the program and added
a first cut at making the program menu driven. He also converted
the code from K&R C to an ANSI/POSIX-conforming C. He re-christened
the program TAC (Terminfo Action Checker). Eric also wrote a man
page for TAC.
In 1997 I decided to dust off the code and make it easier to
use by the novice. I totally rewrote the menu system and added
the editing features I originally planned for TED. I also did
a total rewrite of the code that does the timings. In the process
of rewriting the code I changed it to be more tightly coupled
with ncurses. By this time someone had taken the name TAC so
I re-christened the program TACK.
Daniel Weaver
<danw@znyx.com>

View File

@ -1,211 +0,0 @@
# $Id: Makefile.in,v 1.38 2006/12/17 15:58:32 tom Exp $
##############################################################################
# Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. #
# #
# Permission is hereby granted, free of charge, to any person obtaining a #
# copy of this software and associated documentation files (the "Software"), #
# to deal in the Software without restriction, including without limitation #
# the rights to use, copy, modify, merge, publish, distribute, distribute #
# with modifications, sublicense, and/or sell copies of the Software, and to #
# permit persons to whom the Software is furnished to do so, subject to the #
# following conditions: #
# #
# The above copyright notice and this permission notice shall be included in #
# all copies or substantial portions of the Software. #
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR #
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, #
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL #
# THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING #
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER #
# DEALINGS IN THE SOFTWARE. #
# #
# Except as contained in this notice, the name(s) of the above copyright #
# holders shall not be used in advertising or otherwise to promote the sale, #
# use or other dealings in this Software without prior written #
# authorization. #
##############################################################################
# Makefile for tack
#
# The variable 'srcdir' refers to the source-distribution, and can be set with
# the configure script by "--srcdir=DIR".
#
# The rules are organized to produce the libraries for the configured models,
# and the programs with the configured default model.
# turn off _all_ suffix rules; we'll generate our own
.SUFFIXES:
SHELL = /bin/sh
THIS = Makefile
CF_MFLAGS = @cf_cv_makeflags@
@SET_MAKE@
x = @EXEEXT@
o = .@OBJEXT@
MODEL = ../@DFT_OBJ_SUBDIR@
DESTDIR = @DESTDIR@
srcdir = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
libdir = @libdir@
mandir = @mandir@
includedir = @includedir@
datadir = @datadir@
LIBTOOL = @LIBTOOL@
LIBTOOL_CLEAN = @LIB_CLEAN@
LIBTOOL_COMPILE = @LIB_COMPILE@
LIBTOOL_LINK = @LIB_LINK@
LIBTOOL_INSTALL = @LIB_INSTALL@
LIBTOOL_UNINSTALL = @LIB_UNINSTALL@
INSTALL = @INSTALL@
INSTALL_PROG = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
AWK = @AWK@
LN_S = @LN_S@
CC = @CC@
CPP = @CPP@
CFLAGS = @CFLAGS@
INCDIR = $(srcdir)/../include
CPPFLAGS = -DHAVE_CONFIG_H -I../tack -I$(srcdir) @CPPFLAGS@
CCFLAGS = $(CPPFLAGS) $(CFLAGS)
CFLAGS_LIBTOOL = $(CCFLAGS)
CFLAGS_NORMAL = $(CCFLAGS)
CFLAGS_DEBUG = $(CCFLAGS) @CC_G_OPT@ -DTRACE
CFLAGS_PROFILE = $(CCFLAGS) -pg
CFLAGS_SHARED = $(CCFLAGS) @CC_SHARED_OPTS@
CFLAGS_DEFAULT = $(CFLAGS_@DFT_UPR_MODEL@)
REL_VERSION = @cf_cv_rel_version@
ABI_VERSION = @cf_cv_abi_version@
LOCAL_LIBDIR = @top_builddir@/lib
LD = @LD@
LINK = @LINK_PROGS@ $(LIBTOOL_LINK) $(CC)
LDFLAGS = @EXTRA_LDFLAGS@ \
@TINFO_ARGS@ @LDFLAGS@ @LD_MODEL@ @LIBS@
LDFLAGS_LIBTOOL = $(LDFLAGS) $(CFLAGS_LIBTOOL)
LDFLAGS_NORMAL = $(LDFLAGS) $(CFLAGS_NORMAL)
LDFLAGS_DEBUG = $(LDFLAGS) $(CFLAGS_DEBUG)
LDFLAGS_PROFILE = $(LDFLAGS) $(CFLAGS_PROFILE)
LDFLAGS_SHARED = $(LDFLAGS) $(CFLAGS_SHARED) @LD_SHARED_OPTS@
LDFLAGS_DEFAULT = $(LDFLAGS_@DFT_UPR_MODEL@)
LINT = @LINT@
LINT_OPTS = @LINT_OPTS@
LINT_LIBS = -lncurses@LIB_SUFFIX@ @LIBS@
PROGS = tack$x
# Default library, for linking applications
DEPS_CURSES = ../lib/@LIB_PREFIX@ncurses@DFT_DEP_SUFFIX@
################################################################################
all: $(PROGS)
sources:
install: install.tack
uninstall: uninstall.tack
# this line simplifies the configure-script
libs \
install.libs \
uninstall.libs:
EDITARGS = $(DESTDIR)$(mandir) $(srcdir) $(srcdir)/*.[0-9]*
install.tack: $(PROGS) \
$(DESTDIR)$(bindir) \
$(DESTDIR)$(mandir)
$(LIBTOOL_INSTALL) $(INSTALL_PROG) tack$x $(DESTDIR)$(bindir)/tack$x
sh ../edit_man.sh normal installing $(EDITARGS)
uninstall.tack:
-@$(LIBTOOL_UNINSTALL) rm -f $(DESTDIR)$(bindir)/tack$x
-sh ../edit_man.sh normal removing $(EDITARGS)
$(DESTDIR)$(bindir) \
$(DESTDIR)$(mandir) :
sh $(srcdir)/../mkinstalldirs $@
#
# Rules for building tack
#
DEPS_TACK = \
$(MODEL)/ansi$o \
$(MODEL)/charset$o \
$(MODEL)/color$o \
$(MODEL)/control$o \
$(MODEL)/crum$o \
$(MODEL)/edit$o \
$(MODEL)/fun$o \
$(MODEL)/init$o \
$(MODEL)/menu$o \
$(MODEL)/modes$o \
$(MODEL)/output$o \
$(MODEL)/pad$o \
$(MODEL)/scan$o \
$(MODEL)/sync$o \
$(MODEL)/sysdep$o \
$(MODEL)/tack$o
tack$x: $(DEPS_TACK) $(DEPS_CURSES)
@ECHO_LINK@ $(LINK) $(DEPS_TACK) $(LDFLAGS_DEFAULT) -o $@
#
# Utility productions start here
#
tags:
ctags *.[ch]
@MAKE_UPPER_TAGS@TAGS:
@MAKE_UPPER_TAGS@ etags *.[ch]
mostlyclean ::
-rm -f core tags TAGS *~ *.bak *.i *.atac trace
clean :: mostlyclean
-sh -c "if test -n '$x' ; then $(MAKE) clean x=''; fi"
-rm -f $(PROGS)
-rm -rf .libs
distclean :: clean
-rm -f Makefile
realclean :: distclean
tack.tar: Makefile.in modules *.[ch] tack.1 HISTORY COPYING
tar -cvf tack.tar Makefile.in modules *.[ch] tack.1 HISTORY COPYING
# These rules are used to allow "make -n" to work on a clean directory-tree
../include/hashsize.h \
../include/parametrized.h \
../include/term.h :
cd ../include; $(MAKE) $(CF_MFLAGS)
$(DEPS_CURSES) :
cd ../ncurses; $(MAKE) $(CF_MFLAGS)
lint:
$(LINT) $(LINT_OPTS) $(CPPFLAGS) $(srcdir)/*.c $(LINT_LIBS)
###############################################################################
# The remainder of this file is automatically generated during configuration
###############################################################################

View File

@ -1,14 +0,0 @@
-- $Id: README,v 1.2 2000/03/12 02:39:12 Daniel.Weaver Exp $
The 'tack' program is a diagnostic that is designed to create and
verify the correctness of terminfo's. This program can be used to
create new terminal descriptions that are not included in the standard
release. Although 'tack' is distributed with ncurses, it is not an
integral part of ncurses. It may be removed from the release without
limiting the usefulness of ncurses on those terminals described in the
terminfo data base. The best way to remove 'tack' from the build is
to delete or rename the 'tack' directory before running the configure
script.
Unlike most of ncurses the 'tack' program is covered under the GNU
Public License.

View File

@ -1,854 +0,0 @@
/*
** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
**
** This file is part of TACK.
**
** TACK 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.
**
** TACK 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 TACK; see the file COPYING. If not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
** Boston, MA 02110-1301, USA
*/
#include <tack.h>
MODULE_ID("$Id: ansi.c,v 1.10 2005/09/17 19:49:16 tom Exp $")
/*
* Standalone tests for ANSI terminals. Three entry points:
* test_ansi_graphics(), test_ansi_reports() and test_ansi_sgr().
*/
/*****************************************************************************
*
* Test ANSI status reports
*
*****************************************************************************/
/* ASCII control characters */
#define A_DC1 0x11 /* Control Q */
#define A_DC3 0x13 /* Control S */
#define A_ESC 0x1b
#define A_DCS 0x90
#define A_CSI 0x9b
#define A_ST 0x9c
#define MAX_MODES 256
static char default_bank[] = "\033(B\017";
static int private_use, ape, terminal_class;
static short ansi_value[256];
static unsigned char ansi_buf[512], pack_buf[512];
struct ansi_reports {
int lvl, final;
const char *text;
const char *request;
};
static struct ansi_reports report_list[] = {
{0, 'c', "(DA) Primary device attributes", "\033[0c"},
{1, 0, "(DSR) Terminal status", "\033[5n"},
{1, 'R', "(DSR) Cursor position", "\033[6n"},
{62, 0, "(DA) Secondary device attributes", "\033[>0c"},
{62, 0, "(DSR) Printer status", "\033[?15n"},
{62, 0, "(DSR) Function key definition", "\033[?25n"},
{62, 0, "(DSR) Keyboard language", "\033[?26n"},
{63, 0, "(DECRQSS) Data destination", "\033P$q$}\033\\"},
{63, 0, "(DECRQSS) Status line type", "\033P$q$~\033\\"},
{63, 0, "(DECRQSS) Erase attribute", "\033P$q\"q\033\\"},
{63, 0, "(DECRQSS) Personality", "\033P$q\"p\033\\"},
{63, 0, "(DECRQSS) Top and bottom margins", "\033P$qr\033\\"},
{63, 0, "(DECRQSS) Character attributes", "\033P$qm\033\\"},
{63, 0, "(DECRQSS) Illegal request", "\033P$q@\033\\"},
{63, 0, "(DECRQUPSS) User pref supplemental set", "\033[&u"},
{63, 0, "(DECRQPSR) Cursor information", "\033[1$w"},
{63, 0, "(DECRQPSR) Tab stop information", "\033[2$w"},
{64, 0, "(DA) Tertiary device attributes", "\033[=0c"},
{64, 0, "(DSR) Extended cursor position", "\033[?6n"},
{64, 0, "(DSR) Macro space", "\033[?62n"},
{64, 0, "(DSR) Memory checksum", "\033[?63n"},
{64, 0, "(DSR) Data integrity", "\033[?75n"},
{64, 0, "(DSR) Multiple session status", "\033[?85n"},
{64, 0, "(DECRQSS) Attribute change extent", "\033P$q*x\033\\"},
{64, 0, "(DECRQSS) Columns per page", "\033P$q$|\033\\"},
{64, 0, "(DECRQSS) Lines per page", "\033P$qt\033\\"},
{64, 0, "(DECRQSS) Lines per screen", "\033P$q*|\033\\"},
{64, 0, "(DECRQSS) Left and right margins", "\033P$qs\033\\"},
{64, 0, "(DECRQSS) Local functions", "\033P$q+q\033\\"},
{64, 0, "(DECRQSS) Local function key control", "\033P$q=}\033\\"},
{64, 0, "(DECRQSS) Select modifier key reporting", "\033P$q+r\033\\"},
{64, 0, "(DECRQDE) Window report", "\033[\"v"},
{0, 0, 0, 0}
};
struct request_control {
const char *text;
const char *expect;
const char *request;
const char *set_mode;
const char *reset_mode;
};
/* Request control function selection or setting */
static const struct request_control rqss[] = {
{"Data sent to screen", "0", "$}", "\033[0$}", 0},
{"Data sent to disabled status line", "0", "$}", 0, 0},
{"\033[0$~\033[1$}", "\033[0$}", 0, 0, 0},
{"Data sent to enabled status line", "1", "$}", 0, 0},
{"\033[2$~\033[1$}", "\033[0$}", 0, 0, 0},
{"Disable status line", "0", "$~", "\033[0$~", 0},
{"Top status line", "1", "$~", "\033[1$~", 0},
{"Bottom status line", "2", "$~", "\033[2$~", 0},
{"Erasable character", "0", "\"q", "\033[0\"q", 0},
{"Nonerasable character", "1", "\"q", "\033[1\"q", "\033[0\"q"},
{"Top and bottom margins", "3;10", "r", "\0337\033[3;10r", 0},
{"\033[r\0338", 0, 0, 0, 0},
{"Top and bottom margins", "default", "r", "\0337\033[r", "\0338"},
{"Character attributes, dim, bold", "1", "m", "\033[2;1m", "\033[m"},
{"Character attributes, bold, dim", "2", "m", "\033[1;2m", "\033[m"},
{"Character attributes, under, rev", "4;7", "m", "\033[4;7m", "\033[m"},
{"Character attributes, color", "35;42", "m", "\033[35;42m", "\033[m"},
{"All character attributes", "", "m", "\033[1;2;3;4;5;6;7;8;9m", 0},
{"\033[m", 0, 0, 0, 0},
{0, 0, 0, 0, 0}
};
/*
** read_ansi()
**
** read an ANSI status report from terminal
*/
static void
read_ansi(void)
{
int ch, i, j, last_escape;
fflush(stdout);
read_key((char *)ansi_buf, sizeof(ansi_buf));
/* Throw away control characters inside CSI sequences.
Convert two character 7-bit sequences into 8-bit sequences. */
for (i = j = last_escape = 0; (ch = ansi_buf[i]) != 0; i++) {
if (ch == A_ESC) {
if (last_escape == A_ESC) {
pack_buf[j++] = A_ESC;
}
last_escape = A_ESC;
} else
if (last_escape == A_ESC && ch >= '@' && ch <= '_') {
pack_buf[j++] = last_escape = ch + 0x40;
} else
if (last_escape != A_CSI || (ch > 0x20 && ch != 0x80)) {
if (last_escape == A_ESC) {
pack_buf[j++] = A_ESC;
}
if (ch > 0x80 && ch < 0xa0) {
last_escape = ch;
}
pack_buf[j++] = ch;
}
}
if (last_escape == A_ESC) {
pack_buf[j++] = A_ESC;
}
pack_buf[j] = '\0';
return;
}
/*
** valid_mode(expected)
**
** read a terminal mode status report and parse the result
** Return TRUE if we got the expected terminating character.
*/
static int
valid_mode(int expected)
{
unsigned char *s;
int ch, terminator;
read_ansi();
ape = 0;
ch = UChar(pack_buf[0]);
ansi_value[0] = 0;
if (ch != A_CSI && ch != A_DCS)
return FALSE;
s = pack_buf + 1;
private_use = 0;
if ((*s >= '<') & (*s <= '?')) {
private_use = *s++;
}
terminator = 0;
for (; (ch = *s); s++) {
if (ch >= '0' && ch <= '9')
ansi_value[ape] = ansi_value[ape] * 10 + ch - '0';
else if (ch == ';' || ch == ':')
ansi_value[++ape] = 0;
else if (ch >= '<' && ch <= '?')
private_use = ch;
else if (ch >= ' ')
terminator = (terminator << 8) | ch;
else
break;
}
return terminator == expected;
}
/*
** read_reports()
**
** read all the reports in the ANSI report structure
*/
static int
read_reports(void)
{
int i, j, k, tc, vcr, lc;
char *s;
const char *t;
lc = 5;
terminal_class = tc = 0;
for (i = 0; report_list[i].text; i++, lc++) {
if (terminal_class < report_list[i].lvl &&
tc < report_list[i].lvl) {
put_crlf();
menu_prompt();
ptext("/status [q] > ");
j = wait_here();
if (j != 'n' && j != 'N')
return 0;
tc = report_list[i].lvl;
lc = 1;
} else if (lc + 2 >= lines) {
put_crlf();
ptext("Hit any key to continue ");
(void) wait_here();
lc = 1;
}
sprintf(temp, "%s (%s) ", report_list[i].text,
expand_command(report_list[i].request));
ptext(temp);
for (j = strlen(temp); j < 49; j++)
putchp(' ');
tc_putp(report_list[i].request);
vcr = 0;
if (report_list[i].final == 0) {
read_ansi();
} else if (valid_mode(report_list[i].final))
switch (report_list[i].final) {
case 'c':
terminal_class = ansi_value[0];
break;
case 'R':
vcr = TRUE;
break;
}
j = UChar(pack_buf[0]);
if (j != A_CSI && j != A_DCS) {
put_crlf();
t = "*** The above request gives illegal response ***";
ptext(t);
for (j = strlen(t); j < 49; j++)
putchp(' ');
}
s = expand((const char *)ansi_buf);
if (char_count + expand_chars >= columns) {
put_str("\r\n ");
lc++;
}
putln(s);
if (vcr) { /* find out how big the screen is */
tc_putp(report_list[i].request);
if (!valid_mode('R'))
continue;
j = ansi_value[0];
k = ansi_value[1];
tc_putp("\033[255B\033[255C\033[6n");
if (!valid_mode('R'))
continue;
sprintf(temp, "\033[%d;%dH", j, k);
tc_putp(temp);
ptext("(DSR) Screen size (CSI 6 n)");
for (j = char_count; j < 50; j++)
putchp(' ');
sprintf(temp, "%d x %d", ansi_value[1], ansi_value[0]);
ptextln(temp);
}
}
menu_prompt();
ptext("/status r->repeat test, <return> to continue > ");
return wait_here();
}
/*
** request_cfss()
**
** Request Control function selection or settings
*/
static int
request_cfss(void)
{
int i, j, k, l, ch;
char *s;
put_clear();
ptextln("Request Expected Received");
put_crlf();
for (i = 0; rqss[i].text; i++) {
ptext(rqss[i].text);
j = strlen(rqss[i].text) + strlen(rqss[i].expect);
putchp(' ');
for (j++; j < 40; j++)
putchp(' ');
ptext(rqss[i].expect);
putchp(' ');
tc_putp(rqss[i].set_mode);
sprintf(temp, "\033P$q%s\033\\", rqss[i].request);
tc_putp(temp);
read_ansi();
tc_putp(rqss[i].reset_mode);
putchp(' ');
for (j = 0; ansi_buf[j]; j++) {
if (ansi_buf[j] == 'r') {
for (k = j++; (ch = UChar(ansi_buf[k])) != 0; k++)
if (ch == A_ESC) {
break;
} else if (ch == A_ST) {
break;
}
ansi_buf[k] = '\0';
s = expand((const char *)&ansi_buf[j]);
if (char_count + expand_chars >= columns)
put_str("\r\n ");
put_str(s);
}
}
put_crlf();
}
/* calculate the valid attributes */
ptext("Valid attributes: 0");
j = 0;
for (i = 1; i < 20; i++) {
sprintf(temp, "\033[0;%dm\033P$qm\033\\", i);
tc_putp(temp);
(void) valid_mode('m');
if (ape > 0) {
j = i;
sprintf(temp, "\033[0m; %d", i);
tc_putp(temp);
}
}
put_crlf();
/* calculate how many parameters can be sent */
ptext("Max number of parameters: ");
sprintf(temp, "%dm\033P$qm\033\\", j);
l = -1;
if (j > 0)
for (l = 1; l < 33; l++) {
tc_putp("\033[0");
for (ch = 1; ch <= l; ch++)
put_this(';');
tc_putp(temp);
(void) valid_mode('m');
if (ape == 0)
break;
}
tc_putp("\033[m");
if (l >= 0) {
sprintf(temp, "%d", l);
ptext(temp);
} else
ptext("unknown");
put_crlf();
return wait_here();
}
/*
** mode_display(puc, mode, initial, set, reset)
**
** print the mode display entry
*/
static void
mode_display(const char *p, int n, int c, char s, char r)
{
int k;
sprintf(temp, "%s%d (%c, %c, %c)", p, n, c, s, r);
k = strlen(temp);
if (char_count + k >= columns)
put_crlf();
for (; k < 14; k++)
putchp(' ');
put_str(temp);
}
/*
** terminal_state()
**
** test DECRQM status reports
*/
static void
terminal_state(void)
{
static const char *puc[] = {"", "<", "=", ">", "?", 0};
int i, j, k, l, modes_found;
char *s;
char buf[256], tms[256];
int mode_puc[MAX_MODES], mode_number[MAX_MODES];
char set_value[MAX_MODES], reset_value[MAX_MODES];
char current_value[MAX_MODES];
ptext("Testing terminal mode status. (CSI 0 $ p)");
tc_putp("\033[0$p");
modes_found = 0;
tms[0] = '\0';
if (valid_mode(('$' << 8) | 'y')) {
for (i = 0; puc[i]; i++) {
put_crlf();
if (i) {
sprintf(temp, "Private use: %c", puc[i][0]);
} else {
strcpy(temp, "Standard modes:");
}
k = strlen(temp);
ptext(temp);
for (j = 0; j < (int) sizeof(buf); buf[j++] = ' ')
;
for (j = l = 0; j < 255 && j - l < 50; j++) {
sprintf(temp, "\033[%s%d$p", puc[i], j);
tc_putp(temp);
if (!valid_mode(('$' << 8) | 'y')) {
/* not valid, save terminating value */
s = expand((const char *)ansi_buf);
sprintf(tms, "%s%s%d %s ", tms,
puc[i], j, s);
break;
}
if (private_use != puc[i][0])
break;
if (ansi_value[0] != j)
break;
if (ansi_value[1]) {
l = j;
if (k > 70) {
buf[k] = '\0';
put_crlf();
ptextln(buf);
for (k = 0; k < (int) sizeof(buf);) {
buf[k++] = ' ';
}
k = 0;
}
sprintf(temp, " %d", j);
ptext(temp);
k += strlen(temp);
buf[k - 1] = ansi_value[1] + '0';
if (modes_found >= MAX_MODES)
continue;
current_value[modes_found] =
ansi_value[1] + '0';
/* some modes never return */
if ((i == 0 && j == 13) /* control execution */
|| (puc[i][0] == '?' && j == 2)) /* VT52 */
set_value[modes_found] =
reset_value[modes_found] = '-';
else
set_value[modes_found] =
reset_value[modes_found] = ' ';
mode_puc[modes_found] = i;
mode_number[modes_found++] = j;
}
}
buf[k] = '\0';
if (buf[k - 1] != ' ') {
put_crlf();
ptext(buf);
}
}
if ((i = modes_found) != 0) {
put_crlf();
put_crlf();
if (tms[0]) {
ptextln(tms);
}
ptext("Hit 'Y' to test mode set/reset states: ");
i = wait_here();
}
if (i == 'y' || i == 'Y')
while (1) {
#ifdef STATUSFIX
FILE *fp;
#ifdef TEDANSI
fp = fopen("ted.ansi", "w");
#else
fp = fopen("/dev/console", "w");
#endif
#endif
for (i = j = 0; j < modes_found; j = ++i >> 1) {
if (set_value[j] == '-')
continue;
k = (current_value[j] ^ i) & 1;
sprintf(temp, "\033[%s%d%c\033[%s%d$p",
puc[mode_puc[j]], mode_number[j],
k ? 'l' : 'h',
puc[mode_puc[j]], mode_number[j]);
#ifdef STATUSFIX
if (fp) {
fprintf(fp, "%s\n", expand(temp));
fflush(fp);
}
#endif
tc_putp(temp);
if (!valid_mode(('$' << 8) | 'y'))
continue;
if (k) {
reset_value[j] = ansi_value[1] + '0';
} else {
set_value[j] = ansi_value[1] + '0';
}
}
put_str("\033[30l"); /* added for GORT bug
(WY-185) */
#ifdef STATUSFIX
if (fp)
fclose(fp);
#endif
tty_set();
/* print the results */
put_clear();
putln("mode (initial, set, reset)");
for (j = 0; j < modes_found; j++) {
mode_display(puc[mode_puc[j]], mode_number[j],
current_value[j], set_value[j], reset_value[j]);
}
ptext("\n\nHit 'R' to repeat test. 'S' to sort results: ");
i = wait_here();
if (i == 's' || i == 'S') { /* print the same stuff,
sorted by
current_value */
put_crlf();
for (i = '1'; i <= '4'; i++) {
for (j = 0; j < modes_found; j++) {
if (current_value[j] == i)
mode_display(puc[mode_puc[j]],
mode_number[j], current_value[j],
set_value[j], reset_value[j]);
}
}
ptext("\n\nHit 'R' to repeat test: ");
i = wait_here();
}
if (i != 'r' && i != 'R')
break;
tty_raw(1, char_mask);
}
} else {
tty_set();
}
}
/*
** ansi_report_help()
**
** Display the informational data for the ANSI report test.
*/
static void
ansi_report_help(void)
{
ptext("Begin ANSI status report testing. ");
ptext(" Parity bit set will be displayed in reverse video. ");
ptext(" If the terminal hangs, hit any alphabetic key. ");
ptextln(" Use n to continue testing. Use q to quit.");
put_crlf();
}
/*
** test_ansi_reports()
**
** Test the ANSI status report functions
*/
void
tools_status(
struct test_list *t GCC_UNUSED,
int *state GCC_UNUSED,
int *ch)
{
int i;
put_clear();
ansi_report_help();
tty_raw(1, char_mask);
do {
i = read_reports();
if (i != 'r' && i != 'R') {
*ch = i;
return;
}
} while (i);
if (terminal_class >= 63) {
do {
i = request_cfss();
} while (i == 'r' || i == 'R');
*ch = i;
terminal_state();
} else {
tty_set();
}
}
/*
** display_sgr()
**
** Test a range of ANSI sgr attributes
** puc -> Private Use Character
*/
static void
display_sgr(int puc)
{
int k;
temp[0] = puc;
temp[1] = '\0';
for (k = 0; k < 80; k++) {
if (char_count + 8 > 80)
put_crlf();
else if (char_count + 8 > columns)
put_crlf();
else if (k > 0)
printf(" ");
printf("\033[%s%dmMode %2d\033[0m", temp, k, k);
char_count += 8;
if (puc == '\0') {
if (k == 19)
printf("\033[10m");
if (k == 39)
printf("\033[37m");
if (k == 49)
printf("\033[40m");
}
}
put_crlf();
if (puc == '<')
printf("\033[<1m");
else if (puc)
printf("\033[%s0m", temp);
set_attr(0);
}
/*
** print_sgr20(on, off)
**
** print the sgr line for sgr20()
*/
static void
print_sgr20(int on, int off)
{
if (char_count > columns - 13) {
put_crlf();
} else if (char_count) {
put_str(" ");
}
char_count += 11;
printf("%d/%d \033[%dmon\033[%dm off\033[0m", on, off, on, off);
}
/*
** sgr20(void)
**
** display the enter/exit attributes 1-9 and 20-29
*/
static void
sgr20(void)
{
int k;
put_crlf();
ptextln("Test enter/exit attributes 1-9 and 21-29.");
for (k = 1; k < 10; k++) {
print_sgr20(k, k + 20);
}
print_sgr20(1, 22); /* bold */
print_sgr20(2, 22); /* dim */
print_sgr20(8, 22); /* blank */
printf("\033[0m");
set_attr(0);
}
/*
** tools_sgr(testlist, state, ch)
**
** Run the ANSI graphics rendition mode tool
** Return the last character typed.
*/
void
tools_sgr(
struct test_list *t GCC_UNUSED,
int *state GCC_UNUSED,
int *ch)
{
int k;
put_clear();
for (k = 0;;) {
display_sgr(k);
put_crlf();
menu_prompt();
ptext("/sgr Enter =><?r [<cr>] > ");
k = wait_here();
if ((k == 'r') || (k == 'R')) {
k = 0;
} else if ((k < '<') || (k > '?')) {
break;
}
}
sgr20();
put_newlines(2);
*ch = REQUEST_PROMPT;
}
/*****************************************************************************
*
* Test ANSI graphics
*
*****************************************************************************/
/*
** select_bank(bank)
**
** select a graphics character set for ANSI terminals
*/
static void
select_bank(char *bank)
{
tc_putp(bank);
switch (bank[1] & 3) {
case 0:
putchp('O' & 0x1f); /* control O */
break;
case 1:
putchp('N' & 0x1f); /* control N */
tc_putp("\033~");
break;
case 2:
tc_putp("\033n\033}");
break;
case 3:
tc_putp("\033o\033|");
break;
}
}
/*
** show_characters(bank, bias)
**
** print the ANSI graphics characters
*/
static void
show_characters(char *bank, int bias)
{
int i;
sprintf(temp, "G%d GL ", bank[1] & 3);
ptext(temp);
select_bank(bank);
for (i = ' '; i < 0x80; i++) {
if (char_count >= columns ||
(i != ' ' && (i & 31) == 0))
put_str("\n ");
putchp(i + bias);
}
select_bank(default_bank);
put_str(" DEL <");
select_bank(bank);
putchp(0x7f + bias);
select_bank(default_bank);
putchp('>');
put_crlf();
put_crlf();
}
/* ANSI graphics test
94 96 character sets
G0 ( ,
G1 ) -
G2 * .
G3 + /
Standard Definitions
A UK
B US ASCII
Dec extended definitions
0 Special graphics
*/
/*
** tools_charset(testlist, state, ch)
**
** Run the ANSI alt-charset mode tool
*/
void
tools_charset(
struct test_list *t GCC_UNUSED,
int *state GCC_UNUSED,
int *chp GCC_UNUSED)
{
int j, ch;
char bank[32];
put_clear();
ptext("Enter the bank ()*+,-./ followed by the character set");
ptext(" 0123456789:;<=>? for private use, and");
ptextln(" @A...Z[\\]^_`a...z{|}~ for standard sets.");
strcpy(bank, "\033)0");
for (; bank[0];) {
put_crlf();
show_characters(bank, 0);
/* G0 will not print in GR */
if (bank[1] & 3) {
show_characters(bank, 0x80);
}
ptext("bank+set> ");
for (j = 1; (ch = getchp(char_mask)); j++) {
if (ch == EOF)
break;
putchp(ch);
if (j == 1 && ch > '/')
j++;
bank[j] = ch;
if (ch < ' ' || ch > '/')
break;
if (j + 1 >= (int) sizeof(bank))
break;
}
if (j == 1)
break;
if (bank[j] < '0' || bank[j] > '~')
break;
bank[j + 1] = '\0';
}
put_crlf();
}

View File

@ -1,711 +0,0 @@
/*
** Copyright (C) 1991, 1997-2000 Free Software Foundation, Inc.
**
** This file is part of TACK.
**
** TACK 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.
**
** TACK 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 TACK; see the file COPYING. If not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
** Boston, MA 02110-1301, USA
*/
#include <tack.h>
MODULE_ID("$Id: charset.c,v 1.11 2006/11/26 00:13:36 tom Exp $")
/*
Menu definitions for alternate character set and SGR tests.
*/
static void charset_bel(struct test_list *t, int *state, int *ch);
static void charset_flash(struct test_list *t, int *state, int *ch);
static void charset_civis(struct test_list *t, int *state, int *ch);
static void charset_cvvis(struct test_list *t, int *state, int *ch);
static void charset_cnorm(struct test_list *t, int *state, int *ch);
static void charset_hs(struct test_list *t, int *state, int *ch);
static void charset_status(struct test_list *t, int *state, int *ch);
static void charset_dsl(struct test_list *t, int *state, int *ch);
static void charset_enacs(struct test_list *t, int *state, int *ch);
static void charset_smacs(struct test_list *t, int *state, int *ch);
static void charset_attributes(struct test_list *t, int *state, int *ch);
static void charset_sgr(struct test_list *t, int *state, int *ch);
struct test_list acs_test_list[] = {
{0, 0, 0, 0, "e) edit terminfo", 0, &edit_menu},
{MENU_NEXT, 3, "bel", 0, 0, charset_bel, 0},
{MENU_NEXT, 3, "flash", 0, 0, charset_flash, 0},
{MENU_NEXT, 3, "civis", 0, 0, charset_civis, 0},
{MENU_NEXT, 3, "cvvis", 0, 0, charset_cvvis, 0},
{MENU_NEXT, 3, "cnorm", 0, 0, charset_cnorm, 0},
{MENU_NEXT, 3, "hs", 0, 0, charset_hs, 0},
{MENU_NEXT, 3, "tsl) (fsl) (wsl", "hs", 0, charset_status, 0},
{MENU_NEXT, 3, "dsl", "hs", 0, charset_dsl, 0},
{MENU_NEXT, 0, "acsc) (enacs) (smacs) (rmacs", 0, 0, charset_enacs, 0},
{MENU_NEXT, 0, "smacs) (rmacs", 0, 0, charset_smacs, 0},
{MENU_NEXT, 11, 0, 0, 0, charset_attributes, 0},
{MENU_NEXT, 11, "sgr) (sgr0", "ma", 0, charset_sgr, 0},
{MENU_LAST, 0, 0, 0, 0, 0, 0}
};
const struct mode_list alt_modes[] = {
{"normal", "(sgr0)", "(sgr0)", 1},
{"standout", "(smso)", "(rmso)", 2},
{"underline", "(smul)", "(rmul)", 4},
{"reverse", "(rev)", "(sgr0)", 8},
{"blink", "(blink)", "(sgr0)", 16},
{"dim", "(dim)", "(sgr0)", 32},
{"bold", "(bold)", "(sgr0)", 64},
{"invis", "(invis)", "(sgr0)", 128},
{"protect", "(prot)", "(sgr0)", 256},
{"altcharset", "(smacs)", "(rmacs)", 512}
};
/* On many terminals the underline attribute is the last scan line.
This is OK unless the following line is reverse video.
Then the underline attribute does not show up. The following map
will reorder the display so that the underline attribute will
show up. */
const int mode_map[10] = {0, 1, 3, 4, 5, 6, 7, 8, 9, 2};
struct graphics_pair {
unsigned char c;
const char *name;
};
static struct graphics_pair glyph[] = {
{'+', "arrow pointing right"},
{',', "arrow pointing left"},
{'.', "arrow pointing down"},
{'0', "solid square block"},
{'i', "lantern symbol"},
{'-', "arrow pointing up"},
{'`', "diamond"},
{'a', "checker board (stipple)"},
{'f', "degree symbol"},
{'g', "plus/minus"},
{'h', "board of squares"},
{'j', "lower right corner"},
{'k', "upper right corner"},
{'l', "upper left corner"},
{'m', "lower left corner"},
{'n', "plus"},
{'o', "scan line 1"},
{'p', "scan line 3"},
{'q', "horizontal line"},
{'r', "scan line 7"},
{'s', "scan line 9"},
{'t', "left tee (|-)"},
{'u', "right tee (-|)"},
{'v', "bottom tee(_|_)"},
{'w', "top tee (T)"},
{'x', "vertical line"},
{'y', "less/equal"},
{'z', "greater/equal"},
{'{', "Pi"},
{'|', "not equal"},
{'}', "UK pound sign"},
{'~', "bullet"},
{'\0', "\0"}
};
/*
** charset_hs(test_list, status, ch)
**
** (hs) test Has status line
*/
static void
charset_hs(
struct test_list *t,
int *state,
int *ch)
{
if (has_status_line != 1) {
ptext("(hs) Has-status line is not defined. ");
generic_done_message(t, state, ch);
}
}
/*
** charset_status(test_list, status, ch)
**
** (tsl) (fsl) (wsl) test Status line
*/
static void
charset_status(
struct test_list *t,
int *state,
int *ch)
{
int i, max;
char *s;
static char m[] = "*** status line *** 123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.";
if (has_status_line != 1) {
return;
}
put_clear();
max = width_status_line == -1 ? columns : width_status_line;
sprintf(temp, "Terminal has status line of %d characters", max);
ptextln(temp);
put_str("This line s");
s = TPARM_1(to_status_line, 0);
tc_putp(s);
for (i = 0; i < max; i++)
putchp(m[i]);
tc_putp(from_status_line);
putln("hould not be broken.");
ptextln("If the previous line is not a complete sentence then (tsl) to-status-line, (fsl) from-status-line, or (wsl) width-of-status-line is incorrect." );
generic_done_message(t, state, ch);
}
/*
** charset_dsl(test_list, status, ch)
**
** (dsl) test Disable status line
*/
static void
charset_dsl(
struct test_list *t,
int *state,
int *ch)
{
if (has_status_line != 1) {
return;
}
if (dis_status_line) {
ptextln("Disable status line (dsl)");
tc_putp(dis_status_line);
ptext("If you can still see the status line then (dsl) disable-status-line has failed. ");
} else {
ptext("(dsl) Disable-status-line is not defined. ");
}
generic_done_message(t, state, ch);
}
void
eat_cookie(void)
{ /* put a blank if this is not a magic cookie
terminal */
if (magic_cookie_glitch < 1)
putchp(' ');
}
void
put_mode(char *s)
{ /* send the attribute string (with or without
% execution) */
tc_putp(TPARM_0(s)); /* allow % execution */
}
void
set_attr(int a)
{ /* set the attribute from the bits in a */
int i, b[32];
if (magic_cookie_glitch > 0) {
char_count += magic_cookie_glitch;
}
if (a == 0 && exit_attribute_mode) {
put_mode(exit_attribute_mode);
return;
}
for (i = 0; i < 31; i++) {
b[i] = (a >> i) & 1;
}
tc_putp(TPARM_9(set_attributes, b[1], b[2], b[3], b[4], b[5],
b[6], b[7], b[8], b[9]));
}
/*
** charset_sgr(test_list, status, ch)
**
** (sgr) test Set Graphics Rendition
*/
static void
charset_sgr(
struct test_list *t,
int *state,
int *ch)
{
int i, j;
if (!set_attributes) {
ptext("(sgr) Set-graphics-rendition is not defined. ");
generic_done_message(t, state, ch);
return;
}
if (!exit_attribute_mode) {
ptextln("(sgr0) Set-graphics-rendition-zero is not defined.");
/* go ahead and test anyway */
}
ptext("Test video attributes (sgr)");
for (i = 0; i < (int) (sizeof(alt_modes) / sizeof(struct mode_list));
i++) {
put_crlf();
sprintf(temp, "%d %-20s", i, alt_modes[i].name);
put_str(temp);
set_attr(alt_modes[i].number);
sprintf(temp, "%s", alt_modes[i].name);
put_str(temp);
set_attr(0);
}
putln("\n\nDouble mode test");
for (i = 0; i <= 9; i++) {
sprintf(temp, " %2d ", mode_map[i]);
put_str(temp);
}
for (i = 0; i <= 9; i++) {
put_crlf();
sprintf(temp, "%d", mode_map[i]);
put_str(temp);
for (j = 0; j <= 9; j++) {
eat_cookie();
set_attr((1 << mode_map[i]) | (1 << mode_map[j]));
put_str("Aa");
set_attr(0);
if (j < 9)
eat_cookie();
}
}
put_crlf();
#ifdef max_attributes
if (max_attributes >= 0) {
sprintf(temp, "(ma) Maximum attributes %d ", max_attributes);
ptext(temp);
}
#endif
generic_done_message(t, state, ch);
}
/*
** test_one_attr(mode-number, begin-string, end-string)
**
** Display one attribute line.
*/
static void
test_one_attr(
int n,
char *begin_mode,
char *end_mode)
{
int i;
sprintf(temp, "%-10s %s ", alt_modes[n].name, alt_modes[n].begin_mode);
ptext(temp);
for (; char_count < 19;) {
putchp(' ');
}
if (begin_mode) {
putchp('.');
put_mode(begin_mode);
put_str(alt_modes[n].name);
for (i = strlen(alt_modes[n].name); i < 13; i++) {
putchp(' ');
}
if (end_mode) {
put_mode(end_mode);
sprintf(temp, ". %s", alt_modes[n].end_mode);
} else {
set_attr(0);
strcpy(temp, ". (sgr)");
}
ptextln(temp);
} else {
for (i = 0; i < magic_cookie_glitch; i++)
putchp('*');
put_str("*** missing ***");
for (i = 0; i < magic_cookie_glitch; i++)
putchp('*');
put_crlf();
}
}
/*
** charset_attributes(test_list, status, ch)
**
** Test SGR
*/
static void
charset_attributes(
struct test_list *t,
int *state,
int *ch)
{
putln("Test video attributes");
test_one_attr(1, enter_standout_mode, exit_standout_mode);
test_one_attr(2, enter_underline_mode, exit_underline_mode);
test_one_attr(9, enter_alt_charset_mode, exit_alt_charset_mode);
if (!exit_attribute_mode && !set_attributes) {
ptextln("(sgr0) exit attribute mode is not defined.");
generic_done_message(t, state, ch);
return;
}
test_one_attr(3, enter_reverse_mode, exit_attribute_mode);
test_one_attr(4, enter_blink_mode, exit_attribute_mode);
test_one_attr(5, enter_dim_mode, exit_attribute_mode);
test_one_attr(6, enter_bold_mode, exit_attribute_mode);
test_one_attr(7, enter_secure_mode, exit_attribute_mode);
test_one_attr(8, enter_protected_mode, exit_attribute_mode);
generic_done_message(t, state, ch);
}
#define GLYPHS 256
/*
** charset_smacs(test_list, status, ch)
**
** display all possible acs characters
** (smacs) (rmacs)
*/
static void
charset_smacs(
struct test_list *t,
int *state,
int *ch)
{
int i, c;
if (enter_alt_charset_mode) {
put_clear();
ptextln("The following characters are available. (smacs) (rmacs)");
for (i = ' '; i <= '`'; i += 32) {
put_crlf();
put_mode(exit_alt_charset_mode);
for (c = 0; c < 32; c++) {
putchp(c + i);
}
put_crlf();
put_mode(enter_alt_charset_mode);
for (c = 0; c < 32; c++) {
putchp(c + i);
}
put_mode(exit_alt_charset_mode);
put_crlf();
}
put_mode(exit_alt_charset_mode);
put_crlf();
generic_done_message(t, state, ch);
}
}
static void
test_acs(
int attr)
{ /* alternate character set */
int i, j;
char valid_glyph[GLYPHS];
char acs_table[GLYPHS];
static unsigned char vt100[] = "`afgjklmnopqrstuvwxyz{|}~";
line_count = 0;
for (i = 0; i < GLYPHS; i++) {
valid_glyph[i] = FALSE;
acs_table[i] = i;
}
if (acs_chars) {
sprintf(temp, "Alternate character set map: %s",
expand(acs_chars));
putln(temp);
for (i = 0; acs_chars[i]; i += 2) {
if (acs_chars[i + 1] == 0) {
break;
}
for (j = 0;; j++) {
if (glyph[j].c == (unsigned char) acs_chars[i]) {
acs_table[glyph[j].c] = acs_chars[i + 1];
valid_glyph[glyph[j].c] = TRUE;
break;
}
if (glyph[j].name[0] == '\0') {
if (isgraph(UChar(acs_chars[i]))) {
sprintf(temp, " %c",
acs_chars[i]);
} else {
sprintf(temp, " 0x%02x",
UChar(acs_chars[i]));
}
strcpy(&temp[5], " *** has no mapping ***");
putln(temp);
break;
}
}
}
} else {
ptextln("acs_chars not defined (acsc)");
/* enable the VT-100 graphics characters (default) */
for (i = 0; vt100[i]; i++) {
valid_glyph[vt100[i]] = TRUE;
}
}
if (attr) {
set_attr(attr);
}
_nc_init_acs(); /* puts 'ena_acs' and incidentally links acs_map[] */
for (i = 0; glyph[i].name[0]; i++) {
if (valid_glyph[glyph[i].c]) {
put_mode(enter_alt_charset_mode);
put_this(acs_table[glyph[i].c]);
char_count++;
put_mode(exit_alt_charset_mode);
if (magic_cookie_glitch >= 1) {
sprintf(temp, " %-30.30s", glyph[i].name);
put_str(temp);
if (char_count + 33 >= columns)
put_crlf();
} else {
sprintf(temp, " %-24.24s", glyph[i].name);
put_str(temp);
if (char_count + 26 >= columns)
put_crlf();
}
if (line_count >= lines) {
(void) wait_here();
put_clear();
}
}
}
if (char_count > 1) {
put_crlf();
}
#ifdef ACS_ULCORNER
maybe_wait(5);
put_mode(enter_alt_charset_mode);
put_that(ACS_ULCORNER);
put_that(ACS_TTEE);
put_that(ACS_URCORNER);
put_that(ACS_ULCORNER);
put_that(ACS_HLINE);
put_that(ACS_URCORNER);
char_count += 6;
put_mode(exit_alt_charset_mode);
put_crlf();
put_mode(enter_alt_charset_mode);
put_that(ACS_LTEE);
put_that(ACS_PLUS);
put_that(ACS_RTEE);
put_that(ACS_VLINE);
if (magic_cookie_glitch >= 1)
put_this(' ');
else {
put_mode(exit_alt_charset_mode);
put_this(' ');
put_mode(enter_alt_charset_mode);
}
put_that(ACS_VLINE);
char_count += 6;
put_mode(exit_alt_charset_mode);
put_str(" Here are 2 boxes");
put_crlf();
put_mode(enter_alt_charset_mode);
put_that(ACS_LLCORNER);
put_that(ACS_BTEE);
put_that(ACS_LRCORNER);
put_that(ACS_LLCORNER);
put_that(ACS_HLINE);
put_that(ACS_LRCORNER);
char_count += 6;
put_mode(exit_alt_charset_mode);
put_crlf();
#endif
}
/*
** charset_bel(test_list, status, ch)
**
** (bel) test Bell
*/
static void
charset_bel(
struct test_list *t,
int *state,
int *ch)
{
if (bell) {
ptextln("Testing bell (bel)");
tc_putp(bell);
ptext("If you did not hear the Bell then (bel) has failed. ");
} else {
ptext("(bel) Bell is not defined. ");
}
generic_done_message(t, state, ch);
}
/*
** charset_flash(test_list, status, ch)
**
** (flash) test Visual bell
*/
static void
charset_flash(
struct test_list *t,
int *state,
int *ch)
{
if (flash_screen) {
ptextln("Testing visual bell (flash)");
tc_putp(flash_screen);
ptext("If you did not see the screen flash then (flash) has failed. ");
} else {
ptext("(flash) Flash is not defined. ");
}
generic_done_message(t, state, ch);
}
/*
** charset_civis(test_list, status, ch)
**
** (civis) test Cursor invisible
*/
static void
charset_civis(
struct test_list *t,
int *state,
int *ch)
{
if (cursor_normal) {
if (cursor_invisible) {
ptext("(civis) Turn off the cursor. ");
tc_putp(cursor_invisible);
ptext("If you can still see the cursor then (civis) has failed. ");
} else {
ptext("(civis) Cursor-invisible is not defined. ");
}
generic_done_message(t, state, ch);
tc_putp(cursor_normal);
}
}
/*
** charset_cvvis(test_list, status, ch)
**
** (cvvis) test Cursor very visible
*/
static void
charset_cvvis(
struct test_list *t,
int *state,
int *ch)
{
if (cursor_normal) {
if (cursor_visible) {
ptext("(cvvis) Make cursor very visible. ");
tc_putp(cursor_visible);
ptext("If the cursor is not very visible then (cvvis) has failed. ");
} else {
ptext("(cvvis) Cursor-very-visible is not defined. ");
}
generic_done_message(t, state, ch);
tc_putp(cursor_normal);
}
}
/*
** charset_cnorm(test_list, status, ch)
**
** (cnorm) test Cursor normal
*/
static void
charset_cnorm(
struct test_list *t,
int *state,
int *ch)
{
if (cursor_normal) {
ptext("(cnorm) Normal cursor. ");
tc_putp(cursor_normal);
ptext("If the cursor is not normal then (cnorm) has failed. ");
} else {
ptext("(cnorm) Cursor-normal is not defined. ");
}
generic_done_message(t, state, ch);
}
/*
** charset_enacs(test_list, status, ch)
**
** test Alternate character set mode and alternate characters
** (acsc) (enacs) (smacs) (rmacs)
*/
static void
charset_enacs(
struct test_list *t,
int *state,
int *ch)
{
int c, i;
if (enter_alt_charset_mode || acs_chars) {
c = 0;
while (1) {
put_clear();
/*
for terminals that use separate fonts for
attributes (such as X windows) the line
drawing characters must be checked for
each font.
*/
if (c >= '0' && c <= '9') {
test_acs(alt_modes[c - '0'].number);
set_attr(0);
} else {
test_acs(0);
}
while (1) {
ptextln("[r] to repeat, [012345789] to test with attributes on, [?] for a list of attributes, anything else to go to next test. ");
generic_done_message(t, state, ch);
if (*ch != '?') {
break;
}
for (i = 0; i <= 9; i++) {
sprintf(temp, " %d %s %s", i, alt_modes[i].begin_mode,
alt_modes[i].name);
ptextln(temp);
}
}
if (*ch >= '0' && *ch <= '9') {
c = *ch;
} else
if (*ch != 'r') {
break;
}
}
} else {
ptext("(smacs) Enter-alt-char-set-mode and (acsc) Alternate-char-set are not defined. ");
generic_done_message(t, state, ch);
}
}
/*
** charset_can_test()
**
** Initialize the can_test data base
*/
void
charset_can_test(void)
{
int i;
for (i = 0; i < 9; i++) {
can_test(alt_modes[i].begin_mode, FLAG_CAN_TEST);
can_test(alt_modes[i].end_mode, FLAG_CAN_TEST);
}
}

View File

@ -1,769 +0,0 @@
/*
** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
**
** This file is part of TACK.
**
** TACK 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.
**
** TACK 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 TACK; see the file COPYING. If not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
** Boston, MA 02110-1301, USA
*/
#include <tack.h>
MODULE_ID("$Id: color.c,v 1.7 2006/11/26 00:14:25 tom Exp $")
/*
* Color terminal tests. Has only one entry point: test_color().
*/
static void color_check(struct test_list *, int *, int *);
static void color_setf(struct test_list *, int *, int *);
static void color_matrix(struct test_list *, int *, int *);
static void color_ncv(struct test_list *, int *, int *);
static void color_ccc(struct test_list *, int *, int *);
static void color_bce(struct test_list *, int *, int *);
struct test_list color_test_list[] = {
{0, 0, 0, 0, "e) edit terminfo", 0, &edit_menu},
{MENU_NEXT, 2, "colors) (pairs", 0, 0, color_check, 0},
{MENU_NEXT, 12, "setf) (setb) (scp", 0, 0, color_setf, 0},
{MENU_NEXT, 24, "op", 0, 0, color_matrix, 0},
{MENU_NEXT, 16, "ncv", 0, 0, color_ncv, 0},
{MENU_NEXT, 0, "bce", 0, 0, color_bce, 0},
{MENU_NEXT | MENU_CLEAR, 0, "ccc) (initc) (initp", "hls op oc", 0, color_ccc, 0},
{MENU_LAST, 0, 0, 0, 0, 0, 0}
};
#ifndef COLOR_BLACK
#define COLOR_BLACK 0
#define COLOR_BLUE 1
#define COLOR_GREEN 2
#define COLOR_CYAN 3
#define COLOR_RED 4
#define COLOR_MAGENTA 5
#define COLOR_YELLOW 6
#define COLOR_WHITE 7
#endif
struct color_table {
const char *name;
int index;
int r, g, b;
int h, l, s;
};
static struct color_table def_colors[8] = {
{"black ", COLOR_BLACK, 0, 0, 0, 0, 0, 0},
{"blue ", COLOR_BLUE, 0, 0, 1000, 330, 50, 100},
{"green ", COLOR_GREEN, 0, 1000, 0, 240, 50, 100},
{"cyan ", COLOR_CYAN, 0, 1000, 1000, 300, 50, 100},
{"red ", COLOR_RED, 1000, 0, 0, 120, 50, 100},
{"magenta", COLOR_MAGENTA, 1000, 0, 1000, 60, 50, 100},
{"yellow ", COLOR_YELLOW, 1000, 1000, 0, 180, 50, 100},
{"white ", COLOR_WHITE, 1000, 1000, 1000, 0, 100, 0}
};
#define MAX_PAIR 256
static int fg_color[MAX_PAIR] = {COLOR_BLACK, COLOR_BLUE, COLOR_GREEN,
COLOR_CYAN, COLOR_RED, COLOR_MAGENTA, COLOR_YELLOW, COLOR_WHITE};
static int bg_color[MAX_PAIR] = {COLOR_BLACK, COLOR_BLACK, COLOR_BLACK,
COLOR_BLACK, COLOR_BLACK, COLOR_BLACK, COLOR_BLACK, COLOR_BLACK};
static int pairs_used = 8;
static int a_bright_color, bright_value;
static int cookie_monster, color_step, colors_per_line;
static int R, G, B;
static void reset_colors(void)
{
tc_putp(orig_colors);
tc_putp(TPARM_0(orig_pair));
}
static int
color_trans(int c)
{ /* translate or load the color */
int i;
for (i = 0; i < pairs_used; i++) {
if (fg_color[i] == c) {
return i;
}
}
if (!can_change) {
return 0;
}
if (pairs_used > max_colors || pairs_used >= MAX_PAIR) {
pairs_used = 0;
ptextln("Ran out of colors");
}
fg_color[pairs_used] = c;
bg_color[pairs_used] = c;
if (hue_lightness_saturation) {
tc_putp(TPARM_4(initialize_color, pairs_used,
def_colors[c].h, def_colors[c].l, def_colors[c].s));
} else {
tc_putp(TPARM_4(initialize_color, pairs_used,
def_colors[c].r, def_colors[c].g, def_colors[c].b));
}
return pairs_used++;
}
static void
new_color(
int fg,
int bg,
int hungry)
{ /* change the color to fg and bg. */
int i;
if (hungry) {
eat_cookie();
}
if (set_a_foreground) {
/* set ANSI color (setaf) (setab) */
tc_putp(TPARM_1(set_a_foreground, fg));
tc_putp(TPARM_1(set_a_background, bg));
} else if (set_foreground) {
/* make sure black is zero */
(void) color_trans(COLOR_BLACK);
tc_putp(TPARM_1(set_foreground, color_trans(fg)));
tc_putp(TPARM_1(set_background, color_trans(bg)));
} else { /* set color pair */
for (i = 0; i < pairs_used; i++) {
if (fg_color[i] == fg && bg_color[i] == bg) {
tc_putp(TPARM_1(set_color_pair, i));
if (hungry) {
eat_cookie();
}
return;
}
}
if (!can_change) {
/* try to set just the foreground */
for (i = pairs_used - 1; i; i--) {
if (fg_color[i] == fg)
break;
}
tc_putp(TPARM_1(set_color_pair, i));
if (hungry) {
eat_cookie();
}
return;
}
if (pairs_used > max_pairs || pairs_used >= MAX_PAIR) {
pairs_used = 0;
ptextln("Ran out of color pairs");
}
fg_color[pairs_used] = fg;
bg_color[pairs_used] = bg;
if (hue_lightness_saturation) {
tc_putp(TPARM_7(initialize_pair, pairs_used,
def_colors[fg].h, def_colors[fg].l, def_colors[fg].s,
def_colors[bg].h, def_colors[bg].l, def_colors[bg].s));
} else {
tc_putp(TPARM_7(initialize_pair, pairs_used,
def_colors[fg].r, def_colors[fg].g, def_colors[fg].b,
def_colors[bg].r, def_colors[bg].g, def_colors[bg].b));
}
tc_putp(TPARM_1(set_color_pair, pairs_used));
pairs_used++;
}
if (hungry) {
eat_cookie();
}
}
static void
set_color_step(void)
{ /* set the color_step for the (ccc) display */
int i;
for (i = 2; i < 1000; i++) {
if ((i * i * i) >= max_colors) {
break;
}
}
color_step = 1000 / (i - 1);
}
static void
rgb_2_hls(int r, int g, int b, int *h, int *l, int *s)
{ /* convert RGB to HLS system */
int min, max, t;
if ((min = g < r ? g : r) > b) {
min = b;
}
if ((max = g > r ? g : r) < b) {
max = b;
}
/* calculate lightness */
*l = (min + max) / 20;
if (min == max) { /* black, white and all shades of gray */
*h = 0;
*s = 0;
return;
}
/* calculate saturation */
if (*l < 50) {
*s = ((max - min) * 100) / (max + min);
} else {
*s = ((max - min) * 100) / (2000 - max - min);
}
/* calculate hue */
if (r == max) {
t = 120 + ((g - b) * 60) / (max - min);
} else if (g == max) {
t = 240 + ((b - r) * 60) / (max - min);
} else {
t = 360 + ((r - g) * 60) / (max - min);
}
*h = t % 360;
}
static void
send_color(int p, int r, int g, int b)
{ /* send the initialize_color (initc) command */
int h, l, s;
if (hue_lightness_saturation) {
rgb_2_hls(r, g, b, &h, &l, &s);
tc_putp(TPARM_4(initialize_color, p, h, l, s));
} else {
tc_putp(TPARM_4(initialize_color, p, r, g, b));
}
}
static void
send_pair(int p, int fr, int fg, int fb, int br, int bg, int bb)
{ /* send the initialize_pair (initp) command */
int fh, fl, fs, bh, bl, bs;
if (hue_lightness_saturation) {
rgb_2_hls(fr, fg, fb, &fh, &fl, &fs);
rgb_2_hls(br, bg, bb, &bh, &bl, &bs);
tc_putp(TPARM_7(initialize_pair, p, fh, fl, fs, bh, bl, bs));
} else {
tc_putp(TPARM_7(initialize_pair, p, fr, fg, fb, bb, bg, bb));
}
}
static int
load_palette(int n)
{ /* load the color palette */
int rgb;
for (;;) {
if (pairs_used >= n) {
return FALSE;
}
if (set_a_foreground || set_foreground) {
if (pairs_used >= max_colors) {
return FALSE;
}
send_color(pairs_used, R, G, B);
rgb = R + G + B;
if (rgb > bright_value) {
bright_value = rgb;
a_bright_color = pairs_used;
}
} else {
if (pairs_used >= max_pairs) {
return FALSE;
}
if (pairs_used == 0) {
send_pair(pairs_used, 1000, 1000, 1000, R, G, B);
} else {
send_pair(pairs_used, R, G, B, R, G, B);
}
}
pairs_used++;
if ((B += color_step) > 1000) {
B = 0;
if ((G += color_step) > 1000) {
G = 0;
if ((R += color_step) > 1000) {
return TRUE;
}
}
}
}
}
static int
rainbow(int n)
{ /* print the programmable color display */
int i, c, d, palette_full, initial_pair;
static const struct {
const char *name;
char ch;
} splat[] = {
{"Bg normal", ' '},
{"Fg normal", ' '},
{0, 0}
};
if ((set_a_foreground || set_foreground)
? pairs_used >= max_colors
: pairs_used >= max_pairs) {
ptext("New palette: ");
(void) wait_here();
initial_pair = pairs_used = 1;
bright_value = 0;
} else if (line_count + 3 >= lines) {
ptext("Go: ");
(void) wait_here();
put_clear();
initial_pair = pairs_used = 1;
bright_value = 0;
n++;
} else {
initial_pair = pairs_used;
n += initial_pair;
}
palette_full = load_palette(n);
for (d = 0; splat[d].name; d++) {
c = splat[d].ch;
if (d == 1) {
put_mode(enter_reverse_mode);
}
for (i = initial_pair; i < n; i++) {
if (i >= pairs_used) {
break;
}
if (set_a_foreground) {
if (i >= max_colors) {
break;
}
tc_putp(TPARM_1(set_a_foreground, i));
tc_putp(TPARM_1(set_a_background, i));
} else if (set_foreground) {
if (i >= max_colors) {
break;
}
tc_putp(TPARM_1(set_foreground, i));
tc_putp(TPARM_1(set_background, i));
} else {
if (i >= max_pairs) {
break;
}
tc_putp(TPARM_1(set_color_pair, i));
}
putchp(c);
}
if (d == 1) {
put_mode(exit_attribute_mode);
}
if (set_a_foreground) {
tc_putp(TPARM_1(set_a_foreground, a_bright_color));
tc_putp(TPARM_1(set_a_background, 0));
} else if (set_foreground) {
tc_putp(TPARM_1(set_foreground, a_bright_color));
tc_putp(TPARM_1(set_background, 0));
} else {
tc_putp(TPARM_1(set_color_pair, 0));
}
put_str(" ");
put_str(splat[d].name);
put_crlf();
}
return palette_full;
}
static void
ncv_display(int m)
{ /* print the no_color_video (ncv) test line */
putchp('0' + m);
putchp(' ');
eat_cookie();
set_attr(1 << m);
sprintf(temp, "%-11s", alt_modes[m].name);
put_str(temp);
new_color(COLOR_BLUE, COLOR_BLACK, TRUE);
put_str("blue");
new_color(COLOR_BLACK, COLOR_GREEN, TRUE);
put_str("green");
new_color(COLOR_WHITE, COLOR_BLACK, TRUE);
put_str(alt_modes[m].name);
eat_cookie();
set_attr(0);
reset_colors();
put_crlf();
}
static void
dump_colors(void)
{ /* display the colors in some esthetic
pattern */
static int xmap[8] = {0, 3, 4, 7, 1, 2, 5, 6};
int i, j, k, xi, xj, width, p, cs;
int found_one;
cs = color_step <= 125 ? 125 : color_step;
width = (1000 / cs) + 1;
for (xi = 0; xi < 16; xi++) {
i = (xi & 8) ? xi ^ 15 : xi;
R = i * cs;
if (R <= 1000) {
found_one = FALSE;
for (xj = 0; xj < 32; xj++) {
j = ((xj & 8) ? xj ^ 15 : xj) & 7;
k = xmap[((xi >> 1) & 4) + (xj >> 3)];
G = j * cs;
B = k * cs;
if (G <= 1000 && B <= 1000) {
p = (k * width + j) * width + i;
if (set_a_background) {
if (p >= max_colors) {
continue;
}
send_color(p, R, G, B);
tc_putp(TPARM_1(set_a_background, p));
} else if (set_background) {
if (p >= max_colors) {
continue;
}
send_color(p, R, G, B);
tc_putp(TPARM_1(set_background, p));
} else {
if (p >= max_pairs) {
continue;
}
send_pair(p, R, G, B, R, G, B);
tc_putp(TPARM_1(set_color_pair, p));
}
found_one = TRUE;
putchp(' ');
putchp(' ');
}
}
if (found_one) {
put_crlf();
}
}
}
}
/*
** color_check(test_list, status, ch)
**
** test (colors) and (pairs)
*/
static void
color_check(
struct test_list *t,
int *state,
int *ch)
{
if (max_colors <= 0 && max_pairs <= 0) {
ptext("This is not a color terminal; (colors) and (pairs) are missing. ");
*state |= MENU_STOP;
} else {
sprintf(temp, "This terminal can display %d colors and %d color pairs. (colors) (pairs)",
max_colors, max_pairs);
ptextln(temp);
}
generic_done_message(t, state, ch);
}
/*
** color_setf(test_list, status, ch)
**
** test (setf) (setb) and (scp)
*/
static void
color_setf(
struct test_list *t,
int *state,
int *ch)
{
int i, j;
if (max_colors <= 0 && max_pairs <= 0) {
ptext("This is not a color terminal; (colors) and (pairs) are missing. ");
generic_done_message(t, state, ch);
*state |= MENU_STOP;
return;
}
if ((set_a_foreground == NULL || set_a_background == NULL)
&& (set_foreground == NULL || set_background == NULL)
&& set_color_pair == NULL) {
ptextln("Both set foreground (setaf/setf) and set color pair (scp) are not present.");
if (!set_a_background || !set_background) {
ptextln("(setab/setb) set background not present");
}
ptext("These must be defined for color testing. ");
generic_done_message(t, state, ch);
*state |= MENU_STOP;
return;
}
/* initialize the color palette */
pairs_used = max_colors >= 8 ? 8 : max_colors;
reset_colors();
new_color(COLOR_WHITE, COLOR_BLACK, FALSE);
ptextln("(setf) (setb) (scp) The following colors are predefined:");
ptextln("\n Foreground Background");
put_crlf();
j = max_colors > 8 ? 8 : max_colors;
/*
* the black on white test is the same as the white on black test.
*/
for (i = 1; i < j; i++) {
putchp('0' + def_colors[i].index);
putchp(' ');
sprintf(temp, " %s ", def_colors[i].name);
new_color(def_colors[i].index, COLOR_BLACK, TRUE);
put_str(temp);
new_color(COLOR_BLACK, COLOR_BLACK, TRUE);
put_str(" ");
new_color(COLOR_BLACK, def_colors[i].index, TRUE);
put_str(temp);
new_color(COLOR_WHITE, COLOR_BLACK, FALSE);
put_crlf();
}
reset_colors();
put_crlf();
generic_done_message(t, state, ch);
}
/*
** color_matrix(test_list, status, ch)
**
** test (pairs) (op)
*/
static void
color_matrix(
struct test_list *t,
int *state,
int *ch)
{
int i, j, matrix_size, matrix_area, brightness;
matrix_size = max_colors > 8 ? 8 : max_colors;
sprintf(temp, "(pairs) There are %d color pairs.", max_pairs);
ptextln(temp);
for ( ; matrix_size; matrix_size--) {
if (matrix_size * matrix_size <= max_pairs) {
break;
}
}
matrix_area = matrix_size * matrix_size;
for (brightness = 0; brightness < 2; brightness++) {
put_crlf();
sprintf(temp,
"%dx%d matrix of foreground/background colors, bright *o%s*",
matrix_size, matrix_size, brightness ? "n" : "ff");
put_str(temp);
put_str("\n ");
for (i = 0; i < matrix_size; i++) {
(void) sprintf(temp, "%-8s", def_colors[i].name);
put_str(temp);
}
for (j = 0; j < matrix_area; j++) {
if (j % matrix_size == 0) {
reset_colors();
put_crlf();
if (brightness) {
tc_putp(exit_attribute_mode);
}
(void) sprintf(temp, "%-8s", def_colors[j / matrix_size].name);
put_str(temp);
if (brightness) {
put_mode(enter_bold_mode);
}
}
new_color(def_colors[j % matrix_size].index,
def_colors[j / matrix_size].index,
FALSE);
put_str(" Hello ");
}
reset_colors();
if (brightness) {
tc_putp(exit_attribute_mode);
}
put_crlf();
}
generic_done_message(t, state, ch);
}
/*
** color_ncv(test_list, status, ch)
**
** test (ncv)
*/
static void
color_ncv(
struct test_list *t,
int *state,
int *ch)
{
int i;
if (no_color_video == -1) {
/* I have no idea what this means */
return;
}
sprintf(temp, "According to no_color_video (ncv) which is %d, the following attributes should work correctly with color.", no_color_video);
ptextln(temp);
put_crlf();
set_attr(0);
ncv_display(0);
for (i = 1; i <= 9; i++) {
if (((no_color_video >> (mode_map[i] - 1)) & 1) == 0) {
ncv_display(mode_map[i]);
}
}
if (no_color_video & 0x3ff) {
ptextln("\nThe following attributes should not work correctly with color. (ncv)\n");
for (i = 1; i <= 9; i++) {
if ((no_color_video >> (mode_map[i] - 1)) & 1) {
ncv_display(mode_map[i]);
}
}
}
reset_colors();
put_crlf();
generic_done_message(t, state, ch);
}
/*
** color_bce(test_list, status, ch)
**
** test (bce) background color erase
*/
static void
color_bce(
struct test_list *t,
int *state,
int *ch)
{
new_color(COLOR_CYAN, COLOR_BLUE, FALSE);
put_clear();
put_newlines(2);
reset_colors();
ptextln("If the two lines above are blue then back_color_erase (bce) should be true.");
sprintf(temp, "(bce) is %s in the data base.", back_color_erase ? "true" : "false");
ptextln(temp);
generic_done_message(t, state, ch);
}
/*
** color_ccc(test_list, status, ch)
**
** test (ccc) color palette test (oc) (op) (initc) (initp)
*/
static void
color_ccc(
struct test_list *t,
int *state,
int *ch)
{
int i, j;
if (!can_change) {
ptextln("Terminal can not change colors (ccc)");
generic_done_message(t, state, ch);
return;
}
reset_colors();
pairs_used = 0;
new_color(COLOR_WHITE, COLOR_BLACK, FALSE);
sprintf(temp, "Reloading colors (init%c) using %s method",
set_foreground ? 'c' : 'p',
hue_lightness_saturation ? "HLS" : "RGB");
ptextln(temp);
put_crlf();
j = max_colors > 7 ? 7 : max_colors;
/* redisplay the above test with reinitialized colors */
/* If these colors don't look right to you... */
for (i = 0; i < j; i++) {
sprintf(temp, " %s ", def_colors[i ^ 7].name);
new_color(i ^ 7, COLOR_BLACK, TRUE);
put_str(temp);
new_color(COLOR_BLACK, COLOR_BLACK, TRUE);
put_str(" ");
new_color(COLOR_BLACK, i ^ 7, TRUE);
put_str(temp);
new_color(COLOR_WHITE, COLOR_BLACK, FALSE);
put_crlf();
}
generic_done_message(t, state, ch);
if (*ch != 0 && *ch != 'n') {
reset_colors();
return;
}
pairs_used = 0;
cookie_monster = 0;
if (magic_cookie_glitch > 0) {
cookie_monster =
((set_a_foreground || set_foreground)
? magic_cookie_glitch : 0) +
((set_a_background || set_background)
? magic_cookie_glitch : 0) +
(set_color_pair ? magic_cookie_glitch : 0);
}
set_color_step();
colors_per_line = max_colors > max_pairs
? max_pairs : max_colors;
j = (columns - 14) / (cookie_monster + 1);
if (colors_per_line > j) {
colors_per_line = (j / i) * i;
}
sprintf(temp, "RGB color step %d, cookies %d", color_step,
cookie_monster);
ptextln(temp);
R = G = B = 0;
pairs_used = 0;
for (;;) {
if (rainbow(colors_per_line)) {
break;
}
}
generic_done_message(t, state, ch);
if (*ch != 0 && *ch != 'n') {
reset_colors();
return;
}
dump_colors();
reset_colors();
generic_done_message(t, state, ch);
}

View File

@ -1,664 +0,0 @@
/*
** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
**
** This file is part of TACK.
**
** TACK 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.
**
** TACK 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 TACK; see the file COPYING. If not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
** Boston, MA 02110-1301, USA
*/
#include <tack.h>
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
MODULE_ID("$Id: control.c,v 1.9 2006/06/24 21:27:53 tom Exp $")
/* terminfo test program control subroutines */
#if HAVE_GETTIMEOFDAY
#define MY_TIMER struct timeval
#else
#define MY_TIMER time_t
#endif
/* globals */
int test_complete; /* counts number of tests completed */
char txt_longer_test_time[80]; /* +) use longer time */
char txt_shorter_test_time[80]; /* -) use shorter time */
static int pad_test_duration = 1; /* number of seconds for a pad test */
int auto_pad_mode; /* run the time tests */
int no_alarm_event; /* TRUE if the alarm has not gone off yet */
unsigned long usec_run_time; /* length of last test in microseconds */
static MY_TIMER stop_watch[MAX_TIMERS]; /* Hold the start timers */
char txt_longer_augment[80]; /* >) use bigger augment */
char txt_shorter_augment[80]; /* <) use smaller augment */
/* caps under test data base */
int tt_delay_max; /* max number of milliseconds we can delay */
int tt_delay_used; /* number of milliseconds consumed in delay */
const char *tt_cap[TT_MAX]; /* value of string */
int tt_affected[TT_MAX]; /* lines or columns effected (repetition factor) */
int tt_count[TT_MAX]; /* Number of times sent */
int tt_delay[TT_MAX]; /* Number of milliseconds delay */
int ttp; /* number of entries used */
/* Saved value of the above data base */
const char *tx_cap[TT_MAX]; /* value of string */
int tx_affected[TT_MAX]; /* lines or columns effected (repetition factor) */
int tx_count[TT_MAX]; /* Number of times sent */
int tx_index[TT_MAX]; /* String index */
int tx_delay[TT_MAX]; /* Number of milliseconds delay */
int txp; /* number of entries used */
int tx_characters; /* printing characters sent by test */
unsigned long tx_cps; /* characters per second */
static struct test_list *tx_source; /* The test that generated this data */
#define RESULT_BLOCK 1024
static int blocks; /* number of result blocks available */
static struct test_results *results; /* pointer to next available */
static struct test_results **pads; /* save pad results here */
static void
alloc_arrays(void)
{
if (pads == 0) {
pads = (struct test_results **)calloc(MAX_STRINGS, sizeof(struct test_results *));
}
}
/*
** event_start(number)
**
** Begin the stopwatch at the current time-of-day.
*/
void
event_start(int n)
{
#if HAVE_GETTIMEOFDAY
(void) gettimeofday(&stop_watch[n], (struct timezone *)0);
#else
stop_watch[n] = time((time_t *)0);
#endif
}
/*
** event_time(number)
**
** Return the number of milliseconds since this stop watch began.
*/
long
event_time(int n)
{
#if HAVE_GETTIMEOFDAY
MY_TIMER current_time;
(void) gettimeofday(&current_time, (struct timezone *)0);
return ((current_time.tv_sec - stop_watch[n].tv_sec) * 1000000)
+ current_time.tv_usec - stop_watch[n].tv_usec;
#else
return (time((time_t *)0) - stop_watch[n]) * 1000;
#endif
}
/*****************************************************************************
*
* Execution control for string capability tests
*
*****************************************************************************/
/*
** get_next_block()
**
** Get a results block for pad test data.
*/
static struct test_results *
get_next_block(void)
{
if (blocks <= 0) {
results = (struct test_results *)
malloc(sizeof(struct test_results) * RESULT_BLOCK);
if (!results) {
ptextln("Malloc failed");
return (struct test_results *) 0;
}
blocks = RESULT_BLOCK;
}
blocks--;
return results++;
}
/*
** set_augment_txt()
**
** Initialize the augment menu selections
*/
void
set_augment_txt(void)
{
sprintf(txt_longer_augment,
">) Change lines/characters effected to %d", augment << 1);
sprintf(txt_shorter_augment,
"<) Change lines/characters effected to %d", augment >> 1);
}
void
control_init(void)
{
sprintf(txt_longer_test_time, "+) Change test time to %d seconds",
pad_test_duration + 1);
sprintf(txt_shorter_test_time, "-) Change test time to %d seconds",
pad_test_duration - 1);
set_augment_txt();
}
/*
** msec_cost(cap, affected-count)
**
** Return the number of milliseconds delay needed by the cap.
*/
int
msec_cost(
const char *const cap,
int affcnt)
{
int dec, value, total, star, ch;
const char *cp;
if (!cap) {
return 0;
}
total = 0;
for (cp = cap; *cp; cp++) {
if (*cp == '$' && cp[1] == '<') {
star = 1;
value = dec = 0;
for (cp += 2; (ch = *cp); cp++) {
if (ch >= '0' && ch <= '9') {
value = value * 10 + (ch - '0');
dec *= 10;
} else
if (ch == '.') {
dec = 1;
} else
if (ch == '*') {
star = affcnt;
} else
if (ch == '>') {
break;
}
}
if (dec > 1) {
total += (value * star) / dec;
} else {
total += (value * star);
}
}
}
return total;
}
/*
** liberated(cap)
**
** Return the cap without padding
*/
char *
liberated(char *cap)
{
static char cb[1024];
char *ts, *ls;
cb[0] = '\0';
ls = NULL;
if (cap) {
for (ts = cb; (*ts = *cap); ++cap) {
if (*cap == '$' && cap[1] == '<') {
ls = ts;
}
++ts;
if (*cap == '>') {
if (ls) {
ts = ls;
ls = NULL;
}
}
}
}
return cb;
}
/*
** page_loop()
**
** send CR/LF or go home and bump letter
*/
void
page_loop(void)
{
if (line_count + 2 >= lines) {
NEXT_LETTER;
go_home();
} else {
put_crlf();
}
}
/*
** skip_pad_test(test-list-entry, state, ch, text)
**
** Print the start test line. Handle start up commands.
** Return TRUE if a return is requested.
*/
int
skip_pad_test(
struct test_list *test,
int *state,
int *ch,
const char *text)
{
char rep_text[16];
while(1) {
if (text) {
ptext(text);
}
if ((test->flags & MENU_LC_MASK)) {
sprintf(rep_text, " *%d", augment);
ptext(rep_text);
}
ptext(" [n] > ");
*ch = wait_here();
if (*ch == 's') {
/* Skip is converted to next */
*ch = 'n';
return TRUE;
}
if (*ch == 'q') {
/* Quit is converted to help */
*ch = '?';
return TRUE;
}
if (*ch == '\r' || *ch == '\n' || *ch == 'n' || *ch == 'r') {
/* this is the only response that allows the test to run */
*ch = 0;
}
if (subtest_menu(pad_test_list, state, ch)) {
continue;
}
return (*ch != 0);
}
}
/*
** pad_done_message(test_list)
**
** Print the Done message and request input.
*/
void
pad_done_message(
struct test_list *test,
int *state,
int *ch)
{
int default_action = 0;
char done_message[128];
char rep_text[16];
while (1) {
if ((test->flags & MENU_LC_MASK)) {
sprintf(rep_text, "*%d", augment);
} else {
rep_text[0] = '\0';
}
if (test->caps_done) {
sprintf(done_message, "(%s)%s Done ", test->caps_done,
rep_text);
ptext(done_message);
} else {
if (rep_text[0]) {
ptext(rep_text);
ptext(" ");
}
ptext("Done ");
}
if (debug_level & 2) {
dump_test_stats(test, state, ch);
} else {
*ch = wait_here();
}
if (*ch == '\r' || *ch == '\n') {
*ch = default_action;
return;
}
if (*ch == 's' || *ch == 'n') {
*ch = 0;
return;
}
if (strchr(pad_repeat_test, *ch)) {
/* default action is now repeat */
default_action = 'r';
}
if (subtest_menu(pad_test_list, state, ch)) {
continue;
}
return;
}
}
/*
** sliding_scale(dividend, factor, divisor)
**
** Return (dividend * factor) / divisor
*/
int
sliding_scale(
int dividend,
int factor,
unsigned long divisor)
{
double d = dividend;
if (divisor) {
d = (d * (double) factor) / (double) divisor;
return (int) (d + 0.5);
}
return 0;
}
/*
** pad_test_startup()
**
** Do the stuff needed to begin a test.
*/
void
pad_test_startup(
int do_clear)
{
if (do_clear) {
put_clear();
}
repeats = augment;
raw_characters_sent = 0;
test_complete = ttp = char_count = tt_delay_used = 0;
letter = letters[letter_number = 0];
if (pad_test_duration <= 0) {
pad_test_duration = 1;
}
tt_delay_max = pad_test_duration * 1000;
set_alarm_clock(pad_test_duration);
event_start(TIME_TEST);
}
/*
** still_testing()
**
** This function is called to see if the test loop should be terminated.
*/
int
still_testing(void)
{
fflush(stdout);
test_complete++;
return EXIT_CONDITION;
}
/*
** pad_test_shutdown()
**
** Do the stuff needed to end a test.
*/
void
pad_test_shutdown(
struct test_list *t,
int crlf)
{
int i;
int counts; /* total counts */
int ss; /* Save string index */
int cpo; /* characters per operation */
int delta; /* difference in characters */
int bogus; /* Time is inaccurate */
struct test_results *r; /* Results of current test */
int ss_index[TT_MAX]; /* String index */
alloc_arrays();
if (tty_can_sync == SYNC_TESTED) {
bogus = tty_sync_error();
} else {
bogus = 1;
}
usec_run_time = event_time(TIME_TEST);
tx_source = t;
tx_characters = raw_characters_sent;
tx_cps = sliding_scale(tx_characters, 1000000, usec_run_time);
/* save the data base */
for (txp = ss = counts = 0; txp < ttp; txp++) {
tx_cap[txp] = tt_cap[txp];
tx_count[txp] = tt_count[txp];
tx_delay[txp] = tt_delay[txp];
tx_affected[txp] = tt_affected[txp];
tx_index[txp] = get_string_cap_byvalue(tt_cap[txp]);
if (tx_index[txp] >= 0) {
if (cap_match(t->caps_done, strnames[tx_index[txp]])) {
ss_index[ss++] = txp;
counts += tx_count[txp];
}
}
}
if (crlf) {
put_crlf();
}
if (counts == 0 || tty_cps == 0 || bogus) {
/* nothing to do */
return;
}
/* calculate the suggested pad times */
delta = usec_run_time - sliding_scale(tx_characters, 1000000, tty_cps);
if (delta < 0) {
/* probably should bump tx_characters */
delta = 0;
}
cpo = delta / counts;
for (i = 0; i < ss; i++) {
if (!(r = get_next_block())) {
return;
}
r->next = pads[tx_index[ss_index[i]]];
pads[tx_index[ss_index[i]]] = r;
r->test = t;
r->reps = tx_affected[ss_index[i]];
r->delay = cpo;
}
}
/*
** show_cap_results(index)
**
** Display the previous results
*/
static void
show_cap_results(
int x)
{
struct test_results *r; /* a result */
int delay;
alloc_arrays();
if ((r = pads[x])) {
sprintf(temp, "(%s)", strnames[x]);
ptext(temp);
while (r) {
sprintf(temp, "$<%d>", r->delay / 1000);
put_columns(temp, (int) strlen(temp), 10);
r = r->next;
}
r = pads[x];
while (r) {
if (r->reps > 1) {
delay = r->delay / (r->reps * 100);
sprintf(temp, "$<%d.%d*>", delay / 10, delay % 10);
put_columns(temp, (int) strlen(temp), 10);
}
r = r->next;
}
put_crlf();
}
}
/*
** dump_test_stats(test_list, status, ch)
**
** Dump the statistics about the last test
*/
void
dump_test_stats(
struct test_list *t,
int *state,
int *ch)
{
int i, j;
char tbuf[32];
int x[32];
put_crlf();
if (tx_source && tx_source->caps_done) {
cap_index(tx_source->caps_done, x);
if (x[0] >= 0) {
sprintf(temp, "Caps summary for (%s)",
tx_source->caps_done);
ptextln(temp);
for (i = 0; x[i] >= 0; i++) {
show_cap_results(x[i]);
}
put_crlf();
}
}
sprintf(tbuf, "%011lu", usec_run_time);
sprintf(temp, "Test time: %lu.%s, characters per second %lu, characters %d",
usec_run_time / 1000000UL, &tbuf[5], tx_cps, tx_characters);
ptextln(temp);
for (i = 0; i < txp; i++) {
if ((j = get_string_cap_byvalue(tx_cap[i])) >= 0) {
sprintf(tbuf, "(%s)", strnames[j]);
} else {
strcpy(tbuf, "(?)");
}
sprintf(temp, "%8d %3d $<%3d> %8s %s",
tx_count[i], tx_affected[i], tx_delay[i],
tbuf, expand(tx_cap[i]));
putln(temp);
}
generic_done_message(t, state, ch);
}
/*
** longer_test_time(test_list, status, ch)
**
** Extend the number of seconds for each test.
*/
void
longer_test_time(
struct test_list *t GCC_UNUSED,
int *state GCC_UNUSED,
int *ch)
{
pad_test_duration += 1;
sprintf(txt_longer_test_time, "+) Change test time to %d seconds",
pad_test_duration + 1);
sprintf(txt_shorter_test_time, "-) Change test time to %d seconds",
pad_test_duration - 1);
sprintf(temp, "Tests will run for %d seconds", pad_test_duration);
ptext(temp);
*ch = REQUEST_PROMPT;
}
/*
** shorter_test_time(test_list, status, ch)
**
** Shorten the number of seconds for each test.
*/
void
shorter_test_time(
struct test_list *t GCC_UNUSED,
int *state GCC_UNUSED,
int *ch)
{
if (pad_test_duration > 1) {
pad_test_duration -= 1;
sprintf(txt_longer_test_time, "+) Change test time to %d seconds",
pad_test_duration + 1);
sprintf(txt_shorter_test_time, "-) Change test time to %d seconds",
pad_test_duration - 1);
}
sprintf(temp, "Tests will run for %d second%s", pad_test_duration,
pad_test_duration > 1 ? "s" : "");
ptext(temp);
*ch = REQUEST_PROMPT;
}
/*
** longer_augment(test_list, status, ch)
**
** Lengthen the number of lines/characters effected
*/
void
longer_augment(
struct test_list *t,
int *state GCC_UNUSED,
int *ch)
{
augment <<= 1;
set_augment_txt();
if (augment_test) {
t = augment_test;
}
sprintf(temp, "The pad tests will effect %d %s.", augment,
((t->flags & MENU_LC_MASK) == MENU_lines) ?
"lines" : "characters");
ptextln(temp);
*ch = REQUEST_PROMPT;
}
/*
** shorter_augment(test_list, status, ch)
**
** Shorten the number of lines/characters effected
*/
void
shorter_augment(
struct test_list *t,
int *state GCC_UNUSED,
int *ch)
{
if (augment > 1) {
/* don't let the augment go to zero */
augment >>= 1;
}
set_augment_txt();
if (augment_test) {
t = augment_test;
}
sprintf(temp, "The pad tests will effect %d %s.", augment,
((t->flags & MENU_LC_MASK) == MENU_lines) ?
"lines" : "characters");
ptextln(temp);
*ch = REQUEST_PROMPT;
}

View File

@ -1,426 +0,0 @@
/*
** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
**
** This file is part of TACK.
**
** TACK 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.
**
** TACK 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 TACK; see the file COPYING. If not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
** Boston, MA 02110-1301, USA
*/
#include <tack.h>
MODULE_ID("$Id: crum.c,v 1.5 2006/11/26 00:15:02 tom Exp $")
/*
* Test cursor movement.
*/
static void crum_clear(struct test_list *t, int *state, int *ch);
static void crum_home(struct test_list *t, int *state, int *ch);
static void crum_ll(struct test_list *t, int *state, int *ch);
static void crum_move(struct test_list *t, int *state, int *ch);
static void crum_os(struct test_list *t, int *state, int *ch);
static char crum_text[5][80];
struct test_list crum_test_list[] = {
{0, 0, 0, 0, "e) edit terminfo", 0, &edit_menu},
{MENU_NEXT, 0, "clear", 0, 0, crum_clear, 0},
{MENU_NEXT, 0, "home", 0, 0, crum_home, 0},
{MENU_NEXT, 0, "ll", 0, 0, crum_ll, 0},
{MENU_NEXT, 0, crum_text[0], "home cuu1", 0, crum_move, 0},
{MENU_NEXT + 1, 0, crum_text[1], "cub1 cud1 cuf1 cuu1", 0, crum_move, 0},
{MENU_NEXT + 2, 0, crum_text[2], "cub cud cuf cuu", 0, crum_move, 0},
{MENU_NEXT + 3, 0, crum_text[3], "vpa hpa", 0, crum_move, 0},
{MENU_NEXT + 4, 0, crum_text[4], "cup", 0, crum_move, 0},
{MENU_NEXT, 0, "cup", "os", 0, crum_os, 0},
{MENU_LAST, 0, 0, 0, 0, 0, 0}
};
/*
** move_to(from-row, from-column, to-row, to-column, selection)
**
** move the cursor from (rf, cf) to (rt, ct) using sel
*/
static void
move_to(
int rf,
int cf,
int rt,
int ct,
int sel)
{
char *s;
if (sel & 16) { /* use (cup) */
s = TPARM_2(cursor_address, rt, ct);
tputs(s, lines, tc_putch);
return;
}
if (sel & 8) { /* use (hpa) (vpa) */
if (column_address) {
s = TPARM_1(column_address, ct);
tputs(s, 1, tc_putch);
cf = ct;
}
if (row_address) {
s = TPARM_1(row_address, rt);
tputs(s, 1, tc_putch);
rf = rt;
}
}
if (sel & 4) { /* parameterized relative cursor movement */
if (parm_right_cursor)
if (cf < ct) {
s = TPARM_1(parm_right_cursor, ct - cf);
tputs(s, ct - cf, tc_putch);
cf = ct;
}
if (parm_left_cursor)
if (cf > ct) {
s = TPARM_1(parm_left_cursor, cf - ct);
tputs(s, cf - ct, tc_putch);
cf = ct;
}
if (parm_down_cursor)
if (rf < rt) {
s = TPARM_1(parm_down_cursor, rt - rf);
tputs(s, rt - rf, tc_putch);
rf = rt;
}
if (parm_up_cursor)
if (rf > rt) {
s = TPARM_1(parm_up_cursor, rf - rt);
tputs(s, rf - rt, tc_putch);
rf = rt;
}
}
if (sel & 2) {
if (cursor_left)
while (cf > ct) {
tc_putp(cursor_left);
cf--;
}
/*
do vertical motion next. Just in case cursor_down has a
side effect of changing the column. This could happen if
the tty handler translates NL to CRNL.
*/
if (cursor_down)
while (rf < rt) {
tc_putp(cursor_down);
rf++;
}
if (cursor_up)
while (rf > rt) {
tc_putp(cursor_up);
rf--;
}
if (cursor_right)
while (cf < ct) {
tc_putp(cursor_right);
cf++;
}
}
/* last chance */
if (rf > rt) {
if (can_go_home) { /* a bit drastic but ... */
go_home();
cf = 0;
rf = 0;
} else if (cursor_up) {
while (rf > rt) {
tc_putp(cursor_up);
rf--;
}
}
}
if (ct == 0 && rt > rf) {
put_crlf();
cf = 0;
rf++;
}
if (ct == 0 && cf != 0) {
put_cr();
cf = 0;
}
while (rf < rt) {
put_lf();
rf++;
}
while (cf > ct) {
put_str("\b");
cf--;
}
if (cursor_right) {
while (cf < ct) {
tc_putp(cursor_right);
cf++;
}
} else {
/* go ahead and trash my display */
while (cf < ct) {
putchp(' ');
cf++;
}
}
}
/*
** display_it(selection, text)
**
** print the display using sel
*/
static void
display_it(
int sel,
char *txt)
{
int i, done_line;
put_clear();
go_home();
put_newlines(2);
ptextln(" The top line should be alternating <'s and >'s");
ptextln(" The left side should be alternating A's and V's");
ptext(" Testing ");
ptext(txt);
put_cr();
/* horizontal */
move_to(done_line = line_count, 0, 0, 2, sel);
for (i = 4; i < columns - 2; i += 2) {
putchp('>');
move_to(0, i - 1, 0, i, sel);
}
putchp('>');
i -= 2;
move_to(0, i + 1, 0, i - 1, sel);
for (; i > 2; i -= 2) {
putchp('<');
move_to(0, i, 0, i - 3, sel);
}
putchp('<');
/* vertical */
move_to(0, 2, 0, 0, sel);
for (i = 2; i < lines - 1; i += 2) {
putchp('V');
move_to(i - 2, 1, i, 0, sel);
}
putchp('V');
i -= 2;
move_to(i, 1, i + 1, 0, sel);
for (; i > 0; i -= 2) {
putchp('A');
move_to(i + 1, 1, i - 1, 0, sel);
}
putchp('A');
move_to(i + 1, 1, 0, 0, sel); /* go home first */
move_to(0, 0, done_line + 1, 3, sel);
put_str(txt);
put_str(" Done. ");
}
/*
** crum_clear(test_list, status, ch)
**
** (clear) test Clear screen
*/
static void
crum_clear(
struct test_list *t,
int *state,
int *ch)
{
int i;
if (clear_screen) {
for (i = lines; i > 1; i--) {
putln("garbage");
}
put_clear();
ptextln("This line should start in the home position.");
ptext("The rest of the screen should be clear. ");
} else {
ptextln("(clear) Clear screen is not defined. ");
}
generic_done_message(t, state, ch);
}
/*
** crum_home(test_list, status, ch)
**
** (home) test Home cursor
*/
static void
crum_home(
struct test_list *t,
int *state,
int *ch)
{
if (cursor_home) {
put_clear();
put_newlines(lines / 2);
go_home();
put_crlf();
ptext("The bottom line should have text.");
go_home();
put_newlines(lines - 1);
ptext("This line is on the bottom.");
go_home();
ptextln("This line starts in the home position.");
put_crlf();
} else {
ptextln("(home) Home cursor is not defined. ");
}
generic_done_message(t, state, ch);
}
/*
** crum_ll(test_list, status, ch)
**
** (ll) test Last line
*/
static void
crum_ll(
struct test_list *t,
int *state,
int *ch)
{
/*
(ll) may be simulated with (cup). Don't complain if (cup) is present.
*/
if (cursor_to_ll) {
put_clear();
put_str("This line could be anywhere.");
tc_putp(cursor_to_ll);
ptext("This line should be on the bottom");
go_home();
put_crlf();
} else
if (cursor_address) {
return;
} else {
ptextln("(ll) Move to last line is not defined. ");
}
generic_done_message(t, state, ch);
}
/*
** crum_move(test_list, status, ch)
**
** (*) test all cursor move commands
*/
static void
crum_move(
struct test_list *t,
int *state,
int *ch)
{
char buf[80];
int n;
switch (n = (t->flags & 15)) {
case 0:
sprintf(buf, " (cr) (nel) (cub1)%s",
cursor_home ? " (home)" : (cursor_up ? " (cuu1)" : ""));
break;
case 1:
sprintf(buf, "%s%s%s%s", cursor_left ? " (cub1)" : "",
cursor_down ? " (cud1)" : "", cursor_right ? " (cuf1)" : "",
cursor_up ? " (cuu1)" : "");
if (buf[0] == '\0') {
ptext(" (cub1) (cud1) (cuf1) (cuu1) not defined.");
}
break;
case 2:
sprintf(buf, "%s%s%s%s", parm_left_cursor ? " (cub)" : "",
parm_down_cursor ? " (cud)" : "",
parm_right_cursor ? " (cuf)" : "",
parm_up_cursor ? " (cuu)" : "");
if (buf[0] == '\0') {
ptext(" (cub) (cud) (cuf) (cuu) not defined.");
}
break;
case 3:
sprintf(buf, "%s%s", row_address ? " (vpa)" : "",
column_address ? " (hpa)" : "");
if (buf[0] == '\0') {
ptext(" (vpa) (hpa) not defined.");
}
break;
case 4:
if (!cursor_address) {
ptext(" (cup) not defined. ");
generic_done_message(t, state, ch);
return;
}
strcpy(buf, " (cup)");
break;
}
if (buf[0] == '\0') {
put_str(" Done. ");
} else {
can_test(buf, FLAG_TESTED);
strcpy(crum_text[n], &buf[2]);
crum_text[n][strlen(buf) - 3] = '\0';
display_it(1 << n, buf);
}
*ch = wait_here();
if (*ch != 'r') {
put_clear();
}
}
/*
** crum_os(test_list, status, ch)
**
** (cup) test Cursor position on overstrike terminals
*/
static void
crum_os(
struct test_list *t,
int *state,
int *ch)
{
int i;
if (cursor_address && over_strike) {
put_clear();
for (i = 0; i < columns - 2; i++) {
tc_putch('|');
}
for (i = 1; i < lines - 2; i++) {
put_crlf();
tc_putch('_');
}
for (i = 0; i < columns - 2; i++) {
tputs(TPARM_2(cursor_address, 0, i), lines, tc_putch);
tc_putch('+');
}
for (i = 0; i < lines - 2; i++) {
tputs(TPARM_2(cursor_address, i, 0), lines, tc_putch);
tc_putch(']');
tc_putch('_');
}
go_home();
put_newlines(3);
ptext(" All the characters should look the same. ");
generic_done_message(t, state, ch);
put_clear();
}
}

View File

@ -1,992 +0,0 @@
/*
** Copyright (C) 1997 Free Software Foundation, Inc.
**
** This file is part of TACK.
**
** TACK 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.
**
** TACK 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 TACK; see the file COPYING. If not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
** Boston, MA 02110-1301, USA
*/
#include <tack.h>
#include <time.h>
#include <tic.h>
MODULE_ID("$Id: edit.c,v 1.11 2006/06/24 21:22:42 tom Exp $")
/*
* Terminfo edit features
*/
static void show_info(struct test_list *, int *, int *);
static void show_value(struct test_list *, int *, int *);
static void show_untested(struct test_list *, int *, int *);
static void show_changed(struct test_list *, int *, int *);
#define SHOW_VALUE 1
#define SHOW_EDIT 2
#define SHOW_DELETE 3
struct test_list edit_test_list[] = {
{MENU_CLEAR, 0, 0, 0, "i) display current terminfo", show_info, 0},
{0, 0, 0, 0, "w) write the current terminfo to a file", save_info, 0},
{SHOW_VALUE, 3, 0, 0, "v) show value of a selected cap", show_value, 0},
{SHOW_EDIT, 4, 0, 0, "e) edit value of a selected cap", show_value, 0},
{SHOW_DELETE, 3, 0, 0, "d) delete string", show_value, 0},
{0, 3, 0, 0, "m) show caps that have been modified", show_changed, 0},
{MENU_CLEAR + FLAG_CAN_TEST, 0, 0, 0, "c) show caps that can be tested", show_report, 0},
{MENU_CLEAR + FLAG_TESTED, 0, 0, 0, "t) show caps that have been tested", show_report, 0},
{MENU_CLEAR + FLAG_FUNCTION_KEY, 0, 0, 0, "f) show a list of function keys", show_report, 0},
{MENU_CLEAR, 0, 0, 0, "u) show caps defined that can not be tested", show_untested, 0},
{MENU_LAST, 0, 0, 0, 0, 0, 0}
};
static char change_pad_text[MAX_CHANGES][80];
static struct test_list change_pad_list[MAX_CHANGES] = {
{MENU_LAST, 0, 0, 0, 0, 0, 0}
};
static void build_change_menu(struct test_menu *);
static void change_one_entry(struct test_list *, int *, int *);
struct test_menu change_pad_menu = {
0, 'q', 0,
"Select cap name", "change", 0,
build_change_menu, change_pad_list, 0, 0, 0
};
static TERMTYPE original_term; /* terminal type description */
static char flag_boolean[BOOLCOUNT]; /* flags for booleans */
static char flag_numerics[NUMCOUNT]; /* flags for numerics */
static char *flag_strings; /* flags for strings */
static int *label_strings;
static int xon_index; /* Subscript for (xon) */
static int xon_shadow;
static int start_display; /* the display has just started */
static int display_lines; /* number of lines displayed */
static void
alloc_arrays(void)
{
if (flag_strings == 0) {
label_strings = (int *)calloc(MAX_STRINGS, sizeof(int));
flag_strings = (char *)calloc(MAX_STRINGS, sizeof(char));
}
}
/*
** send_info_string(str)
**
** Return the terminfo string prefixed by the correct separator
*/
static void
send_info_string(
const char *str,
int *ch)
{
int len;
if (display_lines == -1) {
return;
}
len = strlen(str);
if (len + char_count + 3 >= columns) {
if (start_display == 0) {
put_str(",");
}
put_crlf();
if (++display_lines > lines) {
ptext("-- more -- ");
*ch = wait_here();
if (*ch == 'q') {
display_lines = -1;
return;
}
display_lines = 0;
}
if (len >= columns) {
/* if the terminal does not (am) then this loses */
if (columns) {
display_lines += ((strlen(str) + 3) / columns) + 1;
}
put_str(" ");
put_str(str);
start_display = 0;
return;
}
ptext(" ");
} else
if (start_display == 0) {
ptext(", ");
} else {
ptext(" ");
}
ptext(str);
start_display = 0;
}
/*
** show_info(test_list, status, ch)
**
** Display the current terminfo
*/
static void
show_info(
struct test_list *t GCC_UNUSED,
int *state GCC_UNUSED,
int *ch)
{
int i;
char buf[1024];
display_lines = 1;
start_display = 1;
for (i = 0; i < BOOLCOUNT; i++) {
if ((i == xon_index) ? xon_shadow : CUR Booleans[i]) {
send_info_string(boolnames[i], ch);
}
}
for (i = 0; i < NUMCOUNT; i++) {
if (CUR Numbers[i] >= 0) {
sprintf(buf, "%s#%d", numnames[i], CUR Numbers[i]);
send_info_string(buf, ch);
}
}
for (i = 0; i < MAX_STRINGS; i++) {
if (CUR Strings[i]) {
sprintf(buf, "%s=%s", STR_NAME(i),
print_expand(CUR Strings[i]));
send_info_string(buf, ch);
}
}
put_newlines(2);
*ch = REQUEST_PROMPT;
}
/*
** save_info_string(str, fp)
**
** Write the terminfo string prefixed by the correct separator
*/
static void
save_info_string(
const char *str,
FILE *fp)
{
int len;
len = strlen(str);
if (len + display_lines >= 77) {
if (display_lines > 0) {
(void) fprintf(fp, "\n\t");
}
display_lines = 8;
} else
if (display_lines > 0) {
(void) fprintf(fp, " ");
display_lines++;
} else {
(void) fprintf(fp, "\t");
display_lines = 8;
}
(void) fprintf(fp, "%s,", str);
display_lines += len + 1;
}
/*
** save_info(test_list, status, ch)
**
** Write the current terminfo to a file
*/
void
save_info(
struct test_list *t,
int *state,
int *ch)
{
int i;
FILE *fp;
time_t now;
char buf[1024];
if ((fp = fopen(tty_basename, "w")) == (FILE *) NULL) {
(void) sprintf(temp, "can't open: %s", tty_basename);
ptextln(temp);
generic_done_message(t, state, ch);
return;
}
time(&now);
/* Note: ctime() returns a newline at the end of the string */
(void) fprintf(fp, "# Terminfo created by TACK for TERM=%s on %s",
tty_basename, ctime(&now));
(void) fprintf(fp, "%s|%s,\n", tty_basename, longname());
display_lines = 0;
for (i = 0; i < BOOLCOUNT; i++) {
if (i == xon_index ? xon_shadow : CUR Booleans[i]) {
save_info_string(boolnames[i], fp);
}
}
for (i = 0; i < NUMCOUNT; i++) {
if (CUR Numbers[i] >= 0) {
sprintf(buf, "%s#%d", numnames[i], CUR Numbers[i]);
save_info_string(buf, fp);
}
}
for (i = 0; i < MAX_STRINGS; i++) {
if (CUR Strings[i]) {
sprintf(buf, "%s=%s", STR_NAME(i),
_nc_tic_expand(CUR Strings[i], TRUE, TRUE));
save_info_string(buf, fp);
}
}
(void) fprintf(fp, "\n");
(void) fclose(fp);
sprintf(temp, "Terminfo saved as file: %s", tty_basename);
ptextln(temp);
}
/*
** show_value(test_list, status, ch)
**
** Display the value of a selected cap
*/
static void
show_value(
struct test_list *t,
int *state GCC_UNUSED,
int *ch)
{
struct name_table_entry const *nt;
char *s;
int n, op, b;
char buf[1024];
char tmp[1024];
ptext("enter name: ");
read_string(buf, 80);
if (buf[0] == '\0' || buf[1] == '\0') {
*ch = buf[0];
return;
}
if (line_count + 2 >= lines) {
put_clear();
}
op = t->flags & 255;
if ((nt = _nc_find_entry(buf, _nc_info_hash_table))) {
switch (nt->nte_type) {
case BOOLEAN:
if (op == SHOW_DELETE) {
if (nt->nte_index == xon_index) {
xon_shadow = 0;
} else {
CUR Booleans[nt->nte_index] = 0;
}
return;
}
b = nt->nte_index == xon_index ? xon_shadow :
CUR Booleans[nt->nte_index];
sprintf(temp, "boolean %s %s", buf,
b ? "True" : "False");
break;
case STRING:
if (op == SHOW_DELETE) {
CUR Strings[nt->nte_index] = (char *) 0;
return;
}
if (CUR Strings[nt->nte_index]) {
sprintf(temp, "string %s %s", buf,
expand(CUR Strings[nt->nte_index]));
} else {
sprintf(temp, "undefined string %s", buf);
}
break;
case NUMBER:
if (op == SHOW_DELETE) {
CUR Numbers[nt->nte_index] = -1;
return;
}
sprintf(temp, "numeric %s %d", buf,
CUR Numbers[nt->nte_index]);
break;
default:
sprintf(temp, "unknown");
break;
}
ptextln(temp);
} else {
sprintf(temp, "Cap not found: %s", buf);
ptextln(temp);
return;
}
if (op != SHOW_EDIT) {
return;
}
if (nt->nte_type == BOOLEAN) {
ptextln("Value flipped");
if (nt->nte_index == xon_index) {
xon_shadow = !xon_shadow;
} else {
CUR Booleans[nt->nte_index] = !CUR Booleans[nt->nte_index];
}
return;
}
ptextln("Enter new value");
read_string(buf, sizeof(buf));
switch (nt->nte_type) {
case STRING:
_nc_reset_input((FILE *) 0, buf);
_nc_trans_string(tmp, tmp + sizeof(tmp));
s = (char *)malloc(strlen(tmp) + 1);
strcpy(s, tmp);
CUR Strings[nt->nte_index] = s;
sprintf(temp, "new string value %s", nt->nte_name);
ptextln(temp);
ptextln(expand(CUR Strings[nt->nte_index]));
break;
case NUMBER:
if (sscanf(buf, "%d", &n) == 1) {
CUR Numbers[nt->nte_index] = n;
sprintf(temp, "new numeric value %s %d",
nt->nte_name, n);
ptextln(temp);
} else {
sprintf(temp, "Illegal number: %s", buf);
ptextln(temp);
}
break;
default:
break;
}
}
/*
** get_string_cap_byname(name, long_name)
**
** Given a cap name, find the value
** Errors are quietly ignored.
*/
char *
get_string_cap_byname(
const char *name,
const char **long_name)
{
struct name_table_entry const *nt;
if ((nt = _nc_find_entry(name, _nc_info_hash_table))) {
if (nt->nte_type == STRING) {
*long_name = strfnames[nt->nte_index];
return (CUR Strings[nt->nte_index]);
}
}
*long_name = "??";
return (char *) 0;
}
/*
** get_string_cap_byvalue(value)
**
** Given a capability string, find its position in the data base.
** Return the index or -1 if not found.
*/
int
get_string_cap_byvalue(
const char *value)
{
int i;
if (value) {
for (i = 0; i < MAX_STRINGS; i++) {
if (CUR Strings[i] == value) {
return i;
}
}
/* search for translated strings */
for (i = 0; i < TM_last; i++) {
if (TM_string[i].value == value) {
return TM_string[i].index;
}
}
}
return -1;
}
/*
** show_changed(test_list, status, ch)
**
** Display a list of caps that have been changed.
*/
static void
show_changed(
struct test_list *t GCC_UNUSED,
int *state GCC_UNUSED,
int *ch)
{
int i, header = 1, v;
const char *a;
const char *b;
static char title[] = " old value cap new value";
char abuf[1024];
for (i = 0; i < BOOLCOUNT; i++) {
v = (i == xon_index) ? xon_shadow : CUR Booleans[i];
if (original_term.Booleans[i] != v) {
if (header) {
ptextln(title);
header = 0;
}
sprintf(temp, "%30d %6s %d",
original_term.Booleans[i], boolnames[i], v);
ptextln(temp);
}
}
for (i = 0; i < NUMCOUNT; i++) {
if (original_term.Numbers[i] != CUR Numbers[i]) {
if (header) {
ptextln(title);
header = 0;
}
sprintf(temp, "%30d %6s %d",
original_term.Numbers[i], numnames[i],
CUR Numbers[i]);
ptextln(temp);
}
}
for (i = 0; i < MAX_STRINGS; i++) {
a = original_term.Strings[i] ? original_term.Strings[i] : "";
b = CUR Strings[i] ? CUR Strings[i] : "";
if (strcmp(a, b)) {
if (header) {
ptextln(title);
header = 0;
}
strcpy(abuf, _nc_tic_expand(a, TRUE, TRUE));
sprintf(temp, "%30s %6s %s", abuf, STR_NAME(i),
_nc_tic_expand(b, TRUE, TRUE));
putln(temp);
}
}
if (header) {
ptextln("No changes");
}
put_crlf();
*ch = REQUEST_PROMPT;
}
/*
** user_modified()
**
** Return TRUE if the user has modified the terminfo
*/
int
user_modified(void)
{
const char *a, *b;
int i, v;
for (i = 0; i < BOOLCOUNT; i++) {
v = (i == xon_index) ? xon_shadow : CUR Booleans[i];
if (original_term.Booleans[i] != v) {
return TRUE;
}
}
for (i = 0; i < NUMCOUNT; i++) {
if (original_term.Numbers[i] != CUR Numbers[i]) {
return TRUE;
}
}
for (i = 0; i < MAX_STRINGS; i++) {
a = original_term.Strings[i] ? original_term.Strings[i] : "";
b = CUR Strings[i] ? CUR Strings[i] : "";
if (strcmp(a, b)) {
return TRUE;
}
}
return FALSE;
}
/*****************************************************************************
*
* Maintain the list of capabilities that can be tested
*
*****************************************************************************/
/*
** mark_cap(name, flag)
**
** Mark the cap data base with the flag provided.
*/
static void
mark_cap(
char *name,
int flag)
{
struct name_table_entry const *nt;
alloc_arrays();
if ((nt = _nc_find_entry(name, _nc_info_hash_table))) {
switch (nt->nte_type) {
case BOOLEAN:
flag_boolean[nt->nte_index] |= flag;
break;
case STRING:
flag_strings[nt->nte_index] |= flag;
break;
case NUMBER:
flag_numerics[nt->nte_index] |= flag;
break;
default:
sprintf(temp, "unknown cap type (%s)", name);
ptextln(temp);
break;
}
} else {
sprintf(temp, "Cap not found: %s", name);
ptextln(temp);
(void) wait_here();
}
}
/*
** can_test(name-list, flags)
**
** Scan the name list and get the names.
** Enter each name into the can-test data base.
** <space> ( and ) may be used as separators.
*/
void
can_test(
const char *s,
int flags)
{
int ch, j;
char name[32];
if (s) {
for (j = 0; (name[j] = ch = *s); s++) {
if (ch == ' ' || ch == ')' || ch == '(') {
if (j) {
name[j] = '\0';
mark_cap(name, flags);
}
j = 0;
} else {
j++;
}
}
if (j) {
mark_cap(name, flags);
}
}
}
/*
** cap_index(name-list, index-list)
**
** Scan the name list and return a list of indexes.
** <space> ( and ) may be used as separators.
** This list is terminated with -1.
*/
void
cap_index(
const char *s,
int *inx)
{
struct name_table_entry const *nt;
int ch, j;
char name[32];
if (s) {
for (j = 0; ; s++) {
name[j] = ch = *s;
if (ch == ' ' || ch == ')' || ch == '(' || ch == 0) {
if (j) {
name[j] = '\0';
if ((nt = _nc_find_entry(name,
_nc_info_hash_table)) &&
(nt->nte_type == STRING)) {
*inx++ = nt->nte_index;
}
}
if (ch == 0) {
break;
}
j = 0;
} else {
j++;
}
}
}
*inx = -1;
}
/*
** cap_match(name-list, cap)
**
** Scan the name list and see if the cap is in the list.
** Return TRUE if we find an exact match.
** <space> ( and ) may be used as separators.
*/
int
cap_match(
const char *names,
const char *cap)
{
char *s;
int c, l, t;
if (names) {
l = strlen(cap);
while ((s = strstr(names, cap))) {
c = (names == s) ? 0 : *(s - 1);
t = s[l];
if ((c == 0 || c == ' ' || c == '(') &&
(t == 0 || t == ' ' || t == ')')) {
return TRUE;
}
if (t == 0) {
break;
}
names = s + l;
}
}
return FALSE;
}
/*
** show_report(test_list, status, ch)
**
** Display a list of caps that can be tested
*/
void
show_report(
struct test_list *t,
int *state GCC_UNUSED,
int *ch)
{
int i, j, nc, flag;
const char *s;
const char **nx = malloc(BOOLCOUNT + NUMCOUNT + MAX_STRINGS);
alloc_arrays();
flag = t->flags & 255;
nc = 0;
for (i = 0; i < BOOLCOUNT; i++) {
if (flag_boolean[i] & flag) {
nx[nc++] = boolnames[i];
}
}
for (i = 0; i < NUMCOUNT; i++) {
if (flag_numerics[i] & flag) {
nx[nc++] = numnames[i];
}
}
for (i = 0; i < MAX_STRINGS; i++) {
if (flag_strings[i] & flag) {
nx[nc++] = STR_NAME(i);
}
}
/* sort */
for (i = 0; i < nc - 1; i++) {
for (j = i + 1; j < nc; j++) {
if (strcmp(nx[i], nx[j]) > 0) {
s = nx[i];
nx[i] = nx[j];
nx[j] = s;
}
}
}
if (flag & FLAG_FUNCTION_KEY) {
ptextln("The following function keys can be tested:");
} else
if (flag & FLAG_CAN_TEST) {
ptextln("The following capabilities can be tested:");
} else
if (flag & FLAG_TESTED) {
ptextln("The following capabilities have been tested:");
}
put_crlf();
for (i = 0; i < nc; i++) {
sprintf(temp, "%s ", nx[i]);
ptext(temp);
}
put_newlines(1);
*ch = REQUEST_PROMPT;
free (nx);
}
/*
** show_untested(test_list, status, ch)
**
** Display a list of caps that are defined but cannot be tested.
** Don't bother to sort this list.
*/
static void
show_untested(
struct test_list *t GCC_UNUSED,
int *state GCC_UNUSED,
int *ch)
{
int i;
alloc_arrays();
ptextln("Caps that are defined but cannot be tested:");
for (i = 0; i < BOOLCOUNT; i++) {
if (flag_boolean[i] == 0 && CUR Booleans[i]) {
sprintf(temp, "%s ", boolnames[i]);
ptext(temp);
}
}
for (i = 0; i < NUMCOUNT; i++) {
if (flag_numerics[i] == 0 && CUR Numbers[i] >= 0) {
sprintf(temp, "%s ", numnames[i]);
ptext(temp);
}
}
for (i = 0; i < MAX_STRINGS; i++) {
if (flag_strings[i] == 0 && CUR Strings[i]) {
sprintf(temp, "%s ", STR_NAME(i));
ptext(temp);
}
}
put_newlines(1);
*ch = REQUEST_PROMPT;
}
/*
** edit_init()
**
** Initialize the function key data base
*/
void
edit_init(void)
{
int i, j, lc;
char *lab;
struct name_table_entry const *nt;
alloc_arrays();
_nc_copy_termtype(&original_term, &cur_term->type);
for (i = 0; i < BOOLCOUNT; i++) {
original_term.Booleans[i] = CUR Booleans[i];
}
for (i = 0; i < NUMCOUNT; i++) {
original_term.Numbers[i] = CUR Numbers[i];
}
/* scan for labels */
for (i = lc = 0; i < MAX_STRINGS; i++) {
original_term.Strings[i] = CUR Strings[i];
if (strncmp(STR_NAME(i), "lf", 2) == 0) {
flag_strings[i] |= FLAG_LABEL;
if (CUR Strings[i]) {
label_strings[lc++] = i;
}
}
}
/* scan for function keys */
for (i = 0; i < MAX_STRINGS; i++) {
const char *this_name = STR_NAME(i);
if ((this_name[0] == 'k') && strcmp(this_name, "kmous")) {
flag_strings[i] |= FLAG_FUNCTION_KEY;
lab = (char *) 0;
for (j = 0; j < lc; j++) {
if (!strcmp(this_name,
STR_NAME(label_strings[j]))) {
lab = CUR Strings[label_strings[j]];
break;
}
}
enter_key(this_name, CUR Strings[i], lab);
}
}
/* Lookup the translated strings */
for (i = 0; i < TM_last; i++) {
if ((nt = _nc_find_entry(TM_string[i].name,
_nc_info_hash_table)) && (nt->nte_type == STRING)) {
TM_string[i].index = nt->nte_index;
} else {
sprintf(temp, "TM_string lookup failed for: %s",
TM_string[i].name);
ptextln(temp);
}
}
if ((nt = _nc_find_entry("xon", _nc_info_hash_table)) != 0) {
xon_index = nt->nte_index;
}
xon_shadow = xon_xoff;
free(label_strings);
}
/*
** change_one_entry(test_list, status, ch)
**
** Change the padding on the selected cap
*/
static void
change_one_entry(
struct test_list *test,
int *state,
int *chp)
{
struct name_table_entry const *nt;
int i, j, x, star, slash, v, dot, ch;
const char *s;
char *t, *p;
const char *current_string;
char buf[1024];
char pad[1024];
i = test->flags & 255;
if (i == 255) {
/* read the cap name from the user */
ptext("enter name: ");
read_string(pad, 32);
if (pad[0] == '\0' || pad[1] == '\0') {
*chp = pad[0];
return;
}
if ((nt = _nc_find_entry(pad, _nc_info_hash_table)) &&
(nt->nte_type == STRING)) {
x = nt->nte_index;
current_string = CUR Strings[x];
} else {
sprintf(temp, "%s is not a string capability", pad);
ptext(temp);
generic_done_message(test, state, chp);
return;
}
} else {
x = tx_index[i];
current_string = tx_cap[i];
strcpy(pad, STR_NAME(x));
}
if (!current_string) {
ptextln("That string is not currently defined. Please enter a new value, including the padding delay:");
read_string(buf, sizeof(buf));
_nc_reset_input((FILE *) 0, buf);
_nc_trans_string(pad, pad + sizeof(pad));
t = (char *)malloc(strlen(pad) + 1);
strcpy(t, pad);
CUR Strings[x] = t;
sprintf(temp, "new string value %s", STR_NAME(x));
ptextln(temp);
ptextln(expand(t));
return;
}
sprintf(buf, "Current value: (%s) %s", pad, _nc_tic_expand(current_string, TRUE, TRUE));
putln(buf);
ptextln("Enter new pad. 0 for no pad. CR for no change.");
read_string(buf, 32);
if (buf[0] == '\0' || (buf[1] == '\0' && isalpha(UChar(buf[0])))) {
*chp = buf[0];
return;
}
star = slash = FALSE;
for (j = v = dot = 0; (ch = buf[j]); j++) {
if (ch >= '0' && ch <= '9') {
v = ch - '0' + v * 10;
if (dot) {
dot++;
}
} else if (ch == '*') {
star = TRUE;
} else if (ch == '/') {
slash = TRUE;
} else if (ch == '.') {
dot = 1;
} else {
sprintf(temp, "Illegal character: %c", ch);
ptextln(temp);
ptext("General format: 99.9*/ ");
generic_done_message(test, state, chp);
return;
}
}
while (dot > 2) {
v /= 10;
dot--;
}
if (dot == 2) {
sprintf(pad, "%d.%d%s%s", v / 10, v % 10,
star ? "*" : "", slash ? "/" : "");
} else {
sprintf(pad, "%d%s%s",
v, star ? "*" : "", slash ? "/" : "");
}
s = current_string;
t = buf;
for (v = 0; (ch = *t = *s++); t++) {
if (v == '$' && ch == '<') {
while ((ch = *s++) && (ch != '>'));
for (p = pad; (*++t = *p++); );
*t++ = '>';
while ((*t++ = *s++));
pad[0] = '\0';
break;
}
v = ch;
}
if (pad[0]) {
sprintf(t, "$<%s>", pad);
}
if ((t = (char *)malloc(strlen(buf) + 1))) {
strcpy(t, buf);
CUR Strings[x] = t;
if (i != 255) {
tx_cap[i] = t;
}
}
generic_done_message(test, state, chp);
}
/*
** build_change_menu(menu_list)
**
** Build the change pad menu list
*/
static void
build_change_menu(
struct test_menu *m)
{
int i, j, k;
char *s;
for (i = j = 0; i < txp; i++) {
if ((k = tx_index[i]) >= 0) {
s = _nc_tic_expand(tx_cap[i], TRUE, TRUE);
s[40] = '\0';
sprintf(change_pad_text[j], "%c) (%s) %s",
'a' + j, STR_NAME(k), s);
change_pad_list[j].flags = i;
change_pad_list[j].lines_needed = 4;
change_pad_list[j].menu_entry = change_pad_text[j];
change_pad_list[j].test_procedure = change_one_entry;
j++;
}
}
strcpy(change_pad_text[j], "z) enter name");
change_pad_list[j].flags = 255;
change_pad_list[j].lines_needed = 4;
change_pad_list[j].menu_entry = change_pad_text[j];
change_pad_list[j].test_procedure = change_one_entry;
j++;
change_pad_list[j].flags = MENU_LAST;
if (m->menu_title) {
put_crlf();
ptextln(m->menu_title);
}
}

View File

@ -1,925 +0,0 @@
/*
** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
**
** This file is part of TACK.
**
** TACK 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.
**
** TACK 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 TACK; see the file COPYING. If not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
** Boston, MA 02110-1301, USA
*/
#include <tack.h>
MODULE_ID("$Id: fun.c,v 1.9 2006/11/26 00:15:53 tom Exp $")
/*
* Test the function keys on the terminal. The code for echo tests
* lives here too.
*/
static void funkey_keys(struct test_list *, int *, int *);
static void funkey_meta(struct test_list *, int *, int *);
static void funkey_label(struct test_list *, int *, int *);
static void funkey_prog(struct test_list *, int *, int *);
static void funkey_local(struct test_list *, int *, int *);
struct test_list funkey_test_list[] = {
{0, 0, 0, 0, "e) edit terminfo", 0, &edit_menu},
{MENU_CLEAR + FLAG_FUNCTION_KEY, 0, 0, 0, "f) show a list of function keys", show_report, 0},
{MENU_NEXT | MENU_CLEAR, 0, "smkx) (rmkx", 0,
"k) test function keys", funkey_keys, 0},
{MENU_NEXT, 10, "km", "smm rmm", 0, funkey_meta, 0},
{MENU_NEXT, 8, "nlab) (smln) (pln) (rmln", "lw lh", 0, funkey_label, 0},
{MENU_NEXT, 2, "pfx", 0, 0, funkey_prog, 0},
{MENU_NEXT, 2, "pfloc", 0, 0, funkey_local, 0},
{MENU_LAST, 0, 0, 0, 0, 0, 0}
};
static void printer_on(struct test_list *, int *, int *);
static void printer_mc0(struct test_list *, int *, int *);
struct test_list printer_test_list[] = {
{0, 0, 0, 0, "e) edit terminfo", 0, &edit_menu},
{MENU_NEXT | MENU_CLEAR, 0, "mc4) (mc5) (mc5i", 0, 0, printer_on, 0},
{MENU_NEXT | MENU_CLEAR, 0, "mc0", 0, 0, printer_mc0, 0},
{MENU_LAST, 0, 0, 0, 0, 0, 0}
};
/* local definitions */
static const char **fk_name;
static char **fkval;
static char **fk_label; /* function key labels (if any) */
static int *fk_tested;
static int num_strings = 0;
static int fkmax = 1; /* length of longest key */
static int got_labels = 0; /* true if we have some labels */
static int key_count = 0;
static int end_state;
/* unknown function keys */
#define MAX_FK_UNK 50
static char *fk_unknown[MAX_FK_UNK];
static int fk_length[MAX_FK_UNK];
static int funk;
/*
* Initialize arrays that depend on the actual number of strings.
*/
static void
alloc_strings(void)
{
if (num_strings != MAX_STRINGS) {
num_strings = MAX_STRINGS;
fk_name = (const char **)calloc(num_strings, sizeof(const char *));
fkval = (char **)calloc(num_strings, sizeof(char *));
fk_label = (char **)calloc(num_strings, sizeof(char *));
fk_tested = (int *)calloc(num_strings, sizeof(int));
}
}
/*
** keys_tested(first-time, show-help, hex-output)
**
** Display a list of the keys not tested.
*/
static void
keys_tested(
int first_time,
int show_help,
int hex_output)
{
int i, l;
char outbuf[256];
alloc_strings();
put_clear();
tty_set();
flush_input();
if (got_labels) {
putln("Function key labels:");
for (i = 0; i < key_count; ++i) {
if (fk_label[i]) {
sprintf(outbuf, "%s %s",
fk_name[i] ? fk_name[i] : "??", fk_label[i]);
put_columns(outbuf, (int) strlen(outbuf), 16);
}
}
put_newlines(2);
}
if (funk) {
putln("The following keys are not defined:");
for (i = 0; i < funk; ++i) {
put_columns(fk_unknown[i], fk_length[i], 16);
}
put_mode(exit_attribute_mode);
put_newlines(2);
}
if (first_time) {
putln("The following keys are defined:");
} else {
putln("The following keys have not been tested:");
}
if (scan_mode) {
for (i = 0; scan_down[i]; i++) {
if (!scan_tested[i]) {
if (hex_output) {
strcpy(outbuf, hex_expand_to(scan_down[i], 3));
} else {
strcpy(outbuf, expand(scan_down[i]));
}
l = expand_chars;
if (hex_output) {
strcat(outbuf, hex_expand_to(scan_up[i], 3));
} else {
strcat(outbuf, expand(scan_up[i]));
}
expand_chars += l;
l = strlen(scan_name[i]);
if (((char_count + 16) & ~15) +
((expand_chars + 7) & ~7) + l >= columns) {
put_crlf();
} else
if (char_count + 24 > columns) {
put_crlf();
} else if (char_count) {
putchp(' ');
}
put_columns(outbuf, expand_chars, 16);
put_columns(scan_name[i], l, 8);
}
}
} else {
for (i = 0; i < key_count; i++) {
if (!fk_tested[i]) {
if (hex_output) {
strcpy(outbuf, hex_expand_to(fkval[i], 3));
} else {
strcpy(outbuf, expand(fkval[i]));
}
l = strlen(fk_name[i]);
if (((char_count + 16) & ~15) +
((expand_chars + 7) & ~7) + l >= columns) {
put_crlf();
} else
if (char_count + 24 > columns) {
put_crlf();
} else
if (char_count) {
putchp(' ');
}
put_columns(outbuf, expand_chars, 16);
put_columns(fk_name[i], l, 8);
}
}
}
put_newlines(2);
if (show_help) {
ptextln("Hit any function key. Type 'end' to quit. Type ? to update the display.");
put_crlf();
}
}
/*
** enter_key(name, value, label)
**
** Enter a function key into the data base
*/
void
enter_key(
const char *name,
char *value,
char *lab)
{
int j;
alloc_strings();
if (value) {
j = strlen(value);
fkmax = fkmax > j ? fkmax : j;
/* do not permit duplicates */
for (j = 0; j < key_count; j++) {
if (!strcmp(fk_name[j], name)) {
return;
}
}
fkval[key_count] = value;
fk_tested[key_count] = 0;
fk_label[key_count] = lab;
fk_name[key_count++] = name;
if (lab) {
got_labels = TRUE;
}
}
}
static void
fresh_line(void)
{ /* clear the line for a new function key line */
if (over_strike) {
put_crlf();
} else {
put_cr();
if (clr_eol) {
tc_putp(clr_eol);
} else {
put_str(" \r");
}
}
}
static int
end_funky(int ch)
{ /* return true if this is the end */
switch (ch) {
case 'e':
case 'E':
end_state = 'e';
break;
case 'n':
case 'N':
if (end_state == 'e') {
end_state = 'n';
} else {
end_state = 0;
}
break;
case 'd':
case 'D':
if (end_state == 'n') {
end_state = 'd';
} else {
end_state = 0;
}
break;
case 'l':
case 'L':
if (end_state == 'l') {
end_state = '?';
} else {
end_state = 'l';
}
break;
default:
end_state = 0;
break;
}
return end_state == 'd';
}
static int
found_match(char *s, int hx, int cc)
{ /* return true if this string is a match */
int j, f;
char outbuf[256];
alloc_strings();
if (!*s) {
return 0;
}
if (scan_mode) {
for (j = f = 0; scan_down[j]; j++) {
if (scan_length[j] == 0) {
continue;
}
if (!strncmp(s, scan_down[j], scan_length[j])) {
if (!f) { /* first match */
put_cr();
if (hx) {
put_str(hex_expand_to(s, 10));
} else {
put_str(expand_to(s, 10));
}
f = 1;
}
(void) end_funky(scan_name[j][0]);
put_str(" ");
put_str(scan_name[j]);
scan_tested[j] = 1;
s += scan_length[j];
if (strncmp(s, scan_up[j], scan_length[j])) {
put_str(" scan down");
} else {
s += scan_length[j];
}
if (!*s) {
break;
}
j = -1;
}
if (!strncmp(s, scan_up[j], scan_length[j])) {
if (!f) { /* first match */
put_cr();
if (hx) {
put_str(hex_expand_to(s, 10));
} else {
put_str(expand_to(s, 10));
}
f = 1;
}
put_str(" ");
put_str(scan_name[j]);
put_str(" scan up");
s += scan_length[j];
if (!*s) {
break;
}
j = -1;
}
}
} else {
for (j = f = 0; j < key_count; j++) {
if (!strcmp(s, fkval[j])) {
if (!f) { /* first match */
put_cr();
if (hx) {
put_str(hex_expand_to(s, 10));
} else {
put_str(expand_to(s, 10));
}
f = 1;
}
sprintf(outbuf, " (%s)", fk_name[j]);
put_str(outbuf);
if (fk_label[j]) {
sprintf(outbuf, " <%s>", fk_label[j]);
put_str(outbuf);
}
fk_tested[j] = 1;
}
}
}
if (end_state == '?') {
keys_tested(0, 1, hx);
tty_raw(cc, char_mask);
end_state = 0;
}
return f;
}
static int
found_exit(char *keybuf, int hx, int cc)
{ /* return true if the user wants to exit */
int j, k;
char *s;
if (scan_mode) {
if (*keybuf == '\0') {
return TRUE;
}
} else {
/* break is a special case */
if (*keybuf == '\0') {
fresh_line();
tty_set();
ptext("Hit X to exit: ");
if (wait_here() == 'X') {
return TRUE;
}
keys_tested(0, 1, hx);
tty_raw(cc, char_mask);
return FALSE;
}
/* is this the end? */
for (k = 0; (j = (keybuf[k] & STRIP_PARITY)); k++) {
if (end_funky(j)) {
return TRUE;
}
}
j = TRUE; /* does he need an updated list? */
for (k = 0; keybuf[k]; k++) {
j &= (keybuf[k] & STRIP_PARITY) == '?';
}
if (j || end_state == '?') {
keys_tested(0, 1, hx);
tty_raw(cc, char_mask);
end_state = 0;
return FALSE;
}
}
put_cr();
if (hx) {
s = hex_expand_to(keybuf, 10);
} else {
s = expand_to(keybuf, 10);
}
sprintf(temp, "%s Unknown", s);
put_str(temp);
for (j = 0; j < MAX_FK_UNK; j++) {
if (j == funk) {
fk_length[funk] = expand_chars;
if ((fk_unknown[funk] = (char *)malloc(strlen(s) + 1))) {
strcpy(fk_unknown[funk++], s);
}
break;
}
if (fk_length[j] == expand_chars) {
if (!strcmp(fk_unknown[j], s)) {
break;
}
}
}
return FALSE;
}
/*
** funkey_keys(test_list, status, ch)
**
** Test function keys
*/
static void
funkey_keys(
struct test_list *t,
int *state,
int *ch)
{
char keybuf[256];
if (keypad_xmit) {
tc_putp(keypad_xmit);
}
keys_tested(1, 1, hex_out); /* also clears screen */
keybuf[0] = '\0';
end_state = 0;
if (scan_mode) {
fkmax = scan_max;
}
tty_raw(0, char_mask);
while (end_state != 'd') {
read_key(keybuf, sizeof(keybuf));
fresh_line();
if (found_match(keybuf, hex_out, 0)) {
continue;
}
if (found_exit(keybuf, hex_out, 0)) {
break;
}
}
if (keypad_local) {
tc_putp(keypad_local);
}
keys_tested(0, 0, hex_out);
ptext("Function key test ");
generic_done_message(t, state, ch);
}
int
tty_meta_prep(void)
{ /* print a warning before the meta key test */
if (not_a_tty) {
return 0;
}
if (initial_stty_query(TTY_8_BIT)) {
return 0;
}
ptext("The meta key test must be run with the");
ptext(" terminal set for 8 data bits. Two stop bits");
ptext(" may also be needed for correct display. I will");
ptext(" transmit 8 bit data but if the terminal is set for");
ptextln(" 7 bit data, garbage may appear on the screen.");
return 1;
}
/*
** funkey_meta(test_list, status, ch)
**
** Test meta key (km) (smm) (rmm)
*/
static void
funkey_meta(
struct test_list *t,
int *state,
int *ch)
{
int i, j, k, len;
char outbuf[256];
if (has_meta_key) {
put_crlf();
if (char_mask != ALLOW_PARITY) {
if (tty_meta_prep()) {
ptext("\nHit any key to continue > ");
(void) wait_here();
put_crlf();
}
}
ptext("Begin meta key test. (km) (smm) (rmm) Hit any key");
ptext(" with the meta key. The character will be");
ptext(" displayed in hex. If the meta key is working");
ptext(" then the most significant bit will be set. Type");
ptextln(" 'end' to exit.");
tty_raw(1, ALLOW_PARITY);
tc_putp(meta_on);
for (i = j = k = len = 0; i != 'e' || j != 'n' || k != 'd';) {
i = j;
j = k;
k = getchp(ALLOW_PARITY);
if (k == EOF) {
break;
}
if ((len += 3) >= columns) {
put_crlf();
len = 3;
}
sprintf(outbuf, "%02X ", k);
put_str(outbuf);
k &= STRIP_PARITY;
}
tc_putp(meta_off);
put_crlf();
tty_set();
put_crlf();
} else {
ptext("(km) Has-meta-key is not set. ");
}
generic_done_message(t, state, ch);
}
/*
** funkey_label(test_list, status, ch)
**
** Test labels (nlab) (smln) (pln) (rmln) (lw) (lh)
*/
static void
funkey_label(
struct test_list *t,
int *state,
int *ch)
{
int i;
char outbuf[256];
if (num_labels == -1) {
ptextln("Your terminal has no labels. (nlab)");
} else {
sprintf(temp, "Your terminal has %d labels (nlab) that are %d characters wide (lw) and %d lines high (lh)",
num_labels, label_width, label_height);
ptext(temp);
ptextln(" Testing (smln) (pln) (rmln)");
if (label_on) {
tc_putp(label_on);
}
if (label_width <= 0) {
label_width = sizeof(outbuf) - 1;
}
for (i = 1; i <= num_labels; i++) {
sprintf(outbuf, "L%d..............................", i);
outbuf[label_width] = '\0';
tc_putp(TPARM_2(plab_norm, i, outbuf));
}
if (label_off) {
ptext("Hit any key to remove the labels: ");
(void) wait_here();
tc_putp(label_off);
}
}
generic_done_message(t, state, ch);
}
/*
** funkey_prog(test_list, status, ch)
**
** Test program function keys (pfx)
*/
static void
funkey_prog(
struct test_list *t,
int *state,
int *ch)
{
int i, fk;
char mm[256];
fk = 1; /* use function key 1 for now */
if (pkey_xmit) {
/* test program function key */
sprintf(temp,
"(pfx) Set function key %d to transmit abc\\n", fk);
ptextln(temp);
tc_putp(TPARM_2(pkey_xmit, fk, "abc\n"));
sprintf(temp, "Hit function key %d\n", fk);
ptextln(temp);
for (i = 0; i < 4; ++i)
mm[i] = getchp(STRIP_PARITY);
mm[i] = '\0';
put_crlf();
if (mm[0] != 'a' || mm[1] != 'b' || mm[2] != 'c') {
sprintf(temp, "Error string received was: %s", expand(mm));
ptextln(temp);
} else {
putln("Thank you\n");
}
flush_input();
if (key_f1) {
tc_putp(TPARM_2(pkey_xmit, fk, key_f1));
}
} else {
ptextln("Function key transmit (pfx), not present.");
}
generic_done_message(t, state, ch);
}
/*
** funkey_local(test_list, status, ch)
**
** Test program local function keys (pfloc)
*/
static void
funkey_local(
struct test_list *t,
int *state,
int *ch)
{
int fk;
fk = 1;
if (pkey_local) {
/* test local function key */
sprintf(temp,
"(pfloc) Set function key %d to execute a clear and print \"Done!\"", fk);
ptextln(temp);
sprintf(temp, "%sDone!", liberated(clear_screen));
tc_putp(TPARM_2(pkey_local, fk, temp));
sprintf(temp, "Hit function key %d. Then hit return.", fk);
ptextln(temp);
(void) wait_here();
flush_input();
if (key_f1 && pkey_xmit) {
tc_putp(TPARM_2(pkey_xmit, fk, key_f1));
}
} else {
ptextln("Function key execute local (pfloc), not present.");
}
generic_done_message(t, state, ch);
}
/*
** printer_on(test_list, status, ch)
**
** Test printer on/off (mc4) (mc5) (mc5i)
*/
static void
printer_on(
struct test_list *t,
int *state,
int *ch)
{
if (!prtr_on || !prtr_off) {
ptextln("Printer on/off missing. (mc5) (mc4)");
} else if (prtr_silent) {
ptextln("Your printer is silent. (mc5i) is set.");
tc_putp(prtr_on);
ptextln("This line should be on the printer but not your screen. (mc5)");
tc_putp(prtr_off);
ptextln("This line should be only on the screen. (mc4)");
} else {
ptextln("Your printer is not silent. (mc5i) is reset.");
tc_putp(prtr_on);
ptextln("This line should be on the printer and the screen. (mc5)");
tc_putp(prtr_off);
ptextln("This line should only be on the screen. (mc4)");
}
generic_done_message(t, state, ch);
}
/*
** printer_mc0(test_list, status, ch)
**
** Test screen print (mc0)
*/
static void
printer_mc0(
struct test_list *t,
int *state,
int *ch)
{
if (print_screen) {
ptext("I am going to send the contents of the screen to");
ptext(" the printer, then wait for a keystroke from you.");
ptext(" All of the text that appears on the screen");
ptextln(" should be printed. (mc0)");
tc_putp(print_screen);
} else {
ptext("(mc0) Print-screen is not present. ");
}
generic_done_message(t, state, ch);
}
static void
line_pattern(void)
{ /* put up a pattern that will help count the
number of lines */
int i, j;
put_clear();
if (over_strike) {
for (i = 0; i < 100; i++) {
if (i) {
put_crlf();
}
for (j = i / 10; j; j--) {
put_this(' ');
}
put_this('0' + ((i + 1) % 10));
}
} else /* I assume it will scroll */ {
for (i = 100; i; i--) {
sprintf(temp, "\r\n%d", i);
put_str(temp);
}
}
}
static void
column_pattern(void)
{ /* put up a pattern that will help count the
number of columns */
int i, j;
put_clear();
for (i = 0; i < 20; i++) {
for (j = 1; j < 10; j++) {
put_this('0' + j);
}
put_this('.');
}
}
/*
** report_help()
**
** Print the help text for the echo tests
*/
static void
report_help(int crx)
{
ptextln("The following commands may also be entered:");
ptextln(" clear clear screen.");
ptextln(" columns print a test pattern to help count screen width.");
ptextln(" lines print a test pattern to help count screen length.");
ptextln(" end exit.");
ptextln(" echo redisplay last report.");
if (crx) {
ptextln(" hex redisplay last report in hex.");
} else {
ptextln(" hex toggle hex display mode.");
}
ptextln(" help display this list.");
ptextln(" high toggle forced high bit (0x80).");
ptextln(" scan toggle scan mode.");
ptextln(" one echo one character after <cr> or <lf> as is. (report mode)");
ptextln(" two echo two characters after <cr> or <lf> as is.");
ptextln(" all echo all characters after <cr> or <lf> as is. (echo mode)");
}
/*
** tools_report(testlist, state, ch)
**
** Run the echo tool and report tool
*/
void
tools_report(
struct test_list *t,
int *state GCC_UNUSED,
int *pch GCC_UNUSED)
{
int i, j, ch, crp, crx, high_bit, save_scan_mode, hex_display;
char buf[1024];
char txt[8];
hex_display = hex_out;
put_clear();
if ((crx = (t->flags & 255)) == 1) {
ptext("Characters after a CR or LF will be echoed as");
ptextln(" is. All other characters will be expanded.");
report_help(crx);
} else { /* echo test */
ptextln("Begin echo test.");
report_help(crx);
}
memset(txt, 0, sizeof(txt));
save_scan_mode = scan_mode;
tty_raw(1, char_mask);
for (i = crp = high_bit = 0;;) {
ch = getchp(char_mask);
if (ch == EOF) {
break;
}
if (i >= (int) sizeof(buf) - 1) {
i = 0;
}
buf[i++] = ch;
buf[i] = '\0';
for (j = 0; j < (int) sizeof(txt) - 1; j++) {
txt[j] = txt[j + 1];
}
txt[sizeof(txt) - 1] = ch & STRIP_PARITY;
if (crx == 0) { /* echo test */
if (hex_display) {
ptext(hex_expand_to(&buf[i - 1], 3));
} else {
tc_putch(ch | high_bit);
}
} else /* status report test */
if (ch == '\n' || ch == '\r') {
put_crlf();
crp = 0;
} else if (crp++ < crx) {
tc_putch(ch | high_bit);
} else {
put_str(expand(&buf[i - 1]));
}
if (!strncmp(&txt[sizeof(txt) - 7], "columns", 7)) {
column_pattern();
buf[i = 0] = '\0';
crp = 0;
}
if (!strncmp(&txt[sizeof(txt) - 5], "lines", 5)) {
line_pattern();
buf[i = 0] = '\0';
crp = 0;
}
if (!strncmp(&txt[sizeof(txt) - 5], "clear", 5)) {
put_clear();
buf[i = 0] = '\0';
crp = 0;
}
if (!strncmp(&txt[sizeof(txt) - 4], "high", 4)) {
high_bit ^= 0x80;
if (high_bit) {
ptextln("\nParity bit set");
} else {
ptextln("\nParity bit reset");
}
}
if (!strncmp(&txt[sizeof(txt) - 4], "help", 4)) {
put_crlf();
report_help(crx);
}
if (!strncmp(&txt[sizeof(txt) - 4], "echo", 4)) {
/* display the last status report */
/* clear bypass condition on Tek terminals */
put_crlf();
if (i >= 4) {
buf[i -= 4] = '\0';
}
put_str(expand(buf));
}
if (save_scan_mode &&
!strncmp(&txt[sizeof(txt) - 4], "scan", 4)) {
/* toggle scan mode */
scan_mode = !scan_mode;
}
if (!strncmp(&txt[sizeof(txt) - 3], "end", 3))
break;
if (!strncmp(&txt[sizeof(txt) - 3], "hex", 3)) {
if (crx) {
/* display the last status report in hex */
/* clear bypass condition on Tek terminals */
put_crlf();
if (i >= 3) {
buf[i -= 3] = '\0';
}
put_str(hex_expand_to(buf, 3));
} else {
hex_display = !hex_display;
}
}
if (!strncmp(&txt[sizeof(txt) - 3], "two", 3))
crx = 2;
if (!strncmp(&txt[sizeof(txt) - 3], "one", 3))
crx = 1;
if (!strncmp(&txt[sizeof(txt) - 3], "all", 3))
crx = 0;
}
scan_mode = save_scan_mode;
put_crlf();
tty_set();
if (crx) {
ptextln("End of status report test.");
} else {
ptextln("End of echo test.");
}
}

View File

@ -1,316 +0,0 @@
/*
** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
**
** This file is part of TACK.
**
** TACK 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.
**
** TACK 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 TACK; see the file COPYING. If not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
** Boston, MA 02110-1301, USA
*/
/* initialization and wrapup code */
#include <tack.h>
MODULE_ID("$Id: init.c,v 1.7 2006/11/26 00:16:01 tom Exp $")
#if NCURSES_VERSION_MAJOR >= 5 || NCURSES_VERSION_PATCH >= 981219
#define _nc_get_curterm(p) _nc_get_tty_mode(p)
#endif
FILE *debug_fp;
char temp[1024];
char tty_basename[64];
void
put_name(const char *cap, const char *name)
{ /* send the cap name followed by the cap */
if (cap) {
ptext(name);
tc_putp(cap);
}
}
static void
report_cap(const char *tag, const char *s)
{ /* expand the cap or print *** missing *** */
int i;
ptext(tag);
for (i = char_count; i < 13; i++) {
putchp(' ');
}
put_str(" = ");
if (s) {
putln(expand(s));
} else {
putln("*** missing ***");
}
}
void
reset_init(void)
{ /* send the reset and init strings */
int i;
ptext("Terminal reset");
i = char_count;
put_name(reset_1string, " (rs1)");
put_name(reset_2string, " (rs2)");
/* run the reset file */
if (reset_file && reset_file[0]) {
FILE *fp;
int ch;
can_test("rf", FLAG_TESTED);
if ((fp = fopen(reset_file, "r"))) { /* send the reset file */
sprintf(temp, " (rf) %s", reset_file);
ptextln(temp);
while (1) {
ch = getc(fp);
if (ch == EOF)
break;
put_this(ch);
}
fclose(fp);
} else {
sprintf(temp, "\nCannot open reset file (rf) %s", reset_file);
ptextln(temp);
}
}
put_name(reset_3string, " (rs3)");
if (i != char_count) {
put_crlf();
}
ptext(" init");
put_name(init_1string, " (is1)");
put_name(init_2string, " (is2)");
if (set_tab && clear_all_tabs && init_tabs != 8) {
put_crlf();
tc_putp(clear_all_tabs);
for (char_count = 0; char_count < columns; char_count++) {
put_this(' ');
if ((char_count & 7) == 7) {
tc_putp(set_tab);
}
}
put_cr();
}
/* run the initialization file */
if (init_file && init_file[0]) {
FILE *fp;
int ch;
can_test("if", FLAG_TESTED);
if ((fp = fopen(init_file, "r"))) { /* send the init file */
sprintf(temp, " (if) %s", init_file);
ptextln(temp);
while (1) {
ch = getc(fp);
if (ch == EOF)
break;
put_this(ch);
}
fclose(fp);
} else {
sprintf(temp, "\nCannot open init file (if) %s", init_file);
ptextln(temp);
}
}
if (init_prog) {
can_test("iprog", FLAG_TESTED);
(void) system(init_prog);
}
put_name(init_3string, " (is3)");
fflush(stdout);
}
/*
** display_basic()
**
** display the basic terminal definitions
*/
void
display_basic(void)
{
put_str("Name: ");
putln(ttytype);
report_cap("\\r ^M (cr)", carriage_return);
report_cap("\\n ^J (ind)", scroll_forward);
report_cap("\\b ^H (cub1)", cursor_left);
report_cap("\\t ^I (ht)", tab);
/* report_cap("\\f ^L (ff)", form_feed); */
if (newline) {
/* OK if missing */
report_cap(" (nel)", newline);
}
report_cap(" (clear)", clear_screen);
if (!cursor_home && cursor_address) {
report_cap("(cup) (home)", TPARM_2(cursor_address, 0, 0));
} else {
report_cap(" (home)", cursor_home);
}
#ifdef user9
report_cap("ENQ (u9)", user9);
#endif
#ifdef user8
report_cap("ACK (u8)", user8);
#endif
sprintf(temp, "\nTerminal size: %d x %d. Baud rate: %u. Frame size: %d.%d",
columns, lines,
tty_baud_rate,
tty_frame_size >> 1,
(tty_frame_size & 1) * 5);
putln(temp);
}
/*
** curses_setup(exec_name)
**
** Startup ncurses
*/
void
curses_setup(
char *exec_name)
{
int status;
static TERMTYPE term;
char tty_filename[2048];
tty_init();
/**
See if the terminal is in the terminfo data base. This call has
two useful benefits, 1) it returns the filename of the terminfo entry,
and 2) it searches only terminfo's. This allows us to abort before
ncurses starts scanning the termcap file.
**/
if ((status = _nc_read_entry(tty_basename, tty_filename, &term)) == 0) {
const TERMTYPE *fallback = _nc_fallback(tty_basename);
if (fallback) {
term = *fallback;
sprintf(tty_filename, "(fallback)%s", tty_basename);
status = 1;
} else {
fprintf(stderr, "Terminal not found: TERM=%s\n", tty_basename);
show_usage(exec_name);
exit(1);
}
}
if (status == -1) {
fprintf(stderr, "Terminfo database is inaccessible\n");
exit(1);
}
/**
This call will load the terminfo data base and set the cur-term
variable. Only terminals that actually exist will get here so its
OK to ignore errors. This is a good thing since ncurses does not
permit (os) or (gn) to be set.
**/
setupterm(tty_basename, 1, &status);
/**
Get the current terminal definitions. This must be done before
getting the baudrate.
**/
_nc_get_curterm(&cur_term->Nttyb);
tty_baud_rate = baudrate();
tty_cps = (tty_baud_rate << 1) / tty_frame_size;
/* set up the defaults */
replace_mode = TRUE;
scan_mode = 0;
char_count = 0;
select_delay_type = debug_level = 0;
char_mask = (meta_on && meta_on[0] == '\0') ? ALLOW_PARITY : STRIP_PARITY;
/* Don't change the XON/XOFF modes yet. */
select_xon_xoff = initial_stty_query(TTY_XON_XOFF) ? 1 : needs_xon_xoff;
fflush(stdout); /* flush any output */
tty_set();
go_home(); /* set can_go_home */
put_clear(); /* set can_clear_screen */
if (send_reset_init) {
reset_init();
}
/*
I assume that the reset and init strings may not have the correct
pads. (Because that part of the test comes much later.) Because
of this, I allow the terminal some time to catch up.
*/
fflush(stdout); /* waste some time */
sleep(1); /* waste more time */
charset_can_test();
can_test("lines cols cr nxon rf if iprog rmp smcup rmcup", FLAG_CAN_TEST);
edit_init(); /* initialize the edit data base */
if (send_reset_init && enter_ca_mode) {
tc_putp(enter_ca_mode);
put_clear(); /* just in case we switched pages */
}
put_crlf();
ptext("Using terminfo from: ");
ptextln(tty_filename);
put_crlf();
if (tty_can_sync == SYNC_NEEDED) {
verify_time();
}
display_basic();
}
/*
** bye_kids(exit-condition)
**
** Shutdown the terminal, clear the signals, and exit
*/
void
bye_kids(int n)
{ /* reset the tty and exit */
ignoresig();
if (send_reset_init) {
if (exit_ca_mode) {
tc_putp(exit_ca_mode);
}
if (initial_stty_query(TTY_XON_XOFF)) {
if (enter_xon_mode) {
tc_putp(enter_xon_mode);
}
} else if (exit_xon_mode) {
tc_putp(exit_xon_mode);
}
}
if (debug_fp) {
fclose(debug_fp);
}
if (log_fp) {
fclose(log_fp);
}
tty_reset();
fclose(stdin);
fclose(stdout);
fclose(stderr);
if (not_a_tty)
sleep(1);
exit(n);
}

View File

@ -1,421 +0,0 @@
/*
** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
**
** This file is part of TACK.
**
** TACK 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.
**
** TACK 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 TACK; see the file COPYING. If not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
** Boston, MA 02110-1301, USA
*/
#include <tack.h>
MODULE_ID("$Id: menu.c,v 1.3 2005/09/17 19:49:16 tom Exp $")
/*
Menu control
*/
static void test_byname(struct test_menu *, int *, int *);
struct test_list *augment_test;
char prompt_string[80]; /* menu prompt storage */
/*
** menu_prompt()
**
** Print the menu prompt string.
*/
void
menu_prompt(void)
{
ptext(&prompt_string[1]);
}
/*
** menu_test_loop(test-structure, state, control-character)
**
** This function implements the repeat test function.
*/
static void
menu_test_loop(
struct test_list *test,
int *state,
int *ch)
{
int nch, p;
if ((test->flags & MENU_REP_MASK) && (augment_test != test)) {
/* set the augment variable (first time only) */
p = (test->flags >> 8) & 15;
if ((test->flags & MENU_REP_MASK) == MENU_LM1) {
augment = lines - 1;
} else
if ((test->flags & MENU_ONE_MASK) == MENU_ONE) {
augment = 1;
} else
if ((test->flags & MENU_LC_MASK) == MENU_lines) {
augment = lines * p / 10;
} else
if ((test->flags & MENU_LC_MASK) == MENU_columns) {
augment = columns * p / 10;
} else {
augment = 1;
}
augment_test = test;
set_augment_txt();
}
do {
if ((test->flags | *state) & MENU_CLEAR) {
put_clear();
} else
if (line_count + test->lines_needed >= lines) {
put_clear();
}
nch = 0;
if (test->test_procedure) {
/* The procedure takes precedence so I can pass
the menu entry as an argument.
*/
can_test(test->caps_done, FLAG_TESTED);
can_test(test->caps_tested, FLAG_TESTED);
test->test_procedure(test, state, &nch);
} else
if (test->sub_menu) {
/* nested menu's */
menu_display(test->sub_menu, &nch);
*state = 0;
if (nch == 'q' || nch == 's') {
/* Quit and skip are killed here */
nch = '?';
}
} else {
break; /* cya */
}
if (nch == '\r' || nch == '\n' || nch == 'n') {
nch = 0;
break;
}
} while (nch == 'r');
*ch = nch;
}
/*
** menu_display(menu-structure, flags)
**
** This function implements menu control.
*/
void
menu_display(
struct test_menu *menu,
int *last_ch)
{
int test_state = 0, run_standard_tests;
int hot_topic, ch = 0, nch = 0;
struct test_list *mt;
struct test_list *repeat_tests = 0;
int repeat_state = 0;
int prompt_length;
prompt_length = strlen(prompt_string);
if (menu->ident) {
sprintf(&prompt_string[prompt_length], "/%s", menu->ident);
}
hot_topic = menu->default_action;
run_standard_tests = menu->standard_tests ?
menu->standard_tests[0] : -1;
if (!last_ch) {
last_ch = &ch;
}
while (1) {
if (ch == 0) {
/* Display the menu */
put_crlf();
if (menu->menu_function) {
/*
this function may be used to restrict menu
entries. If used it must print the title.
*/
menu->menu_function(menu);
} else
if (menu->menu_title) {
ptextln(menu->menu_title);
}
for (mt = menu->tests; (mt->flags & MENU_LAST) == 0; mt++) {
if (mt->menu_entry) {
ptext(" ");
ptextln(mt->menu_entry);
}
}
if (menu->standard_tests) {
ptext(" ");
ptextln(menu->standard_tests);
ptextln(" r) repeat test");
ptextln(" s) skip to next test");
}
ptextln(" q) quit");
ptextln(" ?) help");
}
if (ch == 0 || ch == REQUEST_PROMPT) {
put_crlf();
ptext(&prompt_string[1]);
if (hot_topic) {
ptext(" [");
putchp(hot_topic);
ptext("]");
}
ptext(" > ");
/* read a character */
ch = wait_here();
}
if (ch == '\r' || ch == '\n') {
ch = hot_topic;
}
if (ch == 'q') {
break;
}
if (ch == '?') {
ch = 0;
continue;
}
nch = ch;
ch = 0;
/* Run one of the standard tests (by request) */
for (mt = menu->tests; (mt->flags & MENU_LAST) == 0; mt++) {
if (mt->menu_entry && (nch == mt->menu_entry[0])) {
if (mt->flags & MENU_MENU) {
test_byname(menu, &test_state, &nch);
} else {
menu_test_loop(mt, &test_state, &nch);
}
ch = nch;
if ((mt->flags & MENU_COMPLETE) && ch == 0) {
/* top level */
hot_topic = 'q';
ch = '?';
}
}
}
if (menu->standard_tests && nch == 'r') {
menu->resume_tests = repeat_tests;
test_state = repeat_state;
nch = run_standard_tests;
}
if (nch == run_standard_tests) {
if (!(mt = menu->resume_tests)) {
mt = menu->tests;
}
if (mt->flags & MENU_LAST) {
mt = menu->tests;
}
/* Run the standard test suite */
for ( ; (mt->flags & MENU_LAST) == 0; ) {
if ((mt->flags & MENU_NEXT) == MENU_NEXT) {
repeat_tests = mt;
repeat_state = test_state;
nch = run_standard_tests;
menu_test_loop(mt, &test_state, &nch);
if (nch != 0 && nch != 'n') {
ch = nch;
break;
}
if (test_state & MENU_STOP) {
break;
}
}
mt++;
}
if (ch == 0) {
ch = hot_topic;
}
menu->resume_tests = mt;
menu->resume_state = test_state;
menu->resume_char = ch;
if (ch == run_standard_tests) {
/* pop up a level */
break;
}
}
}
*last_ch = ch;
prompt_string[prompt_length] = '\0';
}
/*
** generic_done_message(test_list)
**
** Print the Done message and request input.
*/
void
generic_done_message(
struct test_list *test,
int *state,
int *ch)
{
char done_message[128];
if (test->caps_done) {
sprintf(done_message, "(%s) Done ", test->caps_done);
ptext(done_message);
} else {
ptext("Done ");
}
*ch = wait_here();
if (*ch == '\r' || *ch == '\n' || *ch == 'n') {
*ch = 0;
}
if (*ch == 's') {
*state |= MENU_STOP;
*ch = 0;
}
}
/*
** menu_clear_screen(test, state, ch)
**
** Just clear the screen.
*/
void
menu_clear_screen(
struct test_list *test GCC_UNUSED,
int *state GCC_UNUSED,
int *ch GCC_UNUSED)
{
put_clear();
}
/*
** menu_reset_init(test, state, ch)
**
** Send the reset and init strings.
*/
void
menu_reset_init(
struct test_list *test GCC_UNUSED,
int *state GCC_UNUSED,
int *ch GCC_UNUSED)
{
reset_init();
put_crlf();
}
/*
** subtest_menu(test, state, ch)
**
** Scan the menu looking for something to execute
** Return TRUE if we found anything.
*/
int
subtest_menu(
struct test_list *test,
int *state,
int *ch)
{
struct test_list *mt;
if (*ch) {
for (mt = test; (mt->flags & MENU_LAST) == 0; mt++) {
if (mt->menu_entry && (*ch == mt->menu_entry[0])) {
*ch = 0;
menu_test_loop(mt, state, ch);
return TRUE;
}
}
}
return FALSE;
}
/*
** menu_can_scan(menu-structure)
**
** Recursively scan the menu tree and find which cap names can be tested.
*/
void
menu_can_scan(
const struct test_menu *menu)
{
struct test_list *mt;
for (mt = menu->tests; (mt->flags & MENU_LAST) == 0; mt++) {
can_test(mt->caps_done, FLAG_CAN_TEST);
can_test(mt->caps_tested, FLAG_CAN_TEST);
if (!(mt->test_procedure)) {
if (mt->sub_menu) {
menu_can_scan(mt->sub_menu);
}
}
}
}
/*
** menu_search(menu-structure, cap)
**
** Recursively search the menu tree and execute any tests that use cap.
*/
static void
menu_search(
struct test_menu *menu,
int *state,
int *ch,
char *cap)
{
struct test_list *mt;
int nch;
for (mt = menu->tests; (mt->flags & MENU_LAST) == 0; mt++) {
nch = 0;
if (cap_match(mt->caps_done, cap)
|| cap_match(mt->caps_tested, cap)) {
menu_test_loop(mt, state, &nch);
}
if (!(mt->test_procedure)) {
if (mt->sub_menu) {
menu_search(mt->sub_menu, state, &nch, cap);
}
}
if (*state & MENU_STOP) {
break;
}
if (nch != 0 && nch != 'n') {
*ch = nch;
break;
}
}
}
/*
** test_byname(menu, state, ch)
**
** Get a cap name then run all tests that use that cap.
*/
static void
test_byname(
struct test_menu *menu,
int *state GCC_UNUSED,
int *ch)
{
int test_state = 0;
char cap[32];
if (tty_can_sync == SYNC_NOT_TESTED) {
verify_time();
}
ptext("enter name: ");
read_string(cap, sizeof(cap));
if (cap[0]) {
menu_search(menu, &test_state, ch, cap);
}
*ch = '?';
}

View File

@ -1,913 +0,0 @@
/*
** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
**
** This file is part of TACK.
**
** TACK 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.
**
** TACK 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 TACK; see the file COPYING. If not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
** Boston, MA 02110-1301, USA
*/
#include <tack.h>
MODULE_ID("$Id: modes.c,v 1.3 2006/11/26 00:16:21 tom Exp $")
/*
* Tests boolean flags and terminal modes.
*/
static void subtest_os(struct test_list *, int *, int *);
static void subtest_rmam(struct test_list *, int *, int *);
static void subtest_smam(struct test_list *, int *, int *);
static void subtest_am(struct test_list *, int *, int *);
static void subtest_ul(struct test_list *, int *, int *);
static void subtest_uc(struct test_list *, int *, int *);
static void subtest_bw(struct test_list *, int *, int *);
static void subtest_xenl(struct test_list *, int *, int *);
static void subtest_eo(struct test_list *, int *, int *);
static void subtest_xmc(struct test_list *, int *, int *);
static void subtest_xhp(struct test_list *, int *, int *);
static void subtest_mir(struct test_list *, int *, int *);
static void subtest_msgr(struct test_list *, int *, int *);
static void subtest_tbc(struct test_list *, int *, int *);
static void subtest_xt(struct test_list *, int *, int *);
static void subtest_hts(struct test_list *, int *, int *);
static void subtest_cbt(struct test_list *, int *, int *);
static void subtest_in(struct test_list *, int *, int *);
static void subtest_dadb(struct test_list *, int *, int *);
struct test_list mode_test_list[] = {
{0, 0, 0, 0, "e) edit terminfo", 0, &edit_menu},
{MENU_NEXT, 3, "os", 0, 0, subtest_os, 0},
{MENU_NEXT, 1, "rmam", 0, 0, subtest_rmam, 0},
{MENU_NEXT, 1, "smam", 0, 0, subtest_smam, 0},
{MENU_NEXT, 1, "am", 0, 0, subtest_am, 0},
{MENU_NEXT, 3, "ul", 0, 0, subtest_ul, 0},
{MENU_NEXT, 3, "uc", 0, 0, subtest_uc, 0},
{MENU_NEXT, 3, "bw", 0, 0, subtest_bw, 0},
{MENU_NEXT, 4, "xenl", 0, 0, subtest_xenl, 0},
{MENU_NEXT, 3, "eo", 0, 0, subtest_eo, 0},
{MENU_NEXT, 3, "xmc", 0, 0, subtest_xmc, 0},
{MENU_NEXT, 3, "xhp", 0, 0, subtest_xhp, 0},
{MENU_NEXT, 6, "mir", 0, 0, subtest_mir, 0},
{MENU_NEXT, 6, "msgr", 0, 0, subtest_msgr, 0},
{MENU_NEXT | MENU_CLEAR, 0, "tbc", "it", 0, subtest_tbc, 0},
{MENU_NEXT | MENU_CLEAR, 0, "hts", "it", 0, subtest_hts, 0},
{MENU_NEXT, 4, "xt", "it", 0, subtest_xt, 0},
{MENU_NEXT, 1, "cbt", "it", 0, subtest_cbt, 0},
{MENU_NEXT, 6, "in", 0, 0, subtest_in, 0},
{MENU_NEXT, 1, "da) (db", 0, 0, subtest_dadb, 0},
{MENU_LAST, 0, 0, 0, 0, 0, 0}
};
/*
** subtest_os(test_list, status, ch)
**
** test over strike mode (os)
*/
static void
subtest_os(
struct test_list *t,
int *state,
int *ch)
{
ptext("(os) should be true, not false.");
put_cr();
ptextln("(os) should be false.");
sprintf(temp, "(os) over-strike is %s in the data base. ",
over_strike ? "true" : "false");
ptext(temp);
generic_done_message(t, state, ch);
}
/*
** subtest_rmam(test_list, status, ch)
**
** test exit automatic margins mode (rmam)
*/
static void
subtest_rmam(
struct test_list *t,
int *state,
int *ch)
{
int j;
if (!exit_am_mode) {
ptext("(rmam) not present. ");
} else
if (!can_go_home) {
ptext("(rmam) not tested, no way to home cursor. ");
} else
if (over_strike) {
put_clear();
go_home();
tc_putp(exit_am_mode);
ptext("\n(rmam) will reset (am)");
go_home();
for (j = 0; j < columns; j++)
put_this(' ');
ptext("(rmam) will not reset (am)");
go_home();
put_newlines(2);
} else {
put_clear();
go_home();
tc_putp(exit_am_mode);
ptext("\n(rmam) will reset (am)");
go_home();
for (j = 0; j < columns; j++)
put_this(' ');
ptext("(rmam) will not reset (am) ");
go_home();
put_str(" ");
go_home();
put_newlines(2);
}
ptext("Exit-automatic-margins ");
generic_done_message(t, state, ch);
}
/*
** subtest_smam(test_list, status, ch)
**
** test enter automatic margins mode (smam)
*/
static void
subtest_smam(
struct test_list *t,
int *state,
int *ch)
{
int i, j;
if (!enter_am_mode) {
ptext("(smam) not present. ");
} else
if (!can_go_home) {
ptext("(smam) not tested, no way to home cursor. ");
} else
if (over_strike) {
put_clear();
go_home();
tc_putp(enter_am_mode);
ptext("\n(smam) will ");
i = char_count;
ptext("not set (am)");
go_home();
for (j = -i; j < columns; j++)
put_this(' ');
put_str("@@@");
put_newlines(2);
} else {
put_clear();
go_home();
tc_putp(enter_am_mode);
ptext("\n(smam) will not set (am)");
go_home();
for (j = 0; j < columns; j++)
put_this(' ');
ptext("(smam) will set (am) ");
go_home();
put_str(" ");
put_newlines(2);
}
ptext("Enter-automatic-margins ");
generic_done_message(t, state, ch);
}
/*
** subtest_am(test_list, status, ch)
**
** test automatic margins (am)
*/
static void
subtest_am(
struct test_list *t,
int *state,
int *ch)
{
int i, j;
if (!can_go_home) {
ptextln("(am) not tested, no way to home cursor. ");
} else
if (over_strike) {
put_clear();
go_home();
ptext("\n(am) should ");
i = char_count;
ptext("not be set");
go_home();
for (j = -i; j < columns; j++)
put_this(' ');
put_str("@@@");
go_home();
put_newlines(2);
sprintf(temp, "(am) is %s in the data base",
auto_right_margin ? "true" : "false");
ptextln(temp);
} else {
put_clear();
go_home();
ptext("\n(am) should not be set");
go_home();
for (j = 0; j < columns; j++)
put_this(' ');
ptext("(am) should be set ");
go_home();
put_str(" \n\n");
sprintf(temp, "(am) is %s in the data base",
auto_right_margin ? "true" : "false");
ptextln(temp);
}
ptext("Automatic-right-margin ");
generic_done_message(t, state, ch);
}
/* Note: uprint() sends underscore back-space character, and
ucprint() sends character back-space underscore. */
/*
** uprint(string)
**
** underline string for (ul) test
*/
static void
uprint(const char *s)
{
if (s) {
while (*s) {
put_str("_\b");
putchp(*s++);
}
}
}
/*
** ucprint(string)
**
** underline string for (uc) test
*/
static void
ucprint(const char *s)
{
if (s) {
while (*s) {
putchp(*s++);
putchp('\b');
tc_putp(underline_char);
}
}
}
/*
** subtest_ul(test_list, status, ch)
**
** test transparent underline (ul)
*/
static void
subtest_ul(
struct test_list *t,
int *state,
int *ch)
{
if (!over_strike) {
/* (ul) is used only if (os) is reset */
put_crlf();
sprintf(temp, "This text should %sbe underlined.",
transparent_underline ? "" : "not ");
uprint(temp);
put_crlf();
ptextln("If the above line is not underlined the (ul) should be false.");
sprintf(temp, "(ul) Transparent-underline is %s in the data base",
transparent_underline ? "true" : "false");
ptextln(temp);
generic_done_message(t, state, ch);
}
}
/*
** subtest_uc(test_list, status, ch)
**
** test underline character (uc)
*/
static void
subtest_uc(
struct test_list *t,
int *state,
int *ch)
{
if (!over_strike) {
if (underline_char) {
ucprint("This text should be underlined.");
put_crlf();
ptextln("If the above text is not underlined the (uc) has failed.");
ptext("Underline-character ");
} else {
ptext("(uc) underline-character is not defined. ");
}
generic_done_message(t, state, ch);
}
}
/*
** subtest_bw(test_list, status, ch)
**
** test auto left margin (bw)
*/
static void
subtest_bw(
struct test_list *t,
int *state,
int *ch)
{
int i, j;
if (over_strike) {
/* test (bw) */
ptext("\n(bw) should ");
i = char_count;
ptextln("not be set.");
for (j = i; j < columns; j++)
put_str("\b");
put_str("@@@");
put_crlf();
sprintf(temp, "(bw) Auto-left-margin is %s in the data base",
auto_left_margin ? "true" : "false");
ptextln(temp);
} else {
/* test (bw) */
ptextln("(bw) should not be set.");
for (i = 12; i < columns; i++)
put_str("\b");
if (delete_character) {
for (i = 0; i < 4; i++)
tc_putp(delete_character);
} else {
put_str(" ");
}
put_crlf();
sprintf(temp, "(bw) Auto-left-margin is %s in the data base",
auto_left_margin ? "true" : "false");
ptextln(temp);
}
generic_done_message(t, state, ch);
}
/*
** subtest_tbc(test_list, status, ch)
**
** test clear tabs (tbc)
*/
static void
subtest_tbc(
struct test_list *t,
int *state,
int *ch)
{
int tabat; /* the tab spacing we end up with */
int i;
if (clear_all_tabs && !set_tab) {
ptext("(tbc) Clear-all-tabs is defined but (hts) set-tab is not. ");
ptext("Once the tabs are cleared there is no way to set them. ");
} else
if (clear_all_tabs) {
tabat = set_tab ? 8 : init_tabs;
tc_putp(clear_all_tabs);
ptext("Clear tabs (tbc)");
go_home();
put_crlf();
putchp('\t');
putchp('T');
go_home();
put_newlines(2);
for (i = 0; i < columns; i++) {
if (i == tabat) {
putchp('T');
} else {
putchp('.');
}
}
go_home();
ptext("\n\n\nIf the above two lines have T's in the same column then (tbc) has failed. ");
} else {
ptext("(tbc) Clear-all-tabs is not defined. ");
}
generic_done_message(t, state, ch);
}
/*
** subtest_hts(test_list, status, ch)
**
** (ht) and set tabs with (hts)
*/
static void
subtest_hts(
struct test_list *t,
int *state,
int *ch)
{
int tabat; /* the tab spacing we end up with */
int i;
tabat = init_tabs;
if (set_tab) {
ptext("Tabs set with (hts)");
put_crlf();
for (i = 1; i < columns; i++) {
if (i % 8 == 1) {
tc_putp(set_tab);
}
putchp(' ');
}
tabat = 8;
} else {
sprintf(temp, "(hts) Set-tabs not defined. (it) Initial-tabs at %d", init_tabs);
ptext(temp);
}
go_home();
put_newlines(2);
if (tabat <= 0) {
tabat = 8;
}
for (i = tabat; i < columns; i += tabat) {
putchp('\t');
putchp('T');
}
go_home();
put_newlines(3);
for (i = 1; i < columns; i++) {
putchp('.');
}
go_home();
put_newlines(3);
for (i = tabat; i < columns; i += tabat) {
putchp('\t');
putchp('T');
}
go_home();
put_newlines(4);
putchp('.');
for (i = 2; i < columns; i++) {
if (i % tabat == 1) {
putchp('T');
} else {
putchp('.');
}
}
go_home();
put_newlines(5);
if (set_tab) {
ptextln("If the last two lines are not the same then (hts) has failed.");
} else
if (init_tabs > 0) {
ptextln("If the last two lines are not the same then (it) is wrong.");
} else {
ptextln("If the last two lines are the same then maybe you do have tabs and (it) should be changed.");
}
generic_done_message(t, state, ch);
}
/*
** subtest_xt(test_list, status, ch)
**
** (xt) glitch
*/
static void
subtest_xt(
struct test_list *t,
int *state,
int *ch)
{
int tabat; /* the tab spacing we end up with */
int cc;
tabat = set_tab ? 8 : init_tabs;
if (!over_strike && (tabat > 0)) {
ptext("(xt) should not ");
put_cr();
ptext("(xt) should");
cc = char_count;
while (cc < 16) {
putchp('\t');
cc = ((cc / tabat) + 1) * tabat;
}
putln("be set.");
sprintf(temp, "(xt) Destructive-tab is %s in the data base.",
dest_tabs_magic_smso ? "true" : "false");
ptextln(temp);
generic_done_message(t, state, ch);
}
}
/*
** subtest_cbt(test_list, status, ch)
**
** (cbt) back tab
*/
static void
subtest_cbt(
struct test_list *t,
int *state,
int *ch)
{
int i;
if (back_tab) {
put_clear();
ptext("Back-tab (cbt)");
go_home();
put_crlf();
for (i = 1; i < columns; i++) {
putchp(' ');
}
for (i = 0; i < columns; i += 8) {
tc_putp(back_tab);
putchp('T');
tc_putp(back_tab);
}
go_home();
put_newlines(2);
for (i = 1; i < columns; i++) {
if (i % 8 == 1) {
putchp('T');
} else {
putchp(' ');
}
}
go_home();
put_newlines(3);
ptextln("The preceding two lines should be the same.");
} else {
ptextln("(cbt) Back-tab not present");
}
generic_done_message(t, state, ch);
}
/*
** subtest_xenl(test_list, status, ch)
**
** (xenl) eat newline glitch
*/
static void
subtest_xenl(
struct test_list *t,
int *state,
int *ch)
{
int i, j, k;
if (over_strike) {
/* test (xenl) on overstrike terminals */
if (!can_go_home || !can_clear_screen) {
ptextln("(xenl) Newline-glitch not tested, can't home cursor and clear.");
generic_done_message(t, state, ch);
return;
}
put_clear();
/*
this test must be done in raw mode. Otherwise UNIX will
translate CR to CRLF.
*/
if (stty_query(TTY_OUT_TRANS))
tty_raw(1, char_mask);
ptext("\nreset (xenl). Does ");
i = char_count;
put_str("not ignore CR, does ");
k = char_count;
put_str("not ignore LF");
go_home();
for (j = 0; j < columns; j++)
put_this(' ');
put_cr();
for (j = 0; j < i; j++)
putchp(' ');
put_str("@@@\n@@");
go_home();
for (j = 0; j < columns; j++)
put_this(' ');
put_lf();
for (j = 0; j < k; j++)
putchp(' ');
put_str("@@@\r@@");
tty_set();
go_home();
put_newlines(4);
sprintf(temp, "(xenl) Newline-glitch is %s in the data base",
eat_newline_glitch ? "true" : "false");
ptextln(temp);
} else {
/* test (xenl) when (os) is reset */
if (!can_go_home) {
ptextln("(xenl) Newline-glitch not tested, can't home cursor");
generic_done_message(t, state, ch);
return;
}
/* (xenl) test */
put_clear();
/*
this test must be done in raw mode. Otherwise
UNIX will translate CR to CRLF.
*/
if (stty_query(TTY_OUT_TRANS))
tty_raw(1, char_mask);
for (j = 0; j < columns; j++)
put_this(' ');
put_cr();
ptext("(xenl) should be set. Does not ignore CR");
go_home();
put_crlf();
for (j = 0; j < columns; j++)
put_this(' ');
put_lf(); /* test (cud1) */
ptext("(xenl) should be set. Ignores (cud1)");
go_home();
put_newlines(3);
if (scroll_forward && cursor_down &&
strcmp(scroll_forward, cursor_down)) {
for (j = 0; j < columns; j++)
put_this(' ');
put_ind(); /* test (ind) */
ptext("(xenl) should be set. Ignores (ind)");
go_home();
put_newlines(5);
}
tty_set();
ptextln("If you don't see text above telling you to set it, (xenl) should be false");
sprintf(temp, "(xenl) Newline-glitch is %s in the data base",
eat_newline_glitch ? "true" : "false");
ptextln(temp);
}
generic_done_message(t, state, ch);
}
/*
** subtest_eo(test_list, status, ch)
**
** (eo) erase overstrike
*/
static void
subtest_eo(
struct test_list *t,
int *state,
int *ch)
{
if (transparent_underline || over_strike || underline_char) {
ptext("(eo) should ");
if (underline_char) {
ucprint("not");
} else {
uprint("not");
}
put_cr();
ptextln("(eo) should be set");
sprintf(temp, "\n(eo) Erase-overstrike is %s in the data base",
erase_overstrike ? "true" : "false");
ptextln(temp);
generic_done_message(t, state, ch);
}
}
/*
** subtest_xmc(test_list, status, ch)
**
** (xmc) magic cookie glitch
*/
static void
subtest_xmc(
struct test_list *t,
int *state,
int *ch)
{
int i, j;
if (enter_standout_mode) {
sprintf(temp, "\n(xmc) Magic-cookie-glitch is %d in the data base", magic_cookie_glitch);
ptextln(temp);
j = magic_cookie_glitch * 8;
for (i = 0; i < j; i++) {
put_str(" ");
}
ptextln(" These two lines should line up.");
if (j > 0) {
char_count += j;
}
for (i = 0; i < 4; i++) {
put_mode(enter_standout_mode);
putchp(' ');
put_mode(exit_standout_mode);
putchp(' ');
}
ptextln("These two lines should line up.");
ptext("If they don't line up then (xmc) magic-cookie-glitch should be greater than zero. ");
generic_done_message(t, state, ch);
}
}
/*
** subtest_xhp(test_list, status, ch)
**
** (xhp) erase does not clear standout mode
*/
static void
subtest_xhp(
struct test_list *t,
int *state,
int *ch)
{
if (enter_standout_mode) {
put_crlf();
put_mode(enter_standout_mode);
put_str("Stand out");
put_mode(exit_standout_mode);
put_cr();
ptextln("If any part of this line is standout then (xhp) should be set.");
sprintf(temp, "(xhp) Erase-standout-glitch is %s in the data base",
ceol_standout_glitch ? "true" : "false");
ptextln(temp);
generic_done_message(t, state, ch);
}
}
/*
** subtest_mir(test_list, status, ch)
**
** (mir) move in insert mode
*/
static void
subtest_mir(
struct test_list *t,
int *state,
int *ch)
{
int i;
char *s;
if (enter_insert_mode && exit_insert_mode && cursor_address) {
put_clear();
i = line_count;
put_str("\nXXX\nXXX\nXXX\nXXX");
tc_putp(enter_insert_mode);
s = TPARM_2(cursor_address, i + 1, 0);
tputs(s, lines, tc_putch);
putchp('X');
s = TPARM_2(cursor_address, i + 2, 1);
tputs(s, lines, tc_putch);
putchp('X');
s = TPARM_2(cursor_address, i + 3, 2);
tputs(s, lines, tc_putch);
putchp('X');
s = TPARM_2(cursor_address, i + 4, 3);
tputs(s, lines, tc_putch);
putchp('X');
tc_putp(exit_insert_mode);
put_newlines(2);
ptextln("If you see a 4 by 4 block of X's then (mir) should be true.");
sprintf(temp, "(mir) Move-in-insert-mode is %s in the data base",
move_insert_mode ? "true" : "false");
ptextln(temp);
} else {
ptext("(mir) Move-in-insert-mode not tested, ");
if (!enter_insert_mode) {
ptext("(smir) ");
}
if (!exit_insert_mode) {
ptext("(rmir) ");
}
if (!cursor_address) {
ptext("(cup) ");
}
ptext("not present. ");
}
generic_done_message(t, state, ch);
}
/*
** subtest_msgr(test_list, status, ch)
**
** (msgr) move in sgr mode
*/
static void
subtest_msgr(
struct test_list *t,
int *state,
int *ch)
{
int i;
if (cursor_address &&
((enter_standout_mode && exit_standout_mode) ||
(enter_alt_charset_mode && exit_alt_charset_mode))) {
put_crlf();
i = line_count + 1;
tputs(TPARM_2(cursor_address, i, 0), lines, tc_putch);
put_mode(enter_alt_charset_mode);
put_crlf();
/*
some versions of the wy-120 can not clear lines or
screen when in alt charset mode. If (el) and (ed)
are defined then I can test them. If they are not
defined then they can not break (msgr)
*/
tc_putp(clr_eos);
tc_putp(clr_eol);
put_mode(exit_alt_charset_mode);
put_mode(enter_standout_mode);
putchp('X');
tputs(TPARM_2(cursor_address, i + 2, 1), lines, tc_putch);
putchp('X');
tputs(TPARM_2(cursor_address, i + 3, 2), lines, tc_putch);
putchp('X');
tputs(TPARM_2(cursor_address, i + 4, 3), lines, tc_putch);
putchp('X');
put_mode(exit_standout_mode);
put_crlf();
tc_putp(clr_eos); /* OK if missing */
put_crlf();
ptextln("If you see a diagonal line of standout X's then (msgr) should be true. If any of the blanks are standout then (msgr) should be false.");
sprintf(temp, "(msgr) Move-in-SGR-mode is %s in the data base",
move_standout_mode ? "true" : "false");
ptextln(temp);
} else {
ptextln("(smso) (rmso) (smacs) (rmacs) missing; (msgr) Move-in-SGR-mode not tested.");
}
generic_done_message(t, state, ch);
}
/*
** subtest_in(test_list, status, ch)
**
** (in) insert null glitch
*/
static void
subtest_in(
struct test_list *t,
int *state,
int *ch)
{
if (enter_insert_mode && exit_insert_mode) {
ptextln("\nTesting (in) with (smir) and (rmir)");
putln("\tIf these two lines line up ...");
put_str("\tIf these two lines line up ...");
put_cr();
tc_putp(enter_insert_mode);
putchp(' ');
tc_putp(exit_insert_mode);
ptext("\nthen (in) should be set. ");
sprintf(temp,
"(in) Insert-null-glitch is %s in the data base.",
insert_null_glitch ? "true" : "false");
ptextln(temp);
generic_done_message(t, state, ch);
}
}
/*
** subtest_dadb(test_list, status, ch)
**
** (da) (db) data above, (db) data below
*/
static void
subtest_dadb(
struct test_list *t,
int *state,
int *ch)
{
if (can_clear_screen && scroll_reverse && scroll_forward) {
put_clear();
if (scroll_reverse)
ptext("(da) Data-above should be set\r");
home_down();
if (scroll_forward)
ptext("(db) Data-below should be set\r");
tc_putp(scroll_forward);
go_home();
tc_putp(scroll_reverse);
tc_putp(scroll_reverse);
home_down();
tc_putp(scroll_forward);
go_home();
ptextln("\n\n\n\n\nIf the top line is blank then (da) should be false.");
ptextln("If the bottom line is blank then (db) should be false.");
sprintf(temp, "\n(da) Data-above is %s, and (db) Data-below is %s, in the data base.",
memory_above ? "true" : "false",
memory_below ? "true" : "false");
ptextln(temp);
line_count = lines;
} else {
ptextln("(da) Data-above, (db) Data-below not tested, scrolls or (clear) is missing.");
}
generic_done_message(t, state, ch);
}

View File

@ -1,45 +0,0 @@
##############################################################################
# Copyright (c) 1998-1999,2006 Free Software Foundation, Inc. #
# #
# Permission is hereby granted, free of charge, to any person obtaining a #
# copy of this software and associated documentation files (the "Software"), #
# to deal in the Software without restriction, including without limitation #
# the rights to use, copy, modify, merge, publish, distribute, distribute #
# with modifications, sublicense, and/or sell copies of the Software, and to #
# permit persons to whom the Software is furnished to do so, subject to the #
# following conditions: #
# #
# The above copyright notice and this permission notice shall be included in #
# all copies or substantial portions of the Software. #
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR #
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, #
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL #
# THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING #
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER #
# DEALINGS IN THE SOFTWARE. #
# #
# Except as contained in this notice, the name(s) of the above copyright #
# holders shall not be used in advertising or otherwise to promote the sale, #
# use or other dealings in this Software without prior written #
# authorization. #
##############################################################################
# $Id: modules,v 1.5 2006/04/22 22:37:18 tom Exp $
@ base
ansi progs $(srcdir) $(srcdir)/tack.h ../include/term.h
charset progs $(srcdir) $(srcdir)/tack.h ../include/term.h
color progs $(srcdir) $(srcdir)/tack.h ../include/term.h
control progs $(srcdir) $(srcdir)/tack.h ../include/term.h
crum progs $(srcdir) $(srcdir)/tack.h ../include/term.h
edit progs $(srcdir) $(srcdir)/tack.h ../include/term.h $(INCDIR)/tic.h
fun progs $(srcdir) $(srcdir)/tack.h ../include/term.h
init progs $(srcdir) $(srcdir)/tack.h ../include/term.h
menu progs $(srcdir) $(srcdir)/tack.h ../include/term.h
modes progs $(srcdir) $(srcdir)/tack.h ../include/term.h
output progs $(srcdir) $(srcdir)/tack.h ../include/term.h
pad progs $(srcdir) $(srcdir)/tack.h ../include/term.h
scan progs $(srcdir) $(srcdir)/tack.h ../include/term.h
sync progs $(srcdir) $(srcdir)/tack.h ../include/term.h
sysdep progs $(srcdir) $(srcdir)/tack.h ../include/term.h
tack progs $(srcdir) $(srcdir)/tack.h ../include/term.h

View File

@ -1,818 +0,0 @@
/*
** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
**
** This file is part of TACK.
**
** TACK 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.
**
** TACK 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 TACK; see the file COPYING. If not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
** Boston, MA 02110-1301, USA
*/
/* screen formatting and I/O utility functions */
#include <tack.h>
#include <time.h>
MODULE_ID("$Id: output.c,v 1.11 2006/11/26 00:16:49 tom Exp $")
/* globals */
long char_sent; /* number of characters sent */
int char_count; /* counts characters */
int line_count; /* counts line feeds */
int expand_chars; /* length of expand() string */
int replace_mode; /* used to output replace mode padding */
int can_go_home; /* TRUE if we can fashion a home command */
int can_clear_screen; /* TRUE if we can somehow clear the screen */
int raw_characters_sent; /* Total output characters */
static int log_count; /* Number of characters on a log line */
/* translate mode default strings */
#define TM_carriage_return TM_string[0].value
#define TM_cursor_down TM_string[1].value
#define TM_scroll_forward TM_string[2].value
#define TM_newline TM_string[3].value
#define TM_cursor_left TM_string[4].value
#define TM_bell TM_string[5].value
#define TM_form_feed TM_string[6].value
#define TM_tab TM_string[7].value
struct default_string_list TM_string[TM_last] = {
{"cr", "\r", 0},
{"cud1", "\n", 0},
{"ind", "\n", 0},
{"nel", "\r\n", 0},
{"cub1", "\b", 0},
{"bel", "\007", 0},
{"ff", "\f", 0},
{"ht", "\t", 0}
};
static const char *c0[32] = {
"NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK",
"BEL", "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
"DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
"CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US"
};
static const char *c1[32] = {
"", "", "", "", "IND", "NEL", "SSA", "ESA",
"HTS", "HTJ", "VTS", "PLD", "PLU", "RI", "SS2", "SS3",
"DCS", "PU1", "PU2", "STS", "CCH", "MW", "SPA", "EPA",
"", "", "", "CSI", "ST", "OSC", "PM", "APC"
};
int
getnext(int mask)
{ /* get the next character without scan mode
conversion */
int ch;
unsigned char buf;
tc_putp(req_for_input);
fflush(stdout);
if (nodelay_read)
while (1) {
ch = read(fileno(stdin), &buf, 1);
if (ch == -1)
return EOF;
if (ch == 1)
return buf;
}
ch = getchar();
if (ch == EOF)
return EOF;
return ch & mask;
}
int
getchp(int mask)
{ /* read a character with scan mode conversion */
if (scan_mode) {
tc_putp(req_for_input);
fflush(stdout);
return scan_key();
} else
return getnext(mask);
}
/*
** tc_putch(c)
**
** Output one character
*/
int
tc_putch(int c)
{
char_sent++;
raw_characters_sent++;
putchar(c);
if ((raw_characters_sent & 31) == 31) {
fflush(stdout);
}
if (log_fp) {
/* terminal output logging */
c = UChar(c);
if (c < 32) {
fprintf(log_fp, "<%s>", c0[c]);
log_count += 5;
} else
if (c < 127) {
fprintf(log_fp, "%c", c);
log_count += 1;
} else {
fprintf(log_fp, "<%02x>", c);
log_count += 4;
}
if (c == '\n' || log_count >= 80) {
fprintf(log_fp, "\n");
log_count = 0;
}
}
return (c);
}
/*
** tt_tputs(string, reps)
**
** Output a string with tputs() translation.
** Use this function inside timing tests.
*/
void
tt_tputs(const char *string, int reps)
{
int i;
if (string) {
for (i = 0; i < TT_MAX; i++) {
if (i >= ttp) {
tt_cap[i] = string;
tt_affected[i] = reps;
tt_count[i] = 1;
tt_delay[i] = msec_cost(string, reps);
ttp++;
break;
}
if (string == tt_cap[i] && reps == tt_affected[i]) {
tt_count[i]++;
tt_delay_used += tt_delay[i];
break;
}
}
(void) tputs(string, reps, tc_putch);
}
}
/*
** tt_putp(string)
**
** Output a string with tputs() translation.
** Use this function inside timing tests.
*/
void
tt_putp(const char *string)
{
tt_tputs(string, 1);
}
/*
** tt_putparm(string, reps, arg1, arg2)
**
** Send tt_tputs(tparm(string, args1, arg2), reps)
** Use this function inside timing tests.
*/
void
tt_putparm(
NCURSES_CONST char *string,
int reps,
int arg1,
int arg2)
{
int i;
if (string) {
for (i = 0; i < TT_MAX; i++) {
if (i >= ttp) {
tt_cap[i] = string;
tt_affected[i] = reps;
tt_count[i] = 1;
tt_delay[i] = msec_cost(string, reps);
ttp++;
break;
}
if (string == tt_cap[i] && reps == tt_affected[i]) {
tt_count[i]++;
tt_delay_used += tt_delay[i];
break;
}
}
(void) tputs(TPARM_2((NCURSES_CONST char *)string, arg1, arg2), reps, tc_putch);
}
}
/*
** tc_putp(string)
**
** Output a string with tputs() translation.
** Use this function instead of putp() so we can track
** the actual number of characters sent.
*/
int
tc_putp(const char *string)
{
return tputs(string, 1, tc_putch);
}
void
put_this(int c)
{ /* output one character (with padding) */
tc_putch(c);
if (char_padding && replace_mode)
tt_putp(char_padding);
}
void
put_cr(void)
{
if (translate_mode && carriage_return) {
tt_putp(carriage_return);
} else {
tt_putp(TM_carriage_return);
}
char_count = 0;
}
void
put_lf(void)
{ /* send a linefeed (only works in RAW or
CBREAK mode) */
if (translate_mode && cursor_down) {
tt_putp(cursor_down);
} else {
tt_putp(TM_cursor_down);
}
line_count++;
}
void
put_ind(void)
{ /* scroll forward (only works in RAW or
CBREAK mode) */
if (translate_mode && scroll_forward) {
tt_putp(scroll_forward);
} else {
tt_putp(TM_scroll_forward);
}
line_count++;
}
/*
** put_crlf()
**
** Send (nel) or <cr> <lf>
*/
void
put_crlf(void)
{
if (translate_mode && newline) {
tt_putp(newline);
} else {
tt_putp(TM_newline);
}
char_count = 0;
line_count++;
}
/*
** put_new_lines(count)
**
** Send a number of newlines. (nel)
*/
void
put_newlines(int n)
{
while (n-- > 0) {
put_crlf();
}
}
/*
** putchp(character)
**
** Send one character to the terminal.
** This function does translation of control characters.
*/
void
putchp(int c)
{
switch (c) {
case '\b':
if (translate_mode && cursor_left) {
tt_putp(cursor_left);
} else {
tt_putp(TM_cursor_left);
}
char_count--;
break;
case 7:
if (translate_mode && bell) {
tt_putp(bell);
} else {
tt_putp(TM_bell);
}
break;
case '\f':
if (translate_mode && form_feed) {
tt_putp(form_feed);
} else {
tt_putp(TM_form_feed);
}
char_count = 0;
line_count++;
break;
case '\n':
put_crlf();
break;
case '\r':
put_cr();
break;
case '\t':
if (translate_mode && tab) {
tt_putp(tab);
} else {
tt_putp(TM_tab);
}
char_count = ((char_count / 8) + 1) * 8;
break;
default:
put_this(c);
char_count++;
break;
}
}
void
put_str(const char *s)
{ /* send the string to the terminal */
for (; *s; putchp(*s++));
}
void
putln(const char *s)
{ /* output a string followed by a CR LF */
for (; *s; putchp(*s++));
put_crlf();
}
void
put_columns(const char *s, int len, int w)
{ /* put out s in column format */
int l;
if (char_count + w > columns) {
put_crlf();
}
l = char_count % w;
if (l) {
while (l < w) {
putchp(' ');
l++;
}
}
if (char_count && char_count + len >= columns) {
put_crlf();
}
l = char_count;
put_str(s);
char_count = l + len;
}
/*
** ptext(string)
**
** Output a string but do not assume the terminal will wrap to a
** new line. Break the line at a word boundary then send a CR LF.
** This is more esthetic on 40 column terminals.
*/
void
ptext(const char *s)
{
const char *t;
while (*s) {
for (t = s + 1; *t > ' '; t++);
if ((char_count != 0) && ((t - s) + char_count >= columns)) {
put_crlf();
while (*s == ' ')
s++;
}
while (s < t) {
putchp(*s++);
}
}
}
void
put_dec(char *f, int i)
{ /* print a line with a decimal number in it */
char tm[128];
sprintf(tm, f, i / 10, i % 10);
ptext(tm);
}
void
three_digit(char *tx, int i)
{ /* convert the decimal number to a string of
at least 3 digits */
if (i < 1000)
sprintf(tx, "%d.%d", i / 10, i % 10);
else
sprintf(tx, "%d", i / 10);
}
void
ptextln(const char *s)
{ /* print the text using ptext() then add a CR
LF */
ptext(s);
put_crlf();
}
static void
expand_one(int ch, char **v)
{ /* expand one character */
char *t = *v;
if (ch & 0x80) { /* dump it in octal (yuck) */
*t++ = '\\';
*t++ = '0' + ((ch >> 6) & 3);
*t++ = '0' + ((ch >> 3) & 7);
*t++ = '0' + (ch & 7);
expand_chars += 4;
} else if (ch == 127) { /* DEL */
*t++ = '^';
*t++ = '?';
expand_chars += 2;
} else if (ch >= ' ') {
*t++ = ch;
expand_chars++;
} else { /* control characters */
*t++ = '^';
*t++ = ch + '@';
expand_chars += 2;
}
*v = t;
}
char *
expand(const char *s)
{ /* convert the string to printable form */
static char buf[4096];
char *t, *v;
int ch;
if (magic_cookie_glitch <= 0 && exit_attribute_mode) {
v = enter_reverse_mode;
} else {
v = NULL;
}
expand_chars = 0;
t = buf;
if (s) {
for (; (ch = *s); s++) {
if ((ch & 0x80) && v) { /* print it in reverse video
mode */
strcpy(t, liberated(TPARM_0(v)));
for (; *t; t++);
expand_one(ch & 0x7f, &t);
strcpy(t, liberated(TPARM_0(exit_attribute_mode)));
for (; *t; t++);
} else {
expand_one(ch, &t);
}
}
}
*t = '\0';
return buf;
}
char *
print_expand(char *s)
{ /* convert the string to 7-bit printable form */
static char buf[4096];
char *t;
int ch;
expand_chars = 0;
t = buf;
if (s) {
for (; (ch = *s); s++) {
expand_one(ch, &t);
}
}
*t = '\0';
return buf;
}
char *
expand_to(char *s, int l)
{ /* expand s to length l */
char *t;
for (s = t = expand(s); *t; t++);
for (; expand_chars < l; expand_chars++) {
*t++ = ' ';
}
*t = '\0';
return s;
}
char *
hex_expand_to(char *s, int l)
{ /* expand s to length l in hex */
static char buf[4096];
char *t;
for (t = buf; *s; s++) {
sprintf(t, "%02X ", UChar(*s));
t += 3;
if (t - buf > (int) sizeof(buf) - 4) {
break;
}
}
for (; t - buf < l;) {
*t++ = ' ';
}
*t = '\0';
expand_chars = t - buf;
return buf;
}
char *
expand_command(const char *c)
{ /* expand an ANSI escape sequence */
static char buf[256];
int i, j, ch;
char *s;
s = buf;
for (i = FALSE; (ch = UChar(*c)) != 0; c++) {
if (i) {
*s++ = ' ';
}
i = TRUE;
if (ch < 32) {
j = UChar(c[1]);
if (ch == '\033' && j >= '@' && j <= '_') {
ch = j - '@';
c++;
for (j = 0; (*s = c1[ch][j++]); s++);
} else
for (j = 0; (*s = c0[ch][j++]); s++);
} else {
*s++ = ch;
j = UChar(c[1]);
if (ch >= '0' && ch <= '9' &&
j >= '0' && j <= '9') {
i = FALSE;
}
}
}
*s = '\0';
return buf;
}
/*
** go_home()
**
** Move the cursor to the home position
*/
void
go_home(void)
{
int i;
if (cursor_home)
tt_putp(cursor_home);
else if (cursor_address)
tt_putparm(cursor_address, lines, 0, 0);
else if (row_address) { /* use (vpa) */
put_cr();
tt_putparm(row_address, 1, 0, 0);
} else if (cursor_up && cursor_to_ll) {
tt_putp(cursor_to_ll);
for (i = 1; i < lines; i++) {
tt_putp(cursor_up);
}
} else {
can_go_home = FALSE;
return;
}
char_count = line_count = 0;
can_go_home = TRUE;
}
void
home_down(void)
{ /* move the cursor to the lower left hand
corner */
int i;
if (cursor_to_ll)
tt_putp(cursor_to_ll);
else if (cursor_address)
tt_putparm(cursor_address, lines, lines - 1, 0);
else if (row_address) { /* use (vpa) */
put_cr();
tt_putparm(row_address, 1, lines - 1, 0);
} else if (cursor_down && cursor_home) {
tt_putp(cursor_home);
for (i = 1; i < lines; i++)
tt_putp(cursor_down);
} else
return;
char_count = 0;
line_count = lines - 1;
}
void
put_clear(void)
{ /* clear the screen */
int i;
if (clear_screen)
tt_tputs(clear_screen, lines);
else if (clr_eos && can_go_home) {
go_home();
tt_tputs(clr_eos, lines);
} else if (scroll_forward && !over_strike && (can_go_home || cursor_up)) {
/* clear the screen by scrolling */
put_cr();
if (cursor_to_ll) {
tt_putp(cursor_to_ll);
} else if (cursor_address) {
tt_putparm(cursor_address, lines, lines - 1, 0);
} else if (row_address) {
tt_putparm(row_address, 1, lines - 1, 0);
} else {
for (i = 1; i < lines; i++) {
tt_putp(scroll_forward);
}
}
for (i = 1; i < lines; i++) {
tt_putp(scroll_forward);
}
if (can_go_home) {
go_home();
} else {
for (i = 1; i < lines; i++) {
tt_putp(cursor_up);
}
}
} else {
can_clear_screen = FALSE;
return;
}
char_count = line_count = 0;
can_clear_screen = TRUE;
}
/*
** wait_here()
**
** read one character from the input stream
** If the terminal is not in RAW mode then this function will
** wait for a <cr> or <lf>.
*/
int
wait_here(void)
{
char ch, cc[64];
char message[16];
int i, j;
for (i = 0; i < (int) sizeof(cc); i++) {
cc[i] = ch = getchp(STRIP_PARITY);
if (ch == '\r' || ch == '\n') {
put_crlf();
char_sent = 0;
return cc[i ? i - 1 : 0];
}
if (ch >= ' ') {
if (stty_query(TTY_CHAR_MODE)) {
put_crlf();
char_sent = 0;
return ch;
}
continue;
}
if (ch == 023) { /* Control S */
/* ignore control S, but tell me about it */
while (ch == 023 || ch == 021) {
ch = getchp(STRIP_PARITY);
if (i < (int) sizeof(cc))
cc[++i] = ch;
}
put_str("\nThe terminal sent a ^S -");
for (j = 0; j <= i; j++) {
sprintf(message, " %02X", cc[j] & 0xFF);
put_str(message);
}
put_crlf();
i = -1;
} else if (ch != 021) { /* Not Control Q */
/* could be abort character */
spin_flush();
if (tty_can_sync == SYNC_TESTED) {
(void) tty_sync_error();
} else {
put_str("\n? ");
}
}
}
return '?';
}
/*
** read_string(buffer, length)
**
** Read a string of characters from the input stream.
*/
void
read_string(
char *buf,
int length)
{
int ch, i;
for (i = 0; i < length - 1; ) {
ch = getchp(STRIP_PARITY);
if (ch == '\r' || ch == '\n') {
break;
}
if (ch == '\b' || ch == 127) {
if (i) {
putchp('\b');
putchp(' ');
putchp('\b');
i--;
}
} else {
buf[i++] = ch;
putchp(ch);
}
}
buf[i] = '\0';
put_crlf();
char_sent = 0;
}
/*
** maybe_wait(lines)
**
** wait if near the end of the screen, then clear screen
*/
void
maybe_wait(int n)
{
if (line_count + n >= lines) {
if (char_sent != 0) {
ptext("Go? ");
(void) wait_here();
}
put_clear();
} else {
put_crlf();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,264 +0,0 @@
/*
** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
**
** This file is part of TACK.
**
** TACK 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.
**
** TACK 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 TACK; see the file COPYING. If not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
** Boston, MA 02110-1301, USA
*/
/* scan mode keyboard support */
#include <tack.h>
MODULE_ID("$Id: scan.c,v 1.5 2005/09/17 19:49:16 tom Exp $")
unsigned scan_max; /* length of longest scan code */
char **scan_up, **scan_down, **scan_name;
unsigned *scan_tested, *scan_length;
static unsigned *scan_value;
static int shift_state;
static char *str;
static int debug_char_count;
#define SHIFT_KEY 0x100
#define CONTROL_KEY 0x200
#define META_KEY 0x400
#define CAPS_LOCK 0x800
static const struct {
const char *name;
unsigned type;
} scan_special[] = {
{"<shift>", SHIFT_KEY},
{"<left shift>", SHIFT_KEY},
{"<right shift>", SHIFT_KEY},
{"<control>", CONTROL_KEY},
{"<left control>", CONTROL_KEY},
{"<right control>", CONTROL_KEY},
{"<meta>", META_KEY},
{"<left meta>", META_KEY},
{"<right meta>", META_KEY},
{"<caps lock>", CAPS_LOCK},
{"<tab>", '\t'},
{"<space>", ' '},
{"<return>", '\r'},
{"<linefeed>", '\n'},
{"<formfeed>", '\f'},
{"<backspace>", '\b'},
{0, 0}
};
static void
scan_blanks(void)
{ /* scan past the white space */
while (*str == ' ' || *str == '\t')
str++;
}
static char *
smash(void)
{ /* convert a string to hex */
char *s, *t;
int ch, i, j;
t = s = str;
for (i = 0; (ch = *str); str++) {
if (ch >= '0' && ch <= '9')
j = ch - '0';
else if (ch >= 'a' && ch <= 'f')
j = 10 - 'a' + ch;
else if (ch >= 'A' && ch <= 'F')
j = 10 - 'A' + ch;
else if (ch == ' ' || ch == '\t')
break;
else
continue;
if (i) {
*s |= j;
s++;
} else
*s = j << 4;
i ^= 1;
}
*s = '\0';
return t;
}
void
scan_init(char *fn)
{ /* read the scan mode key definitions */
char *s, *sl;
FILE *fp;
int ch, i, j;
unsigned len;
char home[512];
if ((str = getenv("HOME")))
strcpy(home, str);
else
home[0] = '\0';
fp = NULL;
if ((str = getenv("KEYBOARD"))) {
if (!(fp = fopen(str, "r")) && home[0]) {
sprintf(temp, "%s/.scan.%s", home, str);
fp = fopen(temp, "r");
}
}
if (!fp) {
sprintf(temp, ".scan.%s", fn);
fp = fopen(temp, "r");
}
if (!fp && home[0]) {
sprintf(temp, "%s/.scan.%s", home, fn);
fp = fopen(temp, "r");
}
if (!fp) {
ptext("Unable to open scanfile: ");
ptextln(temp);
bye_kids(1);
return;
}
/*
scan file format:
<down value> <up value> <name>
values are in hex. <name> may be any string of characters
*/
scan_up = (char **) malloc(sizeof(char *) * MAX_SCAN);
scan_down = (char **) malloc(sizeof(char *) * MAX_SCAN);
scan_name = (char **) malloc(sizeof(char *) * MAX_SCAN);
scan_tested = (unsigned *) malloc(sizeof(unsigned *) * MAX_SCAN);
scan_length = (unsigned *) malloc(sizeof(unsigned *) * MAX_SCAN);
scan_value = (unsigned *) malloc(sizeof(unsigned *) * MAX_SCAN);
scan_up[0] = scan_down[0] = scan_name[0] = (char *) 0;
str = (char *) malloc(4096); /* buffer space */
sl = str + 4000; /* an upper limit */
scan_max = 1;
for (i = 0;;) {
for (s = str; (ch = getc(fp)) != EOF;) {
if (ch == '\n' || ch == '\r')
break;
*s++ = ch;
}
*s++ = '\0';
if (ch == EOF)
break;
if (*str == '#' || *str == '\0')
continue;
scan_down[i] = smash();
scan_blanks();
scan_up[i] = smash();
scan_blanks();
scan_name[i] = str;
scan_length[i] = strlen(scan_down[i]);
len = strlen(scan_up[i]) + scan_length[i];
if (len > scan_max)
scan_max = len;
scan_value[i] = UChar(scan_name[i][0]);
if (scan_name[i][1]) /* multi-character name */
for (j = 0; scan_special[j].name; j++) {
if (!strcmp(scan_name[i], scan_special[j].name)) {
scan_value[i] = scan_special[j].type;
break;
}
}
i++;
if (str > sl) {
str = (char *) malloc(4096);
sl = str + 4000;
} else
str = s;
}
fclose(fp);
#ifdef notdef
for (i = 0; scan_down[i]; i++) {
put_str(hex_expand_to(scan_down[i], 3));
put_str(hex_expand_to(scan_up[i], 3));
put_str(" ");
put_str(scan_name[i]);
put_crlf();
}
(void) wait_here();
#endif
}
int
scan_key(void)
{ /* read a key and translate scan mode to
ASCII */
unsigned i;
int j, ch;
char buf[64];
for (i = 1;; i++) {
ch = getchar();
if (ch == EOF)
return EOF;
if (debug_fp) {
fprintf(debug_fp, "%02X ", ch);
debug_char_count += 3;
if (debug_char_count > 72) {
fprintf(debug_fp, "\n");
debug_char_count = 0;
}
}
buf[i - 1] = ch;
buf[i] = '\0';
if (buf[0] & 0x80) { /* scan up */
for (j = 0; scan_up[j]; j++) {
if (i == scan_length[j] &&
!strcmp(buf, scan_up[j])) {
i = 0;
shift_state &= ~scan_value[j];
break;
}
}
continue;
}
for (j = 0; scan_down[j]; j++) {
if (i == scan_length[j] && !strcmp(buf, scan_down[j])) {
i = 0;
shift_state |= scan_value[j];
ch = scan_value[j];
if (ch == CAPS_LOCK)
shift_state ^= SHIFT_KEY;
if (ch >= 256)
break;
if (shift_state & SHIFT_KEY) {
if (ch >= 0x60)
ch -= 0x20;
else if (ch >= 0x30 && ch <= 0x3f)
ch -= 0x10;
}
if (shift_state & CONTROL_KEY) {
if ((ch | 0x20) >= 0x60 &&
(ch | 0x20) <= 0x7f)
ch = (ch | 0x20) - 0x60;
}
if (shift_state & META_KEY)
ch |= 0x80;
return ch;
}
}
if (i > scan_max)
i = 1;
}
}

View File

@ -1,436 +0,0 @@
/*
** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
**
** This file is part of TACK.
**
** TACK 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.
**
** TACK 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 TACK; see the file COPYING. If not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
** Boston, MA 02110-1301, USA
*/
#include <tack.h>
#include <time.h>
MODULE_ID("$Id: sync.c,v 1.9 2006/05/06 20:45:48 tom Exp $")
/* terminal-synchronization and performance tests */
static void sync_home(struct test_list *, int *, int *);
static void sync_lines(struct test_list *, int *, int *);
static void sync_clear(struct test_list *, int *, int *);
static void sync_summary(struct test_list *, int *, int *);
static struct test_list sync_test_list[] = {
{MENU_NEXT, 0, 0, 0, "b) baud rate test", sync_home, 0},
{MENU_NEXT, 0, 0, 0, "l) scroll performance", sync_lines, 0},
{MENU_NEXT, 0, 0, 0, "c) clear screen performance", sync_clear, 0},
{MENU_NEXT, 0, 0, 0, "p) summary of results", sync_summary, 0},
{0, 0, 0, 0, txt_longer_test_time, longer_test_time, 0},
{0, 0, 0, 0, txt_shorter_test_time, shorter_test_time, 0},
{MENU_LAST, 0, 0, 0, 0, 0, 0}
};
struct test_menu sync_menu = {
0, 'n', 0,
"Performance tests", "perf", "n) run standard tests",
sync_test, sync_test_list, 0, 0, 0
};
int tty_can_sync; /* TRUE if tty_sync_error() returned FALSE */
static int tty_newline_rate; /* The number of newlines per second */
static int tty_clear_rate; /* The number of clear-screens per second */
unsigned long tty_cps; /* The number of characters per second */
#define TTY_ACK_SIZE 64
static int ACK_terminator; /* terminating ACK character */
static int ACK_length; /* length of ACK string */
static const char *tty_ENQ; /* enquire string */
static char tty_ACK[TTY_ACK_SIZE]; /* ACK response, set by tty_sync_error() */
/*****************************************************************************
*
* Terminal synchronization.
*
* These functions handle the messy business of enq-ack handshaking
* for timing purposes.
*
*****************************************************************************/
int
tty_sync_error(void)
{
int ch, trouble, ack;
trouble = FALSE;
for (;;) {
tt_putp(tty_ENQ); /* send ENQ */
ch = getnext(STRIP_PARITY);
event_start(TIME_SYNC); /* start the timer */
/*
The timer doesn't start until we get the first character.
After that I expect to get the remaining characters of
the acknowledge string in a short period of time. If
that is not true then these characters are coming from
the user and we need to send the ENQ sequence out again.
*/
for (ack = 0; ; ) {
if (ack < TTY_ACK_SIZE - 2) {
tty_ACK[ack] = ch;
tty_ACK[ack + 1] = '\0';
}
if (ch == ACK_terminator) {
return trouble;
}
if (++ack >= ACK_length) {
return trouble;
}
ch = getnext(STRIP_PARITY);
if (event_time(TIME_SYNC) > 400000) {
break;
}
}
set_attr(0); /* just in case */
put_crlf();
if (trouble) {
/* The terminal won't sync. Life is not good. */
return TRUE;
}
put_str(" -- sync -- ");
trouble = TRUE;
}
}
/*
** flush_input()
**
** Throw away any output.
*/
void
flush_input(void)
{
if (tty_can_sync == SYNC_TESTED && ACK_terminator >= 0) {
(void) tty_sync_error();
} else {
spin_flush();
}
}
/*
** probe_enq_ok()
**
** does the terminal do enq/ack handshaking?
*/
static void
probe_enq_ok(void)
{
int tc, len, ulen;
put_str("Testing ENQ/ACK, standby...");
fflush(stdout);
can_test("u8 u9", FLAG_TESTED);
#ifdef user9
tty_ENQ = user9 ? user9 : "\005";
#else
tty_ENQ = "\005";
#endif
tc_putp(tty_ENQ);
event_start(TIME_SYNC); /* start the timer */
read_key(tty_ACK, TTY_ACK_SIZE - 1);
if (event_time(TIME_SYNC) > 400000 || tty_ACK[0] == '\0') {
/* These characters came from the user. Sigh. */
tty_can_sync = SYNC_FAILED;
ptext("\nThis program expects the ENQ sequence to be");
ptext(" answered with the ACK character. This will help");
ptext(" the program reestablish synchronization when");
ptextln(" the terminal is overrun with data.");
ptext("\nENQ sequence from (u9): ");
putln(expand(tty_ENQ));
ptext("ACK received: ");
putln(expand(tty_ACK));
#ifdef user8
len = user8 ? strlen(user8) : 0;
#else
len = 0;
#endif
sprintf(temp, "Length of ACK %d. Expected length of ACK %d.",
(int) strlen(tty_ACK), len);
ptextln(temp);
#ifdef user8
if (len) {
temp[0] = user8[len - 1];
temp[1] = '\0';
ptext("Terminating character found in (u8): ");
putln(expand(temp));
}
#endif
return;
}
tty_can_sync = SYNC_TESTED;
if ((len = strlen(tty_ACK)) == 1) {
/* single character acknowledge string */
ACK_terminator = tty_ACK[0];
ACK_length = 4096;
return;
}
tc = tty_ACK[len - 1];
#ifdef user8
if (user8) {
ulen = strlen(user8);
if (tc == user8[ulen - 1]) {
/* ANSI style acknowledge string */
ACK_terminator = tc;
ACK_length = 4096;
return;
}
}
#endif
/* fixed length acknowledge string */
ACK_length = len;
ACK_terminator = -2;
}
/*
** verify_time()
**
** verify that the time tests are ready to run.
** If the baud rate is not set then compute it.
*/
void
verify_time(void)
{
int status, ch;
if (tty_can_sync == SYNC_FAILED) {
return;
}
probe_enq_ok();
put_crlf();
if (tty_can_sync == SYNC_TESTED) {
put_crlf();
if (ACK_terminator >= 0) {
ptext("ACK terminating character: ");
temp[0] = ACK_terminator;
temp[1] = '\0';
ptextln(expand(temp));
} else {
sprintf(temp, "Fixed length ACK, %d characters",
ACK_length);
ptextln(temp);
}
}
if (tty_baud_rate == 0) {
sync_home(&sync_test_list[0], &status, &ch);
}
}
/*****************************************************************************
*
* Terminal performance tests
*
* Find out how fast the terminal can:
* 1) accept characters
* 2) scroll the screen
* 3) clear the screen
*
*****************************************************************************/
/*
** sync_home(test_list, status, ch)
**
** Baudrate test
*/
static void
sync_home(
struct test_list *t,
int *state,
int *ch)
{
int j, k;
unsigned long rate;
if (!cursor_home && !cursor_address && !row_address) {
ptext("Terminal can not home cursor. ");
generic_done_message(t, state, ch);
return;
}
if (skip_pad_test(t, state, ch,
"(home) Start baudrate search")) {
return;
}
pad_test_startup(1);
do {
go_home();
for (j = 1; j < lines; j++) {
for (k = 0; k < columns; k++) {
if (k & 0xF) {
put_this(letter);
} else {
put_this('.');
}
}
SLOW_TERMINAL_EXIT;
}
NEXT_LETTER;
} while(still_testing());
pad_test_shutdown(t, auto_right_margin == 0);
/* note: tty_frame_size is the real framesize times two.
This takes care of half bits. */
rate = (tx_cps * tty_frame_size) >> 1;
if (rate > tty_baud_rate) {
tty_baud_rate = rate;
}
if (tx_cps > tty_cps) {
tty_cps = tx_cps;
}
sprintf(temp, "%lu characters per second. Baudrate %d ", tx_cps, j);
ptext(temp);
generic_done_message(t, state, ch);
}
/*
** sync_lines(test_list, status, ch)
**
** How many newlines/second?
*/
static void
sync_lines(
struct test_list *t,
int *state,
int *ch)
{
int j;
if (skip_pad_test(t, state, ch,
"(nel) Start scroll performance test")) {
return;
}
pad_test_startup(0);
repeats = 100;
do {
sprintf(temp, "%d", test_complete);
put_str(temp);
put_newlines(repeats);
} while(still_testing());
pad_test_shutdown(t, 0);
j = sliding_scale(tx_count[0], 1000000, usec_run_time);
if (j > tty_newline_rate) {
tty_newline_rate = j;
}
sprintf(temp, "%d linefeeds per second. ", j);
ptext(temp);
generic_done_message(t, state, ch);
}
/*
** sync_clear(test_list, status, ch)
**
** How many clear-screens/second?
*/
static void
sync_clear(
struct test_list *t,
int *state,
int *ch)
{
int j;
if (!clear_screen) {
ptext("Terminal can not clear-screen. ");
generic_done_message(t, state, ch);
return;
}
if (skip_pad_test(t, state, ch,
"(clear) Start clear-screen performance test")) {
return;
}
pad_test_startup(0);
repeats = 20;
do {
sprintf(temp, "%d", test_complete);
put_str(temp);
for (j = 0; j < repeats; j++) {
put_clear();
}
} while(still_testing());
pad_test_shutdown(t, 0);
j = sliding_scale(tx_count[0], 1000000, usec_run_time);
if (j > tty_clear_rate) {
tty_clear_rate = j;
}
sprintf(temp, "%d clear-screens per second. ", j);
ptext(temp);
generic_done_message(t, state, ch);
}
/*
** sync_summary(test_list, status, ch)
**
** Print out the test results.
*/
static void
sync_summary(
struct test_list *t,
int *state,
int *ch)
{
char size[32];
put_crlf();
ptextln("Terminal size characters/sec linefeeds/sec clears/sec");
sprintf(size, "%dx%d", columns, lines);
sprintf(temp, "%-10s%-11s%11lu %11d %11d", tty_basename, size,
tty_cps, tty_newline_rate, tty_clear_rate);
ptextln(temp);
generic_done_message(t, state, ch);
}
/*
** sync_test(menu)
**
** Run at the beginning of the pad tests and function key tests
*/
void
sync_test(
struct test_menu *menu)
{
control_init();
if (tty_can_sync == SYNC_NOT_TESTED) {
verify_time();
}
if (menu->menu_title) {
put_crlf();
ptextln(menu->menu_title);
}
}
/*
** sync_handshake(test_list, status, ch)
**
** Test or retest the ENQ/ACK handshake
*/
void
sync_handshake(
struct test_list *t GCC_UNUSED,
int *state GCC_UNUSED,
int *ch GCC_UNUSED)
{
tty_can_sync = SYNC_NOT_TESTED;
verify_time();
}

View File

@ -1,504 +0,0 @@
/*
** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
**
** This file is part of TACK.
**
** TACK 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.
**
** TACK 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 TACK; see the file COPYING. If not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
** Boston, MA 02110-1301, USA
*/
/*
* Operating system dependent functions. We assume the POSIX API.
* Note: on strict-POSIX systems (including BSD/OS) the select_delay_type
* global has no effect.
*/
#ifdef HAVE_CONFIG_H
#include <ncurses_cfg.h>
#endif
#include <signal.h> /* include before curses.h to work around glibc bug */
#include <tack.h>
#include <term.h>
#include <errno.h>
#if defined(__BEOS__)
#undef false
#undef true
#include <OS.h>
#endif
#if HAVE_SELECT
#if HAVE_SYS_TIME_H && HAVE_SYS_TIME_SELECT
#include <sys/time.h>
#endif
#if HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#endif
MODULE_ID("$Id: sysdep.c,v 1.15 2005/09/17 19:49:16 tom Exp $")
#if DECL_ERRNO
extern int errno;
#endif
#ifdef TERMIOS
#define PUT_TTY(fd, buf) tcsetattr(fd, TCSAFLUSH, buf)
#else
#define PUT_TTY(fd, buf) stty(fd, buf)
#endif
/* globals */
int tty_frame_size; /* asynch frame size times 2 */
unsigned tty_baud_rate; /* baud rate - bits per second */
int not_a_tty; /* TRUE if output is not a tty (i.e. pipe) */
int nodelay_read; /* TRUE if NDELAY is set */
#ifdef TERMIOS
#define TTY_IS_NOECHO !(new_modes.c_lflag & ECHO)
#define TTY_IS_OUT_TRANS (new_modes.c_oflag & OPOST)
#define TTY_IS_CHAR_MODE !(new_modes.c_lflag & ICANON)
#define TTY_WAS_CS8 ((old_modes.c_cflag & CSIZE) == CS8)
#define TTY_WAS_XON_XOFF (old_modes.c_iflag & (IXON|IXOFF))
#else
#define TTY_IS_NOECHO !(new_modes.sg_flags & (ECHO))
#define TTY_IS_OUT_TRANS (new_modes.sg_flags & (CRMOD))
#define TTY_IS_CHAR_MODE (new_modes.sg_flags & (RAW|CBREAK))
#define TTY_WAS_CS8 (old_modes.sg_flags & (PASS8))
#define TTY_WAS_XON_XOFF (old_modes.sg_flags & (TANDEM|MDMBUF|DECCTQ))
#endif
static TTY old_modes, new_modes;
void catchsig(void);
/*
* These are a sneaky way of conditionalizing bit unsets so strict-POSIX
* systems won't see them.
*/
#ifndef XCASE
#define XCASE 0
#endif
#ifndef OLCUC
#define OLCUC 0
#endif
#ifndef IUCLC
#define IUCLC 0
#endif
#ifndef TABDLY
#define TABDLY 0
#endif
#ifndef IXANY
#define IXANY 0
#endif
void
tty_raw(int minch GCC_UNUSED, int mask)
{ /* set tty to raw noecho */
new_modes = old_modes;
#ifdef TERMIOS
#if HAVE_SELECT
new_modes.c_cc[VMIN] = 1;
#else
new_modes.c_cc[VMIN] = minch;
#endif
new_modes.c_cc[VTIME] = 2;
new_modes.c_lflag &=
~(ISIG | ICANON | XCASE | ECHO | ECHOE | ECHOK | ECHONL);
#ifdef LOBLK
new_modes.c_lflag &= ~LOBLK;
#endif
new_modes.c_oflag &= ~(OPOST | OLCUC | TABDLY);
if (mask == ALLOW_PARITY) {
new_modes.c_cflag &= ~(CSIZE | PARENB | HUPCL);
new_modes.c_cflag |= CS8;
}
new_modes.c_iflag &=
~(IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP | INLCR | IGNCR | ICRNL |
IUCLC | IXON | IXANY | IXOFF);
#else
new_modes.sg_flags |= RAW;
#endif
if (not_a_tty)
return;
PUT_TTY(fileno(stdin), &new_modes);
}
void
tty_set(void)
{ /* set tty to special modes */
new_modes = old_modes;
#ifdef TERMIOS
new_modes.c_cc[VMIN] = 1;
new_modes.c_cc[VTIME] = 1;
new_modes.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL);
#if defined(ONLCR) && defined(OCRNL) && defined(ONLRET) && defined(OFILL)
new_modes.c_oflag &= ~(ONLCR | OCRNL | ONLRET | OFILL);
#else
new_modes.c_oflag &= ~(OPOST);
#endif
if (char_mask == ALLOW_PARITY)
new_modes.c_iflag &= ~ISTRIP;
switch (select_xon_xoff) {
case 0:
new_modes.c_iflag &= ~(IXON | IXOFF);
break;
case 1:
#if defined(sequent) && sequent
/* the sequent System V emulation is broken */
new_modes = old_modes;
new_modes.c_cc[VEOL] = 6; /* control F (ACK) */
#endif
new_modes.c_iflag |= IXON | IXOFF;
break;
}
switch (select_delay_type) {
case 0:
#ifdef NLDLY
new_modes.c_oflag &=
~(NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY);
#endif /* NLDLY */
break;
case 1:
#ifdef NLDLY
new_modes.c_oflag &=
~(NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY);
#endif /* NLDLY */
#ifdef NL1
new_modes.c_oflag |= NL1 | CR2;
#endif /* NL1 */
break;
}
if (!(new_modes.c_oflag & (unsigned long) ~OPOST))
new_modes.c_oflag &= (unsigned long) ~OPOST;
#else
new_modes.sg_flags |= RAW;
if (not_a_tty)
return;
#endif
PUT_TTY(fileno(stdin), &new_modes);
}
void
tty_reset(void)
{ /* reset the tty to the original modes */
fflush(stdout);
if (not_a_tty)
return;
PUT_TTY(fileno(stdin), &old_modes);
}
void
tty_init(void)
{ /* ATT terminal init */
#if defined(F_GETFL) && defined(O_NDELAY)
int flags;
flags = fcntl(fileno(stdin), F_GETFL, 0);
nodelay_read = flags & O_NDELAY;
#else
nodelay_read = FALSE;
#endif
not_a_tty = FALSE;
if (GET_TTY(fileno(stdin), &old_modes) == -1) {
if (errno == ENOTTY) {
tty_frame_size = 20;
not_a_tty = TRUE;
return;
}
printf("tcgetattr error: %d\n", errno);
exit(1);
}
/* if TAB3 is set then setterm() wipes out tabs (ht) */
new_modes = old_modes;
#ifdef TERMIOS
#ifdef TABDLY
new_modes.c_oflag &= ~TABDLY;
#endif /* TABDLY */
#endif
if (PUT_TTY(fileno(stdin), &new_modes) == -1) {
printf("tcsetattr error: %d\n", errno);
exit(1);
}
#ifdef sequent
/* the sequent ATT emulation is broken soooo. */
old_modes.c_cflag &= ~(CSIZE | CSTOPB);
old_modes.c_cflag |= CS7 | PARENB;
#endif
catchsig();
#ifdef TERMIOS
switch (old_modes.c_cflag & CSIZE) {
#if defined(CS5) && (CS5 != 0)
case CS5:
tty_frame_size = 10;
break;
#endif
#if defined(CS6) && (CS6 != 0)
case CS6:
tty_frame_size = 12;
break;
#endif
#if defined(CS7) && (CS7 != 0)
case CS7:
tty_frame_size = 14;
break;
#endif
#if defined(CS8) && (CS8 != 0)
case CS8:
tty_frame_size = 16;
break;
#endif
}
tty_frame_size += 2 +
((old_modes.c_cflag & PARENB) ? 2 : 0) +
((old_modes.c_cflag & CSTOPB) ? 4 : 2);
#else
tty_frame_size = 6 +
(old_modes.sg_flags & PASS8) ? 16 : 14;
#endif
}
/*
** stty_query(question)
**
** Does the current driver settings have this property?
*/
int
stty_query(int q)
{
switch (q) {
case TTY_NOECHO:
return TTY_IS_NOECHO;
case TTY_OUT_TRANS:
return TTY_IS_OUT_TRANS;
case TTY_CHAR_MODE:
return TTY_IS_CHAR_MODE;
}
return (-1);
}
/*
** initial_stty_query(question)
**
** Did the initial driver settings have this property?
*/
int
initial_stty_query(int q)
{
switch (q) {
case TTY_8_BIT:
return TTY_WAS_CS8;
case TTY_XON_XOFF:
return TTY_WAS_XON_XOFF;
}
return (-1);
}
#if HAVE_SELECT && defined(FD_ZERO)
static int
char_ready(void)
{
int n;
fd_set ifds;
struct timeval tv;
FD_ZERO(&ifds);
FD_SET(fileno(stdin), &ifds);
tv.tv_sec = 0;
tv.tv_usec = 200000;
n = select(fileno(stdin)+1, &ifds, NULL, NULL, &tv);
return (n != 0);
}
#else
#ifdef FIONREAD
int
char_ready(void)
{
int i, j;
/* the following loop has to be tuned for each computer */
for (j = 0; j < 1000; j++) {
ioctl(fileno(stdin), FIONREAD, &i);
if (i)
return i;
}
return i;
}
#else
#if defined(__BEOS__)
int
char_ready(void)
{
int n = 0;
int howmany = ioctl(0, 'ichr', &n);
return (howmany >= 0 && n > 0);
}
#else
#define char_ready() 1
#endif
#endif
#endif
/*
** spin_flush()
**
** Wait for the input stream to stop.
** Throw away all input characters.
*/
void
spin_flush(void)
{
unsigned char buf[64];
fflush(stdout);
event_start(TIME_FLUSH); /* start the timer */
do {
if (char_ready()) {
(void) read(fileno(stdin), &buf, sizeof(buf));
}
} while (event_time(TIME_FLUSH) < 400000);
}
/*
** read_key(input-buffer, length-of-buffer)
**
** read one function key from the input stream.
** A null character is converted to 0x80.
*/
void
read_key(char *buf, int max)
{
int got, ask, i, l;
char *s;
*buf = '\0';
s = buf;
fflush(stdout);
/* ATT unix may return 0 or 1, Berkeley Unix should be 1 */
while (read(fileno(stdin), s, 1) == 0);
++s;
--max;
while (max > 0 && (ask = char_ready())) {
if (ask > max) {
ask = max;
}
if ((got = read(fileno(stdin), s, (unsigned) ask))) {
s += got;
} else {
break;
}
max -= got;
}
*s = '\0';
l = s - buf;
for (s = buf, i = 0; i < l; i++) {
if ((*s & 0x7f) == 0) {
/* convert nulls to 0x80 */
*(unsigned char *)s = 128;
} else {
/* strip high order bits (if any) */
*s &= char_mask;
}
}
}
void
ignoresig(void)
{
/* ignore signals */
signal(SIGINT, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
signal(SIGTERM, SIG_IGN);
signal(SIGALRM, SIG_IGN);
}
/*
onintr( )
is the interrupt handling routine onintr turns off interrupts while doing
clean-up
onintr always exits fatally
*/
static RETSIGTYPE
onintr(int sig GCC_UNUSED)
{
ignoresig();
tty_reset();
exit(1);
}
/*
catchsig( )
set up to field interrupts (via function onintr( )) so that if interrupted
we can restore the correct terminal modes
catchsig simply returns
*/
void
catchsig(void)
{
if ((signal(SIGINT, SIG_IGN)) == SIG_DFL)
signal(SIGINT, onintr);
if ((signal(SIGHUP, SIG_IGN)) == SIG_DFL)
signal(SIGHUP, onintr);
if ((signal(SIGQUIT, SIG_IGN)) == SIG_DFL)
signal(SIGQUIT, onintr);
if ((signal(SIGTERM, SIG_IGN)) == SIG_DFL)
signal(SIGTERM, onintr);
}
/*
** alarm_event(sig)
**
** Come here for an alarm event
*/
static void
alarm_event(
int sig GCC_UNUSED)
{
no_alarm_event = 0;
}
/*
** set_alarm_clock(seconds)
**
** Set the alarm clock to fire in <seconds>
*/
void
set_alarm_clock(
int seconds)
{
signal(SIGALRM, alarm_event);
no_alarm_event = 1;
(void) alarm((unsigned) seconds);
}

View File

@ -1,340 +0,0 @@
.\"***************************************************************************
.\" Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. *
.\" *
.\" Permission is hereby granted, free of charge, to any person obtaining a *
.\" copy of this software and associated documentation files (the *
.\" "Software"), to deal in the Software without restriction, including *
.\" without limitation the rights to use, copy, modify, merge, publish, *
.\" distribute, distribute with modifications, sublicense, and/or sell *
.\" copies of the Software, and to permit persons to whom the Software is *
.\" furnished to do so, subject to the following conditions: *
.\" *
.\" The above copyright notice and this permission notice shall be included *
.\" in all copies or substantial portions of the Software. *
.\" *
.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
.\" IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
.\" DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
.\" OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
.\" THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
.\" *
.\" Except as contained in this notice, the name(s) of the above copyright *
.\" holders shall not be used in advertising or otherwise to promote the *
.\" sale, use or other dealings in this Software without prior written *
.\" authorization. *
.\"***************************************************************************
.\"
.\" $Id: tack.1,v 1.3 2006/04/22 22:26:55 tom Exp $
.TH tack 1M ""
.ds n 5
.ds d @TERMINFO@
.SH NAME
\fBtack\fR - \fIterminfo\fR action checker
.SH SYNOPSIS
\fBtack\fR [-itV] [term]
.br
.SH DESCRIPTION
The \fBtack\fR program has three purposes:
(1) to help you build a new terminfo entry describing an unknown terminal,
(2) to test the correctness of an existing entry, and
(3) to develop the correct pad timings needed to ensure that screen updates
don't fall behind the incoming data stream.
.PP
\fBTack\fR presents a series of screen-painting and interactive
tests in ways which are intended to make any mismatches between the
terminfo entry and reality visually obvious.
\fBTack\fR also provides tools that can help in understanding how
the terminal operates.
.SS OPTIONS
.TP
.I "\-i"
Usually \fBtack\fR will send the reset and init strings to the terminal
when the program starts up. The \fI-i\fR option will inhibit the
terminal initialization.
.TP
.I "\-t"
Tell \fBtack\fR to override the terminfo settings for basic terminal
functions. When this option is set \fBtack\fR will translate
(cr) to \\r, (cud1) to \\n, (ind) to \\n, (nel) to \\r\\n,
(cub1) to \\b, (bel) to \\007, (ff) to \\f and (ht) to \\t.
.TP
.I "\-V"
Display the version information and exit.
.TP
.I "term"
Terminfo terminal name to be tested. If not present then the $TERM
environment variable will be used.
.SH OVERVIEW
Since \fBtack\fR is designed to test terminfo's it is not possible
to rely on the correctness of the terminfo data base. Because of this
the menuing system used with \fBtack\fR is vary primitive. When a
menu is printed it will scroll the entire screen. To compensate
for this verbose menu system \fBtack\fR permits menu selection
type ahead.
If you already know what action you would like \fBtack\fR to perform
then you can enter that value immediately and avoid the menu display.
When in doubt the question mark (?) is a good character to type.
A carriage return will execute the default action. These default
actions are designed to run all the standard tests.
.PP
When \fBtack\fR first comes up it will display some basic information
about the terminal. Take some time to verify this information.
If it is wrong many of the subsequent tests will fail. The most
important item is the screen size. If the screen size is wrong there
is no point in proceeding. (home) and (clear) are also critical
to the success of subsequent tests. The values of (cr) (ind)
(cub1) and (ht) may effect the tests if they are defined incorrectly.
If they are undefined \fBtack\fR will set them to reasonable defaults.
The last two entries on the display are the enquire and acknowledge strings.
These strings are taken from the user strings (u9) and (u8).
.PP
By now you must be wondering why the terminfo names are enclosed
in parenthesis. This has no profound meaning other than it makes
them stand out. The \fBtack\fR program uses this convention any time
it displays a terminfo name. Remember \fBtack\fR is designed to
rely on as little of the terminfo entry as possible.
.SH CREATING NEW ENTRIES
\fBTack\fR has a number of tools that are designed to help gather
information about the terminal. Although these functions are not
dependent on terminal type, you may wish to execute \fBtack\fR
with options \fI\-it\fR. This will turn off initialization
and default the standard entries.
.PP
These tools may be reached from the main menu by selecting
the 'tools' entry.
.PP
\fBEcho tool\fR: All data typed from the keyboard will be echoed back
to the terminal. Control characters are not translated to the up arrow format
but are sent as control characters. This allows you to test an escape
sequence and see what it actually does. You may also elect to
\fBenable hex output on echo tool\fR this will echo the characters in
hexadecimal. Once the test is running you may enter the 'lines'
or 'columns' keywords which will display a pattern that will help
you determine your screen size. A complete list of keywords will
be displayed when the test starts. Type 'help' to redisplay
the list of available commands.
.PP
\fBReply tool\fR: This tool acts much like the echo tool, but
control characters that are sent from the terminal more than one character
after a carriage return will be expanded to the up arrow format. For example
on a standard ANSI terminal you may type:
CR ESC [ c
and the response will be echoed as something like:
^[ [ ? 6 c
.PP
\fBANSI sgr display\fR: This test assumes you have an ANSI terminal. It
goes through attribute numbers 0 to 79, displaying each in turn and using that
SGR number to write the text. This shows you which of the SGR
modes are actually implemented by the terminal. Note: some terminals (such as
Tektronix color) use the private use characters to augment the functionality of
the SGR command. These private use characters may be interjected into the
escape sequence by typing the character ( <, =, >, ? ) after the original
display has been shown.
.PP
\fBANSI status reports\fR: This test queries the terminal in standard
ANSI/VT-100 fashion. The results of this test may help
determine what options are supported by your terminal.
.PP
\fBANSI character sets\fR: This test displays the character sets
available on a ANSI/VT-100 style terminal.
Character sets on a real VT-100 terminal are usually defined
with smacs=\\E(0 and rmacs=\\E(B. The first character after the
escape defines the font bank. The second character defines the
character set. This test allows you to view any of the possible
combinations. Private use character sets are defined by the digits.
Standard character sets are located in the alphabetic range.
.SH VERIFYING AN EXISTING ENTRY
.PP
You can verify the correctness of an entry with the `begin testing'
function. This entry is the default action and will be chosen
if you hit carriage return (or enter). This will bring up a
secondary menu that allows you to select more specific tests.
.PP
The general philosophy of the program is, for each capability, to send an
appropriate test pattern to the terminal then send a description of
what the user should expect. Occasionally (as when checking function-key
capabilities) the program will ask you to enter input for it to check.
.PP
If the test fails then you have the option of dynamically changing
the terminfo entry and re-running the test. This is done with
the 'edit terminfo' menu item. The edit submenu allows you to change
the offending terminfo entry and immediately retest the capability.
The edit menu lets you do other things with the terminfo, such as;
display the entire terminfo entry,
display which caps have been tested and display which caps cannot
be tested. This menu also allows you to write the newly modified
terminfo to disc. If you have made any modifications to the
terminfo \fBtack\fR will ask you if you want to save the file
to disc before it exits. The filename will be the same as the terminal name.
After the program exits you can run the tic(1M) compiler on the
new terminfo to install it in the terminfo data base.
.PP
.SH CORRECTING PAD TIMINGS
.SS Theory of Overruns and Padding
.PP
Some terminals require significant amounts of time (that is, more than one
transmitted-character interval) to do screen updates that change large
portions of the screen, such as screen clears, line insertions,
line deletions, and scrolls (including scrolls triggered by line feeds
or a write to the lowest, right-hand-most cell of the screen).
.PP
If the computer continues to send characters to the terminal while one
of these time-consuming operations is going on, the screen may be garbled.
Since the length of a character transmission time varies inversely with
transmission speed in cps, entries which function at lower speeds may
break at higher speeds.
.PP
Similar problems result if the host machine is simply sending characters at a
sustained rate faster than the terminal can buffer and process them. In either
case, when the terminal cannot process them and can't tell the host to stop
soon enough, it will just drop them. The dropped characters could be text,
escape sequences or the escape character itself, causing some really
strange-looking displays. This kind of glitch is called an \fIoverrun\fR.
.PP
In terminfo entries, you can attach a \fBpad time\fR to each string capability
that is a number of milliseconds to delay after sending it. This will give
the terminal time to catch up and avoid overruns.
.PP
If you are running a software terminal emulator, or you are on an X pseudo-tty,
or your terminal is on an RS-232C line which correctly handles RTS/CTS
hardware flow control, then pads are not strictly necessary. However, some
display packages (such as ncurses(3X)) use the pad counts to calculate
the fastest way to implement certain functions.
For example: scrolling the screen may be faster than deleting the top line.
.PP
One common way to avoid overruns is with XON/XOFF handshaking.
But even this handshake may have problems at high baud rates.
This is a result of the way XON/XOFF works. The terminal tells
the host to stop with an XOFF. When the host gets this character, it stops
sending. However, there is a small amount of time between the stop request and
the actual stop. During this window, the terminal must continue to accept
characters even though it has told the host to stop. If the terminal sends
the stop request too late, then its internal buffer will overflow. If it sends
the stop character too early, then the terminal is not getting the most
efficient use out of its internal buffers. In a real application at high baud
rates, a terminal could get a dozen or more characters before the host gets
around to suspending transmission. Connecting the terminal over a network
will make the problem much worse.
.PP
(RTS/CTS handshaking does not have this problem because the UARTs are
signal-connected and the "stop flow" is done at the lowest level, without
software intervention).
.PP
.SS Timing your terminal
.PP
In order to get accurate timings from your terminal \fBtack\fR
needs to know when the terminal has finished processing all the
characters that were sent. This requires a different type of handshaking
than the XON/XOFF that is supported by most terminals. \fBTack\fR
needs to send a request to the terminal and wait for its reply.
Many terminals will respond with an ACK when they receive an ENQ.
This is the preferred method since the sequence is short.
ANSI/VT-100 style terminals can mimic this handshake with the
escape sequence that requests 'primary device attributes'.
ESC [ c
The terminal will respond with a sequence like:
ESC [ ? 1 ; 0 c
\fBTack\fR assumes that (u9) is the enquire sequence and that (u8) is the
acknowledge string. A VT-100 style terminal could set u9=\\E[c
and u8=\\E[?1;0c.
Acknowledge strings fall into two categories.
1) Strings with a unique terminating character and,
2) strings of fixed length.
The acknowledge string for the VT-100 is of the first type since
it always ends with the letter 'c'. Some Tektronics terminals
have fixed length acknowledge strings. \fBTack\fR supports both
types of strings by scanning for the terminating character until
the length of the expected acknowledge string has arrived.
(u8) should be set to some typical acknowledge that will be
returned when (u9) is sent.
.PP
\fBTack\fR will test this sequence before running any of the pad
tests or the function key tests. \fBTack\fR will ask you the following:
Hit lower case g to start testing...
After it sends this message it will send the enquire string.
It will then read characters from the terminal until it sees the
letter g.
.PP
.SS Testing and Repairing Pad Timings
.PP
The pad timings in distributed terminfo entries are often incorrect. One
major motivation for this program is to make it relatively easy to tune these
timings.
.PP
You can verify and edit the pad timings for a terminal with
the `test string capabilities'
function (this is also part of the `normal test sequence' function).
.PP
The key to determining pad times is to find out the effective baud rate of
the terminal. The effective baud rate determines the number of characters
per second that the terminal can accept without either handshaking or
losing data. This rate is frequently less than the nominal cps rate on the
RS-232 line.
.PP
\fBTack\fR uses the effective baud rate to judge the duration of the test and
how much a particular escape sequence will perturb the terminal.
.PP
Each pad test has two associated variables that can be tweaked to help verify
the correctness of the pad timings. One is the pad test length. The other is
the pad multiplier, which is used if the pad prefix includes `*'. In curses
use, it is often the first parameter of the capability (if there is one).
For a capability like (dch) or (il) this will be the number of character
positions or lines affected, respectively.
.PP
\fBTack\fR will run the pad tests and display the results to the terminal.
On capabilities that have multipliers \fBtack\fR will not tell you
if the pad needs the multiplier or not. You must make this decision
yourself by rerunning the test with a different multiplier.
If the padding changes in proportion to the multiplier than the
multiplier is required. If the multiplier has little or no effect on
the suggested padding then the multiplier is not needed.
Some capabilities will take several runs to get a good feel for
the correct values. You may wish to make the test longer
to get more accurate results. System load will also effect the
results (a heavily loaded system will not stress the
terminal as much, possibly leading to pad timings that are too short).
.PP
.SH NOTE
The tests done at the beginning of the program are assumed to be correct later
in the code. In particular, \fBtack\fR displays the number of lines and
columns indicated in the terminfo entry as part of its initial output.
If these values are wrong a large number of tests will fail or give incorrect
results.
.SH FILES
.TP 12
tack.log
If logging is enabled then all characters written to the terminal
will also be written to the log file. This gives you the ability
to see how the tests were performed. This feature is disabled by default.
.TP 12
.I "term"
If you make changes to the terminfo entry \fBtack\fR will save
the new terminfo to a file. The file will have the same name
as the terminal name.
.SH SEE ALSO
\fBterminfo\fR(\*n), \fBncurses\fR(3X), \fBtic\fR(1M), \fBinfocmp\fR(1M).
You should also have the documentation supplied by the terminal
manufacturer.
.SH BUGS
If the screen size is incorrect, many of the tests will fail.
.SH AUTHOR
Concept, design, and original implementation by
Daniel Weaver <danw@znyx.com>. Portions of the code and
documentation are by Eric S. Raymond <esr@snark.thyrsus.com>.
.\"#
.\"# The following sets edit modes for GNU EMACS
.\"# Local Variables:
.\"# mode:nroff
.\"# fill-column:79
.\"# End:

View File

@ -1,603 +0,0 @@
/*
** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
**
** This file is part of TACK.
**
** TACK 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.
**
** TACK 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 TACK; see the file COPYING. If not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
** Boston, MA 02110-1301, USA
*/
#include <tack.h>
MODULE_ID("$Id: tack.c,v 1.4 2005/09/17 19:49:16 tom Exp $")
/*
This program is designed to test terminfo, not curses. Therefore
I have used as little of curses as possible.
Pads associated with the following capabilities are used to set
delay times in the handler: (cr), (ind), (cub1), (ff), (tab).
I use the (nxon) capability to set the tty handler with/without
xon/xoff. If (smxon)/(rmxon) is defined I will change the terminal
too.
(xon) inhibits the sending of delay characters in putp().
If the terminal is defined with no padding then the (xon) boolean
is a don't care. In this case I recommend that it be reset.
*/
/*****************************************************************************
*
* Option processing
*
*****************************************************************************/
/* options and modes */
int debug_level; /* debugging level */
int translate_mode; /* translate tab, bs, cr, lf, ff */
int scan_mode; /* use scan codes */
int char_mask; /* either 0xFF else 0x7F, eight bit data mask */
int select_delay_type; /* set handler delays for <cr><lf> */
int select_xon_xoff; /* TTY driver XON/XOFF mode select */
int hex_out; /* Display output in hex */
int send_reset_init; /* Send the reset and initialization strings */
FILE *log_fp; /* Terminal logfile */
/*****************************************************************************
*
* Menu definitions
*
*****************************************************************************/
static void tools_hex_echo(struct test_list *, int *, int *);
static void tools_debug(struct test_list *, int *, int *);
static char hex_echo_menu_entry[80];
static struct test_list tools_test_list[] = {
{0, 0, 0, 0, "s) ANSI status reports", tools_status, 0},
{0, 0, 0, 0, "g) ANSI SGR modes (bold, underline, reverse)", tools_sgr, 0},
{0, 0, 0, 0, "c) ANSI character sets", tools_charset, 0},
{0, 0, 0, 0, hex_echo_menu_entry, tools_hex_echo, 0},
{0, 0, 0, 0, "e) echo tool", tools_report, 0},
{1, 0, 0, 0, "r) reply tool", tools_report, 0},
{0, 0, 0, 0, "p) performance testing", 0, &sync_menu},
{0, 0, 0, 0, "i) send reset and init", menu_reset_init, 0},
{0, 0, "u8) (u9", 0, "u) test ENQ/ACK handshake", sync_handshake, 0},
{0, 0, 0, 0, "d) change debug level", tools_debug, 0},
{MENU_LAST, 0, 0, 0, 0, 0, 0}
};
static struct test_menu tools_menu = {
0, 'q', 0, "Tools Menu", "tools",
0, 0, tools_test_list, 0, 0, 0
};
static void tty_width(struct test_list *, int *, int *);
static void tty_delay(struct test_list *, int *, int *);
static void tty_xon(struct test_list *, int *, int *);
static void tty_trans(struct test_list *, int *, int *);
static void tty_show_state(struct test_menu *);
static char tty_width_menu[80];
static char tty_delay_menu[80];
static char tty_xon_menu[80];
static char tty_trans_menu[80];
static char enable_xon_xoff[] = {"x) enable xon/xoff"};
static char disable_xon_xoff[] = {"x) disable xon/xoff"};
static struct test_list tty_test_list[] = {
{0, 0, 0, 0, tty_width_menu, tty_width, 0},
{0, 0, 0, 0, tty_delay_menu, tty_delay, 0},
{0, 0, 0, 0, tty_xon_menu, tty_xon, 0},
{0, 0, 0, 0, tty_trans_menu, tty_trans, 0},
{MENU_LAST, 0, 0, 0, 0, 0, 0}
};
static struct test_menu tty_menu = {
0, 'q', 0, "Terminal and driver configuration",
"tty", 0,
tty_show_state, tty_test_list, 0, 0, 0
};
struct test_menu edit_menu = {
0, 'q', 0, "Edit terminfo menu",
"edit", 0,
0, edit_test_list, 0, 0, 0
};
static struct test_menu mode_menu = {
0, 'n', 0, "Test modes and glitches:",
"mode", "n) run standard tests",
0, mode_test_list, 0, 0, 0
};
static struct test_menu acs_menu = {
0, 'n', 0,
"Test alternate character set and graphics rendition:",
"acs", "n) run standard tests",
0, acs_test_list, 0, 0, 0
};
static struct test_menu color_menu = {
0, 'n', 0,
"Test color:",
"color", "n) run standard tests",
0, color_test_list, 0, 0, 0
};
static struct test_menu crum_menu = {
0, 'n', 0,
"Test cursor movement:",
"move", "n) run standard tests",
0, crum_test_list, 0, 0, 0
};
static struct test_menu funkey_menu = {
0, 'n', 0,
"Test function keys:",
"fkey", "n) run standard tests",
sync_test, funkey_test_list, 0, 0, 0
};
static struct test_menu printer_menu = {
0, 'n', 0,
"Test printer:",
"printer", "n) run standard tests",
0, printer_test_list, 0, 0, 0
};
static void pad_gen(struct test_list *, int *, int *);
static struct test_menu pad_menu = {
0, 'n', 0,
"Test padding and string capabilities:",
"pad", "n) run standard tests",
sync_test, pad_test_list, 0, 0, 0
};
static struct test_list normal_test_list[] = {
{0, 0, 0, 0, "e) edit terminfo", 0, &edit_menu},
{0, 0, 0, 0, "i) send reset and init", menu_reset_init, 0},
{MENU_NEXT, 0, 0, 0, "x) test modes and glitches", 0, &mode_menu},
{MENU_NEXT, 0, 0, 0, "a) test alternate character set and graphic rendition", 0, &acs_menu},
{MENU_NEXT, 0, 0, 0, "c) test color", 0, &color_menu},
{MENU_NEXT, 0, 0, 0, "m) test cursor movement", 0, &crum_menu},
{MENU_NEXT, 0, 0, 0, "f) test function keys", 0, &funkey_menu},
{MENU_NEXT, 0, 0, 0, "p) test padding and string capabilities", 0, &pad_menu},
{0, 0, 0, 0, "P) test printer", 0, &printer_menu},
{MENU_MENU, 0, 0, 0, "/) test a specific capability", 0, 0},
{0, 0, 0, 0, "t) auto generate pad delays", pad_gen, &pad_menu},
{0, 0, "u8) (u9", 0, 0, sync_handshake, 0},
{MENU_LAST, 0, 0, 0, 0, 0, 0}
};
static struct test_menu normal_menu = {
0, 'n', 0, "Main test menu",
"test", "n) run standard tests",
0, normal_test_list, 0, 0, 0
};
static void start_tools(struct test_list *, int *, int *);
static void start_modes(struct test_list *, int *, int *);
static void start_basic(struct test_list *, int *, int *);
static void start_log(struct test_list *, int *, int *);
static char logging_menu_entry[80] = "l) start logging";
static struct test_list start_test_list[] = {
{0, 0, 0, 0, "b) display basic information", start_basic, 0},
{0, 0, 0, 0, "m) change modes", start_modes, 0},
{0, 0, 0, 0, "t) tools", start_tools, 0},
{MENU_COMPLETE, 0, 0, 0, "n) begin testing", 0, &normal_menu},
{0, 0, 0, 0, logging_menu_entry, start_log, 0},
{MENU_LAST, 0, 0, 0, 0, 0, 0}
};
static struct test_menu start_menu = {
0, 'n', 0, "Main Menu", "tack", 0,
0, start_test_list, 0, 0, 0
};
static struct test_list write_terminfo_list[] = {
{0, 0, 0, 0, "w) write the current terminfo to a file", save_info, 0},
{MENU_LAST, 0, 0, 0, 0, 0, 0}
};
/*****************************************************************************
*
* Menu command interpretation.
*
*****************************************************************************/
/*
** tools_hex_echo(testlist, state, ch)
**
** Flip the hex echo flag.
*/
static void
tools_hex_echo(
struct test_list *t GCC_UNUSED,
int *state GCC_UNUSED,
int *ch GCC_UNUSED)
{
if (hex_out) {
hex_out = FALSE;
strcpy(hex_echo_menu_entry,
"h) enable hex output on echo tool");
} else {
hex_out = TRUE;
strcpy(hex_echo_menu_entry,
"h) disable hex output on echo tool");
}
}
/*
** tools_debug(testlist, state, ch)
**
** Change the debug level.
*/
static void
tools_debug(
struct test_list *t GCC_UNUSED,
int *state GCC_UNUSED,
int *ch)
{
char buf[32];
ptext("Enter a new value: ");
read_string(buf, sizeof(buf));
if (buf[0]) {
sscanf(buf, "%d", &debug_level);
}
sprintf(temp, "Debug level is now %d", debug_level);
ptext(temp);
*ch = REQUEST_PROMPT;
}
/*
** start_tools(testlist, state, ch)
**
** Run the generic test tools
*/
static void
start_tools(
struct test_list *t GCC_UNUSED,
int *state GCC_UNUSED,
int *ch GCC_UNUSED)
{
if (hex_out) {
strcpy(hex_echo_menu_entry,
"h) disable hex output on echo tool");
} else {
strcpy(hex_echo_menu_entry,
"h) enable hex output on echo tool");
}
menu_display(&tools_menu, 0);
}
/*
** tty_show_state()
**
** Display the current state on the tty driver settings
*/
static void
tty_show_state(
struct test_menu *menu GCC_UNUSED)
{
put_crlf();
(void) sprintf(temp,
"Accepting %d bits, UNIX delays %d, XON/XOFF %sabled, speed %u, translate %s, scan-code mode %s.",
(char_mask == ALLOW_PARITY) ? 8 : 7,
select_delay_type,
select_xon_xoff ? "en" : "dis",
tty_baud_rate,
translate_mode ? "on" : "off",
scan_mode ? "on" : "off");
ptextln(temp);
put_crlf();
}
/*
** tty_width(testlist, state, ch)
**
** Change the character width
*/
static void
tty_width(
struct test_list *t GCC_UNUSED,
int *state GCC_UNUSED,
int *ch GCC_UNUSED)
{
if (char_mask == STRIP_PARITY) {
char_mask = ALLOW_PARITY;
strcpy(tty_width_menu, "7) treat terminal as 7-bit");
} else {
char_mask = STRIP_PARITY;
strcpy(tty_width_menu, "8) treat terminal as 8-bit");
}
}
/*
** tty_delay(testlist, state, ch)
**
** Change the delay for <cr><lf> in the TTY driver
*/
static void
tty_delay(
struct test_list *t GCC_UNUSED,
int *state GCC_UNUSED,
int *ch GCC_UNUSED)
{
if (select_delay_type) {
select_delay_type = FALSE;
strcpy(tty_delay_menu,
"d) enable UNIX tty driver delays for <cr><lf>");
} else {
select_delay_type = TRUE;
strcpy(tty_delay_menu,
"d) disable UNIX tty driver delays for <cr><lf>");
}
}
/*
** tty_xon(testlist, state, ch)
**
** Change the XON/XOFF flags in the TTY driver
*/
static void
tty_xon(
struct test_list *t GCC_UNUSED,
int *state GCC_UNUSED,
int *ch GCC_UNUSED)
{
if (select_xon_xoff) {
if (needs_xon_xoff) {
ptextln("This terminal is marked as needing XON/XOFF protocol with (nxon)");
}
if (exit_xon_mode) {
tc_putp(exit_xon_mode);
}
xon_xoff = select_xon_xoff = FALSE;
strcpy(tty_xon_menu, enable_xon_xoff);
} else {
if (enter_xon_mode) {
tc_putp(enter_xon_mode);
}
xon_xoff = select_xon_xoff = TRUE;
strcpy(tty_xon_menu, disable_xon_xoff);
}
tty_set();
}
/*
** tty_trans(testlist, state, ch)
**
** Change the translation mode for special characters
*/
static void
tty_trans(
struct test_list *t GCC_UNUSED,
int *state GCC_UNUSED,
int *ch GCC_UNUSED)
{
if (translate_mode) {
translate_mode = FALSE;
strcpy(tty_trans_menu,
"t) use terminfo values for \\b\\f\\n\\r\\t");
} else {
translate_mode = TRUE;
strcpy(tty_trans_menu,
"t) override terminfo values for \\b\\f\\n\\r\\t");
}
}
/*
** pad_gen(testlist, state, ch)
**
** Menu function for automatic pad generation
*/
static void
pad_gen(
struct test_list *t,
int *state GCC_UNUSED,
int *ch)
{
control_init();
if (tty_can_sync == SYNC_NOT_TESTED) {
verify_time();
}
auto_pad_mode = TRUE;
menu_display(t->sub_menu, ch);
auto_pad_mode = FALSE;
}
/*
** start_modes(testlist, state, ch)
**
** Change the TTY modes
*/
static void
start_modes(
struct test_list *t GCC_UNUSED,
int *state GCC_UNUSED,
int *ch GCC_UNUSED)
{
if (select_delay_type) {
strcpy(tty_delay_menu,
"d) disable UNIX tty driver delays for <cr><lf>");
} else {
strcpy(tty_delay_menu,
"d) enable UNIX tty driver delays for <cr><lf>");
}
if (char_mask == ALLOW_PARITY) {
strcpy(tty_width_menu,
"7) treat terminal as 7-bit");
} else {
strcpy(tty_width_menu,
"8) treat terminal as 8-bit");
}
if (select_xon_xoff) {
strcpy(tty_xon_menu, disable_xon_xoff);
} else {
strcpy(tty_xon_menu, enable_xon_xoff);
}
if (translate_mode) {
strcpy(tty_trans_menu,
"t) override terminfo values for \\b\\f\\n\\r\\t");
} else {
strcpy(tty_trans_menu,
"t) use terminfo values for \\b\\f\\n\\r\\t");
}
menu_display(&tty_menu, 0);
tty_set();
}
/*
** start_basic(testlist, state, ch)
**
** Display basic terminal information
*/
static void
start_basic(
struct test_list *t GCC_UNUSED,
int *state GCC_UNUSED,
int *ch)
{
display_basic();
*ch = REQUEST_PROMPT;
}
/*
** start_log(testlist, state, ch)
**
** Start/stop in logging function
*/
static void
start_log(
struct test_list *t GCC_UNUSED,
int *state GCC_UNUSED,
int *ch GCC_UNUSED)
{
if (logging_menu_entry[5] == 'a') {
ptextln("The log file will capture all characters sent to the terminal.");
if ((log_fp = fopen("tack.log", "w"))) {
ptextln("Start logging to file: tack.log");
strcpy(logging_menu_entry, "l) stop logging");
} else {
ptextln("File open error: tack.log");
}
} else {
if (log_fp) {
fclose(log_fp);
log_fp = 0;
}
ptextln("Terminal output logging stopped.");
strcpy(logging_menu_entry, "l) start logging");
}
}
/*
** show_usage()
**
** Tell the user how its done.
*/
void
show_usage(
char *name)
{
(void) fprintf(stderr, "usage: %s [-itV] [term]\n", name);
}
/*
** print_version()
**
** Print version and other useful information.
*/
void
print_version(void)
{
printf("tack version %d.%02d\n", MAJOR_VERSION, MINOR_VERSION);
printf("Copyright (C) 1997 Free Software Foundation, Inc.\n");
printf("Tack comes with NO WARRANTY, to the extent permitted by law.\n");
printf("You may redistribute copies of Tack under the terms of the\n");
printf("GNU General Public License. For more information about\n");
printf("these matters, see the file named COPYING.\n");
}
/*****************************************************************************
*
* Main sequence
*
*****************************************************************************/
int
main(int argc, char *argv[])
{
int i, j;
char *term_variable;
/* scan the option flags */
send_reset_init = TRUE;
translate_mode = FALSE;
term_variable = getenv("TERM");
tty_can_sync = SYNC_NOT_TESTED;
for (i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
for (j = 1; argv[i][j]; j++) {
switch (argv[i][j]) {
case 'V':
print_version();
return (1);
case 'i':
send_reset_init = FALSE;
break;
case 't':
translate_mode = FALSE;
break;
default:
show_usage(argv[0]);
return (0);
}
}
} else {
term_variable = argv[i];
}
}
(void) strcpy(tty_basename, term_variable);
curses_setup(argv[0]);
menu_can_scan(&normal_menu); /* extract which caps can be tested */
menu_display(&start_menu, 0);
if (user_modified()) {
sprintf(temp, "Hit y to save changes to file: %s ? ",
tty_basename);
ptext(temp);
if (wait_here() == 'y') {
save_info(write_terminfo_list, &i, &j);
}
}
put_str("\nTerminal test complete\n");
bye_kids(0);
return (0);
}

View File

@ -1,428 +0,0 @@
/*
** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
**
** This file is part of TACK.
**
** TACK 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.
**
** TACK 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 TACK; see the file COPYING. If not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
** Boston, MA 02110-1301, USA
*/
/* $Id: tack.h,v 1.16 2006/11/25 23:45:00 tom Exp $ */
#ifndef NCURSES_TACK_H_incl
#define NCURSES_TACK_H_incl 1
/* terminfo action checker include file */
#define MAJOR_VERSION 1
#define MINOR_VERSION 1
#ifdef HAVE_CONFIG_H
#include <ncurses_cfg.h>
#else
#define RETSIGTYPE void
#define GCC_UNUSED /*nothing*/
#define HAVE_GETTIMEOFDAY 1
#define HAVE_SELECT 1
#define HAVE_SYS_TIME_H 1
#define HAVE_SYS_TIME_SELECT 1
#endif
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <curses.h>
#include <term_entry.h>
#include <nc_tparm.h>
#if USE_RCS_IDS
#define MODULE_ID(id) static const char Ident[] = id;
#else
#define MODULE_ID(id) /*nothing*/
#endif
#if !HAVE_STRSTR
extern char *_nc_strstr(const char *, const char *);
#define strstr(h,n) _nc_strstr(h,n)
#endif
#define CUR_TP (&(cur_term->type))
#define MAX_STRINGS NUM_STRINGS(CUR_TP)
#define STR_NAME(n) ExtStrname(CUR_TP,n,strnames)
#define UChar(c) ((unsigned char)(c))
extern FILE *log_fp;
extern FILE *debug_fp;
extern int debug_level;
extern char temp[];
extern char tty_basename[];
extern char tty_shortname[];
#define SYNC_FAILED 0
#define SYNC_TESTED 1
#define SYNC_NOT_TESTED 2
#define SYNC_NEEDED 3
extern int tty_can_sync;
extern int total_pads_sent; /* count pad characters sent */
extern int total_caps_sent; /* count caps sent */
extern int total_printing_characters; /* count printing characters sent */
extern int no_alarm_event; /* TRUE if the alarm has not gone off yet */
extern unsigned long usec_run_time; /* length of last test in microseconds */
extern int raw_characters_sent; /* Total output characters */
/* Stopwatch event timers */
#define TIME_TEST 0
#define TIME_SYNC 1
#define TIME_FLUSH 2
#define MAX_TIMERS 3
/* definitions for pad.c */
#define EXIT_CONDITION (no_alarm_event && (tt_delay_used < tt_delay_max))
#define SLOW_TERMINAL_EXIT if (!test_complete && !EXIT_CONDITION) { break; }
#define CAP_NOT_FOUND if (auto_pad_mode) return
extern char letters[26+1];
#define NEXT_LETTER letter = letters[letter_number =\
letters[letter_number + 1] ? letter_number + 1 : 0]
extern int test_complete; /* counts number of tests completed */
extern char letter;
extern int letter_number;
extern int augment, repeats;
extern long char_sent;
extern const char *pad_repeat_test; /* commands that force repeat */
extern int replace_mode;
extern int char_count, line_count, expand_chars;
extern int can_go_home, can_clear_screen;
extern int translate_mode, scan_mode;
extern int auto_pad_mode; /* TRUE for auto time tests */
extern int char_mask;
extern int hex_out; /* Display output in hex */
/* Parity bit macros */
#define STRIP_PARITY 0x7f
#define ALLOW_PARITY 0xff
/* select_delay_type: 0 -> reset all delays
1 -> force long delays
2 -> do not change the delays */
extern int select_delay_type;
/* select_xon_xoff: 0 -> reset xon/xoff
1 -> set xon/xoff
2 -> do not change xon/xoff */
extern int select_xon_xoff;
extern int tty_frame_size;
extern unsigned tty_baud_rate;
extern unsigned long tty_cps; /* The number of characters per second */
extern int not_a_tty, nodelay_read;
extern int send_reset_init;
/* definitions for stty_query() and initial_stty_query() */
#define TTY_CHAR_MODE 0
#define TTY_NOECHO 1
#define TTY_OUT_TRANS 2
#define TTY_8_BIT 3
#define TTY_XON_XOFF 4
/* scan code definitions */
#define MAX_SCAN 256
/* translate mode default strings */
struct default_string_list {
const char *name; /* terminfo name */
const char *value; /* value of default string */
int index; /* index into the strfname[] array */
};
#define TM_last 8
extern struct default_string_list TM_string[TM_last];
/* attribute structure definition */
struct mode_list {
const char *name;
const char *begin_mode;
const char *end_mode;
int number;
};
extern const struct mode_list alt_modes[];
extern const int mode_map[];
/* Test data base */
#define FLAG_CAN_TEST 1
#define FLAG_TESTED 2
#define FLAG_LABEL 4
#define FLAG_FUNCTION_KEY 8
/* caps under test data base */
#define TT_MAX 8
#define MAX_CHANGES (TT_MAX+2)
extern int tt_delay_max; /* max number of milliseconds we can delay */
extern int tt_delay_used; /* number of milliseconds consumed in delay */
extern const char *tt_cap[TT_MAX]; /* value of string */
extern int tt_affected[TT_MAX]; /* lines or columns effected (repetition
factor) */
extern int tt_count[TT_MAX]; /* Number of times sent */
extern int tt_delay[TT_MAX]; /* Number of milliseconds delay */
extern int ttp; /* number of entries used */
extern const char *tx_cap[TT_MAX]; /* value of string */
extern int tx_affected[TT_MAX]; /* lines or columns effected (repetition
factor) */
extern int tx_count[TT_MAX]; /* Number of times sent */
extern int tx_delay[TT_MAX]; /* Number of milliseconds delay */
extern int tx_index[TT_MAX]; /* String index */
extern int txp; /* number of entries used */
extern int tx_characters; /* printing characters sent by test */
extern unsigned long tx_cps; /* characters per second */
/*
Menu control for tack.
*/
struct test_results {
struct test_results *next; /* point to next entry */
struct test_list *test; /* Test which got these results */
int reps; /* repeat count */
int delay; /* delay times 10 */
};
struct test_list {
int flags; /* Test description flags */
int lines_needed; /* Lines needed for test (0->no action) */
const char *caps_done; /* Caps shown in Done message */
const char *caps_tested; /* Other caps also being tested */
const char *menu_entry; /* Menu entry text (optional) */
/* Function that does testing */
void (*test_procedure)(struct test_list *, int *, int *);
struct test_menu *sub_menu; /* Nested sub-menu */
};
struct test_menu {
int flags; /* Menu feature flag */
int default_action; /* Default command if <cr> <lf> entered */
const char *menu_text; /* Describe this test_menu */
const char *menu_title; /* Title for the menu */
const char *ident; /* short menu name */
const char *standard_tests; /* Standard test text */
/* print current settings (optional) */
void (*menu_function)(struct test_menu *);
struct test_list *tests; /* Pointer to the menu/function pairs */
struct test_list *resume_tests; /* Standard test resume point */
int resume_state; /* resume state of test group */
int resume_char; /* resume ch of test group */
};
/* menu flags */
#define MENU_100c 0x00001a00 /* Augment 100% of columns */
#define MENU_90c 0x00001900 /* Augment 90% of columns */
#define MENU_80c 0x00001800 /* Augment 80% of columns */
#define MENU_70c 0x00001700 /* Augment 70% of columns */
#define MENU_60c 0x00001600 /* Augment 60% of columns */
#define MENU_50c 0x00001500 /* Augment 50% of columns */
#define MENU_40c 0x00001400 /* Augment 40% of columns */
#define MENU_30c 0x00001300 /* Augment 30% of columns */
#define MENU_20c 0x00001200 /* Augment 20% of columns */
#define MENU_10c 0x00001100 /* Augment 10% of columns */
#define MENU_LM1 0x00002e00 /* Augment lines - 1 */
#define MENU_100l 0x00002a00 /* Augment 100% of lines */
#define MENU_90l 0x00002900 /* Augment 90% of lines */
#define MENU_50l 0x00002500 /* Augment 50% of lines */
#define MENU_lines 0x00002000 /* Augment of lines */
#define MENU_columns 0x00001000 /* Augment of columns */
#define MENU_LC_MASK 0x00003000 /* Augment mask for lines and columns */
#define MENU_1L 0x00002f00 /* Augment == one */
#define MENU_1C 0x00001f00 /* Augment == one */
#define MENU_ONE 0x00000f00 /* Augment == one */
#define MENU_ONE_MASK 0x00000f00 /* Augment == one mask */
#define MENU_REP_MASK 0x00003f00 /* Augment mask */
#define MENU_CLEAR 0x00010000 /* clear screen */
#define MENU_INIT 0x00020000 /* Initialization function */
#define MENU_NEXT 0x00040000 /* Next test in sequence */
#define MENU_LAST 0x00080000 /* End of menu list */
#define MENU_STOP 0x00100000 /* Stop testing next-in-sequence */
#define MENU_COMPLETE 0x00200000 /* Test complete after this */
#define MENU_MENU 0x00400000 /* Pass the menu name not test name */
#define REQUEST_PROMPT 256
/* tack.c */
extern struct test_menu edit_menu;
extern void show_usage(char *);
extern void print_version(void);
/* output.c */
extern char *expand(const char *);
extern char *expand_command(const char *);
extern char *expand_to(char *, int);
extern char *hex_expand_to(char *, int);
extern char *print_expand(char *);
extern int getchp(int);
extern int getnext(int);
extern int tc_putch(int);
extern int tc_putp(const char *);
extern int wait_here(void);
extern void go_home(void);
extern void home_down(void);
extern void maybe_wait(int);
extern void ptext(const char *);
extern void ptextln(const char *);
extern void put_clear(void);
extern void put_columns(const char *, int, int);
extern void put_cr(void);
extern void put_crlf(void);
extern void put_dec(char *, int);
extern void put_ind(void);
extern void put_lf(void);
extern void put_newlines(int);
extern void put_str(const char *);
extern void put_this(int);
extern void putchp(int);
extern void putln(const char *);
extern void read_string(char *, int);
extern void three_digit(char *, int);
extern void tt_putp(const char *);
extern void tt_putparm(NCURSES_CONST char *, int, int, int);
extern void tt_tputs(const char *, int);
#define put_that(n) put_this((int) (n))
/* control.c */
extern struct test_list color_test_list[];
extern char *liberated(char *);
extern char txt_longer_augment[80];
extern char txt_longer_test_time[80];
extern char txt_shorter_augment[80];
extern char txt_shorter_test_time[80];
extern int msec_cost(const char *const, int);
extern int skip_pad_test(struct test_list *, int *, int *, const char *);
extern int sliding_scale(int, int, unsigned long);
extern int still_testing(void);
extern long event_time(int);
extern void control_init(void);
extern void dump_test_stats(struct test_list *, int *, int *);
extern void event_start(int);
extern void longer_augment(struct test_list *, int *, int *);
extern void longer_test_time(struct test_list *, int *, int *);
extern void pad_test_shutdown(struct test_list *, int);
extern void pad_test_startup(int);
extern void page_loop(void);
extern void set_augment_txt(void);
extern void shorter_augment(struct test_list *, int *, int *);
extern void shorter_test_time(struct test_list *, int *, int *);
/* charset.c */
extern struct test_list acs_test_list[];
extern void set_attr(int);
extern void eat_cookie(void);
extern void put_mode(char *);
/* crum.c */
extern struct test_list crum_test_list[];
/* ansi.c */
extern void tools_status(struct test_list *, int *, int *);
extern void tools_charset(struct test_list *, int *, int *);
extern void tools_sgr(struct test_list *, int *, int *);
/* edit.c */
extern struct test_menu change_pad_menu;
extern struct test_list edit_test_list[];
extern char *get_string_cap_byname(const char *, const char **);
extern int cap_match(const char *names, const char *cap);
extern int get_string_cap_byvalue(const char *);
extern int user_modified(void);
extern void can_test(const char *, int);
extern void cap_index(const char *, int *);
extern void edit_init(void);
extern void save_info(struct test_list *, int *, int *);
extern void show_report(struct test_list *, int *, int *);
/* fun.c */
extern struct test_list funkey_test_list[];
extern struct test_list printer_test_list[];
extern void enter_key(const char *, char *, char *);
extern int tty_meta_prep(void);
extern void tools_report(struct test_list *, int *, int *);
/* init.c */
extern void reset_init(void);
extern void display_basic(void);
extern void put_name(const char *, const char *);
extern void charset_can_test(void);
extern void curses_setup(char *);
extern void bye_kids(int);
/* scan.c */
extern char **scan_up, **scan_down, **scan_name;
extern int scan_key(void);
extern unsigned scan_max; /* length of longest scan code */
extern unsigned *scan_tested, *scan_length;
extern void scan_init(char *fn);
/* sysdep.c */
extern int initial_stty_query(int);
extern int stty_query(int);
extern void ignoresig(void);
extern void read_key(char *, int);
extern void set_alarm_clock(int);
extern void spin_flush(void);
extern void tty_init(void);
extern void tty_raw(int, int);
extern void tty_reset(void);
extern void tty_set(void);
/* menu.c */
extern char prompt_string[80]; /* menu prompt storage */
extern int subtest_menu(struct test_list *, int *, int *);
extern struct test_list *augment_test;
extern void generic_done_message(struct test_list *, int *, int *);
extern void menu_can_scan(const struct test_menu *);
extern void menu_clear_screen(struct test_list *, int *, int *);
extern void menu_display(struct test_menu *, int *);
extern void menu_prompt(void);
extern void menu_reset_init(struct test_list *, int *, int *);
extern void pad_done_message(struct test_list *, int *, int *);
/* modes.c */
extern struct test_list mode_test_list[];
/* pad.c */
extern struct test_list pad_test_list[];
/* sync.c */
extern struct test_menu sync_menu;
extern int tty_sync_error(void);
extern void flush_input(void);
extern void sync_handshake(struct test_list *, int *, int *);
extern void sync_test(struct test_menu *);
extern void verify_time(void);
#endif /* NCURSES_TACK_H_incl */