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