dat@hpcnof.UUCP (12/31/85)
Attached is a set of files that implement a rather macabre version of hangman (all you sickie netters should like it :-) including my own cursor control library. If anyone gets really motivated, I imagine that translating it into Berkeley Curses (which I didn't have) and reposting it would be quite appreciated. DON'T CHEAT AND LOOK AT THE .hang-words FILE TO SEE WHAT THE WORDS ARE!!! Have fun with this, and all messages from the ACLU or whomever else complains about violent computer games should be routed to /dev/null! -- Dave Taylor Hewlett-Packard (CNO) ihnp4!hpfcla!d_taylor ------- cut here and so on -------- # Shar file generated Tuesday, December 31st 1985 at 9:37 am by dat # Extract with either sh or csh # # Contents of shar file: # README hangman.c hangman.6 curses.c curses.h addword.6 addword.c .hang-words # # -------------- File README --------------- echo extracting file README cat << 'END_OF_FILE' > README To create the hangman game and use it you need merely to unpack all the files (presumably you've already done this!) then $ cc -c -O curses.c $ cc -O addword.c -o addword $ cc -O hangman.c curses.o -o hangman -ltermcap then install it with: $ cp addword /usr/games/addword $ chown games /usr/games/addword $ chmod 4755 /usr/games/addword $ cp .hang-words /usr/games/lib/.hang-words $ chown games /usr/games/lib/.hang-words $ chmod 744 /usr/games/lib/.hang-words $ cp hangman /usr/games/hangman $ chown games /usr/games/hangman $ cp hangman.6 /usr/man/man6 $ cp addword.6 /usr/man/man6 and you should be ready to roll!!! (or hang, as the case may be) **** Any problems encountered, bugs fixed, or great words added should be reported to the author (please) at either of the addresses: ihnp4!hpfcla!d_taylor hpcnof!dat@HPLABS hplabs!hpcnof!dat Thanks and good luck! -- Dave Taylor END_OF_FILE # -------------- File hangman.c --------------- echo extracting file hangman.c cat << 'END_OF_FILE' > hangman.c /** hangman.c **/ /** Plays the game of hangman! **/ /** (C) 1985 Dave Taylor: ihnp4!hpfcla!d_taylor -or- hplabs!hpcnof!dat **/ #include <stdio.h> #include <signal.h> #include "curses.h" #define word_file "/usr/games/lib/.hang-words" #define MAX_CHARS 25 #define MAX_GUESSES 10 #define GUESSED_IT 0 #define TRIED_GUESS 1 #define GOOD_GUESS 2 #define BAD_GUESS 3 #define delay(n) {register int i; for (i=0;i<n;i++); } char word[MAX_CHARS]; char guessed[26], part_word[MAX_CHARS]; int bad_guesses, words_gotten = 0, words_tried = 0; int debug = 0; main(argc) int argc; { char ch; int leave(); debug = (argc>1); switch(InitScreen()) { case -1 : exit(printf("Unknown terminal\n")); case -2 : exit(printf("Not Cursor Addressable\n")); default : break; } if (debug) printf("initscreen succeeded\n"); signal(SIGINT, leave); signal(SIGQUIT,leave); do { initialize(word); ClearScreen(); build_gallows(); show_word(part_word); show_guessed(); if (words_tried) PutLine(9,50,"Success: %2d%%", (int) ((float) 100*((float) words_gotten/(float) words_tried))); while (bad_guesses < MAX_GUESSES && not_guessed()) { switch (guess(&ch)) { case BAD_GUESS : show_gallows(++bad_guesses); add_to_guessed(ch); show_guessed(); break; case GOOD_GUESS : add_to_guessed(ch); show_guessed(); fill_in(ch); show_word(part_word); break; case GUESSED_IT : show_word(word); strcpy(part_word,word); break; case TRIED_GUESS: break; /** no penalty **/ default : PutLine(22,0,"Huh?"); } } if (bad_guesses < MAX_GUESSES) words_gotten++; else PutLine(19,0,"The word you were trying to guess was '%s'",word); words_tried++; PutLine(17,0,"Would you like to try another word? (y/n) "); } while (tolower(ReadACh()) != 'n'); PutLine(19,0,"Your final success rate was %d%%", (int) ((float) 100*((float) words_gotten/(float) words_tried))); CleartoEOLN(); leave(); } int ReadACh() { char ch; Raw(ON); ch = ReadCh(); Raw(OFF); return(ch); } initialize(word) char *word; { /** pick word, and initialize all variables! **/ int max_words, get_word; register int i; FILE *wordfile; if (debug) printf("initialize()\n"); srand(time(0)); if ((wordfile = fopen(word_file, "r")) == NULL) leave(printf("Cannot open wordfile %s!\n", word_file)); fgets(word,MAX_CHARS, wordfile); sscanf(word, "%d", &max_words); get_word = rand() % max_words + 1; while (get_word-- > 0) fgets(word,MAX_CHARS, wordfile); word[strlen(word)-1] = '\0'; /** remove the '\n' **/ fclose(wordfile); for (i= 0; i < 26; i++) guessed[i] = 0; bad_guesses = 0; for (i = 0; i < strlen(word); i++) part_word[i] = '_'; part_word[i] = '\0'; } int not_guessed() { /** returns non-zero iff there are any underlines in the variable part_word (ie the word isn't fully guessed yet!) **/ register int i; while (i < strlen(part_word) && part_word[i] != '_') i++; return(i != strlen(part_word)); } int guess(ch) char *ch; { /** Guess a letter. If RETURN is keyed in, try to guess the entire word. There is NO penalty for attempting to guess the word. Returns either GOOD_GUESS, BAD_GUESS, GUESSED_IT or TRIED_GUESS **/ char guessed_word[MAX_CHARS]; register int i; if (debug) printf("guess()\n"); MoveCursor(21,0); CleartoEOLN(); PutLine(17,0,"Guess a character: "); CleartoEOLN(); *ch = tolower(ReadACh()); MoveCursor(19,0); CleartoEOLN(); switch (*ch) { case 127 : leave(); /** hit DELETE! **/ case 13 : PutLine(19,0,"You think the word is: "); /** <ret> **/ gets(guessed_word,MAX_CHARS); if (strcmp(guessed_word, word) == 0) { PutLine(19,0,"You Got It!"); CleartoEOLN(); return(GUESSED_IT); } else { PutLine(19,0,"Nope."); CleartoEOLN(); return(TRIED_GUESS); } default : if (*ch < (char) 30) leave(); else if (*ch > 'z' || *ch < 'a') { PutLine(19,0,"Guess must be 'A' thru 'Z'"); return(TRIED_GUESS); } if (guessed[*ch - 'a']) { PutLine(19,0,"You already guessed that letter!"); return(TRIED_GUESS); } for (i = 0; i < strlen(word); i++) if (word[i] == *ch) return(GOOD_GUESS); return(BAD_GUESS); } } add_to_guessed(ch) char ch; { /** add ch to guessed. Keep guessed in alphabetical order! **/ if (debug) printf("add_to_guessed(%c)\n",ch); guessed[ch - 'a']++; } show_guessed() { /** show what characters have been guessed so far **/ register int i; if (debug) printf("show_guessed()\n"); PutLine(3,50, "Guessed: "); for (i = 0; i < 26; i++) if (guessed[i]) putchar((char) i + 'a'); fflush(stdout); } fill_in(ch) char ch; { /** fill in all occurances of 'ch' in word **/ register int i; if (debug) printf("fill_in(%c)\n", ch); for (i=0; i < strlen(word); i++) if (word[i] == ch) part_word[i] = ch; } show_word(word) char *word; { PutLine(6,50,"Word: %s", word); CleartoEOLN(); } leave() { MoveCursor(23,0); exit(0); } /******* and now the cheery part: the hanging graphics routines! ********/ /** 0 @ man to be hung -> (|) the hangman -> /|\ / \ / \ **/ char hangee[3][3]; #define put_man(who,l,c) PutLine(l-2,c,"%3.3s",who[0]); \ PutLine(l-1,c,"%3.3s",who[1]); \ PutLine(l,c,"%3.3s", who[2]); #define clear_man(l,c) PutLine(l-2,c," "); \ PutLine(l-1,c," "); \ PutLine(l,c," "); show_gallows(n) int n; { /** draw gallows...as n increases, draw the parts of the man to be hung... **/ int line, column; if (debug) printf("show_gallows(%d)\n", n); if (n == 1) { /** place hangee! **/ strcpy(hangee[0]," 0 "); strcpy(hangee[1],"(|)"); strcpy(hangee[2],"/ \\"); place_man(1, &line, &column); put_man(hangee,line, column); } else if (n < 10) { place_man(n-1, &line, &column); /* remove old hangee */ clear_man(line, column); place_man(n, &line, &column); /* put him at new loc */ put_man(hangee,line, column); fix_gallows(n-1); /* and patch it up */ } else { /** too late: this is the big death scene! **/ place_man(n-1, &line, &column); clear_man(line, column); place_man(n, &line, &column); put_man(hangee,line, column); delay(300); PutLine(4,24,"|"); PutLine(5,24,"|"); PutLine(6,24,"#"); PutLine(7,27,"- Augh!"); } } place_man(n, line, col) int n, *line, *col; { switch(n) { case 1 : *line = 12; *col = 1; break; case 2 : *line = 10; *col = 4; break; case 3 : *line = 9; *col = 7; break; case 4 : *line = 8; *col = 10; break; case 5 : *line = 8; *col = 16; break; case 6 : *line = 8; *col = 17; break; case 7 : *line = 8; *col = 18; break; case 8 : *line = 8; *col = 20; break; case 9 : *line = 7; *col = 23; break; case 10: *line = 9; *col = 23; break; } } fix_gallows(n) int n; { /** fix the pieces being eaten by the little characters as the execution progresses! **/ register int line, col, fix; switch(n) { case 0 : return; case 1 : line = 12; col = 1; fix = 3; break; case 2 : line = 10; col = 4; fix = 3; break; case 3 : line = 9; col = 7; fix = 3; break; case 4 : line = 8; col = 10; fix = 3; break; case 5 : line = 8; col = 16; fix = 1; break; case 6 : line = 8; col = 17; fix = 1; break; case 7 : line = 8; col = 18; fix = 2; break; case 8 : line = 8; col = 20; fix = 3; break; } switch(fix) { case 3: PutLine(line, col, "___"); break; case 2: PutLine(line, col, "__"); break; case 1: PutLine(line, col, "_"); break; } } build_gallows() { /** this is a macabre gallows... **/ PutLine(0,36,"- Hangman -"); MoveCursor(2,0); printf(" ===========\n"); printf(" |/ |\n"); printf(" || #\n"); printf(" || O\n"); printf(" ||\n"); printf(" ||\n"); printf(" ____||_______TTT_________\n"); printf(" ___| | | | |\n"); printf(" ___| | | | |\n"); printf(" | | | | |\n"); printf("____|________|__|____________|__|_____\n"); fflush(stdout); } END_OF_FILE # -------------- File hangman.6 --------------- echo extracting file hangman.6 cat << 'END_OF_FILE' > hangman.6 .TH HAHGMAN 6 .ad b .SH NAME hangman - play the computer in hangman .SH SYNOPSIS .B hangman .SH HP-UX COMPATIBILITY .TP 10 Level: HP-UX/STANDARD .TP Origin: Hewlett Packard .SH DESCRIPTION .I Hangman is a macabre rewrite of the classic game of the same name and is simple to play. .SH AUTHOR Dave Taylor, Hewlett Packard Colorado Network Operation .SH SEE\ ALSO addword(6) .SH BUGS It should be noted that some installations of this program have databases containing extremely difficult words to guess! END_OF_FILE # -------------- File curses.c --------------- echo extracting file curses.c cat << 'END_OF_FILE' > curses.c /** curses.c **/ /** This library gives programs the ability to easily access the termcap information and write screen oriented and raw input programs. The routines can be called as needed, except that to use the cursor / screen routines there must be a call to InitScreen() first. The 'Raw' input routine can be used independently, however. Dave Taylor, HP Colorado Networks **/ #include <stdio.h> #ifdef RAWMODE # include <termio.h> #endif #include <ctype.h> #include "curses.h" #ifdef RAWMODE # define TTYIN 0 #endif extern int debug; #ifdef RAWMODE struct termio _raw_tty, _original_tty; static int _inraw = 0; /* are we IN rawmode? */ #endif static int _intransmit; /* are we transmitting keys? */ static char *_clearscreen, *_moveto, *_up, *_down, *_right, *_left, *_setbold, *_clearbold, *_setunderline, *_clearunderline, *_sethalfbright, *_clearhalfbright, *_setinverse, *_clearinverse, *_cleartoeoln, *_cleartoeos, *_transmit_on, *_transmit_off; static int _lines, _columns; static char _terminal[1024]; /* Storage for terminal entry */ static char _capabilities[256]; /* String for cursor motion */ static char *ptr = _capabilities; /* for buffering */ int outchar(); /* char output for tputs */ InitScreen() { /* Set up all this fun stuff: returns zero if all okay, or; -1 indicating no terminal name associated with this shell, -2..-n No termcap for this terminal type known */ int tgetent(), /* get termcap entry */ error; char *tgetstr(), /* Get termcap capability */ termname[40]; if (strcpy(termname, getenv("TERM")) == NULL) return(-1); if ((error = tgetent(_terminal, termname)) != 1) return(error-2); /* load in all those pesky values */ _clearscreen = tgetstr("cl", &ptr); _moveto = tgetstr("cm", &ptr); _up = tgetstr("up", &ptr); _down = tgetstr("do", &ptr); _right = tgetstr("nd", &ptr); _left = tgetstr("bs", &ptr); _setbold = tgetstr("so", &ptr); _clearbold = tgetstr("se", &ptr); _setunderline = tgetstr("us", &ptr); _clearunderline = tgetstr("ue", &ptr); _setinverse = tgetstr("so", &ptr); _clearinverse = tgetstr("se", &ptr); _sethalfbright = tgetstr("hs", &ptr); _clearhalfbright = tgetstr("he", &ptr); _cleartoeoln = tgetstr("ce", &ptr); _cleartoeos = tgetstr("cd", &ptr); _lines = tgetnum("li"); _columns = tgetnum("co"); _transmit_on = tgetstr("ks", &ptr); _transmit_off = tgetstr("ke", &ptr); if (!_left) { _left = ptr; *ptr++ = '\b'; *ptr++ = '\0'; } return(0); } char *return_value_of(termcap_label) char *termcap_label; { /** this will return the string kept by termcap for the specified capability **/ char *tgetstr(); /* Get termcap capability */ return( (char *) tgetstr(termcap_label, &ptr)); } transmit_functions(newstate) int newstate; { /** turn function key transmission to ON | OFF **/ if (newstate != _intransmit) { _intransmit = ! _intransmit; if (newstate == ON) tputs(_transmit_on, 1, outchar); else tputs(_transmit_off, 1, outchar); fflush(stdout); /* clear the output buffer */ } } /****** now into the 'meat' of the routines...the cursor stuff ******/ ScreenSize(lines, columns) int *lines, *columns; { /** returns the number of lines and columns on the display. **/ *lines = _lines - 1; /* assume index from zero */ *columns = _columns; } ClearScreen() { /* clear the screen: returns -1 if not capable */ if (!_clearscreen) return(-1); tputs(_clearscreen, 1, outchar); fflush(stdout); /* clear the output buffer */ return(0); } MoveCursor(row, col) int row, col; { /** move cursor to the specified row column on the screen. 0,0 is the top left! **/ char *tgoto(); char *stuff; if (!_moveto) return(-1); stuff = (char *) tgoto(_moveto, col, row); tputs(stuff, 1, outchar); fflush(stdout); return(0); } CursorUp() { /** move the cursor up one line **/ if (!_up) return(-1); tputs(_up, 1, outchar); fflush(stdout); return(0); } CursorDown() { /** move the cursor down one line **/ if (!_down) return(-1); tputs(_down, 1, outchar); fflush(stdout); return(0); } CursorLeft() { /** move the cursor one character to the left **/ if (!_left) return(-1); tputs(_left, 1, outchar); fflush(stdout); return(0); } CursorRight() { /** move the cursor one character to the right (nondestructive) **/ if (!_right) return(-1); tputs(_right, 1, outchar); fflush(stdout); return(0); } StartBold() { /** start boldface/standout mode **/ if (!_setbold) return(-1); tputs(_setbold, 1, outchar); fflush(stdout); return(0); } EndBold() { /** compliment of startbold **/ if (!_clearbold) return(-1); tputs(_clearbold, 1, outchar); fflush(stdout); return(0); } StartUnderline() { /** start underline mode **/ if (!_setunderline) return(-1); tputs(_setunderline, 1, outchar); fflush(stdout); return(0); } EndUnderline() { /** the compliment of start underline mode **/ if (!_clearunderline) return(-1); tputs(_clearunderline, 1, outchar); fflush(stdout); return(0); } StartHalfbright() { /** start half intensity mode **/ if (!_sethalfbright) return(-1); tputs(_sethalfbright, 1, outchar); fflush(stdout); return(0); } EndHalfbright() { /** compliment of starthalfbright **/ if (!_clearhalfbright) return(-1); tputs(_clearhalfbright, 1, outchar); fflush(stdout); return(0); } StartInverse() { /** set inverse video mode **/ if (!_setinverse) return(-1); tputs(_setinverse, 1, outchar); fflush(stdout); return(0); } EndInverse() { /** compliment of startinverse **/ if (!_clearinverse) return(-1); tputs(_clearinverse, 1, outchar); fflush(stdout); return(0); } PutLine(x, y, line, args) int x,y; char *line; int args; { /** write line, with 'args', at location x,y **/ MoveCursor(x,y); _doprnt(line, &args, stdout); fflush(stdout); /* ensure it actually gets out! */ } CleartoEOLN() { /** clear to end of line **/ if (!_cleartoeoln) return(-1); tputs(_cleartoeoln, 1, outchar); fflush(stdout); /* clear the output buffer */ return(0); } CleartoEOS() { /** clear to end of screen **/ if (!_cleartoeos) return(-1); tputs(_cleartoeos, 1, outchar); fflush(stdout); /* clear the output buffer */ return(0); } #ifdef RAWMODE Raw(state) int state; { /** state is either ON or OFF, as indicated by call **/ if (state == OFF && _inraw) { (void) ioctl(TTYIN, TCSETAW, &_original_tty); _inraw = 0; } else if (state == ON && ! _inraw) { (void) ioctl(TTYIN, TCGETA, &_original_tty); /** current setting **/ (void) ioctl(TTYIN, TCGETA, &_raw_tty); /** again! **/ _raw_tty.c_iflag &= ~(INLCR | ICRNL |BRKINT); _raw_tty.c_iflag |= IXON; _raw_tty.c_oflag |= OPOST; _raw_tty.c_oflag &= ~(OLCUC | ONLCR | OCRNL | ONOCR | ONLRET); _raw_tty.c_lflag &= ~(ICANON | ECHO); _raw_tty.c_cc[VMIN] = '\01'; _raw_tty.c_cc[VTIME] = '\0'; (void) ioctl(TTYIN, TCSETAW, &_raw_tty); _inraw = 1; } } int ReadCh() { /** read a character with Raw mode set! **/ register int result; char ch; result = read(0, &ch, 1); return(result == 0? EOF : ch); } #endif outchar(c) char c; { /** output the given character. From tputs... **/ /** Note: this CANNOT be a macro! **/ putc(c, stdout); } END_OF_FILE # -------------- File curses.h --------------- echo extracting file curses.h cat << 'END_OF_FILE' > curses.h /*** curses.h ***/ /*** Include file for seperate compilation. ***/ #define OFF 0 #define ON 1 int InitScreen(), /* This must be called before anything else!! */ ClearScreen(), CleartoEOLN(), MoveCursor(), PutLine(), CursorUp(), CursorDown(), CursorLeft(), CursorRight(), StartBold(), EndBold(), StartUnderline(), EndUnderline(), StartHalfbright(), EndHalfbright(), StartInverse(), EndInverse(), transmit_functions(), Raw(), ReadCh(); char *return_value_of(); END_OF_FILE # -------------- File addword.6 --------------- echo extracting file addword.6 cat << 'END_OF_FILE' > addword.6 .TH ADDWORD 6 .ad b .SH NAME addword - add a word to the hangman database .SH SYNOPSIS .B addword word .SH HP-UX COMPATIBILITY .TP 10 Level: HP-UX/STANDARD .TP Origin: Hewlett Packard .SH DESCRIPTION .I Addword adds a new word to the hangman database. .SH AUTHOR Dave Taylor, Hewlett Packard Colorado Network Operation .SH BUGS .I Addword doesn't check to ensure that the word isn't already in the database, so it is possible to duplicate. END_OF_FILE # -------------- File addword.c --------------- echo extracting file addword.c cat << 'END_OF_FILE' > addword.c /*** addword.c ***/ /** Add a word to the hangman word file. Note this must be setuid games. **/ /** (C) 1985 Dave Taylor: ihnp4!hpfcla!d_taylor -or- hplabs!hpcnof!dat **/ #include <stdio.h> #define WLEN 40 #define word_file "/usr/games/lib/.hang-words" #define temp_file "/tmp/hang" #define mode 300 /* -rw------ */ main(argc, argv) int argc; char *argv[]; { int words; char theword[WLEN], filename[40]; FILE *w, *temp; if (argc != 2) exit(printf("Usage: %s <word>\n", argv[0])); if ((w = fopen(word_file,"r")) == NULL) exit(printf("Couldn't open word file!\n")); sprintf(filename,"%s.%d", temp_file, getpid()); if ((temp = fopen(filename,"w")) == NULL) exit(printf("Couldn't open temp file!\n")); fgets(theword, WLEN, w); sscanf(theword, "%d", &words); printf("Adding this word makes %d words!\n", ++words); fprintf(temp, "%d\n", words); while (fgets(theword, WLEN, w) != NULL) fputs(theword, temp); fprintf(temp, "%s\n", argv[1]); fclose(temp); fclose(w); unlink(word_file); link(filename,word_file); unlink(filename); chmod(word_file, mode); } END_OF_FILE # -------------- File .hang-words --------------- echo extracting file .hang-words cat << 'END_OF_FILE' > .hang-words 301 transcontinental supermarket prairie trashcan mysterious interior ulterior xylophone pizza quietest foray confusion kaleidoscope lecherous opiate pious proprietary salacious semaphore suspicion vertigo psychotic surrogate typhoon upholstery vociferous warranty guarantee wrath aerospace affirmation apprehension appease articulate arrogant backhand batten bastinado benediction fight braggadocio brassiere inquisition caprice chimney clique concessionaire corsage destructive castrate strength mythological animation hangman recursion transformation fornicate glockenspiel tongue dictatorship utilitarianism establishment homogeneous horticulture agriculture hymnal hydrometer hyena grandiose hypothesize ballistic iconography ideological illegitimate impediment immune culpable lunar subroutine iterative jigsaw jurisdiction kilogram hashish cocaine marijuana kimono kyack laminate latitudinal longtitudinal cunning tricky presidential contradictory obnoxious gardener nuisance reboot numskull muzzle fodder fascination transliteration compute computer network notice telephone androgynous homophobe terminal device gamey fascination profile ambiance ambulatory whore contradiction fatality chiropractic chicanery buzzard cache xerox internal belch laboratory lightning zodiac victim vignette genre rendezvous vineyard traffic vibrating jostle vampire jamboree juggle oblong coffin noose plaza collegiate seaboard empire script generation submarine linear parallel serial duplicate coaxial triaxial quadrangle ogre howitzer machete cathode camouflage combat hybrid shellac neophyte anthropomorphic worthless jabberwocky wrong kamikaze yawning coiffeur suicide squawk kazoo krypton larynx pyromania prologue appendix communist eunuch pervert masquerade louse magnetic majestic lumberjack jocularity jeopardy luxuriate prophylactic malediction hydroponic manganese horrify masseuse hazard messiah pariah guzzle crucifixion guillotine gallows esoteric pendulum tourniquet thumbscrew enema catheter totalitarianism transducer transcend nirvana organize chaos spectre ghoul asthetic timpani plague twitter pneumonia giggle abdomen bodacious hilarious adjourn peculiar android vestibule zombie popcorn anesthetic cyborg zipper wretched wrench slime wriggle ridicule quoth usher rowboat house valve automobile helicopter vertex vortex virgin violent macabre vomit voodoo voyeur vulture sparrow gondola polychrome monochrome plunder intestine whetstone plight reprieve vulgarity vulcanize cannibalize alcohol vivisection voguish rogue dastardly queer cocatrice nymph nuzzle transmogrification slaughter grotesque transvestite transmutate mutant tsunami cockroach beetle cemetery caustic twinkle villify centrifuge definition uglify dictionary ubiquitous coercion END_OF_FILE echo done with shar extraction
dat@hpcnof.UUCP (01/10/86)
Ooops! I made a slight error in the original posting of my hangman game ... If you're on a Bell system, you'll need to compile the current (or the attached) curses.c module with: cc -O -D RAWMODE -c curses.c (need to define RAWMODE) If you're on a Berkeley system things get much more complex...you need to use the new curses.c file (attached) and compile it with the command: cc -O -D RAWMODE -D BSD -c curses.c DISCLAIMER: I don't have access to a machine running BSD software, so if it turns out that the newly mangled curses program doesn't work, Please help me fix it!! --- Dave Taylor ------ attachment: curses.c /** curses.c **/ /** This library gives programs the ability to easily access the termcap information and write screen oriented and raw input programs. The routines can be called as needed, except that to use the cursor / screen routines there must be a call to InitScreen() first. The 'Raw' input routine can be used independently, however. Dave Taylor, HP Colorado Networks **/ #include <stdio.h> #ifdef RAWMODE # ifdef BSD # include <sgtty.h> # else # include <termio.h> # endif #endif #include <ctype.h> #include "curses.h" #ifdef BSD /** need to define this routine since BSD ctype.h doesn't include it! **/ # define tolower(c) (isupper(c)? c - 'A' + 'a' : c) /** also need to map the System V ioctl stuff... **/ #define TCGETA TIOCGETP #define TCSETAW TIOCSETN #endif #ifdef RAWMODE # define TTYIN 0 #endif extern int debug; #ifdef RAWMODE # ifdef BSD struct sgtty _raw_tty, _original_tty; # else struct termio _raw_tty, _original_tty; # endif static int _inraw = 0; /* are we IN rawmode? */ #endif static int _intransmit; /* are we transmitting keys? */ static char *_clearscreen, *_moveto, *_up, *_down, *_right, *_left, *_setbold, *_clearbold, *_setunderline, *_clearunderline, *_sethalfbright, *_clearhalfbright, *_setinverse, *_clearinverse, *_cleartoeoln, *_cleartoeos, *_transmit_on, *_transmit_off; static int _lines, _columns; static char _terminal[1024]; /* Storage for terminal entry */ static char _capabilities[256]; /* String for cursor motion */ static char *ptr = _capabilities; /* for buffering */ int outchar(); /* char output for tputs */ InitScreen() { /* Set up all this fun stuff: returns zero if all okay, or; -1 indicating no terminal name associated with this shell, -2..-n No termcap for this terminal type known */ int tgetent(), /* get termcap entry */ error; char *tgetstr(), /* Get termcap capability */ termname[40]; if (strcpy(termname, getenv("TERM")) == NULL) return(-1); if ((error = tgetent(_terminal, termname)) != 1) return(error-2); /* load in all those pesky values */ _clearscreen = tgetstr("cl", &ptr); _moveto = tgetstr("cm", &ptr); _up = tgetstr("up", &ptr); _down = tgetstr("do", &ptr); _right = tgetstr("nd", &ptr); _left = tgetstr("bs", &ptr); _setbold = tgetstr("so", &ptr); _clearbold = tgetstr("se", &ptr); _setunderline = tgetstr("us", &ptr); _clearunderline = tgetstr("ue", &ptr); _setinverse = tgetstr("so", &ptr); _clearinverse = tgetstr("se", &ptr); _sethalfbright = tgetstr("hs", &ptr); _clearhalfbright = tgetstr("he", &ptr); _cleartoeoln = tgetstr("ce", &ptr); _cleartoeos = tgetstr("cd", &ptr); _lines = tgetnum("li"); _columns = tgetnum("co"); _transmit_on = tgetstr("ks", &ptr); _transmit_off = tgetstr("ke", &ptr); if (!_left) { _left = ptr; *ptr++ = '\b'; *ptr++ = '\0'; } return(0); } char *return_value_of(termcap_label) char *termcap_label; { /** this will return the string kept by termcap for the specified capability **/ char *tgetstr(); /* Get termcap capability */ return( (char *) tgetstr(termcap_label, &ptr)); } transmit_functions(newstate) int newstate; { /** turn function key transmission to ON | OFF **/ if (newstate != _intransmit) { _intransmit = ! _intransmit; if (newstate == ON) tputs(_transmit_on, 1, outchar); else tputs(_transmit_off, 1, outchar); fflush(stdout); /* clear the output buffer */ } } /****** now into the 'meat' of the routines...the cursor stuff ******/ ScreenSize(lines, columns) int *lines, *columns; { /** returns the number of lines and columns on the display. **/ *lines = _lines - 1; /* assume index from zero */ *columns = _columns; } ClearScreen() { /* clear the screen: returns -1 if not capable */ if (!_clearscreen) return(-1); tputs(_clearscreen, 1, outchar); fflush(stdout); /* clear the output buffer */ return(0); } MoveCursor(row, col) int row, col; { /** move cursor to the specified row column on the screen. 0,0 is the top left! **/ char *tgoto(); char *stuff; if (!_moveto) return(-1); stuff = (char *) tgoto(_moveto, col, row); tputs(stuff, 1, outchar); fflush(stdout); return(0); } CursorUp() { /** move the cursor up one line **/ if (!_up) return(-1); tputs(_up, 1, outchar); fflush(stdout); return(0); } CursorDown() { /** move the cursor down one line **/ if (!_down) return(-1); tputs(_down, 1, outchar); fflush(stdout); return(0); } CursorLeft() { /** move the cursor one character to the left **/ if (!_left) return(-1); tputs(_left, 1, outchar); fflush(stdout); return(0); } CursorRight() { /** move the cursor one character to the right (nondestructive) **/ if (!_right) return(-1); tputs(_right, 1, outchar); fflush(stdout); return(0); } StartBold() { /** start boldface/standout mode **/ if (!_setbold) return(-1); tputs(_setbold, 1, outchar); fflush(stdout); return(0); } EndBold() { /** compliment of startbold **/ if (!_clearbold) return(-1); tputs(_clearbold, 1, outchar); fflush(stdout); return(0); } StartUnderline() { /** start underline mode **/ if (!_setunderline) return(-1); tputs(_setunderline, 1, outchar); fflush(stdout); return(0); } EndUnderline() { /** the compliment of start underline mode **/ if (!_clearunderline) return(-1); tputs(_clearunderline, 1, outchar); fflush(stdout); return(0); } StartHalfbright() { /** start half intensity mode **/ if (!_sethalfbright) return(-1); tputs(_sethalfbright, 1, outchar); fflush(stdout); return(0); } EndHalfbright() { /** compliment of starthalfbright **/ if (!_clearhalfbright) return(-1); tputs(_clearhalfbright, 1, outchar); fflush(stdout); return(0); } StartInverse() { /** set inverse video mode **/ if (!_setinverse) return(-1); tputs(_setinverse, 1, outchar); fflush(stdout); return(0); } EndInverse() { /** compliment of startinverse **/ if (!_clearinverse) return(-1); tputs(_clearinverse, 1, outchar); fflush(stdout); return(0); } PutLine(x, y, line, args) int x,y; char *line; int args; { /** write line, with 'args', at location x,y **/ MoveCursor(x,y); _doprnt(line, &args, stdout); fflush(stdout); /* ensure it actually gets out! */ } CleartoEOLN() { /** clear to end of line **/ if (!_cleartoeoln) return(-1); tputs(_cleartoeoln, 1, outchar); fflush(stdout); /* clear the output buffer */ return(0); } CleartoEOS() { /** clear to end of screen **/ if (!_cleartoeos) return(-1); tputs(_cleartoeos, 1, outchar); fflush(stdout); /* clear the output buffer */ return(0); } #ifdef RAWMODE Raw(state) int state; { /** state is either ON or OFF, as indicated by call **/ if (state == OFF && _inraw) { (void) ioctl(TTYIN, TCSETAW, &_original_tty); _inraw = 0; } else if (state == ON && ! _inraw) { (void) ioctl(TTYIN, TCGETA, &_original_tty); /** current setting **/ (void) ioctl(TTYIN, TCGETA, &_raw_tty); /** again! **/ #ifdef BSD _raw_tty.sg_flags &= ~(CRMOD | ECHO) _raw_tty.sg_flags &= (RAW); #else _raw_tty.c_iflag &= ~(INLCR | ICRNL | BRKINT); _raw_tty.c_iflag |= IXON; _raw_tty.c_oflag |= OPOST; _raw_tty.c_oflag &= ~(OLCUC | ONLCR | OCRNL | ONOCR | ONLRET); _raw_tty.c_lflag &= ~(ICANON | ECHO); _raw_tty.c_cc[VMIN] = '\01'; _raw_tty.c_cc[VTIME] = '\0'; #endif (void) ioctl(TTYIN, TCSETAW, &_raw_tty); _inraw = 1; } } int ReadCh() { /** read a character with Raw mode set! **/ register int result; char ch; result = read(0, &ch, 1); return(result == 0? EOF : ch); } #endif outchar(c) char c; { /** output the given character. From tputs... **/ /** Note: this CANNOT be a macro! **/ putc(c, stdout); }