1 /*****************************************************************************/
2 /* XBlood Copyright (c) 1998-2000 Sakai Hiroaki.                             */
3 /* All Rights Reserved.                                                      */
4 /*===========================================================================*/
5 /* This program is free software; you can redistribute it and/or modify      */
6 /* it under the terms of the GNU General Public License as published by      */
7 /* the Free Software Foundation; either version 2, or (at your option)       */
8 /* any later version.                                                        */
9 /*****************************************************************************/
10 
11 /*****************************************************************************/
12 /* Include Header Files                                                      */
13 /*****************************************************************************/
14 
15 #include<stdio.h>
16 #include<stdlib.h>
17 #include<time.h>
18 #include<X11/Xlib.h>
19 
20 /*****************************************************************************/
21 /* Difinitions of Some Parameters                                            */
22 /*****************************************************************************/
23 
24 #define ON  1
25 #define OFF 0
26 
27 #define DEFAULT_NUMBER 30
28 #define DEFAULT_SIZE   20
29 #define DEFAULT_SPEED 100
30 
31 #define DEFAULT_SCATTER_NUMBER 150
32 #define DEFAULT_SCATTER_RADIUS 200
33 #define DEFAULT_SCATTER_SIZE    60
34 
35 #define DEFAULT_COLOR "red"
36 #define DEFAULT_STAY_FLAG OFF
37 #define DEFAULT_QUIT_FLAG OFF
38 #define DEFAULT_WAIT 10000
39 
40 typedef struct XBlood {
41   Display * display;
42   int screen;
43   Colormap colormap;
44   int width, height;
45   Window root_window;
46   char * display_name;
47   GC gc;
48 } XBlood;
49 
50 typedef struct Blood {
51   int number, size, speed_max;
52   int scatter_number, scatter_radius, scatter_size;
53   char * color;
54   int stay_flag, quit_flag;
55   int wait;
56   XArc * point;
57   int  * speed;
58   int  * count;
59   int depth;
60 } Blood;
61 
62 static char * help_string =
63 "\n" VERSION " Sakai Hiroaki\n\n"
64 "XBlood fills the root window with blood.\n"
65 "Red, blue or green bloody window is very bad taste!\n"
66 "\n"
67 "-display [displayname] The name of the X server to use.\n"
68 "-h, -help              Output help message.\n"
69 "-stay, -noflow         Blood stays the bottom of the root window.\n"
70 "-nostay, -flow         Blood flows down through the root window. (Default)\n"
71 "-quit                  Draw blood and quit.\n"
72 "-noquit                Draw blood and they flow. (Default)\n"
73 "-number [x]            The number of bloody drops. (30)\n"
74 "-size [x]              The maximum size of bloody drops\' width. (20)\n"
75 "-speed [x]             The speed of droping. (100)\n"
76 "-scatter-number [x]    The maximum number of scatters. (150)\n"
77 "-scatter-radius [x]    The maximum radius of scatters. (200)\n"
78 "-scatter-size [x]      The maximum size of scatters. (60)\n"
79 "-color [color]         Bloody drops\' color. (red)\n"
80 "-wait [x]              Wait time. (10000)\n"
81 "\n";
82 
83 /*****************************************************************************/
84 /* Definitions of Functions                                                  */
85 /*****************************************************************************/
86 
SetDefaultValue(XBlood * xbp,Blood * bp)87 void SetDefaultValue(XBlood * xbp, Blood * bp)
88 {
89   xbp->display_name  = NULL;
90   bp->number         = DEFAULT_NUMBER;
91   bp->size           = DEFAULT_SIZE;
92   bp->speed_max      = DEFAULT_SPEED;
93   bp->scatter_number = DEFAULT_SCATTER_NUMBER;
94   bp->scatter_radius = DEFAULT_SCATTER_RADIUS;
95   bp->scatter_size   = DEFAULT_SCATTER_SIZE;
96   bp->color          = DEFAULT_COLOR;
97   bp->stay_flag      = DEFAULT_STAY_FLAG;
98   bp->quit_flag      = DEFAULT_QUIT_FLAG;
99   bp->wait           = DEFAULT_WAIT;
100   bp->depth          = 0;
101 }
102 
Help()103 void Help()
104 {
105   printf("%s", help_string);
106   exit (0);
107 }
108 
ReadParameter(XBlood * xbp,Blood * bp,int ac,char ** av)109 void ReadParameter(XBlood * xbp, Blood * bp, int ac, char ** av)
110 {
111   int i;
112   for (i = 0; i < ac; i++) {
113     if      (!strcmp(av[i], "-h"     )) Help();
114     else if (!strcmp(av[i], "-help"  )) Help();
115     else if (!strcmp(av[i], "-stay"  )) bp->stay_flag = ON;
116     else if (!strcmp(av[i], "-nostay")) bp->stay_flag = OFF;
117     else if (!strcmp(av[i], "-flow"  )) bp->stay_flag = OFF;
118     else if (!strcmp(av[i], "-noflow")) bp->stay_flag = ON;
119     else if (!strcmp(av[i], "-quit"  )) bp->quit_flag = ON;
120     else if (!strcmp(av[i], "-noquit")) bp->quit_flag = OFF;
121     if (i < ac - 1) {
122       if      (!strcmp(av[i],"-display")) xbp->display_name =      av[++i];
123       else if (!strcmp(av[i],"-number" )) bp->number        = atoi(av[++i]);
124       else if (!strcmp(av[i],"-size"   )) bp->size          = atoi(av[++i]);
125       else if (!strcmp(av[i],"-speed"  )) bp->speed_max     = atoi(av[++i]);
126       else if (!strcmp(av[i],"-scatter-number"))
127 	bp->scatter_number = atoi(av[++i]);
128       else if (!strcmp(av[i],"-scatter-radius"))
129 	bp->scatter_radius = atoi(av[++i]);
130       else if (!strcmp(av[i],"-scatter-size"))
131 	bp->scatter_size   = atoi(av[++i]);
132       else if (!strcmp(av[i],"-color"  )) bp->color         =      av[++i];
133       else if (!strcmp(av[i],"-wait"   )) bp->wait          = atoi(av[++i]);
134     }
135   }
136 }
137 
InitializeDisplay(XBlood * xbp)138 void InitializeDisplay(XBlood * xbp)
139 {
140   xbp->display     = XOpenDisplay(xbp->display_name);
141   xbp->screen      = DefaultScreen(xbp->display);
142   xbp->colormap    = DefaultColormap(xbp->display, xbp->screen);
143   xbp->width       = DisplayWidth( xbp->display, xbp->screen);
144   xbp->height      = DisplayHeight(xbp->display, xbp->screen);
145   xbp->root_window = RootWindow(xbp->display, xbp->screen);
146 }
147 
RandomValue(int n)148 int RandomValue(int n)
149 {
150   return ((rand() / 256) % n);
151 }
152 
MakeBlood(XBlood * xbp,Blood * bp,int i)153 void MakeBlood(XBlood * xbp, Blood * bp, int i)
154 {
155   int n, num, w, r, d;
156   int x0, y0, x, y;
157 
158   bp->point[i].width  = RandomValue(bp->size) + 2;
159   bp->point[i].height = bp->point[i].width * 2;
160   bp->point[i].x = RandomValue(xbp->width) - bp->point[i].width / 2;
161   bp->point[i].y = RandomValue(xbp->height + 100) - bp->depth - 100;
162   bp->point[i].angle1 = 0;
163   bp->point[i].angle2 = 360 * 64;
164   bp->speed[i] = RandomValue(bp->speed_max) + 1;
165   bp->count[i] = 0;
166 
167   w = bp->point[i].width * (RandomValue(4) + 5) / 4;
168   x0 = bp->point[i].x - (w - bp->point[i].width) / 2;
169   y0 = bp->point[i].y;
170   XFillArc(xbp->display, xbp->root_window, xbp->gc, x0, y0, w, w, 0, 360 * 64);
171 
172   num = RandomValue(bp->scatter_number);
173   for (n = 0; n < num; n++) {
174     r = RandomValue(bp->point[i].width * bp->scatter_size / 100) + 1;
175     x = x0 + w / 2 - r / 2
176       + RandomValue(bp->point[i].width * bp->scatter_radius / 100)
177       - RandomValue(bp->point[i].width * bp->scatter_radius / 100);
178     y = y0 + w / 2 - r / 2
179       + RandomValue(bp->point[i].width * bp->scatter_radius / 100)
180       - RandomValue(bp->point[i].width * bp->scatter_radius / 100);
181     XFillArc(xbp->display, xbp->root_window, xbp->gc,
182 	     x, y, r, r, 0, 360 * 64);
183   }
184 }
185 
GetColor(XBlood * xbp,char * color)186 unsigned long int GetColor(XBlood * xbp, char * color)
187 {
188   XColor c0, c1;
189   XAllocNamedColor(xbp->display, xbp->colormap, color, &c0, &c1);
190   return (c0.pixel);
191 }
192 
InitializeBlood(XBlood * xbp,Blood * bp)193 void InitializeBlood(XBlood * xbp, Blood * bp)
194 {
195   int i;
196   srand((unsigned)time(NULL));
197   bp->point = (XArc *)malloc(sizeof(XArc) * bp->number);
198   bp->speed = (int  *)malloc(sizeof(int ) * bp->number);
199   bp->count = (int  *)malloc(sizeof(int ) * bp->number);
200   xbp->gc = XCreateGC(xbp->display, xbp->root_window, 0, 0);
201   XSetForeground(xbp->display, xbp->gc, GetColor(xbp, bp->color));
202   XSetArcMode(xbp->display, xbp->gc, ArcPieSlice);
203   for (i = 0; i < bp->number; i++) MakeBlood(xbp, bp, i);
204 }
205 
BloodMain(XBlood * xbp,Blood * bp)206 void BloodMain(XBlood * xbp, Blood * bp)
207 {
208   int i, j;
209 
210   if (bp->quit_flag) return;
211   while (bp->depth < xbp->height) {
212     XFillArcs(xbp->display, xbp->root_window, xbp->gc, bp->point, bp->number);
213     for (j = 0; j < bp->number; j++) {
214       bp->count[j] += bp->speed[j];
215       while (bp->count[j] >= 200) {
216 	bp->count[j] -= 200;
217 	(bp->point[j].y)++;
218       }
219       if (bp->point[j].y >= xbp->height - bp->depth) {
220 	if (bp->stay_flag == ON) {
221 	  (bp->depth)++;
222 	  XFillRectangle(xbp->display, xbp->root_window, xbp->gc,
223 			 0, xbp->height - bp->depth, xbp->width, bp->depth);
224 	}
225 	MakeBlood(xbp, bp, j);
226       }
227     }
228     XFlush(xbp->display);
229     usleep(bp->wait);
230   }
231 }
232 
BloodQuit(XBlood * xbp,Blood * bp)233 void BloodQuit(XBlood * xbp, Blood * bp)
234 {
235   free(bp->point);
236   free(bp->speed);
237   free(bp->count);
238   XCloseDisplay(xbp->display);
239   exit (0);
240 }
241 
main(int argc,char ** argv)242 main(int argc, char ** argv)
243 {
244   XBlood xblood;
245   Blood blood;
246 
247   SetDefaultValue(&xblood, &blood);
248   ReadParameter(&xblood, &blood, argc, argv);
249   InitializeDisplay(&xblood);
250   InitializeBlood(&xblood, &blood);
251   BloodMain(&xblood, &blood);
252   BloodQuit(&xblood, &blood);
253 }
254 
255 /*****************************************************************************/
256 /* End of XBlood                                                             */
257 /*****************************************************************************/
258