summaryrefslogtreecommitdiff
path: root/app/xlockmore/modes/tube.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/tube.c
parent3928433848e2d6a9356f3d438a14b32a4f87f660 (diff)
Importing xlockmore 5.22
Diffstat (limited to 'app/xlockmore/modes/tube.c')
-rw-r--r--app/xlockmore/modes/tube.c476
1 files changed, 476 insertions, 0 deletions
diff --git a/app/xlockmore/modes/tube.c b/app/xlockmore/modes/tube.c
new file mode 100644
index 000000000..1a03a1ac1
--- /dev/null
+++ b/app/xlockmore/modes/tube.c
@@ -0,0 +1,476 @@
+/* -*- Mode: C; tab-width: 4 -*- */
+/* tube --- animated tube */
+
+#if !defined( lint ) && !defined( SABER )
+static const char sccsid[] = "@(#)tube.c 5.09 2003/06/30 xlockmore";
+
+#endif
+
+/*-
+ * Copyright (c) 1997 Dan Stromberg <strombrg@nis.acs.uci.edu>
+ *
+ * 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:
+ * 30-Jun-2003: Changed writeable mode to be more consistent with
+ * xscreensaver's starfish
+ * 01-Nov-2000: Allocation checks
+ * 10-May-1997: Compatible with xscreensaver
+ * 04-Mar-1997: Memory leak fix by Tom Schmidt <tschmidt@micron.com>
+ * 07-Feb-1997: Written by Dan Stromberg <strombrg@nis.acs.uci.edu>
+ */
+
+
+#ifdef STANDALONE
+#define MODE_tube
+#define PROGCLASS "Tube"
+#define HACK_INIT init_tube
+#define HACK_DRAW draw_tube
+#define tube_opts xlockmore_opts
+#define DEFAULTS "*delay: 25000 \n" \
+ "*cycles: 20000 \n" \
+ "*size: -200 \n" \
+ "*ncolors: 200 \n"
+#define SMOOTH_COLORS
+#define WRITABLE_COLORS
+#include "xlockmore.h" /* from the xscreensaver distribution */
+#else /* !STANDALONE */
+#include "xlock.h" /* from the xlockmore distribution */
+#include "color.h"
+#endif /* !STANDALONE */
+
+#ifdef MODE_tube
+
+#define DEF_CYCLE "True"
+
+static Bool cycle_p;
+
+static XrmOptionDescRec opts[] =
+{
+ {(char *) "-cycle", (char *) ".tube.cycle", XrmoptionNoArg, (caddr_t) "on"},
+ {(char *) "+cycle", (char *) ".tube.cycle", XrmoptionNoArg, (caddr_t) "off"}
+};
+
+static argtype vars[] =
+{
+ {(void *) & cycle_p, (char *) "cycle", (char *) "Cycle", (char *) DEF_CYCLE, t_Bool}
+};
+static OptionStruct desc[] =
+{
+ {(char *) "-/+cycle", (char *) "turn on/off colour cycling"}
+};
+
+ModeSpecOpt tube_opts =
+{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
+
+#ifdef USE_MODULES
+ModStruct tube_description =
+{"tube", "init_tube", "draw_tube", "release_tube",
+ NULL, "init_tube", (char *) NULL, &tube_opts,
+ 25000, -9, 20000, -200, 64, 1.0, "",
+ "Shows an animated tube", 0, NULL};
+
+#endif
+
+#define MINSIZE 3
+#define MINSHAPE 1
+
+typedef struct {
+ int dx1, dy1;
+ int x1, y1;
+ int width, height, average, linewidth;
+ int shape;
+ XPoint *pts, *proto_pts;
+ unsigned int cur_color;
+ GC gc;
+ Colormap cmap;
+ unsigned long blackpixel, whitepixel, fg, bg;
+ int direction;
+ XColor *colors;
+ int counter;
+ int ncolors;
+ Bool cycle_p, mono_p, no_colors, reverse;
+ ModeInfo *mi;
+} tubestruct;
+
+static tubestruct *tubes = (tubestruct *) NULL;
+
+static void
+free_pts(tubestruct *tp)
+{
+ if (tp->pts != NULL) {
+ free(tp->pts);
+ tp->pts = (XPoint *) NULL;
+ }
+ if (tp->proto_pts != NULL) {
+ free(tp->proto_pts);
+ tp->proto_pts = (XPoint *) NULL;
+ }
+}
+
+static void
+free_tube(Display *display, tubestruct *tp)
+{
+ ModeInfo *mi = tp->mi;
+
+ free_pts(tp);
+
+ if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
+ MI_WHITE_PIXEL(mi) = tp->whitepixel;
+ MI_BLACK_PIXEL(mi) = tp->blackpixel;
+#ifndef STANDALONE
+ MI_FG_PIXEL(mi) = tp->fg;
+ MI_BG_PIXEL(mi) = tp->bg;
+#endif
+ if (tp->colors != NULL) {
+ if (tp->ncolors && !tp->no_colors)
+ free_colors(display, tp->cmap, tp->colors, tp->ncolors);
+ free(tp->colors);
+ tp->colors = (XColor *) NULL;
+ }
+ if (tp->cmap != None) {
+ XFreeColormap(display, tp->cmap);
+ tp->cmap = None;
+ }
+ }
+ if (tp->gc != None) {
+ XFreeGC(display, tp->gc);
+ tp->gc = None;
+ }
+}
+
+#ifndef STANDALONE
+extern char *background;
+extern char *foreground;
+#endif
+
+void
+init_tube(ModeInfo * mi)
+{
+ Display *display = MI_DISPLAY(mi);
+ Window window = MI_WINDOW(mi);
+ int screen_width, screen_height;
+ int size = MI_SIZE(mi);
+ int star = 1, lw;
+ tubestruct *tp;
+
+ if (tubes == NULL) {
+ if ((tubes = (tubestruct *) calloc(MI_NUM_SCREENS(mi),
+ sizeof (tubestruct))) == NULL)
+ return;
+ }
+ tp = &tubes[MI_SCREEN(mi)];
+ tp->mi = mi;
+
+ screen_width = MI_WIDTH(mi);
+ screen_height = MI_HEIGHT(mi);
+
+ if (size < -MINSIZE) {
+ tp->width = NRAND(MIN(-size, MAX(MINSIZE, screen_width / 2)) -
+ MINSIZE + 1) + MINSIZE;
+ tp->height = NRAND(MIN(-size, MAX(MINSIZE, screen_height / 2)) -
+ MINSIZE + 1) + MINSIZE;
+ } else if (size < MINSIZE) {
+ if (!size) {
+ tp->width = MAX(MINSIZE, screen_width / 2);
+ tp->height = MAX(MINSIZE, screen_height / 2);
+ } else {
+ tp->width = MINSIZE;
+ tp->height = MINSIZE;
+ }
+ } else {
+ tp->width = MIN(size, MAX(MINSIZE, screen_width / 2));
+ tp->height = MIN(size, MAX(MINSIZE, screen_height / 2));
+ }
+ tp->average = (tp->width + tp->height) / 2;
+ tp->reverse = (Bool) (LRAND() & 1);
+ tp->dx1 = LRAND() & 1;
+ if (tp->dx1 == 0)
+ tp->dx1 = -1;
+ tp->dy1 = LRAND() & 1;
+ if (tp->dy1 == 0)
+ tp->dy1 = -1;
+ free_pts(tp);
+ tp->shape = MI_COUNT(mi);
+ if (tp->shape < -MINSHAPE) {
+ tp->shape = NRAND(-tp->shape - MINSHAPE + 1) + MINSHAPE;
+ } else if (tp->shape < MINSHAPE)
+ tp->shape = MINSHAPE;
+
+ if (tp->shape >= 3) {
+ int i;
+ float start;
+
+ tp->width = tp->height = tp->average;
+ if (((tp->pts = (XPoint *) malloc((tp->shape + 1) *
+ sizeof (XPoint))) == NULL) ||
+ ((tp->proto_pts = (XPoint *) malloc((tp->shape + 1) *
+ sizeof (XPoint))) == NULL)) {
+ free_tube(display, tp);
+ return;
+ }
+ start = (float) NRAND(360);
+ do {
+ star = NRAND(tp->shape / 2) + 1; /* Not always a star but thats ok. */
+ } while ((star != 1) && (!(tp->shape % star)));
+ for (i = 0; i < tp->shape; i++) {
+ tp->proto_pts[i].x = tp->average / 2 +
+ (int) (cos((double) start * 2.0 * M_PI / 360.0) * tp->average / 2.0);
+ tp->proto_pts[i].y = tp->average / 2 +
+ (int) (sin((double) start * 2.0 * M_PI / 360.0) * tp->average / 2.0);
+ start += star * 360 / tp->shape;
+ }
+ tp->proto_pts[tp->shape] = tp->proto_pts[0];
+ }
+ tp->linewidth = NRAND(tp->average / 6 + 1) + 1;
+ if (star > 1) /* Make the width less */
+ tp->linewidth = NRAND(tp->linewidth / 2 + 1) + 1;
+ lw = tp->linewidth / 2;
+ tp->x1 = NRAND(screen_width - tp->width - 2 * lw) + lw;
+ tp->y1 = NRAND(screen_height - tp->height - 2 * lw) + lw;
+
+ tp->counter = 0;
+
+ if (!tp->gc) {
+ if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
+ XColor color;
+
+#ifndef STANDALONE
+ tp->fg = MI_FG_PIXEL(mi);
+ tp->bg = MI_BG_PIXEL(mi);
+#endif
+ tp->blackpixel = MI_BLACK_PIXEL(mi);
+ tp->whitepixel = MI_WHITE_PIXEL(mi);
+ if ((tp->cmap = XCreateColormap(display, window,
+ MI_VISUAL(mi), AllocNone)) == None) {
+ free_tube(display, tp);
+ return;
+ }
+ XSetWindowColormap(display, window, tp->cmap);
+ (void) XParseColor(display, tp->cmap, "black", &color);
+ (void) XAllocColor(display, tp->cmap, &color);
+ MI_BLACK_PIXEL(mi) = color.pixel;
+ (void) XParseColor(display, tp->cmap, "white", &color);
+ (void) XAllocColor(display, tp->cmap, &color);
+ MI_WHITE_PIXEL(mi) = color.pixel;
+#ifndef STANDALONE
+ (void) XParseColor(display, tp->cmap, background, &color);
+ (void) XAllocColor(display, tp->cmap, &color);
+ MI_BG_PIXEL(mi) = color.pixel;
+ (void) XParseColor(display, tp->cmap, foreground, &color);
+ (void) XAllocColor(display, tp->cmap, &color);
+ MI_FG_PIXEL(mi) = color.pixel;
+#endif
+ tp->colors = (XColor *) NULL;
+ tp->ncolors = 0;
+ }
+ if ((tp->gc = XCreateGC(display, MI_WINDOW(mi),
+ (unsigned long) 0, (XGCValues *) NULL)) == None) {
+ free_tube(display, tp);
+ return;
+ }
+ }
+ MI_CLEARWINDOW(mi);
+
+ /* Set up colour map */
+ tp->direction = (LRAND() & 1) ? 1 : -1;
+ if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
+ if (tp->colors != NULL) {
+ if (tp->ncolors && !tp->no_colors)
+ free_colors(display, tp->cmap, tp->colors, tp->ncolors);
+ free(tp->colors);
+ tp->colors = (XColor *) NULL;
+ }
+ tp->ncolors = MI_NCOLORS(mi);
+ if (tp->ncolors < 2)
+ tp->ncolors = 2;
+ if (tp->ncolors <= 2)
+ tp->mono_p = True;
+ else
+ tp->mono_p = False;
+
+ if (tp->mono_p)
+ tp->colors = (XColor *) NULL;
+ else
+ if ((tp->colors = (XColor *) malloc(sizeof (*tp->colors) *
+ (tp->ncolors + 1))) == NULL) {
+ free_tube(display, tp);
+ return;
+ }
+ tp->cycle_p = has_writable_cells(mi);
+ if (tp->cycle_p) {
+ if (MI_IS_FULLRANDOM(mi)) {
+ if (!NRAND(8))
+ tp->cycle_p = False;
+ else
+ tp->cycle_p = True;
+ } else {
+ tp->cycle_p = cycle_p;
+ }
+ }
+ if (!tp->mono_p) {
+ if (!(LRAND() % 10))
+ make_random_colormap(
+#if STANDALONE
+ display, MI_WINDOW(mi),
+#else
+ mi,
+#endif
+ tp->cmap, tp->colors, &tp->ncolors,
+ True, True, &tp->cycle_p);
+ else if (!(LRAND() % 2))
+ make_uniform_colormap(
+#if STANDALONE
+ display, MI_WINDOW(mi),
+#else
+ mi,
+#endif
+ tp->cmap, tp->colors, &tp->ncolors,
+ True, &tp->cycle_p);
+ else
+ make_smooth_colormap(
+#if STANDALONE
+ display, MI_WINDOW(mi),
+#else
+ mi,
+#endif
+ tp->cmap, tp->colors, &tp->ncolors,
+ True, &tp->cycle_p);
+ }
+ XInstallColormap(display, tp->cmap);
+ if (tp->ncolors < 2) {
+ tp->ncolors = 2;
+ tp->no_colors = True;
+ } else
+ tp->no_colors = False;
+ if (tp->ncolors <= 2)
+ tp->mono_p = True;
+
+ if (tp->mono_p)
+ tp->cycle_p = False;
+
+ }
+ if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
+ if (tp->mono_p) {
+ tp->cur_color = MI_BLACK_PIXEL(mi);
+ }
+ }
+}
+
+void
+draw_tube(ModeInfo * mi)
+{
+ Display *display = MI_DISPLAY(mi);
+ Window window = MI_WINDOW(mi);
+ unsigned int i;
+ int lw;
+ tubestruct *tp;
+
+ if (tubes == NULL)
+ return;
+ tp = &tubes[MI_SCREEN(mi)];
+
+ if (tp->no_colors) {
+ init_tube(mi);
+ return;
+ }
+ if (tp->shape >= 3 && tp->pts == NULL)
+ return;
+
+ MI_IS_DRAWN(mi) = True;
+ lw = tp->linewidth / 2;
+
+ if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
+ if (tp->mono_p) {
+ XSetForeground(display, tp->gc, tp->cur_color);
+ } else {
+ tp->cur_color = (tp->cur_color + 1) % tp->ncolors;
+ XSetForeground(display, tp->gc, tp->colors[tp->cur_color].pixel);
+ }
+ } else {
+ if (MI_NPIXELS(mi) > 2)
+ XSetForeground(display, tp->gc, MI_PIXEL(mi, tp->cur_color));
+ else if (tp->cur_color)
+ XSetForeground(display, tp->gc, MI_BLACK_PIXEL(mi));
+ else
+ XSetForeground(display, tp->gc, MI_WHITE_PIXEL(mi));
+ if (++tp->cur_color >= (unsigned int) MI_NPIXELS(mi))
+ tp->cur_color = 0;
+ }
+
+ /* Rotate colours */
+ if (tp->cycle_p) {
+ rotate_colors(display, tp->cmap, tp->colors, tp->ncolors,
+ tp->direction);
+ if (!(LRAND() % 1000))
+ tp->direction = -tp->direction;
+ }
+
+ /* move rectangle forward, horiz */
+ tp->x1 += tp->dx1;
+ if (tp->x1 < lw) {
+ tp->x1 = lw;
+ tp->dx1 = -tp->dx1;
+ }
+ if (tp->x1 + tp->width + lw >= MI_WIDTH(mi)) {
+ tp->x1 = MI_WIDTH(mi) - tp->width - 1 - lw;
+ tp->dx1 = -tp->dx1;
+ }
+ /* move rectange forward, vert */
+ tp->y1 += tp->dy1;
+ if (tp->y1 < lw) {
+ tp->y1 = lw;
+ tp->dy1 = -tp->dy1;
+ }
+ if (tp->y1 + tp->height + lw >= MI_HEIGHT(mi)) {
+ tp->y1 = MI_HEIGHT(mi) - tp->height - 1 - lw;
+ tp->dy1 = -tp->dy1;
+ }
+ XSetLineAttributes(display, tp->gc, tp->linewidth + (tp->shape >= 2),
+ LineSolid, CapNotLast, JoinRound);
+ if (tp->shape < 2)
+ XDrawRectangle(display, window, tp->gc,
+ tp->x1, tp->y1, tp->width, tp->height);
+ else if (tp->shape == 2)
+ XDrawArc(display, window, tp->gc,
+ tp->x1, tp->y1, tp->width, tp->height, 0, 23040);
+ else {
+ for (i = 0; i <= (unsigned int) tp->shape; i++) {
+ tp->pts[i].x = tp->x1 + tp->proto_pts[i].x;
+ tp->pts[i].y = tp->y1 + tp->proto_pts[i].y;
+ }
+ XDrawLines(display, window, tp->gc, tp->pts, tp->shape + 1,
+ CoordModeOrigin);
+ }
+ XSetLineAttributes(display, tp->gc, 1, LineSolid, CapNotLast, JoinRound);
+
+ tp->counter++;
+ if (tp->counter > MI_CYCLES(mi)) {
+ init_tube(mi);
+ }
+}
+
+void
+release_tube(ModeInfo * mi)
+{
+ if (tubes != NULL) {
+ int screen;
+
+ for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
+ free_tube(MI_DISPLAY(mi), &tubes[screen]);
+ free(tubes);
+ tubes = (tubestruct *) NULL;
+ }
+}
+
+#endif /* MODE_tube */