Screen packages in general (was Re: Vermont Views)

Stacey Campbell staceyc at sco.COM
Thu Dec 6 06:13:38 AEST 1990


In article <1990Nov27.165132.1335 at bkj386.uucp> anton at analsyn.UUCP writes:
>Now CURSES may not be perfect.  it may be  bloated  and  only  do
>80-90%  of  the  job, but it is there.  it is also a standard, as
>far as the TERMCAP/TERMINFO side goes.

Agreed.  Even if curses doesn't directly support some feature it will
just take a little work to add the required top layer, which can then
be used for other applications' development.

>	   SVR3.2.  They have colour capability in CURSES.  If SCO
>	   etc choose not to implement this for their own reasons
>	   that's their problem.   Go buy your UNIX from someone who
>	   adhere's to the standard.

Just so it is clear, SCO Unix V 3.2 (all versions) supports the
stock AT&T System V 3.2 color curses.  Anton is almost certainly
referring to SCO Xenix.  I've tossed in a fun little curses color
demo at the bottom of this post, so anybody with any System V 3.2
Development System can give it a spin.

>	   The SCO TERMINFO lacks many features that
>	   were introduced in SVR2.0.  In fact most of the SCO XENIX 
>	   implemetation of TERMINFO & utilities is riddled with
>	   bugs.

SCO Xenix comes with System V 3.[01] curses, not Sys V 2 (the clue is
ACS character defines in /usr/include/tinfo.h).  Historically SCO
Xenix was based mostly around termcap curses simply because in
the good old days BSD termcap curses was much more robust and useful
than System V curses.  IMHO System V 3.2 curses, and even to a degree
System V 3.1 curses, are far and away better than BSD curses.

>	   But what about customers buying the package from sortes
>	   and other outlets?
>
>	   To put this in persspective, would you consider buying,
>	   say, Norton Tools for DOS, if they were written so that
>	   they used the '286 & '386 extended instructions and the
>	   features of the VGA ?    I mean this in the sense that
>	   you HAVE to upgrade to use the program at all!

System V 3.2 curses applications execute correctly on Xenix machines,
terminfo files are backward compatible, though it is much nicer to
use Unix terminfo files when on Xenix.  There is no real system
dependent issues when running a 386 Unix curses application on Xenix.
The application only requires a working terminfo file.

>	   We're also trying to produce a product which can be
>	   installed without being an expert in TERMCAP or TERMINFO
>	   and without having to RTFM.

The terminfo(4) man page is a bit daunting.  There is a reasonable
Nutshell book that deals with both termcap and terminfo.

Here's the demo program;

#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#    212 -rw------- Makefile
#   6631 -rw-rw-r-- fire.c
#
# ============= Makefile ==============
if test -f 'Makefile' -a X"$1" != X"-c"; then
	echo 'x - skipping Makefile (File already exists)'
else
echo 'x - extracting Makefile (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
CC= cc
CFLAGS= -O -DM_TERMINFO -UM_TERMCAP
LDFLAGS= -O
OBJS= fire.o
X
#Unix
LDLIBS= -lcurses -lm
X
#Xenix
# LDLIBS= -ltinfo -lm
X
fire: $(OBJS)
X	$(CC) $(LDFLAGS) fire.o -o fire $(LDLIBS)
X
clean:
X	rm -f $(OBJS) fire
SHAR_EOF
chmod 0600 Makefile ||
echo 'restore of Makefile failed'
Wc_c="`wc -c < 'Makefile'`"
test 212 -eq "$Wc_c" ||
	echo 'Makefile: original size 212, current size' "$Wc_c"
fi
# ============= fire.c ==============
if test -f 'fire.c' -a X"$1" != X"-c"; then
	echo 'x - skipping fire.c (File already exists)'
else
echo 'x - extracting fire.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'fire.c' &&
#include <sys/types.h>
#include <math.h>
#include <curses.h>
#include <string.h>
X
#ifndef COLOR_BLACK
#define start_color()
#define COLOR_PAIR(a) 0
#endif
X
extern double drand48();
extern void srand48();
extern long lrand48();
extern time_t time();
extern char *malloc();
extern void free();
extern unsigned int sleep();
X
#define PART_COUNT 10
#define PART_VARIANCE 5
#define SIN_TABLE_SIZE 350
#define COLOR_MIXED -1
#define TABLE_SCALE(val) ((int)(val / M_PI * SIN_TABLE_SIZE))
#define BOUNDCHAR(win, y, x, char) \
X	(((y) >= 0 && (y) < LINES && (x) >= 0 && (x) < COLS) ? \
X		mvwaddch((win), (y), (x), (char)) : 0)
#define PAT_RAND_SEQ	0x01
X
typedef struct particle_t {
X	double y_scale;
X	double x_scale;
X	double x_inc;
X	double x;
X	int old_y, old_x;
X	int direction;
X	int color;
X	int sequence;
X	int pattern_inc;
} particle_t;
X
typedef struct pattern_t {
X	char *string;
X	int mask;
} pattern_t;
X
typedef struct object_t {
X	int rel_y, rel_x;
X	int part_count;
X	pattern_t *pattern;
X	int pat_cycle;
X	int color;
X	int done_count;
X	int life;
X	double y_mag, x_mag;
X	particle_t *particles;
} object_t;
X
typedef struct object_list_t {
X	object_t *object;
X	struct object_list_t *next;
} object_list_t;
X
static pattern_t Patterns[] = {
X	{"......+++++++******@@@@@@@", 0},
X	{"|\\-/", PAT_RAND_SEQ},
X	{".......ooooOOOOoooo", 0},
X	{".........****.......", 0},
X	{"*", 0}
};
X
#define PATTERN_SIZE (sizeof(Patterns) / sizeof(Patterns[0]))
X
static int ColorId = 1;
#define RAND_COLOR() (lrand48() % ColorId + 1)
X
static void DoSinTable();
static void DisplayObject();
static void BuildParticles();
static object_t *BuildObject();
static void InitColors();
static void AddObject();
static void DoObjectList();
static void DeleteObject();
static void FreeMemory();
X
int main(argc, argv)
X
int argc;
char *argv[];
X
{
X	double sin_table[SIN_TABLE_SIZE];
X	object_list_t *top;
X	time_t show_over;
X
X	nice(4);
X	printf("wait.");
X	fflush(stdout);
X	DoSinTable(sin_table);
X	srand48((long)time((time_t *)0));
X	initscr();
X	start_color();
X	curs_set(FALSE);
X	InitColors();
X	top = (object_list_t *)malloc(sizeof(object_list_t));
X	top->object = BuildObject();
X	top->next = 0;
X	show_over = time((time_t *)0) + 10000 * 60;
X	while (time((time_t *)0) < show_over)
X	{
X		if (! (lrand48() % 20))
X			AddObject(&top);
X		else
X			if (! top)
X			{
X				sleep(1);
X				AddObject(&top);
X			}
X		DoObjectList(stdscr, sin_table, &top);
X		wrefresh(stdscr);
X	}
X	endwin();
X	return 0;
}
X
static void DoObjectList(win, sin_table, top)
X
WINDOW *win;
double *sin_table;
object_list_t **top;
X
{
X	object_list_t *now, *old;
X
X	now = *top;
X	while (now)
X	{
X		DisplayObject(win, sin_table, now->object);
X		old = now;
X		now = now->next;
X		if (old->object->done_count >= old->object->part_count ||
X		    old->object->life < 0)
X			DeleteObject(old, top);
X	}
}
X
static void DeleteObject(zap, top)
X
object_list_t *zap;
object_list_t **top;
X
{
X	object_list_t *new, *last;
X
X	if (zap == *top)
X	{
X		new = zap->next;
X		FreeMemory(zap);
X		*top = new;
X		return;
X	}
X	new = *top;
X	while (new != zap)
X	{
X		last = new;
X		new = new->next;
X	}
X	last->next = zap->next;
X	FreeMemory(zap);
}
X
static void FreeMemory(item)
X
object_list_t *item;
X
{
X	free((char *)item->object->particles);
X	free((char *)item->object);
X	free((char *)item);
}
X
static void AddObject(top)
X
object_list_t **top;
X
{
X	object_list_t *new_top;
X
X	new_top = (object_list_t *)malloc(sizeof(object_list_t));
X	new_top->object = BuildObject();
X	new_top->next = *top;
X	*top = new_top;
}
X
static object_t *BuildObject()
X
{
X	object_t *object;
X
X	object = (object_t *)malloc(sizeof(object_t));
X	object->part_count = lrand48() % PART_VARIANCE + PART_COUNT;
X	object->particles = (particle_t *)malloc(object->part_count *
X	    sizeof(particle_t));
X	object->pattern = &Patterns[lrand48() % PATTERN_SIZE];
X	object->pat_cycle = strlen(object->pattern->string);
X	object->rel_y = LINES - lrand48() % 15;
X	object->rel_x = lrand48() % (COLS / 4 * 3) + COLS / 4 * 1 / 2;
X	object->color = lrand48() % 4 ? RAND_COLOR() : COLOR_MIXED;
X	object->done_count = 0;
X	object->y_mag = drand48() * 0.9 + 0.5;
X	object->x_mag = drand48() * 0.9 + 0.5;
X	object->life = lrand48() % 15 + 10;
X	BuildParticles(object);
X
X	return object;
}
X
static void DisplayObject(win, sin_table, object)
X
WINDOW *win;
double *sin_table;
object_t *object;
X
{
X	int i;
X	int draw_y, draw_x;
X	particle_t *p;
X	double y;
X	int sym;
X
X	if (--object->life < 0)
X	{
X		for (i = 0; i < object->part_count; ++i)
X		{
X			p = &object->particles[i];
X			BOUNDCHAR(win, p->old_y, p->old_x, ' ');
X		}
X		return;
X	}
X	for (i = 0; i < object->part_count; ++i)
X	{
X		p = &object->particles[i];
X		if (p->x < M_PI)
X		{
X			BOUNDCHAR(win, p->old_y, p->old_x, ' ');
X			y = sin_table[TABLE_SCALE(p->x)] * p->y_scale;
X			draw_y = object->rel_y - y;
X			draw_x = object->rel_x + p->direction * p->x *
X			    p->x_scale;
X			p->sequence += p->pattern_inc;
X			if (p->sequence < 0)
X				p->sequence = object->pat_cycle - 1;
X			else
X				if (p->sequence >= object->pat_cycle)
X					p->sequence = 0;
X			sym = object->pattern->string[p->sequence];
X			BOUNDCHAR(win, draw_y, draw_x,
X			    sym | COLOR_PAIR(p->color));
X			p->old_y = draw_y;
X			p->old_x = draw_x;
X			p->x += p->x_inc;
X			if (p->x >= M_PI)
X			{
X				BOUNDCHAR(win, draw_y, draw_x, ' ');
X				++object->done_count;
X			}
X		}
X	}
}
X
static void DoSinTable(table)
X
double *table;
X
{
X	int i;
X	double inc;
X	double current;
X
X	inc = M_PI / SIN_TABLE_SIZE;
X	for (i = 0, current = 0.0; i < SIN_TABLE_SIZE; ++i, current += inc)
X	{
X		table[i] = sin(current);
X		if (! (i % 66))
X		{
X			putchar('.');
X			fflush(stdout);
X		}
X	}
}
X
static void BuildParticles(object)
X
object_t *object;
X
{
X	int i;
X	particle_t *p;
X
X	for (i = 0; i < object->part_count; ++i)
X	{
X		p = &object->particles[i];
X		p->y_scale = drand48() * (LINES - 1) * object->y_mag;
X		p->x_scale = drand48() * COLS / 6.0 * object->x_mag;
X		p->x_inc = drand48() * 0.05 + 0.1;
X		p->x = 0.0;
X		p->old_y = 0;
X		p->old_x = 0;
X		p->direction = lrand48() & 1 ? -1 : 1;
X		if (object->pattern->mask & PAT_RAND_SEQ)
X		{
X			p->sequence = lrand48() % object->pat_cycle;
X			p->pattern_inc = -p->direction;
X		}
X		else
X		{
X			p->sequence = 0;
X			p->pattern_inc = 1;
X		}
X		if (object->color == COLOR_MIXED)
X			p->color = RAND_COLOR();
X		else
X			p->color = object->color;
X	}
}
X
static void InitColors()
X
{
#ifdef COLOR_BLACK
X	init_pair(ColorId++, COLOR_RED, COLOR_BLACK);
X	init_pair(ColorId++, COLOR_GREEN, COLOR_BLACK);
X	init_pair(ColorId++, COLOR_YELLOW, COLOR_BLACK);
X	init_pair(ColorId++, COLOR_BLUE, COLOR_BLACK);
X	init_pair(ColorId++, COLOR_MAGENTA, COLOR_BLACK);
X	init_pair(ColorId++, COLOR_CYAN, COLOR_BLACK);
X	init_pair(ColorId, COLOR_WHITE, COLOR_BLACK);
#endif
}
X
SHAR_EOF
chmod 0664 fire.c ||
echo 'restore of fire.c failed'
Wc_c="`wc -c < 'fire.c'`"
test 6631 -eq "$Wc_c" ||
	echo 'fire.c: original size 6631, current size' "$Wc_c"
fi
exit 0
-- 
Stacey Campbell       staceyc at sco.com
{uunet,decwrl,ucscc,att,sq,altos,lotus,phoenix,sun,microsoft,xbs}!sco!staceyc



More information about the Alt.sources mailing list