|
|
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);
}
}
/*-------------------------------------------------------------------------*/