1234 lines
37 KiB
C
1234 lines
37 KiB
C
|
/* -*- Mode: C; tab-width: 4 -*- */
|
||
|
/* dclock --- floating digital clock or message */
|
||
|
|
||
|
#if !defined( lint ) && !defined( SABER )
|
||
|
static const char sccsid[] = "@(#)dclock.c 5.00 2000/11/01 xlockmore";
|
||
|
|
||
|
#endif
|
||
|
|
||
|
/*-
|
||
|
* Copyright (C) 1995 by Michael Stembera <mrbig@fc.net>.
|
||
|
*
|
||
|
* 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:
|
||
|
* 03-Dec-2005: Added a binary clock display, after seeing the binary clock
|
||
|
* at thinkgeek. Petey (petey_leinonen@yahoo.com.au)
|
||
|
* 01-Mar-2005: Added 24 hour clock (alex(at)shark-linux(dot)de)
|
||
|
* 01-Nov-2000: Allocation checks
|
||
|
* 07-May-1999: New "savers" added for y2k and second millennium countdowns.
|
||
|
* Tom Schmidt <tschmidt@micron.com>
|
||
|
* 04-Dec-1998: New "savers" added for hiv, veg, and lab.
|
||
|
* hiv one due to Kenneth Stailey <kstailey@disclosure.com>
|
||
|
* 10-Aug-1998: Population Explosion and Tropical Forest Countdown stuff
|
||
|
* I tried to get precise numbers but they may be off a few
|
||
|
* percent. Whether or not, its still pretty scary IMHO.
|
||
|
* Although I am a US citizen... I have the default for area in
|
||
|
* metric. David Bagley <bagleyd@tux.org>
|
||
|
* 10-May-1997: Compatible with xscreensaver
|
||
|
* 29-Aug-1995: Written.
|
||
|
*/
|
||
|
|
||
|
/*-
|
||
|
* Some of my calculations laid bare... (I have a little problem with
|
||
|
* the consistency of the numbers I got at the Bronx Zoo but proportions
|
||
|
* were figured to be 160.70344 people a minute increase not 180 and
|
||
|
* 35.303144 hectares (87.198766 acres) a minute decrease not 247 (100 acres).
|
||
|
* So I am going with these more conservative numbers.)
|
||
|
*
|
||
|
* Time 0 is 0:00:00 1 Jan 1970 at least according to hard core UNIX fans
|
||
|
* Minutes from 1 Jan 1970 to 21 Jun 1985: 8137440
|
||
|
* Minutes from 21 Jun 1985 to 12 Jul 1988: 6867360
|
||
|
* Total: 15004800
|
||
|
*
|
||
|
* Population Explosion Saver (popex)
|
||
|
* 3,535,369,000 people (figured by extrapolation) 1 Jan 1970
|
||
|
* 4,843,083,596 people 21 Jun 1985 (Opening of Wild Asia in the Bronx Zoo)
|
||
|
* 5,946,692,000 people 12 Jul 1998 (David Bagley visits zoo ;) )
|
||
|
* 180 people a minute increase in global population (I heard 170 also)
|
||
|
* 260,000 people a day increase in global population
|
||
|
*
|
||
|
* Tropical Forest Countdown Saver (forest)
|
||
|
* 1,184,193,000 hectares (figured by extrapolation) 1 Jan 1970
|
||
|
* (2,924,959,000 acres)
|
||
|
* 896,916,700 hectares 21 Jun 1985 (Opening of Wild Asia in the Bronx Zoo)
|
||
|
* (2,215,384,320 acres)
|
||
|
* 654,477,300 hectares 12 Jul 1998 (David Bagley visits zoo ;) )
|
||
|
* (1,616,559,000 acres)
|
||
|
* 247 hectares a minute lost forever (1 hectare = 2.47 acres)
|
||
|
*
|
||
|
* HIV Infection Counter Saver (hiv) (stats from http://www.unaids.org/)
|
||
|
* 33,600,000 31 Dec 1999 living w/HIV
|
||
|
* 16,300,000 31 Dec 1999 dead
|
||
|
* 49,900,000 31 Dec 1999 total infections
|
||
|
* 5,600,000 new infections in 1999
|
||
|
* 10.6545 infections/min
|
||
|
* -118,195,407 virtual cases (figured by extrapolation) 1 Jan 1970
|
||
|
* (this is a result of applying linear tracking to a non-linear event)
|
||
|
*
|
||
|
* Animal Research Counter Saver (lab)
|
||
|
* Approximately 17-22 million animals are used in research each year.
|
||
|
* OK so assume 17,000,000 / 525960 = 32.32184957 per minute
|
||
|
* http://www.fcs.uga.edu/~mhulsey/GDB.html
|
||
|
*
|
||
|
* Animal Consumation Counter Saver (veg)
|
||
|
* Approximately 5 billion are consumed for food annually.
|
||
|
* OK 5,000,000,000 / 525960 = 9506.426344209 per minute
|
||
|
* http://www.fcs.uga.edu/~mhulsey/GDB.html
|
||
|
*/
|
||
|
|
||
|
#ifdef STANDALONE
|
||
|
#define MODE_dclock
|
||
|
#define PROGCLASS "Dclock"
|
||
|
#define HACK_INIT init_dclock
|
||
|
#define HACK_DRAW draw_dclock
|
||
|
#define dclock_opts xlockmore_opts
|
||
|
#define DEFAULTS "*delay: 10000 \n" \
|
||
|
"*cycles: 10000 \n" \
|
||
|
"*ncolors: 64 \n"
|
||
|
#define BRIGHT_COLORS
|
||
|
#define UNIFORM_COLORS
|
||
|
#include "xlockmore.h" /* in xscreensaver distribution */
|
||
|
#include "mode.h"
|
||
|
#else /* STANDALONE */
|
||
|
#include "xlock.h" /* in xlockmore distribution */
|
||
|
#include "util.h"
|
||
|
#endif /* STANDALONE */
|
||
|
#include "iostuff.h"
|
||
|
|
||
|
#ifdef MODE_dclock
|
||
|
|
||
|
#ifndef METRIC
|
||
|
#define METRIC 1
|
||
|
#endif
|
||
|
|
||
|
#if METRIC
|
||
|
#define AREA_MIN 35.303144
|
||
|
#define AREA_TIME_START 1184193000.0
|
||
|
#else
|
||
|
#define AREA_MIN 87.198766
|
||
|
#define AREA_TIME_START 2924959000.0
|
||
|
#endif
|
||
|
|
||
|
#define PEOPLE_MIN 160.70344
|
||
|
#define PEOPLE_TIME_START 3535369000.0
|
||
|
#define HIV_MIN 10.6545
|
||
|
#define HIV_TIME_START -118195407.0
|
||
|
#define LAB_MIN 32.32184957
|
||
|
#define LAB_TIME_START 0
|
||
|
#define VEG_MIN 9506.426344209
|
||
|
#define VEG_TIME_START 0
|
||
|
/* epoch time at midnight 1 January 2000 UTC */
|
||
|
#define Y2K_TIME_START (((30 * 365) + 7) * 24 * 60 * 60)
|
||
|
#define Y2001_TIME_START (Y2K_TIME_START + 366 * 24 * 60 * 60)
|
||
|
|
||
|
#define LED_LEAN 0.2
|
||
|
#define LED_XS 30.0
|
||
|
#define LED_YS 45.0
|
||
|
#define LED_WIDTH (0.15 * LED_YS)
|
||
|
#define LED_INC (LED_LEAN * LED_XS) /* LEAN and INC do not have to be linked */
|
||
|
|
||
|
#define BINARY_WIDTH 10
|
||
|
#define BINARY_HEIGHT 10
|
||
|
#define BINARY_INC 5
|
||
|
|
||
|
#define DEF_BINARY "False"
|
||
|
#define DEF_LED "False"
|
||
|
#define DEF_POPEX "False"
|
||
|
#define DEF_FOREST "False"
|
||
|
#define DEF_HIV "False"
|
||
|
#define DEF_LAB "False"
|
||
|
#define DEF_VEG "False"
|
||
|
#define DEF_TIME24 "False"
|
||
|
#define DEF_Y2K "False"
|
||
|
#define DEF_Y2001 "False"
|
||
|
|
||
|
/*- If you remember your Electronics course...
|
||
|
a
|
||
|
_
|
||
|
f / / b
|
||
|
-g
|
||
|
e /_/ c
|
||
|
d
|
||
|
*/
|
||
|
|
||
|
#define MAX_LEDS 7
|
||
|
static unsigned char digits[][MAX_LEDS]=
|
||
|
{
|
||
|
/* a b c d e f g */
|
||
|
{1, 1, 1, 1, 1, 1, 0}, /* 0 */
|
||
|
{0, 1, 1, 0, 0, 0, 0}, /* 1 */
|
||
|
{1, 1, 0, 1, 1, 0, 1}, /* 2 */
|
||
|
{1, 1, 1, 1, 0, 0, 1}, /* 3 */
|
||
|
{0, 1, 1, 0, 0, 1, 1}, /* 4 */
|
||
|
{1, 0, 1, 1, 0, 1, 1}, /* 5 */
|
||
|
{1, 0, 1, 1, 1, 1, 1}, /* 6 */
|
||
|
{1, 1, 1, 0, 0, 0, 0}, /* 7 */
|
||
|
{1, 1, 1, 1, 1, 1, 1}, /* 8 */
|
||
|
{1, 1, 1, 1, 0, 1, 1} /* 9 */
|
||
|
#if 0
|
||
|
, /* Completeness, we must have completeness */
|
||
|
{1, 1, 1, 0, 1, 1, 1}, /* A */
|
||
|
{0, 0, 1, 1, 1, 1, 1}, /* b */
|
||
|
{1, 0, 0, 1, 1, 1, 0}, /* C */
|
||
|
{0, 1, 1, 1, 1, 0, 1}, /* d */
|
||
|
{1, 0, 0, 1, 1, 1, 1}, /* E */
|
||
|
{1, 0, 0, 0, 1, 1, 1} /* F */
|
||
|
#define MAX_DIGITS 16
|
||
|
#else
|
||
|
#define MAX_DIGITS 10
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
static Bool led;
|
||
|
|
||
|
/* Create an virtual parallelogram, normal rectangle parameters plus "lean":
|
||
|
the amount the start of a will be shifted to the right of the start of d.
|
||
|
*/
|
||
|
|
||
|
static XPoint parallelogramUnit[4] =
|
||
|
{
|
||
|
{1, 0},
|
||
|
{2, 0},
|
||
|
{-1, 1},
|
||
|
{-2, 0}
|
||
|
};
|
||
|
|
||
|
static Bool binary;
|
||
|
static Bool popex;
|
||
|
static Bool forest;
|
||
|
static Bool hiv;
|
||
|
static Bool lab;
|
||
|
static Bool veg;
|
||
|
static Bool time24;
|
||
|
static Bool y2k;
|
||
|
static Bool millennium;
|
||
|
|
||
|
static XrmOptionDescRec opts[] =
|
||
|
{
|
||
|
{(char *) "-binary", (char *) ".dclock.binary", XrmoptionNoArg, (caddr_t) "on"},
|
||
|
{(char *) "+binary", (char *) ".dclock.binary", XrmoptionNoArg, (caddr_t) "off"},
|
||
|
{(char *) "-led", (char *) ".dclock.led", XrmoptionNoArg, (caddr_t) "on"},
|
||
|
{(char *) "+led", (char *) ".dclock.led", XrmoptionNoArg, (caddr_t) "off"},
|
||
|
{(char *) "-popex", (char *) ".dclock.popex", XrmoptionNoArg, (caddr_t) "on"},
|
||
|
{(char *) "+popex", (char *) ".dclock.popex", XrmoptionNoArg, (caddr_t) "off"},
|
||
|
{(char *) "-forest", (char *) ".dclock.forest", XrmoptionNoArg, (caddr_t) "on"},
|
||
|
{(char *) "+forest", (char *) ".dclock.forest", XrmoptionNoArg, (caddr_t) "off"},
|
||
|
{(char *) "-hiv", (char *) ".dclock.hiv", XrmoptionNoArg, (caddr_t) "on"},
|
||
|
{(char *) "+hiv", (char *) ".dclock.hiv", XrmoptionNoArg, (caddr_t) "off"},
|
||
|
{(char *) "-lab", (char *) ".dclock.lab", XrmoptionNoArg, (caddr_t) "on"},
|
||
|
{(char *) "+lab", (char *) ".dclock.lab", XrmoptionNoArg, (caddr_t) "off"},
|
||
|
{(char *) "-veg", (char *) ".dclock.veg", XrmoptionNoArg, (caddr_t) "on"},
|
||
|
{(char *) "+veg", (char *) ".dclock.veg", XrmoptionNoArg, (caddr_t) "off"},
|
||
|
{(char *) "-time24", (char *) ".dclock.time24", XrmoptionNoArg, (caddr_t) "on"},
|
||
|
{(char *) "+time24", (char *) ".dclock.time24", XrmoptionNoArg, (caddr_t) "off"},
|
||
|
{(char *) "-y2k", (char *) ".dclock.y2k", XrmoptionNoArg, (caddr_t) "on"},
|
||
|
{(char *) "+y2k", (char *) ".dclock.y2k", XrmoptionNoArg, (caddr_t) "off"},
|
||
|
{(char *) "-millennium", (char *) ".dclock.millennium", XrmoptionNoArg, (caddr_t) "on"},
|
||
|
{(char *) "+millennium", (char *) ".dclock.millennium", XrmoptionNoArg, (caddr_t) "off"}
|
||
|
};
|
||
|
static argtype vars[] =
|
||
|
{
|
||
|
{(void *) & binary, (char *) "binary", (char *) "Binary", (char *) DEF_BINARY, t_Bool},
|
||
|
{(void *) & led, (char *) "led", (char *) "LED", (char *) DEF_LED, t_Bool},
|
||
|
{(void *) & popex, (char *) "popex", (char *) "PopEx", (char *) DEF_POPEX, t_Bool},
|
||
|
{(void *) & forest, (char *) "forest", (char *) "Forest", (char *) DEF_FOREST, t_Bool},
|
||
|
{(void *) & hiv, (char *) "hiv", (char *) "Hiv", (char *) DEF_HIV, t_Bool},
|
||
|
{(void *) & lab, (char *) "lab", (char *) "Lab", (char *) DEF_LAB, t_Bool},
|
||
|
{(void *) & veg, (char *) "veg", (char *) "Veg", (char *) DEF_VEG, t_Bool},
|
||
|
{(void *) & time24, (char *) "time24", (char *) "Time24", (char *) DEF_TIME24, t_Bool},
|
||
|
{(void *) & y2k, (char *) "y2k", (char *) "Y2K", (char *) DEF_Y2K, t_Bool},
|
||
|
{(void *) & millennium, (char *) "millennium", (char *) "Millennium", (char *) DEF_Y2001, t_Bool}
|
||
|
};
|
||
|
static OptionStruct desc[] =
|
||
|
{
|
||
|
{(char *) "-/+binary", (char *) "turn on/off binary clock display"},
|
||
|
{(char *) "-/+led", (char *) "turn on/off Light Emitting Diode seven segment display"},
|
||
|
{(char *) "-/+popex", (char *) "turn on/off population explosion counter"},
|
||
|
{(char *) "-/+forest", (char *) "turn on/off tropical forest destruction counter"},
|
||
|
{(char *) "-/+hiv", (char *) "turn on/off HIV infection counter"},
|
||
|
{(char *) "-/+lab", (char *) "turn on/off Animal Research counter"},
|
||
|
{(char *) "-/+veg", (char *) "turn on/off Animal Consumation counter"},
|
||
|
{(char *) "-/+time24", (char *) "turn on/off 24 hour display"},
|
||
|
{(char *) "-/+y2k", (char *) "turn on/off Year 2000 countdown"},
|
||
|
{(char *) "-/+millennium", (char *) "turn on/off 3rd Millennium (1 January 2001) countdown"},
|
||
|
};
|
||
|
|
||
|
ModeSpecOpt dclock_opts =
|
||
|
{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
|
||
|
|
||
|
#ifdef USE_MODULES
|
||
|
ModStruct dclock_description =
|
||
|
{"dclock", "init_dclock", "draw_dclock", "release_dclock",
|
||
|
"refresh_dclock", "init_dclock", (char *) NULL, &dclock_opts,
|
||
|
10000, 1, 10000, 1, 64, 0.3, "",
|
||
|
"Shows a floating digital clock or message", 0, NULL};
|
||
|
|
||
|
#endif
|
||
|
|
||
|
#ifdef HAVE_SYS_PARAM_H
|
||
|
#include <sys/param.h>
|
||
|
#endif
|
||
|
#include <time.h>
|
||
|
|
||
|
/* language depended resources */
|
||
|
#if defined FR
|
||
|
#include "dclock-msg-fr.h"
|
||
|
#elif defined NL
|
||
|
#include "dclock-msg-nl.h"
|
||
|
#elif defined JA
|
||
|
#include "dclock-msg-ja.h"
|
||
|
#else
|
||
|
#include "dclock-msg-en.h"
|
||
|
#endif
|
||
|
|
||
|
#ifdef USE_MB
|
||
|
static XFontSet mode_font = None;
|
||
|
static int font_height(XFontSet f)
|
||
|
{
|
||
|
XRectangle ink, log;
|
||
|
if (f == None) {
|
||
|
return 8;
|
||
|
} else {
|
||
|
XmbTextExtents(mode_font, "My", strlen("My"), &ink, &log);
|
||
|
return log.height;
|
||
|
}
|
||
|
}
|
||
|
#define DELTA 0.2
|
||
|
extern XFontSet getFontSet(Display * display);
|
||
|
#else
|
||
|
static XFontStruct *mode_font = None;
|
||
|
#define font_height(f) (f->ascent + f->descent)
|
||
|
#define DELTA 0
|
||
|
extern XFontStruct *getFont(Display * display);
|
||
|
#endif
|
||
|
|
||
|
#ifdef USE_MB
|
||
|
#define free_font(d) if (mode_font!=None){XFreeFontSet(d,mode_font); \
|
||
|
mode_font = None;}
|
||
|
#else
|
||
|
#define free_font(d) if (mode_font!=None){XFreeFont(d,mode_font); \
|
||
|
mode_font = None;}
|
||
|
#endif
|
||
|
|
||
|
#define STRSIZE 50
|
||
|
|
||
|
typedef struct {
|
||
|
int color;
|
||
|
short height, width;
|
||
|
char *str, str1[STRSIZE], str2[STRSIZE], str1old[STRSIZE], str2old[STRSIZE];
|
||
|
char *str1pta, *str2pta, *str1ptb, *str2ptb;
|
||
|
time_t timenew, timeold;
|
||
|
int tzoffset;
|
||
|
short maxx, maxy, clockx, clocky;
|
||
|
short text_height, text_width, text_width1, text_width2;
|
||
|
short text_start1, text_start2;
|
||
|
short text_ascent, text_descent;
|
||
|
short hour;
|
||
|
short dx, dy;
|
||
|
int done;
|
||
|
int pixw, pixh;
|
||
|
Pixmap pixmap;
|
||
|
GC fgGC, bgGC;
|
||
|
Bool popex, forest, hiv, lab, veg, time24, y2k, millennium, led, binary;
|
||
|
XPoint parallelogram[4];
|
||
|
} dclockstruct;
|
||
|
|
||
|
static dclockstruct *dclocks = (dclockstruct *) NULL;
|
||
|
|
||
|
|
||
|
static unsigned long
|
||
|
timeAtLastNewYear(long timeNow)
|
||
|
{
|
||
|
struct tm *t;
|
||
|
|
||
|
t = localtime((const time_t *) &timeNow);
|
||
|
return (unsigned long)(t->tm_year);
|
||
|
}
|
||
|
|
||
|
#ifndef HAVE_SNPRINTF
|
||
|
static double logbase;
|
||
|
#define BASE 10.0
|
||
|
#define GROUP 3
|
||
|
#endif
|
||
|
|
||
|
static void
|
||
|
convert(double x, char *string)
|
||
|
{
|
||
|
#ifdef HAVE_SNPRINTF
|
||
|
/* Also old C compiler can not accept this syntax, but this syntax awares
|
||
|
locale. Known to work with gcc-2.95.2 and glibc-2.1.3. */
|
||
|
(void) snprintf(string, STRSIZE, "%'.0f", x);
|
||
|
#else
|
||
|
|
||
|
int i, j, k = 0;
|
||
|
int place = (int) (log(x) / logbase);
|
||
|
double divisor = 1.0;
|
||
|
|
||
|
for (i = 0; i < place; i++)
|
||
|
divisor *= BASE;
|
||
|
|
||
|
for (i = place; i >= 0; i--) {
|
||
|
j = (int) (x / divisor);
|
||
|
string[k++] = (char) j + '0';
|
||
|
x -= j * divisor;
|
||
|
divisor /= BASE;
|
||
|
if ((i > 0) && (i % GROUP == 0)) {
|
||
|
string[k++] = ',';
|
||
|
}
|
||
|
}
|
||
|
string[k] = '\0';
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
dayhrminsec(long timeCount, int tzoffset, char *string)
|
||
|
{
|
||
|
int days, hours, minutes, secs;
|
||
|
int bufsize, i;
|
||
|
|
||
|
timeCount = ABS(timeCount);
|
||
|
days = (int) (timeCount / 86400);
|
||
|
hours = (int) ((timeCount / 3600) % 24);
|
||
|
minutes = (int) ((timeCount / 60) % 60);
|
||
|
secs = (int) (timeCount % 60);
|
||
|
|
||
|
/* snprintf would make this easier but its not always available */
|
||
|
bufsize = 16 + strlen((days==1) ? DAY : DAYS);
|
||
|
if (bufsize >= STRSIZE)
|
||
|
return;
|
||
|
(void) sprintf(string, "%d %s", days, (days==1) ? DAY : DAYS);
|
||
|
|
||
|
i = strlen(string);
|
||
|
bufsize = 4 + strlen((hours==1) ? HOUR : HOURS);
|
||
|
if (i + bufsize >= STRSIZE)
|
||
|
return;
|
||
|
(void) sprintf(&string[i], " %d %s", hours, (hours==1) ? HOUR : HOURS);
|
||
|
|
||
|
i = strlen(string);
|
||
|
bufsize = 4 + strlen((minutes==1) ? MINUTE : MINUTES);
|
||
|
if (i + bufsize >= STRSIZE)
|
||
|
return;
|
||
|
(void) sprintf(&string[i], " %d %s", minutes, (minutes==1) ? MINUTE : MINUTES);
|
||
|
|
||
|
i = strlen(string);
|
||
|
bufsize += 4 + strlen((secs==1) ? SECOND : SECONDS);
|
||
|
if (i + bufsize >= STRSIZE)
|
||
|
return;
|
||
|
(void) sprintf(&string[i], " %d %s", secs, (secs==1) ? SECOND : SECONDS);
|
||
|
|
||
|
if (!tzoffset) {
|
||
|
i = strlen(string);
|
||
|
bufsize += 6; /* strlen(" (UTC)"); */
|
||
|
if (i + bufsize >= STRSIZE)
|
||
|
return;
|
||
|
(void) strcat(string, " (UTC)");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
drawaled(ModeInfo * mi, int startx, int starty, int aled)
|
||
|
{
|
||
|
Display *display = MI_DISPLAY(mi);
|
||
|
dclockstruct *dp = &dclocks[MI_SCREEN(mi)];
|
||
|
int x_1, y_1, x_2, y_2;
|
||
|
|
||
|
int offset = (int) LED_WIDTH;
|
||
|
int offset2 = (int) (LED_WIDTH / 2.0);
|
||
|
int leanoffset = (int) (offset2 * LED_LEAN);
|
||
|
|
||
|
switch (aled) {
|
||
|
case 0: /* a */
|
||
|
x_1 = startx + dp->parallelogram[0].x;
|
||
|
y_1 = starty + dp->parallelogram[0].y;
|
||
|
x_2 = x_1 + dp->parallelogram[1].x - offset;
|
||
|
y_2 = y_1 + dp->parallelogram[1].y;
|
||
|
x_1 = x_1 + offset;
|
||
|
XDrawLine(display, dp->pixmap, dp->fgGC,
|
||
|
x_1, y_1, x_2, y_2);
|
||
|
break;
|
||
|
case 1: /* b */
|
||
|
x_1 = startx + dp->parallelogram[0].x + dp->parallelogram[1].x;
|
||
|
y_1 = starty + dp->parallelogram[0].y + dp->parallelogram[1].y;
|
||
|
x_2 = x_1 + dp->parallelogram[2].x / 2 + leanoffset;
|
||
|
y_2 = y_1 + dp->parallelogram[2].y / 2 - offset2;
|
||
|
x_1 = x_1 - leanoffset;
|
||
|
y_1 = y_1 + offset2;
|
||
|
XDrawLine(display, dp->pixmap, dp->fgGC,
|
||
|
x_1, y_1, x_2, y_2);
|
||
|
break;
|
||
|
case 2: /* c */
|
||
|
x_1 = startx + dp->parallelogram[0].x + dp->parallelogram[1].x + dp->parallelogram[2].x;
|
||
|
y_1 = starty + dp->parallelogram[0].y + dp->parallelogram[1].y + dp->parallelogram[2].y;
|
||
|
x_2 = x_1 - dp->parallelogram[2].x / 2 - leanoffset;
|
||
|
y_2 = y_1 - dp->parallelogram[2].y / 2 + offset2;
|
||
|
x_1 = x_1 + leanoffset;
|
||
|
y_1 = y_1 - offset2;
|
||
|
XDrawLine(display, dp->pixmap, dp->fgGC,
|
||
|
x_1, y_1, x_2, y_2);
|
||
|
break;
|
||
|
case 3: /* d */
|
||
|
x_1 = startx + dp->parallelogram[0].x + dp->parallelogram[2].x;
|
||
|
y_1 = starty + dp->parallelogram[0].y + dp->parallelogram[2].y;
|
||
|
x_2 = x_1 + dp->parallelogram[1].x - offset;
|
||
|
y_2 = y_1 + dp->parallelogram[1].y;
|
||
|
x_1 = x_1 + offset;
|
||
|
XDrawLine(display, dp->pixmap, dp->fgGC,
|
||
|
x_1, y_1, x_2, y_2);
|
||
|
break;
|
||
|
case 4: /* e */
|
||
|
x_1 = startx + dp->parallelogram[0].x + dp->parallelogram[2].x;
|
||
|
y_1 = starty + dp->parallelogram[0].y + dp->parallelogram[2].y;
|
||
|
x_2 = x_1 - dp->parallelogram[2].x / 2 - leanoffset;
|
||
|
y_2 = y_1 - dp->parallelogram[2].y / 2 + offset2;
|
||
|
x_1 = x_1 + leanoffset;
|
||
|
y_1 = y_1 - offset2;
|
||
|
XDrawLine(display, dp->pixmap, dp->fgGC,
|
||
|
x_1, y_1, x_2, y_2);
|
||
|
break;
|
||
|
case 5: /* f */
|
||
|
x_1 = startx + dp->parallelogram[0].x;
|
||
|
y_1 = starty + dp->parallelogram[0].y;
|
||
|
x_2 = x_1 + dp->parallelogram[2].x / 2 + leanoffset;
|
||
|
y_2 = y_1 + dp->parallelogram[2].y / 2 - offset2;
|
||
|
x_1 = x_1 - leanoffset;
|
||
|
y_1 = y_1 + offset2;
|
||
|
XDrawLine(display, dp->pixmap, dp->fgGC,
|
||
|
x_1, y_1, x_2, y_2);
|
||
|
break;
|
||
|
case 6: /* g */
|
||
|
x_1 = startx + dp->parallelogram[0].x + dp->parallelogram[2].x / 2;
|
||
|
y_1 = starty + dp->parallelogram[0].y + dp->parallelogram[2].y / 2;
|
||
|
x_2 = x_1 + dp->parallelogram[1].x - offset;
|
||
|
y_2 = y_1 + dp->parallelogram[1].y;
|
||
|
x_1 = x_1 + offset;
|
||
|
XDrawLine(display, dp->pixmap, dp->fgGC,
|
||
|
x_1, y_1, x_2, y_2);
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
drawacolon(ModeInfo * mi, int startx, int starty)
|
||
|
{
|
||
|
Display *display = MI_DISPLAY(mi);
|
||
|
dclockstruct *dp = &dclocks[MI_SCREEN(mi)];
|
||
|
int x_1, y_1, x_2, y_2;
|
||
|
|
||
|
int offset2 = (int) (LED_WIDTH / 2.0);
|
||
|
int leanoffset = (int) (offset2 * LED_LEAN);
|
||
|
|
||
|
x_1 = startx + dp->parallelogram[0].x +
|
||
|
(int) (dp->parallelogram[2].x / 2 - 2.0 * leanoffset);
|
||
|
y_1 = starty + dp->parallelogram[0].y + dp->parallelogram[2].y / 2 +
|
||
|
(int) (2.0 * offset2);
|
||
|
x_2 = x_1 - (int) (2.0 * leanoffset);
|
||
|
y_2 = y_1 + (int) (2.0 * offset2);
|
||
|
XDrawLine(display, dp->pixmap, dp->fgGC, x_1, y_1, x_2, y_2);
|
||
|
x_1 = startx + dp->parallelogram[0].x +
|
||
|
dp->parallelogram[2].x / 2 + (int) (2.0 * leanoffset);
|
||
|
y_1 = starty + dp->parallelogram[0].y + dp->parallelogram[2].y / 2 -
|
||
|
(int) (2.0 * offset2);
|
||
|
x_2 = x_1 + (int) (2.0 * leanoffset);
|
||
|
y_2 = y_1 - (int) (2.0 * offset2);
|
||
|
XDrawLine(display, dp->pixmap, dp->fgGC, x_1, y_1, x_2, y_2);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
drawanumber(ModeInfo * mi, int startx, int starty, int digit)
|
||
|
{
|
||
|
int aled;
|
||
|
|
||
|
for (aled = 0; aled < MAX_LEDS; aled++) {
|
||
|
if (digits[digit][aled])
|
||
|
drawaled(mi, startx, starty, aled);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
drawadot(ModeInfo * mi, int startx, int starty, int filled)
|
||
|
{
|
||
|
Display *display = MI_DISPLAY(mi);
|
||
|
dclockstruct *dp = &dclocks[MI_SCREEN(mi)];
|
||
|
|
||
|
if (filled)
|
||
|
XFillArc(display, dp->pixmap, dp->fgGC, startx, starty,
|
||
|
BINARY_WIDTH, BINARY_HEIGHT, 0, 23040);
|
||
|
else
|
||
|
XDrawArc(display, dp->pixmap, dp->fgGC, startx, starty,
|
||
|
BINARY_WIDTH, BINARY_HEIGHT, 0, 23040);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
drawabinary(ModeInfo * mi, int startx, int starty, int dotcount, int digit)
|
||
|
{
|
||
|
int newy;
|
||
|
int filled;
|
||
|
int i;
|
||
|
|
||
|
for (i=0; i < dotcount; i++) {
|
||
|
newy = starty + ((BINARY_HEIGHT + BINARY_INC) * (3 - i));
|
||
|
filled = (digit >> i) & 0x01;
|
||
|
drawadot(mi, startx, newy, filled);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
free_dclock(Display *display, dclockstruct *dp)
|
||
|
{
|
||
|
if (dp->fgGC != None) {
|
||
|
XFreeGC(display, dp->fgGC);
|
||
|
dp->fgGC = None;
|
||
|
}
|
||
|
if (dp->bgGC) {
|
||
|
XFreeGC(display, dp->bgGC);
|
||
|
dp->bgGC = None;
|
||
|
}
|
||
|
if (dp->pixmap) {
|
||
|
XFreePixmap(display, dp->pixmap);
|
||
|
dp->pixmap = None;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
drawDclock(ModeInfo * mi)
|
||
|
{
|
||
|
Display *display = MI_DISPLAY(mi);
|
||
|
Window window = MI_WINDOW(mi);
|
||
|
GC gc = MI_GC(mi);
|
||
|
dclockstruct *dp = &dclocks[MI_SCREEN(mi)];
|
||
|
short xold, yold;
|
||
|
|
||
|
if (dp->led || dp->binary) {
|
||
|
dp->timeold = dp->timenew = time((time_t *) NULL);
|
||
|
dp->str = ctime(&dp->timeold);
|
||
|
} else if (!dp->popex && !dp->forest && !dp->hiv &&
|
||
|
!dp->lab && !dp->veg && !dp->y2k && !dp->millennium) {
|
||
|
if (dp->timeold != (dp->timenew = time((time_t *) NULL))) {
|
||
|
/* only parse if time has changed */
|
||
|
dp->timeold = dp->timenew;
|
||
|
|
||
|
if (!dp->popex && !dp->forest && !dp->hiv && !dp->lab &&
|
||
|
!dp->veg && !dp->y2k && !dp->millennium) {
|
||
|
if (dp->time24)
|
||
|
(void) strftime(dp->str1pta, STRSIZE, "%H:%M:%S", localtime(&(dp->timeold)));
|
||
|
else
|
||
|
(void) strftime(dp->str1pta, STRSIZE, "%I:%M:%S %p", localtime(&(dp->timeold)));
|
||
|
}
|
||
|
(void) strftime(dp->str2pta, STRSIZE, "%a %b %d %Y", localtime(&(dp->timeold)));
|
||
|
}
|
||
|
} else {
|
||
|
long timeNow, timeLocal;
|
||
|
timeNow = seconds();
|
||
|
timeLocal = timeNow - dp->tzoffset;
|
||
|
|
||
|
if (dp->popex) {
|
||
|
convert(PEOPLE_TIME_START + (PEOPLE_MIN / 60.0) * timeNow, dp->str2);
|
||
|
(void) strncat(dp->str2, PEOPLE_STRING, STRSIZE-strlen(dp->str2));
|
||
|
dp->str2pta = dp->str2;
|
||
|
dp->str2ptb = dp->str2pta;
|
||
|
} else if (dp->forest) {
|
||
|
convert(AREA_TIME_START - (AREA_MIN / 60.0) * timeNow, dp->str2);
|
||
|
(void) strncat(dp->str2, TROPICAL_STRING, STRSIZE-strlen(dp->str2));
|
||
|
(void) strncat(dp->str2, AREA_STRING, STRSIZE-strlen(dp->str2));
|
||
|
dp->str2pta = dp->str2;
|
||
|
dp->str2ptb = dp->str2pta;
|
||
|
} else if (dp->hiv) {
|
||
|
convert(HIV_TIME_START + (HIV_MIN / 60.0) * timeNow, dp->str2);
|
||
|
(void) strncat(dp->str2, CASES_STRING, STRSIZE-strlen(dp->str2));
|
||
|
dp->str2pta = dp->str2;
|
||
|
dp->str2ptb = dp->str2pta;
|
||
|
} else if (dp->lab) {
|
||
|
convert((LAB_MIN / 60.0) * (timeNow - timeAtLastNewYear(timeNow)),
|
||
|
dp->str2);
|
||
|
(void) strncat(dp->str2, YEAR_STRING, STRSIZE-strlen(dp->str2));
|
||
|
dp->str2pta = dp->str2;
|
||
|
dp->str2ptb = dp->str2pta;
|
||
|
} else if (dp->veg) {
|
||
|
convert((VEG_MIN / 60.0) * (timeNow - timeAtLastNewYear(timeNow)),
|
||
|
dp->str2);
|
||
|
(void) strncat(dp->str2, YEAR_STRING, STRSIZE-strlen(dp->str2));
|
||
|
dp->str2pta = dp->str2;
|
||
|
dp->str2ptb = dp->str2pta;
|
||
|
} else if (dp->y2k) {
|
||
|
if (Y2K_TIME_START >= timeLocal)
|
||
|
dp->str1pta = (char *) Y2K_STRING;
|
||
|
else
|
||
|
dp->str1pta = (char *) POST_Y2K_STRING;
|
||
|
dp->str1ptb = dp->str1pta;
|
||
|
dayhrminsec(Y2K_TIME_START - timeLocal, dp->tzoffset, dp->str2);
|
||
|
dp->str2pta = dp->str2;
|
||
|
dp->str2ptb = dp->str2pta;
|
||
|
} else if (dp->millennium) {
|
||
|
if (Y2001_TIME_START >= timeLocal)
|
||
|
dp->str1pta = (char *) Y2001_STRING;
|
||
|
else
|
||
|
dp->str1pta = (char *) POST_Y2001_STRING;
|
||
|
dp->str1ptb = dp->str1pta;
|
||
|
dayhrminsec(Y2001_TIME_START - timeLocal, dp->tzoffset, dp->str2);
|
||
|
dp->str2pta = dp->str2;
|
||
|
dp->str2ptb = dp->str2pta;
|
||
|
}
|
||
|
}
|
||
|
/* Recalculate string width since it can change */
|
||
|
xold = dp->clockx;
|
||
|
yold = dp->clocky;
|
||
|
if (!dp->led && !dp->binary) {
|
||
|
#ifdef USE_MB
|
||
|
{
|
||
|
XRectangle ink, logical;
|
||
|
|
||
|
XmbTextExtents(mode_font, dp->str1pta, strlen(dp->str1pta), &ink, &logical);
|
||
|
dp->text_width1 = logical.width;
|
||
|
XmbTextExtents(mode_font, dp->str2pta, strlen(dp->str2pta), &ink, &logical);
|
||
|
dp->text_width2 = logical.width;
|
||
|
}
|
||
|
#else
|
||
|
dp->text_width1 = XTextWidth(mode_font, dp->str1pta, strlen(dp->str1pta));
|
||
|
dp->text_width2 = XTextWidth(mode_font, dp->str2pta, strlen(dp->str2pta));
|
||
|
#endif
|
||
|
|
||
|
if (dp->text_width1 > dp->text_width2) {
|
||
|
dp->text_width = dp->text_width1;
|
||
|
dp->text_start1 = 0;
|
||
|
dp->text_start2 = (dp->text_width - dp->text_width2) / 2;
|
||
|
} else {
|
||
|
dp->text_width = dp->text_width2;
|
||
|
dp->text_start1 = (dp->text_width - dp->text_width1) / 2;
|
||
|
dp->text_start2 = 0;
|
||
|
}
|
||
|
}
|
||
|
dp->width = MI_WIDTH(mi);
|
||
|
dp->height = MI_HEIGHT(mi);
|
||
|
dp->maxx = dp->width - dp->text_width;
|
||
|
dp->maxy = dp->height - dp->text_height - dp->text_descent;
|
||
|
dp->clockx += dp->dx;
|
||
|
dp->clocky += dp->dy;
|
||
|
if (dp->maxx < dp->text_start1) {
|
||
|
if (dp->clockx < dp->maxx + dp->text_start1 ||
|
||
|
dp->clockx > dp->text_start1) {
|
||
|
dp->dx = -dp->dx;
|
||
|
dp->clockx += dp->dx;
|
||
|
}
|
||
|
} else if (dp->maxx > dp->text_start1) {
|
||
|
if (dp->clockx >= dp->maxx + dp->text_start1 ||
|
||
|
dp->clockx <= dp->text_start1) {
|
||
|
dp->dx = -dp->dx;
|
||
|
dp->clockx += dp->dx;
|
||
|
}
|
||
|
}
|
||
|
if (dp->maxy < dp->text_ascent) {
|
||
|
if (dp->clocky > dp->text_ascent || dp->clocky < dp->maxy) {
|
||
|
dp->dy = -dp->dy;
|
||
|
dp->clocky += dp->dy;
|
||
|
}
|
||
|
} else if (dp->maxy > dp->text_ascent) {
|
||
|
if (dp->clocky > dp->maxy || dp->clocky < dp->text_ascent) {
|
||
|
dp->dy = -dp->dy;
|
||
|
dp->clocky += dp->dy;
|
||
|
}
|
||
|
}
|
||
|
if (dp->pixw != dp->text_width ||
|
||
|
dp->pixh != (1 + !dp->led) * dp->text_height) {
|
||
|
XGCValues gcv;
|
||
|
|
||
|
if (dp->pixmap)
|
||
|
MI_CLEARWINDOWCOLORMAPFAST(mi, gc, MI_BLACK_PIXEL(mi));
|
||
|
free_dclock(display, dp);
|
||
|
dp->pixw = dp->text_width;
|
||
|
if (dp->led)
|
||
|
dp->pixh = dp->text_height;
|
||
|
else
|
||
|
dp->pixh = (2 + DELTA) * dp->text_height;
|
||
|
if ((dp->pixmap =
|
||
|
XCreatePixmap(display, window, dp->pixw, dp->pixh, 1)) == None) {
|
||
|
free_dclock(display, dp);
|
||
|
dp->pixw = 0;
|
||
|
dp->pixh = 0;
|
||
|
return;
|
||
|
}
|
||
|
#ifndef USE_MB
|
||
|
gcv.font = mode_font->fid;
|
||
|
#endif
|
||
|
gcv.background = 0;
|
||
|
gcv.foreground = 1;
|
||
|
gcv.graphics_exposures = False;
|
||
|
if ((dp->fgGC = XCreateGC(display, dp->pixmap,
|
||
|
GCForeground | GCBackground | GCGraphicsExposures
|
||
|
#ifndef USE_MB
|
||
|
| GCFont
|
||
|
#endif
|
||
|
, &gcv)) == None) {
|
||
|
free_dclock(display, dp);
|
||
|
dp->pixw = 0;
|
||
|
dp->pixh = 0;
|
||
|
return;
|
||
|
}
|
||
|
gcv.foreground = 0;
|
||
|
if ((dp->bgGC = XCreateGC(display, dp->pixmap,
|
||
|
GCForeground | GCBackground | GCGraphicsExposures
|
||
|
#ifndef USE_MB
|
||
|
| GCFont
|
||
|
#endif
|
||
|
, &gcv)) == None) {
|
||
|
free_dclock(display, dp);
|
||
|
dp->pixw = 0;
|
||
|
dp->pixh = 0;
|
||
|
return;
|
||
|
}
|
||
|
if (!dp->binary)
|
||
|
XSetLineAttributes(display, dp->fgGC,
|
||
|
(unsigned int) (LED_WIDTH),
|
||
|
LineSolid, CapButt, JoinMiter);
|
||
|
}
|
||
|
XFillRectangle(display, dp->pixmap, dp->bgGC, 0, 0, dp->pixw, dp->pixh);
|
||
|
|
||
|
if (dp->led) {
|
||
|
int startx = (int) (LED_WIDTH / 2.0);
|
||
|
int starty = (int) (LED_WIDTH / 2.0);
|
||
|
|
||
|
drawanumber(mi, startx, starty, dp->str[11] - '0');
|
||
|
startx += (int) (LED_XS + LED_WIDTH + LED_INC);
|
||
|
drawanumber(mi, startx, starty, dp->str[12] - '0');
|
||
|
startx += (int) (LED_XS + LED_WIDTH + LED_INC);
|
||
|
drawacolon(mi, startx, starty);
|
||
|
startx += (int) (LED_WIDTH + LED_INC);
|
||
|
drawanumber(mi, startx, starty, dp->str[14] - '0');
|
||
|
startx += (int) (LED_XS + LED_WIDTH + LED_INC);
|
||
|
drawanumber(mi, startx, starty, dp->str[15] - '0');
|
||
|
startx += (int) (LED_XS + LED_WIDTH + LED_INC);
|
||
|
drawacolon(mi, startx, starty);
|
||
|
startx += (int) (LED_WIDTH + LED_INC);
|
||
|
drawanumber(mi, startx, starty, dp->str[17] - '0');
|
||
|
startx += (int) (LED_XS + LED_WIDTH + LED_INC);
|
||
|
drawanumber(mi, startx, starty, dp->str[18] - '0');
|
||
|
} else if (dp->binary) {
|
||
|
int startx = BINARY_WIDTH / 2;
|
||
|
int starty = BINARY_HEIGHT / 2;
|
||
|
|
||
|
/* hour - top number, 0, 1 or 2 */
|
||
|
drawabinary(mi, startx, starty, 2, dp->str[11] - '0');
|
||
|
startx += (BINARY_WIDTH + BINARY_INC);
|
||
|
/* hour - bottom number 0 - 9 */
|
||
|
drawabinary(mi, startx, starty, 4, dp->str[12] - '0');
|
||
|
startx += (BINARY_WIDTH + BINARY_INC);
|
||
|
/* minute - top number, 0 - 5 */
|
||
|
drawabinary(mi, startx, starty, 3, dp->str[14] - '0');
|
||
|
startx += (BINARY_WIDTH + BINARY_INC);
|
||
|
/* minute - bottom number, 0 - 9 */
|
||
|
drawabinary(mi, startx, starty, 4, dp->str[15] - '0');
|
||
|
startx += (BINARY_WIDTH + BINARY_INC);
|
||
|
/* second - top number, 0 - 5 */
|
||
|
drawabinary(mi, startx, starty, 3, dp->str[17] - '0');
|
||
|
startx += (BINARY_WIDTH + BINARY_INC);
|
||
|
/* second - bottom number, 0 - 9 */
|
||
|
drawabinary(mi, startx, starty, 4, dp->str[18] - '0');
|
||
|
startx += (BINARY_WIDTH + BINARY_INC);
|
||
|
} else {
|
||
|
#ifdef USE_MB
|
||
|
(void) XmbDrawString(display, dp->pixmap, mode_font, dp->fgGC,
|
||
|
dp->text_start1, dp->text_ascent,
|
||
|
dp->str1pta, strlen(dp->str1pta));
|
||
|
(void) XmbDrawString(display, dp->pixmap, mode_font, dp->fgGC,
|
||
|
dp->text_start2, dp->text_ascent + dp->text_height,
|
||
|
dp->str2pta, strlen(dp->str2pta));
|
||
|
#else
|
||
|
(void) XDrawString(display, dp->pixmap, dp->fgGC,
|
||
|
dp->text_start1, dp->text_ascent,
|
||
|
dp->str1pta, strlen(dp->str1pta));
|
||
|
(void) XDrawString(display, dp->pixmap, dp->fgGC,
|
||
|
dp->text_start2, dp->text_ascent + dp->text_height,
|
||
|
dp->str2pta, strlen(dp->str2pta));
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
|
||
|
/* This could leave screen dust on the screen if the width changes
|
||
|
But that only happens once a day...
|
||
|
... this is solved by the ClearWindow above
|
||
|
*/
|
||
|
ERASE_IMAGE(display, window, gc,
|
||
|
(dp->clockx - dp->text_start1), (dp->clocky - dp->text_ascent),
|
||
|
(xold - dp->text_start1), (yold - dp->text_ascent),
|
||
|
dp->pixw, dp->pixh);
|
||
|
if (MI_NPIXELS(mi) > 2)
|
||
|
XSetForeground(display, gc, MI_PIXEL(mi, dp->color));
|
||
|
else
|
||
|
XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
|
||
|
XCopyPlane(display, dp->pixmap, window, gc,
|
||
|
0, 0, dp->text_width, (2 + DELTA) * dp->text_height,
|
||
|
dp->clockx - dp->text_start1, dp->clocky - dp->text_ascent,
|
||
|
1L);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
release_dclock(ModeInfo * mi)
|
||
|
{
|
||
|
if (dclocks != NULL) {
|
||
|
int screen;
|
||
|
|
||
|
for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
|
||
|
free_dclock(MI_DISPLAY(mi), &dclocks[screen]);
|
||
|
free(dclocks);
|
||
|
dclocks = (dclockstruct *) NULL;
|
||
|
}
|
||
|
free_font(MI_DISPLAY(mi));
|
||
|
}
|
||
|
|
||
|
#if defined(HAVE_TZSET) && !(defined(BSD) && BSD >= 199306) && !(defined(__CYGWIN__))
|
||
|
extern long timezone;
|
||
|
#endif
|
||
|
|
||
|
void
|
||
|
init_dclock(ModeInfo * mi)
|
||
|
{
|
||
|
Display *display = MI_DISPLAY(mi);
|
||
|
dclockstruct *dp;
|
||
|
long timeNow, timeLocal;
|
||
|
|
||
|
if (dclocks == NULL) {
|
||
|
#ifndef HAVE_SNPRINTF
|
||
|
logbase = log(BASE);
|
||
|
#endif
|
||
|
if ((dclocks = (dclockstruct *) calloc(MI_NUM_SCREENS(mi),
|
||
|
sizeof (dclockstruct))) == NULL)
|
||
|
return;
|
||
|
}
|
||
|
dp = &dclocks[MI_SCREEN(mi)];
|
||
|
|
||
|
dp->width = MI_WIDTH(mi);
|
||
|
dp->height = MI_HEIGHT(mi);
|
||
|
|
||
|
MI_CLEARWINDOW(mi);
|
||
|
|
||
|
dp->binary = False;
|
||
|
dp->led = False;
|
||
|
dp->popex = False;
|
||
|
dp->forest = False;
|
||
|
dp->hiv = False;
|
||
|
dp->lab = False;
|
||
|
dp->veg = False;
|
||
|
dp->time24 = False;
|
||
|
dp->y2k = False;
|
||
|
dp->millennium = False;
|
||
|
#if defined(MODE_dclock_y2k) && defined(MODE_dclock_millennium)
|
||
|
#define NUM_DCLOCK_MODES 11
|
||
|
#endif
|
||
|
#if defined(MODE_dclock_y2k) && !defined(MODE_dclock_millennium)
|
||
|
#define NUM_DCLOCK_MODES 10
|
||
|
#endif
|
||
|
#if !defined(MODE_dclock_y2k) && defined(MODE_dclock_millennium)
|
||
|
#define NUM_DCLOCK_MODES 10
|
||
|
#endif
|
||
|
#if !defined(MODE_dclock_y2k) && !defined(MODE_dclock_millennium)
|
||
|
#define NUM_DCLOCK_MODES 9
|
||
|
#endif
|
||
|
if (MI_IS_FULLRANDOM(mi)) {
|
||
|
switch (NRAND(NUM_DCLOCK_MODES)) {
|
||
|
case 0:
|
||
|
break;
|
||
|
case 1:
|
||
|
dp->led = True;
|
||
|
break;
|
||
|
case 2:
|
||
|
dp->popex = True;
|
||
|
break;
|
||
|
case 3:
|
||
|
dp->forest = True;
|
||
|
break;
|
||
|
case 4:
|
||
|
dp->hiv = True;
|
||
|
break;
|
||
|
case 5:
|
||
|
dp->lab = True;
|
||
|
break;
|
||
|
case 6:
|
||
|
dp->veg = True;
|
||
|
break;
|
||
|
case 7:
|
||
|
dp->time24 = True;
|
||
|
break;
|
||
|
case 8:
|
||
|
dp->binary = True;
|
||
|
break;
|
||
|
#if defined(MODE_dclock_y2k) || defined(MODE_dclock_millennium)
|
||
|
case 9:
|
||
|
#ifdef MODE_dclock_y2k
|
||
|
dp->y2k = True;
|
||
|
#else
|
||
|
dp->millennium = True;
|
||
|
#endif
|
||
|
break;
|
||
|
#if defined(MODE_dclock_y2k) && defined(MODE_dclock_millennium)
|
||
|
case 10:
|
||
|
dp->millennium = True;
|
||
|
break;
|
||
|
#endif
|
||
|
#endif
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
} else { /* first come, first served */
|
||
|
dp->binary = binary;
|
||
|
dp->led = led;
|
||
|
dp->popex = popex;
|
||
|
dp->forest = forest;
|
||
|
dp->hiv = hiv;
|
||
|
dp->lab = lab;
|
||
|
dp->veg = veg;
|
||
|
dp->time24 = time24;
|
||
|
dp->y2k = y2k;
|
||
|
dp->millennium = millennium;
|
||
|
}
|
||
|
|
||
|
if (mode_font == None) {
|
||
|
#ifdef USE_MB
|
||
|
mode_font = getFontSet(display);
|
||
|
#else
|
||
|
mode_font = getFont(display);
|
||
|
#endif
|
||
|
if (mode_font == None) {
|
||
|
release_dclock(mi);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
if (!dp->done) {
|
||
|
dp->done = 1;
|
||
|
#ifndef USE_MB
|
||
|
if (mode_font != None)
|
||
|
XSetFont(display, MI_GC(mi), mode_font->fid);
|
||
|
#endif
|
||
|
}
|
||
|
/* (void)time(&dp->timenew); */
|
||
|
#if defined(HAVE_TZSET) && (!defined(HAVE_TIMELOCAL) || (defined(BSD) && BSD >= 199306))
|
||
|
(void) tzset();
|
||
|
#endif
|
||
|
dp->timeold = dp->timenew = time((time_t *) NULL);
|
||
|
#if defined(HAVE_TIMELOCAL) && !(defined(BSD) && BSD >= 199306)
|
||
|
dp->tzoffset = mktime(localtime(&dp->timeold)) -
|
||
|
mktime(gmtime(&dp->timeold));
|
||
|
#else
|
||
|
#if defined(HAVE_TZSET)
|
||
|
dp->tzoffset = (int)timezone;
|
||
|
#else
|
||
|
dp->tzoffset = 0;
|
||
|
#endif
|
||
|
#endif
|
||
|
if (dp->tzoffset > 86400 || dp->tzoffset < -86400)
|
||
|
dp->tzoffset = 0;
|
||
|
dp->str = ctime(&dp->timeold);
|
||
|
dp->dx = (LRAND() & 1) ? 1 : -1;
|
||
|
dp->dy = (LRAND() & 1) ? 1 : -1;
|
||
|
|
||
|
timeNow = seconds();
|
||
|
timeLocal = timeNow - dp->tzoffset;
|
||
|
if (dp->led) {
|
||
|
int i;
|
||
|
|
||
|
dp->text_descent = 0;
|
||
|
dp->text_ascent = 0;
|
||
|
for (i = 0; i < 4; i++) {
|
||
|
if (parallelogramUnit[i].x == 1)
|
||
|
dp->parallelogram[i].x = (short) (LED_XS * LED_LEAN);
|
||
|
else if (parallelogramUnit[i].x == 2)
|
||
|
dp->parallelogram[i].x = (short) LED_XS;
|
||
|
else if (parallelogramUnit[i].x == -1)
|
||
|
dp->parallelogram[i].x = (short) (-LED_XS * LED_LEAN);
|
||
|
else if (parallelogramUnit[i].x == -2)
|
||
|
dp->parallelogram[i].x = (short) (-LED_XS);
|
||
|
else
|
||
|
dp->parallelogram[i].x = 0;
|
||
|
dp->parallelogram[i].y = (short) (LED_YS * parallelogramUnit[i].y);
|
||
|
}
|
||
|
|
||
|
dp->parallelogram[0].x = (short) ((LED_XS * LED_LEAN) + LED_INC);
|
||
|
dp->parallelogram[0].y = (short) LED_INC;
|
||
|
dp->text_width = (short) (6 * (LED_XS + LED_WIDTH + LED_INC) +
|
||
|
2 * (LED_WIDTH + LED_INC) + LED_XS * LED_LEAN - LED_INC);
|
||
|
dp->text_height = (short) (LED_YS + LED_WIDTH + LED_INC);
|
||
|
dp->maxy = dp->height - dp->text_height;
|
||
|
if (dp->maxy == 0)
|
||
|
dp->clocky = 0;
|
||
|
else if (dp->maxy < 0)
|
||
|
dp->clocky = -NRAND(-dp->maxy);
|
||
|
else
|
||
|
dp->clocky = NRAND(dp->maxy);
|
||
|
} else if (dp->binary) {
|
||
|
dp->text_width = (6 * (BINARY_WIDTH + BINARY_INC)) + BINARY_WIDTH;
|
||
|
dp->text_height = (4 * (BINARY_HEIGHT + BINARY_INC)) + BINARY_HEIGHT;
|
||
|
dp->maxy = dp->height - dp->text_height;
|
||
|
if (dp->maxy == 0)
|
||
|
dp->clocky = 0;
|
||
|
else if (dp->maxy < 0)
|
||
|
dp->clocky = -NRAND(-dp->maxy);
|
||
|
else
|
||
|
dp->clocky = NRAND(dp->maxy);
|
||
|
} else {
|
||
|
#ifdef USE_MB
|
||
|
dp->text_descent = 0;
|
||
|
dp->text_ascent = font_height(mode_font);
|
||
|
#else
|
||
|
dp->text_descent = mode_font->descent;
|
||
|
dp->text_ascent = mode_font->ascent;
|
||
|
#endif
|
||
|
if (dp->popex) {
|
||
|
dp->str1pta = (char *) POPEX_STRING;
|
||
|
dp->str1ptb = dp->str1pta;
|
||
|
} else if (dp->forest) {
|
||
|
dp->str1pta = (char *) FOREST_STRING;
|
||
|
dp->str1ptb = dp->str1pta;
|
||
|
} else if (dp->hiv) {
|
||
|
dp->str1pta = (char *) HIV_STRING;
|
||
|
dp->str1ptb = dp->str1pta;
|
||
|
} else if (dp->lab) {
|
||
|
dp->str1pta = (char *) LAB_STRING;
|
||
|
dp->str1ptb = dp->str1pta;
|
||
|
} else if (dp->veg) {
|
||
|
dp->str1pta = (char *) VEG_STRING;
|
||
|
dp->str1ptb = dp->str1pta;
|
||
|
} else if (dp->y2k) {
|
||
|
if (Y2K_TIME_START >= timeLocal)
|
||
|
dp->str1pta = (char *) Y2K_STRING;
|
||
|
else
|
||
|
dp->str1pta = (char *) POST_Y2K_STRING;
|
||
|
dp->str1ptb = dp->str1pta;
|
||
|
} else if (dp->millennium) {
|
||
|
if (Y2001_TIME_START >= timeLocal)
|
||
|
dp->str1pta = (char *) Y2001_STRING;
|
||
|
else
|
||
|
dp->str1pta = (char *) POST_Y2001_STRING;
|
||
|
dp->str1ptb = dp->str1pta;
|
||
|
} else {
|
||
|
struct tm *t = localtime((const time_t *) &timeLocal);
|
||
|
|
||
|
if (dp->time24)
|
||
|
(void) strftime(dp->str1, STRSIZE, "%H:%M:%S", t);
|
||
|
else
|
||
|
(void) strftime(dp->str1, STRSIZE, "%I:%M:%S %p", t);
|
||
|
dp->hour = t->tm_hour;
|
||
|
(void) strftime(dp->str2, STRSIZE, "%a %b %d %Y", t);
|
||
|
|
||
|
dp->str1pta = dp->str1;
|
||
|
dp->str1ptb = dp->str1old;
|
||
|
}
|
||
|
if (dp->popex) {
|
||
|
convert(PEOPLE_TIME_START + (PEOPLE_MIN / 60.0) * timeNow, dp->str2);
|
||
|
(void) strncat(dp->str2, PEOPLE_STRING, STRSIZE-strlen(dp->str2));
|
||
|
dp->str2pta = dp->str2;
|
||
|
dp->str2ptb = dp->str2pta;
|
||
|
} else if (dp->forest) {
|
||
|
convert(AREA_TIME_START - (AREA_MIN / 60.0) * timeNow, dp->str2);
|
||
|
(void) strncat(dp->str2, TROPICAL_STRING, STRSIZE-strlen(dp->str2));
|
||
|
(void) strncat(dp->str2, AREA_STRING, STRSIZE-strlen(dp->str2));
|
||
|
dp->str2pta = dp->str2;
|
||
|
dp->str2ptb = dp->str2pta;
|
||
|
} else if (dp->hiv) {
|
||
|
convert(HIV_TIME_START + (HIV_MIN / 60.0) * timeNow, dp->str2);
|
||
|
(void) strncat(dp->str2, CASES_STRING, STRSIZE-strlen(dp->str2));
|
||
|
dp->str2pta = dp->str2;
|
||
|
dp->str2ptb = dp->str2pta;
|
||
|
} else if (dp->lab) {
|
||
|
convert((LAB_MIN / 60.0) * (timeNow - timeAtLastNewYear(timeNow)),
|
||
|
dp->str2);
|
||
|
(void) strncat(dp->str2, YEAR_STRING, STRSIZE-strlen(dp->str2));
|
||
|
dp->str2pta = dp->str2;
|
||
|
dp->str2ptb = dp->str2pta;
|
||
|
} else if (dp->veg) {
|
||
|
convert((VEG_MIN / 60.0) * (timeNow - timeAtLastNewYear(timeNow)),
|
||
|
dp->str2);
|
||
|
(void) strncat(dp->str2, YEAR_STRING, STRSIZE-strlen(dp->str2));
|
||
|
dp->str2pta = dp->str2;
|
||
|
} else if (dp->y2k) {
|
||
|
dayhrminsec(Y2K_TIME_START - timeLocal, dp->tzoffset, dp->str2);
|
||
|
dp->str2pta = dp->str2;
|
||
|
} else if (dp->millennium) {
|
||
|
dayhrminsec(Y2001_TIME_START - timeLocal, dp->tzoffset, dp->str2);
|
||
|
dp->str2pta = dp->str2;
|
||
|
} else {
|
||
|
dp->str2pta = dp->str2;
|
||
|
dp->str2ptb = dp->str2old;
|
||
|
}
|
||
|
|
||
|
dp->text_height = font_height(mode_font);
|
||
|
#ifdef USE_MB
|
||
|
{
|
||
|
XRectangle ink, logical;
|
||
|
|
||
|
XmbTextExtents(mode_font, dp->str1pta, strlen(dp->str1pta), &ink, &logical);
|
||
|
dp->text_width1 = logical.width;
|
||
|
XmbTextExtents(mode_font, dp->str2pta, strlen(dp->str2pta), &ink, &logical);
|
||
|
dp->text_width2 = logical.width;
|
||
|
}
|
||
|
#else
|
||
|
dp->text_width1 = XTextWidth(mode_font, dp->str1pta, strlen(dp->str1pta));
|
||
|
dp->text_width2 = XTextWidth(mode_font, dp->str2pta, strlen(dp->str2pta));
|
||
|
#endif
|
||
|
if (dp->text_width1 > dp->text_width2) {
|
||
|
dp->text_width = dp->text_width1;
|
||
|
dp->text_start1 = 0;
|
||
|
dp->text_start2 = (dp->text_width - dp->text_width2) / 2;
|
||
|
} else {
|
||
|
dp->text_width = dp->text_width2;
|
||
|
dp->text_start1 = (dp->text_width - dp->text_width1) / 2;
|
||
|
dp->text_start2 = 0;
|
||
|
}
|
||
|
dp->maxy = dp->height - dp->text_height - dp->text_descent;
|
||
|
if (dp->maxy - dp->text_ascent == 0)
|
||
|
dp->clocky = dp->text_ascent;
|
||
|
else if (dp->maxy - dp->text_ascent < 0)
|
||
|
dp->clocky = -NRAND(dp->text_ascent - dp->maxy) + dp->text_ascent;
|
||
|
else
|
||
|
dp->clocky = NRAND(dp->maxy - dp->text_ascent) + dp->text_ascent;
|
||
|
}
|
||
|
dp->maxx = dp->width - dp->text_width;
|
||
|
if (dp->maxx == 0)
|
||
|
dp->clockx = dp->text_start1;
|
||
|
else if (dp->maxx < 0)
|
||
|
dp->clockx = -NRAND(-dp->maxx) + dp->text_start1;
|
||
|
else
|
||
|
dp->clockx = NRAND(dp->maxx) + dp->text_start1;
|
||
|
|
||
|
if (MI_NPIXELS(mi) > 2)
|
||
|
dp->color = NRAND(MI_NPIXELS(mi));
|
||
|
|
||
|
/* don't want any exposure events from XCopyPlane */
|
||
|
XSetGraphicsExposures(display, MI_GC(mi), False);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
draw_dclock(ModeInfo * mi)
|
||
|
{
|
||
|
dclockstruct *dp;
|
||
|
|
||
|
if (dclocks == NULL)
|
||
|
return;
|
||
|
dp = &dclocks[MI_SCREEN(mi)];
|
||
|
if (mode_font == None)
|
||
|
return;
|
||
|
|
||
|
MI_IS_DRAWN(mi) = True;
|
||
|
drawDclock(mi);
|
||
|
if (MI_NPIXELS(mi) > 2) {
|
||
|
if (++dp->color >= MI_NPIXELS(mi))
|
||
|
dp->color = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
refresh_dclock(ModeInfo * mi)
|
||
|
{
|
||
|
MI_CLEARWINDOW(mi);
|
||
|
}
|
||
|
|
||
|
#endif /* MODE_dclock */
|