xenocara/app/xlockmore/modes/toneclock.c
2006-11-26 11:07:42 +00:00

824 lines
24 KiB
C

/* -*- Mode: C; tab-width: 4 -*- */
/* toneclock --- Screenhack inspired by Peter Schat's toneclock
*/
#if !defined( lint ) && !defined( SABER )
static const char sccsid[] = "@(#)toneclock.c 5.00 2004/09/16 xlockmore";
#endif
/*-
* Copyright (c) 2004 by Jouk Jansen <joukj@hrem.stm.tudelft.nl>
*
* 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.
*
* The author should like to be notified if changes have been made to the
* routine. Response will only be guaranteed when a VMS version of the
* program is available.
*
* Toneclock. Peter Schat (1937-2003) was a Dutch composer. Het invented
* the toneclock, a garphical representation of the tonesystem.
*
* Revision History:
* 20-Dec-2004: Initial release
* 23-Dec-2004: -size determines size of the clock
* -original ignores all options and displays original clock
* -pulsate make the clock pulsating
* 24-Dec-2004: -fill num
* polygon filling chance implemented
* 04-Jan-2005: -move allow moving for small clocks
* 16-Feb-2005: -Number of hours according to "count" option
* -Random polygons
*
*/
#if 0
#define NO_DBUF
#endif
#ifdef STANDALONE
#define MODE_toneclock
#define PROGCLASS "toneclock"
#define HACK_INIT init_toneclock
#define HACK_DRAW draw_toneclock
#define toneclock_opts xlockmore_opts
#define DEFAULTS "*delay: 60000 \n" \
"*count: -20 \n" \
"*cycles: 200 \n" \
"*size: -1000 \n" \
"*ncolors: 64 \n" \
"*fullrandom: True \n" \
"*verbose: False \n"
#include "xlockmore.h" /* in xscreensaver distribution */
#else /* STANDALONE */
#include "xlock.h" /* in xlockmore distribution */
#include "color.h"
#endif /* STANDALONE */
#ifdef MODE_toneclock
#define DEF_NUM_hour 12
#define DEF_CYCLE "True"
#define DEF_ORIGINAL "False"
#define DEF_PULSATING "False"
#define DEF_MOVE "True"
#define DEF_FILL "0"
static Bool cycle_p , original , pulsating , move_clock;
static int fill;
static XrmOptionDescRec opts[] =
{
{(char *) "-fill", (char *) "tomecloc.fill", XrmoptionSepArg, (caddr_t) NULL},
{(char *) "-cycle", (char *) ".toneclock.cycle", XrmoptionNoArg, (caddr_t) "on"},
{(char *) "+cycle", (char *) ".toneclock.cycle", XrmoptionNoArg, (caddr_t) "off"},
{(char *) "-original", (char *) ".toneclock.original", XrmoptionNoArg, (caddr_t) "on"},
{(char *) "+original", (char *) ".toneclock.original", XrmoptionNoArg, (caddr_t) "off"},
{(char *) "-move", (char *) ".toneclock.move", XrmoptionNoArg, (caddr_t) "on"},
{(char *) "+move", (char *) ".toneclock.move", XrmoptionNoArg, (caddr_t) "off"},
{(char *) "-pulsating", (char *) ".toneclock.pulsating", XrmoptionNoArg, (caddr_t) "on"},
{(char *) "+pulsating", (char *) ".toneclock.pulsating", XrmoptionNoArg, (caddr_t) "off"}
};
static argtype vars[] =
{
{(void *) & fill, (char *) "fill", (char *) "Fill", (char *) DEF_FILL, t_Int},
{(void *) & cycle_p, (char *) "cycle", (char *) "Cycle", (char *) DEF_CYCLE, t_Bool},
{(void *) & original, (char *) "original", (char *) "Original", (char *) DEF_ORIGINAL, t_Bool},
{(void *) & move_clock, (char *) "move", (char *) "Move", (char *) DEF_MOVE, t_Bool},
{(void *) & pulsating, (char *) "pulsating", (char *) "Pulsating", (char *) DEF_PULSATING, t_Bool}
};
static OptionStruct desc[] =
{
{(char *) "-fill num", (char *) "polygon filling chance in %"},
{(char *) "-/+cycle", (char *) "turn on/off colour cycling"},
{(char *) "-/+original", (char *) "turn on/off displaying original clock only"},
{(char *) "-/+move", (char *) "turn on/off moving small clocks"},
{(char *) "-/+pulsating", (char *) "turn on/off pulsating clock"}
};
ModeSpecOpt toneclock_opts =
{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
#ifdef USE_MODULES
ModStruct toneclock_description =
{"toneclock", "init_toneclock", "draw_toneclock", "release_toneclock",
"refresh_toneclock", "init_toneclock", (char *) NULL, &toneclock_opts,
60000, -20, 200, -1000, 64, 1.0, "",
"Shows Peter Schat's toneclock", 0, NULL};
#endif
#define PI_RAD (M_PI / 180.0)
typedef struct {
unsigned long colour;
float angle, velocity , radius;
int num_point , num_point1;
int* point_numbers;
Bool draw;
} toneclockhour;
typedef struct {
ModeInfo *mi;
Pixmap dbuf;
GC dbuf_gc;
GC gc;
Colormap cmap;
XColor *colors;
Bool painted;
int win_width, win_height, num_hour, x0, y0 , fill;
float angle , velocity , radius , phase , ph_vel;
float vx , vy , anglex , angley , max_radius;
int a_x , a_y;
int ncolors;
Bool cycle_p, mono_p, no_colors, original, pulsating , moving;
Bool randomhour;
unsigned long blackpixel, whitepixel, fg, bg;
int direction;
int hexadecimal_clock[512];
toneclockhour *hour;
} toneclockstruct;
static int original_clock[12][16] = {
{ 1 , 1 , 5 , 9 , 2 , 2 , 6 , 10 , 3 , 3 , 7 , 11 , 4 , 4 , 8 , 12 } ,
{ 1 , 1 , 2 , 3 , 4 , 4 , 5 , 6 , 7 , 7 , 8 , 9 , 10 , 10 , 11 , 12 } ,
{ 1 , 1 , 2 , 4 , 3 , 3 , 5 , 6 , 7 , 7 , 8 , 10 , 9 , 9 , 11 , 12 } ,
{ 1 , 1 , 2 , 5 , 3 , 3 , 4 , 7 , 6 , 6 , 9 , 10 , 8 , 8 , 11 , 12 } ,
{ 1 , 1 , 2 , 6 , 3 , 3 , 4 , 8 , 5 , 5 , 9 , 10 , 7 , 7 , 11 , 12 } ,
{ 1 , 1 , 2 , 7 , 3 , 3 , 8 , 9 , 4 , 4 , 5 , 10 , 6 , 6 , 11 , 12 } ,
{ 1 , 1 , 3 , 5 , 2 , 2 , 10 , 12 , 4 , 4 , 6 , 8 , 7 , 7 , 9 , 11 } ,
{ 1 , 1 , 3 , 6 , 2 , 2 , 4 , 11 , 5 , 5 , 8 , 10 , 7 , 7 , 9 , 12 } ,
{ 1 , 1 , 3 , 7 , 2 , 2 , 4 , 8 , 5 , 5 , 10 , 11 , 6 , 6 , 10 , 12 } ,
{ 1 , 1 , 3 , 8 , 2 , 2 , 7 , 9 , 4 , 4 , 6 , 11 , 5 , 5 , 10 , 12 } ,
{ 1 , 4 , 7 , 10 , 2 , 5 , 8 , 11 , 3 , 6 , 9 , 12 , 1 , 1 , 1 , 1 } ,
{ 1 , 1 , 4 , 8 , 2 , 2 , 7 , 11 , 3 , 3 , 6 , 10 , 5 , 5 , 9 , 12 }
};
static toneclockstruct *toneclocks = (toneclockstruct *) NULL;
static void
toneclock_drawhour(ModeInfo * mi, toneclockhour * hour0 ,
int x0 , int y0 )
{
Display *display = MI_DISPLAY(mi);
toneclockstruct *tclock;
int i;
#ifdef NO_DBUF
Window drawable = MI_WINDOW(mi);
#else
#define drawable (Drawable) tclock->dbuf
#endif
tclock = &toneclocks[MI_SCREEN(mi)];
for (i = 0; i < hour0->num_point1; i = i + 4)
{
int x , y , x1 , y1 , x2 , y2 , x3 , y3;
x = (int) (hour0->radius * sin( hour0->angle + PI_RAD *
hour0->point_numbers[ i ] * 360.0 /
hour0->num_point ) ) + x0;
y = (int) (hour0->radius * cos( hour0->angle + PI_RAD *
hour0->point_numbers[ i ] * 360.0 /
hour0->num_point ) ) + y0;
x1 = (int) (hour0->radius * sin( hour0->angle + PI_RAD *
hour0->point_numbers[ i + 1 ] * 360.0 /
hour0->num_point ) ) + x0;
y1 = (int) (hour0->radius * cos( hour0->angle + PI_RAD *
hour0->point_numbers[ i + 1 ] * 360.0 /
hour0->num_point ) ) + y0;
x2 = (int) (hour0->radius * sin( hour0->angle + PI_RAD *
hour0->point_numbers[ i + 2 ] * 360.0 /
hour0->num_point ) ) + x0;
y2 = (int) (hour0->radius * cos( hour0->angle + PI_RAD *
hour0->point_numbers[ i + 2 ] * 360.0 /
hour0->num_point ) ) + y0;
x3 = (int) (hour0->radius * sin( hour0->angle + PI_RAD *
hour0->point_numbers[ i + 3 ] * 360.0 /
hour0->num_point ) ) + x0;
y3 = (int) (hour0->radius * cos( hour0->angle + PI_RAD *
hour0->point_numbers[ i + 3 ] * 360.0 /
hour0->num_point ) ) + y0;
if ( hour0->draw )
{
XDrawLine(display, drawable, tclock->gc, x , y , x1 , y1 );
XDrawLine(display, drawable, tclock->gc, x1 , y1 , x2 , y2 );
XDrawLine(display, drawable, tclock->gc, x2 , y2 , x3 , y3 );
XDrawLine(display, drawable, tclock->gc, x , y , x3 , y3 );
}
else
{
XPoint xy[4];
xy[0].x = x;
xy[0].y = y;
xy[1].x = x1;
xy[1].y = y1;
xy[2].x = x2;
xy[2].y = y2;
xy[3].x = x3;
xy[3].y = y3;
XFillPolygon(display, drawable, tclock->gc, xy, 4 , Convex,
CoordModeOrigin);
}
}
}
static void
free_hour(toneclockstruct *tclock)
{
if (tclock->hour != NULL) {
free(tclock->hour);
tclock->hour = (toneclockhour *) NULL;
}
}
static void
free_toneclock(Display *display, toneclockstruct *tclock)
{
ModeInfo *mi = tclock->mi;
if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
MI_WHITE_PIXEL(mi) = tclock->whitepixel;
MI_BLACK_PIXEL(mi) = tclock->blackpixel;
#ifndef STANDALONE
MI_FG_PIXEL(mi) = tclock->fg;
MI_BG_PIXEL(mi) = tclock->bg;
#endif
if (tclock->colors != NULL) {
if (tclock->ncolors && !tclock->no_colors)
free_colors(display, tclock->cmap, tclock->colors, tclock->ncolors);
free(tclock->colors);
tclock->colors = (XColor *) NULL;
}
if (tclock->cmap != None) {
XFreeColormap(display, tclock->cmap);
tclock->cmap = None;
}
}
if (tclock->gc != None) {
XFreeGC(display, tclock->gc);
tclock->gc = None;
}
free_hour(tclock);
#ifndef NO_DBUF
if (tclock->dbuf != None) {
XFreePixmap(display, tclock->dbuf);
tclock->dbuf = None;
}
if (tclock->dbuf_gc != None) {
XFreeGC(display, tclock->dbuf_gc);
tclock->dbuf_gc = None;
}
#endif
}
#ifndef STANDALONE
extern char *background;
extern char *foreground;
#endif
void
init_toneclock(ModeInfo * mi)
{
Display *display = MI_DISPLAY(mi);
Window window = MI_WINDOW(mi);
int i, size_hour, istart;
toneclockstruct *tclock;
/* initialize */
if (toneclocks == NULL) {
if ((toneclocks = (toneclockstruct *) calloc(MI_NUM_SCREENS(mi),
sizeof (toneclockstruct))) == NULL)
return;
}
tclock = &toneclocks[MI_SCREEN(mi)];
tclock->mi = mi;
if (tclock->gc == None) {
if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
XColor color;
#ifndef STANDALONE
tclock->fg = MI_FG_PIXEL(mi);
tclock->bg = MI_BG_PIXEL(mi);
#endif
tclock->blackpixel = MI_BLACK_PIXEL(mi);
tclock->whitepixel = MI_WHITE_PIXEL(mi);
if ((tclock->cmap = XCreateColormap(display, window,
MI_VISUAL(mi), AllocNone)) == None) {
free_toneclock(display, tclock);
return;
}
XSetWindowColormap(display, window, tclock->cmap);
(void) XParseColor(display, tclock->cmap, "black", &color);
(void) XAllocColor(display, tclock->cmap, &color);
MI_BLACK_PIXEL(mi) = color.pixel;
(void) XParseColor(display, tclock->cmap, "white", &color);
(void) XAllocColor(display, tclock->cmap, &color);
MI_WHITE_PIXEL(mi) = color.pixel;
#ifndef STANDALONE
(void) XParseColor(display, tclock->cmap, background, &color);
(void) XAllocColor(display, tclock->cmap, &color);
MI_BG_PIXEL(mi) = color.pixel;
(void) XParseColor(display, tclock->cmap, foreground, &color);
(void) XAllocColor(display, tclock->cmap, &color);
MI_FG_PIXEL(mi) = color.pixel;
#endif
tclock->colors = (XColor *) NULL;
tclock->ncolors = 0;
}
if ((tclock->gc = XCreateGC(display, MI_WINDOW(mi),
(unsigned long) 0, (XGCValues *) NULL)) == None) {
free_toneclock(display, tclock);
return;
}
}
/* Clear Display */
MI_CLEARWINDOW(mi);
tclock->painted = False;
XSetFunction(display, tclock->gc, GXxor);
/*Set up toneclock data */
if (MI_IS_FULLRANDOM(mi)) {
if (NRAND(10))
tclock->original = False;
else
tclock->original = True;
} else {
tclock->original = original;
}
tclock->direction = (LRAND() & 1) ? 1 : -1;
tclock->win_width = MI_WIDTH(mi);
tclock->win_height = MI_HEIGHT(mi);
if (tclock->hour != NULL)
free_hour(tclock);
if ( tclock->original )
{
tclock->num_hour = 12;
}
else
{
tclock->num_hour = MI_COUNT(mi);
}
tclock->x0 = tclock->win_width / 2;
tclock->y0 = tclock->win_height / 2;
if (tclock->num_hour == 0) {
tclock->num_hour = DEF_NUM_hour;
} else if (tclock->num_hour < 0) {
tclock->num_hour = NRAND(-tclock->num_hour) + 1;
}
if ( tclock->num_hour < 12 )
istart = NRAND( 12 - tclock->num_hour );
else
istart = 0;
if ((tclock->hour = (toneclockhour *) calloc(tclock->num_hour,
sizeof (toneclockhour))) == NULL) {
free_toneclock(display, tclock);
return;
}
if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
/* Set up colour map */
if (tclock->colors != NULL) {
if (tclock->ncolors && !tclock->no_colors)
free_colors(display, tclock->cmap, tclock->colors, tclock->ncolors);
free(tclock->colors);
tclock->colors = (XColor *) NULL;
}
tclock->ncolors = MI_NCOLORS(mi);
if (tclock->ncolors < 2)
tclock->ncolors = 2;
if (tclock->ncolors <= 2)
tclock->mono_p = True;
else
tclock->mono_p = False;
if (tclock->mono_p)
tclock->colors = (XColor *) NULL;
else
if ((tclock->colors = (XColor *) malloc(sizeof (*tclock->colors) *
(tclock->ncolors + 1))) == NULL) {
free_toneclock(display, tclock);
return;
}
tclock->cycle_p = has_writable_cells(mi);
if (tclock->cycle_p) {
if (MI_IS_FULLRANDOM(mi)) {
if (!NRAND(8))
tclock->cycle_p = False;
else
tclock->cycle_p = True;
} else {
tclock->cycle_p = cycle_p;
}
}
if (!tclock->mono_p) {
if (!(LRAND() % 10))
make_random_colormap(
#ifdef STANDALONE
MI_DISPLAY(mi), MI_WINDOW(mi),
#else
mi,
#endif
tclock->cmap, tclock->colors, &tclock->ncolors,
True, True, &tclock->cycle_p);
else if (!(LRAND() % 2))
make_uniform_colormap(
#ifdef STANDALONE
MI_DISPLAY(mi), MI_WINDOW(mi),
#else
mi,
#endif
tclock->cmap, tclock->colors, &tclock->ncolors,
True, &tclock->cycle_p);
else
make_smooth_colormap(
#ifdef STANDALONE
MI_DISPLAY(mi), MI_WINDOW(mi),
#else
mi,
#endif
tclock->cmap, tclock->colors, &tclock->ncolors,
True, &tclock->cycle_p);
}
XInstallColormap(display, tclock->cmap);
if (tclock->ncolors < 2) {
tclock->ncolors = 2;
tclock->no_colors = True;
} else
tclock->no_colors = False;
if (tclock->ncolors <= 2)
tclock->mono_p = True;
if (tclock->mono_p)
tclock->cycle_p = False;
}
#ifndef NO_DBUF
if (tclock->dbuf != None)
XFreePixmap(display, tclock->dbuf);
tclock->dbuf = XCreatePixmap(display, window,
tclock->win_width,
tclock->win_height,
MI_DEPTH(mi));
/* Allocation checked */
if (tclock->dbuf != None) {
XGCValues gcv;
gcv.foreground = 0;
gcv.background = 0;
gcv.graphics_exposures = False;
gcv.function = GXcopy;
if (tclock->dbuf_gc != None)
XFreeGC(display, tclock->dbuf_gc);
if ((tclock->dbuf_gc = XCreateGC(display, (Drawable) tclock->dbuf,
GCForeground | GCBackground | GCGraphicsExposures | GCFunction,
&gcv)) == None) {
XFreePixmap(display, tclock->dbuf);
tclock->dbuf = None;
} else {
XFillRectangle(display, (Drawable) tclock->dbuf, tclock->dbuf_gc,
0, 0, tclock->win_width, tclock->win_height);
XSetBackground(display, MI_GC(mi), MI_BLACK_PIXEL(mi));
XSetFunction(display, MI_GC(mi), GXcopy);
}
}
#endif
tclock->angle = NRAND(360) * PI_RAD;
tclock->velocity = (NRAND(7) - 3) * PI_RAD;
size_hour = MIN( tclock->win_width , tclock->win_height) / 3;
tclock->pulsating = False;
tclock->moving = False;
tclock->anglex = 0.0;
tclock->angley = 0.0;
tclock->fill = 0;
tclock->radius = size_hour;
tclock->max_radius =0.0;
if ( ( !tclock->original && NRAND( 15 ) == 3 ) || tclock->num_hour > 12 )
tclock->randomhour = True;
else
tclock->randomhour = False;
if ( !tclock->original && tclock->win_width > 20 )
{
if ( abs( MI_SIZE(mi) ) > size_hour ) {
if ( MI_SIZE( mi ) < 0 )
{
size_hour = -size_hour;
}
}
else
{
size_hour = MI_SIZE(mi);
}
if ( size_hour < 0 )
{
tclock->radius = MIN(NRAND( size_hour - 10) + 10,
tclock->radius );
}
else
{
tclock->radius = MIN( size_hour , tclock->radius );
}
if ( MI_IS_FULLRANDOM( mi ) )
{
if ( NRAND(2) )
tclock->pulsating = True;
else
tclock->pulsating = False;
tclock->fill = NRAND( 101 );
}
else
{
tclock->pulsating = pulsating;
tclock->fill = fill;
}
}
tclock->phase = 0.0;
if ( tclock->pulsating )
tclock->ph_vel = (NRAND(7) - 3) * PI_RAD;
for (i = 0; i < tclock->num_hour; i++) {
toneclockhour *hour0;
hour0 = &tclock->hour[i];
if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
if (tclock->ncolors > 2)
hour0->colour = NRAND(tclock->ncolors - 2) + 2;
else
hour0->colour = 1; /* Just in case */
XSetForeground(display, tclock->gc, tclock->colors[hour0->colour].pixel);
} else {
if (MI_NPIXELS(mi) > 2)
hour0->colour = MI_PIXEL(mi, NRAND(MI_NPIXELS(mi)));
else
hour0->colour = 1; /*Xor'red so WHITE may not be appropriate */
XSetForeground(display, tclock->gc, hour0->colour);
}
hour0->angle = NRAND(360) * PI_RAD;
hour0->velocity = (NRAND(7) - 3) * PI_RAD;
hour0->radius = tclock->radius / 5.0;
tclock->max_radius = MAX( tclock->max_radius , hour0->radius );
hour0->num_point = 12;
hour0->num_point1 = 16;
if ( tclock->randomhour )
{
int j;
hour0->point_numbers = tclock->hexadecimal_clock + i *
hour0->num_point1;
if ( NRAND( 14 ) == 4 )
{
for (j = 0; j < ( hour0->num_point1 / 4 ) - 1 ; j++)
{
hour0->point_numbers[ j * 4 ] = NRAND( 12 ) + 1;
hour0->point_numbers[ j * 4 + 1 ] = NRAND( 12 )
+ 1;
hour0->point_numbers[ j * 4 + 2 ] = NRAND( 12 )
+ 1;
hour0->point_numbers[ j * 4 + 3 ] = NRAND( 12 )
+ 1;
}
hour0->point_numbers[ hour0->num_point1 / 4 ] = 1;
hour0->point_numbers[ 1 + hour0->num_point1 / 4 ] =
1;
hour0->point_numbers[ 2 + hour0->num_point1 / 4 ] =
1;
hour0->point_numbers[ 3 + hour0->num_point1 / 4 ] =
1;
}
else
{
for (j = 0; j < hour0->num_point1 / 4 ; j++)
{
hour0->point_numbers[ j * 4 ] = NRAND( 12 ) + 1;
hour0->point_numbers[ j * 4 + 1 ] =
hour0->point_numbers[ j * 4 ];
hour0->point_numbers[ j * 4 + 2 ] = NRAND( 12 )
+ 1;
hour0->point_numbers[ j * 4 + 3 ] = NRAND( 12 )
+ 1;
}
}
}
else
hour0->point_numbers = original_clock[i+istart];
if ( NRAND( 100 ) >= tclock->fill )
hour0->draw = True;
else
hour0->draw = False;
#ifdef NO_DBUF
{
int x0 , y0;
x0 = (int) (tclock->radius * sin( -tclock->angle - PI_RAD * i *
360.0 / tclock->num_hour ) *
0.5 * ( 1 + cos( tclock->phase ) ) + tclock->x0 +
tclock->a_x * sin( tclock->anglex ) );
y0 = (int) (tclock->radius * cos( -tclock->angle - PI_RAD * i *
360.0 / tclock->num_hour ) *
0.5 * ( 1 + cos( tclock->phase ) ) + tclock->y0 +
tclock->a_y * sin( tclock->angley ) );
toneclock_drawhour(mi , hour0 , x0 , y0 );
}
#endif
}
tclock->a_x = 0;
tclock->a_y = 0;
if ( !tclock->original && tclock->win_width > 20 )
{
if ( tclock->radius < MIN( tclock->win_width , tclock->win_height) /
4 )
{
if ( MI_IS_FULLRANDOM( mi ) )
{
if ( NRAND(2) )
tclock->moving = True;
}
else
{
tclock->moving = move_clock;
}
if ( tclock->moving )
{
tclock->a_x = (int) floor( ( tclock->win_width / 2 ) - 1.05 *
( tclock->radius + tclock->max_radius )
);
tclock->a_y = (int) floor( ( tclock->win_height / 2 ) - 1.05 *
( tclock->radius + tclock->max_radius )
);
tclock->vx = (NRAND(15) - 7) * PI_RAD;
tclock->vy = (NRAND(15) - 7) * PI_RAD;
}
}
}
XFlush(display);
XSetFunction(display, tclock->gc, GXcopy);
}
void
draw_toneclock(ModeInfo * mi)
{
Display *display = MI_DISPLAY(mi);
Window window = MI_WINDOW(mi);
int i;
toneclockstruct *tclock;
if (toneclocks == NULL)
return;
tclock = &toneclocks[MI_SCREEN(mi)];
if (tclock->hour == NULL)
return;
if (tclock->no_colors) {
free_toneclock(display, tclock);
init_toneclock(mi);
return;
}
XSetFunction(display, tclock->gc, GXxor);
#ifndef NO_DBUF
XSetForeground(display,tclock->dbuf_gc,MI_BLACK_PIXEL(mi));
XFillRectangle(display, (Drawable) tclock->dbuf, tclock->dbuf_gc,
0, 0, tclock->win_width, tclock->win_height);
#endif
tclock->painted = True;
MI_IS_DRAWN(mi) = True;
/* Rotate colours */
if (tclock->cycle_p) {
rotate_colors(display, tclock->cmap, tclock->colors, tclock->ncolors,
tclock->direction);
if (!(LRAND() % 1000))
tclock->direction = -tclock->direction;
}
for (i = 0; i < tclock->num_hour; i++) {
toneclockhour *hour0;
int x0 , y0;
x0 = (int) (tclock->radius * sin( -tclock->angle - PI_RAD * i *
360.0 / tclock->num_hour ) *
0.5 * ( 1 + cos( tclock->phase ) ) + tclock->x0 +
tclock->a_x * sin( tclock->anglex ) );
y0 = (int) (tclock->radius * cos( -tclock->angle - PI_RAD * i *
360.0 / tclock->num_hour ) *
0.5 * ( 1 + cos( tclock->phase ) ) + tclock->y0 +
tclock->a_y * sin( tclock->angley ) );
hour0 = &tclock->hour[i];
if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
XSetForeground(display, tclock->gc, tclock->colors[hour0->colour].pixel);
} else {
XSetForeground(display, tclock->gc, hour0->colour);
}
toneclock_drawhour(mi, hour0 , x0 , y0);
hour0->velocity += ((float) NRAND(1001) - 500.0) / 200000.0;
hour0->angle += hour0->velocity;
}
tclock->velocity += ((float) NRAND(1001) - 500.0) / 200000.0;
tclock->angle += tclock->velocity;
if ( tclock->pulsating )
tclock->phase += tclock->ph_vel;
if ( tclock->moving )
{
tclock->anglex += tclock->vx;
tclock->angley += tclock->vy;
}
#ifdef NO_DBUF
for (i = 0; i < tclock->num_hour; i++) {
toneclockhour *hour0;
int x0 , y0;
x0 = (int) (tclock->radius * sin( -tclock->angle - PI_RAD * i *
360.0 / tclock->num_hour ) *
0.5 * ( 1 + cos( tclock->phase ) ) + tclock->x0 +
tclock->a_x * sin( tclock->anglex ) );
y0 = (int) (tclock->radius * cos( -tclock->angle - PI_RAD * i *
360.0 / tclock->num_hour ) *
0.5 * ( 1 + cos( tclock->phase ) ) + tclock->y0 +
tclock->a_y * sin( tclock->angley ) );
hour0 = &tclock->hour[i];
if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
XSetForeground(display, tclock->gc, tclock->colors[hour0->colour].pixel);
} else {
XSetForeground(display, tclock->gc, hour0->colour);
}
toneclock_drawhour(mi, hour0 , x0 , y0);
}
#else
XFlush(display);
XCopyArea (display, (Drawable) tclock->dbuf, window, tclock->dbuf_gc, 0, 0,
tclock->win_width, tclock->win_height, 0, 0);
XFlush(display);
XSetForeground(display,tclock->dbuf_gc,MI_BLACK_PIXEL(mi));
XFillRectangle(display, (Drawable) tclock->dbuf, tclock->dbuf_gc,
0, 0, tclock->win_width, tclock->win_height);
#endif
XSetFunction(display, tclock->gc, GXcopy);
}
void
refresh_toneclock(ModeInfo * mi)
{
toneclockstruct *tclock;
if (toneclocks == NULL)
return;
tclock = &toneclocks[MI_SCREEN(mi)];
if (tclock->hour == NULL)
return;
if (!tclock->painted)
return;
MI_CLEARWINDOW(mi);
#ifdef NO_DBUF
{
Display *display = MI_DISPLAY(mi);
int i;
XSetFunction(display, tclock->gc, GXxor);
for (i = 0; i < tclock->num_hour; i++) {
toneclockhour *hour0;
int x0 , y0;
x0 = (int) (tclock->radius * sin( -tclock->angle - PI_RAD * i *
360.0 / tclock->num_hour ) +
tclock->x0 + tclock->a_x * sin( tclock->anglex ) );
y0 = (int) (tclock->radius * cos( -tclock->angle - PI_RAD * i *
360.0 / tclock->num_hour ) +
tclock->y0 + tclock->a_y * sin( tclock->angley ) );
hour0 = &tclock->hour[i];
if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
XSetForeground(display, tclock->gc, tclock->colors[hour0->colour].pixel);
} else {
XSetForeground(display, tclock->gc, hour0->colour);
}
toneclock_drawhour(mi, hour0 , x0 , y0 );
}
XSetFunction(display, tclock->gc, GXcopy);
}
#endif
}
void
release_toneclock(ModeInfo * mi)
{
if (toneclocks != NULL) {
int screen;
for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
free_toneclock(MI_DISPLAY(mi), &toneclocks[screen]);
free(toneclocks);
toneclocks = (toneclockstruct *) NULL;
}
}
#endif /* MODE_toneclock */