grotwin (Part 2 of 7)
nwh at hrc63.UUCP
nwh at hrc63.UUCP
Sat Jul 12 00:02:17 AEST 1986
#! /bin/sh
# This is a shell archive. To extract the files type 'sh file'
# This archive created on Thu Jul 10 13:32:28 WET 1986
echo 'shar: extracting 'grotwin.c' ( 15356 characters)'
if test -f 'grotwin.c'
then
echo "shar: will not overwrite existing file 'grotwin.c'"
else
cat << \SHAR_EOF > 'grotwin.c'
#ifndef lint
static char sccsid[] = "@(#)grotwin.c 2.2 [ (C) Nigel Holder 1986 ]";
#endif
/***************************************
*
* Author : Nigel Holder
*
* Date : 10 July 1986
*
*
* Copyright (C) 1986 by Nigel Holder
*
* Permission to use this program is granted, provided it is not
* sold, or distributed for direct commercial advantage, and includes
* the copyright notice and this clause.
*
* Grotwin - provides a somewhat primitive windowing capability
* for people unfortunate enough to use the standard 24 x 80 type
* of terminal when the console is in use. Definitely written for
* 4.[2,3] at the present time, as Sys V.2 does not cater for pseudo
* terminals or have the select() facility (amongst other things !)
* (version 8 should fix this).
*
* Files used :-
*
* grotwin.c - window system initialisation
* deals with startup files
*
* manager.c - window manager
* deals with input and output
*
* window.c - window manipulator
* deals with aspects concerning windows
* during normal usage
*
* update.c - simulates dumb terminal for use
* with window manager.
*
* grotwin.h - header file for above
*
* utmp.c - utmp manipulator
* updates utmp entries for each window
*
* grotwin.make - makefile for above
*
* Bugs :-
*
* Can't have the situation where no windows are present !
* Needs a vt100 like terminal type
*
***************************************/
#include <sys/ioctl.h>
#include <sys/file.h>
#include <signal.h>
#include "grotwin.h"
extern int active_windows; /* number of user windows active */
/* system dependent stuff */
static char manfile[] = "/usr/mrc/grotwin.man";
static char helpfile[] = "/usr/mrc/grotwin.help";
static char system_more[] = "more";
static char default_shell[] = "/bin/sh";
static int ignore_homefile = FALSE; /* look for default file */
static char initfile[BUFSIZ + 1]; /* temp string buffer */
/* default startup values that may be changed by user command line */
int timeon = TRUE; /* display clock on top edge */
int win_border = WIN_STANDEND; /* normal brightness window borders */
int startup = TRUE; /* program startup period */
int confused = FALSE; /* for when program hangs up */
int **screen_priority = NULL; /* which window visible at each point */
char timestring[] = " hh:ss "; /* time on top edge of b/g window */
char nottimestring[] = "-------"; /* used when time is not displayed */
struct windowdetails win[MAX_WINDOWS_PLUS]; /* window details */
struct sgttyb masterterm; /* used to store initial tty state */
struct tchars mtchars;
int mlocalmode;
int screenlines; /* lines on users screen */
int screencolumns; /* columns on users screen */
int time_start; /* where time string is placed */
int time_end; /* where time string ends */
char **masterscreen; /* hook to stdscr from curses */
char *progname; /* program name stripped of any /'s*/
char *home_shell; /* shell from users $SHELL variable */
main(argc, argv)
int argc;
char *argv[];
{
int length, i;
char *rindex(), *getenv();
if ((progname = rindex(argv[0], '/')) != NULL) {
++progname;
}
else {
progname = argv[0];
}
/* scan command line */
while (argc > 1 && argv[1][0] == '-') {
switch (argv[1][1]) {
case 'n' :
ignore_homefile = TRUE;
break;
case 't' :
timeon = FALSE;
break;
case 'b' :
win_border = WIN_STANDOUT;
break;
case 'h' :
man_info();
exit(0);
break;
default :
fprintf(stderr,
"usage: %s [-n][-t][-b][-h] [file]\n\n",
progname);
fprintf(stderr, "\t\t-n\t-\tignore ");
fprintf(stderr, "$HOME startup file\n");
fprintf(stderr, "\t\t-t\t-\tturn time off\n");
fprintf(stderr, "\t\t-b\t-\tbold windows\n");
fprintf(stderr, "\t\t-h\t-\thelp info\n");
exit(1);
break;
}
--argc; /* skip over program name */
++argv;
}
if (isatty(0) == 0) {
fprintf(stderr, "%s: standard input not a tty\n", progname);
exit(2);
}
if (argc > 1) { /* check for startup file */
strcpy(initfile, argv[1]);
}
else {
if (ignore_homefile != TRUE) {
/* check for default file in users home directory */
strcpy(initfile, getenv("HOME"));
if (*initfile) {
length = strlen(initfile);
strcpy(initfile + length, "/.");
strcpy(initfile + length + 2, progname);
if (access(initfile, F_OK) == -1) {
*initfile = '\0';
}
}
}
else {
*initfile = '\0';
}
}
for (i = 3 ; i < NOFILE ; ++i) { /* just to be sure */
close(i);
}
/* get user tty characteristics */
ioctl(0, TIOCGETP, &masterterm);
ioctl(0, TIOCLGET, &mlocalmode);
ioctl(0, TIOCGETC, &mtchars);
screen_init(); /* set up curses and screen dimensions */
if (screencolumns < WORLD_MIN_COLUMNS ||
screenlines < WORLD_MIN_ROWS) {
fprintf(stderr, "%s: screen size too small !\r\n", progname);
fprintf(stderr, "screen size must be at least");
fprintf(stderr, " %d lines by %d columns\r\n",
WORLD_MIN_ROWS, WORLD_MIN_COLUMNS);
die();
}
initialise(); /* initialise globals */
setup(); /* initial windows */
startup = FALSE;
manager(); /* the window manager */
/* should never get here */
fprintf(stderr, "\r\n%s: internal error (fallen off end), sorry !\r\n",
progname);
die();
}
static
initialise() /* initialise globals */
{
int **priority_win();
int fatal(), forced_die(), child_exit(), update_time();
int i, string_length;
char **virtwin();
/* set all windows to inactive status */
for (i = 0 ; i < MAX_WINDOWS_PLUS ; ++i) {
win[i].active = FALSE;
strcpy(win[i].pseudo_ttyname, "unknown");
}
/* work out where time will go */
string_length = sizeof(timestring) - 1; /* -1 for null at end */
time_start = (screencolumns - string_length) / 2;
time_end = time_start + string_length - 1;
screen_priority = priority_win(); /* to decide display areas */
/* slight liberty */
masterscreen = stdscr->_y; /* from curses package */
/*******************
* This window is always the lowest priority one.
* It cannot be accessed by the user and therefore provides
* a background for the portions of the screen that are not used.
*******************/
win[MAX_WINDOWS].y_start = 1;
win[MAX_WINDOWS].x_start = 1;
win[MAX_WINDOWS].y_end = screenlines - 1;
win[MAX_WINDOWS].x_end = screencolumns - 1;
win[MAX_WINDOWS].screenptr = virtwin('\0');
win_initialise(MAX_WINDOWS, BACKGROUND);
for (i = 0 ; i < sizeof(nottimestring) - 1 ; ++i) {
nottimestring[i] = BACKGROUND;
}
signal(SIGALRM, update_time);
update_time();
if (timeon == TRUE) { /* display time first time round */
display_time(DISPLAY);
}
top_dog(MAX_WINDOWS); /* install background window */
/* stop a core dump - playing safe as leaves tty in previous state */
signal(SIGILL, fatal);
signal(SIGTRAP, fatal);
signal(SIGIOT, fatal);
signal(SIGEMT, fatal);
signal(SIGSEGV, fatal);
signal(SIGBUS, fatal);
signal(SIGSYS, fatal);
/* signals to be used to stop program externally */
signal(SIGHUP, forced_die);
signal(SIGINT, forced_die);
signal(SIGQUIT, forced_die);
signal(SIGTERM, forced_die);
/* in order to pick up dead children (when a window is removed) */
signal(SIGCHLD, child_exit);
}
static
setup() /* initial windows */
{
FILE *fp, *fopen();
int columns, rows, xstart, ystart;
int i, limit, items_read, winno;
char *getenv(), *rindex(), *fgets();
char *program, buffer[BUFSIZ + 1], buffer2[BUFSIZ + 1];
/* find users favourite shell */
if ((home_shell = getenv("SHELL")) == NULL) {
home_shell = default_shell;
}
/* check for file to define startup windows */
if (*initfile) {
if ((fp = fopen(initfile, "r")) == NULL) {
fprintf(stderr, "%s: can't open %s\r\n",
progname, initfile);
die();
}
limit = MAX_WINDOWS;
}
else { /* default windows */
fp = NULL;
limit = 2;
}
winno = -2; /* invalid value to enable test at end */
for (i = 0 ; i < limit ; ++i) { /* create each window */
program = buffer2;
if (fp != NULL) {
if (fgets(buffer, BUFSIZ, fp) == NULL) {
break;
}
items_read = sscanf(buffer, "%d%d%d%d%[^\n\0]",
&columns, &rows, &xstart, &ystart, program);
if (items_read < 4) {
winno = -2;
break;
}
check_size(&columns, &rows, &xstart, &ystart);
if (items_read < 5) {
strcpy(program, home_shell);
}
else {
while (*program == ' ' || *program == '\t') {
++program;
}
/* if just white space default to shell */
if (! *program) {
strcpy(program, home_shell);
}
}
}
else { /* default window sizes */
columns = -1;
rows = -1;
xstart = -1;
ystart = -1;
check_size(&columns, &rows, &xstart, &ystart);
strcpy(program, home_shell);
}
winno = win_instance(rows, columns, ystart, xstart, program);
if (winno != -1) {
next_input_window(winno);
}
}
if (fp != NULL) {
fclose(fp);
}
if (active_windows <= 0) {
if (winno == -2) {
fprintf(stderr, "%s: format of %s is invalid\r\n",
progname, initfile);
}
else {
fprintf(stderr, "%s: can't open any windows\r\n",
progname);
}
die();
}
}
/*******************
* Check (and change if necessary), that window dimensions selected can
* be displayed on output device screen - if not then firstly move start
* positions and then change dimensions if this fails.
*
* Special negative value meanings:
*
* In size field:
* -1 - full screen width or height depending on position
* -2 - half full screen width or height depending on position
*
* In position field:
* -1 - screen width or height minus specified width or height
* -2 - half full width or height start positiono
*
*******************/
check_size(columns, rows, xstart, ystart)
int *columns, *rows, *xstart, *ystart;
{
if (*columns == -1 || *columns > screencolumns) {
*columns = screencolumns;
}
else {
if (*columns == -2) { /* half width */
*columns = screencolumns / 2;
}
else {
if (*columns < MIN_COLUMNS) { /* too small */
*columns = MIN_COLUMNS;
}
}
}
if (*rows == -1 || *rows > screenlines) {
*rows = screenlines;
}
else {
if (*rows == -2) { /* half heigth */
*rows = screenlines / 2;
}
else {
if (*rows < MIN_ROWS) { /* too small */
*rows = MIN_ROWS;
}
}
}
if (*xstart == -1) { /* pad to fit */
*xstart = screencolumns - *columns;
}
else {
if (*xstart == -2) { /* half width */
*xstart = screencolumns /2 ;
}
if (*xstart + *columns > screencolumns) {
*xstart = screencolumns - *columns;
}
}
if (*ystart == -1) { /* pad to fit */
*ystart = screenlines - *rows;
}
else {
if (*ystart == -2) { /* half height */
*ystart = screenlines /2 ;
}
if (*ystart + *rows > screenlines) {
*ystart = screenlines - *rows;
}
}
}
static
screen_init() /* initialise curses package and screen size */
{
initscr();
screencolumns = COLS;
screenlines = LINES;
raw();
nonl();
noecho();
}
/*******************
* Save current screen in temporary window to enable non-window
* user interaction, such as a short window command summary
* and window status information to occur. Window is replaced
* at end of interaction.
*******************/
inform(function, winno)
int (*function)();
int winno;
{
WINDOW *helpwin, *newwin();
int old_timeon, waiting;
char c;
/*******************
* Need to stop time updating screen since we are
* temporarily not using stdscr.
*******************/
alarm(0); /* turn off alarm */
old_timeon = timeon;
if (timeon == TRUE) { /* remove time */
timeon = FALSE;
display_time(REMOVE);
}
helpwin = newwin(screenlines, screencolumns, 0, 0);
overwrite(stdscr, helpwin);
wclear(stdscr);
wrefresh(stdscr);
/* call supplied function */
if ((waiting = ((*function)(winno))) == TRUE) {
printf("[ Hit return to continue ] ");
fflush(stdout);
read(0, &c, 1);
}
overwrite(helpwin, stdscr);
overwrite(helpwin, curscr);
/* don't know where cursor is, so force whole screen redraw */
wrefresh(curscr);
delwin(helpwin);
if (old_timeon == TRUE) {
timeon = TRUE;
update_time(); /* display time this time round */
}
}
man_info()
{
if (access(manfile, R_OK) != -1) {
sprintf(initfile, "%s %s", system_more, manfile);
system(initfile);
}
else {
fprintf(stderr, "%s: sorry, can't find manual page %s\n",
progname, manfile);
}
}
help_info(winno) /* print help info by pages */
int winno;
{
FILE *fopen(), *fp, *out;
if ((fp = fopen(helpfile, "r")) != NULL) {
page(fp);
fclose(fp);
}
else {
if (startup == FALSE) {
out = stdout;
}
else { /* grotwin -h invocation */
out = stderr;
fprintf(out, "%s: ", progname);
}
fprintf(out, "sorry, helpfile %s not available\r\n", helpfile);
}
return(TRUE);
}
page(fp)
FILE *fp;
{
static char page_string[] = "[ Hit any key for more ] ";
int lines;
char *fgets(), buffer[80];
lines = 1;
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
fputs(buffer, stdout);
putc('\r', stdout);
if (++lines >= screenlines) {
lines = 1;
fputs(page_string, stdout);
fflush(stdout);
read(0, buffer, 1); /* wait for user */
clear_line(sizeof(page_string));
}
}
}
clear_line(length) /* clear a line on screen */
int length;
{
int outchar();
putc('\r', stdout);
/*******************
* Clear line. Try to use termcap delete to end of line,
* delete line or just output plain spaces if all else fails.
* Delete to end of line may be faster than delete line
* since delete line may require the terminal to
* scroll the bottom line.
*******************/
if (CE != (char *) NULL) {
tputs(CE, 1, outchar);
}
else {
if (DL != (char *) NULL) {
tputs(CE, 1, outchar);
}
else { /* bodge it */
while (length--) {
putc(' ', stdout);
}
}
}
putc('\r', stdout);
fflush(stdout);
}
static
outchar(c) /* output routine for use with tputs in clear_line */
char c;
{
putc(c, stdout);
}
forced_die()
{
alarm(0);
signal(SIGINT, SIG_IGN);
signal(SIGCHLD, SIG_IGN);
signal(SIGALRM, SIG_IGN);
kill_all_shells();
}
die()
{
static char confused_mess[] =
"\7\r\n-- Internal error - please report --\r\n";
alarm(0);
if (startup == FALSE) {
wclear(stdscr);
wmove(stdscr, LINES - 1, 0);
wrefresh(stdscr);
}
endwin();
if (screen_priority != NULL) {
free_priority_win(screen_priority);
}
if (confused == REALLY_CONFUSED) {
fprintf(stderr, confused_mess);
exit(3);
}
exit(0);
}
static
fatal()
{
static char fatalmess[] =
"\n\n\7 caught nasty signal - exiting \n";
static int first_time = TRUE;
alarm(0);
signal(SIGINT, SIG_IGN);
signal(SIGALRM, SIG_IGN);
/* endwin will do this anyway, good for following printfs though */
ioctl(0, TIOCSETP, &masterterm);
ioctl(0, TIOCLBIS, &mlocalmode);
ioctl(0, TIOCSETC, &mtchars);
fprintf(stderr, fatalmess);
/* safety check to stop endless recursion if hopelessly lost */
if (first_time) {
first_time = FALSE;
forced_die();
die();
}
exit(4);
}
SHAR_EOF
if test 15356 -ne `wc -c < 'grotwin.c'`
then
echo 'shar: error transmitting 'grotwin.c' (should have been 15353 charcaters)'
fi
fi
exit
Nigel Holder UK JANET: yf21 at uk.co.gec-mrc.u
Marconi Research, ARPA: yf21%u.gec-mrc.co.uk at ucl-cs
Chelmsford,
Essex. CM2 8HN.
+44 245 73331 ext. 3219 / 3214
More information about the Comp.sources.unix
mailing list