diff options
Diffstat (limited to 'contrib/ncurses/test')
33 files changed, 11343 insertions, 0 deletions
diff --git a/contrib/ncurses/test/Makefile.in b/contrib/ncurses/test/Makefile.in new file mode 100644 index 0000000..3626f24 --- /dev/null +++ b/contrib/ncurses/test/Makefile.in @@ -0,0 +1,207 @@ +# $Id: Makefile.in,v 1.51 1999/04/10 21:31:59 tom Exp $ +############################################################################## +# Copyright (c) 1998 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. # +############################################################################## +# +# Author: Thomas E. Dickey <dickey@clark.net> 1996,1997,1998 +# +# Makefile for ncurses tests. + +# turn off _all_ suffix rules; we'll generate our own +.SUFFIXES: + +SHELL = /bin/sh + +x = @PROG_EXT@ + +MODEL = ../@DFT_OBJ_SUBDIR@ +srcdir = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +libdir = @libdir@ +includedir = @includedir@ + +CC = @CC@ + +CFLAGS = @CFLAGS@ +CPPFLAGS = -I../test -I$(srcdir) @CPPFLAGS@ -DHAVE_CONFIG_H + +CCFLAGS = $(CPPFLAGS) $(CFLAGS) + +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_LIBS = @TEST_DEPS@ +MATH_LIB = @MATH_LIB@ + +LD = @LD@ +LINK = @LINK_TESTS@ $(CC) + +LDFLAGS = @LD_MODEL@ @TEST_ARGS@ @LIBS@ @EXTRA_LIBS@ @LOCAL_LDFLAGS@ @LDFLAGS@ + +LDFLAGS_NORMAL = $(LDFLAGS) +LDFLAGS_DEBUG = $(LDFLAGS) @CC_G_OPT@ +LDFLAGS_PROFILE = $(LDFLAGS) -pg +LDFLAGS_SHARED = $(LDFLAGS) @LD_SHARED_OPTS@ + +LDFLAGS_DEFAULT = $(LDFLAGS_@DFT_UPR_MODEL@) + +LINT = @LINT@ +LINT_OPTS = @LINT_OPTS@ +LINT_LIBS = -lform -lmenu -lpanel -lncurses @LIBS@ + +TESTS = \ + blue$x \ + bs$x \ + cardfile$x \ + ditto$x \ + filter$x \ + firework$x \ + firstlast$x \ + gdc$x \ + hanoi$x \ + hashtest$x \ + keynames$x \ + knight$x \ + lrtest$x \ + ncurses$x \ + newdemo$x \ + rain$x \ + tclock$x \ + testaddch$x \ + testcurs$x \ + testscanw$x \ + view$x \ + worm$x \ + xmas$x + +all: $(TESTS) + +sources: + +blue$x: $(MODEL)/blue.o $(LOCAL_LIBS) + @ECHO_LINK@ $(LINK) -o $@ $(MODEL)/blue.o $(LDFLAGS_DEFAULT) + +bs$x: $(MODEL)/bs.o $(LOCAL_LIBS) + @ECHO_LINK@ $(LINK) -o $@ $(MODEL)/bs.o $(LDFLAGS_DEFAULT) + +cardfile$x: $(MODEL)/cardfile.o $(LOCAL_LIBS) + @ECHO_LINK@ $(LINK) -o $@ $(MODEL)/cardfile.o $(LDFLAGS_DEFAULT) + +ditto$x: $(MODEL)/ditto.o $(LOCAL_LIBS) + @ECHO_LINK@ $(LINK) -o $@ $(MODEL)/ditto.o $(LDFLAGS_DEFAULT) + +filter$x: $(MODEL)/filter.o $(LOCAL_LIBS) + @ECHO_LINK@ $(LINK) -o $@ $(MODEL)/filter.o $(LDFLAGS_DEFAULT) + +firework$x: $(MODEL)/firework.o $(LOCAL_LIBS) + @ECHO_LINK@ $(LINK) -o $@ $(MODEL)/firework.o $(LDFLAGS_DEFAULT) + +firstlast$x: $(MODEL)/firstlast.o $(LOCAL_LIBS) + @ECHO_LINK@ $(LINK) -o $@ $(MODEL)/firstlast.o $(LDFLAGS_DEFAULT) + +gdc$x: $(MODEL)/gdc.o $(LOCAL_LIBS) + @ECHO_LINK@ $(LINK) -o $@ $(MODEL)/gdc.o $(LDFLAGS_DEFAULT) + +hanoi$x: $(MODEL)/hanoi.o $(LOCAL_LIBS) + @ECHO_LINK@ $(LINK) -o $@ $(MODEL)/hanoi.o $(LDFLAGS_DEFAULT) + +hashtest$x: $(MODEL)/hashtest.o $(LOCAL_LIBS) + @ECHO_LINK@ $(LINK) -o $@ $(MODEL)/hashtest.o $(LDFLAGS_DEFAULT) + +keynames$x: $(MODEL)/keynames.o $(LOCAL_LIBS) + @ECHO_LINK@ $(LINK) -o $@ $(MODEL)/keynames.o $(LDFLAGS_DEFAULT) + +knight$x: $(MODEL)/knight.o $(LOCAL_LIBS) + @ECHO_LINK@ $(LINK) -o $@ $(MODEL)/knight.o $(LDFLAGS_DEFAULT) + +lrtest$x: $(MODEL)/lrtest.o $(LOCAL_LIBS) + @ECHO_LINK@ $(LINK) -o $@ $(MODEL)/lrtest.o $(LDFLAGS_DEFAULT) + +ncurses$x: $(MODEL)/ncurses.o $(LOCAL_LIBS) + @ECHO_LINK@ $(LINK) -o $@ $(MODEL)/ncurses.o $(LDFLAGS_DEFAULT) + +newdemo$x: $(MODEL)/newdemo.o $(LOCAL_LIBS) + @ECHO_LINK@ $(LINK) -o $@ $(MODEL)/newdemo.o $(LDFLAGS_DEFAULT) + +rain$x: $(MODEL)/rain.o $(LOCAL_LIBS) + @ECHO_LINK@ $(LINK) -o $@ $(MODEL)/rain.o $(LDFLAGS_DEFAULT) + +tclock$x: $(MODEL)/tclock.o $(LOCAL_LIBS) + @ECHO_LINK@ $(LINK) -o $@ $(MODEL)/tclock.o $(LDFLAGS_DEFAULT) $(MATH_LIB) + +testaddch$x: $(MODEL)/testaddch.o $(LOCAL_LIBS) + @ECHO_LINK@ $(LINK) -o $@ $(MODEL)/testaddch.o $(LDFLAGS_DEFAULT) + +testcurs$x: $(MODEL)/testcurs.o $(LOCAL_LIBS) + @ECHO_LINK@ $(LINK) -o $@ $(MODEL)/testcurs.o $(LDFLAGS_DEFAULT) + +testscanw$x: $(MODEL)/testscanw.o $(LOCAL_LIBS) + @ECHO_LINK@ $(LINK) -o $@ $(MODEL)/testscanw.o $(LDFLAGS_DEFAULT) + +view$x: $(MODEL)/view.o $(LOCAL_LIBS) + @ECHO_LINK@ $(LINK) -o $@ $(MODEL)/view.o $(LDFLAGS_DEFAULT) + +worm$x: $(MODEL)/worm.o $(LOCAL_LIBS) + @ECHO_LINK@ $(LINK) -o $@ $(MODEL)/worm.o $(LDFLAGS_DEFAULT) + +xmas$x: $(MODEL)/xmas.o $(LOCAL_LIBS) + @ECHO_LINK@ $(LINK) -o $@ $(MODEL)/xmas.o $(LDFLAGS_DEFAULT) + +install: +install.libs: +install.test: + +uninstall: +uninstall.libs: +uninstall.test: + +mostlyclean :: + -rm -f core tags TAGS *~ *.ln *.atac trace + +clean :: mostlyclean + -rm -rf *.o screendump *.lis $(TESTS) + +distclean :: clean + -rm -f Makefile ncurses_cfg.h config.* + +realclean :: distclean + +lint: + sh -c 'for N in $(TESTS); do echo LINT:$$N; $(LINT) $(LINT_OPTS) $(CPPFLAGS) $(srcdir)/$$N.c $(LINT_LIBS); done' + +# Use this to get a list of test-programs for the standalone configure script. +echo_tests : + @echo "$(TESTS)" +echo_suffix : + @echo "$x" diff --git a/contrib/ncurses/test/README b/contrib/ncurses/test/README new file mode 100644 index 0000000..cd1767a --- /dev/null +++ b/contrib/ncurses/test/README @@ -0,0 +1,22 @@ +The programs in this directory are designed to test your newest toy :-) +Check the sources for any further details. + +blue - Blue Moon, a nifty solitaire (uses color) +bs.c - the game of Battleships (uses color) +firework.c - multi-colored fireworks (uses color) +gdc.c - Great Digital Clock (uses color) +hanoi.c - the game of hanoi (uses color essentially) +knight.c - the game of Knight's Tour (uses color) +lrtest.c - test of access to the lower-right corner +ncurses.c - multi-test program (uses color) +newdemo.c - another test from PDCurses (uses color) +rain.c - rain drops keep falling on my head... +tclock.c - analog/digital clock +testcurs.c - a test from the PDCurses people (uses color) +worm.c - worms run all over your screen (uses color) +xmas.c - Xmas greeting card + +The bs and knight games demonstrate processing of mouse events under xterm. +This directory also contains: + +tracemunch - Perl script to crunch trace scripts to make them easier to read diff --git a/contrib/ncurses/test/blue.c b/contrib/ncurses/test/blue.c new file mode 100644 index 0000000..4f73351 --- /dev/null +++ b/contrib/ncurses/test/blue.c @@ -0,0 +1,440 @@ +/***************************************************************************** + * * + * B l u e M o o n * + * ================= * + * V2.2 * + * A patience game by T.A.Lister * + * Integral screen support by Eric S. Raymond * + * * + *****************************************************************************/ + +/* + * Compile this with the command `cc -O blue.c -lcurses -o blue'. For best + * results, use the ncurses(3) library. On non-Intel machines, SVr4 curses is + * just as good. + * + * $Id: blue.c,v 1.18 1999/01/17 00:11:56 tom Exp $ + */ + +#include <test.priv.h> + +#include <string.h> +#include <signal.h> +#include <time.h> + +#include <term.h> + +#define NOCARD (-1) + +#define ACE 0 +#define KING 12 +#define SUIT_LENGTH 13 + +#define HEARTS 0 +#define SPADES 1 +#define DIAMONDS 2 +#define CLUBS 3 +#define NSUITS 4 + +#define GRID_WIDTH 14 /* 13+1 */ +#define GRID_LENGTH 56 /* 4*(13+1) */ +#define PACK_SIZE 52 + +#define BASEROW 1 +#define PROMPTROW 11 + +#define RED_ON_WHITE 1 +#define BLACK_ON_WHITE 2 +#define BLUE_ON_WHITE 3 + +static RETSIGTYPE die(int onsig) GCC_NORETURN; + +static int deck_size = PACK_SIZE; /* initial deck */ +static int deck[PACK_SIZE]; + +static int grid[GRID_LENGTH]; /* card layout grid */ +static int freeptr[4]; /* free card space pointers */ + +static int deal_number=0; + +static chtype ranks[SUIT_LENGTH][2] = +{ + {' ', 'A'}, + {' ', '2'}, + {' ', '3'}, + {' ', '4'}, + {' ', '5'}, + {' ', '6'}, + {' ', '7'}, + {' ', '8'}, + {' ', '9'}, + {'1', '0'}, + {' ', 'J'}, + {' ', 'Q'}, + {' ', 'K'} +}; + +/* Please note, that this is a bad example. + Color values should not be or'ed in. This + only works, because the characters used here + are plain and have no color attribute themselves. */ +#ifdef COLOR_PAIR +#define OR_COLORS(value,pair) ((value) | COLOR_PAIR(pair)) +#else +#define OR_COLORS(value,pair) (value) +#endif + +#define PC_COLORS(value,pair) (OR_COLORS(value,pair) | A_ALTCHARSET) + +static chtype letters[4] = +{ + OR_COLORS('h', RED_ON_WHITE), /* hearts */ + OR_COLORS('s', BLACK_ON_WHITE), /* spades */ + OR_COLORS('d', RED_ON_WHITE), /* diamonds */ + OR_COLORS('c', BLACK_ON_WHITE), /* clubs */ +}; + +#if defined(__i386__) +static chtype glyphs[] = +{ + PC_COLORS('\003', RED_ON_WHITE), /* hearts */ + PC_COLORS('\006', BLACK_ON_WHITE), /* spades */ + PC_COLORS('\004', RED_ON_WHITE), /* diamonds */ + PC_COLORS('\005', BLACK_ON_WHITE), /* clubs */ +}; +#endif /* __i386__ */ + +static chtype *suits = letters; /* this may change to glyphs below */ + +static RETSIGTYPE die(int onsig) +{ + (void) signal(onsig, SIG_IGN); + endwin(); + exit(EXIT_SUCCESS); +} + +static void init_vars(void) +{ + int i; + + deck_size = PACK_SIZE; + for (i=0; i < PACK_SIZE; i++) + deck[i]=i; + for (i = 0; i < 4; i++) + freeptr[i]=i * GRID_WIDTH; +} + +static void shuffle(int size) +{ + int i,j,numswaps,swapnum,temp; + + numswaps=size*10; /* an arbitrary figure */ + + for (swapnum=0;swapnum<numswaps;swapnum++) + { + i=rand() % size; + j=rand() % size; + temp=deck[i]; + deck[i]=deck[j]; + deck[j]=temp; + } +} + +static void deal_cards(void) +{ + int ptr, card=0, value, csuit, crank, suit, aces[4]; + + for (suit=HEARTS;suit<=CLUBS;suit++) + { + ptr=freeptr[suit]; + grid[ptr++]=NOCARD; /* 1st card space is blank */ + while ((ptr % GRID_WIDTH) != 0) + { + value=deck[card++]; + crank=value % SUIT_LENGTH; + csuit=value / SUIT_LENGTH; + if (crank==ACE) + aces[csuit]=ptr; + grid[ptr++]=value; + } + } + + if (deal_number==1) /* shift the aces down to the 1st column */ + for (suit=HEARTS;suit<=CLUBS;suit++) + { + grid[suit * GRID_WIDTH] = suit * SUIT_LENGTH; + grid[aces[suit]]=NOCARD; + freeptr[suit]=aces[suit]; + } +} + +static void printcard(int value) +{ + (void) addch(' '); + if (value == NOCARD) + (void) addstr(" "); + else + { + addch(ranks[value % SUIT_LENGTH][0] | COLOR_PAIR(BLUE_ON_WHITE)); + addch(ranks[value % SUIT_LENGTH][1] | COLOR_PAIR(BLUE_ON_WHITE)); + addch(suits[value / SUIT_LENGTH]); + } + (void) addch(' '); +} + +static void display_cards(int deal) +{ + int row, card; + + clear(); + (void)printw( + "Blue Moon 2.1 - by Tim Lister & Eric Raymond - Deal %d.\n", + deal); + for(row=HEARTS;row<=CLUBS;row++) + { + move(BASEROW + row + row + 2, 1); + for(card=0;card<GRID_WIDTH;card++) + printcard(grid[row * GRID_WIDTH + card]); + } + + move(PROMPTROW + 2, 0); refresh(); +#define P(x) (void)printw("%s\n", x) +P(" This 52-card solitaire starts with the entire deck shuffled and dealt"); +P("out in four rows. The aces are then moved to the left end of the layout,"); +P("making 4 initial free spaces. You may move to a space only the card that"); +P("matches the left neighbor in suit, and is one greater in rank. Kings are"); +P("high, so no cards may be placed to their right (they create dead spaces)."); +P(" When no moves can be made, cards still out of sequence are reshuffled"); +P("and dealt face up after the ends of the partial sequences, leaving a card"); +P("space after each sequence, so that each row looks like a partial sequence"); +P("followed by a space, followed by enough cards to make a row of 14. "); +P(" A moment's reflection will show that this game cannot take more than 13"); +P("deals. A good score is 1-3 deals, 4-7 is average, 8 or more is poor. "); +#undef P + refresh(); +} + +static int find(int card) +{ + int i; + + if ((card<0) || (card>=PACK_SIZE)) + return(NOCARD); + for(i = 0; i < GRID_LENGTH; i++) + if (grid[i] == card) + return i; + return(NOCARD); +} + +static void movecard(int src, int dst) +{ + grid[dst]=grid[src]; + grid[src]=NOCARD; + + move( BASEROW + (dst / GRID_WIDTH)*2+2, (dst % GRID_WIDTH)*5 + 1); + printcard(grid[dst]); + + move( BASEROW + (src / GRID_WIDTH)*2+2, (src % GRID_WIDTH)*5 + 1); + printcard(grid[src]); + + refresh(); +} + +static void play_game(void) +{ + int dead=0, i, j; + char c; + int selection[4], card; + + while (dead<4) + { + dead=0; + for (i=0;i<4;i++) + { + card=grid[freeptr[i]-1]; + + if ( ((card % SUIT_LENGTH)==KING) + || + (card==NOCARD) ) + selection[i]=NOCARD; + else + selection[i]=find(card+1); + + if (selection[i]==NOCARD) + dead++; + }; + + if (dead < 4) + { + char live[NSUITS+1], *lp = live; + + for (i=0;i<4;i++) + { + if (selection[i] != NOCARD) + { + move(BASEROW + (selection[i] / GRID_WIDTH)*2+3, + (selection[i] % GRID_WIDTH)*5); + (void)printw(" %c ", *lp++ = 'a' + i); + } + }; + *lp = '\0'; + + if (strlen(live) == 1) + { + move(PROMPTROW,0); + (void)printw( + "Making forced moves... "); + refresh(); + (void) sleep(1); + c = live[0]; + } + else + { + char buf[BUFSIZ]; + + (void)sprintf(buf, + "Type [%s] to move, r to redraw, q or INTR to quit: ", + live); + + do { + move(PROMPTROW,0); + (void) addstr(buf); + move(PROMPTROW, (int)strlen(buf)); + clrtoeol(); + (void) addch(' '); + } while + (((c = getch())<'a' || c>'d') && (c!='r') && (c!='q')); + } + + for (j = 0; j < 4; j++) + if (selection[j]!=NOCARD) + { + move(BASEROW + (selection[j] / GRID_WIDTH)*2+3, + (selection[j] % GRID_WIDTH)*5); + (void)printw(" "); + } + + if (c == 'r') + display_cards(deal_number); + else if (c == 'q') + die(SIGINT); + else + { + i = c-'a'; + if (selection[i] == NOCARD) + beep(); + else + { + movecard(selection[i], freeptr[i]); + freeptr[i]=selection[i]; + } + } + } + } + + move(PROMPTROW, 0); + standout(); + (void)printw("Finished deal %d - type any character to continue...", deal_number); + standend(); + (void) getch(); +} + +static int collect_discards(void) +{ + int row, col, cardno=0, finish, gridno; + + for (row=HEARTS;row<=CLUBS;row++) + { + finish=0; + for (col=1;col<GRID_WIDTH;col++) + { + gridno=row * GRID_WIDTH + col; + + if ((grid[gridno]!=(grid[gridno-1]+1))&&(finish==0)) + { + finish=1; + freeptr[row]=gridno; + }; + + if ((finish!=0)&&(grid[gridno]!=NOCARD)) + deck[cardno++]=grid[gridno]; + } + } + return cardno; +} + +static void game_finished(int deal) +{ + clear(); + (void)printw("You finished the game in %d deals. This is ",deal); + standout(); + if (deal<2) + (void)addstr("excellent"); + else if (deal<4) + (void)addstr("good"); + else if (deal<8) + (void)addstr("average"); + else + (void)addstr("poor"); + standend(); + (void) addstr(". "); + refresh(); +} + +int main(int argc, char *argv[]) +{ + (void) signal(SIGINT, die); + initscr(); + + /* + * We use COLOR_GREEN because COLOR_BLACK is wired to the wrong thing. + */ + start_color(); + init_pair(RED_ON_WHITE, COLOR_RED, COLOR_WHITE); + init_pair(BLUE_ON_WHITE, COLOR_BLUE, COLOR_WHITE); + init_pair(BLACK_ON_WHITE, COLOR_BLACK, COLOR_WHITE); + +#ifndef COLOR_PAIR + letters[0] = OR_COLORS('h', RED_ON_WHITE); /* hearts */ + letters[1] = OR_COLORS('s', BLACK_ON_WHITE); /* spades */ + letters[2] = OR_COLORS('d', RED_ON_WHITE); /* diamonds */ + letters[3] = OR_COLORS('c', BLACK_ON_WHITE); /* clubs */ +#if defined(__i386__) && defined(A_ALTCHARSET) + glyphs[0] = PC_COLORS('\003', RED_ON_WHITE); /* hearts */ + glyphs[1] = PC_COLORS('\006', BLACK_ON_WHITE); /* spades */ + glyphs[2] = PC_COLORS('\004', RED_ON_WHITE); /* diamonds */ + glyphs[3] = PC_COLORS('\005', BLACK_ON_WHITE); /* clubs */ +#endif +#endif + +#if defined(__i386__) && defined(A_ALTCHARSET) + if (tigetstr("smpch")) + suits = glyphs; +#endif /* __i386__ && A_ALTCHARSET */ + + cbreak(); + + if (argc == 2) + srand((unsigned)atoi(argv[1])); + else + srand((unsigned)time((time_t *)0)); + + init_vars(); + + do{ + deal_number++; + shuffle(deck_size); + deal_cards(); + display_cards(deal_number); + play_game(); + } + while + ((deck_size=collect_discards()) != 0); + + game_finished(deal_number); + + die(SIGINT); + /*NOTREACHED*/ +} + +/* blue.c ends here */ diff --git a/contrib/ncurses/test/bs.6 b/contrib/ncurses/test/bs.6 new file mode 100644 index 0000000..38cfe82 --- /dev/null +++ b/contrib/ncurses/test/bs.6 @@ -0,0 +1,42 @@ +.TH BATTLESHIPS 6 "Aug 23, 1989" +.SH NAME +bs \- battleships game +.SH SYNOPSIS +battle [ -b | -s ] [ -c ] +.SH DESCRIPTION +This program allows you to play the familiar Battleships game against the +computer on a 10x10 board. The interface is visual and largely +self-explanatory; you place your ships and pick your shots by moving the +cursor around the `sea' with the rogue/hack motion keys hjklyubn. +.PP +Note that when selecting a ship to place, you must type the capital letter +(these are, after all, capital ships). During ship placement, the `r' command +may be used to ignore the current position and randomly place your currently +selected ship. The `R' command will place all remaining ships randomly. The ^L +command (form feed, ASCII 12) will force a screen redraw). +.PP +The command-line arguments control game modes. + +.nf + -b selects a `blitz' variant + -s selects a `salvo' variant + -c permits ships to be placed adjacently +.fi + +The `blitz' variant allows a side to shoot for as long as it continues to +score hits. +.PP +The `salvo' game allows a player one shot per turn for each of his/her ships +still afloat. This puts a premium scoring hits early and knocking out some +ships and also makes much harder the situation where you face a superior force +with only your PT-boat. +.PP +Normally, ships must be separated by at least one square of open water. The +-c option disables this check and allows them to close-pack. +.PP +The algorithm the computer uses once it has found a ship to sink is provably +optimal. The dispersion criterion for the random-fire algorithm may not be. +.SH AUTHORS +Originally written by one Bruce Holloway in 1986. Salvo mode added by Chuck A. +DeGaul (cbosgd!cad). Visual user interface, `closepack' option, code rewrite +and manual page by Eric S. Raymond <esr@snark.thyrsus.com> August 1989. diff --git a/contrib/ncurses/test/bs.c b/contrib/ncurses/test/bs.c new file mode 100644 index 0000000..368abcd --- /dev/null +++ b/contrib/ncurses/test/bs.c @@ -0,0 +1,1268 @@ +/* + * bs.c - original author: Bruce Holloway + * salvo option by: Chuck A DeGaul + * with improved user interface, autoconfiguration and code cleanup + * by Eric S. Raymond <esr@snark.thyrsus.com> + * v1.2 with color support and minor portability fixes, November 1990 + * v2.0 featuring strict ANSI/POSIX conformance, November 1993. + * v2.1 with ncurses mouse support, September 1995 + * + * $Id: bs.c,v 1.24 1999/08/21 23:14:38 tom Exp $ + */ + +#include <test.priv.h> + +#include <signal.h> +#include <ctype.h> +#include <string.h> +#include <assert.h> +#include <time.h> + +#ifndef SIGIOT +#define SIGIOT SIGABRT +#endif + +#ifndef A_UNDERLINE /* BSD curses */ +#define beep() write(1,"\007",1); +#define cbreak crmode +#define saveterm savetty +#define resetterm resetty +#define nocbreak nocrmode +#define strchr index +#endif /* !A_UNDERLINE */ + +static int getcoord(int); + +/* + * Constants for tuning the random-fire algorithm. It prefers moves that + * diagonal-stripe the board with a stripe separation of srchstep. If + * no such preferred moves are found, srchstep is decremented. + */ +#define BEGINSTEP 3 /* initial value of srchstep */ + +/* miscellaneous constants */ +#define SHIPTYPES 5 +#define OTHER (1-turn) +#define PLAYER 0 +#define COMPUTER 1 +#define MARK_HIT 'H' +#define MARK_MISS 'o' +#define CTRLC '\003' /* used as terminate command */ +#define FF '\014' /* used as redraw command */ + +/* coordinate handling */ +#define BWIDTH 10 +#define BDEPTH 10 + +/* display symbols */ +#define SHOWHIT '*' +#define SHOWSPLASH ' ' +#define IS_SHIP(c) (isupper(c) ? TRUE : FALSE) + +/* how to position us on player board */ +#define PYBASE 3 +#define PXBASE 3 +#define PY(y) (PYBASE + (y)) +#define PX(x) (PXBASE + (x)*3) +#define pgoto(y, x) (void)move(PY(y), PX(x)) + +/* how to position us on cpu board */ +#define CYBASE 3 +#define CXBASE 48 +#define CY(y) (CYBASE + (y)) +#define CX(x) (CXBASE + (x)*3) +#define CYINV(y) ((y) - CYBASE) +#define CXINV(x) (((x) - CXBASE) / 3) +#define cgoto(y, x) (void)move(CY(y), CX(x)) + +#define ONBOARD(x, y) (x >= 0 && x < BWIDTH && y >= 0 && y < BDEPTH) + +/* other board locations */ +#define COLWIDTH 80 +#define PROMPTLINE 21 /* prompt line */ +#define SYBASE CYBASE + BDEPTH + 3 /* move key diagram */ +#define SXBASE 63 +#define MYBASE SYBASE - 1 /* diagram caption */ +#define MXBASE 64 +#define HYBASE SYBASE - 1 /* help area */ +#define HXBASE 0 + +/* this will need to be changed if BWIDTH changes */ +static char numbers[] = " 0 1 2 3 4 5 6 7 8 9"; + +static char carrier[] = "Aircraft Carrier"; +static char battle[] = "Battleship"; +static char sub[] = "Submarine"; +static char destroy[] = "Destroyer"; +static char ptboat[] = "PT Boat"; + +static char name[40]; +static char dftname[] = "stranger"; + +/* direction constants */ +#define E 0 +#define SE 1 +#define S 2 +#define SW 3 +#define W 4 +#define NW 5 +#define N 6 +#define NE 7 +static int xincr[8] = {1, 1, 0, -1, -1, -1, 0, 1}; +static int yincr[8] = {0, 1, 1, 1, 0, -1, -1, -1}; + +/* current ship position and direction */ +static int curx = (BWIDTH / 2); +static int cury = (BDEPTH / 2); + +typedef struct +{ + char *name; /* name of the ship type */ + int hits; /* how many times has this ship been hit? */ + char symbol; /* symbol for game purposes */ + int length; /* length of ship */ + char x, y; /* coordinates of ship start point */ + unsigned char dir; /* direction of `bow' */ + bool placed; /* has it been placed on the board? */ +} +ship_t; + +static bool checkplace(int b, ship_t *ss, int vis); + +#define SHIPIT(name, symbol, length) { name, 0, symbol, length, 0,0, 0, FALSE } + +static ship_t plyship[SHIPTYPES] = +{ + SHIPIT(carrier, 'A', 5), + SHIPIT(battle, 'B', 4), + SHIPIT(destroy, 'D', 3), + SHIPIT(sub, 'S', 3), + SHIPIT(ptboat, 'P', 2), +}; + +static ship_t cpuship[SHIPTYPES] = +{ + SHIPIT(carrier, 'A', 5), + SHIPIT(battle, 'B', 4), + SHIPIT(destroy, 'D', 3), + SHIPIT(sub, 'S', 3), + SHIPIT(ptboat, 'P', 2), +}; + +/* "Hits" board, and main board. */ +static char hits[2][BWIDTH][BDEPTH]; +static char board[2][BWIDTH][BDEPTH]; + +static int turn; /* 0=player, 1=computer */ +static int plywon=0, cpuwon=0; /* How many games has each won? */ + +static int salvo, blitz, closepack; + +#define PR (void)addstr + +static RETSIGTYPE uninitgame(int sig) GCC_NORETURN; + +static RETSIGTYPE uninitgame(int sig GCC_UNUSED) +/* end the game, either normally or due to signal */ +{ + clear(); + (void)refresh(); + (void)resetterm(); + (void)echo(); + (void)endwin(); + exit(EXIT_FAILURE); +} + +static void announceopts(void) +/* announce which game options are enabled */ +{ + if (salvo || blitz || closepack) + { + (void) printw("Playing optional game ("); + if (salvo) + (void) printw("salvo, "); + else + (void) printw("nosalvo, "); + if (blitz) + (void) printw("blitz "); + else + (void) printw("noblitz, "); + if (closepack) + (void) printw("closepack)"); + else + (void) printw("noclosepack)"); + } + else + (void) printw( + "Playing standard game (noblitz, nosalvo, noclosepack)"); +} + +static void intro(void) +{ + char *tmpname; + + srand((unsigned)(time(0L)+getpid())); /* Kick the random number generator */ + + (void) signal(SIGINT,uninitgame); + (void) signal(SIGINT,uninitgame); + (void) signal(SIGIOT,uninitgame); /* for assert(3) */ + if(signal(SIGQUIT,SIG_IGN) != SIG_IGN) + (void)signal(SIGQUIT,uninitgame); + + if((tmpname = getlogin()) != 0) + { + (void)strcpy(name,tmpname); + name[0] = toupper(name[0]); + } + else + (void)strcpy(name,dftname); + + (void)initscr(); +#ifdef KEY_MIN + keypad(stdscr, TRUE); +#endif /* KEY_MIN */ + (void)saveterm(); + (void)nonl(); + (void)cbreak(); + (void)noecho(); + +#ifdef PENGUIN + (void)clear(); + (void)mvaddstr(4,29,"Welcome to Battleship!"); + (void)move(8,0); + PR(" \\\n"); + PR(" \\ \\ \\\n"); + PR(" \\ \\ \\ \\ \\_____________\n"); + PR(" \\ \\ \\_____________ \\ \\/ |\n"); + PR(" \\ \\/ \\ \\/ |\n"); + PR(" \\/ \\_____/ |__\n"); + PR(" ________________/ |\n"); + PR(" \\ S.S. Penguin |\n"); + PR(" \\ /\n"); + PR(" \\___________________________________________________/\n"); + + (void) mvaddstr(22,27,"Hit any key to continue..."); (void)refresh(); + (void) getch(); +#endif /* PENGUIN */ + +#ifdef A_COLOR + start_color(); + + init_pair(COLOR_BLACK, COLOR_BLACK, COLOR_BLACK); + init_pair(COLOR_GREEN, COLOR_GREEN, COLOR_BLACK); + init_pair(COLOR_RED, COLOR_RED, COLOR_BLACK); + init_pair(COLOR_CYAN, COLOR_CYAN, COLOR_BLACK); + init_pair(COLOR_WHITE, COLOR_WHITE, COLOR_BLACK); + init_pair(COLOR_MAGENTA, COLOR_MAGENTA, COLOR_BLACK); + init_pair(COLOR_BLUE, COLOR_BLUE, COLOR_BLACK); + init_pair(COLOR_YELLOW, COLOR_YELLOW, COLOR_BLACK); +#endif /* A_COLOR */ + +#ifdef NCURSES_MOUSE_VERSION + (void) mousemask(BUTTON1_CLICKED, (mmask_t *)NULL); +#endif /* NCURSES_MOUSE_VERSION*/ +} + +/* VARARGS1 */ +static void prompt(int n, NCURSES_CONST char *f, const char *s) +/* print a message at the prompt line */ +{ + (void) move(PROMPTLINE + n, 0); + (void) clrtoeol(); + (void) printw(f, s); + (void) refresh(); +} + +static void error(NCURSES_CONST char *s) +{ + (void) move(PROMPTLINE + 2, 0); + (void) clrtoeol(); + if (s) + { + (void) addstr(s); + (void) beep(); + } +} + +static void placeship(int b, ship_t *ss, int vis) +{ + int l; + + for(l = 0; l < ss->length; ++l) + { + int newx = ss->x + l * xincr[ss->dir]; + int newy = ss->y + l * yincr[ss->dir]; + + board[b][newx][newy] = ss->symbol; + if (vis) + { + pgoto(newy, newx); + (void) addch((chtype)ss->symbol); + } + } + ss->hits = 0; +} + +static int rnd(int n) +{ + return(((rand() & 0x7FFF) % n)); +} + +static void randomplace(int b, ship_t *ss) +/* generate a valid random ship placement into px,py */ +{ + register int bwidth = BWIDTH - ss->length; + register int bdepth = BDEPTH - ss->length; + + do { + ss->y = rnd(bdepth); + ss->x = rnd(bwidth); + ss->dir = rnd(2) ? E : S; + } while + (!checkplace(b, ss, FALSE)); +} + +static void initgame(void) +{ + int i, j, unplaced; + ship_t *ss; + + (void) clear(); + (void) mvaddstr(0,35,"BATTLESHIPS"); + (void) move(PROMPTLINE + 2, 0); + announceopts(); + + memset(board, 0, sizeof(char) * BWIDTH * BDEPTH * 2); + memset(hits, 0, sizeof(char) * BWIDTH * BDEPTH * 2); + for (i = 0; i < SHIPTYPES; i++) + { + ss = cpuship + i; + + ss->x = + ss->y = + ss->dir = + ss->hits = 0; + ss->placed = FALSE; + + ss = plyship + i; + + ss->x = + ss->y = + ss->dir = + ss->hits = 0; + ss->placed = FALSE; + } + + /* draw empty boards */ + (void) mvaddstr(PYBASE - 2, PXBASE + 5, "Main Board"); + (void) mvaddstr(PYBASE - 1, PXBASE - 3,numbers); + for(i=0; i < BDEPTH; ++i) + { + (void) mvaddch(PYBASE + i, PXBASE - 3, (chtype)(i + 'A')); +#ifdef A_COLOR + if (has_colors()) + attron(COLOR_PAIR(COLOR_BLUE)); +#endif /* A_COLOR */ + (void) addch(' '); + for (j = 0; j < BWIDTH; j++) + (void) addstr(" . "); +#ifdef A_COLOR + attrset(0); +#endif /* A_COLOR */ + (void) addch(' '); + (void) addch((chtype)(i + 'A')); + } + (void) mvaddstr(PYBASE + BDEPTH, PXBASE - 3,numbers); + (void) mvaddstr(CYBASE - 2, CXBASE + 7,"Hit/Miss Board"); + (void) mvaddstr(CYBASE - 1, CXBASE - 3, numbers); + for(i=0; i < BDEPTH; ++i) + { + (void) mvaddch(CYBASE + i, CXBASE - 3, (chtype)(i + 'A')); +#ifdef A_COLOR + if (has_colors()) + attron(COLOR_PAIR(COLOR_BLUE)); +#endif /* A_COLOR */ + (void) addch(' '); + for (j = 0; j < BWIDTH; j++) + (void) addstr(" . "); +#ifdef A_COLOR + attrset(0); +#endif /* A_COLOR */ + (void) addch(' '); + (void) addch((chtype)(i + 'A')); + } + + (void) mvaddstr(CYBASE + BDEPTH,CXBASE - 3,numbers); + + (void) mvprintw(HYBASE, HXBASE, + "To position your ships: move the cursor to a spot, then"); + (void) mvprintw(HYBASE+1,HXBASE, + "type the first letter of a ship type to select it, then"); + (void) mvprintw(HYBASE+2,HXBASE, + "type a direction ([hjkl] or [4862]), indicating how the"); + (void) mvprintw(HYBASE+3,HXBASE, + "ship should be pointed. You may also type a ship letter"); + (void) mvprintw(HYBASE+4,HXBASE, + "followed by `r' to position it randomly, or type `R' to"); + (void) mvprintw(HYBASE+5,HXBASE, + "place all remaining ships randomly."); + + (void) mvaddstr(MYBASE, MXBASE, "Aiming keys:"); + (void) mvaddstr(SYBASE, SXBASE, "y k u 7 8 9"); + (void) mvaddstr(SYBASE+1, SXBASE, " \\|/ \\|/ "); + (void) mvaddstr(SYBASE+2, SXBASE, "h-+-l 4-+-6"); + (void) mvaddstr(SYBASE+3, SXBASE, " /|\\ /|\\ "); + (void) mvaddstr(SYBASE+4, SXBASE, "b j n 1 2 3"); + + /* have the computer place ships */ + for(ss = cpuship; ss < cpuship + SHIPTYPES; ss++) + { + randomplace(COMPUTER, ss); + placeship(COMPUTER, ss, FALSE); + } + + ss = (ship_t *)NULL; + do { + char c, docked[SHIPTYPES + 2], *cp = docked; + + /* figure which ships still wait to be placed */ + *cp++ = 'R'; + for (i = 0; i < SHIPTYPES; i++) + if (!plyship[i].placed) + *cp++ = plyship[i].symbol; + *cp = '\0'; + + /* get a command letter */ + prompt(1, "Type one of [%s] to pick a ship.", docked+1); + do { + c = getcoord(PLAYER); + } while + (!strchr(docked, c)); + + if (c == 'R') + (void) ungetch('R'); + else + { + /* map that into the corresponding symbol */ + for (ss = plyship; ss < plyship + SHIPTYPES; ss++) + if (ss->symbol == c) + break; + + prompt(1, "Type one of [hjklrR] to place your %s.", ss->name); + pgoto(cury, curx); + } + + do { + c = getch(); + } while + (!strchr("hjklrR", c) || c == FF); + + if (c == FF) + { + (void)clearok(stdscr, TRUE); + (void)refresh(); + } + else if (c == 'r') + { + prompt(1, "Random-placing your %s", ss->name); + randomplace(PLAYER, ss); + placeship(PLAYER, ss, TRUE); + error((char *)NULL); + ss->placed = TRUE; + } + else if (c == 'R') + { + prompt(1, "Placing the rest of your fleet at random...", ""); + for (ss = plyship; ss < plyship + SHIPTYPES; ss++) + if (!ss->placed) + { + randomplace(PLAYER, ss); + placeship(PLAYER, ss, TRUE); + ss->placed = TRUE; + } + error((char *)NULL); + } + else if (strchr("hjkl8462", c)) + { + ss->x = curx; + ss->y = cury; + + switch(c) + { + case 'k': case '8': ss->dir = N; break; + case 'j': case '2': ss->dir = S; break; + case 'h': case '4': ss->dir = W; break; + case 'l': case '6': ss->dir = E; break; + } + + if (checkplace(PLAYER, ss, TRUE)) + { + placeship(PLAYER, ss, TRUE); + error((char *)NULL); + ss->placed = TRUE; + } + } + + for (unplaced = i = 0; i < SHIPTYPES; i++) + unplaced += !plyship[i].placed; + } while + (unplaced); + + turn = rnd(2); + + (void) mvprintw(HYBASE, HXBASE, + "To fire, move the cursor to your chosen aiming point "); + (void) mvprintw(HYBASE+1, HXBASE, + "and strike any key other than a motion key. "); + (void) mvprintw(HYBASE+2, HXBASE, + " "); + (void) mvprintw(HYBASE+3, HXBASE, + " "); + (void) mvprintw(HYBASE+4, HXBASE, + " "); + (void) mvprintw(HYBASE+5, HXBASE, + " "); + + (void) prompt(0, "Press any key to start...", ""); + (void) getch(); +} + +static int getcoord(int atcpu) +{ + int ny, nx, c; + + if (atcpu) + cgoto(cury,curx); + else + pgoto(cury, curx); + (void)refresh(); + for (;;) + { + if (atcpu) + { + (void) mvprintw(CYBASE + BDEPTH+1, CXBASE+11, "(%d, %c)", curx, 'A'+cury); + cgoto(cury, curx); + } + else + { + (void) mvprintw(PYBASE + BDEPTH+1, PXBASE+11, "(%d, %c)", curx, 'A'+cury); + pgoto(cury, curx); + } + + switch(c = getch()) + { + case 'k': case '8': +#ifdef KEY_MIN + case KEY_UP: +#endif /* KEY_MIN */ + ny = cury+BDEPTH-1; nx = curx; + break; + case 'j': case '2': +#ifdef KEY_MIN + case KEY_DOWN: +#endif /* KEY_MIN */ + ny = cury+1; nx = curx; + break; + case 'h': case '4': +#ifdef KEY_MIN + case KEY_LEFT: +#endif /* KEY_MIN */ + ny = cury; nx = curx+BWIDTH-1; + break; + case 'l': case '6': +#ifdef KEY_MIN + case KEY_RIGHT: +#endif /* KEY_MIN */ + ny = cury; nx = curx+1; + break; + case 'y': case '7': +#ifdef KEY_MIN + case KEY_A1: +#endif /* KEY_MIN */ + ny = cury+BDEPTH-1; nx = curx+BWIDTH-1; + break; + case 'b': case '1': +#ifdef KEY_MIN + case KEY_C1: +#endif /* KEY_MIN */ + ny = cury+1; nx = curx+BWIDTH-1; + break; + case 'u': case '9': +#ifdef KEY_MIN + case KEY_A3: +#endif /* KEY_MIN */ + ny = cury+BDEPTH-1; nx = curx+1; + break; + case 'n': case '3': +#ifdef KEY_MIN + case KEY_C3: +#endif /* KEY_MIN */ + ny = cury+1; nx = curx+1; + break; + case FF: + nx = curx; ny = cury; + (void)clearok(stdscr, TRUE); + (void)refresh(); + break; +#ifdef NCURSES_MOUSE_VERSION + case KEY_MOUSE: + { + MEVENT myevent; + + getmouse(&myevent); + if (atcpu + && myevent.y >= CY(0) && myevent.y <= CY(BDEPTH) + && myevent.x >= CX(0) && myevent.x <= CX(BDEPTH)) + { + curx = CXINV(myevent.x); + cury = CYINV(myevent.y); + return(' '); + } + else + { + beep(); + continue; + } + } + /* no fall through */ +#endif /* NCURSES_MOUSE_VERSION */ + + default: + if (atcpu) + (void) mvaddstr(CYBASE + BDEPTH + 1, CXBASE + 11, " "); + else + (void) mvaddstr(PYBASE + BDEPTH + 1, PXBASE + 11, " "); + return(c); + } + + curx = nx % BWIDTH; + cury = ny % BDEPTH; + } +} + +static bool collidecheck(int b, int y, int x) +/* is this location on the selected zboard adjacent to a ship? */ +{ + bool collide; + + /* anything on the square */ + if ((collide = IS_SHIP(board[b][x][y])) != FALSE) + return(collide); + + /* anything on the neighbors */ + if (!closepack) + { + int i; + + for (i = 0; i < 8; i++) + { + int xend, yend; + + yend = y + yincr[i]; + xend = x + xincr[i]; + if (ONBOARD(xend, yend) + && IS_SHIP(board[b][xend][yend])) { + collide = TRUE; + break; + } + } + } + return(collide); +} + +static bool checkplace(int b, ship_t *ss, int vis) +{ + int l, xend, yend; + + /* first, check for board edges */ + xend = ss->x + ss->length * xincr[ss->dir]; + yend = ss->y + ss->length * yincr[ss->dir]; + if (!ONBOARD(xend, yend)) + { + if (vis) + switch(rnd(3)) + { + case 0: + error("Ship is hanging from the edge of the world"); + break; + case 1: + error("Try fitting it on the board"); + break; + case 2: + error("Figure I won't find it if you put it there?"); + break; + } + return(FALSE); + } + + for(l = 0; l < ss->length; ++l) + { + if(collidecheck(b, ss->y+l*yincr[ss->dir], ss->x+l*xincr[ss->dir])) + { + if (vis) + switch(rnd(3)) + { + case 0: + error("There's already a ship there"); + break; + case 1: + error("Collision alert! Aaaaaagh!"); + break; + case 2: + error("Er, Admiral, what about the other ship?"); + break; + } + return(FALSE); + } + } + return(TRUE); +} + +static int awinna(void) +{ + int i, j; + ship_t *ss; + + for(i=0; i<2; ++i) + { + ss = (i) ? cpuship : plyship; + for(j=0; j < SHIPTYPES; ++j, ++ss) + if(ss->length > ss->hits) + break; + if (j == SHIPTYPES) + return(OTHER); + } + return(-1); +} + +static ship_t *hitship(int x, int y) +/* register a hit on the targeted ship */ +{ + ship_t *sb, *ss; + char sym; + int oldx, oldy; + + getyx(stdscr, oldy, oldx); + sb = (turn) ? plyship : cpuship; + if((sym = board[OTHER][x][y]) == 0) + return((ship_t *)NULL); + for(ss = sb; ss < sb + SHIPTYPES; ++ss) + if(ss->symbol == sym) + { + if (++ss->hits < ss->length) /* still afloat? */ + return((ship_t *)NULL); + else /* sunk! */ + { + int i, j; + + if (!closepack) + for (j = -1; j <= 1; j++) + { + int bx = ss->x + j * xincr[(ss->dir + 2) % 8]; + int by = ss->y + j * yincr[(ss->dir + 2) % 8]; + + for (i = -1; i <= ss->length; ++i) + { + int x1, y1; + + x1 = bx + i * xincr[ss->dir]; + y1 = by + i * yincr[ss->dir]; + if (ONBOARD(x1, y1)) + { + hits[turn][x1][y1] = MARK_MISS; + if (turn % 2 == PLAYER) + { + cgoto(y1, x1); +#ifdef A_COLOR + if (has_colors()) + attron(COLOR_PAIR(COLOR_GREEN)); +#endif /* A_COLOR */ + (void)addch(MARK_MISS); +#ifdef A_COLOR + attrset(0); +#endif /* A_COLOR */ + } + } + } + } + + for (i = 0; i < ss->length; ++i) + { + int x1 = ss->x + i * xincr[ss->dir]; + int y1 = ss->y + i * yincr[ss->dir]; + + hits[turn][x1][y1] = ss->symbol; + if (turn % 2 == PLAYER) + { + cgoto(y1, x1); + (void) addch((chtype)(ss->symbol)); + } + } + + (void) move(oldy, oldx); + return(ss); + } + } + (void) move(oldy, oldx); + return((ship_t *)NULL); +} + +static int plyturn(void) +{ + ship_t *ss; + bool hit; + NCURSES_CONST char *m = NULL; + + prompt(1, "Where do you want to shoot? ", ""); + for (;;) + { + (void) getcoord(COMPUTER); + if (hits[PLAYER][curx][cury]) + { + prompt(1, "You shelled this spot already! Try again.", ""); + beep(); + } + else + break; + } + hit = IS_SHIP(board[COMPUTER][curx][cury]); + hits[PLAYER][curx][cury] = (hit ? MARK_HIT : MARK_MISS); + cgoto(cury, curx); +#ifdef A_COLOR + if (has_colors()) { + if (hit) + attron(COLOR_PAIR(COLOR_RED)); + else + attron(COLOR_PAIR(COLOR_GREEN)); + } +#endif /* A_COLOR */ + (void) addch((chtype)hits[PLAYER][curx][cury]); +#ifdef A_COLOR + attrset(0); +#endif /* A_COLOR */ + + prompt(1, "You %s.", hit ? "scored a hit" : "missed"); + if(hit && (ss = hitship(curx, cury))) + { + switch(rnd(5)) + { + case 0: + m = " You sank my %s!"; + break; + case 1: + m = " I have this sinking feeling about my %s...."; + break; + case 2: + m = " My %s has gone to Davy Jones's locker!"; + break; + case 3: + m = " Glub, glub -- my %s is headed for the bottom!"; + break; + case 4: + m = " You'll pick up survivors from my %s, I hope...!"; + break; + } + (void)printw(m, ss->name); + (void)beep(); + return(awinna() == -1); + } + return (hit); +} + +static int sgetc(const char *s) +{ + const char *s1; + int ch; + + (void)refresh(); + for(;;) + { + ch = getch(); + if (islower(ch)) + ch = toupper(ch); + if (ch == CTRLC) + uninitgame(0); + for (s1=s; *s1 && ch != *s1; ++s1) + continue; + if (*s1) + { + (void) addch((chtype)ch); + (void)refresh(); + return(ch); + } + } +} + + +static void randomfire(int *px, int *py) +/* random-fire routine -- implements simple diagonal-striping strategy */ +{ + static int turncount = 0; + static int srchstep = BEGINSTEP; + static int huntoffs; /* Offset on search strategy */ + int ypossible[BWIDTH * BDEPTH], xpossible[BWIDTH * BDEPTH], nposs; + int ypreferred[BWIDTH * BDEPTH], xpreferred[BWIDTH * BDEPTH], npref; + int x, y, i; + + if (turncount++ == 0) + huntoffs = rnd(srchstep); + + /* first, list all possible moves */ + nposs = npref = 0; + for (x = 0; x < BWIDTH; x++) + for (y = 0; y < BDEPTH; y++) + if (!hits[COMPUTER][x][y]) + { + xpossible[nposs] = x; + ypossible[nposs] = y; + nposs++; + if (((x+huntoffs) % srchstep) != (y % srchstep)) + { + xpreferred[npref] = x; + ypreferred[npref] = y; + npref++; + } + } + + if (npref) + { + i = rnd(npref); + + *px = xpreferred[i]; + *py = ypreferred[i]; + } + else if (nposs) + { + i = rnd(nposs); + + *px = xpossible[i]; + *py = ypossible[i]; + + if (srchstep > 1) + --srchstep; + } + else + { + error("No moves possible?? Help!"); + exit(EXIT_FAILURE); + /*NOTREACHED*/ + } +} + +#define S_MISS 0 +#define S_HIT 1 +#define S_SUNK -1 + +static int cpufire(int x, int y) +/* fire away at given location */ +{ + bool hit, sunk; + ship_t *ss = NULL; + + hits[COMPUTER][x][y] = (hit = (board[PLAYER][x][y])) ? MARK_HIT : MARK_MISS; + (void) mvprintw(PROMPTLINE, 0, + "I shoot at %c%d. I %s!", y + 'A', x, hit ? "hit" : "miss"); + if ((sunk = (hit && (ss = hitship(x, y)))) != 0) + (void) printw(" I've sunk your %s", ss->name); + (void)clrtoeol(); + + pgoto(y, x); +#ifdef A_COLOR + if (has_colors()) { + if (hit) + attron(COLOR_PAIR(COLOR_RED)); + else + attron(COLOR_PAIR(COLOR_GREEN)); + } +#endif /* A_COLOR */ + (void)addch((chtype)(hit ? SHOWHIT : SHOWSPLASH)); +#ifdef A_COLOR + attrset(0); +#endif /* A_COLOR */ + + return ((hit ? (sunk ? S_SUNK : S_HIT) : S_MISS) ? TRUE : FALSE); +} + +/* + * This code implements a fairly irregular FSM, so please forgive the rampant + * unstructuredness below. The five labels are states which need to be held + * between computer turns. + */ +static bool cputurn(void) +{ +#define POSSIBLE(x, y) (ONBOARD(x, y) && !hits[COMPUTER][x][y]) +#define RANDOM_FIRE 0 +#define RANDOM_HIT 1 +#define HUNT_DIRECT 2 +#define FIRST_PASS 3 +#define REVERSE_JUMP 4 +#define SECOND_PASS 5 + static int next = RANDOM_FIRE; + static bool used[4]; + static ship_t ts; + int navail, x, y, d, n; + int hit = S_MISS; + + switch(next) + { + case RANDOM_FIRE: /* last shot was random and missed */ + refire: + randomfire(&x, &y); + if (!(hit = cpufire(x, y))) + next = RANDOM_FIRE; + else + { + ts.x = x; ts.y = y; + ts.hits = 1; + next = (hit == S_SUNK) ? RANDOM_FIRE : RANDOM_HIT; + } + break; + + case RANDOM_HIT: /* last shot was random and hit */ + used[E/2] = used[S/2] = used[W/2] = used[N/2] = FALSE; + /* FALLTHROUGH */ + + case HUNT_DIRECT: /* last shot hit, we're looking for ship's long axis */ + for (d = navail = 0; d < 4; d++) + { + x = ts.x + xincr[d*2]; y = ts.y + yincr[d*2]; + if (!used[d] && POSSIBLE(x, y)) + navail++; + else + used[d] = TRUE; + } + if (navail == 0) /* no valid places for shots adjacent... */ + goto refire; /* ...so we must random-fire */ + else + { + for (d = 0, n = rnd(navail) + 1; n; n--) + while (used[d]) + d++; + + assert(d <= 4); + + used[d] = FALSE; + x = ts.x + xincr[d*2]; + y = ts.y + yincr[d*2]; + + assert(POSSIBLE(x, y)); + + if (!(hit = cpufire(x, y))) + next = HUNT_DIRECT; + else + { + ts.x = x; ts.y = y; ts.dir = d*2; ts.hits++; + next = (hit == S_SUNK) ? RANDOM_FIRE : FIRST_PASS; + } + } + break; + + case FIRST_PASS: /* we have a start and a direction now */ + x = ts.x + xincr[ts.dir]; + y = ts.y + yincr[ts.dir]; + if (POSSIBLE(x, y) && (hit = cpufire(x, y))) + { + ts.x = x; ts.y = y; ts.hits++; + next = (hit == S_SUNK) ? RANDOM_FIRE : FIRST_PASS; + } + else + next = REVERSE_JUMP; + break; + + case REVERSE_JUMP: /* nail down the ship's other end */ + d = ts.dir + 4; + x = ts.x + ts.hits * xincr[d]; + y = ts.y + ts.hits * yincr[d]; + if (POSSIBLE(x, y) && (hit = cpufire(x, y))) + { + ts.x = x; ts.y = y; ts.dir = d; ts.hits++; + next = (hit == S_SUNK) ? RANDOM_FIRE : SECOND_PASS; + } + else + next = RANDOM_FIRE; + break; + + case SECOND_PASS: /* kill squares not caught on first pass */ + x = ts.x + xincr[ts.dir]; + y = ts.y + yincr[ts.dir]; + if (POSSIBLE(x, y) && (hit = cpufire(x, y))) + { + ts.x = x; ts.y = y; ts.hits++; + next = (hit == S_SUNK) ? RANDOM_FIRE: SECOND_PASS; + break; + } + else + next = RANDOM_FIRE; + break; + } + + /* check for continuation and/or winner */ + if (salvo) + { + (void)refresh(); + (void)sleep(1); + } + if (awinna() != -1) + return(FALSE); + +#ifdef DEBUG + (void) mvprintw(PROMPTLINE + 2, 0, + "New state %d, x=%d, y=%d, d=%d", + next, x, y, d); +#endif /* DEBUG */ + return ((hit) ? TRUE : FALSE); +} + +static +int playagain(void) +{ + int j; + ship_t *ss; + + for (ss = cpuship; ss < cpuship + SHIPTYPES; ss++) + for(j = 0; j < ss->length; j++) + { + cgoto(ss->y + j * yincr[ss->dir], ss->x + j * xincr[ss->dir]); + (void)addch((chtype)ss->symbol); + } + + if(awinna()) + ++cpuwon; + else + ++plywon; + j = 18 + strlen(name); + if(plywon >= 10) + ++j; + if(cpuwon >= 10) + ++j; + (void) mvprintw(1,(COLWIDTH-j)/2, + "%s: %d Computer: %d",name,plywon,cpuwon); + + prompt(2, (awinna()) ? "Want to be humiliated again, %s [yn]? " + : "Going to give me a chance for revenge, %s [yn]? ",name); + return(sgetc("YN") == 'Y'); +} + +static void do_options(int c, char *op[]) +{ + register int i; + + if (c > 1) + { + for (i=1; i<c; i++) + { + switch(op[i][0]) + { + default: + case '?': + (void) fprintf(stderr, "Usage: battle [-s | -b] [-c]\n"); + (void) fprintf(stderr, "\tWhere the options are:\n"); + (void) fprintf(stderr, "\t-s : play a salvo game\n"); + (void) fprintf(stderr, "\t-b : play a blitz game\n"); + (void) fprintf(stderr, "\t-c : ships may be adjacent\n"); + exit(EXIT_FAILURE); + break; + case '-': + switch(op[i][1]) + { + case 'b': + blitz = 1; + if (salvo == 1) + { + (void) fprintf(stderr, + "Bad Arg: -b and -s are mutually exclusive\n"); + exit(EXIT_FAILURE); + } + break; + case 's': + salvo = 1; + if (blitz == 1) + { + (void) fprintf(stderr, + "Bad Arg: -s and -b are mutually exclusive\n"); + exit(EXIT_FAILURE); + } + break; + case 'c': + closepack = 1; + break; + default: + (void) fprintf(stderr, + "Bad arg: type \"%s ?\" for usage message\n", op[0]); + exit(EXIT_FAILURE); + } + } + } + } +} + +static int scount(int who) +{ + register int i, shots; + register ship_t *sp; + + if (who) + sp = cpuship; /* count cpu shots */ + else + sp = plyship; /* count player shots */ + + for (i=0, shots = 0; i < SHIPTYPES; i++, sp++) + { + if (sp->hits >= sp->length) + continue; /* dead ship */ + else + shots++; + } + return(shots); +} + +int main(int argc, char *argv[]) +{ + do_options(argc, argv); + + intro(); + do { + initgame(); + while(awinna() == -1) + { + if (!blitz) + { + if (!salvo) + { + if(turn) + (void) cputurn(); + else + (void) plyturn(); + } + else + { + register int i; + + i = scount(turn); + while (i--) + { + if (turn) + { + if (cputurn() && awinna() != -1) + i = 0; + } + else + { + if (plyturn() && awinna() != -1) + i = 0; + } + } + } + } + else + while(turn ? cputurn() : plyturn()) + continue; + turn = OTHER; + } + } while + (playagain()); + uninitgame(0); + /*NOTREACHED*/ +} + +/* bs.c ends here */ diff --git a/contrib/ncurses/test/cardfile.c b/contrib/ncurses/test/cardfile.c new file mode 100644 index 0000000..bc2e1ad --- /dev/null +++ b/contrib/ncurses/test/cardfile.c @@ -0,0 +1,420 @@ +/**************************************************************************** + * Copyright (c) 1999 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. * + ****************************************************************************/ + +/* + * Author: Thomas E. Dickey <dickey@clark.net> 1999 + * + * $Id: cardfile.c,v 1.2 1999/06/16 00:41:57 tom Exp $ + * + * File format: text beginning in column 1 is a title; other text forms the content. + */ + +#include <test.priv.h> + +#include <form.h> +#include <panel.h> + +#include <string.h> +#include <ctype.h> + +#define VISIBLE_CARDS 10 +#define OFFSET_CARD 2 + +#ifndef CTRL +#define CTRL(x) ((x) & 0x1f) +#endif + +typedef struct _card { + struct _card *link; + PANEL *panel; + FORM *form; + char *title; + char *content; +} CARD; + +static CARD *all_cards; +static char default_name[] = "cardfile.dat"; + +#if !HAVE_STRDUP +#define strdup my_strdup +static char *strdup (char *s) +{ + char *p = (char *)malloc(strlen(s)+1); + if (p) + strcpy(p, s); + return(p); +} +#endif /* not HAVE_STRDUP */ + +static char *skip(char *buffer) +{ + while (isspace(*buffer)) + buffer++; + return buffer; +} + +static void trim(char *buffer) +{ + unsigned n = strlen(buffer); + while (n-- && isspace(buffer[n])) + buffer[n] = 0; +} + +/*******************************************************************************/ + +static CARD *add_title(const char *title) +{ + CARD *card, *p, *q; + + for (p = all_cards, q = 0; p != 0; q = p, p = p->link) + { + int cmp = strcmp(p->title, title); + if (cmp == 0) + return p; + if (cmp > 0) + break; + } + + card = (CARD *)calloc(1, sizeof(CARD)); + card->title = strdup(title); + card->content = strdup(""); + + if (q == 0) + { + card->link = all_cards; + all_cards = card; + } + else + { + card->link = q->link; + q->link = card; + } + + return card; +} + +static void add_content(CARD *card, char *content) +{ + unsigned total, offset; + + content = skip(content); + if ((total = strlen(content)) != 0) + { + if ((offset = strlen(card->content)) != 0) + { + total += 1 + offset; + card->content = (char *)realloc(card->content, total + 1); + strcpy(card->content + offset++, " "); + } + else + { + card->content = (char *)malloc(total + 1); + } + strcpy(card->content + offset, content); + } +} + +static CARD *find_card(char *title) +{ + CARD *card; + + for (card = all_cards; card != 0; card = card->link) + if (!strcmp(card->title, title)) + break; + + return card; +} + +static void read_data(char *fname) +{ + FILE *fp; + CARD *card = 0; + char buffer[BUFSIZ]; + + if ((fp = fopen(fname, "r")) != 0) + { + while (fgets(buffer, sizeof(buffer), fp)) + { + trim(buffer); + if (isspace(*buffer)) + { + if (card == 0) + card = add_title(""); + add_content(card, buffer); + } + else if ((card = find_card(buffer)) == 0) + { + card = add_title(buffer); + } + } + fclose(fp); + } +} + +/*******************************************************************************/ + +static void write_data(const char *fname) +{ + FILE *fp; + CARD *p = 0; + int n; + + if (!strcmp(fname, default_name)) + fname = "cardfile.out"; + + if ((fp = fopen(fname, "w")) != 0) + { + for (p = all_cards; p != 0; p = p->link) + { + FIELD **f = form_fields(p->form); + for (n = 0; f[n] != 0; n++) + { + char *s = field_buffer(f[n], 0); + if (s != 0 + && (s = strdup(s)) != 0) + { + trim(s); + fprintf(fp, "%s%s\n", n ? "\t" : "", s); + free(s); + } + } + } + fclose(fp); + } +} + +/*******************************************************************************/ + +/* + * Count the cards + */ +static int count_cards(void) +{ + CARD *p; + int count = 0; + + for (p = all_cards; p != 0; p = p->link) + count++; + + return count; +} + +/* + * Shuffle the panels to keep them in a natural hierarchy. + */ +static void order_cards(CARD *first, int depth) +{ + if (first) + { + if (depth && first->link) + order_cards(first->link, depth-1); + top_panel(first->panel); + } +} + +/* + * Return the next card in the list + */ +static CARD *next_card(CARD *now) +{ + if (now->link) + now = now->link; + return now; +} + +/* + * Return the previous card in the list + */ +static CARD *prev_card(CARD *now) +{ + CARD *p; + for (p = all_cards; p != 0; p = p->link) + if (p->link == now) + return p; + return now; +} + + +/*******************************************************************************/ + +static int form_virtualize(WINDOW *w) +{ + int c = wgetch(w); + + switch(c) + { + case CTRL('W'): + return(MAX_FORM_COMMAND + 4); + case CTRL('N'): + return(MAX_FORM_COMMAND + 3); + case CTRL('P'): + return(MAX_FORM_COMMAND + 2); + case CTRL('Q'): + case 033: + return(MAX_FORM_COMMAND + 1); + + case KEY_BACKSPACE: + return(REQ_DEL_PREV); + case KEY_DC: + return(REQ_DEL_CHAR); + case KEY_LEFT: + return(REQ_LEFT_CHAR); + case KEY_RIGHT: + return(REQ_RIGHT_CHAR); + + case KEY_DOWN: + case KEY_NEXT: + return(REQ_NEXT_FIELD); + case KEY_UP: + case KEY_PREVIOUS: + return(REQ_PREV_FIELD); + + default: + return(c); + } +} + +/*******************************************************************************/ + +static void cardfile(char *fname) +{ + WINDOW *win; + CARD *p; + CARD *top_card; + int visible_cards = count_cards(); + int panel_wide = COLS - (visible_cards * OFFSET_CARD); + int panel_high = LINES - (visible_cards * OFFSET_CARD) - 5; + int form_wide = panel_wide - 2; + int form_high = panel_high - 2; + int x = (visible_cards - 1) * OFFSET_CARD; + int y = 0; + int ch; + int finished = FALSE; + + move(LINES - 3, 0); + addstr("^Q/ESC -- exit form ^W -- writes data to file\n"); + addstr("^N -- go to next card ^P -- go to previous card\n"); + addstr("Arrow keys move left/right within a field, up/down between fields"); + + /* make a panel for each CARD */ + for (p = all_cards; p != 0; p = p->link) + { + FIELD **f = (FIELD **)calloc(3, sizeof(FIELD *)); + + win = newwin(panel_high, panel_wide, x, y); + keypad(win, TRUE); + p->panel = new_panel(win); + box(win, 0, 0); + + /* ...and a form in each panel */ + f[0] = new_field(1, form_wide, 0, 0, 0, 0); + set_field_back(f[0], A_REVERSE); + set_field_buffer(f[0], 0, p->title); + + f[1] = new_field(form_high-1, form_wide, 1, 0, 0, 0); + set_field_buffer(f[1], 0, p->content); + set_field_just(f[1], JUSTIFY_LEFT); + + f[2] = 0; + + p->form = new_form(f); + set_form_win(p->form, win); + set_form_sub(p->form, derwin(win, form_high, form_wide, 1, 1)); + post_form(p->form); + + x -= OFFSET_CARD; + y += OFFSET_CARD; + } + + order_cards(top_card = all_cards, visible_cards); + + update_panels(); + + while (!finished) + { + update_panels(); + doupdate(); + + switch(form_driver(top_card->form, ch = form_virtualize(panel_window(top_card->panel)))) + { + case E_OK: + break; + case E_UNKNOWN_COMMAND: + switch (ch) { + case MAX_FORM_COMMAND+1: + finished = TRUE; + break; + case MAX_FORM_COMMAND+2: + top_card = prev_card(top_card); + order_cards(top_card, visible_cards); + break; + case MAX_FORM_COMMAND+3: + top_card = next_card(top_card); + order_cards(top_card, visible_cards); + break; + case MAX_FORM_COMMAND+4: + write_data(fname); + break; + default: + beep(); + break; + } + break; + default: + flash(); + break; + } + } +} + +/*******************************************************************************/ + +int main(int argc, char *argv[]) +{ + int n; + + initscr(); + cbreak(); + noecho(); + + if (argc > 1) + { + for (n = 1; n < argc; n++) + read_data(argv[n]); + cardfile(argv[1]); + } + else + { + read_data(default_name); + cardfile(default_name); + } + + endwin(); + + return EXIT_SUCCESS; +} diff --git a/contrib/ncurses/test/cardfile.dat b/contrib/ncurses/test/cardfile.dat new file mode 100644 index 0000000..deb4b76 --- /dev/null +++ b/contrib/ncurses/test/cardfile.dat @@ -0,0 +1,13 @@ +title 1 + Some text for title1 + and some more text +title 2 + The quicker brown fox ran all over the lazy dog. +put a card before the first two + This is an example of a simple cardfile. +show a fourth card + The fourth card + has a large amount of data, + more than the other cards. + At least, that is what I thought it should do, since I want to see how well + the forms package handles justification. diff --git a/contrib/ncurses/test/configure.in b/contrib/ncurses/test/configure.in new file mode 100644 index 0000000..acbad8a --- /dev/null +++ b/contrib/ncurses/test/configure.in @@ -0,0 +1,176 @@ +dnl*************************************************************************** +dnl Copyright (c) 1998 Free Software Foundation, Inc. * +dnl * +dnl Permission is hereby granted, free of charge, to any person obtaining a * +dnl copy of this software and associated documentation files (the * +dnl "Software"), to deal in the Software without restriction, including * +dnl without limitation the rights to use, copy, modify, merge, publish, * +dnl distribute, distribute with modifications, sublicense, and/or sell * +dnl copies of the Software, and to permit persons to whom the Software is * +dnl furnished to do so, subject to the following conditions: * +dnl * +dnl The above copyright notice and this permission notice shall be included * +dnl in all copies or substantial portions of the Software. * +dnl * +dnl THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * +dnl OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * +dnl MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * +dnl IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * +dnl DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * +dnl OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * +dnl THE USE OR OTHER DEALINGS IN THE SOFTWARE. * +dnl * +dnl Except as contained in this notice, the name(s) of the above copyright * +dnl holders shall not be used in advertising or otherwise to promote the * +dnl sale, use or other dealings in this Software without prior written * +dnl authorization. * +dnl*************************************************************************** +dnl +dnl Author: Thomas E. Dickey <dickey@clark.net> 1996,1997,1998 +dnl +dnl $Id: configure.in,v 1.24 1998/05/16 20:48:14 tom Exp $ +dnl This is a simple configuration-script for the ncurses test programs that +dnl allows the test-directory to be separately configured against a reference +dnl system (i.e., sysvr4 curses) +dnl +dnl If you're configuring ncurses, you shouldn't need to use this script. +dnl It's only for testing purposes. +dnl +dnl dickey@clark.net (Thomas Dickey) +AC_PREREQ(2.12) +AC_INIT(ncurses.c) +AC_CONFIG_HEADER(ncurses_cfg.h:ncurses_tst.hin) + +AC_PROG_CC + +dnl Things that we don't need (or must override) if we're not building ncurses +CC_G_OPT="-g" AC_SUBST(CC_G_OPT) +CC_SHARED_OPTS=unknown AC_SUBST(CC_SHARED_OPTS) +CPPFLAGS="$CPPFLAGS" AC_SUBST(CPPFLAGS) +DFT_DEP_SUFFIX="" AC_SUBST(DFT_DEP_SUFFIX) +DFT_OBJ_SUBDIR=`pwd|sed -e's:.*/::'` AC_SUBST(DFT_OBJ_SUBDIR) +DFT_UPR_MODEL="NORMAL" AC_SUBST(DFT_UPR_MODEL) +ECHO_LINK='@ echo linking $@ ... ;' AC_SUBST(ECHO_LINK) +EXTRA_LIBS="" AC_SUBST(EXTRA_LIBS) +LD="ld" AC_SUBST(LD) +LD_MODEL="" AC_SUBST(LD_MODEL) +LDFLAGS_SHARED="" AC_SUBST(LDFLAGS_SHARED) +LIB_NAME=curses AC_SUBST(LIB_NAME) +LIB_PREFIX="-l" AC_SUBST(LIB_PREFIX) +LINK_TESTS="" AC_SUBST(LINK_TESTS) +LINT=lint AC_SUBST(LINT) +LINT_OPTS="" AC_SUBST(LINT_OPTS) +LOCAL_LDFLAGS="" AC_SUBST(LOCAL_LDFLAGS) +MATH_LIB="-lm" AC_SUBST(MATH_LIB) +PROG_EXT="" AC_SUBST(PROG_EXT) +TEST_ARGS="" AC_SUBST(TEST_ARGS) +TEST_DEPS="" AC_SUBST(TEST_DEPS) +cf_cv_abi_version="" AC_SUBST(cf_cv_abi_version) +cf_cv_rel_version="" AC_SUBST(cf_cv_rel_version) + +dnl SunOS 4.x +AC_ARG_WITH(5lib, + [ --with-5lib use SunOS sysv-libraries], + [LIBS="-L/usr/5lib $LIBS" + CPPFLAGS="$CPPFLAGS -I/usr/5include"]) + +dnl Ncurses, installed in conventional location +AC_ARG_WITH(ncurses, + [ --with-ncurses use ncurses-libraries (installed)], + [AC_CHECK_FUNC(initscr,,[ + AC_CHECK_LIB(gpm,Gpm_Open) + LIB_NAME=ncurses + for p in $HOME /usr/local /usr + do + if test -f $p/include/ncurses/curses.h + then + CPPFLAGS="$CPPFLAGS -I$p/include/ncurses" + test $p != /usr && LIBS="-L$p/lib $LIBS" + break + elif test $p != /usr + then + if test -f $p/include/curses.h + then + CPPFLAGS="$CPPFLAGS -I$p/include" + LIBS="-L$p/lib $LIBS" + break + fi + fi + done + ],[test -d /usr/ccs/lib && LIBS="-L/usr/ccs/lib $LIBS"])]) + +dnl If we've not specified a library, assume we're using sysvr4 libraries +dnl installed conventionally (e.g., SunOS 5.x - solaris). + +dnl Autoconf builds up the $LIBS in reverse order + +AC_CHECK_FUNC(initscr,,[ +AC_CHECK_LIB($LIB_NAME,initscr)]) +AC_CHECK_LIB(form,form_driver) +AC_CHECK_LIB(menu,menu_driver) +AC_CHECK_LIB(panel,new_panel) + +AC_TYPE_SIGNAL + +AC_STDC_HEADERS +AC_HEADER_TIME +AC_CHECK_HEADERS( \ +form.h \ +getopt.h \ +menu.h \ +nc_alloc.h \ +panel.h \ +sys/ioctl.h \ +sys/select.h \ +sys/time.h \ +termios.h \ +unistd.h \ +) + +AC_CHECK_FUNCS( \ +gettimeofday \ +napms \ +resizeterm \ +strdup \ +vsscanf \ +) + +dnl --------------------------------------------------------------------------- +dnl [CF_SYS_TIME_SELECT] +AC_MSG_CHECKING(if sys/time.h conflicts with sys/select.h) +AC_CACHE_VAL(cf_cv_sys_time_select,[ +AC_TRY_COMPILE([ +#if HAVE_SYS_TIME_H +#include <sys/time.h> +#endif +#if HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif +],[],[cf_cv_sys_time_select=yes], + [cf_cv_sys_time_select=no]) + ]) +AC_MSG_RESULT($cf_cv_sys_time_select) +test $cf_cv_sys_time_select = yes && AC_DEFINE(HAVE_SYS_TIME_SELECT) +dnl --------------------------------------------------------------------------- + +AC_OUTPUT(Makefile,[ + cat >>Makefile <<TEST_EOF + +# These rules are generated so we do not rely on suffix rules, which do not +# work consistently for different make-programs (the '\$(MODEL)/' confuses +# some, and the '\$x' confuses others). +TEST_EOF +LIST=`make echo_tests` +LAST=`make echo_suffix` +for n in $LIST +do + N=`echo $n | sed -e s/${LAST}\$//` + cat >>Makefile <<TEST_EOF + +\$(MODEL)/$N.o : $N.c \\ + test.priv.h \\ + ncurses_cfg.h + @echo compiling $N; \$(CC) -c \$(CFLAGS_DEFAULT) $N.c +TEST_EOF +done +],[],sort) diff --git a/contrib/ncurses/test/ditto.c b/contrib/ncurses/test/ditto.c new file mode 100644 index 0000000..8ceafe5 --- /dev/null +++ b/contrib/ncurses/test/ditto.c @@ -0,0 +1,148 @@ +/**************************************************************************** + * Copyright (c) 1998 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. * + ****************************************************************************/ + +/* + * Author: Thomas E. Dickey <dickey@clark.net> 1998 + * + * $Id: ditto.c,v 1.3 1998/08/15 23:39:34 tom Exp $ + * + * The program illustrates how to set up multiple screens from a single + * program. Invoke the program by specifying another terminal on the same + * machine by specifying its device, e.g., + * ditto /dev/ttyp1 + */ +#include <test.priv.h> +#include <sys/stat.h> +#include <errno.h> + +typedef struct { + FILE *input; + FILE *output; + SCREEN *screen; +} DITTO; + +static void +failed(const char *s) +{ + perror(s); + exit(EXIT_FAILURE); +} + +static void +usage(void) +{ + fprintf(stderr, "usage: ditto [terminal1 ...]\n"); + exit(EXIT_FAILURE); +} + +static FILE * +open_tty(char *path) +{ + FILE *fp; + struct stat sb; + + if (stat(path, &sb) < 0) + failed(path); + if ((sb.st_mode & S_IFMT) != S_IFCHR) { + errno = ENOTTY; + failed(path); + } + fp = fopen(path, "a+"); + if (fp == 0) + failed(path); + printf("opened %s\n", path); + return fp; +} + +int +main( + int argc GCC_UNUSED, + char *argv[] GCC_UNUSED) +{ + int j; + int active_tty = 0; + DITTO *data; + + if (argc <= 1) + usage(); + + if ((data = (DITTO *)calloc(argc, sizeof(DITTO))) == 0) + failed("calloc data"); + + data[0].input = stdin; + data[0].output = stdout; + for (j = 1; j < argc; j++) { + data[j].input = + data[j].output = open_tty(argv[j]); + } + + /* + * If we got this far, we have open connection(s) to the terminal(s). + * Set up the screens. + */ + for (j = 0; j < argc; j++) { + active_tty++; + data[j].screen = newterm( + (char *)0, /* assume $TERM is the same */ + data[j].output, + data[j].input); + if (data[j].screen == 0) + failed("newterm"); + cbreak(); + noecho(); + scrollok(stdscr, TRUE); + } + + /* + * Loop, reading characters from any of the inputs and writing to all + * of the screens. + */ + for(;;) { + int ch; + set_term(data[0].screen); + ch = getch(); + if (ch == ERR) + continue; + if (ch == 4) + break; + for (j = 0; j < argc; j++) { + set_term(data[j].screen); + addch(ch); + refresh(); + } + } + + /* + * Cleanup and exit + */ + for (j = argc-1; j >= 0; j--) { + set_term(data[j].screen); + endwin(); + } + return EXIT_SUCCESS; +} diff --git a/contrib/ncurses/test/filter.c b/contrib/ncurses/test/filter.c new file mode 100644 index 0000000..6057396 --- /dev/null +++ b/contrib/ncurses/test/filter.c @@ -0,0 +1,109 @@ +/**************************************************************************** + * Copyright (c) 1998 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. * + ****************************************************************************/ + +/* + * Author: Thomas E. Dickey <dickey@clark.net> 1998 + * + * $Id: filter.c,v 1.2 1998/05/10 00:39:27 tom Exp $ + */ +#include <test.priv.h> + +/* + * An example of the 'filter()' function in ncurses, this program prompts + * for commands and executes them (like a command shell). It illustrates + * how ncurses can be used to implement programs that are not full-screen. + * + * Ncurses differs slightly from SVr4 curses. The latter does not flush its + * state when exiting program mode, so the attributes on the command lines of + * this program 'bleed' onto the executed commands. Rather than use the + * reset_shell_mode() and reset_prog_mode() functions, we could invoke endwin() + * and refresh(), but that does not work any better. + */ + +#ifndef NCURSES_VERSION +#define attr_t long +#define getnstr(s,n) getstr(s) +#endif + +static int new_command(char *buffer, int length, attr_t underline) +{ + int code; + + attron(A_BOLD); + printw("Command: "); + attron(underline); + code = getnstr(buffer, length); + attroff(underline); + attroff(A_BOLD); + printw("\n"); + + return code; +} + +int main( + int argc GCC_UNUSED, + char *argv[] GCC_UNUSED) +{ + SCREEN *sp; + char buffer[80]; + attr_t underline; + + filter(); + sp = newterm((char *)0, stdout, stdin); + cbreak(); + keypad(stdscr, TRUE); + + if (has_colors()) { + int background = COLOR_BLACK; + start_color(); +#ifdef NCURSES_VERSION + if (use_default_colors () != ERR) + background = -1; +#endif + init_pair(1, COLOR_CYAN, background); + underline = COLOR_PAIR(1); + } else { + underline = A_UNDERLINE; + } + + while (new_command(buffer, sizeof(buffer)-1, underline) != ERR + && strlen(buffer) != 0) { + reset_shell_mode(); + printf("\n"); + fflush(stdout); + system(buffer); + reset_prog_mode(); + touchwin(stdscr); + erase(); + refresh(); + } + printw("done"); + refresh(); + endwin(); + return 0; +} diff --git a/contrib/ncurses/test/firework.c b/contrib/ncurses/test/firework.c new file mode 100644 index 0000000..1a37e049 --- /dev/null +++ b/contrib/ncurses/test/firework.c @@ -0,0 +1,154 @@ +/* + * $Id: firework.c,v 1.11 1997/11/01 19:36:25 tom Exp $ + */ +#include <test.priv.h> + +#include <term.h> /* for tparm() */ + +#include <signal.h> +#include <ctype.h> +#include <time.h> + +static int get_colour(chtype *); +static void explode(int row, int col); +static void showit(void); +static RETSIGTYPE onsig(int sig); + +static int my_bg = COLOR_BLACK; + +int main( + int argc GCC_UNUSED, + char *argv[] GCC_UNUSED) +{ +int j; +int start,end,row,diff,flag = 0,direction; +unsigned seed; + + for (j=SIGHUP;j<=SIGTERM;j++) + if (signal(j,SIG_IGN)!=SIG_IGN) + signal(j,onsig); + + initscr(); + if (has_colors()) { + start_color(); +#ifdef NCURSES_VERSION + if (use_default_colors() == OK) + my_bg = -1; +#endif + } + curs_set(0); + + seed = time((time_t *)0); + srand(seed); + cbreak(); + for (;;) { + do { + start = rand() % (COLS -3); + end = rand() % (COLS - 3); + start = (start < 2) ? 2 : start; + end = (end < 2) ? 2 : end; + direction = (start > end) ? -1 : 1; + diff = abs(start-end); + } while (diff<2 || diff>=LINES-2); + attrset(A_NORMAL); + for (row=0;row<diff;row++) { + mvprintw(LINES - row,start + (row * direction), + (direction < 0) ? "\\" : "/"); + if (flag++) { + showit(); + erase(); + flag = 0; + } + } + if (flag++) { + showit(); + flag = 0; + } + seed = time((time_t *)0); + srand(seed); + explode(LINES-row,start+(diff*direction)); + erase(); + showit(); + } +} + +static RETSIGTYPE +onsig(int n GCC_UNUSED) +{ + curs_set(1); + endwin(); + exit(EXIT_FAILURE); +} + +static +void explode(int row, int col) +{ + chtype bold; + erase(); + mvprintw(row,col,"-"); + showit(); + + init_pair(1,get_colour(&bold),my_bg); + attrset(COLOR_PAIR(1) | bold); + mvprintw(row-1,col-1," - "); + mvprintw(row,col-1,"-+-"); + mvprintw(row+1,col-1," - "); + showit(); + + init_pair(1,get_colour(&bold),my_bg); + attrset(COLOR_PAIR(1) | bold); + mvprintw(row-2,col-2," --- "); + mvprintw(row-1,col-2,"-+++-"); + mvprintw(row, col-2,"-+#+-"); + mvprintw(row+1,col-2,"-+++-"); + mvprintw(row+2,col-2," --- "); + showit(); + + init_pair(1,get_colour(&bold),my_bg); + attrset(COLOR_PAIR(1) | bold); + mvprintw(row-2,col-2," +++ "); + mvprintw(row-1,col-2,"++#++"); + mvprintw(row, col-2,"+# #+"); + mvprintw(row+1,col-2,"++#++"); + mvprintw(row+2,col-2," +++ "); + showit(); + + init_pair(1,get_colour(&bold),my_bg); + attrset(COLOR_PAIR(1) | bold); + mvprintw(row-2,col-2," # "); + mvprintw(row-1,col-2,"## ##"); + mvprintw(row, col-2,"# #"); + mvprintw(row+1,col-2,"## ##"); + mvprintw(row+2,col-2," # "); + showit(); + + init_pair(1,get_colour(&bold),my_bg); + attrset(COLOR_PAIR(1) | bold); + mvprintw(row-2,col-2," # # "); + mvprintw(row-1,col-2,"# #"); + mvprintw(row, col-2," "); + mvprintw(row+1,col-2,"# #"); + mvprintw(row+2,col-2," # # "); + showit(); +} + +static +int get_colour(chtype *bold) +{ + int attr; + attr = (rand() % 16) + 1; + + *bold = A_NORMAL; + if (attr > 8) { + *bold = A_BOLD; + attr &= 7; + } + return(attr); +} + +static void +showit(void) +{ + refresh(); + napms(120); +} diff --git a/contrib/ncurses/test/firstlast.c b/contrib/ncurses/test/firstlast.c new file mode 100644 index 0000000..f9515dc --- /dev/null +++ b/contrib/ncurses/test/firstlast.c @@ -0,0 +1,89 @@ +/* + * This test was written by Alexander V. Lukyanov to demonstrate difference + * between ncurses 4.1 and SVR4 curses + * + * $Id: firstlast.c,v 1.2 1997/10/18 21:34:53 tom Exp $ + */ + +#include <test.priv.h> + +static void fill(WINDOW *w,const char *str) +{ + const char *s; + for(;;) { + for(s=str; *s; s++) { + if(waddch(w,*s)==ERR) + { + wmove(w,0,0); + return; + } + } + } +} + +int main( + int argc GCC_UNUSED, + char *argv[] GCC_UNUSED) +{ + WINDOW *large,*small; + initscr(); + noecho(); + + large = newwin(20,60,2,10); + small = newwin(10,30,7,25); + + /* test 1 - addch */ + fill(large,"LargeWindow"); + + refresh(); + wrefresh(large); + wrefresh(small); + + mvwaddstr(small,5,5," Test <place to change> String "); + wrefresh(small); + getch(); + + touchwin(large); + wrefresh(large); + + mvwaddstr(small,5,5," Test <***************> String "); + wrefresh(small); + + /* DIFFERENCE! */ + getch(); + + /* test 2: erase */ + erase(); + refresh(); + getch(); + + /* test 3: clrtoeol */ + werase(small); + wrefresh(small); + touchwin(large); + wrefresh(large); + wmove(small,5,0); + waddstr(small," clrtoeol>"); + wclrtoeol(small); + wrefresh(small); + + /* DIFFERENCE! */; + getch(); + + /* test 4: clrtobot */ + werase(small); + wrefresh(small); + touchwin(large); + wrefresh(large); + wmove(small,5,3); + waddstr(small," clrtobot>"); + wclrtobot(small); + wrefresh(small); + + /* DIFFERENCE! */ + getch(); + + endwin(); + + return EXIT_SUCCESS; +} diff --git a/contrib/ncurses/test/gdc.6 b/contrib/ncurses/test/gdc.6 new file mode 100644 index 0000000..7fa60de --- /dev/null +++ b/contrib/ncurses/test/gdc.6 @@ -0,0 +1,22 @@ +.TH GDC 6 +.SH NAME +gdc \- grand digital clock (curses) +.SH SYNOPSIS +.B gdc +[-s] [ +.I n +] +.SH DESCRIPTION +.I Gdc +runs a digital clock made of reverse-video blanks on a curses +compatible VDU screen. With an optional numeric argument +.I n +it stops after +.I n +seconds (default never). +The optional +.B -s +flag makes digits scroll as they change. In this curses mode implementation, +the scrolling option has trouble keeping up. +.SH AUTHOR +Amos Shapir, modified for curses by John Lupien. diff --git a/contrib/ncurses/test/gdc.c b/contrib/ncurses/test/gdc.c new file mode 100644 index 0000000..ecef2bb --- /dev/null +++ b/contrib/ncurses/test/gdc.c @@ -0,0 +1,235 @@ +/* + * Grand digital clock for curses compatible terminals + * Usage: gdc [-s] [n] -- run for n seconds (default infinity) + * Flags: -s: scroll + * + * modified 10-18-89 for curses (jrl) + * 10-18-89 added signal handling + * + * $Id: gdc.c,v 1.10 1997/10/18 20:06:06 tom Exp $ + */ + +#include <test.priv.h> + +#include <time.h> +#include <signal.h> +#include <string.h> + +#define YBASE 10 +#define XBASE 10 +#define XLENGTH 54 +#define YDEPTH 5 + +/* it won't be */ +static time_t now; /* yeah! */ +static struct tm *tm; + +static short disp[11] = { + 075557, 011111, 071747, 071717, 055711, + 074717, 074757, 071111, 075757, 075717, 002020 +}; +static long older[6], next[6], newer[6], mask; +static char scrol; + +static int sigtermed = 0; + +static int hascolor = 0; + +static void set(int, int); +static void standt(int); +static void movto(int, int); + +static +RETSIGTYPE sighndl(int signo) +{ + signal(signo, sighndl); + sigtermed=signo; +} + +static void +drawbox(void) +{ + chtype bottom[XLENGTH+1]; + int n; + + if(hascolor) + attrset(COLOR_PAIR(3)); + + mvaddch(YBASE - 1, XBASE - 1, ACS_ULCORNER); + hline(ACS_HLINE, XLENGTH); + mvaddch(YBASE - 1, XBASE + XLENGTH, ACS_URCORNER); + + mvaddch(YBASE + YDEPTH, XBASE - 1, ACS_LLCORNER); + mvinchnstr(YBASE + YDEPTH, XBASE, bottom, XLENGTH); + for (n = 0; n < XLENGTH; n++) + bottom[n] = ACS_HLINE | (bottom[n] & (A_ATTRIBUTES | A_COLOR)); + mvaddchnstr(YBASE + YDEPTH, XBASE, bottom, XLENGTH); + mvaddch(YBASE + YDEPTH, XBASE + XLENGTH, ACS_LRCORNER); + + move(YBASE, XBASE - 1); + vline(ACS_VLINE, YDEPTH); + + move(YBASE, XBASE + XLENGTH); + vline(ACS_VLINE, YDEPTH); + + if(hascolor) + attrset(COLOR_PAIR(2)); +} + +int +main(int argc, char *argv[]) +{ +long t, a; +int i, j, s, k; +int n = 0; + + signal(SIGINT,sighndl); + signal(SIGTERM,sighndl); + signal(SIGKILL,sighndl); + + initscr(); + cbreak(); + noecho(); + nodelay(stdscr, 1); + curs_set(0); + + hascolor = has_colors(); + + if(hascolor) { + int bg = COLOR_BLACK; + start_color(); +#ifdef NCURSES_VERSION + if (use_default_colors() == OK) + bg = -1; +#endif + init_pair(1, COLOR_BLACK, COLOR_RED); + init_pair(2, COLOR_RED, bg); + init_pair(3, COLOR_WHITE, bg); + attrset(COLOR_PAIR(2)); + } + + clear(); + refresh(); + while(--argc > 0) { + if(**++argv == '-') + scrol = 1; + else + n = atoi(*argv); + } + + drawbox(); + do { + char buf[30]; + + mask = 0; + time(&now); + tm = localtime(&now); + set(tm->tm_sec%10, 0); + set(tm->tm_sec/10, 4); + set(tm->tm_min%10, 10); + set(tm->tm_min/10, 14); + set(tm->tm_hour%10, 20); + set(tm->tm_hour/10, 24); + set(10, 7); + set(10, 17); + for(k=0; k<6; k++) { + if(scrol) { + for(i=0; i<5; i++) + newer[i] = (newer[i]&~mask) | (newer[i+1]&mask); + newer[5] = (newer[5]&~mask) | (next[k]&mask); + } else + newer[k] = (newer[k]&~mask) | (next[k]&mask); + next[k] = 0; + for(s=1; s>=0; s--) { + standt(s); + for(i=0; i<6; i++) { + if((a = (newer[i]^older[i])&(s ? newer : older)[i]) != 0) { + for(j=0,t=1<<26; t; t>>=1,j++) { + if(a&t) { + if(!(a&(t<<1))) { + movto(YBASE + i, XBASE + 2*j); + } + addstr(" "); + } + } + } + if(!s) { + older[i] = newer[i]; + } + } + if(!s) { + if (scrol) + drawbox(); + refresh(); + if (scrol) + napms(150); + } + } + } + + /* this depends on the detailed format of ctime(3) */ + (void) strcpy(buf, ctime(&now)); + (void) strcpy(buf + 10, buf + 19); + mvaddstr(16, 30, buf); + + movto(6, 0); + drawbox(); + refresh(); + sleep(1); + while(wgetch(stdscr) != ERR) + continue; + if (sigtermed) { + standend(); + clear(); + refresh(); + curs_set(1); + endwin(); + fprintf(stderr, "gdc terminated by signal %d\n", sigtermed); + return EXIT_FAILURE; + } + } while(--n); + standend(); + clear(); + refresh(); + curs_set(1); + endwin(); + return EXIT_SUCCESS; +} + +static void +set(int t, int n) +{ +int i, m; + + m = 7<<n; + for(i=0; i<5; i++) { + next[i] |= ((disp[t]>>(4-i)*3)&07)<<n; + mask |= (next[i]^older[i])&m; + } + if(mask&m) + mask |= m; +} + +static void +standt(int on) +{ + if (on) { + if(hascolor) { + attron(COLOR_PAIR(1)); + } else { + attron(A_STANDOUT); + } + } else { + if(hascolor) { + attron(COLOR_PAIR(2)); + } else { + attroff(A_STANDOUT); + } + } +} + +static void +movto(int line, int col) +{ + move(line, col); +} diff --git a/contrib/ncurses/test/hanoi.c b/contrib/ncurses/test/hanoi.c new file mode 100644 index 0000000..25d906e --- /dev/null +++ b/contrib/ncurses/test/hanoi.c @@ -0,0 +1,297 @@ +/* + * Name: Towers of Hanoi. + * + * Desc: + * This is a playable copy of towers of hanoi. + * Its sole purpose is to demonstrate my Amiga Curses package. + * This program should compile on any system that has Curses. + * 'hanoi' will give a manual game with 7 playing pieces. + * 'hanoi n' will give a manual game with n playing pieces. + * 'hanoi n a' will give an auto solved game with n playing pieces. + * + * Author: Simon J Raybould (sie@fulcrum.bt.co.uk). + * (This version has been slightly modified by the ncurses maintainers.) + * + * Date: 05.Nov.90 + * + * $Id: hanoi.c,v 1.15 1997/10/18 20:11:20 tom Exp $ + */ + +#include <test.priv.h> + +#include <string.h> + +#define NPEGS 3 /* This is not configurable !! */ +#define MINTILES 3 +#define MAXTILES 9 +#define DEFAULTTILES 7 +#define TOPLINE 6 +#define BASELINE 16 +#define STATUSLINE (LINES-3) +#define LEFTPEG 19 +#define MIDPEG 39 +#define RIGHTPEG 59 + +#define LENTOIND(x) (((x)-1)/2) +#define OTHER(a,b) (3-((a)+(b))) + +struct Peg { + size_t Length[MAXTILES]; + int Count; +}; + +static struct Peg Pegs[NPEGS]; +static int PegPos[] = { LEFTPEG, MIDPEG, RIGHTPEG }; +static int TileColour[] = { + COLOR_GREEN, /* Length 3 */ + COLOR_MAGENTA, /* Length 5 */ + COLOR_RED, /* Length 7 */ + COLOR_BLUE, /* Length 9 */ + COLOR_CYAN, /* Length 11 */ + COLOR_YELLOW, /* Length 13 */ + COLOR_GREEN, /* Length 15 */ + COLOR_MAGENTA, /* Length 17 */ + COLOR_RED, /* Length 19 */ +}; +static int NMoves = 0; + +static void InitTiles(int NTiles); +static void DisplayTiles(void); +static void MakeMove(int From, int To); +static void AutoMove(int From, int To, int Num); +static void Usage(void); +static int Solved(int NumTiles); +static int GetMove(int *From, int *To); +static int InvalidMove(int From, int To); + +int +main(int argc, char **argv) +{ +int NTiles, FromCol, ToCol; +unsigned char AutoFlag = 0; + + switch(argc) { + case 1: + NTiles = DEFAULTTILES; + break; + case 2: + NTiles = atoi(argv[1]); + if (NTiles > MAXTILES || NTiles < MINTILES) { + fprintf(stderr, "Range %d to %d\n", MINTILES, MAXTILES); + return EXIT_FAILURE; + } + break; + case 3: + if (strcmp(argv[2], "a")) { + Usage(); + return EXIT_FAILURE; + } + NTiles = atoi(argv[1]); + if (NTiles > MAXTILES || NTiles < MINTILES) { + fprintf(stderr, "Range %d to %d\n", MINTILES, MAXTILES); + return EXIT_FAILURE; + } + AutoFlag = TRUE; + break; + default: + Usage(); + return EXIT_FAILURE; + } +#ifdef NCURSES_VERSION + trace(TRACE_MAXIMUM); +#endif + initscr(); + if (has_colors()) { + int i; + int bg = COLOR_BLACK; + start_color(); +#ifdef NCURSES_VERSION + if (use_default_colors() == OK) + bg = -1; +#endif + for (i = 0; i < 9; i++) + init_pair(i+1, bg, TileColour[i]); + } + cbreak(); + if (LINES < 24) { + endwin(); + fprintf(stderr, "Min screen length 24 lines\n"); + return EXIT_FAILURE; + } + if(AutoFlag) + leaveok(stdscr, TRUE); /* Attempt to remove cursor */ + InitTiles(NTiles); + DisplayTiles(); + if(AutoFlag) { + do { + noecho(); + AutoMove(0, 2, NTiles); + } while(!Solved(NTiles)); + sleep(2); + } else { + echo(); + for(;;) { + if(GetMove(&FromCol, &ToCol)) + break; + if(InvalidMove(FromCol, ToCol)) { + mvaddstr(STATUSLINE, 0, "Invalid Move !!"); + refresh(); + beep(); + continue; + } + MakeMove(FromCol, ToCol); + if(Solved(NTiles)) { + mvprintw(STATUSLINE, 0, "Well Done !! You did it in %d moves", NMoves); + refresh(); + sleep(5); + break; + } + } + } + curs_set(1); + endwin(); + return EXIT_SUCCESS; +} + +static int +InvalidMove(int From, int To) +{ + if(From >= NPEGS) + return TRUE; + if(From < 0) + return TRUE; + if(To >= NPEGS) + return TRUE; + if(To < 0) + return TRUE; + if(From == To) + return TRUE; + if(!Pegs[From].Count) + return TRUE; + if(Pegs[To].Count && + Pegs[From].Length[Pegs[From].Count-1] > + Pegs[To].Length[Pegs[To].Count-1]) + return TRUE; + return FALSE; +} + +static void +InitTiles(int NTiles) +{ + int Size, SlotNo; + + for(Size=NTiles*2+1, SlotNo=0; Size>=3; Size-=2) + Pegs[0].Length[SlotNo++] = Size; + + Pegs[0].Count = NTiles; + Pegs[1].Count = 0; + Pegs[2].Count = 0; +} + +static void +DisplayTiles(void) +{ + int Line, peg, SlotNo; + char TileBuf[BUFSIZ]; + + erase(); + mvaddstr(1, 24, "T O W E R S O F H A N O I"); + mvaddstr(3, 34, "SJR 1990"); + mvprintw(19, 5, "Moves : %d", NMoves); + attrset(A_REVERSE); + mvaddstr(BASELINE, 8, " "); + + for(Line=TOPLINE; Line<BASELINE; Line++) { + mvaddch(Line, LEFTPEG, ' '); + mvaddch(Line, MIDPEG, ' '); + mvaddch(Line, RIGHTPEG, ' '); + } + mvaddch(BASELINE, LEFTPEG, '1'); + mvaddch(BASELINE, MIDPEG, '2'); + mvaddch(BASELINE, RIGHTPEG, '3'); + attrset(A_NORMAL); + + /* Draw tiles */ + for(peg=0; peg<NPEGS; peg++) { + for(SlotNo=0; SlotNo<Pegs[peg].Count; SlotNo++) { + memset(TileBuf, ' ', Pegs[peg].Length[SlotNo]); + TileBuf[Pegs[peg].Length[SlotNo]] = '\0'; + if (has_colors()) + attrset(COLOR_PAIR(LENTOIND(Pegs[peg].Length[SlotNo]))); + else + attrset(A_REVERSE); + mvaddstr(BASELINE-(SlotNo+1), + (int)(PegPos[peg] - Pegs[peg].Length[SlotNo]/2), + TileBuf); + } + } + attrset(A_NORMAL); + refresh(); +} + +static int +GetMove(int *From, int *To) +{ + mvaddstr(STATUSLINE, 0, "Next move ('q' to quit) from "); + clrtoeol(); + refresh(); + if((*From = getch()) == 'q') + return TRUE; + *From -= ('0'+1); + addstr(" to "); + clrtoeol(); + refresh(); + + if((*To = getch()) == 'q') + return TRUE; + *To -= ('0'+1); + refresh(); + napms(500); + + move(STATUSLINE, 0); + clrtoeol(); + refresh(); + return FALSE; +} + +static void +MakeMove(int From, int To) +{ + Pegs[From].Count--; + Pegs[To].Length[Pegs[To].Count] = Pegs[From].Length[Pegs[From].Count]; + Pegs[To].Count++; + NMoves++; + DisplayTiles(); +} + +static void +AutoMove(int From, int To, int Num) +{ + if(Num == 1) { + MakeMove(From, To); + napms(500); + return; + } + AutoMove(From, OTHER(From, To), Num-1); + MakeMove(From, To); + napms(500); + AutoMove(OTHER(From, To), To, Num-1); +} + +static int +Solved(int NumTiles) +{ + int i; + + for(i = 1; i < NPEGS; i++) + if (Pegs[i].Count == NumTiles) + return TRUE; + return FALSE; +} + +static void +Usage() +{ + fprintf(stderr, "Usage: hanoi [<No Of Tiles>] [a]\n"); + fprintf(stderr, "The 'a' option causes the tower to be solved automatically\n"); +} diff --git a/contrib/ncurses/test/hashtest.c b/contrib/ncurses/test/hashtest.c new file mode 100644 index 0000000..514ac89 --- /dev/null +++ b/contrib/ncurses/test/hashtest.c @@ -0,0 +1,219 @@ +/* + * hashtest.c -- test hash mapping + * + * Generate timing statistics for vertical-motion optimization. + * + * $Id: hashtest.c,v 1.14 1998/06/13 22:45:39 tom Exp $ + */ + +#ifdef TRACE +#define Trace(p) _tracef p +#define USE_TRACE 1 +#else +#define Trace(p) /* nothing */ +#endif + +#include <test.priv.h> + +#include <string.h> +#include <ctype.h> +#include <signal.h> + +#define LO_CHAR ' ' +#define HI_CHAR '~' + +static bool continuous = FALSE; +static bool reverse_loops = FALSE; +static bool single_step = FALSE; +static bool extend_corner = FALSE; +static int foot_lines = 0; +static int head_lines = 0; + +static void cleanup(void) +{ + move(LINES-1,0); + clrtoeol(); + refresh(); + endwin(); +} + +static RETSIGTYPE finish(int sig GCC_UNUSED) +{ + cleanup(); + exit(EXIT_FAILURE); +} + +static void genlines(int base) +{ + int i, j; + +#if USE_TRACE + if (base == 'a') + Trace(("Resetting screen")); + else + Trace(("Painting `%c' screen", base)); +#endif + + /* Do this so writes to lower-right corner don't cause a spurious + * scrolling operation. This _shouldn't_ break the scrolling + * optimization, since that's computed in the refresh() call. + */ + scrollok(stdscr, FALSE); + + move(0,0); + for (i = 0; i < head_lines; i++) + for (j = 0; j < COLS; j++) + addch((j % 8 == 0) ? ('A' + j/8) : '-'); + + move(head_lines, 0); + for (i = head_lines; i < LINES - foot_lines; i++) { + int c = (base - LO_CHAR + i) % (HI_CHAR - LO_CHAR + 1) + LO_CHAR; + int hi = (extend_corner || (i < LINES - 1)) ? COLS : COLS - 1; + for (j = 0; j < hi; j++) + addch(c); + } + + for (i = LINES - foot_lines; i < LINES; i++) { + move(i, 0); + for (j = 0; j < (extend_corner ? COLS : COLS - 1); j++) + addch((j % 8 == 0) ? ('A' + j/8) : '-'); + } + + scrollok(stdscr, TRUE); + if (single_step) { + move(LINES-1, 0); + getch(); + } else + refresh(); +} + +static void one_cycle(int ch) +{ + if (continuous) { + genlines(ch); + } else if (ch != 'a') { + genlines('a'); + genlines(ch); + } +} + +static void run_test(bool optimized) +{ + char ch; + int lo = continuous ? LO_CHAR : 'a' - LINES; + int hi = continuous ? HI_CHAR : 'a' + LINES; + + if (lo < LO_CHAR) + lo = LO_CHAR; + if (hi > HI_CHAR) + hi = HI_CHAR; + +#if defined(TRACE) || defined(NCURSES_TEST) + if (optimized) { + Trace(("With hash mapping")); + _nc_optimize_enable |= OPTIMIZE_HASHMAP; + } else { + Trace(("Without hash mapping")); + _nc_optimize_enable &= ~OPTIMIZE_HASHMAP; + } +#endif + + if (reverse_loops) + for (ch = hi; ch >= lo; ch--) + one_cycle(ch); + else + for (ch = lo; ch <= hi; ch++) + one_cycle(ch); +} + +static void usage(void) +{ + static const char *const tbl[] = { + "Usage: hashtest [options]" + ,"" + ,"Options:" + ," -c continuous (don't reset between refresh's)" + ," -f num leave 'num' lines constant for footer" + ," -h num leave 'num' lines constant for header" + ," -l num repeat test 'num' times" + ," -n test the normal optimizer" + ," -o test the hashed optimizer" + ," -r reverse the loops" + ," -s single-step" + ," -x assume lower-right corner extension" + }; + size_t n; + + for (n = 0; n < sizeof(tbl)/sizeof(tbl[0]); n++) + fprintf(stderr, "%s\n", tbl[n]); + exit(EXIT_FAILURE); +} + +int main(int argc, char *argv[]) +{ + int c; + int test_loops = 1; + int test_normal = FALSE; + int test_optimize = FALSE; + + while ((c = getopt(argc, argv, "cf:h:l:norsx")) != EOF) { + switch (c) { + case 'c': + continuous = TRUE; + break; + case 'f': + foot_lines = atoi(optarg); + break; + case 'h': + head_lines = atoi(optarg); + break; + case 'l': + test_loops = atoi(optarg); + break; + case 'n': + test_normal = TRUE; + break; + case 'o': + test_optimize = TRUE; + break; + case 'r': + reverse_loops = TRUE; + break; + case 's': + single_step = TRUE; + break; + case 'x': + extend_corner = TRUE; + break; + default: + usage(); + } + } + if (!test_normal && !test_optimize) { + test_normal = TRUE; + test_optimize = TRUE; + } +#if USE_TRACE + trace(TRACE_TIMES); +#endif + + (void) signal(SIGINT, finish); /* arrange interrupts to terminate */ + + (void) initscr(); /* initialize the curses library */ + keypad(stdscr, TRUE); /* enable keyboard mapping */ + (void) nonl(); /* tell curses not to do NL->CR/NL on output */ + (void) cbreak(); /* take input chars one at a time, no wait for \n */ + (void) noecho(); /* don't echo input */ + scrollok(stdscr, TRUE); + + while (test_loops-- > 0) { + if (test_normal) + run_test(FALSE); + if (test_optimize) + run_test(TRUE); + } + + cleanup(); /* we're done */ + return(EXIT_SUCCESS); +} +/* hashtest.c ends here */ diff --git a/contrib/ncurses/test/keynames.c b/contrib/ncurses/test/keynames.c new file mode 100644 index 0000000..88cadd2 --- /dev/null +++ b/contrib/ncurses/test/keynames.c @@ -0,0 +1,14 @@ +/* + * $Id: keynames.c,v 1.2 1998/06/06 22:45:13 tom Exp $ + */ + +#include <test.priv.h> + +int main(int argc GCC_UNUSED, char *argv[] GCC_UNUSED) +{ + int n; + for (n = -1; n < 512; n++) { + printf("%d(%5o):%s\n", n, n, keyname(n)); + } + return EXIT_SUCCESS; +} diff --git a/contrib/ncurses/test/knight.c b/contrib/ncurses/test/knight.c new file mode 100644 index 0000000..fe31011 --- /dev/null +++ b/contrib/ncurses/test/knight.c @@ -0,0 +1,565 @@ +/* + * Knight's Tour - a brain game + * + * The original of this game was anonymous. It had an unbelievably bogus + * interface, you actually had to enter square coordinates! Redesign by + * Eric S. Raymond <esr@snark.thyrsus.com> July 22 1995. Mouse support + * added September 20th 1995. + * + * $Id: knight.c,v 1.14 1997/08/20 16:22:38 hjl Exp $ + */ + +#include <test.priv.h> + +#include <ctype.h> +#include <signal.h> +#include <string.h> + +/* board size */ +#define BDEPTH 8 +#define BWIDTH 8 + +/* where to start the instructions */ +#define INSTRY 2 +#define INSTRX 35 + +/* corner of board */ +#define BOARDY 2 +#define BOARDX 0 + +/* notification line */ +#define NOTIFYY 21 + +/* virtual color values */ +#define TRAIL_COLOR 1 +#define PLUS_COLOR 2 +#define MINUS_COLOR 3 + +#define CX(x) (2 + 4 * (x)) +#define CY(y) (1 + 2 * (y)) +#define cellmove(y, x) wmove(boardwin, CY(y), CX(x)) +#define CXINV(x) (((x) - 1) / 4) +#define CYINV(y) (((y) - 2) / 2) + +typedef struct +{ + short x, y; +} +cell; + +static short board[BDEPTH][BWIDTH]; /* the squares */ +static int rw,col; /* current row and column */ +static int lastrow,lastcol; /* last location visited */ +static cell history[BDEPTH*BWIDTH]; /* choice history */ +static int movecount; /* count of moves so far */ +static WINDOW *boardwin; /* the board window */ +static WINDOW *helpwin; /* the help window */ +static WINDOW *msgwin; /* the message window */ +static chtype trail = '#'; /* trail character */ +static chtype plus = '+'; /* cursor hot-spot character */ +static chtype minus = '-'; /* possible-move character */ +static chtype oldch; + +static void init(void); +static void play(void); +static void dosquares(void); +static void drawmove(char, int, int, int, int); +static bool evalmove(int, int); +static bool chkmoves(void); +static bool chksqr(int, int); +static int iabs(int); + +int main( + int argc GCC_UNUSED, + char *argv[] GCC_UNUSED) +{ + init(); + + play(); + + endwin(); + return EXIT_SUCCESS; +} + +static void init (void) +{ + srand ((unsigned)getpid()); + initscr (); + cbreak (); /* immediate char return */ + noecho (); /* no immediate echo */ + boardwin = newwin(BDEPTH * 2 + 1, BWIDTH * 4 + 1, BOARDY, BOARDX); + helpwin = newwin(0, 0, INSTRY, INSTRX); + msgwin = newwin(1, INSTRX-1, NOTIFYY, 0); + scrollok(msgwin, TRUE); + keypad(boardwin, TRUE); + + if (has_colors()) + { + int bg = COLOR_BLACK; + + start_color(); +#ifdef NCURSES_VERSION + if (use_default_colors() == OK) + bg = -1; +#endif + + (void) init_pair(TRAIL_COLOR, COLOR_CYAN, bg); + (void) init_pair(PLUS_COLOR, COLOR_RED, bg); + (void) init_pair(MINUS_COLOR, COLOR_GREEN, bg); + + trail |= COLOR_PAIR(TRAIL_COLOR); + plus |= COLOR_PAIR(PLUS_COLOR); + minus |= COLOR_PAIR(MINUS_COLOR); + } + +#ifdef NCURSES_MOUSE_VERSION + (void) mousemask(BUTTON1_CLICKED, (mmask_t *)NULL); +#endif /* NCURSES_MOUSE_VERSION*/ + + oldch = minus; +} + +static void help1(void) +/* game explanation -- initial help screen */ +{ + (void)waddstr(helpwin, "Knight's move is a solitaire puzzle. Your\n"); + (void)waddstr(helpwin, "objective is to visit each square of the \n"); + (void)waddstr(helpwin, "chessboard exactly once by making knight's\n"); + (void)waddstr(helpwin, "moves (one square right or left followed \n"); + (void)waddstr(helpwin, "by two squares up or down, or two squares \n"); + (void)waddstr(helpwin, "right or left followed by one square up or\n"); + (void)waddstr(helpwin, "down). You may start anywhere.\n\n"); + + (void)waddstr(helpwin, "Use arrow keys to move the cursor around.\n"); + (void)waddstr(helpwin, "When you want to move your knight to the \n"); + (void)waddstr(helpwin, "cursor location, press <space> or Enter.\n"); + (void)waddstr(helpwin, "Illegal moves will be rejected with an \n"); + (void)waddstr(helpwin, "audible beep.\n\n"); + (void)waddstr(helpwin, "The program will detect if you solve the\n"); + (void)waddstr(helpwin, "puzzle; also inform you when you run out\n"); + (void)waddstr(helpwin, "of legal moves.\n\n"); + + (void)mvwaddstr(helpwin, NOTIFYY-INSTRY, 0, + "Press `?' to go to keystroke help."); +} + +static void help2(void) +/* keystroke help screen */ +{ + (void)waddstr(helpwin, "Possible moves are shown with `-'.\n\n"); + + (void)waddstr(helpwin, "You can move around with the arrow keys or\n"); + (void)waddstr(helpwin, "with the rogue/hack movement keys. Other\n"); + (void)waddstr(helpwin, "commands allow you to undo moves or redraw.\n"); + (void)waddstr(helpwin, "Your mouse may work; try left-button to\n"); + (void)waddstr(helpwin, "move to the square under the pointer.\n\n"); + + (void)waddstr(helpwin, "x,q -- exit y k u 7 8 9\n"); + (void)waddstr(helpwin, "r -- redraw screen \\|/ \\|/ \n"); + (void)waddstr(helpwin, "u -- undo move h-+-l 4-+-6\n"); + (void)waddstr(helpwin, " /|\\ /|\\ \n"); + (void)waddstr(helpwin, " b j n 1 2 3\n"); + + (void)waddstr(helpwin,"\nYou can place your knight on the selected\n"); + (void)waddstr(helpwin, "square with spacebar, Enter, or the keypad\n"); + (void)waddstr(helpwin, "center key. You can quit with `x' or `q'.\n"); + + (void)mvwaddstr(helpwin, NOTIFYY-INSTRY, 0, + "Press `?' to go to game explanation"); +} + +static void play (void) +/* play the game */ +{ + bool keyhelp; /* TRUE if keystroke help is up */ + int c, ny = 0, nx = 0; + int i, j, count; + + do { + /* clear screen and draw board */ + werase(boardwin); + werase(helpwin); + werase(msgwin); + dosquares(); + help1(); + wnoutrefresh(stdscr); + wnoutrefresh(helpwin); + wnoutrefresh(msgwin); + wnoutrefresh(boardwin); + doupdate(); + + for (i = 0; i < BDEPTH; i++) + for (j = 0; j < BWIDTH; j++) + { + board[i][j] = FALSE; + cellmove(i, j); + waddch(boardwin, minus); + } + memset(history, '\0', sizeof(history)); + history[0].y = history[0].x = -1; + lastrow = lastcol = -2; + movecount = 1; + keyhelp = FALSE; + + for (;;) + { + if (rw != lastrow || col != lastcol) + { + if (lastrow >= 0 && lastcol >= 0) + { + cellmove(lastrow, lastcol); + if (board[lastrow][lastcol]) + waddch(boardwin, trail); + else + waddch(boardwin, oldch); + } + + cellmove(rw, col); + oldch = winch(boardwin); + + lastrow = rw; + lastcol= col; + } + cellmove(rw, col); + waddch(boardwin, plus); + cellmove(rw, col); + + wrefresh(msgwin); + + c = wgetch(boardwin); + + werase(msgwin); + + switch (c) + { + case 'k': case '8': + case KEY_UP: + ny = rw+BDEPTH-1; nx = col; + break; + case 'j': case '2': + case KEY_DOWN: + ny = rw+1; nx = col; + break; + case 'h': case '4': + case KEY_LEFT: + ny = rw; nx = col+BWIDTH-1; + break; + case 'l': case '6': + case KEY_RIGHT: + ny = rw; nx = col+1; + break; + case 'y': case '7': + case KEY_A1: + ny = rw+BDEPTH-1; nx = col+BWIDTH-1; + break; + case 'b': case '1': + case KEY_C1: + ny = rw+1; nx = col+BWIDTH-1; + break; + case 'u': case '9': + case KEY_A3: + ny = rw+BDEPTH-1; nx = col+1; + break; + case 'n': case '3': + case KEY_C3: + ny = rw+1; nx = col+1; + break; + +#ifdef NCURSES_MOUSE_VERSION + case KEY_MOUSE: + { + MEVENT myevent; + + getmouse(&myevent); + if (myevent.y >= CY(0) && myevent.y <= CY(BDEPTH) + && myevent.x >= CX(0) && myevent.x <= CX(BWIDTH)) + { + nx = CXINV(myevent.x); + ny = CYINV(myevent.y); + ungetch('\n'); + break; + } + else + { + beep(); + continue; + } + } +#endif /* NCURSES_MOUSE_VERSION */ + + case KEY_B2: + case '\n': + case ' ': + if (evalmove(rw, col)) + { + drawmove(trail, + history[movecount-1].y, history[movecount-1].x, + rw, col); + history[movecount].y = rw; + history[movecount].x = col; + movecount++; + + if (!chkmoves()) + goto dropout; + } + else + beep(); + break; + + case KEY_REDO: + case '\f': + case 'r': + clearok(curscr, TRUE); + wnoutrefresh(stdscr); + wnoutrefresh(boardwin); + wnoutrefresh(msgwin); + wnoutrefresh(helpwin); + doupdate(); + break; + + case KEY_UNDO: + case KEY_BACKSPACE: + case '\b': + if (movecount == 1) + { + ny = lastrow; + nx = lastcol; + waddstr(msgwin, "\nNo previous move."); + beep(); + } + else + { + int oldy = history[movecount-1].y; + int oldx = history[movecount-1].x; + + board[oldy][oldx] = FALSE; + --movecount; + ny = history[movecount-1].y; + nx = history[movecount-1].x; + drawmove(' ', oldy, oldx, ny, nx); + + /* avoid problems if we just changed the current cell */ + cellmove(lastrow, lastcol); + oldch = winch(boardwin); + } + break; + + case 'q': + case 'x': + goto dropout; + + case '?': + werase(helpwin); + if (keyhelp) + { + help1(); + keyhelp = FALSE; + } + else + { + help2(); + keyhelp = TRUE; + } + wrefresh(helpwin); + break; + + default: + beep(); + break; + } + + col = nx % BWIDTH; + rw = ny % BDEPTH; + } + + dropout: + count = 0; + for (i = 0; i < BDEPTH; i++) + for (j = 0; j < BWIDTH; j++) + if (board[i][j] != 0) + count += 1; + if (count == (BWIDTH * BDEPTH)) + wprintw(msgwin, "\nYou won. Care to try again? "); + else + wprintw(msgwin, "\n%d squares filled. Try again? ", count); + } while + (tolower(wgetch(msgwin)) == 'y'); +} + +static void dosquares (void) +{ + int i, j; + + mvaddstr(0, 20, "KNIGHT'S MOVE -- a logical solitaire"); + + move(BOARDY,BOARDX); + waddch(boardwin, ACS_ULCORNER); + for (j = 0; j < 7; j++) + { + waddch(boardwin, ACS_HLINE); + waddch(boardwin, ACS_HLINE); + waddch(boardwin, ACS_HLINE); + waddch(boardwin, ACS_TTEE); + } + waddch(boardwin, ACS_HLINE); + waddch(boardwin, ACS_HLINE); + waddch(boardwin, ACS_HLINE); + waddch(boardwin, ACS_URCORNER); + + for (i = 1; i < BDEPTH; i++) + { + move(BOARDY + i * 2 - 1, BOARDX); + waddch(boardwin, ACS_VLINE); + for (j = 0; j < BWIDTH; j++) + { + waddch(boardwin, ' '); + waddch(boardwin, ' '); + waddch(boardwin, ' '); + waddch(boardwin, ACS_VLINE); + } + move(BOARDY + i * 2, BOARDX); + waddch(boardwin, ACS_LTEE); + for (j = 0; j < BWIDTH - 1; j++) + { + waddch(boardwin, ACS_HLINE); + waddch(boardwin, ACS_HLINE); + waddch(boardwin, ACS_HLINE); + waddch(boardwin, ACS_PLUS); + } + waddch(boardwin, ACS_HLINE); + waddch(boardwin, ACS_HLINE); + waddch(boardwin, ACS_HLINE); + waddch(boardwin, ACS_RTEE); + } + + move(BOARDY + i * 2 - 1, BOARDX); + waddch(boardwin, ACS_VLINE); + for (j = 0; j < BWIDTH; j++) + { + waddch(boardwin, ' '); + waddch(boardwin, ' '); + waddch(boardwin, ' '); + waddch(boardwin, ACS_VLINE); + } + + move(BOARDY + i * 2, BOARDX); + waddch(boardwin, ACS_LLCORNER); + for (j = 0; j < BWIDTH - 1; j++) + { + waddch(boardwin, ACS_HLINE); + waddch(boardwin, ACS_HLINE); + waddch(boardwin, ACS_HLINE); + waddch(boardwin, ACS_BTEE); + } + waddch(boardwin, ACS_HLINE); + waddch(boardwin, ACS_HLINE); + waddch(boardwin, ACS_HLINE); + waddch(boardwin, ACS_LRCORNER); +} + +static void mark_possibles(int prow, int pcol, chtype mark) +{ + if (chksqr(prow+2,pcol+1)){cellmove(prow+2,pcol+1);waddch(boardwin,mark);}; + if (chksqr(prow+2,pcol-1)){cellmove(prow+2,pcol-1);waddch(boardwin,mark);}; + if (chksqr(prow-2,pcol+1)){cellmove(prow-2,pcol+1);waddch(boardwin,mark);}; + if (chksqr(prow-2,pcol-1)){cellmove(prow-2,pcol-1);waddch(boardwin,mark);}; + if (chksqr(prow+1,pcol+2)){cellmove(prow+1,pcol+2);waddch(boardwin,mark);}; + if (chksqr(prow+1,pcol-2)){cellmove(prow+1,pcol-2);waddch(boardwin,mark);}; + if (chksqr(prow-1,pcol+2)){cellmove(prow-1,pcol+2);waddch(boardwin,mark);}; + if (chksqr(prow-1,pcol-2)){cellmove(prow-1,pcol-2);waddch(boardwin,mark);}; +} + +static void drawmove(char tchar, int oldy, int oldx, int row, int column) +/* place the stars, update board & currents */ +{ + if (movecount <= 1) + { + int i, j; + + for (i = 0; i < BDEPTH; i++) + for (j = 0; j < BWIDTH; j++) + { + cellmove(i, j); + if (winch(boardwin) == minus) + waddch(boardwin, movecount ? ' ' : minus); + } + } + else + { + cellmove(oldy, oldx); + waddch(boardwin, '\b'); + waddch(boardwin, tchar); + waddch(boardwin, tchar); + waddch(boardwin, tchar); + mark_possibles(oldy, oldx, ' '); + } + + if (row != -1 && column != -1) + { + cellmove(row, column); + waddch(boardwin, '\b'); + waddch(boardwin, trail); + waddch(boardwin, trail); + waddch(boardwin, trail); + mark_possibles(row, column, minus); + board[row][column] = TRUE; + } + + wprintw(msgwin, "\nMove %d", movecount); +} + +static bool evalmove(int row, int column) +/* evaluate move */ +{ + if (movecount == 1) + return(TRUE); + else if (board[row][column] == TRUE) + { + waddstr(msgwin, "\nYou've already been there."); + return(FALSE); + } + else + { + int rdif = iabs(row - history[movecount-1].y); + int cdif = iabs(column - history[movecount-1].x); + + if (!((rdif == 1) && (cdif == 2)) && !((rdif == 2) && (cdif == 1))) + { + waddstr(msgwin, "\nThat's not a legal knight's move."); + return(FALSE); + } + } + + return(TRUE); +} + +static bool chkmoves (void) +/* check to see if valid moves are available */ +{ + if (chksqr(rw+2,col+1)) return(TRUE); + if (chksqr(rw+2,col-1)) return(TRUE); + if (chksqr(rw-2,col+1)) return(TRUE); + if (chksqr(rw-2,col-1)) return(TRUE); + if (chksqr(rw+1,col+2)) return(TRUE); + if (chksqr(rw+1,col-2)) return(TRUE); + if (chksqr(rw-1,col+2)) return(TRUE); + if (chksqr(rw-1,col-2)) return(TRUE); + return (FALSE); +} + +static int iabs(int num) +{ + if (num < 0) return (-num); + else return (num); +} + +static bool chksqr (int r1, int c1) +{ + if ((r1 < 0) || (r1 > BDEPTH - 1)) + return(FALSE); + if ((c1 < 0) || (c1 > BWIDTH - 1)) + return(FALSE); + return ((!board[r1][c1]) ? TRUE : FALSE); +} + +/* knight.c ends here */ diff --git a/contrib/ncurses/test/lrtest.c b/contrib/ncurses/test/lrtest.c new file mode 100644 index 0000000..893e1cd --- /dev/null +++ b/contrib/ncurses/test/lrtest.c @@ -0,0 +1,49 @@ +/* + * Test lower-right-hand corner access + * + * by Eric S. Raymond <esr@thyrsus.com> + * + * This can't be part of the ncurses test-program, because ncurses rips off the + * bottom line to do labels. + * + * $Id: lrtest.c,v 0.7 1998/02/12 23:49:11 tom Exp $ + */ + +#include <test.priv.h> + +int +main( + int argc GCC_UNUSED, + char *argv[] GCC_UNUSED) +{ + initscr(); + + move(LINES/2-1, 4); + if (!has_ic()) + { + addstr("Your terminal lacks the capabilities needed to address the\n"); + move(LINES/2, 4); + addstr("lower-right-hand corner of the screen.\n"); + } + else + { + addstr("This is a test of access to the lower right corner.\n"); + move(LINES/2, 4); + addstr("If the top of the box is missing, the test failed.\n"); + move(LINES/2+1, 4); + addstr("Please report this (with a copy of your terminfo entry).\n"); + move(LINES/2+2, 4); + addstr("to the ncurses maintainers, at bug-ncurses@gnu.org.\n"); + } + + box(stdscr, 0, 0); + move(LINES-1, COLS-1); + + refresh(); + + getch(); + endwin(); + return 0; +} + +/* lrtest.c ends here */ diff --git a/contrib/ncurses/test/modules b/contrib/ncurses/test/modules new file mode 100644 index 0000000..3e70d49 --- /dev/null +++ b/contrib/ncurses/test/modules @@ -0,0 +1,57 @@ +# Test-Program modules +# $Id: modules,v 1.10 1999/04/10 21:36:00 tom Exp $ +############################################################################## +# Copyright (c) 1999 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. # +############################################################################## +# +# Author: Thomas E. Dickey <dickey@clark.net> 1997 +# + +@ base +blue progs $(srcdir) ../include/term.h +bs progs $(srcdir) +cardfile progs $(srcdir) ../include/panel.h ../include/menu.h ../include/form.h +ditto progs $(srcdir) +filter progs $(srcdir) +firework progs $(srcdir) ../include/term.h +firstlast progs $(srcdir) +gdc progs $(srcdir) +hanoi progs $(srcdir) +hashtest progs $(srcdir) +keynames progs $(srcdir) +knight progs $(srcdir) +lrtest progs $(srcdir) +ncurses progs $(srcdir) ../include/panel.h ../include/menu.h ../include/form.h +newdemo progs $(srcdir) +rain progs $(srcdir) ../include/term.h +tclock progs $(srcdir) +testaddch progs $(srcdir) +testcurs progs $(srcdir) +testscanw progs $(srcdir) +view progs $(srcdir) +worm progs $(srcdir) +xmas progs $(srcdir) diff --git a/contrib/ncurses/test/ncurses.c b/contrib/ncurses/test/ncurses.c new file mode 100644 index 0000000..667d2ef --- /dev/null +++ b/contrib/ncurses/test/ncurses.c @@ -0,0 +1,3270 @@ +/**************************************************************************** + * Copyright (c) 1998 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. * + ****************************************************************************/ +/**************************************************************************** + +NAME + ncurses.c --- ncurses library exerciser + +SYNOPSIS + ncurses + +DESCRIPTION + An interactive test module for the ncurses library. + +AUTHOR + Author: Eric S. Raymond <esr@snark.thyrsus.com> 1993 + +$Id: ncurses.c,v 1.118 1999/08/10 00:37:30 tom Exp $ + +***************************************************************************/ + +#include <test.priv.h> + +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <assert.h> +#include <signal.h> + +#if HAVE_LOCALE_H +#include <locale.h> +#endif + +#if HAVE_GETTIMEOFDAY +#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 + +#if HAVE_PANEL_H +#define USE_LIBPANEL 1 +#include <panel.h> +#else +#define USE_LIBPANEL 0 +#endif + +#if HAVE_MENU_H && HAVE_LIBMENU +#define USE_LIBMENU 1 +#include <menu.h> +#else +#define USE_LIBMENU 0 +#endif + +#if HAVE_FORM_H && HAVE_LIBFORM +#define USE_LIBFORM 1 +#include <form.h> +#else +#define USE_LIBFORM 0 +#endif + +#ifdef NCURSES_VERSION + +#ifdef TRACE +static int save_trace = TRACE_ORDINARY|TRACE_CALLS; +extern int _nc_tracing; +#endif + +#if !HAVE_NAPMS +#define HAVE_NAPMS 1 +#endif + +#else + +#define mmask_t chtype /* not specified in XSI */ +#define attr_t chtype /* not specified in XSI */ +#define ACS_S3 (acs_map['p']) /* scan line 3 */ +#define ACS_S7 (acs_map['r']) /* scan line 7 */ +#define ACS_LEQUAL (acs_map['y']) /* less/equal */ +#define ACS_GEQUAL (acs_map['z']) /* greater/equal */ +#define ACS_PI (acs_map['{']) /* Pi */ +#define ACS_NEQUAL (acs_map['|']) /* not equal */ +#define ACS_STERLING (acs_map['}']) /* UK pound sign */ + +#endif + +#define P(string) printw("%s\n", string) +#ifndef CTRL +#define CTRL(x) ((x) & 0x1f) +#endif + +#define QUIT CTRL('Q') +#define ESCAPE CTRL('[') +#define BLANK ' ' /* this is the background character */ + +/* The behavior of mvhline, mvvline for negative/zero length is unspecified, + * though we can rely on negative x/y values to stop the macro. + */ +static void do_h_line(int y, int x, chtype c, int to) +{ + if ((to) > (x)) + mvhline(y, x, c, (to) - (x)); +} + +static void do_v_line(int y, int x, chtype c, int to) +{ + if ((to) > (y)) + mvvline(y, x, c, (to) - (y)); +} + +/* Common function to allow ^T to toggle trace-mode in the middle of a test + * so that trace-files can be made smaller. + */ +static int wGetchar(WINDOW *win) +{ + int c; +#ifdef TRACE + while ((c = wgetch(win)) == CTRL('T')) { + if (_nc_tracing) { + save_trace = _nc_tracing; + _tracef("TOGGLE-TRACING OFF"); + _nc_tracing = 0; + } else { + _nc_tracing = save_trace; + } + trace(_nc_tracing); + if (_nc_tracing) + _tracef("TOGGLE-TRACING ON"); + } +#else + c = wgetch(win); +#endif + return c; +} +#define Getchar() wGetchar(stdscr) + +static void Pause(void) +{ + move(LINES - 1, 0); + addstr("Press any key to continue... "); + (void) Getchar(); +} + +static void Cannot(const char *what) +{ + printw("\nThis %s terminal %s\n\n", getenv("TERM"), what); + Pause(); +} + +static void ShellOut(bool message) +{ + if (message) + addstr("Shelling out..."); + def_prog_mode(); + endwin(); + system("sh"); + if (message) + addstr("returned from shellout.\n"); + refresh(); +} + +#ifdef NCURSES_MOUSE_VERSION +static const char *mouse_decode(MEVENT const *ep) +{ + static char buf[80]; + + (void) sprintf(buf, "id %2d at (%2d, %2d, %2d) state %4lx = {", + ep->id, ep->x, ep->y, ep->z, ep->bstate); + +#define SHOW(m, s) if ((ep->bstate & m)==m) {strcat(buf,s); strcat(buf, ", ");} + SHOW(BUTTON1_RELEASED, "release-1") + SHOW(BUTTON1_PRESSED, "press-1") + SHOW(BUTTON1_CLICKED, "click-1") + SHOW(BUTTON1_DOUBLE_CLICKED, "doubleclick-1") + SHOW(BUTTON1_TRIPLE_CLICKED, "tripleclick-1") + SHOW(BUTTON1_RESERVED_EVENT, "reserved-1") + SHOW(BUTTON2_RELEASED, "release-2") + SHOW(BUTTON2_PRESSED, "press-2") + SHOW(BUTTON2_CLICKED, "click-2") + SHOW(BUTTON2_DOUBLE_CLICKED, "doubleclick-2") + SHOW(BUTTON2_TRIPLE_CLICKED, "tripleclick-2") + SHOW(BUTTON2_RESERVED_EVENT, "reserved-2") + SHOW(BUTTON3_RELEASED, "release-3") + SHOW(BUTTON3_PRESSED, "press-3") + SHOW(BUTTON3_CLICKED, "click-3") + SHOW(BUTTON3_DOUBLE_CLICKED, "doubleclick-3") + SHOW(BUTTON3_TRIPLE_CLICKED, "tripleclick-3") + SHOW(BUTTON3_RESERVED_EVENT, "reserved-3") + SHOW(BUTTON4_RELEASED, "release-4") + SHOW(BUTTON4_PRESSED, "press-4") + SHOW(BUTTON4_CLICKED, "click-4") + SHOW(BUTTON4_DOUBLE_CLICKED, "doubleclick-4") + SHOW(BUTTON4_TRIPLE_CLICKED, "tripleclick-4") + SHOW(BUTTON4_RESERVED_EVENT, "reserved-4") + SHOW(BUTTON_CTRL, "ctrl") + SHOW(BUTTON_SHIFT, "shift") + SHOW(BUTTON_ALT, "alt") + SHOW(ALL_MOUSE_EVENTS, "all-events") + SHOW(REPORT_MOUSE_POSITION, "position") +#undef SHOW + + if (buf[strlen(buf)-1] == ' ') + buf[strlen(buf)-2] = '\0'; + (void) strcat(buf, "}"); + return(buf); +} +#endif /* NCURSES_MOUSE_VERSION */ + +/**************************************************************************** + * + * Character input test + * + ****************************************************************************/ + +static void getch_test(void) +/* test the keypad feature */ +{ +char buf[BUFSIZ]; +int c; +int incount = 0, firsttime = 0; +bool blocking = TRUE; +int y, x; + + refresh(); + +#ifdef NCURSES_MOUSE_VERSION + mousemask(ALL_MOUSE_EVENTS, (mmask_t *)0); +#endif + + (void) printw("Delay in 10ths of a second (<CR> for blocking input)? "); + echo(); + getstr(buf); + noecho(); + nonl(); + + if (isdigit(buf[0])) + { + timeout(atoi(buf) * 100); + blocking = FALSE; + } + + c = '?'; + raw(); + for (;;) + { + if (firsttime++) + { + printw("Key pressed: %04o ", c); +#ifdef NCURSES_MOUSE_VERSION + if (c == KEY_MOUSE) + { + MEVENT event; + + getmouse(&event); + printw("KEY_MOUSE, %s\n", mouse_decode(&event)); + } + else +#endif /* NCURSES_MOUSE_VERSION */ + if (c >= KEY_MIN) + { + (void) addstr(keyname(c)); + addch('\n'); + } + else if (c > 0x80) + { + int c2 = (c & 0x7f); + if (isprint(c2)) + (void) printw("M-%c", c2); + else + (void) printw("M-%s", unctrl(c2)); + addstr(" (high-half character)\n"); + } + else + { + if (isprint(c)) + (void) printw("%c (ASCII printable character)\n", c); + else + (void) printw("%s (ASCII control character)\n", unctrl(c)); + } + getyx(stdscr, y, x); + if (y >= LINES-1) + move(0,0); + clrtoeol(); + } + + if (c == 'g') + { + addstr("getstr test: "); + echo(); getstr(buf); noecho(); + printw("I saw `%s'.\n", buf); + } + if (c == 's') + { + ShellOut(TRUE); + } + if (c == 'x' || c == 'q' || (c == ERR && blocking)) + break; + if (c == '?') + { + addstr("Type any key to see its keypad value. Also:\n"); + addstr("g -- triggers a getstr test\n"); + addstr("s -- shell out\n"); + addstr("q -- quit\n"); + addstr("? -- repeats this help message\n"); + } + + while ((c = Getchar()) == ERR) + if (!blocking) + (void) printw("%05d: input timed out\n", incount++); + else { + (void) printw("%05d: input error\n", incount++); + break; + } + } + +#ifdef NCURSES_MOUSE_VERSION + mousemask(0, (mmask_t *)0); +#endif + timeout(-1); + erase(); + noraw(); + nl(); + endwin(); +} + +static int show_attr(int row, int skip, chtype attr, const char *name, bool once) +{ + int ncv = tigetnum("ncv"); + + mvprintw(row, 8, "%s mode:", name); + mvprintw(row, 24, "|"); + if (skip) printw("%*s", skip, " "); + if (once) + attron(attr); + else + attrset(attr); + addstr("abcde fghij klmno pqrst uvwxy z"); + if (once) + attroff(attr); + if (skip) printw("%*s", skip, " "); + printw("|"); + if (attr != A_NORMAL) { + if (!(termattrs() & attr)) { + printw(" (N/A)"); + } else if (ncv > 0 && (getbkgd(stdscr) & A_COLOR)) { + static const attr_t table[] = { + A_STANDOUT, + A_UNDERLINE, + A_REVERSE, + A_BLINK, + A_DIM, + A_BOLD, + A_INVIS, + A_PROTECT, + A_ALTCHARSET + }; + unsigned n; + bool found = FALSE; + for (n = 0; n < sizeof(table)/sizeof(table[0]); n++) { + if ((table[n] & attr) != 0 + && ((1 << n) & ncv) != 0) { + found = TRUE; + break; + } + } + if (found) + printw(" (NCV)"); + } + } + return row + 2; +} + +static bool attr_getc(int *skip, int *fg, int *bg) +{ + int ch = Getchar(); + + if (isdigit(ch)) { + *skip = (ch - '0'); + return TRUE; + } else if (ch == CTRL('L')) { + touchwin(stdscr); + touchwin(curscr); + return TRUE; + } else if (has_colors()) { + switch (ch) { + case 'f': *fg = (*fg + 1); break; + case 'F': *fg = (*fg - 1); break; + case 'b': *bg = (*bg + 1); break; + case 'B': *bg = (*bg - 1); break; + default: + return FALSE; + } + if (*fg >= COLORS) *fg = 0; + if (*fg < 0) *fg = COLORS - 1; + if (*bg >= COLORS) *bg = 0; + if (*bg < 0) *bg = COLORS - 1; + return TRUE; + } + return FALSE; +} + +static void attr_test(void) +/* test text attributes */ +{ + int n; + int skip = tigetnum("xmc"); + int fg = COLOR_BLACK; /* color pair 0 is special */ + int bg = COLOR_BLACK; + bool *pairs = (bool *)calloc(COLOR_PAIRS, sizeof(bool)); + pairs[0] = TRUE; + + if (skip < 0) + skip = 0; + + n = skip; /* make it easy */ + + do { + int row = 2; + int normal = A_NORMAL | BLANK; + + if (has_colors()) { + int pair = (fg * COLORS) + bg; + if (!pairs[pair]) { + init_pair(pair, fg, bg); + pairs[pair] = TRUE; + } + normal |= COLOR_PAIR(pair); + } + bkgdset(normal); + erase(); + + mvaddstr(0, 20, "Character attribute test display"); + + row = show_attr(row, n, A_STANDOUT, "STANDOUT", TRUE); + row = show_attr(row, n, A_REVERSE, "REVERSE", TRUE); + row = show_attr(row, n, A_BOLD, "BOLD", TRUE); + row = show_attr(row, n, A_UNDERLINE, "UNDERLINE", TRUE); + row = show_attr(row, n, A_DIM, "DIM", TRUE); + row = show_attr(row, n, A_BLINK, "BLINK", TRUE); + row = show_attr(row, n, A_PROTECT, "PROTECT", TRUE); + row = show_attr(row, n, A_INVIS, "INVISIBLE", TRUE); + row = show_attr(row, n, A_NORMAL, "NORMAL", FALSE); + + mvprintw(row, 8, + "This terminal does %shave the magic-cookie glitch", + tigetnum("xmc") > -1 ? "" : "not "); + mvprintw(row+1, 8, + "Enter a digit to set gaps on each side of displayed attributes"); + mvprintw(row+2, 8, + "^L = repaint"); + if (has_colors()) + printw(". f/F/b/F toggle colors (now %d/%d)", fg, bg); + + refresh(); + } while (attr_getc(&n, &fg, &bg)); + + free((char *)pairs); + bkgdset(A_NORMAL | BLANK); + erase(); + endwin(); +} + +/**************************************************************************** + * + * Color support tests + * + ****************************************************************************/ + +static NCURSES_CONST char *color_names[] = +{ + "black", + "red", + "green", + "yellow", + "blue", + "magenta", + "cyan", + "white" +}; + +static void show_color_name(int y, int x, int color) +{ + if (COLORS > 8) + mvprintw(y, x, "%02d ", color); + else + mvaddstr(y, x, color_names[color]); +} + +static void color_test(void) +/* generate a color test pattern */ +{ + int i; + int base, top, width; + NCURSES_CONST char *hello; + + refresh(); + (void) printw("There are %d color pairs\n", COLOR_PAIRS); + + width = (COLORS > 8) ? 4 : 8; + hello = (COLORS > 8) ? "Test" : "Hello"; + + for (base = 0; base < 2; base++) + { + top = (COLORS > 8) ? 0 : base * (COLORS+3); + clrtobot(); + (void) mvprintw(top + 1, 0, + "%dx%d matrix of foreground/background colors, bright *%s*\n", + COLORS, COLORS, + base ? "on" : "off"); + for (i = 0; i < COLORS; i++) + show_color_name(top + 2, (i+1) * width, i); + for (i = 0; i < COLORS; i++) + show_color_name(top + 3 + i, 0, i); + for (i = 1; i < COLOR_PAIRS; i++) + { + init_pair(i, i % COLORS, i / COLORS); + attron((attr_t)COLOR_PAIR(i)); + if (base) + attron((attr_t)A_BOLD); + mvaddstr(top + 3 + (i / COLORS), (i % COLORS + 1) * width, hello); + attrset(A_NORMAL); + } + if ((COLORS > 8) || base) + Pause(); + } + + erase(); + endwin(); +} + +static void change_color(int current, int field, int value, int usebase) +{ + short red, green, blue; + + if (usebase) + color_content(current, &red, &green, &blue); + else + red = green = blue = 0; + + switch (field) { + case 0: + red += value; + break; + case 1: + green += value; + break; + case 2: + blue += value; + break; + } + + if (init_color(current, red, green, blue) == ERR) + beep(); +} + +static void color_edit(void) +/* display the color test pattern, without trying to edit colors */ +{ + int i, this_c = 0, value = 0, current = 0, field = 0; + int last_c; + + refresh(); + + for (i = 0; i < COLORS; i++) + init_pair(i, COLOR_WHITE, i); + + mvprintw(LINES-2, 0, "Number: %d", value); + + do { + short red, green, blue; + + attron(A_BOLD); + mvaddstr(0, 20, "Color RGB Value Editing"); + attroff(A_BOLD); + + for (i = 0; i < COLORS; i++) + { + mvprintw(2 + i, 0, "%c %-8s:", + (i == current ? '>' : ' '), + (i < (int) SIZEOF(color_names) + ? color_names[i] : "")); + attrset(COLOR_PAIR(i)); + addstr(" "); + attrset(A_NORMAL); + + /* + * Note: this refresh should *not* be necessary! It works around + * a bug in attribute handling that apparently causes the A_NORMAL + * attribute sets to interfere with the actual emission of the + * color setting somehow. This needs to be fixed. + */ + refresh(); + + color_content(i, &red, &green, &blue); + addstr(" R = "); + if (current == i && field == 0) attron(A_STANDOUT); + printw("%04d", red); + if (current == i && field == 0) attrset(A_NORMAL); + addstr(", G = "); + if (current == i && field == 1) attron(A_STANDOUT); + printw("%04d", green); + if (current == i && field == 1) attrset(A_NORMAL); + addstr(", B = "); + if (current == i && field == 2) attron(A_STANDOUT); + printw("%04d", blue); + if (current == i && field == 2) attrset(A_NORMAL); + attrset(A_NORMAL); + addstr(")"); + } + + mvaddstr(COLORS + 3, 0, + "Use up/down to select a color, left/right to change fields."); + mvaddstr(COLORS + 4, 0, + "Modify field by typing nnn=, nnn-, or nnn+. ? for help."); + + move(2 + current, 0); + + last_c = this_c; + this_c = Getchar(); + if (isdigit(this_c) && !isdigit(last_c)) + value = 0; + + switch (this_c) + { + case KEY_UP: + current = (current == 0 ? (COLORS - 1) : current - 1); + break; + + case KEY_DOWN: + current = (current == (COLORS - 1) ? 0 : current + 1); + break; + + case KEY_RIGHT: + field = (field == 2 ? 0 : field + 1); + break; + + case KEY_LEFT: + field = (field == 0 ? 2 : field - 1); + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + value = value * 10 + (this_c - '0'); + break; + + case '+': + change_color(current, field, value, 1); + break; + + case '-': + change_color(current, field, -value, 1); + break; + + case '=': + change_color(current, field, value, 0); + break; + + case '?': + erase(); + P(" RGB Value Editing Help"); + P(""); + P("You are in the RGB value editor. Use the arrow keys to select one of"); + P("the fields in one of the RGB triples of the current colors; the one"); + P("currently selected will be reverse-video highlighted."); + P(""); + P("To change a field, enter the digits of the new value; they are echoed"); + P("as entered. Finish by typing `='. The change will take effect instantly."); + P("To increment or decrement a value, use the same procedure, but finish"); + P("with a `+' or `-'."); + P(""); + P("To quit, do `x' or 'q'"); + + Pause(); + erase(); + break; + + case 'x': + case 'q': + break; + + default: + beep(); + break; + } + mvprintw(LINES-2, 0, "Number: %d", value); + clrtoeol(); + } while + (this_c != 'x' && this_c != 'q'); + + erase(); + endwin(); +} + +/**************************************************************************** + * + * Soft-key label test + * + ****************************************************************************/ + +static void slk_test(void) +/* exercise the soft keys */ +{ + int c, fmt = 1; + char buf[9]; + + c = CTRL('l'); + do { + move(0, 0); + switch(c) + { + case CTRL('l'): + erase(); + attron(A_BOLD); + mvaddstr(0, 20, "Soft Key Exerciser"); + attroff(A_BOLD); + + move(2, 0); + P("Available commands are:"); + P(""); + P("^L -- refresh screen"); + P("a -- activate or restore soft keys"); + P("d -- disable soft keys"); + P("c -- set centered format for labels"); + P("l -- set left-justified format for labels"); + P("r -- set right-justified format for labels"); + P("[12345678] -- set label; labels are numbered 1 through 8"); + P("e -- erase stdscr (should not erase labels)"); + P("s -- test scrolling of shortened screen"); + P("x, q -- return to main menu"); + P(""); + P("Note: if activating the soft keys causes your terminal to"); + P("scroll up one line, your terminal auto-scrolls when anything"); + P("is written to the last screen position. The ncurses code"); + P("does not yet handle this gracefully."); + refresh(); + /* fall through */ + + case 'a': + slk_restore(); + break; + + case 'e': + wclear(stdscr); + break; + + case 's': + mvprintw(20, 0, "Press Q to stop the scrolling-test: "); + while ((c = Getchar()) != 'Q' && (c != ERR)) + addch((chtype)c); + break; + + case 'd': + slk_clear(); + break; + + case 'l': + fmt = 0; + break; + + case 'c': + fmt = 1; + break; + + case 'r': + fmt = 2; + break; + + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': + (void) mvaddstr(20, 0, "Please enter the label value: "); + echo(); + wgetnstr(stdscr, buf, 8); + noecho(); + slk_set((c - '0'), buf, fmt); + slk_refresh(); + move(20, 0); clrtoeol(); + break; + + case 'x': + case 'q': + goto done; + + default: + beep(); + } + } while + ((c = Getchar()) != EOF); + + done: + erase(); + endwin(); +} + +/**************************************************************************** + * + * Alternate character-set stuff + * + ****************************************************************************/ + +/* ISO 6429: codes 0x80 to 0x9f may be control characters that cause the + * terminal to perform functions. The remaining codes can be graphic. + */ +static void show_upper_chars(int first) +{ + bool C1 = (first == 128); + int code; + int last = first + 31; + int reply; + + erase(); + attron(A_BOLD); + mvprintw(0, 20, "Display of %s Character Codes %d to %d", + C1 ? "C1" : "GR", first, last); + attroff(A_BOLD); + refresh(); + + for (code = first; code <= last; code++) { + int row = 4 + ((code - first) % 16); + int col = ((code - first) / 16) * COLS / 2; + char tmp[80]; + sprintf(tmp, "%3d (0x%x)", code, code); + mvprintw(row, col, "%*s: ", COLS/4, tmp); + if (C1) + nodelay(stdscr, TRUE); + echochar(code); + if (C1) { + /* (yes, this _is_ crude) */ + while ((reply = Getchar()) != ERR) { + addch(reply); + napms(10); + } + nodelay(stdscr, FALSE); + } + } +} + +static int show_1_acs(int n, const char *name, chtype code) +{ + const int height = 16; + int row = 4 + (n % height); + int col = (n / height) * COLS / 2; + mvprintw(row, col, "%*s : ", COLS/4, name); + addch(code); + return n + 1; +} + +static void show_acs_chars(void) +/* display the ACS character set */ +{ + int n; + +#define BOTH(name) #name, name + + erase(); + attron(A_BOLD); + mvaddstr(0, 20, "Display of the ACS Character Set"); + attroff(A_BOLD); + refresh(); + + n = show_1_acs(0, BOTH(ACS_ULCORNER)); + n = show_1_acs(n, BOTH(ACS_LLCORNER)); + n = show_1_acs(n, BOTH(ACS_URCORNER)); + n = show_1_acs(n, BOTH(ACS_LRCORNER)); + n = show_1_acs(n, BOTH(ACS_RTEE)); + n = show_1_acs(n, BOTH(ACS_LTEE)); + n = show_1_acs(n, BOTH(ACS_BTEE)); + n = show_1_acs(n, BOTH(ACS_TTEE)); + n = show_1_acs(n, BOTH(ACS_HLINE)); + n = show_1_acs(n, BOTH(ACS_VLINE)); + n = show_1_acs(n, BOTH(ACS_PLUS)); + n = show_1_acs(n, BOTH(ACS_S1)); + n = show_1_acs(n, BOTH(ACS_S9)); + n = show_1_acs(n, BOTH(ACS_DIAMOND)); + n = show_1_acs(n, BOTH(ACS_CKBOARD)); + n = show_1_acs(n, BOTH(ACS_DEGREE)); + n = show_1_acs(n, BOTH(ACS_PLMINUS)); + n = show_1_acs(n, BOTH(ACS_BULLET)); + n = show_1_acs(n, BOTH(ACS_LARROW)); + n = show_1_acs(n, BOTH(ACS_RARROW)); + n = show_1_acs(n, BOTH(ACS_DARROW)); + n = show_1_acs(n, BOTH(ACS_UARROW)); + n = show_1_acs(n, BOTH(ACS_BOARD)); + n = show_1_acs(n, BOTH(ACS_LANTERN)); + n = show_1_acs(n, BOTH(ACS_BLOCK)); + n = show_1_acs(n, BOTH(ACS_S3)); + n = show_1_acs(n, BOTH(ACS_S7)); + n = show_1_acs(n, BOTH(ACS_LEQUAL)); + n = show_1_acs(n, BOTH(ACS_GEQUAL)); + n = show_1_acs(n, BOTH(ACS_PI)); + n = show_1_acs(n, BOTH(ACS_NEQUAL)); + n = show_1_acs(n, BOTH(ACS_STERLING)); +} + +static void acs_display(void) +{ + int c = 'a'; + + do { + switch (c) { + case 'a': + show_acs_chars(); + break; + case '0': + case '1': + case '2': + case '3': + show_upper_chars((c - '0') * 32 + 128); + break; + } + mvprintw(LINES-3,0, "Note: ANSI terminals may not display C1 characters."); + mvprintw(LINES-2,0, "Select: a=ACS, 0=C1, 1,2,3=GR characters, q=quit"); + refresh(); + } while ((c = Getchar()) != 'x' && c != 'q'); + + Pause(); + erase(); + endwin(); +} + +/* + * Graphic-rendition test (adapted from vttest) + */ +static void +test_sgr_attributes(void) +{ + int pass; + + for (pass = 0; pass < 2; pass++) { + int normal = ((pass == 0 ? A_NORMAL : A_REVERSE)) | BLANK; + + /* Use non-default colors if possible to exercise bce a little */ + if (has_colors()) { + init_pair(1, COLOR_WHITE, COLOR_BLUE); + normal |= COLOR_PAIR(1); + } + bkgdset(normal); + erase(); + mvprintw( 1,20, "Graphic rendition test pattern:"); + + mvprintw( 4, 1, "vanilla"); + +#define set_sgr(mask) bkgdset((normal^(mask))); + set_sgr(A_BOLD); + mvprintw( 4,40, "bold"); + + set_sgr(A_UNDERLINE); + mvprintw( 6, 6, "underline"); + + set_sgr(A_BOLD|A_UNDERLINE); + mvprintw( 6,45, "bold underline"); + + set_sgr(A_BLINK); + mvprintw( 8, 1, "blink"); + + set_sgr(A_BLINK|A_BOLD); + mvprintw( 8,40, "bold blink"); + + set_sgr(A_UNDERLINE|A_BLINK); + mvprintw(10, 6, "underline blink"); + + set_sgr(A_BOLD|A_UNDERLINE|A_BLINK); + mvprintw(10,45, "bold underline blink"); + + set_sgr(A_REVERSE); + mvprintw(12, 1, "negative"); + + set_sgr(A_BOLD|A_REVERSE); + mvprintw(12,40, "bold negative"); + + set_sgr(A_UNDERLINE|A_REVERSE); + mvprintw(14, 6, "underline negative"); + + set_sgr(A_BOLD|A_UNDERLINE|A_REVERSE); + mvprintw(14,45, "bold underline negative"); + + set_sgr(A_BLINK|A_REVERSE); + mvprintw(16, 1, "blink negative"); + + set_sgr(A_BOLD|A_BLINK|A_REVERSE); + mvprintw(16,40, "bold blink negative"); + + set_sgr(A_UNDERLINE|A_BLINK|A_REVERSE); + mvprintw(18, 6, "underline blink negative"); + + set_sgr(A_BOLD|A_UNDERLINE|A_BLINK|A_REVERSE); + mvprintw(18,45, "bold underline blink negative"); + + bkgdset(normal); + mvprintw(LINES-2,1, "%s background. ", pass == 0 ? "Dark" : "Light"); + clrtoeol(); + Pause(); + } + + bkgdset(A_NORMAL | BLANK); + erase(); + endwin(); +} + +/**************************************************************************** + * + * Windows and scrolling tester. + * + ****************************************************************************/ + +#define BOTLINES 4 /* number of line stolen from screen bottom */ + +typedef struct +{ + int y, x; +} +pair; + +#define FRAME struct frame +FRAME +{ + FRAME *next, *last; + bool do_scroll; + bool do_keypad; + WINDOW *wind; +}; + +/* We need to know if these flags are actually set, so don't look in FRAME. + * These names are known to work with SVr4 curses as well as ncurses. + */ +static bool HaveKeypad(FRAME *curp) +{ + WINDOW *win = (curp ? curp->wind : stdscr); + return win->_use_keypad; +} + +static bool HaveScroll(FRAME *curp) +{ + WINDOW *win = (curp ? curp->wind : stdscr); + return win->_scroll; +} + +static void newwin_legend(FRAME *curp) +{ + static const struct { + const char *msg; + int code; + } legend[] = { + { "^C = create window", 0 }, + { "^N = next window", 0 }, + { "^P = previous window", 0 }, + { "^F = scroll forward", 0 }, + { "^B = scroll backward", 0 }, + { "^K = keypad(%s)", 1 }, + { "^S = scrollok(%s)", 2 }, + { "^W = save window to file", 0 }, + { "^R = restore window", 0 }, +#ifdef NCURSES_VERSION + { "^X = resize", 0 }, +#endif + { "^Q%s = exit", 3 } + }; + size_t n; + int y, x; + bool do_keypad = HaveKeypad(curp); + bool do_scroll = HaveScroll(curp); + char buf[BUFSIZ]; + + move(LINES-4, 0); + for (n = 0; n < SIZEOF(legend); n++) { + switch (legend[n].code) { + default: + strcpy(buf, legend[n].msg); + break; + case 1: + sprintf(buf, legend[n].msg, do_keypad ? "yes" : "no"); + break; + case 2: + sprintf(buf, legend[n].msg, do_scroll ? "yes" : "no"); + break; + case 3: + sprintf(buf, legend[n].msg, do_keypad ? "/ESC" : ""); + break; + } + getyx(stdscr, y, x); + addstr((COLS < (x + 3 + (int)strlen(buf))) ? "\n" : (n ? ", " : "")); + addstr(buf); + } + clrtoeol(); +} + +static void transient(FRAME *curp, NCURSES_CONST char *msg) +{ + newwin_legend(curp); + if (msg) + { + mvaddstr(LINES - 1, 0, msg); + refresh(); + napms(1000); + } + + move(LINES-1, 0); + printw("%s characters are echoed, window should %sscroll.", + HaveKeypad(curp) ? "Non-arrow" : "All other", + HaveScroll(curp) ? "" : "not " ); + clrtoeol(); +} + +static void newwin_report(FRAME *curp) +/* report on the cursor's current position, then restore it */ +{ + WINDOW *win = (curp != 0) ? curp->wind : stdscr; + int y, x; + + if (win != stdscr) + transient(curp, (char *)0); + getyx(win, y, x); + move(LINES - 1, COLS - 17); + printw("Y = %2d X = %2d", y, x); + if (win != stdscr) + refresh(); + else + wmove(win, y, x); +} + +static pair *selectcell(int uli, int ulj, int lri, int lrj) +/* arrows keys move cursor, return location at current on non-arrow key */ +{ + static pair res; /* result cell */ + int si = lri - uli + 1; /* depth of the select area */ + int sj = lrj - ulj + 1; /* width of the select area */ + int i = 0, j = 0; /* offsets into the select area */ + + res.y = uli; + res.x = ulj; + for (;;) + { + move(uli + i, ulj + j); + newwin_report((FRAME *)0); + + switch(Getchar()) + { + case KEY_UP: i += si - 1; break; + case KEY_DOWN: i++; break; + case KEY_LEFT: j += sj - 1; break; + case KEY_RIGHT: j++; break; + case QUIT: + case ESCAPE: return((pair *)0); +#ifdef NCURSES_MOUSE_VERSION + case KEY_MOUSE: + { + MEVENT event; + + getmouse(&event); + if (event.y > uli && event.x > ulj) { + i = event.y - uli; + j = event.x - ulj; + } else { + beep(); + break; + } + } + /* FALLTHRU */ +#endif + default: res.y = uli + i; res.x = ulj + j; return(&res); + } + i %= si; + j %= sj; + } +} + +static void outerbox(pair ul, pair lr, bool onoff) +/* draw or erase a box *outside* the given pair of corners */ +{ + mvaddch(ul.y-1, lr.x-1, onoff ? ACS_ULCORNER : ' '); + mvaddch(ul.y-1, lr.x+1, onoff ? ACS_URCORNER : ' '); + mvaddch(lr.y+1, lr.x+1, onoff ? ACS_LRCORNER : ' '); + mvaddch(lr.y+1, ul.x-1, onoff ? ACS_LLCORNER : ' '); + move(ul.y-1, ul.x); hline(onoff ? ACS_HLINE : ' ', lr.x - ul.x + 1); + move(ul.y, ul.x-1); vline(onoff ? ACS_VLINE : ' ', lr.y - ul.y + 1); + move(lr.y+1, ul.x); hline(onoff ? ACS_HLINE : ' ', lr.x - ul.x + 1); + move(ul.y, lr.x+1); vline(onoff ? ACS_VLINE : ' ', lr.y - ul.y + 1); +} + +static WINDOW *getwindow(void) +/* Ask user for a window definition */ +{ + WINDOW *rwindow; + pair ul, lr, *tmp; + + move(0, 0); clrtoeol(); + addstr("Use arrows to move cursor, anything else to mark corner 1"); + refresh(); + if ((tmp = selectcell(2, 1, LINES-BOTLINES-2, COLS-2)) == (pair *)0) + return((WINDOW *)0); + memcpy(&ul, tmp, sizeof(pair)); + mvaddch(ul.y-1, ul.x-1, ACS_ULCORNER); + move(0, 0); clrtoeol(); + addstr("Use arrows to move cursor, anything else to mark corner 2"); + refresh(); + if ((tmp = selectcell(ul.y, ul.x, LINES-BOTLINES-2, COLS-2)) == (pair *)0) + return((WINDOW *)0); + memcpy(&lr, tmp, sizeof(pair)); + + rwindow = subwin(stdscr, lr.y - ul.y + 1, lr.x - ul.x + 1, ul.y, ul.x); + + outerbox(ul, lr, TRUE); + refresh(); + + wrefresh(rwindow); + + move(0, 0); clrtoeol(); + return(rwindow); +} + +static void newwin_move(FRAME *curp, int dy, int dx) +{ + WINDOW *win = (curp != 0) ? curp->wind : stdscr; + int cur_y, cur_x; + int max_y, max_x; + + getyx(win, cur_y, cur_x); + getmaxyx(win, max_y, max_x); + if ((cur_x += dx) < 0) + cur_x = 0; + else if (cur_x >= max_x) + cur_x = max_x - 1; + if ((cur_y += dy) < 0) + cur_y = 0; + else if (cur_y >= max_y) + cur_y = max_y - 1; + wmove(win, cur_y, cur_x); +} + +static FRAME *delete_framed(FRAME *fp, bool showit) +{ + FRAME *np; + + fp->last->next = fp->next; + fp->next->last = fp->last; + + if (showit) { + werase(fp->wind); + wrefresh(fp->wind); + } + delwin(fp->wind); + + np = (fp == fp->next) ? 0 : fp->next; + free(fp); + return np; +} + +static void acs_and_scroll(void) +/* Demonstrate windows */ +{ + int c, i; + FILE *fp; + FRAME *current = (FRAME *)0, *neww; + WINDOW *usescr = stdscr; + +#define DUMPFILE "screendump" + +#ifdef NCURSES_MOUSE_VERSION + mousemask(BUTTON1_CLICKED, (mmask_t *)0); +#endif + c = CTRL('C'); + raw(); + do { + transient((FRAME *)0, (char *)0); + switch(c) + { + case CTRL('C'): + neww = (FRAME *) calloc(1, sizeof(FRAME)); + if ((neww->wind = getwindow()) == (WINDOW *)0) + goto breakout; + + if (current == 0) /* First element, */ + { + neww->next = neww; /* so point it at itself */ + neww->last = neww; + } + else + { + neww->next = current->next; + neww->last = current; + neww->last->next = neww; + neww->next->last = neww; + } + current = neww; + /* SVr4 curses sets the keypad on all newly-created windows to + * false. Someone reported that PDCurses makes new windows inherit + * this flag. Remove the following 'keypad()' call to test this + */ + keypad(current->wind, TRUE); + current->do_keypad = HaveKeypad(current); + current->do_scroll = HaveScroll(current); + break; + + case CTRL('N'): /* go to next window */ + if (current) + current = current->next; + break; + + case CTRL('P'): /* go to previous window */ + if (current) + current = current->last; + break; + + case CTRL('F'): /* scroll current window forward */ + if (current) + wscrl(current->wind, 1); + break; + + case CTRL('B'): /* scroll current window backwards */ + if (current) + wscrl(current->wind, -1); + break; + + case CTRL('K'): /* toggle keypad mode for current */ + if (current) { + current->do_keypad = !current->do_keypad; + keypad(current->wind, current->do_keypad); + } + break; + + case CTRL('S'): + if (current) { + current->do_scroll = !current->do_scroll; + scrollok(current->wind, current->do_scroll); + } + break; + + case CTRL('W'): /* save and delete window */ + if (current == current->next) + break; + if ((fp = fopen(DUMPFILE, "w")) == (FILE *)0) + transient(current, "Can't open screen dump file"); + else + { + (void) putwin(current->wind, fp); + (void) fclose(fp); + + current = delete_framed(current, TRUE); + } + break; + + case CTRL('R'): /* restore window */ + if ((fp = fopen(DUMPFILE, "r")) == (FILE *)0) + transient(current, "Can't open screen dump file"); + else + { + neww = (FRAME *) calloc(1, sizeof(FRAME)); + + neww->next = current->next; + neww->last = current; + neww->last->next = neww; + neww->next->last = neww; + + neww->wind = getwin(fp); + (void) fclose(fp); + + wrefresh(neww->wind); + } + break; + +#ifdef NCURSES_VERSION + case CTRL('X'): /* resize window */ + if (current) + { + pair *tmp, ul, lr; + int mx, my; + + move(0, 0); clrtoeol(); + addstr("Use arrows to move cursor, anything else to mark new corner"); + refresh(); + + getbegyx(current->wind, ul.y, ul.x); + + tmp = selectcell(ul.y, ul.x, LINES-BOTLINES-2, COLS-2); + if (tmp == (pair *)0) + { + beep(); + break; + } + + getmaxyx(current->wind, lr.y, lr.x); + lr.y += (ul.y - 1); + lr.x += (ul.x - 1); + outerbox(ul, lr, FALSE); + wnoutrefresh(stdscr); + + /* strictly cosmetic hack for the test */ + getmaxyx(current->wind, my, mx); + if (my > tmp->y - ul.y) + { + getyx(current->wind, lr.y, lr.x); + wmove(current->wind, tmp->y - ul.y + 1, 0); + wclrtobot(current->wind); + wmove(current->wind, lr.y, lr.x); + } + if (mx > tmp->x - ul.x) + for (i = 0; i < my; i++) + { + wmove(current->wind, i, tmp->x - ul.x + 1); + wclrtoeol(current->wind); + } + wnoutrefresh(current->wind); + + memcpy(&lr, tmp, sizeof(pair)); + (void) wresize(current->wind, lr.y-ul.y+0, lr.x-ul.x+0); + + getbegyx(current->wind, ul.y, ul.x); + getmaxyx(current->wind, lr.y, lr.x); + lr.y += (ul.y - 1); + lr.x += (ul.x - 1); + outerbox(ul, lr, TRUE); + wnoutrefresh(stdscr); + + wnoutrefresh(current->wind); + move(0, 0); clrtoeol(); + doupdate(); + } + break; +#endif /* NCURSES_VERSION */ + + case KEY_F(10): /* undocumented --- use this to test area clears */ + selectcell(0, 0, LINES - 1, COLS - 1); + clrtobot(); + refresh(); + break; + + case KEY_UP: + newwin_move(current, -1, 0); + break; + case KEY_DOWN: + newwin_move(current, 1, 0); + break; + case KEY_LEFT: + newwin_move(current, 0, -1); + break; + case KEY_RIGHT: + newwin_move(current, 0, 1); + break; + + case KEY_BACKSPACE: + /* FALLTHROUGH */ + case KEY_DC: + { + int y, x; + getyx(current->wind, y, x); + if (--x < 0) { + if (--y < 0) + break; + x = getmaxx(current->wind) - 1; + } + mvwdelch(current->wind, y, x); + } + break; + + case '\r': + c = '\n'; + /* FALLTHROUGH */ + + default: + if (current) + waddch(current->wind, (chtype)c); + else + beep(); + break; + } + newwin_report(current); + usescr = (current ? current->wind : stdscr); + wrefresh(usescr); + } while + ((c = wGetchar(usescr)) != QUIT + && !((c == ESCAPE) && (usescr->_use_keypad)) + && (c != ERR)); + + breakout: + while (current != 0) + current = delete_framed(current, FALSE); + + scrollok(stdscr, TRUE); /* reset to driver's default */ +#ifdef NCURSES_MOUSE_VERSION + mousemask(0, (mmask_t *)0); +#endif + noraw(); + erase(); + endwin(); +} + +/**************************************************************************** + * + * Panels tester + * + ****************************************************************************/ + +#if USE_LIBPANEL +static unsigned long nap_msec = 1; + +static NCURSES_CONST char *mod[] = +{ + "test ", + "TEST ", + "(**) ", + "*()* ", + "<--> ", + "LAST " +}; + +/*+------------------------------------------------------------------------- + wait_a_while(msec) +--------------------------------------------------------------------------*/ +static void +wait_a_while(unsigned long msec GCC_UNUSED) +{ +#if HAVE_NAPMS + if(nap_msec == 1) + wGetchar(stdscr); + else + napms(nap_msec); +#else + if(nap_msec == 1) + wGetchar(stdscr); + else if(msec > 1000L) + sleep((int)msec/1000L); + else + sleep(1); +#endif +} /* end of wait_a_while */ + +/*+------------------------------------------------------------------------- + saywhat(text) +--------------------------------------------------------------------------*/ +static void +saywhat(NCURSES_CONST char *text) +{ + wmove(stdscr,LINES - 1,0); + wclrtoeol(stdscr); + waddstr(stdscr, text); +} /* end of saywhat */ + +/*+------------------------------------------------------------------------- + mkpanel(rows,cols,tly,tlx) - alloc a win and panel and associate them +--------------------------------------------------------------------------*/ +static PANEL * +mkpanel(int color, int rows, int cols, int tly, int tlx) +{ +WINDOW *win; +PANEL *pan = 0; + + if ((win = newwin(rows, cols, tly, tlx)) != 0) { + if ((pan = new_panel(win)) == 0) { + delwin(win); + } else if (has_colors()) { + int fg = (color == COLOR_BLUE) ? COLOR_WHITE : COLOR_BLACK; + int bg = color; + init_pair(color, fg, bg); + wbkgdset(win, COLOR_PAIR(color) | ' '); + } else { + wbkgdset(win, A_BOLD | ' '); + } + } + return pan; +} /* end of mkpanel */ + +/*+------------------------------------------------------------------------- + rmpanel(pan) +--------------------------------------------------------------------------*/ +static void +rmpanel(PANEL *pan) +{ +WINDOW *win = panel_window(pan); + del_panel(pan); + delwin(win); +} /* end of rmpanel */ + +/*+------------------------------------------------------------------------- + pflush() +--------------------------------------------------------------------------*/ +static void +pflush(void) +{ + update_panels(); + doupdate(); +} /* end of pflush */ + +/*+------------------------------------------------------------------------- + fill_panel(win) +--------------------------------------------------------------------------*/ +static void +fill_panel(PANEL *pan) +{ +WINDOW *win = panel_window(pan); +int num = ((const char *)panel_userptr(pan))[1]; +int y,x; + + wmove(win,1,1); + wprintw(win,"-pan%c-", num); + wclrtoeol(win); + box(win, 0, 0); + for(y = 2; y < getmaxy(win) - 1; y++) + { + for(x = 1; x < getmaxx(win) - 1; x++) + { + wmove(win,y,x); + waddch(win,num); + } + } +} /* end of fill_panel */ + +static void demo_panels(void) +{ +int itmp; +register int y,x; + + refresh(); + + for(y = 0; y < LINES - 1; y++) + { + for(x = 0; x < COLS; x++) + wprintw(stdscr,"%d",(y + x) % 10); + } + for(y = 0; y < 5; y++) + { + PANEL *p1; + PANEL *p2; + PANEL *p3; + PANEL *p4; + PANEL *p5; + + p1 = mkpanel(COLOR_RED, LINES/2 - 2, COLS/8 + 1, 0, 0); + set_panel_userptr(p1,"p1"); + + p2 = mkpanel(COLOR_GREEN, LINES/2 + 1, COLS/7, LINES/4, COLS/10); + set_panel_userptr(p2,"p2"); + + p3 = mkpanel(COLOR_YELLOW, LINES/4, COLS/10, LINES/2, COLS/9); + set_panel_userptr(p3,"p3"); + + p4 = mkpanel(COLOR_BLUE, LINES/2 - 2, COLS/8, LINES/2 - 2, COLS/3); + set_panel_userptr(p4,"p4"); + + p5 = mkpanel(COLOR_MAGENTA, LINES/2 - 2, COLS/8, LINES/2, COLS/2 - 2); + set_panel_userptr(p5,"p5"); + + fill_panel(p1); + fill_panel(p2); + fill_panel(p3); + fill_panel(p4); + fill_panel(p5); + hide_panel(p4); + hide_panel(p5); + pflush(); + saywhat("press any key to continue"); + wait_a_while(nap_msec); + + saywhat("h3 s1 s2 s4 s5; press any key to continue"); + move_panel(p1,0,0); + hide_panel(p3); + show_panel(p1); + show_panel(p2); + show_panel(p4); + show_panel(p5); + pflush(); + wait_a_while(nap_msec); + + saywhat("s1; press any key to continue"); + show_panel(p1); + pflush(); + wait_a_while(nap_msec); + + saywhat("s2; press any key to continue"); + show_panel(p2); + pflush(); + wait_a_while(nap_msec); + + saywhat("m2; press any key to continue"); + move_panel(p2, LINES/3 + 1, COLS / 8); + pflush(); + wait_a_while(nap_msec); + + saywhat("s3;"); + show_panel(p3); + pflush(); + wait_a_while(nap_msec); + + saywhat("m3; press any key to continue"); + move_panel(p3, LINES/4 + 1, COLS / 15); + pflush(); + wait_a_while(nap_msec); + + saywhat("b3; press any key to continue"); + bottom_panel(p3); + pflush(); + wait_a_while(nap_msec); + + saywhat("s4; press any key to continue"); + show_panel(p4); + pflush(); + wait_a_while(nap_msec); + + saywhat("s5; press any key to continue"); + show_panel(p5); + pflush(); + wait_a_while(nap_msec); + + saywhat("t3; press any key to continue"); + top_panel(p3); + pflush(); + wait_a_while(nap_msec); + + saywhat("t1; press any key to continue"); + top_panel(p1); + pflush(); + wait_a_while(nap_msec); + + saywhat("t2; press any key to continue"); + top_panel(p2); + pflush(); + wait_a_while(nap_msec); + + saywhat("t3; press any key to continue"); + top_panel(p3); + pflush(); + wait_a_while(nap_msec); + + saywhat("t4; press any key to continue"); + top_panel(p4); + pflush(); + wait_a_while(nap_msec); + + for(itmp = 0; itmp < 6; itmp++) + { + WINDOW *w4 = panel_window(p4); + WINDOW *w5 = panel_window(p5); + + saywhat("m4; press any key to continue"); + wmove(w4, LINES/8, 1); + waddstr(w4,mod[itmp]); + move_panel(p4, LINES/6, itmp*(COLS/8)); + wmove(w5, LINES/6, 1); + waddstr(w5,mod[itmp]); + pflush(); + wait_a_while(nap_msec); + + saywhat("m5; press any key to continue"); + wmove(w4, LINES/6, 1); + waddstr(w4,mod[itmp]); + move_panel(p5, LINES/3 - 1,(itmp*10) + 6); + wmove(w5, LINES/8, 1); + waddstr(w5,mod[itmp]); + pflush(); + wait_a_while(nap_msec); + } + + saywhat("m4; press any key to continue"); + move_panel(p4, LINES/6, itmp*(COLS/8)); + pflush(); + wait_a_while(nap_msec); + + saywhat("t5; press any key to continue"); + top_panel(p5); + pflush(); + wait_a_while(nap_msec); + + saywhat("t2; press any key to continue"); + top_panel(p2); + pflush(); + wait_a_while(nap_msec); + + saywhat("t1; press any key to continue"); + top_panel(p1); + pflush(); + wait_a_while(nap_msec); + + saywhat("d2; press any key to continue"); + rmpanel(p2); + pflush(); + wait_a_while(nap_msec); + + saywhat("h3; press any key to continue"); + hide_panel(p3); + pflush(); + wait_a_while(nap_msec); + + saywhat("d1; press any key to continue"); + rmpanel(p1); + pflush(); + wait_a_while(nap_msec); + + saywhat("d4; press any key to continue"); + rmpanel(p4); + pflush(); + wait_a_while(nap_msec); + + saywhat("d5; press any key to continue"); + rmpanel(p5); + pflush(); + wait_a_while(nap_msec); + if(nap_msec == 1) + break; + nap_msec = 100L; + } + + erase(); + endwin(); +} + +/**************************************************************************** + * + * Pad tester + * + ****************************************************************************/ + +#define GRIDSIZE 3 + +static bool show_panner_legend = TRUE; + +static int panner_legend(int line) +{ + static const char *const legend[] = { + "Use arrow keys (or U,D,L,R) to pan, q to quit (?,t,s flags)", + "Use ! to shell-out. Toggle legend:?, timer:t, scroll mark:s.", + "Use +,- (or j,k) to grow/shrink the panner vertically.", + "Use <,> (or h,l) to grow/shrink the panner horizontally." + }; + int n = (SIZEOF(legend) - (LINES - line)); + if (line < LINES && (n >= 0)) { + move(line, 0); + if (show_panner_legend) + printw("%s", legend[n]); + clrtoeol(); + return show_panner_legend; + } + return FALSE; +} + +static void panner_h_cleanup(int from_y, int from_x, int to_x) +{ + if (!panner_legend(from_y)) + do_h_line(from_y, from_x, ' ', to_x); +} + +static void panner_v_cleanup(int from_y, int from_x, int to_y) +{ + if (!panner_legend(from_y)) + do_v_line(from_y, from_x, ' ', to_y); +} + +static void panner(WINDOW *pad, + int top_x, int top_y, int porty, int portx, + int (*pgetc)(WINDOW *)) +{ +#if HAVE_GETTIMEOFDAY + struct timeval before, after; + bool timing = TRUE; +#endif + bool scrollers = TRUE; + int basex = 0; + int basey = 0; + int pxmax, pymax, lowend, highend, c; + + getmaxyx(pad, pymax, pxmax); + scrollok(stdscr, FALSE); /* we don't want stdscr to scroll! */ + + c = KEY_REFRESH; + do { +#ifdef NCURSES_VERSION + /* + * During shell-out, the user may have resized the window. Adjust + * the port size of the pad to accommodate this. Ncurses automatically + * resizes all of the normal windows to fit on the new screen. + */ + if (top_x > COLS) top_x = COLS; + if (portx > COLS) portx = COLS; + if (top_y > LINES) top_y = LINES; + if (porty > LINES) porty = LINES; +#endif + switch(c) + { + case KEY_REFRESH: + erase(); + + /* FALLTHRU */ + case '?': + if (c == '?') + show_panner_legend = !show_panner_legend; + panner_legend(LINES - 4); + panner_legend(LINES - 3); + panner_legend(LINES - 2); + panner_legend(LINES - 1); + break; +#if HAVE_GETTIMEOFDAY + case 't': + timing = !timing; + if (!timing) + panner_legend(LINES-1); + break; +#endif + case 's': + scrollers = !scrollers; + break; + + /* Move the top-left corner of the pad, keeping the bottom-right + * corner fixed. + */ + case 'h': /* increase-columns: move left edge to left */ + if (top_x <= 0) + beep(); + else + { + panner_v_cleanup(top_y, top_x, porty); + top_x--; + } + break; + + case 'j': /* decrease-lines: move top-edge down */ + if (top_y >= porty) + beep(); + else + { + panner_h_cleanup(top_y - 1, top_x - (top_x > 0), portx); + top_y++; + } + break; + + case 'k': /* increase-lines: move top-edge up */ + if (top_y <= 0) + beep(); + else + { + top_y--; + panner_h_cleanup(top_y, top_x, portx); + } + break; + + case 'l': /* decrease-columns: move left-edge to right */ + if (top_x >= portx) + beep(); + else + { + panner_v_cleanup(top_y - (top_y > 0), top_x - 1, porty); + top_x++; + } + break; + + /* Move the bottom-right corner of the pad, keeping the top-left + * corner fixed. + */ + case KEY_IC: /* increase-columns: move right-edge to right */ + if (portx >= pxmax || portx >= COLS) + beep(); + else + { + panner_v_cleanup(top_y - (top_y > 0), portx - 1, porty); + ++portx; + } + break; + + case KEY_IL: /* increase-lines: move bottom-edge down */ + if (porty >= pymax || porty >= LINES) + beep(); + else + { + panner_h_cleanup(porty - 1, top_x - (top_x > 0), portx); + ++porty; + } + break; + + case KEY_DC: /* decrease-columns: move bottom edge up */ + if (portx <= top_x) + beep(); + else + { + portx--; + panner_v_cleanup(top_y - (top_y > 0), portx, porty); + } + break; + + case KEY_DL: /* decrease-lines */ + if (porty <= top_y) + beep(); + else + { + porty--; + panner_h_cleanup(porty, top_x - (top_x > 0), portx); + } + break; + + case KEY_LEFT: /* pan leftwards */ + if (basex > 0) + basex--; + else + beep(); + break; + + case KEY_RIGHT: /* pan rightwards */ + if (basex + portx - (pymax > porty) < pxmax) + basex++; + else + beep(); + break; + + case KEY_UP: /* pan upwards */ + if (basey > 0) + basey--; + else + beep(); + break; + + case KEY_DOWN: /* pan downwards */ + if (basey + porty - (pxmax > portx) < pymax) + basey++; + else + beep(); + break; + + default: + beep(); + break; + } + + mvaddch(top_y - 1, top_x - 1, ACS_ULCORNER); + do_v_line(top_y, top_x - 1, ACS_VLINE, porty); + do_h_line(top_y - 1, top_x, ACS_HLINE, portx); + + if (scrollers && (pxmax > portx - 1)) { + int length = (portx - top_x - 1); + float ratio = ((float) length) / ((float) pxmax); + + lowend = (int)(top_x + (basex * ratio)); + highend = (int)(top_x + ((basex + length) * ratio)); + + do_h_line(porty - 1, top_x, ACS_HLINE, lowend); + if (highend < portx) { + attron(A_REVERSE); + do_h_line(porty - 1, lowend, ' ', highend + 1); + attroff(A_REVERSE); + do_h_line(porty - 1, highend + 1, ACS_HLINE, portx); + } + } else + do_h_line(porty - 1, top_x, ACS_HLINE, portx); + + if (scrollers && (pymax > porty - 1)) { + int length = (porty - top_y - 1); + float ratio = ((float) length) / ((float) pymax); + + lowend = (int)(top_y + (basey * ratio)); + highend = (int)(top_y + ((basey + length) * ratio)); + + do_v_line(top_y, portx - 1, ACS_VLINE, lowend); + if (highend < porty) { + attron(A_REVERSE); + do_v_line(lowend, portx - 1, ' ', highend + 1); + attroff(A_REVERSE); + do_v_line(highend + 1, portx - 1, ACS_VLINE, porty); + } + } else + do_v_line(top_y, portx - 1, ACS_VLINE, porty); + + mvaddch(top_y - 1, portx - 1, ACS_URCORNER); + mvaddch(porty - 1, top_x - 1, ACS_LLCORNER); + mvaddch(porty - 1, portx - 1, ACS_LRCORNER); + +#if HAVE_GETTIMEOFDAY + gettimeofday(&before, 0); +#endif + wnoutrefresh(stdscr); + + pnoutrefresh(pad, + basey, basex, + top_y, top_x, + porty - (pxmax > portx) - 1, + portx - (pymax > porty) - 1); + + doupdate(); +#if HAVE_GETTIMEOFDAY + if (timing) { + double elapsed; + gettimeofday(&after, 0); + elapsed = (after.tv_sec + after.tv_usec / 1.0e6) + - (before.tv_sec + before.tv_usec / 1.0e6); + move(LINES-1, COLS-20); + printw("Secs: %2.03f", elapsed); + refresh(); + } +#endif + + } while + ((c = pgetc(pad)) != KEY_EXIT); + + scrollok(stdscr, TRUE); /* reset to driver's default */ +} + +static +int padgetch(WINDOW *win) +{ + int c; + + switch(c = wGetchar(win)) + { + case '!': ShellOut(FALSE); return KEY_REFRESH; + case CTRL('r'): endwin(); refresh(); return KEY_REFRESH; + case CTRL('l'): return KEY_REFRESH; + case 'U': return(KEY_UP); + case 'D': return(KEY_DOWN); + case 'R': return(KEY_RIGHT); + case 'L': return(KEY_LEFT); + case '+': return(KEY_IL); + case '-': return(KEY_DL); + case '>': return(KEY_IC); + case '<': return(KEY_DC); + case ERR: /* FALLTHRU */ + case 'q': return(KEY_EXIT); + default: return(c); + } +} + +static void demo_pad(void) +/* Demonstrate pads. */ +{ + int i, j; + unsigned gridcount = 0; + WINDOW *panpad = newpad(200, 200); + + for (i = 0; i < 200; i++) + { + for (j = 0; j < 200; j++) + if (i % GRIDSIZE == 0 && j % GRIDSIZE == 0) + { + if (i == 0 || j == 0) + waddch(panpad, '+'); + else + waddch(panpad, (chtype)('A' + (gridcount++ % 26))); + } + else if (i % GRIDSIZE == 0) + waddch(panpad, '-'); + else if (j % GRIDSIZE == 0) + waddch(panpad, '|'); + else + waddch(panpad, ' '); + } + panner_legend(LINES - 4); + panner_legend(LINES - 3); + panner_legend(LINES - 2); + panner_legend(LINES - 1); + + keypad(panpad, TRUE); + + /* Make the pad (initially) narrow enough that a trace file won't wrap. + * We'll still be able to widen it during a test, since that's required + * for testing boundaries. + */ + panner(panpad, 2, 2, LINES - 5, COLS-15, padgetch); + + delwin(panpad); + endwin(); + erase(); +} +#endif /* USE_LIBPANEL */ + +/**************************************************************************** + * + * Tests from John Burnell's PDCurses tester + * + ****************************************************************************/ + +static void Continue (WINDOW *win) +{ + noecho(); + wmove(win, 10, 1); + mvwaddstr(win, 10, 1, " Press any key to continue"); + wrefresh(win); + wGetchar(win); +} + +static void flushinp_test(WINDOW *win) +/* Input test, adapted from John Burnell's PDCurses tester */ +{ + int w, h, bx, by, sw, sh, i; + + WINDOW *subWin; + wclear (win); + + getmaxyx(win, h, w); + getbegyx(win, by, bx); + sw = w / 3; + sh = h / 3; + if((subWin = subwin(win, sh, sw, by + h - sh - 2, bx + w - sw - 2)) == 0) + return; + +#ifdef A_COLOR + if (has_colors()) + { + init_pair(2,COLOR_CYAN,COLOR_BLUE); + wattrset(subWin, COLOR_PAIR(2) | A_BOLD); + } + else + wattrset(subWin, A_BOLD); +#else + wattrset(subWin, A_BOLD); +#endif + box(subWin, ACS_VLINE, ACS_HLINE); + mvwaddstr(subWin, 2, 1, "This is a subwindow"); + wrefresh(win); + + /* + * This used to set 'nocbreak()'. However, Alexander Lukyanov says that + * it only happened to "work" on SVr4 because that implementation does not + * emulate nocbreak+noecho mode, whereas ncurses does. To get the desired + * test behavior, we're using 'cbreak()', which will allow a single + * character to return without needing a newline. - T.Dickey 1997/10/11. + */ + cbreak(); + mvwaddstr(win, 0, 1, "This is a test of the flushinp() call."); + + mvwaddstr(win, 2, 1, "Type random keys for 5 seconds."); + mvwaddstr(win, 3, 1, + "These should be discarded (not echoed) after the subwindow goes away."); + wrefresh(win); + + for (i = 0; i < 5; i++) + { + mvwprintw (subWin, 1, 1, "Time = %d", i); + wrefresh(subWin); + napms(1000); + flushinp(); + } + + delwin (subWin); + werase(win); + flash(); + wrefresh(win); + napms(1000); + + mvwaddstr(win, 2, 1, + "If you were still typing when the window timer expired,"); + mvwaddstr(win, 3, 1, + "or else you typed nothing at all while it was running,"); + mvwaddstr(win, 4, 1, + "test was invalid. You'll see garbage or nothing at all. "); + mvwaddstr(win, 6, 1, "Press a key"); + wmove(win, 9, 10); + wrefresh(win); + echo(); + wGetchar(win); + flushinp(); + mvwaddstr(win, 12, 0, + "If you see any key other than what you typed, flushinp() is broken."); + Continue(win); + + wmove(win, 9, 10); + wdelch(win); + wrefresh(win); + wmove(win, 12, 0); + clrtoeol(); + waddstr(win, + "What you typed should now have been deleted; if not, wdelch() failed."); + Continue(win); + + cbreak(); +} + +/**************************************************************************** + * + * Menu test + * + ****************************************************************************/ + +#if USE_LIBMENU + +#define MENU_Y 8 +#define MENU_X 8 + +static int menu_virtualize(int c) +{ + if (c == '\n' || c == KEY_EXIT) + return(MAX_COMMAND + 1); + else if (c == 'u') + return(REQ_SCR_ULINE); + else if (c == 'd') + return(REQ_SCR_DLINE); + else if (c == 'b' || c == KEY_NPAGE) + return(REQ_SCR_UPAGE); + else if (c == 'f' || c == KEY_PPAGE) + return(REQ_SCR_DPAGE); + else if (c == 'n' || c == KEY_DOWN) + return(REQ_NEXT_ITEM); + else if (c == 'p' || c == KEY_UP) + return(REQ_PREV_ITEM); + else if (c == ' ') + return(REQ_TOGGLE_ITEM); + else { + if (c != KEY_MOUSE) + beep(); + return(c); + } +} + +static const char *animals[] = +{ + "Lions", "Tigers", "Bears", "(Oh my!)", "Newts", "Platypi", "Lemurs", + (char *)0 +}; + +static void menu_test(void) +{ + MENU *m; + ITEM *items[SIZEOF(animals)]; + ITEM **ip = items; + const char **ap; + int mrows, mcols, c; + WINDOW *menuwin; + +#ifdef NCURSES_MOUSE_VERSION + mousemask(ALL_MOUSE_EVENTS, (mmask_t *)0); +#endif + mvaddstr(0, 0, "This is the menu test:"); + mvaddstr(2, 0, " Use up and down arrow to move the select bar."); + mvaddstr(3, 0, " 'n' and 'p' act like arrows."); + mvaddstr(4, 0, " 'b' and 'f' scroll up/down (page), 'u' and 'd' (line)."); + mvaddstr(5, 0, " Press return to exit."); + refresh(); + + for (ap = animals; *ap; ap++) + *ip++ = new_item(*ap, ""); + *ip = (ITEM *)0; + + m = new_menu(items); + + set_menu_format(m, (SIZEOF(animals)+1)/2, 1); + scale_menu(m, &mrows, &mcols); + + menuwin = newwin(mrows + 2, mcols + 2, MENU_Y, MENU_X); + set_menu_win(m, menuwin); + keypad(menuwin, TRUE); + box(menuwin, 0, 0); + + set_menu_sub(m, derwin(menuwin, mrows, mcols, 1, 1)); + + post_menu(m); + + while ((c = menu_driver(m, menu_virtualize(wGetchar(menuwin)))) != E_UNKNOWN_COMMAND) { + if (c == E_REQUEST_DENIED) + beep(); + continue; + } + + (void) mvprintw(LINES - 2, 0, + "You chose: %s\n", item_name(current_item(m))); + (void) addstr("Press any key to continue..."); + wGetchar(stdscr); + + unpost_menu(m); + delwin(menuwin); + + free_menu(m); + for (ip = items; *ip; ip++) + free_item(*ip); +#ifdef NCURSES_MOUSE_VERSION + mousemask(0, (mmask_t *)0); +#endif +} + +#ifdef TRACE +#define T_TBL(name) { #name, name } +static struct { + const char *name; + int mask; +} t_tbl[] = { + T_TBL(TRACE_DISABLE), + T_TBL(TRACE_TIMES), + T_TBL(TRACE_TPUTS), + T_TBL(TRACE_UPDATE), + T_TBL(TRACE_MOVE), + T_TBL(TRACE_CHARPUT), + T_TBL(TRACE_ORDINARY), + T_TBL(TRACE_CALLS), + T_TBL(TRACE_VIRTPUT), + T_TBL(TRACE_IEVENT), + T_TBL(TRACE_BITS), + T_TBL(TRACE_ICALLS), + T_TBL(TRACE_CCALLS), + T_TBL(TRACE_MAXIMUM), + { (char *)0, 0 } +}; + +static char *tracetrace(int tlevel) +{ + static char *buf; + int n; + + if (buf == 0) { + size_t need = 12; + for (n = 0; t_tbl[n].name != 0; n++) + need += strlen(t_tbl[n].name) + 2; + buf = (char *)malloc(need); + } + sprintf(buf, "0x%02x = {", tlevel); + if (tlevel == 0) { + sprintf(buf + strlen(buf), "%s, ", t_tbl[0].name); + } else { + for (n = 1; t_tbl[n].name != 0; n++) + if ((tlevel & t_tbl[n].mask) == t_tbl[n].mask) + { + strcat(buf, t_tbl[n].name); + strcat(buf, ", "); + } + } + if (buf[strlen(buf) - 2] == ',') + buf[strlen(buf) - 2] = '\0'; + return(strcat(buf,"}")); +} + +/* fake a dynamically reconfigurable menu using the 0th entry to deselect + * the others + */ +static int run_trace_menu(MENU *m) +{ + ITEM **items; + ITEM *i, **p; + + for (;;) { + bool changed = FALSE; + switch (menu_driver(m, menu_virtualize(wGetchar(menu_win(m))))) { + case E_UNKNOWN_COMMAND: + return FALSE; + default: + items = menu_items(m); + i = current_item(m); + if (i == items[0]) { + if (item_value(i)) { + for (p = items+1; *p != 0; p++) + if (item_value(*p)) { + set_item_value(*p, FALSE); + changed = TRUE; + } + } + } else { + for (p = items+1; *p != 0; p++) + if (item_value(*p)) { + set_item_value(items[0], FALSE); + changed = TRUE; + break; + } + } + if (!changed) + return TRUE; + } + } +} + +static void trace_set(void) +/* interactively set the trace level */ +{ + MENU *m; + ITEM *items[SIZEOF(t_tbl)]; + ITEM **ip = items; + int mrows, mcols, newtrace; + int n; + WINDOW *menuwin; + + mvaddstr(0, 0, "Interactively set trace level:"); + mvaddstr(2, 0, " Press space bar to toggle a selection."); + mvaddstr(3, 0, " Use up and down arrow to move the select bar."); + mvaddstr(4, 0, " Press return to set the trace level."); + mvprintw(6, 0, "(Current trace level is %s)", tracetrace(_nc_tracing)); + + refresh(); + + for (n = 0; t_tbl[n].name != 0; n++) + *ip++ = new_item(t_tbl[n].name, ""); + *ip = (ITEM *)0; + + m = new_menu(items); + + set_menu_format(m, 0, 2); + scale_menu(m, &mrows, &mcols); + + menu_opts_off(m, O_ONEVALUE); + menuwin = newwin(mrows + 2, mcols + 2, MENU_Y, MENU_X); + set_menu_win(m, menuwin); + keypad(menuwin, TRUE); + box(menuwin, 0, 0); + + set_menu_sub(m, derwin(menuwin, mrows, mcols, 1, 1)); + + post_menu(m); + + for (ip = menu_items(m); *ip; ip++) { + int mask = t_tbl[item_index(*ip)].mask; + if (mask == 0) + set_item_value(*ip, _nc_tracing == 0); + else if ((mask & _nc_tracing) == mask) + set_item_value(*ip, TRUE); + } + + while (run_trace_menu(m)) + continue; + + newtrace = 0; + for (ip = menu_items(m); *ip; ip++) + if (item_value(*ip)) + newtrace |= t_tbl[item_index(*ip)].mask; + trace(newtrace); + _tracef("trace level interactively set to %s", tracetrace(_nc_tracing)); + + (void) mvprintw(LINES - 2, 0, + "Trace level is %s\n", tracetrace(_nc_tracing)); + (void) addstr("Press any key to continue..."); + wGetchar(stdscr); + + unpost_menu(m); + delwin(menuwin); + + free_menu(m); + for (ip = items; *ip; ip++) + free_item(*ip); +} +#endif /* TRACE */ +#endif /* USE_LIBMENU */ + +/**************************************************************************** + * + * Forms test + * + ****************************************************************************/ +#if USE_LIBFORM +static FIELD *make_label(int frow, int fcol, NCURSES_CONST char *label) +{ + FIELD *f = new_field(1, strlen(label), frow, fcol, 0, 0); + + if (f) + { + set_field_buffer(f, 0, label); + set_field_opts(f, field_opts(f) & ~O_ACTIVE); + } + return(f); +} + +static FIELD *make_field(int frow, int fcol, int rows, int cols, bool secure) +{ + FIELD *f = new_field(rows, cols, frow, fcol, 0, secure ? 1 : 0); + + if (f) { + set_field_back(f, A_UNDERLINE); + set_field_userptr(f, (void *)0); + } + return(f); +} + +static void display_form(FORM *f) +{ + WINDOW *w; + int rows, cols; + + scale_form(f, &rows, &cols); + + if ((w =newwin(rows+2, cols+4, 0, 0)) != (WINDOW *)0) + { + set_form_win(f, w); + set_form_sub(f, derwin(w, rows, cols, 1, 2)); + box(w, 0, 0); + keypad(w, TRUE); + } + + if (post_form(f) != E_OK) + wrefresh(w); +} + +static void erase_form(FORM *f) +{ + WINDOW *w = form_win(f); + WINDOW *s = form_sub(f); + + unpost_form(f); + werase(w); + wrefresh(w); + delwin(s); + delwin(w); +} + +static int edit_secure(FIELD *me, int c) +{ + int rows, cols, frow, fcol, nbuf; + + if (field_info(me, &rows, &cols, &frow, &fcol, (int *)0, &nbuf) == E_OK + && nbuf > 0) { + char temp[80]; + long len; + + strcpy(temp, field_buffer(me, 1)); + len = (long)(char *) field_userptr(me); + if (c <= KEY_MAX) { + if (isgraph(c)) { + temp[len++] = c; + temp[len] = 0; + set_field_buffer(me, 1, temp); + c = '*'; + } else { + c = 0; + } + } else { + switch (c) { + case REQ_BEG_FIELD: + case REQ_CLR_EOF: + case REQ_CLR_EOL: + case REQ_DEL_LINE: + case REQ_DEL_WORD: + case REQ_DOWN_CHAR: + case REQ_END_FIELD: + case REQ_INS_CHAR: + case REQ_INS_LINE: + case REQ_LEFT_CHAR: + case REQ_NEW_LINE: + case REQ_NEXT_WORD: + case REQ_PREV_WORD: + case REQ_RIGHT_CHAR: + case REQ_UP_CHAR: + c = 0; /* we don't want to do inline editing */ + break; + case REQ_CLR_FIELD: + if (len) { + temp[0] = 0; + set_field_buffer(me, 1, temp); + } + break; + case REQ_DEL_CHAR: + case REQ_DEL_PREV: + if (len) { + temp[--len] = 0; + set_field_buffer(me, 1, temp); + } + break; + } + } + set_field_userptr(me, (void *)len); + } + return c; +} + +static int form_virtualize(FORM *f, WINDOW *w) +{ + static const struct { + int code; + int result; + } lookup[] = { + { CTRL('A'), REQ_NEXT_CHOICE }, + { CTRL('B'), REQ_PREV_WORD }, + { CTRL('C'), REQ_CLR_EOL }, + { CTRL('D'), REQ_DOWN_FIELD }, + { CTRL('E'), REQ_END_FIELD }, + { CTRL('F'), REQ_NEXT_PAGE }, + { CTRL('G'), REQ_DEL_WORD }, + { CTRL('H'), REQ_DEL_PREV }, + { CTRL('I'), REQ_INS_CHAR }, + { CTRL('K'), REQ_CLR_EOF }, + { CTRL('L'), REQ_LEFT_FIELD }, + { CTRL('M'), REQ_NEW_LINE }, + { CTRL('N'), REQ_NEXT_FIELD }, + { CTRL('O'), REQ_INS_LINE }, + { CTRL('P'), REQ_PREV_FIELD }, + { CTRL('R'), REQ_RIGHT_FIELD }, + { CTRL('S'), REQ_BEG_FIELD }, + { CTRL('U'), REQ_UP_FIELD }, + { CTRL('V'), REQ_DEL_CHAR }, + { CTRL('W'), REQ_NEXT_WORD }, + { CTRL('X'), REQ_CLR_FIELD }, + { CTRL('Y'), REQ_DEL_LINE }, + { CTRL('Z'), REQ_PREV_CHOICE }, + { ESCAPE, MAX_FORM_COMMAND + 1 }, + { KEY_BACKSPACE, REQ_DEL_PREV }, + { KEY_DOWN, REQ_DOWN_CHAR }, + { KEY_END, REQ_LAST_FIELD }, + { KEY_HOME, REQ_FIRST_FIELD }, + { KEY_LEFT, REQ_LEFT_CHAR }, + { KEY_LL, REQ_LAST_FIELD }, + { KEY_NEXT, REQ_NEXT_FIELD }, + { KEY_NPAGE, REQ_NEXT_PAGE }, + { KEY_PPAGE, REQ_PREV_PAGE }, + { KEY_PREVIOUS, REQ_PREV_FIELD }, + { KEY_RIGHT, REQ_RIGHT_CHAR }, + { KEY_UP, REQ_UP_CHAR }, + { QUIT, MAX_FORM_COMMAND + 1 } + }; + + static int mode = REQ_INS_MODE; + int c = wGetchar(w); + unsigned n; + FIELD *me = current_field(f); + + if (c == CTRL(']')) { + if (mode == REQ_INS_MODE) + mode = REQ_OVL_MODE; + else + mode = REQ_INS_MODE; + c = mode; + } else { + for (n = 0; n < sizeof(lookup)/sizeof(lookup[0]); n++) { + if (lookup[n].code == c) { + c = lookup[n].result; + break; + } + } + } + + /* + * Force the field that the user is typing into to be in reverse video, + * while the other fields are shown underlined. + */ + if (c <= KEY_MAX) { + c = edit_secure(me, c); + set_field_back(me, A_REVERSE); + } else if (c <= MAX_FORM_COMMAND) { + c = edit_secure(me, c); + set_field_back(me, A_UNDERLINE); + } + return c; +} + +static int my_form_driver(FORM *form, int c) +{ + if (c == (MAX_FORM_COMMAND + 1) + && form_driver(form, REQ_VALIDATION) == E_OK) + return(TRUE); + else + { + beep(); + return(FALSE); + } +} + +static void demo_forms(void) +{ + WINDOW *w; + FORM *form; + FIELD *f[12], *secure; + int finished = 0, c; + unsigned n = 0; + + move(18, 0); + addstr("Defined form-traversal keys: ^Q/ESC- exit form\n"); + addstr("^N -- go to next field ^P -- go to previous field\n"); + addstr("Home -- go to first field End -- go to last field\n"); + addstr("^L -- go to field to left ^R -- go to field to right\n"); + addstr("^U -- move upward to field ^D -- move downward to field\n"); + addstr("^W -- go to next word ^B -- go to previous word\n"); + addstr("^S -- go to start of field ^E -- go to end of field\n"); + addstr("^H -- delete previous char ^Y -- delete line\n"); + addstr("^G -- delete current word ^C -- clear to end of line\n"); + addstr("^K -- clear to end of field ^X -- clear field\n"); + addstr("Arrow keys move within a field as you would expect."); + + mvaddstr(4, 57, "Forms Entry Test"); + + refresh(); + + /* describe the form */ + f[n++] = make_label(0, 15, "Sample Form"); + f[n++] = make_label(2, 0, "Last Name"); + f[n++] = make_field(3, 0, 1, 18, FALSE); + f[n++] = make_label(2, 20, "First Name"); + f[n++] = make_field(3, 20, 1, 12, FALSE); + f[n++] = make_label(2, 34, "Middle Name"); + f[n++] = make_field(3, 34, 1, 12, FALSE); + f[n++] = make_label(5, 0, "Comments"); + f[n++] = make_field(6, 0, 4, 46, FALSE); + f[n++] = make_label(5, 20, "Password:"); + secure = + f[n++] = make_field(5, 30, 1, 9, TRUE); + f[n++] = (FIELD *)0; + + form = new_form(f); + + display_form(form); + + w = form_win(form); + raw(); + while (!finished) + { + switch(form_driver(form, c = form_virtualize(form, w))) + { + case E_OK: + mvaddstr(5, 57, field_buffer(secure, 1)); + clrtoeol(); + refresh(); + break; + case E_UNKNOWN_COMMAND: + finished = my_form_driver(form, c); + break; + default: + beep(); + break; + } + } + + erase_form(form); + + free_form(form); + for (c = 0; f[c] != 0; c++) + free_field(f[c]); + noraw(); +} +#endif /* USE_LIBFORM */ + +/**************************************************************************** + * + * Overlap test + * + ****************************************************************************/ + +static void fillwin(WINDOW *win, char ch) +{ + int y, x; + int y1, x1; + + getmaxyx(win, y1, x1); + for (y = 0; y < y1; y++) + { + wmove(win, y, 0); + for (x = 0; x < x1; x++) + waddch(win, ch); + } +} + +static void crosswin(WINDOW *win, char ch) +{ + int y, x; + int y1, x1; + + getmaxyx(win, y1, x1); + for (y = 0; y < y1; y++) + { + for (x = 0; x < x1; x++) + if (((x > (x1 - 1) / 3) && (x <= (2 * (x1 - 1)) / 3)) + || (((y > (y1 - 1) / 3) && (y <= (2 * (y1 - 1)) / 3)))) + { + wmove(win, y, x); + waddch(win, ch); + } + } +} + +static void overlap_test(void) +/* test effects of overlapping windows */ +{ + int ch; + + WINDOW *win1 = newwin(9, 20, 3, 3); + WINDOW *win2 = newwin(9, 20, 9, 16); + + raw(); + refresh(); + move(0, 0); + printw("This test shows the behavior of wnoutrefresh() with respect to\n"); + printw("the shared region of two overlapping windows A and B. The cross\n"); + printw("pattern in each window does not overlap the other.\n"); + + + move(18, 0); + printw("a = refresh A, then B, then doupdate. b = refresh B, then A, then doupdaute\n"); + printw("c = fill window A with letter A. d = fill window B with letter B.\n"); + printw("e = cross pattern in window A. f = cross pattern in window B.\n"); + printw("g = clear window A. h = clear window B.\n"); + printw("i = overwrite A onto B. j = overwrite B onto A.\n"); + printw("^Q/ESC = terminate test."); + + while ((ch = Getchar()) != QUIT && ch != ESCAPE) + switch (ch) + { + case 'a': /* refresh window A first, then B */ + wnoutrefresh(win1); + wnoutrefresh(win2); + doupdate(); + break; + + case 'b': /* refresh window B first, then A */ + wnoutrefresh(win2); + wnoutrefresh(win1); + doupdate(); + break; + + case 'c': /* fill window A so it's visible */ + fillwin(win1, 'A'); + break; + + case 'd': /* fill window B so it's visible */ + fillwin(win2, 'B'); + break; + + case 'e': /* cross test pattern in window A */ + crosswin(win1, 'A'); + break; + + case 'f': /* cross test pattern in window A */ + crosswin(win2, 'B'); + break; + + case 'g': /* clear window A */ + wclear(win1); + wmove(win1, 0, 0); + break; + + case 'h': /* clear window B */ + wclear(win2); + wmove(win2, 0, 0); + break; + + case 'i': /* overwrite A onto B */ + overwrite(win1, win2); + break; + + case 'j': /* overwrite B onto A */ + overwrite(win2, win1); + break; + } + + delwin(win2); + delwin(win1); + erase(); + endwin(); +} + +/**************************************************************************** + * + * Main sequence + * + ****************************************************************************/ + +static bool +do_single_test(const char c) +/* perform a single specified test */ +{ + switch (c) + { + case 'a': + getch_test(); + break; + + case 'b': + attr_test(); + break; + + case 'c': + if (!has_colors()) + Cannot("does not support color."); + else + color_test(); + break; + + case 'd': + if (!has_colors()) + Cannot("does not support color."); + else if (!can_change_color()) + Cannot("has hardwired color values."); + else + color_edit(); + break; + + case 'e': + slk_test(); + break; + + case 'f': + acs_display(); + break; + +#if USE_LIBPANEL + case 'o': + demo_panels(); + break; +#endif + + case 'g': + acs_and_scroll(); + break; + + case 'i': + flushinp_test(stdscr); + break; + + case 'k': + test_sgr_attributes(); + break; + +#if USE_LIBMENU + case 'm': + menu_test(); + break; +#endif + +#if USE_LIBPANEL + case 'p': + demo_pad(); + break; +#endif + +#if USE_LIBFORM + case 'r': + demo_forms(); + break; +#endif + + case 's': + overlap_test(); + break; + +#if USE_LIBMENU && defined(TRACE) + case 't': + trace_set(); + break; +#endif + + case '?': + break; + + default: + return FALSE; + } + + return TRUE; +} + +static void +usage(void) +{ + static const char *const tbl[] = { + "Usage: ncurses [options]" + ,"" + ,"Options:" + ," -e fmt specify format for soft-keys test (e)" + ," -f rip-off footer line (can repeat)" + ," -h rip-off header line (can repeat)" + ," -s msec specify nominal time for panel-demo (default: 1, to hold)" +#ifdef TRACE + ," -t mask specify default trace-level (may toggle with ^T)" +#endif + }; + size_t n; + for (n = 0; n < sizeof(tbl)/sizeof(tbl[0]); n++) + fprintf(stderr, "%s\n", tbl[n]); + exit(EXIT_FAILURE); +} + +static void +set_terminal_modes(void) +{ + noraw(); + cbreak(); + noecho(); + scrollok(stdscr, TRUE); + idlok(stdscr, TRUE); + keypad(stdscr, TRUE); +} + +#ifdef SIGUSR1 +static RETSIGTYPE announce_sig(int sig) +{ + (void) fprintf(stderr, "Handled signal %d\r\n", sig); +} +#endif + +static int rip_footer(WINDOW *win, int columns) +{ + wbkgd(win, A_REVERSE); + werase(win); + wmove(win, 0, 0); + wprintw(win, "footer: %d columns", columns); + wnoutrefresh(win); + return OK; +} + +static int rip_header(WINDOW *win, int columns) +{ + wbkgd(win, A_REVERSE); + werase(win); + wmove(win, 0, 0); + wprintw(win, "header: %d columns", columns); + wnoutrefresh(win); + return OK; +} + +/*+------------------------------------------------------------------------- + main(argc,argv) +--------------------------------------------------------------------------*/ + +int +main(int argc, char *argv[]) +{ + int command, c; + int my_e_param = 1; + +#if HAVE_LOCALE_H + setlocale(LC_CTYPE, ""); +#endif + + while ((c = getopt(argc, argv, "e:fhs:t:")) != EOF) { + switch (c) { + case 'e': + my_e_param = atoi(optarg); +#ifdef NCURSES_VERSION + if (my_e_param > 3) /* allow extended layouts */ + usage(); +#else + if (my_e_param > 1) + usage(); +#endif + break; + case 'f': + ripoffline(-1, rip_footer); + break; + case 'h': + ripoffline(1, rip_header); + break; +#if USE_LIBPANEL + case 's': + nap_msec = atol(optarg); + break; +#endif +#ifdef TRACE + case 't': + save_trace = atoi(optarg); + break; +#endif + default: + usage(); + } + } + + /* + * If there's no menus (unlikely for ncurses!), then we'll have to set + * tracing on initially, just in case the user wants to test something that + * doesn't involve wGetchar. + */ +#ifdef TRACE + /* enable debugging */ +#if !USE_LIBMENU + trace(save_trace); +#else + if (!isatty(fileno(stdin))) + trace(save_trace); +#endif /* USE_LIBMENU */ +#endif /* TRACE */ + + /* tell it we're going to play with soft keys */ + slk_init(my_e_param); + +#ifdef SIGUSR1 + /* set up null signal catcher so we can see what interrupts to getch do */ + signal(SIGUSR1, announce_sig); +#endif + + /* we must initialize the curses data structure only once */ + initscr(); + bkgdset(BLANK); + + /* tests, in general, will want these modes */ + start_color(); + set_terminal_modes(); + def_prog_mode(); + + /* + * Return to terminal mode, so we're guaranteed of being able to + * select terminal commands even if the capabilities are wrong. + */ + endwin(); + + (void) puts("Welcome to ncurses. Press ? for help."); + + do { + (void) puts("This is the ncurses main menu"); + (void) puts("a = keyboard and mouse input test"); + (void) puts("b = character attribute test"); + (void) puts("c = color test pattern"); + (void) puts("d = edit RGB color values"); + (void) puts("e = exercise soft keys"); + (void) puts("f = display ACS characters"); + (void) puts("g = display windows and scrolling"); + (void) puts("i = test of flushinp()"); + (void) puts("k = display character attributes"); +#if USE_LIBMENU + (void) puts("m = menu code test"); +#endif +#if USE_LIBPANEL + (void) puts("o = exercise panels library"); + (void) puts("p = exercise pad features"); + (void) puts("q = quit"); +#endif +#if USE_LIBFORM + (void) puts("r = exercise forms code"); +#endif + (void) puts("s = overlapping-refresh test"); +#if USE_LIBMENU && defined(TRACE) + (void) puts("t = set trace level"); +#endif + (void) puts("? = repeat this command summary"); + + (void) fputs("> ", stdout); + (void) fflush(stdout); /* necessary under SVr4 curses */ + + /* + * This used to be an 'fgets()' call. However (on Linux, at least) + * mixing stream I/O and 'read()' (used in the library) causes the + * input stream to be flushed when switching between the two. + */ + command = 0; + for(;;) { + char ch; + if (read(fileno(stdin), &ch, 1) <= 0) { + if (command == 0) + command = 'q'; + break; + } else if (command == 0 && !isspace(ch)) { + command = ch; + } else if (ch == '\n' || ch == '\r') { + if (command != 0) + break; + (void) fputs("> ", stdout); + (void) fflush(stdout); + } + } + + if (do_single_test(command)) { + /* + * This may be overkill; it's intended to reset everything back + * to the initial terminal modes so that tests don't get in + * each other's way. + */ + flushinp(); + set_terminal_modes(); + reset_prog_mode(); + clear(); + refresh(); + endwin(); + if (command == '?') { + (void) puts("This is the ncurses capability tester."); + (void) puts("You may select a test from the main menu by typing the"); + (void) puts("key letter of the choice (the letter to left of the =)"); + (void) puts("at the > prompt. The commands `x' or `q' will exit."); + } + continue; + } + } while + (command != 'q'); + + ExitProgram(EXIT_SUCCESS); +} + +/* ncurses.c ends here */ diff --git a/contrib/ncurses/test/ncurses_tst.hin b/contrib/ncurses/test/ncurses_tst.hin new file mode 100644 index 0000000..1d77cbd --- /dev/null +++ b/contrib/ncurses/test/ncurses_tst.hin @@ -0,0 +1,56 @@ +/**************************************************************************** + * Copyright (c) 1998 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. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Thomas E. Dickey <dickey@clark.net> 1998 * + ****************************************************************************/ +/* + * $Id: ncurses_tst.hin,v 1.2 1998/02/11 12:14:05 tom Exp $ + * + * This is a template-file used to generate the "ncurses_cfg.h" file. + * + * Rather than list every definition, the configuration script substitutes + * the definitions that it finds using 'sed'. You need a patch (971222) + * to autoconf 2.12 to do this. + */ +#ifndef NC_CONFIG_H +#define NC_CONFIG_H +@DEFS@ + + /* The C compiler may not treat these properly but C++ has to */ +#ifdef __cplusplus +#undef const +#undef inline +#else +#if defined(lint) || defined(TRACE) +#undef inline +#define inline /* nothing */ +#endif +#endif + +#endif /* NC_CONFIG_H */ diff --git a/contrib/ncurses/test/newdemo.c b/contrib/ncurses/test/newdemo.c new file mode 100644 index 0000000..d47d275 --- /dev/null +++ b/contrib/ncurses/test/newdemo.c @@ -0,0 +1,348 @@ +/* + * newdemo.c - A demo program using PDCurses. The program illustrate + * the use of colours for text output. + * + * $Id: newdemo.c,v 1.17 1997/09/20 15:11:26 tom Exp $ + */ + +#include <test.priv.h> + +#include <signal.h> +#include <time.h> +#include <string.h> + +static int SubWinTest(WINDOW *win); +static int WaitForUser(WINDOW *win); +static int BouncingBalls(WINDOW *win); +static RETSIGTYPE trap(int); + +#define delay_output(x) napms(x) + +/* + * The Australian map + */ +const char *AusMap[16] = +{ + " A A ", + " N.T. AAAAA AAAA ", + " AAAAAAAAAAA AAAAAAAA ", + " AAAAAAAAAAAAAAAAAAAAAAAAA Qld.", + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAA ", + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ", + " AAAAAAAAAAAAAAAAAAAAAAAAAAAA ", + " AAAAAAAAAAAAAAAAAAAAAAAAA N.S.W.", + "W.A. AAAAAAAAA AAAAAA Vic.", + " AAA S.A. AA", + " A Tas.", + "" +}; + +/* + * Funny messages + */ +#define NMESSAGES 6 + +NCURSES_CONST char *messages[] = +{ + "Hello from the Land Down Under", + "The Land of crocs. and a big Red Rock", + "Where the sunflower runs along the highways", + "the dusty red roads lead one to loneliness", + "Blue sky in the morning and", + "freezing nights and twinkling stars", + "" +}; + +/* + * Main driver + */ +int +main( + int argc GCC_UNUSED, + char *argv[] GCC_UNUSED) +{ +WINDOW *win; +int w, x, y, i, j, k; +char buffer[200]; +const char *message; +int width, height; +chtype save[80]; +chtype c; + + initscr(); + start_color(); + cbreak(); + signal(SIGINT, trap); + width = 48; + height = 14; /* Create a drawing window */ + win = newwin(height, width, (LINES-height)/2, (COLS-width)/2); + if(win == NULL) + { endwin(); + return 1; + } + + while(1) + { init_pair(1,COLOR_WHITE,COLOR_BLUE); + wattrset(win, COLOR_PAIR(1)); + werase(win); + + init_pair(2,COLOR_RED,COLOR_RED); + wattrset(win, COLOR_PAIR(2)); + box(win, ACS_VLINE, ACS_HLINE); + wrefresh(win); + /* Do ramdom output of a character */ + wattrset(win, COLOR_PAIR(1)); + c = 'a'; + for(i=0; i < 5000; ++i) + { x = rand() % (width-2) + 1; + y = rand() % (height-2) + 1; + mvwaddch(win, y, x, c); + wrefresh(win); + nodelay(win,TRUE); + if (wgetch(win) != ERR) + break; + if(i == 2000) + { c = 'b'; + init_pair(3,COLOR_CYAN,COLOR_YELLOW); + wattron(win, COLOR_PAIR(3)); + } + } + + SubWinTest(win); + /* Erase and draw green window */ + init_pair(4,COLOR_YELLOW,COLOR_GREEN); + wbkgd(win, COLOR_PAIR(4) | A_BOLD); + wattrset(win, COLOR_PAIR(4) | A_BOLD); + werase(win); + wrefresh(win); + /* Draw RED bounding box */ + wattrset(win, COLOR_PAIR(2)); + box(win, ' ', ' '); + wrefresh(win); + /* Display Australia map */ + wattrset(win, COLOR_PAIR(4) | A_BOLD); + i = 0; + while(*AusMap[i]) + { mvwaddstr(win, i+1, 8, AusMap[i]); + wrefresh(win); + delay_output(50); + ++i; + } + + init_pair(5,COLOR_BLUE,COLOR_WHITE); + wattrset(win, COLOR_PAIR(5) | A_BLINK); + mvwaddstr(win, height-2, 6, " PDCurses 2.1 for DOS, OS/2 and Unix"); + wrefresh(win); + + /* Draw running messages */ + init_pair(6,COLOR_YELLOW,COLOR_WHITE); + wattrset(win, COLOR_PAIR(6)); + message = messages[j = 0]; + i = 1; + w = width-2; + strcpy(buffer, message); + while(j < NMESSAGES) { + while ((int)strlen(buffer) < w) { + strcat(buffer, " ... "); + strcat(buffer, messages[++j % NMESSAGES]); + } + + if (i < w) + mvwaddnstr(win, height/2, w - i, buffer, i); + else + mvwaddnstr(win, height/2, 1, buffer, w); + + wrefresh(win); + nodelay(win,TRUE); + if (wgetch(win) != ERR) + { flushinp(); + break; + } + if (i++ >= w) { + for (k = 0; (buffer[k] = buffer[k+1]) != '\0'; k++) + ; + } + delay_output(100); + } + + j = 0; + /* Draw running As across in RED */ + init_pair(7,COLOR_RED,COLOR_GREEN); + wattron(win, COLOR_PAIR(7)); + for(i=2; i < width - 4; ++i) + { + k = mvwinch(win, 4, i); + if (k == ERR) + break; + save[j++] = c = k; + c &= A_CHARTEXT; + mvwaddch(win, 4, i, c); + } + wrefresh(win); + + /* Put a message up wait for a key */ + i = height-2; + wattrset(win, COLOR_PAIR(5)); + mvwaddstr(win, i, 5, " Type a key to continue or 'Q' to quit "); + wrefresh(win); + + if(WaitForUser(win) == 1) + break; + + j = 0; /* Restore the old line */ + for(i=2; i < width - 4; ++i) + mvwaddch(win, 4, i, save[j++]); + wrefresh(win); + + BouncingBalls(win); + /* Put a message up wait for a key */ + i = height-2; + wattrset(win, COLOR_PAIR(5)); + mvwaddstr(win, i, 5, " Type a key to continue or 'Q' to quit "); + wrefresh(win); + if(WaitForUser(win) == 1) + break; + } + endwin(); + return 0; +} + +/* + * Test sub windows + */ +static int +SubWinTest(WINDOW *win) +{ +int w, h, sw, sh, bx, by; +WINDOW *swin1, *swin2, *swin3; + + getmaxyx(win, h, w); + getbegyx(win, by, bx); + sw = w / 3; + sh = h / 3; + if((swin1 = subwin(win, sh, sw, by+3, bx+5)) == NULL) + return 1; + if((swin2 = subwin(win, sh, sw, by+4, bx+8)) == NULL) + return 1; + if((swin3 = subwin(win, sh, sw, by+5, bx+11)) == NULL) + return 1; + + init_pair(8,COLOR_RED,COLOR_BLUE); + wattrset(swin1, COLOR_PAIR(8)); + werase(swin1); + mvwaddstr(swin1, 0, 3, "Sub-window 1"); + wrefresh(swin1); + + init_pair(8,COLOR_CYAN,COLOR_MAGENTA); + wattrset(swin2, COLOR_PAIR(8)); + werase(swin2); + mvwaddstr(swin2, 0, 3, "Sub-window 2"); + wrefresh(swin2); + + init_pair(8,COLOR_YELLOW,COLOR_GREEN); + wattrset(swin3, COLOR_PAIR(8)); + werase(swin3); + mvwaddstr(swin3, 0, 3, "Sub-window 3"); + wrefresh(swin3); + + delwin(swin1); + delwin(swin2); + delwin(swin3); + WaitForUser(win); + return 0; +} + +/* + * Bouncing balls + */ +static int +BouncingBalls(WINDOW *win) +{ +int w, h; +int x1, y1, xd1, yd1; +int x2, y2, xd2, yd2; +int x3, y3, xd3, yd3; + + getmaxyx(win, h, w); + x1 = 2 + rand() % (w - 4); + y1 = 2 + rand() % (h - 4); + x2 = 2 + rand() % (w - 4); + y2 = 2 + rand() % (h - 4); + x3 = 2 + rand() % (w - 4); + y3 = 2 + rand() % (h - 4); + xd1 = 1; yd1 = 1; + xd2 = 1; yd2 = 0; + xd3 = 0; yd3 = 1; + nodelay(win,TRUE); + while(wgetch(win) == ERR) + { x1 = xd1 > 0 ? ++x1 : --x1; + if(x1 <= 1 || x1 >= w - 2) + xd1 = xd1 ? 0 : 1; + y1 = yd1 > 0 ? ++y1 : --y1; + if(y1 <= 1 || y1 >= h - 2) + yd1 = yd1 ? 0 : 1; + + x2 = xd2 > 0 ? ++x2 : --x2; + if(x2 <= 1 || x2 >= w - 2) + xd2 = xd2 ? 0 : 1; + y2 = yd2 > 0 ? ++y2 : --y2; + if(y2 <= 1 || y2 >= h - 2) + yd2 = yd2 ? 0 : 1; + + x3 = xd3 > 0 ? ++x3 : --x3; + if(x3 <= 1 || x3 >= w - 2) + xd3 = xd3 ? 0 : 1; + y3 = yd3 > 0 ? ++y3 : --y3; + if(y3 <= 1 || y3 >= h - 2) + yd3 = yd3 ? 0 : 1; + + init_pair(8,COLOR_RED,COLOR_BLUE); + wattrset(win, COLOR_PAIR(8)); + mvwaddch(win, y1, x1, 'O'); + init_pair(8,COLOR_BLUE,COLOR_RED); + wattrset(win, COLOR_PAIR(8)); + mvwaddch(win, y2, x2, '*'); + init_pair(8,COLOR_YELLOW,COLOR_WHITE); + wattrset(win, COLOR_PAIR(8)); + mvwaddch(win, y3, x3, '@'); + wmove(win, 0, 0); + wrefresh(win); + delay_output(100); + } + return 0; +} + +/* + * Wait for user + */ +static int WaitForUser(WINDOW *win) +{ + time_t t; + chtype key; + + nodelay(win,TRUE); + t = time((time_t *)0); + while(1) + { + if ((int)(key = wgetch(win)) != ERR) + { + if (key == 'q' || key == 'Q') + return 1; + else + return 0; + } + if (time((time_t *)0) - t > 5) + return 0; + } +} + +/* + * Trap interrupt + */ +static RETSIGTYPE trap(int sig GCC_UNUSED) +{ + endwin(); + exit(EXIT_FAILURE); +} + +/* End of DEMO.C */ diff --git a/contrib/ncurses/test/rain.c b/contrib/ncurses/test/rain.c new file mode 100644 index 0000000..4132a43 --- /dev/null +++ b/contrib/ncurses/test/rain.c @@ -0,0 +1,131 @@ +/* + * $Id: rain.c,v 1.11 1997/09/18 18:36:46 tom Exp $ + */ +#include <test.priv.h> + +#include <term.h> /* for tparm() */ + +#include <signal.h> + +/* rain 11/3/1980 EPS/CITHEP */ + +static float ranf(void); +static void onsig(int sig); + +static int next_j(int j) +{ + if (j==0) j=4; else --j; + if (has_colors()) { + int z = (int)(3*ranf()); + chtype color = COLOR_PAIR(z); + if (z) + color |= A_BOLD; + attrset(color); + } + return j; +} + +int +main( + int argc GCC_UNUSED, + char *argv[] GCC_UNUSED) +{ +int x, y, j; +static int xpos[5], ypos[5]; +float r; +float c; + + for (j=SIGHUP;j<=SIGTERM;j++) + if (signal(j,SIG_IGN)!=SIG_IGN) signal(j,onsig); + + initscr(); + if (has_colors()) { + int bg = COLOR_BLACK; + start_color(); +#ifdef NCURSES_VERSION + if (use_default_colors() == OK) + bg = -1; +#endif + init_pair(1, COLOR_BLUE, bg); + init_pair(2, COLOR_CYAN, bg); + } + nl(); + noecho(); + curs_set(0); + timeout(0); + + r = (float)(LINES - 4); + c = (float)(COLS - 4); + for (j=5;--j>=0;) { + xpos[j]=(int)(c* ranf())+2; + ypos[j]=(int)(r* ranf())+2; + } + + for (j=0;;) { + x=(int)(c*ranf())+2; + y=(int)(r*ranf())+2; + + mvaddch(y,x, '.'); + + mvaddch(ypos[j], xpos[j], 'o'); + + j = next_j(j); + mvaddch(ypos[j], xpos[j], 'O'); + + j = next_j(j); + mvaddch( ypos[j]-1, xpos[j], '-'); + mvaddstr(ypos[j], xpos[j]-1, "|.|"); + mvaddch( ypos[j]+1, xpos[j], '-'); + + j = next_j(j); + mvaddch( ypos[j]-2, xpos[j], '-'); + mvaddstr(ypos[j]-1, xpos[j]-1, "/ \\"); + mvaddstr(ypos[j], xpos[j]-2, "| O |"); + mvaddstr(ypos[j]+1, xpos[j]-1, "\\ /"); + mvaddch( ypos[j]+2, xpos[j], '-'); + + j = next_j(j); + mvaddch( ypos[j]-2, xpos[j], ' '); + mvaddstr(ypos[j]-1, xpos[j]-1, " "); + mvaddstr(ypos[j], xpos[j]-2, " "); + mvaddstr(ypos[j]+1, xpos[j]-1, " "); + mvaddch( ypos[j]+2, xpos[j], ' '); + + xpos[j] = x; ypos[j] = y; + + switch(getch()) + { + case('q'): + case('Q'): + curs_set(1); + endwin(); + return(EXIT_SUCCESS); +#ifdef KEY_RESIZE + case(KEY_RESIZE): + r = (float)(LINES - 4); + c = (float)(COLS - 4); + break; +#endif + } + napms(50); + } +} + +static void +onsig(int n GCC_UNUSED) +{ + curs_set(1); + endwin(); + exit(EXIT_FAILURE); +} + +static float +ranf(void) +{ + float rv; + long r = rand(); + + r &= 077777; + rv =((float)r/32767.); + return rv; +} diff --git a/contrib/ncurses/test/tclock.c b/contrib/ncurses/test/tclock.c new file mode 100644 index 0000000..bccce31 --- /dev/null +++ b/contrib/ncurses/test/tclock.c @@ -0,0 +1,184 @@ +#include "test.priv.h" + +#include <float.h> +#include <math.h> +#include <time.h> + +/* + tclock - analog/digital clock for curses. + If it gives you joy, then + (a) I'm glad + (b) you need to get out more :-) + + This program is copyright Howard Jones, September 1994 + (ha.jones@ic.ac.uk). It may be freely distributed as + long as this copyright message remains intact, and any + modifications are clearly marked as such. [In fact, if + you modify it, I wouldn't mind the modifications back, + especially if they add any nice features. A good one + would be a precalc table for the 60 hand positions, so + that the floating point stuff can be ditched. As I said, + it was a 20 hackup minute job.] + + COMING SOON: tfishtank. Be the envy of your mac-owning + colleagues. +*/ + +/* To compile: cc -o tclock tclock.c -lcurses -lm */ + +#ifndef PI +#define PI 3.141592654 +#endif + +#define sign(_x) (_x<0?-1:1) + +#define ASPECT 2.2 +#define ROUND(value) ((int)((value) + 0.5)) + +#define A2X(angle,radius) ROUND(ASPECT * radius * sin(angle)) +#define A2Y(angle,radius) ROUND(radius * cos(angle)) + +/* Plot a point */ +static void +plot(int x,int y,char col) +{ + mvaddch(y,x,(chtype)col); +} + + +/* Draw a diagonal(arbitrary) line using Bresenham's alogrithm. */ +static void +dline(int from_x, int from_y, int x2, int y2, char ch) +{ + int dx,dy; + int ax,ay; + int sx,sy; + int x,y; + int d; + + dx=x2-from_x; + dy=y2-from_y; + + ax=abs(dx*2); + ay=abs(dy*2); + + sx=sign(dx); + sy=sign(dy); + + x=from_x; + y=from_y; + + if(ax>ay) + { + d=ay-(ax/2); + + while(1) + { + plot(x,y,ch); + if(x==x2) return; + + if(d>=0) + { + y+=sy; + d-=ax; + } + x+=sx; + d+=ay; + } + } + else + { + d=ax-(ay/2); + + while(1) + { + plot(x,y,ch); + if(y==y2) return; + + if(d>=0) + { + x+=sx; + d-=ay; + } + y+=sy; + d+=ax; + } + } +} + +int +main( + int argc GCC_UNUSED, + char *argv[] GCC_UNUSED) +{ + int i,cx,cy; + double mradius, hradius, mangle, hangle; + double sangle, sradius, hours; + int hdx, hdy; + int mdx, mdy; + int sdx, sdy; + time_t tim; + struct tm *t; + char szChar[10]; + + initscr(); + noecho(); + + cx=39; + cy=12; + mradius=9; + hradius=6; + sradius=8; + + for(i=0;i<12;i++) + { + sangle=(i+1)*(2.0*PI)/12.0; + sradius=10; + sdx = A2X(sangle, sradius); + sdy = A2Y(sangle, sradius); + sprintf(szChar,"%d",i+1); + + mvaddstr((int)(cy-sdy),(int)(cx+sdx),szChar); + } + + mvaddstr(0,0,"ASCII Clock by Howard Jones (ha.jones@ic.ac.uk),1994"); + + sradius=8; + for(;;) + { + napms(1000); + + tim = time(0); + t = localtime(&tim); + + hours = (t->tm_hour + (t->tm_min/60.0)); + if(hours>12.0) hours -= 12.0; + + mangle = ((t->tm_min) * (2 * PI)/60.0); + mdx = A2X(mangle, mradius); + mdy = A2Y(mangle, mradius); + + hangle = ((hours) * (2.0 * PI)/12.0); + hdx = A2X(hangle, hradius); + hdy = A2Y(hangle, hradius); + + sangle = ((t->tm_sec) * (2.0 * PI)/60.0); + sdx = A2X(sangle, sradius); + sdy = A2Y(sangle, sradius); + + plot(cx+sdx,cy-sdy,'O'); + dline(cx,cy,cx+hdx,cy-hdy,'.'); + dline(cx,cy,cx+mdx,cy-mdy,'#'); + + mvaddstr(23,0,ctime(&tim)); + refresh(); + if ((t->tm_sec % 5) == 0) beep(); + + plot(cx+sdx,cy-sdy,' '); + dline(cx,cy,cx+hdx,cy-hdy,' '); + dline(cx,cy,cx+mdx,cy-mdy,' '); + + } + + return 0; +} diff --git a/contrib/ncurses/test/test.priv.h b/contrib/ncurses/test/test.priv.h new file mode 100644 index 0000000..0ae4331 --- /dev/null +++ b/contrib/ncurses/test/test.priv.h @@ -0,0 +1,90 @@ +/**************************************************************************** + * Copyright (c) 1998 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. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Thomas E. Dickey <dickey@clark.net> 1996 * + ****************************************************************************/ +/* $Id: test.priv.h,v 1.15 1998/02/11 12:14:04 tom Exp $ */ +#if HAVE_CONFIG_H +#include <ncurses_cfg.h> +#endif + +#include <stdlib.h> +#include <sys/types.h> + +#if HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include <curses.h> + +#ifdef NCURSES_NOMACROS +#include <nomacros.h> +#endif + +#if HAVE_GETOPT_H +#include <getopt.h> +#else +/* 'getopt()' may be prototyped in <stdlib.h>, but declaring its variables + * doesn't hurt. + */ +extern char *optarg; +extern int optind; +#endif /* HAVE_GETOPT_H */ + +#ifndef GCC_NORETURN +#define GCC_NORETURN /* nothing */ +#endif +#ifndef GCC_UNUSED +#define GCC_UNUSED /* nothing */ +#endif + +#define SIZEOF(table) (sizeof(table)/sizeof(table[0])) + +#if defined(NCURSES_VERSION) && HAVE_NC_ALLOC_H +#include <nc_alloc.h> +#endif + +#ifndef ExitProgram +#define ExitProgram(code) return code +#endif + +#ifndef EXIT_SUCCESS +#define EXIT_SUCCESS 0 +#endif +#ifndef EXIT_FAILURE +#define EXIT_FAILURE 1 +#endif + +/* Use this to quiet gcc's -Wwrite-strings warnings, but accommodate SVr4 + * curses which doesn't have const parameters declared (so far) in the places + * that XSI shows. + */ +#ifndef NCURSES_CONST +#define NCURSES_CONST /* nothing */ +#endif diff --git a/contrib/ncurses/test/testaddch.c b/contrib/ncurses/test/testaddch.c new file mode 100644 index 0000000..444da0a --- /dev/null +++ b/contrib/ncurses/test/testaddch.c @@ -0,0 +1,60 @@ +/* + * This is an example written by Alexander V. Lukyanov <lav@yars.free.net>, + * to demonstrate an inconsistency between ncurses and SVr4 curses. + * + * $Id: testaddch.c,v 1.3 1997/10/18 21:35:15 tom Exp $ + */ +#include <test.priv.h> + +static void attr_addstr(const char *s, chtype a) +{ + while(*s) + addch(((unsigned char)(*s++))|a); +} + +int +main( + int argc GCC_UNUSED, + char *argv[] GCC_UNUSED) +{ + unsigned i; + chtype back,set,attr; + + initscr(); + start_color(); + init_pair(1,COLOR_WHITE,COLOR_BLUE); + init_pair(2,COLOR_WHITE,COLOR_RED); + init_pair(3,COLOR_BLACK,COLOR_MAGENTA); + init_pair(4,COLOR_BLACK,COLOR_GREEN); + init_pair(5,COLOR_BLACK,COLOR_CYAN); + init_pair(6,COLOR_BLACK,COLOR_YELLOW); + init_pair(7,COLOR_BLACK,COLOR_WHITE); + + for(i=0; i<8; i++) + { + back = (i&1) ? A_BOLD|'B' : ' '; + set = (i&2) ? A_REVERSE : 0; + attr = (i&4) ? COLOR_PAIR(4) : 0; + + bkgdset(back); + attrset(set); + + attr_addstr("Test string with spaces -> <-\n",attr); + } + addch('\n'); + for(i=0; i<8; i++) + { + back = (i&1) ? A_BOLD|'B'|COLOR_PAIR(1) : ' '; + set = (i&2) ? A_REVERSE|COLOR_PAIR(2) : 0; + attr = (i&4) ? COLOR_PAIR(4) : 0; + + bkgdset(back); + attrset(set); + + attr_addstr("Test string with spaces -> <-\n",attr); + } + + getch(); + endwin(); + return EXIT_SUCCESS; +} diff --git a/contrib/ncurses/test/testcurs.c b/contrib/ncurses/test/testcurs.c new file mode 100644 index 0000000..ff77657 --- /dev/null +++ b/contrib/ncurses/test/testcurs.c @@ -0,0 +1,640 @@ +/* + * + * This is a test program for the PDCurses screen package for IBM PC type + * machines. + * + * This program was written by John Burnell (johnb@kea.am.dsir.govt.nz) + * wrs(5/28/93) -- modified to be consistent (perform identically) with either + * PDCurses or under Unix System V, R4 + * + * $Id: testcurs.c,v 1.19 1999/02/14 00:42:28 tom Exp $ + */ + +#include <test.priv.h> +#include <ctype.h> + +#if defined(XCURSES) +char *XCursesProgramName = "testcurs"; +#endif + +static int initTest (WINDOW **); +static void display_menu (int,int); +static void inputTest (WINDOW *); +static void introTest (WINDOW *); +static void outputTest (WINDOW *); +static void padTest (WINDOW *); +static void scrollTest (WINDOW *); +# if defined(PDCURSES) && !defined(XCURSES) +static void resizeTest (WINDOW *); +#endif + +struct commands +{ + NCURSES_CONST char *text; + void (*function)(WINDOW *); +}; +typedef struct commands COMMAND; + +const COMMAND command[] = +{ + {"Intro Test", introTest}, + {"Pad Test", padTest}, +# if defined(PDCURSES) && !defined(XCURSES) + {"Resize Test", resizeTest}, +#endif + {"Scroll Test", scrollTest}, + {"Input Test", inputTest}, + {"Output Test", outputTest} +}; +#define MAX_OPTIONS ((sizeof(command)/sizeof(command[0]))) + +int width, height; + +int +main( + int argc GCC_UNUSED, + char *argv[] GCC_UNUSED) +{ +WINDOW *win; +int key,old_option=(-1),new_option=0; +bool quit=FALSE; + +#ifdef PDCDEBUG + PDC_debug("testcurs started\n"); +#endif + if (!initTest (&win)) return EXIT_FAILURE; + +#ifdef A_COLOR + if (has_colors()) + { + init_pair(1,COLOR_WHITE,COLOR_BLUE); + wbkgd(win, COLOR_PAIR(1)); + } + else + wbkgd(win, A_REVERSE); +#else + wbkgd(win, A_REVERSE); +#endif + + erase(); + display_menu(old_option,new_option); + while(1) + { + noecho(); + keypad(stdscr,TRUE); + raw(); + key = getch(); + switch(key) + { + case 10: + case 13: + case KEY_ENTER: + erase(); + refresh(); + (*command[new_option].function)(win); + erase(); + display_menu(old_option,new_option); + break; + case KEY_UP: + new_option = (new_option == 0) ? new_option : new_option-1; + display_menu(old_option,new_option); + break; + case KEY_DOWN: + new_option = (new_option == MAX_OPTIONS-1) ? new_option : new_option+1; + display_menu(old_option,new_option); + break; + case 'Q': + case 'q': + quit = TRUE; + break; + default: break; + } + if (quit == TRUE) + break; + } + + delwin (win); + + endwin(); +#ifdef XCURSES + XCursesExit(); +#endif + return EXIT_SUCCESS; +} + +static +void Continue (WINDOW *win) +{ + wmove(win, 10, 1); + wclrtoeol(win); + mvwaddstr(win, 10, 1, " Press any key to continue"); + wrefresh(win); + raw(); + wgetch(win); +} + +static int +initTest (WINDOW **win) +{ +#ifdef PDCDEBUG + PDC_debug("initTest called\n"); +#endif +#ifdef NCURSES_VERSION + trace(TRACE_MAXIMUM); +#endif + initscr(); +#ifdef PDCDEBUG + PDC_debug("after initscr()\n"); +#endif +#ifdef A_COLOR + if (has_colors()) + start_color(); +#endif + width = 60; + height = 13; /* Create a drawing window */ + *win = newwin(height, width, (LINES-height)/2, (COLS-width)/2); + if(*win == NULL) + { + endwin(); + return 0; + } + return 1; +} + +static void +introTest (WINDOW *win) +{ + wmove( win, height/2-5, width/2 ); + wvline( win, ACS_VLINE, 10 ); + wmove( win, height/2, width/2-10 ); + whline( win, ACS_HLINE, 20 ); + Continue(win); + + beep (); + werase(win); + + box(win, ACS_VLINE, ACS_HLINE); + wrefresh(win); + cbreak (); + mvwaddstr(win, 1, 1, "You should have rectangle in the middle of the screen"); + mvwaddstr(win, 2, 1, "You should have heard a beep"); + Continue(win); + return; +} + +static void +scrollTest (WINDOW *win) +{ + int i; + int OldX, OldY; + NCURSES_CONST char *Message = "The window will now scroll slowly"; + + wclear(win); + mvwprintw (win, height - 2, 1, Message); + wrefresh (win); + scrollok(win, TRUE); + for (i = 1; i <= height; i++) { + napms(250); + scroll(win); + wrefresh (win); + } + + getmaxyx (win, OldY, OldX); + mvwprintw (win, 6, 1, "The top of the window will scroll"); + wmove (win, 1, 1); + wsetscrreg (win, 0, 4); + box(win, ACS_VLINE, ACS_HLINE); + wrefresh (win); + for (i = 1; i <= 5; i++) { + napms(500); + scroll(win); + wrefresh (win); + } + + mvwprintw (win, 3, 1, "The bottom of the window will scroll"); + wmove (win, 8, 1); + wsetscrreg (win, 5, --OldY); + box(win, ACS_VLINE, ACS_HLINE); + wrefresh (win); + for (i = 5; i <= OldY; i++) { + napms (300); + wscrl(win,-1); + wrefresh (win); + } + wsetscrreg (win, 0, OldY); + +} + +static void +inputTest (WINDOW *win) +{ + int w, h, bx, by, sw, sh, i, c,num; + char buffer [80]; + WINDOW *subWin; + wclear (win); + + getmaxyx(win, h, w); + getbegyx(win, by, bx); + sw = w / 3; + sh = h / 3; + if((subWin = subwin(win, sh, sw, by + h - sh - 2, bx + w - sw - 2)) == NULL) + return; + +#ifdef A_COLOR + if (has_colors()) + { + init_pair(2,COLOR_WHITE,COLOR_RED); + wbkgd(subWin, COLOR_PAIR(2) | A_BOLD); + } + else + wbkgd(subWin, A_BOLD); +#else + wbkgd(subWin, A_BOLD); +#endif + box(subWin, ACS_VLINE, ACS_HLINE); + wrefresh(win); + + nocbreak(); + mvwaddstr(win, 2, 1, "Press some keys for 5 seconds"); + mvwaddstr(win, 1, 1, "Pressing ^C should do nothing"); + wrefresh(win); + + werase (subWin); + box(subWin, ACS_VLINE, ACS_HLINE); + for (i = 0; i < 5; i++) { + mvwprintw (subWin, 1, 1, "Time = %d", i); + wrefresh(subWin); + napms(1000); + flushinp(); + } + + delwin (subWin); + werase(win); + flash(); + wrefresh(win); + napms(500); + + mvwaddstr(win, 2, 1, "Press a key, followed by ENTER"); + wmove(win, 9, 10); + wrefresh(win); + echo(); + noraw(); + wgetch(win); + flushinp(); + + wmove(win, 9, 10); + wdelch(win); + mvwaddstr(win, 4, 1, "The character should now have been deleted"); + Continue(win); + + wclear (win); + mvwaddstr(win, 1, 1, "Press keys (or mouse buttons) to show their names"); + mvwaddstr(win, 2, 1, "Press spacebar to finish"); + wrefresh(win); + keypad(win, TRUE); + raw(); + noecho(); + typeahead(-1); +#if defined(PDCURSES) + mouse_set(ALL_MOUSE_EVENTS); +#endif + while(1) { + wmove(win,3,5); + c = wgetch(win); + wclrtobot(win); + if (c >= KEY_MIN) + wprintw(win,"Key Pressed: %s", keyname(c)); + else + if (isprint(c)) + wprintw(win,"Key Pressed: %c", c); + else + wprintw(win,"Key Pressed: %s", unctrl(c)); +#if defined(PDCURSES) + if (c == KEY_MOUSE) { + int button=0; + request_mouse_pos(); + if (BUTTON_CHANGED(1)) + button = 1; + else + if (BUTTON_CHANGED(2)) + button = 2; + else + if (BUTTON_CHANGED(3)) + button = 3; + else + button = 0; + wmove(win,4,18); + wprintw(win,"Button %d: ",button); + if (MOUSE_MOVED) + wprintw(win,"moved: "); + else + if ((BUTTON_STATUS(button) & BUTTON_ACTION_MASK) == BUTTON_PRESSED) + wprintw(win,"pressed: "); + else + if ((BUTTON_STATUS(button) & BUTTON_ACTION_MASK) == BUTTON_DOUBLE_CLICKED) + wprintw(win,"double: "); + else + wprintw(win,"released: "); + wprintw(win," Position: Y: %d X: %d",MOUSE_Y_POS,MOUSE_X_POS); + } +#endif + wrefresh(win); + if (c == ' ') + break; + } +#if 0 + nodelay(win, TRUE); + wgetch(win); + nodelay(win, FALSE); +#endif +#if defined(PDCURSES) + mouse_set(0L); +#endif + refresh(); + wclear (win); + mvwaddstr(win, 3, 2, "The window should have moved"); + mvwaddstr(win, 4, 2, "This text should have appeared without you pressing a key"); + mvwaddstr(win, 6, 2, "Enter a number then a string separated by space"); + mvwin(win, 2, 1); + wrefresh(win); + echo(); + noraw(); + num = 0; + *buffer = 0; + mvwscanw(win, 7, 6, "%d %s", &num,buffer); + mvwprintw(win, 8, 6, "String: %s Number: %d", buffer,num); + Continue(win); +} + +static void +outputTest (WINDOW *win) +{ + WINDOW *win1; + char Buffer [80]; + chtype ch; + int by, bx; + + nl (); + wclear (win); + mvwaddstr(win, 1, 1, "You should now have a screen in the upper left corner, and this text should have wrapped"); + mvwin(win, 2, 1); + waddstr(win,"\nThis text should be down\n"); + waddstr(win, "and broken into two here ^"); + Continue(win); + + wclear(win); + wattron(win, A_BOLD); + mvwaddstr(win, 1, 1, "A new window will appear with this text in it"); + mvwaddstr(win, 8, 1, "Press any key to continue"); + wrefresh(win); + wgetch(win); + + getbegyx(win, by, bx); + + if (LINES < 24 || COLS < 75) { + mvwaddstr(win, 5, 1, "Some tests have been skipped as they require a"); + mvwaddstr(win, 6, 1, "display of at least 24 LINES by 75 COLUMNS"); + Continue(win); + } else { + win1 = newwin(10, 50, 14, 25); + if(win1 == NULL) + { + endwin(); + return; + } +#ifdef A_COLOR + if (has_colors()) + { + init_pair(3,COLOR_BLUE,COLOR_WHITE); + wbkgd(win1, COLOR_PAIR(3)); + } + else + wbkgd(win1, A_NORMAL); +#else + wbkgd(win1, A_NORMAL); +#endif + wclear (win1); + mvwaddstr(win1, 5, 1, "This text should appear; using overlay option"); + copywin(win, win1,0,0,0,0,9,49,TRUE); + +#if defined(PDCURSES) && !defined(XCURSES) + box(win1,0xb3,0xc4); +#else + box(win1,ACS_VLINE,ACS_HLINE); +#endif + wmove(win1, 8, 26); + wrefresh(win1); + wgetch(win1); + + wclear(win1); + wattron(win1, A_BLINK); + mvwaddstr(win1, 4, 1, "This blinking text should appear in only the second window"); + wattroff(win1, A_BLINK); + mvwin(win1, by, bx); + overlay(win, win1); + mvwin(win1,14,25); + wmove(win1, 8, 26); + wrefresh(win1); + wgetch(win1); + delwin(win1); + } + + clear(); + wclear(win); + wrefresh(win); + mvwaddstr(win, 6, 2, "This line shouldn't appear"); + mvwaddstr(win, 4, 2, "Only half of the next line is visible"); + mvwaddstr(win, 5, 2, "Only half of the next line is visible"); + wmove(win, 6, 1); + wclrtobot (win); + wmove(win, 5, 20); + wclrtoeol (win); + mvwaddstr(win, 8, 2, "This line also shouldn't appear"); + wmove(win, 8, 1); + wdeleteln(win); + Continue(win); + + wmove (win, 5, 9); + ch = winch (win); + + wclear(win); + wmove (win, 6, 2); + waddstr (win, "The next char should be l: "); + winsch (win, ch); + Continue(win); + + mvwinsstr( win, 6, 2, "A1B2C3D4E5" ); + Continue(win); + + wmove(win, 5, 1); + winsertln (win); + mvwaddstr(win, 5, 2, "The lines below should have moved down"); + Continue(win); + + wclear(win); + wmove(win, 2, 2); + wprintw(win, "This is a formatted string in a window: %d %s\n", 42, "is it"); + mvwaddstr(win, 10, 1, "Enter a string: "); + wrefresh(win); + noraw(); + echo(); + *Buffer = 0; + wscanw (win, "%s", Buffer); + + printw("This is a formatted string in stdscr: %d %s\n", 42, "is it"); + mvaddstr(10, 1, "Enter a string: "); + *Buffer = 0; + scanw ("%s", Buffer); + + if (tigetstr("cvvis") != 0) { + wclear(win); + curs_set(2); + mvwaddstr(win, 1, 1, "The cursor should appear as a block (visible)"); + Continue(win); + } + + if (tigetstr("civis") != 0) { + wclear(win); + curs_set(0); + mvwaddstr(win, 1, 1, "The cursor should have disappeared (invisible)"); + Continue(win); + } + + if (tigetstr("cnorm") != 0) { + wclear(win); + curs_set(1); + mvwaddstr(win, 1, 1, "The cursor should be an underline (normal)"); + Continue(win); + } + +#ifdef A_COLOR + if ( has_colors() ) { + wclear(win); + mvwaddstr(win, 1, 1, "Colors should change after you press a key"); + Continue(win); + init_pair(1, COLOR_RED, COLOR_WHITE); + wrefresh(win); + } +#endif + + werase(win); + mvwaddstr(win, 1, 1, "Information About Your Terminal"); + mvwaddstr(win, 3, 1, termname()); + mvwaddstr(win, 4, 1, longname()); + if ( termattrs() & A_BLINK ) + mvwaddstr(win,5, 1, "This terminal supports blinking."); + else + mvwaddstr(win,5, 1, "This terminal does NOT support blinking."); + + mvwaddnstr( win, 7,5, "Have a nice day!ok", 16 ); + wrefresh(win); + + mvwinnstr( win, 7,5, Buffer, 18 ); + mvaddstr( LINES-2, 10, Buffer ); + refresh(); + Continue(win); +} + +#if defined(PDCURSES) && !defined(XCURSES) +static void +resizeTest(WINDOW *dummy GCC_UNUSED) +{ + WINDOW *win1; + + savetty (); + + clear(); + refresh(); +# if defined(OS2) + resize_term(50,120); +# else + resize_term(50,80); +# endif + + win1 = newwin(10, 50, 14, 25); + if(win1 == NULL) + { endwin(); + return; + } +#ifdef A_COLOR + if (has_colors()) + { + init_pair(3,COLOR_BLUE,COLOR_WHITE); + wattrset(win1, COLOR_PAIR(3)); + } +#endif + wclear (win1); + + mvwaddstr(win1, 1, 1, "The screen may now have 50 lines"); + Continue(win1); + + wclear (win1); + resetty (); + + mvwaddstr(win1, 1, 1, "The screen should now be reset"); + Continue(win1); + + delwin(win1); + + clear(); + refresh(); + +} +#endif + +static void +padTest(WINDOW *dummy GCC_UNUSED) +{ +WINDOW *pad, *spad; + + pad = newpad(50,100); + wattron(pad, A_REVERSE); + mvwaddstr(pad, 5, 2, "This is a new pad"); + wattrset(pad,A_NORMAL); + mvwaddstr(pad, 8, 0, "The end of this line should be truncated here:except now"); + mvwaddstr(pad,11, 1, "This line should not appear.It will now"); + wmove(pad, 10, 1); + wclrtoeol(pad); + mvwaddstr(pad, 10, 1, " Press any key to continue"); + prefresh(pad,0,0,0,0,10,45); + keypad(pad, TRUE); + raw(); + wgetch(pad); + + spad = subpad(pad,12,25,6,52); + mvwaddstr(spad, 2, 2, "This is a new subpad"); + box(spad,0,0); + prefresh(pad,0,0,0,0,15,75); + keypad(pad, TRUE); + raw(); + wgetch(pad); + + mvwaddstr(pad, 35, 2, "This is displayed at line 35 in the pad"); + mvwaddstr(pad, 40, 1, " Press any key to continue"); + prefresh(pad,30,0,0,0,10,45); + keypad(pad, TRUE); + raw(); + wgetch(pad); + + delwin(pad); +} + +static void +display_menu(int old_option,int new_option) +{ + register size_t i; + + attrset(A_NORMAL); + mvaddstr(3,20,"PDCurses Test Program"); + + for (i=0;i<MAX_OPTIONS;i++) + mvaddstr(5+i,25,command[i].text); + if (old_option != (-1)) + mvaddstr(5+old_option,25,command[old_option].text); + attrset(A_REVERSE); + mvaddstr(5+new_option,25,command[new_option].text); + attrset(A_NORMAL); + mvaddstr(13,3,"Use Up and Down Arrows to select - Enter to run - Q to quit"); + refresh(); +} + diff --git a/contrib/ncurses/test/testscanw.c b/contrib/ncurses/test/testscanw.c new file mode 100644 index 0000000..8420ea0 --- /dev/null +++ b/contrib/ncurses/test/testscanw.c @@ -0,0 +1,38 @@ +/* gleaned from a web-search, shows a bug combining scanw and implicit scroll. + * Date: 1997/03/17 + * From: bayern@morpheus.cis.yale.edu + * + * $Id: testscanw.c,v 1.5 1997/09/20 14:16:20 tom Exp $ + */ +#include <test.priv.h> +#include <ctype.h> + +int main(int argc, char *argv[]) +{ + long badanswer = 1; + long *response = &badanswer; + + initscr(); + scrollok(stdscr, TRUE); + idlok(stdscr, TRUE); + echo(); + +#if 0 + trace(TRACE_UPDATE|TRACE_CALLS); +#endif + while (argc > 1) { + if (isdigit(*argv[1])) + move(atoi(argv[1]), 0); + else if (!strcmp(argv[1], "-k")) + keypad(stdscr, TRUE); + argc--, argv++; + } + + while (badanswer) { + printw("Enter a number (0 to quit):\n"); + printw("--> "); + scanw("%20ld", response); /* yes, it's a pointer */ + } + endwin(); + return EXIT_SUCCESS; +} diff --git a/contrib/ncurses/test/tracemunch b/contrib/ncurses/test/tracemunch new file mode 100755 index 0000000..d6761cd --- /dev/null +++ b/contrib/ncurses/test/tracemunch @@ -0,0 +1,98 @@ +#!/usr/bin/perl +# +# tracemunch -- compactify ncurses trace logs +# +# The error logs produced by ncurses with tracing enabled can be very tedious +# to wade through. This script helps by compacting runs of log lines that +# can be conveniently expressed as higher-level operations. +# +# ($Id: tracemunch,v 1.2 1995/10/06 15:02:37 esr Exp $) + +$putattr="PutAttrChar\\('(.)' = 0x.., {A_NORMAL}\\) at \\(([0-9]+), ([0-9]+)\\)"; +$waddnstr="waddnstr\\(0x([0-9a-f]+),\"([^\"]+)\",[0-9]+\\) called {A_NORMAL}"; + +sub transaddr +{ + $arg = $_[0]; + + $arg =~ s/$curscr/curscr/ if ($curscr); + $arg =~ s/$newscr/newscr/ if ($newscr); + $arg =~ s/$stdscr/stdscr/ if ($stdscr); + + return $arg; +} + +while (<STDIN>) +{ +CLASSIFY: { + # Transform window pointer addresses so it's easier to compare logs + $awaiting = "curscr" if ($_ =~ /creating curscr/); + $awaiting = "newscr" if ($_ =~ /creating newscr/); + $awaiting = "stdscr" if ($_ =~ /creating stdscr/); + if ($awaiting && $_ =~ /newwin: returned window is 0x([0-9a-f]+)/) + { + $curscr = "0x$1" if ($awaiting eq "curscr"); + $newscr = "0x$1" if ($awaiting eq "newscr"); + $stdscr = "0x$1" if ($awaiting eq "stdscr"); + $awaiting = ""; + } + + # Compactify runs of PutAttrChar calls (TR_CHARPUT) + if ($_ =~ /$putattr/) + { + $putattr_chars = $1; + $starty = $2; + $startx = $3; + while (<STDIN>) + { + if ($_ =~ /$putattr/) { + $putattr_chars .= $1; + } else { + last; + } + } + print "RUN of PutAttrChar()s: \"$putattr_chars\" from ${starty}, ${startx}\n"; + redo CLASSIFY; + } + + # Compactify runs of waddnstr calls (TR_CALLS) + if ($_ =~ /$waddnstr/) + { + $waddnstr_chars = $2; + $winaddr = $1; + while (<STDIN>) + { + if ($_ =~ /$waddnstr/ && $1 eq $winaddr) { + $waddnstr_chars .= $2; + } else { + last; + } + } + $winaddstr = &transaddr($winaddr); + print "RUN of waddnstr()s: $winaddr, \"$waddnstr_chars\"\n"; + redo CLASSIFY; + } + + # More transformations can go here + + # Repeated runs of anything + $anyline = &transaddr($_); + $repeatcount = 1; + while (<STDIN>) { + if (&transaddr($_) eq $anyline) { + $repeatcount++; + } else { + last; + } + } + if ($repeatcount > 1) { + print "${repeatcount} REPEATS OF $anyline"; + } else { + print $anyline + } + redo CLASSIFY if $_; + + } # :CLASSIFY +} + +# tracemunch ends here diff --git a/contrib/ncurses/test/view.c b/contrib/ncurses/test/view.c new file mode 100644 index 0000000..8381dc8 --- /dev/null +++ b/contrib/ncurses/test/view.c @@ -0,0 +1,362 @@ +/* + * view.c -- a silly little viewer program + * + * written by Eric S. Raymond <esr@snark.thyrsus.com> December 1994 + * to test the scrolling code in ncurses. + * + * modified by Thomas Dickey <dickey@clark.net> July 1995 to demonstrate + * the use of 'resizeterm()'. + * + * Takes a filename argument. It's a simple file-viewer with various + * scroll-up and scroll-down commands. + * + * n -- scroll one line forward + * p -- scroll one line back + * + * Either command accepts a numeric prefix interpreted as a repeat count. + * Thus, typing `5n' should scroll forward 5 lines in the file. + * + * The way you can tell this is working OK is that, in the trace file, + * there should be one scroll operation plus a small number of line + * updates, as opposed to a whole-page update. This means the physical + * scroll operation worked, and the refresh() code only had to do a + * partial repaint. + * + * $Id: view.c,v 1.27 1998/08/22 18:33:41 tom Exp $ + */ + +#include <test.priv.h> + +#include <string.h> +#include <ctype.h> +#include <signal.h> + +#if HAVE_TERMIOS_H +# include <termios.h> +#else +# include <sgtty.h> +#endif + +#if !defined(sun) || !HAVE_TERMIOS_H +# if HAVE_SYS_IOCTL_H +# include <sys/ioctl.h> +# endif +#endif + +/* This is needed to compile 'struct winsize' */ +#if NEED_PTEM_H +#include <sys/stream.h> +#include <sys/ptem.h> +#endif + +static RETSIGTYPE finish(int sig) GCC_NORETURN; +static void show_all(void); + +#if defined(SIGWINCH) && defined(TIOCGWINSZ) && defined(NCURSES_VERSION) +#define CAN_RESIZE 1 +#else +#define CAN_RESIZE 0 +#endif + +#if CAN_RESIZE +static RETSIGTYPE adjust(int sig); +static int interrupted; +#endif + +static int waiting; +static int shift; + +static char *fname; +static char **lines; +static char **lptr; + +#if !HAVE_STRDUP +#define strdup my_strdup +static char *strdup (char *s) +{ + char *p; + + p = malloc(strlen(s)+1); + if (p) + strcpy(p,s); + return(p); +} +#endif /* not HAVE_STRDUP */ + +static void usage(void) +{ + static const char *msg[] = { + "Usage: view [options] file" + ,"" + ,"Options:" + ," -n NUM specify maximum number of lines (default 1000)" +#if defined(KEY_RESIZE) + ," -r use experimental KEY_RESIZE rather than our own handler" +#endif +#ifdef TRACE + ," -t trace screen updates" + ," -T NUM specify trace mask" +#endif + }; + size_t n; + for (n = 0; n < SIZEOF(msg); n++) + fprintf(stderr, "%s\n", msg[n]); + exit (EXIT_FAILURE); +} + +int main(int argc, char *argv[]) +{ +int MAXLINES = 1000; +FILE *fp; +char buf[BUFSIZ]; +int i; +char **olptr; +int done = FALSE; +int length = 0; +#if CAN_RESIZE +bool use_resize = TRUE; +#endif + + while ((i = getopt(argc, argv, "n:rtT:")) != EOF) { + switch (i) { + case 'n': + if ((MAXLINES = atoi(optarg)) < 1) + usage(); + break; +#if CAN_RESIZE + case 'r': + use_resize = FALSE; + break; +#endif +#ifdef TRACE + case 'T': + trace(atoi(optarg)); + break; + case 't': + trace(TRACE_CALLS); + break; +#endif + default: + usage(); + } + } + if (optind + 1 != argc) + usage(); + + if ((lines = (char **)calloc(MAXLINES+2, sizeof(*lines))) == 0) + usage(); + + fname = argv[optind]; + if ((fp = fopen(fname, "r")) == 0) { + perror(fname); + return EXIT_FAILURE; + } + + (void) signal(SIGINT, finish); /* arrange interrupts to terminate */ +#if CAN_RESIZE + if (use_resize) + (void) signal(SIGWINCH, adjust); /* arrange interrupts to resize */ +#endif + + /* slurp the file */ + for (lptr = &lines[0]; (lptr - lines) < MAXLINES; lptr++) { + char temp[BUFSIZ], *s, *d; + int col; + + if (fgets(buf, sizeof(buf), fp) == 0) + break; + + /* convert tabs so that shift will work properly */ + for (s = buf, d = temp, col = 0; (*d = *s) != '\0'; s++) { + if (*d == '\n') { + *d = '\0'; + break; + } else if (*d == '\t') { + col = (col | 7) + 1; + while ((d-temp) != col) + *d++ = ' '; + } else if (isprint(*d)) { + col++; + d++; + } else { + sprintf(d, "\\%03o", *s & 0xff); + d += strlen(d); + col = (d - temp); + } + } + *lptr = strdup(temp); + } + (void) fclose(fp); + length = lptr - lines; + + (void) initscr(); /* initialize the curses library */ + keypad(stdscr, TRUE); /* enable keyboard mapping */ + (void) nonl(); /* tell curses not to do NL->CR/NL on output */ + (void) cbreak(); /* take input chars one at a time, no wait for \n */ + (void) noecho(); /* don't echo input */ + idlok(stdscr, TRUE); /* allow use of insert/delete line */ + + lptr = lines; + while (!done) { + int n, c; + bool got_number; + + show_all(); + + got_number = FALSE; + n = 0; + for (;;) { +#if CAN_RESIZE + if (interrupted) + adjust(0); +#endif + waiting = TRUE; + c = getch(); + waiting = FALSE; + if ((c < 127) && isdigit(c)) { + if (!got_number) { + mvprintw(0,0, "Count: "); + clrtoeol(); + } + addch(c); + n = 10 * n + (c - '0'); + got_number = TRUE; + } + else + break; + } + if (!got_number && n == 0) + n = 1; + + switch(c) { + case KEY_DOWN: + case 'n': + olptr = lptr; + for (i = 0; i < n; i++) + if ((lptr - lines) < (length - LINES + 1)) + lptr++; + else + break; + wscrl(stdscr, lptr - olptr); + break; + + case KEY_UP: + case 'p': + olptr = lptr; + for (i = 0; i < n; i++) + if (lptr > lines) + lptr--; + else + break; + wscrl(stdscr, lptr - olptr); + break; + + case 'h': + case KEY_HOME: + lptr = lines; + break; + + case 'e': + case KEY_END: + if (length > LINES) + lptr = lines + length - LINES + 1; + else + lptr = lines; + break; + + case 'r': + case KEY_RIGHT: + shift++; + break; + + case 'l': + case KEY_LEFT: + if (shift) + shift--; + else + beep(); + break; + + case 'q': + done = TRUE; + break; + +#ifdef KEY_RESIZE + case KEY_RESIZE: /* ignore this; ncurses will repaint */ + break; +#endif +#if CAN_RESIZE + case ERR: + break; +#endif + default: + beep(); + } + } + + finish(0); /* we're done */ +} + +static RETSIGTYPE finish(int sig) +{ + endwin(); + exit(sig != 0 ? EXIT_FAILURE : EXIT_SUCCESS); +} + +#if CAN_RESIZE +/* + * This uses functions that are "unsafe", but it seems to work on SunOS and + * Linux. The 'wrefresh(curscr)' is needed to force the refresh to start from + * the top of the screen -- some xterms mangle the bitmap while resizing. + */ +static RETSIGTYPE adjust(int sig) +{ + if (waiting || sig == 0) { + struct winsize size; + + if (ioctl(fileno(stdout), TIOCGWINSZ, &size) == 0) { + resizeterm(size.ws_row, size.ws_col); + wrefresh(curscr); /* Linux needs this */ + show_all(); + } + interrupted = FALSE; + } else { + interrupted = TRUE; + } + (void) signal(SIGWINCH, adjust); /* some systems need this */ +} +#endif /* CAN_RESIZE */ + +static void show_all(void) +{ + int i; + char temp[BUFSIZ]; + char *s; + +#if CAN_RESIZE + sprintf(temp, "(%3dx%3d) col %d ", LINES, COLS, shift); + i = strlen(temp); + sprintf(temp+i, "view %.*s", (int)(sizeof(temp)-7-i), fname); +#else + sprintf(temp, "view %.*s", (int)sizeof(temp)-7, fname); +#endif + move(0,0); + printw("%.*s", COLS, temp); + clrtoeol(); + + scrollok(stdscr, FALSE); /* prevent screen from moving */ + for (i = 1; i < LINES; i++) { + move(i, 0); + if ((s = lptr[i-1]) != 0 && (int)strlen(s) > shift) + printw("%3ld:%.*s", (long) (lptr+i-lines), COLS-4, s + shift); + else + printw("%3ld:", (long) (lptr+i-lines)); + clrtoeol(); + } + setscrreg(1, LINES-1); + scrollok(stdscr, TRUE); + refresh(); +} + +/* view.c ends here */ + diff --git a/contrib/ncurses/test/worm.c b/contrib/ncurses/test/worm.c new file mode 100644 index 0000000..a02113b --- /dev/null +++ b/contrib/ncurses/test/worm.c @@ -0,0 +1,372 @@ +/* + + @@@ @@@ @@@@@@@@@@ @@@@@@@@@@@ @@@@@@@@@@@@ + @@@ @@@ @@@@@@@@@@@@ @@@@@@@@@@@@ @@@@@@@@@@@@@ + @@@ @@@ @@@@ @@@@ @@@@ @@@@ @@@ @@@@ + @@@ @@ @@@ @@@ @@@ @@@ @@@ @@@ @@@ + @@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@ @@@ + @@@@ @@@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@ + @@@@@@@@@@@@ @@@@ @@@@ @@@ @@@ @@@ @@@ + @@@@ @@@@ @@@@@@@@@@@@ @@@ @@@ @@@ @@@ + @@ @@ @@@@@@@@@@ @@@ @@@ @@@ @@@ + + Eric P. Scott + Caltech High Energy Physics + October, 1980 + + Hacks to turn this into a test frame for cursor movement: + Eric S. Raymond <esr@snark.thyrsus.com> + January, 1995 + + July 1995 (esr): worms is now in living color! :-) + +Options: + -f fill screen with copies of 'WORM' at start. + -l <n> set worm length + -n <n> set number of worms + -t make worms leave droppings + -T <start> <end> set trace interval + -S set single-stepping during trace interval + -N suppress cursor-movement optimization + + This program makes a good torture-test for the ncurses cursor-optimization + code. You can use -T to set the worm move interval over which movement + traces will be dumped. The program stops and waits for one character of + input at the beginning and end of the interval. + + $Id: worm.c,v 1.23 1999/03/06 22:52:04 tom Exp $ +*/ + +#include <test.priv.h> + +#include <term.h> /* for tparm() */ + +#include <signal.h> + +#define cursor(col,row) move(row,col) + +short *ref[128]; +static chtype flavor[]={ + 'O' , '*', '#', '$', '%', '0', '@', +}; +#define MAXWORMS (sizeof(flavor)/sizeof(chtype)) +static const short xinc[]={ + 1, 1, 1, 0, -1, -1, -1, 0 +}, yinc[]={ + -1, 0, 1, 1, 1, 0, -1, -1 +}; +static struct worm { + int orientation, head; + short *xpos, *ypos; +} worm[40]; + +static const char *field; +static int length=16, number=3; +static chtype trail=' '; + +#ifdef TRACE +int generation, trace_start, trace_end, singlestep; +#endif /* TRACE */ +static const struct options { + int nopts; + int opts[3]; +} normal[8]={ + { 3, { 7, 0, 1 } }, + { 3, { 0, 1, 2 } }, + { 3, { 1, 2, 3 } }, + { 3, { 2, 3, 4 } }, + { 3, { 3, 4, 5 } }, + { 3, { 4, 5, 6 } }, + { 3, { 5, 6, 7 } }, + { 3, { 6, 7, 0 } } +}, upper[8]={ + { 1, { 1, 0, 0 } }, + { 2, { 1, 2, 0 } }, + { 0, { 0, 0, 0 } }, + { 0, { 0, 0, 0 } }, + { 0, { 0, 0, 0 } }, + { 2, { 4, 5, 0 } }, + { 1, { 5, 0, 0 } }, + { 2, { 1, 5, 0 } } +}, left[8]={ + { 0, { 0, 0, 0 } }, + { 0, { 0, 0, 0 } }, + { 0, { 0, 0, 0 } }, + { 2, { 2, 3, 0 } }, + { 1, { 3, 0, 0 } }, + { 2, { 3, 7, 0 } }, + { 1, { 7, 0, 0 } }, + { 2, { 7, 0, 0 } } +}, right[8]={ + { 1, { 7, 0, 0 } }, + { 2, { 3, 7, 0 } }, + { 1, { 3, 0, 0 } }, + { 2, { 3, 4, 0 } }, + { 0, { 0, 0, 0 } }, + { 0, { 0, 0, 0 } }, + { 0, { 0, 0, 0 } }, + { 2, { 6, 7, 0 } } +}, lower[8]={ + { 0, { 0, 0, 0 } }, + { 2, { 0, 1, 0 } }, + { 1, { 1, 0, 0 } }, + { 2, { 1, 5, 0 } }, + { 1, { 5, 0, 0 } }, + { 2, { 5, 6, 0 } }, + { 0, { 0, 0, 0 } }, + { 0, { 0, 0, 0 } } +}, upleft[8]={ + { 0, { 0, 0, 0 } }, + { 0, { 0, 0, 0 } }, + { 0, { 0, 0, 0 } }, + { 0, { 0, 0, 0 } }, + { 0, { 0, 0, 0 } }, + { 1, { 3, 0, 0 } }, + { 2, { 1, 3, 0 } }, + { 1, { 1, 0, 0 } } +}, upright[8]={ + { 2, { 3, 5, 0 } }, + { 1, { 3, 0, 0 } }, + { 0, { 0, 0, 0 } }, + { 0, { 0, 0, 0 } }, + { 0, { 0, 0, 0 } }, + { 0, { 0, 0, 0 } }, + { 0, { 0, 0, 0 } }, + { 1, { 5, 0, 0 } } +}, lowleft[8]={ + { 3, { 7, 0, 1 } }, + { 0, { 0, 0, 0 } }, + { 0, { 0, 0, 0 } }, + { 1, { 1, 0, 0 } }, + { 2, { 1, 7, 0 } }, + { 1, { 7, 0, 0 } }, + { 0, { 0, 0, 0 } }, + { 0, { 0, 0, 0 } } +}, lowright[8]={ + { 0, { 0, 0, 0 } }, + { 1, { 7, 0, 0 } }, + { 2, { 5, 7, 0 } }, + { 1, { 5, 0, 0 } }, + { 0, { 0, 0, 0 } }, + { 0, { 0, 0, 0 } }, + { 0, { 0, 0, 0 } }, + { 0, { 0, 0, 0 } } +}; + +static RETSIGTYPE onsig(int sig); +static float ranf(void); + +int +main(int argc, char *argv[]) +{ +int x, y; +int n; +struct worm *w; +const struct options *op; +int h; +short *ip; +int last, bottom; + + for (x=1;x<argc;x++) { + register char *p; + p=argv[x]; + if (*p=='-') p++; + switch (*p) { + case 'f': + field="WORM"; + break; + case 'l': + if (++x==argc) goto usage; + if ((length=atoi(argv[x]))<2||length>1024) { + fprintf(stderr,"%s: Invalid length\n",*argv); + return EXIT_FAILURE; + } + break; + case 'n': + if (++x==argc) goto usage; + if ((number=atoi(argv[x]))<1||number>40) { + fprintf(stderr,"%s: Invalid number of worms\n",*argv); + return EXIT_FAILURE; + } + break; + case 't': + trail='.'; + break; +#ifdef TRACE + case 'S': + singlestep = TRUE; + break; + case 'T': + trace_start = atoi(argv[++x]); + trace_end = atoi(argv[++x]); + break; + case 'N': + _nc_optimize_enable ^= OPTIMIZE_ALL; /* declared by ncurses */ + break; +#endif /* TRACE */ + default: + usage: + fprintf(stderr, "usage: %s [-field] [-length #] [-number #] [-trail]\n",*argv); + return EXIT_FAILURE; + } + } + + signal(SIGINT, onsig); + initscr(); + noecho(); + cbreak(); + nonl(); + + curs_set(0); + + bottom = LINES-1; + last = COLS-1; + +#ifdef A_COLOR + if (has_colors()) + { + int bg = COLOR_BLACK; + start_color(); +#ifdef NCURSES_VERSION + if (use_default_colors() == OK) + bg = -1; +#endif + + init_pair(COLOR_GREEN, COLOR_GREEN, bg); + init_pair(COLOR_RED, COLOR_RED, bg); + init_pair(COLOR_CYAN, COLOR_CYAN, bg); + init_pair(COLOR_WHITE, COLOR_WHITE, bg); + init_pair(COLOR_MAGENTA, COLOR_MAGENTA, bg); + init_pair(COLOR_BLUE, COLOR_BLUE, bg); + init_pair(COLOR_YELLOW, COLOR_YELLOW, bg); + + flavor[0] |= COLOR_PAIR(COLOR_GREEN) | A_BOLD; + flavor[1] |= COLOR_PAIR(COLOR_RED) | A_BOLD; + flavor[2] |= COLOR_PAIR(COLOR_CYAN) | A_BOLD; + flavor[3] |= COLOR_PAIR(COLOR_WHITE) | A_BOLD; + flavor[4] |= COLOR_PAIR(COLOR_MAGENTA) | A_BOLD; + flavor[5] |= COLOR_PAIR(COLOR_BLUE) | A_BOLD; + flavor[6] |= COLOR_PAIR(COLOR_YELLOW) | A_BOLD; + } +#endif /* A_COLOR */ + + ip=(short *)malloc(LINES*COLS*sizeof (short)); + + for (n=0;n<LINES;) { + ref[n++]=ip; ip+=COLS; + } + for (ip=ref[0],n=LINES*COLS;--n>=0;) *ip++=0; + +#ifdef BADCORNER + /* if addressing the lower right corner doesn't work in your curses */ + ref[bottom][last]=1; +#endif /* BADCORNER */ + + for (n=number, w= &worm[0];--n>=0;w++) { + w->orientation=w->head=0; + if (!(ip=(short *)malloc((length+1)*sizeof (short)))) { + fprintf(stderr,"%s: out of memory\n",*argv); + return EXIT_FAILURE; + } + w->xpos=ip; + for (x=length;--x>=0;) *ip++ = -1; + if (!(ip=(short *)malloc((length+1)*sizeof (short)))) { + fprintf(stderr,"%s: out of memory\n",*argv); + return EXIT_FAILURE; + } + w->ypos=ip; + for (y=length;--y>=0;) *ip++ = -1; + } + if (field) { + register const char *p; + p=field; + for (y=bottom;--y>=0;) { + for (x=COLS;--x>=0;) { + addch((chtype)(*p++)); + if (!*p) p=field; + } + addch('\n'); + } + } + napms(10); + refresh(); + + for (;;) { +#ifdef TRACE + if (trace_start || trace_end) { + if (generation == trace_start) { + trace(TRACE_CALLS); + getch(); + } else if (generation == trace_end) { + trace(0); + getch(); + } + + if (singlestep && generation > trace_start && generation < trace_end) + getch(); + + generation++; + } +#endif /* TRACE */ + + for (n=0,w= &worm[0];n<number;n++,w++) { + if ((x=w->xpos[h=w->head])<0) { + cursor(x=w->xpos[h]=0,y=w->ypos[h]=bottom); + addch(flavor[n % MAXWORMS]); + ref[y][x]++; + } + else y=w->ypos[h]; + if (++h==length) h=0; + if (w->xpos[w->head=h]>=0) { + register int x1, y1; + x1=w->xpos[h]; y1=w->ypos[h]; + if (--ref[y1][x1]==0) { + cursor(x1,y1); addch(trail); + } + } + op= &(x==0 ? (y==0 ? upleft : (y==bottom ? lowleft : left)) : + (x==last ? (y==0 ? upright : (y==bottom ? lowright : right)) : + (y==0 ? upper : (y==bottom ? lower : normal))))[w->orientation]; + switch (op->nopts) { + case 0: + refresh(); + curs_set(1); + endwin(); + return EXIT_SUCCESS; + case 1: + w->orientation=op->opts[0]; + break; + default: + w->orientation=op->opts[(int)(ranf()*(float)op->nopts)]; + } + cursor(x+=xinc[w->orientation], y+=yinc[w->orientation]); + + if (y < 0 ) y = 0; + addch(flavor[n % MAXWORMS]); + ref[w->ypos[h]=y][w->xpos[h]=x]++; + } + napms(10); + refresh(); + } +} + +static RETSIGTYPE +onsig(int sig GCC_UNUSED) +{ + standend(); + refresh(); + curs_set(1); + endwin(); + exit(EXIT_FAILURE); +} + +static float +ranf(void) +{ +float rv; +long r = rand(); + + r &= 077777; + rv =((float)r/32767.); + return rv; +} diff --git a/contrib/ncurses/test/xmas.c b/contrib/ncurses/test/xmas.c new file mode 100644 index 0000000..3923c77 --- /dev/null +++ b/contrib/ncurses/test/xmas.c @@ -0,0 +1,1148 @@ +/******************************************************************************/ +/* asciixmas */ +/* December 1989 Larry Bartz Indianapolis, IN */ +/* */ +/* */ +/* I'm dreaming of an ascii character-based monochrome Christmas, */ +/* Just like the one's I used to know! */ +/* Via a full duplex communications channel, */ +/* At 9600 bits per second, */ +/* Even though it's kinda slow. */ +/* */ +/* I'm dreaming of an ascii character-based monochrome Christmas, */ +/* With ev'ry C program I write! */ +/* May your screen be merry and bright! */ +/* And may all your Christmases be amber or green, */ +/* (for reduced eyestrain and improved visibility)! */ +/* */ +/* */ +/* */ +/* */ +/* */ +/* IMPLEMENTATION */ +/* */ +/* Feel free to modify the defined string FROMWHO to reflect you, your */ +/* organization, your site, whatever. */ +/* */ +/* This really looks a lot better if you can turn off your cursor before */ +/* execution. I wanted to do that here but very few termcap entries or */ +/* terminfo definitions have the appropriate string defined. If you know */ +/* the string(s) for the terminal(s) you use or which your site supports, */ +/* you could call asciixmas from within a shell in which you issue the */ +/* string to the terminal. The cursor is distracting but it doesn't really */ +/* ruin the show. */ +/* */ +/* At our site, we invoke this for our users just after login and the */ +/* determination of terminal type. */ +/* */ +/* */ +/* PORTABILITY */ +/* */ +/* I wrote this using only the very simplest curses functions so that it */ +/* might be the most portable. I was personally able to test on five */ +/* different cpu/UNIX combinations. */ +/* */ +/* */ +/* COMPILE */ +/* */ +/* usually this: */ +/* */ +/* cc -O asciixmas.c -lcurses -o asciixmas -s */ +/* */ +/* */ +/* Zilog S8000 models 11, 21, 31, etc with ZEUS variant of SYSTEM III */ +/* maybe other SYSTEM III also: */ +/* */ +/* cc asciixmas.c -lcurses -ltermlib -o asciixmas -s */ +/* */ +/* as above with optional "peephole optimizer" installed: */ +/* */ +/* cc -O asciixmas.c -lcurses -ltermlib -o asciixmas -s */ +/* */ +/* */ +/* Zilog S8000 models 32, 130 with WE32100 chip and SYS V, REL2 */ +/* maybe 3B2 also? */ +/* */ +/* cc -f -O -K sd asciixmas.c -lcurses -o asciixmas -s */ +/* */ +/* */ +/* Pyramid, Sequent, any other "dual universe" types compile and execute */ +/* under either universe. The compile line for the ucb universe (as you */ +/* might expect) is the same as for SYS III UNIX: */ +/* */ +/* cc -O asciixmas.c -lcurses -ltermlib -o asciixmas -s */ +/* */ +/* The above compile will also hold true for other BSD systems. (I hope) */ +/* */ +/* */ +/* */ +/* */ +/* For the Scrooges out there among you who don't want this thing to loop */ +/* forever (or until the user hits a key), insert this into your compile */ +/* line just after "cc" : */ +/* */ +/* -DNOLOOP */ +/* */ +/* like so: */ +/* */ +/* cc -DNOLOOP -O asciixmas.c -lcurses -o asciixmas -s */ +/* */ +/* */ +/* */ +/******************************************************************************/ + +/* + * $Id: xmas.c,v 1.12 1998/01/18 01:13:47 tom Exp $ + */ +#include <test.priv.h> + +#include <signal.h> + +#define FROMWHO "Mark Hessling - (M.Hessling@gu.edu.au)" + +static int my_bg = COLOR_BLACK; +static int y_pos, x_pos; + +static WINDOW + *treescrn, *treescrn2,*treescrn3, *treescrn4,*treescrn5, *treescrn6, + *treescrn7, *treescrn8, + *dotdeer0, + *stardeer0, + *lildeer0, *lildeer1, *lildeer2, *lildeer3, + *middeer0, *middeer1, *middeer2, *middeer3, + *bigdeer0, *bigdeer1, *bigdeer2, *bigdeer3, *bigdeer4, + *lookdeer0, *lookdeer1, *lookdeer2, *lookdeer3, *lookdeer4, + *w_holiday, + *w_del_msg; + +static int boxit(void); +static int seas(void); +static int greet(void); +static int fromwho(void); +static int tree(void); +static int balls(void); +static int star(void); +static int strng1(void); +static int strng2(void); +static int strng3(void); +static int strng4(void); +static int strng5(void); +static int reindeer(void); +static int blinkit(void); +static RETSIGTYPE done(int sig) GCC_NORETURN ; + +static void +set_color(WINDOW *win, chtype color) +{ + if (has_colors()) { + static bool *pairs; + int n = (color + 1); + if (pairs == 0) + pairs = (bool *)calloc(COLORS+1, sizeof(bool)); + if (!pairs[n]) { + init_pair(n, color, my_bg); + pairs[n] = TRUE; + } + wattroff(win, A_COLOR); + wattron(win, COLOR_PAIR(n)); + } +} + +static void +unset_color(WINDOW *win) +{ + if (has_colors()) + wattrset(win, COLOR_PAIR(0)); +} + +static void +look_out(int msecs) +{ + napms(msecs); + if (getch() != ERR) { + beep(); + done(0); + } +} + +int main( + int argc GCC_UNUSED, + char **argv GCC_UNUSED) +{ +int loopy; + + initscr(); + noecho(); + nonl(); + refresh(); + signal(SIGINT,done); + signal(SIGTERM,done); +#if !defined DOS && !defined OS2 + signal(SIGHUP,done); + signal(SIGQUIT,done); +#endif + if (has_colors()) { + start_color(); +#ifdef NCURSES_VERSION + if (use_default_colors() == OK) + my_bg = -1; +#endif + } + curs_set(0); + + treescrn = newwin(16,27,3,53); + treescrn2 = newwin(16,27,3,53); + treescrn3 = newwin(16,27,3,53); + treescrn4 = newwin(16,27,3,53); + treescrn5 = newwin(16,27,3,53); + treescrn6 = newwin(16,27,3,53); + treescrn7 = newwin(16,27,3,53); + treescrn8 = newwin(16,27,3,53); + + dotdeer0 = newwin(3,71,0,8); + + stardeer0 = newwin(4,56,0,8); + + lildeer0 = newwin(7,53,0,8); + lildeer1 = newwin(2,4,0,0); + lildeer2 = newwin(2,4,0,0); + lildeer3 = newwin(2,4,0,0); + + middeer0 = newwin(15,42,0,8); + middeer1 = newwin(3,7,0,0); + middeer2 = newwin(3,7,0,0); + middeer3 = newwin(3,7,0,0); + + bigdeer0 = newwin(10,23,0,0); + bigdeer1 = newwin(10,23,0,0); + bigdeer2 = newwin(10,23,0,0); + bigdeer3 = newwin(10,23,0,0); + bigdeer4 = newwin(10,23,0,0); + + lookdeer0 = newwin(10,25,0,0); + lookdeer1 = newwin(10,25,0,0); + lookdeer2 = newwin(10,25,0,0); + lookdeer3 = newwin(10,25,0,0); + lookdeer4 = newwin(10,25,0,0); + + w_holiday = newwin(1,26,3,27); + + w_del_msg = newwin(1,19,23,60); + + mvwaddstr(w_del_msg,0,0,"Hit any key to quit"); + + mvwaddstr(w_holiday,0,0,"H A P P Y H O L I D A Y S"); + + /* set up the windows for our various reindeer */ + + /* lildeer1 */ + mvwaddch(lildeer1,0,0,(chtype)'V'); + mvwaddch(lildeer1,1,0,(chtype)'@'); + mvwaddch(lildeer1,1,1,(chtype)'<'); + mvwaddch(lildeer1,1,2,(chtype)'>'); + mvwaddch(lildeer1,1,3,(chtype)'~'); + + /* lildeer2 */ + mvwaddch(lildeer2,0,0,(chtype)'V'); + mvwaddch(lildeer2,1,0,(chtype)'@'); + mvwaddch(lildeer2,1,1,(chtype)'|'); + mvwaddch(lildeer2,1,2,(chtype)'|'); + mvwaddch(lildeer2,1,3,(chtype)'~'); + + /* lildeer3 */ + mvwaddch(lildeer3,0,0,(chtype)'V'); + mvwaddch(lildeer3,1,0,(chtype)'@'); + mvwaddch(lildeer3,1,1,(chtype)'>'); + mvwaddch(lildeer3,1,2,(chtype)'<'); + mvwaddch(lildeer2,1,3,(chtype)'~'); + + + /* middeer1 */ + mvwaddch(middeer1,0,2,(chtype)'y'); + mvwaddch(middeer1,0,3,(chtype)'y'); + mvwaddch(middeer1,1,2,(chtype)'0'); + mvwaddch(middeer1,1,3,(chtype)'('); + mvwaddch(middeer1,1,4,(chtype)'='); + mvwaddch(middeer1,1,5,(chtype)')'); + mvwaddch(middeer1,1,6,(chtype)'~'); + mvwaddch(middeer1,2,3,(chtype)'\\'); + mvwaddch(middeer1,2,4,(chtype)'/'); + + /* middeer2 */ + mvwaddch(middeer2,0,2,(chtype)'y'); + mvwaddch(middeer2,0,3,(chtype)'y'); + mvwaddch(middeer2,1,2,(chtype)'0'); + mvwaddch(middeer2,1,3,(chtype)'('); + mvwaddch(middeer2,1,4,(chtype)'='); + mvwaddch(middeer2,1,5,(chtype)')'); + mvwaddch(middeer2,1,6,(chtype)'~'); + mvwaddch(middeer2,2,3,(chtype)'|'); + mvwaddch(middeer2,2,5,(chtype)'|'); + + /* middeer3 */ + mvwaddch(middeer3,0,2,(chtype)'y'); + mvwaddch(middeer3,0,3,(chtype)'y'); + mvwaddch(middeer3,1,2,(chtype)'0'); + mvwaddch(middeer3,1,3,(chtype)'('); + mvwaddch(middeer3,1,4,(chtype)'='); + mvwaddch(middeer3,1,5,(chtype)')'); + mvwaddch(middeer3,1,6,(chtype)'~'); + mvwaddch(middeer3,2,2,(chtype)'/'); + mvwaddch(middeer3,2,6,(chtype)'\\'); + + + /* bigdeer1 */ + mvwaddch(bigdeer1,0,17,(chtype)'\\'); + mvwaddch(bigdeer1,0,18,(chtype)'/'); + mvwaddch(bigdeer1,0,20,(chtype)'\\'); + mvwaddch(bigdeer1,0,21,(chtype)'/'); + mvwaddch(bigdeer1,1,18,(chtype)'\\'); + mvwaddch(bigdeer1,1,20,(chtype)'/'); + mvwaddch(bigdeer1,2,19,(chtype)'|'); + mvwaddch(bigdeer1,2,20,(chtype)'_'); + mvwaddch(bigdeer1,3,18,(chtype)'/'); + mvwaddch(bigdeer1,3,19,(chtype)'^'); + mvwaddch(bigdeer1,3,20,(chtype)'0'); + mvwaddch(bigdeer1,3,21,(chtype)'\\'); + mvwaddch(bigdeer1,4,17,(chtype)'/'); + mvwaddch(bigdeer1,4,18,(chtype)'/'); + mvwaddch(bigdeer1,4,19,(chtype)'\\'); + mvwaddch(bigdeer1,4,22,(chtype)'\\'); + mvwaddstr(bigdeer1,5,7,"^~~~~~~~~// ~~U"); + mvwaddstr(bigdeer1,6,7,"( \\_____( /"); + mvwaddstr(bigdeer1,7,8,"( ) /"); + mvwaddstr(bigdeer1,8,9,"\\\\ /"); + mvwaddstr(bigdeer1,9,11,"\\>/>"); + + /* bigdeer2 */ + mvwaddch(bigdeer2,0,17,(chtype)'\\'); + mvwaddch(bigdeer2,0,18,(chtype)'/'); + mvwaddch(bigdeer2,0,20,(chtype)'\\'); + mvwaddch(bigdeer2,0,21,(chtype)'/'); + mvwaddch(bigdeer2,1,18,(chtype)'\\'); + mvwaddch(bigdeer2,1,20,(chtype)'/'); + mvwaddch(bigdeer2,2,19,(chtype)'|'); + mvwaddch(bigdeer2,2,20,(chtype)'_'); + mvwaddch(bigdeer2,3,18,(chtype)'/'); + mvwaddch(bigdeer2,3,19,(chtype)'^'); + mvwaddch(bigdeer2,3,20,(chtype)'0'); + mvwaddch(bigdeer2,3,21,(chtype)'\\'); + mvwaddch(bigdeer2,4,17,(chtype)'/'); + mvwaddch(bigdeer2,4,18,(chtype)'/'); + mvwaddch(bigdeer2,4,19,(chtype)'\\'); + mvwaddch(bigdeer2,4,22,(chtype)'\\'); + mvwaddstr(bigdeer2,5,7,"^~~~~~~~~// ~~U"); + mvwaddstr(bigdeer2,6,7,"(( )____( /"); + mvwaddstr(bigdeer2,7,7,"( / |"); + mvwaddstr(bigdeer2,8,8,"\\/ |"); + mvwaddstr(bigdeer2,9,9,"|> |>"); + + /* bigdeer3 */ + mvwaddch(bigdeer3,0,17,(chtype)'\\'); + mvwaddch(bigdeer3,0,18,(chtype)'/'); + mvwaddch(bigdeer3,0,20,(chtype)'\\'); + mvwaddch(bigdeer3,0,21,(chtype)'/'); + mvwaddch(bigdeer3,1,18,(chtype)'\\'); + mvwaddch(bigdeer3,1,20,(chtype)'/'); + mvwaddch(bigdeer3,2,19,(chtype)'|'); + mvwaddch(bigdeer3,2,20,(chtype)'_'); + mvwaddch(bigdeer3,3,18,(chtype)'/'); + mvwaddch(bigdeer3,3,19,(chtype)'^'); + mvwaddch(bigdeer3,3,20,(chtype)'0'); + mvwaddch(bigdeer3,3,21,(chtype)'\\'); + mvwaddch(bigdeer3,4,17,(chtype)'/'); + mvwaddch(bigdeer3,4,18,(chtype)'/'); + mvwaddch(bigdeer3,4,19,(chtype)'\\'); + mvwaddch(bigdeer3,4,22,(chtype)'\\'); + mvwaddstr(bigdeer3,5,7,"^~~~~~~~~// ~~U"); + mvwaddstr(bigdeer3,6,6,"( ()_____( /"); + mvwaddstr(bigdeer3,7,6,"/ / /"); + mvwaddstr(bigdeer3,8,5,"|/ \\"); + mvwaddstr(bigdeer3,9,5,"/> \\>"); + + /* bigdeer4 */ + mvwaddch(bigdeer4,0,17,(chtype)'\\'); + mvwaddch(bigdeer4,0,18,(chtype)'/'); + mvwaddch(bigdeer4,0,20,(chtype)'\\'); + mvwaddch(bigdeer4,0,21,(chtype)'/'); + mvwaddch(bigdeer4,1,18,(chtype)'\\'); + mvwaddch(bigdeer4,1,20,(chtype)'/'); + mvwaddch(bigdeer4,2,19,(chtype)'|'); + mvwaddch(bigdeer4,2,20,(chtype)'_'); + mvwaddch(bigdeer4,3,18,(chtype)'/'); + mvwaddch(bigdeer4,3,19,(chtype)'^'); + mvwaddch(bigdeer4,3,20,(chtype)'0'); + mvwaddch(bigdeer4,3,21,(chtype)'\\'); + mvwaddch(bigdeer4,4,17,(chtype)'/'); + mvwaddch(bigdeer4,4,18,(chtype)'/'); + mvwaddch(bigdeer4,4,19,(chtype)'\\'); + mvwaddch(bigdeer4,4,22,(chtype)'\\'); + mvwaddstr(bigdeer4,5,7,"^~~~~~~~~// ~~U"); + mvwaddstr(bigdeer4,6,6,"( )______( /"); + mvwaddstr(bigdeer4,7,5,"(/ \\"); + mvwaddstr(bigdeer4,8,0,"v___= ----^"); + + + /* lookdeer1 */ + mvwaddstr(lookdeer1,0,16,"\\/ \\/"); + mvwaddstr(lookdeer1,1,17,"\\Y/ \\Y/"); + mvwaddstr(lookdeer1,2,19,"\\=/"); + mvwaddstr(lookdeer1,3,17,"^\\o o/^"); + mvwaddstr(lookdeer1,4,17,"//( )"); + mvwaddstr(lookdeer1,5,7,"^~~~~~~~~// \\O/"); + mvwaddstr(lookdeer1,6,7,"( \\_____( /"); + mvwaddstr(lookdeer1,7,8,"( ) /"); + mvwaddstr(lookdeer1,8,9,"\\\\ /"); + mvwaddstr(lookdeer1,9,11,"\\>/>"); + + /* lookdeer2 */ + mvwaddstr(lookdeer2,0,16,"\\/ \\/"); + mvwaddstr(lookdeer2,1,17,"\\Y/ \\Y/"); + mvwaddstr(lookdeer2,2,19,"\\=/"); + mvwaddstr(lookdeer2,3,17,"^\\o o/^"); + mvwaddstr(lookdeer2,4,17,"//( )"); + mvwaddstr(lookdeer2,5,7,"^~~~~~~~~// \\O/"); + mvwaddstr(lookdeer2,6,7,"(( )____( /"); + mvwaddstr(lookdeer2,7,7,"( / |"); + mvwaddstr(lookdeer2,8,8,"\\/ |"); + mvwaddstr(lookdeer2,9,9,"|> |>"); + + /* lookdeer3 */ + mvwaddstr(lookdeer3,0,16,"\\/ \\/"); + mvwaddstr(lookdeer3,1,17,"\\Y/ \\Y/"); + mvwaddstr(lookdeer3,2,19,"\\=/"); + mvwaddstr(lookdeer3,3,17,"^\\o o/^"); + mvwaddstr(lookdeer3,4,17,"//( )"); + mvwaddstr(lookdeer3,5,7,"^~~~~~~~~// \\O/"); + mvwaddstr(lookdeer3,6,6,"( ()_____( /"); + mvwaddstr(lookdeer3,7,6,"/ / /"); + mvwaddstr(lookdeer3,8,5,"|/ \\"); + mvwaddstr(lookdeer3,9,5,"/> \\>"); + + /* lookdeer4 */ + mvwaddstr(lookdeer4,0,16,"\\/ \\/"); + mvwaddstr(lookdeer4,1,17,"\\Y/ \\Y/"); + mvwaddstr(lookdeer4,2,19,"\\=/"); + mvwaddstr(lookdeer4,3,17,"^\\o o/^"); + mvwaddstr(lookdeer4,4,17,"//( )"); + mvwaddstr(lookdeer4,5,7,"^~~~~~~~~// \\O/"); + mvwaddstr(lookdeer4,6,6,"( )______( /"); + mvwaddstr(lookdeer4,7,5,"(/ \\"); + mvwaddstr(lookdeer4,8,0,"v___= ----^"); + + + + /***********************************************/ + cbreak(); + nodelay(stdscr,TRUE); + for (;;) { + clear(); + werase(treescrn); + touchwin(w_del_msg); + touchwin(treescrn); + werase(treescrn2); + touchwin(treescrn2); + werase(treescrn8); + touchwin(treescrn8); + refresh(); + look_out(150); + boxit(); + refresh(); + look_out(150); + seas(); + refresh(); + look_out(150); + greet(); + refresh(); + look_out(150); + fromwho(); + refresh(); + look_out(150); + tree(); + look_out(150); + balls(); + look_out(150); + star(); + look_out(150); + strng1(); + strng2(); + strng3(); + strng4(); + strng5(); + + + /* set up the windows for our blinking trees */ + /* **************************************** */ + /* treescrn3 */ + + overlay(treescrn, treescrn3); + + /*balls*/ + mvwaddch(treescrn3, 4, 18, ' '); + mvwaddch(treescrn3, 7, 6, ' '); + mvwaddch(treescrn3, 8, 19, ' '); + mvwaddch(treescrn3, 11, 22, ' '); + + /*star*/ + mvwaddch(treescrn3, 0, 12, '*'); + + /*strng1*/ + mvwaddch(treescrn3, 3, 11, ' '); + + /*strng2*/ + mvwaddch(treescrn3, 5, 13, ' '); + mvwaddch(treescrn3, 6, 10, ' '); + + /*strng3*/ + mvwaddch(treescrn3, 7, 16, ' '); + mvwaddch(treescrn3, 7, 14, ' '); + + /*strng4*/ + mvwaddch(treescrn3, 10, 13, ' '); + mvwaddch(treescrn3, 10, 10, ' '); + mvwaddch(treescrn3, 11, 8, ' '); + + /*strng5*/ + mvwaddch(treescrn3, 11, 18, ' '); + mvwaddch(treescrn3, 12, 13, ' '); + + + /* treescrn4 */ + + overlay(treescrn, treescrn4); + + /*balls*/ + mvwaddch(treescrn4, 3, 9, ' '); + mvwaddch(treescrn4, 4, 16, ' '); + mvwaddch(treescrn4, 7, 6, ' '); + mvwaddch(treescrn4, 8, 19, ' '); + mvwaddch(treescrn4, 11, 2, ' '); + mvwaddch(treescrn4, 12, 23, ' '); + + /*star*/ + wstandout(treescrn4); + mvwaddch(treescrn4, 0, 12, '*'); + wstandend(treescrn4); + + /*strng1*/ + mvwaddch(treescrn4, 3, 13, ' '); + + /*strng2*/ + + /*strng3*/ + mvwaddch(treescrn4, 7, 15, ' '); + mvwaddch(treescrn4, 8, 11, ' '); + + /*strng4*/ + mvwaddch(treescrn4, 9, 16, ' '); + mvwaddch(treescrn4, 10, 12, ' '); + mvwaddch(treescrn4, 11, 8, ' '); + + /*strng5*/ + mvwaddch(treescrn4, 11, 18, ' '); + mvwaddch(treescrn4, 12, 14, ' '); + + + /* treescrn5 */ + + overlay(treescrn, treescrn5); + + /*balls*/ + mvwaddch(treescrn5, 3, 15, ' '); + mvwaddch(treescrn5, 10, 20, ' '); + mvwaddch(treescrn5, 12, 1, ' '); + + /*star*/ + mvwaddch(treescrn5, 0, 12, '*'); + + /*strng1*/ + mvwaddch(treescrn5, 3, 11, ' '); + + /*strng2*/ + mvwaddch(treescrn5, 5, 12, ' '); + + /*strng3*/ + mvwaddch(treescrn5, 7, 14, ' '); + mvwaddch(treescrn5, 8, 10, ' '); + + /*strng4*/ + mvwaddch(treescrn5, 9, 15, ' '); + mvwaddch(treescrn5, 10, 11, ' '); + mvwaddch(treescrn5, 11, 7, ' '); + + /*strng5*/ + mvwaddch(treescrn5, 11, 17, ' '); + mvwaddch(treescrn5, 12, 13, ' '); + + /* treescrn6 */ + + overlay(treescrn, treescrn6); + + /*balls*/ + mvwaddch(treescrn6, 6, 7, ' '); + mvwaddch(treescrn6, 7, 18, ' '); + mvwaddch(treescrn6, 10, 4, ' '); + mvwaddch(treescrn6, 11, 23, ' '); + + /*star*/ + wstandout(treescrn6); + mvwaddch(treescrn6, 0, 12, '*'); + wstandend(treescrn6); + + /*strng1*/ + + /*strng2*/ + mvwaddch(treescrn6, 5, 11, ' '); + + /*strng3*/ + mvwaddch(treescrn6, 7, 13, ' '); + mvwaddch(treescrn6, 8, 9, ' '); + + /*strng4*/ + mvwaddch(treescrn6, 9, 14, ' '); + mvwaddch(treescrn6, 10, 10, ' '); + mvwaddch(treescrn6, 11, 6, ' '); + + /*strng5*/ + mvwaddch(treescrn6, 11, 16, ' '); + mvwaddch(treescrn6, 12, 12, ' '); + + /* treescrn7 */ + + overlay(treescrn, treescrn7); + + /*balls*/ + mvwaddch(treescrn7, 3, 15, ' '); + mvwaddch(treescrn7, 6, 7, ' '); + mvwaddch(treescrn7, 7, 18, ' '); + mvwaddch(treescrn7, 10, 4, ' '); + mvwaddch(treescrn7, 11, 22, ' '); + + /*star*/ + mvwaddch(treescrn7, 0, 12, '*'); + + /*strng1*/ + mvwaddch(treescrn7, 3, 12, ' '); + + /*strng2*/ + mvwaddch(treescrn7, 5, 13, ' '); + mvwaddch(treescrn7, 6, 9, ' '); + + /*strng3*/ + mvwaddch(treescrn7, 7, 15, ' '); + mvwaddch(treescrn7, 8, 11, ' '); + + /*strng4*/ + mvwaddch(treescrn7, 9, 16, ' '); + mvwaddch(treescrn7, 10, 12, ' '); + mvwaddch(treescrn7, 11, 8, ' '); + + /*strng5*/ + mvwaddch(treescrn7, 11, 18, ' '); + mvwaddch(treescrn7, 12, 14, ' '); + + + look_out(150); + reindeer(); + + touchwin(w_holiday); + wrefresh(w_holiday); + wrefresh(w_del_msg); + + look_out(500); + for(loopy = 0;loopy < 100;loopy++) { + blinkit(); + } + +#ifdef NOLOOP + done(0); +#endif + } + /*NOTREACHED*/ +} + +static int boxit(void) +{ + int x = 0; + + while(x < 20) { + mvaddch(x, 7, '|'); + ++x; + } + + x = 8; + + while(x < 80) { + mvaddch(19, x, '_'); + ++x; + } + + x = 0; + + while(x < 80) { + mvaddch(22, x, '_'); + ++x; + } + + return( 0 ); +} + +static int seas(void) +{ + mvaddch(4, 1, 'S'); + mvaddch(6, 1, 'E'); + mvaddch(8, 1, 'A'); + mvaddch(10, 1, 'S'); + mvaddch(12, 1, 'O'); + mvaddch(14, 1, 'N'); + mvaddch(16, 1, '`'); + mvaddch(18, 1, 'S'); + + return( 0 ); +} + + +static int greet(void) +{ + mvaddch(3, 5, 'G'); + mvaddch(5, 5, 'R'); + mvaddch(7, 5, 'E'); + mvaddch(9, 5, 'E'); + mvaddch(11, 5, 'T'); + mvaddch(13, 5, 'I'); + mvaddch(15, 5, 'N'); + mvaddch(17, 5, 'G'); + mvaddch(19, 5, 'S'); + + return( 0 ); +} + + +static int fromwho(void) +{ + mvaddstr(21, 13, FROMWHO); + return( 0 ); +} + +static int tree(void) +{ + set_color(treescrn, COLOR_GREEN); + mvwaddch(treescrn, 1, 11, (chtype)'/'); + mvwaddch(treescrn, 2, 11, (chtype)'/'); + mvwaddch(treescrn, 3, 10, (chtype)'/'); + mvwaddch(treescrn, 4, 9, (chtype)'/'); + mvwaddch(treescrn, 5, 9, (chtype)'/'); + mvwaddch(treescrn, 6, 8, (chtype)'/'); + mvwaddch(treescrn, 7, 7, (chtype)'/'); + mvwaddch(treescrn, 8, 6, (chtype)'/'); + mvwaddch(treescrn, 9, 6, (chtype)'/'); + mvwaddch(treescrn, 10, 5, (chtype)'/'); + mvwaddch(treescrn, 11, 3, (chtype)'/'); + mvwaddch(treescrn, 12, 2, (chtype)'/'); + + mvwaddch(treescrn, 1, 13, (chtype)'\\'); + mvwaddch(treescrn, 2, 13, (chtype)'\\'); + mvwaddch(treescrn, 3, 14, (chtype)'\\'); + mvwaddch(treescrn, 4, 15, (chtype)'\\'); + mvwaddch(treescrn, 5, 15, (chtype)'\\'); + mvwaddch(treescrn, 6, 16, (chtype)'\\'); + mvwaddch(treescrn, 7, 17, (chtype)'\\'); + mvwaddch(treescrn, 8, 18, (chtype)'\\'); + mvwaddch(treescrn, 9, 18, (chtype)'\\'); + mvwaddch(treescrn, 10, 19, (chtype)'\\'); + mvwaddch(treescrn, 11, 21, (chtype)'\\'); + mvwaddch(treescrn, 12, 22, (chtype)'\\'); + + mvwaddch(treescrn, 4, 10, (chtype)'_'); + mvwaddch(treescrn, 4, 14, (chtype)'_'); + mvwaddch(treescrn, 8, 7, (chtype)'_'); + mvwaddch(treescrn, 8, 17, (chtype)'_'); + + mvwaddstr(treescrn, 13, 0, "//////////// \\\\\\\\\\\\\\\\\\\\\\\\"); + + mvwaddstr(treescrn, 14, 11, "| |"); + mvwaddstr(treescrn, 15, 11, "|_|"); + + unset_color(treescrn); + wrefresh(treescrn); + wrefresh(w_del_msg); + + return( 0 ); +} + + +static int balls(void) +{ + overlay(treescrn, treescrn2); + + set_color(treescrn2, COLOR_BLUE); + mvwaddch(treescrn2, 3, 9, (chtype)'@'); + mvwaddch(treescrn2, 3, 15, (chtype)'@'); + mvwaddch(treescrn2, 4, 8, (chtype)'@'); + mvwaddch(treescrn2, 4, 16, (chtype)'@'); + mvwaddch(treescrn2, 5, 7, (chtype)'@'); + mvwaddch(treescrn2, 5, 17, (chtype)'@'); + mvwaddch(treescrn2, 7, 6, (chtype)'@'); + mvwaddch(treescrn2, 7, 18, (chtype)'@'); + mvwaddch(treescrn2, 8, 5, (chtype)'@'); + mvwaddch(treescrn2, 8, 19, (chtype)'@'); + mvwaddch(treescrn2, 10, 4, (chtype)'@'); + mvwaddch(treescrn2, 10, 20, (chtype)'@'); + mvwaddch(treescrn2, 11, 2, (chtype)'@'); + mvwaddch(treescrn2, 11, 22, (chtype)'@'); + mvwaddch(treescrn2, 12, 1, (chtype)'@'); + mvwaddch(treescrn2, 12, 23, (chtype)'@'); + + unset_color(treescrn2); + wrefresh(treescrn2); + wrefresh(w_del_msg); + return( 0 ); +} + + +static int star(void) +{ + wattrset(treescrn2, A_BOLD | A_BLINK); + set_color(treescrn2, COLOR_YELLOW); + + mvwaddch(treescrn2, 0, 12, (chtype)'*'); + wstandend(treescrn2); + + unset_color(treescrn2); + wrefresh(treescrn2); + wrefresh(w_del_msg); + return( 0 ); +} + + +static int strng1(void) +{ + wattrset(treescrn2, A_BOLD | A_BLINK); + set_color(treescrn2, COLOR_WHITE); + + mvwaddch(treescrn2, 3, 13, (chtype)'\''); + mvwaddch(treescrn2, 3, 12, (chtype)':'); + mvwaddch(treescrn2, 3, 11, (chtype)'.'); + + wattroff(treescrn2, A_BOLD | A_BLINK); + unset_color(treescrn2); + + wrefresh(treescrn2); + wrefresh(w_del_msg); + return( 0 ); +} + + +static int strng2(void) +{ + wattrset(treescrn2, A_BOLD | A_BLINK); + set_color(treescrn2, COLOR_WHITE); + + mvwaddch(treescrn2, 5, 14, (chtype)'\''); + mvwaddch(treescrn2, 5, 13, (chtype)':'); + mvwaddch(treescrn2, 5, 12, (chtype)'.'); + mvwaddch(treescrn2, 5, 11, (chtype)','); + mvwaddch(treescrn2, 6, 10, (chtype)'\''); + mvwaddch(treescrn2, 6, 9, (chtype)':'); + + wattroff(treescrn2, A_BOLD | A_BLINK); + unset_color(treescrn2); + + wrefresh(treescrn2); + wrefresh(w_del_msg); + return( 0 ); +} + + +static int strng3(void) +{ + wattrset(treescrn2, A_BOLD | A_BLINK); + set_color(treescrn2, COLOR_WHITE); + + mvwaddch(treescrn2, 7, 16, (chtype)'\''); + mvwaddch(treescrn2, 7, 15, (chtype)':'); + mvwaddch(treescrn2, 7, 14, (chtype)'.'); + mvwaddch(treescrn2, 7, 13, (chtype)','); + mvwaddch(treescrn2, 8, 12, (chtype)'\''); + mvwaddch(treescrn2, 8, 11, (chtype)':'); + mvwaddch(treescrn2, 8, 10, (chtype)'.'); + mvwaddch(treescrn2, 8, 9, (chtype)','); + + wattroff(treescrn2, A_BOLD | A_BLINK); + unset_color(treescrn2); + + wrefresh(treescrn2); + wrefresh(w_del_msg); + return( 0 ); +} + + +static int strng4(void) +{ + wattrset(treescrn2, A_BOLD | A_BLINK); + set_color(treescrn2, COLOR_WHITE); + + mvwaddch(treescrn2, 9, 17, (chtype)'\''); + mvwaddch(treescrn2, 9, 16, (chtype)':'); + mvwaddch(treescrn2, 9, 15, (chtype)'.'); + mvwaddch(treescrn2, 9, 14, (chtype)','); + mvwaddch(treescrn2, 10, 13, (chtype)'\''); + mvwaddch(treescrn2, 10, 12, (chtype)':'); + mvwaddch(treescrn2, 10, 11, (chtype)'.'); + mvwaddch(treescrn2, 10, 10, (chtype)','); + mvwaddch(treescrn2, 11, 9, (chtype)'\''); + mvwaddch(treescrn2, 11, 8, (chtype)':'); + mvwaddch(treescrn2, 11, 7, (chtype)'.'); + mvwaddch(treescrn2, 11, 6, (chtype)','); + mvwaddch(treescrn2, 12, 5, (chtype)'\''); + + wattroff(treescrn2, A_BOLD | A_BLINK); + unset_color(treescrn2); + + wrefresh(treescrn2); + wrefresh(w_del_msg); + return( 0 ); +} + + +static int strng5(void) +{ + wattrset(treescrn2, A_BOLD | A_BLINK); + set_color(treescrn2, COLOR_WHITE); + + mvwaddch(treescrn2, 11, 19, (chtype)'\''); + mvwaddch(treescrn2, 11, 18, (chtype)':'); + mvwaddch(treescrn2, 11, 17, (chtype)'.'); + mvwaddch(treescrn2, 11, 16, (chtype)','); + mvwaddch(treescrn2, 12, 15, (chtype)'\''); + mvwaddch(treescrn2, 12, 14, (chtype)':'); + mvwaddch(treescrn2, 12, 13, (chtype)'.'); + mvwaddch(treescrn2, 12, 12, (chtype)','); + + wattroff(treescrn2, A_BOLD | A_BLINK); + unset_color(treescrn2); + + /* save a fully lit tree */ + overlay(treescrn2, treescrn); + + wrefresh(treescrn2); + wrefresh(w_del_msg); + return( 0 ); +} + + + +static int blinkit(void) +{ +static int cycle; + + if(cycle > 4) { + cycle = 0; + } + + + touchwin(treescrn8); + + switch(cycle) { + case 0: + overlay(treescrn3, treescrn8); + wrefresh(treescrn8); + wrefresh(w_del_msg); + break; + case 1: + overlay(treescrn4, treescrn8); + wrefresh(treescrn8); + wrefresh(w_del_msg); + break; + case 2: + overlay(treescrn5, treescrn8); + wrefresh(treescrn8); + wrefresh(w_del_msg); + break; + case 3: + overlay(treescrn6, treescrn8); + wrefresh(treescrn8); + wrefresh(w_del_msg); + break; + case 4: + overlay(treescrn7, treescrn8); + wrefresh(treescrn8); + wrefresh(w_del_msg); + break; + } + touchwin(treescrn8); + + /*ALL ON***************************************************/ + + overlay(treescrn, treescrn8); + wrefresh(treescrn8); + wrefresh(w_del_msg); + + ++cycle; + return( 0 ); +} + +static void +deer_step(WINDOW *win, int y, int x) +{ + mvwin(win, y, x); + wrefresh(win); + wrefresh(w_del_msg); + look_out(5); +} + +static int reindeer(void) +{ + int looper; + y_pos = 0; + + + for(x_pos = 70; x_pos > 62; x_pos--) { + if(x_pos < 62) { + y_pos = 1; + } + for(looper = 0; looper < 4; looper++) { + mvwaddch(dotdeer0, y_pos, x_pos, (chtype)'.'); + wrefresh(dotdeer0); + wrefresh(w_del_msg); + werase(dotdeer0); + wrefresh(dotdeer0); + wrefresh(w_del_msg); + look_out(50); + } + } + + y_pos = 2; + + for(; x_pos > 50; x_pos--) { + for(looper = 0; looper < 4; looper++) { + + if(x_pos < 56) { + y_pos = 3; + + mvwaddch(stardeer0, y_pos, x_pos, (chtype)'*'); + wrefresh(stardeer0); + wrefresh(w_del_msg); + werase(stardeer0); + wrefresh(stardeer0); + wrefresh(w_del_msg); + } else { + mvwaddch(dotdeer0, y_pos, x_pos, (chtype)'*'); + wrefresh(dotdeer0); + wrefresh(w_del_msg); + werase(dotdeer0); + wrefresh(dotdeer0); + wrefresh(w_del_msg); + } + } + } + + x_pos = 58; + + for(y_pos = 2; y_pos < 5; y_pos++) { + + touchwin(lildeer0); + wrefresh(lildeer0); + wrefresh(w_del_msg); + + for(looper = 0; looper < 4; looper++) { + deer_step(lildeer3, y_pos, x_pos); + deer_step(lildeer2, y_pos, x_pos); + deer_step(lildeer1, y_pos, x_pos); + deer_step(lildeer2, y_pos, x_pos); + deer_step(lildeer3, y_pos, x_pos); + + touchwin(lildeer0); + wrefresh(lildeer0); + wrefresh(w_del_msg); + + x_pos -= 2; + } + } + + + x_pos = 35; + + for(y_pos = 5; y_pos < 10; y_pos++) { + + touchwin(middeer0); + wrefresh(middeer0); + wrefresh(w_del_msg); + + for(looper = 0; looper < 2; looper++) { + deer_step(middeer3, y_pos, x_pos); + deer_step(middeer2, y_pos, x_pos); + deer_step(middeer1, y_pos, x_pos); + deer_step(middeer2, y_pos, x_pos); + deer_step(middeer3, y_pos, x_pos); + + touchwin(middeer0); + wrefresh(middeer0); + wrefresh(w_del_msg); + + x_pos -= 3; + } + } + + look_out(300); + + y_pos = 1; + + for(x_pos = 8; x_pos < 16; x_pos++) { + deer_step(bigdeer4, y_pos, x_pos); + deer_step(bigdeer3, y_pos, x_pos); + deer_step(bigdeer2, y_pos, x_pos); + deer_step(bigdeer1, y_pos, x_pos); + deer_step(bigdeer2, y_pos, x_pos); + deer_step(bigdeer3, y_pos, x_pos); + deer_step(bigdeer4, y_pos, x_pos); + deer_step(bigdeer0, y_pos, x_pos); + } + + --x_pos; + + for(looper = 0; looper < 6; looper++) { + deer_step(lookdeer4, y_pos, x_pos); + deer_step(lookdeer3, y_pos, x_pos); + deer_step(lookdeer2, y_pos, x_pos); + deer_step(lookdeer1, y_pos, x_pos); + deer_step(lookdeer2, y_pos, x_pos); + deer_step(lookdeer3, y_pos, x_pos); + deer_step(lookdeer4, y_pos, x_pos); + } + + deer_step(lookdeer0, y_pos, x_pos); + + for(; y_pos < 10; y_pos++) { + for(looper = 0; looper < 2; looper++) { + deer_step(bigdeer4, y_pos, x_pos); + deer_step(bigdeer3, y_pos, x_pos); + deer_step(bigdeer2, y_pos, x_pos); + deer_step(bigdeer1, y_pos, x_pos); + deer_step(bigdeer2, y_pos, x_pos); + deer_step(bigdeer3, y_pos, x_pos); + deer_step(bigdeer4, y_pos, x_pos); + } + deer_step(bigdeer0, y_pos, x_pos); + } + + --y_pos; + + deer_step(lookdeer3, y_pos, x_pos); + return( 0 ); +} + +static RETSIGTYPE done(int sig GCC_UNUSED) +{ + signal(SIGINT,done); + signal(SIGTERM,done); +#if !defined DOS && !defined OS2 + signal(SIGHUP,done); + signal(SIGQUIT,done); +#endif + move(LINES-1,0); + refresh(); + endwin(); + curs_set(1); + exit(EXIT_SUCCESS); +} |