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