|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T u
Length: 6633 (0x19e9) Types: TextFile Names: »utils.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/General/Tt/utils.c«
/***************************************************************************\ |* *| |* utils.c: A version of Tetris to run on ordinary terminals, *| |* (ie., not needing a workstation, so should available *| |* to peasant Newwords+ users. This module supplies all *| |* the function that I will need, but which are not *| |* intrinsically a part of Tetris itself. *| |* *| |* Author: Mike Taylor (mirk@uk.ac.warwick.cs) *| |* Started: Fri May 26 12:26:05 BST 1989 *| |* *| \***************************************************************************/ #include <varargs.h> #include <curses.h> #include <strings.h> #include <sys/types.h> #include <sys/time.h> #include <errno.h> #include "tt.h" #include "utils.h" #include "screen.h" /*-------------------------------------------------------------------------*/ extern char *rindex (); extern char *getenv (); /***************************************************************************\ |* *| |* The function basename() acts like the UNIX(tm) command of the same *| |* name. It takes as its argument a string, and returns the last path- *| |* component of that string, (ie, the section after the last '/'), or *| |* the whole string if it has no '/'. *| |* *| \***************************************************************************/ char *basename (name) char *name; { char *slash; if (slash = rindex (name, '/')) return (slash+1); else return (name); } /***************************************************************************\ |* *| |* This is my home-made varargs-based version of C++'s neat function of *| |* the same name. It saves all that tedious mucking about with static *| |* buffers which you sprintf into, then forget all about, by basically *| |* being a sprintf with its own statis storage. It takes as arguments *| |* exactly the same things as printf(3), and returns a pointer to the *| |* resultant string. *| |* *| \***************************************************************************/ /*VARARGS*/ char *form (va_alist) va_dcl { va_list pvar; char *fmt_string; static char result[LINELEN]; va_start (pvar); fmt_string = va_arg (pvar, char*); (void) vsprintf (result, fmt_string, pvar); va_end (pvar); return (result); } /***************************************************************************\ |* *| |* This is yer bog-standard "print a message and quit" function, except *| |* that it checks to see if we are in curses(3x), and if so, takes us *| |* out before doing its stuff. The arguments are an integer, the exit *| |* status, and a string containing an error report, to which will be *| |* prepended the program name when it is printed. If the status code *| |* is LE_OK, (ie. nothing went wrong), no message is printed. *| |* *| \***************************************************************************/ void die (status, line) int status; char *line; { if (in_curses) { myrefresh (); #ifndef LINT nocbreak (); echo (); #endif /* LINT */ endwin (); } if (status != LE_OK) (void) printf ("%s: %s\n", prog_name, line); #ifndef LOCKF (void) unlink (LOCK_FILE); /* Just in case :-) */ #endif /* LOCKF */ exit (status); } /***************************************************************************\ |* *| |* The function get_termcap extracts the information we need from the *| |* UNIX terminal capability database. It has been (correctly) pointed *| |* out that most of what I do in this function is already done for me *| |* by curses(3x), but (A) curses behaves stupidly on terminals with *| |* termcap's "sg" non-zero, (ie. refuses to enter standout mode, so *| |* you *have* to do it manually), and (B) I wanted to prove a point to *| |* Sunny and others, who said it was impossible. Tgets() sucks :-P *| |* *| \***************************************************************************/ void get_termcap () { static char bp[1024]; /* Seems odd to hardwire the 1024, but ... */ char *term_name; /* ... the manual entry told me to do it! */ int status; /* Success/failure of tgetent here */ char *tmp_ptr = tc_string; /* Pointer to be advanced by tgetstr() */ if ((term_name = getenv ("TERM")) == NULL) die (LE_ENV, "couldn't get TERM from environment"); if ((status = tgetent (bp, term_name)) == -1) die (LE_TERMCAP, "couldn't open TERMCAP file"); if (status == 0) die (LE_TERMCAP, "couldn't find your terminal in TERMCAP file"); if ((screen_depth = tgetnum ("li")) == -1) die (LE_TERMCAP, "couldn't get screen-depth from termcap"); if ((screen_width = tgetnum ("co")) == -1) die (LE_TERMCAP, "couldn't get screen-width from termcap"); if ((so_gunk = tgetnum ("sg")) == -1) so_gunk = 0; /* Default value */ so_str = tmp_ptr; if (tgetstr ("so", &tmp_ptr) == NULL) die (LE_TERMCAP, "couldn't get standout code from termcap"); se_str = tmp_ptr; if (tgetstr ("se", &tmp_ptr) == NULL) die (LE_TERMCAP, "couldn't get standend code from termcap"); } /***************************************************************************\ |* *| |* The function flush_keybord() checks to see whether there are any *| |* keystrokes waiting to be read, and if so reads them and throws *| |* them away. Surprising how complex this needs to be, but the only *| |* alternative I can think of is to ioctl() stdin to be non-blocking, *| |* read() until it returns 0, then ioctl() it back, which is scarcely *| |* an improvement. *| |* *| \***************************************************************************/ void flush_keyboard () { fd_set fds; /* Will contain only stdin */ struct timeval timeout; /* Will contain a zero timeout (poll) */ static char buffer[LINELEN]; /* Will be used as the buffer to read(2) */ int status; /* Contains select(2)'s return value */ while (1) { FD_ZERO (&fds); FD_SET (0, &fds); timeout.tv_sec = 0L; timeout.tv_usec = 0L; if (((status = select (1, &fds, (fd_set*) NULL, (fd_set*) NULL, &timeout)) == -1) && (errno != EINTR)) die (LE_SELECT, "select(2) failed in flush_keybord()"); if ((status == 0) || (status == -1)) break; /* Can only be -1 if errno == EINTR */ (void) read (0, buffer, LINELEN); } } /*-------------------------------------------------------------------------*/