1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* laser --- spinning lasers */
4 #if !defined( lint ) && !defined( SABER )
5 static const char sccsid[] = "@(#)laser.c 5.00 2000/11/01 xlockmore";
10 * Copyright (c) 1995 Pascal Pensa <pensa@aurora.unice.fr>
12 * Permission to use, copy, modify, and distribute this software and its
13 * documentation for any purpose and without fee is hereby granted,
14 * provided that the above copyright notice appear in all copies and that
15 * both that copyright notice and this permission notice appear in
16 * supporting documentation.
18 * This file is provided AS IS with no warranties of any kind. The author
19 * shall have no liability with respect to the infringement of copyrights,
20 * trade secrets or any patents by this file or any part thereof. In no
21 * event will the author be liable for any lost revenue or profits or
22 * other special, indirect and consequential damages.
25 * 01-Nov-2000: Allocation checks
26 * 10-May-1997: Compatible with xscreensaver
32 #define PROGCLASS "Laser"
33 #define HACK_INIT init_laser
34 #define HACK_DRAW draw_laser
35 #define laser_opts xlockmore_opts
36 #define DEFAULTS "*delay: 40000 \n" \
41 #include "xlockmore.h" /* in xscreensaver distribution */
42 #else /* STANDALONE */
43 #include "xlock.h" /* in xlockmore distribution */
44 #endif /* STANDALONE */
48 ModeSpecOpt laser_opts =
49 {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
52 ModStruct laser_description =
53 {"laser", "init_laser", "draw_laser", "release_laser",
54 "refresh_laser", "init_laser", (char *) NULL, &laser_opts,
55 20000, -10, 200, 1, 64, 1.0, "",
56 "Shows spinning lasers", 0, NULL};
60 #define MINREDRAW 3 /* Number of redrawn on each frame */
63 #define MINLASER 1 /* Laser number */
65 #define MINWIDTH 2 /* Laser ray width range */
68 #define MINSPEED 2 /* Speed range */
71 #define MINDIST 10 /* Minimal distance from edges */
73 #define COLORSTEP 2 /* Laser color step */
75 #define RANGE_RAND(min,max) (int) ((min) + LRAND() % ((max) - (min)))
78 TOP, RIGHT, BOTTOM, LEFT
82 int bx; /* border x */
83 int by; /* border y */
84 border bn; /* active border */
85 int dir; /* direction */
86 int speed; /* laser velocity from MINSPEED to MAXSPEED */
87 int sx[MAXWIDTH]; /* x stack */
88 int sy[MAXWIDTH]; /* x stack */
89 XGCValues gcv; /* for color */
95 int cx; /* center x */
96 int cy; /* center y */
97 int lw; /* laser width */
98 int ln; /* laser number */
99 int lr; /* laser redraw */
100 int sw; /* stack width */
101 int so; /* stack offset */
102 int time; /* up time */
104 XGCValues gcv_black; /* for black color */
108 static lasersstruct *lasers = (lasersstruct *) NULL;
111 free_laser(Display *display, lasersstruct *lp)
113 if (lp->laser != NULL) {
114 (void) free((void *) lp->laser);
115 lp->laser = (laserstruct *) NULL;
117 if (lp->stippledGC != None) {
118 XFreeGC(display, lp->stippledGC);
119 lp->stippledGC = None;
124 init_laser(ModeInfo * mi)
126 Display *display = MI_DISPLAY(mi);
130 if (lasers == NULL) {
131 if ((lasers = (lasersstruct *) calloc(MI_NUM_SCREENS(mi),
132 sizeof (lasersstruct))) == NULL)
135 lp = &lasers[MI_SCREEN(mi)];
137 lp->width = MI_WIDTH(mi);
138 lp->height = MI_HEIGHT(mi);
141 lp->ln = MI_COUNT(mi);
142 if (lp->ln < -MINLASER) {
143 /* if lp->ln is random ... the size can change */
144 if (lp->laser != NULL) {
145 (void) free((void *) lp->laser);
146 lp->laser = (laserstruct *) NULL;
148 lp->ln = NRAND(-lp->ln - MINLASER + 1) + MINLASER;
149 } else if (lp->ln < MINLASER)
152 if (lp->laser == NULL) {
153 if ((lp->laser = (laserstruct *) malloc(lp->ln *
154 sizeof (laserstruct))) == NULL) {
155 free_laser(display, lp);
159 if (lp->stippledGC == None) {
162 gcv.foreground = MI_WHITE_PIXEL(mi);
163 gcv.background = MI_BLACK_PIXEL(mi);
164 lp->gcv_black.foreground = MI_BLACK_PIXEL(mi);
165 if ((lp->stippledGC = XCreateGC(display, MI_WINDOW(mi),
166 GCForeground | GCBackground, &gcv)) == None) {
167 free_laser(display, lp);
173 if (MINDIST < lp->width - MINDIST)
174 lp->cx = RANGE_RAND(MINDIST, lp->width - MINDIST);
176 lp->cx = RANGE_RAND(0, lp->width);
177 if (MINDIST < lp->height - MINDIST)
178 lp->cy = RANGE_RAND(MINDIST, lp->height - MINDIST);
180 lp->cy = RANGE_RAND(0, lp->height);
181 lp->lw = RANGE_RAND(MINWIDTH, MAXWIDTH);
182 lp->lr = RANGE_RAND(MINREDRAW, MAXREDRAW);
186 if (MI_NPIXELS(mi) > 2)
187 c = NRAND(MI_NPIXELS(mi));
189 for (i = 0; i < lp->ln; i++) {
190 laserstruct *l = &lp->laser[i];
192 l->bn = (border) NRAND(4);
196 l->bx = NRAND(lp->width);
201 l->by = NRAND(lp->height);
204 l->bx = NRAND(lp->width);
209 l->by = NRAND(lp->height);
212 l->dir = (int) (LRAND() & 1);
213 l->speed = ((RANGE_RAND(MINSPEED, MAXSPEED) * lp->width) / 1000) + 1;
214 if (MI_NPIXELS(mi) > 2) {
215 l->gcv.foreground = MI_PIXEL(mi, c);
216 c = (c + COLORSTEP) % MI_NPIXELS(mi);
218 l->gcv.foreground = MI_WHITE_PIXEL(mi);
223 draw_laser_once(ModeInfo * mi)
225 Display *display = MI_DISPLAY(mi);
226 lasersstruct *lp = &lasers[MI_SCREEN(mi)];
229 for (i = 0; i < lp->ln; i++) {
230 laserstruct *l = &lp->laser[i];
232 if (lp->sw >= lp->lw) {
233 XChangeGC(display, lp->stippledGC, GCForeground, &(lp->gcv_black));
234 XDrawLine(display, MI_WINDOW(mi), lp->stippledGC,
236 l->sx[lp->so], l->sy[lp->so]);
251 l->bx = lp->width + l->by;
258 if (l->bx >= lp->width) {
259 l->by = lp->height - l->bx % lp->width;
266 if (l->by >= lp->height) {
267 l->bx = l->by % lp->height;
276 if (l->bx >= lp->width) {
277 l->by = l->bx % lp->width;
284 if (l->by >= lp->height) {
285 l->bx = lp->width - l->by % lp->height;
293 l->by = lp->height + l->bx;
308 XChangeGC(display, lp->stippledGC, GCForeground, &l->gcv);
309 XDrawLine(display, MI_WINDOW(mi), lp->stippledGC,
310 lp->cx, lp->cy, l->bx, l->by);
312 l->sx[lp->so] = l->bx;
313 l->sy[lp->so] = l->by;
320 lp->so = (lp->so + 1) % lp->lw;
324 draw_laser(ModeInfo * mi)
331 lp = &lasers[MI_SCREEN(mi)];
332 if (lp->laser == NULL)
335 MI_IS_DRAWN(mi) = True;
336 for (i = 0; i < lp->lr; i++)
339 if (++lp->time > MI_CYCLES(mi))
344 release_laser(ModeInfo * mi)
346 if (lasers != NULL) {
349 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
350 free_laser(MI_DISPLAY(mi), &lasers[screen]);
351 (void) free((void *) lasers);
352 lasers = (lasersstruct *) NULL;
357 refresh_laser(ModeInfo * mi)
362 #endif /* MODE_laser */