summaryrefslogtreecommitdiffstats
path: root/hacks
diff options
context:
space:
mode:
Diffstat (limited to 'hacks')
-rw-r--r--hacks/bsod.c26
-rw-r--r--hacks/ccurve.c2
-rw-r--r--hacks/config/README4
-rw-r--r--hacks/config/bouncingcow.xml6
-rw-r--r--hacks/config/deepstars.xml29
-rw-r--r--hacks/config/flyingtoasters.xml1
-rw-r--r--hacks/config/glplanet.xml11
-rw-r--r--hacks/config/gravitywell.xml44
-rw-r--r--hacks/config/hexadrop.xml2
-rw-r--r--hacks/config/imsmap.xml2
-rw-r--r--hacks/config/unknownpleasures.xml2
-rw-r--r--hacks/filmleader.c20
-rw-r--r--hacks/fontglide.c4
-rw-r--r--hacks/fps.c45
-rw-r--r--hacks/fuzzyflakes.c8
-rw-r--r--hacks/glitchpeg.c17
-rw-r--r--hacks/glx/Makefile.in77
-rw-r--r--hacks/glx/bouncingcow.c224
-rw-r--r--hacks/glx/bouncingcow.man5
-rw-r--r--hacks/glx/boxed.c2
-rw-r--r--hacks/glx/circuit.man2
-rw-r--r--hacks/glx/deepstars.c387
-rw-r--r--hacks/glx/deepstars.man57
-rw-r--r--hacks/glx/esper.c4
-rw-r--r--hacks/glx/fliptext.c4
-rw-r--r--hacks/glx/flyingtoasters.c24
-rw-r--r--hacks/glx/flyingtoasters.man4
-rw-r--r--hacks/glx/gears.c6
-rw-r--r--hacks/glx/glhanoi.c4
-rw-r--r--hacks/glx/glplanet.c206
-rw-r--r--hacks/glx/glplanet.man10
-rw-r--r--hacks/glx/glslideshow.c32
-rw-r--r--hacks/glx/gravitywell.c767
-rw-r--r--hacks/glx/gravitywell.man64
-rw-r--r--hacks/glx/hypertorus.c4
-rw-r--r--hacks/glx/jigsaw.c4
-rw-r--r--hacks/glx/lament.c2
-rw-r--r--hacks/glx/peepers.c5
-rw-r--r--hacks/glx/quickhull.c7
-rw-r--r--hacks/glx/sonar-icmp.c53
-rw-r--r--hacks/glx/splodesic.c2
-rw-r--r--hacks/glx/unknownpleasures.c120
-rw-r--r--hacks/glx/unknownpleasures.man6
-rw-r--r--hacks/hexadrop.c54
-rw-r--r--hacks/kumppa.c8
-rw-r--r--hacks/petri.c11
-rw-r--r--hacks/shadebobs.c2
-rwxr-xr-xhacks/webcollage6
-rw-r--r--hacks/xjack.c10
49 files changed, 2193 insertions, 203 deletions
diff --git a/hacks/bsod.c b/hacks/bsod.c
index f3af911..040db54 100644
--- a/hacks/bsod.c
+++ b/hacks/bsod.c
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1998-2018 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1998-2019 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@@ -6391,9 +6391,9 @@ static const char *bsod_defaults [] = {
".win10.fontB: Arial 50, Helvetica 50",
".win10.fontC: Arial 9, Helvetica 9",
- /* The real Solaris font is ../OSX/Gallant19.bdf but I don't know how
- to convert that to a TTF, so let's use Luxi Mono instead. */
- ".solaris.font: Luxi Mono 12, PxPlus IBM VGA8 12, Courier Bold 12",
+ /* The real Solaris font is Gallant (../OSX/gallant12x22.ttf)
+ but Luxi Mono (../OSX/luximr.ttf) is pretty close as well. */
+ ".solaris.font: Gallant12x22 12, Luxi Mono 12, PxPlus IBM VGA8 12, Courier Bold 12",
/* "Arial" loads "ArialMT" but "Arial Bold" does not load "Arial-BoldMT"? */
".ransomware.font: Arial 11, Helvetica 11",
@@ -6413,7 +6413,7 @@ static const char *bsod_defaults [] = {
".macinstall.bigFont: -*-helvetica-medium-r-*-*-*-120-*-*-*-*-*-*",
".msdos.font: PxPlus IBM VGA8 32",
".nt.font: PxPlus IBM VGA8 12",
- ".solaris.font: Luxi Mono 12, PxPlus IBM VGA8 12, Courier Bold 12",
+ ".solaris.font: Gallant12x22 14, Luxi Mono 12, PxPlus IBM VGA8 12, Courier Bold 12",
".win10.font: -*-helvetica-medium-r-*-*-*-120-*-*-*-*-*-*",
".win10.bigFont: -*-helvetica-medium-r-*-*-*-120-*-*-*-*-*-*",
@@ -6433,7 +6433,7 @@ static const char *bsod_defaults [] = {
".mac.bigFont: Monaco 18, Courier Bold 18",
".macsbug.font: Monaco 10, Courier Bold 9",
- ".macsbug.bigFont: Monaco 24, Courier Bold 24",
+ ".macsbug.bigFont: Monaco 10, Courier Bold 9",
".macx.font: Courier Bold 9",
".macx.bigFont: Courier Bold 14",
@@ -6442,13 +6442,13 @@ static const char *bsod_defaults [] = {
".macinstall.font: Helvetica 24, Arial 24",
".macinstall.bigFont: Helvetica 24, Arial 24",
- ".hvx.bigFont: PxPlus IBM VGA8 16, Courier Bold 14",
- ".hppalinux.bigFont: PxPlus IBM VGA8 16, Courier Bold 14",
- ".linux.bigFont: PxPlus IBM VGA8 16, Courier Bold 14",
- ".hpux.bigFont: PxPlus IBM VGA8 16, Courier Bold 14",
- ".msdos.font: PxPlus IBM VGA8 16, Courier Bold 14",
- ".solaris.font: Luxi Mono 12, PxPlus IBM VGA8 12, Courier Bold 12",
- ".solaris.bigFont: Luxi Mono 16, PxPlus IBM VGA8 16, Courier Bold 14",
+ ".hvx.bigFont: PxPlus IBM VGA8 24, Courier Bold 14",
+ ".hppalinux.bigFont: PxPlus IBM VGA8 24, Courier Bold 14",
+ ".linux.bigFont: PxPlus IBM VGA8 24, Courier Bold 14",
+ ".hpux.bigFont: PxPlus IBM VGA8 24, Courier Bold 14",
+ ".msdos.font: PxPlus IBM VGA8 24, Courier Bold 14",
+ ".solaris.font: Gallant12x22 12, Luxi Mono 12, PxPlus IBM VGA8 12, Courier Bold 12",
+ ".solaris.bigFont: Gallant12x22 22, Luxi Mono 16, PxPlus IBM VGA8 16, Courier Bold 14",
".win10.font: Arial 24, Helvetica 24",
".win10.bigFont: Arial 24, Helvetica 24",
diff --git a/hacks/ccurve.c b/hacks/ccurve.c
index a4423b2..874ada8 100644
--- a/hacks/ccurve.c
+++ b/hacks/ccurve.c
@@ -223,7 +223,7 @@ self_similar_normalized (struct state *st,
double x = 0.0;
double y = 0.0;
- replacement = (Position*)(malloc (segment_count * sizeof (Segment)));
+ replacement = (Position*)(malloc (segment_count * sizeof (*replacement)));
copy_points (segment_count, points, replacement);
assert (fabs ((replacement [segment_count - 1].x) - 1.0) < EPSILON);
assert (fabs (replacement [segment_count - 1].y) < EPSILON);
diff --git a/hacks/config/README b/hacks/config/README
index 5981463..58c4195 100644
--- a/hacks/config/README
+++ b/hacks/config/README
@@ -4,8 +4,8 @@
a screen saver and locker for the X window system
by Jamie Zawinski
- version 5.42
- 28-Dec-2018
+ version 5.43
+ 09-Jul-2019
https://www.jwz.org/xscreensaver/
diff --git a/hacks/config/bouncingcow.xml b/hacks/config/bouncingcow.xml
index 0e3dfe5..abbb0cb 100644
--- a/hacks/config/bouncingcow.xml
+++ b/hacks/config/bouncingcow.xml
@@ -19,7 +19,11 @@
_label="Number of cows" _low-label="Moo" _high-label="Herd"
low="1" high="9" default="1"/>
- <boolean id="wire" _label="Wireframe" arg-set="-wireframe"/>
+ <boolean id="mathematical"
+ _label="Mathematically ideal cows (spherical, frictionless)"
+ arg-set="-mathematical"/>
+
+ <boolean id="wire" _label="Wireframe" arg-set="-wireframe"/>
<boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
<xscreensaver-updater />
diff --git a/hacks/config/deepstars.xml b/hacks/config/deepstars.xml
new file mode 100644
index 0000000..e1118e2
--- /dev/null
+++ b/hacks/config/deepstars.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="deepstars" _label="DeepStars" gl="yes">
+
+ <command arg="-root"/>
+
+ <video href="https://www.youtube.com/watch?v=_FhYeKXGpxs"/>
+
+ <number id="delay" type="slider" arg="-delay %"
+ _label="Frame rate" _low-label="Low" _high-label="High"
+ low="0" high="100000" default="30000"
+ convert="invert"/>
+
+ <number id="speed" type="slider" arg="-speed %"
+ _label="Speed" _low-label="Slow" _high-label="Fast"
+ low="0.01" high="8.0" default="1.0"/>
+
+ <number id="smear" type="slider" arg="-smear %"
+ _label="Smear" _low-label="Low" _high-label="High"
+ low="0.1" high="5.0" default="1.0"/>
+
+ <xscreensaver-updater />
+
+ <_description>
+A long exposure of the night sky, showing star paths as vapor trails.
+
+Written by Jamie Zawinski; 2019.
+ </_description>
+</screensaver>
diff --git a/hacks/config/flyingtoasters.xml b/hacks/config/flyingtoasters.xml
index 7df6459..6b5f1f1 100644
--- a/hacks/config/flyingtoasters.xml
+++ b/hacks/config/flyingtoasters.xml
@@ -25,6 +25,7 @@
<hgroup>
<boolean id="tex" _label="Chrome" arg-unset="-no-texture"/>
+ <boolean id="fog" _label="Fog" arg-unset="-no-fog"/>
<boolean id="wire" _label="Wireframe" arg-set="-wireframe"/>
<boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
</hgroup>
diff --git a/hacks/config/glplanet.xml b/hacks/config/glplanet.xml
index 5714b7a..802f629 100644
--- a/hacks/config/glplanet.xml
+++ b/hacks/config/glplanet.xml
@@ -5,6 +5,7 @@
<command arg="-root"/>
<video href="https://www.youtube.com/watch?v=ohcJ1bVkLZ4"/>
+<!--<video href="https://www.youtube.com/watch?v=OZ6zRLLFLk4"/>-->
<number id="delay" type="slider" arg="-delay %"
_label="Frame rate" _low-label="Low" _high-label="High"
@@ -21,10 +22,18 @@
<boolean id="rotate" _label="Rotate" arg-unset="-no-rotate"/>
<boolean id="roll" _label="Roll" arg-unset="-no-roll"/>
<boolean id="stars" _label="Stars" arg-unset="-no-stars"/>
+ <select id="mode">
+ <option id="globe" _label="Globe"/>
+ <option id="mercator" _label="Mercator"
+ arg-set="-mode mercator"/>
+ <option id="equirectangular" _label="Equirectangular"
+ arg-set="-mode equirectangular"/>
+ </select>
+
</hgroup>
<hgroup>
- <boolean id="wire" _label="Wireframe" arg-set="-wireframe"/>
+ <boolean id="wire" _label="Wireframe" arg-set="-wireframe"/>
<boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
</hgroup>
diff --git a/hacks/config/gravitywell.xml b/hacks/config/gravitywell.xml
new file mode 100644
index 0000000..ebecd1c
--- /dev/null
+++ b/hacks/config/gravitywell.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="gravitywell" _label="GravityWell" gl="yes">
+
+ <command arg="-root"/>
+
+ <video href="https://www.youtube.com/watch?v=yhsw0QhIjjs"/>
+
+ <hgroup>
+ <vgroup>
+
+ <number id="delay" type="slider" arg="-delay %"
+ _label="Frame rate" _low-label="Low" _high-label="High"
+ low="0" high="100000" default="30000"
+ convert="invert"/>
+
+ <number id="speed" type="slider" arg="-speed %"
+ _label="Speed" _low-label="Slow" _high-label="Fast"
+ low="0.01" high="8.0" default="1.0"/>
+
+ <number id="resolution" type="slider" arg="-resolution %"
+ _label="Resolution" _low-label="Low" _high-label="High"
+ low="1.0" high="5.0" default="1.0"/>
+ </vgroup>
+ <vgroup>
+
+ <number id="grid-size" type="slider" arg="-grid-size %"
+ _label="Grid Size" _low-label="Dense" _high-label="Sparse"
+ low="0.1" high="5.0" default="1.0"/>
+
+ <number id="count" type="slider" arg="-count %"
+ _label="Number of stars" _low-label="One" _high-label="Lots"
+ low="1" high="40" default="15"/>
+ </vgroup>
+ </hgroup>
+
+ <xscreensaver-updater />
+
+ <_description>
+Massive objects distort space in a two dimensional universe.
+
+Written by Jamie Zawinski; 2019.
+ </_description>
+</screensaver>
diff --git a/hacks/config/hexadrop.xml b/hacks/config/hexadrop.xml
index 8f8baef..b845963 100644
--- a/hacks/config/hexadrop.xml
+++ b/hacks/config/hexadrop.xml
@@ -35,7 +35,7 @@
<select id="uniform">
<option id="r-uniform" _label="Random speed"/>
<option id="uniform" _label="Uniform speed" arg-set="-uniform-speed"/>
- <option id="no-uniform" _label="Non-uniform speed" arg-set="-no-uniform-speed"/>
+ <option id="no-uniform" _label="Non-uniform speed" arg-set="-nonuniform-speed"/>
</select>
<select id="lockstep">
diff --git a/hacks/config/imsmap.xml b/hacks/config/imsmap.xml
index f3d3cb2..f0feda9 100644
--- a/hacks/config/imsmap.xml
+++ b/hacks/config/imsmap.xml
@@ -21,7 +21,7 @@
<number id="ncolors" type="slider" arg="-ncolors %"
_label="Number of colors" _low-label="Two" _high-label="Many"
- low="1" high="255" default="50"/>
+ low="3" high="255" default="50"/>
<select id="mode">
<option id="random" _label="Random coloration"/>
diff --git a/hacks/config/unknownpleasures.xml b/hacks/config/unknownpleasures.xml
index 0730599..8cac817 100644
--- a/hacks/config/unknownpleasures.xml
+++ b/hacks/config/unknownpleasures.xml
@@ -44,6 +44,8 @@
<boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
</hgroup>
+ <file id="mask" _label="Mask image" arg="-mask %"/>
+
<xscreensaver-updater />
<_description>
diff --git a/hacks/filmleader.c b/hacks/filmleader.c
index 25b64c4..2aabb9d 100644
--- a/hacks/filmleader.c
+++ b/hacks/filmleader.c
@@ -1,4 +1,4 @@
-/* filmleader, Copyright (c) 2018 Jamie Zawinski <jwz@jwz.org>
+/* filmleader, Copyright (c) 2018-2019 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@@ -223,10 +223,10 @@ filmleader_draw (Display *dpy, Window window, void *closure)
XftTextExtentsUtf8 (dpy, xftfont, (FcChar8 *)
blurbs[i].s[0], strlen(blurbs[i].s[0]),
&extents);
- lbearing = -extents.x;
+ /* lbearing = -extents.x; */
rbearing = extents.width - extents.x;
ascent = extents.y;
- descent = extents.height - extents.y;
+ /* descent = extents.height - extents.y; */
x = (st->w - rbearing) / 2;
y = st->h * 0.1 + ascent;
@@ -245,10 +245,10 @@ filmleader_draw (Display *dpy, Window window, void *closure)
XftTextExtentsUtf8 (dpy, xftfont, (FcChar8 *)
blurbs[i].s[0], strlen(blurbs[i].s[j]),
&extents);
- lbearing = -extents.x;
- rbearing = extents.width - extents.x;
- ascent = extents.y;
- descent = extents.height - extents.y;
+ /* lbearing = -extents.x; */
+ /* rbearing = extents.width - extents.x; */
+ /* ascent = extents.y; */
+ /* descent = extents.height - extents.y; */
}
}
@@ -360,7 +360,7 @@ filmleader_draw (Display *dpy, Window window, void *closure)
lbearing = -extents.x;
rbearing = extents.width - extents.x;
ascent = extents.y;
- descent = extents.height - extents.y;
+ /* descent = extents.height - extents.y; */
x = st->w * 0.1;
y = st->h * 0.1 + ascent;
@@ -377,8 +377,8 @@ filmleader_draw (Display *dpy, Window window, void *closure)
XftTextExtentsUtf8 (dpy, xftfont, (FcChar8 *) s, strlen(s), &extents);
lbearing = -extents.x;
rbearing = extents.width - extents.x;
- ascent = extents.y;
- descent = extents.height - extents.y;
+ /* ascent = extents.y; */
+ /* descent = extents.height - extents.y; */
x = st->w * 0.1;
y = st->h * 0.95;
diff --git a/hacks/fontglide.c b/hacks/fontglide.c
index df8f498..54c11b1 100644
--- a/hacks/fontglide.c
+++ b/hacks/fontglide.c
@@ -2421,8 +2421,8 @@ fontglide_free (Display *dpy, Window window, void *closure)
textclient_close (s->tc);
-// if (s->b && s->b != s->window) XFreePixmap (dpy, s->b);
-// if (s->ba && s->ba != s->b) XFreePixmap (dpy, s->ba);
+/* if (s->b && s->b != s->window) XFreePixmap (dpy, s->b); */
+/* if (s->ba && s->ba != s->b) XFreePixmap (dpy, s->ba); */
XFreeGC (dpy, s->bg_gc);
if (s->charset) free (s->charset);
if (s->font_override) free (s->font_override);
diff --git a/hacks/fps.c b/hacks/fps.c
index a24f623..6322fbe 100644
--- a/hacks/fps.c
+++ b/hacks/fps.c
@@ -1,4 +1,4 @@
-/* fps, Copyright (c) 2001-2018 Jamie Zawinski <jwz@jwz.org>
+/* fps, Copyright (c) 2001-2019 Jamie Zawinski <jwz@jwz.org>
* Draw a frames-per-second display (Xlib and OpenGL).
*
* Permission to use, copy, modify, distribute, and sell this software and its
@@ -170,14 +170,41 @@ fps_compute (fps_state *st, unsigned long polys, double depth)
if (depth >= 0.0)
{
- unsigned long L = strlen (st->string);
- char *s = st->string + L;
- strcat (s, "\nDepth: ");
- sprintf (s + strlen(s), "%.1f", depth);
- L = strlen (s);
- /* Remove trailing ".0" in case depth is not a fraction. */
- if (s[L-2] == '.' && s[L-1] == '0')
- s[L-2] = 0;
+ const char *s = "";
+ unsigned long ldepth = depth;
+# if 0
+ if (depth >= (1024 * 1024 * 1024))
+ ldepth = depth / (1024 * 1024 * 1024), s = "G";
+ else if (depth >= (1024 * 1024)) ldepth >>= 20, s = "M";
+ else if (depth >= 2048) ldepth >>= 10, s = "K";
+# endif
+ strcat (st->string, "\nDepth: ");
+ if (ldepth >= 1000000000)
+ sprintf (st->string + strlen(st->string),
+ "%lu,%03lu,%03lu,%03lu%s ",
+ (ldepth / 1000000000),
+ ((ldepth / 1000000) % 1000),
+ ((ldepth / 1000) % 1000),
+ (ldepth % 1000), s);
+ else if (ldepth >= 1000000)
+ sprintf (st->string + strlen(st->string), "%lu,%03lu,%03lu%s ",
+ (ldepth / 1000000), ((ldepth / 1000) % 1000),
+ (ldepth % 1000), s);
+ else if (ldepth >= 1000)
+ sprintf (st->string + strlen(st->string), "%lu,%03lu%s ",
+ (ldepth / 1000), (ldepth % 1000), s);
+ else if (*s)
+ sprintf (st->string + strlen(st->string), "%lu%s ",
+ ldepth, s);
+ else
+ {
+ int L;
+ sprintf (st->string + strlen(st->string), "%.1f", depth);
+ L = strlen (st->string);
+ /* Remove trailing ".0" in case depth is not a fraction. */
+ if (st->string[L-2] == '.' && st->string[L-1] == '0')
+ st->string[L-2] = 0;
+ }
}
}
diff --git a/hacks/fuzzyflakes.c b/hacks/fuzzyflakes.c
index 7429fa8..d655ca9 100644
--- a/hacks/fuzzyflakes.c
+++ b/hacks/fuzzyflakes.c
@@ -300,8 +300,8 @@ FuzzyFlakesColorHelper(Flake *flake)
iG1 = nG1 * 255;
iB1 = nB1 * 255;
- flake->Colors.Fore = malloc(sizeof(unsigned char) * 8);
- flake->Colors.Bord = malloc(sizeof(unsigned char) * 8);
+ flake->Colors.Fore = malloc(sizeof(char) * 8);
+ flake->Colors.Bord = malloc(sizeof(char) * 8);
sprintf(flake->Colors.Fore, "#%02X%02X%02X", iR0, iG0, iB0);
sprintf(flake->Colors.Bord, "#%02X%02X%02X", iR1, iG1, iB1);
@@ -372,7 +372,7 @@ FuzzyFlakesInit(Flake *flake)
{
if (flake->Colors.Back)
free(flake->Colors.Back);
- flake->Colors.Back = malloc(sizeof(unsigned char) * 8);
+ flake->Colors.Back = malloc(sizeof(char) * 8);
sprintf(flake->Colors.Back, "#%X%X%X%X%X%X", random() % 16,
random() % 16, random() % 16, random() % 16, random() % 16,
random() % 16);
@@ -387,7 +387,7 @@ FuzzyFlakesInit(Flake *flake)
fprintf(stderr, " reverting to random\n");
if (flake->Colors.Back)
free(flake->Colors.Back);
- flake->Colors.Back = malloc(sizeof(unsigned char) * 8);
+ flake->Colors.Back = malloc(sizeof(char) * 8);
sprintf(flake->Colors.Back, "#%X%X%X%X%X%X", random() % 16,
random() % 16, random() % 16, random() % 16, random() % 16,
random() % 16);
diff --git a/hacks/glitchpeg.c b/hacks/glitchpeg.c
index 4f3b052..91a05de 100644
--- a/hacks/glitchpeg.c
+++ b/hacks/glitchpeg.c
@@ -1,4 +1,4 @@
-/* glitchpeg, Copyright (c) 2018 Jamie Zawinski <jwz@jwz.org>
+/* glitchpeg, Copyright (c) 2018-2019 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@@ -232,6 +232,13 @@ xscreensaver_getimage_file_cb (XtPointer closure, int *source, XtInputId *id)
while (L > 0 && (buf[L-1] == '\r' || buf[L-1] == '\n'))
buf[--L] = 0;
+ if (!*file)
+ {
+ fprintf (stderr, "%s: no suitable images in imageDirectory\n",
+ progname);
+ return;
+ }
+
fp = fopen (file, "r");
if (! fp)
{
@@ -286,6 +293,14 @@ glitchpeg_init (Display *dpy, Window window)
XClearWindow (st->dpy, st->window);
+# if 0 /* This check doesn't work, because X11 resources are the devil. */
+ if (! get_boolean_resource (dpy, "chooseRandomImages", "Boolean"))
+ {
+ fprintf (stderr, "%s: chooseRandomImages must be True", progname);
+ exit (1);
+ }
+# endif
+
return st;
}
diff --git a/hacks/glx/Makefile.in b/hacks/glx/Makefile.in
index 91e4d51..482bed3 100644
--- a/hacks/glx/Makefile.in
+++ b/hacks/glx/Makefile.in
@@ -43,6 +43,8 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SETUID = @INSTALL_SETUID@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_DIRS = @INSTALL_DIRS@
+PROG_SETCAP = @PROG_SETCAP@
+SETCAP_FLAGS = cap_net_raw=p
X_CFLAGS = @X_CFLAGS@
X_LIBS = @X_LIBS@
@@ -60,6 +62,9 @@ HACK_LIBS = $(HACK_PRE) @ANIM_LIBS@ $(HACK_POST2)
PNG_LIBS = $(HACK_PRE) @PNG_LIBS@ $(HACK_POST2)
GLE_LIBS = $(HACK_PRE) @GLE_LIBS@ @PNG_LIBS@ $(HACK_POST2)
TEXT_LIBS = @PTY_LIBS@
+#### Is LIBCAP_CFLAGS necessary?
+LIBCAP_CFLAGS = @LIBCAP_CFLAGS@
+LIBCAP_LIBS = @LIBCAP_LIBS@
HACK_SRC = $(srcdir)/..
HACK_BIN = ..
@@ -132,7 +137,7 @@ SRCS = xscreensaver-gl-helper.c normals.c erase-gl.c fps-gl.c \
raverhoop.c hydrostat.c discoball.c cubetwist.c cubestack.c \
splodesic.c hexstrut.c vigilance.c seccam.c esper.c \
razzledazzle.c ships.c peepers.c crumbler.c quickhull.c \
- maze3d.c handsy.c handsy_model.c
+ maze3d.c handsy.c handsy_model.c gravitywell.c deepstars.c
OBJS = xscreensaver-gl-helper.o normals.o erase-gl.o fps-gl.o \
atlantis.o b_draw.o b_lockglue.o b_sphere.o bubble3d.o \
@@ -179,7 +184,7 @@ OBJS = xscreensaver-gl-helper.o normals.o erase-gl.o fps-gl.o \
raverhoop.o hydrostat.o discoball.o cubetwist.o cubestack.o \
splodesic.o hexstrut.o vigilance.o seccam.o esper.o \
razzledazzle.o ships.o peepers.o crumbler.o quickhull.o \
- maze3d.o handsy.o handsy_model.o
+ maze3d.o handsy.o handsy_model.o gravitywell.o deepstars.o
GL_EXES = cage gears moebius pipes sproingies stairs superquadrics \
morph3d rubik atlantis lament bubble3d glplanet pulsar \
@@ -200,9 +205,10 @@ GL_EXES = cage gears moebius pipes sproingies stairs superquadrics \
splitflap dymaxionmap unicrud energystream raverhoop \
hydrostat discoball cubetwist cubestack splodesic \
hexstrut vigilance esper razzledazzle peepers crumbler \
- maze3d handsy
+ maze3d handsy gravitywell deepstars
GLE_EXES = extrusion
SUID_EXES = sonar
+SETCAP_EXES = sonar
GL_UTIL_EXES = xscreensaver-gl-helper
JWZGLES_OBJS = @JWZGLES_OBJS@
HACK_EXES_1 = @GL_EXES@ @GLE_EXES@
@@ -225,7 +231,7 @@ HACK_OBJS = $(JWZGLES_OBJS) $(HACK_BIN)/screenhack.o @ANIM_OBJS@ \
$(UTILS_BIN)/colors.o $(UTILS_BIN)/async_netdb.o \
$(UTILS_BIN)/aligned_malloc.o $(UTILS_BIN)/thread_util.o \
$(UTILS_BIN)/utf8wc.o $(UTILS_BIN)/pow2.o \
- $(UTILS_BIN)/font-retry-xft.o
+ $(UTILS_BIN)/font-retry-xft.o @XMU_OBJS@
HDRS = atlantis.h bubble3d.h buildlwo.h e_textures.h \
grab-ximage.h tube.h sphere.h boxed.h \
@@ -266,7 +272,8 @@ GL_MEN = atlantis.man boxed.man bubble3d.man cage.man circuit.man \
unicrud.man energystream.man raverhoop.man hydrostat.man \
discoball.man cubetwist.man cubestack.man splodesic.man \
hexstrut.man vigilance.man esper.man razzledazzle.man \
- peepers.man crumbler.man maze3d.man handsy.man
+ peepers.man crumbler.man maze3d.man handsy.man \
+ gravitywell.man deepstars.man
MEN = @GL_MEN@
RETIRED_MEN = glforestfire.man
EXTRAS = README Makefile.in dxf2gl.pl vrml2gl.pl wfront2gl.pl \
@@ -321,6 +328,20 @@ install-program:: $(EXES)
exit 1 ; \
fi ; \
done ; \
+ \
+ exes="${SETCAP_EXES}" ; \
+ if [ @SETCAP_HACKS@ = yes ]; then \
+ for program in $$exes; do \
+ echo $(PROG_SETCAP) $(SETCAP_FLAGS) $$idir/$$program ; \
+ if $(PROG_SETCAP) $(SETCAP_FLAGS) $$idir/$$program ; then \
+ true ; \
+ else \
+ echo "" ; \
+ echo "WARNING: unable to setcap $$program" ; \
+ echo "" ; \
+ fi ; \
+ done ; \
+ fi ; \
fi
@@ -898,7 +919,7 @@ skytentacles: skytentacles.o $(TENTACLE_OBJS)
SONAR_OBJS=sonar-sim.o sonar-icmp.o $(HACK_TRACK_OBJS)
sonar: sonar.o $(SONAR_OBJS)
- $(CC_HACK) -o $@ $@.o $(SONAR_OBJS) $(HACK_LIBS)
+ $(CC_HACK) -o $@ $@.o $(SONAR_OBJS) $(HACK_LIBS) $(LIBCAP_LIBS)
JIGSAW_OBJS=normals.o $(UTILS_BIN)/spline.o $(HACK_TRACK_GRAB_OBJS)
jigsaw: jigsaw.o $(JIGSAW_OBJS)
@@ -932,8 +953,8 @@ kaleidocycle: $(KALEIDOCYCLE_OBJS)
quasicrystal: quasicrystal.o $(HACK_TRACK_OBJS)
$(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS)
-unknownpleasures: unknownpleasures.o $(HACK_TRACK_OBJS)
- $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS)
+unknownpleasures: unknownpleasures.o $(PNG) $(HACK_TRACK_OBJS)
+ $(CC_HACK) -o $@ $@.o $(PNG) $(HACK_TRACK_OBJS) $(HACK_LIBS) $(PNG_LIBS)
geodesic: geodesic.o normals.o $(HACK_TRACK_OBJS)
$(CC_HACK) -o $@ $@.o normals.o $(HACK_TRACK_OBJS) $(HACK_LIBS)
@@ -1006,6 +1027,11 @@ handsy: handsy.o $(HANDSY_OBJS)
handsy_dxf::
./dxf2gl.pl --smooth 28 --layers handsy.dxf handsy_model.c
+gravitywell: gravitywell.o $(HACK_TRACK_OBJS)
+ $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS)
+
+deepstars: deepstars.o $(HACK_TRACK_OBJS)
+ $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS)
##############################################################################
#
@@ -1518,6 +1544,23 @@ dangerball.o: $(UTILS_SRC)/visual.h
dangerball.o: $(UTILS_SRC)/yarandom.h
dangerball.o: $(HACK_SRC)/xlockmoreI.h
dangerball.o: $(HACK_SRC)/xlockmore.h
+deepstars.o: ../../config.h
+deepstars.o: $(HACK_SRC)/fps.h
+deepstars.o: $(srcdir)/gltrackball.h
+deepstars.o: $(HACK_SRC)/recanim.h
+deepstars.o: $(HACK_SRC)/screenhackI.h
+deepstars.o: $(srcdir)/sphere.h
+deepstars.o: $(UTILS_SRC)/colors.h
+deepstars.o: $(UTILS_SRC)/erase.h
+deepstars.o: $(UTILS_SRC)/font-retry.h
+deepstars.o: $(UTILS_SRC)/grabscreen.h
+deepstars.o: $(UTILS_SRC)/hsv.h
+deepstars.o: $(UTILS_SRC)/resources.h
+deepstars.o: $(UTILS_SRC)/usleep.h
+deepstars.o: $(UTILS_SRC)/visual.h
+deepstars.o: $(UTILS_SRC)/yarandom.h
+deepstars.o: $(HACK_SRC)/xlockmoreI.h
+deepstars.o: $(HACK_SRC)/xlockmore.h
discoball.o: ../../config.h
discoball.o: $(HACK_SRC)/fps.h
discoball.o: $(srcdir)/gltrackball.h
@@ -2161,6 +2204,22 @@ grab-ximage.o: $(UTILS_SRC)/grabscreen.h
grab-ximage.o: $(UTILS_SRC)/pow2.h
grab-ximage.o: $(UTILS_SRC)/visual.h
grab-ximage.o: $(UTILS_SRC)/xshm.h
+gravitywell.o: ../../config.h
+gravitywell.o: $(HACK_SRC)/fps.h
+gravitywell.o: $(srcdir)/gltrackball.h
+gravitywell.o: $(HACK_SRC)/recanim.h
+gravitywell.o: $(HACK_SRC)/screenhackI.h
+gravitywell.o: $(UTILS_SRC)/colors.h
+gravitywell.o: $(UTILS_SRC)/erase.h
+gravitywell.o: $(UTILS_SRC)/font-retry.h
+gravitywell.o: $(UTILS_SRC)/grabscreen.h
+gravitywell.o: $(UTILS_SRC)/hsv.h
+gravitywell.o: $(UTILS_SRC)/resources.h
+gravitywell.o: $(UTILS_SRC)/usleep.h
+gravitywell.o: $(UTILS_SRC)/visual.h
+gravitywell.o: $(UTILS_SRC)/yarandom.h
+gravitywell.o: $(HACK_SRC)/xlockmoreI.h
+gravitywell.o: $(HACK_SRC)/xlockmore.h
handsy_model.o: ../../config.h
handsy_model.o: $(srcdir)/gllist.h
handsy.o: ../../config.h
@@ -3402,6 +3461,7 @@ unicrud.o: $(HACK_SRC)/xlockmore.h
unknownpleasures.o: ../../config.h
unknownpleasures.o: $(HACK_SRC)/fps.h
unknownpleasures.o: $(srcdir)/gltrackball.h
+unknownpleasures.o: $(srcdir)/grab-ximage.h
unknownpleasures.o: $(HACK_SRC)/recanim.h
unknownpleasures.o: $(HACK_SRC)/screenhackI.h
unknownpleasures.o: $(UTILS_SRC)/colors.h
@@ -3413,6 +3473,7 @@ unknownpleasures.o: $(UTILS_SRC)/resources.h
unknownpleasures.o: $(UTILS_SRC)/usleep.h
unknownpleasures.o: $(UTILS_SRC)/visual.h
unknownpleasures.o: $(UTILS_SRC)/yarandom.h
+unknownpleasures.o: $(HACK_SRC)/ximage-loader.h
unknownpleasures.o: $(HACK_SRC)/xlockmoreI.h
unknownpleasures.o: $(HACK_SRC)/xlockmore.h
vigilance.o: ../../config.h
diff --git a/hacks/glx/bouncingcow.c b/hacks/glx/bouncingcow.c
index bcbea24..5dc9466 100644
--- a/hacks/glx/bouncingcow.c
+++ b/hacks/glx/bouncingcow.c
@@ -1,4 +1,4 @@
-/* bouncingcow, Copyright (c) 2003-2018 Jamie Zawinski <jwz@jwz.org>
+/* bouncingcow, Copyright (c) 2003-2019 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@@ -19,6 +19,7 @@
# define release_cow 0
#define DEF_SPEED "1.0"
#define DEF_TEXTURE "(none)"
+#define DEF_MATHEMATICAL "False"
#undef countof
#define countof(x) (sizeof((x))/sizeof((*x)))
@@ -68,6 +69,8 @@ typedef struct {
GLuint *dlists;
GLuint texture;
+ enum { BOUNCE, INFLATE, DEFLATE } mode;
+ GLfloat ratio;
int nfloaters;
floater *floaters;
@@ -78,16 +81,20 @@ static cow_configuration *bps = NULL;
static GLfloat speed;
static const char *do_texture;
+static Bool mathematical;
static XrmOptionDescRec opts[] = {
{ "-speed", ".speed", XrmoptionSepArg, 0 },
{"-texture", ".texture", XrmoptionSepArg, 0 },
{"+texture", ".texture", XrmoptionNoArg, "(none)" },
+ {"-mathematical", ".mathematical", XrmoptionNoArg, "True" },
+ {"+mathematical", ".mathematical", XrmoptionNoArg, "False" },
};
static argtype vars[] = {
{&speed, "speed", "Speed", DEF_SPEED, t_Float},
{&do_texture, "texture", "Texture", DEF_TEXTURE, t_String},
+ {&mathematical,"mathematical","Mathematical",DEF_MATHEMATICAL,t_Bool},
};
ENTRYPOINT ModeSpecOpt cow_opts = {countof(opts), opts, countof(vars), vars, NULL};
@@ -196,29 +203,33 @@ cow_handle_event (ModeInfo *mi, XEvent *event)
/* Textures
*/
-static Bool
+static void
load_texture (ModeInfo *mi, const char *filename)
{
+ cow_configuration *bp = &bps[MI_SCREEN(mi)];
Display *dpy = mi->dpy;
Visual *visual = mi->xgwa.visual;
char buf[1024];
XImage *image;
+ bp->texture = 0;
if (MI_IS_WIREFRAME(mi))
- return False;
+ return;
if (!filename ||
!*filename ||
!strcasecmp (filename, "(none)"))
{
glDisable (GL_TEXTURE_2D);
- return False;
+ return;
}
image = file_to_ximage (dpy, visual, filename);
- if (!image) return False;
+ if (!image) return;
clear_gl_error();
+ glGenTextures (1, &bp->texture);
+ glBindTexture (GL_TEXTURE_2D, bp->texture);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA,
image->width, image->height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, image->data);
@@ -228,62 +239,24 @@ load_texture (ModeInfo *mi, const char *filename)
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
glPixelStorei (GL_UNPACK_ROW_LENGTH, image->width);
-
- return True;
}
-ENTRYPOINT void
-init_cow (ModeInfo *mi)
+static void
+render_cow (ModeInfo *mi, GLfloat ratio)
{
- cow_configuration *bp;
+ cow_configuration *bp = &bps[MI_SCREEN(mi)];
int wire = MI_IS_WIREFRAME(mi);
int i;
- Bool tex_p = False;
-
- MI_INIT (mi, bps);
-
- bp = &bps[MI_SCREEN(mi)];
-
- bp->glx_context = init_GL(mi);
-
- reshape_cow (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
-
- glShadeModel(GL_SMOOTH);
-
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_NORMALIZE);
- glEnable(GL_CULL_FACE);
-
- if (!wire)
+ if (! bp->dlists)
+ bp->dlists = (GLuint *) calloc (countof(all_objs)+1, sizeof(GLuint));
+ for (i = 0; i < countof(all_objs); i++)
{
- GLfloat pos[4] = {0.4, 0.2, 0.4, 0.0};
-/* GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0};*/
- GLfloat amb[4] = {0.2, 0.2, 0.2, 1.0};
- GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0};
- GLfloat spc[4] = {1.0, 1.0, 1.0, 1.0};
-
- glEnable(GL_LIGHTING);
- glEnable(GL_LIGHT0);
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_CULL_FACE);
-
- glLightfv(GL_LIGHT0, GL_POSITION, pos);
- glLightfv(GL_LIGHT0, GL_AMBIENT, amb);
- glLightfv(GL_LIGHT0, GL_DIFFUSE, dif);
- glLightfv(GL_LIGHT0, GL_SPECULAR, spc);
+ if (bp->dlists[i])
+ glDeleteLists (bp->dlists[i], 1);
+ bp->dlists[i] = glGenLists (1);
}
- bp->trackball = gltrackball_init (False);
-
- bp->dlists = (GLuint *) calloc (countof(all_objs)+1, sizeof(GLuint));
- for (i = 0; i < countof(all_objs); i++)
- bp->dlists[i] = glGenLists (1);
-
- tex_p = load_texture (mi, do_texture);
- if (tex_p)
- glBindTexture (GL_TEXTURE_2D, bp->texture);
-
for (i = 0; i < countof(all_objs); i++)
{
GLfloat black[4] = {0, 0, 0, 1};
@@ -296,7 +269,7 @@ init_cow (ModeInfo *mi)
if (i == HIDE)
{
GLfloat color[4] = {0.63, 0.43, 0.36, 1.00};
- if (tex_p)
+ if (bp->texture)
{
/* if we have a texture, make the base color be white. */
color[0] = color[1] = color[2] = 1.0;
@@ -366,11 +339,121 @@ init_cow (ModeInfo *mi)
glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shiny);
}
- renderList (gll, wire);
+ if (ratio == 0)
+ renderList (gll, wire);
+ else
+ {
+ /* Transition between a physics cow (cow-shaped) and a
+ mathematical cow (spherical).
+ */
+ struct gllist *gll2 = (struct gllist *) malloc (sizeof(*gll2));
+ GLfloat *p = (GLfloat *) malloc (gll->points * 6 * sizeof(*p));
+ GLfloat scale2 = 0.5 + (0.5 * (1-ratio));
+ const GLfloat *pin = (GLfloat *) gll->data;
+ GLfloat *pout = p;
+ int j;
+ GLfloat scale = 10.46;
+
+ memcpy (gll2, gll, sizeof(*gll2));
+ gll2->next = 0;
+ gll2->data = p;
+
+ for (j = 0; j < gll2->points; j++)
+ {
+ const GLfloat *ppi;
+ GLfloat *ppo, d;
+ int k;
+ switch (gll2->format) {
+ case GL_N3F_V3F:
+
+ /* Verts transition from cow-shaped to the surface of
+ the enclosing sphere. */
+ ppi = &pin[3];
+ ppo = &pout[3];
+ d = sqrt (ppi[0]*ppi[0] + ppi[1]*ppi[1] + ppi[2]*ppi[2]);
+ for (k = 0; k < 3; k++)
+ {
+ GLfloat min = ppi[k];
+ GLfloat max = ppi[k] / d * scale;
+ ppo[k] = (min + ratio * (max - min)) * scale2;
+ }
+
+ /* Normals are the ratio between original normals and
+ the radial coordinates. */
+ ppi = &pin[0];
+ ppo = &pout[0];
+ for (k = 0; k < 3; k++)
+ {
+ GLfloat min = ppi[k];
+ GLfloat max = ppi[k] / d;
+ ppo[k] = (min + ratio * (max - min));
+ }
+
+ pin += 6;
+ pout += 6;
+ break;
+ default: abort(); break; /* write me */
+ }
+ }
+
+ renderList (gll2, wire);
+ free (gll2);
+ free (p);
+ }
glEndList ();
}
+}
+
+
+ENTRYPOINT void
+init_cow (ModeInfo *mi)
+{
+ cow_configuration *bp;
+ int wire = MI_IS_WIREFRAME(mi);
+ int i;
+
+ MI_INIT (mi, bps);
+
+ bp = &bps[MI_SCREEN(mi)];
+
+ bp->glx_context = init_GL(mi);
+
+ reshape_cow (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+
+ glShadeModel(GL_SMOOTH);
+
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_NORMALIZE);
+ glEnable(GL_CULL_FACE);
+
+ if (!wire)
+ {
+ GLfloat pos[4] = {0.4, 0.2, 0.4, 0.0};
+/* GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0};*/
+ GLfloat amb[4] = {0.2, 0.2, 0.2, 1.0};
+ GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0};
+ GLfloat spc[4] = {1.0, 1.0, 1.0, 1.0};
+
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
+
+ glLightfv(GL_LIGHT0, GL_POSITION, pos);
+ glLightfv(GL_LIGHT0, GL_AMBIENT, amb);
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, dif);
+ glLightfv(GL_LIGHT0, GL_SPECULAR, spc);
+ }
+
+ bp->trackball = gltrackball_init (False);
+
+ load_texture (mi, do_texture);
+
+ bp->ratio = 0;
+ render_cow (mi, bp->ratio);
+ bp->mode = BOUNCE;
bp->nfloaters = MI_COUNT (mi);
bp->floaters = (floater *) calloc (bp->nfloaters, sizeof (floater));
@@ -482,6 +565,39 @@ draw_cow (ModeInfo *mi)
mi->polygon_count = 0;
+ if (mathematical)
+ {
+ switch (bp->mode) {
+ case BOUNCE:
+ if (bp->ratio == 0 && !(random() % 400))
+ bp->mode = INFLATE;
+ else if (bp->ratio > 0 && !(random() % 2000))
+ bp->mode = DEFLATE;
+ break;
+ case INFLATE:
+ bp->ratio += 0.01;
+ if (bp->ratio >= 1)
+ {
+ bp->ratio = 1;
+ bp->mode = BOUNCE;
+ }
+ break;
+ case DEFLATE:
+ bp->ratio -= 0.01;
+ if (bp->ratio <= 0)
+ {
+ bp->ratio = 0;
+ bp->mode = BOUNCE;
+ }
+ break;
+ default:
+ abort();
+ }
+
+ if (bp->ratio > 0)
+ render_cow (mi, bp->ratio);
+ }
+
# if 0
{
floater F;
diff --git a/hacks/glx/bouncingcow.man b/hacks/glx/bouncingcow.man
index 516d1de..9657d41 100644
--- a/hacks/glx/bouncingcow.man
+++ b/hacks/glx/bouncingcow.man
@@ -10,6 +10,7 @@ bouncingcow - a happy cow on a trampoline in 3D. Moo.
[\-delay \fInumber\fP]
[\-speed \fInumber\fP]
[\-count \fInumber\fP]
+[\-mathematical]
[\-texture \fIfilename\fP]
[\-wireframe]
[\-fps]
@@ -42,6 +43,10 @@ An image file to paint on the cow's hide.
Note that on most systems, GL textures must have dimensions that are a
power of two.
.TP 8
+.B \-mathematical
+Periodically transition to display mathematically ideal cows (spherical,
+frictionless).
+.TP 8
.B \-wireframe
Render in wireframe instead of solid.
.TP 8
diff --git a/hacks/glx/boxed.c b/hacks/glx/boxed.c
index 6ce82bb..7d1b5d0 100644
--- a/hacks/glx/boxed.c
+++ b/hacks/glx/boxed.c
@@ -1248,7 +1248,7 @@ pinit(ModeInfo * mi)
gp->tic = gp->camtic = rnd() * 100.0f;
/* define tex1 (bottom plate) */
- gp->tex1 = (char *)malloc(3*width*height*sizeof(GLuint));
+ gp->tex1 = (char *)malloc(3*width*height*sizeof(*gp->tex1));
texpixels = 256*256; /*width*height;*/
texpixeldata = header_data;
texpixeltarget = gp->tex1;
diff --git a/hacks/glx/circuit.man b/hacks/glx/circuit.man
index 794f97b..f41f51c 100644
--- a/hacks/glx/circuit.man
+++ b/hacks/glx/circuit.man
@@ -44,7 +44,7 @@ Whether the scene should spin.
Rotation speed, 0 - 100. Default: 1.
.TP 8
.B \-light | \-no-light
-Whether to us lighting, or flat coloring.
+Whether to use lighting, or flat coloring.
.TP 8
.B \-fps
Display the current frame rate, CPU load, and polygon count.
diff --git a/hacks/glx/deepstars.c b/hacks/glx/deepstars.c
new file mode 100644
index 0000000..b477e00
--- /dev/null
+++ b/hacks/glx/deepstars.c
@@ -0,0 +1,387 @@
+/* xscreensaver, Copyright (c) 2019 Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#ifdef STANDALONE
+#define DEFAULTS "*delay: 30000 \n" \
+ "*showFPS: False \n" \
+ "*suppressRotationAnimation: True\n" \
+
+# define release_deepstars 0
+# include "xlockmore.h" /* from the xscreensaver distribution */
+#else /* !STANDALONE */
+# include "xlock.h" /* from the xlockmore distribution */
+#endif /* !STANDALONE */
+
+#ifdef USE_GL /* whole file */
+
+#include "sphere.h"
+#include "gltrackball.h"
+
+#define DEF_SPEED "1.0"
+#define DEF_SMEAR "1.0"
+#define SMEAR_BASE 400
+#define SPEED_BASE 0.02
+
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+#undef BELLRAND
+#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3)
+
+static GLfloat speed_arg, smear_arg;
+
+static XrmOptionDescRec opts[] = {
+ {"-speed", ".speed", XrmoptionSepArg, 0 },
+ {"-smear", ".smear", XrmoptionSepArg, 0 },
+};
+
+static argtype vars[] = {
+ {&speed_arg, "speed" ,"Speed", DEF_SPEED, t_Float},
+ {&smear_arg, "smear" ,"Smear", DEF_SMEAR, t_Float},
+};
+
+ENTRYPOINT ModeSpecOpt deepstars_opts = {countof(opts), opts, countof(vars), vars, NULL};
+
+#ifdef USE_MODULES
+ModStruct deepstars_description =
+{"deepstars", "init_deepstars", "draw_deepstars", NULL,
+ "draw_deepstars", "init_deepstars", "free_deepstars", &deepstars_opts,
+ 1000, 1, 2, 1, 4, 1.0, "",
+ "Animates texture mapped sphere (deepstars)", 0, NULL};
+#endif
+
+typedef struct {
+ GLfloat *colors;
+ GLuint starlist, groundlist;
+ int ncolors, starcount, groundcount;
+ GLXContext *glx_context;
+ GLfloat z, latitude, facing;
+ int smear, dsmear;
+ trackball_state *trackball;
+ Bool button_down_p;
+} starstruct;
+
+static starstruct *deepstarss = NULL;
+
+
+ENTRYPOINT void
+reshape_deepstars (ModeInfo *mi, int width, int height)
+{
+ starstruct *gp = &deepstarss[MI_SCREEN(mi)];
+ GLfloat h = (GLfloat) height / (GLfloat) width;
+
+ glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *gp->glx_context);
+
+ glViewport(0, 0, (GLint) width, (GLint) height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-1.0, 1.0, -h, h, 5.0, 200.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef(0.0, 0.0, -40);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+}
+
+
+ENTRYPOINT Bool
+deepstars_handle_event (ModeInfo *mi, XEvent *event)
+{
+ starstruct *gp = &deepstarss[MI_SCREEN(mi)];
+
+ /* Neutralize any horizontal motion, and flip Y */
+ GLfloat rot = current_device_rotation();
+ Bool rotp = ((rot > 45 && rot < 135) ||
+ (rot < -45 && rot > -135));
+
+ if (event->xany.type == ButtonPress ||
+ event->xany.type == ButtonRelease)
+ {
+ if (rotp)
+ {
+ event->xbutton.y = MI_HEIGHT(mi) / 2;
+ event->xbutton.x = MI_WIDTH(mi) - event->xbutton.x;
+ }
+ else
+ {
+ event->xbutton.x = MI_WIDTH(mi) / 2;
+ event->xbutton.y = MI_HEIGHT(mi) - event->xbutton.y;
+ }
+ }
+ else if (event->xany.type == MotionNotify)
+ {
+ if (rotp)
+ {
+ event->xmotion.y = MI_HEIGHT(mi) / 2;
+ event->xmotion.x = MI_WIDTH(mi) - event->xmotion.x;
+ }
+ else
+ {
+ event->xmotion.x = MI_WIDTH(mi) / 2;
+ event->xmotion.y = MI_HEIGHT(mi) - event->xmotion.y;
+ }
+ }
+
+ if (gltrackball_event_handler (event, gp->trackball,
+ MI_WIDTH (mi), MI_HEIGHT (mi),
+ &gp->button_down_p))
+ return True;
+ else if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
+ {
+ if (gp->smear <= 1)
+ gp->dsmear = 1;
+ else
+ gp->dsmear = gp->smear = 0;
+ return True;
+ }
+
+ return False;
+}
+
+
+ENTRYPOINT void
+init_deepstars (ModeInfo * mi)
+{
+ starstruct *gp;
+ int screen = MI_SCREEN(mi);
+
+ int i, j, k;
+ int width = MI_WIDTH(mi);
+ int height = MI_HEIGHT(mi);
+ int size = (width > height ? width : height);
+ int nstars = size * size / 80;
+ int max_size = 3;
+ GLfloat inc = 0.5;
+ int sizes = max_size / inc;
+ GLfloat scale = 1;
+
+ MI_INIT (mi, deepstarss);
+ gp = &deepstarss[screen];
+
+ if ((gp->glx_context = init_GL(mi)) != NULL) {
+ reshape_deepstars(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+ }
+
+# ifdef HAVE_MOBILE
+ scale *= 3;
+ nstars /= 3;
+# else /* !HAVE_MOBILE */
+ if (MI_WIDTH(mi) > 2560) { /* Retina displays */
+ scale *= 2;
+ nstars /= 2;
+ }
+# endif /* !HAVE_MOBILE */
+
+
+ gp->trackball = gltrackball_init (True);
+
+ gp->latitude = 10 + frand(70);
+ gp->facing = 10 * (frand(1.0)-0.5);
+
+ /* Only need a small number of distinct star colors, and we have one
+ display list for each color, so we can modify the alpha.
+ */
+ gp->ncolors = 16;
+ gp->colors = (GLfloat *) malloc (4 * gp->ncolors * sizeof(*gp->colors));
+
+ for (i = 0; i < gp->ncolors; i++)
+ {
+ GLfloat d = 0.1;
+ GLfloat r = 0.15 + frand(0.3);
+ GLfloat g = r + frand(d) - d;
+ GLfloat b = r + frand(d) - d;
+ gp->colors[i*4+0] = r;
+ gp->colors[i*4+1] = g;
+ gp->colors[i*4+2] = b;
+ gp->colors[i*4+3] = 1;
+ }
+
+ gp->starcount = nstars / gp->ncolors;
+ gp->starlist = glGenLists(gp->ncolors);
+ for (i = 0; i < gp->ncolors; i++)
+ {
+ glNewList (gp->starlist + i, GL_COMPILE);
+ for (j = 1; j <= sizes; j++)
+ {
+ glPointSize (inc * j * scale);
+ glBegin (GL_POINTS);
+ for (k = 0; k < gp->starcount / sizes; k++)
+ {
+ GLfloat x = frand(1)-0.5;
+ GLfloat y = frand(1)-0.5;
+ GLfloat z = ((random() & 1)
+ ? frand(1)-0.5
+ : (BELLRAND(1)-0.5)/20); /* milky way */
+ GLfloat d = sqrt (x*x + y*y + z*z);
+ x /= d;
+ y /= d;
+ z /= d;
+ glVertex3f (x, y, z);
+ }
+ glEnd();
+ }
+ glEndList();
+ }
+
+ glDisable (GL_BLEND);
+ gp->groundlist = glGenLists(1);
+ glNewList(gp->groundlist, GL_COMPILE);
+ {
+ GLfloat inc = 0.5;
+ glColor3f (0.02, 0.02, 0.05);
+ glBegin (GL_QUAD_STRIP);
+ gp->groundcount = 50;
+ for (i = 0; i <= gp->groundcount; i++)
+ {
+ glVertex3f (i / (GLfloat) gp->groundcount, 0, 0);
+ glVertex3f (i / (GLfloat) gp->groundcount, inc, 0);
+ inc += 0.1 * (frand(1.0) - 0.5);
+ }
+ glEnd();
+ }
+ glEndList();
+}
+
+
+ENTRYPOINT void
+draw_deepstars (ModeInfo * mi)
+{
+ starstruct *gp = &deepstarss[MI_SCREEN(mi)];
+ Display *dpy = MI_DISPLAY(mi);
+ Window window = MI_WINDOW(mi);
+ int smear_change = 800;
+ int sky_scale = 60;
+ int i, j;
+
+ if (!gp->glx_context)
+ return;
+
+ glDrawBuffer(GL_BACK);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glXMakeCurrent (dpy, window, *gp->glx_context);
+
+ mi->polygon_count = 0;
+
+ glEnable (GL_LINE_SMOOTH);
+ glEnable (GL_POINT_SMOOTH);
+ glDisable (GL_DEPTH_TEST);
+ glDisable (GL_CULL_FACE);
+
+ glPushMatrix();
+
+ gltrackball_rotate (gp->trackball);
+
+ /* At the equator, Polaris is on the horizon. In the Arctic, overhead. */
+ glRotatef (180 - gp->latitude, 1, 0, 0);
+ glRotatef (gp->facing, 0, 1, 0);
+
+ if (gp->dsmear == 0 && !(random() % smear_change))
+ gp->dsmear = 1;
+ else if (gp->smear == SMEAR_BASE * smear_arg && !(random() % smear_change))
+ gp->dsmear = -1;
+
+ if (! gp->button_down_p)
+ gp->smear += gp->dsmear;
+ if (gp->smear < 1) gp->smear = 1;
+ else if (gp->smear > SMEAR_BASE * smear_arg)
+ gp->smear = SMEAR_BASE * smear_arg;
+
+ if (!gp->button_down_p)
+ gp->z -= SPEED_BASE * speed_arg;
+
+ glEnable (GL_BLEND);
+ glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ for (i = 0; i < gp->smear; i++)
+ {
+ GLfloat alpha = 1 - (i / (GLfloat) gp->smear);
+
+ glPushMatrix();
+
+ glRotatef (gp->z - (-i * SPEED_BASE * speed_arg), 0, 0, 1);
+
+# if 0
+ if (i == 0)
+ {
+ glBegin(GL_LINES);
+ glVertex3f(0,0,0); glVertex3f(0,0,-3);
+ glVertex3f(0,-1,0); glVertex3f(0,1,0);
+ glVertex3f(-1,0,0); glVertex3f(1,0,0);
+ glEnd();
+
+ glPushMatrix();
+ glRotatef (90, 1, 0, 0);
+ glScalef (sky_scale, sky_scale, sky_scale);
+ mi->polygon_count += unit_sphere (12, 24, 1);
+ glPopMatrix();
+ }
+# endif
+
+ glRotatef (50, 1, 0, 0); /* Tilt milky way */
+ glScalef (sky_scale, sky_scale, sky_scale);
+
+ for (j = 0; j < gp->ncolors; j++)
+ {
+ gp->colors[j*4+3] = alpha;
+ glColor4fv (&gp->colors[j*4]);
+ glCallList (gp->starlist + j);
+ mi->polygon_count += gp->starcount;
+ }
+ glPopMatrix();
+ }
+
+ glPopMatrix();
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ {
+ glLoadIdentity();
+
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ {
+ glLoadIdentity();
+ glTranslatef (-1, -1, 0);
+ glScalef (2, 0.7, 1);
+ glCallList (gp->groundlist);
+ mi->polygon_count += gp->groundcount;
+ }
+ glPopMatrix();
+ }
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+
+ glMatrixMode(GL_MODELVIEW);
+
+ if (mi->fps_p) do_fps (mi);
+ glFinish();
+ glXSwapBuffers(dpy, window);
+}
+
+
+ENTRYPOINT void
+free_deepstars (ModeInfo * mi)
+{
+ starstruct *gp = &deepstarss[MI_SCREEN(mi)];
+
+ if (!gp->glx_context) return;
+ glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *gp->glx_context);
+ if (gp->colors) free (gp->colors);
+ if (glIsList(gp->groundlist)) glDeleteLists(gp->groundlist, 1);
+ if (glIsList(gp->starlist)) glDeleteLists(gp->starlist, gp->ncolors);
+ if (gp->trackball) gltrackball_free (gp->trackball);
+}
+
+
+XSCREENSAVER_MODULE ("DeepStars", deepstars)
+
+#endif
diff --git a/hacks/glx/deepstars.man b/hacks/glx/deepstars.man
new file mode 100644
index 0000000..bd4a65a
--- /dev/null
+++ b/hacks/glx/deepstars.man
@@ -0,0 +1,57 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+deepstars - screen saver.
+.SH SYNOPSIS
+.B deepstars
+[\-display \fIhost:display.screen\fP]
+[\-visual \fIvisual\fP]
+[\-window]
+[\-root]
+[\-delay \fInumber\fP]
+[\-speed \fInumber\fP]
+[\-smear \fInumber\fP]
+.SH DESCRIPTION
+A long exposure of the night sky, showing star paths as vapor trails.
+.SH OPTIONS
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use. Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-window
+Draw on a newly-created window. This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-delay \fInumber\fP
+Per-frame delay, in microseconds. Default: 30000 (0.03 seconds).
+.TP 8
+.B \-speed \fInumber\fP
+Animation speed. 2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-smear \fInumber\fP
+How long the vapor trails should be.
+2.0 means twice as long, 0.5 means half as long.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 2019 by Jamie Zawinski. Permission to use, copy, modify,
+distribute, and sell this software and its documentation for any purpose is
+hereby granted without fee, provided that the above copyright notice appear
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation. No representations are made about the
+suitability of this software for any purpose. It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski.
diff --git a/hacks/glx/esper.c b/hacks/glx/esper.c
index e7d85a9..90887a8 100644
--- a/hacks/glx/esper.c
+++ b/hacks/glx/esper.c
@@ -210,7 +210,7 @@ typedef enum {
MANUAL_RETICLE_ON,
MANUAL_RETICLE,
MANUAL_BOX_ON,
- MANUAL_BOX,
+ MANUAL_BOX
} anim_state;
typedef enum { NEW, IN, FULL, OUT, DEAD } sprite_state;
@@ -1185,13 +1185,13 @@ static void
draw_flash_sprite (ModeInfo *mi, sprite *sp)
{
/* esper_state *ss = &sss[MI_SCREEN(mi)]; */
+ int wire = MI_IS_WIREFRAME(mi);
GLfloat o = sp->opacity;
if (o <= 0) return;
o = 0.7; /* Too fast to see, so keep it consistent */
glPushMatrix();
- int wire = MI_IS_WIREFRAME(mi);
if (!wire)
glDisable (GL_TEXTURE_2D);
glColor4f (0, 0, 1, o);
diff --git a/hacks/glx/fliptext.c b/hacks/glx/fliptext.c
index 951c188..030900b 100644
--- a/hacks/glx/fliptext.c
+++ b/hacks/glx/fliptext.c
@@ -1,5 +1,5 @@
/*
- * fliptext, Copyright (c) 2005-2015 Jamie Zawinski <jwz@jwz.org>
+ * fliptext, Copyright (c) 2005-2019 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@@ -805,7 +805,7 @@ init_fliptext (ModeInfo *mi)
MI_INIT(mi, scs);
sc = &scs[MI_SCREEN(mi)];
- sc->lines = (line **) calloc (max_lines+1, sizeof(char *));
+ sc->lines = (line **) calloc (max_lines+1, sizeof(*sc->lines));
sc->dpy = MI_DISPLAY(mi);
diff --git a/hacks/glx/flyingtoasters.c b/hacks/glx/flyingtoasters.c
index a527e8b..dce20e7 100644
--- a/hacks/glx/flyingtoasters.c
+++ b/hacks/glx/flyingtoasters.c
@@ -1,4 +1,4 @@
-/* flyingtoasters, Copyright (c) 2003-2018 Jamie Zawinski <jwz@jwz.org>
+/* flyingtoasters, Copyright (c) 2003-2019 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@@ -40,6 +40,7 @@
#define DEF_NTOASTERS "20"
#define DEF_NSLICES "25"
#define DEF_TEXTURE "True"
+#define DEF_FOG "True"
#undef BELLRAND
#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3)
@@ -138,6 +139,7 @@ static GLfloat speed;
static int ntoasters;
static int nslices;
static int do_texture;
+static int do_fog;
static XrmOptionDescRec opts[] = {
{ "-speed", ".speed", XrmoptionSepArg, 0 },
@@ -145,6 +147,8 @@ static XrmOptionDescRec opts[] = {
{ "-nslices", ".nslices", XrmoptionSepArg, 0 },
{"-texture", ".texture", XrmoptionNoArg, "True" },
{"+texture", ".texture", XrmoptionNoArg, "False" },
+ {"-fog", ".fog", XrmoptionNoArg, "True" },
+ {"+fog", ".fog", XrmoptionNoArg, "False" },
};
static argtype vars[] = {
@@ -152,6 +156,7 @@ static argtype vars[] = {
{&ntoasters, "ntoasters", "Count", DEF_NTOASTERS, t_Int},
{&nslices, "nslices", "Count", DEF_NSLICES, t_Int},
{&do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool},
+ {&do_fog, "fog", "Fog", DEF_FOG, t_Bool},
};
ENTRYPOINT ModeSpecOpt toasters_opts = {countof(opts), opts, countof(vars), vars, NULL};
@@ -651,6 +656,12 @@ draw_grid (ModeInfo *mi)
glVertex3f( GRID_SIZE/2, -GRID_SIZE/2, GRID_DEPTH/2);
glVertex3f( GRID_SIZE/2, GRID_SIZE/2, GRID_DEPTH/2);
glEnd();
+ glBegin(GL_QUADS);
+ glVertex3f( GRID_SIZE/2, -GRID_SIZE/2, -GRID_DEPTH/2);
+ glVertex3f( GRID_SIZE/2, GRID_SIZE/2, -GRID_DEPTH/2);
+ glVertex3f( 0, GRID_SIZE/2, -GRID_DEPTH/2);
+ glVertex3f( 0, -GRID_SIZE/2, -GRID_DEPTH/2);
+ glEnd();
glPopMatrix();
if (!MI_IS_WIREFRAME(mi)) glEnable(GL_LIGHTING);
@@ -845,6 +856,15 @@ draw_toasters (ModeInfo *mi)
glTranslatef (0, 0, -GRID_DEPTH/2.5);
draw_grid (mi);
+ if (do_fog && !MI_IS_WIREFRAME(mi))
+ {
+ GLfloat fog_color[4] = { 0, 0, 0, 1 };
+ glFogi (GL_FOG_MODE, GL_EXP2);
+ glFogfv (GL_FOG_COLOR, fog_color);
+ glFogf (GL_FOG_DENSITY, 0.0085);
+ glEnable (GL_FOG);
+ }
+
mi->polygon_count = 0;
for (i = 0; i < bp->nfloaters; i++)
{
@@ -872,11 +892,11 @@ free_toasters (ModeInfo *mi)
if (!bp->glx_context) return;
glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *bp->glx_context);
- if (bp->dlists) free (bp->dlists);
if (bp->floaters) free (bp->floaters);
if (bp->user_trackball) gltrackball_free (bp->user_trackball);
for (i = 0; i < countof(all_objs); i++)
if (glIsList(bp->dlists[i])) glDeleteLists(bp->dlists[i], 1);
+ if (bp->dlists) free (bp->dlists);
if (bp->toast_texture) glDeleteTextures (1, &bp->toast_texture);
# ifndef HAVE_JWZGLES
if (bp->chrome_texture) glDeleteTextures (1, &bp->chrome_texture);
diff --git a/hacks/glx/flyingtoasters.man b/hacks/glx/flyingtoasters.man
index dbe5d5a..1de96da 100644
--- a/hacks/glx/flyingtoasters.man
+++ b/hacks/glx/flyingtoasters.man
@@ -12,6 +12,7 @@ flyingtoasters - 3d space-age jet-powered flying toasters (and toast)
[\-ntoasters \fInumber\fP]
[\-nslices \fInumber\fP]
[\-no-texture]
+[\-no-fog]
[\-wireframe]
[\-fps]
.SH DESCRIPTION
@@ -44,6 +45,9 @@ How many slices of toast to draw. Default 25.
.B \-no-texture
Turn off texture mapping (for slow machines.)
.TP 8
+.B \-no-fog
+Turn off fog (do not fade out distant toasters.)
+.TP 8
.B \-wireframe
Render in wireframe instead of solid.
.TP 8
diff --git a/hacks/glx/gears.c b/hacks/glx/gears.c
index feaae8c..86e7e97 100644
--- a/hacks/glx/gears.c
+++ b/hacks/glx/gears.c
@@ -1,4 +1,4 @@
-/* gears, Copyright (c) 2007-2014 Jamie Zawinski <jwz@jwz.org>
+/* gears, Copyright (c) 2007-2019 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@@ -684,7 +684,7 @@ planetary_gears (ModeInfo *mi)
g0->spokes = 0;
g0->size = INVOLUTE_LARGE;
- bp->gears = (gear **) calloc (6, sizeof(**bp->gears));
+ bp->gears = (gear **) calloc (6, sizeof(*bp->gears));
bp->ngears = 0;
bp->gears[bp->ngears++] = g1;
@@ -768,7 +768,7 @@ init_gears (ModeInfo *mi)
if (total_gears <= 0)
total_gears = 3 + fabs (BELLRAND (8) - 4); /* 3 - 7, mostly 3. */
- bp->gears = (gear **) calloc (total_gears+2, sizeof(**bp->gears));
+ bp->gears = (gear **) calloc (total_gears+2, sizeof(*bp->gears));
bp->ngears = 0;
for (i = 0; i < total_gears; i++)
diff --git a/hacks/glx/glhanoi.c b/hacks/glx/glhanoi.c
index eaf775f..46cdc68 100644
--- a/hacks/glx/glhanoi.c
+++ b/hacks/glx/glhanoi.c
@@ -1296,7 +1296,7 @@ static void initData(glhcfg *glhanoi)
glhanoi->pole[i].size = glhanoi->numberOfDisks;
}
checkAllocAndExit(
- !!(glhanoi->diskPos = calloc(glhanoi->numberOfDisks, sizeof(double))),
+ !!(glhanoi->diskPos = calloc(glhanoi->numberOfDisks, sizeof(float))),
"diskPos");
if (glhanoi->trailQSize) {
@@ -1430,7 +1430,7 @@ static GLubyte *makeTexture(glhcfg *glhanoi, int x_size, int y_size, int z_size,
double xi, yi, zi;
if((textureData =
- calloc(x_size * y_size * z_size, sizeof(GLuint))) == NULL) {
+ calloc(x_size * y_size * z_size, sizeof(GLubyte))) == NULL) {
return NULL;
}
diff --git a/hacks/glx/glplanet.c b/hacks/glx/glplanet.c
index a2f6889..83748cc 100644
--- a/hacks/glx/glplanet.c
+++ b/hacks/glx/glplanet.c
@@ -65,6 +65,7 @@
#define DEF_RESOLUTION "128"
#define DEF_IMAGE "BUILTIN"
#define DEF_IMAGE2 "BUILTIN"
+#define DEF_MODE "globe"
#define BLENDED_TERMINATOR
@@ -83,6 +84,7 @@ static char *which_image;
static char *which_image2;
static int resolution;
static GLfloat spin_arg;
+static char *mode_arg;
static XrmOptionDescRec opts[] = {
{"-rotate", ".rotate", XrmoptionNoArg, "true" },
@@ -96,9 +98,11 @@ static XrmOptionDescRec opts[] = {
{"-stars", ".stars", XrmoptionNoArg, "true" },
{"+stars", ".stars", XrmoptionNoArg, "false" },
{"-spin", ".spin", XrmoptionSepArg, 0 },
+ {"-no-spin", ".spin", XrmoptionNoArg, "0" },
{"-image", ".image", XrmoptionSepArg, 0 },
{"-image2", ".image2", XrmoptionSepArg, 0 },
{"-resolution", ".resolution", XrmoptionSepArg, 0 },
+ {"-mode", ".mode", XrmoptionSepArg, 0 },
};
static argtype vars[] = {
@@ -110,6 +114,7 @@ static argtype vars[] = {
{&spin_arg, "spin", "Spin", DEF_SPIN, t_Float},
{&which_image, "image", "Image", DEF_IMAGE, t_String},
{&which_image2,"image2", "Image", DEF_IMAGE2, t_String},
+ {&mode_arg, "mode" ,"Mode" , DEF_MODE, t_String},
{&resolution, "resolution","Resolution", DEF_RESOLUTION, t_Int},
};
@@ -154,6 +159,7 @@ typedef struct {
Bool button_down_p;
GLuint tex1, tex2;
int draw_axis;
+ enum { GLOBE, EQUIRECTANGULAR, MERCATOR } mode;
} planetstruct;
@@ -268,6 +274,138 @@ setup_texture (ModeInfo * mi)
static void
+unit_mercator (int stacks, int slices, int wire_p, Bool mercp)
+{
+ int i, j;
+ GLfloat x, y, ty, xs, ys;
+ GLfloat lastx = 0, lasty = 0, lastty = 0;
+ GLfloat r, north, south;
+
+ /* #### TODO: the grid lines are always rendered as Equirectangular,
+ not Mercator. */
+
+ stacks /= 2;
+ xs = 1.0 / slices;
+ ys = 1.0 / stacks;
+
+ glPushMatrix();
+ r = 1.8;
+ glScalef (r, r, r);
+ glFrontFace(GL_CW);
+
+ r = 0.35; /* Grids are roughly square at equator */
+
+ if (mercp)
+ {
+ /* The poles go to infinity. The traditional Mercator projection
+ omits the Northern and Southern latitudes asymmetrically to
+ move Europe toward the center. How Colonial! */
+ north = 85 / 180.0;
+ south = -66 / 180.0;
+ }
+ else
+ {
+ /* Antarctica should be roughly the same width as North America,
+ but even Equirectangular is crazypants here. */
+ north = 80 / 180.0;
+ south = -north;
+ }
+
+
+ for (j = 0, y = -0.5, ty = 0; j <= stacks;
+ lasty = y, lastty = ty, y += ys, j++)
+ {
+ GLfloat th;
+
+ ty = (0.5 - y) * (south - north) - south;
+ ty += 0.5;
+
+ th = M_PI * (ty - 0.5); /* latitude in radians */
+
+ if (mercp)
+ {
+ /* Obviously I have no idea what I'm doing here */
+ ty = 2 * (atan (pow(M_E, th)) - M_PI/4);
+ ty *= 0.41;
+ ty += 0.5;
+ }
+
+ /* Draw the end caps
+ */
+ if (j == 0 || j == stacks)
+ {
+ GLfloat xx, yy, lxx, lyy;
+ glFrontFace(j == 0 ? GL_CCW : GL_CW);
+
+ if (j == stacks && !wire_p) glEnd();
+
+ glNormal3f (0, (j == 0 ? -1 : 1), 0);
+
+ glBegin (wire_p ? GL_LINE_LOOP : GL_TRIANGLES);
+
+ for (i = 0, x = 0, lastx = 0, lxx = 0;
+ i <= slices;
+ lastx = x, lxx = xx, lyy = yy, x += xs, i++)
+ {
+ xx = r * cos(M_PI * 2 * x);
+ yy = r * sin(M_PI * 2 * x);
+ if (i == 0) continue;
+
+ glTexCoord2f (x, j == 0 ? 0 : 1);
+ glVertex3f (0, y, 0);
+ glTexCoord2f (lastx, ty); glVertex3f (lxx, y, lyy);
+ glTexCoord2f (x, ty); glVertex3f (xx, y, yy);
+ }
+ glEnd();
+ glFrontFace(GL_CW);
+
+ if (!wire_p) glBegin (GL_QUADS);
+ }
+
+ if (j == 0)
+ continue;
+
+ /* Draw one ring of quads.
+ */
+ for (i = 0, x = 0, lastx = 0; i <= slices; lastx = x, x += xs, i++)
+ {
+ GLfloat xx = r * cos(M_PI * 2 * x);
+ GLfloat yy = r * sin(M_PI * 2 * x);
+ GLfloat lx = r * cos(M_PI * 2 * lastx);
+ GLfloat ly = r * sin(M_PI * 2 * lastx);
+ GLfloat y2 = y;
+ GLfloat ly2 = lasty;
+
+#if 0
+ if (mercp)
+ {
+ y2 = ty - 0.5;
+ ly2 = lastty - 0.5;
+ }
+#endif
+
+ if (i == 0) continue;
+ if (wire_p) glBegin(GL_LINE_LOOP);
+ glNormal3f (lx, 0, ly);
+ glTexCoord2f (lastx, lastty); glVertex3f (lx, ly2, ly);
+ glNormal3f (xx, 0, yy);
+ glTexCoord2f (x, lastty); glVertex3f (xx, ly2, yy);
+ glNormal3f (xx, 0, yy);
+ glTexCoord2f (x, ty); glVertex3f (xx, y2, yy);
+ glNormal3f (lx, 0, ly);
+ glTexCoord2f (lastx, ty); glVertex3f (lx, y2, ly);
+ if (wire_p) glEnd();
+ }
+ }
+
+ if (!wire_p) glEnd();
+
+ glPopMatrix();
+}
+
+
+
+static void
init_stars (ModeInfo *mi)
{
planetstruct *gp = &planets[MI_SCREEN(mi)];
@@ -452,6 +590,20 @@ init_planet (ModeInfo * mi)
reshape_planet(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
}
+ if (!mode_arg || !*mode_arg || !strcasecmp(mode_arg, "GLOBE"))
+ gp->mode = GLOBE;
+ else if (!strcasecmp(mode_arg, "EQUIRECTANGULAR"))
+ gp->mode = EQUIRECTANGULAR;
+ else if (!strcasecmp(mode_arg, "mercator"))
+ gp->mode = MERCATOR;
+ else
+ {
+ fprintf (stderr,
+ "%s: mode must be 'globe', 'merecator' or 'equirectangular',"
+ " not '%s'\n", progname, mode_arg);
+ exit (1);
+ }
+
{
char *f = get_string_resource(mi->dpy, "imageForeground", "Foreground");
char *b = get_string_resource(mi->dpy, "imageBackground", "Background");
@@ -513,7 +665,10 @@ init_planet (ModeInfo * mi)
glFrontFace(GL_CCW);
glPushMatrix();
glRotatef (90, 1, 0, 0);
- unit_sphere (resolution, resolution, wire);
+ if (gp->mode == GLOBE)
+ unit_sphere (resolution, resolution, wire);
+ else
+ unit_mercator (resolution, resolution, wire, (gp->mode == MERCATOR));
glPopMatrix();
glEndList();
@@ -533,24 +688,27 @@ init_planet (ModeInfo * mi)
}
# endif
- glPushMatrix();
- glScalef (1.01, 1.01, 1.01);
- unit_dome (resolution, resolution, wire);
-
-# ifdef BLENDED_TERMINATOR
- terminator_tube (mi, resolution);
- if (!wire)
+ if (gp->mode == GLOBE)
{
- /* We have to draw the transparent side of the mask too,
- though I'm not sure why. */
- GLfloat c[] = { 0, 0, 0, 0 };
- glColor4fv (c);
- if (!do_texture)
- glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, c);
- glRotatef (180, 1, 0, 0);
+ glPushMatrix();
+ glScalef (1.01, 1.01, 1.01);
unit_dome (resolution, resolution, wire);
- }
+
+# ifdef BLENDED_TERMINATOR
+ terminator_tube (mi, resolution);
+ if (!wire)
+ {
+ /* We have to draw the transparent side of the mask too,
+ though I'm not sure why. */
+ GLfloat c[] = { 0, 0, 0, 0 };
+ glColor4fv (c);
+ if (!do_texture)
+ glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, c);
+ glRotatef (180, 1, 0, 0);
+ unit_dome (resolution, resolution, wire);
+ }
# endif
+ }
glPopMatrix();
glEndList();
@@ -562,8 +720,10 @@ init_planet (ModeInfo * mi)
glPushMatrix ();
glRotatef (90, 1, 0, 0); /* unit_sphere is off by 90 */
glRotatef (8, 0, 1, 0); /* line up the time zones */
- unit_sphere (12, 24, 1);
- unit_sphere (12, 24, 1);
+ if (gp->mode == GLOBE)
+ unit_sphere (12, 24, 1);
+ else
+ unit_mercator (20, 24, 1, (gp->mode == MERCATOR));
glBegin(GL_LINES);
glVertex3f(0, -2, 0);
glVertex3f(0, 2, 0);
@@ -599,7 +759,8 @@ draw_planet (ModeInfo * mi)
if (do_rotate && !gp->button_down_p)
{
- gp->z -= 0.001 * spin_arg; /* the sun sets in the west */
+ int wat = gp->mode == GLOBE ? 1 : -1;
+ gp->z -= 0.001 * spin_arg * wat; /* the sun sets in the west */
if (gp->z < 0) gp->z += 1;
}
@@ -685,7 +846,7 @@ draw_planet (ModeInfo * mi)
glPopMatrix();
}
- else if (!do_texture || gp->tex2)
+ else if (!do_texture || (gp->tex2 && gp->mode == GLOBE))
{
/* Originally we just used GL_LIGHT0 to produce the day/night sides of
the planet, but that always looked crappy, even with a vast number of
@@ -802,6 +963,11 @@ draw_planet (ModeInfo * mi)
#endif /* BLENDED_TERMINATOR */
}
+ else if (gp->mode != GLOBE)
+ {
+ glDisable (GL_LIGHTING);
+ glDisable (GL_BLEND);
+ }
if (gp->draw_axis)
{
diff --git a/hacks/glx/glplanet.man b/hacks/glx/glplanet.man
index 6a62dc9..f0602a8 100644
--- a/hacks/glx/glplanet.man
+++ b/hacks/glx/glplanet.man
@@ -10,6 +10,7 @@ glplanet - rotating 3d texture-mapped planet.
[\-delay \fInumber\fP]
[\-image \fIfile\fP]
[\-image2 \fIfile\fP]
+[\-mode \fIstring\fP]
[\-resolution \fInumber\fP]
[\-wireframe]
[\-fps]
@@ -40,6 +41,15 @@ The day texture map to wrap around the planet's surface.
The night texture map to wrap around the planet's surface.
The two will be blended together at the dusk terminator.
.TP 8
+.B \-mode globe
+All is right with the world.
+.TP 8
+.B \-mode equirectangular
+Wat.
+.TP 8
+.B \-mode mercator
+Good day, Sir. I said GOOD DAY.
+.TP 8
.B \-resolution
The resolution of the planetary mesh. Default: 128.
.TP 8
diff --git a/hacks/glx/glslideshow.c b/hacks/glx/glslideshow.c
index 77c741c..0edc1eb 100644
--- a/hacks/glx/glslideshow.c
+++ b/hacks/glx/glslideshow.c
@@ -388,8 +388,8 @@ destroy_image (ModeInfo *mi, image *img)
int i;
if (!img) abort();
- if (!img->loaded_p) abort();
- if (!img->used_p) abort();
+ /* if (!img->loaded_p) abort(); */
+ /* if (!img->used_p) abort(); */
if (img->texid <= 0) abort();
if (img->refcount != 0) abort();
@@ -1200,6 +1200,10 @@ draw_slideshow (ModeInfo *mi)
new_sprite (mi);
if (!ss->redisplay_needed_p)
+ /* Nothing to do! Don't bother drawing a texture or even swapping the
+ frame buffers. Note that this means that the FPS display will be
+ wrong: "Load" will be frozen on whatever it last was, when in
+ reality it will be close to 0. */
return;
if (debug_p && ss->now - ss->prev_frame_time > 1)
@@ -1222,21 +1226,27 @@ ENTRYPOINT void
free_slideshow (ModeInfo *mi)
{
slideshow_state *ss = &sss[MI_SCREEN(mi)];
- int i;
+ /* int i; */
if (!ss->glx_context) return;
glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *ss->glx_context);
if (ss->font_data) free_texture_font (ss->font_data);
- for (i = 0; i < ss->nimages; i++) {
- if (ss->images[i]) {
- if (ss->images[i]->title) free (ss->images[i]->title);
- if (ss->images[i]->texid) glDeleteTextures (1, &ss->images[i]->texid);
- free (ss->images[i]);
- }
+ ss->font_data = 0;
+
+# if 0
+ /* The lifetime of these objects is incomprehensible.
+ Doing this causes free pointers to be run from the XtInput.
+ */
+ for (i = ss->nimages-1; i >= 0; i--) {
+ if (ss->images[i] && ss->images[i]->refcount == 0)
+ destroy_image (mi, ss->images[i]);
}
- for (i = 0; i < countof(ss->sprites); i++) {
- if (ss->sprites[i]) free (ss->sprites[i]);
+
+ for (i = countof(ss->sprites)-1; i >= 0; i--) {
+ if (ss->sprites[i])
+ destroy_sprite (mi, ss->sprites[i]);
}
+# endif
}
XSCREENSAVER_MODULE_2 ("GLSlideshow", glslideshow, slideshow)
diff --git a/hacks/glx/gravitywell.c b/hacks/glx/gravitywell.c
new file mode 100644
index 0000000..7078764
--- /dev/null
+++ b/hacks/glx/gravitywell.c
@@ -0,0 +1,767 @@
+/* gravitywell, Copyright (c) 2019 Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#define DEFAULTS "*delay: 30000 \n" \
+ "*count: 15 \n" \
+ "*gridColor: #00FF00\n" \
+ "*gridColor2: #FF0000\n" \
+ "*showFPS: False \n" \
+ "*wireframe: False \n"
+
+# define release_gw 0
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+#define DEF_SPEED "1.0"
+#define DEF_RESOLUTION "1.0"
+#define DEF_GRID_SIZE "1.0"
+
+#include "xlockmore.h"
+#include "gltrackball.h"
+#include "colors.h"
+#include "hsv.h"
+
+#include <ctype.h>
+
+#define ASSERT(x)
+
+#ifdef USE_GL /* whole file */
+
+typedef struct {
+ GLfloat mass;
+ GLfloat ro2, rm2, ri2; /* outer/middle/inner */
+ GLfloat ro, radius;
+ GLfloat x, y, dx, dy;
+ GLfloat surface_gravity, depth;
+} star;
+
+typedef struct {
+ GLXContext *glx_context;
+ trackball_state *user_trackball;
+ Bool button_down_p;
+ int nstars;
+ star *stars;
+ int grid_w, grid_h;
+ GLfloat *grid;
+ char *segs;
+ GLfloat *vtx, *col;
+ GLfloat color[4];
+ int ncolors;
+ XColor *colors;
+} gw_configuration;
+
+static gw_configuration *bps = NULL;
+
+static GLfloat speed, resolution, grid_size;
+
+#define RESOLUTION_BASE 512
+#define GRID_SIZE_BASE 7
+#define SPEED_BASE 2.5
+#define MASS_EPSILON 0.03
+#define SLOPE_EPSILON 0.06
+#define GRID_SEG 16u /* Power-of-two here is faster. */
+#define MAX_MASS_COLOR 120
+
+static XrmOptionDescRec opts[] = {
+ { "-speed", ".speed", XrmoptionSepArg, 0 },
+ { "-resolution", ".resolution", XrmoptionSepArg, 0 },
+ { "-grid-size", ".gridSize", XrmoptionSepArg, 0 },
+};
+
+static argtype vars[] = {
+ {&speed, "speed", "Speed", DEF_SPEED, t_Float},
+ {&resolution, "resolution", "Resolution", DEF_RESOLUTION, t_Float},
+ {&grid_size, "gridSize", "GridSize", DEF_GRID_SIZE, t_Float},
+};
+
+ENTRYPOINT ModeSpecOpt gw_opts = {
+ countof(opts), opts, countof(vars), vars, NULL};
+
+
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#define WCLIP(x,hi) MIN(MAX((int)(x),0),(hi))
+
+/* Window management, etc
+ */
+ENTRYPOINT void
+reshape_gw (ModeInfo *mi, int width, int height)
+{
+ GLfloat h = (GLfloat) height / (GLfloat) width;
+ int y = 0;
+
+ if (width > height * 5) { /* tiny window: show middle */
+ height = width * 9/16;
+ y = -height/2;
+ h = height / (GLfloat) width;
+ }
+
+ glViewport (0, y, width, height);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective (40, 1/h, 10, 1000);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ gluLookAt( 0, 0, 30,
+ 0, 0, 0,
+ 0, 1, 0);
+
+ glClear(GL_COLOR_BUFFER_BIT);
+}
+
+
+ENTRYPOINT Bool
+gw_handle_event (ModeInfo *mi, XEvent *event)
+{
+ gw_configuration *bp = &bps[MI_SCREEN(mi)];
+
+ if (gltrackball_event_handler (event, bp->user_trackball,
+ MI_WIDTH (mi), MI_HEIGHT (mi),
+ &bp->button_down_p))
+ return True;
+ return False;
+}
+
+
+static void
+parse_color (ModeInfo *mi, char *key, GLfloat color[4])
+{
+ XColor xcolor;
+ char *string = get_string_resource (mi->dpy, key, "Color");
+ if (!XParseColor (mi->dpy, mi->xgwa.colormap, string, &xcolor))
+ {
+ fprintf (stderr, "%s: unparsable color in %s: %s\n", progname,
+ key, string);
+ exit (1);
+ }
+ free (string);
+
+ color[0] = xcolor.red / 65536.0;
+ color[1] = xcolor.green / 65536.0;
+ color[2] = xcolor.blue / 65536.0;
+ color[3] = 1;
+}
+
+
+static void
+new_star (const gw_configuration *bp, star *s)
+{
+ int w = bp->grid_w * GRID_SEG;
+
+ s->radius = 2 * (2 + frand(3) + frand(3) + frand(3));
+ s->mass = s->radius * 150 * (2 + frand(3) + frand(3) + frand(3));
+
+ s->ro2 = s->mass / MASS_EPSILON;
+ s->ro = sqrt (s->ro2);
+ s->rm2 = pow (s->mass * (2.0f / SLOPE_EPSILON), 2.0f / 3.0f);
+ s->ri2 = s->radius * s->radius;
+ if (s->rm2 < s->ri2)
+ s->rm2 = s->ri2;
+ if (s->ro2 < s->rm2)
+ s->ro2 = s->rm2;
+
+ s->x = w * (s == bp->stars ? 0.5 : (0.35 + frand(0.3)));
+ s->dx = ((frand(1.0) - 0.5) * 0.1) / resolution;
+ s->dy = (0.1 + frand(0.6)) / resolution;
+
+ /* What the experienced gravitation would be at the surface of the
+ star, were the mass actually held in a singularity at its center.
+ */
+ s->surface_gravity = s->mass / s->ri2;
+ s->depth = s->surface_gravity;
+}
+
+
+static void
+move_stars (ModeInfo *mi)
+{
+ gw_configuration *bp = &bps[MI_SCREEN(mi)];
+ int w = bp->grid_w * GRID_SEG;
+ int h = bp->grid_h * GRID_SEG;
+ int i;
+
+ for (i = 0; i < bp->nstars; i++)
+ {
+ star *s = &bp->stars[i];
+ /* Move stars off screen until most of their influence fades */
+ GLfloat off = speed * SPEED_BASE * resolution;
+ s->x += s->dx * off;
+ s->y += s->dy * off;
+
+ if (s->x < -s->ro ||
+ s->y < -s->ro ||
+ s->x >= w + s->ro ||
+ s->y >= h + s->ro)
+ {
+ new_star (bp, s);
+ s->y = -s->ro;
+ }
+ }
+}
+
+
+static void
+calc_o (gw_configuration *bp, GLfloat mass, GLfloat cx, GLfloat y02,
+ unsigned from, unsigned to)
+{
+ GLfloat x0 = cx - from * GRID_SEG;
+ GLfloat g0 = mass / (x0*x0 + y02);
+ unsigned x;
+
+ ASSERT (to <= bp->grid_w || to <= bp->grid_h);
+
+ for (x = from; x < to; x++)
+ {
+ GLfloat *g = &bp->grid[x * GRID_SEG];
+ GLfloat g1;
+
+ x0 = cx - (x + 1) * GRID_SEG;
+ g1 = mass / (x0*x0 + y02);
+
+ g[0] += g0;
+ if (bp->segs[x])
+ {
+ GLfloat d = (g1 - g0) / GRID_SEG;
+ unsigned i;
+ for(i = 1; i != GRID_SEG; i++)
+ {
+ g0 += d;
+ g[i] += g0;
+ }
+ }
+ g0 = g1;
+ }
+}
+
+
+static void
+make_hires (gw_configuration *bp, unsigned from, unsigned to, unsigned w)
+{
+ unsigned x;
+
+ /* One bigger than from/to so that there's a good angle between the middle
+ and inner zones.
+
+ Don't make the last GRID_SEG high-res. This keeps the length consistent.
+ */
+ if (from)
+ from--;
+ from = MIN(from / GRID_SEG, w - 1);
+ to = MIN(to / GRID_SEG + 1, w - 1);
+
+ ASSERT (to <= bp->grid_w - 1 || to <= bp->grid_h - 1);
+
+ for (x = from; x < to; x++)
+ {
+ if (! bp->segs[x])
+ {
+ GLfloat *g = &bp->grid[x * GRID_SEG];
+ GLfloat g0 = g[0], g1 = g[GRID_SEG];
+ GLfloat d = (g1 - g0) / GRID_SEG;
+ unsigned i;
+ for (i = 1; i != GRID_SEG; i++)
+ {
+ g0 += d;
+ g[i] = g0;
+ }
+ bp->segs[x] = True;
+ }
+ }
+}
+
+
+static void
+calc_m (gw_configuration *bp, GLfloat mass, GLfloat cx, GLfloat y02,
+ unsigned from, unsigned to)
+{
+ GLfloat *gridp = bp->grid;
+ unsigned x;
+
+ ASSERT (to <= bp->grid_w * GRID_SEG + 1 || to <= bp->grid_h * GRID_SEG + 1);
+
+ for (x = from; x < to; x++)
+ {
+ /* Inverse square of distance from mass as a point source */
+ GLfloat x0 = cx - x;
+ gridp[x] += mass / (x0*x0 + y02);
+ }
+}
+
+
+#define EASE(r) (sin ((r) * M_PI_2))
+
+static void
+draw_row (ModeInfo *mi, int w, int y, Bool swap)
+{
+ gw_configuration *bp = &bps[MI_SCREEN(mi)];
+ int i;
+ int x;
+ int polys;
+ int w2 = w * GRID_SEG;
+
+ GLfloat *vtx_x;
+ GLfloat *vtx_y;
+ GLfloat *gridp = bp->grid;
+ memset (gridp, 0, w2 * sizeof(*gridp));
+ memset (bp->segs, 0, w);
+
+ for (i = 0; i < bp->nstars; i++)
+ {
+ star *s = &bp->stars[i];
+ GLfloat cx, cy;
+ unsigned olo, ohi, mlo, mhi, ilo, ihi;
+ GLfloat mass, max;
+ /* Move stars off screen until most of their influence fades */
+ GLfloat ro, rm, ri;
+
+ GLfloat y0;
+ GLfloat y02;
+
+ if (swap)
+ {
+ cy = s->x;
+ cx = s->y;
+ }
+ else
+ {
+ cx = s->x;
+ cy = s->y;
+ }
+ mass = s->mass;
+ max = s->surface_gravity;
+
+ y0 = cy - y;
+ y02 = y0 * y0;
+
+ if (y02 > s->ro2) continue;
+
+ ro = sqrtf (s->ro2 - y02);
+ olo = WCLIP((cx - ro) / GRID_SEG + 1, w); /* GLfloat -> int */
+ ohi = WCLIP((cx + ro) / GRID_SEG + 1, w);
+
+ rm = s->rm2 > y02 ? sqrtf (s->rm2 - y02) : 0;
+ mlo = WCLIP((cx - rm) + 1, w2);
+ mhi = WCLIP((cx + rm) + 1, w2);
+
+ ASSERT (mlo <= mhi);
+
+ if (mlo != mhi)
+ {
+ ri = s->ri2 > y02 ? sqrtf (s->ri2 - y02) : 0;
+ ilo = WCLIP(cx - ri + 1, w2);
+ ihi = WCLIP(cx + ri + 1, w2);
+
+ mlo -= mlo % GRID_SEG;
+ mhi += GRID_SEG - 1;
+ mhi -= mhi % GRID_SEG;
+
+ /* These go first. */
+ make_hires (bp, mlo, ilo, w);
+ make_hires (bp, ihi, mhi, w);
+
+ calc_m (bp, mass, cx, y02, mlo, ilo);
+ calc_m (bp, mass, cx, y02, ihi, mhi);
+
+ /* This does a bit more work than it needs to. */
+ for (x = ilo; x < ihi; x++)
+ gridp[x] += max;
+ }
+
+ calc_o (bp, mass, cx, y02, olo, mlo / GRID_SEG);
+ calc_o (bp, mass, cx, y02, mhi / GRID_SEG, ohi);
+ }
+
+ if (swap)
+ {
+ vtx_y = bp->vtx;
+ vtx_x = bp->vtx + 1;
+ }
+ else
+ {
+ vtx_x = bp->vtx;
+ vtx_y = bp->vtx + 1;
+ }
+
+# define COLOR_CODE 0
+
+# if COLOR_CODE
+ {
+ unsigned grid_max = bp->grid_w > bp->grid_h ? bp->grid_w : bp->grid_h;
+ GLfloat *color = malloc(sizeof(GLfloat) * 4 * (grid_max * GRID_SEG + 1));
+ glEnableClientState (GL_COLOR_ARRAY);
+ glColorPointer (4, GL_FLOAT, 0, color);
+# endif
+
+ ASSERT (! bp->segs[w - 1]);
+
+ polys = 0;
+ for (x = 0; x != w; x++)
+ {
+ if (! bp->segs[x])
+ {
+ int ci;
+ size_t vp = polys * 3;
+ size_t cp = polys * 4;
+# if COLOR_CODE
+ GLfloat slope = 0;
+ if (x != 0)
+ slope += fabs(gridp[x * GRID_SEG] - gridp[(x - 1) * GRID_SEG]);
+ if (x != w - 1)
+ slope += fabs(gridp[(x + 1) * GRID_SEG] - gridp[x * GRID_SEG]);
+ slope = 1 - (slope / (SLOPE_EPSILON * 2));
+
+ color[cp] = slope;
+ color[cp + 1] = slope;
+ color[cp + 2] = 1;
+ color[cp + 3] = 1;
+# endif
+ vtx_x[vp] = x * GRID_SEG;
+ bp->vtx[vp + 2] = gridp[x * GRID_SEG];
+ polys += 1;
+
+ ci = EASE (bp->vtx[vp + 2] / MAX_MASS_COLOR) * bp->ncolors;
+ bp->col[cp] = bp->colors[ci].red / 65536.0;
+ bp->col[cp+1] = bp->colors[ci].green / 65536.0;
+ bp->col[cp+2] = bp->colors[ci].blue / 65536.0;
+ bp->col[cp+3] = 1;
+ }
+ else
+ {
+ for(i = 0; i != GRID_SEG; i++)
+ {
+ int ci;
+ size_t vp = (polys + i) * 3;
+ size_t cp = (polys + i) * 4;
+# if COLOR_CODE
+ color[cp] = 1;
+ color[cp + 1] = 0.75;
+ color[cp + 2] = 0;
+ color[cp + 3] = 1;
+# endif
+ vtx_x[vp] = x * GRID_SEG + i;
+ bp->vtx[vp + 2] = gridp[x * GRID_SEG + i];
+
+ ci = EASE (bp->vtx[vp + 2] / MAX_MASS_COLOR) * bp->ncolors;
+ bp->col[cp] = bp->colors[ci].red / 65536.0;
+ bp->col[cp+1] = bp->colors[ci].green / 65536.0;
+ bp->col[cp+2] = bp->colors[ci].blue / 65536.0;
+ bp->col[cp+3] = 1;
+ }
+ polys += GRID_SEG;
+ }
+ }
+
+ for (i = 0; i < polys; i++)
+ vtx_y[i * 3] = y; /* + random() * (MASS_EPSILON / (MAXRAND)); */
+
+ mi->polygon_count += polys;
+ glDrawArrays (GL_LINE_STRIP, 0, polys);
+
+# if COLOR_CODE
+ glDisableClientState (GL_COLOR_ARRAY);
+ free (color);
+ }
+# endif
+}
+
+
+ENTRYPOINT void
+init_gw (ModeInfo *mi)
+{
+ gw_configuration *bp;
+ unsigned grid_max, vtx_max;
+ int i;
+ MI_INIT (mi, bps);
+
+ bp = &bps[MI_SCREEN(mi)];
+
+ bp->glx_context = init_GL(mi);
+
+ reshape_gw (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+
+ glShadeModel(GL_SMOOTH);
+
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_NORMALIZE);
+ glEnable(GL_CULL_FACE);
+
+ {
+ int h1, h2;
+ double s1, v1, s2, v2;
+ GLfloat color2[4];
+ parse_color (mi, "gridColor", bp->color);
+ parse_color (mi, "gridColor2", color2);
+ rgb_to_hsv (bp->color[0] * 65536,
+ bp->color[1] * 65536,
+ bp->color[2] * 65536,
+ &h1, &s1, &v1);
+ rgb_to_hsv (color2[0] * 65536,
+ color2[1] * 65536,
+ color2[2] * 65536,
+ &h2, &s2, &v2);
+ bp->ncolors = 128;
+ bp->colors = (XColor *) calloc(bp->ncolors, sizeof(XColor));
+ make_color_ramp (0, 0, 0,
+ h1, s1, v1, h2, s2, v2,
+ bp->colors, &bp->ncolors,
+ False, 0, False);
+ }
+
+ bp->user_trackball = gltrackball_init (False);
+
+ bp->grid_w = (RESOLUTION_BASE * resolution) / GRID_SEG;
+ if (bp->grid_w < 2) bp->grid_w = 2;
+ bp->grid_h = bp->grid_w;
+
+ grid_max = bp->grid_w > bp->grid_h ? bp->grid_w : bp->grid_h;
+ vtx_max = grid_max * GRID_SEG;
+ bp->grid = (GLfloat *) calloc (vtx_max, sizeof(*bp->grid));
+ bp->vtx = (GLfloat *) calloc (vtx_max * 3, sizeof(*bp->vtx));
+ bp->col = (GLfloat *) calloc (vtx_max * 4, sizeof(*bp->col));
+ bp->segs = (char *) calloc (grid_max, sizeof(*bp->segs));
+ if (! bp->grid || ! bp->vtx || ! bp->col || ! bp->segs) abort();
+
+ bp->nstars = MI_COUNT(mi);
+ bp->stars = (star *) calloc (bp->nstars, sizeof (star));
+
+ for (i = 0; i < bp->nstars; i++)
+ {
+ star *s = &bp->stars[i];
+ new_star (bp, s);
+ s->y = frand(s->ro * 2 + bp->grid_h * GRID_SEG) - s->ro;
+ }
+
+ /* Let's tilt the floor a little. */
+ gltrackball_reset (bp->user_trackball,
+ -0.4 + frand(0.8),
+ -0.3 + frand(0.2));
+}
+
+
+ENTRYPOINT void
+draw_gw (ModeInfo *mi)
+{
+ gw_configuration *bp = &bps[MI_SCREEN(mi)];
+ int wire = MI_IS_WIREFRAME(mi);
+ Display *dpy = MI_DISPLAY(mi);
+ Window window = MI_WINDOW(mi);
+ int gridmod = grid_size * GRID_SIZE_BASE;
+ int x, y, i;
+ int sample_x, sample_y;
+ GLfloat sample_z = -1;
+
+ if (!bp->glx_context)
+ return;
+
+ glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *bp->glx_context);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glPushMatrix ();
+
+# ifdef HAVE_MOBILE
+ glRotatef (current_device_rotation(), 0, 0, 1); /* right side up */
+# endif
+
+ gltrackball_rotate (bp->user_trackball);
+
+#if 0
+ glScalef(0.05/resolution, 0.05/resolution, 0.05/resolution);
+#endif
+
+ glRotatef (90, 1, 0, 0);
+ glTranslatef (-bp->grid_w * (GRID_SEG / 2.0f),
+ -bp->grid_h * (GRID_SEG * 0.75f),
+ 3);
+
+#if 0
+ glColor3f(1,0,0);
+ glPushMatrix();
+ glTranslatef(0,0,0);
+ glScalef (bp->grid_w * GRID_SEG,
+ bp->grid_w * GRID_SEG,
+ bp->grid_w * GRID_SEG);
+ glDisable (GL_FOG);
+ glBegin(GL_LINE_LOOP);
+ glVertex3f(0, 0, 0);
+ glVertex3f(1, 0, 0);
+ glVertex3f(1, 1, 0);
+ glVertex3f(.4, 1, 0);
+ glVertex3f(.5, .5, 0);
+ glVertex3f(.6, 1, 0);
+ glVertex3f(0, 1, 0);
+ glEnd();
+ glPopMatrix();
+ glColor3f(0,1,0);
+ if (!wire) glEnable (GL_FOG);
+#endif
+
+ if (!wire)
+ {
+ GLfloat fog_color[4] = { 0, 0, 0, 1 };
+
+ glLineWidth (2);
+ glEnable (GL_LINE_SMOOTH);
+ glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
+ glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable (GL_BLEND);
+
+ glFogi (GL_FOG_MODE, GL_EXP2);
+ glFogfv (GL_FOG_COLOR, fog_color);
+ glFogf (GL_FOG_DENSITY, 0.005);
+ glEnable (GL_FOG);
+ }
+
+ glEnableClientState (GL_COLOR_ARRAY);
+ glEnableClientState (GL_VERTEX_ARRAY);
+ glColorPointer (4, GL_FLOAT, 0, bp->col);
+ glVertexPointer (3, GL_FLOAT, 0, bp->vtx);
+
+ /* Somewhere near the midpoint of the view */
+ sample_x = ((int) (bp->grid_w * GRID_SEG * 0.5) / gridmod) * gridmod;
+ sample_y = ((int) (bp->grid_h * GRID_SEG * 0.75) / GRID_SEG) * GRID_SEG;
+
+ /* Find the cumulative gravitational effect at the midpoint of each star,
+ for the depth of the foot-circle. This duplicates some of the draw_row()
+ logic. */
+ for (i = 0; i < bp->nstars; i++)
+ {
+ star *s0 = &bp->stars[i];
+ GLfloat x0 = s0->x;
+ GLfloat y0 = s0->y;
+ int j;
+ s0->depth = s0->surface_gravity;
+ for (j = 0; j < bp->nstars; j++)
+ {
+ star *s1;
+ GLfloat x1, y1, d2;
+ if (i == j) continue;
+ s1 = &bp->stars[j];
+ x1 = s1->x;
+ y1 = s1->y;
+ d2 = (x1-x0)*(x1-x0) + (y1-y0)*(y1-y0);
+ s0->depth += s1->mass / d2;
+ }
+ }
+
+ mi->polygon_count = 0;
+ for (y = 0; y < (bp->grid_h - 1) * GRID_SEG; y += gridmod)
+ draw_row (mi, bp->grid_w, y, False);
+ for (x = 0; x < (bp->grid_w - 1) * GRID_SEG; x += gridmod)
+ {
+ draw_row (mi, bp->grid_h, x, True);
+ if (x == sample_x)
+ sample_z = bp->grid[sample_y];
+ }
+
+ if (mi->fps_p)
+ {
+ /* Mass of Sol is 2x10^30kg, or 332 kilo-Earths.
+ But I'm not sure what the funniest number to put here is. */
+ /* mi->recursion_depth = (int) sample_z/4; */
+ mi->recursion_depth = (int) (sample_z * 30000);
+ glColor4fv (bp->color);
+ glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, bp->color);
+ glBegin(GL_LINES);
+ glVertex3f (sample_x-0.15, sample_y-0.15, sample_z);
+ glVertex3f (sample_x+0.15, sample_y+0.15, sample_z);
+ glVertex3f (sample_x-0.15, sample_y+0.15, sample_z);
+ glVertex3f (sample_x+0.15, sample_y-0.15, sample_z);
+ glEnd();
+ }
+
+ /* Draw a circle around the "footprint" at the bottom of the gravity well.
+ */
+ for (i = 0; i < bp->nstars; i++)
+ {
+ int steps = 16;
+ star *s = &bp->stars[i];
+ GLfloat th, color[4];
+ int ci;
+ ci = EASE (s->depth / MAX_MASS_COLOR) * bp->ncolors;
+ color[0] = bp->colors[ci].red / 65536.0;
+ color[1] = bp->colors[ci].green / 65536.0;
+ color[2] = bp->colors[ci].blue / 65536.0;
+ color[3] = 1;
+ glColor4fv (color);
+ glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
+ glPushMatrix();
+ glTranslatef (s->x, s->y, 0);
+ glBegin (GL_LINE_LOOP);
+ for (th = 0; th < M_PI * 2; th += M_PI/steps)
+ glVertex3f (s->radius * cos(th), s->radius * sin(th), s->depth);
+ glEnd();
+ glPopMatrix();
+ mi->polygon_count += steps;
+ }
+
+#if 0
+ {
+ for (i = 0; i < bp->nstars; i++)
+ {
+ star *s = &bp->stars[i];
+ GLfloat maxr = sqrt (s->mass / MASS_EPSILON);
+ GLfloat th;
+ glPushMatrix();
+ glTranslatef (s->x, s->y, 0);
+ glColor3f(0, 0, 1);
+ glBegin (GL_LINE_LOOP);
+ for (th = 0; th < M_PI * 2; th += M_PI/32)
+ glVertex3f (s->radius * cos(th), s->radius * sin(th), 0);
+ glEnd();
+ glColor3f(0, 0, 0.5);
+ glBegin (GL_LINE_LOOP);
+ for (th = 0; th < M_PI * 2; th += M_PI/32)
+ glVertex3f (maxr * cos(th), maxr * sin(th), 0);
+ glEnd();
+ glBegin (GL_LINES);
+ glVertex3f ( 3000 * s->dx, 3000 * s->dy, 0);
+ glVertex3f (-3000 * s->dx, -3000 * s->dy, 0);
+ glEnd();
+ glPopMatrix();
+ }
+ }
+#endif
+
+ glPopMatrix ();
+
+ if (! bp->button_down_p)
+ move_stars (mi);
+
+ if (mi->fps_p) do_fps (mi);
+ glFinish();
+
+ glXSwapBuffers(dpy, window);
+}
+
+
+ENTRYPOINT void
+free_gw (ModeInfo *mi)
+{
+ gw_configuration *bp = &bps[MI_SCREEN(mi)];
+
+ if (!bp->glx_context) return;
+ glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *bp->glx_context);
+
+ if (bp->user_trackball) gltrackball_free (bp->user_trackball);
+ if (bp->stars) free (bp->stars);
+ if (bp->grid) free (bp->grid);
+ if (bp->vtx) free (bp->vtx);
+ if (bp->col) free (bp->col);
+ if (bp->segs) free (bp->segs);
+ if (bp->colors) free (bp->colors);
+}
+
+XSCREENSAVER_MODULE_2 ("GravityWell", gravitywell, gw)
+
+#endif /* USE_GL */
diff --git a/hacks/glx/gravitywell.man b/hacks/glx/gravitywell.man
new file mode 100644
index 0000000..a33d578
--- /dev/null
+++ b/hacks/glx/gravitywell.man
@@ -0,0 +1,64 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+gravitywell - spaaaaace.
+.SH SYNOPSIS
+.B gravitywell
+[\-display \fIhost:display.screen\fP]
+[\-visual \fIvisual\fP]
+[\-window]
+[\-root]
+[\-delay \fInumber\fP]
+[\-speed \fInumber\fP]
+[\-resolution \fInumber\fP]
+[\-grid-size \fInumber\fP]
+[\-count \fInumber\fP]
+.SH DESCRIPTION
+Massive objects distort space in a two dimensional universe.
+.SH OPTIONS
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use. Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-window
+Draw on a newly-created window. This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-delay \fInumber\fP
+Per-frame delay, in microseconds. Default: 30000 (0.03 seconds).
+.TP 8
+.B \-speed \fInumber\fP
+Animation speed. 2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-resolution \fInumber\fP
+Density of the underlying universe. Default: 1.0.
+.TP 8
+.B \-grid-size \fInumber\fP
+Grid Size. Smaller values are more dense. Default: 1.0.
+.TP 8
+.B \-count \fInumber\fP
+Number of stars. Default: 15.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 2019 by Jamie Zawinski. Permission to use, copy, modify,
+distribute, and sell this software and its documentation for any purpose is
+hereby granted without fee, provided that the above copyright notice appear
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation. No representations are made about the
+suitability of this software for any purpose. It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski.
diff --git a/hacks/glx/hypertorus.c b/hacks/glx/hypertorus.c
index df64923..8aa8d4d 100644
--- a/hacks/glx/hypertorus.c
+++ b/hacks/glx/hypertorus.c
@@ -736,6 +736,10 @@ static void display_hypertorus(ModeInfo *mi)
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
+ /* Let's keep a constant aspect ratio rather than stretching with the
+ shape of the window */
+ glScalef (hp->WindH / (GLfloat) hp->WindW, 1, 1);
+
mi->polygon_count = hypertorus(mi,0.0,2.0*M_PI,0.0,2.0*M_PI,64,64);
}
diff --git a/hacks/glx/jigsaw.c b/hacks/glx/jigsaw.c
index 38716e2..9c9e911 100644
--- a/hacks/glx/jigsaw.c
+++ b/hacks/glx/jigsaw.c
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1997-2017 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1997-2019 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@@ -555,7 +555,7 @@ draw_piece (jigsaw_configuration *jc, puzzle_piece *p,
# else /* !HAVE_TESS */
GLfloat *tri = (GLfloat *)
- (GLfloat *) malloc (s->n_points * 4 * 3 * 3 * sizeof(*pts));
+ malloc (s->n_points * 4 * 3 * 3 * sizeof(*tri));
GLfloat *otri = tri;
int count;
GLdouble zz;
diff --git a/hacks/glx/lament.c b/hacks/glx/lament.c
index d84a58f..6af37c4 100644
--- a/hacks/glx/lament.c
+++ b/hacks/glx/lament.c
@@ -209,7 +209,7 @@ typedef enum {
LAMENT_LEVIATHAN_EXPAND,
LAMENT_LEVIATHAN_UNTWIST,
LAMENT_LEVIATHAN_UNFADE,
- LAMENT_LEVIATHAN_UNSPIN,
+ LAMENT_LEVIATHAN_UNSPIN
} lament_type;
diff --git a/hacks/glx/peepers.c b/hacks/glx/peepers.c
index 4d15ff8..3dc8fc1 100644
--- a/hacks/glx/peepers.c
+++ b/hacks/glx/peepers.c
@@ -1,4 +1,4 @@
-/* peepers, Copyright (c) 2018 Jamie Zawinski <jwz@jwz.org>
+/* peepers, Copyright (c) 2018-2019 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@@ -851,7 +851,7 @@ draw_ball (ModeInfo *mi, component which)
polys++;
}
glEnd();
- return polys;
+ goto DONE;
}
for (i = xstart; i <= xstop; i++)
@@ -1009,6 +1009,7 @@ draw_ball (ModeInfo *mi, component which)
if (!wire)
glEnd();
+ DONE:
free (stacks);
free (normals);
diff --git a/hacks/glx/quickhull.c b/hacks/glx/quickhull.c
index 4c46ca0..ff517db 100644
--- a/hacks/glx/quickhull.c
+++ b/hacks/glx/quickhull.c
@@ -1351,10 +1351,11 @@ qh_quickhull3d(qh_vertex_t const* vertices, unsigned int nvertices)
}
for (i = 0; i < context.nfaces; ++i) {
+ qh_half_edge_t e0, e1, e2;
if (!context.valid[i]) { continue; }
- qh_half_edge_t e0 = context.edges[context.faces[i].edges[0]];
- qh_half_edge_t e1 = context.edges[context.faces[i].edges[1]];
- qh_half_edge_t e2 = context.edges[context.faces[i].edges[2]];
+ e0 = context.edges[context.faces[i].edges[0]];
+ e1 = context.edges[context.faces[i].edges[1]];
+ e2 = context.edges[context.faces[i].edges[2]];
m.vertices[m.nvertices++] = context.vertices[e0.to_vertex];
m.vertices[m.nvertices++] = context.vertices[e1.to_vertex];
diff --git a/hacks/glx/sonar-icmp.c b/hacks/glx/sonar-icmp.c
index 862f358..961dcf5 100644
--- a/hacks/glx/sonar-icmp.c
+++ b/hacks/glx/sonar-icmp.c
@@ -1,4 +1,4 @@
-/* sonar, Copyright (c) 1998-2018 Jamie Zawinski and Stephen Martin
+/* sonar, Copyright (c) 1998-2019 Jamie Zawinski and Stephen Martin
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@@ -68,6 +68,9 @@
# ifdef HAVE_GETIFADDRS
# include <ifaddrs.h>
# endif
+# ifdef HAVE_LIBCAP
+# include <sys/capability.h>
+# endif
#endif /* HAVE_ICMP || HAVE_ICMPHDR */
#if defined(HAVE_ICMP)
@@ -1483,7 +1486,7 @@ parse_mode (sonar_sensor_data *ssd, char **error_ret, char **desc_ret,
if (!ping_works_p)
{
- *error_ret = strdup ("Sonar must be setuid to ping!\n"
+ *error_ret = strdup ("Sonar must be setuid or libcap to ping!\n"
"Running simulation instead.");
return 0;
}
@@ -1569,6 +1572,46 @@ parse_mode (sonar_sensor_data *ssd, char **error_ret, char **desc_ret,
}
+static Bool
+set_net_raw_capalibity(int enable_p)
+{
+ Bool ret_status = False;
+# ifdef HAVE_LIBCAP
+ cap_t cap_status;
+ cap_value_t cap_value[] = { CAP_NET_RAW, };
+ cap_flag_value_t cap_flag_value;
+ cap_flag_value_t new_value = enable_p ? CAP_SET : CAP_CLEAR;
+
+ cap_status = cap_get_proc();
+ do {
+ cap_flag_value = CAP_CLEAR;
+ if (cap_get_flag (cap_status, CAP_NET_RAW, CAP_EFFECTIVE, &cap_flag_value))
+ break;
+ if (cap_flag_value == new_value)
+ {
+ ret_status = True;
+ break;
+ }
+
+ cap_set_flag (cap_status, CAP_EFFECTIVE, 1, cap_value, new_value);
+ if (!cap_set_proc(cap_status))
+ ret_status = True;
+ } while (0);
+
+ if (cap_status) cap_free (cap_status);
+# endif /* HAVE_LIBCAP */
+
+ return ret_status;
+}
+
+static Bool
+set_ping_capability (void)
+{
+ if (geteuid() == 0) return True;
+ return set_net_raw_capalibity (True);
+}
+
+
sonar_sensor_data *
sonar_init_ping (Display *dpy, char **error_ret, char **desc_ret,
const char *subnet, int timeout,
@@ -1615,6 +1658,10 @@ sonar_init_ping (Display *dpy, char **error_ret, char **desc_ret,
On MacOS X, we can avoid the whole problem by using a
non-privileged datagram instead of a raw socket.
+
+ On recent Linux systems (2012-ish?) we can avoid setuid by instead
+ using cap_set_flag(... CAP_NET_RAW). To make that call the executable
+ needs to have "sudo setcap cap_net_raw=p sonar" done to it first.
*/
if (global_icmpsock)
{
@@ -1628,7 +1675,7 @@ sonar_init_ping (Display *dpy, char **error_ret, char **desc_ret,
{
socket_initted_p = True;
}
- else if (geteuid() == 0 &&
+ else if (set_ping_capability() &&
(pd->icmpsock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) >= 0)
{
socket_initted_p = True;
diff --git a/hacks/glx/splodesic.c b/hacks/glx/splodesic.c
index a68e992..9a2f3a6 100644
--- a/hacks/glx/splodesic.c
+++ b/hacks/glx/splodesic.c
@@ -249,7 +249,7 @@ static void
link_neighbors (ModeInfo *mi)
{
splodesic_configuration *bp = &bps[MI_SCREEN(mi)];
- triangle *t0 = bp->triangles;
+ triangle *t0;
int i;
/* Triangles are neighbors if they share an edge (exactly 2 points).
diff --git a/hacks/glx/unknownpleasures.c b/hacks/glx/unknownpleasures.c
index a52819f..1fdee6d 100644
--- a/hacks/glx/unknownpleasures.c
+++ b/hacks/glx/unknownpleasures.c
@@ -1,4 +1,5 @@
-/* unknownpleasures, Copyright (c) 2013-2018 Jamie Zawinski <jwz@jwz.org>
+/* unknownpleasures, Copyright (c) 2013-2018, 2019
+ * -Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@@ -28,10 +29,6 @@
*
* TODO:
*
- * - Load images and feed them line by line into the plotter, so it scrolls.
- *
- * - Same but use the image as a mask against the random graph data.
- *
* - Take a function generator program as a command line argument:
* read lines of N float values from it, interpolate to full width.
*/
@@ -43,6 +40,7 @@
#define DEF_NOISE "1.0"
#define DEF_ASPECT "1.9"
#define DEF_BUZZ "False"
+#define DEF_MASK "(none)"
#define DEFAULTS "*delay: 30000 \n" \
"*count: 80 \n" \
@@ -57,6 +55,8 @@
#include "xlockmore.h"
#include "colors.h"
#include "gltrackball.h"
+#include "ximage-loader.h"
+#include "grab-ximage.h"
#include <ctype.h>
#ifdef USE_GL /* whole file */
@@ -70,6 +70,7 @@ GLfloat amplitude_arg;
GLfloat noise_arg;
GLfloat aspect_arg;
Bool buzz_arg;
+char *mask_arg;
typedef struct {
@@ -88,6 +89,9 @@ typedef struct {
GLuint *lines; /* Display lists for each edge * face * frame */
GLfloat *heights; /* Animated elevation / alpha of each line */
GLfloat fg[4], bg[4]; /* Colors */
+ XImage *mask;
+ double mask_scale;
+ int frame_count;
} unk_configuration;
static unk_configuration *bps = NULL;
@@ -102,6 +106,7 @@ static XrmOptionDescRec opts[] = {
{ "-no-ortho", ".ortho", XrmoptionNoArg, "False" },
{ "-buzz", ".buzz", XrmoptionNoArg, "True" },
{ "-no-buzz", ".buzz", XrmoptionNoArg, "False" },
+ { "-mask", ".mask", XrmoptionSepArg, 0 },
};
static argtype vars[] = {
@@ -112,6 +117,7 @@ static argtype vars[] = {
{&noise_arg, "noise", "Noise", DEF_NOISE, t_Float},
{&aspect_arg, "aspect", "Aspect", DEF_ASPECT, t_Float},
{&buzz_arg, "buzz", "Buzz", DEF_BUZZ, t_Bool},
+ {&mask_arg, "mask", "Image", DEF_MASK, t_String},
};
ENTRYPOINT ModeSpecOpt unk_opts = {countof(opts), opts, countof(vars), vars, NULL};
@@ -241,21 +247,26 @@ reshape_unk (ModeInfo *mi, int width, int height)
GLfloat lw = 1;
GLfloat s = 1;
+# ifdef HAVE_MOBILE
+ lw = 4;
+ s = 1.4;
+
+# else /* !HAVE_MOBILE */
+
if (MI_WIDTH(mi) > 2560) lw = 4; /* Retina displays */
-# ifdef HAVE_COCOA
+# ifdef HAVE_COCOA
else if (MI_WIDTH(mi) > 1280) lw = 3; /* WTF */
-# endif
+# endif
else if (MI_WIDTH(mi) > 1920) lw = 3;
else if (mi->xgwa.width > 640 && mi->xgwa.height > 640) lw = 2;
-# ifdef HAVE_MOBILE
- lw = 4;
- s = 1.4;
-# else
/* Make the image fill the screen a little more fully */
if (mi->xgwa.width <= 640 || mi->xgwa.height <= 640)
s = 1.2;
-# endif
+
+# endif /* !HAVE_MOBILE */
+
+ s /= 1.9 / bp->aspect;
glScalef (s, s, s);
glLineWidth (lw);
@@ -264,6 +275,68 @@ reshape_unk (ModeInfo *mi, int width, int height)
glClear(GL_COLOR_BUFFER_BIT);
}
+static void
+load_image (ModeInfo *mi)
+{
+ unk_configuration *bp = &bps[MI_SCREEN(mi)];
+ XImage *image0;
+ int x, y;
+ double xs, ys;
+ unsigned long max = 0;
+
+ if (!mask_arg || !*mask_arg || !strcasecmp(mask_arg, "(none)"))
+ return;
+
+ image0 = file_to_ximage (MI_DISPLAY (mi), MI_VISUAL (mi), mask_arg);
+ if (!image0) return;
+
+ bp->mask = XCreateImage (MI_DISPLAY(mi), MI_VISUAL(mi), 32, ZPixmap, 0, 0,
+ bp->resolution,
+ bp->count * image0->height / image0->width *
+ (1.9 / bp->aspect) * 0.75,
+ 32, 0);
+ if (!bp->mask) abort();
+ bp->mask->data = (char *)
+ malloc (bp->mask->height * bp->mask->bytes_per_line);
+ if (!bp->mask->data) abort();
+
+ xs = image0->width / (double) bp->mask->width;
+ ys = image0->height / (double) bp->mask->height;
+
+ /* Scale the image down to a 1-bit mask. */
+ for (y = 0; y < bp->mask->height; y++)
+ for (x = 0; x < bp->mask->width; x++)
+ {
+ int x2, y2, n = 0;
+ double total = 0;
+ unsigned long p;
+ for (y2 = y * ys; y2 < (y+1) * ys; y2++)
+ for (x2 = x * xs; x2 < (x+1) * xs; x2++)
+ {
+ unsigned long agbr = XGetPixel (image0, x2, y2);
+ unsigned long a = (agbr >> 24) & 0xFF;
+ unsigned long gray = (a == 0
+ ? 0
+ : ((((agbr >> 16) & 0xFF) +
+ ((agbr >> 8) & 0xFF) +
+ ((agbr >> 0) & 0xFF))
+ / 3));
+# if 0
+ if (gray < 96) gray /= 2; /* a little more contrast */
+# endif
+ total += gray / 255.0;
+ n++;
+ }
+ p = 255 * total / n;
+ if (p > max) max = p;
+ p = (0xFF << 24) | (p << 16) | (p << 8) | p;
+ XPutPixel (bp->mask, x, bp->mask->height-y-1, p);
+ }
+
+ bp->mask_scale = 255.0 / max;
+ XDestroyImage (image0);
+}
+
# ifdef DEBUG
static GLfloat poly1 = 0, poly2 = 0;
@@ -353,7 +426,9 @@ generate_signal (ModeInfo *mi)
for (j = 0; j < nspikes; j++)
{
- double off = frand (0.8) - 0.4;
+ double off = (bp->mask
+ ? frand (1.0) - 0.5 /* all the way to the edge */
+ : frand (0.8) - 0.4); /* leave a margin */
double amp = (0.1 + frand (0.9)) * nspikes;
double freq = (7 + frand (11)) * bp->noise;
for (i = 0, r = -0.5, p = points;
@@ -371,7 +446,10 @@ generate_signal (ModeInfo *mi)
/* Multiply by baseline clipping curve, add static. */
for (i = 0, r = -0.5, p = points; i < bp->resolution; i++, r += step, p++)
*p = ((*p / max)
- * (0.5 + 0.5 * cos1 (r * r * M_PI * 14) * (1 - frand(0.2))));
+ * (0.5 +
+ 0.5
+ * (bp->mask ? 1 : cos1 (r * r * M_PI * 14))
+ * (1 - frand(0.2))));
return points;
}
@@ -414,6 +492,16 @@ tick_unk (ModeInfo *mi)
{
GLfloat x = i / (GLfloat) bp->resolution;
GLfloat z = (points[i] + frand (0.05)) * bp->amplitude;
+
+ if (bp->mask)
+ {
+ int h = bp->mask->height; /* leave a 10% gutter */
+ int y = bp->frame_count % (int) (h * 1.1);
+ unsigned long p = (y < h ? XGetPixel (bp->mask, i, y) : 0);
+ unsigned long gray = ((p >> 8) & 0xFF);
+ z *= gray * bp->mask_scale / 255.0;
+ }
+
if (z < 0) z = 0;
if (z > bp->amplitude) z = bp->amplitude;
glVertex3f (x, 0, z);
@@ -426,6 +514,7 @@ tick_unk (ModeInfo *mi)
}
}
+ bp->frame_count++;
mi->polygon_count *= bp->count;
mi->polygon_count += 5; /* base */
@@ -471,6 +560,8 @@ init_unk (ModeInfo *mi)
if (MI_COUNT(mi) < 1) MI_COUNT(mi) = 1;
/* bp->count is set in reshape */
+ load_image (mi);
+
bp->base = glGenLists (1);
glNewList (bp->base, GL_COMPILE);
{
@@ -673,6 +764,7 @@ free_unk (ModeInfo *mi)
glDeleteLists (bp->lines[i], 1);
free (bp->lines);
free (bp->heights);
+ if (bp->mask) XDestroyImage (bp->mask);
}
XSCREENSAVER_MODULE_2 ("UnknownPleasures", unknownpleasures, unk)
diff --git a/hacks/glx/unknownpleasures.man b/hacks/glx/unknownpleasures.man
index 2eab727..405d78f 100644
--- a/hacks/glx/unknownpleasures.man
+++ b/hacks/glx/unknownpleasures.man
@@ -13,6 +13,7 @@ unknownpleasures - a waterfall graph of the signal from pulsar PSR B1919+21.
[\-resolution \fInumber\fP]
[\-amplitude \fInumber\fP]
[\-noise \fInumber\fP]
+[\-mask \fIfile\fP]
[\-no-ortho]
[\-buzz]
[\-wireframe]
@@ -55,6 +56,11 @@ Height of the waves, 0 - 1.0. Default: 0.13.
.B \-noise \fInumber\fP
How noisy the signal is. 2 for twice as noisy, 0.5 for half as noisy.
.TP 8
+.B \-mask \fIfile\fP
+Use the given image file as a clipping mask against the data.
+A high contrast image of around 256x256 works best.
+Signal peaks appear in the dark areas.
+.TP 8
.B \-ortho | \-no-ortho
Whether to use an orthographic projection.
.TP 8
diff --git a/hacks/hexadrop.c b/hacks/hexadrop.c
index e8c2d65..b1b7d49 100644
--- a/hacks/hexadrop.c
+++ b/hacks/hexadrop.c
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1999-2018 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1999-2019 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@@ -337,7 +337,7 @@ hexadrop_reshape (Display *dpy, Window window, void *closure,
static void
-hexadrop_free (Display *dpy, Window window, void *closure)
+hexadrop_free_1 (Display *dpy, Window window, void *closure)
{
state *st = (state *) closure;
if (st->colors)
@@ -356,7 +356,16 @@ hexadrop_free (Display *dpy, Window window, void *closure)
XFreeGC (st->dpy, st->gc);
st->gc = 0;
}
- free (st);
+
+ memset (st, 0, sizeof(*st));
+}
+
+
+static void
+hexadrop_free (Display *dpy, Window window, void *closure)
+{
+ hexadrop_free_1 (dpy, window, closure);
+ free (closure);
}
@@ -367,15 +376,35 @@ hexadrop_event (Display *dpy, Window window, void *closure, XEvent *event)
if (screenhack_event_helper (dpy, window, event))
{
- cell *c = st->cells;
- int i;
- st->cells = 0;
- hexadrop_free (st->dpy, st->window, st);
- free (st->cells);
- st->cells = c;
- for (i = 0; i < st->ncells; i++)
- st->cells[i].initted_p = False;
- hexadrop_init_1 (st->dpy, st->window, st);
+ if (random() % 5) /* Change everything */
+ {
+ hexadrop_free_1 (st->dpy, st->window, st);
+ hexadrop_init_1 (dpy, window, st);
+ }
+ else /* Change colors only */
+ {
+ /* Save the old geometry */
+ cell *c = st->cells;
+ int n = st->ncells;
+ int s = st->sides;
+ int i;
+
+ /* Protect it from being freed */
+ st->cells = 0;
+ hexadrop_free_1 (st->dpy, st->window, st);
+ hexadrop_init_1 (dpy, window, st);
+
+ /* Reset the old cells */
+ for (i = 0; i < n; i++)
+ c[i].initted_p = False;
+
+ /* Re-init, then put them back. */
+ free (st->cells);
+ st->cells = c;
+ st->ncells = n;
+ st->sides = s;
+ }
+
return True;
}
@@ -408,6 +437,7 @@ static XrmOptionDescRec hexadrop_options [] = {
{ "-ncolors", ".ncolors", XrmoptionSepArg, 0 },
{ "-uniform-speed", ".uniform", XrmoptionNoArg, "True" },
{ "-no-uniform-speed",".uniform", XrmoptionNoArg, "False" },
+ { "-nonuniform-speed",".uniform", XrmoptionNoArg, "False" },
{ "-lockstep", ".lockstep", XrmoptionNoArg, "True" },
{ "-no-lockstep", ".lockstep", XrmoptionNoArg, "False" },
{ 0, 0, 0, 0 }
diff --git a/hacks/kumppa.c b/hacks/kumppa.c
index fc5167d..f4cc5bb 100644
--- a/hacks/kumppa.c
+++ b/hacks/kumppa.c
@@ -215,10 +215,10 @@ static Bool make_rots(struct state *st, double xspeed,double yspeed)
st->rotsizeY=(int)(2/yspeed+1);
iy=(double)(st->midy+1)/(double)(st->rotsizeY);
- st->Xrotations=malloc((st->midx+2)*sizeof(unsigned int));
- st->Xrottable=malloc((st->rotsizeX+1)*sizeof(unsigned int));
- st->Yrotations=malloc((st->midy+2)*sizeof(unsigned int));
- st->Yrottable=malloc((st->rotsizeY+1)*sizeof(unsigned int));
+ st->Xrotations=malloc((st->midx+2)*sizeof(int));
+ st->Xrottable=malloc((st->rotsizeX+1)*sizeof(int));
+ st->Yrotations=malloc((st->midy+2)*sizeof(int));
+ st->Yrottable=malloc((st->rotsizeY+1)*sizeof(int));
chks=malloc(((st->midx>st->midy)?st->midx:st->midy)*sizeof(Bool));
if (!st->Xrottable || !st->Yrottable || !st->Xrotations || !st->Yrotations || !chks) return False;
diff --git a/hacks/petri.c b/hacks/petri.c
index e97c582..1906369 100644
--- a/hacks/petri.c
+++ b/hacks/petri.c
@@ -245,7 +245,10 @@ setup_display (struct state *st)
XWindowAttributes xgwa;
int cell_size = get_integer_resource (st->dpy, "size", "Integer");
- int osize, alloc_size, oalloc;
+ int osize, alloc_size;
+#if 0
+ int oalloc;
+#endif
int mem_throttle = 0;
char *s;
@@ -404,7 +407,9 @@ setup_display (struct state *st)
st->arr_height = st->windowHeight / cell_size;
alloc_size = sizeof(cell) * st->arr_width * st->arr_height;
+# if 0
oalloc = alloc_size;
+# endif
if (mem_throttle > 0)
while (cell_size < st->windowWidth/10 &&
@@ -419,7 +424,8 @@ setup_display (struct state *st)
if (osize != cell_size)
{
- if (0 && !st->warned)
+# if 0
+ if (!st->warned)
{
fprintf (stderr,
"%s: throttling cell size from %d to %d because of %dM limit.\n",
@@ -432,6 +438,7 @@ setup_display (struct state *st)
((float) alloc_size) / (1 << 20));
st->warned = 1;
}
+# endif
}
st->xSize = st->arr_width ? st->windowWidth / st->arr_width : 0;
diff --git a/hacks/shadebobs.c b/hacks/shadebobs.c
index d796162..8aaf6f7 100644
--- a/hacks/shadebobs.c
+++ b/hacks/shadebobs.c
@@ -121,7 +121,7 @@ static void InitShadeBob( struct state *st, SShadeBob *pShadeBob, Bool bDark )
double nDelta;
int iWidth, iHeight;
- if( ( pShadeBob->anDeltaMap = calloc( st->iBobDiameter * st->iBobDiameter, sizeof(char) ) ) == NULL )
+ if( ( pShadeBob->anDeltaMap = calloc( st->iBobDiameter * st->iBobDiameter, sizeof(signed char) ) ) == NULL )
{
fprintf( stderr, "%s: Could not allocate Delta Map!\n", progname );
return;
diff --git a/hacks/webcollage b/hacks/webcollage
index bacc814..5cc1196 100755
--- a/hacks/webcollage
+++ b/hacks/webcollage
@@ -1,6 +1,6 @@
#!/usr/bin/perl -w
#
-# webcollage, Copyright © 1999-2018 by Jamie Zawinski <jwz@jwz.org>
+# webcollage, Copyright © 1999-2019 by Jamie Zawinski <jwz@jwz.org>
# This program decorates the screen with random images from the web.
# One satisfied customer described it as "a nonstop pop culture brainbath."
#
@@ -60,7 +60,7 @@ use LWP::UserAgent;
my $progname = $0; $progname =~ s@.*/@@g;
-my ($version) = ('$Revision: 1.182 $' =~ m/\s(\d[.\d]+)\s/s);
+my ($version) = ('$Revision: 1.183 $' =~ m/\s(\d[.\d]+)\s/s);
my $copyright = "WebCollage $version, Copyright (c) 1999-2017" .
" Jamie Zawinski <jwz\@jwz.org>\n" .
" https://www.jwz.org/webcollage/\n";
@@ -228,6 +228,7 @@ my %warningless_sites = (
"tinypic.com" => 1,
"flickr.com" => 1,
"staticflickr.com" => 1,
+ "live.staticflickr.com" => 1,
"pbase.com" => 1,
"blogger.com" => 1,
"multiply.com" => 1,
@@ -2149,7 +2150,6 @@ sub pick_from_flickr_recent($) {
my ($img) = ($chunk =~ m@"displayUrl": *"(.*?)"@six);
next unless defined ($img);
$img =~ s/\\//gs;
- $img = "//" unless ($img =~ m@^/@s);
$img = "http:$img" unless ($img =~ m/^http/s);
my ($user) = ($chunk =~ m/"pathAlias": *"(.*?)"/si);
diff --git a/hacks/xjack.c b/hacks/xjack.c
index 27e4c9e..5feedb2 100644
--- a/hacks/xjack.c
+++ b/hacks/xjack.c
@@ -84,16 +84,18 @@ xjack_init (Display *dpy, Window window)
XGCValues gcv;
char *fontname;
+
st->dpy = dpy;
st->window = window;
st->s = source;
st->delay = get_integer_resource (st->dpy, "delay", "Integer");
- fontname = get_string_resource (st->dpy, "font", "Font");
XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
- if (st->xgwa.width <= 480)
- fontname = "-*-courier-medium-r-*-*-*-180-*-*-m-*-*-*";
+ if (st->xgwa.width > 480)
+ fontname = get_string_resource (st->dpy, "font", "Font");
+ else
+ fontname = get_string_resource (st->dpy, "font2", "Font");
st->font = load_font_retry (st->dpy, fontname);
if (!st->font) abort();
@@ -474,8 +476,10 @@ static const char *xjack_defaults [] = {
"*fpsSolid: true",
#ifdef HAVE_COCOA
".font: American Typewriter 24",
+ ".font2: American Typewriter 10",
#else
".font: -*-courier-medium-r-*-*-*-240-*-*-m-*-*-*",
+ ".font2: -*-courier-medium-r-*-*-*-180-*-*-m-*-*-*",
#endif
"*delay: 50000",
0