#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  vttest vttest/esc.c vttest/header.h vttest/main.c
#   vttest/read.me vttest/vttest.1
# Wrapped by mildram@atlas on Sun Jan 24 17:36:30 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test ! -d vttest ; then
    echo shar: Creating directory \"vttest\"
    mkdir vttest
fi
if test -f vttest/esc.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"vttest/esc.c\"
else
echo shar: Extracting \"vttest/esc.c\" \(7946 characters\)
sed "s/^X//" >vttest/esc.c <<'END_OF_vttest/esc.c'
X#include "header.h"
X
Xprintln(s) char *s; {
X  printf("%s\n", s);
X}
X
Xesc(s) char *s; {
X  printf("%c%s", 27, s);
X}
X
Xesc2(s1, s2) char s1, s2; {
X  printf("%c%s%s", 27, s1, s2);
X}
X
Xbrcstr(ps, c) char *ps, c; {
X  printf("%c[%s%c", 27, ps, c);
X}
X
Xbrc(pn,c) int pn; char c; {
X  printf("%c[%d%c", 27, pn, c);
X}
X
Xbrc2(pn1, pn2 ,c) int pn1, pn2; char c; {
X  printf("%c[%d;%d%c", 27, pn1, pn2, c);
X}
X
Xcub(pn) int pn; {  /* Cursor Backward */
X  brc(pn,'D');
X}
Xcud(pn) int pn; {  /* Cursor Down */
X  brc(pn,'B');
X}
Xcuf(pn) int pn; {  /* Cursor Forward */
X  brc(pn,'C');
X}
Xcup(pn1, pn2) int pn1, pn2; {  /* Cursor Position */
X  brc2(pn1, pn2, 'H');
X}
Xcuu(pn) int pn; {  /* Cursor Up */
X  brc(pn,'A');
X}
Xda() {	/* Device Attributes */
X  brc(0,'c');
X}
Xdecaln() {	/* Screen Alignment Display */
X  esc("#8");
X}
Xdecdhl(lower) int lower; {	/* Double Height Line (also double width) */
X  if (lower) esc("#4");
X  else		 esc("#3");
X}
Xdecdwl() {	/* Double Wide Line */
X  esc("#6");
X}
Xdeckpam() {  /* Keypad Application Mode */
X  esc("=");
X}
Xdeckpnm() {  /* Keypad Numeric Mode */
X  esc(">");
X}
Xdecll(ps) char *ps; {  /* Load LEDs */
X  brcstr(ps, 'q');
X}
Xdecrc() {  /* Restore Cursor */
X  esc("8");
X}
Xdecreqtparm(pn) int pn; {  /* Request Terminal Parameters */
X  brc(pn,'x');
X}
Xdecsc() {  /* Save Cursor */
X  esc("7");
X}
Xdecstbm(pn1, pn2) int pn1, pn2; {  /* Set Top and Bottom Margins */
X  if (pn1 || pn2) brc2(pn1, pn2, 'r');
X  else		  esc("[r");
X  /* Good for >24-line terminals */
X}
Xdecswl() {	/* Single With Line */
X  esc("#5");
X}
Xdectst(pn) int pn; {  /* Invoke Confidence Test */
X  brc2(2, pn, 'y');
X}
Xdsr(pn) int pn; {  /* Device Status Report */
X  brc(pn, 'n');
X}
Xed(pn) int pn; {  /* Erase in Display */
X  brc(pn, 'J');
X}
Xel(pn) int pn; {  /* Erase in Line */
X  brc(pn,'K');
X}
Xhts() {  /* Horizontal Tabulation Set */
X  esc("H");
X}
Xhvp(pn1, pn2) int pn1, pn2; {  /* Horizontal and Vertical Position */
X  brc2(pn1, pn2, 'f');
X}
Xind() {  /* Index */
X  esc("D");
X}
Xnel() {  /* Next Line */
X  esc("E");
X}
Xri() {	/* Reverse Index */
X  esc("M");
X}
Xris() { /*	Reset to Initial State */
X  esc("c");
X}
Xrm(ps) char *ps; {	/* Reset Mode */
X  brcstr(ps, 'l');
X}
Xscs(g,c) int g; char c; {  /* Select character Set */
X  printf("%c%c%c%c%c%c%c", 27, g ? ')' : '(', c,
X			   27, g ? '(' : ')', 'B',
X			 g ? 14 : 15);
X}
Xsgr(ps) char *ps; {  /* Select Graphic Rendition */
X  brcstr(ps, 'm');
X}
Xsm(ps) char *ps; {	/* Set Mode */
X  brcstr(ps, 'h');
X}
Xtbc(pn) int pn; {  /* Tabulation Clear */
X  brc(pn, 'g');
X}
X
Xvt52cup(l,c) int l,c; {
X  printf("%cY%c%c", 27, l + 31, c + 31);
X}
X
Xchar inchar() {
X
X  /*
X   *   Wait until a character is typed on the terminal
X   *   then read it, without waiting for CR.
X   */
X
X#ifdef UNIX
X  int lval, waittime, getpid(); static int val; char ch;
X
X  fflush(stdout);
X  lval = val;
X  brkrd = 0;
X  reading = 1;
X  read(0,&ch,1);
X  reading = 0;
X  if (brkrd)
X	val = 0177;
X  else
X	val = ch;
X  if ((val==0177) && (val==lval))
X	kill(getpid(), (int) SIGTERM);
X#endif
X#ifdef SARG10
X  int val, waittime;
X
X  waittime = 0;
X  while(!uuo(051,2,&val)) { 	  /* TTCALL 2, (INCHRS)   */
X	zleep(100); 			  /* Wait 0.1 seconds */
X	if ((waittime += ttymode) > 600)  /* Time-out, in case	  */
X  return('\177');                 /* of hung in ttybin(1) */
X  }
X#endif
X#ifdef SARG20 /* try to fix a time-out function */
X  int val, waittime;
X
X  waittime = 0;
X  while(jsys(SIBE,2,_PRIIN) == 0) {   /* Is input empty? */
X	zleep(100);
X	if ((waittime += ttymode) > 600)
X  return('\177');
X  }
X  ejsys(BIN,_PRIIN);
X  val = jsac[2];
X#endif
X  return(val);
X}
X
Xchar *instr() {
X
X  /*
X   *   Get an unfinished string from the terminal:
X   *   wait until a character is typed on the terminal,
X   *   then read it, and all other available characters.
X   *   Return a pointer to that string.
X   */
X
X
X  int i, val, crflag; long l1; char ch;
X  static char result[80];
X
X  i = 0;
X  result[i++] = inchar();
X/* Wait 0.1 seconds (1 second in vanilla UNIX) */
X#ifdef SARG10
X  if (trmop(01031,0) < 5) zleep(500); /* wait longer if low speed */
X  else			  zleep(100);
X#else
X  zleep(100);
X#endif
X#ifdef UNIX
X  fflush(stdout);
X#ifdef XENIX
X  while(rdchk(0)) {
X	read(0,result+i,1);
X	if (i++ == 78) break;
X  }
X#else
X#ifdef SIII
X  while(read(2,result+i,1) == 1)
X	if (i++ == 78) break;
X#else
X  while(ioctl(0,FIONREAD,&l1), l1 > 0L) {
X	while(l1-- > 0L) {
X  read(0,result+i,1);
X  if (i++ == 78) goto out1;
X	}
X  }
Xout1:
X#endif
X#endif
X#endif
X#ifdef SARG10
X  while(uuo(051,2,&val)) {	  /* TTCALL 2, (INCHRS)  */
X	if (!(val == '\012' && crflag))   /* TOPS-10 adds LF to CR */
X  result[i++] = val;
X	crflag = val == '\015';
X	if (i == 79) break;
X	zleep(50);		/* Wait 0.05 seconds */
X  }
X#endif
X#ifdef SARG20
X  while(jsys(SIBE,2,_PRIIN) != 0) {   /* read input until buffer is empty */
X	ejsys(BIN,_PRIIN);
X	result[i++] = jsac[2];
X	if (i == 79) break;
X	zleep(50);		  /* Wait 0.05 seconds */
X  }
X#endif
X  result[i] = '\0';
X  return(result);
X}
X
Xttybin(bin) int bin; {
X#ifdef SARG10
X  #define OPEN 050
X  #define IO_MOD 0000017
X  #define _IOPIM 2
X  #define _IOASC 0
X  #define _TOPAG 01021
X  #define _TOSET 01000
X
X  int v;
X  static int arglst[] = {
X	_IOPIM,
X	`TTY`,
X	0
X  };
X  arglst[0] = bin ? _IOPIM : _IOASC;
X  v = uuo(OPEN, 1, &arglst[0]);
X  if (!v) { printf("OPEN failed"); exit(); }
X  trmop(_TOPAG + _TOSET, bin ? 0 : 1);
X  ttymode = bin;
X#endif
X#ifdef SARG20
X  /*  TTYBIN will set the line in BINARY/ASCII mode
X   *  BINARY mode is needed to send control characters
X   *  Bit 28 must be 0 (we don't flip it).
X   *  Bit 29 is used for the mode change.
X   */
X
X  #define _TTASC 0000100
X  #define _MOXOF 0000043
X
X  int v;
X
X  ejsys(RFMOD,_CTTRM);
X  v = ejsys(SFMOD,_CTTRM, bin ? (~_TTASC & jsac[2]) : (_TTASC | jsac[2]));
X  if (v) { printf("SFMOD failed"); exit(); }
X  v = ejsys(MTOPR,_CTTRM,_MOXOF,0);
X  if (v) { printf("MTOPR failed"); exit(); }
X#endif
X}
X
X#ifdef SARG20
X/*
X *	  SUPERBIN turns off/on all input character interrupts
X *	  This affects ^C, ^O, ^T
X *	  Beware where and how you use it !!!!!!!
X */
X
Xsuperbin(bin) int bin; {
X  int v;
X
X  v = ejsys(STIW,(0//-5), bin ? 0 : -1);
X  if (v) { printf("STIW superbinary setting failed"); exit(); }
X  ttymode = bin;
X}
X
X/*
X *	  PAGE affects the ^S/^Q handshake.
X *	  Set bit 34 to turn it on. Clear it for off.
X */
X
Xpage(bin) int bin; {
X  int v;
X
X  #define TT_PGM 0000002
X
X  ejsys(RFMOD,_CTTRM);	  /* Get the current terminal status */
X  v = ejsys(STPAR,_CTTRM, bin ? (TT_PGM | jsac[2]) : (~TT_PGM & jsac[2]));
X  if (v) { printf("STPAR failed"); exit(); }
X}
X#endif
X
Xtrmop(fc,arg) int fc, arg; {
X#ifdef SARG10
X  int retvalp;
X  int arglst[3];
X
X  /* TRMOP is a TOPS-10 monitor call that does things to the terminal. */
X
X  /* Find out TTY nbr (PA1050 barfs if TRMOP get -1 instead of udx)    */
X  /* A TRMNO monitor call returns the udx (Universal Device Index)	   */
X
X  arglst[0] = fc;	  /* function code	  */
X  arglst[1] = calli(0115, -1);	  /* udx, TRMNO. UUO  */
X  arglst[2] = arg;		  /* Optional argument	  */
X
X  if (calli(0116, 3 // &arglst[0], &retvalp))		/* TRMOP. UUO */
X  return (retvalp);
X  else {
X	printf("?Error return in TRMOP.");
X	exit();
X  }
X#endif
X}
X
Xinputline(s) char *s; {
X  scanf("%s",s);
X#ifdef SARG10
X  readnl();
X#endif
X#ifdef SARG20
X  readnl();
X#endif
X}
X
Xinflush() {
X
X  /*
X   *   Flush input buffer, make sure no pending input character
X   */
X
X  int val;
X
X#ifdef UNIX
X#ifdef XENIX
X  while(rdchk(0)) read(0,&val,1);
X#else
X#ifdef SIII
X  while(read(2,&val,1));
X#else
X  long l1;
X  ioctl (0, FIONREAD, &l1);
X  while(l1-- > 0L) read(0,&val,1);
X#endif
X#endif
X#endif
X#ifdef SARG10
X  while(uuo(051,2,&val))  /* TTCALL 2, (INCHRS)  */
X	;
X#endif
X#ifdef SARG20
X  ejsys(CFIBF,_PRIIN);		  /* Clear input buffer */
X#endif
X}
X
Xzleep(t) int t; {
X
X/*
X *	  Sleep and do nothing (don't waste CPU) for t milliseconds
X */
X
X#ifdef SARG10
X  calli(072,t); 	  /* (HIBER) t milliseconds */
X#endif
X#ifdef SARG20
X  ejsys(DISMS,t); /* DISMISS for t milliseconds */
X#endif
X#ifdef UNIX
X  t = t / 1000;
X  if (t == 0) t = 1;
X  sleep(t); 	  /* UNIX can only sleep whole seconds */
X#endif
X}
END_OF_vttest/esc.c
if test 7946 -ne `wc -c <vttest/esc.c`; then
    echo shar: \"vttest/esc.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f vttest/header.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"vttest/header.h\"
else
echo shar: Extracting \"vttest/header.h\" \(1238 characters\)
sed "s/^X//" >vttest/header.h <<'END_OF_vttest/header.h'
X#define VERSION "1.7b 1985-04-19"
X
X/* Choose one of these */
X
X/* #define XENIX	/* XENIX implies UNIX				*/
X/* #define SIII 	/* SIII  implies UNIX, (NDELAY a la System III) */
X#define UNIX		/* UNIX 					*/
X/* #define VMS		/* VMS not done yet -- send me your version!!!! */
X/* #define SARG20	/* Sargasso C for TOPS-20			*/
X/* #define SARG10	/* Sargasso C for TOPS-10			*/
X
X/* These #ifdef:s are implementation dependent stuff for the Sargasso C */
X/* Unix C barfs on directives like "#strings", so we keep them
X*/
X/* indented. Then unix c can't find them, but Sargasso C *can*.
X*/
X/* Admittedly kludgey, but it works...) 				  */
X#ifdef SARG10
X  #define _UNIXCON	/* Make UNIX-flavored I/O on TOPS */
X  #strings low		/* put strings in lowseg mem so we can modify them. */
X#endif
X#ifdef SARG20
X  #define _UNIXCON	/* Make UNIX-flavored I/O on TOPS */
X  #strings low		/* put strings in lowseg mem so we can modify them. */
X  #include <TOPS20.HDR>
X#endif
X
X#include <stdio.h>
X
X
X#ifdef UNIX
X#include <ctype.h>
X#include <sgtty.h>
X#include <signal.h>
X#include <setjmp.h>
Xjmp_buf intrenv;
Xstruct sgttyb sgttyOrg, sgttyNew;
Xchar stdioBuf[BUFSIZ];
Xint brkrd, reading;
Xextern onterm(), onbrk();
X#ifdef SIII
X#include <fcntl.h>
X#endif
X#endif
Xint ttymode;
END_OF_vttest/header.h
if test 1238 -ne `wc -c <vttest/header.h`; then
    echo shar: \"vttest/header.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f vttest/main.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"vttest/main.c\"
else
echo shar: Extracting \"vttest/main.c\" \(54655 characters\)
sed "s/^X//" >vttest/main.c <<'END_OF_vttest/main.c'
X/*
X			   VTTEST.C
X
X	 Written Novemeber 1983 - July 1984 by Per Lindberg,
X	 Stockholm University Computer Center (QZ), Sweden.
X
X		  THE MAD PROGRAMMER STRIKES AGAIN!
X
X		   This software is (c) 1984 by QZ
X	   Non-commercial use and copying allowed.
X
XIf you are developing a commercial product, and use this program to do
Xit, and that product is successful, please send a sum of money of your
Xchoice to the address below.
X
X*/
X
X#include "header.h"
X
Xchar inchar(), *instr(), *lookup();
X
Xstruct table {
X	int key;
X	char *msg;
X} paritytable[] = {
X	{ 1, "NONE" },
X	{ 4, "ODD"  },
X	{ 5, "EVEN" },
X	{ -1, "" }
X},nbitstable[] = {
X	{ 1, "8" },
X	{ 2, "7" },
X	{ -1,"" }
X},speedtable[] = {
X	{	0,	  "50" },
X	{	8,	  "75" },
X	{  16,	 "110" },
X	{  24,	 "132.5"},
X	{  32,	 "150" },
X	{  40,	 "200" },
X	{  48,	 "300" },
X	{  56,	 "600" },
X	{  64,	"1200" },
X	{  72,	"1800" },
X	{  80,	"2000" },
X	{  88,	"2400" },
X	{  96,	"3600" },
X	{ 104,	"4800" },
X	{ 112,	"9600" },
X	{ 120, "19200" },
X	{ -1, "" }
X};
X
Xmain() {
X
X  int menuchoice;
X
X  static char *mainmenu[] = {
X  "Exit",
X  "Test of cursor movements",
X  "Test of screen features",
X  "Test of character sets",
X  "Test of double-sized characters",
X  "Test of keyboard",
X  "Test of terminal reports",
X  "Test of VT52 mode",
X  "Test of VT102 features (Insert/Delete Char/Line)",
X  "Test of known bugs",
X  "Test of reset and self-test",
X  ""
X	};
X
X#ifdef UNIX
X  initterminal(setjmp(intrenv));
X  signal(SIGINT, onbrk);
X  signal(SIGTERM, onterm);
X  reading = 0;
X#else
X  initterminal(0);
X#endif
X  do {
X#ifdef SARG20
X	ttybin(1);	  /* set line to binary mode again. It's reset somehow!! */
X#endif
X	ed(2);
X	cup(5,10); printf("VT100 test program, version %s", VERSION);
X	cup(7,10); println("Choose test type:");
X	menuchoice = menu(mainmenu);
X	switch (menuchoice) {
X  case 1:  tst_movements();   break;
X  case 2:  tst_screen();	  break;
X  case 3:  tst_characters();  break;
X  case 4:  tst_doublesize();  break;
X  case 5:  tst_keyboard();	  break;
X  case 6:  tst_reports();	  break;
X  case 7:  tst_vt52();		  break;
X  case 8:  tst_insdel();	  break;
X  case 9:  tst_bugs();		  break;
X  case 10: tst_rst();	  break;
X	}
X  } while (menuchoice);
X  bye();
X}
X
Xtst_movements() {
X
X  /* Test of:
X	 CUF (Cursor Forward)
X	 CUB (Cursor Backward)
X	 CUD (Cursor Down)		IND (Index)  NEL (Next Line)
X	 CUU (Cursor Up)		RI	(Reverse Index)
X	 CUP (Cursor Position)	HVP (Horizontal and Vertical Position)
X	 ED  (Erase in Display)
X	 EL  (Erase in Line)
X	 DECALN (Screen Alignment Display)
X	 <CR> <BS>
X	 Cursor control characters inside CSI sequences
X  */
X
X  int i, row, col, pass, width, hlfxtra;
X  char c, *ctext = "This is a correct sentence";
X
X  for (pass = 0; pass <= 1; pass++) {
X	if (pass == 0) { rm("?3"); width =  80; hlfxtra =  0; }
X	else	   { sm("?3"); width = 132; hlfxtra = 26; }
X
X	decaln();
X	cup( 9,10+hlfxtra); ed(1);
X	cup(18,60+hlfxtra); ed(0); el(1);
X	cup( 9,71+hlfxtra); el(0);
X	for (row = 10; row <= 16; row++) {
X  cup(row, 10+hlfxtra); el(1);
X  cup(row, 71+hlfxtra); el(0);
X	}
X	cup(17,30); el(2);
X	for (col = 1; col <= width; col++) {
X  hvp(24, col); printf("*");
X  hvp( 1, col); printf("*");
X	}
X	cup(2,2);
X	for (row = 2; row <= 23; row++) {
X  printf("+");
X  cub(1);
X  ind();
X	}
X	cup(23,width-1);
X	for (row = 23; row >=2; row--) {
X  printf("+");
X  cub(1); ri();
X	}
X	cup(2,1);
X	for (row = 2; row <= 23; row++) {
X  printf("*");  cup(row, width);
X  printf("*");
X  cub(10);
X  if (row < 10) nel();
X  else			printf("\n");
X	}
X	cup(2,10);
X	cub(42+hlfxtra); cuf(2);
X	for (col = 3; col <= width-2; col++) {
X  printf("+");
X  cuf(0); cub(2); cuf(1);
X	}
X	cup(23,70+hlfxtra);
X	cuf(42+hlfxtra); cub(2);
X	for (col = width-2; col >= 3; col--) {
X  printf("+");
X  cub(1); cuf(1); cub(0); printf("%c", 8);
X	}
X	cup( 1, 1); cuu(10); cuu(1); cuu(0);
X	cup(24,width); cud(10); cud(1); cud(0);
X
X	cup(10,12+hlfxtra);
X	for (row = 10; row <= 15; row++) {
X  for (col = 12+hlfxtra; col <= 69+hlfxtra; col++) printf(" ");
X  cud(1); cub(58);
X	}
X	cuu(5); cuf(1);
X	printf("The screen should be cleared,  and have an unbroken bor-");
X	cup(12,13+hlfxtra);
X	printf("der of *'s and +'s around the edge,   and exactly in the");
X	cup(13,13+hlfxtra);
X	printf("middle  there should be a frame of E's around this  text");
X	cup(14,13+hlfxtra);
X	printf("with  one (1) free position around it.    ");
X	holdit();
X  }
X  rm("?3");
X
X  ed(2);
X  cup(1,1);
X  println("Test of cursor-control characters inside ESC sequences.");
X  println("Below should be two identical lines:");
X  println("");
X  println("A B C D E F G H I J K L M N O P Q R S");
X  for (i = 1; i < 20; i++) {
X	printf("%c", 64 + i);
X	brcstr("2\010", 'C');     /* Two forward, one backspace */
X  }
X  println("");
X  println("");
X  holdit();
X
X  ed(2);
X  cup(1,1);
X  println("Test of leading zeros in ESC sequences.");
X  printf("Two lines below you should see the sentence \"%s\".",ctext);
X  for (col = 1; *ctext; col++)
X   printf("\033[00000000004;00000000%dH%c",col,*ctext++);
X  cup(20,1);
X  holdit();
X}
X
Xtst_screen() {
X
X  /* Test of:
X	 - DECSTBM (Set Top and Bottom Margins)
X	 - TBC	   (Tabulation Clear)
X	 - HTS	   (Horizontal Tabulation Set)
X	 - SM RM   (Set/Reset mode): - 80/132 chars
X				 - Origin: Realtive/absolute
X			   - Scroll: Smooth/jump
X			   - Wraparound
X	 - SGR	   (Select Graphic Rendition)
X	 - SM RM   (Set/Reset Mode) - Inverse
X	 - DECSC   (Save Cursor)
X	 - DECRC   (Restore Cursor)
X  */
X
X  int i, j, cset, row, col, down, soft, background;
X
X  static char *tststr = "*qx`";
X  static char *attr[5] = { ";0", ";1", ";4", ";5", ";7" };
X
X  cup(1,1);
X  sm("?7");  /* Wrap Around ON */
X  for (col = 1; col <= 160; col++) printf("*");
X  rm("?7");  /* Wrap Around OFF */
X  cup(3,1);
X  for (col = 1; col <= 160; col++) printf("*");
X  sm("?7");  /* Wrap Around ON */
X  cup(5,1);
X  println("This should be three identical lines of *'s completely filling");
X  println("the top of the screen without any empty lines between.");
X  println("(Test of WRAP AROUND mode setting.)");
X  holdit();
X
X  ed(2);
X  tbc(3);
X  cup(1,1);
X  for (col = 1; col <= 78; col += 3) {
X	cuf(3); hts();
X  }
X  cup(1,4);
X  for (col = 4; col <= 78; col += 6) {
X	tbc(0); cuf(6);
X  }
X  cup(1,7); tbc(1); tbc(2); /* no-op */
X  cup(1,1); for (col = 1; col <= 78; col += 6) printf("\t*");
X  cup(2,2); for (col = 2; col <= 78; col += 6) printf("     *");
X  cup(4,1);
X  println("Test of TAB setting/resetting. These two lines");
X  printf("should look the same. ");
X  holdit();
X  for (background = 0; background <= 1; background++) {
X	if (background) rm("?5");
X	else		sm("?5");
X	sm("?3"); /* 132 cols */
X	ed(2);	  /* VT100 clears screen on SM3/RM3, but not obviously, so... */
X	cup(1,1); tbc(3);
X	for (col = 1; col <= 132; col += 8) {
X  cuf(8); hts();
X	}
X	cup(1,1); for (col = 1; col <= 130; col += 10) printf("1234567890");
X	printf("12");
X	for (row = 3; row <= 20; row++) {
X  cup(row,row);
X  printf("This is 132 column mode, %s background.",
X  background ? "dark" : "light");
X	}
X	holdit();
X	rm("?3"); /* 80 cols */
X	ed(2);	  /* VT100 clears screen on SM3/RM3, but not obviously, so... */
X	cup(1,1); for (col = 1; col <= 80; col += 10) printf("1234567890");
X	for (row = 3; row <= 20; row++) {
X  cup(row,row);
X  printf("This is 80 column mode, %s background.",
X  background ? "dark" : "light");
X	}
X	holdit();
X  }
X  ed(2);
X  sm("?6"); /* Origin mode (relative) */
X  for (soft = -1; soft <= 0; soft++) {
X	if (soft) sm("?4");
X	else  rm("?4");
X	for (row = 12; row >= 1; row -= 11) {
X  decstbm(row, 24-row+1);
X  ed(2);
X  for (down = 0; down >= -1; down--) {
X	if (down) cuu(24);
X  else		cud(24);
X  for (i = 1; i <= 30; i++) {
X	printf("%s scroll %s region %d Line %d\n",
X	   soft ? "Soft" : "Jump",
X	   down ? "down" : "up",
X	   2*(13-row), i);
X	if (down) { ri(); ri(); }
X  }
X  }
X  holdit();
X	}
X  }
X  ed(2);
X  decstbm(23,24);
X  printf(
X  "\nOrigin mode test. This line should be at the bottom of the screen.");
X  cup(1,1);
X  printf("%s",
X  "This line should be the one above the bottom of the screeen. ");
X  holdit();
X  ed(2);
X  rm("?6"); /* Origin mode (absolute) */
X  cup(24,1);
X  printf(
X  "Origin mode test. This line should be at the bottom of the screen.");
X  cup(1,1);
X  printf("%s", "This line should be at the top if the screen. ");
X  holdit();
X  decstbm(1,24);
X
X  ed(2);
X  cup( 1,20); printf("Graphic rendition test pattern:");
X  cup( 4, 1); sgr("0");         printf("vanilla");
X  cup( 4,40); sgr("0;1");       printf("bold");
X  cup( 6, 6); sgr(";4");        printf("underline");
X  cup( 6,45);sgr(";1");sgr("4");printf("bold underline");
X  cup( 8, 1); sgr("0;5");       printf("blink");
X  cup( 8,40); sgr("0;5;1");     printf("bold blink");
X  cup(10, 6); sgr("0;4;5");     printf("underline blink");
X  cup(10,45); sgr("0;1;4;5");   printf("bold underline blink");
X  cup(12, 1); sgr("1;4;5;0;7"); printf("negative");
X  cup(12,40); sgr("0;1;7");     printf("bold negative");
X  cup(14, 6); sgr("0;4;7");     printf("underline negative");
X  cup(14,45); sgr("0;1;4;7");   printf("bold underline negative");
X  cup(16, 1); sgr("1;4;;5;7");  printf("blink negative");
X  cup(16,40); sgr("0;1;5;7");   printf("bold blink negative");
X  cup(18, 6); sgr("0;4;5;7");   printf("underline blink negative");
X  cup(18,45); sgr("0;1;4;5;7"); printf("bold underline blink negative");
X  sgr("");
X
X  rm("?5"); /* Inverse video off */
X  cup(23,1); el(0); printf("Dark background. "); holdit();
X  sm("?5"); /* Inverse video */
X  cup(23,1); el(0); printf("Light background. "); holdit();
X  rm("?5");
X  ed(2);
X  cup(8,12); printf("normal");
X  cup(8,24); printf("bold");
X  cup(8,36); printf("underscored");
X  cup(8,48); printf("blinking");
X  cup(8,60); printf("reversed");
X  cup(10,1); printf("stars:");
X  cup(12,1); printf("line:");
X  cup(14,1); printf("x'es:");
X  cup(16,1); printf("diamonds:");
X  for (cset = 0; cset <= 3; cset++) {
X	for (i = 0; i <= 4; i++) {
X	cup(10 + 2 * cset, 12 + 12 * i);
X	sgr(attr[i]);
X	if (cset == 0 || cset == 2) scs(0,'B');
X	else			scs(0,'0');
X  for (j = 0; j <= 4; j++) {
X	printf("%c", tststr[cset]);
X  }
X  decsc();
X  cup(cset + 1, i + 1); sgr(""); scs(0,'B'); printf("A");
X  decrc();
X  for (j = 0; j <= 4; j++) {
X	printf("%c", tststr[cset]);
X  }
X	}
X  }
X  sgr("0"); scs(0,'B'); cup(21,1);
X  println("Test of the SAVE/RESTORE CURSOR feature. There should");
X  println("be ten characters of each flavour, and a rectangle");
X  println("of 5 x 4 A's filling the top left of the screen.");
X  holdit();
X}
X
Xtst_characters() {
X  /* Test of:
X	 SCS	(Select character Set)
X  */
X
X  int i, j, g, cset;
X  char chcode[5], *setmsg[5];
X
X  chcode[0] = 'A';
X  chcode[1] = 'B';
X  chcode[2] = '0';
X  chcode[3] = '1';
X  chcode[4] = '2';
X  setmsg[0] = "UK / national";
X  setmsg[1] = "US ASCII";
X  setmsg[2] = "Special graphics and line drawing";
X  setmsg[3] = "Alternate character ROM standard characters";
X  setmsg[4] = "Alternate character ROM special graphics";
X
X  cup(1,10); printf("Selected as G0 (with SI)");
X  cup(1,48); printf("Selected as G1 (with SO)");
X  for (cset = 0; cset <= 4; cset++) {
X	scs(1,'B');
X	cup(3 + 4 * cset, 1);
X	sgr("1");
X	printf("Character set %c (%s)",chcode[cset], setmsg[cset]);
X	sgr("0");
X	for (g = 0; g <= 1; g++) {
X  scs(g,chcode[cset]);
X  for (i = 1; i <= 3; i++) {
X	cup(3 + 4 * cset + i, 10 + 38 * g);
X	for (j = 0; j <= 31; j++) {
X	printf("%c", i * 32 + j);
X  }
X  }
X	}
X  }
X  scs(1,'B');
X  cup(24,1); printf("These are the installed character sets. ");
X  holdit();
X}
X
Xtst_doublesize() {
X  /* Test of:
X	 DECSWL  (Single Width Line)
X	 DECDWL  (Double Width Line)
X	 DECDHL  (Double Height Line) (also implicit double width)
X  */
X
X  int col, i, w, w1;
X
X  /* Print the test pattern in both 80 and 132 character width	*/
X
X  for(w = 0; w <= 1; w++) {
X	w1 = 13 * w;
X
X	ed(2);
X	cup(1, 1);
X	if (w) { sm("?3"); printf("132 column mode"); }
X	else   { rm("?3"); printf(" 80 column mode"); }
X
X	cup( 5, 3 + 2 * w1);
X	printf("v------- left margin");
X
X	cup( 7, 3 + 2 * w1);
X	printf("This is a normal-sized line");
X	decdhl(0); decdhl(1); decdwl(); decswl();
X
X	cup( 9, 2 + w1);
X	printf("This is a Double-width line");
X	decswl(); decdhl(0); decdhl(1); decdwl();
X
X	cup(11, 2 + w1);
X	decdwl(); decswl(); decdhl(1); decdhl(0);
X	printf("This is a Double-width-and-height line");
X	cup(12, 2 + w1);
X	decdwl(); decswl(); decdhl(0); decdhl(1);
X	printf("This is a Double-width-and-height line");
X
X	cup(14, 2 + w1);
X	decdwl(); decswl(); decdhl(1); decdhl(0); el(2);
X	printf("This is another such line");
X	cup(15, 2 + w1);
X	decdwl(); decswl(); decdhl(0); decdhl(1);
X	printf("This is another such line");
X
X	cup(17, 3 + 2 * w1);
X	printf("^------- left margin");
X
X	cup(21, 1);
X	printf("This is not a double-width line");
X	for (i = 0; i <= 1; i++) {
X  cup(21,6);
X  if (i) { printf("**is**"); decdwl(); }
X  else	 { printf("is not"); decswl(); }
X  cup(23,1); holdit();
X	}
X  }
X  /* Set vanilla tabs for next test */
X  cup(1,1); tbc(3); for (col = 1; col <= 132; col += 8) { cuf(8); hts(); }
X  rm("?3");
X  ed(2);
X  scs(0,'0');
X
X  cup( 8,1); decdhl(0); printf("lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk");
X  cup( 9,1); decdhl(1); printf("lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk");
X  cup(10,1); decdhl(0); printf("x%c%c%c%c%cx",9,9,9,9,9);
X  cup(11,1); decdhl(1); printf("x%c%c%c%c%cx",9,9,9,9,9);
X  cup(12,1); decdhl(0); printf("x%c%c%c%c%cx",9,9,9,9,9);
X  cup(13,1); decdhl(1); printf("x%c%c%c%c%cx",9,9,9,9,9);
X  cup(14,1); decdhl(0); printf("x                                      x");
X  cup(15,1); decdhl(1); printf("x                                      x");
X  cup(16,1); decdhl(0); printf("mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj");
X  cup(17,1); decdhl(1); printf("mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj");
X  scs(0,'B'); sgr("1;5");
X  cup(12,3);
X  printf("* The mad programmer strikes again * ");
X  cup(13,3); printf("%c",9); cub(6);
X  printf("* The mad programmer strikes again *");
X  sgr("0");
X  cup(22,1);
X  println("Another test pattern...  a frame with blinking bold text,");
X  printf("all in double-height double-width size. ");
X  holdit();
X
X  decstbm(8,24); /* Absolute origin mode, so cursor is set at (1,1) */
X  cup(8,1);
X  for (i = 1; i <= 12; i++)
X	ri();
X  decstbm(0,0);   /* No scroll region */
X  cup(1,1);
X  printf("%s", "Exactly half of the box should remain. ");
X  holdit();
X}
X
Xtst_keyboard() {
X
X/* Test of:
X	 - DECLL   (Load LEDs)
X	 - Keyboard return messages
X	 - SM RM   (Set/Reset Mode) - Cursor Keys
X				- Auto repeat
X	 - DECKPAM (Keypad Application Mode)
X	 - DECKPNM (Keypad Numeric Mode)
X
XThe standard VT100 keayboard layout:
X
X							UP	 DN   LE  RI
X
XESC   1!   2@	3#	 4$   5%   6^	7&	 8*   9(   0)	-_	 =+   `~  BS
X
XTAB*	qQ	 wW   eE   rR	tT	 yY   uU   iI	oO	 pP   [{   ]}  DEL
X
X**	 **   aA   sS	dD	 fF   gG   hH	jJ	 kK   lL   ;:	,"   RETN  \|
X
X**	 ****	zZ	 xX   cC   vV	bB	 nN   mM   ,<	.>	 /?   ****	 LF
X
X		 ****************SPACE BAR****************
X
X							   PF1 PF2 PF3 PF4
X
X							   *7* *8* *9* *-*
X
X							   *4* *5* *6* *,*
X
X							   *1* *2* *3*
X
X							   ***0*** *.* ENT
X*/
X
X  char *ledmsg[6], *ledseq[6];
X
X  int  i, j, okflag;
X  int  kblayout;
X  int  ckeymode;
X  int  fkeymode;
X  char kbdc;
X  char *kbds = " ";
X  char *curkeystr, *fnkeystr, *abmstr;
X  char arptstring[500];
X
X  static struct key {
X  char c;
X  int  row;
X  int  col;
X  char *symbol;
X  } keytab [] = {
X  { 27, 1,	0, "ESC" },
X  { '1', 1,  6, "1" },    { '!', 1,  7, "!" },
X  { '2', 1, 11, "2" },    { '@', 1, 12, "@" },
X  { '3', 1, 16, "3" },    { '#', 1, 17, "#" },
X  { '4', 1, 21, "4" },    { '$', 1, 22, "$" },
X  { '5', 1, 26, "5" },    {'\%', 1, 27, "%" },
X  { '6', 1, 31, "6" },    { '^', 1, 32, "^" },
X  { '7', 1, 36, "7" },    { '&', 1, 37, "&" },
X  { '8', 1, 41, "8" },    { '*', 1, 42, "*" },
X  { '9', 1, 46, "9" },    { '(', 1, 47, "(" },
X  { '0', 1, 51, "0" },    { ')', 1, 52, ")" },
X  { '-', 1, 56, "-" },    { '_', 1, 57, "_" },
X  { '=', 1, 61, "=" },    { '+', 1, 62, "+" },
X  { '`', 1, 66, "`" },    { '~', 1, 67, "~" },
X  {   8, 1, 70, "BS" },
X  {   9, 2,  0, " TAB " },
X  { 'q', 2,  8, "q" },    { 'Q', 2,  9, "Q" },
X  { 'w', 2, 13, "w" },    { 'W', 2, 14, "W" },
X  { 'e', 2, 18, "e" },    { 'E', 2, 19, "E" },
X  { 'r', 2, 23, "r" },    { 'R', 2, 24, "R" },
X  { 't', 2, 28, "t" },    { 'T', 2, 29, "T" },
X  { 'y', 2, 33, "y" },    { 'Y', 2, 34, "Y" },
X  { 'u', 2, 38, "u" },    { 'U', 2, 39, "U" },
X  { 'i', 2, 43, "i" },    { 'I', 2, 44, "I" },
X  { 'o', 2, 48, "o" },    { 'O', 2, 49, "O" },
X  { 'p', 2, 53, "p" },    { 'P', 2, 54, "P" },
X  { '[', 2, 58, "[" },    { '{', 2, 59, "{" },
X  { ']', 2, 63, "]" },    { '}', 2, 64, "}" },
X  { 127, 2, 71, "DEL" },
X  { 'a', 3, 10, "a" },    { 'A', 3, 11, "A" },
X  { 's', 3, 15, "s" },    { 'S', 3, 16, "S" },
X  { 'd', 3, 20, "d" },    { 'D', 3, 21, "D" },
X  { 'f', 3, 25, "f" },    { 'F', 3, 26, "F" },
X  { 'g', 3, 30, "g" },    { 'G', 3, 31, "G" },
X  { 'h', 3, 35, "h" },    { 'H', 3, 36, "H" },
X  { 'j', 3, 40, "j" },    { 'J', 3, 41, "J" },
X  { 'k', 3, 45, "k" },    { 'K', 3, 46, "K" },
X  { 'l', 3, 50, "l" },    { 'L', 3, 51, "L" },
X  { ';', 3, 55, ";" },    { ':', 3, 56, ":" },
X  {'\'', 3, 60, "'" },    { '"', 3, 61,"\"" },
X  {  13, 3, 65, "RETN"},
X  {'\\', 3, 71,"\\" },    { '|', 3, 72, "|" },
X  { 'z', 4, 12, "z" },    { 'Z', 4, 13, "Z" },
X  { 'x', 4, 17, "x" },    { 'X', 4, 18, "X" },
X  { 'c', 4, 22, "c" },    { 'C', 4, 23, "C" },
X  { 'v', 4, 27, "v" },    { 'V', 4, 28, "V" },
X  { 'b', 4, 32, "b" },    { 'B', 4, 33, "B" },
X  { 'n', 4, 37, "n" },    { 'N', 4, 38, "N" },
X  { 'm', 4, 42, "m" },    { 'M', 4, 43, "M" },
X  { ',', 4, 47, "," },    { '<', 4, 48, "<" },
X  { '.', 4, 52, "." },    { '>', 4, 53, ">" },
X  { '/', 4, 57, "/" },    { '?', 4, 58, "?" },
X  {  10, 4, 69, "LF" },
X  { ' ', 5, 13, "                SPACE BAR                "},
X  {'\0', 0,  0, ""  }
X	};
X
X  static struct natkey {
X  char natc;
X  int  natrow;
X  int  natcol;
X  char *natsymbol;
X  } natkeytab [][29] = {
X  {
X	{ '"', 1, 12, "\""},
X	{ '&', 1, 32, "&" },
X	{ '/', 1, 37, "/" },
X	{ '(', 1, 42, "(" },
X	{ ')', 1, 47, ")" },
X	{ '=', 1, 52, "=" },
X	{ '+', 1, 56, "+" },    { '?', 1, 57, "?" },
X	{ '`', 1, 61, "`" },    { '@', 1, 62, "@" },
X	{ '<', 1, 66, "<" },    { '>', 1, 67, ">" },
X	{ '}', 2, 58, "}" },    { ']', 2, 59, "]" },
X	{ '^', 2, 63, "^" },    { '~', 2, 64, "~" },
X	{ '|', 3, 55, "|" },    {'\\', 3, 56,"\\" },
X	{ '{', 3, 60, "{" },    { '[', 3, 61, "[" },
X	{'\'', 3, 71, "'" },    { '*', 3, 72, "*" },
X	{ ',', 4, 47, "," },    { ';', 4, 48, ";" },
X	{ '.', 4, 52, "." },    { ':', 4, 53, ":" },
X	{ '-', 4, 57, "-" },    { '_', 4, 58, "_" },
X	{'\0', 0,  0, ""  }
X  },
X  {
X	{ '"', 1, 12, "\""},
X	{ '&', 1, 32, "&" },
X	{ '/', 1, 37, "/" },
X	{ '(', 1, 42, "(" },
X	{ ')', 1, 47, ")" },
X	{ '=', 1, 52, "=" },
X	{ '+', 1, 56, "+" },    { '?', 1, 57, "?" },
X	{ '`', 1, 61, "`" },    { '@', 1, 62, "@" },
X	{ '<', 1, 66, "<" },    { '>', 1, 67, ">" },
X	{ '}', 2, 58, "}" },    { ']', 2, 59, "]" },
X	{ '~', 2, 63, "~" },    { '^', 2, 64, "^" },
X	{ '|', 3, 55, "|" },    {'\\', 3, 56,"\\" },
X	{ '{', 3, 60, "{" },    { '[', 3, 61, "[" },
X	{'\'', 3, 71, "'" },    { '*', 3, 72, "*" },
X	{ ',', 4, 47, "," },    { ';', 4, 48, ";" },
X	{ '.', 4, 52, "." },    { ':', 4, 53, ":" },
X	{ '-', 4, 57, "-" },    { '_', 4, 58, "_" },
X	{'\0', 0,  0, ""  }
X  }
X  };
X
X  static struct curkey {
X  char *curkeymsg[3];
X  int  curkeyrow;
X  int  curkeycol;
X  char *curkeysymbol;
X  char *curkeyname;
X  } curkeytab [] = {
X
X  /* A Reset, A Set,  VT52	*/
X
X  {{"\033[A","\033OA","\033A"}, 0, 56, "UP",  "Up arrow"   },
X  {{"\033[B","\033OB","\033B"}, 0, 61, "DN",  "Down arrow" },
X  {{"\033[D","\033OD","\033D"}, 0, 66, "LT",  "Left arrow" },
X  {{"\033[C","\033OC","\033C"}, 0, 71, "RT",  "Right arrow"},
X  {{"",      "",       ""     }, 0,  0, "",    "" }
X  };
X
X  static struct fnkey {
X  char *fnkeymsg[4];
X  int  fnkeyrow;
X  int  fnkeycol;
X  char *fnkeysymbol;
X  char *fnkeyname;
X  } fnkeytab [] = {
X
X  /* ANSI-num,ANSI-app,VT52-nu,VT52-ap,  r, c,	symb   name 	*/
X
X  {{"\033OP","\033OP","\033P","\033P" }, 6, 59, "PF1", "PF1"        },
X  {{"\033OQ","\033OQ","\033Q","\033Q" }, 6, 63, "PF2", "PF2"        },
X  {{"\033OR","\033OR","\033R","\033R" }, 6, 67, "PF3", "PF3"        },
X  {{"\033OS","\033OS","\033S","\033S" }, 6, 71, "PF4", "PF4"        },
X  {{"7",     "\033Ow","7",    "\033?w"}, 7, 59, " 7 ", "Numeric 7"  },
X  {{"8",     "\033Ox","8",    "\033?x"}, 7, 63, " 8 ", "Numeric 8"  },
X  {{"9",     "\033Oy","9",    "\033?y"}, 7, 67, " 9 ", "Numeric 9"  },
X  {{"-",     "\033Om","-",    "\033?m"}, 7, 71, " - ", "Minus"      },
X  {{"4",     "\033Ot","4",    "\033?t"}, 8, 59, " 4 ", "Numeric 4"  },
X  {{"5",     "\033Ou","5",    "\033?u"}, 8, 63, " 5 ", "Numeric 5"  },
X  {{"6",     "\033Ov","6",    "\033?v"}, 8, 67, " 6 ", "Numeric 6"  },
X  {{",",     "\033Ol",",",    "\033?l"}, 8, 71, " , ", "Comma"      },
X  {{"1",     "\033Oq","1",    "\033?q"}, 9, 59, " 1 ", "Numeric 1"  },
X  {{"2",     "\033Or","2",    "\033?r"}, 9, 63, " 2 ", "Numeric 2"  },
X  {{"3",     "\033Os","3",    "\033?s"}, 9, 67, " 3 ", "Numeric 3"  },
X  {{"0",     "\033Op","0",    "\033?p"},10, 59,"   O   ","Numeric 0"},
X  {{".",     "\033On",".",    "\033?n"},10, 67, " . ", "Point"      },
X  {{"\015",  "\033OM","\015", "\033?M"},10, 71, "ENT", "ENTER"      },
X  {{"","","",""},       0,  0, "",    ""           }
X	};
X
X  static struct ckey {
X  int  ccount;
X  char *csymbol;
X  } ckeytab [] = {
X  { 0, "NUL (CTRL-@ or CTRL-Space)" },
X  { 0, "SOH (CTRL-A)" },
X  { 0, "STX (CTRL-B)" },
X  { 0, "ETX (CTRL-C)" },
X  { 0, "EOT (CTRL-D)" },
X  { 0, "ENQ (CTRL-E)" },
X  { 0, "ACK (CTRL-F)" },
X  { 0, "BEL (CTRL-G)" },
X  { 0, "BS  (CTRL-H) (BACK SPACE)" },
X  { 0, "HT  (CTRL-I) (TAB)" },
X  { 0, "LF  (CTRL-J) (LINE FEED)" },
X  { 0, "VT  (CTRL-K)" },
X  { 0, "FF  (CTRL-L)" },
X  { 0, "CR  (CTRL-M) (RETURN)" },
X  { 0, "SO  (CTRL-N)" },
X  { 0, "SI  (CTRL-O)" },
X  { 0, "DLE (CTRL-P)" },
X  { 0, "DC1 (CTRL-Q) (X-On)" },
X  { 0, "DC2 (CTRL-R)" },
X  { 0, "DC3 (CTRL-S) (X-Off)" },
X  { 0, "DC4 (CTRL-T)" },
X  { 0, "NAK (CTRL-U)" },
X  { 0, "SYN (CTRL-V)" },
X  { 0, "ETB (CTRL-W)" },
X  { 0, "CAN (CTRL-X)" },
X  { 0, "EM  (CTRL-Y)" },
X  { 0, "SUB (CTRL-Z)" },
X  { 0, "ESC (CTRL-[) (ESCAPE)" },
X  { 0, "FS  (CTRL-\\ or CTRL-? or CTRL-_)" },
X  { 0, "GS  (CTRL-])" },
X  { 0, "RS  (CTRL-^ or CTRL-~ or CTRL-`)" },
X  { 0, "US  (CTRL-_ or CTRL-?)" }
X  };
X
X  static char *keyboardmenu[] = {
X  "Standard American ASCII layout",
X  "Swedish national layout D47",
X  "Swedish national layout E47",
X  /* add new keyboard layouts here */
X  ""
X	};
X
X  static char *curkeymodes[3] = {
X  "ANSI / Cursor key mode RESET",
X  "ANSI / Cursor key mode SET",
X  "VT52 Mode"
X  };
X
X  static char *fnkeymodes[4] = {
X  "ANSI Numeric mode",
X  "ANSI Application mode",
X  "VT52 Numeric mode",
X  "VT52 Application mode"
X  };
X
X  ledmsg[0] = "L1 L2 L3 L4"; ledseq[0] = "1;2;3;4";
X  ledmsg[1] = "   L2 L3 L4"; ledseq[1] = "1;0;4;3;2";
X  ledmsg[2] = "   L2 L3";    ledseq[2] = "1;4;;2;3";
X  ledmsg[3] = "L1 L2";       ledseq[3] = ";;2;1";
X  ledmsg[4] = "L1";          ledseq[4] = "1";
X  ledmsg[5] = "";            ledseq[5] = "";
X
X#ifdef UNIX
X  fflush(stdout);
X#endif
X  ed(2);
X  cup(10,1);
X  println("These LEDs (\"lamps\") on the keyboard should be on:");
X  for (i = 0; i <= 5; i++) {
X	cup(10,52); el(0); printf("%s", ledmsg[i]);
X	decll("0");
X	decll(ledseq[i]);
X	cup(12,1); holdit();
X  }
X
X  ed(2);
X  cup(10,1);
X  println("Test of the AUTO REPEAT feature");
X  println("");
X  println("Hold down an alphanumeric key for a while, then push RETURN.");
X  printf("%s", "Auto Repeat OFF: ");
X  rm("?8");
X  inputline(arptstring);
X  if (strlen(arptstring) == 0)		println("No characters read!??");
X  else if (strlen(arptstring) == 1) println("OK.");
X  else					println("Too many characters read.");
X  println("");
X  println("Hold down an alphanumeric key for a while, then push RETURN.");
X  printf("%s", "Auto Repeat ON: ");
X  sm("?8");
X  inputline(arptstring);
X  if (strlen(arptstring) == 0)		println("No characters read!??");
X  else if (strlen(arptstring) == 1) println("Not enough characters read.");
X  else					println("OK.");
X  println("");
X  holdit();
X
X  ed(2);
X  cup(5,10);
X  println("Choose keyboard layout:");
X  kblayout = menu(keyboardmenu);
X  if (kblayout) {
X	kblayout--;
X	for (j = 0; natkeytab[kblayout][j].natc != '\0'; j++) {
X  for (i = 0; keytab[i].c != '\0'; i++) {
X  if (keytab[i].row == natkeytab[kblayout][j].natrow &&
X	  keytab[i].col == natkeytab[kblayout][j].natcol) {
X	keytab[i].c = natkeytab[kblayout][j].natc;
X	keytab[i].symbol = natkeytab[kblayout][j].natsymbol;
X	break;
X  }
X  }
X	}
X  }
X
X  ed(2);
X  for (i = 0; keytab[i].c != '\0'; i++) {
X	cup(1 + 2 * keytab[i].row, 1 + keytab[i].col);
X	sgr("7");
X	printf("%s", keytab[i].symbol);
X	sgr("");
X  }
X  cup(22,1);
X#ifdef UNIX
X  sgttyNew.sg_flags &= ~CRMOD;
X  sgttyNew.sg_flags &= ~ECHO;
X  stty(0, &sgttyNew);
X#endif
X  inflush();
X  printf("Press each key, both shifted and unshifted. Finish with RETURN:");
X  do { /* while (kbdc != 13) */
X	cup(23,1); kbdc = inchar();
X	cup(23,1); el(0);
X	sprintf(kbds, "%c", kbdc);
X	chrprint(kbds);
X	for (i = 0; keytab[i].c != '\0'; i++) {
X  if (keytab[i].c == kbdc) {
X	cup(1 + 2 * keytab[i].row, 1 + keytab[i].col);
X  printf("%s", keytab[i].symbol);
X  break;
X  }
X	}
X  } while (kbdc != 13);
X#ifdef SARG10
X  inchar();  /* Local hack: Read LF that TOPS-10 adds to CR */
X#endif
X  cup(23,1); el(0);
X
X  for (ckeymode = 0; ckeymode <= 2; ckeymode++) {
X	if (ckeymode) sm("?1");
X	else		rm("?1");
X	for (i = 0; curkeytab[i].curkeysymbol[0] != '\0'; i++) {
X  cup(1 + 2 * curkeytab[i].curkeyrow, 1 + curkeytab[i].curkeycol);
X  sgr("7");
X  printf("%s", curkeytab[i].curkeysymbol);
X  sgr("");
X	}
X	cup(20,1); printf("<%s>%20s", curkeymodes[ckeymode], "");
X	cup(22,1); el(0);
X	cup(22,1); printf("%s", "Press each cursor key. Finish with TAB.");
X	for(;;) {
X  cup(23,1);
X  if (ckeymode == 2) rm("?2"); /* VT52 mode */
X  curkeystr = instr();
X  esc("<");                      /* ANSI mode */
X  cup(23,1); el(0);
X  cup(23,1); chrprint(curkeystr);
X  if (!strcmp(curkeystr,"\t")) break;
X  for (i = 0; curkeytab[i].curkeysymbol[0] != '\0'; i++) {
X  if (!strcmp(curkeystr,curkeytab[i].curkeymsg[ckeymode])) {
X	sgr("7");
X	printf(" (%s key) ", curkeytab[i].curkeyname);
X	sgr("");
X	cup(1 + 2 * curkeytab[i].curkeyrow,
X		1 + curkeytab[i].curkeycol);
X	printf("%s", curkeytab[i].curkeysymbol);
X	break;
X  }
X  }
X  if (i == sizeof(curkeytab) / sizeof(struct curkey) - 1) {
X  sgr("7");
X  printf("%s", " (Unknown cursor key) ");
X  sgr("");
X  }
X	}
X  }
X
X  for (fkeymode = 0; fkeymode <= 3; fkeymode++) {
X	for (i = 0; fnkeytab[i].fnkeysymbol[0] != '\0'; i++) {
X  cup(1 + 2 * fnkeytab[i].fnkeyrow, 1 + fnkeytab[i].fnkeycol);
X  sgr("7");
X  printf("%s", fnkeytab[i].fnkeysymbol);
X  sgr("");
X	}
X	cup(20,1); printf("<%s>%20s", fnkeymodes[fkeymode], "");
X	cup(22,1); el(0);
X	cup(22,1); printf("%s", "Press each function key. Finish with TAB.");
X	for(;;) {
X  cup(23,1);
X  if (fkeymode >= 2)  rm("?2");    /* VT52 mode */
X  if (fkeymode % 2)   deckpam();   /* Application mode */
X  else			   deckpnm(); /* Numeric mode	  */
X  fnkeystr = instr();
X  esc("<");                               /* ANSI mode */
X  cup(23,1); el(0);
X  cup(23,1); chrprint(fnkeystr);
X  if (!strcmp(fnkeystr,"\t")) break;
X  for (i = 0; fnkeytab[i].fnkeysymbol[0] != '\0'; i++) {
X  if (!strcmp(fnkeystr,fnkeytab[i].fnkeymsg[fkeymode])) {
X	sgr("7");
X	printf(" (%s key) ", fnkeytab[i].fnkeyname);
X	sgr("");
X	cup(1 + 2 * fnkeytab[i].fnkeyrow, 1 + fnkeytab[i].fnkeycol);
X	printf("%s", fnkeytab[i].fnkeysymbol);
X	break;
X  }
X  }
X  if (i == sizeof(fnkeytab) / sizeof(struct fnkey) - 1) {
X  sgr("7");
X  printf("%s", " (Unknown function key) ");
X  sgr("");
X  }
X	}
X  }
X
X#ifdef UNIX
X  sgttyNew.sg_flags |= CRMOD;
X  stty(0, &sgttyNew);
X#endif
X  ed(2);
X  cup(5,1);
X  println("Finally, a check of the ANSWERBACK MESSAGE, which can be sent");
X  println("by pressing CTRL-BREAK. The answerback message can be loaded");
X  println("in SET-UP B by pressing SHIFT-A and typing e.g.");
X  println("");
X  println("         \" H e l l o , w o r l d Return \"");
X  println("");
X  println("(the double-quote characters included).  Do that, and then try");
X  println("to send an answerback message with CTRL-BREAK.  If it works,");
X  println("the answerback message should be displayed in reverse mode.");
X  println("Finish with a single RETURN.");
X
X#ifdef UNIX
X  sgttyNew.sg_flags &= ~CRMOD;
X  stty(0, &sgttyNew);
X#endif
X  do {
X	cup(17,1);
X	inflush();
X	abmstr = instr();
X	cup(17,1);
X	el(0);
X	chrprint(abmstr);
X  } while (strcmp(abmstr,"\r"));
X
X  ed(2);
X  for (i = 0; i < 32; i++) {
X	cup(1 + (i % 16), 1 + 40 * (i / 16));
X	sgr("7");
X	printf("%s", ckeytab[i].csymbol);
X	sgr("0");
X  }
X  cup(19,1);
X#ifdef UNIX
X  sgttyNew.sg_flags |= CRMOD;
X  stty(0, &sgttyNew);
X#endif
X  println(
X  "Push each CTRL-key TWICE. Note that you should be able to send *all*");
X  println(
X  "CTRL-codes twice, including CTRL-S (X-Off) and CTRL-Q (X-Off)!");
X  println(
X  "Finish with DEL (also called DELETE or RUB OUT), or wait 1 minute.");
X#ifdef UNIX
X#ifdef SIII
X  sgttyNew.sg_flags &= ~CBREAK;
X  stty(0, &sgttyNew);
X#endif
X  sgttyNew.sg_flags |= RAW;
X  stty(0, &sgttyNew);
X#endif
X  ttybin(1);
X#ifdef SARG20
X  page(0);	  /* Turn off all character processing at input */
X  superbin(1);	  /* Turn off ^C (among others). Keep your fingers crossed!! */
X#endif
X  do {
X	cup(23,1); kbdc = inchar();
X	cup(23,1); el(0);
X	if (kbdc < 32) printf("  %s", ckeytab[kbdc].csymbol);
X	else {
X  sprintf(kbds, "%c", kbdc);
X  chrprint(kbds);
X  printf("%s", " -- not a CTRL key");
X	}
X	if (kbdc < 32) ckeytab[kbdc].ccount++;
X	if (ckeytab[kbdc].ccount == 2) {
X  cup(1 + (kbdc % 16), 1 + 40 * (kbdc / 16));
X  printf("%s", ckeytab[kbdc].csymbol);
X	}
X  } while (kbdc != '\177');
X#ifdef UNIX
X  sgttyNew.sg_flags &= ~RAW;
X  sgttyNew.sg_flags |= ECHO;
X  stty(0, &sgttyNew);
X#ifdef SIII
X  sgttyNew.sg_flags |= CBREAK;
X  stty(0, &sgttyNew);
X#endif
X#endif
X  ttybin(0);
X#ifdef SARG20
X  superbin(0);	  /* Puuuh! We made it!? */
X  page(1);	  /* Back to normal input processing */
X  ttybin(1);  /* This must be the mode for DEC20 */
X#endif
X  cup(24,1);
X  okflag = 1;
X  for (i = 0; i < 32; i++) if (ckeytab[i].ccount < 2) okflag = 0;
X  if (okflag) printf("%s", "OK. ");
X  else	  printf("%s", "You have not been able to send all CTRL keys! ");
X  holdit();
X}
X
Xtst_reports() {
X  /* Test of:
X   <ENQ>	   (AnswerBack Message)
X   SM RM	   (Set/Reset Mode) - LineFeed / Newline
X   DSR		   (Device Status Report)
X   DA	   (Device Attributes)
X   DECREQTPARM (Request Terminal Parameters)
X  */
X
X  int parity, nbits, xspeed, rspeed, clkmul, flags;
X  int i, reportpos;
X  char *report, *report2;
X  static char *attributes[][2] = {
X	{ "\033[?1;0c",   "No options (vanilla VT100)" },
X	{ "\033[?1;1c",   "VT100 with STP" },
X	{ "\033[?1;2c",   "VT100 with AVO (could be a VT102)" },
X	{ "\033[?1;3c",   "VT100 with STP and AVO" },
X	{ "\033[?1;4c",   "VT100 with GPO" },
X	{ "\033[?1;5c",   "VT100 with STP and GPO" },
X	{ "\033[?1;6c",   "VT100 with AVO and GPO" },
X	{ "\033[?1;7c",   "VT100 with STP, AVO and GPO" },
X	{ "\033[?1;11c",  "VT100 with PP and AVO" },
X	{ "\033[?1;15c",  "VT100 with PP, GPO and AVO" },
X	{ "\033[?4;2c",   "VT132 with AVO" },
X	{ "\033[?4;3c",   "VT132 with AVO and STP" },
X	{ "\033[?4;6c",   "VT132 with GPO and AVO" },
X	{ "\033[?4;7c",   "VT132 with GPO, AVO, and STP" },
X	{ "\033[?4;11c",  "VT132 with PP and AVO" },
X	{ "\033[?4;15c",  "VT132 with PP, GPO and AVO" },
X	{ "\033[?7c",     "VT131" },
X	{ "\033[?12;5c",  "VT125" },           /* VT125 also has ROM version */
X	{ "\033[?12;7c",  "VT125 with AVO" },  /* number, so this won't work */
X	{ "\033[?5;0c",   "VK100 (GIGI)" },
X	{ "\033[?5c",     "VK100 (GIGI)" },
X	{ "", "" }
X  };
X
X#ifdef UNIX
X  sgttyNew.sg_flags &= ~ECHO;
X  stty(0, &sgttyNew);
X#endif
X  cup(5,1);
X  println("This is a test of the ANSWERBACK MESSAGE. (To load the A.B.M.");
X  println("see the TEST KEYBOARD part of this program). Below here, the");
X  println("current answerback message in your terminal should be");
X  println("displayed. Finish this test with RETURN.");
X  cup(10,1);
X  inflush();
X  printf("%c", 5); /* ENQ */
X  report = instr();
X  cup(10,1);
X  chrprint(report);
X  cup(12,1);
X  holdit();
X
X  ed(2);
X  cup(1,1);
X  println("Test of LineFeed/NewLine mode.");
X  cup(3,1);
X  sm("20");
X#ifdef UNIX
X  sgttyNew.sg_flags &= ~CRMOD;
X  stty(0, &sgttyNew);
X#endif
X  printf("NewLine mode set. Push the RETURN key: ");
X  report = instr();
X  cup(4,1);
X  el(0);
X  chrprint(report);
X  if (!strcmp(report, "\015\012")) printf(" -- OK");
X  else				   printf(" -- Not expected");
X  cup(6,1);
X  rm("20");
X  printf("NewLine mode reset. Push the RETURN key: ");
X  report = instr();
X  cup(7,1);
X  el(0);
X  chrprint(report);
X  if (!strcmp(report, "\015")) printf(" -- OK");
X  else			   printf(" -- Not expected");
X  cup(9,1);
X#ifdef UNIX
X  sgttyNew.sg_flags |= CRMOD;
X  stty(0, &sgttyNew);
X#endif
X  holdit();
X
X  ed(2);
X  cup(1,1);
X  printf("Test of Device Status Report 5 (report terminal status).");
X  cup(2,1);
X  dsr(5);
X  report = instr();
X  cup(2,1);
X  el(0);
X  printf("Report is: ");
X  chrprint(report);
X  if	  (!strcmp(report,"\033[0n")) printf(" -- means \"TERMINAL OK\"");
X  else if (!strcmp(report,"\033[3n")) printf(" -- means \"TERMINAL OK\"");
X  else				  printf(" -- Unknown response!");
X
X  cup(4,1);
X  println("Test of Device Status Report 6 (report cursor position).");
X  cup(5,1);
X  dsr(6);
X  report = instr();
X  cup(5,1);
X  el(0);
X  printf("Report is: ");
X  chrprint(report);
X  if (!strcmp(report,"\033[5;1R")) printf(" -- OK");
X  else				   printf(" -- Unknown response!");
X
X  cup(7,1);
X  println("Test of Device Attributes report (what are you)");
X  cup(8,1);
X  da(0);
X  report = instr();
X  cup(8,1);
X  el(0);
X  printf("Report is: ");
X  chrprint(report);
X  for (i = 0; *attributes[i][0] != '\0'; i++) {
X	if (!strcmp(report,attributes[i][0])) break;
X  }
X  if (*attributes[i][0] == '\0')
X  printf(" -- Unknown response, refer to the manual");
X  else {
X	printf(" -- means %s", attributes[i][1]);
X	if (i) {
X  cup(9,1);
X  println("Legend: STP = Processor Option");
X  println("        AVO = Advanced Video Option");
X  println("        GPO = Graphics Processor Option");
X  println("        PP  = Printer Port");
X	}
X  }
X
X  cup(14,1);
X  println("Test of the \"Request Terminal Parameters\" feature, argument 0.");
X  cup(15,1);
X  decreqtparm(0);
X  report = instr();
X  cup(15,1);
X  el(0);
X  printf("Report is: ");
X  chrprint(report);
X  if (strlen(report) < 16
X   || report[0] != '\033'
X   || report[1] != '['
X   || report[2] != '2'
X   || report[3] != ';')
X  println(" -- Bad format");
X  else {
X	reportpos = 4;
X	parity = scanto(report, &reportpos, ';');
X	nbits  = scanto(report, &reportpos, ';');
X	xspeed = scanto(report, &reportpos, ';');
X	rspeed = scanto(report, &reportpos, ';');
X	clkmul = scanto(report, &reportpos, ';');
X	flags  = scanto(report, &reportpos, 'x');
X	if (parity == 0 || nbits == 0 || clkmul == 0) println(" -- Bad format");
X	else					  println(" -- OK");
X	printf(
X	"This means: Parity %s, %s bits, xmitspeed %s, recvspeed %s.\n",
X	lookup(paritytable, parity),
X	lookup(nbitstable, nbits),
X	lookup(speedtable, xspeed),
X	lookup(speedtable, rspeed));
X	printf("(CLoCk MULtiplier = %d, STP option flags = %d)\n", clkmul, flags);
X  }
X
X  cup(19,1);
X  println("Test of the \"Request Terminal Parameters\" feature, argument 1.");
X  cup(20,1);
X  decreqtparm(1); /* Does the same as decreqtparm(0), reports "3" */
X  report2 = instr();
X  cup(20,1);
X  el(0);
X  printf("Report is: ");
X  chrprint(report2);
X  if (strlen(report2) < 3
X   || report2[2] != '3')
X  println(" -- Bad format");
X  else {
X	report2[2] = '2';
X	if (!strcmp(report,report2)) println(" -- OK");
X	else			 println(" -- Bad format");
X  }
X  cup(24,1);
X  holdit();
X#ifdef UNIX
X  sgttyNew.sg_flags |= ECHO;
X  stty(0, &sgttyNew);
X#endif
X}
X
Xtst_vt52() {
X
X  static struct rtabl {
X  char *rcode;
X  char *rmsg;
X  } resptable[] = {
X  { "\033/K", " -- OK (means Standard VT52)" },
X  { "\033/Z", " -- OK (means VT100 emulating VT52)" },
X  { "",       " -- Unknown response"}
X  };
X
X  int i,j;
X  char *response;
X
X  rm("?2");  /* Reset ANSI (VT100) mode, Set VT52 mode        */
X  esc("H");  /* Cursor home   */
X  esc("J");  /* Erase to end of screen        */
X  esc("H");  /* Cursor home   */
X  for (i = 0; i <= 23; i++) {
X	for (j = 0; j <= 9; j++)
X	printf("%s", "FooBar ");
X	println("Bletch");
X  }
X  esc("H");  /* Cursor home   */
X  esc("J");  /* Erase to end of screen        */
X
X  vt52cup(7,47);
X  printf("nothing more.");
X  for (i = 1; i <= 10; i++) printf("THIS SHOULD GO AWAY! ");
X  for (i = 1; i <= 5; i++) {
X	vt52cup(1,1);
X	printf("%s", "Back scroll (this should go away)");
X	esc("I");                 /* Reverse LineFeed (with backscroll!)  */
X  }
X  vt52cup(12,60);
X  esc("J");  /* Erase to end of screen        */
X  for (i = 2; i <= 6; i++) {
X	vt52cup(i,1);
X	esc("K");         /* Erase to end of line */
X  }
X
X  for (i = 2; i <= 23; i++) {
X	vt52cup(i,70); printf("%s", "**Foobar");
X  }
X  vt52cup(23,10);
X  for (i = 23; i >= 2; i--) {
X	printf("%s", "*");
X	printf("%c", 8);  /* BS */
X	esc("I");         /* Reverse LineFeed (LineStarve)        */
X  }
X  vt52cup(1,70);
X  for (i = 70; i >= 10; i--) {
X	printf("%s", "*");
X	esc("D"); esc("D");       /* Cursor Left */
X  }
X  vt52cup(24,10);
X  for (i = 10; i <= 70; i++) {
X	printf("%s", "*");
X	printf("%c", 8);  /* BS */
X	esc("C");         /* Cursor Right */
X  }
X  vt52cup(2,11);
X  for (i = 2; i <= 23; i++) {
X	printf("%s", "!");
X	printf("%c", 8);  /* BS */
X	esc("B");         /* Cursor Down  */
X  }
X  vt52cup(23,69);
X  for (i = 23; i >= 2; i--) {
X	printf("%s", "!");
X	printf("%c", 8);  /* BS */
X	esc("A");         /* Cursor Up    */
X  }
X  for (i = 2; i <= 23; i++) {
X	vt52cup(i,71);
X	esc("K");         /* Erase to end of line */
X  }
X
X  vt52cup(10,16);
X  printf("%s", "The screen should be cleared, and have a centered");
X  vt52cup(11,16);
X  printf("%s", "rectangle of \"*\"s with \"!\"s on the inside to the");
X  vt52cup(12,16);
X  printf("%s", "left and right. Only this, and");
X  vt52cup(13,16);
X  holdit();
X
X  esc("H");  /* Cursor home   */
X  esc("J");  /* Erase to end of screen        */
X  printf("%s", "This is the normal character set:");
X  for (j =	0; j <=  1; j++) {
X	vt52cup(3 + j, 16);
X	for (i = 0; i <= 47; i++)
X	printf("%c", 32 + i + 48 * j);
X  }
X  vt52cup(6,1);
X  printf("%s", "This is the special graphics character set:");
X  esc("F");   /* Select Special Graphics character set        */
X  for (j =	0; j <=  1; j++) {
X	vt52cup(8 + j, 16);
X	for (i = 0; i <= 47; i++)
X	printf("%c", 32 + i + 48 * j);
X  }
X  esc("G");   /* Select ASCII character set   */
X  vt52cup(12,1);
X  holdit();
X
X  esc("H");  /* Cursor home   */
X  esc("J");  /* Erase to end of screen        */
X  println("Test of terminal response to IDENTIFY command");
X  esc("Z");   /* Identify     */
X  response = instr();
X  println("");
X  printf("Response was");
X  esc("<");  /* Enter ANSI mode (VT100 mode) */
X  chrprint(response);
X  for(i = 0; resptable[i].rcode[0] != '\0'; i++)
X	if (!strcmp(response, resptable[i].rcode))
X  break;
X  printf("%s", resptable[i].rmsg);
X  println("");
X  println("");
X  holdit();
X}
X
Xtst_insdel() {
X
X	/* Test of:
X   SM/RM(4) (= IRM (Insertion/replacement mode))
X   ICH (Insert Character)
X   DCH (Delete character)
X   IL  (Insert line)
X   DL  (Delete line)
X	*/
X
X  int i, row, col, sw, dblchr, scr132;
X
X  for(scr132 = 0; scr132 <= 1; scr132++) {
X	if (scr132) { sm("?3"); sw = 132; }
X	else	{ rm("?3"); sw =  80; }
X	ed(2);
X	cup(1,1);
X	for (row=1; row<=24; row++) {
X  cup(row,1);
X  for (col=1; col<=sw; col++)
X	  printf("%c", 'A'-1+row);
X	}
X	cup(4,1);
X	printf("Screen accordion test (Insert & Delete Line). "); holdit();
X	ri(); el(2);
X	decstbm( 2,23);
X	sm("?6");
X	cup(1,1);
X	for (row=1; row<=24; row++) {
X  il(row);
X  dl(row);
X	}
X	rm("?6");
X	decstbm( 0, 0);
X	cup(2,1);
X	printf(
X	"Top line: A's, bottom line: X's, this line, nothing more. ");
X	holdit();
X	cup(2,1); ed(0);
X	cup(1,2);
X	printf("B");
X	cub(1);
X	sm("4");
X	for (col=2; col<=sw-1; col++)
X  printf("*");
X	rm("4");
X	cup(4,1);
X	printf("Test of 'Insert Mode'. The top line should be 'A*** ... ***B'. ");
X	holdit(); ri(); el(2);
X	cup(1,2);
X	dch(sw-2);
X	cup(4,1);
X	printf("Test of 'Delete Character'. The top line should be 'AB'. ");
X	holdit();
X
X	for(dblchr = 1; dblchr <= 2; dblchr++) {
X  ed(2);
X  for (row=1; row<=24; row++) {
X  cup(row,1);
X  if (dblchr == 2) decdwl();
X  for (col=1; col<=sw/dblchr; col++)
X	printf("%c", 'A'-1+row);
X  cup(row,sw/dblchr-row);
X  dch(row);
X  }
X  cup(4,1);
X  println("The right column should be staggered ");
X  printf("by one.  ");
X  holdit();
X	}
X	ed(2);
X	cup(1,1);
X	println("If your terminal has the ANSI 'Insert Character' function");
X	println("(the VT102 does not), then you should see a line like this");
X	println("  A B C D E F G H I J K L M N O P Q R S T U V W X Y Z");
X	println("below:");
X	println("");
X	for (i = 'Z'; i >= 'A'; i--) {
X  printf("%c\010",i);
X  ich(2);
X	}
X	cup(10,1);
X	holdit();
X
X	if (sw == 132) rm("?3");
X  }
X}
X
Xdch(pn) int pn; { brc(pn, 'P'); }  /* Delete character */
Xich(pn) int pn; { brc(pn, '@'); }  /* Insert character -- not in VT102 */
Xdl(pn)	int pn; { brc(pn, 'M'); }  /* Delete line */
Xil(pn)	int pn; { brc(pn, 'L'); }  /* Insert line */
X
X/*	Test of some known VT100 bugs and misfeatures  */
X
Xtst_bugs() {
X
X  int i, menuchoice;
X
X  static char *menutable[] = {
X	"Exit to main menu",
X	"Bug A: Smooth scroll to jump scroll",
X	"Bug B: Scrolling region",
X	"Bug C: Wide to narrow screen",
X	"Bug D: Narrow to wide screen",
X	"Bug E: Cursor move from double- to single-wide line",
X	"Bug F: Column mode escape sequence",
X	"Wrap around with cursor addressing",
X	"Erase right half of double width lines",
X	"Funny scroll regions",
X	/* Add more here */
X	""
X  };
X
X  static char *hmsg[] = {
X  "Test of known bugs in the DEC VT100 series. The numbering of some of",
X  "the bugs (A-F) refers to the article 'VT100 MAGIC' by Sami Tabih in",
X  "the 'Proceedings of the DEC Users Society' at St. Louis, Missouri, May",
X  "1983. To understand some of the tests, you have to look at the source",
X  "code or the article. Of course, a good VT100-compatible terminal",
X  "should not have these bugs (or have some means of disabling them)! If",
X  "a bug appears, you might want to RESET the terminal before continuing",
X  "the test. There is a test of the RESET function in the main menu.",
X  "" };
X
X  do {
X	ed(2); cup(1,1);
X	for (i = 0; *hmsg[i]; i++) println(hmsg[i]);
X	println("");
X	println("          Choose bug test number:");
X	menuchoice = menu(menutable);
X	switch (menuchoice) {
X  case	1:	bug_a();  break;
X  case	2:	bug_b();  break;
X  case	3:	bug_c();  break;
X  case	4:	bug_d();  break;
X  case	5:	bug_e();  break;
X  case	6:	bug_f();  break;
X  case	7:	bug_w();  break;
X  case	8:	bug_l();  break;
X  case	9:	bug_s();  break;
X	}
X  } while (menuchoice);
X}
X
X/* Bug A: Smooth scroll to jump scroll */
X
Xbug_a() {
X  int i;
X
X  cup (10, 1);
X  println("This is a test of the VT100 'Scroll while toggle softscroll'");
X  println("bug.  The cursor may disappear, or move UP the screen, or");
X  println("multiple copies of some lines may appear.");
X  holdit();
X
X  /*  Invoke the bug  */
X
X  esc ("[24H");                               /* Simplified cursor movement
X*/
X  rm("?4"); for (i = 1; i <= 20; i++) printf("\n");
X  sm("?4"); for (i = 1; i <= 10; i++) printf("\n");
X  rm("?4"); for (i = 1; i <=  5; i++) printf("\n");
X
X  /* That should be enough to show the bug. But we'll try another way:
X*/
X  sm ("?4");                          /* Set soft scroll              */
X  nel ();			  /* "NextLine", move down        */
X  rm ("?4");                          /* Reset soft scroll            */
X  nel ();			  /* "NextLine", move down        */
X  for (i = 1; i <= 10; i++) {	  /* Show the bug		  */
X  printf ("Softscroll bug test, line %d.  ", i);
X  holdit();
X  }
X  println("That should have been enough to show the bug, if present.");
X  holdit();
X}
X
X/*	Bug B: Scrolling region  */
X
Xbug_b() {
X  char c;
X
X  decaln();
X  cup( 1,1); el(0);
X  printf("Line 11 should be double-wide, line 12 should be cleared.");
X  cup( 2,1); el(0);
X  printf("Then, the letters A-P should be written at the beginning");
X  cup( 3,1); el(0);
X  printf("of lines 12-24, and the empty line and A-E are scrolled away.");
X  cup( 4,1); el(0);
X  printf("If the bug is present, some lines are confused, look at K-P.");
X  cup(11,1); decdwl();
X  decstbm(12,24);
X  cup(12,1); el(0); printf("Here we go... "); holdit();
X  cup(12,1); ri();					  /* Bug comes here */
X  for (c = 'A'; c <= 'P'; c++) printf("%c\n",c);      /* Bug shows here */
X  holdit();
X  decstbm(0,0); 					  /* No scr. region */
X}
X
X/*	Bug C: Wide to narrow screen  */
X
Xbug_c() {
X  sm("?3");                                           /* 132 column mode */
X  cup(1,81);
X  rm("?3");                                           /*  80 column mode */
X  cup(12,5);
X  printf("Except for this line, the screen should be blank. ");
X  holdit();
X}
X
X/*	Bug D: Narrow to wide screen  */
X
Xbug_d() {
X  int i;
X  char result;
X  /* Make the bug appear */
X  do {
X	cup(14,1);
X
X	/* The original code in the article says
X	 * PRINT ESC$; "[13;1H"; CHR$(10%);
X	 * but I guess a cup(14,1); would do.
X	 * (To output a pure LF might be tricky).
X	 */
X
X	sm("?3");               /* Make the bug visible */
X	cup(1,9); decdwl();
X	println("You should see blinking text at the bottom line.");
X	cup(3,9); decdwl();
X	println("Enter 0 to exit, 1 to try to invoke the bug again.");
X	cup(24,9); decdwl(); sgr("1;5;7");
X	printf("If you can see this then the bug did not appear."); sgr("");
X	cup(4,9); decdwl();
X	result = inchar(); readnl();
X	rm("?3");
X  } while (result == '1');
X  sm("?4");   /* Syrup scroll */
X  cup(23,1);
X  for (i = 1; i <= 5; i++)
X  println("If the bug is present, this should make things much worse!");
X  holdit();
X  rm("?4");   /* Jump scroll */
X}
X
X/*	Bug E: Cursor move from double- to single-wide line  */
X
Xbug_e() {
X  int i;
X  static char *rend[2] = { "\033[m", "\033[7m" };
X  sm("?3");
X  cup(1,1); decdwl();
X  println("This test should put an 'X' at line 3 column 100.");
X  for (i = 1; i <= 12; i++) printf("1234567890%s",rend[i & 1]);
X  cup(1,1);   /* The bug appears when we jump from a dobule-wide line */
X  cup(3,100); /* to a single-wide line, column > 66.		  */
X  printf("X");
X  cup(4, 66); printf("!                                 !");
X  cup(5,1);
X  printf("--------------------------- The 'X' should NOT be above here -");
X  printf("---+------------ but above here -----+");
X  cup(10,1); decdwl(); holdit();
X  rm("?3");
X}
X
X/*	Bug F: Column mode escape sequence	*/
X
Xbug_f() {
X  int i, row, col;
X
X /*
X  *  VT100 "toggle origin mode, forget rest" bug.  If you try to set
X  *   (or clear) parameters and one of them is the "origin mode"
X  *   ("?6") parameter, parameters that appear after the "?6"
X  *   remain unaffected.  This is also true on CIT-101 terminals.
X  */
X  sm ("?5");                          /* Set reverse mode             */
X  sm ("?3");                          /* Set 132 column mode          */
X  println("Test VT100 'Toggle origin mode, forget rest' bug, part 1.");
X  println("The screen should be in reverse, 132 column mode.");
X  holdit();
X  ed (2);
X  rm ("?6;5;3");              /* Reset (origin, reverse, 132 col)     */
X  println("Test VT100 'Toggle origin mode, forget rest' bug, part 2.\n");
X  println("The screen should be in non-reverse, 80 column mode.");
X  holdit();
X}
X
X  /*  Bug W:
X   *  The dreaded "wraparound" bug!  You CUP to col 80, write a char,
X   *  CUP to another line in col 80, write a char. And the brain-damaged
X   *  terminal thinks that "Hokay, so he's written a char in col 80, so
X   *  I stay in col 80 and wait for next character. Let's see now, here
X   *  comes another character, and I'm still in col 80, so I must make
X   *  a NewLine first." -- It doesn't clear that "still in col 80" flag
X   *  on a CUP. Argh!
X   */
X
Xbug_w() {
X  int row, col;
X
X  cup (16,1);
X  println("   This illustrates the \"wrap around bug\" which exists on a");
X  println("   standard VT100. At the top of the screen there should be");
X  println("   a row of +'s, and the rightmost column should be filled");
X  println("   with *'s. But if the bug is present, some of the *'s may");
X  println("   be placed in other places, e.g. in the leftmost column,");
X  println("   and the top line of +'s may be scrolled away.");
X
X  cup(1,1);
X  for (col = 1; col <= 79; col++)
X  printf ("+");
X  for (row = 1; row <= 24; row++) {
X  hvp (row, 80);
X  printf ("*");
X  }
X  cup(24,1);
X  holdit();
X}
X
X  /*  Bug L:
X   *  Check if the right half of double-width lines comes back
X   *  when a line is first set to single-width, filled with stuff,
X   *  set to double-width, and finally reset to single-width.
X   *
X   *  A VT100 has this misfeature, and many others. Foo!
X   */
X
Xbug_l() {
X  cup(15, 1);
X  printf("This-is-a-long-line-This-is-a-long-line-");
X  printf("This-is-a-long-line-This-is-a-long-line-");
X  cup(1, 1);
X  printf("This is a test of what happens to the right half of double-width");
X  println(" lines.");
X  printf("A common misfeature is that the right half does not come back");
X  println(" when a long");
X  printf("single-width line is set to double-width and then reset to");
X  println(" single-width.");
X
X  cup(5, 1);
X  println("Now the line below should contain 80 characters in single width.");
X  holdit();
X  cup(15, 1); decdwl();
X  cup(8, 1);
X  println("Now the line below should contain 40 characters in double width.");
X  holdit();
X  cup(15, 1); decswl();
X  cup(11, 1);
X  println("Now the line below should contain 80 characters in single width.");
X  holdit();
X
X  /* ...and in 132 column mode	*/
X
X  sm("?3");
X  ed(2);
X  cup(15, 1);
X  printf("This-is-a-long-line-This-is-a-long-line-");
X  printf("This-is-a-long-line-This-is-a-long-line-");
X  printf("This-is-a-long-line-This-is-a-long-line-");
X  printf("ending-here-");
X
X  cup(1, 1);
X  printf("This is the same test in 132 column mode.");
X
X  cup(5, 1);
X  println("Now the line below should contain 132 characters in single width.");
X  holdit();
X  cup(15, 1); decdwl();
X  cup(8, 1);
X  println("Now the line below should contain 66 characters in double width.");
X  holdit();
X  cup(15, 1); decswl();
X  cup(11, 1);
X  println("Now the line below should contain 132 characters in single width.");
X  holdit();
X  rm("?3");
X}
X
Xbug_s() {
X  int i;
X  decstbm(20,10); /* 20-10=-10, < 2, so no scroll region. */
X  cup(1,1);
X  for (i=1; i<=20; i++)
X	printf("This is 20 lines of text (line %d), no scroll region.\n", i);
X  holdit();
X  ed(2);
X  decstbm(0,1); 	  /* Should be interpreted as decstbm(1,1) = none */
X  cup(1,1);
X  for (i=1; i<=20; i++)
X	printf("This is 20 lines of text (line %d), no scroll region.\n", i);
X  holdit();
X  decstbm(0,0); 	  /* No scroll region (just in case...)   */
X}
X
Xtst_rst() {
X
X  /*
X   * Test of
X   *  - RIS    (Reset to Initial State)
X   *  - DECTST (invoke terminal test)
X   */
X
X  cup(10,1);
X  printf ("The terminal will now be RESET. ");
X  holdit();
X  ris();
X#ifdef UNIX
X  fflush(stdout);
X#endif
X  zleep(5000);		  /* Wait 5.0 seconds */
X  cup(10,1);
X  println("The terminal is now RESET. Next, the built-in confidence test");
X  printf("%s", "will be invoked. ");
X  holdit();
X  ed(2);
X  dectst(1);
X#ifdef UNIX
X  fflush(stdout);
X#endif
X  zleep(5000);		  /* Wait 5.0 seconds */
X  cup(10,1);
X  println("If the built-in confidence test found any errors, a code");
X  printf("%s", "is visible above. ");
X  holdit();
X}
X
Xinitterminal(pn) int pn; {
X
X#ifdef UNIX
X  if (pn==0) {
X	fflush(stdout);
X	gtty(0,&sgttyOrg);
X	gtty(0,&sgttyNew);
X	sgttyNew.sg_flags |= CBREAK;
X	}
X  else	{
X	fflush(stdout);
X	inflush();
X	sleep(2);
X	sgttyNew.sg_flags = sgttyOrg.sg_flags | CBREAK;
X	}
X  stty(0,&sgttyNew);
X#ifdef SIII
X  close(2);
X  open("/dev/tty",O_RDWR|O_NDELAY);
X#endif
X#endif
X#ifdef SARG10
X  /* Set up neccesary TOPS-10 terminal parameters */
X
X  trmop(02041, `VT100`);  /* tty type vt100   */
X  trmop(02002, 0);	  /* tty no tape  */
X  trmop(02003, 0);	  /* tty lc   */
X  trmop(02005, 1);	  /* tty tab  */
X  trmop(02010, 1);	  /* tty no crlf  */
X  trmop(02020, 0);	  /* tty no tape  */
X  trmop(02021, 1);	  /* tty page */
X  trmop(02025, 0);	  /* tty blanks   */
X  trmop(02026, 1);	  /* tty no alt   */
X  trmop(02040, 1);	  /* tty defer	  */
X#endif
X#ifdef SARG20
X  ttybin(1);  /* set line to binary mode */
X#endif
X  /* Set up my personal prejudices	  */
X
X  esc("<");   /* Enter ANSI mode (if in VT52 mode)    */
X  rm("?1");     /* cursor keys normal   */
X  rm("?3");   /* 80 col mode          */
X  rm("?4");     /* Jump scroll          */
X  rm("?5");     /* Normal screen        */
X  rm("?6");   /* Absolute origin mode */
X  sm("?7");   /* Wrap around on       */
X  rm("?8");   /* Auto repeat off      */
X  decstbm(0,0);   /* No scroll region */
X  sgr("0");     /* Normal character attributes  */
X
X}
X
Xbye () {
X  /* Force my personal prejudices upon the poor luser */
X
X  esc("<");   /* Enter ANSI mode (if in VT52 mode)    */
X  rm("?1");     /* cursor keys normal   */
X  rm("?3");   /* 80 col mode          */
X  rm("?5");     /* Normal screen        */
X  rm("?6");   /* Absolute origin mode */
X  sm("?7");   /* Wrap around on       */
X  sm("?8");   /* Auto repeat on       */
X  decstbm(0,0);   /* No scroll region */
X  sgr("0");     /* Normal character attributes  */
X
X  /* Say goodbye */
X
X  ed(2);
X  cup(12,30);
X  printf("That's all, folks!\n");
X  printf("\n\n\n");
X  inflush();
X#ifdef SARG20
X  ttybin(0);  /* reset line to normal mode */
X#endif
X#ifdef UNIX
X  stty(0,&sgttyOrg);
X#endif
X  exit();
X}
X
X#ifdef UNIX
Xonbrk() {
X  signal(SIGINT, onbrk);
X  if (reading)
X	brkrd = 1;
X  else
X	longjmp(intrenv, 1);
X}
X
Xonterm() {
X  signal(SIGTERM, onterm);
X  longjmp(intrenv, 1);
X}
X#endif
X
Xholdit() {
X  inflush();
X  printf("Push <RETURN>");
X  readnl();
X}
X
Xreadnl() {
X#ifdef UNIX
X  char ch;
X  fflush(stdout);
X  brkrd = 0;
X  reading = 1;
X  do { read(0,&ch,1); } while(ch != '\n' && !brkrd);
X  if (brkrd)
X	kill(getpid(), SIGTERM);
X  reading = 0;
X#endif
X#ifdef SARG10
X while (getchar() != '\n')
X ;
X#endif
X#ifdef SARG20
X while (getchar() != '\n')
X   ;
X#endif
X}
X
Xscanto(str, pos, toc) char *str; int *pos; char toc; {
X  char c;
X  int result = 0;
X
X  while (toc != (c = str[(*pos)++])) {
X	if (isdigit(c)) result = result * 10 + c - '0';
X	else break;
X  }
X  if (c == toc) return(result);
X  else		return(0);
X}
X
Xchar *lookup(t, k) struct table t[]; int k; {
X
X  int i;
X  for (i = 0; t[i].key != -1; i++) {
X	if (t[i].key == k) return(t[i].msg);
X  }
X  return("BAD VALUE");
X}
X
Xmenu(table) char *table[]; {
X
X  int i, tablesize, choice;
X  char c;
X  char storage[80];
X  char *s = storage;
X  println("");
X  tablesize = 0;
X  for (i = 0; *table[i] != '\0'; i++) {
X	printf("          %d. %s\n", i, table[i]);
X	tablesize++;
X  }
X  tablesize--;
X
X  printf("\n          Enter choice number (0 - %d): ", tablesize);
X  for(;;) {
X	inputline(s);
X	choice = 0;
X	while (c = *s++) choice = 10 * choice + c - '0';
X	if (choice >= 0 && choice <= tablesize) {
X  ed(2);
X  return (choice);
X	}
X	printf("          Bad choice, try again: ");
X  }
X}
X
Xchrprint (s) char *s; {
X
X  int i;
X
X  printf("  ");
X  sgr("7");
X  printf(" ");
X  for (i = 0; s[i] != '\0'; i++) {
X	if (s[i] <= ' ' || s[i] == '\177')
X	printf("<%d> ", s[i]);
X	else printf("%c ", s[i]);
X  }
X  sgr("");
X}
END_OF_vttest/main.c
if test 54655 -ne `wc -c <vttest/main.c`; then
    echo shar: \"vttest/main.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f vttest/read.me -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"vttest/read.me\"
else
echo shar: Extracting \"vttest/read.me\" \(2466 characters\)
sed "s/^X//" >vttest/read.me <<'END_OF_vttest/read.me'
XNOTES FROM THE MOD.SOURCES MODERATOR:
XI split the source up into the three separate pieces it now is.
XIn doing this, I put lines like "int reading;" in a header file
Xthat both C modules include.  If your Unix requires one of these
Xto be "extern int reading;" then you will have some editing to do.
XAlso note that this program uses FIONREAD, which must be implemented
Xdifferently in SystemV, etc., and check out the setjmp() call...
X      /Rich $alz
XOh, yeah:  I also wrote the Makefile and manpage, such as they are.
X-------------------------------------------------------------------
X
XThis is a program to test the compatibility (or to demonstrate the
Xnon-compatibility) of so-called "VT100-compatible" terminals. In
Xconformance of the good old hacker traditions, the only documentation
Xof this program is the source code itself. To understand it, you also
Xneed a copy of the original VT100 manual from DEC.
X
XComments and bug reports: Since this is a release (via USENET) to the
Xwhole world, a lot of people are going to have opinions and fresh
Xideas about it. (What -- bugs in MY program? Aww...)  I can't deal
Xwith everyone sending me a hacked version, but if you have found a
Xserious bug, or ported it to VMS, do tell me. I can't promise any new
Xversion release, though. From this version on (1.7b) VTTEST will have
Xto live its own life without its father holding its hand.
X
XMy adress is:
X
XNetwork-mail adress:	 (mcvax,seismo)!enea!suadb!lindberg
X
XReal-world-mail address: Per Lindberg
X			 QZ, Stockholm University Computing Center
X		       Box 27322
X		       S - 102 54  Stockholm
X		       SWEDEN
X
XThe original version of this program is written for the Sargasso C
Xcompiler for the DECsystem-10. Many thanks to all sales persons with
Xquote VT100-compatible unquote terminals, who prompted me to write
Xthis program, and also to:
X
X-- Bo Kleve, LIDAC, Linkoping University, Sweden
X   for the portation to DECSYSTEM-20 with the Sargasso C compiler
X
X-- Johan Widen, TTDS, Royal Institute of Technology, Stockholm, Sweden
X   for the portation to various UNIX systems (incl. System III and Xenix)
X
X-- Russ Herman, AES Data Inc., Missisauga, Ont. Canada
X   for fixes and code for the VT102 test
X
XThanx also to JMR "Gremlin" at KTH, and Goran Wallberg at QZ
Xfor suggestions, bug fixes, etc.
X
XThis program does not have support for all the different variations
Xof VT100, like VT125, VT131 nor the new VT200 series. Feel free to
Xadd that yourself. Happy Hacking!
X
X		 /TMP
END_OF_vttest/read.me
if test 2466 -ne `wc -c <vttest/read.me`; then
    echo shar: \"vttest/read.me\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f vttest/vttest.1 -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"vttest/vttest.1\"
else
echo shar: Extracting \"vttest/vttest.1\" \(351 characters\)
sed "s/^X//" >vttest/vttest.1 <<'END_OF_vttest/vttest.1'
X.TH VTTEST 1 "LOCAL"
X.SH NAME
Xvttest \- test VT100-type terminal
X.SH SYNOPSIS
X.B vttest
X.SH DESCRIPTION
X.I Vttest
Xis a program designed to test the functionality of a VT100 terminal
X(or emulator thereof).
XIt tests both display (escape sequence handling) and keyboard.
X.PP
XThe program is menu\-driven and contains full on\-line operating
Xinstructions.
END_OF_vttest/vttest.1
if test 351 -ne `wc -c <vttest/vttest.1`; then
    echo shar: \"vttest/vttest.1\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0
