[comp.windows.x] seasonal demo follows

rick@hanauma (Richard Ottolini) (12/20/89)

/*
display Hanukkah Menorah

options:
-display DISPLAY	display
-size 0.2		size fraction
-bg blue		background color (monochrome black)
-candle red		menorah color (monochrome white)
-flame yellow		flame color (monochrome white)
-ncandle 8		number of candles
-flicker -noflicker	flame flicker

interactivity:
clicking candle ignites or douses flame;
exposure and resize.
*/
/*
compile: cc hanu.c -lX11
wakes up once a second to flicker and process events
*/
#include <stdio.h>
#include <X11/Xlib.h>

/* x window definitions and globals */
#define	SIZE	0.2
#define	TITLE	"HANUKKAH GREETINGS!"
Display	*display;
int screen;
int depth;
int width;
int height;
Colormap colormap;
Window window;
GC gc;
char back_color[30] = "blue";
int back_pixel;

/* candle definitions and globals */
#define NCANDLE	8
int ncandle = NCANDLE;
char candle_color[30] = "red";
int candle_pixel;

/* flame definitions and globals */
#define	FLAME_OFF	0
#define	FLAME_ON	1
#define	FLAME1		1
#define	FLAME2		2
char flame_color[30] = "yellow";
int flame_pixel;
int flame_state[20];
int flicker = 1;

main (argc,argv)
int argc;
char **argv;
	{
	GetparInit (argc,argv);
	Init ();
	Loop ();
	}

/* initialize x windows */
Init ()
	{
	char display_name[80];
	float size = SIZE;
	XColor color1, color2;

	if (Getpar ("display","s",display_name) == 0) {
		strcpy (display_name,getenv("DISPLAY"));
		}
	if ((display = XOpenDisplay (display_name)) == NULL) {
		err ("cant open display");
		}
	screen = DefaultScreen (display);
	depth = DefaultDepth (display,screen);
	colormap = XDefaultColormap (display,screen);
	if (depth == 1) {  /* monochrome */
		back_pixel = BlackPixel (display,screen);
		candle_pixel = WhitePixel (display,screen);
		flame_pixel = WhitePixel (display,screen);
		}
	else	{
		Getpar ("bg","s",back_color);
		XAllocNamedColor (display,colormap,back_color,&color1,&color2);
		back_pixel = color1.pixel;
		Getpar ("candle","s",candle_color);
		XAllocNamedColor (display,colormap,candle_color,&color1,&color2);
		candle_pixel = color1.pixel;
		Getpar ("flame","s",candle_color);
		XAllocNamedColor (display,colormap,flame_color,&color1,&color2);
		flame_pixel = color1.pixel;
		}
	Getpar ("size","f",&size);
	width = DisplayWidth (display,screen) * size;
	height = DisplayHeight (display,screen) * size;
	window = XCreateSimpleWindow (display,RootWindow(display,screen),
		0,0,width,height,
		1,WhitePixel(display,screen),back_pixel);
	gc = XCreateGC (display,window,0,0);
	XStoreName (display,window,TITLE);
	XSelectInput (display,window,VisibilityChangeMask|StructureNotifyMask|ButtonPressMask);
	XMapWindow (display,window);
	Getpar ("ncandle","d",&ncandle);
	if (Getpar ("flicker","0",&flicker)) flicker = 1;
	if (Getpar ("noflicker","0",&flicker)) flicker = 0;
	printf ("Click to ignite flame\n");
	XFlush (display);
	}

Loop ()
	{
	int i;
	static XEvent event;

	while (1) {
		while (XPending(display)) {
			XNextEvent (display,&event);
			switch (event.type) {
			/* resize */
			case ConfigureNotify:
				if (width == event.xconfigure.width &&
				    height == event.xconfigure.height) break;
				width = event.xconfigure.width;
				height = event.xconfigure.height;
			case VisibilityNotify:
				DrawCandle ();
				for (i=0; i<ncandle; i++) DrawFlame (i);
				break;
			/* ignite or douse flame */
			case ButtonPress:
				i = (event.xbutton.x*ncandle) / width;
				if (flame_state[i] != FLAME_OFF) {
					flame_state[i] = FLAME_OFF;
					}
				else	{
					flame_state[i] = FLAME_ON;
					}
				DrawFlame (i);
				break;
				}
			}
		/* flicker */
		if (flicker) {
			for (i=0; i<ncandle; i++) {
				if (flame_state[i] != FLAME_OFF) DrawFlame (i);
				}
			}
		/* decrease load */
		sleep (1);
		}
	}

DrawCandle ()
	{
	int i;
	XClearWindow (display,window);
	XSetForeground (display,gc,candle_pixel);
	/* stalks */
	for (i=0; i<ncandle; i++) {
		XFillRectangle (display,window,gc,
			(int)((i+.5)*width/(ncandle+.5)),
			(int)(height*0.2),
			(int)(width/((ncandle+.5)*2)),
			(int)(height*0.4));
		}
	/* base */
	XFillRectangle (display,window,gc,
		(int)(.5*width/(ncandle+.5)),
		(int)(height*0.6)-1,
		(int)(width*(1.-1./(ncandle+.5))),
		(int)(height*0.1));
	XFillRectangle (display,window,gc,
		(int)((ncandle*.5)*width/(ncandle+.5)),
		(int)(height*0.7)-2,
			(int)(width/((ncandle+.5)*2)),
		(int)(height*0.2));
	XFlush (display);
	}

DrawFlame (i)
int i;
	{
	switch (flame_state[i]) {
	/* erase */
	case FLAME_OFF:
		XSetForeground (display,gc,back_pixel);
		XFillRectangle (display,window,gc,
			(int)((i+.5)*width/(ncandle+.5)),
			(int)(height*0.03),
			(int)(width/((ncandle+.5)*2)),
			(int)(height*0.15));
		break;
	/* draw large */
	case FLAME1:
		XSetForeground (display,gc,flame_pixel);
		XFillRectangle (display,window,gc,
			(int)((i+.5)*width/(ncandle+.5)),
			(int)(height*0.03),
			(int)(width/((ncandle+.5)*2)),
			(int)(height*0.15));
		 if (flicker) flame_state[i] = FLAME2;
		break;
	/* shrink */
	case FLAME2:
		XSetForeground (display,gc,back_pixel);
		XFillRectangle (display,window,gc,
			(int)((i+.5)*width/(ncandle+.5)),
			(int)(height*0.03),
			(int)(width/((ncandle+.5)*2)),
			(int)(height*0.05));
		flame_state[i] = FLAME1;
		break;
		}
	}

err (message)
char *message;
	{
	printf ("%s\n",message);
	exit (-1);
	}

/* getpar routines */

int xargc;
char **xargv;

GetparInit (argc,argv)
int argc;
char **argv;
	{
	xargc = argc;
	xargv = argv;
	}

Getpar (key,type,value)
char *key, *type;
union {int *i; float *f; char *s;} value;
	{
	int iarg, status;
	double atof();

	status = 0;
	for (iarg=1; iarg<xargc; iarg++) if (xargv[iarg][0] == '-' &&
		!strcmp (xargv[iarg]+1,key)) {
		switch (type[0]) {
		case 'd':
			*value.i = atoi (xargv[++iarg]);
			status = 1;
			break;
		case 'f':
			*value.f = atof (xargv[++iarg]);
			status = 1;
			break;
		case 's':
			strcpy (value.s,xargv[++iarg]);
			status = 1;
			break;
		case '0':
			status = 1;
			break;
		case '1':
			iarg++;
			if (xargv[iarg][0] == '1' || xargv[iarg][0] == 'y') *value.i = 1;
			if (xargv[iarg][0] == '0' || xargv[iarg][0] == 'n') *value.i = 0;
			status = 1;
			break;
			}
		}
	return (status);
	}

jonnyg@umd5.umd.edu (Jon Greenblatt) (12/21/89)

In article <6591@lindy.Stanford.EDU> rick@hanauma (Richard Ottolini) writes:
>/*
>display Hanukkah Menorah

	I think this patch speaks for itself!

				JonnyG.


*** hanuka.c.bak        Wed Dec 20 12:18:06 1989
--- hanuka.c    Wed Dec 20 12:32:11 1989
***************
*** 36,39 ****
  int back_pixel;

  /* candle definitions and globals */
! #define NCANDLE       8
--- 36,39 ----
  int back_pixel;

  /* candle definitions and globals */
! #define NCANDLE       9

lou@atanasoff.rutgers.edu (Lou Steinberg) (12/27/89)

Cute!  I revised the program to add a shamash (an additional "servant"
candle, usually placed higher than the others).  Here are diffs:

*** hanu.c.ORIG	Tue Dec 26 15:39:42 1989
--- hanu.c.NEW	Tue Dec 26 15:40:01 1989
***************
*** 37,41 ****
  
  /* candle definitions and globals */
! #define NCANDLE	8
  int ncandle = NCANDLE;
  char candle_color[30] = "red";
--- 37,42 ----
  
  /* candle definitions and globals */
! #define NCANDLE	9
! #define SHAMASH 4		/* which candle is shamash - 0 is leftmost */
  int ncandle = NCANDLE;
  char candle_color[30] = "red";
***************
*** 153,156 ****
--- 154,163 ----
  	}
  
+ int shoff (i)			/* if candle i is shamash, extra height for */
+ int i;				/* shamash,  else 0 */
+ {
+   return ( (i == SHAMASH ? (height*.1) : 0) );
+ }
+ 	  
  DrawCandle ()
  	{
***************
*** 162,168 ****
  		XFillRectangle (display,window,gc,
  			(int)((i+.5)*width/(ncandle+.5)),
! 			(int)(height*0.2),
  			(int)(width/((ncandle+.5)*2)),
! 			(int)(height*0.4));
  		}
  	/* base */
--- 169,175 ----
  		XFillRectangle (display,window,gc,
  			(int)((i+.5)*width/(ncandle+.5)),
! 			(int)(height*0.3-shoff(i)),
  			(int)(width/((ncandle+.5)*2)),
! 			(int)(height*0.4)+shoff(i));
  		}
  	/* base */
***************
*** 169,173 ****
  	XFillRectangle (display,window,gc,
  		(int)(.5*width/(ncandle+.5)),
! 		(int)(height*0.6)-1,
  		(int)(width*(1.-1./(ncandle+.5))),
  		(int)(height*0.1));
--- 176,180 ----
  	XFillRectangle (display,window,gc,
  		(int)(.5*width/(ncandle+.5)),
! 		(int)(height*0.7)-1,
  		(int)(width*(1.-1./(ncandle+.5))),
  		(int)(height*0.1));
***************
*** 174,180 ****
  	XFillRectangle (display,window,gc,
  		(int)((ncandle*.5)*width/(ncandle+.5)),
! 		(int)(height*0.7)-2,
  			(int)(width/((ncandle+.5)*2)),
! 		(int)(height*0.2));
  	XFlush (display);
  	}
--- 181,187 ----
  	XFillRectangle (display,window,gc,
  		(int)((ncandle*.5)*width/(ncandle+.5)),
! 		(int)(height*0.8)-2,
  			(int)(width/((ncandle+.5)*2)),
! 		(int)(height*0.18));
  	XFlush (display);
  	}
***************
*** 189,193 ****
  		XFillRectangle (display,window,gc,
  			(int)((i+.5)*width/(ncandle+.5)),
! 			(int)(height*0.03),
  			(int)(width/((ncandle+.5)*2)),
  			(int)(height*0.15));
--- 196,200 ----
  		XFillRectangle (display,window,gc,
  			(int)((i+.5)*width/(ncandle+.5)),
! 			(int)(height*0.13-shoff(i)),
  			(int)(width/((ncandle+.5)*2)),
  			(int)(height*0.15));
***************
*** 198,202 ****
  		XFillRectangle (display,window,gc,
  			(int)((i+.5)*width/(ncandle+.5)),
! 			(int)(height*0.03),
  			(int)(width/((ncandle+.5)*2)),
  			(int)(height*0.15));
--- 205,209 ----
  		XFillRectangle (display,window,gc,
  			(int)((i+.5)*width/(ncandle+.5)),
! 			(int)(height*0.13-shoff(i)),
  			(int)(width/((ncandle+.5)*2)),
  			(int)(height*0.15));
***************
*** 208,212 ****
  		XFillRectangle (display,window,gc,
  			(int)((i+.5)*width/(ncandle+.5)),
! 			(int)(height*0.03),
  			(int)(width/((ncandle+.5)*2)),
  			(int)(height*0.05));
--- 215,219 ----
  		XFillRectangle (display,window,gc,
  			(int)((i+.5)*width/(ncandle+.5)),
! 			(int)(height*0.13-shoff(i)),
  			(int)(width/((ncandle+.5)*2)),
  			(int)(height*0.05));
-- 
					Lou Steinberg

uucp:   {pretty much any major site}!rutgers!aramis.rutgers.edu!lou 
arpa:   lou@cs.rutgers.edu