summaryrefslogtreecommitdiff
path: root/app/xlockmore/modes/bubble.c
diff options
context:
space:
mode:
authorMatthieu Herrb <matthieu@cvs.openbsd.org>2006-11-26 11:09:41 +0000
committerMatthieu Herrb <matthieu@cvs.openbsd.org>2006-11-26 11:09:41 +0000
commit95c2d1cbda23a41cdf6e63520c7f0b825e63dd5b (patch)
tree06d3ffa4312e568c4157f69fe1bddaddec9bc497 /app/xlockmore/modes/bubble.c
parent3928433848e2d6a9356f3d438a14b32a4f87f660 (diff)
Importing xlockmore 5.22
Diffstat (limited to 'app/xlockmore/modes/bubble.c')
-rw-r--r--app/xlockmore/modes/bubble.c312
1 files changed, 312 insertions, 0 deletions
diff --git a/app/xlockmore/modes/bubble.c b/app/xlockmore/modes/bubble.c
new file mode 100644
index 000000000..4107cadf8
--- /dev/null
+++ b/app/xlockmore/modes/bubble.c
@@ -0,0 +1,312 @@
+/* -*- Mode: C; tab-width: 4 -*- */
+/* bubble --- simple exploding bubbles */
+
+#if !defined( lint ) && !defined( SABER )
+static const char sccsid[] = "@(#)bubble.c 5.00 2000/11/01 xlockmore";
+
+#endif
+
+/*-
+ * Copyright (c) 1998 by Charles Vidal <cvidal@ivsweb.com>
+ * http://www.chez.com/vidalc
+ * and David Bagley
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appear in all copies and that
+ * both that copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * This file is provided AS IS with no warranties of any kind. The author
+ * shall have no liability with respect to the infringement of copyrights,
+ * trade secrets or any patents by this file or any part thereof. In no
+ * event will the author be liable for any lost revenue or profits or
+ * other special, indirect and consequential damages.
+ *
+ * Revision History:
+ * 01-Nov-2000: Allocation checks
+ * 10-Jan-1998: Written.
+ */
+
+#ifdef STANDALONE
+#define MODE_bubble
+#define PROGCLASS "Bubble"
+#define HACK_INIT init_bubble
+#define HACK_DRAW draw_bubble
+#define bubble_opts xlockmore_opts
+#define DEFAULTS "*delay: 100000 \n" \
+ "*count: 25 \n" \
+ "*size: 100 \n" \
+ "*ncolors: 200 \n" \
+ "*fullrandom: True \n"
+#define UNIFORM_COLORS
+#include "xlockmore.h" /* in xscreensaver distribution */
+#else /* STANDALONE */
+#include "xlock.h" /* in xlockmore distribution */
+#endif /* STANDALONE */
+
+#ifdef MODE_bubble
+
+#define DEF_BOIL "False"
+static Bool boil;
+
+static XrmOptionDescRec opts[] =
+{
+ {(char *) "-boil", (char *) ".bubble.boil", XrmoptionNoArg, (caddr_t) "on"},
+ {(char *) "+boil", (char *) ".bubble.boil", XrmoptionNoArg, (caddr_t) "off"}
+};
+static argtype vars[] =
+{
+ {(void *) & boil, (char *) "boil", (char *) "Boil", (char *) DEF_BOIL, t_Bool}
+};
+static OptionStruct desc[] =
+{
+ {(char *) "-/+boil", (char *) "turn on/off boil"}
+};
+
+ModeSpecOpt bubble_opts =
+{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
+
+#ifdef USE_MODULES
+ModStruct bubble_description =
+{"bubble", "init_bubble", "draw_bubble", "release_bubble",
+ "refresh_bubble", "init_bubble", (char *) NULL, &bubble_opts,
+ 100000, 25, 1, 100, 64, 0.6, "",
+ "Shows popping bubbles", 0, NULL};
+
+#endif
+
+typedef struct {
+ int x, y, life;
+} bubbletype;
+
+#define MINSIZE 20
+#define MINBUBBLES 1
+
+typedef struct {
+ int direction;
+ int color;
+ int width, height;
+ int nbubbles;
+ Bool boil;
+ bubbletype *bubble;
+ int d;
+ Pixmap dbuf;
+ GC dbuf_gc;
+} bubblestruct;
+
+static bubblestruct *bubbles = (bubblestruct *) NULL;
+
+static void
+updateBubble(ModeInfo * mi, int i)
+{
+ bubblestruct *bp = &bubbles[MI_SCREEN(mi)];
+ int x, diameter, x4, y4, diameter4;
+
+ if (bp->bubble[i].life + 1 > bp->d - NRAND(16) ||
+ bp->bubble[i].y < 0) {
+ bp->bubble[i].life = 0;
+ return;
+ }
+ ++bp->bubble[i].life;
+ diameter = bp->bubble[i].life;
+ x = bp->bubble[i].x;
+ if (bp->boil) {
+ bp->bubble[i].y -= diameter / 2;
+ x += (int) (cos((double) (diameter +
+ bp->bubble[i].x) / (M_PI / 5.0)) * (double) diameter);
+ }
+ /* SunOS 4.1.X xnews server may crash without this */
+ if (diameter < 4) {
+ XFillRectangle(MI_DISPLAY(mi), bp->dbuf, bp->dbuf_gc,
+ x - diameter / 2, bp->bubble[i].y - diameter / 2,
+ diameter, diameter);
+ } else {
+ XDrawArc(MI_DISPLAY(mi), bp->dbuf, bp->dbuf_gc,
+ x - diameter / 2, bp->bubble[i].y - diameter / 2,
+ diameter, diameter, 0, 23040);
+ }
+ diameter4 = diameter / 4;
+ if (diameter4 > 0) {
+ x4 = x - diameter4 / 2 +
+ ((bp->direction / 2) ? (-1) : 1) * diameter / 6;
+ y4 = bp->bubble[i].y - diameter4 / 2 +
+ ((bp->direction % 2) ? 1 : (-1)) * diameter / 6;
+ /* SunOS 4.1.X xnews server may crash without this */
+ if (diameter4 < 4) {
+ XFillRectangle(MI_DISPLAY(mi), bp->dbuf, bp->dbuf_gc,
+ x4, y4, diameter4, diameter4);
+ } else {
+ XFillArc(MI_DISPLAY(mi), bp->dbuf, bp->dbuf_gc,
+ x4, y4, diameter4, diameter4, 0, 23040);
+ }
+ }
+}
+
+static void
+changeBubble(ModeInfo * mi)
+{
+ bubblestruct *bp = &bubbles[MI_SCREEN(mi)];
+ int i;
+
+ for (i = 0; i < bp->nbubbles; i++) {
+ if (bp->bubble[i].life != 0)
+ updateBubble(mi, i);
+ }
+ i = NRAND(bp->nbubbles);
+ if (bp->bubble[i].life == 0) {
+ bp->bubble[i].x = NRAND(bp->width);
+ if (bp->boil)
+ bp->bubble[i].y = bp->height -
+ ((bp->height >= 16) ? NRAND(bp->height / 16) : 0);
+ else
+ bp->bubble[i].y = NRAND(bp->height);
+ updateBubble(mi, i);
+ }
+}
+
+static void
+free_bubble(Display *display, bubblestruct *bp)
+{
+ if (bp->dbuf != None) {
+ XFreePixmap(display, bp->dbuf);
+ bp->dbuf = None;
+ }
+ if (bp->dbuf_gc != None) {
+ XFreeGC(display, bp->dbuf_gc);
+ bp->dbuf_gc = None;
+ }
+ if (bp->bubble != NULL) {
+ free(bp->bubble);
+ bp->bubble = (bubbletype *) NULL;
+ }
+}
+
+void
+init_bubble(ModeInfo * mi)
+{
+ bubblestruct *bp;
+ int size = MI_SIZE(mi);
+ Display *display = MI_DISPLAY(mi);
+ Window window = MI_WINDOW(mi);
+ XGCValues gcv;
+
+ if (bubbles == NULL) {
+ if ((bubbles = (bubblestruct *) calloc(MI_NUM_SCREENS(mi),
+ sizeof (bubblestruct))) == NULL)
+ return;
+ }
+ bp = &bubbles[MI_SCREEN(mi)];
+
+ bp->width = MI_WIDTH(mi);
+ bp->height = MI_HEIGHT(mi);
+ bp->direction = NRAND(4);
+ if (MI_IS_FULLRANDOM(mi))
+ bp->boil = (Bool) (LRAND() & 1);
+ else
+ bp->boil = boil;
+
+ if (size < -MINSIZE)
+ bp->d = NRAND(MIN(-size, MAX(MINSIZE,
+ MIN(bp->width, bp->height) / 2)) - MINSIZE + 1) + MINSIZE;
+ else if (size < MINSIZE) {
+ if (!size)
+ bp->d = MAX(MINSIZE, MIN(bp->width, bp->height) / 2);
+ else
+ bp->d = MINSIZE;
+ } else
+ bp->d = MIN(size, MAX(MINSIZE,
+ MIN(bp->width, bp->height) / 2));
+ bp->nbubbles = MI_COUNT(mi);
+ if (bp->nbubbles < -MINBUBBLES) {
+ bp->nbubbles = NRAND(-bp->nbubbles - MINBUBBLES + 1) + MINBUBBLES;
+ } else if (bp->nbubbles < MINBUBBLES)
+ bp->nbubbles = MINBUBBLES;
+ if (bp->bubble != NULL)
+ free(bp->bubble);
+ if ((bp->bubble = (bubbletype *) calloc(bp->nbubbles,
+ sizeof (bubbletype))) == NULL) {
+ free_bubble(display, bp);
+ return;
+ }
+ if (MI_NPIXELS(mi) > 2)
+ bp->color = NRAND(MI_NPIXELS(mi));
+
+ if (bp->dbuf != None)
+ XFreePixmap(display, bp->dbuf);
+ if ((bp->dbuf = XCreatePixmap(display, window, bp->width, bp->height,
+ 1)) == None) {
+ free_bubble(display, bp);
+ return;
+ }
+ /* Do not want any exposure events from XCopyPlane */
+ XSetGraphicsExposures(display, MI_GC(mi), False);
+
+ gcv.foreground = 1;
+ gcv.background = 0;
+ gcv.function = GXcopy;
+ gcv.graphics_exposures = False;
+ gcv.line_width = 2;
+ if (bp->dbuf_gc)
+ XFreeGC(display, bp->dbuf_gc);
+ if ((bp->dbuf_gc = XCreateGC(display, bp->dbuf,
+ GCForeground | GCBackground | GCLineWidth | GCFunction,
+ &gcv)) == None) {
+ free_bubble(display, bp);
+ return;
+ }
+ MI_CLEARWINDOW(mi);
+}
+
+void
+draw_bubble(ModeInfo * mi)
+{
+ Display *display = MI_DISPLAY(mi);
+ Window window = MI_WINDOW(mi);
+ GC gc = MI_GC(mi);
+ bubblestruct *bp;
+
+ if (bubbles == NULL)
+ return;
+ bp = &bubbles[MI_SCREEN(mi)];
+ if (bp->bubble == NULL)
+ return;
+
+ MI_IS_DRAWN(mi) = True;
+ if (MI_NPIXELS(mi) <= 2)
+ XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
+ else {
+ bp->color = (bp->color + 1) % MI_NPIXELS(mi);
+ XSetForeground(display, gc, MI_PIXEL(mi, bp->color));
+ }
+ if (bp->dbuf) {
+ XSetForeground(display, bp->dbuf_gc, 0);
+ XFillRectangle(display, bp->dbuf, bp->dbuf_gc,
+ 0, 0, bp->width, bp->height);
+ XSetForeground(display, bp->dbuf_gc, 1);
+ changeBubble(mi);
+ XCopyPlane(display, bp->dbuf, window, gc,
+ 0, 0, bp->width, bp->height, 0, 0, 1);
+ }
+}
+
+void
+release_bubble(ModeInfo * mi)
+{
+ if (bubbles != NULL) {
+ int screen;
+
+ for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
+ free_bubble(MI_DISPLAY(mi), &bubbles[screen]);
+ free(bubbles);
+ bubbles = (bubblestruct *) NULL;
+ }
+}
+
+void
+refresh_bubble(ModeInfo * mi)
+{
+ /* Do nothing, it will refresh by itself */
+}
+
+#endif /* MODE_bubble */