diff options
author | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2006-11-26 11:09:41 +0000 |
---|---|---|
committer | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2006-11-26 11:09:41 +0000 |
commit | 95c2d1cbda23a41cdf6e63520c7f0b825e63dd5b (patch) | |
tree | 06d3ffa4312e568c4157f69fe1bddaddec9bc497 /app/xlockmore/modes/tube.c | |
parent | 3928433848e2d6a9356f3d438a14b32a4f87f660 (diff) |
Importing xlockmore 5.22
Diffstat (limited to 'app/xlockmore/modes/tube.c')
-rw-r--r-- | app/xlockmore/modes/tube.c | 476 |
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 */ |