From http://www.jwz.org/xscreensaver/xscreensaver-5.38.tar.gz
authorZygo Blaxell <zblaxell@waya.furryterror.org>
Fri, 22 Dec 2017 02:17:43 +0000 (21:17 -0500)
committerZygo Blaxell <zblaxell@waya.furryterror.org>
Fri, 22 Dec 2017 02:18:54 +0000 (21:18 -0500)
-rw-rw-r-- 1 zblaxell zblaxell 10712548 Dec 20 15:14 xscreensaver-5.38.tar.gz
b4e6b6799e8e244c894db277d6ff2bf5ee48290c  xscreensaver-5.38.tar.gz

353 files changed:
Makefile.in
OSX/Media-iOS.xcassets/AppIcon.appiconset/Contents.json
OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner1024.png [new file with mode: 0644]
OSX/SaverRunner.m
OSX/SaverRunner.plist
OSX/Updater.plist
OSX/XScreenSaver.plist
OSX/XScreenSaverGLView.m
OSX/XScreenSaverView.h
OSX/XScreenSaverView.m
OSX/bindist.rtf
OSX/iSaverRunner.plist
OSX/ios-function-table.m
OSX/updates.xml
OSX/xscreensaver.xcodeproj/project.pbxproj
README
README.hacking
aclocal.m4
android/Makefile
android/README
android/android.iml [new file with mode: 0644]
android/build.gradle [new file with mode: 0644]
android/gradle/wrapper/gradle-wrapper.jar [new file with mode: 0644]
android/gradle/wrapper/gradle-wrapper.properties [new file with mode: 0644]
android/gradlew [new file with mode: 0755]
android/gradlew.bat [new file with mode: 0644]
android/local.properties [new file with mode: 0644]
android/project/build.gradle [deleted file]
android/project/gradle/wrapper/gradle-wrapper.jar [deleted file]
android/project/gradle/wrapper/gradle-wrapper.properties [deleted file]
android/project/gradlew [deleted file]
android/project/gradlew.bat [deleted file]
android/project/local.properties [deleted file]
android/project/project.iml [deleted file]
android/project/settings.gradle [deleted file]
android/project/xscreensaver/.idea/compiler.xml [deleted file]
android/project/xscreensaver/.idea/gradle.xml [deleted file]
android/project/xscreensaver/.idea/misc.xml [deleted file]
android/project/xscreensaver/.idea/modules.xml [deleted file]
android/project/xscreensaver/.idea/workspace.xml [deleted file]
android/project/xscreensaver/assets/fonts/OCRAStd.otf [deleted symlink]
android/project/xscreensaver/assets/fonts/PxPlus_IBM_VGA8.ttf [deleted symlink]
android/project/xscreensaver/assets/fonts/YearlReg.ttf [deleted symlink]
android/project/xscreensaver/build.gradle [deleted file]
android/project/xscreensaver/build.xml [deleted file]
android/project/xscreensaver/gradle/wrapper/gradle-wrapper.jar [deleted file]
android/project/xscreensaver/gradle/wrapper/gradle-wrapper.properties [deleted file]
android/project/xscreensaver/gradlew [deleted file]
android/project/xscreensaver/gradlew.bat [deleted file]
android/project/xscreensaver/jni/Android.mk [deleted file]
android/project/xscreensaver/jni/Application.mk [deleted file]
android/project/xscreensaver/local.properties [deleted file]
android/project/xscreensaver/project.properties [deleted file]
android/project/xscreensaver/res/drawable-ldpi/icon.png [deleted file]
android/project/xscreensaver/res/drawable-mdpi/icon.png [deleted file]
android/project/xscreensaver/res/drawable/thumbnail.png [deleted file]
android/project/xscreensaver/res/layout-land/activity_xscreensaver.xml [deleted file]
android/project/xscreensaver/res/layout/activity_xscreensaver.xml [deleted file]
android/project/xscreensaver/res/layout/main.xml [deleted file]
android/project/xscreensaver/res/layout/preference_blurb.xml [deleted file]
android/project/xscreensaver/res/layout/slider_preference.xml [deleted file]
android/project/xscreensaver/src/org/jwz/xscreensaver/SliderPreference.java [deleted file]
android/project/xscreensaver/src/org/jwz/xscreensaver/TTFAnalyzer.java [deleted file]
android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverActivity.java [deleted file]
android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverApp.java [deleted file]
android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverDaydream.java [deleted file]
android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverRenderer.java [deleted file]
android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverSettings.java [deleted file]
android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverWallpaper.java [deleted file]
android/project/xscreensaver/src/org/jwz/xscreensaver/jwxyz.java [deleted file]
android/project/xscreensaver/xscreensaver.iml [deleted file]
android/settings.gradle [new file with mode: 0644]
android/xscreensaver/.idea/.name [new file with mode: 0644]
android/xscreensaver/.idea/compiler.xml [new file with mode: 0644]
android/xscreensaver/.idea/gradle.xml [new file with mode: 0644]
android/xscreensaver/.idea/misc.xml [new file with mode: 0644]
android/xscreensaver/.idea/modules.xml [new file with mode: 0644]
android/xscreensaver/.idea/runConfigurations.xml [new file with mode: 0644]
android/xscreensaver/.idea/workspace.xml [new file with mode: 0644]
android/xscreensaver/assets/fonts/OCRAStd.otf [new symlink]
android/xscreensaver/assets/fonts/PxPlus_IBM_VGA8.ttf [new symlink]
android/xscreensaver/assets/fonts/YearlReg.ttf [new symlink]
android/xscreensaver/build.gradle [new file with mode: 0644]
android/xscreensaver/build.xml [new file with mode: 0644]
android/xscreensaver/gradle/wrapper/gradle-wrapper.jar [new file with mode: 0644]
android/xscreensaver/gradle/wrapper/gradle-wrapper.properties [new file with mode: 0644]
android/xscreensaver/gradlew [new file with mode: 0644]
android/xscreensaver/gradlew.bat [new file with mode: 0644]
android/xscreensaver/jni/Android.mk [new file with mode: 0644]
android/xscreensaver/jni/Application.mk [new file with mode: 0644]
android/xscreensaver/local.properties [new file with mode: 0644]
android/xscreensaver/project.properties [new file with mode: 0644]
android/xscreensaver/res/drawable-ldpi/icon.png [new file with mode: 0644]
android/xscreensaver/res/drawable-mdpi/icon.png [new file with mode: 0644]
android/xscreensaver/res/drawable/thumbnail.png [new file with mode: 0644]
android/xscreensaver/res/layout-land/activity_xscreensaver.xml [new file with mode: 0644]
android/xscreensaver/res/layout/activity_tv_xscreensaver.xml [new file with mode: 0644]
android/xscreensaver/res/layout/activity_xscreensaver.xml [new file with mode: 0644]
android/xscreensaver/res/layout/main.xml [new file with mode: 0644]
android/xscreensaver/res/layout/preference_blurb.xml [new file with mode: 0644]
android/xscreensaver/res/layout/slider_preference.xml [new file with mode: 0644]
android/xscreensaver/src/org/jwz/xscreensaver/SliderPreference.java [new file with mode: 0644]
android/xscreensaver/src/org/jwz/xscreensaver/TTFAnalyzer.java [new file with mode: 0644]
android/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverActivity.java [new file with mode: 0644]
android/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverApp.java [new file with mode: 0644]
android/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverDaydream.java [new file with mode: 0644]
android/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverSettings.java [new file with mode: 0644]
android/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverTVActivity.java [new file with mode: 0644]
android/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverWallpaper.java [new file with mode: 0644]
android/xscreensaver/src/org/jwz/xscreensaver/jwxyz.java [new file with mode: 0644]
android/xscreensaver/xscreensaver.iml [new file with mode: 0644]
config.h.in
configure
driver/XScreenSaver.ad.in
driver/XScreenSaver_ad.h
driver/demo-Gtk.c
driver/dpms.c
driver/lock.c
driver/splash.c
driver/test-passwd.c
driver/windows.c
driver/xscreensaver-command.c
driver/xscreensaver-getimage.c
driver/xscreensaver.h
driver/xscreensaver.man
hacks/Makefile.in
hacks/analogtv.c
hacks/ant.c
hacks/apollonian.c
hacks/asm6502.c
hacks/attraction.c
hacks/barcode.c
hacks/blaster.c
hacks/bouboule.c
hacks/braid.c
hacks/bsod.c
hacks/bsod.man
hacks/check-configs.pl
hacks/compass.c
hacks/config/README
hacks/config/bsod.xml
hacks/config/dnalogo.xml
hacks/config/esper.xml [new file with mode: 0644]
hacks/config/m6502.xml
hacks/config/vermiculate.xml
hacks/coral.c
hacks/crystal.c
hacks/demon.c
hacks/discrete.c
hacks/drift.c
hacks/epicycle.c
hacks/euler2d.c
hacks/fadeplot.c
hacks/fiberlamp.c
hacks/flag.c
hacks/flow.c
hacks/fluidballs.c
hacks/forest.c
hacks/fps.c
hacks/galaxy.c
hacks/glx/Makefile.in
hacks/glx/antinspect.c
hacks/glx/antmaze.c
hacks/glx/antspotlight.c
hacks/glx/atlantis.c
hacks/glx/atunnel.c
hacks/glx/b_lockglue.c
hacks/glx/blinkbox.c
hacks/glx/blocktube.c
hacks/glx/boing.c
hacks/glx/bouncingcow.c
hacks/glx/boxed.c
hacks/glx/cage.c
hacks/glx/carousel.c
hacks/glx/circuit.c
hacks/glx/cityflow.c
hacks/glx/companion.c
hacks/glx/crackberg.c
hacks/glx/cube21.c
hacks/glx/cubenetic.c
hacks/glx/cubestack.c
hacks/glx/cubestorm.c
hacks/glx/cubetwist.c
hacks/glx/cubicgrid.c
hacks/glx/dangerball.c
hacks/glx/discoball.c
hacks/glx/dnalogo.c
hacks/glx/dymaxionmap.c
hacks/glx/endgame.c
hacks/glx/energystream.c
hacks/glx/engine.c
hacks/glx/erase-gl.c [new file with mode: 0644]
hacks/glx/esper.c [new file with mode: 0644]
hacks/glx/esper.man [new file with mode: 0644]
hacks/glx/extrusion.c
hacks/glx/flipflop.c
hacks/glx/flipscreen3d.c
hacks/glx/fliptext.c
hacks/glx/flurry.c
hacks/glx/flyingtoasters.c
hacks/glx/gears.c
hacks/glx/geodesic.c
hacks/glx/geodesicgears.c
hacks/glx/gflux.c
hacks/glx/glblur.c
hacks/glx/glcells.c
hacks/glx/gleidescope.c
hacks/glx/glforestfire.c
hacks/glx/glhanoi.c
hacks/glx/glknots.c
hacks/glx/glmatrix.c
hacks/glx/glplanet.c
hacks/glx/glschool.c
hacks/glx/glslideshow.c
hacks/glx/glsnake.c
hacks/glx/gltext.c
hacks/glx/gltext.man
hacks/glx/glut_mroman.h [new file with mode: 0644]
hacks/glx/grab-ximage.c
hacks/glx/hexstrut.c
hacks/glx/hilbert.c
hacks/glx/hydrostat.c
hacks/glx/hypertorus.c
hacks/glx/hypnowheel.c
hacks/glx/jigglypuff.c
hacks/glx/jigsaw.c
hacks/glx/juggler3d.c
hacks/glx/kaleidocycle.c
hacks/glx/klein.c
hacks/glx/lament.c
hacks/glx/lavalite.c
hacks/glx/lockward.c
hacks/glx/menger.c
hacks/glx/mirrorblob.c
hacks/glx/moebius.c
hacks/glx/moebiusgears.c
hacks/glx/molecule.c
hacks/glx/morph3d.c
hacks/glx/noof.c
hacks/glx/photopile.c
hacks/glx/pinion.c
hacks/glx/pipes.c
hacks/glx/polyhedra-gl.c
hacks/glx/polytopes.c
hacks/glx/projectiveplane.c
hacks/glx/providence.c
hacks/glx/pulsar.c
hacks/glx/quasicrystal.c
hacks/glx/queens.c
hacks/glx/raverhoop.c
hacks/glx/romanboy.c
hacks/glx/rubik.c
hacks/glx/rubikblocks.c
hacks/glx/sballs.c
hacks/glx/sierpinski3d.c
hacks/glx/skytentacles.c
hacks/glx/sonar.c
hacks/glx/spheremonics.c
hacks/glx/splitflap.c
hacks/glx/splodesic.c
hacks/glx/sproingies.c
hacks/glx/sproingiewrap.c
hacks/glx/stairs.c
hacks/glx/starwars.c
hacks/glx/stonerview.c
hacks/glx/superquadrics.c
hacks/glx/surfaces.c
hacks/glx/tangram.c
hacks/glx/texfont.c
hacks/glx/timetunnel.c
hacks/glx/topblock.c
hacks/glx/tronbit.c
hacks/glx/unicrud.c
hacks/glx/unknownpleasures.c
hacks/glx/vigilance.c
hacks/glx/voronoi.c
hacks/glx/winduprobot.c
hacks/glx/xlock-gl-utils.c
hacks/goop.c
hacks/grav.c
hacks/hopalong.c
hacks/ifs.c
hacks/images/m6502/dmsc.asm
hacks/images/m6502/dmsc.txt [new file with mode: 0644]
hacks/images/m6502/texture.asm [new file with mode: 0644]
hacks/images/ransomware.xpm [new file with mode: 0644]
hacks/intermomentary.c
hacks/juggle.c
hacks/julia.c
hacks/laser.c
hacks/lightning.c
hacks/lisa.c
hacks/lissie.c
hacks/loop.c
hacks/m6502.c
hacks/metaballs.c
hacks/moire2.c
hacks/mountain.c
hacks/munch.c
hacks/pacman.c
hacks/penetrate.c
hacks/penrose.c
hacks/phosphor.c
hacks/polyominoes.c
hacks/popsquares.c
hacks/pyro.c
hacks/recanim.c
hacks/rocks.c
hacks/rotor.c
hacks/screenhack.c
hacks/sierpinski.c
hacks/slidescreen.c
hacks/slip.c
hacks/sphere.c
hacks/spiral.c
hacks/squiral.c
hacks/starfish.c
hacks/strange.c
hacks/swirl.c
hacks/testx11.c
hacks/thornbird.c
hacks/triangle.c
hacks/vermiculate.c
hacks/vines.c
hacks/wander.c
hacks/webcollage
hacks/webcollage-helper-cocoa.m
hacks/webcollage-helper.c
hacks/worm.c
hacks/wormhole.c
hacks/xlockmore.c
hacks/xlockmore.h
hacks/xlockmoreI.h
hacks/xmatrix.c
hacks/xrayswarm.c
hacks/zoom.c
jwxyz/Makefile.in
jwxyz/jwxyz-android.c
jwxyz/jwxyz-android.h
jwxyz/jwxyz-cocoa.m
jwxyz/jwxyz-common.c
jwxyz/jwxyz-gl.c
jwxyz/jwxyz-timers.c
jwxyz/jwxyz.h
jwxyz/jwxyz.m
jwxyz/jwxyzI.h
po/POTFILES.in
po/ru.po
utils/erase.c
utils/erase.h
utils/version.h
utils/xft.c
xscreensaver.spec

index cf80264b42dd5b8491fc43b8450caa4e842eb85f..17c698d5c6b6b56700a576789fc5a3d5eba57db2 100644 (file)
@@ -230,55 +230,6 @@ rpm::
   echo '' ;                                                               \
   ls -lFG xscreensaver*-$$VERS-*.rpm
 
-test-tar::
-       @                                                                   \
-  VERS=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ]*\).*/\1/p' utils/version.h` ;  \
-  D=xscreensaver-$$VERS ;                                                  \
-  ADIR=archive/ ;                                                          \
-  NAME="$${ADIR}$$D.tar.gz" ;                                              \
-  if [ ! -f $$NAME ]; then                                                 \
-    echo "$$NAME does not exist!  Did you forget to \`make tar'?" ;        \
-    exit 1 ;                                                               \
-  fi ;                                                                     \
-                                                                           \
-  set -e ;                                                                 \
-  set -x ;                                                                 \
-                                                                           \
-  if [ -d $$D ]; then                                                      \
-   chmod -R u+w $$D ;                                                      \
-  fi ;                                                                     \
-  rm -rf $$D ;                                                             \
-  zcat $${ADIR}$$D.tar.gz | tar -xf - ;                                            \
-  cd $$D ;                                                                 \
-  chmod -R a-w . ;                                                         \
-  chmod u+w . ;                                                                    \
-  mkdir BIN ;                                                              \
-  mkdir BIN/motif ;                                                        \
-  mkdir BIN/lesstif ;                                                      \
-  chmod a-w . ;                                                                    \
-                                                                           \
-  ( cd BIN/motif ;                                                         \
-    CC=cc ;                                                                \
-    export CC ;                                                                    \
-    ../../configure --without-xpm --without-xdbe --without-xshm            \
-                   --with-motif=/usr/local/motif ;                         \
-    echo --------------------------------------------------------------- ;  \
-    gmake all ;                                                                    \
-    ( cd driver; gmake tests ) ;                                           \
-    echo --------------------------------------------------------------- ); \
-                                                                           \
-  ( cd BIN/lesstif ;                                                       \
-    CC=cc ;                                                                \
-    export CC ;                                                                    \
-    ../../configure --with-motif=/usr/local/lesstif --without-gnome ;      \
-    echo --------------------------------------------------------------- ;  \
-    ( cd utils; gmake all ) ;                                              \
-    ( cd jwxyz; gmake all ) ;                                              \
-    ( cd driver; gmake all ) ;                                             \
-    echo --------------------------------------------------------------- ); \
-                                                                           \
-  chmod -R u+w .
-
 dmg::
        $(MAKE) -C OSX release dmg
 apk::
@@ -363,6 +314,7 @@ www::
   for EXT in tar.gz dmg ; do                                               \
     OLDEST=`ls xscreensaver*.$$EXT |                                       \
       fgrep -v 5.14 |                                                      \
+      fgrep -v 5.34 |                                                      \
       head -n 1` ;                                                         \
     /bin/echo -n "Delete $$DEST/$$OLDEST? ";                               \
     read line;                                                             \
index 89e33affd486aad4e864c5f84c76a07640123a74..f7aa929a07885b0357e79c37e8b32c172dde2969 100644 (file)
@@ -1,5 +1,15 @@
 {
   "images" : [
+    {
+      "idiom" : "iphone",
+      "size" : "20x20",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "20x20",
+      "scale" : "3x"
+    },
     {
       "size" : "29x29",
       "idiom" : "iphone",
       "filename" : "iSaverRunner180.png",
       "scale" : "3x"
     },
+    {
+      "idiom" : "ipad",
+      "size" : "20x20",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "20x20",
+      "scale" : "2x"
+    },
     {
       "size" : "29x29",
       "idiom" : "ipad",
       "idiom" : "ipad",
       "filename" : "iSaverRunner167.png",
       "scale" : "2x"
+    },
+    {
+      "size" : "1024x1024",
+      "idiom" : "ios-marketing",
+      "filename" : "iSaverRunner1024.png",
+      "scale" : "1x"
     }
   ],
   "info" : {
diff --git a/OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner1024.png b/OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner1024.png
new file mode 100644 (file)
index 0000000..a548d1c
Binary files /dev/null and b/OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner1024.png differ
index 5d0259b8ab5deef272d7fc75aa079916797528d5..f358fb754500f5c27cb3bf78404163b23beed1db 100644 (file)
@@ -1416,7 +1416,7 @@ FAIL:
                                   backing:NSBackingStoreBuffered
                                     defer:YES
                                    screen:screen];
-  [win setMinSize:[win frameRectForContentRect:rect].size];
+//  [win setMinSize:[win frameRectForContentRect:rect].size];
   [[win contentView] addSubview: (pbox ? (NSView *) pbox : (NSView *) sv)];
   [pbox release];
 
index 457c5f451f5437c5e13f0112ad906de6620e91ae..692e5764a1973541fc3bb3989985067192905556 100644 (file)
@@ -7,7 +7,7 @@
        <key>CFBundleExecutable</key>
        <string>${EXECUTABLE_NAME}</string>
        <key>CFBundleGetInfoString</key>
-       <string>5.37</string>
+       <string>5.38</string>
        <key>CFBundleIconFile</key>
        <string>SaverRunner</string>
        <key>CFBundleIdentifier</key>
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleLongVersionString</key>
-       <string>5.37</string>
+       <string>5.38</string>
        <key>CFBundleName</key>
        <string>${PRODUCT_NAME}</string>
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleShortVersionString</key>
-       <string>5.37</string>
+       <string>5.38</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.37</string>
+       <string>5.38</string>
        <key>LSMinimumSystemVersion</key>
        <string>${MACOSX_DEPLOYMENT_TARGET}</string>
        <key>NSHumanReadableCopyright</key>
-       <string>5.37</string>
+       <string>5.38</string>
        <key>NSMainNibFile</key>
        <string>SaverRunner</string>
        <key>NSPrincipalClass</key>
index 515452ad7f1150ae8f65dd4d9d30f480fbafb495..e25e0348f3960d50157d7985ef0084d7d962b9a0 100644 (file)
@@ -9,7 +9,7 @@
        <key>CFBundleExecutable</key>
        <string>${EXECUTABLE_NAME}</string>
        <key>CFBundleGetInfoString</key>
-       <string>5.37</string>
+       <string>5.38</string>
        <key>CFBundleIconFile</key>
        <string>SaverRunner</string>
        <key>CFBundleIdentifier</key>
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleLongVersionString</key>
-       <string>5.37</string>
+       <string>5.38</string>
        <key>CFBundleName</key>
        <string>${PRODUCT_NAME}</string>
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleShortVersionString</key>
-       <string>5.37</string>
+       <string>5.38</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.37</string>
+       <string>5.38</string>
        <key>LSMinimumSystemVersion</key>
        <string>${MACOSX_DEPLOYMENT_TARGET}</string>
        <key>LSUIElement</key>
        <true/>
        <key>NSHumanReadableCopyright</key>
-       <string>5.37</string>
+       <string>5.38</string>
        <key>NSMainNibFile</key>
        <string>Updater</string>
        <key>NSPrincipalClass</key>
index 04a25c58a68b86925def81a670ca7140794c3f50..480276eae33e76064583aafe7a4c97dea6803949 100644 (file)
        <key>CFBundlePackageType</key>
        <string>BNDL</string>
        <key>CFBundleShortVersionString</key>
-       <string>5.37</string>
+       <string>5.38</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.37</string>
+       <string>5.38</string>
        <key>LSMinimumSystemVersion</key>
        <string>10.8</string>
        <key>NSMainNibFile</key>
index d61964f8d3b3fd0dad5fd909ecc3938c5b6be79b..57b0c7c74b8c57351af4d050b4518b860eb13af7 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2006-2016 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2006-2017 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
@@ -41,14 +41,19 @@ extern void check_gl_error (const char *type);
 @implementation XScreenSaverGLView
 
 
-#ifdef USE_IPHONE
 /* With GL programs, drawing at full resolution isn't a problem.
  */
 - (CGFloat) hackedContentScaleFactor
 {
+# ifdef USE_IPHONE
   return [self contentScaleFactor];
+# else
+  return self.window.backingScaleFactor;
+# endif
 }
 
+# ifdef USE_IPHONE
+
 - (BOOL)ignoreRotation
 {
   return FALSE;                // Allow xwindow and the glViewport to change shape
index dffa58e97081deb37ad6cadf471e75146a34afb7..8283d35e16ff8e665caf73cd7cc6b6cef87aceed 100644 (file)
@@ -29,6 +29,7 @@
 #else
 # import <Cocoa/Cocoa.h>
 # import <ScreenSaver/ScreenSaver.h>
+//# define USE_TOUCHBAR
 #endif
 
 
@@ -85,6 +86,8 @@
   fps_state *fpst;
   void (*fps_cb) (Display *, Window, fps_state *, void *);
 
+  BOOL _lowrez_p;              // Whether the saver prefers 1990s pixels.
+
 # ifdef USE_IPHONE
   BOOL screenLocked;
   BOOL _ignoreRotation;                // whether hack requested "always portrait".
 
 # endif // !USE_IPHONE
 
+# ifdef USE_TOUCHBAR
+  NSWindow *touchbar_window;
+  XScreenSaverView *touchbar_view;
+# endif
+
   NSOpenGLContext *ogl_ctx;      // OpenGL rendering context
 
 # ifdef JWXYZ_QUARTZ
 - (NSUserDefaultsController *) userDefaultsController;
 + (NSString *) decompressXML:(NSData *)xml;
 
-#ifdef USE_IPHONE
 - (CGFloat) hackedContentScaleFactor;
+
+#ifdef USE_IPHONE
 - (void)setScreenLocked:(BOOL)locked;
 - (NSDictionary *)getGLProperties;
 - (void)addExtraRenderbuffers:(CGSize)size;
index 947525dde25b52bfcc64ea4c2600663367c6d174..1ec05a7df80254fd1fa92b42ab892dcb5a2075a4 100644 (file)
@@ -22,7 +22,6 @@
 #import "XScreenSaverConfigSheet.h"
 #import "Updater.h"
 #import "screenhackI.h"
-#import "xlockmoreI.h"
 #import "pow2.h"
 #import "jwxyzI.h"
 #import "jwxyz-cocoa.h"
@@ -645,6 +644,9 @@ add_default_options (const XrmOptionDescRec *opts,
     // from initWithFrame.
     [ogl_ctx setView:self];
 
+    // Get device pixels instead of points.
+    self.wantsBestResolutionOpenGLSurface = YES;
+
     // This may not be necessary if there's FBO support.
 #  ifdef JWXYZ_GL
     xwindow->window.pixfmt = pixfmt;
@@ -676,6 +678,11 @@ add_default_options (const XrmOptionDescRec *opts,
 
     new_backbuffer_size = NSSizeToCGSize ([self bounds].size);
 
+    // Scale factor for desktop retina displays
+    double s = [self hackedContentScaleFactor];
+    new_backbuffer_size.width *= s;
+    new_backbuffer_size.height *= s;
+
 # else  // USE_IPHONE
     if (!ogl_ctx) {
       CAEAGLLayer *eagl_layer = (CAEAGLLayer *) self.layer;
@@ -728,6 +735,50 @@ add_default_options (const XrmOptionDescRec *opts,
 
   [self setViewport];
   [self createBackbuffer:new_backbuffer_size];
+
+# ifdef USE_TOUCHBAR
+  static BOOL created_touchbar = NO;
+
+  if (!touchbar_view &&
+      //#### !self.isPreview &&
+      self.window.screen == [[NSScreen screens] objectAtIndex: 0] &&
+      !created_touchbar) {
+
+    // Figure out which NSScreen has the touchbar on it;
+    // find its bounds; create a saver there.
+
+    created_touchbar = YES;
+    NSScreen *tbs = [[NSScreen screens] lastObject]; // #### write me
+    NSRect rect = [tbs visibleFrame];
+
+    // #### debugging
+    rect.origin.x += 40;
+    rect.origin.x += 40;
+    rect.size.width /= 4;
+    rect.size.height /= 4;
+    NSLog(@"## TB %.0f, %.0f  %.0f x %.0f",
+          rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
+
+    touchbar_view = [[[self class] alloc]
+                      initWithFrame:rect
+                      saverName:[NSString stringWithCString:xsft->progclass
+                                          encoding:NSISOLatin1StringEncoding]
+                      isPreview:self.isPreview];
+    [touchbar_view setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
+
+    touchbar_window = [[NSWindow alloc]
+                        initWithContentRect:rect
+                        styleMask: (NSTitledWindowMask|NSResizableWindowMask)
+                        backing:NSBackingStoreBuffered
+                        defer:YES
+                        screen:tbs];
+    [touchbar_window setTitle: @"XScreenSaver Touchbar"];
+    [[touchbar_window contentView] addSubview: touchbar_view];
+    [touchbar_window makeKeyAndOrderFront:touchbar_window];
+  }
+
+  if (touchbar_view) [touchbar_view startAnimation];
+# endif // USE_TOUCHBAR
 }
 
 - (void)stopAnimation
@@ -749,7 +800,7 @@ add_default_options (const XrmOptionDescRec *opts,
        xsft->free_cb (xdpy, xwindow, xdata);
     [self unlockFocus];
 
-    jwxyz_free_display (xdpy);
+    jwxyz_quartz_free_display (xdpy);
     xdpy = NULL;
 # if defined JWXYZ_GL && !defined USE_IPHONE
     CFRelease (xwindow->ogl_ctx);
@@ -800,6 +851,19 @@ add_default_options (const XrmOptionDescRec *opts,
   backbuffer_data = NULL;
   backbuffer_len = 0;
 # endif
+
+# ifdef USE_TOUCHBAR
+  if (touchbar_view) {
+    [touchbar_view stopAnimation];
+    [touchbar_window close];
+
+    [touchbar_view release];
+    [touchbar_window release];
+
+    touchbar_view = nil;
+    touchbar_window = nil;
+  }
+# endif
 }
 
 
@@ -835,18 +899,12 @@ screenhack_do_fps (Display *dpy, Window w, fps_state *fpst, void *closure)
 }
 
 
-#ifdef USE_IPHONE
+/* Some of the older X11 savers look bad if a "pixel" is not a thing you can
+   see.  They expect big, chunky, luxurious 1990s pixels, and if they use
+   "device" pixels on a Retina screen, everything just disappears.
 
-/* On iPhones with Retina displays, we can draw the savers in "real"
-   pixels, and that works great.  The 320x480 "point" screen is really
-   a 640x960 *pixel* screen.  However, Retina iPads have 768x1024
-   point screens which are 1536x2048 pixels, and apparently that's
-   enough pixels that copying those bits to the screen is slow.  Like,
-   drops us from 15fps to 7fps.  So, on Retina iPads, we don't draw in
-   real pixels.  This will probably make the savers look better
-   anyway, since that's a higher resolution than most desktop monitors
-   have even today.  (This is only true for X11 programs, not GL 
-   programs.  Those are fine at full rez.)
+   Retina iPads have 768x1024 point screens which are 1536x2048 pixels,
+   2017 iMac screens are 5120x2880 in device pixels.
 
    This method is overridden in XScreenSaverGLView, since this kludge
    isn't necessary for GL programs, being resolution independent by
@@ -854,32 +912,27 @@ screenhack_do_fps (Display *dpy, Window w, fps_state *fpst, void *closure)
  */
 - (CGFloat) hackedContentScaleFactor
 {
-  NSSize bsize = [self bounds].size;
-
-  CGFloat
-    max_bsize = bsize.width > bsize.height ? bsize.width : bsize.height;
-
-  // Ratio of screen size in pixels to view size in points.
+# ifdef USE_IPHONE
   CGFloat s = self.contentScaleFactor;
+# else
+  CGFloat s = self.window.backingScaleFactor;
+# endif
 
-  // Two constraints:
-
-  // 1. Don't exceed -- let's say 1280 pixels in either direction.
-  //    (Otherwise the frame rate gets bad.)
-  //    Actually let's make that 1440 since iPhone 6 is natively 1334.
-  CGFloat mag0 = ceil(max_bsize * s / 1440);
-
-  // 2. Don't let the pixel size get too small.
-  //    (Otherwise pixels in IFS and similar are too fine.)
-  //    So don't let the result be > 2 pixels per point.
-  CGFloat mag1 = ceil(s / 2);
+  if (_lowrez_p) {
+    NSSize b = [self bounds].size;
+    CGFloat wh = b.width > b.height ? b.width : b.height;
+    const int max = 800; // maybe 1024?
+    wh *= s;
+    if (wh > max)
+      s *= max / wh;
+  }
 
-  // As of iPhone 6, mag0 is always >= mag1. This may not be true in the future.
-  // (desired scale factor) = s / (desired magnification factor)
-  return s / (mag0 > mag1 ? mag0 : mag1);
+  return s;
 }
 
 
+#ifdef USE_IPHONE
+
 double
 current_device_rotation (void)
 {
@@ -1095,11 +1148,10 @@ gl_check_ver (const struct gl_version *caps,
 
 #  ifdef USE_IPHONE
   GLfloat s = self.contentScaleFactor;
-  GLfloat hs = self.hackedContentScaleFactor;
 #  else // !USE_IPHONE
-  const GLfloat s = 1;
-  const GLfloat hs = s;
+  const GLfloat s = self.window.backingScaleFactor;
 #  endif
+  GLfloat hs = self.hackedContentScaleFactor;
 
   // On OS X this almost isn't necessary, except for the ugly aliasing
   // artifacts.
@@ -1455,11 +1507,11 @@ gl_check_ver (const struct gl_version *caps,
     new_size.width  = new_size.height;
     new_size.height = swap;
   }
+#  endif // USE_IPHONE
 
   double s = self.hackedContentScaleFactor;
   new_size.width *= s;
   new_size.height *= s;
-#  endif // USE_IPHONE
 
   [self prepareContext];
   [self setViewport];
@@ -1541,11 +1593,13 @@ gl_check_ver (const struct gl_version *caps,
 
   if (!initted_p) {
 
+    resized_p = NO;
+
     if (! xdpy) {
 # ifdef JWXYZ_QUARTZ
       xwindow->cgc = backbuffer;
 # endif // JWXYZ_QUARTZ
-      xdpy = jwxyz_make_display (xwindow);
+      xdpy = jwxyz_quartz_make_display (xwindow);
 
 # if defined USE_IPHONE
       /* Some X11 hacks (fluidballs) want to ignore all rotation events. */
@@ -1557,6 +1611,24 @@ gl_check_ver (const struct gl_version *caps,
 #  endif // !JWXYZ_GL
 # endif // USE_IPHONE
 
+      _lowrez_p = get_boolean_resource (xdpy, "lowrez", "Lowrez");
+      if (_lowrez_p) {
+        resized_p = YES;
+
+# if !defined __OPTIMIZE__ || TARGET_IPHONE_SIMULATOR
+        NSSize  b = [self bounds].size;
+        CGFloat s = self.hackedContentScaleFactor;
+#  ifdef USE_IPHONE
+        CGFloat o = self.contentScaleFactor;
+#  else
+        CGFloat o = self.window.backingScaleFactor;
+#  endif
+        NSLog(@"lowrez: scaling %.0fx%.0f -> %.0fx%.0f (%.02f)",
+              b.width * o, b.height * o,
+              b.width * s, b.height * s, s);
+# endif
+      }
+
       [self resize_x11];
     }
 
@@ -1566,7 +1638,6 @@ gl_check_ver (const struct gl_version *caps,
         xsft->setup_cb (xsft, xsft->setup_arg);
     }
     initted_p = YES;
-    resized_p = NO;
     NSAssert(!xdata, @"xdata already initialized");
 
 
@@ -1785,6 +1856,10 @@ gl_check_ver (const struct gl_version *caps,
 # if defined USE_IPHONE && defined JWXYZ_QUARTZ
   UIGraphicsPopContext();
 # endif
+
+# ifdef USE_TOUCHBAR
+  if (touchbar_view) [touchbar_view animateOneFrame];
+# endif
 }
 
 
@@ -1983,11 +2058,7 @@ gl_check_ver (const struct gl_version *caps,
   
   NSPoint p = [[[e window] contentView] convertPoint:[e locationInWindow]
                                             toView:self];
-# ifdef USE_IPHONE
   double s = [self hackedContentScaleFactor];
-# else
-  int s = 1;
-# endif
   int x = s * p.x;
   int y = s * ([self bounds].size.height - p.y);
 
@@ -2742,6 +2813,18 @@ gl_check_ver (const struct gl_version *caps,
     [self addSubview:closeBox];
   }
 
+  // Don't hide the buttons under the iPhone X bezel.
+  UIEdgeInsets is = { 0, };
+  if ([self respondsToSelector:@selector(safeAreaInsets)]) {
+#   pragma clang diagnostic push   // "only available on iOS 11.0 or newer"
+#   pragma clang diagnostic ignored "-Wunguarded-availability-new"
+    is = [self safeAreaInsets];
+#   pragma clang diagnostic pop
+    [closeBox setFrame:CGRectMake(is.left, is.top,
+                                  self.bounds.size.width - is.right - is.left,
+                                  ih + off)];
+  }
+
   if (closeBox.layer.opacity <= 0) {  // Fade in
 
     CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"opacity"];
index 74e15780416f6a7f90e3fe24db559462f37ab1be..9f112e7d40f66749d810657980bb2b7386555e88 100644 (file)
@@ -16,8 +16,8 @@
 \b0 by Jamie Zawinski\
 and many others\
 \
-version 5.37\
-05-Jul-2017\
+version 5.38\
+20-Dec-2017\
 \
 {\field{\*\fldinst{HYPERLINK "https://www.jwz.org/xscreensaver/"}}{\fldrslt \cf2 \ul \ulc2 https://www.jwz.org/xscreensaver/}}\
 \pard\pardeftab720
index fef1480dba947c8af7fd654c7493133d6856f8a0..e2923073863ce2bfa32188c4408b1713fb6ca462 100644 (file)
@@ -9,7 +9,7 @@
        <key>CFBundleExecutable</key>
        <string>${EXECUTABLE_NAME}</string>
        <key>CFBundleGetInfoString</key>
-       <string>5.37</string>
+       <string>5.38</string>
        <key>CFBundleIcons</key>
        <dict/>
        <key>CFBundleIcons~ipad</key>
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleLongVersionString</key>
-       <string>5.37</string>
+       <string>5.38</string>
        <key>CFBundleName</key>
        <string>${PRODUCT_NAME}</string>
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleShortVersionString</key>
-       <string>5.37</string>
+       <string>5.38</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.37</string>
+       <string>5.38</string>
        <key>LSRequiresIPhoneOS</key>
        <true/>
        <key>NSHumanReadableCopyright</key>
-       <string>5.37</string>
+       <string>5.38</string>
        <key>NSMainNibFile</key>
        <string>iSaverRunner</string>
        <key>UIAppFonts</key>
index e1a05a43fe1d94610e8c3cd58d34b01e78304c85..4940fd0558d4baabb33aae8322fa66df460f8cfb 100644 (file)
@@ -1,5 +1,5 @@
 /* Generated file, do not edit.
-   Created: Thu Jun  1 17:53:59 2017 by build-fntable.pl 1.5.
+   Created: Fri Dec  1 17:57:48 2017 by build-fntable.pl 1.5.
  */
 
 #import <Foundation/Foundation.h>
@@ -70,6 +70,7 @@ extern struct xscreensaver_function_table
  engine_xscreensaver_function_table,
  epicycle_xscreensaver_function_table,
  eruption_xscreensaver_function_table,
+ esper_xscreensaver_function_table,
  euler2d_xscreensaver_function_table,
  fadeplot_xscreensaver_function_table,
  fiberlamp_xscreensaver_function_table,
@@ -302,6 +303,7 @@ NSDictionary *make_function_table_dict(void)
        [NSValue valueWithPointer:&engine_xscreensaver_function_table], @"engine",
        [NSValue valueWithPointer:&epicycle_xscreensaver_function_table], @"epicycle",
        [NSValue valueWithPointer:&eruption_xscreensaver_function_table], @"eruption",
+       [NSValue valueWithPointer:&esper_xscreensaver_function_table], @"esper",
        [NSValue valueWithPointer:&euler2d_xscreensaver_function_table], @"euler2d",
        [NSValue valueWithPointer:&fadeplot_xscreensaver_function_table], @"fadeplot",
        [NSValue valueWithPointer:&fiberlamp_xscreensaver_function_table], @"fiberlamp",
index 9c8f7cfb418afb959247a9460727c27b2657bc38..d4d2a0118dd4229b51ee0c296da2a6136fd7257f 100644 (file)
@@ -7,6 +7,17 @@
   <link>https://www.jwz.org/xscreensaver/updates.xml</link>
   <description>Updates to xscreensaver.</description>
   <language>en</language>
+  <item>
+   <title>Version 5.37</title>
+   <link>https://www.jwz.org/xscreensaver/xscreensaver-5.37.dmg</link>
+   <description><![CDATA[&bull; New hack, `vigilance'. <BR>&bull; Added Mac Software Update and VMware to `bsod'. <BR>&bull; OSX: Grabbing the desktop works again. <BR>&bull; OSX: Pinch to zoom. <BR>&bull; Android: Both Daydreams and Live Wallpapers are implemented. <BR>&bull; Updated `webcollage' for recent changes. <BR>&bull; Various bug fixes.]]></description>
+   <pubDate>Wed, 05 Jul 2017 10:55:51 -0700</pubDate>
+   <enclosure url="https://www.jwz.org/xscreensaver/xscreensaver-5.37.dmg"
+    sparkle:version="5.37"
+    sparkle:dsaSignature="MCwCFFsEWCDZbAY8Owz7k4lcs+uGM+LUAhQlLSsjg0Eqkd2TX2UfxiFdPrciTA=="
+    length="52481386"
+    type="application/octet-stream" />
+  </item>
   <item>
    <title>Version 5.36</title>
    <link>https://www.jwz.org/xscreensaver/xscreensaver-5.36.dmg</link>
index 479545fd0edb512278e59897ef620204bb7ede81..942114b9d757f2ec4a6558f8654327a6c55a1555 100644 (file)
                                AF777A3D09B660B500EA3033 /* PBXTargetDependency */,
                                AFACE8911CC8365F008B24CD /* PBXTargetDependency */,
                                AF777A3B09B660B500EA3033 /* PBXTargetDependency */,
+                               AF21078F1FD23D9800B61EA9 /* PBXTargetDependency */,
                                AF777A3909B660B400EA3033 /* PBXTargetDependency */,
                                AF777A3709B660B400EA3033 /* PBXTargetDependency */,
                                AF777A3509B660B400EA3033 /* PBXTargetDependency */,
                AF1FDA88158FF96600C40F17 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
                AF1FDA89158FF96600C40F17 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
                AF1FDA8A158FF96600C40F17 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AF2107781FD23BDD00B61EA9 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AF21077A1FD23BDD00B61EA9 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AF21077B1FD23BDD00B61EA9 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AF21077C1FD23BDD00B61EA9 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AF21077D1FD23BDD00B61EA9 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AF21077E1FD23BDD00B61EA9 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AF21077F1FD23BDD00B61EA9 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AF2107801FD23BDD00B61EA9 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AF2107891FD23D2800B61EA9 /* esper.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF2107881FD23D2800B61EA9 /* esper.xml */; };
+               AF21078A1FD23D2800B61EA9 /* esper.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF2107881FD23D2800B61EA9 /* esper.xml */; };
+               AF21078C1FD23D5000B61EA9 /* esper.c in Sources */ = {isa = PBXBuildFile; fileRef = AF21078B1FD23D5000B61EA9 /* esper.c */; };
+               AF21078D1FD23D5000B61EA9 /* esper.c in Sources */ = {isa = PBXBuildFile; fileRef = AF21078B1FD23D5000B61EA9 /* esper.c */; settings = {COMPILER_FLAGS = "-DUSE_GL"; }; };
+               AF2107901FD23FEC00B61EA9 /* OCRAStd.otf in Resources */ = {isa = PBXBuildFile; fileRef = AFEC68361BD6CA85004C1B64 /* OCRAStd.otf */; };
                AF241F83107C38DF00046A84 /* dropshadow.c in Sources */ = {isa = PBXBuildFile; fileRef = AF241F81107C38DF00046A84 /* dropshadow.c */; };
                AF2C31E615C0F7FE007A6896 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
                AF2C31EA15C0FC9C007A6896 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
                        remoteGlobalIDString = AF1B0FA71D7AB4740011DBE4;
                        remoteInfo = Hexstrut;
                };
+               AF2107731FD23BDD00B61EA9 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AF21078E1FD23D9800B61EA9 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF2107711FD23BDD00B61EA9;
+                       remoteInfo = Esper;
+               };
                AF32D9E20F3AD0B40080F535 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                AF1B0FBC1D7AB4740011DBE4 /* Hexstrut.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Hexstrut.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AF1B0FBE1D7AB5210011DBE4 /* hexstrut.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = hexstrut.c; path = hacks/glx/hexstrut.c; sourceTree = "<group>"; };
                AF1B0FBF1D7AB5210011DBE4 /* hexstrut.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = hexstrut.xml; sourceTree = "<group>"; };
+               AF2107861FD23BDE00B61EA9 /* Esper.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Esper.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AF2107881FD23D2800B61EA9 /* esper.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = esper.xml; sourceTree = "<group>"; };
+               AF21078B1FD23D5000B61EA9 /* esper.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = esper.c; path = hacks/glx/esper.c; sourceTree = "<group>"; };
                AF241F81107C38DF00046A84 /* dropshadow.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = dropshadow.c; path = hacks/glx/dropshadow.c; sourceTree = "<group>"; };
                AF241F82107C38DF00046A84 /* dropshadow.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; name = dropshadow.h; path = hacks/glx/dropshadow.h; sourceTree = "<group>"; };
                AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF2107791FD23BDD00B61EA9 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF21077A1FD23BDD00B61EA9 /* libjwxyz.a in Frameworks */,
+                               AF21077B1FD23BDD00B61EA9 /* ScreenSaver.framework in Frameworks */,
+                               AF21077C1FD23BDD00B61EA9 /* QuartzCore.framework in Frameworks */,
+                               AF21077D1FD23BDD00B61EA9 /* Cocoa.framework in Frameworks */,
+                               AF21077E1FD23BDD00B61EA9 /* Carbon.framework in Frameworks */,
+                               AF21077F1FD23BDD00B61EA9 /* OpenGL.framework in Frameworks */,
+                               AF2107801FD23BDD00B61EA9 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF32D9E80F3AD0B40080F535 /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                                AFEE10A01D17E20B00AAC8F7 /* Splodesic.saver */,
                                AF1B0FBC1D7AB4740011DBE4 /* Hexstrut.saver */,
                                AF633C161EE0BA6F00AB33BD /* Vigilance.saver */,
+                               AF2107861FD23BDE00B61EA9 /* Esper.saver */,
                        );
                        name = Products;
                        path = ..;
                                AFA55E2509935F2B00F3E977 /* endgame.c */,
                                AFACE88A1CC83578008B24CD /* energystream.c */,
                                AFA55C230993435300F3E977 /* engine.c */,
+                               AF21078B1FD23D5000B61EA9 /* esper.c */,
                                AF642409099FFAF0000F4CD4 /* extrusion-helix2.c */,
                                AF64240A099FFAF0000F4CD4 /* extrusion-helix3.c */,
                                AF64240B099FFAF0000F4CD4 /* extrusion-helix4.c */,
                                AFC2589C0988A468000655EE /* engine.xml */,
                                AFC2589D0988A468000655EE /* epicycle.xml */,
                                AFC2589E0988A468000655EE /* eruption.xml */,
+                               AF2107881FD23D2800B61EA9 /* esper.xml */,
                                AFC2589F0988A468000655EE /* euler2d.xml */,
                                AFC258A00988A468000655EE /* extrusion.xml */,
                                AFC258A10988A468000655EE /* fadeplot.xml */,
                        productReference = AF1B0FBC1D7AB4740011DBE4 /* Hexstrut.saver */;
                        productType = "com.apple.product-type.bundle";
                };
+               AF2107711FD23BDD00B61EA9 /* Esper */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AF2107831FD23BDD00B61EA9 /* Build configuration list for PBXNativeTarget "Esper" */;
+                       buildPhases = (
+                               AF2107741FD23BDD00B61EA9 /* Resources */,
+                               AF2107761FD23BDD00B61EA9 /* Sources */,
+                               AF2107791FD23BDD00B61EA9 /* Frameworks */,
+                               AF2107811FD23BDD00B61EA9 /* Rez */,
+                               AF2107821FD23BDD00B61EA9 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AF2107721FD23BDD00B61EA9 /* PBXTargetDependency */,
+                       );
+                       name = Esper;
+                       productName = DangerBall;
+                       productReference = AF2107861FD23BDE00B61EA9 /* Esper.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
                AF32D9E00F3AD0B40080F535 /* RubikBlocks */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = AF32D9F10F3AD0B40080F535 /* Build configuration list for PBXNativeTarget "RubikBlocks" */;
                29B97313FDCFA39411CA2CEA /* Project object */ = {
                        isa = PBXProject;
                        attributes = {
-                               LastUpgradeCheck = 0830;
+                               LastUpgradeCheck = 0920;
                                TargetAttributes = {
                                        AF08398F09930B6B00277BE9 = {
                                                DevelopmentTeam = 4627ATJELP;
                                        AF1B0FA71D7AB4740011DBE4 = {
                                                DevelopmentTeam = 4627ATJELP;
                                        };
+                                       AF2107711FD23BDD00B61EA9 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
                                        AF32D9E00F3AD0B40080F535 = {
                                                DevelopmentTeam = 4627ATJELP;
                                        };
                                AFACE8731CC83458008B24CD /* EnergyStream */,
                                AFA55E0D09935EDC00F3E977 /* Endgame */,
                                AFA55C0E0993431300F3E977 /* Engine */,
+                               AF2107711FD23BDD00B61EA9 /* Esper */,
                                AF6423F2099FF9C2000F4CD4 /* Extrusion */,
                                AFA5603209936D5100F3E977 /* FlipFlop */,
                                AF77773E09B6446500EA3033 /* FlipScreen3D */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF2107741FD23BDD00B61EA9 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF2107891FD23D2800B61EA9 /* esper.xml in Resources */,
+                               AF2107901FD23FEC00B61EA9 /* OCRAStd.otf in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF32D9E30F3AD0B40080F535 /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                                AF918AEB158FC53D002B5D1E /* engine.xml in Resources */,
                                AF918AEC158FC53D002B5D1E /* epicycle.xml in Resources */,
                                AF918AED158FC53D002B5D1E /* eruption.xml in Resources */,
+                               AF21078A1FD23D2800B61EA9 /* esper.xml in Resources */,
                                AF918AEE158FC53D002B5D1E /* euler2d.xml in Resources */,
                                AF918AF0158FC53D002B5D1E /* fadeplot.xml in Resources */,
                                AF918AF1158FC53D002B5D1E /* fiberlamp.xml in Resources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF2107811FD23BDD00B61EA9 /* Rez */ = {
+                       isa = PBXRezBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF32D9EF0F3AD0B40080F535 /* Rez */ = {
                        isa = PBXRezBuildPhase;
                        buildActionMask = 2147483647;
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
+               AF2107821FD23BDD00B61EA9 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
+                       showEnvVarsInLog = 0;
+               };
                AF32D9F00F3AD0B40080F535 /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF2107761FD23BDD00B61EA9 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF2107781FD23BDD00B61EA9 /* XScreenSaverSubclass.m in Sources */,
+                               AF21078C1FD23D5000B61EA9 /* esper.c in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF32D9E50F3AD0B40080F535 /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                                AF918A4A158FC3E5002B5D1E /* endgame.c in Sources */,
                                AFACE88F1CC83617008B24CD /* energystream.c in Sources */,
                                AF918A4B158FC3E5002B5D1E /* engine.c in Sources */,
+                               AF21078D1FD23D5000B61EA9 /* esper.c in Sources */,
                                AF918A54158FC3E5002B5D1E /* flipflop.c in Sources */,
                                AF918A55158FC3E5002B5D1E /* flipscreen3d.c in Sources */,
                                AF918A56158FC3E5002B5D1E /* fliptext.c in Sources */,
                        target = AF1B0FA71D7AB4740011DBE4 /* Hexstrut */;
                        targetProxy = AF1B0FC41D7AB5740011DBE4 /* PBXContainerItemProxy */;
                };
+               AF2107721FD23BDD00B61EA9 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AF2107731FD23BDD00B61EA9 /* PBXContainerItemProxy */;
+               };
+               AF21078F1FD23D9800B61EA9 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF2107711FD23BDD00B61EA9 /* Esper */;
+                       targetProxy = AF21078E1FD23D9800B61EA9 /* PBXContainerItemProxy */;
+               };
                AF32D9E10F3AD0B40080F535 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
                        };
                        name = Release;
                };
+               AF2107841FD23BDD00B61EA9 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AF2107851FD23BDD00B61EA9 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
                AF32D9F20F3AD0B40080F535 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
                                BUNDLE_IDENTIFIER = "org.jwz.${PROJECT_NAME:rfc1034identifier}.${PRODUCT_NAME:rfc1034identifier}";
                                CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
+                               CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
+                               CLANG_WARN_COMMA = NO;
                                CLANG_WARN_CONSTANT_CONVERSION = YES;
                                CLANG_WARN_EMPTY_BODY = YES;
                                CLANG_WARN_ENUM_CONVERSION = YES;
                                CLANG_WARN_INFINITE_RECURSION = YES;
                                CLANG_WARN_INT_CONVERSION = YES;
+                               CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
                                CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+                               CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+                               CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+                               CLANG_WARN_STRICT_PROTOTYPES = YES;
                                CLANG_WARN_SUSPICIOUS_MOVE = YES;
                                CLANG_WARN_UNREACHABLE_CODE = NO;
                                CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
                                        "GETTIMEOFDAY_TWO_ARGS=1",
                                        "HAVE_UNISTD_H=1",
                                        "STANDALONE=1",
+                                       "HAVE_GL=1",
                                        "HAVE_GLBINDTEXTURE=1",
                                        "HAVE_UNAME=1",
                                        "HAVE_ICMP=1",
                                        "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
                                );
                                GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+                               GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
                                GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
                                GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
                                GCC_WARN_ABOUT_RETURN_TYPE = YES;
                                ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
                                BUNDLE_IDENTIFIER = "org.jwz.${PROJECT_NAME:rfc1034identifier}.${PRODUCT_NAME:rfc1034identifier}";
                                CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
+                               CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
+                               CLANG_WARN_COMMA = NO;
                                CLANG_WARN_CONSTANT_CONVERSION = YES;
                                CLANG_WARN_EMPTY_BODY = YES;
                                CLANG_WARN_ENUM_CONVERSION = YES;
                                CLANG_WARN_INFINITE_RECURSION = YES;
                                CLANG_WARN_INT_CONVERSION = YES;
+                               CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
                                CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+                               CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+                               CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+                               CLANG_WARN_STRICT_PROTOTYPES = YES;
                                CLANG_WARN_SUSPICIOUS_MOVE = YES;
                                CLANG_WARN_UNREACHABLE_CODE = NO;
                                CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
                                        "GETTIMEOFDAY_TWO_ARGS=1",
                                        "HAVE_UNISTD_H=1",
                                        "STANDALONE=1",
+                                       "HAVE_GL=1",
                                        "HAVE_GLBINDTEXTURE=1",
                                        "HAVE_UNAME=1",
                                        "HAVE_ICMP=1",
                                        "CLASS=XScreenSaver${EXECUTABLE_NAME}View",
                                        "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
                                );
+                               GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
                                GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
                                GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
                                GCC_WARN_ABOUT_RETURN_TYPE = YES;
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
+               AF2107831FD23BDD00B61EA9 /* Build configuration list for PBXNativeTarget "Esper" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AF2107841FD23BDD00B61EA9 /* Debug */,
+                               AF2107851FD23BDD00B61EA9 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                AF32D9F10F3AD0B40080F535 /* Build configuration list for PBXNativeTarget "RubikBlocks" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
diff --git a/README b/README
index 333b464f2d9439f760745be1b8b2e34cec7fe0f3..8a29747aada000706f41ade38ebf341d2514cf11 100644 (file)
--- a/README
+++ b/README
@@ -3,7 +3,8 @@
 
                              a collection of
                             free screen savers
-                            for X11 and MacOS
+                             for X11, macOS,
+                             iOS and Android
 
                             By Jamie Zawinski
                              and many others
@@ -14,8 +15,8 @@
 
 This is the XScreenSaver source code distribution.  It is strongly recommended
 that you install a binary release rather than trying to compile it yourself.
-Binaries are available for almost all platforms, including MacOS X.  See the
-XScreenSaver web site for details.
+Executables are available for almost all platforms, including macOS, iOS, and
+Android.  See the XScreenSaver web site for details.
 
 To compile for a Unix system with X11:
 
@@ -26,9 +27,9 @@ To compile for a Unix system with X11:
     If you are on an "apt"-based system, "apt-get build-dep xscreensaver"
     might install most of the compilation dependencies.
 
-To compile for MacOS X or iOS:
+To compile for macOS X or iOS:
 
-    Use the included XCode project.  Requires XCode 6 and MacOS X 10.8
+    Use the included XCode project.  Requires XCode 6 and macOS 10.8
     or newer.
 
 To compile for Android:
@@ -45,27 +46,49 @@ XScreenSaver has an extensive manual -- please read it!
 
 ===============================================================================
 
+5.38   * New hack, 'esper'.
+       * macOS: Support for Retina displays.
+       * X11: `webcollage' now works with ImageMagick instead of with
+         pbmtools if `webcollage-helper' is not installed.
+       * 'bsod' now accepts Dunning-Krugerrands.
+       * Android: These hacks work now: 'anemone', 'anemotaxis', 'atlantis',
+         'bouboule', 'celtic', 'compass', 'crackberg', 'epicycle',
+         'fuzzyflakes', 'goop', 'kumppa' 'munch', 'pacman', 'polyominoes',
+         'slip'.
+       * Android: Thick lines work better for: 'anemone', 'anemotaxis',
+         'celtic', 'compass', 'deluxe', 'epicycle', 'fuzzyflakes', 'pacman'
+       * Android: Assorted performance improvements, especially for 'kumppa'
+         and 'slip'.
+        * Android TV: Daydreams work.
+       * iOS: Tweaks for iPhone X.
+       * Lots of xlockmore-derived hacks now have animated erase routines.
+       * 'crystal' works properly on non-X11 systems.
+       * 'm6502' now includes 'texture.asm'.
+       * X11: Try harder to find sensible fonts for the password dialog.
+
 5.37   * New hack, `vigilance'.
        * Added Mac Software Update and VMware to `bsod'.
-       * OSX: Grabbing the desktop works again.
-       * OSX: Pinch to zoom.
+       * macOS: Grabbing the desktop works again.
+       * macOS: Pinch to zoom.
        * Android: Both Daydreams and Live Wallpapers are implemented.
        * Updated `webcollage' for recent changes.
        * Various bug fixes.
+
 5.36   * New hacks, `discoball', `cubetwist', `cubestack', `splodesic'
           and `hexstrut'.
-       * OSX: loading image files works in `dymaxionmap', `glplanet',
+       * macOS: loading image files works in `dymaxionmap', `glplanet',
          `lavalite', `pulsar', `gleidescope' and `extrusion'.
         * Several new programs in `m6502'.
         * `rotzoomer -mode circle'.
         * Better titles in `photopile'.
+
 5.35   * New hacks, `dymaxionmap', `unicrud', `energystream', `raverhoop'
           and `hydrostat'.
        * Added Windows 10 to `bsod'.
        * X11: ignore WM_USER_TIME property changes with days-old timestamps.
           Thanks, KDE.
-        * MacOS, iOS: Better fonts in `BSOD' and `memscroller'.
-       * MacOS 10.8 or later and iOS 6.0 or later are now required, since
+        * macOS, iOS: Better fonts in `bsod' and `memscroller'.
+       * macOS 10.8 or later and iOS 6.0 or later are now required, since
          Xcode 6 can no longer build executables that work on older OSes.
        * Many, many Android improvements.
        * iOS: Fixed rotation to work with the new iOS 8+ API.
@@ -73,7 +96,7 @@ XScreenSaver has an extensive manual -- please read it!
 
 5.34   * Fixed a crash when hot-swapping monitors while locked.
        * Fixed some incorrect output from `xscreensaver-command -watch'.
-       * Various OSX and iOS performance improvements.
+       * Various macOS and iOS performance improvements.
 
 5.33   * New hacks, `splitflap' and `romanboy'.
        * Better detection of user activity on modern GNOME systems.
@@ -84,20 +107,20 @@ XScreenSaver has an extensive manual -- please read it!
 
 5.32   * Fixed some X11 compilation problems.
        * Fixed display size and shake gestures on iOS.
-       * OSX/iOS Performance improvements.
+       * macOS/iOS Performance improvements.
 
 5.31   * New hacks, `geodesicgears', `binaryring' and `cityflow'.
         * UTF-8 text support (instead of only Latin1) and antialiased text
-          on X11 with Xft (instead of only on OSX/iOS) in `fontglide',
+          on X11 with Xft (instead of only on macOS/iOS) in `fontglide',
           `noseguy', `fliptext', `starwars', and `winduprobot'.
           The other text-displaying hacks (`apple2', `phosphor', `xmatrix',
           and `gltext') also now accept UTF-8 input, though they convert it
           to Latin1 or ASCII.
        * `glplanet' now has both day and night maps, and a sharp terminator.
-       * Fixed `webcollage' on OSX.
+       * Fixed `webcollage' on macOS.
        * Fixed a transparency glitch in `winduprobot'.
        * `lockward' works on iOS.
-       * Text and image loading work on OSX 10.10.
+       * Text and image loading work on macOS 10.10.
        * Rotation works properly on iOS 8.
        * Added a search field on iOS.
        * Preliminary, unfinished support for Android.
@@ -112,7 +135,7 @@ XScreenSaver has an extensive manual -- please read it!
        * Most hacks respond to mouse-clicks, double-taps and swipes as
           meaning "do something different now".
        * Reworked OpenGL fonts.
-       * The OSX auto-update installer wasn't working. This time for sure?
+       * The macOS auto-update installer wasn't working. This time for sure?
        * Various minor fixes.
 
 5.29   * Downgraded to Xcode 5.0.2 to make it possible to build savers
@@ -120,7 +143,7 @@ XScreenSaver has an extensive manual -- please read it!
        * Updated `webcollage' for recent changes.
 
 5.28   * Fixed some compilation problems and intermittent crashes.
-        * Turned off the OSX 10.6 enable_gc hack. It didn't work.
+        * Turned off the macOS 10.6 enable_gc hack. It didn't work.
 
 5.27   * New hacks, `tessellimage' and `projectiveplane'.
         * Added support for pthreads, because Dave Odell is a madman.
@@ -129,16 +152,16 @@ XScreenSaver has an extensive manual -- please read it!
         * X11: Don't assume Suspend = 0 implies "No DPMS".
        * Minor updates to `boxed' and `klein'.
         * Fixed possible crash in `apple2', `noseguy', `xmatrix', `shadebobs'.
-        * Fixed possible crash in OSX preferences.
-        * OSX Performance improvements.
+        * Fixed possible crash in macOS preferences.
+        * macOS Performance improvements.
         * Plugged some leaks.
 
 5.26   * More auto-updater tweaks.
 
-5.25   * Try harder to bypass Quarrantine and Gatekeeper in OSX installer.
+5.25   * Try harder to bypass Quarrantine and Gatekeeper in macOS installer.
        * Some files were missing from the tarball.
 
-5.24   * Added "Automatically check for updates" option on OSX.
+5.24   * Added "Automatically check for updates" option on macOS.
        * Updated feed-loading for recent Flickr changes.
        * Updated `webcollage' for recent Google changes.
        * Added Instagram and Bing as `webcollage' image sources.
@@ -146,13 +169,13 @@ XScreenSaver has an extensive manual -- please read it!
        * Bug fixes.
 
 5.23   * New hack, `geodesic'.
-       * iOS and OSX: huge XCopyArea performance improvements.
+       * iOS and macOS: huge XCopyArea performance improvements.
        * More heuristics for using RSS feeds as image sources.
        * Improved Wikipedia parser.
        * Updated `webcollage' for recent Flickr changes.
        * Added Android to `bsod'.
-       * OSX: Added a real installer.
-       * iOS and OSX: fixed a font-metrics bug.
+       * macOS: Added a real installer.
+       * iOS and macOS: fixed a font-metrics bug.
        * iOS: Fixed aspect ratio bug in non-rotating apps when launched in
          landscape mode.
        * Made `quasicrystal' work on weak graphics cards.
@@ -181,14 +204,14 @@ XScreenSaver has an extensive manual -- please read it!
          now requires a login to get any feeds.
        * New version of `fireworkx'.
        * Minor fixes to `distort', `fontglide', `xmatrix'.
-       * New MacOS crash in `bsod'.
+       * New macOS crash in `bsod'.
        * New mode in `lcdscrub'.
 
 5.20   * Support for iPhone 5 screen size.
-       * Fixed modifier key handing in Apple2.app and Phosphor.app on MacOS.
+       * Fixed modifier key handing in Apple2.app and Phosphor.app on macOS.
        * Various minor bug fixes.
 
-5.19   * MacOS 10.8.0 compatibility.
+5.19   * macOS 10.8.0 compatibility.
        * iOS performance improvements.
 
 5.18   * iOS responds to shake gestures to randomize.
@@ -216,10 +239,10 @@ XScreenSaver has an extensive manual -- please read it!
          `imageDirectory' may contain a URL.
        * Updated `webcollage' for recent search engine changes.
        * `phosphor' and `apple2' can now be run as standalone terminal
-         emulator applications on MacOS.
+         emulator applications on macOS.
        * `photopile' sped up.
        * New molecule in `molecule'.
-       * "Upgraded" to XCode 4.0, which means that MacOS 10.4 PPC builds are
+       * "Upgraded" to XCode 4.0, which means that macOS 10.4 PPC builds are
          impossible, and Intel is now required.
        * Turned on LC_CTYPE on Linux; maybe Japanese password entry works
          now?
@@ -238,10 +261,10 @@ XScreenSaver has an extensive manual -- please read it!
        * Passwords that contain UTF-8 non-Latin1 chars are now typeable.
        * Numerous minor stability fixes.
 
-5.12   * Big speed improvement on OSX for heavy XCopyArea users (`xmatrix',
+5.12   * Big speed improvement on macOS for heavy XCopyArea users (`xmatrix',
          `moire2', `phosphor', etc.)
-       * Plugged a bad OSX-only Pixmap leak.
-       * Kludged around the OSX pty bug that caused text to be truncated in
+       * Plugged a bad macOS-only Pixmap leak.
+       * Kludged around the macOS pty bug that caused text to be truncated in
          phosphor, starwars, apple2, etc.
        * New molecule in `molecule'.
        * `glhanoi' now supports an arbitrary number of poles.
@@ -249,25 +272,25 @@ XScreenSaver has an extensive manual -- please read it!
        * Added support for XInput-style alternate input devices.
 
 5.11   * New versions of `photopile', `strange'.
-       * Worked around MacOS 10.6 garbage collector bug that caused the
+       * Worked around macOS 10.6 garbage collector bug that caused the
          screen saver process to become enormous.
        * Fixed flicker in `pipes', `cubestorm', and `noof'.
-       * Fixed EXIF rotation on MacOS 10.6.
-       * Fixed desktop-grabbing when screen locked on MacOS.
+       * Fixed EXIF rotation on macOS 10.6.
+       * Fixed desktop-grabbing when screen locked on macOS.
        * Minor fixes to `circuit', `polyhedra', `tangram', `gears', `pinion',
          `substrate', `xanalogtv'.
        * Fixed some leaks in `xanalogtv' and `apple2'.
        * Better seeding of the RNG.
 
-5.10   * Fixed some crashes and color problems on MacOS 10.6.
+5.10   * Fixed some crashes and color problems on macOS 10.6.
        * Retired `hypercube' and `hyperball', which are redundant with
          `polytopes'.
 
 
-5.09   * Ported to MacOS 10.6, including various 64-bit fixes.
+5.09   * Ported to macOS 10.6, including various 64-bit fixes.
        * New hack, `rubikblocks'.
        * Fixed another potential RANDR crash.
-       * Use correct proxy server on MacOS.
+       * Use correct proxy server on macOS.
        * `molecule' now correctly displays PDB 3.2 files.
        * Updates to `mirrorblob', `glhanoi', and `sonar'.
        * Rewritten version of `klein' hack.
@@ -298,11 +321,11 @@ XScreenSaver has an extensive manual -- please read it!
        * `flipflop' can load images onto the tiles.
        * Fixed the bouncing ball in `stairs'.
        * Added the missing Utah Teapotahedron to `polyhedra'.
-       * `blitspin' works with color images on MacOS now.
+       * `blitspin' works with color images on macOS now.
        * Added transparency to `stonerview'.
        * Improved layout of the preferences dialogs: they should all now be
          usable even on ridiculously tiny laptop screens.
-       * MacOS preferences text fields now prevent you from entering numbers
+       * macOS preferences text fields now prevent you from entering numbers
          that are out of range.
        * Added "Reset to Defaults" button on X11.
        * Added relevant Wikipedia links to many of the screen saver
@@ -331,9 +354,9 @@ XScreenSaver has an extensive manual -- please read it!
          rectangles available.
        * Don't warning about receipt of bogus ClientMessages, since Gnome's
          just never going to stop sending those.
-       * Worked around MacOS 10.5 perl bug that caused the text-displaying
+       * Worked around macOS 10.5 perl bug that caused the text-displaying
          hacks to fail on some systems.
-       * Hopefully fixed font-related System Preferences crashes in MacOS
+       * Hopefully fixed font-related System Preferences crashes in macOS
          savers.
        * The recent PAM changes broke the "Caps Lock" warning in the password
          dialog, the failed login warnings, and syslogging.  Fixed all that.
@@ -347,7 +370,7 @@ XScreenSaver has an extensive manual -- please read it!
          `fireworkx' and `webcollage'.
        * `pong' can now display the current time as the score.
        * `xmatrix -mode pipe' works better.
-       * Minor tweaks for compilation on MacOS 10.5.0.
+       * Minor tweaks for compilation on macOS 10.5.0.
 
 5.03   * New hacks, `cwaves', `glcells', `m6502', and `voronoi'.
        * Minor fixes to `bsod'.
@@ -356,27 +379,27 @@ XScreenSaver has an extensive manual -- please read it!
          changes.
 
 5.02   * Reworked PAM code to support fingerprint readers, etc.
-       * Ported `webcollage' to MacOS.
-       * Added MacOS 10.2 and 10.3 kernel panics to `bsod'.
+       * Ported `webcollage' to macOS.
+       * Added macOS 10.2 and 10.3 kernel panics to `bsod'.
        * Fixed a Xinerama crash when changing the screen count.
        * New blobbier `mirrorblob'.
        * Minor updates to `lisa', `bsod', `ifs', `hypertorus', `polytopes',
          `circuit', `endgame', `crackberg', `flipflop', `flipscreen3d',
          `fliptext', and `carousel'.
-       * Enabled multi-threaded OpenGL on MacOS.
+       * Enabled multi-threaded OpenGL on macOS.
 
 5.01   * Backed out recent locale-related changes, since they broke far more
          things than they fixed.
        * Fail gracefully with ridiculously small window sizes.
-       * `xflame' and `flag' ignore bitmap option on MacOS.
-       * `speedmine' prefs work on MacOS.
+       * `xflame' and `flag' ignore bitmap option on macOS.
+       * `speedmine' prefs work on macOS.
        * Better explosions in `boxed'.
        * More dynamic motion in `sproingies'.
        * More options in `flipflop'.
        * Minor updates to `topblock'.
        * Various other minor fixes.
 
-5.00   * Ported to MacOS X! (10.4.0 or newer)
+5.00   * Ported to macOS! (10.4.0 or newer)
        * API change: instead of providing a single screenhack() function that
          does not return, screen savers using the screenhack.h framework must
          now provide "init" and "draw one frame" functions instead.  All
@@ -392,7 +415,7 @@ XScreenSaver has an extensive manual -- please read it!
        * Changes to the defaults and command-line options of many hacks to
          make the .xml files more consistent.
        * Reap zombies in `glslideshow' and `carousel'.
-       * `sonar' works without setuid on MacOS (dgram icmp).
+       * `sonar' works without setuid on macOS (dgram icmp).
        * `xmatrix -mode pipe' displays the text of a subprocess.
        * `endgame' has higher resolution chess-piece models.
        * `webcollage' takes a -directory option to get images from a local
@@ -419,7 +442,7 @@ XScreenSaver has an extensive manual -- please read it!
          seem to be installed.
        * Don't install `ant' by default, since there is some Java tool of
          that name, which was causing confusion.  And also it's boring.
-       * Made screen grabbing work again on MacOS 10.4.2.
+       * Made screen grabbing work again on macOS 10.4.2.
        * No longer prints bogus warnings about ClientMessages intended for
          the window manager.
        * Ignore unprintable characters in passwd entry field.
@@ -539,7 +562,7 @@ XScreenSaver has an extensive manual -- please read it!
        * New version of `glsnake' (with many more models.)
        * Another Windows crash in `bsod'; also HVX/GCOS6/TPS6.
        * New version of `endgame'.
-       * Screen grabbing works on MacOS X.
+       * Screen grabbing works on macOS.
        * Various minor fixes.
 
 4.13   * On Xinerama systems, xscreensaver now runs one hack on each monitor
@@ -582,7 +605,7 @@ XScreenSaver has an extensive manual -- please read it!
 
 4.08   * New hacks, `atunnels' and `piecewise'.
        * Physics improvement in `fluidballs'.
-       * Various fixes for XDarwin systems (X11 on MacOS X.)
+       * Various fixes for XDarwin systems (X11 on macOS.)
        * Added -clock option to `barcode'.
        * Minor fixes to `endgame', `flurry', `flipscreen3d', and `gflux'.
 
@@ -619,7 +642,7 @@ XScreenSaver has an extensive manual -- please read it!
        * Updated to latest `config.guess' and `config.sub'.
        * Fixed occasional core dump in `distort'.
        * Added a Linux fsck failure and kernel panic to `bsod'.
-       * Added MacOS X kernel panic to `bsod'.
+       * Added macOS kernel panic to `bsod'.
        * Fixed a bug in `bsod' (all bsod bugs are ironic.)
        * Fixed a bug that caused `xscreensaver-gl-helper' to print a nonsense
          visual ID with some versions of `printf': this could cause GL
index 3cceb5773c0be4ea083002a2a73d604d23b7e9d2..6fc2fe583c40370f0fc96f3dce9830d79ae170a7 100644 (file)
@@ -92,7 +92,7 @@ The XScreenSaver API
   You may not store global state in global variables, or in function-local
   static variables.  All of your runtime state must be encapsulted in the
   "state" object created by your "init" function.  If you use global or
-  static variables, your screen saver will not work properly on MacOS.
+  static variables, your screen saver will not work properly on macOS.
 
   Do not call XSync() or XFlush().  If you think you need to do that, it
   probably means that you are you are relying on the speed of the graphics
@@ -101,29 +101,46 @@ The XScreenSaver API
 
 
 ==========================================================================
-The XLockMore API
+The xlockmore API
 ==========================================================================
 
   Some of the display modes that come with xscreensaver were ported from
-  XLock, and so, for historical reasons, they follow a slightly different
+  xlock, and so, for historical reasons, they follow a slightly different
   programming convention.  For newly-written Xlib programs, you'd be
   better off following the pattern used in hacks like "Deluxe" than in
-  hacks like "Flag".  The XLockMore ones are the ones that begin with
+  hacks like "Flag".  The xlockmore ones are the ones that begin with
   "#ifdef STANDALONE" and #include "xlockmore.h".
 
-  But, all OpenGL screen savers have to follow the XLockMore API.
+  But, all OpenGL screen savers have to follow the xlockmore API.
 
-  The XLockMore API is similar to the XScreenSaver API, in that you define
+  The xlockmore API is similar to the XScreenSaver API, in that you define
   (roughly) the same set of functions, but the naming conventions are
   slightly different.  Instead of "hackname_init", it's "init_hackname",
   and it should be preceeded with the pseudo-declaration ENTRYPOINT.
 
-  One annoying mis-feature of the XLockMore API is that it *requires* you
+  One annoying mis-feature of the xlockmore API is that it *requires* you
   to make use of global variables for two things: first, for each of your
   command line options; and second, for an array that holds your global
   state objects.  These are the only exceptions to the "never use global
   variables" rule.
 
+  There are a few important differences between the original xlockmore API
+  and XScreenSaver's implementation:
+
+  - XScreenSaver does not use refresh_hackname or change_hackname.
+
+  - XScreenSaver provides two additional hooks not present in xlockmore:
+    reshape_hackname, and hackname_handle_event. These are respectively
+    equivalent to hackname_reshape and hackname_event in the XScreenSaver
+    API.
+
+  - Under Xlib, MI_CLEARWINDOW doesn't clear the window immediately.
+    Instead, due to double buffering on macOS/iOS/Android, it waits until
+    after init_hackname or draw_hackname returns before clearing. Make
+    sure not to issue any Xlib drawing calls immediately after a call to
+    MI_CLEARWINDOW, as these will be erased. To clear the window
+    immediately, just use XClearWindow.
+
 
 ==========================================================================
 Programming Tips
@@ -163,16 +180,19 @@ Programming Tips
 
 
 ==========================================================================
-MacOS, iOS and Android
+macOS, iOS and Android
 ==========================================================================
 
   Though XScreenSaver started its life as an X11 program, it also now runs
-  on MacOS, iOS and Android, due to a maniacal collection of compatibility
+  on macOS, iOS and Android, due to a maniacal collection of compatibility
   shims.  If you do your development on an X11 system, and follow the
   usual XScreenSaver APIs, you shouldn't need to do anything special for
-  it to also work on MacOS and on phones.
+  it to also work on macOS and on phones.
 
   See the READMEs in the OSX/ and android/ directories for instructions on
   compiling for those platforms.
 
+  To check that an X11 saver will fit well on a mobile device, test it
+  with -geometry 640x1136 and 640x960.  That's a good first step, anyway.
+
 ==========================================================================
index 03fbf5158016c09247081a3631a3bc115819ae7a..28686cb17ebf4914dc5891de494bda98cb0a9f0c 100644 (file)
@@ -1,6 +1,6 @@
-# generated automatically by aclocal 1.15 -*- Autoconf -*-
+# generated automatically by aclocal 1.15.1 -*- Autoconf -*-
 
-# Copyright (C) 1996-2014 Free Software Foundation, Inc.
+# Copyright (C) 1996-2017 Free Software Foundation, Inc.
 
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -111,6 +111,51 @@ fi
 AC_SUBST($1)dnl
 ])
 
+dnl Checks for special options needed on Mac OS X.
+dnl Defines INTL_MACOSX_LIBS.
+dnl
+dnl Copied from intlmacosx.m4 in gettext, GPL.
+dnl Copyright (C) 2004-2013 Free Software Foundation, Inc.
+glib_DEFUN([glib_gt_INTL_MACOSX],
+[
+  dnl Check for API introduced in Mac OS X 10.2.
+  AC_CACHE_CHECK([for CFPreferencesCopyAppValue],
+    [gt_cv_func_CFPreferencesCopyAppValue],
+    [gt_save_LIBS="$LIBS"
+     LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation"
+     AC_LINK_IFELSE(
+       [AC_LANG_PROGRAM(
+          [[#include <CoreFoundation/CFPreferences.h>]],
+          [[CFPreferencesCopyAppValue(NULL, NULL)]])],
+       [gt_cv_func_CFPreferencesCopyAppValue=yes],
+       [gt_cv_func_CFPreferencesCopyAppValue=no])
+     LIBS="$gt_save_LIBS"])
+  if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then
+    AC_DEFINE([HAVE_CFPREFERENCESCOPYAPPVALUE], [1],
+      [Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in the CoreFoundation framework.])
+  fi
+  dnl Check for API introduced in Mac OS X 10.3.
+  AC_CACHE_CHECK([for CFLocaleCopyCurrent], [gt_cv_func_CFLocaleCopyCurrent],
+    [gt_save_LIBS="$LIBS"
+     LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation"
+     AC_LINK_IFELSE(
+       [AC_LANG_PROGRAM(
+          [[#include <CoreFoundation/CFLocale.h>]],
+          [[CFLocaleCopyCurrent();]])],
+       [gt_cv_func_CFLocaleCopyCurrent=yes],
+       [gt_cv_func_CFLocaleCopyCurrent=no])
+     LIBS="$gt_save_LIBS"])
+  if test $gt_cv_func_CFLocaleCopyCurrent = yes; then
+    AC_DEFINE([HAVE_CFLOCALECOPYCURRENT], [1],
+      [Define to 1 if you have the Mac OS X function CFLocaleCopyCurrent in the CoreFoundation framework.])
+  fi
+  INTL_MACOSX_LIBS=
+  if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then
+    INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation"
+  fi
+  AC_SUBST([INTL_MACOSX_LIBS])
+])
+
 # GLIB_WITH_NLS
 #-----------------
 glib_DEFUN([GLIB_WITH_NLS],
@@ -124,6 +169,8 @@ glib_DEFUN([GLIB_WITH_NLS],
     XGETTEXT=:
     INTLLIBS=
 
+    glib_gt_INTL_MACOSX
+
     AC_CHECK_HEADER(libintl.h,
      [gt_cv_func_dgettext_libintl="no"
       libintl_extra_libs=""
@@ -207,7 +254,7 @@ glib_DEFUN([GLIB_WITH_NLS],
       fi
   
       if test "$gt_cv_func_dgettext_libintl" = "yes"; then
-        INTLLIBS="-lintl $libintl_extra_libs"
+        INTLLIBS="-lintl $libintl_extra_libs $INTL_MACOSX_LIBS"
       fi
   
       if test "$gt_cv_have_gettext" = "yes"; then
@@ -651,7 +698,7 @@ AC_DEFUN([AM_NLS],
   AC_SUBST([USE_NLS])
 ])
 
-# Copyright (C) 2006-2014 Free Software Foundation, Inc.
+# Copyright (C) 2006-2017 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
index 7549411bcb96ac8a9c0ea709e1ef5cd430ccfeba..0ba4f58acc579dbf29fa410eda14b165da5590bd 100644 (file)
@@ -1,7 +1,7 @@
 # XScreenSaver for Android
 
 export TERM=dumb
-GRADLE = cd project ; ./gradlew
+GRADLE = ./gradlew
 
 default:: debug
 all:: release
@@ -41,6 +41,7 @@ export ANDROID_HACKS=         \
        anemone                 \
        anemotaxis              \
        apollonian              \
+       atlantis                \
        attraction              \
        atunnel                 \
        blaster                 \
@@ -50,14 +51,17 @@ export ANDROID_HACKS=               \
        bouncingcow             \
        boxed                   \
        boxfit                  \
+       bouboule                \
        braid                   \
        bsod                    \
        cage                    \
        ccurve                  \
+       celtic                  \
        cloudlife               \
        companioncube           \
        compass                 \
        coral                   \
+       crackberg               \
        crystal                 \
        cubestack               \
        cubestorm               \
@@ -67,6 +71,7 @@ export ANDROID_HACKS=         \
        dangerball              \
        decayscreen             \
        deco                    \
+       deluxe                  \
        demon                   \
        discrete                \
        discoball               \
@@ -126,6 +131,7 @@ export ANDROID_HACKS=               \
        moebiusgears            \
        moire                   \
        morph3d                 \
+       munch                   \
        nerverot                \
        noof                    \
        penetrate               \
@@ -133,6 +139,7 @@ export ANDROID_HACKS=               \
        petri                   \
        piecewise               \
        pinion                  \
+       polyominoes             \
        polytopes               \
        pong                    \
        popsquares              \
@@ -153,6 +160,7 @@ export ANDROID_HACKS=               \
        sierpinski              \
        sierpinski3d            \
        slidescreen             \
+       slip                    \
        splodesic               \
        squiral                 \
        stairs                  \
@@ -179,6 +187,7 @@ export ANDROID_HACKS=               \
        wormhole                \
        xflame                  \
        xlyap                   \
+       xrayswarm               \
        xspirograph             \
 
 
@@ -188,23 +197,19 @@ ANDROID_TODO=                     \
        antinspect              \
        antmaze                 \
        antspotlight            \
-       atlantis                \
        barcode                 \
        binaryring              \
        blitspin                \
-       bouboule                \
        bumps                   \
        carousel                \
-       celtic                  \
        circuit                 \
        cityflow                \
-       crackberg               \
        cube21                  \
        cubenetic               \
        cubicgrid               \
-       deluxe                  \
        dymaxionmap             \
        endgame                 \
+       esper                   \
        flipscreen3d            \
        fliptext                \
        fontglide               \
@@ -226,19 +231,16 @@ ANDROID_TODO=                     \
        moire2                  \
        molecule                \
        mountain                \
-       munch                   \
        noseguy                 \
        pedal                   \
        phosphor                \
        photopile               \
        pipes                   \
-       polyominoes             \
        projectiveplane         \
        pulsar                  \
        qix                     \
        queens                  \
        skytentacles            \
-       slip                    \
        speedmine               \
        spheremonics            \
        splitflap               \
@@ -252,7 +254,6 @@ ANDROID_TODO=                       \
        xanalogtv               \
        xjack                   \
        xmatrix                 \
-       xrayswarm               \
        zoom                    \
 
 
@@ -285,7 +286,7 @@ m6502.h::
                fi; \
        done
 
-project/xscreensaver/res/drawable/%.png:
+xscreensaver/res/drawable/%.png:
        @\
        FILE1=`echo "$@" | sed 's!^.*/\([^/]*\)\.png$$!\1.jpg!'` ;      \
        FILE2="$@" ;                                                    \
@@ -303,19 +304,19 @@ project/xscreensaver/res/drawable/%.png:
 
 thumbs::
        @for f in $(ANDROID_HACKS) $(ANDROID_TODO) ; do                 \
-         $(MAKE) project/xscreensaver/res/drawable/$$f.png ;           \
+         $(MAKE) xscreensaver/res/drawable/$$f.png ;                   \
        done
 
 clean_thumbs::
        @\
        for f in $(ANDROID_HACKS) $(ANDROID_TODO) ; do                  \
-         rm -f project/xscreensaver/res/drawable/$$f.png ;             \
+         rm -f xscreensaver/res/drawable/$$f.png ;                     \
        done
 
 distclean:: clean_thumbs clean
 
 
-EXTRA_TARFILES = project/xscreensaver/res/drawable/thumbnail.png \
+EXTRA_TARFILES = xscreensaver/res/drawable/thumbnail.png \
 
 echo_tarfiles:
        @FILES=`find . $(EXTRA_TARFILES) \( \(  \
@@ -358,7 +359,7 @@ $(KEYSTORE):
        keytool -genkey -v -keystore $@ \
        -alias xscreensaver -keyalg RSA -keysize 2048 -validity 10000
 
-APK_DIR       = project/xscreensaver/build/outputs/apk/
+APK_DIR       = xscreensaver/build/outputs/apk/
 APK_UNSIGNED  = $(APK_DIR)/xscreensaver-release-unsigned.apk
 APK_UNALIGNED = $(APK_DIR)/xscreensaver-release-unaligned.apk
 APK_SIGNED    = $(APK_DIR)/xscreensaver-release.apk
index fb7a4da9c5a24e0ea97e938e2991ca5702010bb3..0a2081f16fec2714ff91037f9cef74d4aca13211 100644 (file)
@@ -19,9 +19,9 @@ To set up your Android development environment:
       "build-tools/", etc.)  That is, it should be "sdk/ndk/".
 
     set $ANDROID_HOME to where your SDK is installed, or
-    set "sdk.dir" in project/local.properties.
+    set "sdk.dir" in the file local.properties.
     On MacOS, the value you want is probably ~/Library/Android/sdk/
-    Also set "ndk.dir" in project/local.properties.
+    Also set "ndk.dir" in local.properties.
 
 To build:
 
@@ -30,7 +30,7 @@ To build:
     make
 
     Hopefully an "xscreensaver-debug.apk" file will appear in
-    android/project/xscreensaver/build/outputs/apk/.
+    android/xscreensaver/build/outputs/apk/.
 
     Load that onto your device and go to:
       Settings / Display / Daydream
@@ -60,7 +60,7 @@ To build:
 
     To load it into the currently-running emulator or device:
       $ANDROID_HOME/platform-tools/adb install -r \
-        project/xscreensaver/build/outputs/apk/xscreensaver-debug.apk
+        xscreensaver/build/outputs/apk/xscreensaver-debug.apk
 
     Extremely verbose log output, including stack traces:
         $ANDROID_HOME/platform-tools/adb logcat
@@ -79,50 +79,50 @@ To build:
 Directory structure:
 
     Boilerplate for the Java version of "make":
-        project/*gradle*
-        project/*.properties
-        project/xscreensaver/*gradle*
-        project/xscreensaver/build.*
-        project/xscreensaver/*.properties
+        *gradle*
+        *.properties
+        xscreensaver/*gradle*
+        xscreensaver/build.*
+        xscreensaver/*.properties
 
     The other half of the Makefile:
-        project/xscreensaver/jni/*.mk
+        xscreensaver/jni/*.mk
 
     Source code:
-        project/xscreensaver/src/org/jwz/xscreensaver/*.java
-        project/xscreensaver/res/layout/*.xml
+        xscreensaver/src/org/jwz/xscreensaver/*.java
+        xscreensaver/res/layout/*.xml
 
     Other relevant source code is in ../jwxyz/ and ../hacks/.
 
     Icons:
-        project/xscreensaver/res/drawable-ldpi/
-        project/xscreensaver/res/drawable-mdpi/
-        project/xscreensaver/res/drawable/
+        xscreensaver/res/drawable-ldpi/
+        xscreensaver/res/drawable-mdpi/
+        xscreensaver/res/drawable/
 
     Files that we generate:
 
         gen/function-table.h
-        project/xscreensaver/AndroidManifest.xml
-        project/xscreensaver/res/drawable/*.png
-        project/xscreensaver/res/values/settings.xml
-        project/xscreensaver/res/values/strings.xml
-        project/xscreensaver/res/xml/*.xml
-        project/xscreensaver/src/org/jwz/xscreensaver/gen/*.java
+        xscreensaver/AndroidManifest.xml
+        xscreensaver/res/drawable/*.png
+        xscreensaver/res/values/settings.xml
+        xscreensaver/res/values/strings.xml
+        xscreensaver/res/xml/*.xml
+        xscreensaver/src/org/jwz/xscreensaver/gen/*.java
 
     Other files generated as a part of the build process:
 
         gen/
-        project/.gradle/
-        project/xscreensaver/build/
-        project/xscreensaver/build/outputs/apk/  -- app appears here
-        project/xscreensaver/jni/
-        project/xscreensaver/libs/
-        project/xscreensaver/obj/
-        project/xscreensaver/res/
-        project/xscreensaver/res/drawable/
-        project/xscreensaver/res/values/
-        project/xscreensaver/res/xml/
-        project/xscreensaver/src/org/jwz/xscreensaver/gen/
+        .gradle/
+        xscreensaver/build/
+        xscreensaver/build/outputs/apk/  -- app appears here
+        xscreensaver/jni/
+        xscreensaver/libs/
+        xscreensaver/obj/
+        xscreensaver/res/
+        xscreensaver/res/drawable/
+        xscreensaver/res/values/
+        xscreensaver/res/xml/
+        xscreensaver/src/org/jwz/xscreensaver/gen/
 
 When adding a new hack, edit android/Makefile, then "make clean" and "make".
 
@@ -150,8 +150,6 @@ TODO list, and known bugs:
     display the error message in a dialog.  The catch works, but the dialog
     box does not.
 
-  anemone      needs thick lines
-  anemotaxis    needs thick lines
   antinspect    crashes emulator, sometimes
   antmaze       crashes emulator, sometimes
   antspotlight crashes emulator, sometimes
@@ -161,29 +159,24 @@ TODO list, and known bugs:
   binaryring    pixmaps
   blitspin      images
   bouboule      ?
-  braid         thick lines
   bsod          pixmaps, XCopyArea problems
   bumps         XPutImage
   carousel      blank
-  celtic        thick lines
   circuit      crashes emulator
   cityflow     crashes emulator, sometimes
-  compass       thick lines
   crackberg    crashes emulator, sometimes
   cube21       crashes emulator, sometimes
   cubenetic    crashes emulator, sometimes
   cubicgrid    crashes emulator, sometimes
-  deluxe        thick lines
   dnalogo       codeword is blank
   dymaxionmap  crashes emulator
   endgame      crashes emulator
   engine        text
-  epicycle      thick lines
+  esper         text
   flipflop      images
   flipscreen3d  images
   fliptext      text
   fontglide     text
-  fuzzyflakes   thick lines
   gflux         images
   glblur        crashes emulator, sometimes
   gleidescope   images
@@ -228,11 +221,9 @@ TODO list, and known bugs:
   substrate     background should be white
   surfaces      crashes emulator
   tessellimage  pixmaps
-  truchet       thick lines
   twang         background should be black
   unicrud       pixmaps
   xanalogtv     pixmaps
   xjack         blank
   xmatrix       pixmaps
-  xrayswarm     thick lines
   zoom          pixmaps
diff --git a/android/android.iml b/android/android.iml
new file mode 100644 (file)
index 0000000..7db6b23
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id="android" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/xscreensaver" external.system.id="GRADLE" type="JAVA_MODULE" version="4">
+  <component name="FacetManager">
+    <facet type="java-gradle" name="Java-Gradle">
+      <configuration>
+        <option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
+        <option name="BUILDABLE" value="false" />
+      </configuration>
+    </facet>
+  </component>
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <excludeFolder url="file://$MODULE_DIR$/.gradle" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/android/build.gradle b/android/build.gradle
new file mode 100644 (file)
index 0000000..613cb90
--- /dev/null
@@ -0,0 +1,24 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+    repositories {
+        jcenter()
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:2.1.0'
+    }
+
+    // This allows versions of Gradle past 2.9 to be used with the Gradle
+    // Android plugin.
+    // https://discuss.gradle.org/t/gradle-thinks-2-10-is-less-than-2-2-when-resolving-plugins/13434/2
+//    System.properties['com.android.build.gradle.overrideVersionCheck'] = 'true';
+}
+
+task clean(type: Delete) {
+    delete('./build')
+}
+
+task distClean(type: Delete) {
+    delete('./.gradle')
+}
+
+distClean.dependsOn clean
diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar
new file mode 100644 (file)
index 0000000..13372ae
Binary files /dev/null and b/android/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644 (file)
index 0000000..729f41b
--- /dev/null
@@ -0,0 +1,6 @@
+#Sun Jun 12 14:20:28 PDT 2016
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-bin.zip
diff --git a/android/gradlew b/android/gradlew
new file mode 100755 (executable)
index 0000000..9d82f78
--- /dev/null
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+    JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/android/gradlew.bat b/android/gradlew.bat
new file mode 100644 (file)
index 0000000..aec9973
--- /dev/null
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off\r
+@rem ##########################################################################\r
+@rem\r
+@rem  Gradle startup script for Windows\r
+@rem\r
+@rem ##########################################################################\r
+\r
+@rem Set local scope for the variables with windows NT shell\r
+if "%OS%"=="Windows_NT" setlocal\r
+\r
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r
+set DEFAULT_JVM_OPTS=\r
+\r
+set DIRNAME=%~dp0\r
+if "%DIRNAME%" == "" set DIRNAME=.\r
+set APP_BASE_NAME=%~n0\r
+set APP_HOME=%DIRNAME%\r
+\r
+@rem Find java.exe\r
+if defined JAVA_HOME goto findJavaFromJavaHome\r
+\r
+set JAVA_EXE=java.exe\r
+%JAVA_EXE% -version >NUL 2>&1\r
+if "%ERRORLEVEL%" == "0" goto init\r
+\r
+echo.\r
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r
+echo.\r
+echo Please set the JAVA_HOME variable in your environment to match the\r
+echo location of your Java installation.\r
+\r
+goto fail\r
+\r
+:findJavaFromJavaHome\r
+set JAVA_HOME=%JAVA_HOME:"=%\r
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe\r
+\r
+if exist "%JAVA_EXE%" goto init\r
+\r
+echo.\r
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r
+echo.\r
+echo Please set the JAVA_HOME variable in your environment to match the\r
+echo location of your Java installation.\r
+\r
+goto fail\r
+\r
+:init\r
+@rem Get command-line arguments, handling Windowz variants\r
+\r
+if not "%OS%" == "Windows_NT" goto win9xME_args\r
+if "%@eval[2+2]" == "4" goto 4NT_args\r
+\r
+:win9xME_args\r
+@rem Slurp the command line arguments.\r
+set CMD_LINE_ARGS=\r
+set _SKIP=2\r
+\r
+:win9xME_args_slurp\r
+if "x%~1" == "x" goto execute\r
+\r
+set CMD_LINE_ARGS=%*\r
+goto execute\r
+\r
+:4NT_args\r
+@rem Get arguments from the 4NT Shell from JP Software\r
+set CMD_LINE_ARGS=%$\r
+\r
+:execute\r
+@rem Setup the command line\r
+\r
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar\r
+\r
+@rem Execute Gradle\r
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\r
+\r
+:end\r
+@rem End local scope for the variables with windows NT shell\r
+if "%ERRORLEVEL%"=="0" goto mainEnd\r
+\r
+:fail\r
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r
+rem the _cmd.exe /c_ return code!\r
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1\r
+exit /b 1\r
+\r
+:mainEnd\r
+if "%OS%"=="Windows_NT" endlocal\r
+\r
+:omega\r
diff --git a/android/local.properties b/android/local.properties
new file mode 100644 (file)
index 0000000..238a21c
--- /dev/null
@@ -0,0 +1,11 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must *NOT* be checked into Version Control Systems,
+# as it contains information specific to your local configuration.
+
+# location of the SDK. This is only used by Ant
+# For customization when using a Version Control System, please read the
+# header note.
+sdk.dir=/Users/jwz/Library/Android/sdk
+ndk.dir=/Users/jwz/Library/Android/sdk/ndk
diff --git a/android/project/build.gradle b/android/project/build.gradle
deleted file mode 100644 (file)
index 613cb90..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// Top-level build file where you can add configuration options common to all sub-projects/modules.
-buildscript {
-    repositories {
-        jcenter()
-    }
-    dependencies {
-        classpath 'com.android.tools.build:gradle:2.1.0'
-    }
-
-    // This allows versions of Gradle past 2.9 to be used with the Gradle
-    // Android plugin.
-    // https://discuss.gradle.org/t/gradle-thinks-2-10-is-less-than-2-2-when-resolving-plugins/13434/2
-//    System.properties['com.android.build.gradle.overrideVersionCheck'] = 'true';
-}
-
-task clean(type: Delete) {
-    delete('./build')
-}
-
-task distClean(type: Delete) {
-    delete('./.gradle')
-}
-
-distClean.dependsOn clean
diff --git a/android/project/gradle/wrapper/gradle-wrapper.jar b/android/project/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644 (file)
index 13372ae..0000000
Binary files a/android/project/gradle/wrapper/gradle-wrapper.jar and /dev/null differ
diff --git a/android/project/gradle/wrapper/gradle-wrapper.properties b/android/project/gradle/wrapper/gradle-wrapper.properties
deleted file mode 100644 (file)
index 729f41b..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#Sun Jun 12 14:20:28 PDT 2016
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-bin.zip
diff --git a/android/project/gradlew b/android/project/gradlew
deleted file mode 100755 (executable)
index 9d82f78..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-#!/usr/bin/env bash
-
-##############################################################################
-##
-##  Gradle start up script for UN*X
-##
-##############################################################################
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
-
-warn ( ) {
-    echo "$*"
-}
-
-die ( ) {
-    echo
-    echo "$*"
-    echo
-    exit 1
-}
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-case "`uname`" in
-  CYGWIN* )
-    cygwin=true
-    ;;
-  Darwin* )
-    darwin=true
-    ;;
-  MINGW* )
-    msys=true
-    ;;
-esac
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
-    ls=`ls -ld "$PRG"`
-    link=`expr "$ls" : '.*-> \(.*\)$'`
-    if expr "$link" : '/.*' > /dev/null; then
-        PRG="$link"
-    else
-        PRG=`dirname "$PRG"`"/$link"
-    fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
-    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
-        # IBM's JDK on AIX uses strange locations for the executables
-        JAVACMD="$JAVA_HOME/jre/sh/java"
-    else
-        JAVACMD="$JAVA_HOME/bin/java"
-    fi
-    if [ ! -x "$JAVACMD" ] ; then
-        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-    fi
-else
-    JAVACMD="java"
-    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
-    MAX_FD_LIMIT=`ulimit -H -n`
-    if [ $? -eq 0 ] ; then
-        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
-            MAX_FD="$MAX_FD_LIMIT"
-        fi
-        ulimit -n $MAX_FD
-        if [ $? -ne 0 ] ; then
-            warn "Could not set maximum file descriptor limit: $MAX_FD"
-        fi
-    else
-        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
-    fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
-    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
-    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
-    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-    JAVACMD=`cygpath --unix "$JAVACMD"`
-
-    # We build the pattern for arguments to be converted via cygpath
-    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
-    SEP=""
-    for dir in $ROOTDIRSRAW ; do
-        ROOTDIRS="$ROOTDIRS$SEP$dir"
-        SEP="|"
-    done
-    OURCYGPATTERN="(^($ROOTDIRS))"
-    # Add a user-defined pattern to the cygpath arguments
-    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
-        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
-    fi
-    # Now convert the arguments - kludge to limit ourselves to /bin/sh
-    i=0
-    for arg in "$@" ; do
-        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
-        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
-
-        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
-            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
-        else
-            eval `echo args$i`="\"$arg\""
-        fi
-        i=$((i+1))
-    done
-    case $i in
-        (0) set -- ;;
-        (1) set -- "$args0" ;;
-        (2) set -- "$args0" "$args1" ;;
-        (3) set -- "$args0" "$args1" "$args2" ;;
-        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
-        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
-        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
-        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
-        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
-        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
-    esac
-fi
-
-# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
-function splitJvmOpts() {
-    JVM_OPTS=("$@")
-}
-eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
-JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
-
-exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/android/project/gradlew.bat b/android/project/gradlew.bat
deleted file mode 100644 (file)
index aec9973..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-@if "%DEBUG%" == "" @echo off\r
-@rem ##########################################################################\r
-@rem\r
-@rem  Gradle startup script for Windows\r
-@rem\r
-@rem ##########################################################################\r
-\r
-@rem Set local scope for the variables with windows NT shell\r
-if "%OS%"=="Windows_NT" setlocal\r
-\r
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r
-set DEFAULT_JVM_OPTS=\r
-\r
-set DIRNAME=%~dp0\r
-if "%DIRNAME%" == "" set DIRNAME=.\r
-set APP_BASE_NAME=%~n0\r
-set APP_HOME=%DIRNAME%\r
-\r
-@rem Find java.exe\r
-if defined JAVA_HOME goto findJavaFromJavaHome\r
-\r
-set JAVA_EXE=java.exe\r
-%JAVA_EXE% -version >NUL 2>&1\r
-if "%ERRORLEVEL%" == "0" goto init\r
-\r
-echo.\r
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r
-echo.\r
-echo Please set the JAVA_HOME variable in your environment to match the\r
-echo location of your Java installation.\r
-\r
-goto fail\r
-\r
-:findJavaFromJavaHome\r
-set JAVA_HOME=%JAVA_HOME:"=%\r
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe\r
-\r
-if exist "%JAVA_EXE%" goto init\r
-\r
-echo.\r
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r
-echo.\r
-echo Please set the JAVA_HOME variable in your environment to match the\r
-echo location of your Java installation.\r
-\r
-goto fail\r
-\r
-:init\r
-@rem Get command-line arguments, handling Windowz variants\r
-\r
-if not "%OS%" == "Windows_NT" goto win9xME_args\r
-if "%@eval[2+2]" == "4" goto 4NT_args\r
-\r
-:win9xME_args\r
-@rem Slurp the command line arguments.\r
-set CMD_LINE_ARGS=\r
-set _SKIP=2\r
-\r
-:win9xME_args_slurp\r
-if "x%~1" == "x" goto execute\r
-\r
-set CMD_LINE_ARGS=%*\r
-goto execute\r
-\r
-:4NT_args\r
-@rem Get arguments from the 4NT Shell from JP Software\r
-set CMD_LINE_ARGS=%$\r
-\r
-:execute\r
-@rem Setup the command line\r
-\r
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar\r
-\r
-@rem Execute Gradle\r
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\r
-\r
-:end\r
-@rem End local scope for the variables with windows NT shell\r
-if "%ERRORLEVEL%"=="0" goto mainEnd\r
-\r
-:fail\r
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r
-rem the _cmd.exe /c_ return code!\r
-if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1\r
-exit /b 1\r
-\r
-:mainEnd\r
-if "%OS%"=="Windows_NT" endlocal\r
-\r
-:omega\r
diff --git a/android/project/local.properties b/android/project/local.properties
deleted file mode 100644 (file)
index 238a21c..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must *NOT* be checked into Version Control Systems,
-# as it contains information specific to your local configuration.
-
-# location of the SDK. This is only used by Ant
-# For customization when using a Version Control System, please read the
-# header note.
-sdk.dir=/Users/jwz/Library/Android/sdk
-ndk.dir=/Users/jwz/Library/Android/sdk/ndk
diff --git a/android/project/project.iml b/android/project/project.iml
deleted file mode 100644 (file)
index de3d86e..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module external.linked.project.id="project" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/xscreensaver" external.system.id="GRADLE" type="JAVA_MODULE" version="4">
-  <component name="FacetManager">
-    <facet type="java-gradle" name="Java-Gradle">
-      <configuration>
-        <option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
-        <option name="BUILDABLE" value="false" />
-      </configuration>
-    </facet>
-  </component>
-  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
-    <exclude-output />
-    <content url="file://$MODULE_DIR$">
-      <excludeFolder url="file://$MODULE_DIR$/.gradle" />
-    </content>
-    <orderEntry type="inheritedJdk" />
-    <orderEntry type="sourceFolder" forTests="false" />
-  </component>
-</module>
\ No newline at end of file
diff --git a/android/project/settings.gradle b/android/project/settings.gradle
deleted file mode 100644 (file)
index 5fc665b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-include ':xscreensaver'
diff --git a/android/project/xscreensaver/.idea/compiler.xml b/android/project/xscreensaver/.idea/compiler.xml
deleted file mode 100644 (file)
index 9a8b7e5..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="CompilerConfiguration">
-    <option name="DEFAULT_COMPILER" value="Javac" />
-    <resourceExtensions />
-    <wildcardResourcePatterns>
-      <entry name="!?*.java" />
-      <entry name="!?*.form" />
-      <entry name="!?*.class" />
-      <entry name="!?*.groovy" />
-      <entry name="!?*.scala" />
-      <entry name="!?*.flex" />
-      <entry name="!?*.kt" />
-      <entry name="!?*.clj" />
-    </wildcardResourcePatterns>
-    <annotationProcessing>
-      <profile default="true" name="Default" enabled="false">
-        <processorPath useClasspath="true" />
-      </profile>
-    </annotationProcessing>
-  </component>
-</project>
\ No newline at end of file
diff --git a/android/project/xscreensaver/.idea/gradle.xml b/android/project/xscreensaver/.idea/gradle.xml
deleted file mode 100644 (file)
index 19fd5f1..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="GradleSettings">
-    <option name="linkedExternalProjectsSettings">
-      <GradleProjectSettings>
-        <option name="distributionType" value="LOCAL" />
-        <option name="externalProjectPath" value="$PROJECT_DIR$" />
-        <option name="gradleHome" value="$APPLICATION_HOME_DIR$/gradle/gradle-2.14.1" />
-        <option name="modules">
-          <set>
-            <option value="$PROJECT_DIR$/.." />
-            <option value="$PROJECT_DIR$" />
-          </set>
-        </option>
-        <option name="resolveModulePerSourceSet" value="false" />
-      </GradleProjectSettings>
-    </option>
-  </component>
-</project>
\ No newline at end of file
diff --git a/android/project/xscreensaver/.idea/misc.xml b/android/project/xscreensaver/.idea/misc.xml
deleted file mode 100644 (file)
index cc15a25..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="ProjectLevelVcsManager" settingsEditedManually="false">
-    <OptionsSetting value="true" id="Add" />
-    <OptionsSetting value="true" id="Remove" />
-    <OptionsSetting value="true" id="Checkout" />
-    <OptionsSetting value="true" id="Update" />
-    <OptionsSetting value="true" id="Status" />
-    <OptionsSetting value="true" id="Edit" />
-    <ConfirmationsSetting value="0" id="Add" />
-    <ConfirmationsSetting value="0" id="Remove" />
-  </component>
-  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK" />
-</project>
\ No newline at end of file
diff --git a/android/project/xscreensaver/.idea/modules.xml b/android/project/xscreensaver/.idea/modules.xml
deleted file mode 100644 (file)
index f317927..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="ProjectModuleManager">
-    <modules>
-      <module fileurl="file://$PROJECT_DIR$/../project.iml" filepath="$PROJECT_DIR$/../project.iml" />
-      <module fileurl="file://$PROJECT_DIR$/xscreensaver.iml" filepath="$PROJECT_DIR$/xscreensaver.iml" />
-    </modules>
-  </component>
-</project>
\ No newline at end of file
diff --git a/android/project/xscreensaver/.idea/workspace.xml b/android/project/xscreensaver/.idea/workspace.xml
deleted file mode 100644 (file)
index 516bf62..0000000
+++ /dev/null
@@ -1,1863 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="ChangeListManager">
-    <list default="true" id="41008724-035d-4e24-92b6-6dfb9231c83c" name="Default" comment="" />
-    <ignored path="xscreensaver.iws" />
-    <ignored path=".idea/workspace.xml" />
-    <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
-    <option name="TRACKING_ENABLED" value="true" />
-    <option name="SHOW_DIALOG" value="false" />
-    <option name="HIGHLIGHT_CONFLICTS" value="true" />
-    <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
-    <option name="LAST_RESOLUTION" value="IGNORE" />
-  </component>
-  <component name="ChangesViewManager" flattened_view="true" show_ignored="false" />
-  <component name="CreatePatchCommitExecutor">
-    <option name="PATCH_PATH" value="" />
-  </component>
-  <component name="ExecutionTargetManager" SELECTED_TARGET="default_target" />
-  <component name="ExternalProjectsData">
-    <projectState path="$PROJECT_DIR$">
-      <ProjectState />
-    </projectState>
-  </component>
-  <component name="FavoritesManager">
-    <favorites_list name="xscreensaver" />
-  </component>
-  <component name="GradleLocalSettings">
-    <option name="availableProjects">
-      <map>
-        <entry>
-          <key>
-            <ExternalProjectPojo>
-              <option name="name" value="project" />
-              <option name="path" value="$PROJECT_DIR$" />
-            </ExternalProjectPojo>
-          </key>
-          <value>
-            <list>
-              <ExternalProjectPojo>
-                <option name="name" value=":xscreensaver" />
-                <option name="path" value="$PROJECT_DIR$" />
-              </ExternalProjectPojo>
-              <ExternalProjectPojo>
-                <option name="name" value="project" />
-                <option name="path" value="$PROJECT_DIR$/.." />
-              </ExternalProjectPojo>
-            </list>
-          </value>
-        </entry>
-      </map>
-    </option>
-    <option name="availableTasks">
-      <map>
-        <entry key="$PROJECT_DIR$/..">
-          <value>
-            <list>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays all buildscript dependencies declared in root project 'project'." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value=":buildEnvironment" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value=":clean" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the components produced by root project 'project'. [incubating]" />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value=":components" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays all dependencies declared in root project 'project'." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value=":dependencies" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the insight into a specific dependency in root project 'project'." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value=":dependencyInsight" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value=":distClean" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays a help message." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value=":help" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Initializes a new Gradle build. [incubating]" />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value=":init" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the configuration model of root project 'project'. [incubating]" />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value=":model" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the sub-projects of root project 'project'." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value=":projects" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the properties of root project 'project'." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value=":properties" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the tasks runnable from root project 'project' (some of the displayed tasks may belong to subprojects)." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value=":tasks" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Generates Gradle wrapper files. [incubating]" />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value=":wrapper" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the Android dependencies of the project." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="androidDependencies" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles all variants of all applications and secondary packages." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="assemble" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles all the Test applications." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="assembleAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles all Debug builds." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="assembleDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="assembleDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="assembleDebugUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles all Release builds." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="assembleRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="assembleReleaseUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles and tests this project." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="build" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles and tests this project and all projects that depend on it." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="buildDependents" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles and tests this project and all projects it depends on." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="buildNeeded" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs all checks." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="check" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="checkDebugManifest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="checkReleaseManifest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugAidl" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugAndroidTestAidl" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugAndroidTestJavaWithJavac" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugAndroidTestNdk" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugAndroidTestRenderscript" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugAndroidTestShaders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugAndroidTestSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugJavaWithJavac" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugNdk" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugRenderscript" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugShaders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugUnitTestJavaWithJavac" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugUnitTestSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileLint" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileReleaseAidl" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileReleaseJavaWithJavac" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileReleaseNdk" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileReleaseRenderscript" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileReleaseShaders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileReleaseSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileReleaseUnitTestJavaWithJavac" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileReleaseUnitTestSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="config_h" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Installs and runs instrumentation tests for all flavors on connected devices." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="connectedAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs all device checks on currently connected devices." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="connectedCheck" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Installs and runs the tests for debug on connected devices." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="connectedDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Installs and runs instrumentation tests using all Device Providers." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="deviceAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs all device checks using Device Providers and Test Servers." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="deviceCheck" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="downloadNeededDrawables" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugAndroidTestAssets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugAndroidTestBuildConfig" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugAndroidTestResValues" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugAndroidTestResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugAndroidTestSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugAssets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugBuildConfig" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugResValues" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateReleaseAssets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateReleaseBuildConfig" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateReleaseResValues" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateReleaseResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateReleaseSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="incrementalDebugAndroidTestJavaCompilationSafeguard" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="incrementalDebugJavaCompilationSafeguard" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="incrementalDebugUnitTestJavaCompilationSafeguard" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="incrementalReleaseJavaCompilationSafeguard" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="incrementalReleaseUnitTestJavaCompilationSafeguard" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Installs the Debug build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="installDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Installs the android (on device) tests for the Debug build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="installDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="jarDebugClasses" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="jarReleaseClasses" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs lint on all variants." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="lint" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs lint on the Debug build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="lintDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs lint on the Release build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="lintRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs lint on just the fatal issues in the Release build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="lintVitalRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeDebugAndroidTestAssets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeDebugAndroidTestJniLibFolders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeDebugAndroidTestResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeDebugAndroidTestShaders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeDebugAssets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeDebugJniLibFolders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeDebugResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeDebugShaders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeReleaseAssets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeReleaseJniLibFolders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeReleaseResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeReleaseShaders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Creates a version of android.jar that's suitable for unit tests." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mockableAndroidJar" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="ndkBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="objlibClean" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="packageDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="packageDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="packageRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="perlBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="perlClean" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preDebugAndroidTestBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preDebugBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preDebugUnitTestBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="prePackageMarkerForDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="prePackageMarkerForDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="prePackageMarkerForRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preReleaseBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preReleaseUnitTestBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="prepareDebugAndroidTestDependencies" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="prepareDebugDependencies" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="prepareDebugUnitTestDependencies" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="prepareReleaseDependencies" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="prepareReleaseUnitTestDependencies" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processDebugAndroidTestJavaRes" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processDebugAndroidTestManifest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processDebugAndroidTestResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processDebugJavaRes" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processDebugManifest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processDebugResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processDebugUnitTestJavaRes" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processReleaseJavaRes" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processReleaseManifest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processReleaseResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processReleaseUnitTestJavaRes" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the signing info for each variant." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="signingReport" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Prints out all the source sets defined in this project." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="sourceSets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Run unit tests for all variants." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="test" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Run unit tests for the debug build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="testDebugUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Run unit tests for the release build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="testReleaseUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformClassesWithDexForDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformClassesWithDexForDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformClassesWithDexForRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformNative_libsWithMergeJniLibsForDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformNative_libsWithMergeJniLibsForDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformNative_libsWithMergeJniLibsForRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformResourcesWithMergeJavaResForDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformResourcesWithMergeJavaResForDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformResourcesWithMergeJavaResForDebugUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformResourcesWithMergeJavaResForRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformResourcesWithMergeJavaResForReleaseUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Uninstall all applications." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="uninstallAll" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Uninstalls the Debug build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="uninstallDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Uninstalls the android (on device) tests for the Debug build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="uninstallDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Uninstalls the Release build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="uninstallRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="validateDebugSigning" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="zipalignDebug" />
-              </ExternalTaskPojo>
-            </list>
-          </value>
-        </entry>
-        <entry key="$PROJECT_DIR$">
-          <value>
-            <list>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the sub-projects of project ':xscreensaver'." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="projects" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="assembleReleaseUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="prepareDebugDependencies" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processReleaseJavaRes" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateReleaseAssets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs lint on the Debug build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="lintDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="assembleDebugUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="prePackageMarkerForDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Creates a version of android.jar that's suitable for unit tests." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mockableAndroidJar" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the configuration model of project ':xscreensaver'. [incubating]" />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="model" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the tasks runnable from project ':xscreensaver'." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="tasks" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="incrementalDebugJavaCompilationSafeguard" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs all device checks using Device Providers and Test Servers." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="deviceCheck" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays all dependencies declared in project ':xscreensaver'." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="dependencies" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processDebugResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs lint on all variants." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="lint" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="packageDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="prePackageMarkerForRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileReleaseNdk" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugJavaWithJavac" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles and tests this project and all projects it depends on." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="buildNeeded" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugAndroidTestBuildConfig" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processDebugUnitTestJavaRes" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Run unit tests for the release build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="testReleaseUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugAndroidTestShaders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeDebugShaders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformNative_libsWithMergeJniLibsForDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugAndroidTestJavaWithJavac" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the components produced by project ':xscreensaver'. [incubating]" />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="components" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileReleaseRenderscript" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles all Debug builds." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="assembleDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processDebugAndroidTestManifest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugUnitTestJavaWithJavac" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformResourcesWithMergeJavaResForReleaseUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="prePackageMarkerForDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformClassesWithDexForDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preDebugAndroidTestBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processDebugAndroidTestJavaRes" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processReleaseUnitTestJavaRes" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Uninstalls the Release build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="uninstallRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileReleaseShaders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeReleaseResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugAndroidTestSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="prepareDebugAndroidTestDependencies" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="incrementalDebugAndroidTestJavaCompilationSafeguard" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="checkReleaseManifest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugAndroidTestSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeReleaseJniLibFolders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="prepareReleaseDependencies" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processReleaseResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Installs and runs instrumentation tests using all Device Providers." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="deviceAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeDebugAndroidTestAssets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processReleaseManifest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Uninstalls the android (on device) tests for the Debug build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="uninstallDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the insight into a specific dependency in project ':xscreensaver'." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="dependencyInsight" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateReleaseSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="incrementalReleaseUnitTestJavaCompilationSafeguard" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preReleaseBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles all variants of all applications and secondary packages." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="assemble" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="incrementalDebugUnitTestJavaCompilationSafeguard" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="incrementalReleaseJavaCompilationSafeguard" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays a help message." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="help" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileReleaseUnitTestSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Installs the android (on device) tests for the Debug build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="installDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeDebugAssets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs all device checks on currently connected devices." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="connectedCheck" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Installs and runs the tests for debug on connected devices." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="connectedDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Uninstall all applications." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="uninstallAll" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles all the Test applications." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="assembleAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processDebugAndroidTestResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="zipalignDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformNative_libsWithMergeJniLibsForDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="packageRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugAidl" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeDebugResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preDebugUnitTestBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileLint" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugAndroidTestResValues" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeReleaseShaders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the Android dependencies of the project." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="androidDependencies" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugAndroidTestNdk" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugUnitTestSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeDebugAndroidTestJniLibFolders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformClassesWithDexForDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="assembleDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="objlibClean" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processDebugJavaRes" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugAndroidTestAssets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileReleaseJavaWithJavac" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="jarReleaseClasses" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformResourcesWithMergeJavaResForDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="downloadNeededDrawables" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="prepareReleaseUnitTestDependencies" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Run unit tests for all variants." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="test" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugNdk" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformNative_libsWithMergeJniLibsForRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeDebugAndroidTestResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preReleaseUnitTestBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugResValues" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs all checks." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="check" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="validateDebugSigning" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Run unit tests for the debug build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="testDebugUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Installs and runs instrumentation tests for all flavors on connected devices." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="connectedAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="jarDebugClasses" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformClassesWithDexForRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Installs the Debug build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="installDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformResourcesWithMergeJavaResForRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileReleaseSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileReleaseUnitTestJavaWithJavac" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugShaders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformResourcesWithMergeJavaResForDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileReleaseAidl" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="config_h" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs lint on the Release build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="lintRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles and tests this project and all projects that depend on it." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="buildDependents" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugAssets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays all buildscript dependencies declared in project ':xscreensaver'." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="buildEnvironment" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="checkDebugManifest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeDebugJniLibFolders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Prints out all the source sets defined in this project." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="sourceSets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformResourcesWithMergeJavaResForDebugUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="perlBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeReleaseAssets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugRenderscript" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateReleaseBuildConfig" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="prepareDebugUnitTestDependencies" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="perlClean" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateReleaseResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs lint on just the fatal issues in the Release build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="lintVitalRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="ndkBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Uninstalls the Debug build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="uninstallDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the signing info for each variant." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="signingReport" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugAndroidTestAidl" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeDebugAndroidTestShaders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Deletes the build directory." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="clean" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preDebugBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugBuildConfig" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles and tests this project." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="build" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles all Release builds." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="assembleRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugAndroidTestRenderscript" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugAndroidTestResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processDebugManifest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="packageDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateReleaseResValues" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the properties of project ':xscreensaver'." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="properties" />
-              </ExternalTaskPojo>
-            </list>
-          </value>
-        </entry>
-      </map>
-    </option>
-    <option name="modificationStamps">
-      <map>
-        <entry key="$PROJECT_DIR$" value="4395090424000" />
-      </map>
-    </option>
-    <option name="projectBuildClasspath">
-      <map>
-        <entry key="$PROJECT_DIR$">
-          <value>
-            <ExternalProjectBuildClasspathPojo>
-              <option name="modulesBuildClasspath">
-                <map>
-                  <entry key="$PROJECT_DIR$/..">
-                    <value>
-                      <ExternalModuleBuildClasspathPojo>
-                        <option name="entries">
-                          <list>
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle/2.1.2/a15b8a1abdb158716cb2eca322c8c055dcf3c73d/gradle-2.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-core/2.1.2/23fa54cbd68abe0d190b3f19b8db553c22b1e95e/gradle-core-2.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder/2.1.2/b0f8f1b2be1cca433af04ac59c032bb65f104f68/builder-2.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint/25.1.2/73b0fca79c61b7d4212354d2dc54310f18d3eab1/lint-25.1.2.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/android/tools/build/transform-api/2.0.0-deprecated-use-gradle-api/transform-api-2.0.0-deprecated-use-gradle-api.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-api/2.1.2/13a4ad6e82603eca38f0f46e308db7b2374bd33a/gradle-api-2.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/compilerCommon/2.1.2/658479d60a2ad7f511ea43028a9dbe6f7658779d/compilerCommon-2.1.2.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm/5.0.3/asm-5.0.3-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm/5.0.3/asm-5.0.3.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-commons/5.0.3/asm-commons-5.0.3-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-commons/5.0.3/asm-commons-5.0.3.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/proguard/proguard-gradle/5.2.1/proguard-gradle-5.2.1-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/proguard/proguard-gradle/5.2.1/proguard-gradle-5.2.1.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/jacoco/org.jacoco.core/0.7.4.201502262128/org.jacoco.core-0.7.4.201502262128-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/jacoco/org.jacoco.core/0.7.4.201502262128/org.jacoco.core-0.7.4.201502262128.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/antlr/antlr/3.5.2/antlr-3.5.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-model/2.1.2/54929c8a9d8c2dd13c945c3f5ad0ec5546cdc006/builder-model-2.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-test-api/2.1.2/ee73cc6c008005128538d86c1c56a27e2d96c32/builder-test-api-2.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdklib/25.1.2/59cdf46da07c365d456606d3985a51702db87c24/sdklib-25.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdk-common/25.1.2/1dcda99e022faddbf24336c0c8b37398773f4c36/sdk-common-25.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/common/25.1.2/c15c73c5ddedc9ac2afdfda827fa23a9b59b9b9d/common-25.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/manifest-merger/25.1.2/2f070c6b90be1642f37aafe15e42f21ba73394da/manifest-merger-25.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.ddms/ddmlib/25.1.2/521439862ec854d683a19a351fcc3beda4653346/ddmlib-25.1.2.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/android/tools/jack/jack-api/0.10.0/jack-api-0.10.0.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/android/tools/jill/jill-api/0.10.0/jill-api-0.10.0.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/squareup/javawriter/2.5.0/javawriter-2.5.0-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/squareup/javawriter/2.5.0/javawriter-2.5.0.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/bouncycastle/bcpkix-jdk15on/1.48/bcpkix-jdk15on-1.48-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/bouncycastle/bcpkix-jdk15on/1.48/bcpkix-jdk15on-1.48.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/bouncycastle/bcprov-jdk15on/1.48/bcprov-jdk15on-1.48-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/bouncycastle/bcprov-jdk15on/1.48/bcprov-jdk15on-1.48.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-tree/5.0.3/asm-tree-5.0.3-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-tree/5.0.3/asm-tree-5.0.3.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-checks/25.1.2/68583e445a033021d9792c9d84ac7ce8ea549c81/lint-checks-25.1.2.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/eclipse/jdt/core/compiler/ecj/4.4.2/ecj-4.4.2-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/eclipse/jdt/core/compiler/ecj/4.4.2/ecj-4.4.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/annotations/25.1.2/9dbfadaaf19097c12787c68cf43a12c739936345/annotations-25.1.2.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/google/guava/guava/17.0/guava-17.0-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/google/guava/guava/17.0/guava-17.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/baseLibrary/2.1.2/d0395908c940f4171fb024435b25f7458c1147f3/baseLibrary-2.1.2.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/tunnelvisionlabs/antlr4/4.5/antlr4-4.5.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-io/commons-io/2.4/commons-io-2.4-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-io/commons-io/2.4/commons-io-2.4.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/googlecode/juniversalchardet/juniversalchardet/1.0.3/juniversalchardet-1.0.3.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/proguard/proguard-base/5.2.1/proguard-base-5.2.1-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/proguard/proguard-base/5.2.1/proguard-base-5.2.1.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-debug-all/5.0.1/asm-debug-all-5.0.1-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-debug-all/5.0.1/asm-debug-all-5.0.1.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/antlr/antlr-runtime/3.5.2/antlr-runtime-3.5.2.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/antlr/ST4/4.0.8/ST4-4.0.8.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.layoutlib/layoutlib-api/25.1.2/b93f0de181063ee2f673d7d6cac0bdbb94cc1b90/layoutlib-api-25.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/dvlib/25.1.2/bfcb16fb0e44568bd8e31c6aaf1850c1dcd06483/dvlib-25.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/repository/25.1.2/1a1f5f59b21a42817eec50b7aced4400bb72273b/repository-25.1.2.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/google/code/gson/gson/2.2.4/gson-2.2.4-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/google/code/gson/gson/2.2.4/gson-2.2.4.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/commons/commons-compress/1.8.1/commons-compress-1.8.1-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/commons/commons-compress/1.8.1/commons-compress-1.8.1.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpclient/4.1.1/httpclient-4.1.1-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpclient/4.1.1/httpclient-4.1.1.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpmime/4.1/httpmime-4.1-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpmime/4.1/httpmime-4.1.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/kxml/kxml2/2.3.0/kxml2-2.3.0-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/kxml/kxml2/2.3.0/kxml2-2.3.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-api/25.1.2/f9f6807b68d486eaf34cc3f08b6f098f89cf3db8/lint-api-25.1.2.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-analysis/5.0.3/asm-analysis-5.0.3-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-analysis/5.0.3/asm-analysis-5.0.3.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/tunnelvisionlabs/antlr4-runtime/4.5/antlr4-runtime-4.5.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/tunnelvisionlabs/antlr4-annotations/4.5/antlr4-annotations-4.5.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/intellij/annotations/12.0/annotations-12.0-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/intellij/annotations/12.0/annotations-12.0.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpcore/4.1/httpcore-4.1-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpcore/4.1/httpcore-4.1.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-codec/commons-codec/1.4/commons-codec-1.4-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-codec/commons-codec/1.4/commons-codec-1.4.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/android/tools/external/lombok/lombok-ast/0.2.3/lombok-ast-0.2.3-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/android/tools/external/lombok/lombok-ast/0.2.3/lombok-ast-0.2.3.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/abego/treelayout/org.abego.treelayout.core/1.0.1/org.abego.treelayout.core-1.0.1.jar" />
-                          </list>
-                        </option>
-                        <option name="path" value="$PROJECT_DIR$/.." />
-                      </ExternalModuleBuildClasspathPojo>
-                    </value>
-                  </entry>
-                  <entry key="$PROJECT_DIR$">
-                    <value>
-                      <ExternalModuleBuildClasspathPojo>
-                        <option name="entries">
-                          <list>
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle/2.1.2/a15b8a1abdb158716cb2eca322c8c055dcf3c73d/gradle-2.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-core/2.1.2/23fa54cbd68abe0d190b3f19b8db553c22b1e95e/gradle-core-2.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder/2.1.2/b0f8f1b2be1cca433af04ac59c032bb65f104f68/builder-2.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint/25.1.2/73b0fca79c61b7d4212354d2dc54310f18d3eab1/lint-25.1.2.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/android/tools/build/transform-api/2.0.0-deprecated-use-gradle-api/transform-api-2.0.0-deprecated-use-gradle-api.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-api/2.1.2/13a4ad6e82603eca38f0f46e308db7b2374bd33a/gradle-api-2.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/compilerCommon/2.1.2/658479d60a2ad7f511ea43028a9dbe6f7658779d/compilerCommon-2.1.2.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm/5.0.3/asm-5.0.3-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm/5.0.3/asm-5.0.3.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-commons/5.0.3/asm-commons-5.0.3-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-commons/5.0.3/asm-commons-5.0.3.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/proguard/proguard-gradle/5.2.1/proguard-gradle-5.2.1-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/proguard/proguard-gradle/5.2.1/proguard-gradle-5.2.1.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/jacoco/org.jacoco.core/0.7.4.201502262128/org.jacoco.core-0.7.4.201502262128-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/jacoco/org.jacoco.core/0.7.4.201502262128/org.jacoco.core-0.7.4.201502262128.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/antlr/antlr/3.5.2/antlr-3.5.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-model/2.1.2/54929c8a9d8c2dd13c945c3f5ad0ec5546cdc006/builder-model-2.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-test-api/2.1.2/ee73cc6c008005128538d86c1c56a27e2d96c32/builder-test-api-2.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdklib/25.1.2/59cdf46da07c365d456606d3985a51702db87c24/sdklib-25.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdk-common/25.1.2/1dcda99e022faddbf24336c0c8b37398773f4c36/sdk-common-25.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/common/25.1.2/c15c73c5ddedc9ac2afdfda827fa23a9b59b9b9d/common-25.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/manifest-merger/25.1.2/2f070c6b90be1642f37aafe15e42f21ba73394da/manifest-merger-25.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.ddms/ddmlib/25.1.2/521439862ec854d683a19a351fcc3beda4653346/ddmlib-25.1.2.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/android/tools/jack/jack-api/0.10.0/jack-api-0.10.0.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/android/tools/jill/jill-api/0.10.0/jill-api-0.10.0.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/squareup/javawriter/2.5.0/javawriter-2.5.0-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/squareup/javawriter/2.5.0/javawriter-2.5.0.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/bouncycastle/bcpkix-jdk15on/1.48/bcpkix-jdk15on-1.48-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/bouncycastle/bcpkix-jdk15on/1.48/bcpkix-jdk15on-1.48.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/bouncycastle/bcprov-jdk15on/1.48/bcprov-jdk15on-1.48-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/bouncycastle/bcprov-jdk15on/1.48/bcprov-jdk15on-1.48.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-tree/5.0.3/asm-tree-5.0.3-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-tree/5.0.3/asm-tree-5.0.3.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-checks/25.1.2/68583e445a033021d9792c9d84ac7ce8ea549c81/lint-checks-25.1.2.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/eclipse/jdt/core/compiler/ecj/4.4.2/ecj-4.4.2-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/eclipse/jdt/core/compiler/ecj/4.4.2/ecj-4.4.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/annotations/25.1.2/9dbfadaaf19097c12787c68cf43a12c739936345/annotations-25.1.2.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/google/guava/guava/17.0/guava-17.0-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/google/guava/guava/17.0/guava-17.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/baseLibrary/2.1.2/d0395908c940f4171fb024435b25f7458c1147f3/baseLibrary-2.1.2.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/tunnelvisionlabs/antlr4/4.5/antlr4-4.5.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-io/commons-io/2.4/commons-io-2.4-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-io/commons-io/2.4/commons-io-2.4.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/googlecode/juniversalchardet/juniversalchardet/1.0.3/juniversalchardet-1.0.3.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/proguard/proguard-base/5.2.1/proguard-base-5.2.1-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/proguard/proguard-base/5.2.1/proguard-base-5.2.1.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-debug-all/5.0.1/asm-debug-all-5.0.1-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-debug-all/5.0.1/asm-debug-all-5.0.1.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/antlr/antlr-runtime/3.5.2/antlr-runtime-3.5.2.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/antlr/ST4/4.0.8/ST4-4.0.8.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.layoutlib/layoutlib-api/25.1.2/b93f0de181063ee2f673d7d6cac0bdbb94cc1b90/layoutlib-api-25.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/dvlib/25.1.2/bfcb16fb0e44568bd8e31c6aaf1850c1dcd06483/dvlib-25.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/repository/25.1.2/1a1f5f59b21a42817eec50b7aced4400bb72273b/repository-25.1.2.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/google/code/gson/gson/2.2.4/gson-2.2.4-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/google/code/gson/gson/2.2.4/gson-2.2.4.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/commons/commons-compress/1.8.1/commons-compress-1.8.1-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/commons/commons-compress/1.8.1/commons-compress-1.8.1.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpclient/4.1.1/httpclient-4.1.1-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpclient/4.1.1/httpclient-4.1.1.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpmime/4.1/httpmime-4.1-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpmime/4.1/httpmime-4.1.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/kxml/kxml2/2.3.0/kxml2-2.3.0-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/kxml/kxml2/2.3.0/kxml2-2.3.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-api/25.1.2/f9f6807b68d486eaf34cc3f08b6f098f89cf3db8/lint-api-25.1.2.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-analysis/5.0.3/asm-analysis-5.0.3-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-analysis/5.0.3/asm-analysis-5.0.3.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/tunnelvisionlabs/antlr4-runtime/4.5/antlr4-runtime-4.5.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/tunnelvisionlabs/antlr4-annotations/4.5/antlr4-annotations-4.5.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/intellij/annotations/12.0/annotations-12.0-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/intellij/annotations/12.0/annotations-12.0.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpcore/4.1/httpcore-4.1-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpcore/4.1/httpcore-4.1.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-codec/commons-codec/1.4/commons-codec-1.4-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-codec/commons-codec/1.4/commons-codec-1.4.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/android/tools/external/lombok/lombok-ast/0.2.3/lombok-ast-0.2.3-sources.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/android/tools/external/lombok/lombok-ast/0.2.3/lombok-ast-0.2.3.jar" />
-                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/abego/treelayout/org.abego.treelayout.core/1.0.1/org.abego.treelayout.core-1.0.1.jar" />
-                          </list>
-                        </option>
-                        <option name="path" value="$PROJECT_DIR$" />
-                      </ExternalModuleBuildClasspathPojo>
-                    </value>
-                  </entry>
-                </map>
-              </option>
-              <option name="name" value="xscreensaver" />
-              <option name="projectBuildClasspath">
-                <list>
-                  <option value="$PROJECT_DIR$/buildSrc/src/main/java" />
-                  <option value="$PROJECT_DIR$/buildSrc/src/main/groovy" />
-                </list>
-              </option>
-            </ExternalProjectBuildClasspathPojo>
-          </value>
-        </entry>
-      </map>
-    </option>
-    <option name="externalProjectsViewState">
-      <projects_view />
-    </option>
-  </component>
-  <component name="ProjectFrameBounds">
-    <option name="x" value="73" />
-    <option name="y" value="23" />
-    <option name="width" value="1137" />
-    <option name="height" value="1029" />
-  </component>
-  <component name="ProjectLevelVcsManager" settingsEditedManually="false">
-    <OptionsSetting value="true" id="Add" />
-    <OptionsSetting value="true" id="Remove" />
-    <OptionsSetting value="true" id="Checkout" />
-    <OptionsSetting value="true" id="Update" />
-    <OptionsSetting value="true" id="Status" />
-    <OptionsSetting value="true" id="Edit" />
-    <ConfirmationsSetting value="0" id="Add" />
-    <ConfirmationsSetting value="0" id="Remove" />
-  </component>
-  <component name="ProjectView">
-    <navigator currentView="AndroidView" proportions="" version="1">
-      <flattenPackages />
-      <showMembers />
-      <showModules />
-      <showLibraryContents />
-      <hideEmptyPackages />
-      <abbreviatePackageNames />
-      <autoscrollToSource />
-      <autoscrollFromSource />
-      <sortByType />
-      <manualOrder />
-      <foldersAlwaysOnTop value="true" />
-    </navigator>
-    <panes>
-      <pane id="ProjectPane" />
-      <pane id="PackagesPane" />
-      <pane id="Scope" />
-      <pane id="AndroidView">
-        <subPane>
-          <PATH>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="xscreensaver" />
-              <option name="myItemType" value="com.android.tools.idea.navigator.nodes.AndroidViewProjectNode" />
-            </PATH_ELEMENT>
-          </PATH>
-        </subPane>
-      </pane>
-      <pane id="Scratches" />
-    </panes>
-  </component>
-  <component name="PropertiesComponent">
-    <property name="GoToClass.includeLibraries" value="false" />
-    <property name="GoToClass.toSaveIncludeLibraries" value="false" />
-    <property name="GoToFile.includeJavaFiles" value="false" />
-    <property name="MemberChooser.sorted" value="false" />
-    <property name="MemberChooser.showClasses" value="true" />
-    <property name="MemberChooser.copyJavadoc" value="false" />
-    <property name="settings.editor.selected.configurable" value="android.sdk-updates" />
-    <property name="settings.editor.splitter.proportion" value="0.2" />
-    <property name="SearchEverywhereHistoryKey" value="sdk manager&#9;ACTION&#9;WelcomeScreen.RunAndroidSdkManager" />
-  </component>
-  <component name="RunManager" selected="Android App.xscreensaver">
-    <configuration default="true" type="AndroidRunConfigurationType" factoryName="Android App">
-      <module name="" />
-      <option name="DEPLOY" value="true" />
-      <option name="ARTIFACT_NAME" value="" />
-      <option name="PM_INSTALL_OPTIONS" value="" />
-      <option name="ACTIVITY_EXTRA_FLAGS" value="" />
-      <option name="MODE" value="default_activity" />
-      <option name="TARGET_SELECTION_MODE" value="SHOW_DIALOG" />
-      <option name="PREFERRED_AVD" value="" />
-      <option name="CLEAR_LOGCAT" value="false" />
-      <option name="SHOW_LOGCAT_AUTOMATICALLY" value="false" />
-      <option name="SKIP_NOOP_APK_INSTALLATIONS" value="true" />
-      <option name="FORCE_STOP_RUNNING_APP" value="true" />
-      <option name="DEBUGGER_TYPE" value="Auto" />
-      <option name="USE_LAST_SELECTED_DEVICE" value="false" />
-      <option name="PREFERRED_AVD" value="" />
-      <option name="SELECTED_CLOUD_MATRIX_CONFIGURATION_ID" value="-1" />
-      <option name="SELECTED_CLOUD_MATRIX_PROJECT_ID" value="" />
-      <Auto>
-        <option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
-        <option name="WORKING_DIR" value="" />
-        <option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
-      </Auto>
-      <Hybrid>
-        <option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
-        <option name="WORKING_DIR" value="" />
-        <option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
-      </Hybrid>
-      <Java />
-      <Native>
-        <option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
-        <option name="WORKING_DIR" value="" />
-        <option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
-      </Native>
-      <Profilers>
-        <option name="ENABLE_ADVANCED_PROFILING" value="true" />
-        <option name="GAPID_ENABLED" value="false" />
-        <option name="GAPID_DISABLE_PCS" value="false" />
-        <option name="SUPPORT_LIB_ENABLED" value="true" />
-        <option name="INSTRUMENTATION_ENABLED" value="true" />
-      </Profilers>
-      <option name="DEEP_LINK" value="" />
-      <option name="ACTIVITY_CLASS" value="" />
-      <method />
-    </configuration>
-    <configuration default="true" type="Application" factoryName="Application">
-      <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
-      <option name="MAIN_CLASS_NAME" />
-      <option name="VM_PARAMETERS" />
-      <option name="PROGRAM_PARAMETERS" />
-      <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
-      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
-      <option name="ALTERNATIVE_JRE_PATH" />
-      <option name="ENABLE_SWING_INSPECTOR" value="false" />
-      <option name="ENV_VARIABLES" />
-      <option name="PASS_PARENT_ENVS" value="true" />
-      <module name="" />
-      <envs />
-      <method />
-    </configuration>
-    <configuration default="true" type="JUnit" factoryName="JUnit">
-      <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
-      <module name="" />
-      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
-      <option name="ALTERNATIVE_JRE_PATH" />
-      <option name="PACKAGE_NAME" />
-      <option name="MAIN_CLASS_NAME" />
-      <option name="METHOD_NAME" />
-      <option name="TEST_OBJECT" value="class" />
-      <option name="VM_PARAMETERS" value="-ea" />
-      <option name="PARAMETERS" />
-      <option name="WORKING_DIRECTORY" value="$MODULE_DIR$" />
-      <option name="ENV_VARIABLES" />
-      <option name="PASS_PARENT_ENVS" value="true" />
-      <option name="TEST_SEARCH_SCOPE">
-        <value defaultName="singleModule" />
-      </option>
-      <envs />
-      <patterns />
-      <method>
-        <option name="Make" enabled="false" />
-        <option name="Android.Gradle.BeforeRunTask" enabled="true" />
-      </method>
-    </configuration>
-    <configuration default="true" type="Remote" factoryName="Remote">
-      <option name="USE_SOCKET_TRANSPORT" value="true" />
-      <option name="SERVER_MODE" value="false" />
-      <option name="SHMEM_ADDRESS" value="javadebug" />
-      <option name="HOST" value="localhost" />
-      <option name="PORT" value="5005" />
-      <method />
-    </configuration>
-    <configuration default="true" type="TestNG" factoryName="TestNG">
-      <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
-      <module name="" />
-      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
-      <option name="ALTERNATIVE_JRE_PATH" />
-      <option name="SUITE_NAME" />
-      <option name="PACKAGE_NAME" />
-      <option name="MAIN_CLASS_NAME" />
-      <option name="METHOD_NAME" />
-      <option name="GROUP_NAME" />
-      <option name="TEST_OBJECT" value="CLASS" />
-      <option name="VM_PARAMETERS" value="-ea" />
-      <option name="PARAMETERS" />
-      <option name="WORKING_DIRECTORY" value="$MODULE_DIR$" />
-      <option name="OUTPUT_DIRECTORY" />
-      <option name="ANNOTATION_TYPE" />
-      <option name="ENV_VARIABLES" />
-      <option name="PASS_PARENT_ENVS" value="true" />
-      <option name="TEST_SEARCH_SCOPE">
-        <value defaultName="singleModule" />
-      </option>
-      <option name="USE_DEFAULT_REPORTERS" value="false" />
-      <option name="PROPERTIES_FILE" />
-      <envs />
-      <properties />
-      <listeners />
-      <method />
-    </configuration>
-    <configuration default="false" name="xscreensaver" type="AndroidRunConfigurationType" factoryName="Android App">
-      <module name="xscreensaver" />
-      <option name="DEPLOY" value="true" />
-      <option name="ARTIFACT_NAME" value="" />
-      <option name="PM_INSTALL_OPTIONS" value="" />
-      <option name="ACTIVITY_EXTRA_FLAGS" value="" />
-      <option name="MODE" value="default_activity" />
-      <option name="TARGET_SELECTION_MODE" value="SHOW_DIALOG" />
-      <option name="PREFERRED_AVD" value="" />
-      <option name="CLEAR_LOGCAT" value="false" />
-      <option name="SHOW_LOGCAT_AUTOMATICALLY" value="false" />
-      <option name="SKIP_NOOP_APK_INSTALLATIONS" value="true" />
-      <option name="FORCE_STOP_RUNNING_APP" value="true" />
-      <option name="DEBUGGER_TYPE" value="Auto" />
-      <option name="USE_LAST_SELECTED_DEVICE" value="false" />
-      <option name="PREFERRED_AVD" value="" />
-      <option name="SELECTED_CLOUD_MATRIX_CONFIGURATION_ID" value="-1" />
-      <option name="SELECTED_CLOUD_MATRIX_PROJECT_ID" value="" />
-      <Auto>
-        <option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
-        <option name="WORKING_DIR" value="" />
-        <option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
-      </Auto>
-      <Hybrid>
-        <option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
-        <option name="WORKING_DIR" value="" />
-        <option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
-      </Hybrid>
-      <Java />
-      <Native>
-        <option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
-        <option name="WORKING_DIR" value="" />
-        <option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
-      </Native>
-      <Profilers>
-        <option name="ENABLE_ADVANCED_PROFILING" value="true" />
-        <option name="GAPID_ENABLED" value="false" />
-        <option name="GAPID_DISABLE_PCS" value="false" />
-        <option name="SUPPORT_LIB_ENABLED" value="true" />
-        <option name="INSTRUMENTATION_ENABLED" value="true" />
-      </Profilers>
-      <option name="DEEP_LINK" value="" />
-      <option name="ACTIVITY_CLASS" value="" />
-      <method />
-    </configuration>
-    <list size="1">
-      <item index="0" class="java.lang.String" itemvalue="Android App.xscreensaver" />
-    </list>
-    <configuration name="&lt;template&gt;" type="Applet" default="true" selected="false">
-      <option name="MAIN_CLASS_NAME" />
-      <option name="HTML_FILE_NAME" />
-      <option name="HTML_USED" value="false" />
-      <option name="WIDTH" value="400" />
-      <option name="HEIGHT" value="300" />
-      <option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" />
-      <option name="VM_PARAMETERS" />
-    </configuration>
-    <configuration name="&lt;template&gt;" type="#org.jetbrains.idea.devkit.run.PluginConfigurationType" default="true" selected="false">
-      <option name="VM_PARAMETERS" value="-Xmx512m -Xms256m -XX:MaxPermSize=250m -ea" />
-    </configuration>
-  </component>
-  <component name="ShelveChangesManager" show_recycled="false">
-    <option name="remove_strategy" value="false" />
-  </component>
-  <component name="SvnConfiguration">
-    <configuration />
-  </component>
-  <component name="TaskManager">
-    <task active="true" id="Default" summary="Default task">
-      <changelist id="41008724-035d-4e24-92b6-6dfb9231c83c" name="Default" comment="" />
-      <created>1475536195508</created>
-      <option name="number" value="Default" />
-      <option name="presentableId" value="Default" />
-      <updated>1475536195508</updated>
-    </task>
-    <servers />
-  </component>
-  <component name="ToolWindowManager">
-    <frame x="73" y="23" width="1137" height="1029" extended-state="0" />
-    <editor active="false" />
-    <layout>
-      <window_info id="Nl-Palette" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
-      <window_info id="Build Variants" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
-      <window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
-      <window_info id="Android Monitor" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
-      <window_info id="Properties" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
-      <window_info id="Capture Tool" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
-      <window_info id="Designer" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
-      <window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
-      <window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
-      <window_info id="Android Model" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
-      <window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
-      <window_info id="Messages" active="true" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.32968238" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
-      <window_info id="Palette&#9;" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
-      <window_info id="Image Layers" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
-      <window_info id="Capture Analysis" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
-      <window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
-      <window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
-      <window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
-      <window_info id="Captures" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
-      <window_info id="Gradle Console" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
-      <window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.2547945" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
-      <window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32968238" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
-      <window_info id="Gradle" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
-      <window_info id="Theme Preview" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
-      <window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
-      <window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
-      <window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
-      <window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="SLIDING" type="SLIDING" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
-      <window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
-      <window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
-      <window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
-    </layout>
-  </component>
-  <component name="VcsContentAnnotationSettings">
-    <option name="myLimit" value="2678400000" />
-  </component>
-  <component name="XDebuggerManager">
-    <breakpoint-manager />
-    <watches-manager />
-  </component>
-</project>
\ No newline at end of file
diff --git a/android/project/xscreensaver/assets/fonts/OCRAStd.otf b/android/project/xscreensaver/assets/fonts/OCRAStd.otf
deleted file mode 120000 (symlink)
index 6a6cb46..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../OSX/OCRAStd.otf
\ No newline at end of file
diff --git a/android/project/xscreensaver/assets/fonts/PxPlus_IBM_VGA8.ttf b/android/project/xscreensaver/assets/fonts/PxPlus_IBM_VGA8.ttf
deleted file mode 120000 (symlink)
index 7be8e8e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../OSX/PxPlus_IBM_VGA8.ttf
\ No newline at end of file
diff --git a/android/project/xscreensaver/assets/fonts/YearlReg.ttf b/android/project/xscreensaver/assets/fonts/YearlReg.ttf
deleted file mode 120000 (symlink)
index d67181b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../OSX/YearlReg.ttf
\ No newline at end of file
diff --git a/android/project/xscreensaver/build.gradle b/android/project/xscreensaver/build.gradle
deleted file mode 100644 (file)
index c0f9f10..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-apply plugin: 'android'
-
-dependencies {
-    compile fileTree(include: '*.jar', dir: 'libs')
-}
-
-android {
-    compileSdkVersion 21
-    buildToolsVersion "21.1.2"
-    compileOptions {
-        sourceCompatibility JavaVersion.VERSION_1_7
-        targetCompatibility JavaVersion.VERSION_1_7
-    }
-    sourceSets {
-        main {
-            manifest.srcFile 'AndroidManifest.xml'
-            java.srcDirs = ['src']
-            resources.srcDirs = ['src']
-            aidl.srcDirs = ['src']
-            renderscript.srcDirs = ['src']
-            res.srcDirs = ['res']
-            assets.srcDirs = ['assets']
-            // jniLibs.srcDirs = ['jni']
-            jniLibs.srcDirs = ['libs']
-            jni.srcDirs = [] // disable automatic ndk-build call
-        }
-
-        // Move the tests to tests/java, tests/res, etc...
-        instrumentTest.setRoot('tests')
-
-        // Move the build types to build-types/<type>
-        // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
-        // This moves them out of them default location under src/<type>/... which would
-        // conflict with src/ being used by the main source set.
-        // Adding new build types or product flavors should be accompanied
-        // by a similar customization.
-        debug.setRoot('build-types/debug')
-        release.setRoot('build-types/release')
-    }
-    project.ext.versionCodes = ['armeabi': 1, 'armeabi-v7a': 2, 'arm64-v8a': 3, 'mips': 5, 'mips64': 6, 'x86': 8, 'x86_64': 9]
-    //versionCode digit for each supported ABI, with 64bit>32bit and x86>armeabi-*
-
-
-    // put ndk-build in build's path, or replace below with its full path
-    task ndkBuild(type: Exec) {
-       Properties properties = new Properties()
-         properties.load(project.rootProject.file('local.properties').newDataInputStream())
-       def ndkDir = properties.getProperty('ndk.dir')
-       commandLine "$ndkDir/ndk-build", '-C', file('jni').absolutePath,
-          '-j' + Runtime.getRuntime().availableProcessors().toString()
-    }
-
-    // generate files early in the process
-    task perlBuild(type: Exec) {
-        commandLine 'sh', '-c',
-          'cd ../..; ../hacks/check-configs.pl --build-android $ANDROID_HACKS'
-    }
-  
-    task perlClean(type: Delete) {
-        delete('../../gen')
-        delete('res/values')
-        delete('res/xml')
-        delete('src/org/jwz/xscreensaver/gen')
-        delete('AndroidManifest.xml')
-    }
-
-    task objlibClean(type: Delete) {
-        delete('./build')
-        delete('./libs')
-        delete('./obj')
-    }
-
-    task downloadNeededDrawables(type: Exec) {
-        commandLine 'sh', '-c',
-          'cd ../../ ; \
-           for f in $ANDROID_HACKS; do \
-            f=`echo "$f" | sed s/rd-bomb/rdbomb/` ; \
-             make -s project/xscreensaver/res/drawable/$f.png ; \
-           done'
-    }
-    preBuild.dependsOn downloadNeededDrawables
-
-    preBuild.dependsOn perlBuild
-
-    task config_h(type: Exec) {
-        commandLine 'sh', '-c',
-          'if [ ! -s ../../../config.h ]; then \
-             echo "" >&2 ; echo "" >&2 ; \
-             echo "config.h does not exist.  cd .. and run ./configure" >&2 ; \
-             echo "" >&2 ; \
-             exit 1 ; \
-           fi'
-    }
-    preBuild.dependsOn config_h
-
-    clean.dependsOn perlClean
-    clean.dependsOn objlibClean
-
-    tasks.withType(JavaCompile) {
-        options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
-    }
-
-    tasks.withType(JavaCompile) {
-        compileTask -> compileTask.dependsOn ndkBuild
-    }
-
-
-    defaultConfig {
-        minSdkVersion 15
-        targetSdkVersion 21
-    }
-    productFlavors {
-    }
-    buildTypes {
-        debug {
-            jniDebuggable true
-        }
-    }
-}
diff --git a/android/project/xscreensaver/build.xml b/android/project/xscreensaver/build.xml
deleted file mode 100644 (file)
index abda7fe..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project name="Xscreensaver" default="help">
-
-    <!-- The local.properties file is created and updated by the 'android' tool.
-         It contains the path to the SDK. It should *NOT* be checked into
-         Version Control Systems. -->
-    <property file="local.properties" />
-
-    <!-- The ant.properties file can be created by you. It is only edited by the
-         'android' tool to add properties to it.
-         This is the place to change some Ant specific build properties.
-         Here are some properties you may want to change/update:
-
-         source.dir
-             The name of the source directory. Default is 'src'.
-         out.dir
-             The name of the output directory. Default is 'bin'.
-
-         For other overridable properties, look at the beginning of the rules
-         files in the SDK, at tools/ant/build.xml
-
-         Properties related to the SDK location or the project target should
-         be updated using the 'android' tool with the 'update' action.
-
-         This file is an integral part of the build system for your
-         application and should be checked into Version Control Systems.
-
-         -->
-    <property file="ant.properties" />
-
-    <!-- if sdk.dir was not set from one of the property file, then
-         get it from the ANDROID_HOME env var.
-         This must be done before we load project.properties since
-         the proguard config can use sdk.dir -->
-    <property environment="env" />
-    <condition property="sdk.dir" value="${env.ANDROID_HOME}">
-        <isset property="env.ANDROID_HOME" />
-    </condition>
-
-    <!-- The project.properties file is created and updated by the 'android'
-         tool, as well as ADT.
-
-         This contains project specific properties such as project target, and library
-         dependencies. Lower level build properties are stored in ant.properties
-         (or in .classpath for Eclipse projects).
-
-         This file is an integral part of the build system for your
-         application and should be checked into Version Control Systems. -->
-    <loadproperties srcFile="project.properties" />
-
-    <!-- quick check on sdk.dir -->
-    <fail
-            message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
-            unless="sdk.dir"
-    />
-
-    <!--
-        Import per project custom build rules if present at the root of the project.
-        This is the place to put custom intermediary targets such as:
-            -pre-build
-            -pre-compile
-            -post-compile (This is typically used for code obfuscation.
-                           Compiled code location: ${out.classes.absolute.dir}
-                           If this is not done in place, override ${out.dex.input.absolute.dir})
-            -post-package
-            -post-build
-            -pre-clean
-    -->
-    <import file="custom_rules.xml" optional="true" />
-
-    <!-- Import the actual build file.
-
-         To customize existing targets, there are two options:
-         - Customize only one target:
-             - copy/paste the target into this file, *before* the
-               <import> task.
-             - customize it to your needs.
-         - Customize the whole content of build.xml
-             - copy/paste the content of the rules files (minus the top node)
-               into this file, replacing the <import> task.
-             - customize to your needs.
-
-         ***********************
-         ****** IMPORTANT ******
-         ***********************
-         In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
-         in order to avoid having your file be overridden by tools such as "android update project"
-    -->
-    <!-- version-tag: 1 -->
-    <import file="${sdk.dir}/tools/ant/build.xml" />
-
-</project>
diff --git a/android/project/xscreensaver/gradle/wrapper/gradle-wrapper.jar b/android/project/xscreensaver/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644 (file)
index 13372ae..0000000
Binary files a/android/project/xscreensaver/gradle/wrapper/gradle-wrapper.jar and /dev/null differ
diff --git a/android/project/xscreensaver/gradle/wrapper/gradle-wrapper.properties b/android/project/xscreensaver/gradle/wrapper/gradle-wrapper.properties
deleted file mode 100644 (file)
index 04e285f..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#Mon Dec 28 10:00:20 PST 2015
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
diff --git a/android/project/xscreensaver/gradlew b/android/project/xscreensaver/gradlew
deleted file mode 100644 (file)
index 9d82f78..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-#!/usr/bin/env bash
-
-##############################################################################
-##
-##  Gradle start up script for UN*X
-##
-##############################################################################
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
-
-warn ( ) {
-    echo "$*"
-}
-
-die ( ) {
-    echo
-    echo "$*"
-    echo
-    exit 1
-}
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-case "`uname`" in
-  CYGWIN* )
-    cygwin=true
-    ;;
-  Darwin* )
-    darwin=true
-    ;;
-  MINGW* )
-    msys=true
-    ;;
-esac
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
-    ls=`ls -ld "$PRG"`
-    link=`expr "$ls" : '.*-> \(.*\)$'`
-    if expr "$link" : '/.*' > /dev/null; then
-        PRG="$link"
-    else
-        PRG=`dirname "$PRG"`"/$link"
-    fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
-    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
-        # IBM's JDK on AIX uses strange locations for the executables
-        JAVACMD="$JAVA_HOME/jre/sh/java"
-    else
-        JAVACMD="$JAVA_HOME/bin/java"
-    fi
-    if [ ! -x "$JAVACMD" ] ; then
-        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-    fi
-else
-    JAVACMD="java"
-    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
-    MAX_FD_LIMIT=`ulimit -H -n`
-    if [ $? -eq 0 ] ; then
-        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
-            MAX_FD="$MAX_FD_LIMIT"
-        fi
-        ulimit -n $MAX_FD
-        if [ $? -ne 0 ] ; then
-            warn "Could not set maximum file descriptor limit: $MAX_FD"
-        fi
-    else
-        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
-    fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
-    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
-    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
-    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-    JAVACMD=`cygpath --unix "$JAVACMD"`
-
-    # We build the pattern for arguments to be converted via cygpath
-    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
-    SEP=""
-    for dir in $ROOTDIRSRAW ; do
-        ROOTDIRS="$ROOTDIRS$SEP$dir"
-        SEP="|"
-    done
-    OURCYGPATTERN="(^($ROOTDIRS))"
-    # Add a user-defined pattern to the cygpath arguments
-    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
-        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
-    fi
-    # Now convert the arguments - kludge to limit ourselves to /bin/sh
-    i=0
-    for arg in "$@" ; do
-        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
-        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
-
-        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
-            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
-        else
-            eval `echo args$i`="\"$arg\""
-        fi
-        i=$((i+1))
-    done
-    case $i in
-        (0) set -- ;;
-        (1) set -- "$args0" ;;
-        (2) set -- "$args0" "$args1" ;;
-        (3) set -- "$args0" "$args1" "$args2" ;;
-        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
-        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
-        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
-        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
-        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
-        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
-    esac
-fi
-
-# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
-function splitJvmOpts() {
-    JVM_OPTS=("$@")
-}
-eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
-JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
-
-exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/android/project/xscreensaver/gradlew.bat b/android/project/xscreensaver/gradlew.bat
deleted file mode 100644 (file)
index aec9973..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-@if "%DEBUG%" == "" @echo off\r
-@rem ##########################################################################\r
-@rem\r
-@rem  Gradle startup script for Windows\r
-@rem\r
-@rem ##########################################################################\r
-\r
-@rem Set local scope for the variables with windows NT shell\r
-if "%OS%"=="Windows_NT" setlocal\r
-\r
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r
-set DEFAULT_JVM_OPTS=\r
-\r
-set DIRNAME=%~dp0\r
-if "%DIRNAME%" == "" set DIRNAME=.\r
-set APP_BASE_NAME=%~n0\r
-set APP_HOME=%DIRNAME%\r
-\r
-@rem Find java.exe\r
-if defined JAVA_HOME goto findJavaFromJavaHome\r
-\r
-set JAVA_EXE=java.exe\r
-%JAVA_EXE% -version >NUL 2>&1\r
-if "%ERRORLEVEL%" == "0" goto init\r
-\r
-echo.\r
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r
-echo.\r
-echo Please set the JAVA_HOME variable in your environment to match the\r
-echo location of your Java installation.\r
-\r
-goto fail\r
-\r
-:findJavaFromJavaHome\r
-set JAVA_HOME=%JAVA_HOME:"=%\r
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe\r
-\r
-if exist "%JAVA_EXE%" goto init\r
-\r
-echo.\r
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r
-echo.\r
-echo Please set the JAVA_HOME variable in your environment to match the\r
-echo location of your Java installation.\r
-\r
-goto fail\r
-\r
-:init\r
-@rem Get command-line arguments, handling Windowz variants\r
-\r
-if not "%OS%" == "Windows_NT" goto win9xME_args\r
-if "%@eval[2+2]" == "4" goto 4NT_args\r
-\r
-:win9xME_args\r
-@rem Slurp the command line arguments.\r
-set CMD_LINE_ARGS=\r
-set _SKIP=2\r
-\r
-:win9xME_args_slurp\r
-if "x%~1" == "x" goto execute\r
-\r
-set CMD_LINE_ARGS=%*\r
-goto execute\r
-\r
-:4NT_args\r
-@rem Get arguments from the 4NT Shell from JP Software\r
-set CMD_LINE_ARGS=%$\r
-\r
-:execute\r
-@rem Setup the command line\r
-\r
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar\r
-\r
-@rem Execute Gradle\r
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\r
-\r
-:end\r
-@rem End local scope for the variables with windows NT shell\r
-if "%ERRORLEVEL%"=="0" goto mainEnd\r
-\r
-:fail\r
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r
-rem the _cmd.exe /c_ return code!\r
-if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1\r
-exit /b 1\r
-\r
-:mainEnd\r
-if "%OS%"=="Windows_NT" endlocal\r
-\r
-:omega\r
diff --git a/android/project/xscreensaver/jni/Android.mk b/android/project/xscreensaver/jni/Android.mk
deleted file mode 100644 (file)
index 9f54540..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-LOCAL_PATH := $(call my-dir)/../../../..
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := xscreensaver
-
-# The base framework files:
-LOCAL_SRC_FILES := \
-    android/screenhack-android.c \
-    jwxyz/jwxyz-android.c \
-    jwxyz/jwxyz-common.c \
-    jwxyz/jwxyz-gl.c \
-    jwxyz/jwxyz-timers.c \
-    jwxyz/jwzgles.c \
-
-# Utilities used by the hacks:
-LOCAL_SRC_FILES += \
-    hacks/analogtv.c \
-    hacks/delaunay.c \
-    hacks/fps.c \
-    hacks/glx/dropshadow.c \
-    hacks/glx/chessmodels.c \
-    hacks/glx/fps-gl.c \
-    hacks/glx/gltrackball.c \
-    hacks/glx/glut_stroke.c \
-    hacks/glx/glut_swidth.c \
-    hacks/glx/grab-ximage.c \
-    hacks/glx/marching.c \
-    hacks/glx/normals.c \
-    hacks/glx/rotator.c \
-    hacks/glx/sphere.c \
-    hacks/glx/texfont.c \
-    hacks/glx/trackball.c \
-    hacks/glx/tube.c \
-    hacks/glx/xpm-ximage.c \
-    hacks/xlockmore.c \
-    hacks/xpm-pixmap.c \
-    utils/async_netdb.c \
-    utils/aligned_malloc.c \
-    utils/colorbars.c \
-    utils/colors.c \
-    utils/erase.c \
-    utils/grabclient.c \
-    utils/hsv.c \
-    utils/logo.c \
-    utils/minixpm.c \
-    utils/pow2.c \
-    utils/resources.c \
-    utils/spline.c \
-    utils/textclient-mobile.c \
-    utils/thread_util.c \
-    utils/usleep.c \
-    utils/utf8wc.c \
-    utils/xft.c \
-    utils/xshm.c \
-    utils/yarandom.c \
-
-# The source files of all of the currently active hacks:
-LOCAL_SRC_FILES += $(shell \
-  for f in $$ANDROID_HACKS ; do \
-    if [ "$$f" = "companioncube" ]; then f="companion"; fi ; \
-    if [ -f "../../../../hacks/$$f.c" ]; then \
-      echo "hacks/$$f.c" ; \
-    else \
-      echo "hacks/glx/$$f.c" ; \
-    fi ; \
-  done )
-
-# Some savers occupy more than one source file:
-LOCAL_SRC_FILES += \
-    hacks/apple2-main.c \
-    hacks/asm6502.c \
-    hacks/pacman_ai.c \
-    hacks/pacman_level.c \
-    hacks/glx/b_draw.c \
-    hacks/glx/b_lockglue.c \
-    hacks/glx/b_sphere.c \
-    hacks/glx/buildlwo.c \
-    hacks/glx/companion_quad.c \
-    hacks/glx/companion_disc.c \
-    hacks/glx/companion_heart.c \
-    hacks/glx/cow_face.c \
-    hacks/glx/cow_hide.c \
-    hacks/glx/cow_hoofs.c \
-    hacks/glx/cow_horns.c \
-    hacks/glx/cow_tail.c \
-    hacks/glx/cow_udder.c \
-    hacks/glx/dolphin.c \
-    hacks/glx/gllist.c \
-    hacks/glx/glschool_alg.c \
-    hacks/glx/glschool_gl.c \
-    hacks/glx/involute.c \
-    hacks/glx/lament_model.c \
-    hacks/glx/pipeobjs.c \
-    hacks/glx/robot.c \
-    hacks/glx/robot-wireframe.c \
-    hacks/glx/polyhedra-gl.c \
-    hacks/glx/s1_1.c \
-    hacks/glx/s1_2.c \
-    hacks/glx/s1_3.c \
-    hacks/glx/s1_4.c \
-    hacks/glx/s1_5.c \
-    hacks/glx/s1_6.c \
-    hacks/glx/s1_b.c \
-    hacks/glx/seccam.c \
-    hacks/glx/shark.c \
-    hacks/glx/sonar-sim.c \
-    hacks/glx/sonar-icmp.c \
-    hacks/glx/splitflap_obj.c \
-    hacks/glx/sproingiewrap.c \
-    hacks/glx/stonerview-move.c \
-    hacks/glx/stonerview-osc.c \
-    hacks/glx/stonerview-view.c \
-    hacks/glx/swim.c \
-    hacks/glx/tangram_shapes.c \
-    hacks/glx/teapot.c \
-    hacks/glx/toast.c \
-    hacks/glx/toast2.c \
-    hacks/glx/toaster.c \
-    hacks/glx/toaster_base.c \
-    hacks/glx/toaster_handle.c \
-    hacks/glx/toaster_handle2.c \
-    hacks/glx/toaster_jet.c \
-    hacks/glx/toaster_knob.c \
-    hacks/glx/toaster_slots.c \
-    hacks/glx/toaster_wing.c \
-    hacks/glx/tronbit_idle1.c \
-    hacks/glx/tronbit_idle2.c \
-    hacks/glx/tronbit_no.c \
-    hacks/glx/tronbit_yes.c \
-    hacks/glx/tunnel_draw.c \
-    hacks/glx/whale.c \
-
-LOCAL_LDLIBS := -lGLESv1_CM -ldl -llog -lEGL -latomic
-
-LOCAL_C_INCLUDES := \
-       $(LOCAL_PATH) \
-       $(LOCAL_PATH)/android \
-       $(LOCAL_PATH)/utils \
-       $(LOCAL_PATH)/jwxyz \
-       $(LOCAL_PATH)/hacks \
-       $(LOCAL_PATH)/hacks/glx \
-
-# -Wnested-externs would also be here, but for Android unistd.h.
-LOCAL_CFLAGS += \
-       -std=c99 \
-       -Wall \
-       -Wstrict-prototypes \
-       -Wmissing-prototypes \
-       -DSTANDALONE=1 \
-       -DHAVE_ANDROID=1 \
-       -DUSE_GL=1 \
-       -DHAVE_JWXYZ=1 \
-       -DJWXYZ_GL=1 \
-       -DHAVE_JWZGLES=1 \
-       -DHAVE_XUTF8DRAWSTRING=1 \
-       -DHAVE_GLBINDTEXTURE=1 \
-       -DGL_VERSION_ES_CM_1_0 \
-       -DHAVE_UNISTD_H=1 \
-       -DHAVE_INTTYPES_H=1 \
-       -DHAVE_UNAME=1 \
-       -DHAVE_UTIL_H=1 \
-       -DGETTIMEOFDAY_TWO_ARGS=1 \
-       -DHAVE_ICMP=1 \
-       -DHAVE_PTHREAD=1 \
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/android/project/xscreensaver/jni/Application.mk b/android/project/xscreensaver/jni/Application.mk
deleted file mode 100644 (file)
index a7aa11b..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# Get this value from android/Makefile
-APP_ABI := $(shell echo $$APP_ABI)
-APP_STL := stlport_static
-APP_PLATFORM := android-14
-# ^^ this can be increased
-
diff --git a/android/project/xscreensaver/local.properties b/android/project/xscreensaver/local.properties
deleted file mode 100644 (file)
index d530e0d..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-## This file is automatically generated by Android Studio.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must *NOT* be checked into Version Control Systems,
-# as it contains information specific to your local configuration.
-#
-# Location of the SDK. This is only used by Gradle.
-# For customization when using a Version Control System, please read the
-# header note.
-#Mon Oct 03 16:09:56 PDT 2016
-sdk.dir=/Users/jwz/Library/Android/sdk
diff --git a/android/project/xscreensaver/project.properties b/android/project/xscreensaver/project.properties
deleted file mode 100644 (file)
index 1e1e7a3..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must be checked in Version Control Systems.
-#
-# To customize properties used by the Ant build system edit
-# "ant.properties", and override values to adapt the script to your
-# project structure.
-#
-# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
-#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
-
-android.library.reference.1=
-# Project target.
-target=android-19
diff --git a/android/project/xscreensaver/res/drawable-ldpi/icon.png b/android/project/xscreensaver/res/drawable-ldpi/icon.png
deleted file mode 100644 (file)
index c4d1934..0000000
Binary files a/android/project/xscreensaver/res/drawable-ldpi/icon.png and /dev/null differ
diff --git a/android/project/xscreensaver/res/drawable-mdpi/icon.png b/android/project/xscreensaver/res/drawable-mdpi/icon.png
deleted file mode 100644 (file)
index 1e14e4b..0000000
Binary files a/android/project/xscreensaver/res/drawable-mdpi/icon.png and /dev/null differ
diff --git a/android/project/xscreensaver/res/drawable/thumbnail.png b/android/project/xscreensaver/res/drawable/thumbnail.png
deleted file mode 100644 (file)
index a86c16c..0000000
Binary files a/android/project/xscreensaver/res/drawable/thumbnail.png and /dev/null differ
diff --git a/android/project/xscreensaver/res/layout-land/activity_xscreensaver.xml b/android/project/xscreensaver/res/layout-land/activity_xscreensaver.xml
deleted file mode 100644 (file)
index 24f33e0..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- TODO: Remove action bar; it's redundant. -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent"
-    android:orientation="horizontal"
-    android:gravity="center_horizontal"
-    tools:context="org.jwz.xscreensaver.XScreenSaverActivity">
-
-    <LinearLayout
-        android:layout_width="wrap_content"
-        android:layout_height="fill_parent"
-        android:layout_centerHorizontal="true"
-        android:layout_centerVertical="true"
-        android:gravity="center_vertical"
-        android:orientation="vertical">
-
-        <ImageView
-            android:layout_width="256sp"
-            android:layout_height="256sp"
-            android:layout_centerHorizontal="true"
-            android:src="@drawable/thumbnail" />
-        <!-- TODO: Version number! -->
-    </LinearLayout>
-
-    <LinearLayout
-        android:layout_width="wrap_content"
-        android:layout_height="fill_parent"
-        android:layout_centerHorizontal="true"
-        android:layout_centerVertical="true"
-        android:gravity="center_vertical"
-        android:orientation="vertical">
-
-
-        <TextView
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"
-            android:gravity="center"
-            android:text="XScreenSaver"
-            android:textSize="32sp" />
-        <Button
-            android:id="@+id/apply_wallpaper"
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"
-            android:text="Open live wallpaper list" />
-        <Button
-            android:id="@+id/apply_daydream"
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"
-            android:text="Open Daydream list" />
-        <TextView
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"
-            android:autoLink="web"
-            android:gravity="center"
-            android:text="https://www.jwz.org/xscreensaver/" />
-    </LinearLayout>
-</LinearLayout>
diff --git a/android/project/xscreensaver/res/layout/activity_xscreensaver.xml b/android/project/xscreensaver/res/layout/activity_xscreensaver.xml
deleted file mode 100644 (file)
index 8adfa00..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- TODO: Flip layout orientation on rotation. And maybe make scrollable? -->
-<!-- TODO: Remove action bar; it's redundant. -->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent"
-    tools:context="org.jwz.xscreensaver.XScreenSaverActivity">
-    <LinearLayout
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_centerHorizontal="true"
-        android:layout_centerVertical="true"
-        android:orientation="vertical">
-        <ImageView
-            android:layout_width="256sp"
-            android:layout_height="256sp"
-            android:layout_centerHorizontal="true"
-            android:src="@drawable/thumbnail" />
-        <!-- TODO: Version number! -->
-        <TextView
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"
-            android:gravity="center"
-            android:text="XScreenSaver"
-            android:textSize="32sp" />
-        <Button
-            android:id="@+id/apply_wallpaper"
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"
-            android:text="Open live wallpaper list" />
-        <Button
-            android:id="@+id/apply_daydream"
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"
-            android:text="Open Daydream list" />
-        <TextView
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"
-            android:autoLink="web"
-            android:gravity="center"
-            android:text="https://www.jwz.org/xscreensaver/" />
-    </LinearLayout>
-</RelativeLayout>
diff --git a/android/project/xscreensaver/res/layout/main.xml b/android/project/xscreensaver/res/layout/main.xml
deleted file mode 100644 (file)
index 4361cfe..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent"
-    >
-</LinearLayout>
diff --git a/android/project/xscreensaver/res/layout/preference_blurb.xml b/android/project/xscreensaver/res/layout/preference_blurb.xml
deleted file mode 100644 (file)
index 66e6d82..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!-- Layout for the description of each screen saver, that appears
-     at the bottom of the preferences screen.  Based on
-     sdk/platforms/android-21/data/res/layout/preference.xml
- -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:minHeight="?android:attr/listPreferredItemHeight"
-    android:gravity="center_vertical"
-    android:paddingEnd="?android:attr/scrollbarSize"
-    android:background="?android:attr/selectableItemBackground" >
-
-    <ImageView
-        android:id="@+android:id/icon"
-        android:layout_gravity="top"
-        android:layout_width="40dip"
-        android:layout_height="40dip"
-        android:layout_marginTop="0dip"
-        />
-
-    <RelativeLayout
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="0dip"
-        android:layout_marginEnd="0dip"
-        android:layout_marginTop="6dip"
-        android:layout_marginBottom="6dip"
-        android:layout_weight="1">
-
-        <TextView android:id="@+android:id/summary"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_below="@android:id/title"
-            android:layout_alignStart="@android:id/title"
-            android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="?android:attr/textColorPrimary"
-            android:layout_marginTop="8dip"
-            android:maxLines="1000" />
-
-    </RelativeLayout>
-
-</LinearLayout>
diff --git a/android/project/xscreensaver/res/layout/slider_preference.xml b/android/project/xscreensaver/res/layout/slider_preference.xml
deleted file mode 100644 (file)
index 69647ff..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!-- Layout for org/jwz/xscreensaver/SliderPreference.java -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:minHeight="?android:attr/listPreferredItemHeight"
-    android:gravity="center_vertical"
-    android:paddingEnd="?android:attr/scrollbarSize"
-    android:background="?android:attr/selectableItemBackground" >
-
-    <TextView
-        android:id="@+android:id/title"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:ellipsize="end"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_weight="40"
-        android:width="0dp"
-        android:layout_marginLeft="16dip" />
-
-    <LinearLayout
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_weight="60"
-        android:orientation="vertical"
-        android:layout_marginLeft="0dip" >
-
-        <SeekBar
-            android:id="@+id/slider_preference_seekbar"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content" />
-
-        <RelativeLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal" >
-
-            <TextView
-                android:id="@+id/slider_preference_low"
-                android:textAppearance="?android:attr/textAppearanceSmall"
-                android:ellipsize="end"
-                android:singleLine="true"
-                android:layout_alignParentLeft="true"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content" />
-
-            <TextView
-                android:id="@+id/slider_preference_high"
-                android:layout_alignParentRight="true"
-                android:textAppearance="?android:attr/textAppearanceSmall"
-                android:ellipsize="end"
-                android:singleLine="true"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content" />
-
-        </RelativeLayout>
-    </LinearLayout>
-</LinearLayout>
diff --git a/android/project/xscreensaver/src/org/jwz/xscreensaver/SliderPreference.java b/android/project/xscreensaver/src/org/jwz/xscreensaver/SliderPreference.java
deleted file mode 100644 (file)
index c1a1a1d..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * xscreensaver, Copyright (c) 2016 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.
- *
- * A numeric preference as a slider, inline in the preferences list.
- * XML options include:
- *
- *  low, high (floats) -- smallest and largest allowed values.
- *  If low > high, the value increases as the slider's thumb moves left.
- *
- *  lowLabel, highLabel (strings) -- labels shown at the left and right
- *  ends of the slider.
- *
- *  integral (boolean) -- whether to use whole numbers instead of floats;
- */
-
-package org.jwz.xscreensaver;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.content.res.Resources;
-import android.preference.Preference;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.SeekBar;
-import android.widget.TextView;
-import android.util.Log;
-
-public class SliderPreference extends Preference {
-
-  protected float low, high;
-  protected String low_label, high_label;
-  protected boolean integral;
-  protected float mValue;
-  protected int seekbar_ticks;
-
-  public SliderPreference(Context context, AttributeSet attrs) {
-    this (context, attrs, 0);
-  }
-
-  public SliderPreference (Context context, AttributeSet attrs, int defStyle) {
-    super (context, attrs, defStyle);
-
-    Resources res = context.getResources();
-
-    // Parse these from the "<SliderPreference>" tag
-    low        = Float.parseFloat (attrs.getAttributeValue (null, "low"));
-    high       = Float.parseFloat (attrs.getAttributeValue (null, "high"));
-    integral   = attrs.getAttributeBooleanValue (null, "integral", false);
-    low_label  = res.getString(
-                   attrs.getAttributeResourceValue (null, "lowLabel", 0));
-    high_label = res.getString(
-                   attrs.getAttributeResourceValue (null, "highLabel", 0));
-
-    seekbar_ticks = (integral
-                     ? (int) Math.floor (Math.abs (high - low))
-                     : 100000);
-
-    setWidgetLayoutResource (R.layout.slider_preference);
-  }
-
-
-  @Override
-  protected void onSetInitialValue (boolean restore, Object def) {
-    if (restore) {
-      mValue = getPersistedFloat (low);
-    } else {
-      mValue = (Float) def;
-      persistFloat (mValue);
-    }
-    //Log.d("xscreensaver", String.format("SLIDER INIT %s: %f",
-    //      low_label, mValue));
-  }
-
-  @Override
-  protected Object onGetDefaultValue(TypedArray a, int index) {
-    return a.getFloat (index, low);
-  }
-
-
-  public float getValue() {
-    return mValue;
-  }
-
-  public void setValue (float value) {
-
-    if (low < high) {
-      value = Math.max (low, Math.min (high, value));
-    } else {
-      value = Math.max (high, Math.min (low, value));
-    }
-
-    if (integral)
-      value = Math.round (value);
-
-    if (value != mValue) {
-      //Log.d("xscreensaver", String.format("SLIDER %s: %f", low_label, value));
-      persistFloat (value);
-      mValue = value;
-      notifyChanged();
-    }
-  }
-
-
-  @Override
-  protected View onCreateView (ViewGroup parent) {
-    View view = super.onCreateView(parent);
-
-    TextView low_view = (TextView)
-      view.findViewById (R.id.slider_preference_low);
-    low_view.setText (low_label);
-
-    TextView high_view = (TextView)
-      view.findViewById (R.id.slider_preference_high);
-    high_view.setText (high_label);
-
-    SeekBar seekbar = (SeekBar)
-      view.findViewById (R.id.slider_preference_seekbar);
-    seekbar.setMax (seekbar_ticks);
-
-    float ratio = (mValue - low) / (high - low);
-    int seek_value = (int) (ratio * (float) seekbar_ticks);
-
-    seekbar.setProgress (seek_value);
-
-    final SliderPreference slider = this;
-
-    seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
-
-        @Override
-        public void onStopTrackingTouch(SeekBar seekBar) {
-        }
-
-        @Override
-        public void onStartTrackingTouch(SeekBar seekBar) {
-        }
-
-        @Override
-        public void onProgressChanged (SeekBar seekBar, int progress,
-                                       boolean fromUser) {
-          if (fromUser) {
-            float ratio = (float) progress / (float) seekbar_ticks;
-            float value = low + (ratio * (high - low));
-            slider.setValue (value);
-            callChangeListener (progress);
-          }
-        }
-      });
-
-    return view;
-  }
-}
diff --git a/android/project/xscreensaver/src/org/jwz/xscreensaver/TTFAnalyzer.java b/android/project/xscreensaver/src/org/jwz/xscreensaver/TTFAnalyzer.java
deleted file mode 100644 (file)
index 3d01345..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-
- * Copyright (C) 2011 George Yunaev @ Ulduzsoft
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
-
-  http://www.ulduzsoft.com/2012/01/enumerating-the-fonts-on-android-platform/
- */
-package org.jwz.xscreensaver;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.util.HashMap;
-// The class which loads the TTF file, parses it and returns the TTF font name
-class TTFAnalyzer
-{
-    // This function parses the TTF file and returns the font name specified in the file
-    public String getTtfFontName( String fontFilename )
-    {
-        try
-        {
-            // Parses the TTF file format.
-            // See http://developer.apple.com/fonts/ttrefman/rm06/Chap6.html
-            m_file = new RandomAccessFile( fontFilename, "r" );
-            // Read the version first
-            int version = readDword();
-            // The version must be either 'true' (0x74727565) or 0x00010000 or 'OTTO' (0x4f54544f) for CFF style fonts.
-            if ( version != 0x74727565 && version != 0x00010000 && version != 0x4f54544f)
-                return null;
-            // The TTF file consist of several sections called "tables", and we need to know how many of them are there.
-            int numTables = readWord();
-            // Skip the rest in the header
-            readWord(); // skip searchRange
-            readWord(); // skip entrySelector
-            readWord(); // skip rangeShift
-            // Now we can read the tables
-            for ( int i = 0; i < numTables; i++ )
-            {
-                // Read the table entry
-                int tag = readDword();
-                readDword(); // skip checksum
-                int offset = readDword();
-                int length = readDword();
-                // Now here' the trick. 'name' field actually contains the textual string name.
-                // So the 'name' string in characters equals to 0x6E616D65
-                if ( tag == 0x6E616D65 )
-                {
-                    // Here's the name section. Read it completely into the allocated buffer
-                    byte[] table = new byte[ length ];
-                    m_file.seek( offset );
-                    read( table );
-                    // This is also a table. See http://developer.apple.com/fonts/ttrefman/rm06/Chap6name.html
-                    // According to Table 36, the total number of table records is stored in the second word, at the offset 2.
-                    // Getting the count and string offset - remembering it's big endian.
-                    int count = getWord( table, 2 );
-                    int string_offset = getWord( table, 4 );
-                    // Record starts from offset 6
-                    for ( int record = 0; record < count; record++ )
-                    {
-                        // Table 37 tells us that each record is 6 words -> 12 bytes, and that the nameID is 4th word so its offset is 6.
-                        // We also need to account for the first 6 bytes of the header above (Table 36), so...
-                        int nameid_offset = record * 12 + 6;
-                        int platformID = getWord( table, nameid_offset );
-                        int nameid_value = getWord( table, nameid_offset + 6 );
-                        // Table 42 lists the valid name Identifiers. We're interested in 4 but not in Unicode encoding (for simplicity).
-                        // The encoding is stored as PlatformID and we're interested in Mac encoding
-                        if ( nameid_value == 4 && platformID == 1 )
-                        {
-                            // We need the string offset and length, which are the word 6 and 5 respectively
-                            int name_length = getWord( table, nameid_offset + 8 );
-                            int name_offset = getWord( table, nameid_offset + 10 );
-                            // The real name string offset is calculated by adding the string_offset
-                            name_offset = name_offset + string_offset;
-                            // Make sure it is inside the array
-                            if ( name_offset >= 0 && name_offset + name_length < table.length )
-                                return new String( table, name_offset, name_length );
-                        }
-                    }
-                }
-            }
-            return null;
-        }
-        catch (FileNotFoundException e)
-        {
-            // Permissions?
-            return null;
-        }
-        catch (IOException e)
-        {
-            // Most likely a corrupted font file
-            return null;
-        }
-    }
-    // Font file; must be seekable
-    private RandomAccessFile m_file = null;
-    // Helper I/O functions
-    private int readByte() throws IOException
-    {
-        return m_file.read() & 0xFF;
-    }
-    private int readWord() throws IOException
-    {
-        int b1 = readByte();
-        int b2 = readByte();
-        return b1 << 8 | b2;
-    }
-    private int readDword() throws IOException
-    {
-        int b1 = readByte();
-        int b2 = readByte();
-        int b3 = readByte();
-        int b4 = readByte();
-        return b1 << 24 | b2 << 16 | b3 << 8 | b4;
-    }
-    private void read( byte [] array ) throws IOException
-    {
-        if ( m_file.read( array ) != array.length )
-            throw new IOException();
-    }
-    // Helper
-    private int getWord( byte [] array, int offset )
-    {
-        int b1 = array[ offset ] & 0xFF;
-        int b2 = array[ offset + 1 ] & 0xFF;
-        return b1 << 8 | b2;
-    }
-}
diff --git a/android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverActivity.java b/android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverActivity.java
deleted file mode 100644 (file)
index dea2fad..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * xscreensaver, Copyright (c) 2016 Jamie Zawinski <jwz@jwz.org>
- * and Dennis Sheil <dennis@panaceasupplies.com>
- *
- * 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.
- *
- * This is the XScreenSaver "application" that just brings up the
- * Live Wallpaper preferences.
- */
-
-package org.jwz.xscreensaver;
-
-import android.app.Activity;
-import android.app.WallpaperManager;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.os.Build;
-import android.os.Bundle;
-import android.view.View;
-import android.provider.Settings;
-
-public class XScreenSaverActivity extends Activity
-  implements View.OnClickListener {
-
-  @Override
-  protected void onCreate(Bundle savedInstanceState) {
-    super.onCreate(savedInstanceState);
-    // openList();
-    setContentView(R.layout.activity_xscreensaver);
-
-    findViewById(R.id.apply_wallpaper).setOnClickListener(this);
-    findViewById(R.id.apply_daydream).setOnClickListener(this);
-  }
-
-  @Override
-  public void onClick(View v) {
-    switch (v.getId()) {
-    case R.id.apply_wallpaper:
-      startActivity(new Intent(WallpaperManager.ACTION_LIVE_WALLPAPER_CHOOSER));
-      break;
-
-    case R.id.apply_daydream:
-      String action;
-      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
-        action = Settings.ACTION_DREAM_SETTINGS;
-      } else {
-        action = Settings.ACTION_DISPLAY_SETTINGS;
-      }
-      startActivity(new Intent(action));
-      break;
-    }
-  }
-}
diff --git a/android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverApp.java b/android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverApp.java
deleted file mode 100644 (file)
index dd1050a..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * xscreensaver, Copyright (c) 2016 Jamie Zawinski <jwz@jwz.org>
- * and Dennis Sheil <dennis@panaceasupplies.com>
- *
- * 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.
- */
-
-package org.jwz.xscreensaver;
-
-import android.app.Application;
-
-public class XScreenSaverApp extends Application {
-  public XScreenSaverApp() {
-    super();
-  }
-}
diff --git a/android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverDaydream.java b/android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverDaydream.java
deleted file mode 100644 (file)
index e321721..0000000
+++ /dev/null
@@ -1,278 +0,0 @@
-/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * xscreensaver, Copyright (c) 2016 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.
- *
- * The superclass of every saver's Daydream.
- *
- * Each Daydream needs a distinct subclass in order to show up in the list.
- * We know which saver we are running by the subclass name; we know which
- * API to use by how the subclass calls super().
- */
-
-package org.jwz.xscreensaver;
-
-import java.lang.Exception;
-import android.view.View;
-import android.view.Window;
-import android.view.WindowManager;
-import android.view.KeyEvent;
-import android.service.dreams.DreamService;
-import android.opengl.GLSurfaceView;
-import android.view.GestureDetector;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.os.Message;
-import android.os.Handler;
-import android.os.Looper;
-import android.app.AlertDialog;
-import android.content.DialogInterface;
-import android.util.Log;
-
-public class XScreenSaverDaydream extends DreamService
-  implements GestureDetector.OnGestureListener,
-             GestureDetector.OnDoubleTapListener,
-             Handler.Callback {
-
-  private GLSurfaceView glview;
-  XScreenSaverRenderer renderer;
-  private GestureDetector detector;
-  boolean button_down_p;
-  Bitmap screenshot;
-
-  private void LOG (String fmt, Object... args) {
-    Log.d ("xscreensaver",
-           this.getClass().getSimpleName() + ": " +
-           String.format (fmt, args));
-  }
-
-  protected XScreenSaverDaydream () {
-    super();
-  }
-
-  // Called when jwxyz_abort() is called, or other exceptions are thrown.
-  //
-  public boolean handleMessage (Message msg) {
-
-    String err = msg.obj.toString();
-    LOG ("Caught exception: %s", err);
-
-    this.finish();  // Exit the Daydream
-
-    final AlertDialog.Builder b = new AlertDialog.Builder(this);
-    b.setMessage (err);
-    b.setCancelable (false);
-    b.setPositiveButton ("Bummer",
-                         new DialogInterface.OnClickListener() {
-                           public void onClick(DialogInterface d, int id) {
-                           }
-                         });
-
-    // #### This isn't working:
-    // "Attempted to add window with non-application token"
-    // "Unable to add window -- token null is not for an application"
-    // I think I need to get an "Activity" to run it on somehow?
-
-    new Handler (Looper.getMainLooper()).post (new Runnable() {
-        public void run() {
-          AlertDialog alert = b.create();
-          alert.setTitle (this.getClass().getSimpleName() + " crashed");
-          alert.setIcon(android.R.drawable.ic_dialog_alert);
-          alert.show();
-        }
-      });
-
-    return true;
-  }
-
-
-  @Override
-  public void onAttachedToWindow() {
-    super.onAttachedToWindow();
-
-    setInteractive (true);
-    setFullscreen (true);
-    saveScreenshot();
-
-    glview = new GLSurfaceView (this);
-    renderer =
-      new XScreenSaverRenderer (XScreenSaverRenderer.saverNameOf (this),
-                                getApplicationContext(), screenshot,
-                                this, glview);
-    setContentView (glview);
-
-    detector = new GestureDetector (this, this);
-  }
-
-  public void onDreamingStarted() {
-    super.onDreamingStarted();
-  }
-
-  public void onDreamingStopped() {
-    super.onDreamingStopped();
-    glview.onPause();
-  }
-
-  public void onDetachedFromWindow() {
-    super.onDetachedFromWindow();
-    glview.onPause();
-  }
-
-
-  // At startup, before we have blanked the screen, save a screenshot
-  // for later use by the hacks.
-  //
-  private void saveScreenshot() {
-    View view = getWindow().getDecorView().getRootView();
-    if (view == null) {
-      LOG ("unable to get root view for screenshot");
-    } else {
-
-      // This doesn't work:
-  /*
-      boolean was = view.isDrawingCacheEnabled();
-      if (!was) view.setDrawingCacheEnabled (true);
-      view.buildDrawingCache();
-      screenshot = view.getDrawingCache();
-      if (!was) view.setDrawingCacheEnabled (false);
-      if (screenshot == null) {
-        LOG ("unable to get screenshot bitmap from %s", view.toString());
-      } else {
-        screenshot = Bitmap.createBitmap (screenshot);
-      }
-   */
-
-      // This doesn't work either: width and height are both -1...
-
-      int w = view.getLayoutParams().width;
-      int h = view.getLayoutParams().height;
-      if (w <= 0 || h <= 0) {
-        LOG ("unable to get root view for screenshot");
-      } else {
-        screenshot = Bitmap.createBitmap (w, h, Bitmap.Config.ARGB_8888);
-        Canvas c = new Canvas (screenshot);
-        view.layout (0, 0, w, h);
-        view.draw (c);
-      }
-    }
-  }
-
-
-
-  /* We distinguish between taps and drags.
-
-     - Drags/pans (down, motion, up) are sent to the saver to handle.
-     - Single-taps exit the saver.
-     - Long-press single-taps are sent to the saver as ButtonPress/Release;
-     - Double-taps are sent to the saver as a "Space" keypress.
-
-     #### TODO:
-     - Swipes (really, two-finger drags/pans) send Up/Down/Left/RightArrow.
-   */
-
-  @Override
-  public boolean onSingleTapConfirmed (MotionEvent event) {
-    this.finish();  // Exit the Daydream
-    return true;
-  }
-
-  @Override
-  public boolean onDoubleTap (MotionEvent event) {
-    renderer.sendKeyEvent (new KeyEvent (KeyEvent.ACTION_DOWN,
-                                         KeyEvent.KEYCODE_SPACE));
-    return true;
-  }
-
-  @Override
-  public void onLongPress (MotionEvent event) {
-    if (! button_down_p) {
-      int x = (int) event.getX (event.getPointerId (0));
-      int y = (int) event.getY (event.getPointerId (0));
-      renderer.sendButtonEvent (x, y, true);
-      renderer.sendButtonEvent (x, y, false);
-    }
-  }
-
-  @Override
-  public void onShowPress (MotionEvent event) {
-    if (! button_down_p) {
-      button_down_p = true;
-      int x = (int) event.getX (event.getPointerId (0));
-      int y = (int) event.getY (event.getPointerId (0));
-      renderer.sendButtonEvent (x, y, true);
-    }
-  }
-
-  @Override
-  public boolean onScroll (MotionEvent e1, MotionEvent e2, 
-                           float distanceX, float distanceY) {
-    if (button_down_p)
-      renderer.sendMotionEvent ((int) e2.getX (e2.getPointerId (0)),
-                                (int) e2.getY (e2.getPointerId (0)));
-    return true;
-  }
-
-  // If you drag too fast, you get a single onFling event instead of a
-  // succession of onScroll events.  I can't figure out how to disable it.
-  @Override
-  public boolean onFling (MotionEvent e1, MotionEvent e2, 
-                          float velocityX, float velocityY) {
-    return false;
-  }
-
-  public boolean dragEnded (MotionEvent event) {
-    if (button_down_p) {
-      int x = (int) event.getX (event.getPointerId (0));
-      int y = (int) event.getY (event.getPointerId (0));
-      renderer.sendButtonEvent (x, y, false);
-      button_down_p = false;
-    }
-    return true;
-  }
-
-  @Override
-  public boolean onDown (MotionEvent event) {
-    return false;
-  }
-
-  @Override
-  public boolean onSingleTapUp (MotionEvent event) {
-    return false;
-  }
-
-  @Override
-  public boolean onDoubleTapEvent (MotionEvent event) {
-    return false;
-  }
-
-  @Override 
-  public boolean dispatchTouchEvent (MotionEvent event) {
-    detector.onTouchEvent (event);
-    if (event.getAction() == MotionEvent.ACTION_UP)
-      dragEnded (event);
-    return super.dispatchTouchEvent (event);
-  }
-
-  @Override
-  public boolean dispatchKeyEvent (KeyEvent event) {
-
-    // In the emulator, this doesn't receive keyboard arrow keys, PgUp, etc.
-    // Some other keys like "Home" are interpreted before we get here, and
-    // function keys do weird shit.
-
-    super.dispatchKeyEvent (event);
-    renderer.sendKeyEvent (event);
-    return true;
-  }
-
-  // Dunno what dispatchKeyShortcutEvent does, but apparently nothing useful.
-
-}
diff --git a/android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverRenderer.java b/android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverRenderer.java
deleted file mode 100644 (file)
index 5ae5a5a..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * xscreensaver, Copyright (c) 2016 Jamie Zawinski <jwz@jwz.org>
- * and Dennis Sheil <dennis@panaceasupplies.com>
- *
- * 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.
- */
-
-package org.jwz.xscreensaver;
-
-import java.util.Map;
-import java.lang.RuntimeException;
-import android.view.Display;
-import android.view.WindowManager;
-import android.view.Surface;
-import android.view.KeyEvent;
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.opengl.GLSurfaceView;
-import java.util.Timer;
-import java.util.TimerTask;
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.opengles.GL10;
-import org.jwz.xscreensaver.jwxyz;
-import android.os.Message;
-import android.os.Handler;
-import android.util.Log;
-
-
-public class XScreenSaverRenderer implements GLSurfaceView.Renderer {
-
-  boolean initTried = false;
-  jwxyz jwxyz_obj = null;
-
-  String hack;
-  Handler.Callback abort_callback;
-
-  Context app;
-  Bitmap screenshot;
-
-  GLSurfaceView glview;
-
-  class RenderTask extends TimerTask {
-    public void run() {
-      glview.requestRender();
-    }
-  };
-
-  Timer timer = new Timer();
-
-  private void LOG (String fmt, Object... args) {
-    Log.d ("xscreensaver",
-           this.getClass().getSimpleName() + ": " +
-           String.format (fmt, args));
-  }
-
-  private void except(Exception e) {
-    jwxyz_obj = null;
-    Message m = Message.obtain (null, 0, (Object) e);
-    abort_callback.handleMessage (m);
-  }
-
-  public XScreenSaverRenderer (String hack,
-                               Context app,
-                               Bitmap screenshot,
-                               Handler.Callback abort_callback,
-                               GLSurfaceView glview) {
-    super();
-    this.hack   = hack;
-    this.app    = app;
-    this.screenshot = screenshot;
-    this.abort_callback = abort_callback;
-    this.glview = glview;
-    LOG ("init %s", hack);
-
-    this.glview.setEGLConfigChooser (8, 8, 8, 8, 16, 0);
-    this.glview.setRenderer (this);
-    this.glview.setRenderMode (GLSurfaceView.RENDERMODE_WHEN_DIRTY);
-  }
-
-  static public String saverNameOf (Object obj) {
-    // Extract the saver name from e.g. "gen.Daydream$BouncingCow"
-    String name = obj.getClass().getSimpleName();
-    int index = name.lastIndexOf('$');
-    if (index != -1) {
-      index++;
-      name = name.substring (index, name.length() - index);
-    }
-    return name.toLowerCase();
-  }
-
-  public void onDrawFrame (GL10 gl) {
-    try {
-      if (jwxyz_obj != null) {
-        long delay = jwxyz_obj.nativeRender();
-        // java.util.Timer doesn't seem to like to re-use TimerTasks, so
-        // there's a slow object churn here: one TimerTask per frame.
-        timer.schedule(new RenderTask(), delay / 1000);
-      }
-    } catch (RuntimeException e) {
-      except (e);
-    }
-  }
-
-  public void onSurfaceChanged(GL10 gl, int w, int h) {
-    try {
-      if (jwxyz_obj == null)
-        jwxyz_obj = new jwxyz (hack, app, screenshot, w, h);
-
-      double r = 0;
-
-      Display d = glview.getDisplay();
-
-      if (d != null) {
-        switch (d.getRotation()) {
-        case Surface.ROTATION_90:  r = 90;  break;
-        case Surface.ROTATION_180: r = 180; break;
-        case Surface.ROTATION_270: r = 270; break;
-        }
-      }
-
-      jwxyz_obj.nativeResize (w, h, r);
-
-      glview.requestRender();
-
-    } catch (RuntimeException e) {
-      except (e);
-    }
-  }
-
-  public void onSurfaceCreated (GL10 gl, EGLConfig config) {
-    try {
-      LOG ("onSurfaceCreated %s / %s / %s", 
-           gl.glGetString (GL10.GL_VENDOR),
-           gl.glGetString (GL10.GL_RENDERER),
-           gl.glGetString (GL10.GL_VERSION));
-
-      if (!initTried) {
-        initTried = true;
-      } else {
-        if (jwxyz_obj != null) {
-          jwxyz_obj.nativeDone();
-          jwxyz_obj = null;
-        }
-      }
-    } catch (RuntimeException e) {
-      except (e);
-    }
-  }
-
-  public void release() {
-    try {
-      if (jwxyz_obj != null) {
-        jwxyz_obj.nativeDone();
-        jwxyz_obj = null;
-      }
-    } catch (RuntimeException e) {
-      except (e);
-    }
-  }
-
-  public void sendButtonEvent (int x, int y, boolean down) {
-    try {
-      jwxyz_obj.sendButtonEvent (x, y, down);
-    } catch (RuntimeException e) {
-      except (e);
-    }
-  }
-
-  public void sendMotionEvent (int x, int y) {
-    try {
-      jwxyz_obj.sendMotionEvent (x, y);
-    } catch (RuntimeException e) {
-      except (e);
-    }
-  }
-
-  public void sendKeyEvent (KeyEvent event) {
-    try {
-      jwxyz_obj.sendKeyEvent (event);
-    } catch (RuntimeException e) {
-      except (e);
-    }
-  }
-
-
-  static
-  {
-    System.loadLibrary ("xscreensaver");
-  }
-}
diff --git a/android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverSettings.java b/android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverSettings.java
deleted file mode 100644 (file)
index ce91bc1..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * xscreensaver, Copyright (c) 2016 Jamie Zawinski <jwz@jwz.org>
- * and Dennis Sheil <dennis@panaceasupplies.com>
- *
- * 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.
- *
- * The superclass of every saver's preferences panel.
- *
- * The only reason the subclasses of this class exist is so that we know
- * which "_settings.xml" to read -- we extract the base name from self's
- * class.
- *
- * project/xscreensaver/res/xml/SAVER_dream.xml refers to it as
- * android:settingsActivity="SAVER_Settings".  If there was some way
- * to pass an argument from the XML into here, or to otherwise detect
- * which Dream was instantiating this Settings, we wouldn't need those
- * hundreds of Settings subclasses.
- */
-
-package org.jwz.xscreensaver;
-
-import android.content.SharedPreferences;
-import android.os.Bundle;
-
-import android.content.SharedPreferences;
-import android.preference.PreferenceActivity;
-import android.preference.Preference;
-import android.preference.ListPreference;
-import android.preference.EditTextPreference;
-import android.preference.CheckBoxPreference;
-import org.jwz.xscreensaver.SliderPreference;
-
-import org.jwz.xscreensaver.R;
-import java.util.Map;
-import java.lang.reflect.Field;
-
-public abstract class XScreenSaverSettings extends PreferenceActivity
-  implements SharedPreferences.OnSharedPreferenceChangeListener {
-
-  @Override
-  protected void onCreate (Bundle icicle) {
-    super.onCreate (icicle);
-
-    // Extract the saver name from e.g. "BouncingCowSettings"
-    String name = this.getClass().getSimpleName();
-    String tail = "Settings";
-    if (name.endsWith(tail))
-      name = name.substring (0, name.length() - tail.length());
-    name = name.toLowerCase();
-
-    // #### All of these have been deprecated:
-    //   getPreferenceManager()
-    //   addPreferencesFromResource(int)
-    //   findPreference(CharSequence)
-
-    getPreferenceManager().setSharedPreferencesName (name);
-
-    // read R.xml.SAVER_settings dynamically
-    int res = -1;
-    String pref_class = name + "_settings";
-    try { res = R.xml.class.getDeclaredField(pref_class).getInt (null); }
-    catch (Exception e) { }
-    if (res != -1)
-      addPreferencesFromResource (res);
-
-    final int res_final = res;
-
-    SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
-    prefs.registerOnSharedPreferenceChangeListener (this);
-    updateAllPrefsSummaries (prefs);
-
-    // Find the "Reset to defaults" button and install a click handler on it.
-    //
-    Preference reset = findPreference (name + "_reset");
-    reset.setOnPreferenceClickListener(
-      new Preference.OnPreferenceClickListener() {
-        @Override
-        public boolean onPreferenceClick(Preference preference) {
-
-          SharedPreferences prefs =
-            getPreferenceManager().getSharedPreferences();
-
-          // Wipe everything from the preferences hash, then reload defaults.
-          prefs.edit().clear().commit();
-          getPreferenceScreen().removeAll();
-          addPreferencesFromResource (res_final);
-
-          // I guess we need to re-get this after the removeAll?
-          prefs = getPreferenceManager().getSharedPreferences();
-
-          // But now we need to iterate over every Preference widget and
-          // push the new value down into it.  If you think this all looks
-          // ridiculously non-object-oriented and completely insane, that's
-          // because it is.
-
-          Map <String, ?> keys = prefs.getAll();
-          for (Map.Entry <String, ?> entry : keys.entrySet()) {
-            String key = entry.getKey();
-            String val = String.valueOf (entry.getValue());
-
-            Preference pref = findPreference (key);
-            if (pref instanceof ListPreference) {
-              ((ListPreference) pref).setValue (prefs.getString (key, ""));
-            } else if (pref instanceof SliderPreference) {
-              ((SliderPreference) pref).setValue (prefs.getFloat (key, 0));
-            } else if (pref instanceof EditTextPreference) {
-              ((EditTextPreference) pref).setText (prefs.getString (key, ""));
-            } else if (pref instanceof CheckBoxPreference) {
-              ((CheckBoxPreference) pref).setChecked (
-                prefs.getBoolean (key,false));
-            }
-
-            updatePrefsSummary (prefs, pref);
-          }
-          return true;
-        }
-      });
-  }
-
-  @Override
-  protected void onResume() {
-    super.onResume();
-    SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
-    prefs.registerOnSharedPreferenceChangeListener (this);
-    updateAllPrefsSummaries(prefs);
-  }
-
-  @Override
-  protected void onPause() {
-    getPreferenceManager().getSharedPreferences().
-      unregisterOnSharedPreferenceChangeListener(this);
-    super.onPause();
-  }
-
-  @Override
-  protected void onDestroy() {
-    getPreferenceManager().getSharedPreferences().
-      unregisterOnSharedPreferenceChangeListener(this);
-    super.onDestroy();
-  }
-
-  public void onSharedPreferenceChanged (SharedPreferences sharedPreferences,
-                                         String key) {
-    updatePrefsSummary(sharedPreferences, findPreference(key));
-  }
-
-  protected void updatePrefsSummary(SharedPreferences sharedPreferences,
-                                    Preference pref) {
-    if (pref == null)
-      return;
-
-    if (pref instanceof ListPreference) {
-      pref.setTitle (((ListPreference) pref).getEntry());
-    } else if (pref instanceof SliderPreference) {
-      float v = ((SliderPreference) pref).getValue();
-      int i = (int) Math.floor (v);
-      if (v == i)
-        pref.setSummary (String.valueOf (i));
-      else
-        pref.setSummary (String.valueOf (v));
-    } else if (pref instanceof EditTextPreference) {
-      pref.setSummary (((EditTextPreference) pref).getText());
-    }
-  }
-
-  protected void updateAllPrefsSummaries(SharedPreferences prefs) {
-
-    Map <String, ?> keys = prefs.getAll();
-    for (Map.Entry <String, ?> entry : keys.entrySet()) {
-      updatePrefsSummary (prefs, findPreference (entry.getKey()));
-    }
-  }
-}
diff --git a/android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverWallpaper.java b/android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverWallpaper.java
deleted file mode 100644 (file)
index b03c904..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * xscreensaver, Copyright (c) 2016 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.
- *
- * The superclass of every saver's Wallpaper.
- *
- * Each Wallpaper needs a distinct subclass in order to show up in the list.
- * We know which saver we are running by the subclass name; we know which
- * API to use by how the subclass calls super().
- */
-
-package org.jwz.xscreensaver;
-
-import android.opengl.GLSurfaceView;
-import android.os.Handler;
-import android.os.Message;
-import android.service.wallpaper.WallpaperService;
-import android.view.GestureDetector;
-import android.view.SurfaceHolder;
-import android.util.Log;
-import java.lang.RuntimeException;
-import java.lang.Thread;
-
-public class XScreenSaverWallpaper extends WallpaperService
-/*implements GestureDetector.OnGestureListener,
-             GestureDetector.OnDoubleTapListener, */ {
-
-  /* TODO: Input! */
-
-  @Override
-  public Engine onCreateEngine() {
-    return new XScreenSaverGLEngine();
-  }
-
-  class XScreenSaverGLEngine extends Engine
-  implements Handler.Callback {
-
-    GLSurfaceView glview;
-
-    @Override
-    public void onSurfaceCreated (SurfaceHolder holder) {
-      /* Old GLWallpaperService warns against working with a GLSurfaceView
-         in the Engine constructor.
-       */
-      glview = new GLSurfaceView (XScreenSaverWallpaper.this) {
-        @Override
-        public SurfaceHolder getHolder() {
-          return XScreenSaverGLEngine.this.getSurfaceHolder();
-        }
-      };
-
-      new XScreenSaverRenderer (
-        XScreenSaverRenderer.saverNameOf (XScreenSaverWallpaper.this),
-        XScreenSaverWallpaper.this, null, this, glview);
-      // super.onSurfaceCreated(holder);
-      glview.surfaceCreated(holder);
-      // glview.requestRender();
-    }
-
-    @Override
-    public void onVisibilityChanged(final boolean visible) {
-      if (glview != null) {
-        if (visible)
-          glview.onResume();
-        else
-          glview.onPause();
-      }
-    }
-
-    /* These aren't necessary...maybe? */
-/*
-    @Override
-    public void onSurfaceChanged (SurfaceHolder holder, int format,
-                                  int width, int height) {
-      if (glview)
-        glview.surfaceChanged(holder, format, width, height);
-      // super.onSurfaceChanged(holder, format, width, height);
-    }
-
-    @Override
-    public void onSurfaceDestroyed (SurfaceHolder holder) {
-      glview.surfaceDestroyed(holder);
-    }
-*/
-
-    @Override
-    public boolean handleMessage (Message msg) {
-      Log.d ("xscreensaver", msg.obj.toString());
-      throw (RuntimeException)msg.obj;
-      // return false;
-    }
-  }
-}
diff --git a/android/project/xscreensaver/src/org/jwz/xscreensaver/jwxyz.java b/android/project/xscreensaver/src/org/jwz/xscreensaver/jwxyz.java
deleted file mode 100644 (file)
index 95952e0..0000000
+++ /dev/null
@@ -1,779 +0,0 @@
-/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * xscreensaver, Copyright (c) 2016 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.
- *
- * This class is how the C implementation of jwxyz calls back into Java
- * to do things that OpenGL does not have access to without Java-based APIs.
- * It is the Java companion to jwxyz-android.c and screenhack-android.c.
- */
-
-package org.jwz.xscreensaver;
-
-import java.util.Map;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.ArrayList;
-import java.util.Random;
-import android.view.KeyEvent;
-import android.content.SharedPreferences;
-import android.content.Context;
-import android.content.ContentResolver;
-import android.content.res.AssetManager;
-import android.graphics.Typeface;
-import android.graphics.Rect;
-import android.graphics.Paint;
-import android.graphics.Paint.FontMetrics;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Matrix;
-import android.net.Uri;
-import java.net.URL;
-import java.nio.ByteBuffer;
-import java.io.File;
-import java.io.InputStream;
-import java.io.FileOutputStream;
-import java.lang.Runnable;
-import java.lang.Thread;
-import android.database.Cursor;
-import android.provider.MediaStore;
-import android.provider.MediaStore.MediaColumns;
-import android.media.ExifInterface;
-import org.jwz.xscreensaver.TTFAnalyzer;
-import android.util.Log;
-
-public class jwxyz {
-
-  private void LOG (String fmt, Object... args) {
-    Log.d ("xscreensaver",
-           this.getClass().getSimpleName() + ": " +
-           String.format (fmt, args));
-  }
-
-  private long nativeRunningHackPtr;
-
-  String hack;
-  Context app;
-  Bitmap screenshot;
-
-  public final static int STYLE_BOLD      = 1;
-  public final static int STYLE_ITALIC    = 2;
-  public final static int STYLE_MONOSPACE = 4;
-
-  public final static int FONT_FAMILY = 0;
-  public final static int FONT_FACE   = 1;
-  public final static int FONT_RANDOM = 2;
-
-  SharedPreferences prefs;
-  Hashtable<String, String> defaults = new Hashtable<String, String>();
-
-
-  // Maps font names to either: String (system font) or Typeface (bundled).
-  private Hashtable<String, Object> all_fonts =
-    new Hashtable<String, Object>();
-
-
-  // These are defined in jwxyz-android.c:
-  //
-  private native void nativeInit (String hack,
-                                  Hashtable<String,String> defaults,
-                                  int w, int h);
-  public native void nativeResize (int w, int h, double rot);
-  public native long nativeRender ();
-  public native void nativeDone ();
-  public native void sendButtonEvent (int x, int y, boolean down);
-  public native void sendMotionEvent (int x, int y);
-  public native void sendKeyEvent (boolean down_p, int code, int mods);
-
-  // Constructor
-  public jwxyz (String hack, Context app, Bitmap screenshot, int w, int h) {
-
-    this.hack = hack;
-    this.app  = app;
-    this.screenshot = screenshot;
-
-    // nativeInit populates 'defaults' with the default values for keys
-    // that are not overridden by SharedPreferences.
-
-    prefs = app.getSharedPreferences (hack, 0);
-    scanSystemFonts();
-    nativeInit (hack, defaults, w, h);
-  }
-
-/*  TODO: Can't do this yet; nativeDone requires the OpenGL context to be set.
-  protected void finalize() {
-    if (nativeRunningHackPtr != 0) {
-      nativeDone();
-    }
-  } */
-
-
-  public String getStringResource (String name) {
-
-    name = hack + "_" + name;
-
-    if (prefs.contains(name)) {
-
-      // SharedPreferences is very picky that you request the exact type that
-      // was stored: if it is a float and you ask for a string, you get an
-      // exception instead of the float converted to a string.
-
-      String s = null;
-      try { return prefs.getString (name, "");
-      } catch (Exception e) { }
-
-      try { return Float.toString (prefs.getFloat (name, 0));
-      } catch (Exception e) { }
-
-      try { return Long.toString (prefs.getLong (name, 0));
-      } catch (Exception e) { }
-
-      try { return Integer.toString (prefs.getInt (name, 0));
-      } catch (Exception e) { }
-
-      try { return (prefs.getBoolean (name, false) ? "true" : "false");
-      } catch (Exception e) { }
-    }
-
-    // If we got to here, it's not in there, so return the default.
-    return defaults.get (name);
-  }
-
-
-  private String mungeFontName (String name) {
-    // Roboto-ThinItalic => RobotoThin
-    // AndroidCock Regular => AndroidClock
-    String tails[] = { "Bold", "Italic", "Oblique", "Regular" };
-    for (String tail : tails) {
-      String pres[] = { " ", "-", "_", "" };
-      for (String pre : pres) {
-        int i = name.indexOf(pre + tail);
-        if (i > 0) name = name.substring (0, i);
-      }
-    }
-    return name;
-  }
-
-
-  private void scanSystemFonts() {
-
-    // First parse the system font directories for the global fonts.
-
-    String[] fontdirs = { "/system/fonts", "/system/font", "/data/fonts" };
-    TTFAnalyzer analyzer = new TTFAnalyzer();
-    for (String fontdir : fontdirs) {
-      File dir = new File(fontdir);
-      if (!dir.exists())
-        continue;
-      File[] files = dir.listFiles();
-      if (files == null)
-        continue;
-
-      for (File file : files) {
-        String name = analyzer.getTtfFontName (file.getAbsolutePath());
-        if (name == null) {
-          // LOG ("unparsable system font: %s", file);
-        } else {
-          name = mungeFontName (name);
-          if (! all_fonts.contains (name)) {
-            // LOG ("system font \"%s\" %s", name, file);
-            all_fonts.put (name, name);
-          }
-        }
-      }
-    }
-
-    // Now parse our assets, for our bundled fonts.
-
-    AssetManager am = app.getAssets();
-    String dir = "fonts";
-    String[] files = null;
-    try { files = am.list(dir); }
-    catch (Exception e) { LOG("listing assets: %s", e.toString()); }
-
-    for (String fn : files) {
-      String fn2 = dir + "/" + fn;
-      Typeface t = Typeface.createFromAsset (am, fn2);
-
-      File tmpfile = null;
-      try {
-        tmpfile = new File(app.getCacheDir(), fn);
-        if (tmpfile.createNewFile() == false) {
-          tmpfile.delete();
-          tmpfile.createNewFile();
-        }
-
-        InputStream in = am.open (fn2);
-        FileOutputStream out = new FileOutputStream (tmpfile);
-        byte[] buffer = new byte[1024 * 512];
-        while (in.read(buffer, 0, 1024 * 512) != -1) {
-          out.write(buffer);
-        }
-        out.close();
-        in.close();
-
-        String name = analyzer.getTtfFontName (tmpfile.getAbsolutePath());
-        tmpfile.delete();
-
-        name = mungeFontName (name);
-        all_fonts.put (name, t);
-        // LOG ("asset font \"%s\" %s", name, fn);
-      } catch (Exception e) {
-        if (tmpfile != null) tmpfile.delete();
-        LOG ("error: %s", e.toString());
-      }
-    }
-  }
-
-
-  // Parses family names from X Logical Font Descriptions, including a few
-  // standard X font names that aren't handled by try_xlfd_font().
-  // Returns [ String name, Typeface ]
-  private Object[] parseXLFD (int mask, int traits,
-                              String name, int name_type) {
-    boolean fixed  = false;
-    boolean serif  = false;
-
-    int style_jwxyz = mask & traits;
-
-    if (name_type != FONT_RANDOM) {
-      if ((style_jwxyz & STYLE_BOLD) != 0 ||
-          name.equals("fixed") ||
-          name.equals("courier") ||
-          name.equals("console") ||
-          name.equals("lucidatypewriter") ||
-          name.equals("monospace")) {
-        fixed = true;
-      } else if (name.equals("times") ||
-                 name.equals("georgia") ||
-                 name.equals("serif")) {
-        serif = true;
-      } else if (name.equals("serif-monospace")) {
-        fixed = true;
-        serif = true;
-      }
-    } else {
-      Random r = new Random();
-      serif = r.nextBoolean();      // Not much to randomize here...
-      fixed = (r.nextInt(8) == 0);
-    }
-
-    name = (fixed
-            ? (serif ? "serif-monospace" : "monospace")
-            : (serif ? "serif" : "sans-serif"));
-
-    int style_android = 0;
-    if ((style_jwxyz & STYLE_BOLD) != 0)
-      style_android |= Typeface.BOLD;
-    if ((style_jwxyz & STYLE_ITALIC) != 0)
-      style_android |= Typeface.ITALIC;
-
-    return new Object[] { name, Typeface.create(name, style_android) };
-  }
-
-
-  // Parses "Native Font Name One 12, Native Font Name Two 14".
-  // Returns [ String name, Typeface ]
-  private Object[] parseNativeFont (String name) {
-    Object font2 = all_fonts.get (name);
-    if (font2 instanceof String)
-      font2 = Typeface.create (name, Typeface.NORMAL);
-    return new Object[] { name, (Typeface)font2 };
-  }
-
-
-  // Returns [ Paint paint, String family_name, Float ascent, Float descent ]
-  public Object[] loadFont(int mask, int traits, String name, int name_type,
-                           float size) {
-    Object pair[];
-
-    if (name_type != FONT_RANDOM && name.equals("")) return null;
-
-    if (name_type == FONT_FACE) {
-      pair = parseNativeFont (name);
-    } else {
-      pair = parseXLFD (mask, traits, name, name_type);
-    }
-
-    String name2  = (String)   pair[0];
-    Typeface font = (Typeface) pair[1];
-
-    size *= 2;
-
-    String suffix = (font.isBold() && font.isItalic() ? " bold italic" :
-                     font.isBold()   ? " bold"   :
-                     font.isItalic() ? " italic" :
-                     "");
-    Paint paint = new Paint();
-    paint.setTypeface (font);
-    paint.setTextSize (size);
-    paint.setColor (Color.argb (0xFF, 0xFF, 0xFF, 0xFF));
-
-    LOG ("load font \"%s\" = \"%s %.1f\"", name, name2 + suffix, size);
-
-    FontMetrics fm = paint.getFontMetrics();
-    return new Object[] { paint, name2, -fm.ascent, fm.descent };
-  }
-
-
-  /* Returns a byte[] array containing XCharStruct with an optional
-     bitmap appended to it.
-     lbearing, rbearing, width, ascent, descent: 2 bytes each.
-     Followed by a WxH pixmap, 32 bits per pixel.
-   */
-  public ByteBuffer renderText (Paint paint, String text, boolean render_p) {
-
-    if (paint == null) {
-      LOG ("no font");
-      return null;
-    }
-
-    /* Font metric terminology, as used by X11:
-
-       "lbearing" is the distance from the logical origin to the leftmost
-       pixel.  If a character's ink extends to the left of the origin, it is
-       negative.
-
-       "rbearing" is the distance from the logical origin to the rightmost
-       pixel.
-
-       "descent" is the distance from the logical origin to the bottommost
-       pixel.  For characters with descenders, it is positive.  For
-       superscripts, it is negative.
-
-       "ascent" is the distance from the logical origin to the topmost pixel.
-       It is the number of pixels above the baseline.
-
-       "width" is the distance from the logical origin to the position where
-       the logical origin of the next character should be placed.
-
-       If "rbearing" is greater than "width", then this character overlaps the
-       following character.  If smaller, then there is trailing blank space.
-
-       The bbox coordinates returned by getTextBounds grow down and right:
-       for a character with ink both above and below the baseline, top is
-       negative and bottom is positive.
-     */
-    FontMetrics fm = paint.getFontMetrics();
-    Rect bbox = new Rect();
-    paint.getTextBounds (text, 0, text.length(), bbox);
-
-    /* The bbox returned by getTextBounds measures from the logical origin
-       with right and down being positive.  This means most characters have
-       a negative top, and characters with descenders have a positive bottom.
-     */
-    int lbearing  =  bbox.left;
-    int rbearing  =  bbox.right;
-    int ascent    = -bbox.top;
-    int descent   =  bbox.bottom;
-    int width     = (int) paint.measureText (text);
-
-    int w = rbearing - lbearing;
-    int h = ascent + descent;
-    int size = 5 * 2 + (render_p ? w * h * 4 : 0);
-
-    ByteBuffer bits = ByteBuffer.allocateDirect (size);
-
-    bits.put ((byte) ((lbearing >> 8) & 0xFF));
-    bits.put ((byte) ( lbearing       & 0xFF));
-    bits.put ((byte) ((rbearing >> 8) & 0xFF));
-    bits.put ((byte) ( rbearing       & 0xFF));
-    bits.put ((byte) ((width    >> 8) & 0xFF));
-    bits.put ((byte) ( width          & 0xFF));
-    bits.put ((byte) ((ascent   >> 8) & 0xFF));
-    bits.put ((byte) ( ascent         & 0xFF));
-    bits.put ((byte) ((descent  >> 8) & 0xFF));
-    bits.put ((byte) ( descent        & 0xFF));
-
-    if (render_p && w > 0 && h > 0) {
-      Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
-      Canvas canvas = new Canvas (bitmap);
-      canvas.drawText (text, -lbearing, ascent, paint);
-      bitmap.copyPixelsToBuffer (bits);
-      bitmap.recycle();
-    }
-
-    return bits;
-  }
-
-
-  /* Returns the contents of the URL.
-     Loads the URL in a background thread: if the URL has not yet loaded,
-     this will return null.  Once the URL has completely loaded, the full
-     contents will be returned.  Calling this again after that starts the
-     URL loading again.
-   */
-  private String loading_url = null;
-  private ByteBuffer loaded_url_body = null;
-
-  public synchronized ByteBuffer loadURL (String url) {
-
-    if (loaded_url_body != null) {                     // Thread finished
-
-      // LOG ("textclient finished %s", loading_url);
-
-      ByteBuffer bb = loaded_url_body;
-      loading_url = null;
-      loaded_url_body = null;
-      return bb;
-
-    } else if (loading_url != null) {                  // Waiting on thread
-      // LOG ("textclient waiting...");
-      return null;
-
-    } else {                                           // Launch thread
-
-      loading_url = url;
-      LOG ("textclient launching %s...", url);
-
-      new Thread (new Runnable() {
-          public void run() {
-            int size0 = 10240;
-            int size = size0;
-            int count = 0;
-            ByteBuffer body = ByteBuffer.allocateDirect (size);
-
-            try {
-              URL u = new URL (loading_url);
-              // LOG ("textclient thread loading: %s", u.toString());
-              InputStream s = u.openStream();
-              byte buf[] = new byte[10240];
-              while (true) {
-                int n = s.read (buf);
-                if (n == -1) break;
-                // LOG ("textclient thread read %d", n);
-                if (count + n + 1 >= size) {
-                  int size2 = (int) (size * 1.2 + size0);
-                  // LOG ("textclient thread expand %d -> %d", size, size2);
-                  ByteBuffer body2 = ByteBuffer.allocateDirect (size2);
-                  body.rewind();
-                  body2.put (body);
-                  body2.position (count);
-                  body = body2;
-                  size = size2;
-                }
-                body.put (buf, 0, n);
-                count += n;
-              }
-            } catch (Exception e) {
-              LOG ("load URL error: %s", e.toString());
-              body.clear();
-              body.put (e.toString().getBytes());
-              body.put ((byte) 0);
-            }
-
-            // LOG ("textclient thread finished %s (%d)", loading_url, size);
-            loaded_url_body = body;
-          }
-        }).start();
-
-      return null;
-    }
-  }
-
-
-  private ByteBuffer convertBitmap (String name, Bitmap bitmap,
-                                    int target_width, int target_height,
-                                    ExifInterface exif,
-                                    boolean rotate_p) {
-    if (bitmap == null) return null;
-
-    try {
-
-      int width  = bitmap.getWidth();
-      int height = bitmap.getHeight();
-
-      LOG ("read image %s: %d x %d", name, width, height);
-
-      // First rotate the image as per EXIF.
-
-      if (exif != null) {
-        int deg = 0;
-        switch (exif.getAttributeInt (ExifInterface.TAG_ORIENTATION,
-                                      ExifInterface.ORIENTATION_NORMAL)) {
-        case ExifInterface.ORIENTATION_ROTATE_90:  deg = 90;  break;
-        case ExifInterface.ORIENTATION_ROTATE_180: deg = 180; break;
-        case ExifInterface.ORIENTATION_ROTATE_270: deg = 270; break;
-        }
-        if (deg != 0) {
-          LOG ("%s: EXIF rotate %d", name, deg);
-          Matrix matrix = new Matrix();
-          matrix.preRotate (deg);
-          bitmap = Bitmap.createBitmap (bitmap, 0, 0, width, height,
-                                        matrix, true);
-          width  = bitmap.getWidth();
-          height = bitmap.getHeight();
-        }
-      }
-
-      // If the caller requested that we rotate the image to best fit the
-      // screen, rotate it again.  (Could combine this with the above and
-      // avoid copying the image again, but I'm lazy.)
-
-      if (rotate_p &&
-          (width > height) != (target_width > target_height)) {
-        LOG ("%s: rotated to fit screen", name);
-        Matrix matrix = new Matrix();
-        matrix.preRotate (90);
-        bitmap = Bitmap.createBitmap (bitmap, 0, 0, width, height,
-                                      matrix, true);
-        width  = bitmap.getWidth();
-        height = bitmap.getHeight();
-      }
-
-      // Resize the image to be not larger than the screen, potentially
-      // copying it for the third time.
-      // Actually, always scale it, scaling up if necessary.
-
-//    if (width > target_width || height > target_height)
-      {
-        float r1 = target_width  / (float) width;
-        float r2 = target_height / (float) height;
-        float r = (r1 > r2 ? r2 : r1);
-        LOG ("%s: resize %.1f: %d x %d => %d x %d", name,
-             r, width, height, (int) (width * r), (int) (height * r));
-        width  = (int) (width * r);
-        height = (int) (height * r);
-        bitmap = Bitmap.createScaledBitmap (bitmap, width, height, true);
-        width  = bitmap.getWidth();
-        height = bitmap.getHeight();
-      }
-
-      // Now convert it to a ByteBuffer in the form expected by the C caller.
-
-      byte[] nameb = name.getBytes("UTF-8");
-      int size     = bitmap.getByteCount() + 4 + nameb.length + 1;
-
-      ByteBuffer bits = ByteBuffer.allocateDirect (size);
-
-      bits.put ((byte) ((width  >> 8) & 0xFF));
-      bits.put ((byte) ( width        & 0xFF));
-      bits.put ((byte) ((height >> 8) & 0xFF));
-      bits.put ((byte) ( height       & 0xFF));
-      bits.put (nameb);
-      bits.put ((byte) 0);
-
-      // The fourth of five copies.  Good thing these are supercomputers.
-      bitmap.copyPixelsToBuffer (bits);
-
-      return bits;
-
-    } catch (Exception e) {
-      LOG ("image %s unreadable: %s", name, e.toString());
-    }
-
-    return null;
-  }
-
-
-  public ByteBuffer loadRandomImage (int target_width, int target_height,
-                                     boolean rotate_p) {
-
-    int min_size = 480;
-    int max_size = 0x7FFF;
-
-    ArrayList<String> imgs = new ArrayList<String>();
-
-    ContentResolver cr = app.getContentResolver();
-    String[] cols = { MediaColumns.DATA,
-                      MediaColumns.MIME_TYPE,
-                      MediaColumns.WIDTH,
-                      MediaColumns.HEIGHT };
-    Uri uris[] = {
-      android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI,
-      android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI };
-
-    for (int i = 0; i < uris.length; i++) {
-      Cursor cursor = cr.query (uris[i], cols, null, null, null);
-      int j = 0;
-      int path_col   = cursor.getColumnIndexOrThrow (cols[j++]);
-      int type_col   = cursor.getColumnIndexOrThrow (cols[j++]);
-      int width_col  = cursor.getColumnIndexOrThrow (cols[j++]);
-      int height_col = cursor.getColumnIndexOrThrow (cols[j++]);
-      while (cursor.moveToNext()) {
-        String path = cursor.getString(path_col);
-        String type = cursor.getString(type_col);
-        int w = Integer.parseInt (cursor.getString(width_col));
-        int h = Integer.parseInt (cursor.getString(height_col));
-        if (type.startsWith("image/") &&
-            w > min_size && h > min_size &&
-            w < max_size && h < max_size) {
-          imgs.add (path);
-        }
-      }
-      cursor.close();
-    }
-
-    String which = null;
-
-    int count = imgs.size();
-    if (count == 0) {
-      LOG ("no images");
-      return null;
-    }
-
-    int i = new Random().nextInt (count);
-    which = imgs.get (i);
-    LOG ("picked image %d of %d: %s", i, count, which);
-
-    Uri uri = Uri.fromFile (new File (which));
-    String name = uri.getLastPathSegment();
-    Bitmap bitmap = null;
-    ExifInterface exif = null;
-
-    try {
-      bitmap = MediaStore.Images.Media.getBitmap (cr, uri);
-    } catch (Exception e) {
-      LOG ("image %s unloadable: %s", which, e.toString());
-      return null;
-    }
-
-    try {
-      exif = new ExifInterface (uri.getPath());  // If it fails, who cares
-    } catch (Exception e) {
-    }
-
-    ByteBuffer bits = convertBitmap (name, bitmap,
-                                     target_width, target_height,
-                                     exif, rotate_p);
-    bitmap.recycle();
-    return bits;
-  }
-
-
-  public ByteBuffer getScreenshot (int target_width, int target_height,
-                                   boolean rotate_p) {
-    return convertBitmap ("Screenshot", screenshot,
-                          target_width, target_height,
-                          null, rotate_p);
-  }
-
-
-  // Sadly duplicated from jwxyz.h (and thence X.h and keysymdef.h)
-  //
-  private static final int ShiftMask =    (1<<0);
-  private static final int LockMask =     (1<<1);
-  private static final int ControlMask =   (1<<2);
-  private static final int Mod1Mask =     (1<<3);
-  private static final int Mod2Mask =     (1<<4);
-  private static final int Mod3Mask =     (1<<5);
-  private static final int Mod4Mask =     (1<<6);
-  private static final int Mod5Mask =     (1<<7);
-  private static final int Button1Mask =   (1<<8);
-  private static final int Button2Mask =   (1<<9);
-  private static final int Button3Mask =   (1<<10);
-  private static final int Button4Mask =   (1<<11);
-  private static final int Button5Mask =   (1<<12);
-
-  private static final int XK_Shift_L =           0xFFE1;
-  private static final int XK_Shift_R =           0xFFE2;
-  private static final int XK_Control_L =  0xFFE3;
-  private static final int XK_Control_R =  0xFFE4;
-  private static final int XK_Caps_Lock =  0xFFE5;
-  private static final int XK_Shift_Lock = 0xFFE6;
-  private static final int XK_Meta_L =    0xFFE7;
-  private static final int XK_Meta_R =    0xFFE8;
-  private static final int XK_Alt_L =     0xFFE9;
-  private static final int XK_Alt_R =     0xFFEA;
-  private static final int XK_Super_L =           0xFFEB;
-  private static final int XK_Super_R =           0xFFEC;
-  private static final int XK_Hyper_L =           0xFFED;
-  private static final int XK_Hyper_R =           0xFFEE;
-
-  private static final int XK_Home =      0xFF50;
-  private static final int XK_Left =      0xFF51;
-  private static final int XK_Up =        0xFF52;
-  private static final int XK_Right =     0xFF53;
-  private static final int XK_Down =      0xFF54;
-  private static final int XK_Prior =     0xFF55;
-  private static final int XK_Page_Up =           0xFF55;
-  private static final int XK_Next =      0xFF56;
-  private static final int XK_Page_Down =  0xFF56;
-  private static final int XK_End =       0xFF57;
-  private static final int XK_Begin =     0xFF58;
-
-  private static final int XK_F1 =        0xFFBE;
-  private static final int XK_F2 =        0xFFBF;
-  private static final int XK_F3 =        0xFFC0;
-  private static final int XK_F4 =        0xFFC1;
-  private static final int XK_F5 =        0xFFC2;
-  private static final int XK_F6 =        0xFFC3;
-  private static final int XK_F7 =        0xFFC4;
-  private static final int XK_F8 =        0xFFC5;
-  private static final int XK_F9 =        0xFFC6;
-  private static final int XK_F10 =       0xFFC7;
-  private static final int XK_F11 =       0xFFC8;
-  private static final int XK_F12 =       0xFFC9;
-
-  public void sendKeyEvent (KeyEvent event) {
-    int uc    = event.getUnicodeChar();
-    int jcode = event.getKeyCode();
-    int jmods = event.getModifiers();
-    int xcode = 0;
-    int xmods = 0;
-
-    switch (jcode) {
-    case KeyEvent.KEYCODE_SHIFT_LEFT:       xcode = XK_Shift_L;   break;
-    case KeyEvent.KEYCODE_SHIFT_RIGHT:      xcode = XK_Shift_R;   break;
-    case KeyEvent.KEYCODE_CTRL_LEFT:        xcode = XK_Control_L; break;
-    case KeyEvent.KEYCODE_CTRL_RIGHT:       xcode = XK_Control_R; break;
-    case KeyEvent.KEYCODE_CAPS_LOCK:        xcode = XK_Caps_Lock; break;
-    case KeyEvent.KEYCODE_META_LEFT:        xcode = XK_Meta_L;    break;
-    case KeyEvent.KEYCODE_META_RIGHT:       xcode = XK_Meta_R;    break;
-    case KeyEvent.KEYCODE_ALT_LEFT:         xcode = XK_Alt_L;     break;
-    case KeyEvent.KEYCODE_ALT_RIGHT:        xcode = XK_Alt_R;     break;
-
-    case KeyEvent.KEYCODE_HOME:                     xcode = XK_Home;      break;
-    case KeyEvent.KEYCODE_DPAD_LEFT:        xcode = XK_Left;      break;
-    case KeyEvent.KEYCODE_DPAD_UP:          xcode = XK_Up;        break;
-    case KeyEvent.KEYCODE_DPAD_RIGHT:       xcode = XK_Right;     break;
-    case KeyEvent.KEYCODE_DPAD_DOWN:        xcode = XK_Down;      break;
-  //case KeyEvent.KEYCODE_NAVIGATE_PREVIOUS: xcode = XK_Prior;    break;
-    case KeyEvent.KEYCODE_PAGE_UP:          xcode = XK_Page_Up;   break;
-  //case KeyEvent.KEYCODE_NAVIGATE_NEXT:     xcode = XK_Next;     break;
-    case KeyEvent.KEYCODE_PAGE_DOWN:        xcode = XK_Page_Down; break;
-    case KeyEvent.KEYCODE_MOVE_END:         xcode = XK_End;       break;
-    case KeyEvent.KEYCODE_MOVE_HOME:        xcode = XK_Begin;     break;
-
-    case KeyEvent.KEYCODE_F1:               xcode = XK_F1;        break;
-    case KeyEvent.KEYCODE_F2:               xcode = XK_F2;        break;
-    case KeyEvent.KEYCODE_F3:               xcode = XK_F3;        break;
-    case KeyEvent.KEYCODE_F4:               xcode = XK_F4;        break;
-    case KeyEvent.KEYCODE_F5:               xcode = XK_F5;        break;
-    case KeyEvent.KEYCODE_F6:               xcode = XK_F6;        break;
-    case KeyEvent.KEYCODE_F7:               xcode = XK_F7;        break;
-    case KeyEvent.KEYCODE_F8:               xcode = XK_F8;        break;
-    case KeyEvent.KEYCODE_F9:               xcode = XK_F9;        break;
-    case KeyEvent.KEYCODE_F10:              xcode = XK_F10;       break;
-    case KeyEvent.KEYCODE_F11:              xcode = XK_F11;       break;
-    case KeyEvent.KEYCODE_F12:              xcode = XK_F12;       break;
-    default:                                xcode = uc;           break;
-    }
-
-    if (0 != (jmods & KeyEvent.META_SHIFT_ON))     xmods |= ShiftMask;
-    if (0 != (jmods & KeyEvent.META_CAPS_LOCK_ON)) xmods |= LockMask;
-    if (0 != (jmods & KeyEvent.META_CTRL_MASK))    xmods |= ControlMask;
-    if (0 != (jmods & KeyEvent.META_ALT_MASK))    xmods |= Mod1Mask;
-    if (0 != (jmods & KeyEvent.META_META_ON))      xmods |= Mod1Mask;
-    if (0 != (jmods & KeyEvent.META_SYM_ON))       xmods |= Mod2Mask;
-    if (0 != (jmods & KeyEvent.META_FUNCTION_ON))  xmods |= Mod3Mask;
-
-    /* If you touch and release Shift, you get no events.
-       If you type Shift-A, you get Shift down, A down, A up, Shift up.
-       So let's just ignore all lone modifier key events.
-     */
-    if (xcode >= XK_Shift_L && xcode <= XK_Hyper_R)
-      return;
-
-    boolean down_p = event.getAction() == KeyEvent.ACTION_DOWN;
-    sendKeyEvent (down_p, xcode, xmods);
-  }
-
-}
diff --git a/android/project/xscreensaver/xscreensaver.iml b/android/project/xscreensaver/xscreensaver.iml
deleted file mode 100644 (file)
index 1af1dc5..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module external.linked.project.id=":xscreensaver" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" type="JAVA_MODULE" version="4">
-  <component name="FacetManager">
-    <facet type="android-gradle" name="Android-Gradle">
-      <configuration>
-        <option name="GRADLE_PROJECT_PATH" value=":xscreensaver" />
-      </configuration>
-    </facet>
-    <facet type="android" name="Android">
-      <configuration>
-        <option name="SELECTED_BUILD_VARIANT" value="debug" />
-        <option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
-        <option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
-        <option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
-        <afterSyncTasks>
-          <task>generateDebugSources</task>
-        </afterSyncTasks>
-        <option name="ALLOW_USER_CONFIGURATION" value="false" />
-      </configuration>
-    </facet>
-  </component>
-  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
-    <output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
-    <output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/debug" />
-    <exclude-output />
-    <content url="file://$MODULE_DIR$">
-      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
-      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
-      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
-      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
-      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
-      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
-      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
-      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
-      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/build-types/debug/res" type="java-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/build-types/debug/resources" type="java-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/build-types/debug/assets" type="java-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/build-types/debug/aidl" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/build-types/debug/java" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/build-types/debug/jni" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/build-types/debug/rs" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/build-types/debug/shaders" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/src/testDebug/aidl" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/testDebug/java" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/testDebug/jni" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/testDebug/rs" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/testDebug/shaders" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/res" type="java-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/src" type="java-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/assets" type="java-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/jni" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-safeguard" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-support" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
-      <excludeFolder url="file://$MODULE_DIR$/build/outputs" />
-      <excludeFolder url="file://$MODULE_DIR$/build/tmp" />
-    </content>
-    <orderEntry type="jdk" jdkName="Android API 21 Platform" jdkType="Android SDK" />
-    <orderEntry type="sourceFolder" forTests="false" />
-  </component>
-</module>
\ No newline at end of file
diff --git a/android/settings.gradle b/android/settings.gradle
new file mode 100644 (file)
index 0000000..5fc665b
--- /dev/null
@@ -0,0 +1 @@
+include ':xscreensaver'
diff --git a/android/xscreensaver/.idea/.name b/android/xscreensaver/.idea/.name
new file mode 100644 (file)
index 0000000..1fd74d1
--- /dev/null
@@ -0,0 +1 @@
+android
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/compiler.xml b/android/xscreensaver/.idea/compiler.xml
new file mode 100644 (file)
index 0000000..9a8b7e5
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="CompilerConfiguration">
+    <option name="DEFAULT_COMPILER" value="Javac" />
+    <resourceExtensions />
+    <wildcardResourcePatterns>
+      <entry name="!?*.java" />
+      <entry name="!?*.form" />
+      <entry name="!?*.class" />
+      <entry name="!?*.groovy" />
+      <entry name="!?*.scala" />
+      <entry name="!?*.flex" />
+      <entry name="!?*.kt" />
+      <entry name="!?*.clj" />
+    </wildcardResourcePatterns>
+    <annotationProcessing>
+      <profile default="true" name="Default" enabled="false">
+        <processorPath useClasspath="true" />
+      </profile>
+    </annotationProcessing>
+  </component>
+</project>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/gradle.xml b/android/xscreensaver/.idea/gradle.xml
new file mode 100644 (file)
index 0000000..19fd5f1
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="GradleSettings">
+    <option name="linkedExternalProjectsSettings">
+      <GradleProjectSettings>
+        <option name="distributionType" value="LOCAL" />
+        <option name="externalProjectPath" value="$PROJECT_DIR$" />
+        <option name="gradleHome" value="$APPLICATION_HOME_DIR$/gradle/gradle-2.14.1" />
+        <option name="modules">
+          <set>
+            <option value="$PROJECT_DIR$/.." />
+            <option value="$PROJECT_DIR$" />
+          </set>
+        </option>
+        <option name="resolveModulePerSourceSet" value="false" />
+      </GradleProjectSettings>
+    </option>
+  </component>
+</project>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/misc.xml b/android/xscreensaver/.idea/misc.xml
new file mode 100644 (file)
index 0000000..a6ba7e0
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectLevelVcsManager" settingsEditedManually="false">
+    <OptionsSetting value="true" id="Add" />
+    <OptionsSetting value="true" id="Remove" />
+    <OptionsSetting value="true" id="Checkout" />
+    <OptionsSetting value="true" id="Update" />
+    <OptionsSetting value="true" id="Status" />
+    <OptionsSetting value="true" id="Edit" />
+    <ConfirmationsSetting value="0" id="Add" />
+    <ConfirmationsSetting value="0" id="Remove" />
+  </component>
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
+    <output url="file://$PROJECT_DIR$/build/classes" />
+  </component>
+  <component name="ProjectType">
+    <option name="id" value="Android" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/modules.xml b/android/xscreensaver/.idea/modules.xml
new file mode 100644 (file)
index 0000000..33191fe
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/../android.iml" filepath="$PROJECT_DIR$/../android.iml" />
+      <module fileurl="file://$PROJECT_DIR$/xscreensaver.iml" filepath="$PROJECT_DIR$/xscreensaver.iml" />
+    </modules>
+  </component>
+</project>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/runConfigurations.xml b/android/xscreensaver/.idea/runConfigurations.xml
new file mode 100644 (file)
index 0000000..7f68460
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="RunConfigurationProducerService">
+    <option name="ignoredProducers">
+      <set>
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
+      </set>
+    </option>
+  </component>
+</project>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/workspace.xml b/android/xscreensaver/.idea/workspace.xml
new file mode 100644 (file)
index 0000000..0d78d0c
--- /dev/null
@@ -0,0 +1,1845 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ChangeListManager">
+    <list default="true" id="41008724-035d-4e24-92b6-6dfb9231c83c" name="Default" comment="" />
+    <ignored path="xscreensaver.iws" />
+    <ignored path=".idea/workspace.xml" />
+    <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
+    <option name="TRACKING_ENABLED" value="true" />
+    <option name="SHOW_DIALOG" value="false" />
+    <option name="HIGHLIGHT_CONFLICTS" value="true" />
+    <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
+    <option name="LAST_RESOLUTION" value="IGNORE" />
+  </component>
+  <component name="CreatePatchCommitExecutor">
+    <option name="PATCH_PATH" value="" />
+  </component>
+  <component name="ExecutionTargetManager" SELECTED_TARGET="default_target" />
+  <component name="ExternalProjectsData">
+    <projectState path="$PROJECT_DIR$">
+      <ProjectState />
+    </projectState>
+  </component>
+  <component name="ExternalProjectsManager">
+    <system id="GRADLE">
+      <state>
+        <projects_view />
+      </state>
+    </system>
+  </component>
+  <component name="FavoritesManager">
+    <favorites_list name="xscreensaver" />
+  </component>
+  <component name="GradleLocalSettings">
+    <option name="myGradleHomes">
+      <map>
+        <entry key="$PROJECT_DIR$" value="$USER_HOME$/.gradle/wrapper/dists/gradle-2.14.1-bin/2r579t5wehc7ew5kc8vfqezww/gradle-2.14.1" />
+      </map>
+    </option>
+    <option name="myGradleVersions">
+      <map>
+        <entry key="$PROJECT_DIR$" value="2.14.1" />
+      </map>
+    </option>
+    <option name="availableProjects">
+      <map>
+        <entry>
+          <key>
+            <ExternalProjectPojo>
+              <option name="name" value="android" />
+              <option name="path" value="$PROJECT_DIR$" />
+            </ExternalProjectPojo>
+          </key>
+          <value>
+            <list>
+              <ExternalProjectPojo>
+                <option name="name" value=":xscreensaver" />
+                <option name="path" value="$PROJECT_DIR$" />
+              </ExternalProjectPojo>
+              <ExternalProjectPojo>
+                <option name="name" value="android" />
+                <option name="path" value="$PROJECT_DIR$/.." />
+              </ExternalProjectPojo>
+            </list>
+          </value>
+        </entry>
+      </map>
+    </option>
+    <option name="availableTasks">
+      <map>
+        <entry key="$PROJECT_DIR$/..">
+          <value>
+            <list>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays all buildscript dependencies declared in root project 'android'." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value=":buildEnvironment" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value=":clean" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the components produced by root project 'android'. [incubating]" />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value=":components" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays all dependencies declared in root project 'android'." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value=":dependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the insight into a specific dependency in root project 'android'." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value=":dependencyInsight" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value=":distClean" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays a help message." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value=":help" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Initializes a new Gradle build. [incubating]" />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value=":init" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the configuration model of root project 'android'. [incubating]" />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value=":model" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the sub-projects of root project 'android'." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value=":projects" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the properties of root project 'android'." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value=":properties" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the tasks runnable from root project 'android' (some of the displayed tasks may belong to subprojects)." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value=":tasks" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Generates Gradle wrapper files. [incubating]" />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value=":wrapper" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the Android dependencies of the project." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="androidDependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles all variants of all applications and secondary packages." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assemble" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles all the Test applications." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assembleAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles all Debug builds." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assembleDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assembleDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assembleDebugUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles all Release builds." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assembleRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assembleReleaseUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles and tests this project." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="build" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles and tests this project and all projects that depend on it." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="buildDependents" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles and tests this project and all projects it depends on." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="buildNeeded" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs all checks." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="check" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="checkDebugManifest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="checkReleaseManifest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAidl" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAndroidTestAidl" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAndroidTestJavaWithJavac" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAndroidTestNdk" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAndroidTestRenderscript" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAndroidTestShaders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAndroidTestSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugJavaWithJavac" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugNdk" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugRenderscript" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugShaders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugUnitTestJavaWithJavac" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugUnitTestSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileLint" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseAidl" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseJavaWithJavac" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseNdk" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseRenderscript" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseShaders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseUnitTestJavaWithJavac" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseUnitTestSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="config_h" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Installs and runs instrumentation tests for all flavors on connected devices." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="connectedAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs all device checks on currently connected devices." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="connectedCheck" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Installs and runs the tests for debug on connected devices." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="connectedDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Installs and runs instrumentation tests using all Device Providers." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="deviceAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs all device checks using Device Providers and Test Servers." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="deviceCheck" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="downloadNeededDrawables" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugAndroidTestAssets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugAndroidTestBuildConfig" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugAndroidTestResValues" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugAndroidTestResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugAndroidTestSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugAssets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugBuildConfig" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugResValues" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateReleaseAssets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateReleaseBuildConfig" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateReleaseResValues" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateReleaseResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateReleaseSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="incrementalDebugAndroidTestJavaCompilationSafeguard" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="incrementalDebugJavaCompilationSafeguard" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="incrementalDebugUnitTestJavaCompilationSafeguard" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="incrementalReleaseJavaCompilationSafeguard" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="incrementalReleaseUnitTestJavaCompilationSafeguard" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Installs the Debug build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="installDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Installs the android (on device) tests for the Debug build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="installDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="jarDebugClasses" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="jarReleaseClasses" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs lint on all variants." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="lint" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs lint on the Debug build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="lintDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs lint on the Release build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="lintRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs lint on just the fatal issues in the Release build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="lintVitalRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugAndroidTestAssets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugAndroidTestJniLibFolders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugAndroidTestResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugAndroidTestShaders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugAssets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugJniLibFolders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugShaders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeReleaseAssets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeReleaseJniLibFolders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeReleaseResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeReleaseShaders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Creates a version of android.jar that's suitable for unit tests." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mockableAndroidJar" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="ndkBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="objlibClean" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="packageDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="packageDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="packageRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="perlBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="perlClean" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preDebugAndroidTestBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preDebugBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preDebugUnitTestBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prePackageMarkerForDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prePackageMarkerForDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prePackageMarkerForRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preReleaseBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preReleaseUnitTestBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prepareDebugAndroidTestDependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prepareDebugDependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prepareDebugUnitTestDependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prepareReleaseDependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prepareReleaseUnitTestDependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugAndroidTestJavaRes" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugAndroidTestManifest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugAndroidTestResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugJavaRes" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugManifest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugUnitTestJavaRes" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processReleaseJavaRes" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processReleaseManifest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processReleaseResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processReleaseUnitTestJavaRes" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the signing info for each variant." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="signingReport" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Prints out all the source sets defined in this project." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="sourceSets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Run unit tests for all variants." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="test" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Run unit tests for the debug build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="testDebugUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Run unit tests for the release build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="testReleaseUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformClassesWithDexForDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformClassesWithDexForDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformClassesWithDexForRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformNative_libsWithMergeJniLibsForDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformNative_libsWithMergeJniLibsForDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformNative_libsWithMergeJniLibsForRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformResourcesWithMergeJavaResForDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformResourcesWithMergeJavaResForDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformResourcesWithMergeJavaResForDebugUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformResourcesWithMergeJavaResForRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformResourcesWithMergeJavaResForReleaseUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Uninstall all applications." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="uninstallAll" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Uninstalls the Debug build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="uninstallDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Uninstalls the android (on device) tests for the Debug build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="uninstallDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Uninstalls the Release build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="uninstallRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="validateDebugSigning" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="zipalignDebug" />
+              </ExternalTaskPojo>
+            </list>
+          </value>
+        </entry>
+        <entry key="$PROJECT_DIR$">
+          <value>
+            <list>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the sub-projects of project ':xscreensaver'." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="projects" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assembleReleaseUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prepareDebugDependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processReleaseJavaRes" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateReleaseAssets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs lint on the Debug build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="lintDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assembleDebugUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prePackageMarkerForDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Creates a version of android.jar that's suitable for unit tests." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mockableAndroidJar" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the configuration model of project ':xscreensaver'. [incubating]" />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="model" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the tasks runnable from project ':xscreensaver'." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="tasks" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="incrementalDebugJavaCompilationSafeguard" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs all device checks using Device Providers and Test Servers." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="deviceCheck" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays all dependencies declared in project ':xscreensaver'." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="dependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs lint on all variants." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="lint" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="packageDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prePackageMarkerForRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseNdk" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugJavaWithJavac" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles and tests this project and all projects it depends on." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="buildNeeded" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugAndroidTestBuildConfig" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugUnitTestJavaRes" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Run unit tests for the release build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="testReleaseUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAndroidTestShaders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugShaders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformNative_libsWithMergeJniLibsForDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAndroidTestJavaWithJavac" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the components produced by project ':xscreensaver'. [incubating]" />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="components" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseRenderscript" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles all Debug builds." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assembleDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugAndroidTestManifest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugUnitTestJavaWithJavac" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformResourcesWithMergeJavaResForReleaseUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prePackageMarkerForDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformClassesWithDexForDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preDebugAndroidTestBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugAndroidTestJavaRes" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processReleaseUnitTestJavaRes" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Uninstalls the Release build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="uninstallRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseShaders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeReleaseResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugAndroidTestSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prepareDebugAndroidTestDependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="incrementalDebugAndroidTestJavaCompilationSafeguard" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="checkReleaseManifest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAndroidTestSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeReleaseJniLibFolders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prepareReleaseDependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processReleaseResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Installs and runs instrumentation tests using all Device Providers." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="deviceAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugAndroidTestAssets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processReleaseManifest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Uninstalls the android (on device) tests for the Debug build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="uninstallDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the insight into a specific dependency in project ':xscreensaver'." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="dependencyInsight" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateReleaseSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="incrementalReleaseUnitTestJavaCompilationSafeguard" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preReleaseBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles all variants of all applications and secondary packages." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assemble" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="incrementalDebugUnitTestJavaCompilationSafeguard" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="incrementalReleaseJavaCompilationSafeguard" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays a help message." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="help" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseUnitTestSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Installs the android (on device) tests for the Debug build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="installDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugAssets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs all device checks on currently connected devices." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="connectedCheck" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Installs and runs the tests for debug on connected devices." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="connectedDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Uninstall all applications." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="uninstallAll" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles all the Test applications." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assembleAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugAndroidTestResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="zipalignDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformNative_libsWithMergeJniLibsForDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="packageRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAidl" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preDebugUnitTestBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileLint" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugAndroidTestResValues" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeReleaseShaders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the Android dependencies of the project." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="androidDependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAndroidTestNdk" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugUnitTestSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugAndroidTestJniLibFolders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformClassesWithDexForDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assembleDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="objlibClean" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugJavaRes" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugAndroidTestAssets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseJavaWithJavac" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="jarReleaseClasses" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformResourcesWithMergeJavaResForDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="downloadNeededDrawables" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prepareReleaseUnitTestDependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Run unit tests for all variants." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="test" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugNdk" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformNative_libsWithMergeJniLibsForRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugAndroidTestResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preReleaseUnitTestBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugResValues" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs all checks." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="check" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="validateDebugSigning" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Run unit tests for the debug build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="testDebugUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Installs and runs instrumentation tests for all flavors on connected devices." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="connectedAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="jarDebugClasses" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformClassesWithDexForRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Installs the Debug build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="installDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformResourcesWithMergeJavaResForRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseSources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseUnitTestJavaWithJavac" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugShaders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformResourcesWithMergeJavaResForDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileReleaseAidl" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="config_h" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs lint on the Release build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="lintRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles and tests this project and all projects that depend on it." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="buildDependents" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugAssets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays all buildscript dependencies declared in project ':xscreensaver'." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="buildEnvironment" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="checkDebugManifest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugJniLibFolders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Prints out all the source sets defined in this project." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="sourceSets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="transformResourcesWithMergeJavaResForDebugUnitTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="perlBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeReleaseAssets" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugRenderscript" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateReleaseBuildConfig" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="prepareDebugUnitTestDependencies" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="perlClean" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateReleaseResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Runs lint on just the fatal issues in the Release build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="lintVitalRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="ndkBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Uninstalls the Debug build." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="uninstallDebug" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the signing info for each variant." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="signingReport" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAndroidTestAidl" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="mergeDebugAndroidTestShaders" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Deletes the build directory." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="clean" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="preDebugBuild" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugBuildConfig" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles and tests this project." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="build" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Assembles all Release builds." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="assembleRelease" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="compileDebugAndroidTestRenderscript" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateDebugAndroidTestResources" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="processDebugManifest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="packageDebugAndroidTest" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="generateReleaseResValues" />
+              </ExternalTaskPojo>
+              <ExternalTaskPojo>
+                <option name="description" value="Displays the properties of project ':xscreensaver'." />
+                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
+                <option name="name" value="properties" />
+              </ExternalTaskPojo>
+            </list>
+          </value>
+        </entry>
+      </map>
+    </option>
+    <option name="projectBuildClasspath">
+      <map>
+        <entry key="$PROJECT_DIR$">
+          <value>
+            <ExternalProjectBuildClasspathPojo>
+              <option name="modulesBuildClasspath">
+                <map>
+                  <entry key="$PROJECT_DIR$/..">
+                    <value>
+                      <ExternalModuleBuildClasspathPojo>
+                        <option name="entries">
+                          <list>
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle/2.1.0/6d96b336cb51a348725e6c366aefd74682dce465/gradle-2.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-core/2.1.0/527d4386755e742b500df6cc2f2b0dc2bb798dfe/gradle-core-2.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder/2.1.0/525d7c91bd7acccecba4a6a4e611b772b0824f21/builder-2.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint/25.1.0/2bc7dab70d203eebda02f12b20a6170c190f6b29/lint-25.1.0.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/android/tools/build/transform-api/2.0.0-deprecated-use-gradle-api/transform-api-2.0.0-deprecated-use-gradle-api.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-api/2.1.0/f3278f0caee0382a1cc3dfccd08d7981b1d69013/gradle-api-2.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/compilerCommon/2.1.0/92d114064b10fde26f5363c6d965767852b42828/compilerCommon-2.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm/5.0.3/dcc2193db20e19e1feca8b1240dbbc4e190824fa/asm-5.0.3.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-commons/5.0.3/a7111830132c7f87d08fe48cb0ca07630f8cb91c/asm-commons-5.0.3.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/proguard/proguard-gradle/5.2.1/proguard-gradle-5.2.1.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jacoco/org.jacoco.core/0.7.4.201502262128/31482f50411a3a5769b6c78fa9b97ba731c205e7/org.jacoco.core-0.7.4.201502262128.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/antlr/antlr/3.5.2/antlr-3.5.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-model/2.1.0/a3aa281eebfdb2f9f13b73c754648ad434f515ab/builder-model-2.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-test-api/2.1.0/b3b98fa0514c5e7301233db9586317a8aeda2aa0/builder-test-api-2.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdklib/25.1.0/aad711bbb11a5d987e2f7894ca47531ef7152ae/sdklib-25.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdk-common/25.1.0/54053c7fe667b737870d3fa509b0d3c53eccb7f/sdk-common-25.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/common/25.1.0/f28e33233e0d20119a04256036324ac2aba3426d/common-25.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/manifest-merger/25.1.0/db4c07f151804f5091156fe128312d817535126a/manifest-merger-25.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.ddms/ddmlib/25.1.0/7aae7364ea2a1d632fd86938bd71b1078930bd2c/ddmlib-25.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.jack/jack-api/0.10.0/f44f53e8f713714f9a1bf9b2cabfea3584b00878/jack-api-0.10.0.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/android/tools/jill/jill-api/0.10.0/jill-api-0.10.0.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/squareup/javawriter/2.5.0/javawriter-2.5.0.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/bouncycastle/bcpkix-jdk15on/1.48/bcpkix-jdk15on-1.48.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/bouncycastle/bcprov-jdk15on/1.48/bcprov-jdk15on-1.48.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-tree/5.0.3/287749b48ba7162fb67c93a026d690b29f410bed/asm-tree-5.0.3.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-checks/25.1.0/8527298ca77202032b16b729bd1849e44f445adc/lint-checks-25.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.eclipse.jdt.core.compiler/ecj/4.4.2/71d67f5bab9465ec844596ef844f40902ae25392/ecj-4.4.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/annotations/25.1.0/6fdec5fc3e0b5a7b1a5866d9e8910d9bc4ceee4f/annotations-25.1.0.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/google/guava/guava/17.0/guava-17.0-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/google/guava/guava/17.0/guava-17.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/baseLibrary/2.1.0/a7aeef173c4e5b104ec04f146f8e8f9debde1c5e/baseLibrary-2.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.tunnelvisionlabs/antlr4/4.5/a0e860e317147848e69ac145bc5196901a9993bf/antlr4-4.5.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-io/commons-io/2.4/commons-io-2.4.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/googlecode/juniversalchardet/juniversalchardet/1.0.3/juniversalchardet-1.0.3.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/proguard/proguard-base/5.2.1/proguard-base-5.2.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-debug-all/5.0.1/asm-debug-all-5.0.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/antlr/antlr-runtime/3.5.2/antlr-runtime-3.5.2.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/antlr/ST4/4.0.8/ST4-4.0.8.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.layoutlib/layoutlib-api/25.1.0/26620cea0540ae08e4d19c71f1e779e04c6c545a/layoutlib-api-25.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/dvlib/25.1.0/ca582735b513a64217f39fccb7ea9285e7e0e23d/dvlib-25.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/repository/25.1.0/cb53d8e728e092299f9d62fc7c8e34567d882616/repository-25.1.0.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/google/code/gson/gson/2.2.4/gson-2.2.4.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/commons/commons-compress/1.8.1/commons-compress-1.8.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpclient/4.1.1/httpclient-4.1.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpmime/4.1/httpmime-4.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/kxml/kxml2/2.3.0/kxml2-2.3.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-api/25.1.0/ee915d21b52ee1c5884173c044c19cef14e5c623/lint-api-25.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-analysis/5.0.3/c7126aded0e8e13fed5f913559a0dd7b770a10f3/asm-analysis-5.0.3.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.tunnelvisionlabs/antlr4-runtime/4.5/5067478827a98f5ab77d9fc577903edc57af3da4/antlr4-runtime-4.5.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.tunnelvisionlabs/antlr4-annotations/4.5/2c5996120a0ac690de575bd8ac36250e6720a6b8/antlr4-annotations-4.5.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/intellij/annotations/12.0/annotations-12.0.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpcore/4.1/httpcore-4.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-codec/commons-codec/1.4/commons-codec-1.4.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/android/tools/external/lombok/lombok-ast/0.2.3/lombok-ast-0.2.3.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.abego.treelayout/org.abego.treelayout.core/1.0.1/e31e79cba7a5414cf18fa69f3f0a2cf9ee997b61/org.abego.treelayout.core-1.0.1.jar" />
+                          </list>
+                        </option>
+                        <option name="path" value="$PROJECT_DIR$/.." />
+                      </ExternalModuleBuildClasspathPojo>
+                    </value>
+                  </entry>
+                  <entry key="$PROJECT_DIR$">
+                    <value>
+                      <ExternalModuleBuildClasspathPojo>
+                        <option name="entries">
+                          <list>
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle/2.1.0/6d96b336cb51a348725e6c366aefd74682dce465/gradle-2.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-core/2.1.0/527d4386755e742b500df6cc2f2b0dc2bb798dfe/gradle-core-2.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder/2.1.0/525d7c91bd7acccecba4a6a4e611b772b0824f21/builder-2.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint/25.1.0/2bc7dab70d203eebda02f12b20a6170c190f6b29/lint-25.1.0.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/android/tools/build/transform-api/2.0.0-deprecated-use-gradle-api/transform-api-2.0.0-deprecated-use-gradle-api.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-api/2.1.0/f3278f0caee0382a1cc3dfccd08d7981b1d69013/gradle-api-2.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/compilerCommon/2.1.0/92d114064b10fde26f5363c6d965767852b42828/compilerCommon-2.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm/5.0.3/dcc2193db20e19e1feca8b1240dbbc4e190824fa/asm-5.0.3.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-commons/5.0.3/a7111830132c7f87d08fe48cb0ca07630f8cb91c/asm-commons-5.0.3.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/proguard/proguard-gradle/5.2.1/proguard-gradle-5.2.1.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jacoco/org.jacoco.core/0.7.4.201502262128/31482f50411a3a5769b6c78fa9b97ba731c205e7/org.jacoco.core-0.7.4.201502262128.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/antlr/antlr/3.5.2/antlr-3.5.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-model/2.1.0/a3aa281eebfdb2f9f13b73c754648ad434f515ab/builder-model-2.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-test-api/2.1.0/b3b98fa0514c5e7301233db9586317a8aeda2aa0/builder-test-api-2.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdklib/25.1.0/aad711bbb11a5d987e2f7894ca47531ef7152ae/sdklib-25.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdk-common/25.1.0/54053c7fe667b737870d3fa509b0d3c53eccb7f/sdk-common-25.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/common/25.1.0/f28e33233e0d20119a04256036324ac2aba3426d/common-25.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/manifest-merger/25.1.0/db4c07f151804f5091156fe128312d817535126a/manifest-merger-25.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.ddms/ddmlib/25.1.0/7aae7364ea2a1d632fd86938bd71b1078930bd2c/ddmlib-25.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.jack/jack-api/0.10.0/f44f53e8f713714f9a1bf9b2cabfea3584b00878/jack-api-0.10.0.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/android/tools/jill/jill-api/0.10.0/jill-api-0.10.0.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/squareup/javawriter/2.5.0/javawriter-2.5.0.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/bouncycastle/bcpkix-jdk15on/1.48/bcpkix-jdk15on-1.48.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/bouncycastle/bcprov-jdk15on/1.48/bcprov-jdk15on-1.48.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-tree/5.0.3/287749b48ba7162fb67c93a026d690b29f410bed/asm-tree-5.0.3.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-checks/25.1.0/8527298ca77202032b16b729bd1849e44f445adc/lint-checks-25.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.eclipse.jdt.core.compiler/ecj/4.4.2/71d67f5bab9465ec844596ef844f40902ae25392/ecj-4.4.2.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/annotations/25.1.0/6fdec5fc3e0b5a7b1a5866d9e8910d9bc4ceee4f/annotations-25.1.0.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/google/guava/guava/17.0/guava-17.0-sources.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/google/guava/guava/17.0/guava-17.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/baseLibrary/2.1.0/a7aeef173c4e5b104ec04f146f8e8f9debde1c5e/baseLibrary-2.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.tunnelvisionlabs/antlr4/4.5/a0e860e317147848e69ac145bc5196901a9993bf/antlr4-4.5.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-io/commons-io/2.4/commons-io-2.4.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/googlecode/juniversalchardet/juniversalchardet/1.0.3/juniversalchardet-1.0.3.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/proguard/proguard-base/5.2.1/proguard-base-5.2.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/ow2/asm/asm-debug-all/5.0.1/asm-debug-all-5.0.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/antlr/antlr-runtime/3.5.2/antlr-runtime-3.5.2.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/antlr/ST4/4.0.8/ST4-4.0.8.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.layoutlib/layoutlib-api/25.1.0/26620cea0540ae08e4d19c71f1e779e04c6c545a/layoutlib-api-25.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/dvlib/25.1.0/ca582735b513a64217f39fccb7ea9285e7e0e23d/dvlib-25.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/repository/25.1.0/cb53d8e728e092299f9d62fc7c8e34567d882616/repository-25.1.0.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/google/code/gson/gson/2.2.4/gson-2.2.4.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/commons/commons-compress/1.8.1/commons-compress-1.8.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpclient/4.1.1/httpclient-4.1.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpmime/4.1/httpmime-4.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/net/sf/kxml/kxml2/2.3.0/kxml2-2.3.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-api/25.1.0/ee915d21b52ee1c5884173c044c19cef14e5c623/lint-api-25.1.0.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-analysis/5.0.3/c7126aded0e8e13fed5f913559a0dd7b770a10f3/asm-analysis-5.0.3.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.tunnelvisionlabs/antlr4-runtime/4.5/5067478827a98f5ab77d9fc577903edc57af3da4/antlr4-runtime-4.5.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.tunnelvisionlabs/antlr4-annotations/4.5/2c5996120a0ac690de575bd8ac36250e6720a6b8/antlr4-annotations-4.5.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/intellij/annotations/12.0/annotations-12.0.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/org/apache/httpcomponents/httpcore/4.1/httpcore-4.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/commons-codec/commons-codec/1.4/commons-codec-1.4.jar" />
+                            <option value="$APPLICATION_HOME_DIR$/gradle/m2repository/com/android/tools/external/lombok/lombok-ast/0.2.3/lombok-ast-0.2.3.jar" />
+                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.abego.treelayout/org.abego.treelayout.core/1.0.1/e31e79cba7a5414cf18fa69f3f0a2cf9ee997b61/org.abego.treelayout.core-1.0.1.jar" />
+                          </list>
+                        </option>
+                        <option name="path" value="$PROJECT_DIR$" />
+                      </ExternalModuleBuildClasspathPojo>
+                    </value>
+                  </entry>
+                </map>
+              </option>
+              <option name="name" value="xscreensaver" />
+              <option name="projectBuildClasspath">
+                <list>
+                  <option value="$PROJECT_DIR$/buildSrc/src/main/java" />
+                  <option value="$PROJECT_DIR$/buildSrc/src/main/groovy" />
+                </list>
+              </option>
+            </ExternalProjectBuildClasspathPojo>
+          </value>
+        </entry>
+      </map>
+    </option>
+    <option name="externalProjectsViewState">
+      <projects_view />
+    </option>
+  </component>
+  <component name="ProjectFrameBounds">
+    <option name="x" value="73" />
+    <option name="y" value="23" />
+    <option name="width" value="1137" />
+    <option name="height" value="1029" />
+  </component>
+  <component name="ProjectLevelVcsManager" settingsEditedManually="false">
+    <OptionsSetting value="true" id="Add" />
+    <OptionsSetting value="true" id="Remove" />
+    <OptionsSetting value="true" id="Checkout" />
+    <OptionsSetting value="true" id="Update" />
+    <OptionsSetting value="true" id="Status" />
+    <OptionsSetting value="true" id="Edit" />
+    <ConfirmationsSetting value="0" id="Add" />
+    <ConfirmationsSetting value="0" id="Remove" />
+  </component>
+  <component name="ProjectView">
+    <navigator currentView="AndroidView" proportions="" version="1">
+      <flattenPackages />
+      <showMembers />
+      <showModules />
+      <showLibraryContents />
+      <hideEmptyPackages />
+      <abbreviatePackageNames />
+      <autoscrollToSource />
+      <autoscrollFromSource />
+      <sortByType />
+      <manualOrder />
+      <foldersAlwaysOnTop value="true" />
+    </navigator>
+    <panes>
+      <pane id="PackagesPane" />
+      <pane id="ProjectPane" />
+      <pane id="AndroidView">
+        <subPane>
+          <PATH>
+            <PATH_ELEMENT>
+              <option name="myItemId" value="android" />
+              <option name="myItemType" value="com.android.tools.idea.navigator.nodes.AndroidViewProjectNode" />
+            </PATH_ELEMENT>
+          </PATH>
+        </subPane>
+      </pane>
+      <pane id="Scope" />
+      <pane id="Scratches" />
+    </panes>
+  </component>
+  <component name="PropertiesComponent">
+    <property name="GoToClass.includeLibraries" value="false" />
+    <property name="GoToClass.toSaveIncludeLibraries" value="false" />
+    <property name="GoToFile.includeJavaFiles" value="false" />
+    <property name="MemberChooser.sorted" value="false" />
+    <property name="MemberChooser.showClasses" value="true" />
+    <property name="MemberChooser.copyJavadoc" value="false" />
+    <property name="settings.editor.selected.configurable" value="android.sdk-updates" />
+    <property name="settings.editor.splitter.proportion" value="0.2" />
+    <property name="SearchEverywhereHistoryKey" value="sdk manager&#9;ACTION&#9;WelcomeScreen.RunAndroidSdkManager" />
+    <property name="last_opened_file_path" value="$PROJECT_DIR$" />
+  </component>
+  <component name="RunManager" selected="Android App.xscreensaver">
+    <configuration default="true" type="AndroidJUnit" factoryName="Android JUnit">
+      <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+      <module name="" />
+      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+      <option name="ALTERNATIVE_JRE_PATH" />
+      <option name="PACKAGE_NAME" />
+      <option name="MAIN_CLASS_NAME" />
+      <option name="METHOD_NAME" />
+      <option name="TEST_OBJECT" value="class" />
+      <option name="VM_PARAMETERS" />
+      <option name="PARAMETERS" />
+      <option name="WORKING_DIRECTORY" />
+      <option name="ENV_VARIABLES" />
+      <option name="PASS_PARENT_ENVS" value="true" />
+      <option name="TEST_SEARCH_SCOPE">
+        <value defaultName="singleModule" />
+      </option>
+      <envs />
+      <patterns />
+      <method>
+        <option name="Make" enabled="false" />
+        <option name="Android.Gradle.BeforeRunTask" enabled="true" />
+      </method>
+    </configuration>
+    <configuration default="true" type="AndroidRunConfigurationType" factoryName="Android App">
+      <module name="" />
+      <option name="DEPLOY" value="true" />
+      <option name="ARTIFACT_NAME" value="" />
+      <option name="PM_INSTALL_OPTIONS" value="" />
+      <option name="ACTIVITY_EXTRA_FLAGS" value="" />
+      <option name="MODE" value="default_activity" />
+      <option name="PREFERRED_AVD" value="" />
+      <option name="CLEAR_LOGCAT" value="false" />
+      <option name="SHOW_LOGCAT_AUTOMATICALLY" value="false" />
+      <option name="SKIP_NOOP_APK_INSTALLATIONS" value="true" />
+      <option name="FORCE_STOP_RUNNING_APP" value="true" />
+      <option name="TARGET_SELECTION_MODE" value="SHOW_DIALOG" />
+      <option name="USE_LAST_SELECTED_DEVICE" value="false" />
+      <option name="PREFERRED_AVD" value="" />
+      <option name="SELECTED_CLOUD_MATRIX_CONFIGURATION_ID" value="-1" />
+      <option name="SELECTED_CLOUD_MATRIX_PROJECT_ID" value="" />
+      <option name="DEBUGGER_TYPE" value="Auto" />
+      <Auto>
+        <option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
+        <option name="SHOW_STATIC_VARS" value="true" />
+        <option name="WORKING_DIR" value="" />
+        <option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
+        <option name="SHOW_OPTIMIZED_WARNING" value="true" />
+      </Auto>
+      <Hybrid>
+        <option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
+        <option name="SHOW_STATIC_VARS" value="true" />
+        <option name="WORKING_DIR" value="" />
+        <option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
+        <option name="SHOW_OPTIMIZED_WARNING" value="true" />
+      </Hybrid>
+      <Java />
+      <Native>
+        <option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
+        <option name="SHOW_STATIC_VARS" value="true" />
+        <option name="WORKING_DIR" value="" />
+        <option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
+        <option name="SHOW_OPTIMIZED_WARNING" value="true" />
+      </Native>
+      <Profilers>
+        <option name="ENABLE_ADVANCED_PROFILING" value="true" />
+        <option name="SUPPORT_LIB_ENABLED" value="true" />
+        <option name="INSTRUMENTATION_ENABLED" value="true" />
+      </Profilers>
+      <option name="DEEP_LINK" value="" />
+      <option name="ACTIVITY_CLASS" value="" />
+      <method />
+    </configuration>
+    <configuration default="true" type="Application" factoryName="Application">
+      <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+      <option name="MAIN_CLASS_NAME" />
+      <option name="VM_PARAMETERS" />
+      <option name="PROGRAM_PARAMETERS" />
+      <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
+      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+      <option name="ALTERNATIVE_JRE_PATH" />
+      <option name="ENABLE_SWING_INSPECTOR" value="false" />
+      <option name="ENV_VARIABLES" />
+      <option name="PASS_PARENT_ENVS" value="true" />
+      <module name="" />
+      <envs />
+      <method />
+    </configuration>
+    <configuration default="true" type="Remote" factoryName="Remote">
+      <option name="USE_SOCKET_TRANSPORT" value="true" />
+      <option name="SERVER_MODE" value="false" />
+      <option name="SHMEM_ADDRESS" value="javadebug" />
+      <option name="HOST" value="localhost" />
+      <option name="PORT" value="5005" />
+      <method />
+    </configuration>
+    <configuration default="true" type="TestNG" factoryName="TestNG">
+      <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+      <module name="" />
+      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+      <option name="ALTERNATIVE_JRE_PATH" />
+      <option name="SUITE_NAME" />
+      <option name="PACKAGE_NAME" />
+      <option name="MAIN_CLASS_NAME" />
+      <option name="METHOD_NAME" />
+      <option name="GROUP_NAME" />
+      <option name="TEST_OBJECT" value="CLASS" />
+      <option name="VM_PARAMETERS" value="-ea" />
+      <option name="PARAMETERS" />
+      <option name="WORKING_DIRECTORY" value="$MODULE_DIR$" />
+      <option name="OUTPUT_DIRECTORY" />
+      <option name="ANNOTATION_TYPE" />
+      <option name="ENV_VARIABLES" />
+      <option name="PASS_PARENT_ENVS" value="true" />
+      <option name="TEST_SEARCH_SCOPE">
+        <value defaultName="singleModule" />
+      </option>
+      <option name="USE_DEFAULT_REPORTERS" value="false" />
+      <option name="PROPERTIES_FILE" />
+      <envs />
+      <properties />
+      <listeners />
+      <method />
+    </configuration>
+    <configuration default="false" name="xscreensaver" type="AndroidRunConfigurationType" factoryName="Android App">
+      <module name="xscreensaver" />
+      <option name="DEPLOY" value="true" />
+      <option name="ARTIFACT_NAME" value="" />
+      <option name="PM_INSTALL_OPTIONS" value="" />
+      <option name="ACTIVITY_EXTRA_FLAGS" value="" />
+      <option name="MODE" value="default_activity" />
+      <option name="PREFERRED_AVD" value="" />
+      <option name="CLEAR_LOGCAT" value="false" />
+      <option name="SHOW_LOGCAT_AUTOMATICALLY" value="false" />
+      <option name="SKIP_NOOP_APK_INSTALLATIONS" value="true" />
+      <option name="FORCE_STOP_RUNNING_APP" value="true" />
+      <option name="TARGET_SELECTION_MODE" value="SHOW_DIALOG" />
+      <option name="USE_LAST_SELECTED_DEVICE" value="false" />
+      <option name="PREFERRED_AVD" value="" />
+      <option name="SELECTED_CLOUD_MATRIX_CONFIGURATION_ID" value="-1" />
+      <option name="SELECTED_CLOUD_MATRIX_PROJECT_ID" value="" />
+      <option name="DEBUGGER_TYPE" value="Auto" />
+      <Auto>
+        <option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
+        <option name="SHOW_STATIC_VARS" value="true" />
+        <option name="WORKING_DIR" value="" />
+        <option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
+        <option name="SHOW_OPTIMIZED_WARNING" value="true" />
+      </Auto>
+      <Hybrid>
+        <option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
+        <option name="SHOW_STATIC_VARS" value="true" />
+        <option name="WORKING_DIR" value="" />
+        <option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
+        <option name="SHOW_OPTIMIZED_WARNING" value="true" />
+      </Hybrid>
+      <Java />
+      <Native>
+        <option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
+        <option name="SHOW_STATIC_VARS" value="true" />
+        <option name="WORKING_DIR" value="" />
+        <option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
+        <option name="SHOW_OPTIMIZED_WARNING" value="true" />
+      </Native>
+      <Profilers>
+        <option name="ENABLE_ADVANCED_PROFILING" value="true" />
+        <option name="SUPPORT_LIB_ENABLED" value="true" />
+        <option name="INSTRUMENTATION_ENABLED" value="true" />
+      </Profilers>
+      <option name="DEEP_LINK" value="" />
+      <option name="ACTIVITY_CLASS" value="" />
+      <method />
+    </configuration>
+    <list size="1">
+      <item index="0" class="java.lang.String" itemvalue="Android App.xscreensaver" />
+    </list>
+    <configuration name="&lt;template&gt;" type="Applet" default="true" selected="false">
+      <option name="MAIN_CLASS_NAME" />
+      <option name="HTML_FILE_NAME" />
+      <option name="HTML_USED" value="false" />
+      <option name="WIDTH" value="400" />
+      <option name="HEIGHT" value="300" />
+      <option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" />
+      <option name="VM_PARAMETERS" />
+    </configuration>
+    <configuration name="&lt;template&gt;" type="#org.jetbrains.idea.devkit.run.PluginConfigurationType" default="true" selected="false">
+      <option name="VM_PARAMETERS" value="-Xmx512m -Xms256m -XX:MaxPermSize=250m -ea" />
+    </configuration>
+  </component>
+  <component name="ShelveChangesManager" show_recycled="false">
+    <option name="remove_strategy" value="false" />
+  </component>
+  <component name="SvnConfiguration">
+    <configuration />
+  </component>
+  <component name="TaskManager">
+    <task active="true" id="Default" summary="Default task">
+      <changelist id="41008724-035d-4e24-92b6-6dfb9231c83c" name="Default" comment="" />
+      <created>1475536195508</created>
+      <option name="number" value="Default" />
+      <option name="presentableId" value="Default" />
+      <updated>1475536195508</updated>
+    </task>
+    <servers />
+  </component>
+  <component name="ToolWindowManager">
+    <frame x="73" y="23" width="1137" height="1029" extended-state="6" />
+    <editor active="false" />
+    <layout>
+      <window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
+      <window_info id="Messages" active="true" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.32968238" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
+      <window_info id="Build Variants" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="true" content_ui="tabs" />
+      <window_info id="Image Layers" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
+      <window_info id="Capture Analysis" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
+      <window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="true" content_ui="tabs" />
+      <window_info id="Android Monitor" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
+      <window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
+      <window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
+      <window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
+      <window_info id="Captures" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
+      <window_info id="Capture Tool" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
+      <window_info id="Gradle Console" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="true" content_ui="tabs" />
+      <window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.2547945" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
+      <window_info id="Gradle" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
+      <window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
+      <window_info id="Android Model" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="true" content_ui="tabs" />
+      <window_info id="Theme Preview" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
+      <window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
+      <window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="true" content_ui="tabs" />
+      <window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
+      <window_info id="Nl-Palette" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
+      <window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
+      <window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="SLIDING" type="SLIDING" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
+      <window_info id="Properties" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
+      <window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
+      <window_info id="Designer" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
+      <window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
+      <window_info id="Palette&#9;" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
+      <window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
+      <window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32968238" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
+    </layout>
+  </component>
+  <component name="Vcs.Log.UiProperties">
+    <option name="RECENTLY_FILTERED_USER_GROUPS">
+      <collection />
+    </option>
+    <option name="RECENTLY_FILTERED_BRANCH_GROUPS">
+      <collection />
+    </option>
+  </component>
+  <component name="VcsContentAnnotationSettings">
+    <option name="myLimit" value="2678400000" />
+  </component>
+  <component name="XDebuggerManager">
+    <breakpoint-manager />
+    <watches-manager />
+  </component>
+</project>
\ No newline at end of file
diff --git a/android/xscreensaver/assets/fonts/OCRAStd.otf b/android/xscreensaver/assets/fonts/OCRAStd.otf
new file mode 120000 (symlink)
index 0000000..6259345
--- /dev/null
@@ -0,0 +1 @@
+../../../../OSX/OCRAStd.otf
\ No newline at end of file
diff --git a/android/xscreensaver/assets/fonts/PxPlus_IBM_VGA8.ttf b/android/xscreensaver/assets/fonts/PxPlus_IBM_VGA8.ttf
new file mode 120000 (symlink)
index 0000000..184d654
--- /dev/null
@@ -0,0 +1 @@
+../../../../OSX/PxPlus_IBM_VGA8.ttf
\ No newline at end of file
diff --git a/android/xscreensaver/assets/fonts/YearlReg.ttf b/android/xscreensaver/assets/fonts/YearlReg.ttf
new file mode 120000 (symlink)
index 0000000..8977be4
--- /dev/null
@@ -0,0 +1 @@
+../../../../OSX/YearlReg.ttf
\ No newline at end of file
diff --git a/android/xscreensaver/build.gradle b/android/xscreensaver/build.gradle
new file mode 100644 (file)
index 0000000..6d1151f
--- /dev/null
@@ -0,0 +1,108 @@
+apply plugin: 'android'
+
+dependencies {
+    compile fileTree(include: '*.jar', dir: 'libs')
+}
+
+android {
+    compileSdkVersion 21
+    buildToolsVersion "21.1.2"
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_7
+        targetCompatibility JavaVersion.VERSION_1_7
+    }
+    sourceSets {
+        main {
+            manifest.srcFile 'AndroidManifest.xml'
+            java.srcDirs = ['src']
+            resources.srcDirs = ['src']
+            aidl.srcDirs = ['src']
+            renderscript.srcDirs = ['src']
+            res.srcDirs = ['res']
+            assets.srcDirs = ['assets']
+            // jniLibs.srcDirs = ['jni']
+            jniLibs.srcDirs = ['libs']
+            jni.srcDirs = [] // disable automatic ndk-build call
+        }
+
+        // Move the tests to tests/java, tests/res, etc...
+        instrumentTest.setRoot('tests')
+
+        // Move the build types to build-types/<type>
+        // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
+        // This moves them out of them default location under src/<type>/... which would
+        // conflict with src/ being used by the main source set.
+        // Adding new build types or product flavors should be accompanied
+        // by a similar customization.
+        debug.setRoot('build-types/debug')
+        release.setRoot('build-types/release')
+    }
+    project.ext.versionCodes = ['armeabi': 1, 'armeabi-v7a': 2, 'arm64-v8a': 3, 'mips': 5, 'mips64': 6, 'x86': 8, 'x86_64': 9]
+    //versionCode digit for each supported ABI, with 64bit>32bit and x86>armeabi-*
+
+
+    // put ndk-build in build's path, or replace below with its full path
+    task ndkBuild(type: Exec) {
+       Properties properties = new Properties()
+         properties.load(project.rootProject.file('local.properties').newDataInputStream())
+       def ndkDir = properties.getProperty('ndk.dir')
+       commandLine "$ndkDir/ndk-build", '-C', file('jni').absolutePath,
+          '-j' + Runtime.getRuntime().availableProcessors().toString()
+    }
+
+    // generate files early in the process
+    task perlBuild(type: Exec) {
+        commandLine 'sh', '-c',
+          'cd ..; ../hacks/check-configs.pl --build-android $ANDROID_HACKS'
+    }
+  
+    task perlClean(type: Delete) {
+        delete('../gen')
+        delete('res/values')
+        delete('res/xml')
+        delete('src/org/jwz/xscreensaver/gen')
+        delete('AndroidManifest.xml')
+    }
+
+    task objlibClean(type: Delete) {
+        delete('./build')
+        delete('./libs')
+        delete('./obj')
+    }
+
+    task downloadNeededDrawables(type: Exec) {
+        commandLine 'sh', '-c',
+          'cd ../ ; \
+           for f in $ANDROID_HACKS; do \
+            f=`echo "$f" | sed s/rd-bomb/rdbomb/` ; \
+             make -s xscreensaver/res/drawable/$f.png ; \
+           done'
+    }
+    preBuild.dependsOn downloadNeededDrawables
+
+    preBuild.dependsOn perlBuild
+
+    clean.dependsOn perlClean
+    clean.dependsOn objlibClean
+
+    tasks.withType(JavaCompile) {
+        options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
+    }
+
+    tasks.withType(JavaCompile) {
+        compileTask -> compileTask.dependsOn ndkBuild
+    }
+
+
+    defaultConfig {
+        minSdkVersion 15
+        targetSdkVersion 21
+    }
+    productFlavors {
+    }
+    buildTypes {
+        debug {
+            jniDebuggable true
+        }
+    }
+}
diff --git a/android/xscreensaver/build.xml b/android/xscreensaver/build.xml
new file mode 100644 (file)
index 0000000..abda7fe
--- /dev/null
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="Xscreensaver" default="help">
+
+    <!-- The local.properties file is created and updated by the 'android' tool.
+         It contains the path to the SDK. It should *NOT* be checked into
+         Version Control Systems. -->
+    <property file="local.properties" />
+
+    <!-- The ant.properties file can be created by you. It is only edited by the
+         'android' tool to add properties to it.
+         This is the place to change some Ant specific build properties.
+         Here are some properties you may want to change/update:
+
+         source.dir
+             The name of the source directory. Default is 'src'.
+         out.dir
+             The name of the output directory. Default is 'bin'.
+
+         For other overridable properties, look at the beginning of the rules
+         files in the SDK, at tools/ant/build.xml
+
+         Properties related to the SDK location or the project target should
+         be updated using the 'android' tool with the 'update' action.
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems.
+
+         -->
+    <property file="ant.properties" />
+
+    <!-- if sdk.dir was not set from one of the property file, then
+         get it from the ANDROID_HOME env var.
+         This must be done before we load project.properties since
+         the proguard config can use sdk.dir -->
+    <property environment="env" />
+    <condition property="sdk.dir" value="${env.ANDROID_HOME}">
+        <isset property="env.ANDROID_HOME" />
+    </condition>
+
+    <!-- The project.properties file is created and updated by the 'android'
+         tool, as well as ADT.
+
+         This contains project specific properties such as project target, and library
+         dependencies. Lower level build properties are stored in ant.properties
+         (or in .classpath for Eclipse projects).
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems. -->
+    <loadproperties srcFile="project.properties" />
+
+    <!-- quick check on sdk.dir -->
+    <fail
+            message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
+            unless="sdk.dir"
+    />
+
+    <!--
+        Import per project custom build rules if present at the root of the project.
+        This is the place to put custom intermediary targets such as:
+            -pre-build
+            -pre-compile
+            -post-compile (This is typically used for code obfuscation.
+                           Compiled code location: ${out.classes.absolute.dir}
+                           If this is not done in place, override ${out.dex.input.absolute.dir})
+            -post-package
+            -post-build
+            -pre-clean
+    -->
+    <import file="custom_rules.xml" optional="true" />
+
+    <!-- Import the actual build file.
+
+         To customize existing targets, there are two options:
+         - Customize only one target:
+             - copy/paste the target into this file, *before* the
+               <import> task.
+             - customize it to your needs.
+         - Customize the whole content of build.xml
+             - copy/paste the content of the rules files (minus the top node)
+               into this file, replacing the <import> task.
+             - customize to your needs.
+
+         ***********************
+         ****** IMPORTANT ******
+         ***********************
+         In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
+         in order to avoid having your file be overridden by tools such as "android update project"
+    -->
+    <!-- version-tag: 1 -->
+    <import file="${sdk.dir}/tools/ant/build.xml" />
+
+</project>
diff --git a/android/xscreensaver/gradle/wrapper/gradle-wrapper.jar b/android/xscreensaver/gradle/wrapper/gradle-wrapper.jar
new file mode 100644 (file)
index 0000000..13372ae
Binary files /dev/null and b/android/xscreensaver/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/android/xscreensaver/gradle/wrapper/gradle-wrapper.properties b/android/xscreensaver/gradle/wrapper/gradle-wrapper.properties
new file mode 100644 (file)
index 0000000..c177021
--- /dev/null
@@ -0,0 +1,6 @@
+#Tue Oct 17 12:24:22 PDT 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
diff --git a/android/xscreensaver/gradlew b/android/xscreensaver/gradlew
new file mode 100644 (file)
index 0000000..9d82f78
--- /dev/null
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+    JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/android/xscreensaver/gradlew.bat b/android/xscreensaver/gradlew.bat
new file mode 100644 (file)
index 0000000..aec9973
--- /dev/null
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off\r
+@rem ##########################################################################\r
+@rem\r
+@rem  Gradle startup script for Windows\r
+@rem\r
+@rem ##########################################################################\r
+\r
+@rem Set local scope for the variables with windows NT shell\r
+if "%OS%"=="Windows_NT" setlocal\r
+\r
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r
+set DEFAULT_JVM_OPTS=\r
+\r
+set DIRNAME=%~dp0\r
+if "%DIRNAME%" == "" set DIRNAME=.\r
+set APP_BASE_NAME=%~n0\r
+set APP_HOME=%DIRNAME%\r
+\r
+@rem Find java.exe\r
+if defined JAVA_HOME goto findJavaFromJavaHome\r
+\r
+set JAVA_EXE=java.exe\r
+%JAVA_EXE% -version >NUL 2>&1\r
+if "%ERRORLEVEL%" == "0" goto init\r
+\r
+echo.\r
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r
+echo.\r
+echo Please set the JAVA_HOME variable in your environment to match the\r
+echo location of your Java installation.\r
+\r
+goto fail\r
+\r
+:findJavaFromJavaHome\r
+set JAVA_HOME=%JAVA_HOME:"=%\r
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe\r
+\r
+if exist "%JAVA_EXE%" goto init\r
+\r
+echo.\r
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r
+echo.\r
+echo Please set the JAVA_HOME variable in your environment to match the\r
+echo location of your Java installation.\r
+\r
+goto fail\r
+\r
+:init\r
+@rem Get command-line arguments, handling Windowz variants\r
+\r
+if not "%OS%" == "Windows_NT" goto win9xME_args\r
+if "%@eval[2+2]" == "4" goto 4NT_args\r
+\r
+:win9xME_args\r
+@rem Slurp the command line arguments.\r
+set CMD_LINE_ARGS=\r
+set _SKIP=2\r
+\r
+:win9xME_args_slurp\r
+if "x%~1" == "x" goto execute\r
+\r
+set CMD_LINE_ARGS=%*\r
+goto execute\r
+\r
+:4NT_args\r
+@rem Get arguments from the 4NT Shell from JP Software\r
+set CMD_LINE_ARGS=%$\r
+\r
+:execute\r
+@rem Setup the command line\r
+\r
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar\r
+\r
+@rem Execute Gradle\r
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\r
+\r
+:end\r
+@rem End local scope for the variables with windows NT shell\r
+if "%ERRORLEVEL%"=="0" goto mainEnd\r
+\r
+:fail\r
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r
+rem the _cmd.exe /c_ return code!\r
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1\r
+exit /b 1\r
+\r
+:mainEnd\r
+if "%OS%"=="Windows_NT" endlocal\r
+\r
+:omega\r
diff --git a/android/xscreensaver/jni/Android.mk b/android/xscreensaver/jni/Android.mk
new file mode 100644 (file)
index 0000000..53ce1f9
--- /dev/null
@@ -0,0 +1,196 @@
+LOCAL_PATH := $(call my-dir)/../../..
+
+# -Wnested-externs would also be here, but for Android unistd.h.
+SHARED_CFLAGS = \
+    -std=c99 \
+    -Wall \
+    -Wstrict-prototypes \
+    -Wmissing-prototypes \
+    -DSTANDALONE=1 \
+    -DHAVE_ANDROID=1 \
+    -DHAVE_GL=1 \
+    -DHAVE_JWXYZ=1 \
+    -DJWXYZ_GL=1 \
+    -DJWXYZ_IMAGE=1 \
+    -DHAVE_JWZGLES=1 \
+    -DHAVE_XUTF8DRAWSTRING=1 \
+    -DHAVE_GLBINDTEXTURE=1 \
+    -DGL_VERSION_ES_CM_1_0 \
+    -DHAVE_UNISTD_H=1 \
+    -DHAVE_INTTYPES_H=1 \
+    -DHAVE_UNAME=1 \
+    -DHAVE_UTIL_H=1 \
+    -DGETTIMEOFDAY_TWO_ARGS=1 \
+    -DHAVE_ICMP=1 \
+    -DHAVE_PTHREAD=1 \
+
+SHARED_C_INCLUDES = \
+    $(LOCAL_PATH) \
+    $(LOCAL_PATH)/android \
+    $(LOCAL_PATH)/utils \
+    $(LOCAL_PATH)/jwxyz \
+    $(LOCAL_PATH)/hacks \
+    $(LOCAL_PATH)/hacks/glx \
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := xscreensaver-gl
+
+LOCAL_SRC_FILES := \
+    android/screenhack-android.c \
+    hacks/glx/dropshadow.c \
+    hacks/glx/chessmodels.c \
+    hacks/glx/fps-gl.c \
+    hacks/glx/gltrackball.c \
+    hacks/glx/glut_stroke.c \
+    hacks/glx/glut_swidth.c \
+    hacks/glx/grab-ximage.c \
+    hacks/glx/marching.c \
+    hacks/glx/normals.c \
+    hacks/glx/rotator.c \
+    hacks/glx/sphere.c \
+    hacks/glx/texfont.c \
+    hacks/glx/trackball.c \
+    hacks/glx/tube.c \
+    hacks/glx/xpm-ximage.c \
+
+# Some savers occupy more than one source file:
+LOCAL_SRC_FILES += \
+    hacks/glx/b_draw.c \
+    hacks/glx/b_lockglue.c \
+    hacks/glx/b_sphere.c \
+    hacks/glx/buildlwo.c \
+    hacks/glx/companion_quad.c \
+    hacks/glx/companion_disc.c \
+    hacks/glx/companion_heart.c \
+    hacks/glx/cow_face.c \
+    hacks/glx/cow_hide.c \
+    hacks/glx/cow_hoofs.c \
+    hacks/glx/cow_horns.c \
+    hacks/glx/cow_tail.c \
+    hacks/glx/cow_udder.c \
+    hacks/glx/dolphin.c \
+    hacks/glx/gllist.c \
+    hacks/glx/glschool_alg.c \
+    hacks/glx/glschool_gl.c \
+    hacks/glx/involute.c \
+    hacks/glx/lament_model.c \
+    hacks/glx/pipeobjs.c \
+    hacks/glx/robot.c \
+    hacks/glx/robot-wireframe.c \
+    hacks/glx/polyhedra-gl.c \
+    hacks/glx/s1_1.c \
+    hacks/glx/s1_2.c \
+    hacks/glx/s1_3.c \
+    hacks/glx/s1_4.c \
+    hacks/glx/s1_5.c \
+    hacks/glx/s1_6.c \
+    hacks/glx/s1_b.c \
+    hacks/glx/seccam.c \
+    hacks/glx/shark.c \
+    hacks/glx/sonar-sim.c \
+    hacks/glx/sonar-icmp.c \
+    hacks/glx/splitflap_obj.c \
+    hacks/glx/sproingiewrap.c \
+    hacks/glx/stonerview-move.c \
+    hacks/glx/stonerview-osc.c \
+    hacks/glx/stonerview-view.c \
+    hacks/glx/swim.c \
+    hacks/glx/tangram_shapes.c \
+    hacks/glx/teapot.c \
+    hacks/glx/toast.c \
+    hacks/glx/toast2.c \
+    hacks/glx/toaster.c \
+    hacks/glx/toaster_base.c \
+    hacks/glx/toaster_handle.c \
+    hacks/glx/toaster_handle2.c \
+    hacks/glx/toaster_jet.c \
+    hacks/glx/toaster_knob.c \
+    hacks/glx/toaster_slots.c \
+    hacks/glx/toaster_wing.c \
+    hacks/glx/tronbit_idle1.c \
+    hacks/glx/tronbit_idle2.c \
+    hacks/glx/tronbit_no.c \
+    hacks/glx/tronbit_yes.c \
+    hacks/glx/tunnel_draw.c \
+    hacks/glx/whale.c \
+
+# The source files of the currently active GL hacks:
+LOCAL_SRC_FILES += $(shell \
+  for f in $$ANDROID_HACKS ; do \
+    if [ "$$f" = "companioncube" ]; then f="companion"; fi ; \
+    if [ -f "../../../hacks/glx/$$f.c" ]; then \
+      echo "hacks/glx/$$f.c" ; \
+    fi ; \
+  done )
+
+LOCAL_C_INCLUDES := $(SHARED_C_INCLUDES)
+LOCAL_CFLAGS += $(SHARED_CFLAGS) -DUSE_GL
+
+include $(BUILD_STATIC_LIBRARY)
+
+##############################################################################
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := xscreensaver
+
+LOCAL_STATIC_LIBRARIES := xscreensaver-gl
+
+# The base framework files:
+LOCAL_SRC_FILES := \
+    jwxyz/jwxyz-android.c \
+    jwxyz/jwxyz-common.c \
+    jwxyz/jwxyz-gl.c \
+    jwxyz/jwxyz-image.c \
+    jwxyz/jwxyz-timers.c \
+    jwxyz/jwzgles.c \
+
+# Utilities used by the hacks:
+LOCAL_SRC_FILES += \
+    hacks/analogtv.c \
+    hacks/delaunay.c \
+    hacks/fps.c \
+    hacks/xlockmore.c \
+    hacks/xpm-pixmap.c \
+    utils/async_netdb.c \
+    utils/aligned_malloc.c \
+    utils/colorbars.c \
+    utils/colors.c \
+    utils/erase.c \
+    utils/grabclient.c \
+    utils/hsv.c \
+    utils/logo.c \
+    utils/minixpm.c \
+    utils/pow2.c \
+    utils/resources.c \
+    utils/spline.c \
+    utils/textclient-mobile.c \
+    utils/thread_util.c \
+    utils/usleep.c \
+    utils/utf8wc.c \
+    utils/xft.c \
+    utils/xshm.c \
+    utils/yarandom.c \
+
+# The source files of the currently active Xlib hacks:
+LOCAL_SRC_FILES += $(shell \
+  for f in $$ANDROID_HACKS ; do \
+    if [ -f "../../../hacks/$$f.c" ]; then \
+      echo "hacks/$$f.c" ; \
+    fi ; \
+  done )
+
+# Some savers occupy more than one source file:
+LOCAL_SRC_FILES += \
+    hacks/apple2-main.c \
+    hacks/asm6502.c \
+    hacks/pacman_ai.c \
+    hacks/pacman_level.c \
+
+LOCAL_LDLIBS := -lGLESv1_CM -ldl -llog -lEGL -latomic -landroid
+
+LOCAL_C_INCLUDES := $(SHARED_C_INCLUDES)
+LOCAL_CFLAGS += $(SHARED_CFLAGS)
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/android/xscreensaver/jni/Application.mk b/android/xscreensaver/jni/Application.mk
new file mode 100644 (file)
index 0000000..a7aa11b
--- /dev/null
@@ -0,0 +1,6 @@
+# Get this value from android/Makefile
+APP_ABI := $(shell echo $$APP_ABI)
+APP_STL := stlport_static
+APP_PLATFORM := android-14
+# ^^ this can be increased
+
diff --git a/android/xscreensaver/local.properties b/android/xscreensaver/local.properties
new file mode 100644 (file)
index 0000000..d530e0d
--- /dev/null
@@ -0,0 +1,11 @@
+## This file is automatically generated by Android Studio.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must *NOT* be checked into Version Control Systems,
+# as it contains information specific to your local configuration.
+#
+# Location of the SDK. This is only used by Gradle.
+# For customization when using a Version Control System, please read the
+# header note.
+#Mon Oct 03 16:09:56 PDT 2016
+sdk.dir=/Users/jwz/Library/Android/sdk
diff --git a/android/xscreensaver/project.properties b/android/xscreensaver/project.properties
new file mode 100644 (file)
index 0000000..1e1e7a3
--- /dev/null
@@ -0,0 +1,15 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+android.library.reference.1=
+# Project target.
+target=android-19
diff --git a/android/xscreensaver/res/drawable-ldpi/icon.png b/android/xscreensaver/res/drawable-ldpi/icon.png
new file mode 100644 (file)
index 0000000..c4d1934
Binary files /dev/null and b/android/xscreensaver/res/drawable-ldpi/icon.png differ
diff --git a/android/xscreensaver/res/drawable-mdpi/icon.png b/android/xscreensaver/res/drawable-mdpi/icon.png
new file mode 100644 (file)
index 0000000..1e14e4b
Binary files /dev/null and b/android/xscreensaver/res/drawable-mdpi/icon.png differ
diff --git a/android/xscreensaver/res/drawable/thumbnail.png b/android/xscreensaver/res/drawable/thumbnail.png
new file mode 100644 (file)
index 0000000..a86c16c
Binary files /dev/null and b/android/xscreensaver/res/drawable/thumbnail.png differ
diff --git a/android/xscreensaver/res/layout-land/activity_xscreensaver.xml b/android/xscreensaver/res/layout-land/activity_xscreensaver.xml
new file mode 100644 (file)
index 0000000..24f33e0
--- /dev/null
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- TODO: Remove action bar; it's redundant. -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="horizontal"
+    android:gravity="center_horizontal"
+    tools:context="org.jwz.xscreensaver.XScreenSaverActivity">
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="fill_parent"
+        android:layout_centerHorizontal="true"
+        android:layout_centerVertical="true"
+        android:gravity="center_vertical"
+        android:orientation="vertical">
+
+        <ImageView
+            android:layout_width="256sp"
+            android:layout_height="256sp"
+            android:layout_centerHorizontal="true"
+            android:src="@drawable/thumbnail" />
+        <!-- TODO: Version number! -->
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="fill_parent"
+        android:layout_centerHorizontal="true"
+        android:layout_centerVertical="true"
+        android:gravity="center_vertical"
+        android:orientation="vertical">
+
+
+        <TextView
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:gravity="center"
+            android:text="XScreenSaver"
+            android:textSize="32sp" />
+        <Button
+            android:id="@+id/apply_wallpaper"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:text="Open live wallpaper list" />
+        <Button
+            android:id="@+id/apply_daydream"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:text="Open Daydream list" />
+        <TextView
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:autoLink="web"
+            android:gravity="center"
+            android:text="https://www.jwz.org/xscreensaver/" />
+    </LinearLayout>
+</LinearLayout>
diff --git a/android/xscreensaver/res/layout/activity_tv_xscreensaver.xml b/android/xscreensaver/res/layout/activity_tv_xscreensaver.xml
new file mode 100644 (file)
index 0000000..a6f9c84
--- /dev/null
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- TODO: Flip layout orientation on rotation. And maybe make scrollable? -->
+<!-- TODO: Remove action bar; it's redundant. -->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    tools:context="org.jwz.xscreensaver.XScreenSaverTVActivity">
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerHorizontal="true"
+        android:layout_centerVertical="true"
+        android:orientation="vertical">
+        <ImageView
+            android:layout_width="256sp"
+            android:layout_height="256sp"
+            android:layout_centerHorizontal="true"
+            android:src="@drawable/thumbnail" />
+        <!-- TODO: Version number! -->
+        <TextView
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:gravity="center"
+            android:text="XScreenSaver"
+            android:textSize="32sp" />
+        <!-- TODO: Either figure out how to open daydream settings directly on
+             Android TV, or change this to say "Open Settings". -->
+        <Button
+            android:id="@+id/apply_daydream"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:text="Open Daydream list" />
+        <TextView
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:autoLink="web"
+            android:gravity="center"
+            android:text="https://www.jwz.org/xscreensaver/" />
+    </LinearLayout>
+</RelativeLayout>
diff --git a/android/xscreensaver/res/layout/activity_xscreensaver.xml b/android/xscreensaver/res/layout/activity_xscreensaver.xml
new file mode 100644 (file)
index 0000000..8adfa00
--- /dev/null
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- TODO: Flip layout orientation on rotation. And maybe make scrollable? -->
+<!-- TODO: Remove action bar; it's redundant. -->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    tools:context="org.jwz.xscreensaver.XScreenSaverActivity">
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerHorizontal="true"
+        android:layout_centerVertical="true"
+        android:orientation="vertical">
+        <ImageView
+            android:layout_width="256sp"
+            android:layout_height="256sp"
+            android:layout_centerHorizontal="true"
+            android:src="@drawable/thumbnail" />
+        <!-- TODO: Version number! -->
+        <TextView
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:gravity="center"
+            android:text="XScreenSaver"
+            android:textSize="32sp" />
+        <Button
+            android:id="@+id/apply_wallpaper"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:text="Open live wallpaper list" />
+        <Button
+            android:id="@+id/apply_daydream"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:text="Open Daydream list" />
+        <TextView
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:autoLink="web"
+            android:gravity="center"
+            android:text="https://www.jwz.org/xscreensaver/" />
+    </LinearLayout>
+</RelativeLayout>
diff --git a/android/xscreensaver/res/layout/main.xml b/android/xscreensaver/res/layout/main.xml
new file mode 100644 (file)
index 0000000..4361cfe
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    >
+</LinearLayout>
diff --git a/android/xscreensaver/res/layout/preference_blurb.xml b/android/xscreensaver/res/layout/preference_blurb.xml
new file mode 100644 (file)
index 0000000..66e6d82
--- /dev/null
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Layout for the description of each screen saver, that appears
+     at the bottom of the preferences screen.  Based on
+     sdk/platforms/android-21/data/res/layout/preference.xml
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeight"
+    android:gravity="center_vertical"
+    android:paddingEnd="?android:attr/scrollbarSize"
+    android:background="?android:attr/selectableItemBackground" >
+
+    <ImageView
+        android:id="@+android:id/icon"
+        android:layout_gravity="top"
+        android:layout_width="40dip"
+        android:layout_height="40dip"
+        android:layout_marginTop="0dip"
+        />
+
+    <RelativeLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="0dip"
+        android:layout_marginEnd="0dip"
+        android:layout_marginTop="6dip"
+        android:layout_marginBottom="6dip"
+        android:layout_weight="1">
+
+        <TextView android:id="@+android:id/summary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@android:id/title"
+            android:layout_alignStart="@android:id/title"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:textColor="?android:attr/textColorPrimary"
+            android:layout_marginTop="8dip"
+            android:maxLines="1000" />
+
+    </RelativeLayout>
+
+</LinearLayout>
diff --git a/android/xscreensaver/res/layout/slider_preference.xml b/android/xscreensaver/res/layout/slider_preference.xml
new file mode 100644 (file)
index 0000000..69647ff
--- /dev/null
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Layout for org/jwz/xscreensaver/SliderPreference.java -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeight"
+    android:gravity="center_vertical"
+    android:paddingEnd="?android:attr/scrollbarSize"
+    android:background="?android:attr/selectableItemBackground" >
+
+    <TextView
+        android:id="@+android:id/title"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:ellipsize="end"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_weight="40"
+        android:width="0dp"
+        android:layout_marginLeft="16dip" />
+
+    <LinearLayout
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_weight="60"
+        android:orientation="vertical"
+        android:layout_marginLeft="0dip" >
+
+        <SeekBar
+            android:id="@+id/slider_preference_seekbar"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" />
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal" >
+
+            <TextView
+                android:id="@+id/slider_preference_low"
+                android:textAppearance="?android:attr/textAppearanceSmall"
+                android:ellipsize="end"
+                android:singleLine="true"
+                android:layout_alignParentLeft="true"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content" />
+
+            <TextView
+                android:id="@+id/slider_preference_high"
+                android:layout_alignParentRight="true"
+                android:textAppearance="?android:attr/textAppearanceSmall"
+                android:ellipsize="end"
+                android:singleLine="true"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content" />
+
+        </RelativeLayout>
+    </LinearLayout>
+</LinearLayout>
diff --git a/android/xscreensaver/src/org/jwz/xscreensaver/SliderPreference.java b/android/xscreensaver/src/org/jwz/xscreensaver/SliderPreference.java
new file mode 100644 (file)
index 0000000..c1a1a1d
--- /dev/null
@@ -0,0 +1,160 @@
+/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * xscreensaver, Copyright (c) 2016 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.
+ *
+ * A numeric preference as a slider, inline in the preferences list.
+ * XML options include:
+ *
+ *  low, high (floats) -- smallest and largest allowed values.
+ *  If low > high, the value increases as the slider's thumb moves left.
+ *
+ *  lowLabel, highLabel (strings) -- labels shown at the left and right
+ *  ends of the slider.
+ *
+ *  integral (boolean) -- whether to use whole numbers instead of floats;
+ */
+
+package org.jwz.xscreensaver;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.content.res.Resources;
+import android.preference.Preference;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.util.Log;
+
+public class SliderPreference extends Preference {
+
+  protected float low, high;
+  protected String low_label, high_label;
+  protected boolean integral;
+  protected float mValue;
+  protected int seekbar_ticks;
+
+  public SliderPreference(Context context, AttributeSet attrs) {
+    this (context, attrs, 0);
+  }
+
+  public SliderPreference (Context context, AttributeSet attrs, int defStyle) {
+    super (context, attrs, defStyle);
+
+    Resources res = context.getResources();
+
+    // Parse these from the "<SliderPreference>" tag
+    low        = Float.parseFloat (attrs.getAttributeValue (null, "low"));
+    high       = Float.parseFloat (attrs.getAttributeValue (null, "high"));
+    integral   = attrs.getAttributeBooleanValue (null, "integral", false);
+    low_label  = res.getString(
+                   attrs.getAttributeResourceValue (null, "lowLabel", 0));
+    high_label = res.getString(
+                   attrs.getAttributeResourceValue (null, "highLabel", 0));
+
+    seekbar_ticks = (integral
+                     ? (int) Math.floor (Math.abs (high - low))
+                     : 100000);
+
+    setWidgetLayoutResource (R.layout.slider_preference);
+  }
+
+
+  @Override
+  protected void onSetInitialValue (boolean restore, Object def) {
+    if (restore) {
+      mValue = getPersistedFloat (low);
+    } else {
+      mValue = (Float) def;
+      persistFloat (mValue);
+    }
+    //Log.d("xscreensaver", String.format("SLIDER INIT %s: %f",
+    //      low_label, mValue));
+  }
+
+  @Override
+  protected Object onGetDefaultValue(TypedArray a, int index) {
+    return a.getFloat (index, low);
+  }
+
+
+  public float getValue() {
+    return mValue;
+  }
+
+  public void setValue (float value) {
+
+    if (low < high) {
+      value = Math.max (low, Math.min (high, value));
+    } else {
+      value = Math.max (high, Math.min (low, value));
+    }
+
+    if (integral)
+      value = Math.round (value);
+
+    if (value != mValue) {
+      //Log.d("xscreensaver", String.format("SLIDER %s: %f", low_label, value));
+      persistFloat (value);
+      mValue = value;
+      notifyChanged();
+    }
+  }
+
+
+  @Override
+  protected View onCreateView (ViewGroup parent) {
+    View view = super.onCreateView(parent);
+
+    TextView low_view = (TextView)
+      view.findViewById (R.id.slider_preference_low);
+    low_view.setText (low_label);
+
+    TextView high_view = (TextView)
+      view.findViewById (R.id.slider_preference_high);
+    high_view.setText (high_label);
+
+    SeekBar seekbar = (SeekBar)
+      view.findViewById (R.id.slider_preference_seekbar);
+    seekbar.setMax (seekbar_ticks);
+
+    float ratio = (mValue - low) / (high - low);
+    int seek_value = (int) (ratio * (float) seekbar_ticks);
+
+    seekbar.setProgress (seek_value);
+
+    final SliderPreference slider = this;
+
+    seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+
+        @Override
+        public void onStopTrackingTouch(SeekBar seekBar) {
+        }
+
+        @Override
+        public void onStartTrackingTouch(SeekBar seekBar) {
+        }
+
+        @Override
+        public void onProgressChanged (SeekBar seekBar, int progress,
+                                       boolean fromUser) {
+          if (fromUser) {
+            float ratio = (float) progress / (float) seekbar_ticks;
+            float value = low + (ratio * (high - low));
+            slider.setValue (value);
+            callChangeListener (progress);
+          }
+        }
+      });
+
+    return view;
+  }
+}
diff --git a/android/xscreensaver/src/org/jwz/xscreensaver/TTFAnalyzer.java b/android/xscreensaver/src/org/jwz/xscreensaver/TTFAnalyzer.java
new file mode 100644 (file)
index 0000000..3d01345
--- /dev/null
@@ -0,0 +1,153 @@
+/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+
+ * Copyright (C) 2011 George Yunaev @ Ulduzsoft
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+
+  http://www.ulduzsoft.com/2012/01/enumerating-the-fonts-on-android-platform/
+ */
+package org.jwz.xscreensaver;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.HashMap;
+// The class which loads the TTF file, parses it and returns the TTF font name
+class TTFAnalyzer
+{
+    // This function parses the TTF file and returns the font name specified in the file
+    public String getTtfFontName( String fontFilename )
+    {
+        try
+        {
+            // Parses the TTF file format.
+            // See http://developer.apple.com/fonts/ttrefman/rm06/Chap6.html
+            m_file = new RandomAccessFile( fontFilename, "r" );
+            // Read the version first
+            int version = readDword();
+            // The version must be either 'true' (0x74727565) or 0x00010000 or 'OTTO' (0x4f54544f) for CFF style fonts.
+            if ( version != 0x74727565 && version != 0x00010000 && version != 0x4f54544f)
+                return null;
+            // The TTF file consist of several sections called "tables", and we need to know how many of them are there.
+            int numTables = readWord();
+            // Skip the rest in the header
+            readWord(); // skip searchRange
+            readWord(); // skip entrySelector
+            readWord(); // skip rangeShift
+            // Now we can read the tables
+            for ( int i = 0; i < numTables; i++ )
+            {
+                // Read the table entry
+                int tag = readDword();
+                readDword(); // skip checksum
+                int offset = readDword();
+                int length = readDword();
+                // Now here' the trick. 'name' field actually contains the textual string name.
+                // So the 'name' string in characters equals to 0x6E616D65
+                if ( tag == 0x6E616D65 )
+                {
+                    // Here's the name section. Read it completely into the allocated buffer
+                    byte[] table = new byte[ length ];
+                    m_file.seek( offset );
+                    read( table );
+                    // This is also a table. See http://developer.apple.com/fonts/ttrefman/rm06/Chap6name.html
+                    // According to Table 36, the total number of table records is stored in the second word, at the offset 2.
+                    // Getting the count and string offset - remembering it's big endian.
+                    int count = getWord( table, 2 );
+                    int string_offset = getWord( table, 4 );
+                    // Record starts from offset 6
+                    for ( int record = 0; record < count; record++ )
+                    {
+                        // Table 37 tells us that each record is 6 words -> 12 bytes, and that the nameID is 4th word so its offset is 6.
+                        // We also need to account for the first 6 bytes of the header above (Table 36), so...
+                        int nameid_offset = record * 12 + 6;
+                        int platformID = getWord( table, nameid_offset );
+                        int nameid_value = getWord( table, nameid_offset + 6 );
+                        // Table 42 lists the valid name Identifiers. We're interested in 4 but not in Unicode encoding (for simplicity).
+                        // The encoding is stored as PlatformID and we're interested in Mac encoding
+                        if ( nameid_value == 4 && platformID == 1 )
+                        {
+                            // We need the string offset and length, which are the word 6 and 5 respectively
+                            int name_length = getWord( table, nameid_offset + 8 );
+                            int name_offset = getWord( table, nameid_offset + 10 );
+                            // The real name string offset is calculated by adding the string_offset
+                            name_offset = name_offset + string_offset;
+                            // Make sure it is inside the array
+                            if ( name_offset >= 0 && name_offset + name_length < table.length )
+                                return new String( table, name_offset, name_length );
+                        }
+                    }
+                }
+            }
+            return null;
+        }
+        catch (FileNotFoundException e)
+        {
+            // Permissions?
+            return null;
+        }
+        catch (IOException e)
+        {
+            // Most likely a corrupted font file
+            return null;
+        }
+    }
+    // Font file; must be seekable
+    private RandomAccessFile m_file = null;
+    // Helper I/O functions
+    private int readByte() throws IOException
+    {
+        return m_file.read() & 0xFF;
+    }
+    private int readWord() throws IOException
+    {
+        int b1 = readByte();
+        int b2 = readByte();
+        return b1 << 8 | b2;
+    }
+    private int readDword() throws IOException
+    {
+        int b1 = readByte();
+        int b2 = readByte();
+        int b3 = readByte();
+        int b4 = readByte();
+        return b1 << 24 | b2 << 16 | b3 << 8 | b4;
+    }
+    private void read( byte [] array ) throws IOException
+    {
+        if ( m_file.read( array ) != array.length )
+            throw new IOException();
+    }
+    // Helper
+    private int getWord( byte [] array, int offset )
+    {
+        int b1 = array[ offset ] & 0xFF;
+        int b2 = array[ offset + 1 ] & 0xFF;
+        return b1 << 8 | b2;
+    }
+}
diff --git a/android/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverActivity.java b/android/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverActivity.java
new file mode 100644 (file)
index 0000000..dea2fad
--- /dev/null
@@ -0,0 +1,60 @@
+/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * xscreensaver, Copyright (c) 2016 Jamie Zawinski <jwz@jwz.org>
+ * and Dennis Sheil <dennis@panaceasupplies.com>
+ *
+ * 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.
+ *
+ * This is the XScreenSaver "application" that just brings up the
+ * Live Wallpaper preferences.
+ */
+
+package org.jwz.xscreensaver;
+
+import android.app.Activity;
+import android.app.WallpaperManager;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.Build;
+import android.os.Bundle;
+import android.view.View;
+import android.provider.Settings;
+
+public class XScreenSaverActivity extends Activity
+  implements View.OnClickListener {
+
+  @Override
+  protected void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    // openList();
+    setContentView(R.layout.activity_xscreensaver);
+
+    findViewById(R.id.apply_wallpaper).setOnClickListener(this);
+    findViewById(R.id.apply_daydream).setOnClickListener(this);
+  }
+
+  @Override
+  public void onClick(View v) {
+    switch (v.getId()) {
+    case R.id.apply_wallpaper:
+      startActivity(new Intent(WallpaperManager.ACTION_LIVE_WALLPAPER_CHOOSER));
+      break;
+
+    case R.id.apply_daydream:
+      String action;
+      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+        action = Settings.ACTION_DREAM_SETTINGS;
+      } else {
+        action = Settings.ACTION_DISPLAY_SETTINGS;
+      }
+      startActivity(new Intent(action));
+      break;
+    }
+  }
+}
diff --git a/android/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverApp.java b/android/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverApp.java
new file mode 100644 (file)
index 0000000..dd1050a
--- /dev/null
@@ -0,0 +1,22 @@
+/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * xscreensaver, Copyright (c) 2016 Jamie Zawinski <jwz@jwz.org>
+ * and Dennis Sheil <dennis@panaceasupplies.com>
+ *
+ * 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.
+ */
+
+package org.jwz.xscreensaver;
+
+import android.app.Application;
+
+public class XScreenSaverApp extends Application {
+  public XScreenSaverApp() {
+    super();
+  }
+}
diff --git a/android/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverDaydream.java b/android/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverDaydream.java
new file mode 100644 (file)
index 0000000..019c98e
--- /dev/null
@@ -0,0 +1,269 @@
+/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * xscreensaver, Copyright (c) 2016-2017 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.
+ *
+ * The superclass of every saver's Daydream.
+ *
+ * Each Daydream needs a distinct subclass in order to show up in the list.
+ * We know which saver we are running by the subclass name; we know which
+ * API to use by how the subclass calls super().
+ */
+
+package org.jwz.xscreensaver;
+
+import android.view.Display;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.view.KeyEvent;
+import android.service.dreams.DreamService;
+import android.view.GestureDetector;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.os.Message;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+
+public class XScreenSaverDaydream extends DreamService {
+
+  private class SaverView extends SurfaceView
+    implements SurfaceHolder.Callback {
+
+    private boolean initTried = false;
+    private jwxyz jwxyz_obj;
+
+    private GestureDetector detector;
+
+    private Runnable on_quit = new Runnable() {
+      @Override
+      public void run() {
+        finish();  // Exit the Daydream
+      }
+    };
+
+    SaverView () {
+      super (XScreenSaverDaydream.this);
+      getHolder().addCallback(this);
+    }
+
+    @Override
+    public void surfaceChanged (SurfaceHolder holder, int format,
+                                int width, int height) {
+
+      if (width == 0 || height == 0) {
+        detector = null;
+        jwxyz_obj.close();
+        jwxyz_obj = null;
+      }
+
+      Log.d ("xscreensaver",
+             String.format("surfaceChanged: %dx%d", width, height));
+
+      /*
+      double r = 0;
+
+      Display d = view.getDisplay();
+
+      if (d != null) {
+        switch (d.getRotation()) {
+        case Surface.ROTATION_90:  r = 90;  break;
+        case Surface.ROTATION_180: r = 180; break;
+        case Surface.ROTATION_270: r = 270; break;
+        }
+      }
+      */
+
+      if (jwxyz_obj == null) {
+        jwxyz_obj = new jwxyz (jwxyz.saverNameOf (XScreenSaverDaydream.this),
+                               XScreenSaverDaydream.this, screenshot,
+                               width, height, holder.getSurface(), on_quit);
+        detector = new GestureDetector (XScreenSaverDaydream.this, jwxyz_obj);
+      } else {
+        jwxyz_obj.resize (width, height);
+      }
+
+      jwxyz_obj.start();
+    }
+
+    @Override
+    public void surfaceCreated (SurfaceHolder holder) {
+      if (!initTried) {
+        initTried = true;
+      } else {
+        if (jwxyz_obj != null) {
+          jwxyz_obj.close();
+          jwxyz_obj = null;
+        }
+      }
+    }
+
+    @Override
+    public void surfaceDestroyed (SurfaceHolder holder) {
+      if (jwxyz_obj != null) {
+        jwxyz_obj.close();
+        jwxyz_obj = null;
+      }
+    }
+
+    @Override
+    public boolean onTouchEvent (MotionEvent event) {
+      detector.onTouchEvent (event);
+      if (event.getAction() == MotionEvent.ACTION_UP)
+        jwxyz_obj.dragEnded (event);
+      return true;
+    }
+
+    @Override
+    public boolean onKeyDown (int keyCode, KeyEvent event) {
+      // In the emulator, this doesn't receive keyboard arrow keys, PgUp, etc.
+      // Some other keys like "Home" are interpreted before we get here, and
+      // function keys do weird shit.
+
+      // TODO: Does this still work? And is the above still true?
+
+      if (view.jwxyz_obj != null)
+        view.jwxyz_obj.sendKeyEvent (event);
+      return true;
+    }
+  }
+
+  private SaverView view;
+  Bitmap screenshot;
+
+  private void LOG (String fmt, Object... args) {
+    Log.d ("xscreensaver",
+           this.getClass().getSimpleName() + ": " +
+           String.format (fmt, args));
+  }
+
+  protected XScreenSaverDaydream () {
+    super();
+  }
+
+  // Called when jwxyz_abort() is called, or other exceptions are thrown.
+  //
+/*
+  @Override
+  public void uncaughtException (Thread thread, Throwable ex) {
+
+    renderer = null;
+    String err = ex.toString();
+    LOG ("Caught exception: %s", err);
+
+    this.finish();  // Exit the Daydream
+
+    final AlertDialog.Builder b = new AlertDialog.Builder(this);
+    b.setMessage (err);
+    b.setCancelable (false);
+    b.setPositiveButton ("Bummer",
+                         new DialogInterface.OnClickListener() {
+                           public void onClick(DialogInterface d, int id) {
+                           }
+                         });
+
+    // #### This isn't working:
+    // "Attempted to add window with non-application token"
+    // "Unable to add window -- token null is not for an application"
+    // I think I need to get an "Activity" to run it on somehow?
+
+    new Handler (Looper.getMainLooper()).post (new Runnable() {
+        public void run() {
+          AlertDialog alert = b.create();
+          alert.setTitle (this.getClass().getSimpleName() + " crashed");
+          alert.setIcon(android.R.drawable.ic_dialog_alert);
+          alert.show();
+        }
+      });
+
+    old_handler.uncaughtException (thread, ex);
+  }
+*/
+
+
+  @Override
+  public void onAttachedToWindow() {
+    super.onAttachedToWindow();
+
+    setInteractive (true);
+    setFullscreen (true);
+    saveScreenshot();
+
+    view = new SaverView ();
+    setContentView (view);
+  }
+
+  public void onDreamingStarted() {
+    super.onDreamingStarted();
+    // view.jwxyz_obj.start();
+  }
+
+  public void onDreamingStopped() {
+    super.onDreamingStopped();
+    view.jwxyz_obj.pause();
+  }
+
+  public void onDetachedFromWindow() {
+    super.onDetachedFromWindow();
+    try {
+      if (view.jwxyz_obj != null)
+        view.jwxyz_obj.pause();
+    } catch (Exception exc) {
+      // Fun fact: Android swallows exceptions coming from here, then crashes
+      // elsewhere.
+      LOG ("onDetachedFromWindow: %s", exc.toString());
+      throw exc;
+    }
+  }
+
+
+  // At startup, before we have blanked the screen, save a screenshot
+  // for later use by the hacks.
+  //
+  private void saveScreenshot() {
+    View view = getWindow().getDecorView().getRootView();
+    if (view == null) {
+      LOG ("unable to get root view for screenshot");
+    } else {
+
+      // This doesn't work:
+  /*
+      boolean was = view.isDrawingCacheEnabled();
+      if (!was) view.setDrawingCacheEnabled (true);
+      view.buildDrawingCache();
+      screenshot = view.getDrawingCache();
+      if (!was) view.setDrawingCacheEnabled (false);
+      if (screenshot == null) {
+        LOG ("unable to get screenshot bitmap from %s", view.toString());
+      } else {
+        screenshot = Bitmap.createBitmap (screenshot);
+      }
+   */
+
+      // This doesn't work either: width and height are both -1...
+
+      int w = view.getLayoutParams().width;
+      int h = view.getLayoutParams().height;
+      if (w <= 0 || h <= 0) {
+        LOG ("unable to get root view for screenshot");
+      } else {
+        screenshot = Bitmap.createBitmap (w, h, Bitmap.Config.ARGB_8888);
+        Canvas c = new Canvas (screenshot);
+        view.layout (0, 0, w, h);
+        view.draw (c);
+      }
+    }
+  }
+}
diff --git a/android/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverSettings.java b/android/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverSettings.java
new file mode 100644 (file)
index 0000000..ce91bc1
--- /dev/null
@@ -0,0 +1,179 @@
+/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * xscreensaver, Copyright (c) 2016 Jamie Zawinski <jwz@jwz.org>
+ * and Dennis Sheil <dennis@panaceasupplies.com>
+ *
+ * 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.
+ *
+ * The superclass of every saver's preferences panel.
+ *
+ * The only reason the subclasses of this class exist is so that we know
+ * which "_settings.xml" to read -- we extract the base name from self's
+ * class.
+ *
+ * project/xscreensaver/res/xml/SAVER_dream.xml refers to it as
+ * android:settingsActivity="SAVER_Settings".  If there was some way
+ * to pass an argument from the XML into here, or to otherwise detect
+ * which Dream was instantiating this Settings, we wouldn't need those
+ * hundreds of Settings subclasses.
+ */
+
+package org.jwz.xscreensaver;
+
+import android.content.SharedPreferences;
+import android.os.Bundle;
+
+import android.content.SharedPreferences;
+import android.preference.PreferenceActivity;
+import android.preference.Preference;
+import android.preference.ListPreference;
+import android.preference.EditTextPreference;
+import android.preference.CheckBoxPreference;
+import org.jwz.xscreensaver.SliderPreference;
+
+import org.jwz.xscreensaver.R;
+import java.util.Map;
+import java.lang.reflect.Field;
+
+public abstract class XScreenSaverSettings extends PreferenceActivity
+  implements SharedPreferences.OnSharedPreferenceChangeListener {
+
+  @Override
+  protected void onCreate (Bundle icicle) {
+    super.onCreate (icicle);
+
+    // Extract the saver name from e.g. "BouncingCowSettings"
+    String name = this.getClass().getSimpleName();
+    String tail = "Settings";
+    if (name.endsWith(tail))
+      name = name.substring (0, name.length() - tail.length());
+    name = name.toLowerCase();
+
+    // #### All of these have been deprecated:
+    //   getPreferenceManager()
+    //   addPreferencesFromResource(int)
+    //   findPreference(CharSequence)
+
+    getPreferenceManager().setSharedPreferencesName (name);
+
+    // read R.xml.SAVER_settings dynamically
+    int res = -1;
+    String pref_class = name + "_settings";
+    try { res = R.xml.class.getDeclaredField(pref_class).getInt (null); }
+    catch (Exception e) { }
+    if (res != -1)
+      addPreferencesFromResource (res);
+
+    final int res_final = res;
+
+    SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
+    prefs.registerOnSharedPreferenceChangeListener (this);
+    updateAllPrefsSummaries (prefs);
+
+    // Find the "Reset to defaults" button and install a click handler on it.
+    //
+    Preference reset = findPreference (name + "_reset");
+    reset.setOnPreferenceClickListener(
+      new Preference.OnPreferenceClickListener() {
+        @Override
+        public boolean onPreferenceClick(Preference preference) {
+
+          SharedPreferences prefs =
+            getPreferenceManager().getSharedPreferences();
+
+          // Wipe everything from the preferences hash, then reload defaults.
+          prefs.edit().clear().commit();
+          getPreferenceScreen().removeAll();
+          addPreferencesFromResource (res_final);
+
+          // I guess we need to re-get this after the removeAll?
+          prefs = getPreferenceManager().getSharedPreferences();
+
+          // But now we need to iterate over every Preference widget and
+          // push the new value down into it.  If you think this all looks
+          // ridiculously non-object-oriented and completely insane, that's
+          // because it is.
+
+          Map <String, ?> keys = prefs.getAll();
+          for (Map.Entry <String, ?> entry : keys.entrySet()) {
+            String key = entry.getKey();
+            String val = String.valueOf (entry.getValue());
+
+            Preference pref = findPreference (key);
+            if (pref instanceof ListPreference) {
+              ((ListPreference) pref).setValue (prefs.getString (key, ""));
+            } else if (pref instanceof SliderPreference) {
+              ((SliderPreference) pref).setValue (prefs.getFloat (key, 0));
+            } else if (pref instanceof EditTextPreference) {
+              ((EditTextPreference) pref).setText (prefs.getString (key, ""));
+            } else if (pref instanceof CheckBoxPreference) {
+              ((CheckBoxPreference) pref).setChecked (
+                prefs.getBoolean (key,false));
+            }
+
+            updatePrefsSummary (prefs, pref);
+          }
+          return true;
+        }
+      });
+  }
+
+  @Override
+  protected void onResume() {
+    super.onResume();
+    SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
+    prefs.registerOnSharedPreferenceChangeListener (this);
+    updateAllPrefsSummaries(prefs);
+  }
+
+  @Override
+  protected void onPause() {
+    getPreferenceManager().getSharedPreferences().
+      unregisterOnSharedPreferenceChangeListener(this);
+    super.onPause();
+  }
+
+  @Override
+  protected void onDestroy() {
+    getPreferenceManager().getSharedPreferences().
+      unregisterOnSharedPreferenceChangeListener(this);
+    super.onDestroy();
+  }
+
+  public void onSharedPreferenceChanged (SharedPreferences sharedPreferences,
+                                         String key) {
+    updatePrefsSummary(sharedPreferences, findPreference(key));
+  }
+
+  protected void updatePrefsSummary(SharedPreferences sharedPreferences,
+                                    Preference pref) {
+    if (pref == null)
+      return;
+
+    if (pref instanceof ListPreference) {
+      pref.setTitle (((ListPreference) pref).getEntry());
+    } else if (pref instanceof SliderPreference) {
+      float v = ((SliderPreference) pref).getValue();
+      int i = (int) Math.floor (v);
+      if (v == i)
+        pref.setSummary (String.valueOf (i));
+      else
+        pref.setSummary (String.valueOf (v));
+    } else if (pref instanceof EditTextPreference) {
+      pref.setSummary (((EditTextPreference) pref).getText());
+    }
+  }
+
+  protected void updateAllPrefsSummaries(SharedPreferences prefs) {
+
+    Map <String, ?> keys = prefs.getAll();
+    for (Map.Entry <String, ?> entry : keys.entrySet()) {
+      updatePrefsSummary (prefs, findPreference (entry.getKey()));
+    }
+  }
+}
diff --git a/android/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverTVActivity.java b/android/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverTVActivity.java
new file mode 100644 (file)
index 0000000..a9f4b55
--- /dev/null
@@ -0,0 +1,50 @@
+/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * xscreensaver, Copyright (c) 2017 Jamie Zawinski <jwz@jwz.org>
+ * and Dennis Sheil <dennis@panaceasupplies.com>
+ *
+ * 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.
+ *
+ * This is the XScreenSaver "application" that just brings up the
+ * Daydream preferences for Android TV.
+ */
+
+package org.jwz.xscreensaver;
+
+import android.app.Activity;
+import android.app.WallpaperManager;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.Build;
+import android.os.Bundle;
+import android.view.View;
+import android.provider.Settings;
+
+public class XScreenSaverTVActivity extends Activity
+  implements View.OnClickListener {
+
+  @Override
+  protected void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    setContentView(R.layout.activity_tv_xscreensaver);
+    findViewById(R.id.apply_daydream).setOnClickListener(this);
+  }
+
+  @Override
+  public void onClick(View v) {
+    switch (v.getId()) {
+
+    case R.id.apply_daydream:
+      String action;
+      Intent intent = new Intent(android.provider.Settings.ACTION_SETTINGS);
+      startActivityForResult(intent, 0);
+      break;
+    }
+  }
+}
diff --git a/android/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverWallpaper.java b/android/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverWallpaper.java
new file mode 100644 (file)
index 0000000..4ce5da5
--- /dev/null
@@ -0,0 +1,105 @@
+/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * xscreensaver, Copyright (c) 2016-2017 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.
+ *
+ * The superclass of every saver's Wallpaper.
+ *
+ * Each Wallpaper needs a distinct subclass in order to show up in the list.
+ * We know which saver we are running by the subclass name; we know which
+ * API to use by how the subclass calls super().
+ */
+
+package org.jwz.xscreensaver;
+
+import android.service.wallpaper.WallpaperService;
+import android.view.GestureDetector;
+import android.view.SurfaceHolder;
+import android.util.Log;
+import java.lang.RuntimeException;
+import java.lang.Thread;
+import org.jwz.xscreensaver.jwxyz;
+
+public class XScreenSaverWallpaper extends WallpaperService
+/*implements GestureDetector.OnGestureListener,
+             GestureDetector.OnDoubleTapListener, */ {
+
+  /* TODO: Input! */
+
+  @Override
+  public Engine onCreateEngine() {
+    // Log.d("xscreensaver", "tid = " + Thread.currentThread().getId());
+    return new XScreenSaverGLEngine();
+  }
+
+  class XScreenSaverGLEngine extends Engine {
+
+    private boolean initTried = false;
+    private jwxyz jwxyz_obj;
+
+    @Override
+    public void onSurfaceCreated (SurfaceHolder holder) {
+      super.onSurfaceCreated(holder);
+
+      if (!initTried) {
+        initTried = true;
+      } else {
+        if (jwxyz_obj != null) {
+          jwxyz_obj.close();
+          jwxyz_obj = null;
+        }
+      }
+    }
+
+    @Override
+    public void onVisibilityChanged(final boolean visible) {
+      if (jwxyz_obj != null) {
+        if (visible)
+          jwxyz_obj.start();
+        else
+          jwxyz_obj.pause();
+      }
+    }
+
+    @Override
+    public void onSurfaceChanged (SurfaceHolder holder, int format,
+                                  int width, int height) {
+
+      super.onSurfaceChanged(holder, format, width, height);
+
+      if (width == 0 || height == 0) {
+        jwxyz_obj.close();
+        jwxyz_obj = null;
+      }
+
+      Log.d ("xscreensaver",
+             String.format("surfaceChanged: %dx%d", width, height));
+
+      if (jwxyz_obj == null) {
+        jwxyz_obj = new jwxyz (jwxyz.saverNameOf(XScreenSaverWallpaper.this),
+                               XScreenSaverWallpaper.this, null,
+                               width, height, holder.getSurface(), null);
+      } else {
+        jwxyz_obj.resize (width, height);
+      }
+
+      jwxyz_obj.start();
+    }
+
+    @Override
+    public void onSurfaceDestroyed (SurfaceHolder holder) {
+      super.onSurfaceDestroyed (holder);
+
+      if (jwxyz_obj != null) {
+        jwxyz_obj.close();
+        jwxyz_obj = null;
+      }
+    }
+  }
+}
diff --git a/android/xscreensaver/src/org/jwz/xscreensaver/jwxyz.java b/android/xscreensaver/src/org/jwz/xscreensaver/jwxyz.java
new file mode 100644 (file)
index 0000000..9ad2c17
--- /dev/null
@@ -0,0 +1,1079 @@
+/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * xscreensaver, Copyright (c) 2016-2017 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.
+ *
+ * This class is how the C implementation of jwxyz calls back into Java
+ * to do things that OpenGL does not have access to without Java-based APIs.
+ * It is the Java companion to jwxyz-android.c and screenhack-android.c.
+ */
+
+package org.jwz.xscreensaver;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.ArrayList;
+import java.util.Random;
+import android.app.AlertDialog;
+import android.view.KeyEvent;
+import android.content.SharedPreferences;
+import android.content.Context;
+import android.content.ContentResolver;
+import android.content.DialogInterface;
+import android.content.res.AssetManager;
+import android.graphics.Typeface;
+import android.graphics.Rect;
+import android.graphics.Paint;
+import android.graphics.Paint.FontMetrics;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.net.Uri;
+import android.view.GestureDetector;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.io.File;
+import java.io.InputStream;
+import java.io.FileOutputStream;
+import java.lang.InterruptedException;
+import java.lang.Runnable;
+import java.lang.Thread;
+import java.util.TimerTask;
+import android.database.Cursor;
+import android.provider.MediaStore;
+import android.provider.MediaStore.MediaColumns;
+import android.media.ExifInterface;
+import org.jwz.xscreensaver.TTFAnalyzer;
+import android.util.Log;
+import android.view.Surface;
+
+
+public class jwxyz
+  implements GestureDetector.OnGestureListener,
+             GestureDetector.OnDoubleTapListener {
+
+  private class PrefListener
+    implements SharedPreferences.OnSharedPreferenceChangeListener {
+
+    @Override
+    public void onSharedPreferenceChanged (SharedPreferences sharedPreferences, String key)
+    {
+      if (key.startsWith(hack + "_")) {
+        if (render != null) {
+          boolean was_animating;
+          synchronized (render) {
+            was_animating = animating_p;
+          }
+          close();
+          if (was_animating)
+            start();
+        }
+      }
+    }
+  };
+
+  private static class SurfaceLost extends Exception {
+    SurfaceLost () {
+      super("surface lost");
+    }
+
+    SurfaceLost (String detailMessage) {
+      super(detailMessage);
+    }
+  }
+
+  public final static int STYLE_BOLD      = 1;
+  public final static int STYLE_ITALIC    = 2;
+  public final static int STYLE_MONOSPACE = 4;
+
+  public final static int FONT_FAMILY = 0;
+  public final static int FONT_FACE   = 1;
+  public final static int FONT_RANDOM = 2;
+
+  private long nativeRunningHackPtr;
+
+  private String hack;
+  private Context app;
+  private Bitmap screenshot;
+
+  SharedPreferences prefs;
+  SharedPreferences.OnSharedPreferenceChangeListener pref_listener;
+  Hashtable<String, String> defaults = new Hashtable<String, String>();
+
+
+  // Maps font names to either: String (system font) or Typeface (bundled).
+  private Hashtable<String, Object> all_fonts =
+    new Hashtable<String, Object>();
+
+  int width, height;
+  Surface surface;
+  boolean animating_p;
+
+  // Doubles as the mutex controlling width/height/animating_p.
+  private Thread render;
+
+  private Runnable on_quit;
+  boolean button_down_p;
+
+  // These are defined in jwxyz-android.c:
+  //
+  private native long nativeInit (String hack,
+                                  Hashtable<String,String> defaults,
+                                  int w, int h, Surface window)
+                                  throws SurfaceLost;
+  private native void nativeResize (int w, int h, double rot);
+  private native long nativeRender ();
+  private native void nativeDone ();
+  public native void sendButtonEvent (int x, int y, boolean down);
+  public native void sendMotionEvent (int x, int y);
+  public native void sendKeyEvent (boolean down_p, int code, int mods);
+
+  private void LOG (String fmt, Object... args) {
+    Log.d ("xscreensaver", hack + ": " + String.format (fmt, args));
+  }
+
+  static public String saverNameOf (Object obj) {
+    // Extract the saver name from e.g. "gen.Daydream$BouncingCow"
+    String name = obj.getClass().getSimpleName();
+    int index = name.lastIndexOf('$');
+    if (index != -1) {
+      index++;
+      name = name.substring (index, name.length() - index);
+    }
+    return name.toLowerCase();
+  }
+
+  // Constructor
+  public jwxyz (String hack, Context app, Bitmap screenshot, int w, int h,
+                Surface surface, Runnable on_quit) {
+
+    this.hack = hack;
+    this.app  = app;
+    this.screenshot = screenshot;
+    this.on_quit = on_quit;
+    this.width = w;
+    this.height = h;
+    this.surface = surface;
+
+    // nativeInit populates 'defaults' with the default values for keys
+    // that are not overridden by SharedPreferences.
+
+    prefs = app.getSharedPreferences (hack, 0);
+
+    // Keep a strong reference to pref_listener, because
+    // registerOnSharedPreferenceChangeListener only uses a weak reference.
+    pref_listener = new PrefListener();
+    prefs.registerOnSharedPreferenceChangeListener (pref_listener);
+
+    scanSystemFonts();
+  }
+
+  protected void finalize() {
+    if (render != null) {
+      LOG ("jwxyz finalized without close. This might be OK.");
+      close();
+    }
+  }
+
+
+  public String getStringResource (String name) {
+
+    name = hack + "_" + name;
+
+    if (prefs.contains(name)) {
+
+      // SharedPreferences is very picky that you request the exact type that
+      // was stored: if it is a float and you ask for a string, you get an
+      // exception instead of the float converted to a string.
+
+      String s = null;
+      try { return prefs.getString (name, "");
+      } catch (Exception e) { }
+
+      try { return Float.toString (prefs.getFloat (name, 0));
+      } catch (Exception e) { }
+
+      try { return Long.toString (prefs.getLong (name, 0));
+      } catch (Exception e) { }
+
+      try { return Integer.toString (prefs.getInt (name, 0));
+      } catch (Exception e) { }
+
+      try { return (prefs.getBoolean (name, false) ? "true" : "false");
+      } catch (Exception e) { }
+    }
+
+    // If we got to here, it's not in there, so return the default.
+    return defaults.get (name);
+  }
+
+
+  private String mungeFontName (String name) {
+    // Roboto-ThinItalic => RobotoThin
+    // AndroidCock Regular => AndroidClock
+    String tails[] = { "Bold", "Italic", "Oblique", "Regular" };
+    for (String tail : tails) {
+      String pres[] = { " ", "-", "_", "" };
+      for (String pre : pres) {
+        int i = name.indexOf(pre + tail);
+        if (i > 0) name = name.substring (0, i);
+      }
+    }
+    return name;
+  }
+
+
+  private void scanSystemFonts() {
+
+    // First parse the system font directories for the global fonts.
+
+    String[] fontdirs = { "/system/fonts", "/system/font", "/data/fonts" };
+    TTFAnalyzer analyzer = new TTFAnalyzer();
+    for (String fontdir : fontdirs) {
+      File dir = new File(fontdir);
+      if (!dir.exists())
+        continue;
+      File[] files = dir.listFiles();
+      if (files == null)
+        continue;
+
+      for (File file : files) {
+        String name = analyzer.getTtfFontName (file.getAbsolutePath());
+        if (name == null) {
+          // LOG ("unparsable system font: %s", file);
+        } else {
+          name = mungeFontName (name);
+          if (! all_fonts.contains (name)) {
+            // LOG ("system font \"%s\" %s", name, file);
+            all_fonts.put (name, name);
+          }
+        }
+      }
+    }
+
+    // Now parse our assets, for our bundled fonts.
+
+    AssetManager am = app.getAssets();
+    String dir = "fonts";
+    String[] files = null;
+    try { files = am.list(dir); }
+    catch (Exception e) { LOG("listing assets: %s", e.toString()); }
+
+    for (String fn : files) {
+      String fn2 = dir + "/" + fn;
+      Typeface t = Typeface.createFromAsset (am, fn2);
+
+      File tmpfile = null;
+      try {
+        tmpfile = new File(app.getCacheDir(), fn);
+        if (tmpfile.createNewFile() == false) {
+          tmpfile.delete();
+          tmpfile.createNewFile();
+        }
+
+        InputStream in = am.open (fn2);
+        FileOutputStream out = new FileOutputStream (tmpfile);
+        byte[] buffer = new byte[1024 * 512];
+        while (in.read(buffer, 0, 1024 * 512) != -1) {
+          out.write(buffer);
+        }
+        out.close();
+        in.close();
+
+        String name = analyzer.getTtfFontName (tmpfile.getAbsolutePath());
+        tmpfile.delete();
+
+        name = mungeFontName (name);
+        all_fonts.put (name, t);
+        // LOG ("asset font \"%s\" %s", name, fn);
+      } catch (Exception e) {
+        if (tmpfile != null) tmpfile.delete();
+        LOG ("error: %s", e.toString());
+      }
+    }
+  }
+
+
+  // Parses family names from X Logical Font Descriptions, including a few
+  // standard X font names that aren't handled by try_xlfd_font().
+  // Returns [ String name, Typeface ]
+  private Object[] parseXLFD (int mask, int traits,
+                              String name, int name_type) {
+    boolean fixed  = false;
+    boolean serif  = false;
+
+    int style_jwxyz = mask & traits;
+
+    if (name_type != FONT_RANDOM) {
+      if ((style_jwxyz & STYLE_BOLD) != 0 ||
+          name.equals("fixed") ||
+          name.equals("courier") ||
+          name.equals("console") ||
+          name.equals("lucidatypewriter") ||
+          name.equals("monospace")) {
+        fixed = true;
+      } else if (name.equals("times") ||
+                 name.equals("georgia") ||
+                 name.equals("serif")) {
+        serif = true;
+      } else if (name.equals("serif-monospace")) {
+        fixed = true;
+        serif = true;
+      }
+    } else {
+      Random r = new Random();
+      serif = r.nextBoolean();      // Not much to randomize here...
+      fixed = (r.nextInt(8) == 0);
+    }
+
+    name = (fixed
+            ? (serif ? "serif-monospace" : "monospace")
+            : (serif ? "serif" : "sans-serif"));
+
+    int style_android = 0;
+    if ((style_jwxyz & STYLE_BOLD) != 0)
+      style_android |= Typeface.BOLD;
+    if ((style_jwxyz & STYLE_ITALIC) != 0)
+      style_android |= Typeface.ITALIC;
+
+    return new Object[] { name, Typeface.create(name, style_android) };
+  }
+
+
+  // Parses "Native Font Name One 12, Native Font Name Two 14".
+  // Returns [ String name, Typeface ]
+  private Object[] parseNativeFont (String name) {
+    Object font2 = all_fonts.get (name);
+    if (font2 instanceof String)
+      font2 = Typeface.create (name, Typeface.NORMAL);
+    return new Object[] { name, (Typeface)font2 };
+  }
+
+
+  // Returns [ Paint paint, String family_name, Float ascent, Float descent ]
+  public Object[] loadFont(int mask, int traits, String name, int name_type,
+                           float size) {
+    Object pair[];
+
+    if (name_type != FONT_RANDOM && name.equals("")) return null;
+
+    if (name_type == FONT_FACE) {
+      pair = parseNativeFont (name);
+    } else {
+      pair = parseXLFD (mask, traits, name, name_type);
+    }
+
+    String name2  = (String)   pair[0];
+    Typeface font = (Typeface) pair[1];
+
+    size *= 2;
+
+    String suffix = (font.isBold() && font.isItalic() ? " bold italic" :
+                     font.isBold()   ? " bold"   :
+                     font.isItalic() ? " italic" :
+                     "");
+    Paint paint = new Paint();
+    paint.setTypeface (font);
+    paint.setTextSize (size);
+    paint.setColor (Color.argb (0xFF, 0xFF, 0xFF, 0xFF));
+
+    LOG ("load font \"%s\" = \"%s %.1f\"", name, name2 + suffix, size);
+
+    FontMetrics fm = paint.getFontMetrics();
+    return new Object[] { paint, name2, -fm.ascent, fm.descent };
+  }
+
+
+  /* Returns a byte[] array containing XCharStruct with an optional
+     bitmap appended to it.
+     lbearing, rbearing, width, ascent, descent: 2 bytes each.
+     Followed by a WxH pixmap, 32 bits per pixel.
+   */
+  public ByteBuffer renderText (Paint paint, String text, boolean render_p,
+                                boolean antialias_p) {
+
+    if (paint == null) {
+      LOG ("no font");
+      return null;
+    }
+
+    /* Font metric terminology, as used by X11:
+
+       "lbearing" is the distance from the logical origin to the leftmost
+       pixel.  If a character's ink extends to the left of the origin, it is
+       negative.
+
+       "rbearing" is the distance from the logical origin to the rightmost
+       pixel.
+
+       "descent" is the distance from the logical origin to the bottommost
+       pixel.  For characters with descenders, it is positive.  For
+       superscripts, it is negative.
+
+       "ascent" is the distance from the logical origin to the topmost pixel.
+       It is the number of pixels above the baseline.
+
+       "width" is the distance from the logical origin to the position where
+       the logical origin of the next character should be placed.
+
+       If "rbearing" is greater than "width", then this character overlaps the
+       following character.  If smaller, then there is trailing blank space.
+
+       The bbox coordinates returned by getTextBounds grow down and right:
+       for a character with ink both above and below the baseline, top is
+       negative and bottom is positive.
+     */
+    paint.setAntiAlias (antialias_p);
+    FontMetrics fm = paint.getFontMetrics();
+    Rect bbox = new Rect();
+    paint.getTextBounds (text, 0, text.length(), bbox);
+
+    /* The bbox returned by getTextBounds measures from the logical origin
+       with right and down being positive.  This means most characters have
+       a negative top, and characters with descenders have a positive bottom.
+     */
+    int lbearing  =  bbox.left;
+    int rbearing  =  bbox.right;
+    int ascent    = -bbox.top;
+    int descent   =  bbox.bottom;
+    int width     = (int) paint.measureText (text);
+
+    int w = rbearing - lbearing;
+    int h = ascent + descent;
+    int size = 5 * 2 + (render_p ? w * h * 4 : 0);
+
+    ByteBuffer bits = ByteBuffer.allocateDirect (size);
+
+    bits.put ((byte) ((lbearing >> 8) & 0xFF));
+    bits.put ((byte) ( lbearing       & 0xFF));
+    bits.put ((byte) ((rbearing >> 8) & 0xFF));
+    bits.put ((byte) ( rbearing       & 0xFF));
+    bits.put ((byte) ((width    >> 8) & 0xFF));
+    bits.put ((byte) ( width          & 0xFF));
+    bits.put ((byte) ((ascent   >> 8) & 0xFF));
+    bits.put ((byte) ( ascent         & 0xFF));
+    bits.put ((byte) ((descent  >> 8) & 0xFF));
+    bits.put ((byte) ( descent        & 0xFF));
+
+    if (render_p && w > 0 && h > 0) {
+      Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+      Canvas canvas = new Canvas (bitmap);
+      canvas.drawText (text, -lbearing, ascent, paint);
+      bitmap.copyPixelsToBuffer (bits);
+      bitmap.recycle();
+    }
+
+    return bits;
+  }
+
+
+  /* Returns the contents of the URL.
+     Loads the URL in a background thread: if the URL has not yet loaded,
+     this will return null.  Once the URL has completely loaded, the full
+     contents will be returned.  Calling this again after that starts the
+     URL loading again.
+   */
+  private String loading_url = null;
+  private ByteBuffer loaded_url_body = null;
+
+  public synchronized ByteBuffer loadURL (String url) {
+
+    if (loaded_url_body != null) {                     // Thread finished
+
+      // LOG ("textclient finished %s", loading_url);
+
+      ByteBuffer bb = loaded_url_body;
+      loading_url = null;
+      loaded_url_body = null;
+      return bb;
+
+    } else if (loading_url != null) {                  // Waiting on thread
+      // LOG ("textclient waiting...");
+      return null;
+
+    } else {                                           // Launch thread
+
+      loading_url = url;
+      LOG ("textclient launching %s...", url);
+
+      new Thread (new Runnable() {
+          public void run() {
+            int size0 = 10240;
+            int size = size0;
+            int count = 0;
+            ByteBuffer body = ByteBuffer.allocateDirect (size);
+
+            try {
+              URL u = new URL (loading_url);
+              // LOG ("textclient thread loading: %s", u.toString());
+              InputStream s = u.openStream();
+              byte buf[] = new byte[10240];
+              while (true) {
+                int n = s.read (buf);
+                if (n == -1) break;
+                // LOG ("textclient thread read %d", n);
+                if (count + n + 1 >= size) {
+                  int size2 = (int) (size * 1.2 + size0);
+                  // LOG ("textclient thread expand %d -> %d", size, size2);
+                  ByteBuffer body2 = ByteBuffer.allocateDirect (size2);
+                  body.rewind();
+                  body2.put (body);
+                  body2.position (count);
+                  body = body2;
+                  size = size2;
+                }
+                body.put (buf, 0, n);
+                count += n;
+              }
+            } catch (Exception e) {
+              LOG ("load URL error: %s", e.toString());
+              body.clear();
+              body.put (e.toString().getBytes());
+              body.put ((byte) 0);
+            }
+
+            // LOG ("textclient thread finished %s (%d)", loading_url, size);
+            loaded_url_body = body;
+          }
+        }).start();
+
+      return null;
+    }
+  }
+
+
+  private ByteBuffer convertBitmap (String name, Bitmap bitmap,
+                                    int target_width, int target_height,
+                                    ExifInterface exif,
+                                    boolean rotate_p) {
+    if (bitmap == null) return null;
+
+    try {
+
+      int width  = bitmap.getWidth();
+      int height = bitmap.getHeight();
+
+      LOG ("read image %s: %d x %d", name, width, height);
+
+      // First rotate the image as per EXIF.
+
+      if (exif != null) {
+        int deg = 0;
+        switch (exif.getAttributeInt (ExifInterface.TAG_ORIENTATION,
+                                      ExifInterface.ORIENTATION_NORMAL)) {
+        case ExifInterface.ORIENTATION_ROTATE_90:  deg = 90;  break;
+        case ExifInterface.ORIENTATION_ROTATE_180: deg = 180; break;
+        case ExifInterface.ORIENTATION_ROTATE_270: deg = 270; break;
+        }
+        if (deg != 0) {
+          LOG ("%s: EXIF rotate %d", name, deg);
+          Matrix matrix = new Matrix();
+          matrix.preRotate (deg);
+          bitmap = Bitmap.createBitmap (bitmap, 0, 0, width, height,
+                                        matrix, true);
+          width  = bitmap.getWidth();
+          height = bitmap.getHeight();
+        }
+      }
+
+      // If the caller requested that we rotate the image to best fit the
+      // screen, rotate it again.  (Could combine this with the above and
+      // avoid copying the image again, but I'm lazy.)
+
+      if (rotate_p &&
+          (width > height) != (target_width > target_height)) {
+        LOG ("%s: rotated to fit screen", name);
+        Matrix matrix = new Matrix();
+        matrix.preRotate (90);
+        bitmap = Bitmap.createBitmap (bitmap, 0, 0, width, height,
+                                      matrix, true);
+        width  = bitmap.getWidth();
+        height = bitmap.getHeight();
+      }
+
+      // Resize the image to be not larger than the screen, potentially
+      // copying it for the third time.
+      // Actually, always scale it, scaling up if necessary.
+
+//    if (width > target_width || height > target_height)
+      {
+        float r1 = target_width  / (float) width;
+        float r2 = target_height / (float) height;
+        float r = (r1 > r2 ? r2 : r1);
+        LOG ("%s: resize %.1f: %d x %d => %d x %d", name,
+             r, width, height, (int) (width * r), (int) (height * r));
+        width  = (int) (width * r);
+        height = (int) (height * r);
+        bitmap = Bitmap.createScaledBitmap (bitmap, width, height, true);
+        width  = bitmap.getWidth();
+        height = bitmap.getHeight();
+      }
+
+      // Now convert it to a ByteBuffer in the form expected by the C caller.
+
+      byte[] nameb = name.getBytes("UTF-8");
+      int size     = bitmap.getByteCount() + 4 + nameb.length + 1;
+
+      ByteBuffer bits = ByteBuffer.allocateDirect (size);
+
+      bits.put ((byte) ((width  >> 8) & 0xFF));
+      bits.put ((byte) ( width        & 0xFF));
+      bits.put ((byte) ((height >> 8) & 0xFF));
+      bits.put ((byte) ( height       & 0xFF));
+      bits.put (nameb);
+      bits.put ((byte) 0);
+
+      // The fourth of five copies.  Good thing these are supercomputers.
+      bitmap.copyPixelsToBuffer (bits);
+
+      return bits;
+
+    } catch (Exception e) {
+      LOG ("image %s unreadable: %s", name, e.toString());
+    }
+
+    return null;
+  }
+
+
+  public ByteBuffer loadRandomImage (int target_width, int target_height,
+                                     boolean rotate_p) {
+
+    int min_size = 480;
+    int max_size = 0x7FFF;
+
+    ArrayList<String> imgs = new ArrayList<String>();
+
+    ContentResolver cr = app.getContentResolver();
+    String[] cols = { MediaColumns.DATA,
+                      MediaColumns.MIME_TYPE,
+                      MediaColumns.WIDTH,
+                      MediaColumns.HEIGHT };
+    Uri uris[] = {
+      android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI,
+      android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI };
+
+    for (int i = 0; i < uris.length; i++) {
+      Cursor cursor = cr.query (uris[i], cols, null, null, null);
+      int j = 0;
+      int path_col   = cursor.getColumnIndexOrThrow (cols[j++]);
+      int type_col   = cursor.getColumnIndexOrThrow (cols[j++]);
+      int width_col  = cursor.getColumnIndexOrThrow (cols[j++]);
+      int height_col = cursor.getColumnIndexOrThrow (cols[j++]);
+      while (cursor.moveToNext()) {
+        String path = cursor.getString(path_col);
+        String type = cursor.getString(type_col);
+        int w = Integer.parseInt (cursor.getString(width_col));
+        int h = Integer.parseInt (cursor.getString(height_col));
+        if (type.startsWith("image/") &&
+            w > min_size && h > min_size &&
+            w < max_size && h < max_size) {
+          imgs.add (path);
+        }
+      }
+      cursor.close();
+    }
+
+    String which = null;
+
+    int count = imgs.size();
+    if (count == 0) {
+      LOG ("no images");
+      return null;
+    }
+
+    int i = new Random().nextInt (count);
+    which = imgs.get (i);
+    LOG ("picked image %d of %d: %s", i, count, which);
+
+    Uri uri = Uri.fromFile (new File (which));
+    String name = uri.getLastPathSegment();
+    Bitmap bitmap = null;
+    ExifInterface exif = null;
+
+    try {
+      bitmap = MediaStore.Images.Media.getBitmap (cr, uri);
+    } catch (Exception e) {
+      LOG ("image %s unloadable: %s", which, e.toString());
+      return null;
+    }
+
+    try {
+      exif = new ExifInterface (uri.getPath());  // If it fails, who cares
+    } catch (Exception e) {
+    }
+
+    ByteBuffer bits = convertBitmap (name, bitmap,
+                                     target_width, target_height,
+                                     exif, rotate_p);
+    bitmap.recycle();
+    return bits;
+  }
+
+
+  public ByteBuffer getScreenshot (int target_width, int target_height,
+                                   boolean rotate_p) {
+    return convertBitmap ("Screenshot", screenshot,
+                          target_width, target_height,
+                          null, rotate_p);
+  }
+
+
+  // Sadly duplicated from jwxyz.h (and thence X.h and keysymdef.h)
+  //
+  private static final int ShiftMask =    (1<<0);
+  private static final int LockMask =     (1<<1);
+  private static final int ControlMask =   (1<<2);
+  private static final int Mod1Mask =     (1<<3);
+  private static final int Mod2Mask =     (1<<4);
+  private static final int Mod3Mask =     (1<<5);
+  private static final int Mod4Mask =     (1<<6);
+  private static final int Mod5Mask =     (1<<7);
+  private static final int Button1Mask =   (1<<8);
+  private static final int Button2Mask =   (1<<9);
+  private static final int Button3Mask =   (1<<10);
+  private static final int Button4Mask =   (1<<11);
+  private static final int Button5Mask =   (1<<12);
+
+  private static final int XK_Shift_L =           0xFFE1;
+  private static final int XK_Shift_R =           0xFFE2;
+  private static final int XK_Control_L =  0xFFE3;
+  private static final int XK_Control_R =  0xFFE4;
+  private static final int XK_Caps_Lock =  0xFFE5;
+  private static final int XK_Shift_Lock = 0xFFE6;
+  private static final int XK_Meta_L =    0xFFE7;
+  private static final int XK_Meta_R =    0xFFE8;
+  private static final int XK_Alt_L =     0xFFE9;
+  private static final int XK_Alt_R =     0xFFEA;
+  private static final int XK_Super_L =           0xFFEB;
+  private static final int XK_Super_R =           0xFFEC;
+  private static final int XK_Hyper_L =           0xFFED;
+  private static final int XK_Hyper_R =           0xFFEE;
+
+  private static final int XK_Home =      0xFF50;
+  private static final int XK_Left =      0xFF51;
+  private static final int XK_Up =        0xFF52;
+  private static final int XK_Right =     0xFF53;
+  private static final int XK_Down =      0xFF54;
+  private static final int XK_Prior =     0xFF55;
+  private static final int XK_Page_Up =           0xFF55;
+  private static final int XK_Next =      0xFF56;
+  private static final int XK_Page_Down =  0xFF56;
+  private static final int XK_End =       0xFF57;
+  private static final int XK_Begin =     0xFF58;
+
+  private static final int XK_F1 =        0xFFBE;
+  private static final int XK_F2 =        0xFFBF;
+  private static final int XK_F3 =        0xFFC0;
+  private static final int XK_F4 =        0xFFC1;
+  private static final int XK_F5 =        0xFFC2;
+  private static final int XK_F6 =        0xFFC3;
+  private static final int XK_F7 =        0xFFC4;
+  private static final int XK_F8 =        0xFFC5;
+  private static final int XK_F9 =        0xFFC6;
+  private static final int XK_F10 =       0xFFC7;
+  private static final int XK_F11 =       0xFFC8;
+  private static final int XK_F12 =       0xFFC9;
+
+  public void sendKeyEvent (KeyEvent event) {
+    int uc    = event.getUnicodeChar();
+    int jcode = event.getKeyCode();
+    int jmods = event.getModifiers();
+    int xcode = 0;
+    int xmods = 0;
+
+    switch (jcode) {
+    case KeyEvent.KEYCODE_SHIFT_LEFT:       xcode = XK_Shift_L;   break;
+    case KeyEvent.KEYCODE_SHIFT_RIGHT:      xcode = XK_Shift_R;   break;
+    case KeyEvent.KEYCODE_CTRL_LEFT:        xcode = XK_Control_L; break;
+    case KeyEvent.KEYCODE_CTRL_RIGHT:       xcode = XK_Control_R; break;
+    case KeyEvent.KEYCODE_CAPS_LOCK:        xcode = XK_Caps_Lock; break;
+    case KeyEvent.KEYCODE_META_LEFT:        xcode = XK_Meta_L;    break;
+    case KeyEvent.KEYCODE_META_RIGHT:       xcode = XK_Meta_R;    break;
+    case KeyEvent.KEYCODE_ALT_LEFT:         xcode = XK_Alt_L;     break;
+    case KeyEvent.KEYCODE_ALT_RIGHT:        xcode = XK_Alt_R;     break;
+
+    case KeyEvent.KEYCODE_HOME:                     xcode = XK_Home;      break;
+    case KeyEvent.KEYCODE_DPAD_LEFT:        xcode = XK_Left;      break;
+    case KeyEvent.KEYCODE_DPAD_UP:          xcode = XK_Up;        break;
+    case KeyEvent.KEYCODE_DPAD_RIGHT:       xcode = XK_Right;     break;
+    case KeyEvent.KEYCODE_DPAD_DOWN:        xcode = XK_Down;      break;
+  //case KeyEvent.KEYCODE_NAVIGATE_PREVIOUS: xcode = XK_Prior;    break;
+    case KeyEvent.KEYCODE_PAGE_UP:          xcode = XK_Page_Up;   break;
+  //case KeyEvent.KEYCODE_NAVIGATE_NEXT:     xcode = XK_Next;     break;
+    case KeyEvent.KEYCODE_PAGE_DOWN:        xcode = XK_Page_Down; break;
+    case KeyEvent.KEYCODE_MOVE_END:         xcode = XK_End;       break;
+    case KeyEvent.KEYCODE_MOVE_HOME:        xcode = XK_Begin;     break;
+
+    case KeyEvent.KEYCODE_F1:               xcode = XK_F1;        break;
+    case KeyEvent.KEYCODE_F2:               xcode = XK_F2;        break;
+    case KeyEvent.KEYCODE_F3:               xcode = XK_F3;        break;
+    case KeyEvent.KEYCODE_F4:               xcode = XK_F4;        break;
+    case KeyEvent.KEYCODE_F5:               xcode = XK_F5;        break;
+    case KeyEvent.KEYCODE_F6:               xcode = XK_F6;        break;
+    case KeyEvent.KEYCODE_F7:               xcode = XK_F7;        break;
+    case KeyEvent.KEYCODE_F8:               xcode = XK_F8;        break;
+    case KeyEvent.KEYCODE_F9:               xcode = XK_F9;        break;
+    case KeyEvent.KEYCODE_F10:              xcode = XK_F10;       break;
+    case KeyEvent.KEYCODE_F11:              xcode = XK_F11;       break;
+    case KeyEvent.KEYCODE_F12:              xcode = XK_F12;       break;
+    default:                                xcode = uc;           break;
+    }
+
+    if (0 != (jmods & KeyEvent.META_SHIFT_ON))     xmods |= ShiftMask;
+    if (0 != (jmods & KeyEvent.META_CAPS_LOCK_ON)) xmods |= LockMask;
+    if (0 != (jmods & KeyEvent.META_CTRL_MASK))    xmods |= ControlMask;
+    if (0 != (jmods & KeyEvent.META_ALT_MASK))    xmods |= Mod1Mask;
+    if (0 != (jmods & KeyEvent.META_META_ON))      xmods |= Mod1Mask;
+    if (0 != (jmods & KeyEvent.META_SYM_ON))       xmods |= Mod2Mask;
+    if (0 != (jmods & KeyEvent.META_FUNCTION_ON))  xmods |= Mod3Mask;
+
+    /* If you touch and release Shift, you get no events.
+       If you type Shift-A, you get Shift down, A down, A up, Shift up.
+       So let's just ignore all lone modifier key events.
+     */
+    if (xcode >= XK_Shift_L && xcode <= XK_Hyper_R)
+      return;
+
+    boolean down_p = event.getAction() == KeyEvent.ACTION_DOWN;
+    sendKeyEvent (down_p, xcode, xmods);
+  }
+
+  void start () {
+    if (render == null) {
+      animating_p = true;
+      render = new Thread(new Runnable() {
+        @Override
+        public void run()
+        {
+          int currentWidth, currentHeight;
+          synchronized (render) {
+            while (true) {
+              while (!animating_p || width == 0 || height == 0) {
+                try {
+                  render.wait();
+                } catch(InterruptedException exc) {
+                  return;
+                }
+              }
+
+              try {
+                nativeInit (hack, defaults, width, height, surface);
+                currentWidth = width;
+                currentHeight= height;
+                break;
+              } catch (SurfaceLost exc) {
+                width = 0;
+                height = 0;
+              }
+            }
+          }
+
+        main_loop:
+          while (true) {
+            synchronized (render) {
+              assert width != 0;
+              assert height != 0;
+              while (!animating_p) {
+                try {
+                  render.wait();
+                } catch(InterruptedException exc) {
+                  break main_loop;
+                }
+              }
+
+              if (currentWidth != width || currentHeight != height) {
+                currentWidth = width;
+                currentHeight = height;
+                nativeResize (width, height, 0);
+              }
+            }
+
+            long delay = nativeRender();
+
+            synchronized (render) {
+              if (delay != 0) {
+                try {
+                  render.wait(delay / 1000, (int)(delay % 1000) * 1000);
+                } catch (InterruptedException exc) {
+                  break main_loop;
+                }
+              } else {
+                if (Thread.interrupted ()) {
+                  break main_loop;
+                }
+              }
+            }
+          }
+
+          assert nativeRunningHackPtr != 0;
+          nativeDone ();
+        }
+      });
+
+      render.start();
+    } else {
+      synchronized(render) {
+        animating_p = true;
+        render.notify();
+      }
+    }
+  }
+
+  void pause () {
+    if (render == null)
+      return;
+    synchronized (render) {
+      animating_p = false;
+      render.notify();
+    }
+  }
+
+  void close () {
+    if (render == null)
+      return;
+    synchronized (render) {
+      animating_p = false;
+      render.interrupt();
+    }
+    try {
+      render.join();
+    } catch (InterruptedException exc) {
+    }
+    render = null;
+  }
+
+  void resize (int w, int h) {
+    assert w != 0;
+    assert h != 0;
+    if (render != null) {
+      synchronized (render) {
+        width = w;
+        height = h;
+        render.notify();
+      }
+    } else {
+      width = w;
+      height = h;
+    }
+  }
+
+
+  /* We distinguish between taps and drags.
+
+     - Drags/pans (down, motion, up) are sent to the saver to handle.
+     - Single-taps exit the saver.
+     - Long-press single-taps are sent to the saver as ButtonPress/Release;
+     - Double-taps are sent to the saver as a "Space" keypress.
+
+     #### TODO:
+     - Swipes (really, two-finger drags/pans) send Up/Down/Left/RightArrow.
+   */
+
+  @Override
+  public boolean onSingleTapConfirmed (MotionEvent event) {
+    if (on_quit != null)
+      on_quit.run();
+    return true;
+  }
+
+  @Override
+  public boolean onDoubleTap (MotionEvent event) {
+    sendKeyEvent (new KeyEvent (KeyEvent.ACTION_DOWN,
+                                KeyEvent.KEYCODE_SPACE));
+    return true;
+  }
+
+  @Override
+  public void onLongPress (MotionEvent event) {
+    if (! button_down_p) {
+      int x = (int) event.getX (event.getPointerId (0));
+      int y = (int) event.getY (event.getPointerId (0));
+      sendButtonEvent (x, y, true);
+      sendButtonEvent (x, y, false);
+    }
+  }
+
+  @Override
+  public void onShowPress (MotionEvent event) {
+    if (! button_down_p) {
+      button_down_p = true;
+      int x = (int) event.getX (event.getPointerId (0));
+      int y = (int) event.getY (event.getPointerId (0));
+      sendButtonEvent (x, y, true);
+    }
+  }
+
+  @Override
+  public boolean onScroll (MotionEvent e1, MotionEvent e2, 
+                           float distanceX, float distanceY) {
+    // LOG ("onScroll: %d", button_down_p ? 1 : 0);
+    if (button_down_p)
+      sendMotionEvent ((int) e2.getX (e2.getPointerId (0)),
+                       (int) e2.getY (e2.getPointerId (0)));
+    return true;
+  }
+
+  // If you drag too fast, you get a single onFling event instead of a
+  // succession of onScroll events.  I can't figure out how to disable it.
+  @Override
+  public boolean onFling (MotionEvent e1, MotionEvent e2, 
+                          float velocityX, float velocityY) {
+    return false;
+  }
+
+  public boolean dragEnded (MotionEvent event) {
+    if (button_down_p) {
+      int x = (int) event.getX (event.getPointerId (0));
+      int y = (int) event.getY (event.getPointerId (0));
+      sendButtonEvent (x, y, false);
+      button_down_p = false;
+    }
+    return true;
+  }
+
+  @Override
+  public boolean onDown (MotionEvent event) {
+    return false;
+  }
+
+  @Override
+  public boolean onSingleTapUp (MotionEvent event) {
+    return false;
+  }
+
+  @Override
+  public boolean onDoubleTapEvent (MotionEvent event) {
+    return false;
+  }
+
+
+  static {
+    System.loadLibrary ("xscreensaver");
+
+/*
+    Thread.setDefaultUncaughtExceptionHandler(
+      new Thread.UncaughtExceptionHandler() {
+        Thread.UncaughtExceptionHandler old_handler =
+          Thread.currentThread().getUncaughtExceptionHandler();
+
+        @Override
+        public void uncaughtException (Thread thread, Throwable ex) {
+          String err = ex.toString();
+          Log.d ("xscreensaver", "Caught exception: " + err);
+          old_handler.uncaughtException (thread, ex);
+        }
+      });
+*/
+  }
+}
diff --git a/android/xscreensaver/xscreensaver.iml b/android/xscreensaver/xscreensaver.iml
new file mode 100644 (file)
index 0000000..cd23018
--- /dev/null
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id=":xscreensaver" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" type="JAVA_MODULE" version="4">
+  <component name="FacetManager">
+    <facet type="android-gradle" name="Android-Gradle">
+      <configuration>
+        <option name="GRADLE_PROJECT_PATH" value=":xscreensaver" />
+      </configuration>
+    </facet>
+    <facet type="android" name="Android">
+      <configuration>
+        <option name="SELECTED_BUILD_VARIANT" value="debug" />
+        <option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
+        <option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
+        <afterSyncTasks>
+          <task>generateDebugSources</task>
+        </afterSyncTasks>
+        <option name="ALLOW_USER_CONFIGURATION" value="false" />
+        <option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/res" />
+      </configuration>
+    </facet>
+  </component>
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
+    <output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
+    <output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/debug" />
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/build-types/debug/res" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/build-types/debug/resources" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/build-types/debug/assets" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/build-types/debug/aidl" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/build-types/debug/java" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/build-types/debug/rs" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/build-types/debug/shaders" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/testDebug/aidl" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/testDebug/java" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/testDebug/rs" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/testDebug/shaders" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/res" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/assets" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
+      <excludeFolder url="file://$MODULE_DIR$/build/outputs" />
+      <excludeFolder url="file://$MODULE_DIR$/build/tmp" />
+    </content>
+    <orderEntry type="jdk" jdkName="Android API 21 Platform" jdkType="Android SDK" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
index c3dd3756732ed419c6e848d1254e45ed4cc55bbb..708552cdef99dfa4b495a78886871863f49bc292 100644 (file)
 /* Define to 1 if you have the `bind_textdomain_codeset' function. */
 #undef HAVE_BIND_TEXTDOMAIN_CODESET
 
+/* Define to 1 if you have the Mac OS X function CFLocaleCopyCurrent in the
+   CoreFoundation framework. */
+#undef HAVE_CFLOCALECOPYCURRENT
+
+/* Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in
+   the CoreFoundation framework. */
+#undef HAVE_CFPREFERENCESCOPYAPPVALUE
+
 /* Define this if you have Gnome and want to build support for the
    xscreensaver control panel in the Gnome Control Center (gnomecc). (This is
    needed only with Gtk 1.x.) */
index 5f1515b1d30a58179ce84a05ab7a9eb1b31aa8dc..9a58e8999afdde0be0bda4beb32616c604d27e87 100755 (executable)
--- a/configure
+++ b/configure
@@ -710,6 +710,7 @@ DATADIRNAME
 CATOBJEXT
 CATALOGS
 MSGFMT_OPTS
+INTL_MACOSX_LIBS
 GETTEXT_PACKAGE
 ALL_LINGUAS
 GMSGFMT
@@ -7708,6 +7709,82 @@ $as_echo "#define HAVE_LC_MESSAGES 1" >>confdefs.h
     XGETTEXT=:
     INTLLIBS=
 
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CFPreferencesCopyAppValue" >&5
+$as_echo_n "checking for CFPreferencesCopyAppValue... " >&6; }
+if ${gt_cv_func_CFPreferencesCopyAppValue+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  gt_save_LIBS="$LIBS"
+     LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation"
+     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <CoreFoundation/CFPreferences.h>
+int
+main ()
+{
+CFPreferencesCopyAppValue(NULL, NULL)
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  gt_cv_func_CFPreferencesCopyAppValue=yes
+else
+  gt_cv_func_CFPreferencesCopyAppValue=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+     LIBS="$gt_save_LIBS"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_CFPreferencesCopyAppValue" >&5
+$as_echo "$gt_cv_func_CFPreferencesCopyAppValue" >&6; }
+  if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then
+
+$as_echo "#define HAVE_CFPREFERENCESCOPYAPPVALUE 1" >>confdefs.h
+
+  fi
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CFLocaleCopyCurrent" >&5
+$as_echo_n "checking for CFLocaleCopyCurrent... " >&6; }
+if ${gt_cv_func_CFLocaleCopyCurrent+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  gt_save_LIBS="$LIBS"
+     LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation"
+     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <CoreFoundation/CFLocale.h>
+int
+main ()
+{
+CFLocaleCopyCurrent();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  gt_cv_func_CFLocaleCopyCurrent=yes
+else
+  gt_cv_func_CFLocaleCopyCurrent=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+     LIBS="$gt_save_LIBS"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_CFLocaleCopyCurrent" >&5
+$as_echo "$gt_cv_func_CFLocaleCopyCurrent" >&6; }
+  if test $gt_cv_func_CFLocaleCopyCurrent = yes; then
+
+$as_echo "#define HAVE_CFLOCALECOPYCURRENT 1" >>confdefs.h
+
+  fi
+  INTL_MACOSX_LIBS=
+  if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then
+    INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation"
+  fi
+
+
+
     ac_fn_c_check_header_mongrel "$LINENO" "libintl.h" "ac_cv_header_libintl_h" "$ac_includes_default"
 if test "x$ac_cv_header_libintl_h" = xyes; then :
   gt_cv_func_dgettext_libintl="no"
@@ -8048,7 +8125,7 @@ done
       fi
 
       if test "$gt_cv_func_dgettext_libintl" = "yes"; then
-        INTLLIBS="-lintl $libintl_extra_libs"
+        INTLLIBS="-lintl $libintl_extra_libs $INTL_MACOSX_LIBS"
       fi
 
       if test "$gt_cv_have_gettext" = "yes"; then
@@ -13311,7 +13388,7 @@ if ${ac_cv_mesagl_version_string+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 13318 "configure"
+#line 13395 "configure"
 #include "confdefs.h"
 #include <GL/gl.h>
 #ifndef MESA_MAJOR_VERSION
index 353bb643f9f5526288cb39603bef1cdb2fc8f5a0..fa2587a905f424666d7a4f5405785a0aa72c1d54 100644 (file)
@@ -4,8 +4,8 @@
 !            a screen saver and locker for the X window system
 !                            by Jamie Zawinski
 !
-!                              version 5.37
-!                              05-Jul-2017
+!                              version 5.38
+!                              20-Dec-2017
 !
 ! See "man xscreensaver" for more info.  The latest version is always
 ! available at https://www.jwz.org/xscreensaver/
@@ -381,6 +381,7 @@ GetViewPortIsFullOfLies: False
 @GL_KLUDGE@ GL:                                raverhoop -root                             \n\
 @GL_KLUDGE@ GL:                                splodesic -root                             \n\
 @GL_KLUDGE@ GL:                                unicrud -root                               \n\
+@GL_KLUDGE@ GL:                                esper -root                                 \n\
 @GL_KLUDGE@ GL:                                vigilance -root                             \n
 
 
@@ -402,15 +403,37 @@ XScreenSaver.bourneShell:         /bin/sh
 ! Resources for the password and splash-screen dialog boxes of
 ! the "xscreensaver" daemon.
 !
-*Dialog.headingFont:           *-helvetica-bold-r-*-*-*-180-*-*-*-iso8859-1
-*Dialog.bodyFont:              *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1
-*Dialog.labelFont:             *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1
-*Dialog.unameFont:             *-helvetica-bold-r-*-*-*-120-*-*-*-iso8859-1
-*Dialog.buttonFont:            *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1
-*Dialog.dateFont:              *-helvetica-medium-r-*-*-*-80-*-*-*-iso8859-1
+*Dialog.headingFont:   -*-helvetica-bold-r-*-*-*-180-*-*-*-*-iso8859-1
+*Dialog.bodyFont:      -*-helvetica-bold-r-*-*-*-140-*-*-*-*-iso8859-1
+*Dialog.labelFont:     -*-helvetica-bold-r-*-*-*-140-*-*-*-*-iso8859-1
+*Dialog.unameFont:     -*-helvetica-bold-r-*-*-*-120-*-*-*-*-iso8859-1
+*Dialog.buttonFont:    -*-helvetica-bold-r-*-*-*-140-*-*-*-*-iso8859-1
+*Dialog.dateFont:      -*-helvetica-medium-r-*-*-*-80-*-*-*-*-iso8859-1
+
+! Fucking Ubuntu doesn't install Helvetica by default! Come ON!
+! What a weirdo exotic font that is, that nobody would care to use!
+!
+*Dialog.headingFont2:  -*-bitstream charter-bold-r-*-*-*-160-*-*-*-*-iso8859-1
+*Dialog.bodyFont2:     -*-bitstream charter-bold-r-*-*-*-120-*-*-*-*-iso8859-1
+*Dialog.labelFont2:    -*-bitstream charter-bold-r-*-*-*-120-*-*-*-*-iso8859-1
+*Dialog.unameFont2:    -*-bitstream charter-bold-r-*-*-*-100-*-*-*-*-iso8859-1
+*Dialog.buttonFont2:   -*-bitstream charter-bold-r-*-*-*-120-*-*-*-*-iso8859-1
+*Dialog.dateFont2:     -*-bitstream charter-medium-r-*-*-*-80-*-*-*-*-iso8859-1
+
+! Fall back to anything variable width that supports ASCII.
+*Dialog.headingFont3:  -*-*-bold-r-*-*-*-180-*-*-p-*-iso8859-1
+*Dialog.bodyFont3:     -*-*-bold-r-*-*-*-140-*-*-p-*-iso8859-1
+*Dialog.labelFont3:    -*-*-bold-r-*-*-*-140-*-*-p-*-iso8859-1
+*Dialog.unameFont3:    -*-*-bold-r-*-*-*-120-*-*-p-*-iso8859-1
+*Dialog.buttonFont3:   -*-*-bold-r-*-*-*-140-*-*-p-*-iso8859-1
+*Dialog.dateFont3:     -*-*-medium-r-*-*-*-80-*-*-p-*-iso8859-1
+
 ! Helvetica asterisks look terrible.
-!*passwd.passwdFont:           *-helvetica-medium-r-*-*-*-140-*-*-*-iso8859-1
-*passwd.passwdFont:            *-courier-medium-r-*-*-*-140-*-*-*-iso8859-1
+*passwd.passwdFont:    -*-courier-medium-r-*-*-*-140-*-*-*-iso8859-1
+*passwd.passwdFont2:   -*-bitstream-courier 10 pitch-medium-r-*-*-*-140-*-*-*-iso8859-1
+*passwd.passwdFont3:   -*-*-medium-r-*-*-*-140-*-m-*-iso8859-1
+*passwd.passwdFont4:   -*-*-medium-r-*-*-*-140-*-c-*-iso8859-1
+
 
 *Dialog.foreground:            #000000
 *Dialog.background:            #E6E6E6
index ded085ece7822d38536a8cb1f6de0bb9be51ae21..577ed6bf7f97822612cc5e4dae73d7bca458fbea 100644 (file)
                                compass -root                               \\n\
                                deluxe -root                                \\n\
 -                              demon -root                                 \\n\
-- GL:                          extrusion -root                             \\n\
+  GL:                          extrusion -root                             \\n\
 -                              loop -root                                  \\n\
                                penetrate -root                             \\n\
                                petri -root                                 \\n\
   GL:                          raverhoop -root                             \\n\
   GL:                          splodesic -root                             \\n\
   GL:                          unicrud -root                               \\n\
+  GL:                          esper -root                                 \\n\
   GL:                          vigilance -root                             \\n",
 "XScreenSaver.pointerPollTime:         0:00:05",
 "XScreenSaver.pointerHysteresis:               10",
 "XScreenSaver.initialDelay:            0:00:00",
 "XScreenSaver.windowCreationTimeout:   0:00:30",
 "XScreenSaver.bourneShell:             /bin/sh",
-"*Dialog.headingFont:          *-helvetica-bold-r-*-*-*-180-*-*-*-iso8859-1",
-"*Dialog.bodyFont:             *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1",
-"*Dialog.labelFont:            *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1",
-"*Dialog.unameFont:            *-helvetica-bold-r-*-*-*-120-*-*-*-iso8859-1",
-"*Dialog.buttonFont:           *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1",
-"*Dialog.dateFont:             *-helvetica-medium-r-*-*-*-80-*-*-*-iso8859-1",
-"*passwd.passwdFont:           *-courier-medium-r-*-*-*-140-*-*-*-iso8859-1",
+"*Dialog.headingFont:  -*-helvetica-bold-r-*-*-*-180-*-*-*-*-iso8859-1",
+"*Dialog.bodyFont:     -*-helvetica-bold-r-*-*-*-140-*-*-*-*-iso8859-1",
+"*Dialog.labelFont:    -*-helvetica-bold-r-*-*-*-140-*-*-*-*-iso8859-1",
+"*Dialog.unameFont:    -*-helvetica-bold-r-*-*-*-120-*-*-*-*-iso8859-1",
+"*Dialog.buttonFont:   -*-helvetica-bold-r-*-*-*-140-*-*-*-*-iso8859-1",
+"*Dialog.dateFont:     -*-helvetica-medium-r-*-*-*-80-*-*-*-*-iso8859-1",
+"*Dialog.headingFont2: -*-bitstream charter-bold-r-*-*-*-160-*-*-*-*-iso8859-1",
+"*Dialog.bodyFont2:    -*-bitstream charter-bold-r-*-*-*-120-*-*-*-*-iso8859-1",
+"*Dialog.labelFont2:   -*-bitstream charter-bold-r-*-*-*-120-*-*-*-*-iso8859-1",
+"*Dialog.unameFont2:   -*-bitstream charter-bold-r-*-*-*-100-*-*-*-*-iso8859-1",
+"*Dialog.buttonFont2:  -*-bitstream charter-bold-r-*-*-*-120-*-*-*-*-iso8859-1",
+"*Dialog.dateFont2:    -*-bitstream charter-medium-r-*-*-*-80-*-*-*-*-iso8859-1",
+"*Dialog.headingFont3: -*-*-bold-r-*-*-*-180-*-*-p-*-iso8859-1",
+"*Dialog.bodyFont3:    -*-*-bold-r-*-*-*-140-*-*-p-*-iso8859-1",
+"*Dialog.labelFont3:   -*-*-bold-r-*-*-*-140-*-*-p-*-iso8859-1",
+"*Dialog.unameFont3:   -*-*-bold-r-*-*-*-120-*-*-p-*-iso8859-1",
+"*Dialog.buttonFont3:  -*-*-bold-r-*-*-*-140-*-*-p-*-iso8859-1",
+"*Dialog.dateFont3:    -*-*-medium-r-*-*-*-80-*-*-p-*-iso8859-1",
+"*passwd.passwdFont:   -*-courier-medium-r-*-*-*-140-*-*-*-iso8859-1",
+"*passwd.passwdFont2:  -*-bitstream-courier 10 pitch-medium-r-*-*-*-140-*-*-*-iso8859-1",
+"*passwd.passwdFont3:  -*-*-medium-r-*-*-*-140-*-m-*-iso8859-1",
+"*passwd.passwdFont4:  -*-*-medium-r-*-*-*-140-*-c-*-iso8859-1",
 "*Dialog.foreground:           #000000",
 "*Dialog.background:           #E6E6E6",
 "*Dialog.Button.foreground:    #000000",
index f5c483965a3a8ead6947abc473d9ea4a823f1c29..03d5244c59e9b87fad33db0413f656f91efbd6f4 100644 (file)
@@ -1,5 +1,5 @@
 /* demo-Gtk.c --- implements the interactive demo-mode and options dialogs.
- * xscreensaver, Copyright (c) 1993-2016 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1993-2017 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
@@ -1039,12 +1039,6 @@ await_xscreensaver (state *s)
                "\n"));
 
       if (root_p)
-
-# ifdef __GNUC__
-        __extension__     /* don't warn about "string length is greater than
-                             the length ISO C89 compilers are required to
-                             support" in the following expression... */
-# endif
         strcat (buf, STFU
          _("You are running as root.  This usually means that xscreensaver\n"
             "was unable to contact your X server because access control is\n"
@@ -2920,7 +2914,6 @@ populate_prefs_page (state *s)
 
     /* DPMS
      */
-dpms_supported=1;
     SENSITIZE ("dpms_frame",              dpms_supported);
     SENSITIZE ("dpms_button",             dpms_supported);
     SENSITIZE ("dpms_quickoff_button",    dpms_supported);
@@ -4630,12 +4623,6 @@ g_log_handler (const gchar *log_domain, GLogLevelFlags log_level,
 }
 
 
-#ifdef __GNUC__
- __extension__     /* shut up about "string length is greater than the length
-                      ISO C89 compilers are required to support" when including
-                      the .ad file... */
-#endif
-
 STFU
 static char *defaults[] = {
 #include "XScreenSaver_ad.h"
index 553e476ee0886597ff6bfd4453a0e6c61732d1ad..a0dd7b87a2a37d507b808aabe0ee8ca00c732754 100644 (file)
@@ -281,6 +281,7 @@ monitor_power_on (saver_info *si, Bool on_p)
 
 void
 sync_server_dpms_settings (Display *dpy, Bool enabled_p,
+                           Bool dpms_quickoff_p,
                            int standby_secs, int suspend_secs, int off_secs,
                            Bool verbose_p)
 {
index ec413aee1a933779522f6b0d9a599bec355382eb..4445c24eb8dd894ecf94f36a8118ec7c7534a04e 100644 (file)
@@ -1,5 +1,5 @@
 /* lock.c --- handling the password dialog for locking-mode.
- * xscreensaver, Copyright (c) 1993-2016 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1993-2017 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
@@ -200,7 +200,6 @@ new_passwd_window (saver_info *si)
   passwd_dialog_data *pw;
   Screen *screen;
   Colormap cmap;
-  char *f;
   saver_screen_info *ssi = &si->screens [mouse_screen (si)];
 
   pw = (passwd_dialog_data *) calloc (1, sizeof(*pw));
@@ -277,40 +276,20 @@ new_passwd_window (saver_info *si)
 
   pw->passwd_string = strdup("");
 
-  f = get_string_resource (si->dpy, "passwd.headingFont", "Dialog.Font");
-  pw->heading_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
-  if (!pw->heading_font) pw->heading_font = XLoadQueryFont (si->dpy, "fixed");
-  if (f) free (f);
-
-  f = get_string_resource (si->dpy, "passwd.buttonFont", "Dialog.Font");
-  pw->button_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
-  if (!pw->button_font) pw->button_font = XLoadQueryFont (si->dpy, "fixed");
-  if (f) free (f);
-
-  f = get_string_resource(si->dpy, "passwd.bodyFont", "Dialog.Font");
-  pw->body_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
-  if (!pw->body_font) pw->body_font = XLoadQueryFont (si->dpy, "fixed");
-  if (f) free (f);
-
-  f = get_string_resource(si->dpy, "passwd.labelFont", "Dialog.Font");
-  pw->label_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
-  if (!pw->label_font) pw->label_font = XLoadQueryFont (si->dpy, "fixed");
-  if (f) free (f);
-
-  f = get_string_resource(si->dpy, "passwd.passwdFont", "Dialog.Font");
-  pw->passwd_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
-  if (!pw->passwd_font) pw->passwd_font = XLoadQueryFont (si->dpy, "fixed");
-  if (f) free (f);
-
-  f = get_string_resource(si->dpy, "passwd.dateFont", "Dialog.Font");
-  pw->date_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
-  if (!pw->date_font) pw->date_font = XLoadQueryFont (si->dpy, "fixed");
-  if (f) free (f);
-
-  f = get_string_resource(si->dpy, "passwd.unameFont", "Dialog.Font");
-  pw->uname_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
-  if (!pw->uname_font) pw->uname_font = XLoadQueryFont (si->dpy, "fixed");
-  if (f) free (f);
+  pw->heading_font =
+    splash_load_font (si->dpy, "passwd.headingFont", "Dialog.Font");
+  pw->button_font =
+    splash_load_font (si->dpy, "passwd.buttonFont", "Dialog.Font");
+  pw->body_font =
+    splash_load_font (si->dpy, "passwd.bodyFont", "Dialog.Font");
+  pw->label_font =
+    splash_load_font (si->dpy, "passwd.labelFont", "Dialog.Font");
+  pw->passwd_font =
+    splash_load_font (si->dpy, "passwd.passwdFont", "Dialog.Font");
+  pw->date_font =
+    splash_load_font (si->dpy, "passwd.dateFont", "Dialog.Font");
+  pw->uname_font =
+    splash_load_font (si->dpy, "passwd.unameFont", "Dialog.Font");
   
   pw->show_uname_p = get_boolean_resource(si->dpy, "passwd.uname", "Boolean");
 
index 38381e06a2ac0407c57428070a55f97d2dbd33f4..e382fa2a58ab42a7911bea4485b6ca41bdc7246c 100644 (file)
@@ -103,6 +103,31 @@ static void do_prefs (saver_screen_info *ssi);
 static void do_help (saver_screen_info *ssi);
 
 
+XFontStruct *
+splash_load_font (Display *dpy, char *name, char *class)
+{
+  /* Try RES, RES2, etc. */
+  int i;
+  for (i = 0; i < 4; i++)
+    {
+      char *name2 = (char *) malloc (strlen(name) + 2);
+      char *s;
+      if (i)
+        sprintf (name2, "%s%d", name, i+1);
+      else
+        strcpy (name2, name);
+      s = get_string_resource (dpy, name2, class);
+      free (name2);
+      if (s && *s)
+        {
+          XFontStruct *f = XLoadQueryFont (dpy, s);
+          if (f) return f;
+        }
+    }
+  return XLoadQueryFont (dpy, "fixed");
+}
+
+
 struct splash_dialog_data {
 
   saver_screen_info *prompt_screen;
@@ -165,7 +190,6 @@ make_splash_dialog (saver_info *si)
   splash_dialog_data *sp;
   saver_screen_info *ssi;
   Colormap cmap;
-  char *f;
 
   Bool whine = decrepit_p ();
 
@@ -246,20 +270,12 @@ make_splash_dialog (saver_info *si)
     sp->heading_label = s;
   }
 
-  f = get_string_resource (si->dpy, "splash.headingFont", "Dialog.Font");
-  sp->heading_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
-  if (!sp->heading_font) sp->heading_font = XLoadQueryFont (si->dpy, "fixed");
-  if (f) free (f);
-
-  f = get_string_resource(si->dpy, "splash.bodyFont", "Dialog.Font");
-  sp->body_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
-  if (!sp->body_font) sp->body_font = XLoadQueryFont (si->dpy, "fixed");
-  if (f) free (f);
-
-  f = get_string_resource(si->dpy, "splash.buttonFont", "Dialog.Font");
-  sp->button_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
-  if (!sp->button_font) sp->button_font = XLoadQueryFont (si->dpy, "fixed");
-  if (f) free (f);
+  sp->heading_font =
+    splash_load_font (si->dpy, "splash.headingFont", "Dialog.Font");
+  sp->body_font =
+    splash_load_font (si->dpy, "splash.bodyFont", "Dialog.Font");
+  sp->button_font =
+    splash_load_font (si->dpy, "splash.buttonFont", "Dialog.Font");
 
   sp->foreground = get_pixel_resource (si->dpy, cmap,
                                        "splash.foreground",
index 2bd62199084b96fe3b00e2b28e6b686a2127d2bf..9b4f98e4dc6fb448f6a917e5c40340ff884a3338 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1998-2016 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1998-2017 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
@@ -168,7 +168,7 @@ main (int argc, char **argv)
   progname = argv[0];
   {
     char *s = strrchr(progname, '/');
-    if (*s) strcpy (progname, s+1);
+    if (*s) progname = s+1;
   }
 
   if (argc != 2) goto USAGE;
index 1a9701aa52121f23ebc9a7269830d5472572fb54..9b2bf8476f1cffff44808fb189243d8ca77b0ad8 100644 (file)
@@ -944,6 +944,9 @@ store_saver_id (saver_screen_info *ssi)
   struct passwd *p = getpwuid (getuid ());
   const char *name, *host;
   char *id;
+# if defined(HAVE_UNAME)
+  struct utsname uts;
+# endif /* UNAME */
 
   /* First store the name and class on the window.
    */
@@ -976,7 +979,6 @@ store_saver_id (saver_screen_info *ssi)
 
 # if defined(HAVE_UNAME)
   {
-    struct utsname uts;
     if (uname (&uts) < 0)
       host = "???";
     else
index 6adf1fdd5e852ca6a9b9987842b88593b34ac987..f4a855df167037655f68772f3dc4b5cea1af7c1e 100644 (file)
@@ -130,8 +130,8 @@ usage: %s -<option>\n\
   -watch        Prints a line each time the screensaver changes state: when\n\
                 the screen blanks, locks, unblanks, or when the running hack\n\
                 is changed.  This option never returns; it is intended for\n\
-                by shell scripts that want to react to the screensaver in\n\
-                some way.\n\
+                use by shell scripts that want to react to the screensaver\n\
+                in some way.\n\
 \n\
   See the man page for more details.\n\
   For updates, check https://www.jwz.org/xscreensaver/\n\
index f702f679294f7c05f353f1ed18ad5460e4987bb3..89cd6d5275c016c983448bbe087c90f21f20e2c6 100644 (file)
@@ -256,9 +256,24 @@ compute_image_scaling (int src_w, int src_h,
       float rw = (float) dest_w  / src_w;
       float rh = (float) dest_h / src_h;
       float r = (rw < rh ? rw : rh);
-      int tw = src_w * r;
-      int th = src_h * r;
-      int pct = (r * 100);
+      int tw, th, pct;
+
+      /* If the window is a goofy aspect ratio, take a middle slice of
+         the image instead. */
+      if (dest_w > dest_h * 5 || dest_h > dest_w * 5)
+        {
+          double r2 = (dest_w > dest_h
+                       ? dest_w / (double) dest_h
+                       : dest_h / (double) dest_w);
+          r *= r2;
+          if (verbose_p)
+            fprintf (stderr, "%s: weird aspect: scaling by %.1f\n",
+                     progname, r2);
+        }
+
+      tw = src_w * r;
+      th = src_h * r;
+      pct = (r * 100);
 
 #if 0
       /* this optimization breaks things */
@@ -281,8 +296,8 @@ compute_image_scaling (int src_w, int src_h,
   if (destx < 0) srcx = -destx, destx = 0;
   if (desty < 0) srcy = -desty, desty = 0;
 
-  if (dest_w < src_w) src_w = dest_w;
-  if (dest_h < src_h) src_h = dest_h;
+  /* if (dest_w < src_w) src_w = dest_w;
+     if (dest_h < src_h) src_h = dest_h; */
 
   *scaled_w_ret = src_w;
   *scaled_h_ret = src_h;
@@ -292,8 +307,8 @@ compute_image_scaling (int src_w, int src_h,
   *scaled_to_y_ret = desty;
 
   if (verbose_p)
-    fprintf (stderr, "%s: displaying %dx%d image at %d,%d in %dx%d.\n",
-             progname, src_w, src_h, destx, desty, dest_w, dest_h);
+    fprintf (stderr, "%s: displaying %dx%d+%d+%d image at %d,%d in %dx%d.\n",
+             progname, src_w, src_h, srcx, srcy, destx, desty, dest_w, dest_h);
 }
 
 
@@ -466,6 +481,8 @@ read_file_gdk (Screen *screen, Window window, Drawable drawable,
          gdk_pixbuf_render_pixmap_and_mask_for_colormap() instead.
          But I haven't tried.
        */
+      if (srcx > 0) w -= srcx;
+      if (srcy > 0) h -= srcy;
       gdk_pixbuf_xlib_render_to_drawable_alpha (pb, drawable,
                                                 srcx, srcy, destx, desty,
                                                 w, h,
@@ -1491,7 +1508,7 @@ drawable_miniscule_p (Display *dpy, Drawable drawable)
   int xx, yy;
   unsigned int bw, d, w = 0, h = 0;
   XGetGeometry (dpy, drawable, &root, &xx, &yy, &w, &h, &bw, &d);
-  return (w < 32 || h < 32);
+  return (w < 32 || h < 30);
 }
 
 
index 877d119857f639f3b2394402ec5497f3dc734faa..42cf7940b27bd0fda8ae78655a69e8dddafac4e8 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1993-2016 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1993-2017 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
@@ -116,6 +116,7 @@ extern int string_width (XFontStruct *font, char *s);
 
 extern void make_splash_dialog (saver_info *si);
 extern void handle_splash_event (saver_info *si, XEvent *e);
+extern XFontStruct *splash_load_font (Display *, char *name, char *class);
 
 
 /* =======================================================================
index 1928429aa58655336f1c4f513b02501733b1b153..12eb67df7d875f0819d16bbf4e35a274e198bc3b 100644 (file)
@@ -162,7 +162,7 @@ is no \fI~/.xscreensaver\fP file yet.)
 To change your power management settings, run
 .BR xscreensaver\-demo (1)
 and change the various timeouts through the user interface.
-Alternately, you can edit the \fI~/.xscreensaver\fP file directly.
+Alternatively, you can edit the \fI~/.xscreensaver\fP file directly.
 
 If the power management section is grayed out in the
 .BR xscreensaver\-demo (1)
index 2a090f6d92ebaed8217f7c6d0f9205e5b66ba946..643a2cae3ed39c2c056157dfe8fd0ce7d4180cbe 100644 (file)
@@ -196,7 +196,8 @@ HACK_OBJS_1 = fps.o $(UTILS_BIN)/resources.o $(UTILS_BIN)/visual.o \
                  $(UTILS_BIN)/usleep.o $(UTILS_BIN)/yarandom.o \
                  $(UTILS_BIN)/utf8wc.o @XMU_OBJS@ @XFT_OBJS@ @ANIM_OBJS@
 HACK_OBJS      = screenhack.o $(HACK_OBJS_1)
-XLOCK_OBJS     = screenhack.o xlockmore.o $(COLOR_OBJS) $(HACK_OBJS_1)
+XLOCK_OBJS     = screenhack.o xlockmore.o $(COLOR_OBJS) $(HACK_OBJS_1) \
+                 $(ERASE)
 COLOR_OBJS     = $(UTILS_BIN)/hsv.o $(UTILS_BIN)/colors.o
 GRAB_OBJS      = $(UTILS_BIN)/grabclient.o
 XSHM_OBJS      = $(UTILS_BIN)/xshm.o
@@ -262,6 +263,7 @@ EXTRAS              = README Makefile.in xml2man.pl m6502.sh .gdbinit \
                  images/noseguy/$(STAR).xbm \
                  images/noseguy/$(STAR).xpm \
                  images/m6502/$(STAR).asm \
+                 images/m6502/$(STAR).txt \
                  images/molecules/$(STAR).pdb \
                  images/pacman/$(STAR).xpm
 
@@ -874,8 +876,9 @@ hexadrop:   hexadrop.o      $(HACK_OBJS) $(COL)
 tessellimage:  tessellimage.o  delaunay.o $(HACK_OBJS) $(GRAB)
        $(CC_HACK) -o $@ $@.o   delaunay.o $(HACK_OBJS) $(GRAB) $(HACK_LIBS)
 
-testx11:       testx11.o       glx/rotator.o $(HACK_OBJS)
-       $(CC_HACK) -o $@ $@.o   glx/rotator.o $(HACK_OBJS) $(COL) $(HACK_LIBS)
+testx11:       testx11.o       glx/rotator.o $(HACK_OBJS) $(COL) $(BARS) $(ERASE)
+       $(CC_HACK) -o $@ $@.o   glx/rotator.o $(HACK_OBJS) $(COL) $(BARS) $(ERASE) $(HACK_LIBS)
+
 glx/rotator.o: glx/rotator.c
        cd glx ; \
        $(MAKE) $(@F) CC="$(CC)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)"
@@ -886,20 +889,20 @@ glx/rotator.o:    glx/rotator.c
 bouboule:      bouboule.o      $(XLOCK_OBJS)
        $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(HACK_LIBS)
 
-braid:         braid.o         $(XLOCK_OBJS) $(ERASE)
-       $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(ERASE) $(HACK_LIBS)
+braid:         braid.o         $(XLOCK_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(HACK_LIBS)
 
-drift:         drift.o         $(XLOCK_OBJS) $(ERASE)
-       $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(ERASE) $(HACK_LIBS)
+drift:         drift.o         $(XLOCK_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(HACK_LIBS)
 
 flag:          flag.o          $(XLOCK_OBJS) $(XPM)
        $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(XPM) $(XPM_LIBS)
 
-forest:                forest.o        $(XLOCK_OBJS) $(ERASE)
-       $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(ERASE) $(HACK_LIBS)
+forest:                forest.o        $(XLOCK_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(HACK_LIBS)
 
-vines:         vines.o         $(XLOCK_OBJS) $(ERASE)
-       $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(ERASE) $(HACK_LIBS)
+vines:         vines.o         $(XLOCK_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(HACK_LIBS)
 
 galaxy:                galaxy.o        $(XLOCK_OBJS)
        $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(HACK_LIBS)
@@ -907,8 +910,8 @@ galaxy:             galaxy.o        $(XLOCK_OBJS)
 grav:          grav.o          $(XLOCK_OBJS)
        $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(HACK_LIBS)
 
-hopalong:      hopalong.o      $(XLOCK_OBJS) $(ERASE)
-       $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(ERASE) $(HACK_LIBS)
+hopalong:      hopalong.o      $(XLOCK_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(HACK_LIBS)
 
 julia:         julia.o         $(XLOCK_OBJS)
        $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(HACK_LIBS)
@@ -961,8 +964,8 @@ worm:               worm.o          $(XLOCK_OBJS)
 rotor:         rotor.o         $(XLOCK_OBJS)
        $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(HACK_LIBS)
 
-ant:           ant.o           $(XLOCK_OBJS) $(ERASE)
-       $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(ERASE) $(HACK_LIBS)
+ant:           ant.o           $(XLOCK_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(HACK_LIBS)
 
 demon:         demon.o         $(XLOCK_OBJS)
        $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(HACK_LIBS)
@@ -973,14 +976,14 @@ loop:             loop.o          $(XLOCK_OBJS)
 flow:          flow.o          $(XLOCK_OBJS)
        $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(HACK_LIBS)
 
-discrete:      discrete.o      $(XLOCK_OBJS) $(ERASE)
-       $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(ERASE) $(HACK_LIBS)
+discrete:      discrete.o      $(XLOCK_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(HACK_LIBS)
 
 crystal:       crystal.o       $(XLOCK_OBJS)
        $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(HACK_LIBS)
 
-apollonian:    apollonian.o    $(XLOCK_OBJS) $(ERASE)
-       $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(ERASE) $(HACK_LIBS)
+apollonian:    apollonian.o    $(XLOCK_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(HACK_LIBS)
 
 euler2d:       euler2d.o       $(XLOCK_OBJS)
        $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(HACK_LIBS)
@@ -988,8 +991,8 @@ euler2d:    euler2d.o       $(XLOCK_OBJS)
 juggle:                juggle.o        $(XLOCK_OBJS)
        $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(HACK_LIBS)
 
-polyominoes:   polyominoes.o   $(XLOCK_OBJS) $(ERASE)
-       $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(ERASE) $(HACK_LIBS)
+polyominoes:   polyominoes.o   $(XLOCK_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(HACK_LIBS)
 
 thornbird:     thornbird.o     $(XLOCK_OBJS)
        $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(HACK_LIBS)
@@ -1071,7 +1074,6 @@ ant.o: $(UTILS_SRC)/hsv.h
 ant.o: $(UTILS_SRC)/resources.h
 ant.o: $(UTILS_SRC)/usleep.h
 ant.o: $(UTILS_SRC)/visual.h
-ant.o: $(UTILS_SRC)/xshm.h
 ant.o: $(UTILS_SRC)/yarandom.h
 ant.o: $(srcdir)/xlockmoreI.h
 ant.o: $(srcdir)/xlockmore.h
@@ -1085,7 +1087,6 @@ apollonian.o: $(UTILS_SRC)/hsv.h
 apollonian.o: $(UTILS_SRC)/resources.h
 apollonian.o: $(UTILS_SRC)/usleep.h
 apollonian.o: $(UTILS_SRC)/visual.h
-apollonian.o: $(UTILS_SRC)/xshm.h
 apollonian.o: $(UTILS_SRC)/yarandom.h
 apollonian.o: $(srcdir)/xlockmoreI.h
 apollonian.o: $(srcdir)/xlockmore.h
@@ -1189,12 +1190,12 @@ bouboule.o: ../config.h
 bouboule.o: $(srcdir)/fps.h
 bouboule.o: $(srcdir)/screenhackI.h
 bouboule.o: $(UTILS_SRC)/colors.h
+bouboule.o: $(UTILS_SRC)/erase.h
 bouboule.o: $(UTILS_SRC)/grabscreen.h
 bouboule.o: $(UTILS_SRC)/hsv.h
 bouboule.o: $(UTILS_SRC)/resources.h
 bouboule.o: $(UTILS_SRC)/usleep.h
 bouboule.o: $(UTILS_SRC)/visual.h
-bouboule.o: $(UTILS_SRC)/xshm.h
 bouboule.o: $(UTILS_SRC)/yarandom.h
 bouboule.o: $(srcdir)/xlockmoreI.h
 bouboule.o: $(srcdir)/xlockmore.h
@@ -1220,7 +1221,6 @@ braid.o: $(UTILS_SRC)/hsv.h
 braid.o: $(UTILS_SRC)/resources.h
 braid.o: $(UTILS_SRC)/usleep.h
 braid.o: $(UTILS_SRC)/visual.h
-braid.o: $(UTILS_SRC)/xshm.h
 braid.o: $(UTILS_SRC)/yarandom.h
 braid.o: $(srcdir)/xlockmoreI.h
 braid.o: $(srcdir)/xlockmore.h
@@ -1238,6 +1238,7 @@ bsod.o: $(srcdir)/images/macbomb.xbm
 bsod.o: $(srcdir)/images/mac.xbm
 bsod.o: $(srcdir)/images/osx_10_2.xpm
 bsod.o: $(srcdir)/images/osx_10_3.xpm
+bsod.o: $(srcdir)/images/ransomware.xpm
 bsod.o: $(srcdir)/screenhackI.h
 bsod.o: $(srcdir)/screenhack.h
 bsod.o: $(UTILS_SRC)/aligned_malloc.h
@@ -1398,12 +1399,12 @@ crystal.o: ../config.h
 crystal.o: $(srcdir)/fps.h
 crystal.o: $(srcdir)/screenhackI.h
 crystal.o: $(UTILS_SRC)/colors.h
+crystal.o: $(UTILS_SRC)/erase.h
 crystal.o: $(UTILS_SRC)/grabscreen.h
 crystal.o: $(UTILS_SRC)/hsv.h
 crystal.o: $(UTILS_SRC)/resources.h
 crystal.o: $(UTILS_SRC)/usleep.h
 crystal.o: $(UTILS_SRC)/visual.h
-crystal.o: $(UTILS_SRC)/xshm.h
 crystal.o: $(UTILS_SRC)/yarandom.h
 crystal.o: $(srcdir)/xlockmoreI.h
 crystal.o: $(srcdir)/xlockmore.h
@@ -1472,12 +1473,12 @@ demon.o: ../config.h
 demon.o: $(srcdir)/fps.h
 demon.o: $(srcdir)/screenhackI.h
 demon.o: $(UTILS_SRC)/colors.h
+demon.o: $(UTILS_SRC)/erase.h
 demon.o: $(UTILS_SRC)/grabscreen.h
 demon.o: $(UTILS_SRC)/hsv.h
 demon.o: $(UTILS_SRC)/resources.h
 demon.o: $(UTILS_SRC)/usleep.h
 demon.o: $(UTILS_SRC)/visual.h
-demon.o: $(UTILS_SRC)/xshm.h
 demon.o: $(UTILS_SRC)/yarandom.h
 demon.o: $(srcdir)/xlockmoreI.h
 demon.o: $(srcdir)/xlockmore.h
@@ -1491,7 +1492,6 @@ discrete.o: $(UTILS_SRC)/hsv.h
 discrete.o: $(UTILS_SRC)/resources.h
 discrete.o: $(UTILS_SRC)/usleep.h
 discrete.o: $(UTILS_SRC)/visual.h
-discrete.o: $(UTILS_SRC)/xshm.h
 discrete.o: $(UTILS_SRC)/yarandom.h
 discrete.o: $(srcdir)/xlockmoreI.h
 discrete.o: $(srcdir)/xlockmore.h
@@ -1517,7 +1517,6 @@ drift.o: $(UTILS_SRC)/hsv.h
 drift.o: $(UTILS_SRC)/resources.h
 drift.o: $(UTILS_SRC)/usleep.h
 drift.o: $(UTILS_SRC)/visual.h
-drift.o: $(UTILS_SRC)/xshm.h
 drift.o: $(UTILS_SRC)/yarandom.h
 drift.o: $(srcdir)/xlockmoreI.h
 drift.o: $(srcdir)/xlockmore.h
@@ -1548,12 +1547,12 @@ euler2d.o: ../config.h
 euler2d.o: $(srcdir)/fps.h
 euler2d.o: $(srcdir)/screenhackI.h
 euler2d.o: $(UTILS_SRC)/colors.h
+euler2d.o: $(UTILS_SRC)/erase.h
 euler2d.o: $(UTILS_SRC)/grabscreen.h
 euler2d.o: $(UTILS_SRC)/hsv.h
 euler2d.o: $(UTILS_SRC)/resources.h
 euler2d.o: $(UTILS_SRC)/usleep.h
 euler2d.o: $(UTILS_SRC)/visual.h
-euler2d.o: $(UTILS_SRC)/xshm.h
 euler2d.o: $(UTILS_SRC)/yarandom.h
 euler2d.o: $(srcdir)/xlockmoreI.h
 euler2d.o: $(srcdir)/xlockmore.h
@@ -1561,12 +1560,12 @@ fadeplot.o: ../config.h
 fadeplot.o: $(srcdir)/fps.h
 fadeplot.o: $(srcdir)/screenhackI.h
 fadeplot.o: $(UTILS_SRC)/colors.h
+fadeplot.o: $(UTILS_SRC)/erase.h
 fadeplot.o: $(UTILS_SRC)/grabscreen.h
 fadeplot.o: $(UTILS_SRC)/hsv.h
 fadeplot.o: $(UTILS_SRC)/resources.h
 fadeplot.o: $(UTILS_SRC)/usleep.h
 fadeplot.o: $(UTILS_SRC)/visual.h
-fadeplot.o: $(UTILS_SRC)/xshm.h
 fadeplot.o: $(UTILS_SRC)/yarandom.h
 fadeplot.o: $(srcdir)/xlockmoreI.h
 fadeplot.o: $(srcdir)/xlockmore.h
@@ -1574,12 +1573,12 @@ fiberlamp.o: ../config.h
 fiberlamp.o: $(srcdir)/fps.h
 fiberlamp.o: $(srcdir)/screenhackI.h
 fiberlamp.o: $(UTILS_SRC)/colors.h
+fiberlamp.o: $(UTILS_SRC)/erase.h
 fiberlamp.o: $(UTILS_SRC)/grabscreen.h
 fiberlamp.o: $(UTILS_SRC)/hsv.h
 fiberlamp.o: $(UTILS_SRC)/resources.h
 fiberlamp.o: $(UTILS_SRC)/usleep.h
 fiberlamp.o: $(UTILS_SRC)/visual.h
-fiberlamp.o: $(UTILS_SRC)/xshm.h
 fiberlamp.o: $(UTILS_SRC)/yarandom.h
 fiberlamp.o: $(srcdir)/xlockmoreI.h
 fiberlamp.o: $(srcdir)/xlockmore.h
@@ -1599,12 +1598,12 @@ flag.o: $(srcdir)/fps.h
 flag.o: $(srcdir)/images/bob.xbm
 flag.o: $(srcdir)/screenhackI.h
 flag.o: $(UTILS_SRC)/colors.h
+flag.o: $(UTILS_SRC)/erase.h
 flag.o: $(UTILS_SRC)/grabscreen.h
 flag.o: $(UTILS_SRC)/hsv.h
 flag.o: $(UTILS_SRC)/resources.h
 flag.o: $(UTILS_SRC)/usleep.h
 flag.o: $(UTILS_SRC)/visual.h
-flag.o: $(UTILS_SRC)/xshm.h
 flag.o: $(UTILS_SRC)/yarandom.h
 flag.o: $(srcdir)/xlockmoreI.h
 flag.o: $(srcdir)/xlockmore.h
@@ -1624,12 +1623,12 @@ flow.o: ../config.h
 flow.o: $(srcdir)/fps.h
 flow.o: $(srcdir)/screenhackI.h
 flow.o: $(UTILS_SRC)/colors.h
+flow.o: $(UTILS_SRC)/erase.h
 flow.o: $(UTILS_SRC)/grabscreen.h
 flow.o: $(UTILS_SRC)/hsv.h
 flow.o: $(UTILS_SRC)/resources.h
 flow.o: $(UTILS_SRC)/usleep.h
 flow.o: $(UTILS_SRC)/visual.h
-flow.o: $(UTILS_SRC)/xshm.h
 flow.o: $(UTILS_SRC)/yarandom.h
 flow.o: $(srcdir)/xlockmoreI.h
 flow.o: $(srcdir)/xlockmore.h
@@ -1664,12 +1663,12 @@ forest.o: ../config.h
 forest.o: $(srcdir)/fps.h
 forest.o: $(srcdir)/screenhackI.h
 forest.o: $(UTILS_SRC)/colors.h
+forest.o: $(UTILS_SRC)/erase.h
 forest.o: $(UTILS_SRC)/grabscreen.h
 forest.o: $(UTILS_SRC)/hsv.h
 forest.o: $(UTILS_SRC)/resources.h
 forest.o: $(UTILS_SRC)/usleep.h
 forest.o: $(UTILS_SRC)/visual.h
-forest.o: $(UTILS_SRC)/xshm.h
 forest.o: $(UTILS_SRC)/yarandom.h
 forest.o: $(srcdir)/xlockmoreI.h
 forest.o: $(srcdir)/xlockmore.h
@@ -1699,12 +1698,12 @@ galaxy.o: ../config.h
 galaxy.o: $(srcdir)/fps.h
 galaxy.o: $(srcdir)/screenhackI.h
 galaxy.o: $(UTILS_SRC)/colors.h
+galaxy.o: $(UTILS_SRC)/erase.h
 galaxy.o: $(UTILS_SRC)/grabscreen.h
 galaxy.o: $(UTILS_SRC)/hsv.h
 galaxy.o: $(UTILS_SRC)/resources.h
 galaxy.o: $(UTILS_SRC)/usleep.h
 galaxy.o: $(UTILS_SRC)/visual.h
-galaxy.o: $(UTILS_SRC)/xshm.h
 galaxy.o: $(UTILS_SRC)/yarandom.h
 galaxy.o: $(srcdir)/xlockmoreI.h
 galaxy.o: $(srcdir)/xlockmore.h
@@ -1725,12 +1724,12 @@ grav.o: ../config.h
 grav.o: $(srcdir)/fps.h
 grav.o: $(srcdir)/screenhackI.h
 grav.o: $(UTILS_SRC)/colors.h
+grav.o: $(UTILS_SRC)/erase.h
 grav.o: $(UTILS_SRC)/grabscreen.h
 grav.o: $(UTILS_SRC)/hsv.h
 grav.o: $(UTILS_SRC)/resources.h
 grav.o: $(UTILS_SRC)/usleep.h
 grav.o: $(UTILS_SRC)/visual.h
-grav.o: $(UTILS_SRC)/xshm.h
 grav.o: $(UTILS_SRC)/yarandom.h
 grav.o: $(srcdir)/xlockmoreI.h
 grav.o: $(srcdir)/xlockmore.h
@@ -1800,7 +1799,6 @@ hopalong.o: $(UTILS_SRC)/hsv.h
 hopalong.o: $(UTILS_SRC)/resources.h
 hopalong.o: $(UTILS_SRC)/usleep.h
 hopalong.o: $(UTILS_SRC)/visual.h
-hopalong.o: $(UTILS_SRC)/xshm.h
 hopalong.o: $(UTILS_SRC)/yarandom.h
 hopalong.o: $(srcdir)/xlockmoreI.h
 hopalong.o: $(srcdir)/xlockmore.h
@@ -1889,12 +1887,12 @@ juggle.o: ../config.h
 juggle.o: $(srcdir)/fps.h
 juggle.o: $(srcdir)/screenhackI.h
 juggle.o: $(UTILS_SRC)/colors.h
+juggle.o: $(UTILS_SRC)/erase.h
 juggle.o: $(UTILS_SRC)/grabscreen.h
 juggle.o: $(UTILS_SRC)/hsv.h
 juggle.o: $(UTILS_SRC)/resources.h
 juggle.o: $(UTILS_SRC)/usleep.h
 juggle.o: $(UTILS_SRC)/visual.h
-juggle.o: $(UTILS_SRC)/xshm.h
 juggle.o: $(UTILS_SRC)/yarandom.h
 juggle.o: $(srcdir)/xlockmoreI.h
 juggle.o: $(srcdir)/xlockmore.h
@@ -1902,12 +1900,12 @@ julia.o: ../config.h
 julia.o: $(srcdir)/fps.h
 julia.o: $(srcdir)/screenhackI.h
 julia.o: $(UTILS_SRC)/colors.h
+julia.o: $(UTILS_SRC)/erase.h
 julia.o: $(UTILS_SRC)/grabscreen.h
 julia.o: $(UTILS_SRC)/hsv.h
 julia.o: $(UTILS_SRC)/resources.h
 julia.o: $(UTILS_SRC)/usleep.h
 julia.o: $(UTILS_SRC)/visual.h
-julia.o: $(UTILS_SRC)/xshm.h
 julia.o: $(UTILS_SRC)/yarandom.h
 julia.o: $(srcdir)/xlockmoreI.h
 julia.o: $(srcdir)/xlockmore.h
@@ -1939,12 +1937,12 @@ laser.o: ../config.h
 laser.o: $(srcdir)/fps.h
 laser.o: $(srcdir)/screenhackI.h
 laser.o: $(UTILS_SRC)/colors.h
+laser.o: $(UTILS_SRC)/erase.h
 laser.o: $(UTILS_SRC)/grabscreen.h
 laser.o: $(UTILS_SRC)/hsv.h
 laser.o: $(UTILS_SRC)/resources.h
 laser.o: $(UTILS_SRC)/usleep.h
 laser.o: $(UTILS_SRC)/visual.h
-laser.o: $(UTILS_SRC)/xshm.h
 laser.o: $(UTILS_SRC)/yarandom.h
 laser.o: $(srcdir)/xlockmoreI.h
 laser.o: $(srcdir)/xlockmore.h
@@ -1963,12 +1961,12 @@ lightning.o: ../config.h
 lightning.o: $(srcdir)/fps.h
 lightning.o: $(srcdir)/screenhackI.h
 lightning.o: $(UTILS_SRC)/colors.h
+lightning.o: $(UTILS_SRC)/erase.h
 lightning.o: $(UTILS_SRC)/grabscreen.h
 lightning.o: $(UTILS_SRC)/hsv.h
 lightning.o: $(UTILS_SRC)/resources.h
 lightning.o: $(UTILS_SRC)/usleep.h
 lightning.o: $(UTILS_SRC)/visual.h
-lightning.o: $(UTILS_SRC)/xshm.h
 lightning.o: $(UTILS_SRC)/yarandom.h
 lightning.o: $(srcdir)/xlockmoreI.h
 lightning.o: $(srcdir)/xlockmore.h
@@ -1976,12 +1974,12 @@ lisa.o: ../config.h
 lisa.o: $(srcdir)/fps.h
 lisa.o: $(srcdir)/screenhackI.h
 lisa.o: $(UTILS_SRC)/colors.h
+lisa.o: $(UTILS_SRC)/erase.h
 lisa.o: $(UTILS_SRC)/grabscreen.h
 lisa.o: $(UTILS_SRC)/hsv.h
 lisa.o: $(UTILS_SRC)/resources.h
 lisa.o: $(UTILS_SRC)/usleep.h
 lisa.o: $(UTILS_SRC)/visual.h
-lisa.o: $(UTILS_SRC)/xshm.h
 lisa.o: $(UTILS_SRC)/yarandom.h
 lisa.o: $(srcdir)/xlockmoreI.h
 lisa.o: $(srcdir)/xlockmore.h
@@ -1989,12 +1987,12 @@ lissie.o: ../config.h
 lissie.o: $(srcdir)/fps.h
 lissie.o: $(srcdir)/screenhackI.h
 lissie.o: $(UTILS_SRC)/colors.h
+lissie.o: $(UTILS_SRC)/erase.h
 lissie.o: $(UTILS_SRC)/grabscreen.h
 lissie.o: $(UTILS_SRC)/hsv.h
 lissie.o: $(UTILS_SRC)/resources.h
 lissie.o: $(UTILS_SRC)/usleep.h
 lissie.o: $(UTILS_SRC)/visual.h
-lissie.o: $(UTILS_SRC)/xshm.h
 lissie.o: $(UTILS_SRC)/yarandom.h
 lissie.o: $(srcdir)/xlockmoreI.h
 lissie.o: $(srcdir)/xlockmore.h
@@ -2014,12 +2012,12 @@ loop.o: ../config.h
 loop.o: $(srcdir)/fps.h
 loop.o: $(srcdir)/screenhackI.h
 loop.o: $(UTILS_SRC)/colors.h
+loop.o: $(UTILS_SRC)/erase.h
 loop.o: $(UTILS_SRC)/grabscreen.h
 loop.o: $(UTILS_SRC)/hsv.h
 loop.o: $(UTILS_SRC)/resources.h
 loop.o: $(UTILS_SRC)/usleep.h
 loop.o: $(UTILS_SRC)/visual.h
-loop.o: $(UTILS_SRC)/xshm.h
 loop.o: $(UTILS_SRC)/yarandom.h
 loop.o: $(srcdir)/xlockmoreI.h
 loop.o: $(srcdir)/xlockmore.h
@@ -2103,12 +2101,12 @@ mountain.o: ../config.h
 mountain.o: $(srcdir)/fps.h
 mountain.o: $(srcdir)/screenhackI.h
 mountain.o: $(UTILS_SRC)/colors.h
+mountain.o: $(UTILS_SRC)/erase.h
 mountain.o: $(UTILS_SRC)/grabscreen.h
 mountain.o: $(UTILS_SRC)/hsv.h
 mountain.o: $(UTILS_SRC)/resources.h
 mountain.o: $(UTILS_SRC)/usleep.h
 mountain.o: $(UTILS_SRC)/visual.h
-mountain.o: $(UTILS_SRC)/xshm.h
 mountain.o: $(UTILS_SRC)/yarandom.h
 mountain.o: $(srcdir)/xlockmoreI.h
 mountain.o: $(srcdir)/xlockmore.h
@@ -2163,12 +2161,12 @@ pacman_ai.o: $(srcdir)/pacman.h
 pacman_ai.o: $(srcdir)/pacman_level.h
 pacman_ai.o: $(srcdir)/screenhackI.h
 pacman_ai.o: $(UTILS_SRC)/colors.h
+pacman_ai.o: $(UTILS_SRC)/erase.h
 pacman_ai.o: $(UTILS_SRC)/grabscreen.h
 pacman_ai.o: $(UTILS_SRC)/hsv.h
 pacman_ai.o: $(UTILS_SRC)/resources.h
 pacman_ai.o: $(UTILS_SRC)/usleep.h
 pacman_ai.o: $(UTILS_SRC)/visual.h
-pacman_ai.o: $(UTILS_SRC)/xshm.h
 pacman_ai.o: $(UTILS_SRC)/yarandom.h
 pacman_ai.o: $(srcdir)/xlockmoreI.h
 pacman_ai.o: $(srcdir)/xpm-pixmap.h
@@ -2178,12 +2176,12 @@ pacman_level.o: $(srcdir)/pacman.h
 pacman_level.o: $(srcdir)/pacman_level.h
 pacman_level.o: $(srcdir)/screenhackI.h
 pacman_level.o: $(UTILS_SRC)/colors.h
+pacman_level.o: $(UTILS_SRC)/erase.h
 pacman_level.o: $(UTILS_SRC)/grabscreen.h
 pacman_level.o: $(UTILS_SRC)/hsv.h
 pacman_level.o: $(UTILS_SRC)/resources.h
 pacman_level.o: $(UTILS_SRC)/usleep.h
 pacman_level.o: $(UTILS_SRC)/visual.h
-pacman_level.o: $(UTILS_SRC)/xshm.h
 pacman_level.o: $(UTILS_SRC)/yarandom.h
 pacman_level.o: $(srcdir)/xlockmoreI.h
 pacman_level.o: $(srcdir)/xpm-pixmap.h
@@ -2228,12 +2226,12 @@ pacman.o: $(srcdir)/pacman.h
 pacman.o: $(srcdir)/pacman_level.h
 pacman.o: $(srcdir)/screenhackI.h
 pacman.o: $(UTILS_SRC)/colors.h
+pacman.o: $(UTILS_SRC)/erase.h
 pacman.o: $(UTILS_SRC)/grabscreen.h
 pacman.o: $(UTILS_SRC)/hsv.h
 pacman.o: $(UTILS_SRC)/resources.h
 pacman.o: $(UTILS_SRC)/usleep.h
 pacman.o: $(UTILS_SRC)/visual.h
-pacman.o: $(UTILS_SRC)/xshm.h
 pacman.o: $(UTILS_SRC)/yarandom.h
 pacman.o: $(srcdir)/xlockmoreI.h
 pacman.o: $(srcdir)/xlockmore.h
@@ -2265,12 +2263,12 @@ penrose.o: ../config.h
 penrose.o: $(srcdir)/fps.h
 penrose.o: $(srcdir)/screenhackI.h
 penrose.o: $(UTILS_SRC)/colors.h
+penrose.o: $(UTILS_SRC)/erase.h
 penrose.o: $(UTILS_SRC)/grabscreen.h
 penrose.o: $(UTILS_SRC)/hsv.h
 penrose.o: $(UTILS_SRC)/resources.h
 penrose.o: $(UTILS_SRC)/usleep.h
 penrose.o: $(UTILS_SRC)/visual.h
-penrose.o: $(UTILS_SRC)/xshm.h
 penrose.o: $(UTILS_SRC)/yarandom.h
 penrose.o: $(srcdir)/xlockmoreI.h
 penrose.o: $(srcdir)/xlockmore.h
@@ -2322,7 +2320,6 @@ polyominoes.o: $(UTILS_SRC)/hsv.h
 polyominoes.o: $(UTILS_SRC)/resources.h
 polyominoes.o: $(UTILS_SRC)/usleep.h
 polyominoes.o: $(UTILS_SRC)/visual.h
-polyominoes.o: $(UTILS_SRC)/xshm.h
 polyominoes.o: $(UTILS_SRC)/yarandom.h
 polyominoes.o: $(srcdir)/xlockmoreI.h
 polyominoes.o: $(srcdir)/xlockmore.h
@@ -2438,12 +2435,12 @@ rotor.o: ../config.h
 rotor.o: $(srcdir)/fps.h
 rotor.o: $(srcdir)/screenhackI.h
 rotor.o: $(UTILS_SRC)/colors.h
+rotor.o: $(UTILS_SRC)/erase.h
 rotor.o: $(UTILS_SRC)/grabscreen.h
 rotor.o: $(UTILS_SRC)/hsv.h
 rotor.o: $(UTILS_SRC)/resources.h
 rotor.o: $(UTILS_SRC)/usleep.h
 rotor.o: $(UTILS_SRC)/visual.h
-rotor.o: $(UTILS_SRC)/xshm.h
 rotor.o: $(UTILS_SRC)/yarandom.h
 rotor.o: $(srcdir)/xlockmoreI.h
 rotor.o: $(srcdir)/xlockmore.h
@@ -2488,12 +2485,12 @@ sierpinski.o: ../config.h
 sierpinski.o: $(srcdir)/fps.h
 sierpinski.o: $(srcdir)/screenhackI.h
 sierpinski.o: $(UTILS_SRC)/colors.h
+sierpinski.o: $(UTILS_SRC)/erase.h
 sierpinski.o: $(UTILS_SRC)/grabscreen.h
 sierpinski.o: $(UTILS_SRC)/hsv.h
 sierpinski.o: $(UTILS_SRC)/resources.h
 sierpinski.o: $(UTILS_SRC)/usleep.h
 sierpinski.o: $(UTILS_SRC)/visual.h
-sierpinski.o: $(UTILS_SRC)/xshm.h
 sierpinski.o: $(UTILS_SRC)/yarandom.h
 sierpinski.o: $(srcdir)/xlockmoreI.h
 sierpinski.o: $(srcdir)/xlockmore.h
@@ -2512,12 +2509,12 @@ slip.o: ../config.h
 slip.o: $(srcdir)/fps.h
 slip.o: $(srcdir)/screenhackI.h
 slip.o: $(UTILS_SRC)/colors.h
+slip.o: $(UTILS_SRC)/erase.h
 slip.o: $(UTILS_SRC)/grabscreen.h
 slip.o: $(UTILS_SRC)/hsv.h
 slip.o: $(UTILS_SRC)/resources.h
 slip.o: $(UTILS_SRC)/usleep.h
 slip.o: $(UTILS_SRC)/visual.h
-slip.o: $(UTILS_SRC)/xshm.h
 slip.o: $(UTILS_SRC)/yarandom.h
 slip.o: $(srcdir)/xlockmoreI.h
 slip.o: $(srcdir)/xlockmore.h
@@ -2537,12 +2534,12 @@ sphere.o: ../config.h
 sphere.o: $(srcdir)/fps.h
 sphere.o: $(srcdir)/screenhackI.h
 sphere.o: $(UTILS_SRC)/colors.h
+sphere.o: $(UTILS_SRC)/erase.h
 sphere.o: $(UTILS_SRC)/grabscreen.h
 sphere.o: $(UTILS_SRC)/hsv.h
 sphere.o: $(UTILS_SRC)/resources.h
 sphere.o: $(UTILS_SRC)/usleep.h
 sphere.o: $(UTILS_SRC)/visual.h
-sphere.o: $(UTILS_SRC)/xshm.h
 sphere.o: $(UTILS_SRC)/yarandom.h
 sphere.o: $(srcdir)/xlockmoreI.h
 sphere.o: $(srcdir)/xlockmore.h
@@ -2550,12 +2547,12 @@ spiral.o: ../config.h
 spiral.o: $(srcdir)/fps.h
 spiral.o: $(srcdir)/screenhackI.h
 spiral.o: $(UTILS_SRC)/colors.h
+spiral.o: $(UTILS_SRC)/erase.h
 spiral.o: $(UTILS_SRC)/grabscreen.h
 spiral.o: $(UTILS_SRC)/hsv.h
 spiral.o: $(UTILS_SRC)/resources.h
 spiral.o: $(UTILS_SRC)/usleep.h
 spiral.o: $(UTILS_SRC)/visual.h
-spiral.o: $(UTILS_SRC)/xshm.h
 spiral.o: $(UTILS_SRC)/yarandom.h
 spiral.o: $(srcdir)/xlockmoreI.h
 spiral.o: $(srcdir)/xlockmore.h
@@ -2599,6 +2596,7 @@ strange.o: $(srcdir)/fps.h
 strange.o: $(srcdir)/screenhackI.h
 strange.o: $(UTILS_SRC)/aligned_malloc.h
 strange.o: $(UTILS_SRC)/colors.h
+strange.o: $(UTILS_SRC)/erase.h
 strange.o: $(UTILS_SRC)/grabscreen.h
 strange.o: $(UTILS_SRC)/hsv.h
 strange.o: $(UTILS_SRC)/pow2.h
@@ -2625,6 +2623,7 @@ swirl.o: ../config.h
 swirl.o: $(srcdir)/fps.h
 swirl.o: $(srcdir)/screenhackI.h
 swirl.o: $(UTILS_SRC)/colors.h
+swirl.o: $(UTILS_SRC)/erase.h
 swirl.o: $(UTILS_SRC)/grabscreen.h
 swirl.o: $(UTILS_SRC)/hsv.h
 swirl.o: $(UTILS_SRC)/resources.h
@@ -2662,7 +2661,9 @@ testx11.o: $(srcdir)/fps.h
 testx11.o: $(srcdir)/glx/rotator.h
 testx11.o: $(srcdir)/screenhackI.h
 testx11.o: $(srcdir)/screenhack.h
+testx11.o: $(UTILS_SRC)/colorbars.h
 testx11.o: $(UTILS_SRC)/colors.h
+testx11.o: $(UTILS_SRC)/erase.h
 testx11.o: $(UTILS_SRC)/grabscreen.h
 testx11.o: $(UTILS_SRC)/hsv.h
 testx11.o: $(UTILS_SRC)/resources.h
@@ -2673,12 +2674,12 @@ thornbird.o: ../config.h
 thornbird.o: $(srcdir)/fps.h
 thornbird.o: $(srcdir)/screenhackI.h
 thornbird.o: $(UTILS_SRC)/colors.h
+thornbird.o: $(UTILS_SRC)/erase.h
 thornbird.o: $(UTILS_SRC)/grabscreen.h
 thornbird.o: $(UTILS_SRC)/hsv.h
 thornbird.o: $(UTILS_SRC)/resources.h
 thornbird.o: $(UTILS_SRC)/usleep.h
 thornbird.o: $(UTILS_SRC)/visual.h
-thornbird.o: $(UTILS_SRC)/xshm.h
 thornbird.o: $(UTILS_SRC)/yarandom.h
 thornbird.o: $(srcdir)/xlockmoreI.h
 thornbird.o: $(srcdir)/xlockmore.h
@@ -2686,12 +2687,12 @@ triangle.o: ../config.h
 triangle.o: $(srcdir)/fps.h
 triangle.o: $(srcdir)/screenhackI.h
 triangle.o: $(UTILS_SRC)/colors.h
+triangle.o: $(UTILS_SRC)/erase.h
 triangle.o: $(UTILS_SRC)/grabscreen.h
 triangle.o: $(UTILS_SRC)/hsv.h
 triangle.o: $(UTILS_SRC)/resources.h
 triangle.o: $(UTILS_SRC)/usleep.h
 triangle.o: $(UTILS_SRC)/visual.h
-triangle.o: $(UTILS_SRC)/xshm.h
 triangle.o: $(UTILS_SRC)/yarandom.h
 triangle.o: $(srcdir)/xlockmoreI.h
 triangle.o: $(srcdir)/xlockmore.h
@@ -2739,7 +2740,6 @@ vines.o: $(UTILS_SRC)/hsv.h
 vines.o: $(UTILS_SRC)/resources.h
 vines.o: $(UTILS_SRC)/usleep.h
 vines.o: $(UTILS_SRC)/visual.h
-vines.o: $(UTILS_SRC)/xshm.h
 vines.o: $(UTILS_SRC)/yarandom.h
 vines.o: $(srcdir)/xlockmoreI.h
 vines.o: $(srcdir)/xlockmore.h
@@ -2806,12 +2806,12 @@ worm.o: ../config.h
 worm.o: $(srcdir)/fps.h
 worm.o: $(srcdir)/screenhackI.h
 worm.o: $(UTILS_SRC)/colors.h
+worm.o: $(UTILS_SRC)/erase.h
 worm.o: $(UTILS_SRC)/grabscreen.h
 worm.o: $(UTILS_SRC)/hsv.h
 worm.o: $(UTILS_SRC)/resources.h
 worm.o: $(UTILS_SRC)/usleep.h
 worm.o: $(UTILS_SRC)/visual.h
-worm.o: $(UTILS_SRC)/xshm.h
 worm.o: $(UTILS_SRC)/yarandom.h
 worm.o: $(srcdir)/xlockmoreI.h
 worm.o: $(srcdir)/xlockmore.h
@@ -2862,12 +2862,12 @@ xlockmore.o: $(srcdir)/fps.h
 xlockmore.o: $(srcdir)/screenhackI.h
 xlockmore.o: $(srcdir)/screenhack.h
 xlockmore.o: $(UTILS_SRC)/colors.h
+xlockmore.o: $(UTILS_SRC)/erase.h
 xlockmore.o: $(UTILS_SRC)/grabscreen.h
 xlockmore.o: $(UTILS_SRC)/hsv.h
 xlockmore.o: $(UTILS_SRC)/resources.h
 xlockmore.o: $(UTILS_SRC)/usleep.h
 xlockmore.o: $(UTILS_SRC)/visual.h
-xlockmore.o: $(UTILS_SRC)/xshm.h
 xlockmore.o: $(UTILS_SRC)/yarandom.h
 xlockmore.o: $(srcdir)/xlockmoreI.h
 xlyap.o: ../config.h
index 642037de54d6365f05055089efb0f9c26f694b8f..81e3823305e2fa656e505cf248cbab51c36df23f 100644 (file)
@@ -305,7 +305,8 @@ analogtv_configure(analogtv *it)
   /* If the window is very small, don't let the image we draw get lower
      than the actual TV resolution (266x200.)
 
-     If the aspect ratio of the window is close to a 4:3 or 16:9 ratio,
+     If the aspect ratio of the window is close to a 4:3 or 16:9 ratio --
+     or if it is a completely weird aspect ratio --
      then scale the image to exactly fill the window.
 
      Otherwise, center the image either horizontally or vertically,
@@ -317,6 +318,8 @@ analogtv_configure(analogtv *it)
   float percent = 0.15;
   float min_ratio =  4.0 / 3.0 * (1 - percent);
   float max_ratio = 16.0 / 9.0 * (1 + percent);
+  float crazy_min_ratio = 10;
+  float crazy_max_ratio = 1/crazy_min_ratio;
   float ratio;
   float height_snap=0.025;
 
@@ -370,6 +373,20 @@ analogtv_configure(analogtv *it)
 # endif
     }
 
+  if (ratio < crazy_min_ratio || ratio > crazy_max_ratio)
+    {
+      if (ratio < crazy_min_ratio)
+        hlim = it->xgwa.height;
+      else
+        wlim = it->xgwa.width;
+# ifdef DEBUG
+      fprintf (stderr,
+               "size: aspect: %dx%d in %dx%d (%.3f < %.3f < %.3f)\n",
+               wlim, hlim, it->xgwa.width, it->xgwa.height,
+               min_ratio, ratio, max_ratio);
+# endif
+    }
+
 
   height_diff = ((hlim + ANALOGTV_VISLINES/2) % ANALOGTV_VISLINES) - ANALOGTV_VISLINES/2;
   if (height_diff != 0 && abs(height_diff) < hlim * height_snap)
index bc697ca989313c40cfc81c55cdf426554d7147ed..56d3036cc8e8baa718e3343671325df3037a34dc 100644 (file)
@@ -66,9 +66,9 @@ static const char sccsid[] = "@(#)ant.c       5.00 2000/11/01 xlockmore";
                                        "*fpsSolid: true    \n" \
 
 # define reshape_ant 0
+# define release_ant 0
 # define ant_handle_event 0
 # include "xlockmore.h"                /* in xscreensaver distribution */
-# include "erase.h"
 #else /* STANDALONE */
 # include "xlock.h"            /* in xlockmore distribution */
 #endif /* STANDALONE */
@@ -121,8 +121,8 @@ ENTRYPOINT ModeSpecOpt ant_opts =
 #ifdef USE_MODULES
 const ModStruct ant_description =
 {"ant",
- "init_ant", "draw_ant", "release_ant",
- "refresh_ant", "init_ant", (char *) NULL, &ant_opts,
+ "init_ant", "draw_ant", (char *) NULL,
+ "refresh_ant", "init_ant", "free_ant", &ant_opts,
  1000, -3, 40000, -12, 64, 1.0, "",
  "Shows Langton's and Turk's generalized ants", 0, NULL};
 
@@ -131,7 +131,7 @@ const ModStruct ant_description =
 #define ANTBITS(n,w,h)\
   if ((ap->pixmaps[ap->init_bits]=\
   XCreatePixmapFromBitmapData(display,window,(char *)n,w,h,1,0,1))==None){\
-  free_ant(display,ap); return;} else {ap->init_bits++;}
+  free_ant(mi); return;} else {ap->init_bits++;}
 
 /* If you change the table you may have to change the following 2 constants */
 #define STATES 2
@@ -183,9 +183,6 @@ typedef struct {
                XPoint      hexagon[7];         /* Need more than 6 for truchet */
                XPoint      triangle[2][4];     /* Need more than 3 for truchet */
        } shape;
-#ifdef STANDALONE
-  eraser_state *eraser;
-#endif
 } antfarmstruct;
 
 static char plots[] =
@@ -975,9 +972,11 @@ getTurk(ModeInfo * mi, int i)
                               ap->n, ap->neighbors, number, ap->ncolors);
 }
 
-static void
-free_ant(Display *display, antfarmstruct *ap)
+ENTRYPOINT void
+free_ant(ModeInfo * mi)
 {
+       Display *display = MI_DISPLAY(mi);
+       antfarmstruct *ap = &antfarms[MI_SCREEN(mi)];
        int         shade;
 
 #ifdef DO_STIPPLE
@@ -1013,7 +1012,12 @@ init_ant(ModeInfo * mi)
        int         col, row, dir;
        int         i;
 
-    MI_INIT (mi, antfarms, 0);
+       MI_INIT(mi, antfarms);
+       /*if (antfarms == NULL) {
+               if ((antfarms = (antfarmstruct *) calloc(MI_NUM_SCREENS(mi),
+                                           sizeof (antfarmstruct))) == NULL)
+                       return;
+       }*/
        ap = &antfarms[MI_SCREEN(mi)];
 
        ap->redrawing = 0;
@@ -1027,7 +1031,7 @@ init_ant(ModeInfo * mi)
                        if ((ap->stippledGC = XCreateGC(display, window,
                                                         GCFillStyle,
                                        &gcv)) == None) {
-                               free_ant(display, ap);
+                               free_ant(mi);
                                return;
                        }
                }
@@ -1187,7 +1191,7 @@ init_ant(ModeInfo * mi)
        if (ap->ants == NULL) {
                if ((ap->ants = (antstruct *) malloc(ap->n * sizeof (antstruct))) ==
                                NULL) {
-                       free_ant(display, ap);
+                       free_ant(mi);
                        return;
                }
        }
@@ -1195,14 +1199,14 @@ init_ant(ModeInfo * mi)
                (void) free((void *) ap->tape);
        if ((ap->tape = (unsigned char *) calloc(ap->ncols * ap->nrows,
                        sizeof (unsigned char))) == NULL) {
-               free_ant(display, ap);
+               free_ant(mi);
                return;
        }
        if (ap->truchet_state != NULL)
                (void) free((void *) ap->truchet_state);
        if ((ap->truchet_state = (unsigned char *) calloc(ap->ncols * ap->nrows,
                        sizeof (unsigned char))) == NULL) {
-               free_ant(display, ap);
+               free_ant(mi);
                return;
        }
 
@@ -1242,13 +1246,6 @@ draw_ant(ModeInfo * mi)
        if (ap->ants == NULL)
                return;
 
-#ifdef STANDALONE
-    if (ap->eraser) {
-      ap->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), ap->eraser);
-      return;
-    }
-#endif
-
        MI_IS_DRAWN(mi) = True;
        ap->painted = True;
        for (i = 0; i < ap->n; i++) {
@@ -1309,9 +1306,6 @@ draw_ant(ModeInfo * mi)
                draw_anant(mi, anant->direction, anant->col, anant->row);
        }
        if (++ap->generation > MI_CYCLES(mi)) {
-#ifdef STANDALONE
-      ap->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), ap->eraser);
-#endif
                init_ant(mi);
        }
        if (ap->redrawing) {
@@ -1333,19 +1327,7 @@ draw_ant(ModeInfo * mi)
        }
 }
 
-ENTRYPOINT void
-release_ant(ModeInfo * mi)
-{
-       if (antfarms != NULL) {
-               int         screen;
-
-               for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
-                       free_ant(MI_DISPLAY(mi), &antfarms[screen]);
-               (void) free((void *) antfarms);
-               antfarms = (antfarmstruct *) NULL;
-       }
-}
-
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_ant(ModeInfo * mi)
 {
@@ -1361,6 +1343,7 @@ refresh_ant(ModeInfo * mi)
                ap->redrawpos = 0;
        }
 }
+#endif
 
 XSCREENSAVER_MODULE ("Ant", ant)
 
index 6986e73eb3a14ad272032223dc9f1f26dbcf4ba8..4b28ac3fdcdb2651ed38c9a0328b1f552ef2b820 100644 (file)
@@ -75,10 +75,10 @@ static const char sccsid[] = "@(#)apollonian.c      5.02 2001/07/01 xlockmore";
                                        "*fpsSolid: true   \n" \
                                        "*ignoreRotation: True" \
 
-# define refresh_apollonian 0
 # define release_apollonian 0
+# define reshape_apollonian 0
+# define apollonian_handle_event 0
 # include "xlockmore.h"                /* in xscreensaver distribution */
-# include "erase.h"
 #else /* STANDALONE */
 # include "xlock.h"            /* in xlockmore distribution */
 #endif /* STANDALONE */
@@ -119,7 +119,7 @@ extern XFontStruct *getFont(Display * display);
 #ifdef USE_MODULES
 ModStruct   apollonian_description =
 {"apollonian", "init_apollonian", "draw_apollonian", (char *) NULL,
- "init_apollonian", "init_apollonian", (char *) NULL, &apollonian_opts,
+ "init_apollonian", "init_apollonian", "free_apollonian", &apollonian_opts,
  1000000, 64, 20, 1, 64, 1.0, "",
  "Shows Apollonian Circles", 0, NULL};
 
@@ -299,9 +299,6 @@ typedef struct {
 #endif
        int         time;
        int         game;
-#ifdef STANDALONE
-  eraser_state *eraser;
-#endif
 } apollonianstruct;
 
 static apollonianstruct *apollonians = (apollonianstruct *) NULL;
@@ -682,7 +679,7 @@ init_apollonian (ModeInfo * mi)
        apollonianstruct *cp;
        int i;
 
-       MI_INIT (mi, apollonians, free_apollonian);
+       MI_INIT (mi, apollonians);
        cp = &apollonians[MI_SCREEN(mi)];
 
        cp->size = MAX(MIN(MI_WIDTH(mi), MI_HEIGHT(mi)) - 1, 1);
@@ -727,9 +724,7 @@ init_apollonian (ModeInfo * mi)
                        cquad(&(cp->c1), &(cp->c2), &(cp->c3), &(cp->c4));
        }
        cp->time = 0;
-#ifndef STANDALONE
        MI_CLEARWINDOW(mi);
-#endif
        if (cp->game != 0) {
                double q123;
 
@@ -782,14 +777,6 @@ draw_apollonian (ModeInfo * mi)
                return;
        cp = &apollonians[MI_SCREEN(mi)];
 
-#ifdef STANDALONE
-    if (cp->eraser) {
-      cp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), cp->eraser);
-      if (!cp->eraser)
-        init_apollonian(mi);
-      return;
-    }
-#endif
 
        MI_IS_DRAWN(mi) = True;
 
@@ -815,31 +802,7 @@ draw_apollonian (ModeInfo * mi)
                }
        }
        if (++cp->time > MI_CYCLES(mi))
-      {
-#ifdef STANDALONE
-        cp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), cp->eraser);
-#else /* !STANDALONE */
                init_apollonian(mi);
-#endif /* !STANDALONE */
-      }
-}
-
-ENTRYPOINT void
-reshape_apollonian(ModeInfo * mi, int width, int height)
-{
-  XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi));
-  init_apollonian (mi);
-}
-
-ENTRYPOINT Bool
-apollonian_handle_event (ModeInfo *mi, XEvent *event)
-{
-  if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
-    {
-      reshape_apollonian (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
-      return True;
-    }
-  return False;
 }
 
 XSCREENSAVER_MODULE ("Apollonian", apollonian)
index c95e5babd9e8e50cbb9fd0cf3017e173edfbeb18..27d2824f45e1c050fdb077c72c9d57cd72691e9b 100644 (file)
@@ -549,7 +549,7 @@ static void jmpBIT(machine_6502 *machine, m6502_AddrMode adm){
   Pointer ptr;
   BOOL isValue = getValue(machine, adm, &ptr);
   warnValue(isValue);
-  machine->regP = setBit(machine->regP, ZERO_FL, (ptr.value & machine->regA));
+  machine->regP = setBit(machine->regP, ZERO_FL, !(ptr.value & machine->regA));
   machine->regP = setBit(machine->regP, OVERFLOW_FL, bitOn(ptr.value, OVERFLOW_FL));
   machine->regP = setBit(machine->regP, NEGATIVE_FL, bitOn(ptr.value, NEGATIVE_FL));
   
@@ -2042,7 +2042,7 @@ static BOOL compileCode(machine_6502 *machine, const char *code){
       AsmLine *p;
       if(asmlist != NULL){
         for (p = asmlist; p != NULL; p = p->next)
-          fprintf(stderr,"%s lbl: %s addr: %d ParamLbl: %s ParamAddr: %d\n",
+          fprintf(stderr,"%s lbl: %s addr: %x ParamLbl: %s ParamAddr: %x\n",
                   p->command, p->label->label, p->label->addr,
                   p->param->label, p->param->lbladdr);
             }
@@ -2199,7 +2199,7 @@ void m6502_eval_file(machine_6502 *machine, const char *filename, m6502_Plotter
   do{
     sleep(0); /* XXX */
 #if 0
-    trace(machine);
+    m6502_trace(machine, stdout);
 #endif
     execute(machine);
   }while(machine->codeRunning);
index 331cbcf8e5b8f73a34d053900864e4faa8ce9a3b..4fe22c237e00c6147b557af5dd0ad29d418eb790 100644 (file)
@@ -162,6 +162,7 @@ attraction_init (Display *dpy, Window window)
   double th;
   Colormap cmap;
   char *mode_str, *graph_mode_str;
+  double size_scale;
 
   XGetWindowAttributes (dpy, window, &xgwa);
   st->xlim = xgwa.width;
@@ -342,8 +343,12 @@ attraction_init (Display *dpy, Window window)
   jwxyz_XSetAntiAliasing (dpy, st->erase_gc, False);
 #endif
 
+  size_scale = 3;
+  if (xgwa.width < 100 || xgwa.height < 100)  /* tiny windows */
+    size_scale = 0.75;
+
   /* let's make the balls bigger by default */
-#define rand_size() (3 * (8 + (random () % 7)))
+#define rand_size() (size_scale * (8 + (random () % 7)))
 
   if (st->orbit_p && !st->global_size)
     /* To orbit, all objects must be the same mass, or the math gets
index cd3038ce534b1bf4fc109b621232a387bb3bf6db..271aad9948283fbf212d26b80356a6ee537507eb 100644 (file)
@@ -1635,6 +1635,12 @@ static void scrollModel (struct state *st)
             st->barcodes[st->barcode_count - 1].mag * BARCODE_WIDTH);
        barcode->x += RAND_FLOAT_01 * 100;
        barcode->mag = RAND_FLOAT_01 * MAX_MAG;
+
+        if (st->windowWidth < 100 || st->windowHeight < 100) {
+          barcode->mag *= 0.5;
+          if (barcode->mag <= 0) barcode->mag = 1;
+        }
+
        barcode->y =
            RAND_FLOAT_01 * (st->windowHeight - BARCODE_HEIGHT * barcode->mag);
        if (barcode->y < 0) 
index 3944146fffa048dad91a15388456691cd93ab6e8..a60351af03d98497befb639203a913ff53dd08c4 100644 (file)
@@ -1096,6 +1096,7 @@ blaster_free (Display *dpy, Window window, void *closure)
 
 
 static const char *blaster_defaults [] = {
+  ".lowrez: true",
   ".background:        black",
   ".foreground:        white",
   "*fpsSolid:  true",
index e3379aa3c6e6c0d555a63cf3defb80973d7cbff6..7923ce87bc15f5e22863153662c3158d0b2b57cb 100644 (file)
@@ -298,8 +298,6 @@ sinfree(SinVariable * point)
        }
 }
 
-static void free_bouboule(ModeInfo * mi);
-
 
 /***************/
 ENTRYPOINT void
@@ -318,7 +316,7 @@ init_bouboule(ModeInfo * mi)
        int         i;
        double      theta, omega;
 
-       MI_INIT (mi, starfield, free_bouboule);
+       MI_INIT (mi, starfield);
        sp = &starfield[MI_SCREEN(mi)];
 
        sp->width = MI_WIN_WIDTH(mi);
@@ -802,7 +800,7 @@ draw_bouboule(ModeInfo * mi)
        }
 }
 
-static void
+ENTRYPOINT void
 free_bouboule(ModeInfo * mi)
 {
        StarField  *sp = &starfield[MI_SCREEN(mi)];
@@ -847,10 +845,12 @@ reshape_bouboule(ModeInfo * mi, int width, int height)
         POSCANRAND);
 }
 
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_bouboule(ModeInfo * mi)
 {
        /* Do nothing, it will refresh by itself */
 }
+#endif
 
 XSCREENSAVER_MODULE ("Bouboule", bouboule)
index 1f82334cbda963575339ee04974fdad51c452ade..4f5a77c9caa4040fd670d068a874e25a7a557a9a 100644 (file)
@@ -41,9 +41,11 @@ static const char sccsid[] = "@(#)braid.c    5.00 2000/11/01 xlockmore";
                                   "*ignoreRotation: True" \
 
 # define UNIFORM_COLORS
+# define free_braid 0
 # define release_braid 0
+# define reshape_braid 0
+# define braid_handle_event 0
 # include "xlockmore.h"
-# include "erase.h"
 #else /* STANDALONE */
 # include "xlock.h"
 # define ENTRYPOINT /**/
@@ -101,9 +103,6 @@ typedef struct {
        float       top, bottom, left, right;
        int         age;
        int         color_direction;
-#ifdef STANDALONE
-  eraser_state *eraser;
-#endif
 } braidtype;
 
 static braidtype *braids = (braidtype *) NULL;
@@ -171,7 +170,7 @@ init_braid(ModeInfo * mi)
        int         i, count, comp, c;
        float       min_length;
 
-       MI_INIT (mi, braids, 0);
+       MI_INIT (mi, braids);
        braid = &braids[MI_SCREEN(mi)];
 
        braid->center_x = MI_WIDTH(mi) / 2;
@@ -181,9 +180,7 @@ init_braid(ModeInfo * mi)
        /* jwz: go in the other direction sometimes. */
        braid->color_direction = ((LRAND() & 1) ? 1 : -1);
 
-#ifndef STANDALONE
        MI_CLEARWINDOW(mi);
-#endif
 
        min_length = (braid->center_x > braid->center_y) ?
                braid->center_y : braid->center_x;
@@ -283,15 +280,6 @@ draw_braid(ModeInfo * mi)
                return;
        braid = &braids[MI_SCREEN(mi)];
 
-#ifdef STANDALONE
-    if (braid->eraser) {
-      braid->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), braid->eraser);
-      if (!braid->eraser)
-        init_braid(mi);
-      return;
-    }
-#endif
-
        MI_IS_DRAWN(mi) = True;
        XSetLineAttributes(display, MI_GC(mi), braid->linewidth,
                           LineSolid,
@@ -438,38 +426,17 @@ draw_braid(ModeInfo * mi)
        XSetLineAttributes(display, MI_GC(mi), 1, LineSolid, CapNotLast, JoinRound);
 
        if (++braid->age > MI_CYCLES(mi)) {
-#ifdef STANDALONE
-      braid->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), braid->eraser);
-#else
                init_braid(mi);
-#endif
        }
 }
 
-ENTRYPOINT void
-reshape_braid(ModeInfo * mi, int width, int height)
-{
-  XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi));
-  init_braid (mi);
-}
-
-ENTRYPOINT Bool
-braid_handle_event (ModeInfo *mi, XEvent *event)
-{
-  if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
-    {
-      reshape_braid (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
-      return True;
-    }
-
-  return False;
-}
-
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_braid(ModeInfo * mi)
 {
        MI_CLEARWINDOW(mi);
 }
+#endif
 
 XSCREENSAVER_MODULE ("Braid", braid)
 
index 534f30e13a23f54574ec761faf5d435d1dc852ef..553eb5e0cfa7eabfbe695303e4d93f6f1b566b2a 100644 (file)
@@ -5,7 +5,7 @@
  * 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 
+ * software for any purpose.  It is provided "as is" without express or
  * implied warranty.
  *
  * Blue Screen of Death: the finest in personal computer emulation.
@@ -60,6 +60,7 @@
 # include "images/osx_10_2.xpm"
 # include "images/osx_10_3.xpm"
 # include "images/android.xpm"
+# include "images/ransomware.xpm"
 #endif
 #include "images/atari.xbm"
 #include "images/mac.xbm"
 # define MAX(A,B) ((A)>(B)?(A):(B))
 
 #undef EOF
-typedef enum { EOF=0, 
-               LEFT, CENTER, RIGHT, 
-               LEFT_FULL, CENTER_FULL, RIGHT_FULL, 
+typedef enum { EOF=0,
+               LEFT, CENTER, RIGHT,
+               LEFT_FULL, CENTER_FULL, RIGHT_FULL,
                COLOR, INVERT, MOVETO, MARGINS,
                CURSOR_BLOCK, CURSOR_LINE, RECT, LINE, COPY, PIXMAP, IMG, FONT,
                PAUSE, CHAR_DELAY, LINE_DELAY,
-               LOOP, RESET
+               LOOP, RESET, VERT_MARGINS, CROP
 } bsod_event_type;
 
 struct bsod_event {
@@ -98,9 +99,11 @@ struct bsod_state {
   unsigned long fg, bg;
   GC gc;
   int left_margin, right_margin;       /* for text wrapping */
-  int top_margin, bottom_margin;       /* for text scrolling */
+  int top_margin, bottom_margin;       /* for text scrolling and cropping */
+  int xoff, yoff;
   Bool wrap_p;
   Bool scroll_p;
+  Bool crop_p;                  /* If True, chops off extra text vertically */
 
   Pixmap pixmap;               /* Source image used by BSOD_PIXMAP */
 
@@ -210,6 +213,16 @@ struct bsod_state {
   (bst)->pos++; \
   } while (0)
 
+/* Set the prevailing top/bottom margins (used when scrolling and cropping text)
+ */
+#define BSOD_VERT_MARGINS(bst,top,bottom) do { \
+  ensure_queue (bst); \
+  (bst)->queue[(bst)->pos].type = VERT_MARGINS; \
+  (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (top)); \
+  (bst)->queue[(bst)->pos].arg2 = (void *) ((long) (bottom)); \
+  (bst)->pos++; \
+  } while (0)
+
 /* Draw a blinking cursor; type is CURSOR_BLOCK or CURSOR_LINE.
    usec is how long 1/2 of a cycle is.  count is how many times to blink.
    (You can pass a gigantic number if this is the last thing in your mode.)
@@ -286,7 +299,7 @@ struct bsod_state {
   (bst)->pos++; \
   } while (0)
 
-/* Jump around in the state table.  You can use this as the last thing 
+/* Jump around in the state table.  You can use this as the last thing
    in your state table to repeat the last N elements forever.
  */
 #define BSOD_LOOP(bst,off) do { \
@@ -304,6 +317,16 @@ struct bsod_state {
   (bst)->pos++; \
   } while (0)
 
+/* Sets the crop state, if True, will not write text below the bottom_margin
+ */
+#define BSOD_CROP(bst, state) do { \
+  ensure_queue (bst); \
+  (bst)->queue[(bst)->pos].type = CROP; \
+  (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (state)); \
+  (bst)->pos++; \
+  } while (0)
+
+
 
 static void
 ensure_queue (struct bsod_state *bst)
@@ -316,10 +339,10 @@ ensure_queue (struct bsod_state *bst)
   if (n < 100) n *= 2;
   n *= 1.2;
 
-  bst->queue = (struct bsod_event *) 
+  bst->queue = (struct bsod_event *)
     realloc (bst->queue, n * sizeof(*bst->queue));
   if (!bst->queue) abort();
-  memset (bst->queue + bst->queue_size, 0, 
+  memset (bst->queue + bst->queue_size, 0,
           (n - bst->queue_size) * sizeof(*bst->queue));
   bst->queue_size = n;
 }
@@ -353,11 +376,11 @@ position_for_text (struct bsod_state *bst, const char *line)
   switch (bst->queue[bst->pos].type) {
   case LEFT:
   case LEFT_FULL:
-    bst->current_left = bst->left_margin;
+    bst->current_left = bst->left_margin + bst->xoff;
     break;
   case RIGHT:
   case RIGHT_FULL:
-    bst->x = max_width - bst->right_margin;
+    bst->x = max_width - bst->right_margin - bst->xoff;
     bst->current_left = bst->x;
     break;
   case CENTER:
@@ -366,7 +389,7 @@ position_for_text (struct bsod_state *bst, const char *line)
       int w = (bst->xgwa.width - bst->left_margin - bst->right_margin -
                max_width);
       if (w < 0) w = 0;
-      bst->x = bst->left_margin + (w / 2);
+      bst->x = bst->left_margin + bst->xoff + (w / 2);
       bst->current_left = bst->x;
       break;
     }
@@ -382,20 +405,21 @@ bst_crlf (struct bsod_state *bst)
   int lh = bst->font->ascent + bst->font->descent;
   bst->x = bst->current_left;
   if (!bst->scroll_p ||
-      bst->y + lh < bst->xgwa.height - bst->bottom_margin)
+      bst->y + lh < bst->xgwa.height - bst->bottom_margin - bst->yoff)
     bst->y += lh;
   else
     {
       int w = bst->xgwa.width  - bst->right_margin - bst->left_margin;
       int h = bst->xgwa.height - bst->top_margin - bst->bottom_margin;
       XCopyArea (bst->dpy, bst->window, bst->window, bst->gc,
-                 bst->left_margin,
-                 bst->top_margin + lh,
+                 bst->left_margin + bst->xoff,
+                 bst->top_margin + bst->yoff + lh,
                  w, h - lh,
-                 bst->left_margin,
-                 bst->top_margin);
+                 bst->left_margin + bst->xoff,
+                 bst->top_margin + bst->yoff);
       XClearArea (bst->dpy, bst->window,
-                  bst->left_margin, bst->top_margin + h - lh, w, lh, False);
+                  bst->left_margin + bst->xoff,
+                  bst->top_margin + bst->yoff + h - lh, w, lh, False);
     }
 }
 
@@ -405,6 +429,12 @@ draw_char (struct bsod_state *bst, char c)
 {
   if (!c)
     abort();
+  else if (bst->crop_p && bst->y >=
+           (bst->xgwa.height - bst->bottom_margin - bst->yoff))
+    {
+      /* reached the bottom of the drawing area, and crop_p = True */
+      return;
+    }
   else if (c == '\r')
     {
       bst->x = bst->current_left;
@@ -414,10 +444,10 @@ draw_char (struct bsod_state *bst, char c)
       if (bst->macx_eol_kludge)
         {
           /* Special case for the weird way OSX crashes print newlines... */
-          XDrawImageString (bst->dpy, bst->window, bst->gc, 
+          XDrawImageString (bst->dpy, bst->window, bst->gc,
                             bst->x, bst->y, " ", 1);
-          XDrawImageString (bst->dpy, bst->window, bst->gc, 
-                            bst->x, 
+          XDrawImageString (bst->dpy, bst->window, bst->gc,
+                            bst->x,
                             bst->y + bst->font->ascent + bst->font->descent,
                             " ", 1);
         }
@@ -429,8 +459,8 @@ draw_char (struct bsod_state *bst, char c)
                ? bst->font->per_char['n'-bst->font->min_char_or_byte2].width
                : bst->font->min_bounds.width);
       bst->x -= cw;
-      if (bst->x < bst->left_margin)
-        bst->x = bst->left_margin;
+      if (bst->x < bst->left_margin + bst->xoff)
+        bst->x = bst->left_margin + bst->xoff;
     }
   else
     {
@@ -438,11 +468,11 @@ draw_char (struct bsod_state *bst, char c)
       XCharStruct ov;
       XTextExtents (bst->font, &c, 1, &dir, &ascent, &descent, &ov);
 
-      if (bst->wrap_p && 
-          bst->x + ov.width > bst->xgwa.width - bst->right_margin)
+      if (bst->wrap_p &&
+          bst->x + ov.width > bst->xgwa.width - bst->right_margin - bst->xoff)
         bst_crlf (bst);
 
-      XDrawImageString (bst->dpy, bst->window, bst->gc, 
+      XDrawImageString (bst->dpy, bst->window, bst->gc,
                         bst->x, bst->y, &c, 1);
       bst->x += ov.width;
     }
@@ -473,7 +503,7 @@ bsod_pop (struct bsod_state *bst)
         {
           long delay = bst->line_delay;
           bst->pos++;
-          bst->current_left = bst->left_margin;
+          bst->current_left = bst->left_margin + bst->xoff;
           return delay;
         }
 
@@ -569,8 +599,8 @@ bsod_pop (struct bsod_state *bst)
       int h    = (long) bst->queue[bst->pos].arg4;
       int tox  = (long) bst->queue[bst->pos].arg5;
       int toy  = (long) bst->queue[bst->pos].arg6;
-      XCopyArea (bst->dpy, 
-                 (type == PIXMAP ? bst->pixmap : bst->window), 
+      XCopyArea (bst->dpy,
+                 (type == PIXMAP ? bst->pixmap : bst->window),
                  bst->window, bst->gc,
                  srcx, srcy, w, h, tox, toy);
       bst->pos++;
@@ -579,7 +609,7 @@ bsod_pop (struct bsod_state *bst)
   case IMG:
     {
       if (bst->img_loader) abort();
-      bst->img_loader = load_image_async_simple (0, bst->xgwa.screen, 
+      bst->img_loader = load_image_async_simple (0, bst->xgwa.screen,
                                                  bst->window, bst->window,
                                                  0, 0);
       bst->pos++;
@@ -622,6 +652,13 @@ bsod_pop (struct bsod_state *bst)
       bst->pos++;
       return 0;
     }
+  case VERT_MARGINS:
+    {
+      bst->top_margin    = (long) bst->queue[bst->pos].arg1;
+      bst->bottom_margin = (long) bst->queue[bst->pos].arg2;
+      bst->pos++;
+      return 0;
+    }
   case CURSOR_BLOCK:
   case CURSOR_LINE:
     {
@@ -678,6 +715,12 @@ bsod_pop (struct bsod_state *bst)
       bst->pos = 0;
       return 0;
     }
+  case CROP:
+    {
+      bst->crop_p = (long) bst->queue[bst->pos].arg1;
+      bst->pos++;
+      return 0;
+    }
   case EOF:
     {
       bst->pos = -1;
@@ -803,9 +846,21 @@ make_bsod_state (Display *dpy, Window window,
   jwxyz_XSetAntiAliasing (dpy, bst->gc, True);
 #endif
 
+# ifdef USE_IPHONE
+  /* Stupid iPhone X bezel.
+     #### This is the worst of all possible ways to do this!
+   */
+  if (bst->xgwa.width == 2436 || bst->xgwa.height == 2436) {
+    if (bst->xgwa.width > bst->xgwa.height)
+      bst->xoff = 96;
+    else
+      bst->yoff = 96;
+  }
+# endif
+
   bst->left_margin = bst->right_margin = 10;
-  bst->x = bst->left_margin;
-  bst->y = bst->font->ascent + bst->left_margin;
+  bst->x = bst->left_margin + bst->xoff;
+  bst->y = bst->font->ascent + bst->left_margin + bst->yoff;
 
   XSetWindowBackground (dpy, window, gcv.background);
   return bst;
@@ -877,6 +932,9 @@ static struct bsod_state *
 windows_31 (Display *dpy, Window window)
 {
   struct bsod_state *bst = make_bsod_state (dpy, window, "windows", "Windows");
+
+  bst->xoff = bst->left_margin = bst->right_margin = 0;
+
   BSOD_INVERT (bst);
   BSOD_TEXT   (bst, CENTER, "Windows\n");
   BSOD_INVERT (bst);
@@ -891,7 +949,7 @@ windows_31 (Display *dpy, Window window)
                "\n");
   BSOD_TEXT   (bst, CENTER, "Press any key to continue");
 
-  bst->y = ((bst->xgwa.height -
+  bst->y = ((bst->xgwa.height - bst->yoff -
              ((bst->font->ascent + bst->font->descent) * 9))
             / 2);
 
@@ -928,7 +986,7 @@ vmware (Display *dpy, Window window)
                "0x3a37ffc:[0x750902]CpuSched_StartWorld+0x109 stack: 0x0, 0x0, 0x0\n"
                "0x3a38000:[0x0]blk_dev+0xfd76461f stack: 0x0, 0x0, 0x0\n"
                "VMK uptime: 7:05:43:45.014 TSC: 1751259712918392\n"
-               "Starting coredump to disk\n"); 
+               "Starting coredump to disk\n");
   BSOD_CHAR_DELAY (bst, 10000);                
   BSOD_TEXT (bst, LEFT,        "using slot 1 of 1... ");
   BSOD_CHAR_DELAY (bst, 300000);
@@ -948,7 +1006,7 @@ vmware (Display *dpy, Window window)
 
 /*  BSOD_CURSOR (bst, CURSOR_LINE, 240000, 999999);*/
                
-/*  bst->y = ((bst->xgwa.height -
+/*  bst->y = ((bst->xgwa.height - bst->yoff -
              ((bst->font->ascent + bst->font->descent) * 9))
             / 2);*/
 
@@ -1053,7 +1111,7 @@ windows_me (Display *dpy, Window window)
   BSOD_CURSOR (bst, CURSOR_LINE, 120000, 999999);
 
   bst->left_margin = 40;
-  bst->y = ((bst->xgwa.height -
+  bst->y = ((bst->xgwa.height - bst->yoff -
              ((bst->font->ascent + bst->font->descent) * 3))
             / 2);
 
@@ -1111,7 +1169,7 @@ windows_xp (Display *dpy, Window window)
 static struct bsod_state *
 windows_lh (Display *dpy, Window window)
 {
-  struct bsod_state *bst = 
+  struct bsod_state *bst =
     make_bsod_state (dpy, window, "windowslh", "WindowsLH");
 
   unsigned long fg = bst->fg;
@@ -1147,7 +1205,8 @@ windows_lh (Display *dpy, Window window)
      "or computer\n"
      "manufacturer.\n"
      );
-  BSOD_MOVETO (bst, bst->left_margin, bst->xgwa.height - bst->font->descent);
+  BSOD_MOVETO (bst, bst->left_margin + bst->xoff,
+               bst->xgwa.height - bst->yoff - bst->font->descent);
   BSOD_COLOR (bst, bg, bg2);
   BSOD_TEXT (bst, LEFT_FULL, " SPACE=Continue\n");
 
@@ -1158,10 +1217,43 @@ windows_lh (Display *dpy, Window window)
 }
 
 
+static struct bsod_state *
+windows_10_update (Display *dpy, Window window)
+{
+  struct bsod_state *bst =
+    make_bsod_state (dpy, window, "win10", "Win10");
+  const char *fmt  = "Working on updates  %d%%";
+  char        line1[255];
+  const char *line2 = "Don't turn off your PC. This will take a while.";
+  const char *line3 = "Your PC will restart several times.";
+  int line_height = bst->fontA->ascent + bst->fontA->descent;
+  int y1 = bst->xgwa.height / 2 - line_height * 4;
+  int y2 = bst->xgwa.height - bst->yoff - line_height * 3;
+  int pct;
+
+  /* TODO: win10_spinner.gif goes at (y - line_height * 2 - 64). */
+
+  for (pct = 0; pct < 98; pct++)
+    {
+      BSOD_MOVETO (bst, 0, y1);
+      sprintf (line1, fmt, pct);
+      BSOD_TEXT (bst, CENTER, line1);
+      BSOD_MOVETO (bst, 0, y1 + line_height);
+      BSOD_TEXT (bst, CENTER, line2);
+      BSOD_MOVETO (bst, 0, y2);
+      BSOD_TEXT (bst, CENTER, line3);
+      BSOD_PAUSE (bst, 200000 + (random() % 3000000) + (random() % 3000000));
+    }
+
+  XClearWindow (dpy, window);
+  return bst;
+}
+
+
 static struct bsod_state *
 windows_10 (Display *dpy, Window window)
 {
-  struct bsod_state *bst = 
+  struct bsod_state *bst =
     make_bsod_state (dpy, window, "win10", "Win10");
 
   int qr_width  = 41;
@@ -1201,10 +1293,10 @@ windows_10 (Display *dpy, Window window)
     "For more information about this issue and\n",
     "possible fixes, visit\n",
 /*  "https://www.jwz.org/xscreensaver\n",*/
-    "http://youtu.be/-RjmN9RZyr4\n", 
+    "http://youtu.be/-RjmN9RZyr4\n",
     "\n",
     "If you call a support person, give them this info:\n",
-    "Stop code CRITICAL_PROCESS_DIED", 
+    "Stop code CRITICAL_PROCESS_DIED",
  };
   int i, y = 0, y0 = 0;
   int line_height0 = bst->fontB->ascent;
@@ -1214,12 +1306,17 @@ windows_10 (Display *dpy, Window window)
   int top, left0, left;
   int stop = 60 + (random() % 39);
 
+  if (!(random() % 7))
+    return windows_10_update (dpy, window);
+
+
   line_height1 *= 1.3;
   line_height2 *= 1.5;
 
-  top = ((bst->xgwa.height - (line_height0 * 1 +
-                              line_height1 * 6 +
-                              line_height2 * 6))
+  top = ((bst->xgwa.height - bst->yoff
+          - (line_height0 * 1 +
+             line_height1 * 6 +
+             line_height2 * 6))
          / 2);
 
   {
@@ -1302,6 +1399,452 @@ windows_other (Display *dpy, Window window)
   }
 }
 
+/* Windows and Apple2 ransomware.
+ */
+static struct bsod_state *apple2ransomware (Display *, Window);
+
+static struct bsod_state *
+windows_ransomware (Display *dpy, Window window)
+{
+  struct bsod_state *bst = make_bsod_state (dpy, window,
+                                            "ransomware", "Ransomware");
+  char buf[1024];
+
+  int pix_w = 0, pix_h = 0;
+  Pixmap pixmap = xpm_data_to_pixmap (dpy, window,
+                                      (char **) (ransomware_xpm),
+                                      &pix_w, &pix_h, 0);
+
+  /* Don't start the countdown from the start, advance the deadline by 3 - 30
+     hours */
+  int advance_deadline = (random() % 97200) + 10800;
+
+  time_t now = time(NULL);
+  const time_t stage1_deadline = now + 259200 - advance_deadline; /* 3 days */
+  const time_t stage2_deadline = now + 604800 - advance_deadline; /* 7 days */
+  char stage1_deadline_str[25], stage2_deadline_str[25];
+  char countdown_str[16];
+  int stage1_countdown_y, stage2_countdown_y;
+  int countdown_d, countdown_h, countdown_m, countdown_s, countdown_r;
+  const int line_height = bst->font->ascent + bst->font->descent;
+  int i;
+
+  const char *currencies[] = {
+    "Blitcoin",
+    "clicks",
+    "Ass Pennies",
+    "Dollary-doos",
+    "Dunning-Krugerrands",
+    "Dunning-Krugerrands",
+    "Dunning-Krugerrands",
+    "Dunning-Krugerrands",
+    "Dunning-Krugerrands",
+    "gift certificates",
+    "secret sauce",
+    "Tribbles",
+  };
+
+  const char *currency = currencies[random() % countof(currencies)];
+
+  const char *header_quips[] = {
+    "Oops, your screens have been encrypted!",
+    "Oops, your screens have been encrypted!",
+    "Oops, your screens have been encrypted!",
+    "Oops, your screens have been encrypted!",
+    "Oops, your screen have encrypted!",
+    "Oops, you're screens have been encrypted!",
+    "Oops, your screens have been encrupted!",
+    "Oops, your screens have been encrumpet!",
+    "Oops, your screens have been encrusted!",
+    "If you don't pay this ransom, then you are a theif!",
+    "Your screen was subject to the laws of mathomatics!",
+    "Oops, your screen was shaved by Occam's Razor!",
+    "Oops, your screen was perturbated by Langford's Basilisk!",
+    "Your screen is now stored as Snapchat messages!",
+    "Oops, your screen is now stored on Betamax!",
+    "Oops, your screen is now in the clown!",
+    "Oops, your screen has been deprecated!",
+    "Oops, you're screen was seized by the FBI!",
+    "All your screen was shared with your coworkers!",
+    "All your screen are belong to us.",
+    "Well actually, your screen isn't needed anymore.",
+    "u just got popped with some 0day shit!!",
+    "M'lady,",
+  };
+
+  const char *header_quip = header_quips[random() % countof(header_quips)];
+
+  /* You got this because... */
+  const char *excuse_quips[] = {
+    "all human actions are equivalent and all are on principle doomed "
+    "to failure",
+    "you hold a diverse portfolio of cryptocurrencies",
+    "you need to get in on ransomware futures at the ground floor",
+    "your flight was overbooked",
+    "you did not apply the security update for bugs NSA keys secret from "
+    "Microsoft in your Windows(R) operating system",
+    "you are bad and you should feel bad",
+    "you used the wifi at defcon",
+    "you lack official Clown Strike[TM] threaty threat technology",
+  };
+
+  const char *excuse_quip = excuse_quips[random() % countof(excuse_quips)];
+
+  /* WELL ACTUALLY, screensavers aren't really nescessary anymore because... */
+  const char *screensaver_quips[] = {
+    "I read it on hacker news",
+    "that's official Debian policy now",
+    "that is the official policy of United Airlines",
+    "they cause global warming",
+    "they lack an eternal struggle",
+    "they lack a vapid dichotomy",
+    "those electrons could be used for gold farming instead",
+    "you can make more money in art exhibitions",
+  };
+
+  const char *screensaver_quip =
+    screensaver_quips[random() % countof(screensaver_quips)];
+
+  /* Positions of UI elements. Layout:
+
+  +---------+-+---------------------------------------+
+  |   LOGO  | |               HEADER                  |
+  |         | |---------------------------------------|
+  |         | | NOTE TEXT                             |
+  |   DEAD  | |                                       |
+  |   LINE  | |                                       |
+  |  TIMERS | |                                       |
+  |         | |                                       |
+  |         | |                                       |
+  |         | |                                       |
+  |         | |                                       |
+  |         | |                                       |
+  +---------+ |                                       |
+  | LINKS   | +---------------------------------------+
+  | LINKS   | | FOOTER                                |
+  +---------+-+---------------------------------------+
+
+  The right side of the UI maximises to available width.
+  The note text maximises to available height.
+  The logo, header and timers are anchored to the top left of the window.
+  The links and footer are anchored to the bottom left of the window.
+  The entire window is a fixed 4:3 scale, with a minimum margin around it.
+  */
+
+  /* Minimum margin around the window */
+  int margin_size = 50;
+
+  /* Right side of window (header, ransom note, BTC address, buttons) */
+  const int right_pane_x = 270;
+  /* "oops" header */
+  const int header_y = 5;
+  /* Ransom note */
+  const int ransom_y = 40;
+  /* Footer area */
+  const int footer_height = 100;
+
+  /* Left pane (deadlines, countdown, links) */
+  const int left_pane_width = right_pane_x - 5;
+  /* Logo (shown at top left corner) */
+  int logo_x = (left_pane_width - pix_w) / 2;
+  int logo_y = 10;
+  /* Deadline position */
+  const int deadline_y = 130;
+  /* Links height */
+  const int links_height = 100;
+  const int links_x = 20;
+
+  /* main window text */
+  unsigned long fg = bst->fg;
+  unsigned long bg = bst->bg;
+  /* ransom note */
+  unsigned long fg2 = get_pixel_resource (dpy, bst->xgwa.colormap,
+                                          "ransomware.foreground2",
+                                          "Ransomware.Foreground");
+  unsigned long bg2 = get_pixel_resource (dpy, bst->xgwa.colormap,
+                                          "ransomware.background2",
+                                          "Ransomware.Background");
+  /* buttons */
+  unsigned long fg3 = get_pixel_resource (dpy, bst->xgwa.colormap,
+                                          "ransomware.foreground3",
+                                          "Ransomware.Foreground");
+  unsigned long bg3 = get_pixel_resource (dpy, bst->xgwa.colormap,
+                                          "ransomware.background3",
+                                          "Ransomware.Background");
+  /* links */
+  unsigned long link = get_pixel_resource (dpy, bst->xgwa.colormap,
+                                           "ransomware.link",
+                                           "Ransomware.Foreground");
+  /* headers */
+  unsigned long theader = get_pixel_resource (dpy, bst->xgwa.colormap,
+                                              "ransomware.timerheader",
+                                              "Ransomware.Foreground");
+
+  const char *lines[] = {
+    "*What Happened To My Computer?\n",
+    "Your important pixels are paintcrypted. All of your documents, photos, ",
+    "videos, databases, icons, dick pics are not accessible because they ",
+    "have been bitblted. Maybe you are looking for a way to get them back, ",
+    "but don't waste your time. Nobody can recover your pixels without our ",
+    "pointer motion clicker services.\n",
+    "\n",
+    "*Can I Recover My Important Dick Pix?\n",
+    "Yes. We guarantee that you can recover them safely and easily. But you ",
+    "not have much time.\n",
+    "You can expose some files for free. Try it now by pressing <The Any ",
+    "Key>.\n",
+    "But if you want to unsave all your screens, then you need to pay. ",
+    "You have only 3 days to click. After that the clicks will double. ",
+    "After 7 days your pixels will be gone forever.\n",
+    "We will have free events for cheapskates who can't pay in 6 months, ",
+    "long after all the pixels are xored.\n",
+    "\n",
+    "*How do I pay?\n",
+    "Payment is accepted in ", "[C]",
+    " only. For more information, press <About ", "[C]", ">.",
+    " Please check the current price of ", "[C]", " and buy some ", "[C]",
+    ". For more information, press <How to buy ", "[C]", ">.\n",
+    "And send the correct amount to the address specified below. After your ",
+    "payment, press <Check Payment>. Best time to check: 4-6am, Mon-Fri.\n",
+    "\n",
+    "*Why Did I Get This?\n",
+    "You got this because ", "[Q]",
+    ". Also you didn't click hard enough and now Tinkerbelle is dead.\n",
+    "\n",
+    "*But Aren't Screensavers Are Necessary?\n",
+    "WELL ACTUALLY, screensavers aren't really nescessary anymore because ",
+    "[S]", ".\n",
+    "\n",
+    "Please file complaints to @POTUS on Twitter.\n",
+    "\n"
+    "\n"
+    "\n"
+    "\n",
+    "*GREETZ TO CRASH OVERRIDE AND ALSO JOEY\n",
+  };
+
+  /* Make a 4:3 ratio box inside of the workspace */
+  int box_width = bst->xgwa.width - (margin_size * 2);
+  int box_height = bst->xgwa.height - bst->yoff - (margin_size * 2);
+  int box_x = margin_size;
+  int box_y = margin_size;
+  if ((bst->xgwa.width / 4) * 3 > bst->xgwa.height) {
+    /* Widescreen, make narrow bits */
+    box_width = (bst->xgwa.height * 4 / 3) - (margin_size * 2);
+    box_x = (bst->xgwa.width - box_width) / 2;
+  } else {
+    /* Narrowscreen, make wide bits */
+    box_height = (bst->xgwa.width * 3 / 4) - (margin_size * 2);
+    box_y = (bst->xgwa.height - bst->yoff - box_height) / 2;
+  }
+
+  if (box_width < 750 && box_x == margin_size) {
+    /* Not much width... */
+    box_width = bst->xgwa.width;
+    box_x = 0;
+  }
+
+
+  bst->xoff = bst->left_margin = bst->right_margin = 0;
+
+  if (!(random() % 8))
+    return apple2ransomware (dpy, window);
+
+  /* Grab the desktop image */
+  /* BSOD_IMG (bst); */
+  bst->wrap_p = True;
+
+  /* Draw the main red window */
+  BSOD_INVERT (bst);
+  BSOD_RECT (bst, True, box_x, box_y, box_width, box_height);
+
+  if (pixmap) {
+    bst->pixmap = pixmap;
+    BSOD_PIXMAP (bst, 0, 0, pix_w, pix_h, box_x + logo_x, box_y + logo_y);
+  }
+
+  /* Setup deadlines */
+  strftime (stage1_deadline_str, sizeof(stage1_deadline_str),
+            "%m/%d/%Y %H:%M:%S\n\n", localtime(&stage1_deadline));
+  strftime (stage2_deadline_str, sizeof(stage1_deadline_str),
+            "%m/%d/%Y %H:%M:%S\n\n", localtime(&stage2_deadline));
+
+  BSOD_INVERT (bst);
+  /* Draw header pane */
+  BSOD_FONT (bst, 0);
+  BSOD_MOVETO (bst, box_x + right_pane_x, box_y + header_y + bst->fontA->ascent);
+  BSOD_MARGINS (bst, box_x + right_pane_x, box_x);
+  BSOD_COLOR (bst, fg, bg);
+  BSOD_TEXT (bst, CENTER, header_quip);
+
+  /* Draw left-side timers */
+  BSOD_MOVETO (bst, box_x, box_y + deadline_y);
+  BSOD_MARGINS (bst, box_x, box_x + box_width - left_pane_width);
+  BSOD_FONT (bst, 1);
+
+  BSOD_COLOR (bst, theader, bg);
+  BSOD_TEXT (bst, CENTER, "Payment will be raised on\n");
+  BSOD_COLOR (bst, fg, bg);
+  BSOD_TEXT (bst, CENTER, stage1_deadline_str);
+
+  BSOD_TEXT (bst, CENTER, "Time Left\n");
+  stage1_countdown_y = (line_height * 4) + box_y + deadline_y;
+  BSOD_TEXT (bst, CENTER, "\n");
+  BSOD_TEXT (bst, CENTER, "\n\n");
+
+  BSOD_COLOR (bst, theader, bg);
+  BSOD_TEXT (bst, CENTER, "Your pixels will be lost on\n");
+  BSOD_COLOR (bst, fg, bg);
+  BSOD_TEXT (bst, CENTER, stage2_deadline_str);
+
+  BSOD_TEXT (bst, CENTER, "Time Left\n");
+  stage2_countdown_y = (line_height * 9) + box_y + deadline_y;
+  BSOD_TEXT (bst, CENTER, "\n");
+
+  /* Draw links */
+  BSOD_FONT (bst, 1);
+  BSOD_MOVETO (bst, box_x + links_x, box_y + box_height - links_height);
+  BSOD_MARGINS (bst, box_x + links_x, box_x + box_width - left_pane_width);
+  BSOD_COLOR (bst, link, bg);
+
+  if (box_height > 425) {
+    /* Don't show this on small screens */
+    BSOD_TEXT (bst, LEFT, "\n");
+    BSOD_TEXT (bst, LEFT, "About ");
+    BSOD_TEXT (bst, LEFT, currency);
+    BSOD_TEXT (bst, LEFT, "\n\n"
+                          "How to buy ");
+    BSOD_TEXT (bst, LEFT, currency);
+    BSOD_TEXT (bst, LEFT, "\n\n"
+                          "Contact us\n");
+  }
+
+  /* Ransom note text area */
+  BSOD_COLOR (bst, bg2, fg2);
+  BSOD_RECT (bst, True, box_x + right_pane_x, box_y + ransom_y,
+             box_width - right_pane_x - 10,
+             box_height - ransom_y - footer_height);
+  BSOD_MOVETO (bst, box_x + right_pane_x + 5,
+               box_y + ransom_y + (line_height * 1.1));
+  BSOD_MARGINS (bst, box_x + right_pane_x + 5, box_x + 15);
+  /* VERT_MARGINS are a bit high, to ensure we draw as much text as we can in
+   * the box, even if the line is partially cut. We'll draw over this later.
+   */
+  BSOD_VERT_MARGINS (bst, box_y + ransom_y, box_y + (footer_height / 2));
+  BSOD_INVERT (bst);
+
+  /* Write out the ransom note itself */
+  BSOD_CROP (bst, True);
+  for (i = 0; i < countof(lines); i++)
+    {
+      const char *s = lines[i];
+      if (!strcmp(s, "[C]")) s = currency;
+      else if  (!strcmp(s, "[Q]")) s = excuse_quip;
+      else if  (!strcmp(s, "[S]")) s = screensaver_quip;
+
+      if (*s == '*')
+        {
+          s++;
+          BSOD_FONT (bst, 2);
+        }
+      else
+        BSOD_FONT (bst, 0);
+
+      BSOD_TEXT (bst, LEFT, s);
+    }
+  BSOD_CROP (bst, False);
+  BSOD_FONT (bst, 0);
+
+  /* Draw over any overflowing ransom text. */
+  BSOD_COLOR (bst, bg, fg);
+  BSOD_RECT (bst, True, box_x + right_pane_x,
+             box_y + box_height - footer_height,
+             box_width - right_pane_x, footer_height);
+
+  /* Draw the footer */
+  BSOD_COLOR (bst, theader, bg);
+  BSOD_MOVETO (bst, box_x + right_pane_x,
+               box_y + box_height - footer_height + line_height);
+
+  sprintf(buf, "Send $%.2f of %s to this address:\n", 101+frand(888), currency);
+  BSOD_TEXT (bst, LEFT, buf);
+  BSOD_COLOR (bst, fg2, bg2);
+
+  /* address, has some extra slashes in there because it's a fake address */
+  for (i = 0; i < 40; i++) {
+    const char *s =
+      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123459789";
+    buf[i] = s[random() % strlen(s)];
+  }
+  strncpy (buf, " //", 3);
+  buf[10] = '/';
+  buf[17] = '/';
+  buf[24] = '/';
+  strcpy (buf+33, " ");
+  BSOD_TEXT (bst, LEFT, buf);
+
+  BSOD_COLOR (bst, fg, bg);
+  BSOD_TEXT (bst, LEFT, "   ");
+  BSOD_COLOR (bst, fg3, bg3);
+  BSOD_TEXT (bst, LEFT, "  Copy  ");
+  BSOD_COLOR (bst, fg, bg);
+  BSOD_TEXT (bst, LEFT, "\n\n");
+
+  BSOD_COLOR (bst, fg3, bg3);
+  BSOD_TEXT (bst, LEFT, "  Demogrify Screen  ");
+  BSOD_COLOR (bst, fg, bg);
+  BSOD_TEXT (bst, LEFT, "            ");
+  BSOD_COLOR (bst, fg3, bg3);
+  BSOD_TEXT (bst, LEFT, "  Check Payment  ");
+
+
+  /* Draw countdown timers */
+  BSOD_COLOR (bst, fg, bg);
+  BSOD_FONT (bst, 0);
+  do {
+    /* First timer */
+    BSOD_MOVETO (bst, box_x, stage1_countdown_y);
+    BSOD_MARGINS (bst, box_x, box_x + box_width - left_pane_width);
+
+    countdown_r = stage1_deadline - now;
+    countdown_s = countdown_r % 60;
+    countdown_m = (countdown_r / 60) % 60;
+    countdown_h = (countdown_r / 3600) % 24;
+    countdown_d = (countdown_r / 86400);
+
+    sprintf (countdown_str, "%02d:%02d:%02d:%02d\n",
+             countdown_d, countdown_h, countdown_m, countdown_s);
+
+    BSOD_TEXT (bst, CENTER, countdown_str);
+
+    /* Second timer */
+    BSOD_MOVETO (bst, box_x, stage2_countdown_y);
+
+    countdown_r = stage2_deadline - now;
+    countdown_s = countdown_r % 60;
+    countdown_m = (countdown_r / 60) % 60;
+    countdown_h = (countdown_r / 3600) % 24;
+    countdown_d = (countdown_r / 86400);
+
+    sprintf (countdown_str, "%02d:%02d:%02d:%02d\n",
+             countdown_d, countdown_h, countdown_m, countdown_s);
+
+    BSOD_TEXT (bst, CENTER, countdown_str);
+
+    BSOD_PAUSE (bst, 1000000);
+    now++;
+
+    /* While the "correct" thing to do is create enough of a script to fill the
+     * stage2_deadline, this would be 7 days of "frames", which is quite a bit
+     * of memory. Instead, only fill the buffer with 1 hour of frames, which is
+     * enough to make the point before xscreensaver cycles us.
+     */
+  } while (stage1_deadline - now > 3600);
+
+  XClearWindow (dpy, window);
+  return bst;
+}
+
 
 /* As seen in Portal 2.  By jwz.
  */
@@ -1326,7 +1869,9 @@ glados (Display *dpy, Window window)
 
   int i;
 
-  bst->y = ((bst->xgwa.height -
+  bst->xoff = bst->left_margin = bst->right_margin = 0;
+
+  bst->y = ((bst->xgwa.height - bst->yoff -
              ((bst->font->ascent + bst->font->descent) * countof(panicstr)))
             / 2);
 
@@ -1387,7 +1932,7 @@ sco (Display *dpy, Window window)
      "** Press Any Key to Reboot **\n"
     );
 
-  bst->y = ((bst->xgwa.height -
+  bst->y = ((bst->xgwa.height - bst->yoff -
              ((bst->font->ascent + bst->font->descent) * 18)));
 
   XClearWindow (dpy, window);
@@ -1400,10 +1945,11 @@ sco (Display *dpy, Window window)
 static struct bsod_state *
 sparc_linux (Display *dpy, Window window)
 {
-  struct bsod_state *bst = make_bsod_state (dpy, window, 
+  struct bsod_state *bst = make_bsod_state (dpy, window,
                                             "sparclinux", "SparcLinux");
   bst->scroll_p = True;
-  bst->y = bst->xgwa.height - bst->font->ascent - bst->font->descent;
+  bst->y = bst->xgwa.height - bst->yoff
+    - bst->font->ascent - bst->font->descent;
 
   BSOD_TEXT (bst, LEFT,
         "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
@@ -1485,7 +2031,7 @@ bsd (Display *dpy, Window window)
   BSOD_TEXT (bst, LEFT, (b ? "damn!" : "sunk!"));
   BSOD_TEXT (bst, LEFT, "\nRebooting\n");
 
-  bst->y = ((bst->xgwa.height -
+  bst->y = ((bst->xgwa.height - bst->yoff -
              ((bst->font->ascent + bst->font->descent) * 4)));
 
   XClearWindow (dpy, window);
@@ -1507,6 +2053,9 @@ amiga (Display *dpy, Window window)
                                           "amiga.background2",
                                           "Amiga.Background");
 
+  bst->yoff = 0;
+  bst->top_margin = bst->bottom_margin = 0;
+
 # ifdef DO_XPM
   pixmap = xpm_data_to_pixmap (dpy, window, (char **) amiga_hand,
                                &pix_w, &pix_h, 0);
@@ -1519,6 +2068,7 @@ amiga (Display *dpy, Window window)
                               pixmap, pix_w, pix_h);
       pix_w *= 2;
       pix_h *= 2;
+      lw *= 2;
     }
 
   XSetLineAttributes (dpy, bst->gc, lw, LineSolid, CapButt, JoinMiter);
@@ -1596,7 +2146,7 @@ atari (Display *dpy, Window window)
   for (i = 1; i< 7; i++)
     BSOD_COPY (bst, x, y, pix_w, pix_h, (x + (i*offset)), y);
 
-  for (; i< 10; i++) 
+  for (; i< 10; i++)
     {
       BSOD_PAUSE (bst, 1000000);
       BSOD_COPY (bst, x, y, pix_w, pix_h, (x + (i*offset)), y);
@@ -1624,6 +2174,8 @@ mac (Display *dpy, Window window)
   const char *string = ("0 0 0 0 0 0 0 F\n"
                        "0 0 0 0 0 0 0 3");
 
+  bst->xoff = bst->left_margin = bst->right_margin = 0;
+
   pixmap = XCreatePixmapFromBitmapData(dpy, window, (char *) mac_bits,
                                       mac_width, mac_height,
                                       bst->fg, bst->bg, bst->xgwa.depth);
@@ -1757,6 +2309,8 @@ macsbug (Display *dpy, Window window)
                                          "macsbug.borderColor",
                                          "MacsBug.BorderColor");
 
+  bst->xoff = bst->left_margin = bst->right_margin = 0;
+
   for (s = body; *s; s++) if (*s == '\n') body_lines++;
 
   char_width = (bst->font->per_char
@@ -1767,8 +2321,8 @@ macsbug (Display *dpy, Window window)
   col_right   = char_width  * 12;  /* number of columns in `left' */
   page_bottom = line_height * 47;  /* number of lines in `left'   */
 
-  if (page_bottom > bst->xgwa.height
-    page_bottom = bst->xgwa.height;
+  if (page_bottom > bst->xgwa.height - bst->yoff)
+    page_bottom = bst->xgwa.height - bst->yoff;
 
   row_bottom = page_bottom - line_height;
   row_top    = row_bottom - (line_height * 4);
@@ -1802,15 +2356,15 @@ macsbug (Display *dpy, Window window)
   BSOD_TEXT (bst, LEFT, bottom);
 
   BSOD_RECT (bst, True, xoff + col_right, yoff, 2, page_bottom);
-  BSOD_RECT (bst, True, xoff + col_right, yoff + row_top, 
+  BSOD_RECT (bst, True, xoff + col_right, yoff + row_top,
              page_right - col_right, 1);
-  BSOD_RECT (bst, True, xoff + col_right, yoff + row_bottom, 
+  BSOD_RECT (bst, True, xoff + col_right, yoff + row_bottom,
              page_right - col_right, 1);
   BSOD_RECT (bst, False, xoff-2, yoff, page_right+4, page_bottom);
 
   BSOD_LINE_DELAY (bst, 500);
-  BSOD_MOVETO (bst, 
-               xoff + col_right + char_width, 
+  BSOD_MOVETO (bst,
+               xoff + col_right + char_width,
                yoff + body_top + line_height);
   BSOD_MARGINS (bst, xoff + col_right + char_width, yoff);
   BSOD_TEXT (bst, LEFT, body);
@@ -1846,6 +2400,16 @@ mac1 (Display *dpy, Window window)
                                         macbomb_width, macbomb_height,
                                         bst->fg, bst->bg, bst->xgwa.depth);
 
+  if (pixmap && 
+      pix_w < bst->xgwa.width / 2 &&
+      pix_h < bst->xgwa.height / 2)
+    {
+      pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual,
+                              bst->xgwa.depth, pixmap, pix_w, pix_h);
+      pix_w *= 2;
+      pix_h *= 2;
+    }
+
   x = (bst->xgwa.width - pix_w) / 2;
   y = (bst->xgwa.height - pix_h) / 2;
   if (y < 0) y = 0;
@@ -1955,7 +2519,7 @@ macx_10_2 (Display *dpy, Window window, Bool v10_3_p)
   int pix_w = 0, pix_h = 0;
   int x, y;
 
-  pixmap = xpm_data_to_pixmap (dpy, window, 
+  pixmap = xpm_data_to_pixmap (dpy, window,
                                (char **) (v10_3_p ? osx_10_3 : osx_10_2),
                                &pix_w, &pix_h, 0);
   if (! pixmap) abort();
@@ -2186,6 +2750,8 @@ macx_install (Display *dpy, Window window)
   int i, min;
   double pct;
 
+  bst->xoff = bst->left_margin = bst->right_margin = 0;
+
   pixmap = XCreatePixmapFromBitmapData (dpy, window, (char *) apple_bits,
                                         apple_width, apple_height,
                                         fg, bg, bst->xgwa.depth);
@@ -2276,7 +2842,7 @@ macx (Display *dpy, Window window)
 static struct bsod_state *
 blitdamage (Display *dpy, Window window)
 {
-  struct bsod_state *bst = 
+  struct bsod_state *bst =
     make_bsod_state (dpy, window, "blitdamage", "BlitDamage");
 
   int i;
@@ -2286,7 +2852,7 @@ blitdamage (Display *dpy, Window window)
   int steps;
   int src_x, src_y;
   int x, y;
-  
+
   w = bst->xgwa.width;
   h = bst->xgwa.height;
 
@@ -2295,27 +2861,27 @@ blitdamage (Display *dpy, Window window)
   steps = 50;
   chunk_w = w / (random() % 1 + 1);
   chunk_h = h / (random() % 1 + 1);
-  if (random() & 0x1000) 
+  if (random() & 0x1000)
     delta_y = random() % 600;
   if (!delta_y || (random() & 0x2000))
     delta_x = random() % 600;
-  src_x = 0; 
-  src_y = 0; 
+  src_x = 0;
+  src_y = 0;
   x = 0;
   y = 0;
-  
+
   BSOD_IMG (bst);
   for (i = 0; i < steps; i++) {
-    if (x + chunk_w > w) 
+    if (x + chunk_w > w)
       x -= w;
     else
       x += delta_x;
-    
+
     if (y + chunk_h > h)
       y -= h;
     else
       y += delta_y;
-    
+
     BSOD_COPY (bst, src_x, src_y, chunk_w, chunk_h, x, y);
     BSOD_PAUSE (bst, 1000);
   }
@@ -2478,7 +3044,7 @@ os2 (Display *dpy, Window window)
 
 /* SPARC Solaris panic. Should look pretty authentic on Solaris boxes.
  * Anton Solovyev <solovam@earthlink.net>
- */ 
+ */
 static struct bsod_state *
 sparc_solaris (Display *dpy, Window window)
 {
@@ -2489,13 +3055,13 @@ sparc_solaris (Display *dpy, Window window)
   bst->wrap_p = True;
   bst->left_margin = bst->right_margin = bst->xgwa.width  * 0.07;
   bst->top_margin = bst->bottom_margin = bst->xgwa.height * 0.07;
-  bst->y = bst->top_margin + bst->font->ascent;
+  bst->y = bst->top_margin + bst->yoff + bst->font->ascent;
 
   BSOD_IMG (bst);
   BSOD_PAUSE (bst, 3000000);
 
   BSOD_INVERT(bst);
-  BSOD_RECT (bst, True, 
+  BSOD_RECT (bst, True,
              bst->left_margin, bst->top_margin,
              bst->xgwa.width - bst->left_margin - bst->right_margin,
              bst->xgwa.height - bst->top_margin - bst->bottom_margin);
@@ -2566,6 +3132,9 @@ linux_fsck (Display *dpy, Window window)
   int i;
   const char *sysname;
   char buf[1024];
+# ifdef HAVE_UNAME
+  struct utsname uts;
+#endif /* UNAME */
 
   const char *linux_panic[] = {
    " kernel: Unable to handle kernel paging request at virtual "
@@ -2608,7 +3177,6 @@ linux_fsck (Display *dpy, Window window)
   sysname = "linux";
 # ifdef HAVE_UNAME
   {
-    struct utsname uts;
     char *s;
     if (uname (&uts) >= 0)
       sysname = uts.nodename;
@@ -2627,7 +3195,7 @@ linux_fsck (Display *dpy, Window window)
   BSOD_CHAR_DELAY (bst, 300000);
   BSOD_TEXT (bst, LEFT, ".........\n");
   BSOD_CHAR_DELAY (bst, 0);
-  BSOD_TEXT (bst, LEFT, 
+  BSOD_TEXT (bst, LEFT,
              "xinit:  X server slow to shut down, sending KILL signal.\n"
              "waiting for server to die ");
   BSOD_CHAR_DELAY (bst, 300000);
@@ -2794,7 +3362,7 @@ linux_fsck (Display *dpy, Window window)
   if (0 == random() % 10)
     goto PANIC;
 
-  BSOD_TEXT (bst, LEFT, 
+  BSOD_TEXT (bst, LEFT,
              "Pass 3: Checking directory connectivity\n"
              "/lost+found not found.  Create? yes\n");
   BSOD_PAUSE (bst, 2000000);
@@ -2802,7 +3370,7 @@ linux_fsck (Display *dpy, Window window)
   /* Unconnected directory inode 4949 (/var/spool/squid/06/???)
      Connect to /lost+found<y>? yes
 
-     '..' in /var/spool/squid/06/08 (20351) is <The NULL inode> (0), should be 
+     '..' in /var/spool/squid/06/08 (20351) is <The NULL inode> (0), should be
      /var/spool/squid/06 (20350).
      Fix<y>? yes
 
@@ -2909,12 +3477,16 @@ linux_fsck (Display *dpy, Window window)
 static struct bsod_state *
 hppa_linux (Display *dpy, Window window)
 {
-  struct bsod_state *bst = 
+  struct bsod_state *bst =
     make_bsod_state (dpy, window, "hppalinux", "HPPALinux");
 
   int i = 0;
   const char *release, *sysname, *gccversion, *version;
   long int linedelay = 0;
+  char ss[1024];
+# ifdef HAVE_UNAME
+  struct utsname uts;
+# endif /* UNAME */
 
   __extension__
   struct { long int delay; const char *string; } linux_panic[] =
@@ -3055,7 +3627,6 @@ hppa_linux (Display *dpy, Window window)
   version = "#2 Mon Dec 8 06:09:27 GMT 2003";
 # ifdef HAVE_UNAME
   {
-    struct utsname uts;
     char *s;
     if (uname (&uts) >= 0)
       {
@@ -3079,8 +3650,7 @@ hppa_linux (Display *dpy, Window window)
 
   /* Insert current host name into banner on line 2 */
   {
-    char ss[1024];
-    snprintf (ss, 1024, linux_panic[1].string, 
+    snprintf (ss, 1024, linux_panic[1].string,
              release, sysname, gccversion, version);
     linux_panic[1].string = ss;
   }
@@ -3095,7 +3665,8 @@ hppa_linux (Display *dpy, Window window)
       i++;
     }
 
-  bst->y = bst->xgwa.height - bst->font->ascent - bst->font->descent;
+  bst->y = bst->xgwa.height - bst->yoff
+    - bst->font->ascent - bst->font->descent;
 
   XClearWindow(dpy, window);
   return bst;
@@ -3116,6 +3687,9 @@ vms (Display *dpy, Window window)
   char *s, *s1;
   int i;
   int arg_count;
+# ifdef HAVE_UNAME
+  struct utsname uts;
+# endif /* UNAME */
 
   __extension__
 
@@ -3188,7 +3762,6 @@ vms (Display *dpy, Window window)
   sysname = "VMS001";
 # ifdef HAVE_UNAME
   {
-    struct utsname uts;
     if (uname (&uts) >= 0)
       sysname = uts.nodename;
     s = strchr (sysname, '.');
@@ -3290,7 +3863,8 @@ hvx (Display *dpy, Window window)
 
   bst->scroll_p = True;
   bst->wrap_p = True;
-  bst->y = bst->xgwa.height - bst->bottom_margin - bst->font->ascent;
+  bst->y = bst->xgwa.height - bst->bottom_margin - bst->yoff
+    - bst->font->ascent;
 
   BSOD_CHAR_DELAY (bst, 10000);
   BSOD_TEXT (bst, LEFT,
@@ -3352,14 +3926,17 @@ hpux (Display *dpy, Window window)
   struct bsod_state *bst = make_bsod_state (dpy, window, "hpux", "HPUX");
   const char *sysname;
   char buf[2048];
+# ifdef HAVE_UNAME
+  struct utsname uts;
+# endif /* UNAME */
 
   bst->scroll_p = True;
-  bst->y = bst->xgwa.height - bst->bottom_margin - bst->font->ascent;
+  bst->y = bst->xgwa.height - bst->bottom_margin - bst->yoff
+    - bst->font->ascent;
 
   sysname = "HPUX";
 # ifdef HAVE_UNAME
   {
-    struct utsname uts;
     char *s;
     if (uname (&uts) >= 0)
       sysname = uts.nodename;
@@ -3451,7 +4028,7 @@ hpux (Display *dpy, Window window)
     for (i = 0; i <= steps; i++)
       {
         if (i > steps) i = steps;
-        sprintf (buf, 
+        sprintf (buf,
                "*** Dumping: %3d%% complete (%d of 40 MB) (device 64:0x2)\r",
                  i * 100 / steps,
                  i * size / steps);
@@ -3478,7 +4055,8 @@ os390 (Display *dpy, Window window)
   struct bsod_state *bst = make_bsod_state (dpy, window, "os390", "OS390");
 
   bst->scroll_p = True;
-  bst->y = bst->xgwa.height - bst->bottom_margin - bst->font->ascent;
+  bst->y = bst->xgwa.height - bst->bottom_margin - bst->yoff
+    - bst->font->ascent;
 
   BSOD_LINE_DELAY (bst, 100000);
   BSOD_TEXT (bst, LEFT,
@@ -3540,14 +4118,17 @@ tru64 (Display *dpy, Window window)
   struct bsod_state *bst = make_bsod_state (dpy, window, "tru64", "Tru64");
   const char *sysname;
   char buf[2048];
+# ifdef HAVE_UNAME
+  struct utsname uts;
+#endif /* UNAME */
 
   bst->scroll_p = True;
-  bst->y = bst->xgwa.height - bst->bottom_margin - bst->font->ascent;
+  bst->y = bst->xgwa.height - bst->bottom_margin - bst->yoff
+    - bst->font->ascent;
 
   sysname = "127.0.0.1";
 # ifdef HAVE_UNAME
   {
-    struct utsname uts;
     if (uname (&uts) >= 0)
       sysname = uts.nodename;
   }
@@ -3604,7 +4185,7 @@ tru64 (Display *dpy, Window window)
   BSOD_PAUSE (bst, 3000000);
 
   BSOD_TEXT (bst, LEFT,
-    "\n"   
+    "\n"
     "CPU 0 booting\n"
     "\n"
     "\n"
@@ -3773,7 +4354,7 @@ nvidia_draw (struct bsod_state *bst)
 
   nvs->tick++;
   if ((random() % 5) == 0)    /* change the display */
-    nvspatter (nvs->grid, nvs->rows, nvs->cols, nvs->ncolors, 
+    nvspatter (nvs->grid, nvs->rows, nvs->cols, nvs->ncolors,
                countof(nvs->bits), False);
 
   return 250000;
@@ -3829,7 +4410,7 @@ nvidia (Display *dpy, Window window)
       if (!nvs->gc1) nvs->gc1 = XCreateGC (dpy, nvs->bits[i], 0, &gcv);
 
       XSetForeground (dpy, nvs->gc1, 0);
-      XFillRectangle (dpy, nvs->bits[i], nvs->gc1, 0, 0, 
+      XFillRectangle (dpy, nvs->bits[i], nvs->gc1, 0, 0,
                       nvs->cellw, nvs->cellh);
       XSetForeground (dpy, nvs->gc1, 1);
 
@@ -3843,10 +4424,10 @@ nvidia (Display *dpy, Window window)
 
   /* Randomize the grid
    */
-  nvspatter (nvs->grid, nvs->rows, nvs->cols, nvs->ncolors, 
+  nvspatter (nvs->grid, nvs->rows, nvs->cols, nvs->ncolors,
              countof(nvs->bits), True);
   for (i = 0; i < 20; i++)
-    nvspatter (nvs->grid, nvs->rows, nvs->cols, nvs->ncolors, 
+    nvspatter (nvs->grid, nvs->rows, nvs->cols, nvs->ncolors,
                countof(nvs->bits), False);
 
   return bst;
@@ -3865,7 +4446,7 @@ nvidia (Display *dpy, Window window)
  * The Apple ][ logic and video hardware is in apple2.c. The TV is emulated by
  * analogtv.c for maximum realism
  *
- * Trevor Blackwell <tlb@tlb.org> 
+ * Trevor Blackwell <tlb@tlb.org>
  */
 
 static const char * const apple2_basic_errors[]={
@@ -3912,10 +4493,10 @@ static void a2controller_crash(apple2_sim_t *sim, int *stepno,
   if (!sim->controller_data)
     sim->controller_data = calloc(sizeof(struct mydata),1);
   mine=(struct mydata *) sim->controller_data;
-  
+
   switch(*stepno) {
   case 0:
-    
+
     a2_init_memory_active(sim);
     sim->dec->powerup = 1000.0;
 
@@ -4147,6 +4728,134 @@ apple2crash (Display *dpy, Window window)
 }
 
 
+static void
+a2controller_ransomware(apple2_sim_t *sim, int *stepno,
+                        double *next_actiontime)
+{
+  apple2_state_t *st=sim->st;
+
+  struct mydata {
+    const char *str;
+    Bool bold_p;
+  } *mine;
+
+  if (!sim->controller_data)
+    sim->controller_data = calloc(sizeof(struct mydata),1);
+  mine=(struct mydata *) sim->controller_data;
+
+  switch(*stepno) {
+  case 0:
+
+    st->gr_mode |= A2_GR_FULL;
+    a2_cls(st);
+    a2_goto(st,0,16);
+    a2_prints(st, "APPLE ][");
+    a2_goto(st,2,0);
+    *stepno = 10;
+    *next_actiontime += 2;
+    break;
+
+  case 10:
+    a2_prints(st, "READY\n\n");
+    *stepno = 11;
+    *next_actiontime += 1;
+    break;
+
+  case 11:
+    a2_goto(st, 1, 0);
+    *stepno = 12;
+    mine->str =
+      ("\n"
+       " _____________________________________\n"
+       "/                                     \\\n"
+       "! OOPS YOUR FILES HAVE BEEN ENCRYPTED !\n"
+       "!          ________________________   !\n"
+       "!         !                        !  !\n"
+       "!  [/--\\]   !  [ WHAT HAPPENED TO MY ] !  !\n"
+       "!  [!]  [!]   !  [ COMPUTER? ]           !  !\n"
+       "!  [!]  [!]   !                        !  !\n"
+       "! [######]  !  [ CAN I RECOVER MY ]    !  !\n"
+       "! [######]  !  [ FILES? ]              !  !\n"
+       "! [######]  !                        !  !\n"
+       "! [######]  !  [ HOW DO I PAY? ]       !  !\n"
+       "!         !                        !  !\n"
+       "!         !________________________!  !\n"
+       "!                                     !\n"
+       "!         BITCOIN ACCEPTED HERE       !\n"
+       "\\_____________________________________/\n"
+       "\n"
+       "\n"
+       "WAITING FOR BLOCKCHAIN..@\n"
+       "\n"
+       "PLEASE INSERT NEXT FLOPPY: "
+       );
+    break;
+
+  case 12:
+    {
+      char c = *mine->str;
+      mine->str++;
+
+      if (c == 0)
+        {
+          *next_actiontime += 30;
+          *stepno = 0;
+        }
+      else if (c == '[')
+        mine->bold_p++;
+      else if (c == ']')
+        mine->bold_p--;
+      else
+        {
+          if (c == '@')
+            {
+              c = '.';
+              *next_actiontime += 2;
+            }
+
+          if (mine->bold_p)
+            c |= 0xC0;
+          a2_printc_noscroll(st, c);
+          if (c == '.')
+            *next_actiontime += 1;
+        }
+    }
+    break;
+
+  case A2CONTROLLER_FREE:
+    return;
+  }
+}
+
+
+static int
+a2_ransomware_draw (struct bsod_state *bst)
+{
+  apple2_sim_t *sim = (apple2_sim_t *) bst->closure;
+  if (! sim) {
+    sim = apple2_start (bst->dpy, bst->window, 9999999,
+                        a2controller_ransomware);
+    bst->closure = sim;
+  }
+
+  if (! apple2_one_frame (sim)) {
+    bst->closure = 0;
+  }
+
+  return 10000;
+}
+
+static struct bsod_state *
+apple2ransomware (Display *dpy, Window window)
+{
+  struct bsod_state *bst = make_bsod_state (dpy, window, "apple2", "Apple2");
+  bst->draw_cb = a2_ransomware_draw;
+  bst->free_cb = a2_free;
+  return bst;
+}
+
+
+
 /* A crash spotted on a cash machine circa 2006, by jwz.  I didn't note
    what model it was; probably a Tranax Mini-Bank 1000 or similar vintage.
  */
@@ -4167,7 +4876,7 @@ atm (Display *dpy, Window window)
                                         atm_width, atm_height,
                                         bst->fg, bst->bg, bst->xgwa.depth);
 
-  while (pix_w <= bst->xgwa.width  * scale && 
+  while (pix_w <= bst->xgwa.width  * scale &&
          pix_h <= bst->xgwa.height * scale)
     {
       pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual, bst->xgwa.depth,
@@ -4302,7 +5011,7 @@ android (Display *dpy, Window window)
 
   while (1) {
     unsigned long delay =
-      ((state == 0 || 
+      ((state == 0 ||
         state == countof(lines0) ||
         state == countof(lines0) + countof(lines1) ||
         state == countof(lines0) + countof(lines1) + countof(lines2))
@@ -4314,10 +5023,11 @@ android (Display *dpy, Window window)
         BSOD_COLOR (bst, bg, bg);
         BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, bst->xgwa.height);
         BSOD_COLOR (bst, bg, c1);
-        BSOD_MOVETO (bst, bst->left_margin, bst->top_margin + line_height);
+        BSOD_MOVETO (bst, bst->left_margin + bst->xoff,
+                     bst->top_margin + bst->yoff + line_height);
         BSOD_TEXT (bst, LEFT, "*** UNLOCKED ***\n");
         BSOD_COLOR (bst, c2, bg);
-        BSOD_TEXT (bst, LEFT, 
+        BSOD_TEXT (bst, LEFT,
                    "PRIMOU PVT SHIP S-OFF RL\n"
                    "HBOOT-1.17.0000\n"
                    "CPLD-None\n"
@@ -4334,7 +5044,7 @@ android (Display *dpy, Window window)
         if (pixmap)
           {
             int x = (bst->xgwa.width - pix_w) / 2;
-            int y = bst->xgwa.height - pix_h;
+            int y = bst->xgwa.height - bst->yoff - pix_h;
             BSOD_PIXMAP (bst, 0, 0, pix_w, pix_h, x, y);
           }
       }
@@ -4434,6 +5144,7 @@ static const struct {
   { "NT",              windows_nt },
   { "Win2K",           windows_other },
   { "Win10",           windows_10 },
+  { "Ransomware",      windows_ransomware },
   { "Amiga",           amiga },
   { "Mac",             mac },
   { "MacsBug",         macsbug },
@@ -4547,7 +5258,7 @@ bsod_draw (Display *dpy, Window window, void *closure)
 
   if (dst->bst && dst->bst->img_loader)   /* still loading */
     {
-      dst->bst->img_loader = 
+      dst->bst->img_loader =
         load_image_async_simple (dst->bst->img_loader, 0, 0, 0, 0, 0);
       return 100000;
     }
@@ -4638,9 +5349,9 @@ bsod_draw (Display *dpy, Window window, void *closure)
               dst->which = dst->only = 0;
             }
         }
-          
+
       if (dst->debug_p)
-        fprintf (stderr, "%s: %s: launch\n", progname, 
+        fprintf (stderr, "%s: %s: launch\n", progname,
                  all_modes[dst->which].name);
 
       /* Run the mode setup routine...
@@ -4657,15 +5368,18 @@ bsod_draw (Display *dpy, Window window, void *closure)
       if (dst->bst)
         {
           if (dst->debug_p)
-            fprintf (stderr, "%s: %s: queue size: %d (%d)\n", progname, 
+            fprintf (stderr, "%s: %s: queue size: %d (%d)\n", progname,
                      dst->name, dst->bst->pos, dst->bst->queue_size);
 
           hack_title (dst);
           dst->bst->pos = 0;
-          dst->bst->x = dst->bst->current_left = dst->bst->left_margin;
+          dst->bst->x = dst->bst->current_left =
+            dst->bst->left_margin + dst->bst->xoff;
 
-          if (dst->bst->y < dst->bst->top_margin + dst->bst->font->ascent)
-            dst->bst->y = dst->bst->top_margin + dst->bst->font->ascent;
+          if (dst->bst->y < 
+              dst->bst->top_margin + dst->bst->yoff + dst->bst->font->ascent)
+            dst->bst->y =
+              dst->bst->top_margin + dst->bst->yoff + dst->bst->font->ascent;
         }
     }
 
@@ -4674,7 +5388,7 @@ bsod_draw (Display *dpy, Window window, void *closure)
 
 
 static void
-bsod_reshape (Display *dpy, Window window, void *closure, 
+bsod_reshape (Display *dpy, Window window, void *closure,
               unsigned int w, unsigned int h)
 {
   struct driver_state *dst = (struct driver_state *) closure;
@@ -4747,6 +5461,7 @@ static const char *bsod_defaults [] = {
   "*doNT:                 True",
   "*doWin2K:              True",
   "*doWin10:              True",
+  "*doRansomware:         True",
   "*doAmiga:              True",
   "*doMac:                True",
   "*doMacsBug:            True",
@@ -4790,6 +5505,16 @@ static const char *bsod_defaults [] = {
   ".win10.foreground:      White",
   ".win10.background:      #1070AA",
 
+  ".ransomware.foreground:   White",
+  ".ransomware.background:   #841212",
+  ".ransomware.foreground2:  Black",      /* ransom note */
+  ".ransomware.background2:  White",
+  ".ransomware.foreground3:  Black",      /* buttons */
+  ".ransomware.background3:  #AAAAAA",
+  ".ransomware.link:         #7BF9F6",
+  ".ransomware.timerheader:  #BDBE02",
+
+
   ".glaDOS.foreground:    White",
   ".glaDOS.background:    #0000AA",    /* EGA color 0x01. */
 
@@ -4906,6 +5631,10 @@ static const char *bsod_defaults [] = {
   ".win10.fontC:          Arial 9, Helvetica 9",
   ".win10.bigFont2:       ",
 
+  ".ransomware.font:         Arial 10, Helvetica 10",
+  ".ransomware.fontB:        Arial 8, Helvetica 8",
+  ".ransomware.fontC:        Arial 10, Helvetica Bold 10",
+
 # elif defined(HAVE_ANDROID)
 
   "*font:                 PxPlus IBM VGA8 16",
@@ -4928,32 +5657,36 @@ static const char *bsod_defaults [] = {
   ".win10.fontC:          -*-helvetica-medium-r-*-*-*-90-*-*-*-*-*-*",
   ".win10.bigFont2:       ",
 
+  ".ransomware.font:      -*-helvetica-medium-r-*-*-*-100-*-*-*-*-*-*",
+  ".ransomware.fontB:     -*-helvetica-medium-r-*-*-*-80-*-*-*-*-*-*",
+  ".ransomware.fontC:     -*-helvetica-bold-r-*-*-*-100-*-*-*-*-*-*",
+
 # elif defined(HAVE_COCOA)
 
-  "*font:                 PxPlus IBM VGA8 8,  Courier-Bold 9",
-  "*bigFont:              PxPlus IBM VGA8 32, Courier-Bold 24",
+  "*font:                 PxPlus IBM VGA8 8,  Courier Bold 9",
+  "*bigFont:              PxPlus IBM VGA8 32, Courier Bold 24",
   "*font2:                ",
   "*bigFont2:             ",
 
-  ".mac.font:             Monaco 10, Courier-Bold 9",
-  ".mac.bigFont:          Monaco 18, Courier-Bold 18",
+  ".mac.font:             Monaco 10, Courier Bold 9",
+  ".mac.bigFont:          Monaco 18, Courier Bold 18",
 
-  ".macsbug.font:         Monaco 10, Courier-Bold 9",
-  ".macsbug.bigFont:      Monaco 24, Courier-Bold 24",
+  ".macsbug.font:         Monaco 10, Courier Bold 9",
+  ".macsbug.bigFont:      Monaco 24, Courier Bold 24",
 
-  ".macx.font:            Courier-Bold 9",
-  ".macx.bigFont:         Courier-Bold 14",
-  ".macdisk.font:         Courier-Bold 9",
-  ".macdisk.bigFont:      Courier-Bold 18",
+  ".macx.font:            Courier Bold 9",
+  ".macx.bigFont:         Courier Bold 14",
+  ".macdisk.font:         Courier Bold 9",
+  ".macdisk.bigFont:      Courier Bold 18",
   ".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",
-  ".solaris.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",
+  ".hvx.bigFont:          PxPlus IBM VGA8 16, Courier Bold 14",
+  ".hppalinux.bigFont:    PxPlus IBM VGA8 16, Courier Bold 14",
+  ".solaris.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",
 
   ".win10.font:                   Arial 24, Helvetica 24",
   ".win10.bigFont:        Arial 24, Helvetica 24",
@@ -4961,6 +5694,11 @@ static const char *bsod_defaults [] = {
   ".win10.fontC:          Arial 16, Helvetica 16",
   ".win10.bigFont2:       ",
 
+  ".ransomware.font:         Arial 24, Helvetica 24",
+  ".ransomware.bigFont:      Arial 24, Helvetica 24",
+  ".ransomware.fontB:        Arial 16, Helvetica 16",
+  ".ransomware.fontC:        Arial Bold 24, Helvetica Bold 24",
+
 # else   /* X11 */
 
   "*font:                 9x15bold",
@@ -4999,6 +5737,12 @@ static const char *bsod_defaults [] = {
   ".win10.font2:          ",
   ".win10.bigFont2:       ",
 
+  ".ransomware.font:      -*-helvetica-medium-r-*-*-*-180-*-*-*-*-*-*",
+  ".ransomware.bigFont:           -*-helvetica-medium-r-*-*-*-180-*-*-*-*-*-*",
+  ".ransomware.fontB:     -*-helvetica-medium-r-*-*-*-140-*-*-*-*-*-*",
+  ".ransomware.fontC:     -*-helvetica-bold-r-*-*-*-180-*-*-*-*-*-*",
+
+
 # endif  /* X11 */
 
   0
@@ -5016,6 +5760,8 @@ static const XrmOptionDescRec bsod_options [] = {
   { "-no-2k",          ".doWin2K",             XrmoptionNoArg,  "False" },
   { "-win10",          ".doWin10",             XrmoptionNoArg,  "True"  },
   { "-no-win10",       ".doWin10",             XrmoptionNoArg,  "False" },
+  { "-ransomware",     ".doRansomware",        XrmoptionNoArg,  "True"  },
+  { "-no-ransomware",  ".doRansomware",        XrmoptionNoArg,  "False" },
   { "-amiga",          ".doAmiga",             XrmoptionNoArg,  "True"  },
   { "-no-amiga",       ".doAmiga",             XrmoptionNoArg,  "False" },
   { "-mac",            ".doMac",               XrmoptionNoArg,  "True"  },
index a82eb81dbe11edc1f4ae29463b7ee625bd244ac6..bd8289ffb284b868074b9db595e07f913b819ccd 100644 (file)
@@ -77,6 +77,7 @@ hacks are displayed and which aren't.
 .BR doNT ,
 .BR doWin2K ,
 .BR doWin10 ,
+.BR doRansomware ,
 .BR doAmiga ,
 .BR doMac ,
 .BR doMac1 ,
index a65979d988efc7a332100ee3084b6a8dc56ee43a..7a1e26f5230754488d27f57b27d339ae995a97cb 100755 (executable)
@@ -21,7 +21,7 @@ use diagnostics;
 use strict;
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my ($version) = ('$Revision: 1.24 $' =~ m/\s(\d[.\d]+)\s/s);
+my ($version) = ('$Revision: 1.25 $' =~ m/\s(\d[.\d]+)\s/s);
 
 my $verbose = 0;
 my $debug_p = 0;
@@ -696,7 +696,7 @@ sub build_android(@) {
   my (@savers) = @_;
 
   my $package     = "org.jwz.xscreensaver";
-  my $project_dir = "project/xscreensaver";
+  my $project_dir = "xscreensaver";
   my $xml_dir     = "$project_dir/res/xml";
   my $values_dir  = "$project_dir/res/values";
   my $java_dir    = "$project_dir/src/org/jwz/xscreensaver/gen";
@@ -1055,6 +1055,30 @@ sub build_android(@) {
                 "  </intent-filter>\n" .
                 "</activity>\n");
 
+
+  $manifest .= ("<activity android:name=\"" .
+                "org.jwz.xscreensaver.XScreenSaverTVActivity\"\n" .
+                "  android:theme=\"\@android:style/Theme.Holo\"\n" .
+                "  android:label=\"\@string/app_name\">\n" .
+                "  <intent-filter>\n" .
+                "    <action android:name=\"android.intent.action" .
+                ".MAIN\" />\n" .
+                "    <category android:name=\"android.intent.category" .
+                ".LEANBACK_LAUNCHER\" />\n" .
+                "  </intent-filter>\n" .
+                "  <intent-filter>\n" .
+                "    <action android:name=\"android.intent.action" .
+                ".VIEW\" />\n" .
+                "    <category android:name=\"android.intent.category" .
+                ".DEFAULT\" />\n" .
+                "    <category android:name=\"android.intent.category" .
+                ".BROWSABLE\" />\n" .
+                "  </intent-filter>\n" .
+                "</activity>\n");
+
+
+
+
   # Android wants this to be an int
   my $versb = $vers;
   $versb =~ s/^(\d+)\.(\d+).*$/{ $1 * 10000 + $2 * 100 }/sex;
@@ -1074,12 +1098,20 @@ sub build_android(@) {
                "  <uses-feature android:glEsVersion=\"0x00010001\"\n" .
                "    android:required=\"true\" />\n" .
 
+               "  <uses-feature android:name=\"android.software.leanback\"\n" .
+               "    android:required=\"false\" />\n" .
+
+               "  <uses-feature" .
+               " android:name=\"android.hardware.touchscreen\"\n" .
+               "    android:required=\"false\" />\n" .
+
                "  <uses-permission android:name=\"" .
                    "android.permission.INTERNET\" />\n" .
                "  <uses-permission android:name=\"" .
                    "android.permission.READ_EXTERNAL_STORAGE\" />\n" .
 
                "  <application android:icon=\"\@drawable/thumbnail\"\n" .
+               "    android:banner=\"\@drawable/thumbnail\"\n" .
                "    android:label=\"\@string/app_name\"\n" .
                "    android:name=\".XScreenSaverApp\">\n" .
                $manifest .
index 38d890e5120e878848b38ee2eabf1c30b4933543..9d62870f6d163be6a6107a588f43930ee97019b8 100644 (file)
@@ -829,6 +829,10 @@ compass_init (Display *dpy, Window window)
   XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
   st->size2 = MIN(st->xgwa.width, st->xgwa.height);
 
+  if (st->xgwa.width > st->xgwa.height * 5 ||  /* goofy aspect ratio */
+      st->xgwa.height > st->xgwa.width * 5)
+    st->size2 = MAX(st->xgwa.width, st->xgwa.height);
+
   if (st->size2 > 600) st->size2 = 600;
 
   st->size = (st->size2 / 2) * 0.8;
index a9dd1a14cc596cc8dbd812680441b8d946db2799..67eeb52477f10fc1f8fb1a2c95f9f402e640cb07 100644 (file)
@@ -4,8 +4,8 @@
             a screen saver and locker for the X window system
                             by Jamie Zawinski
 
-                              version 5.37
-                               05-Jul-2017
+                              version 5.38
+                               20-Dec-2017
 
                      https://www.jwz.org/xscreensaver/
 
index 16c52d8639edec001cc5c1a5c720615d846aa5e5..ea3d07cb13aafbd24575e9d427a76840a3987809 100644 (file)
    <boolean id="glados"     _label="GLaDOS"         arg-unset="-no-glados"/>
    <boolean id="android"    _label="Android"        arg-unset="-no-android"/>
    <boolean id="apple2"     _label="Apple ]["       arg-unset="-no-apple2"/>
-   <boolean id="vmware"     _label="VMware"         arg-unset="-no-vmware"/>
+   <boolean id="ransomware" _label="Ransomware"     arg-unset="-no-ransomware"/>
   </vgroup>
   <vgroup>
    <boolean id="nvidia"     _label="NVidia"         arg-unset="-no-nvidia"/>
    <boolean id="os2"        _label="OS/2"           arg-unset="-no-os2"/>
    <boolean id="mac"        _label="Sad Mac"        arg-unset="-no-mac"/>
    <boolean id="mac1"       _label="Mac bomb"       arg-unset="-no-mac1"/>
+   <boolean id="vmware"     _label="VMware"         arg-unset="-no-vmware"/>
   </vgroup>
   <vgroup>
    <boolean id="macsbug"    _label="MacsBug"        arg-unset="-no-macsbug"/>
index 9d37d53e3a51c7e3a9ef58c2c17a1d7127c91ec6..ac10f15ae9be4c9ba694c3ee4f31cb92769d85e4 100644 (file)
@@ -15,7 +15,7 @@
    <option id="glyph"    _label="DNA Lounge logo" arg-set="-mode helix"/>
    <option id="pizza"    _label="DNA Pizza logo"  arg-set="-mode pizza"/>
    <option id="both"     _label="DNA Lounge and DNA Pizza logos"/>
-   <option id="codeword" _label="Codeword logo"   arg-set="-mode codeword"/>
+<!--<option id="codeword" _label="Codeword logo"  arg-set="-mode codeword"/>-->
   </select>
   <hgroup>
    <boolean id="wire"    _label="Wireframe"       arg-set="-wireframe"/>
diff --git a/hacks/config/esper.xml b/hacks/config/esper.xml
new file mode 100644 (file)
index 0000000..5607c04
--- /dev/null
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="esper" _label="Esper" gl="yes">
+
+  <command arg="-root"/>
+
+  <video href="http://www.youtube.com/watch?v=_er7xZd7zUU"/>
+
+  <hgroup>
+   <vgroup>
+   <number id="delay" type="slider" arg="-delay %"
+           _label="Frame rate" _low-label="Low" _high-label="High"
+           low="0" high="100000" default="20000"
+           convert="invert"/>
+
+    <number id="speed" type="slider" arg="-speed %"
+            _label="Speed" _low-label="Slow" _high-label="Fast"
+            low="0.2" high="20" default="1.0"/>
+
+   </vgroup>
+   <vgroup>
+
+    <boolean id="titles" _label="Show file names" arg-unset="-no-titles"/>
+    <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
+
+    <xscreensaver-image />
+
+    <xscreensaver-updater />
+
+   </vgroup>
+  </hgroup>
+
+  <_description>
+"Enhance 224 to 176. Pull out track right. Center in pull back.  Pull
+back. Wait a minute. Go right. Stop. Enhance 57 19. Track 45 left.
+Gimme a hardcopy right there."
+
+The Esper Machine was a voice-controlled forensic device used by LAPD
+in 2019, as documented in the 1982 film, Blade Runner.  It was capable
+of enhancing photographs to an extreme degree, including reconstructing
+different viewpoints within the space from the reflections on various
+objects in the photograph.
+
+Written by Jamie Zawinski; 2017.
+  </_description>
+</screensaver>
index 4eec9aba6b16a18510763ad70affcfa865b1c3bc..dcde3cb138d7a6f2640e3081a2dd015fde634360 100644 (file)
@@ -6,17 +6,16 @@
 
   <video href="https://www.youtube.com/watch?v=KlDw0nYwUe4"/>
 
-  <number id="displaytime" type="slider" arg="-displaytime %"
-          _label="Display time for each program"
-          _low-label="5 seconds" _high-label="2 minutes"
-         low="5" high="120" default="20" />
-
   <file id="file" _label="Assembly file" arg="-file %"/>
 
   <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
 
   <hgroup>
    <vgroup>
+    <number id="displaytime" type="slider" arg="-displaytime %"
+            _label="Display time for each program"
+            _low-label="5 seconds" _high-label="2 minutes"
+            low="5.0" high="120.0" default="30.0" />
     <number id="tvcolor" type="slider" arg="-tv-color %"
             _label="Color Knob" _low-label="Low" _high-label="High"
             low="0" high="1000" default="70"/>
             low="0" high="100" default="5"/>
    </vgroup>
    <vgroup>
+    <number id="ips" type="slider" arg="-ips %"
+            _label="Instructions per second"
+            _low-label="500" _high-label="120000"
+            low="500" high="120000" default="15000" />
     <number id="tvbrightness" type="slider" arg="-tv-brightness %"
             _label="Brightness Knob" _low-label="Low" _high-label="High"
             low="0" high="200" default="150"/>
index 55a8b755e18be359348ccbc3a287b6771211b234..7d82ab019a988d10f6918c474149b5d511c61ebb 100644 (file)
@@ -8,7 +8,7 @@
 
   <number id="speed" type="slider" arg="-speed %"
           _label="Duration" _low-label="Short" _high-label="Long"
-          low="0" high="1000" default="0" />
+          low="1" high="1000" default="1" />
 
   <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
 
index 0f7f255a544a3a88e968f5a6ec0edfdd4e7b1398..9cfcf50a4f032815fa2e6790281ce2c342dc7d19 100644 (file)
@@ -289,6 +289,7 @@ coral_free (Display *dpy, Window window, void *closure)
 }
 
 static const char *coral_defaults[] = {
+  ".lowrez:    true",
   ".background:        black",
   ".foreground:        white",
   "*fpsSolid:  true",
index 2a12a7e2cd84421d0f8f1e7669bf9620464004f1..9f33529c5ebdb52f96c5a621394cdd8ab43da2e6 100644 (file)
@@ -78,6 +78,8 @@ static const char sccsid[] = "@(#)crystal.c   4.12 98/09/10 xlockmore";
                                                 "*ignoreRotation: True \n" \
 
 # define release_crystal 0
+# define reshape_crystal 0
+# define crystal_handle_event 0
 # include "xlockmore.h"                /* in xscreensaver distribution */
 #else /* STANDALONE */
 # include "xlock.h"                    /* in xlockmore distribution */
@@ -146,7 +148,7 @@ ENTRYPOINT ModeSpecOpt crystal_opts =
 #ifdef USE_MODULES
 ModStruct   crystal_description =
 {"crystal", "init_crystal", "draw_crystal", NULL,
- "refresh_crystal", "init_crystal", NULL, &crystal_opts,
+ "refresh_crystal", "init_crystal", "free_crystal", &crystal_opts,
  60000, -40, 200, -15, 64, 1.0, "",
  "Shows polygons in 2D plane groups", 0, NULL};
 
@@ -266,6 +268,8 @@ typedef struct {
        Bool        cycle_p, mono_p, no_colors;
        unsigned long blackpixel, whitepixel, fg, bg;
        int         direction, invert;
+       unsigned long grid_pixel;
+       int         inx, iny;
 } crystalstruct;
 
 static crystalstruct *crystals = NULL;
@@ -564,6 +568,7 @@ ENTRYPOINT void
 draw_crystal(ModeInfo * mi)
 {
        Display    *display = MI_DISPLAY(mi);
+       Window      window = MI_WINDOW(mi);
        crystalstruct *cryst = &crystals[MI_SCREEN(mi)];
        int         i;
 
@@ -575,8 +580,148 @@ draw_crystal(ModeInfo * mi)
                init_crystal(mi);
                return;
        }
-       cryst->painted = True;
-       MI_IS_DRAWN(mi) = True;
+
+       /* Moved from init_crystal because you can't draw after MI_CLEARWINDOW in
+          XScreenSaver. - Dave Odell <dmo2118@gmail.com>
+        */
+       if (cryst->unit_cell
+#ifndef HAVE_JWXYZ
+               && !cryst->painted
+#endif
+               ) {
+          int y_coor1 , y_coor2;
+          
+               XSetForeground(display, cryst->gc, cryst->grid_pixel);
+               if (cryst->grid_cell) {
+                       int         inx, iny;
+
+                  if ( cryst->invert )
+                    y_coor1 = y_coor2 = cryst->win_height - cryst->offset_h;
+                  else
+                    y_coor1 = y_coor2 = cryst->offset_h;
+                       XDrawLine(display, window, cryst->gc, cryst->offset_w,
+                                 y_coor1, cryst->offset_w + cryst->nx * cryst->a,
+                                 y_coor2);
+                  if ( cryst->invert )
+                    {
+                       y_coor1 = cryst->win_height - cryst->offset_h;
+                       y_coor2 = cryst->win_height - (int) (cryst->ny *
+                                                            cryst->b *
+                                        cos((cryst->gamma - 90) * PI_RAD)) -
+                         cryst->offset_h;
+                    }
+                  else
+                    {
+                       y_coor1 = cryst->offset_h;
+                       y_coor2 = (int) (cryst->ny * cryst->b *
+                                        cos((cryst->gamma - 90) * PI_RAD)) +
+                         cryst->offset_h;
+                    }
+                       XDrawLine(display, window, cryst->gc, cryst->offset_w,
+                                 y_coor1, (int) (cryst->offset_w - cryst->ny * cryst->b *
+                                         sin((cryst->gamma - 90) * PI_RAD)),
+                                 y_coor2);
+                       inx = cryst->nx;
+                       for (iny = 1; iny <= cryst->ny; iny++) {
+                  if ( cryst->invert )
+                    {
+                       y_coor1 = cryst->win_height -
+                         (int) (iny * cryst->b * cos((cryst->gamma - 90) *
+                                                 PI_RAD)) - cryst->offset_h;
+                       y_coor2 = cryst->win_height -
+                         (int) (iny * cryst->b * cos((cryst->gamma - 90) *
+                                                     PI_RAD)) -
+                         cryst->offset_h;
+                    }
+                  else
+                    {
+                       y_coor1 = (int) (iny * cryst->b * cos((cryst->gamma - 90) *
+                                                 PI_RAD)) + cryst->offset_h;
+                       y_coor2 = (int) (iny * cryst->b * cos((cryst->gamma - 90) * PI_RAD)) +
+                                         cryst->offset_h;
+                    }
+                               XDrawLine(display, window, cryst->gc,
+                                         (int) (cryst->offset_w +
+                                    inx * cryst->a - (int) (iny * cryst->b *
+                                        sin((cryst->gamma - 90) * PI_RAD))),
+                                         y_coor1,
+                                   (int) (cryst->offset_w - iny * cryst->b *
+                                          sin((cryst->gamma - 90) * PI_RAD)),
+                                         y_coor2);
+                       }
+                       iny = cryst->ny;
+                       for (inx = 1; inx <= cryst->nx; inx++) {
+                          if ( cryst->invert )
+                            {
+                               y_coor1 =cryst->win_height -
+                                 (int) (iny * cryst->b *
+                                               cos((cryst->gamma - 90) *
+                                                   PI_RAD)) - cryst->offset_h;
+                               y_coor2 =cryst->win_height - cryst->offset_h;
+                            }
+                          else
+                            {
+                               y_coor1 =(int) (iny * cryst->b *
+                                               cos((cryst->gamma - 90) *
+                                                   PI_RAD)) + cryst->offset_h;
+                               y_coor2 =cryst->offset_h;
+                            }
+                               XDrawLine(display, window, cryst->gc,
+                                         (int) (cryst->offset_w +
+                                    inx * cryst->a - (int) (iny * cryst->b *
+                                        sin((cryst->gamma - 90) * PI_RAD))),
+                                         y_coor1,
+                                         cryst->offset_w + inx * cryst->a,
+                                         y_coor2);
+                       }
+               } else {
+                  if ( cryst->invert )
+                    {
+                       y_coor1 =cryst->win_height -
+                         (int) (cryst->iny * cryst->b *
+                                                 cos((cryst->gamma - 90) *
+                                                     PI_RAD)) -
+                         cryst->offset_h;
+                       y_coor2 =cryst->win_height -
+                         (int) ( ( cryst->iny + 1 ) * cryst->b *
+                                                 cos((cryst->gamma - 90) *
+                                                     PI_RAD)) -
+                         cryst->offset_h;
+                    }
+                  else
+                    {
+                       y_coor1 =(int) (cryst->iny * cryst->b *
+                                                 cos((cryst->gamma - 90) *
+                                                     PI_RAD)) +
+                         cryst->offset_h;
+                       y_coor2 =(int) (( cryst->iny + 1 ) * cryst->b *
+                                                 cos((cryst->gamma - 90) *
+                                                     PI_RAD)) +
+                         cryst->offset_h;
+                    }
+                       XDrawLine(display, window, cryst->gc,
+                                 cryst->offset_w + cryst->inx * cryst->a - (int) (cryst->iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
+                                 y_coor1,
+                                 cryst->offset_w + (cryst->inx + 1) * cryst->a - (int) (cryst->iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
+                                 y_coor1);
+                       XDrawLine(display, window, cryst->gc,
+                                 cryst->offset_w + cryst->inx * cryst->a - (int) (cryst->iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
+                                 y_coor1,
+                                 cryst->offset_w + cryst->inx * cryst->a - (int) ((cryst->iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
+                                 y_coor2);
+                       XDrawLine(display, window, cryst->gc,
+                                 cryst->offset_w + (cryst->inx + 1) * cryst->a - (int) (cryst->iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
+                                 y_coor1,
+                                 cryst->offset_w + (cryst->inx + 1) * cryst->a - (int) ((cryst->iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
+                                 y_coor2);
+                       XDrawLine(display, window, cryst->gc,
+                                 cryst->offset_w + cryst->inx * cryst->a - (int) ((cryst->iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
+                                 y_coor2,
+                                 cryst->offset_w + (cryst->inx + 1) * cryst->a - (int) ((cryst->iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
+                                 y_coor2);
+               }
+       }
+
        XSetFunction(display, cryst->gc, GXxor);
 
 /* Rotate colours */
@@ -597,7 +742,10 @@ draw_crystal(ModeInfo * mi)
                } else {
                        XSetForeground(display, cryst->gc, atom0->colour);
                }
-               crystal_drawatom(mi, atom0);
+#ifndef HAVE_JWXYZ
+               if(cryst->painted)
+                       crystal_drawatom(mi, atom0);
+#endif
                atom0->velocity[0] += NRAND(3) - 1;
                atom0->velocity[0] = MAX(-20, MIN(20, atom0->velocity[0]));
                atom0->velocity[1] += NRAND(3) - 1;
@@ -620,8 +768,11 @@ draw_crystal(ModeInfo * mi)
                crystal_drawatom(mi, atom0);
        }
        XSetFunction(display, cryst->gc, GXcopy);
+       cryst->painted = True;
+       MI_IS_DRAWN(mi) = True;
 }
 
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_crystal(ModeInfo * mi)
 {
@@ -788,8 +939,9 @@ refresh_crystal(ModeInfo * mi)
        }
        XSetFunction(display, cryst->gc, GXcopy);
 }
+#endif
 
-static void
+ENTRYPOINT void
 free_crystal(ModeInfo * mi)
 {
        Display    *display = MI_DISPLAY(mi);
@@ -821,7 +973,6 @@ ENTRYPOINT void
 init_crystal(ModeInfo * mi)
 {
        Display    *display = MI_DISPLAY(mi);
-       Window      window = MI_WINDOW(mi);
        crystalstruct *cryst;
        int         i, max_atoms, size_atom, neqv;
        int         cell_min;
@@ -829,7 +980,7 @@ init_crystal(ModeInfo * mi)
 #define MIN_CELL 200
 
 /* initialize */
-       MI_INIT (mi, crystals, free_crystal);
+       MI_INIT (mi, crystals);
        cryst = &crystals[MI_SCREEN(mi)];
 
        if (!cryst->gc) {
@@ -1020,146 +1171,6 @@ init_crystal(ModeInfo * mi)
        }
        cryst->a = cryst->a / cryst->nx;
        cryst->b = cryst->b / cryst->ny;
-       if (cryst->unit_cell) {
-          int y_coor1 , y_coor2;
-          
-               if (MI_NPIXELS(mi) > 2)
-                       XSetForeground(display, cryst->gc, MI_PIXEL(mi, NRAND(MI_NPIXELS(mi))));
-               else
-                       XSetForeground(display, cryst->gc, MI_WHITE_PIXEL(mi));
-               if (cryst->grid_cell) {
-                       int         inx, iny;
-
-                  if ( cryst->invert )
-                    y_coor1 = y_coor2 = cryst->win_height - cryst->offset_h;
-                  else
-                    y_coor1 = y_coor2 = cryst->offset_h;
-                       XDrawLine(display, window, cryst->gc, cryst->offset_w,
-                                 y_coor1, cryst->offset_w + cryst->nx * cryst->a,
-                                 y_coor2);
-                  if ( cryst->invert )
-                    {
-                       y_coor1 = cryst->win_height - cryst->offset_h;
-                       y_coor2 = cryst->win_height - (int) (cryst->ny *
-                                                            cryst->b *
-                                        cos((cryst->gamma - 90) * PI_RAD)) -
-                         cryst->offset_h;
-                    }
-                  else
-                    {
-                       y_coor1 = cryst->offset_h;
-                       y_coor2 = (int) (cryst->ny * cryst->b *
-                                        cos((cryst->gamma - 90) * PI_RAD)) +
-                         cryst->offset_h;
-                    }
-                       XDrawLine(display, window, cryst->gc, cryst->offset_w,
-                                 y_coor1, (int) (cryst->offset_w - cryst->ny * cryst->b *
-                                         sin((cryst->gamma - 90) * PI_RAD)),
-                                 y_coor2);
-                       inx = cryst->nx;
-                       for (iny = 1; iny <= cryst->ny; iny++) {
-                  if ( cryst->invert )
-                    {
-                       y_coor1 = cryst->win_height -
-                         (int) (iny * cryst->b * cos((cryst->gamma - 90) *
-                                                 PI_RAD)) - cryst->offset_h;
-                       y_coor2 = cryst->win_height -
-                         (int) (iny * cryst->b * cos((cryst->gamma - 90) *
-                                                     PI_RAD)) -
-                         cryst->offset_h;
-                    }
-                  else
-                    {
-                       y_coor1 = (int) (iny * cryst->b * cos((cryst->gamma - 90) *
-                                                 PI_RAD)) + cryst->offset_h;
-                       y_coor2 = (int) (iny * cryst->b * cos((cryst->gamma - 90) * PI_RAD)) +
-                                         cryst->offset_h;
-                    }
-                               XDrawLine(display, window, cryst->gc,
-                                         (int) (cryst->offset_w +
-                                    inx * cryst->a - (int) (iny * cryst->b *
-                                        sin((cryst->gamma - 90) * PI_RAD))),
-                                         y_coor1,
-                                   (int) (cryst->offset_w - iny * cryst->b *
-                                          sin((cryst->gamma - 90) * PI_RAD)),
-                                         y_coor2);
-                       }
-                       iny = cryst->ny;
-                       for (inx = 1; inx <= cryst->nx; inx++) {
-                          if ( cryst->invert )
-                            {
-                               y_coor1 =cryst->win_height -
-                                 (int) (iny * cryst->b *
-                                               cos((cryst->gamma - 90) *
-                                                   PI_RAD)) - cryst->offset_h;
-                               y_coor2 =cryst->win_height - cryst->offset_h;
-                            }
-                          else
-                            {
-                               y_coor1 =(int) (iny * cryst->b *
-                                               cos((cryst->gamma - 90) *
-                                                   PI_RAD)) + cryst->offset_h;
-                               y_coor2 =cryst->offset_h;
-                            }
-                               XDrawLine(display, window, cryst->gc,
-                                         (int) (cryst->offset_w +
-                                    inx * cryst->a - (int) (iny * cryst->b *
-                                        sin((cryst->gamma - 90) * PI_RAD))),
-                                         y_coor1,
-                                         cryst->offset_w + inx * cryst->a,
-                                         y_coor2);
-                       }
-               } else {
-                       int         inx, iny;
-
-                       inx = NRAND(cryst->nx);
-                       iny = NRAND(cryst->ny);
-                  if ( cryst->invert )
-                    {
-                       y_coor1 =cryst->win_height -
-                         (int) (iny * cryst->b *
-                                                 cos((cryst->gamma - 90) *
-                                                     PI_RAD)) -
-                         cryst->offset_h;
-                       y_coor2 =cryst->win_height -
-                         (int) ( ( iny + 1 ) * cryst->b *
-                                                 cos((cryst->gamma - 90) *
-                                                     PI_RAD)) -
-                         cryst->offset_h;
-                    }
-                  else
-                    {
-                       y_coor1 =(int) (iny * cryst->b *
-                                                 cos((cryst->gamma - 90) *
-                                                     PI_RAD)) +
-                         cryst->offset_h;
-                       y_coor2 =(int) (( iny + 1 ) * cryst->b *
-                                                 cos((cryst->gamma - 90) *
-                                                     PI_RAD)) +
-                         cryst->offset_h;
-                    }
-                       XDrawLine(display, window, cryst->gc,
-                                 cryst->offset_w + inx * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
-                                 y_coor1,
-                                 cryst->offset_w + (inx + 1) * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
-                                 y_coor1);
-                       XDrawLine(display, window, cryst->gc,
-                                 cryst->offset_w + inx * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
-                                 y_coor1,
-                                 cryst->offset_w + inx * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
-                                 y_coor2);
-                       XDrawLine(display, window, cryst->gc,
-                                 cryst->offset_w + (inx + 1) * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
-                                 y_coor1,
-                                 cryst->offset_w + (inx + 1) * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
-                                 y_coor2);
-                       XDrawLine(display, window, cryst->gc,
-                                 cryst->offset_w + inx * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
-                                 y_coor2,
-                                 cryst->offset_w + (inx + 1) * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
-                                 y_coor2);
-               }
-       }
        if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
 /* Set up colour map */
                if (cryst->colors && cryst->ncolors && !cryst->no_colors)
@@ -1232,13 +1243,11 @@ init_crystal(ModeInfo * mi)
                                atom0->colour = NRAND(cryst->ncolors - 2) + 2;
                        else
                                atom0->colour = 1;      /* Just in case */
-                       XSetForeground(display, cryst->gc, cryst->colors[atom0->colour].pixel);
                } else {
                        if (MI_NPIXELS(mi) > 2)
                                atom0->colour = MI_PIXEL(mi, NRAND(MI_NPIXELS(mi)));
                        else
                                atom0->colour = 1;      /*Xor'red so WHITE may not be appropriate */
-                       XSetForeground(display, cryst->gc, atom0->colour);
                }
                atom0->x0 = NRAND(cryst->a);
                atom0->y0 = NRAND(cryst->b);
@@ -1259,26 +1268,17 @@ init_crystal(ModeInfo * mi)
                else
                        atom0->num_point = 4;
                crystal_setupatom(atom0, cryst->gamma);
-               crystal_drawatom(mi, atom0);
        }
        XSetFunction(display, cryst->gc, GXcopy);
-}
 
-ENTRYPOINT void
-reshape_crystal(ModeInfo * mi, int width, int height)
-{
-  init_crystal(mi);
-}
+       if (MI_NPIXELS(mi) > 2)
+               cryst->grid_pixel = MI_PIXEL(mi, NRAND(MI_NPIXELS(mi)));
+       else
+               cryst->grid_pixel = MI_WHITE_PIXEL(mi);
+
+       cryst->inx = NRAND(cryst->nx);
+       cryst->iny = NRAND(cryst->ny);
 
-ENTRYPOINT Bool
-crystal_handle_event (ModeInfo *mi, XEvent *event)
-{
-  if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
-    {
-      reshape_crystal (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
-      return True;
-    }
-  return False;
 }
 
 XSCREENSAVER_MODULE ("Crystal", crystal)
index eb926ca6b150c7403dca4d30932e367ea28a01aa..0fff863146b55228f223e6c65528cfc3c2c7cd8a 100644 (file)
@@ -62,6 +62,8 @@ static const char sccsid[] = "@(#)demon.c     5.00 2000/11/01 xlockmore";
 
 # define UNIFORM_COLORS
 # define release_demon 0
+# define reshape_demon 0
+# define demon_handle_event 0
 # include "xlockmore.h"                /* in xscreensaver distribution */
 #else /* STANDALONE */
 # include "xlock.h"            /* in xlockmore distribution */
@@ -97,7 +99,7 @@ ENTRYPOINT ModeSpecOpt demon_opts =
 #ifdef USE_MODULES
 ModStruct   demon_description =
 {"demon", "init_demon", "draw_demon", (char *) NULL,
- "refresh_demon", "init_demon", (char *) NULL, &demon_opts,
+ "refresh_demon", "init_demon", "free_demon", &demon_opts,
  50000, 0, 1000, -7, 64, 1.0, "",
  "Shows Griffeath's cellular automata", 0, NULL};
 
@@ -110,7 +112,7 @@ ModStruct   demon_description =
 
 #define REDRAWSTEP 2000                /* How many cells to draw per cycle */
 #define MINSTATES 2
-#define MINGRIDSIZE 24
+#define MINGRIDSIZE 5
 #define MINSIZE 4
 #define NEIGHBORKINDS 6
 
@@ -277,7 +279,7 @@ free_struct(demonstruct * dp)
        }
 }
 
-static void
+ENTRYPOINT void
 free_demon(ModeInfo * mi)
 {
        Display    *display = MI_DISPLAY(mi);
@@ -415,9 +417,12 @@ init_demon (ModeInfo * mi)
        int         size = MI_SIZE(mi), nk;
        demonstruct *dp;
 
-       MI_INIT (mi, demons, free_demon);
+       MI_INIT (mi, demons);
        dp = &demons[MI_SCREEN(mi)];
 
+    if (MI_WIDTH(mi) < 100 || MI_HEIGHT(mi) < 100)  /* tiny window */
+      size = MIN(MI_WIDTH(mi), MI_HEIGHT(mi));
+
        dp->generation = 0;
        dp->redrawing = 0;
 #ifdef DO_STIPPLE
@@ -927,15 +932,7 @@ draw_demon (ModeInfo * mi)
        }
 }
 
-
-ENTRYPOINT void
-reshape_demon(ModeInfo * mi, int width, int height)
-{
-  XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi));
-  init_demon (mi);
-}
-
-
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_demon (ModeInfo * mi)
 {
@@ -948,19 +945,7 @@ refresh_demon (ModeInfo * mi)
        dp->redrawing = 1;
        dp->redrawpos = 0;
 }
-
-ENTRYPOINT Bool
-demon_handle_event (ModeInfo *mi, XEvent *event)
-{
-  if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
-    {
-      reshape_demon (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
-      return True;
-    }
-  return False;
-}
-
-
+#endif
 
 XSCREENSAVER_MODULE ("Demon", demon)
 
index ecf4ce5c959f5a8816141410d7d6e3f3f52ac78c..bfb4459a233324d31a0b45d8cb2c332d3498c7e0 100644 (file)
@@ -39,11 +39,12 @@ static const char sccsid[] = "@(#)discrete.c        5.00 2000/11/01 xlockmore";
                                        "*ncolors: 100 \n" \
                                        "*fpsSolid: true \n" \
                                    "*ignoreRotation: True \n" \
+                                   "*lowrez: True \n" \
 
 # define SMOOTH_COLORS
 # define release_discrete 0
+# define discrete_handle_event 0
 # include "xlockmore.h"                /* in xscreensaver distribution */
-# include "erase.h"
 #else /* STANDALONE */
 # include "xlock.h"            /* in xlockmore distribution */
 #endif /* STANDALONE */
@@ -56,7 +57,7 @@ ENTRYPOINT ModeSpecOpt discrete_opts =
 #ifdef USE_MODULES
 ModStruct   discrete_description =
 {"discrete", "init_discrete", "draw_discrete", (char *) NULL,
- "refresh_discrete", "init_discrete", (char *) NULL, &discrete_opts,
+ "refresh_discrete", "init_discrete", "free_discrete", &discrete_opts,
  1000, 4096, 2500, 1, 64, 1.0, "",
  "Shows various discrete maps", 0, NULL};
 
@@ -102,23 +103,17 @@ typedef struct {
 
     int sqrt_sign, std_sign;
 
-#ifdef STANDALONE
-  eraser_state *eraser;
-#endif
-
 } discretestruct;
 
 static discretestruct *discretes = (discretestruct *) NULL;
 
-static void free_discrete(ModeInfo * mi);
-
 ENTRYPOINT void
 init_discrete (ModeInfo * mi)
 {
        double      range;
        discretestruct *hp;
 
-       MI_INIT (mi, discretes, free_discrete);
+       MI_INIT (mi, discretes);
        hp = &discretes[MI_SCREEN(mi)];
 
        hp->maxx = MI_WIDTH(mi);
@@ -247,10 +242,8 @@ init_discrete (ModeInfo * mi)
                /* if fails will check later */
        }
 
-#ifndef STANDALONE
        /* Clear the background. */
        MI_CLEARWINDOW(mi);
-#endif
 
        XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_WHITE_PIXEL(mi));
        hp->count = 0;
@@ -403,20 +396,13 @@ draw_discrete (ModeInfo * mi)
   int cycles = MI_CYCLES(mi);
   int i;
 
-  if (hp->eraser) {
-    hp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), hp->eraser);
-    if (!hp->eraser)
-      init_discrete(mi);
-    return;
-  }
-
   for (i = 0; i < 10; i++) {
     draw_discrete_1 (mi);
     hp->count++;
   }
 
   if (hp->count > cycles) {
-    hp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), hp->eraser);
+    init_discrete(mi);
   }
 }
 
@@ -430,7 +416,7 @@ reshape_discrete(ModeInfo * mi, int width, int height)
   XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi));
 }
 
-static void
+ENTRYPOINT void
 free_discrete(ModeInfo * mi)
 {
        discretestruct *hp = &discretes[MI_SCREEN(mi)];
@@ -441,25 +427,13 @@ free_discrete(ModeInfo * mi)
        }
 }
 
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_discrete(ModeInfo * mi)
 {
        MI_CLEARWINDOW(mi);
 }
-
-ENTRYPOINT Bool
-discrete_handle_event (ModeInfo *mi, XEvent *event)
-{
-  discretestruct *hp = &discretes[MI_SCREEN(mi)];
-  if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
-    {
-      hp->count = MI_CYCLES(mi);
-      return True;
-    }
-  return False;
-}
-
-
+#endif
 
 XSCREENSAVER_MODULE ("Discrete", discrete)
 
index e24a40ee04e8a69e859491c52664b9aadce96adb..e88986b234fd6c2c8022130f630bb8214b5ca1de 100644 (file)
@@ -40,8 +40,9 @@ static const char sccsid[] = "@(#)drift.c     5.00 2000/11/01 xlockmore";
 
 # define SMOOTH_COLORS
 # define release_drift 0
+# define reshape_drift 0
+# define drift_handle_event 0
 # include "xlockmore.h"                /* in xscreensaver distribution */
-# include "erase.h"
 #else /* STANDALONE */
 # define ENTRYPOINT /**/
 # include "xlock.h"            /* in xlockmore distribution */
@@ -83,7 +84,7 @@ ENTRYPOINT ModeSpecOpt drift_opts =
 #ifdef USE_MODULES
 ModStruct   drift_description =
 {"drift", "init_drift", "draw_drift", (char *) NULL,
- "refresh_drift", "init_drift", (char *) NULL, &drift_opts,
+ "refresh_drift", "init_drift", "free_drift", &drift_opts,
  10000, 30, 1, 1, 64, 1.0, "",
  "Shows cosmic drifting flame fractals", 0, NULL};
 
@@ -134,10 +135,7 @@ typedef struct {
        long        saved_random_bits;
        int         nbits;
 
-#ifdef STANDALONE
   int erase_countdown;
-  eraser_state *eraser;
-#endif
 } driftstruct;
 
 static driftstruct *drifts = (driftstruct *) NULL;
@@ -242,9 +240,7 @@ initmode(ModeInfo * mi, int mode)
        }
        dp->fractal_len = (dp->fractal_len * MI_COUNT(mi)) / 20;
 
-#ifndef STANDALONE
        MI_CLEARWINDOW(mi);
-#endif
 }
 
 static void
@@ -269,7 +265,7 @@ pick_df_coefs(ModeInfo * mi)
        }
 }
 
-static void
+ENTRYPOINT void
 free_drift(ModeInfo * mi)
 {
        driftstruct *dp = &drifts[MI_SCREEN(mi)];
@@ -350,7 +346,7 @@ init_drift(ModeInfo * mi)
 {
        driftstruct *dp;
 
-       MI_INIT (mi, drifts, free_drift);
+       MI_INIT (mi, drifts);
        dp = &drifts[MI_SCREEN(mi)];
 
        dp->width = MI_WIDTH(mi);
@@ -621,14 +617,11 @@ draw_drift(ModeInfo * mi)
 
     if (dp->erase_countdown) {
       if (!--dp->erase_countdown) {
-        dp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), dp->eraser);
+        initmode(mi, frandom(dp, 2));
+        initfractal(mi);
       }
       return;
     }
-    if (dp->eraser) {
-      dp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), dp->eraser);
-      return;
-    }
 
        MI_IS_DRAWN(mi) = True;
        dp->timer = 3000;
@@ -638,10 +631,8 @@ draw_drift(ModeInfo * mi)
                if (dp->total_points++ > dp->fractal_len) {
                        draw_flush(mi, dp, window);
                        if (0 == --dp->nfractals) {
-#ifdef STANDALONE
               dp->erase_countdown = 4 * 1000000 / MI_PAUSE(mi);
-#endif /* STANDALONE */
-                               initmode(mi, frandom(dp, 2));
+                               return;
                        }
                        initfractal(mi);
                }
@@ -668,30 +659,13 @@ draw_drift(ModeInfo * mi)
        }
 }
 
-ENTRYPOINT void
-reshape_drift(ModeInfo * mi, int width, int height)
-{
-  MI_CLEARWINDOW(mi);
-  init_drift (mi);
-}
-
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_drift(ModeInfo * mi)
 {
        MI_CLEARWINDOW(mi);
 }
-
-ENTRYPOINT Bool
-drift_handle_event (ModeInfo *mi, XEvent *event)
-{
-  if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
-    {
-      reshape_drift (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
-      return True;
-    }
-  return False;
-}
-
+#endif
 
 XSCREENSAVER_MODULE ("Drift", drift)
 
index 91a47a28ee93489cca060e3f2dce3795595cf5e3..89fab0b26f073c645adef703aeb55cad75e9b553 100644 (file)
@@ -618,6 +618,17 @@ static void rescale_circles(struct state *st, Body *pb,
     {
       printf("enlarge by x%.2f skipped...\n", scale);
     }
+
+  if (st->width > st->height * 5 ||  /* window has weird aspect */
+      st->height > st->width * 5)
+    {
+      Circle *p;
+      double r = (st->width > st->height
+                  ? st->width / (double) st->height
+                  : st->height / (double) st->width);
+      for (p=pb->epicycles; p; p=p->pchild)
+        p->radius *= r;
+    }
 }
 
 
index f804e427834a19b48499a00cfb1f6b66de8863b4..d42a2bbfd16becf622d396a516afeb73dae43c05 100644 (file)
@@ -51,6 +51,8 @@ static const char sccsid[] = "@(#)euler2d.c   5.00 2000/11/01 xlockmore";
 
 # define SMOOTH_COLORS
 # define release_euler2d 0
+# define reshape_euler2d 0
+# define euler2d_handle_event 0
 # include "xlockmore.h"                /* in xscreensaver distribution */
 #else /* STANDALONE */
 # include "xlock.h"            /* in xlockmore distribution */
@@ -91,7 +93,7 @@ ENTRYPOINT ModeSpecOpt euler2d_opts =
 #ifdef USE_MODULES
 ModStruct   euler2d_description = {
        "euler2d", "init_euler2d", "draw_euler2d", (char *) NULL,
-       "refresh_euler2d", "init_euler2d", (char *) NULL, &euler2d_opts,
+       "refresh_euler2d", "init_euler2d", "free_euler2d", &euler2d_opts,
        1000, 1024, 3000, 1, 64, 1.0, "",
        "Simulates 2D incompressible invisid fluid.", 0, NULL
 };
@@ -113,6 +115,7 @@ typedef struct {
        int        height;
        int        count;
        double     xshift,yshift,scale;
+       double     xshift2,yshift2;
        double     radius;
 
         int        N;
@@ -483,7 +486,7 @@ ode_solve(euler2dstruct *sp)
 #define allocate(p,t,s) if ((p=(t*)malloc(sizeof(t)*s))==NULL)\
 {free_euler2d(mi);return;}
 
-static void
+ENTRYPOINT void
 free_euler2d(ModeInfo * mi)
 {
        euler2dstruct *sp = &euler2ds[MI_SCREEN(mi)];
@@ -522,7 +525,7 @@ init_euler2d (ModeInfo * mi)
        delta_t = 0.001;
         if (power>1.0) delta_t *= pow(0.1,power-1);
 
-       MI_INIT (mi, euler2ds, free_euler2d);
+       MI_INIT (mi, euler2ds);
        sp = &euler2ds[MI_SCREEN(mi)];
 
 #ifdef HAVE_JWXYZ
@@ -534,9 +537,26 @@ init_euler2d (ModeInfo * mi)
 
        sp->count = 0;
 
+    sp->xshift2 = sp->yshift2 = 0;
+
        sp->width = MI_WIDTH(mi);
        sp->height = MI_HEIGHT(mi);
 
+    if (sp->width > sp->height * 5 ||  /* window has weird aspect */
+        sp->height > sp->width * 5)
+    {
+      if (sp->width > sp->height)
+        {
+          sp->height = sp->width * 0.8;
+          sp->yshift2 = -sp->height/2;
+        }
+      else
+        {
+          sp->width = sp->height * 0.8;
+          sp->xshift2 = -sp->width/2;
+        }
+    }
+
        sp->N = MI_COUNT(mi)+number_of_vortex_points;
        sp->Nvortex = number_of_vortex_points;
 
@@ -675,6 +695,8 @@ init_euler2d (ModeInfo * mi)
                else
                        sp->yshift = (low[besti-nr_rotates/2]+high[besti-nr_rotates/2])/2.0*sp->scale+sp->height/2;
 
+        sp->xshift += sp->xshift2;
+        sp->yshift += sp->yshift2;
 
 /* Initialize boundary */
 
@@ -852,31 +874,13 @@ draw_euler2d (ModeInfo * mi)
 
 }
 
-ENTRYPOINT void
-reshape_euler2d(ModeInfo * mi, int width, int height)
-{
-  XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi));
-  init_euler2d (mi);
-}
-
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_euler2d (ModeInfo * mi)
 {
        MI_CLEARWINDOW(mi);
 }
-
-ENTRYPOINT Bool
-euler2d_handle_event (ModeInfo *mi, XEvent *event)
-{
-  if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
-    {
-      init_euler2d (mi);
-      return True;
-    }
-  return False;
-}
-
-
+#endif
 
 XSCREENSAVER_MODULE ("Euler2D", euler2d)
 
index 093941efd55faf61b10309eb0254757ddbae1287..93f471969e409135bd5cb6788e6f544b748ac62b 100644 (file)
@@ -54,7 +54,7 @@ ENTRYPOINT ModeSpecOpt fadeplot_opts =
 #ifdef USE_MODULES
 ModStruct   fadeplot_description =
 {"fadeplot", "init_fadeplot", "draw_fadeplot", (char *) NULL,
- "refresh_fadeplot", "init_fadeplot", (char *) NULL, &fadeplot_opts,
+ "refresh_fadeplot", "init_fadeplot", "free_fadeplot", &fadeplot_opts,
  30000, 10, 1500, 1, 64, 0.6, "",
  "Shows a fading plot of sine squared", 0, NULL};
 
@@ -75,7 +75,7 @@ typedef struct {
 
 static fadeplotstruct *fadeplots = (fadeplotstruct *) NULL;
 
-static void
+ENTRYPOINT void
 free_fadeplot(ModeInfo * mi)
 {
        fadeplotstruct *fp = &fadeplots[MI_SCREEN(mi)];
@@ -113,7 +113,7 @@ init_fadeplot (ModeInfo * mi)
 {
        fadeplotstruct *fp;
 
-       MI_INIT (mi, fadeplots, free_fadeplot);
+       MI_INIT (mi, fadeplots);
        fp = &fadeplots[MI_SCREEN(mi)];
 
        fp->width = MI_WIDTH(mi);
@@ -221,10 +221,12 @@ reshape_fadeplot(ModeInfo * mi, int width, int height)
        fp->factor.y = MAX(fp->height / (2 * fp->min), 1);
 }
 
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_fadeplot (ModeInfo * mi)
 {
 }
+#endif
 
 XSCREENSAVER_MODULE ("FadePlot", fadeplot)
 
index e6cd3d8f2c97764be6e171e5948b18e4394508d0..580851acba808f6b108fa108d8e5a7d811f74321 100644 (file)
@@ -39,6 +39,7 @@ static const char sccsid[] = "@(#)fiberlamp.c 5.00 2000/11/01 xlockmore";
 
 # define UNIFORM_COLORS
 # define release_fiberlamp 0
+# define reshape_fiberlamp 0
 # define fiberlamp_handle_event 0
 # include "xlockmore.h"                /* in xscreensaver distribution */
 #else /* STANDALONE */
@@ -53,7 +54,7 @@ ENTRYPOINT ModeSpecOpt fiberlamp_opts =
 #ifdef USE_MODULES
 ModStruct   fiberlamp_description =
 {"fiberlamp", "init_fiberlamp", "draw_fiberlamp", (char *) NULL,
- "draw_fiberlamp", "change_fiberlamp", (char *) NULL, &fiberlamp_opts,
+ "draw_fiberlamp", "change_fiberlamp", "free_fiberlamp", &fiberlamp_opts,
  1000, 500, 10000, 0, 64, 1.0, "", "Shows a Fiber Optic Lamp", 0, NULL};
 
 #endif
@@ -142,7 +143,7 @@ free_fiber(fiberlampstruct *fl)
        }
 }
 
-static void
+ENTRYPOINT void
 free_fiberlamp(ModeInfo *mi)
 {
     fiberlampstruct *fl = &fiberlamps[MI_SCREEN(mi)];
@@ -158,7 +159,7 @@ init_fiberlamp(ModeInfo * mi)
 {
   fiberlampstruct *fl;
 
-  MI_INIT (mi, fiberlamps, free_fiberlamp);
+  MI_INIT (mi, fiberlamps);
   fl = &fiberlamps[MI_SCREEN(mi)];
 
   /* Create or Resize double buffer */
@@ -273,13 +274,6 @@ init_fiberlamp(ModeInfo * mi)
   change_fiberlamp(mi);
 }
 
-/* Used by xscreensaver.  xlock just uses init_fiberlamp */
-ENTRYPOINT void
-reshape_fiberlamp(ModeInfo * mi, int width, int height)
-{
-  init_fiberlamp(mi);
-}
-
 /* sort fibers so they get drawn back-to-front, one bubble pass is
    enough as the order only changes slowly */
 static void
@@ -302,15 +296,36 @@ draw_fiberlamp (ModeInfo * mi)
   fiberlampstruct *fl;
   int f, i;
   int x, y;
+  int ww, hh;
   Window unused;
+  short cx, cy;
 
-  short cx = MI_WIDTH(mi)/2;
+  ww = MI_WIDTH(mi);
+  hh = MI_HEIGHT(mi);
+
+  cx = MI_WIDTH(mi)/2;
 #if defined PLAN || defined CHECKCOLORWHEEL
-  short cy = MI_HEIGHT(mi)/2;
+  cy = MI_HEIGHT(mi)/2;
 #else
-  short cy = MI_HEIGHT(mi);
+  cy = MI_HEIGHT(mi);
 #endif
 
+  if (ww > hh * 5 ||  /* window has weird aspect */
+      hh > ww * 5)
+    {
+      if (ww > hh)
+        {
+          hh = ww;
+          cy = hh / 4;
+        }
+      else
+        {
+          ww = hh;
+          cx = 0;
+          cy = hh*3/4;
+        }
+    }
+
   if (fiberlamps == NULL)
        return;
   fl = &fiberlamps[MI_SCREEN(mi)];
@@ -380,11 +395,11 @@ draw_fiberlamp (ModeInfo * mi)
                n->z = p->z + LEN(i-1) * se * sp;
          }
 
-         fs->draw[i-1].x = cx + MI_WIDTH(mi)/2*n->x;
+         fs->draw[i-1].x = cx + ww/2*n->x;
 #if defined PLAN || defined CHECKCOLORWHEEL /* Plan */
-         fs->draw[i-1].y = cy + MI_WIDTH(mi)/2*n->z;
+         fs->draw[i-1].y = cy + ww/2*n->z;
 #else /* Elevation */
-         fs->draw[i-1].y = cy + MI_WIDTH(mi)/2*n->y;
+         fs->draw[i-1].y = cy + ww/2*n->y;
 #endif
        }
        MI_IS_DRAWN(mi) = True;
@@ -446,11 +461,13 @@ draw_fiberlamp (ModeInfo * mi)
   }
 }
 
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_fiberlamp(ModeInfo * mi)
 {
        MI_CLEARWINDOW(mi);
 }
+#endif
 
 XSCREENSAVER_MODULE ("Fiberlamp", fiberlamp)
 
index 72c1bbb99312a767ca458e06dd232dda8592564b..874f5d8261e5a8c5800d282ca5f8e587a12e1e37 100644 (file)
@@ -47,9 +47,11 @@ static const char sccsid[] = "@(#)flag.c     4.02 97/04/01 xlockmore";
                                        "*font:         " DEF_FONT      "\n"    \
                                        "*text:                                 \n" \
                                        "*fpsSolid:             true    \n" \
+                                   "*lowrez:       true    \n" \
 
 # define BRIGHT_COLORS
 # define UNIFORM_COLORS
+# define release_flag 0
 # define reshape_flag 0
 # define flag_handle_event 0
 # include "xlockmore.h"                                /* from the xscreensaver distribution */
@@ -432,7 +434,7 @@ init_flag(ModeInfo * mi)
        int         size = MI_SIZE(mi);
        flagstruct *fp;
 
-       MI_INIT (mi, flags, 0);
+       MI_INIT (mi, flags);
        fp = &flags[MI_SCREEN(mi)];
 
        make_flag_bits(mi);
@@ -496,9 +498,6 @@ init_flag(ModeInfo * mi)
        XClearWindow(display, MI_WINDOW(mi));
 }
 
-ENTRYPOINT void release_flag(ModeInfo * mi);
-
-
 ENTRYPOINT void
 draw_flag(ModeInfo * mi)
 {
@@ -531,34 +530,29 @@ draw_flag(ModeInfo * mi)
        fp->sidx %= (ANGLES * MI_NPIXELS(mi));
        fp->timer++;
        if ((MI_CYCLES(mi) > 0) && (fp->timer >= MI_CYCLES(mi)))
-      {
-        release_flag(mi);
                init_flag(mi);
-      }
 }
 
 ENTRYPOINT void
-release_flag(ModeInfo * mi)
+free_flag(ModeInfo * mi)
 {
-       if (flags != NULL) {
-               int         screen;
-
-               for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
-                 {
-                       if (flags[screen].cache && flags[screen].dbufp)
-                               XFreePixmap(MI_DISPLAY(mi), flags[screen].cache);
-                       if (flags[screen].image)
-                         XDestroyImage(flags[screen].image);
-                 }
-               (void) free((void *) flags);
-               flags = NULL;
-       }
+       int         screen = MI_SCREEN(mi);
+
+       if (flags == NULL)
+               return;
+
+       if (flags[screen].cache && flags[screen].dbufp)
+               XFreePixmap(MI_DISPLAY(mi), flags[screen].cache);
+       if (flags[screen].image)
+         XDestroyImage(flags[screen].image);
 }
 
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_flag(ModeInfo * mi)
 {
        /* Do nothing, it will refresh by itself */
 }
+#endif
 
 XSCREENSAVER_MODULE ("Flag", flag)
index df9aadc366efc82d5866e3e75c18a3d0b2e849fc..6dddd8e0a99434eae64279f7f3e805c6592567ff 100644 (file)
@@ -103,6 +103,8 @@ static const char sccsid[] = "@(#)flow.c    5.00 2000/11/01 xlockmore";
                                        "*ncolors:     200   \n"
 
 # define release_flow 0
+# define reshape_flow 0
+# define flow_handle_event 0
 # include "xlockmore.h"                /* in xscreensaver distribution */
 #else /* STANDALONE */
 # include "xlock.h"            /* in xlockmore distribution */
@@ -163,8 +165,8 @@ ENTRYPOINT ModeSpecOpt flow_opts =
 
 #ifdef USE_MODULES
 ModStruct   flow_description = {
-       "flow", "init_flow", "draw_flow", "release_flow",
-       "refresh_flow", "init_flow", NULL, &flow_opts,
+       "flow", "init_flow", "draw_flow", NULL,
+       "refresh_flow", "init_flow", "free_flow", &flow_opts,
        1000, 1024, 10000, -10, 200, 1.0, "",
        "Shows dynamic strange attractors", 0, NULL
 };
@@ -388,7 +390,7 @@ Iterate(dvector *p, dvector(*ODE)(Par par, double x, double y, double z),
 #define allocate(p,t,s) if ((p=(t*)malloc(sizeof(t)*s))==NULL)\
 {free_flow(mi);return;}
 
-static void
+ENTRYPOINT void
 free_flow(ModeInfo * mi)
 {
        flowstruct *sp = &flows[MI_SCREEN(mi)];
@@ -626,7 +628,7 @@ init_flow (ModeInfo * mi)
        flowstruct *sp;
        char       *name;
        
-       MI_INIT (mi, flows, free_flow);
+       MI_INIT (mi, flows);
        sp = &flows[MI_SCREEN(mi)];
 
        sp->count2 = 0;
@@ -1196,30 +1198,13 @@ draw_flow (ModeInfo * mi)
        }
 }
 
-ENTRYPOINT void
-reshape_flow(ModeInfo * mi, int width, int height)
-{
-  init_flow (mi);
-}
-
-
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_flow (ModeInfo * mi)
 {
        if(!dbufp) MI_CLEARWINDOW(mi);
 }
-
-ENTRYPOINT Bool
-flow_handle_event (ModeInfo *mi, XEvent *event)
-{
-  if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
-    {
-      init_flow (mi);
-      return True;
-    }
-  return False;
-}
-
+#endif
 
 XSCREENSAVER_MODULE ("Flow", flow)
 
index 7fc43bd2c9d5ae8afb63c668b7de7dbfe8f28a97..3e39af090763e55e2f7e1a1c0327de52498301d6 100644 (file)
@@ -296,6 +296,12 @@ fluidballs_init (Display *dpy, Window window)
   state->max_radius = get_float_resource (dpy, "size", "Size") / 2;
   if (state->max_radius < 1.0) state->max_radius = 1.0;
 
+  if (state->xgwa.width < 100 || state->xgwa.height < 100) /* tiny window */
+    {
+      if (state->max_radius > 5)
+        state->max_radius = 5;
+    }
+
   state->random_sizes_p = get_boolean_resource (dpy, "random", "Random");
 
   /* If the initial window size is too small to hold all these balls,
index bd1e0cea694d389bfa4be2f4ac38d2a79f458124..38a480d9351fcbf76b7ea34baeff94bcedafa90b 100644 (file)
@@ -32,7 +32,7 @@
                     "*fpsSolid:          true     \n" \
 
 # include "xlockmore.h"     /* from the xscreensaver distribution */
-# define refresh_trees 0
+# define free_trees 0
 # define release_trees 0
 # define reshape_trees 0
 # define trees_handle_event 0
@@ -113,7 +113,7 @@ init_trees(ModeInfo * mi)
     XSetForeground(display, gc, colors[1].pixel);
   }
 
-  MI_INIT (mi, trees, 0);
+  MI_INIT (mi, trees);
 
   XClearWindow(display, MI_WINDOW(mi));
   XSetLineAttributes(display, gc, 2, LineSolid, CapButt, JoinMiter);
index 97a2c8b6353337a30ca9b099f30610addcb6113a..38bdbf6a2fdf12a7e3808f0e6229001afc4c2131 100644 (file)
@@ -1,4 +1,4 @@
-/* fps, Copyright (c) 2001-2014 Jamie Zawinski <jwz@jwz.org>
+/* fps, Copyright (c) 2001-2017 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
@@ -24,10 +24,16 @@ fps_init (Display *dpy, Window window)
   fps_state *st;
   const char *font;
   XFontStruct *f;
+  Bool top_p;
+  XWindowAttributes xgwa;
 
   if (! get_boolean_resource (dpy, "doFPS", "DoFPS"))
     return 0;
 
+  if (!strcasecmp (progname, "BSOD")) return 0;  /* Never worked right */
+
+  top_p = get_boolean_resource (dpy, "fpsTop", "FPSTop");
+
   st = (fps_state *) calloc (1, sizeof(*st));
 
   st->dpy = dpy;
@@ -36,12 +42,12 @@ fps_init (Display *dpy, Window window)
 
   font = get_string_resource (dpy, "fpsFont", "Font");
 
-  if (!font) font = "-*-courier-bold-r-normal-*-180-*";
+  if (!font)
+    font = "-*-courier-bold-r-normal-*-*-180-*-*-*-*-*-*"; /* also texfont.c */
   f = XLoadQueryFont (dpy, font);
   if (!f) f = XLoadQueryFont (dpy, "fixed");
 
   {
-    XWindowAttributes xgwa;
     XGCValues gcv;
     XGetWindowAttributes (dpy, window, &xgwa);
     gcv.font = f->fid;
@@ -56,9 +62,20 @@ fps_init (Display *dpy, Window window)
   st->font = f;
   st->x = 10;
   st->y = 10;
-  if (get_boolean_resource (dpy, "fpsTop", "FPSTop"))
+  if (top_p)
     st->y = - (st->font->ascent + st->font->descent + 10);
 
+# ifdef USE_IPHONE
+  /* Don't hide the FPS display under the iPhone X bezel.
+     #### This is the worst of all possible ways to do this!  But how else?
+   */
+  if (xgwa.width == 2436 || xgwa.height == 2436)
+    {
+      st->x += 48;
+      st->y += 48 * (top_p ? -1 : 1);
+    }
+# endif
+
   strcpy (st->string, "FPS: ... ");
 
   return st;
index 7f72af5b2ccb22b0aee64cb6c13af4805341d13f..3a6e1f78582c08671210d80cb6de507696cfdfb1 100644 (file)
@@ -46,9 +46,12 @@ static const char sccsid[] = "@(#)galaxy.c 4.04 97/07/28 xlockmore";
                                        "*ncolors:  64   \n" \
                                        "*fpsSolid:  true   \n" \
                                        "*ignoreRotation: True \n" \
+                                   "*lowrez: True \n" \
 
 # define UNIFORM_COLORS
 # define release_galaxy 0
+# define reshape_galaxy 0
+# define galaxy_handle_event 0
 # include "xlockmore.h"    /* from the xscreensaver distribution */
 #else  /* !STANDALONE */
 # include "xlock.h"     /* from the xlockmore distribution */
@@ -158,8 +161,8 @@ x-axis */
 
 static unistruct *universes = NULL;
 
-static void
-free_galaxies(ModeInfo * mi)
+ENTRYPOINT void
+free_galaxy(ModeInfo * mi)
 {
  unistruct  *gp = &universes[MI_SCREEN(mi)];
  if (gp->galaxies != NULL) {
@@ -193,7 +196,7 @@ startover(ModeInfo * mi)
  gp->rot_x = 0;
 
  if (MI_BATCHCOUNT(mi) < -MINGALAXIES)
-  free_galaxies(mi);
+  free_galaxy(mi);
  gp->ngalaxies = MI_BATCHCOUNT(mi);
  if (gp->ngalaxies < -MINGALAXIES)
   gp->ngalaxies = NRAND(-gp->ngalaxies - MINGALAXIES + 1) + MINGALAXIES;
@@ -308,7 +311,7 @@ init_galaxy(ModeInfo * mi)
 {
  unistruct  *gp;
 
- MI_INIT (mi, universes, free_galaxies);
+ MI_INIT (mi, universes);
  gp = &universes[MI_SCREEN(mi)];
 
 # ifdef HAVE_JWXYZ     /* Don't second-guess Quartz's double-buffering */
@@ -437,29 +440,12 @@ draw_galaxy(ModeInfo * mi)
     startover(mi);
 }
 
-ENTRYPOINT void
-reshape_galaxy(ModeInfo * mi, int width, int height)
-{
-  XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi));
-  init_galaxy (mi);
-}
-
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_galaxy(ModeInfo * mi)
 {
  /* Do nothing, it will refresh by itself */
 }
-
-ENTRYPOINT Bool
-galaxy_handle_event (ModeInfo *mi, XEvent *event)
-{
-  if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
-    {
-      reshape_galaxy (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
-      return True;
-    }
-  return False;
-}
-
+#endif
 
 XSCREENSAVER_MODULE ("Galaxy", galaxy)
index 50ad7225e7a6132b0d4eaea065b04118277cc387..56443f1b29552c2d79319f7e1e8b9b2481e7f48f 100644 (file)
@@ -82,10 +82,10 @@ UTILDIR_OBJS        = $(UTILS_BIN)/colors.o $(UTILS_BIN)/grabclient.o \
                  $(UTILS_BIN)/aligned_malloc.o $(UTILS_BIN)/thread_util.o \
                  $(UTILS_BIN)/spline.o $(UTILS_BIN)/pow2.o
 JWXYZ_OBJS     = $(JWXYZ_BIN)/jwzgles.o
-HACKDIR_OBJS   = $(HACK_SRC)/screenhack.o $(UTILS_SRC)/xlockmore.o \
+HACKDIR_OBJS   = $(HACK_SRC)/screenhack.o $(HACK_SRC)/xlockmore.o \
                  $(HACK_SRC)/fps.o
 
-SRCS           = xscreensaver-gl-helper.c normals.c fps-gl.c \
+SRCS           = xscreensaver-gl-helper.c normals.c erase-gl.c fps-gl.c \
                  atlantis.c b_draw.c b_lockglue.c b_sphere.c bubble3d.c \
                  buildlwo.c cage.c dolphin.c gears.c lament.c lament_model.c \
                  moebius.c morph3d.c pipeobjs.c pipes.c rubik.c s1_1.c s1_2.c \
@@ -128,9 +128,9 @@ SRCS                = xscreensaver-gl-helper.c normals.c fps-gl.c \
                  cityflow.c romanboy.c splitflap.c splitflap_obj.c \
                  dymaxionmap.c unicrud.c energystream.c raverhoop.c \
                  hydrostat.c discoball.c cubetwist.c cubestack.c splodesic.c \
-                 hexstrut.c vigilance.c seccam.c
+                 hexstrut.c vigilance.c seccam.c esper.c
 
-OBJS           = xscreensaver-gl-helper.o normals.o fps-gl.o \
+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 \
                  buildlwo.o cage.o dolphin.o gears.o lament.o lament_model.o \
                  moebius.o morph3d.o pipeobjs.o pipes.o rubik.o s1_1.o s1_2.o \
@@ -173,7 +173,7 @@ OBJS                = xscreensaver-gl-helper.o normals.o fps-gl.o \
                  cityflow.o romanboy.o splitflap.o splitflap_obj.o \
                  dymaxionmap.o unicrud.o energystream.o raverhoop.o \
                  hydrostat.o discoball.o cubetwist.o cubestack.o splodesic.o \
-                 hexstrut.o vigilance.o seccam.o
+                 hexstrut.o vigilance.o seccam.o esper.o
 
 GL_EXES                = cage gears moebius pipes sproingies stairs superquadrics \
                  morph3d rubik atlantis lament bubble3d glplanet pulsar \
@@ -193,7 +193,7 @@ GL_EXES             = cage gears moebius pipes sproingies stairs superquadrics \
                  geodesicgears projectiveplane winduprobot cityflow romanboy \
                  splitflap dymaxionmap unicrud energystream raverhoop \
                  hydrostat discoball cubetwist cubestack splodesic \
-                 hexstrut vigilance
+                 hexstrut vigilance esper
 GLE_EXES       = extrusion
 SUID_EXES      = sonar
 GL_UTIL_EXES   = xscreensaver-gl-helper
@@ -211,8 +211,8 @@ RETIRED_GL_EXES     = glforestfire
 
 FPS_OBJS       = texfont.o $(HACK_BIN)/fps.o fps-gl.o @XFT_OBJS@
 HACK_OBJS      = $(JWZGLES_OBJS) $(HACK_BIN)/screenhack.o @ANIM_OBJS@ \
-                 xlockmore-gl.o xlock-gl-utils.o ${FPS_OBJS} \
-                 $(UTILS_BIN)/resources.o $(UTILS_BIN)/visual.o \
+                 $(HACK_BIN)/xlockmore.o xlock-gl-utils.o erase-gl.o \
+                 ${FPS_OBJS} $(UTILS_BIN)/resources.o $(UTILS_BIN)/visual.o \
                  $(UTILS_BIN)/visual-gl.o $(UTILS_BIN)/usleep.o \
                  $(UTILS_BIN)/yarandom.o $(UTILS_BIN)/hsv.o \
                  $(UTILS_BIN)/colors.o $(UTILS_BIN)/async_netdb.o \
@@ -222,13 +222,13 @@ HACK_OBJS = $(JWZGLES_OBJS) $(HACK_BIN)/screenhack.o @ANIM_OBJS@ \
 HDRS           = atlantis.h bubble3d.h buildlwo.h e_textures.h xpm-ximage.h \
                  grab-ximage.h tube.h sphere.h boxed.h \
                  stonerview.h stonerview-move.h stonerview-osc.h \
-                 glutstroke.h glut_roman.h marching.h rotator.h trackball.h \
-                 gltrackball.h chessmodels.h chessgames.h gllist.h flurry.h \
-                 tunnel_draw.h ants.h polyhedra.h normals.h \
-                 texfont.h tangram_shapes.h sproingies.h extrusion.h \
-                 glschool.h glschool_gl.h glschool_alg.h topblock.h \
-                 involute.h teapot.h sonar.h dropshadow.h starwars.h \
-                 teapot2.h dnapizza.h curlicue.h
+                 glutstroke.h glut_roman.h glut_mroman.h marching.h \
+                 rotator.h trackball.h gltrackball.h chessmodels.h \
+                 chessgames.h gllist.h flurry.h tunnel_draw.h ants.h \
+                 polyhedra.h normals.h texfont.h tangram_shapes.h \
+                 sproingies.h extrusion.h glschool.h glschool_gl.h \
+                 glschool_alg.h topblock.h involute.h teapot.h sonar.h \
+                 dropshadow.h starwars.h teapot2.h dnapizza.h curlicue.h
 GL_MEN         = atlantis.man boxed.man bubble3d.man cage.man circuit.man \
                  cubenetic.man dangerball.man engine.man extrusion.man \
                  flipscreen3d.man gears.man gflux.man \
@@ -256,7 +256,7 @@ GL_MEN              = atlantis.man boxed.man bubble3d.man cage.man circuit.man \
                  cityflow.man romanboy.man splitflap.man dymaxionmap.man \
                  unicrud.man energystream.man raverhoop.man hydrostat.man \
                  discoball.man cubetwist.man cubestack.man splodesic.man \
-                 hexstrut.man vigilance.man
+                 hexstrut.man vigilance.man esper.man
 MEN            = @GL_MEN@
 RETIRED_MEN    = glforestfire.man
 EXTRAS         = README Makefile.in dxf2gl.pl vrml2gl.pl wfront2gl.pl \
@@ -529,12 +529,10 @@ xscreensaver-gl-helper: $(HELPER_OBJS)
        $(CC) $(LDFLAGS) -o $@ $(HELPER_OBJS) $(LIBS) $(X_LIBS) $(HACK_POST2)
 
 
-# These hacks use a slightly-differently-compiled variant of xlockmore.c.
+# These hacks use a slightly-differently-compiled variant of recanim.c.
 # This is how to make the the other .o file from it.
 #
 XLM_CFLAGS=-DUSE_GL $(INCLUDES) $(DEFS) $(CPPFLAGS) $(CFLAGS) $(X_CFLAGS)
-xlockmore-gl.o: $(HACK_SRC)/xlockmore.c
-       $(CC) -o $@ -c $(XLM_CFLAGS) $(HACK_SRC)/xlockmore.c
 recanim-gl.o: $(HACK_SRC)/recanim.c
        $(CC) -o $@ -c $(XLM_CFLAGS) $(HACK_SRC)/recanim.c
 
@@ -965,6 +963,9 @@ splodesic:  splodesic.o     $(HACK_TRACK_OBJS)
 hexstrut:      hexstrut.o       normals.o $(HACK_TRACK_OBJS)
        $(CC_HACK) -o $@ $@.o    normals.o $(HACK_TRACK_OBJS) $(HACK_LIBS)
 
+esper: esper.o                 $(HACK_GRAB_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(HACK_GRAB_OBJS) $(HACK_LIBS)
+
 ##############################################################################
 #
 # DO NOT DELETE: updated by make distdepend
@@ -975,12 +976,12 @@ antinspect.o: $(srcdir)/gltrackball.h
 antinspect.o: $(HACK_SRC)/screenhackI.h
 antinspect.o: $(srcdir)/sphere.h
 antinspect.o: $(UTILS_SRC)/colors.h
+antinspect.o: $(UTILS_SRC)/erase.h
 antinspect.o: $(UTILS_SRC)/grabscreen.h
 antinspect.o: $(UTILS_SRC)/hsv.h
 antinspect.o: $(UTILS_SRC)/resources.h
 antinspect.o: $(UTILS_SRC)/usleep.h
 antinspect.o: $(UTILS_SRC)/visual.h
-antinspect.o: $(UTILS_SRC)/xshm.h
 antinspect.o: $(UTILS_SRC)/yarandom.h
 antinspect.o: $(HACK_SRC)/xlockmoreI.h
 antinspect.o: $(HACK_SRC)/xlockmore.h
@@ -993,12 +994,12 @@ antmaze.o: $(HACK_SRC)/screenhackI.h
 antmaze.o: $(srcdir)/sphere.h
 antmaze.o: $(srcdir)/tube.h
 antmaze.o: $(UTILS_SRC)/colors.h
+antmaze.o: $(UTILS_SRC)/erase.h
 antmaze.o: $(UTILS_SRC)/grabscreen.h
 antmaze.o: $(UTILS_SRC)/hsv.h
 antmaze.o: $(UTILS_SRC)/resources.h
 antmaze.o: $(UTILS_SRC)/usleep.h
 antmaze.o: $(UTILS_SRC)/visual.h
-antmaze.o: $(UTILS_SRC)/xshm.h
 antmaze.o: $(UTILS_SRC)/yarandom.h
 antmaze.o: $(HACK_SRC)/xlockmoreI.h
 antmaze.o: $(HACK_SRC)/xlockmore.h
@@ -1012,12 +1013,12 @@ antspotlight.o: $(HACK_SRC)/screenhackI.h
 antspotlight.o: $(srcdir)/sphere.h
 antspotlight.o: $(srcdir)/tube.h
 antspotlight.o: $(UTILS_SRC)/colors.h
+antspotlight.o: $(UTILS_SRC)/erase.h
 antspotlight.o: $(UTILS_SRC)/grabscreen.h
 antspotlight.o: $(UTILS_SRC)/hsv.h
 antspotlight.o: $(UTILS_SRC)/resources.h
 antspotlight.o: $(UTILS_SRC)/usleep.h
 antspotlight.o: $(UTILS_SRC)/visual.h
-antspotlight.o: $(UTILS_SRC)/xshm.h
 antspotlight.o: $(UTILS_SRC)/yarandom.h
 antspotlight.o: $(HACK_SRC)/xlockmoreI.h
 antspotlight.o: $(HACK_SRC)/xlockmore.h
@@ -1027,12 +1028,12 @@ atlantis.o: $(HACK_SRC)/fps.h
 atlantis.o: $(HACK_SRC)/images/sea-texture.xpm
 atlantis.o: $(HACK_SRC)/screenhackI.h
 atlantis.o: $(UTILS_SRC)/colors.h
+atlantis.o: $(UTILS_SRC)/erase.h
 atlantis.o: $(UTILS_SRC)/grabscreen.h
 atlantis.o: $(UTILS_SRC)/hsv.h
 atlantis.o: $(UTILS_SRC)/resources.h
 atlantis.o: $(UTILS_SRC)/usleep.h
 atlantis.o: $(UTILS_SRC)/visual.h
-atlantis.o: $(UTILS_SRC)/xshm.h
 atlantis.o: $(UTILS_SRC)/yarandom.h
 atlantis.o: $(HACK_SRC)/xlockmoreI.h
 atlantis.o: $(HACK_SRC)/xlockmore.h
@@ -1048,12 +1049,12 @@ atunnel.o: $(HACK_SRC)/images/tunnel5.xpm
 atunnel.o: $(HACK_SRC)/screenhackI.h
 atunnel.o: $(srcdir)/tunnel_draw.h
 atunnel.o: $(UTILS_SRC)/colors.h
+atunnel.o: $(UTILS_SRC)/erase.h
 atunnel.o: $(UTILS_SRC)/grabscreen.h
 atunnel.o: $(UTILS_SRC)/hsv.h
 atunnel.o: $(UTILS_SRC)/resources.h
 atunnel.o: $(UTILS_SRC)/usleep.h
 atunnel.o: $(UTILS_SRC)/visual.h
-atunnel.o: $(UTILS_SRC)/xshm.h
 atunnel.o: $(UTILS_SRC)/yarandom.h
 atunnel.o: $(HACK_SRC)/xlockmoreI.h
 atunnel.o: $(HACK_SRC)/xlockmore.h
@@ -1063,12 +1064,12 @@ b_draw.o: ../../config.h
 b_draw.o: $(HACK_SRC)/fps.h
 b_draw.o: $(HACK_SRC)/screenhackI.h
 b_draw.o: $(UTILS_SRC)/colors.h
+b_draw.o: $(UTILS_SRC)/erase.h
 b_draw.o: $(UTILS_SRC)/grabscreen.h
 b_draw.o: $(UTILS_SRC)/hsv.h
 b_draw.o: $(UTILS_SRC)/resources.h
 b_draw.o: $(UTILS_SRC)/usleep.h
 b_draw.o: $(UTILS_SRC)/visual.h
-b_draw.o: $(UTILS_SRC)/xshm.h
 b_draw.o: $(UTILS_SRC)/yarandom.h
 b_draw.o: $(HACK_SRC)/xlockmoreI.h
 blinkbox.o: ../../config.h
@@ -1076,12 +1077,12 @@ blinkbox.o: $(HACK_SRC)/fps.h
 blinkbox.o: $(HACK_SRC)/screenhackI.h
 blinkbox.o: $(srcdir)/sphere.h
 blinkbox.o: $(UTILS_SRC)/colors.h
+blinkbox.o: $(UTILS_SRC)/erase.h
 blinkbox.o: $(UTILS_SRC)/grabscreen.h
 blinkbox.o: $(UTILS_SRC)/hsv.h
 blinkbox.o: $(UTILS_SRC)/resources.h
 blinkbox.o: $(UTILS_SRC)/usleep.h
 blinkbox.o: $(UTILS_SRC)/visual.h
-blinkbox.o: $(UTILS_SRC)/xshm.h
 blinkbox.o: $(UTILS_SRC)/yarandom.h
 blinkbox.o: $(HACK_SRC)/xlockmoreI.h
 blinkbox.o: $(HACK_SRC)/xlockmore.h
@@ -1090,12 +1091,12 @@ b_lockglue.o: ../../config.h
 b_lockglue.o: $(HACK_SRC)/fps.h
 b_lockglue.o: $(HACK_SRC)/screenhackI.h
 b_lockglue.o: $(UTILS_SRC)/colors.h
+b_lockglue.o: $(UTILS_SRC)/erase.h
 b_lockglue.o: $(UTILS_SRC)/grabscreen.h
 b_lockglue.o: $(UTILS_SRC)/hsv.h
 b_lockglue.o: $(UTILS_SRC)/resources.h
 b_lockglue.o: $(UTILS_SRC)/usleep.h
 b_lockglue.o: $(UTILS_SRC)/visual.h
-b_lockglue.o: $(UTILS_SRC)/xshm.h
 b_lockglue.o: $(UTILS_SRC)/yarandom.h
 b_lockglue.o: $(HACK_SRC)/xlockmoreI.h
 b_lockglue.o: $(HACK_SRC)/xlockmore.h
@@ -1104,12 +1105,12 @@ blocktube.o: $(HACK_SRC)/fps.h
 blocktube.o: $(HACK_SRC)/images/blocktube.xpm
 blocktube.o: $(HACK_SRC)/screenhackI.h
 blocktube.o: $(UTILS_SRC)/colors.h
+blocktube.o: $(UTILS_SRC)/erase.h
 blocktube.o: $(UTILS_SRC)/grabscreen.h
 blocktube.o: $(UTILS_SRC)/hsv.h
 blocktube.o: $(UTILS_SRC)/resources.h
 blocktube.o: $(UTILS_SRC)/usleep.h
 blocktube.o: $(UTILS_SRC)/visual.h
-blocktube.o: $(UTILS_SRC)/xshm.h
 blocktube.o: $(UTILS_SRC)/yarandom.h
 blocktube.o: $(HACK_SRC)/xlockmoreI.h
 blocktube.o: $(HACK_SRC)/xlockmore.h
@@ -1119,12 +1120,12 @@ boing.o: $(HACK_SRC)/fps.h
 boing.o: $(srcdir)/gltrackball.h
 boing.o: $(HACK_SRC)/screenhackI.h
 boing.o: $(UTILS_SRC)/colors.h
+boing.o: $(UTILS_SRC)/erase.h
 boing.o: $(UTILS_SRC)/grabscreen.h
 boing.o: $(UTILS_SRC)/hsv.h
 boing.o: $(UTILS_SRC)/resources.h
 boing.o: $(UTILS_SRC)/usleep.h
 boing.o: $(UTILS_SRC)/visual.h
-boing.o: $(UTILS_SRC)/xshm.h
 boing.o: $(UTILS_SRC)/yarandom.h
 boing.o: $(HACK_SRC)/xlockmoreI.h
 boing.o: $(HACK_SRC)/xlockmore.h
@@ -1135,12 +1136,12 @@ bouncingcow.o: $(srcdir)/gltrackball.h
 bouncingcow.o: $(srcdir)/rotator.h
 bouncingcow.o: $(HACK_SRC)/screenhackI.h
 bouncingcow.o: $(UTILS_SRC)/colors.h
+bouncingcow.o: $(UTILS_SRC)/erase.h
 bouncingcow.o: $(UTILS_SRC)/grabscreen.h
 bouncingcow.o: $(UTILS_SRC)/hsv.h
 bouncingcow.o: $(UTILS_SRC)/resources.h
 bouncingcow.o: $(UTILS_SRC)/usleep.h
 bouncingcow.o: $(UTILS_SRC)/visual.h
-bouncingcow.o: $(UTILS_SRC)/xshm.h
 bouncingcow.o: $(UTILS_SRC)/yarandom.h
 bouncingcow.o: $(HACK_SRC)/xlockmoreI.h
 bouncingcow.o: $(HACK_SRC)/xlockmore.h
@@ -1150,12 +1151,12 @@ boxed.o: ../../config.h
 boxed.o: $(HACK_SRC)/fps.h
 boxed.o: $(HACK_SRC)/screenhackI.h
 boxed.o: $(UTILS_SRC)/colors.h
+boxed.o: $(UTILS_SRC)/erase.h
 boxed.o: $(UTILS_SRC)/grabscreen.h
 boxed.o: $(UTILS_SRC)/hsv.h
 boxed.o: $(UTILS_SRC)/resources.h
 boxed.o: $(UTILS_SRC)/usleep.h
 boxed.o: $(UTILS_SRC)/visual.h
-boxed.o: $(UTILS_SRC)/xshm.h
 boxed.o: $(UTILS_SRC)/yarandom.h
 boxed.o: $(HACK_SRC)/xlockmoreI.h
 boxed.o: $(HACK_SRC)/xlockmore.h
@@ -1164,12 +1165,12 @@ b_sphere.o: ../../config.h
 b_sphere.o: $(HACK_SRC)/fps.h
 b_sphere.o: $(HACK_SRC)/screenhackI.h
 b_sphere.o: $(UTILS_SRC)/colors.h
+b_sphere.o: $(UTILS_SRC)/erase.h
 b_sphere.o: $(UTILS_SRC)/grabscreen.h
 b_sphere.o: $(UTILS_SRC)/hsv.h
 b_sphere.o: $(UTILS_SRC)/resources.h
 b_sphere.o: $(UTILS_SRC)/usleep.h
 b_sphere.o: $(UTILS_SRC)/visual.h
-b_sphere.o: $(UTILS_SRC)/xshm.h
 b_sphere.o: $(UTILS_SRC)/yarandom.h
 b_sphere.o: $(HACK_SRC)/xlockmoreI.h
 bubble3d.o: $(srcdir)/bubble3d.h
@@ -1177,12 +1178,12 @@ bubble3d.o: ../../config.h
 bubble3d.o: $(HACK_SRC)/fps.h
 bubble3d.o: $(HACK_SRC)/screenhackI.h
 bubble3d.o: $(UTILS_SRC)/colors.h
+bubble3d.o: $(UTILS_SRC)/erase.h
 bubble3d.o: $(UTILS_SRC)/grabscreen.h
 bubble3d.o: $(UTILS_SRC)/hsv.h
 bubble3d.o: $(UTILS_SRC)/resources.h
 bubble3d.o: $(UTILS_SRC)/usleep.h
 bubble3d.o: $(UTILS_SRC)/visual.h
-bubble3d.o: $(UTILS_SRC)/xshm.h
 bubble3d.o: $(UTILS_SRC)/yarandom.h
 bubble3d.o: $(HACK_SRC)/xlockmoreI.h
 buildlwo.o: $(srcdir)/buildlwo.h
@@ -1192,12 +1193,12 @@ cage.o: $(HACK_SRC)/fps.h
 cage.o: $(HACK_SRC)/images/wood.xpm
 cage.o: $(HACK_SRC)/screenhackI.h
 cage.o: $(UTILS_SRC)/colors.h
+cage.o: $(UTILS_SRC)/erase.h
 cage.o: $(UTILS_SRC)/grabscreen.h
 cage.o: $(UTILS_SRC)/hsv.h
 cage.o: $(UTILS_SRC)/resources.h
 cage.o: $(UTILS_SRC)/usleep.h
 cage.o: $(UTILS_SRC)/visual.h
-cage.o: $(UTILS_SRC)/xshm.h
 cage.o: $(UTILS_SRC)/yarandom.h
 cage.o: $(HACK_SRC)/xlockmoreI.h
 cage.o: $(HACK_SRC)/xlockmore.h
@@ -1210,12 +1211,12 @@ carousel.o: $(srcdir)/rotator.h
 carousel.o: $(HACK_SRC)/screenhackI.h
 carousel.o: $(srcdir)/texfont.h
 carousel.o: $(UTILS_SRC)/colors.h
+carousel.o: $(UTILS_SRC)/erase.h
 carousel.o: $(UTILS_SRC)/grabscreen.h
 carousel.o: $(UTILS_SRC)/hsv.h
 carousel.o: $(UTILS_SRC)/resources.h
 carousel.o: $(UTILS_SRC)/usleep.h
 carousel.o: $(UTILS_SRC)/visual.h
-carousel.o: $(UTILS_SRC)/xshm.h
 carousel.o: $(UTILS_SRC)/yarandom.h
 carousel.o: $(HACK_SRC)/xlockmoreI.h
 carousel.o: $(HACK_SRC)/xlockmore.h
@@ -1226,12 +1227,12 @@ circuit.o: $(HACK_SRC)/fps.h
 circuit.o: $(HACK_SRC)/screenhackI.h
 circuit.o: $(srcdir)/texfont.h
 circuit.o: $(UTILS_SRC)/colors.h
+circuit.o: $(UTILS_SRC)/erase.h
 circuit.o: $(UTILS_SRC)/grabscreen.h
 circuit.o: $(UTILS_SRC)/hsv.h
 circuit.o: $(UTILS_SRC)/resources.h
 circuit.o: $(UTILS_SRC)/usleep.h
 circuit.o: $(UTILS_SRC)/visual.h
-circuit.o: $(UTILS_SRC)/xshm.h
 circuit.o: $(UTILS_SRC)/yarandom.h
 circuit.o: $(HACK_SRC)/xlockmoreI.h
 circuit.o: $(HACK_SRC)/xlockmore.h
@@ -1240,12 +1241,12 @@ cityflow.o: $(HACK_SRC)/fps.h
 cityflow.o: $(srcdir)/gltrackball.h
 cityflow.o: $(HACK_SRC)/screenhackI.h
 cityflow.o: $(UTILS_SRC)/colors.h
+cityflow.o: $(UTILS_SRC)/erase.h
 cityflow.o: $(UTILS_SRC)/grabscreen.h
 cityflow.o: $(UTILS_SRC)/hsv.h
 cityflow.o: $(UTILS_SRC)/resources.h
 cityflow.o: $(UTILS_SRC)/usleep.h
 cityflow.o: $(UTILS_SRC)/visual.h
-cityflow.o: $(UTILS_SRC)/xshm.h
 cityflow.o: $(UTILS_SRC)/yarandom.h
 cityflow.o: $(HACK_SRC)/xlockmoreI.h
 cityflow.o: $(HACK_SRC)/xlockmore.h
@@ -1260,12 +1261,12 @@ companion.o: $(srcdir)/gltrackball.h
 companion.o: $(srcdir)/rotator.h
 companion.o: $(HACK_SRC)/screenhackI.h
 companion.o: $(UTILS_SRC)/colors.h
+companion.o: $(UTILS_SRC)/erase.h
 companion.o: $(UTILS_SRC)/grabscreen.h
 companion.o: $(UTILS_SRC)/hsv.h
 companion.o: $(UTILS_SRC)/resources.h
 companion.o: $(UTILS_SRC)/usleep.h
 companion.o: $(UTILS_SRC)/visual.h
-companion.o: $(UTILS_SRC)/xshm.h
 companion.o: $(UTILS_SRC)/yarandom.h
 companion.o: $(HACK_SRC)/xlockmoreI.h
 companion.o: $(HACK_SRC)/xlockmore.h
@@ -1288,12 +1289,12 @@ crackberg.o: ../../config.h
 crackberg.o: $(HACK_SRC)/fps.h
 crackberg.o: $(HACK_SRC)/screenhackI.h
 crackberg.o: $(UTILS_SRC)/colors.h
+crackberg.o: $(UTILS_SRC)/erase.h
 crackberg.o: $(UTILS_SRC)/grabscreen.h
 crackberg.o: $(UTILS_SRC)/hsv.h
 crackberg.o: $(UTILS_SRC)/resources.h
 crackberg.o: $(UTILS_SRC)/usleep.h
 crackberg.o: $(UTILS_SRC)/visual.h
-crackberg.o: $(UTILS_SRC)/xshm.h
 crackberg.o: $(UTILS_SRC)/yarandom.h
 crackberg.o: $(HACK_SRC)/xlockmoreI.h
 crackberg.o: $(HACK_SRC)/xlockmore.h
@@ -1302,12 +1303,12 @@ cube21.o: $(HACK_SRC)/fps.h
 cube21.o: $(srcdir)/gltrackball.h
 cube21.o: $(HACK_SRC)/screenhackI.h
 cube21.o: $(UTILS_SRC)/colors.h
+cube21.o: $(UTILS_SRC)/erase.h
 cube21.o: $(UTILS_SRC)/grabscreen.h
 cube21.o: $(UTILS_SRC)/hsv.h
 cube21.o: $(UTILS_SRC)/resources.h
 cube21.o: $(UTILS_SRC)/usleep.h
 cube21.o: $(UTILS_SRC)/visual.h
-cube21.o: $(UTILS_SRC)/xshm.h
 cube21.o: $(UTILS_SRC)/yarandom.h
 cube21.o: $(HACK_SRC)/xlockmoreI.h
 cube21.o: $(HACK_SRC)/xlockmore.h
@@ -1317,12 +1318,12 @@ cubenetic.o: $(srcdir)/gltrackball.h
 cubenetic.o: $(srcdir)/rotator.h
 cubenetic.o: $(HACK_SRC)/screenhackI.h
 cubenetic.o: $(UTILS_SRC)/colors.h
+cubenetic.o: $(UTILS_SRC)/erase.h
 cubenetic.o: $(UTILS_SRC)/grabscreen.h
 cubenetic.o: $(UTILS_SRC)/hsv.h
 cubenetic.o: $(UTILS_SRC)/resources.h
 cubenetic.o: $(UTILS_SRC)/usleep.h
 cubenetic.o: $(UTILS_SRC)/visual.h
-cubenetic.o: $(UTILS_SRC)/xshm.h
 cubenetic.o: $(UTILS_SRC)/yarandom.h
 cubenetic.o: $(HACK_SRC)/xlockmoreI.h
 cubenetic.o: $(HACK_SRC)/xlockmore.h
@@ -1332,12 +1333,12 @@ cubestack.o: $(srcdir)/gltrackball.h
 cubestack.o: $(srcdir)/rotator.h
 cubestack.o: $(HACK_SRC)/screenhackI.h
 cubestack.o: $(UTILS_SRC)/colors.h
+cubestack.o: $(UTILS_SRC)/erase.h
 cubestack.o: $(UTILS_SRC)/grabscreen.h
 cubestack.o: $(UTILS_SRC)/hsv.h
 cubestack.o: $(UTILS_SRC)/resources.h
 cubestack.o: $(UTILS_SRC)/usleep.h
 cubestack.o: $(UTILS_SRC)/visual.h
-cubestack.o: $(UTILS_SRC)/xshm.h
 cubestack.o: $(UTILS_SRC)/yarandom.h
 cubestack.o: $(HACK_SRC)/xlockmoreI.h
 cubestack.o: $(HACK_SRC)/xlockmore.h
@@ -1347,12 +1348,12 @@ cubestorm.o: $(srcdir)/gltrackball.h
 cubestorm.o: $(srcdir)/rotator.h
 cubestorm.o: $(HACK_SRC)/screenhackI.h
 cubestorm.o: $(UTILS_SRC)/colors.h
+cubestorm.o: $(UTILS_SRC)/erase.h
 cubestorm.o: $(UTILS_SRC)/grabscreen.h
 cubestorm.o: $(UTILS_SRC)/hsv.h
 cubestorm.o: $(UTILS_SRC)/resources.h
 cubestorm.o: $(UTILS_SRC)/usleep.h
 cubestorm.o: $(UTILS_SRC)/visual.h
-cubestorm.o: $(UTILS_SRC)/xshm.h
 cubestorm.o: $(UTILS_SRC)/yarandom.h
 cubestorm.o: $(HACK_SRC)/xlockmoreI.h
 cubestorm.o: $(HACK_SRC)/xlockmore.h
@@ -1363,12 +1364,12 @@ cubetwist.o: $(srcdir)/normals.h
 cubetwist.o: $(srcdir)/rotator.h
 cubetwist.o: $(HACK_SRC)/screenhackI.h
 cubetwist.o: $(UTILS_SRC)/colors.h
+cubetwist.o: $(UTILS_SRC)/erase.h
 cubetwist.o: $(UTILS_SRC)/grabscreen.h
 cubetwist.o: $(UTILS_SRC)/hsv.h
 cubetwist.o: $(UTILS_SRC)/resources.h
 cubetwist.o: $(UTILS_SRC)/usleep.h
 cubetwist.o: $(UTILS_SRC)/visual.h
-cubetwist.o: $(UTILS_SRC)/xshm.h
 cubetwist.o: $(UTILS_SRC)/yarandom.h
 cubetwist.o: $(HACK_SRC)/xlockmoreI.h
 cubetwist.o: $(HACK_SRC)/xlockmore.h
@@ -1378,12 +1379,12 @@ cubicgrid.o: $(srcdir)/gltrackball.h
 cubicgrid.o: $(srcdir)/rotator.h
 cubicgrid.o: $(HACK_SRC)/screenhackI.h
 cubicgrid.o: $(UTILS_SRC)/colors.h
+cubicgrid.o: $(UTILS_SRC)/erase.h
 cubicgrid.o: $(UTILS_SRC)/grabscreen.h
 cubicgrid.o: $(UTILS_SRC)/hsv.h
 cubicgrid.o: $(UTILS_SRC)/resources.h
 cubicgrid.o: $(UTILS_SRC)/usleep.h
 cubicgrid.o: $(UTILS_SRC)/visual.h
-cubicgrid.o: $(UTILS_SRC)/xshm.h
 cubicgrid.o: $(UTILS_SRC)/yarandom.h
 cubicgrid.o: $(HACK_SRC)/xlockmoreI.h
 cubicgrid.o: $(HACK_SRC)/xlockmore.h
@@ -1395,12 +1396,12 @@ dangerball.o: $(HACK_SRC)/screenhackI.h
 dangerball.o: $(srcdir)/sphere.h
 dangerball.o: $(srcdir)/tube.h
 dangerball.o: $(UTILS_SRC)/colors.h
+dangerball.o: $(UTILS_SRC)/erase.h
 dangerball.o: $(UTILS_SRC)/grabscreen.h
 dangerball.o: $(UTILS_SRC)/hsv.h
 dangerball.o: $(UTILS_SRC)/resources.h
 dangerball.o: $(UTILS_SRC)/usleep.h
 dangerball.o: $(UTILS_SRC)/visual.h
-dangerball.o: $(UTILS_SRC)/xshm.h
 dangerball.o: $(UTILS_SRC)/yarandom.h
 dangerball.o: $(HACK_SRC)/xlockmoreI.h
 dangerball.o: $(HACK_SRC)/xlockmore.h
@@ -1411,12 +1412,12 @@ discoball.o: $(srcdir)/normals.h
 discoball.o: $(srcdir)/rotator.h
 discoball.o: $(HACK_SRC)/screenhackI.h
 discoball.o: $(UTILS_SRC)/colors.h
+discoball.o: $(UTILS_SRC)/erase.h
 discoball.o: $(UTILS_SRC)/grabscreen.h
 discoball.o: $(UTILS_SRC)/hsv.h
 discoball.o: $(UTILS_SRC)/resources.h
 discoball.o: $(UTILS_SRC)/usleep.h
 discoball.o: $(UTILS_SRC)/visual.h
-discoball.o: $(UTILS_SRC)/xshm.h
 discoball.o: $(UTILS_SRC)/yarandom.h
 discoball.o: $(HACK_SRC)/xlockmoreI.h
 discoball.o: $(HACK_SRC)/xlockmore.h
@@ -1430,13 +1431,13 @@ dnalogo.o: $(srcdir)/sphere.h
 dnalogo.o: $(srcdir)/texfont.h
 dnalogo.o: $(srcdir)/tube.h
 dnalogo.o: $(UTILS_SRC)/colors.h
+dnalogo.o: $(UTILS_SRC)/erase.h
 dnalogo.o: $(UTILS_SRC)/grabscreen.h
 dnalogo.o: $(UTILS_SRC)/hsv.h
 dnalogo.o: $(UTILS_SRC)/resources.h
 dnalogo.o: $(UTILS_SRC)/usleep.h
 dnalogo.o: $(UTILS_SRC)/utf8wc.h
 dnalogo.o: $(UTILS_SRC)/visual.h
-dnalogo.o: $(UTILS_SRC)/xshm.h
 dnalogo.o: $(UTILS_SRC)/yarandom.h
 dnalogo.o: $(HACK_SRC)/xlockmoreI.h
 dnalogo.o: $(HACK_SRC)/xlockmore.h
@@ -1456,12 +1457,12 @@ dropshadow.o: $(srcdir)/dropshadow.h
 dropshadow.o: $(HACK_SRC)/fps.h
 dropshadow.o: $(HACK_SRC)/screenhackI.h
 dropshadow.o: $(UTILS_SRC)/colors.h
+dropshadow.o: $(UTILS_SRC)/erase.h
 dropshadow.o: $(UTILS_SRC)/grabscreen.h
 dropshadow.o: $(UTILS_SRC)/hsv.h
 dropshadow.o: $(UTILS_SRC)/resources.h
 dropshadow.o: $(UTILS_SRC)/usleep.h
 dropshadow.o: $(UTILS_SRC)/visual.h
-dropshadow.o: $(UTILS_SRC)/xshm.h
 dropshadow.o: $(UTILS_SRC)/yarandom.h
 dropshadow.o: $(HACK_SRC)/xlockmoreI.h
 dymaxionmap.o: ../../config.h
@@ -1475,12 +1476,12 @@ dymaxionmap.o: $(HACK_SRC)/screenhackI.h
 dymaxionmap.o: $(srcdir)/sphere.h
 dymaxionmap.o: $(srcdir)/texfont.h
 dymaxionmap.o: $(UTILS_SRC)/colors.h
+dymaxionmap.o: $(UTILS_SRC)/erase.h
 dymaxionmap.o: $(UTILS_SRC)/grabscreen.h
 dymaxionmap.o: $(UTILS_SRC)/hsv.h
 dymaxionmap.o: $(UTILS_SRC)/resources.h
 dymaxionmap.o: $(UTILS_SRC)/usleep.h
 dymaxionmap.o: $(UTILS_SRC)/visual.h
-dymaxionmap.o: $(UTILS_SRC)/xshm.h
 dymaxionmap.o: $(UTILS_SRC)/yarandom.h
 dymaxionmap.o: $(HACK_SRC)/xlockmoreI.h
 dymaxionmap.o: $(HACK_SRC)/xlockmore.h
@@ -1492,12 +1493,12 @@ endgame.o: $(HACK_SRC)/fps.h
 endgame.o: $(srcdir)/gltrackball.h
 endgame.o: $(HACK_SRC)/screenhackI.h
 endgame.o: $(UTILS_SRC)/colors.h
+endgame.o: $(UTILS_SRC)/erase.h
 endgame.o: $(UTILS_SRC)/grabscreen.h
 endgame.o: $(UTILS_SRC)/hsv.h
 endgame.o: $(UTILS_SRC)/resources.h
 endgame.o: $(UTILS_SRC)/usleep.h
 endgame.o: $(UTILS_SRC)/visual.h
-endgame.o: $(UTILS_SRC)/xshm.h
 endgame.o: $(UTILS_SRC)/yarandom.h
 endgame.o: $(HACK_SRC)/xlockmoreI.h
 endgame.o: $(HACK_SRC)/xlockmore.h
@@ -1507,12 +1508,12 @@ energystream.o: $(srcdir)/gltrackball.h
 energystream.o: $(srcdir)/rotator.h
 energystream.o: $(HACK_SRC)/screenhackI.h
 energystream.o: $(UTILS_SRC)/colors.h
+energystream.o: $(UTILS_SRC)/erase.h
 energystream.o: $(UTILS_SRC)/grabscreen.h
 energystream.o: $(UTILS_SRC)/hsv.h
 energystream.o: $(UTILS_SRC)/resources.h
 energystream.o: $(UTILS_SRC)/usleep.h
 energystream.o: $(UTILS_SRC)/visual.h
-energystream.o: $(UTILS_SRC)/xshm.h
 energystream.o: $(UTILS_SRC)/yarandom.h
 energystream.o: $(HACK_SRC)/xlockmoreI.h
 energystream.o: $(HACK_SRC)/xlockmore.h
@@ -1523,15 +1524,34 @@ engine.o: $(srcdir)/rotator.h
 engine.o: $(HACK_SRC)/screenhackI.h
 engine.o: $(srcdir)/texfont.h
 engine.o: $(UTILS_SRC)/colors.h
+engine.o: $(UTILS_SRC)/erase.h
 engine.o: $(UTILS_SRC)/grabscreen.h
 engine.o: $(UTILS_SRC)/hsv.h
 engine.o: $(UTILS_SRC)/resources.h
 engine.o: $(UTILS_SRC)/usleep.h
 engine.o: $(UTILS_SRC)/visual.h
-engine.o: $(UTILS_SRC)/xshm.h
 engine.o: $(UTILS_SRC)/yarandom.h
 engine.o: $(HACK_SRC)/xlockmoreI.h
 engine.o: $(HACK_SRC)/xlockmore.h
+erase-gl.o: ../../config.h
+erase-gl.o: $(UTILS_SRC)/erase.h
+erase-gl.o: $(UTILS_SRC)/utils.h
+esper.o: ../../config.h
+esper.o: $(HACK_SRC)/fps.h
+esper.o: $(srcdir)/grab-ximage.h
+esper.o: $(HACK_SRC)/screenhackI.h
+esper.o: $(srcdir)/texfont.h
+esper.o: $(UTILS_SRC)/colors.h
+esper.o: $(UTILS_SRC)/erase.h
+esper.o: $(UTILS_SRC)/grabscreen.h
+esper.o: $(UTILS_SRC)/hsv.h
+esper.o: $(UTILS_SRC)/resources.h
+esper.o: $(UTILS_SRC)/usleep.h
+esper.o: $(UTILS_SRC)/visual.h
+esper.o: $(UTILS_SRC)/xshm.h
+esper.o: $(UTILS_SRC)/yarandom.h
+esper.o: $(HACK_SRC)/xlockmoreI.h
+esper.o: $(HACK_SRC)/xlockmore.h
 extrusion-helix2.o: ../../config.h
 extrusion-helix2.o: $(srcdir)/extrusion.h
 extrusion-helix3.o: ../../config.h
@@ -1547,12 +1567,12 @@ extrusion.o: $(srcdir)/gltrackball.h
 extrusion.o: $(srcdir)/rotator.h
 extrusion.o: $(HACK_SRC)/screenhackI.h
 extrusion.o: $(UTILS_SRC)/colors.h
+extrusion.o: $(UTILS_SRC)/erase.h
 extrusion.o: $(UTILS_SRC)/grabscreen.h
 extrusion.o: $(UTILS_SRC)/hsv.h
 extrusion.o: $(UTILS_SRC)/resources.h
 extrusion.o: $(UTILS_SRC)/usleep.h
 extrusion.o: $(UTILS_SRC)/visual.h
-extrusion.o: $(UTILS_SRC)/xshm.h
 extrusion.o: $(UTILS_SRC)/yarandom.h
 extrusion.o: $(HACK_SRC)/xlockmoreI.h
 extrusion.o: $(HACK_SRC)/xlockmore.h
@@ -1569,12 +1589,12 @@ flipflop.o: $(srcdir)/gltrackball.h
 flipflop.o: $(srcdir)/grab-ximage.h
 flipflop.o: $(HACK_SRC)/screenhackI.h
 flipflop.o: $(UTILS_SRC)/colors.h
+flipflop.o: $(UTILS_SRC)/erase.h
 flipflop.o: $(UTILS_SRC)/grabscreen.h
 flipflop.o: $(UTILS_SRC)/hsv.h
 flipflop.o: $(UTILS_SRC)/resources.h
 flipflop.o: $(UTILS_SRC)/usleep.h
 flipflop.o: $(UTILS_SRC)/visual.h
-flipflop.o: $(UTILS_SRC)/xshm.h
 flipflop.o: $(UTILS_SRC)/yarandom.h
 flipflop.o: $(HACK_SRC)/xlockmoreI.h
 flipflop.o: $(HACK_SRC)/xlockmore.h
@@ -1584,12 +1604,12 @@ flipscreen3d.o: $(srcdir)/gltrackball.h
 flipscreen3d.o: $(srcdir)/grab-ximage.h
 flipscreen3d.o: $(HACK_SRC)/screenhackI.h
 flipscreen3d.o: $(UTILS_SRC)/colors.h
+flipscreen3d.o: $(UTILS_SRC)/erase.h
 flipscreen3d.o: $(UTILS_SRC)/grabscreen.h
 flipscreen3d.o: $(UTILS_SRC)/hsv.h
 flipscreen3d.o: $(UTILS_SRC)/resources.h
 flipscreen3d.o: $(UTILS_SRC)/usleep.h
 flipscreen3d.o: $(UTILS_SRC)/visual.h
-flipscreen3d.o: $(UTILS_SRC)/xshm.h
 flipscreen3d.o: $(UTILS_SRC)/yarandom.h
 flipscreen3d.o: $(HACK_SRC)/xlockmoreI.h
 flipscreen3d.o: $(HACK_SRC)/xlockmore.h
@@ -1598,13 +1618,13 @@ fliptext.o: $(HACK_SRC)/fps.h
 fliptext.o: $(HACK_SRC)/screenhackI.h
 fliptext.o: $(srcdir)/texfont.h
 fliptext.o: $(UTILS_SRC)/colors.h
+fliptext.o: $(UTILS_SRC)/erase.h
 fliptext.o: $(UTILS_SRC)/grabscreen.h
 fliptext.o: $(UTILS_SRC)/hsv.h
 fliptext.o: $(UTILS_SRC)/resources.h
 fliptext.o: $(UTILS_SRC)/textclient.h
 fliptext.o: $(UTILS_SRC)/usleep.h
 fliptext.o: $(UTILS_SRC)/visual.h
-fliptext.o: $(UTILS_SRC)/xshm.h
 fliptext.o: $(UTILS_SRC)/yarandom.h
 fliptext.o: $(HACK_SRC)/xlockmoreI.h
 fliptext.o: $(HACK_SRC)/xlockmore.h
@@ -1615,12 +1635,12 @@ flurry.o: $(srcdir)/gltrackball.h
 flurry.o: $(srcdir)/rotator.h
 flurry.o: $(HACK_SRC)/screenhackI.h
 flurry.o: $(UTILS_SRC)/colors.h
+flurry.o: $(UTILS_SRC)/erase.h
 flurry.o: $(UTILS_SRC)/grabscreen.h
 flurry.o: $(UTILS_SRC)/hsv.h
 flurry.o: $(UTILS_SRC)/resources.h
 flurry.o: $(UTILS_SRC)/usleep.h
 flurry.o: $(UTILS_SRC)/visual.h
-flurry.o: $(UTILS_SRC)/xshm.h
 flurry.o: $(UTILS_SRC)/yarandom.h
 flurry.o: $(HACK_SRC)/xlockmoreI.h
 flurry.o: $(HACK_SRC)/xlockmore.h
@@ -1652,12 +1672,12 @@ flyingtoasters.o: $(HACK_SRC)/images/chromesphere.xpm
 flyingtoasters.o: $(HACK_SRC)/images/toast.xpm
 flyingtoasters.o: $(HACK_SRC)/screenhackI.h
 flyingtoasters.o: $(UTILS_SRC)/colors.h
+flyingtoasters.o: $(UTILS_SRC)/erase.h
 flyingtoasters.o: $(UTILS_SRC)/grabscreen.h
 flyingtoasters.o: $(UTILS_SRC)/hsv.h
 flyingtoasters.o: $(UTILS_SRC)/resources.h
 flyingtoasters.o: $(UTILS_SRC)/usleep.h
 flyingtoasters.o: $(UTILS_SRC)/visual.h
-flyingtoasters.o: $(UTILS_SRC)/xshm.h
 flyingtoasters.o: $(UTILS_SRC)/yarandom.h
 flyingtoasters.o: $(HACK_SRC)/xlockmoreI.h
 flyingtoasters.o: $(HACK_SRC)/xlockmore.h
@@ -1668,12 +1688,12 @@ fps-gl.o: $(HACK_SRC)/fps.h
 fps-gl.o: $(HACK_SRC)/screenhackI.h
 fps-gl.o: $(srcdir)/texfont.h
 fps-gl.o: $(UTILS_SRC)/colors.h
+fps-gl.o: $(UTILS_SRC)/erase.h
 fps-gl.o: $(UTILS_SRC)/grabscreen.h
 fps-gl.o: $(UTILS_SRC)/hsv.h
 fps-gl.o: $(UTILS_SRC)/resources.h
 fps-gl.o: $(UTILS_SRC)/usleep.h
 fps-gl.o: $(UTILS_SRC)/visual.h
-fps-gl.o: $(UTILS_SRC)/xshm.h
 fps-gl.o: $(UTILS_SRC)/yarandom.h
 fps-gl.o: $(HACK_SRC)/xlockmoreI.h
 gears.o: ../../config.h
@@ -1685,12 +1705,12 @@ gears.o: $(srcdir)/rotator.h
 gears.o: $(HACK_SRC)/screenhackI.h
 gears.o: $(srcdir)/tube.h
 gears.o: $(UTILS_SRC)/colors.h
+gears.o: $(UTILS_SRC)/erase.h
 gears.o: $(UTILS_SRC)/grabscreen.h
 gears.o: $(UTILS_SRC)/hsv.h
 gears.o: $(UTILS_SRC)/resources.h
 gears.o: $(UTILS_SRC)/usleep.h
 gears.o: $(UTILS_SRC)/visual.h
-gears.o: $(UTILS_SRC)/xshm.h
 gears.o: $(UTILS_SRC)/yarandom.h
 gears.o: $(HACK_SRC)/xlockmoreI.h
 gears.o: $(HACK_SRC)/xlockmore.h
@@ -1704,12 +1724,12 @@ geodesicgears.o: $(srcdir)/rotator.h
 geodesicgears.o: $(HACK_SRC)/screenhackI.h
 geodesicgears.o: $(srcdir)/texfont.h
 geodesicgears.o: $(UTILS_SRC)/colors.h
+geodesicgears.o: $(UTILS_SRC)/erase.h
 geodesicgears.o: $(UTILS_SRC)/grabscreen.h
 geodesicgears.o: $(UTILS_SRC)/hsv.h
 geodesicgears.o: $(UTILS_SRC)/resources.h
 geodesicgears.o: $(UTILS_SRC)/usleep.h
 geodesicgears.o: $(UTILS_SRC)/visual.h
-geodesicgears.o: $(UTILS_SRC)/xshm.h
 geodesicgears.o: $(UTILS_SRC)/yarandom.h
 geodesicgears.o: $(HACK_SRC)/xlockmoreI.h
 geodesicgears.o: $(HACK_SRC)/xlockmore.h
@@ -1721,12 +1741,12 @@ geodesic.o: $(srcdir)/normals.h
 geodesic.o: $(srcdir)/rotator.h
 geodesic.o: $(HACK_SRC)/screenhackI.h
 geodesic.o: $(UTILS_SRC)/colors.h
+geodesic.o: $(UTILS_SRC)/erase.h
 geodesic.o: $(UTILS_SRC)/grabscreen.h
 geodesic.o: $(UTILS_SRC)/hsv.h
 geodesic.o: $(UTILS_SRC)/resources.h
 geodesic.o: $(UTILS_SRC)/usleep.h
 geodesic.o: $(UTILS_SRC)/visual.h
-geodesic.o: $(UTILS_SRC)/xshm.h
 geodesic.o: $(UTILS_SRC)/yarandom.h
 geodesic.o: $(HACK_SRC)/xlockmoreI.h
 geodesic.o: $(HACK_SRC)/xlockmore.h
@@ -1736,12 +1756,12 @@ gflux.o: $(srcdir)/gltrackball.h
 gflux.o: $(srcdir)/grab-ximage.h
 gflux.o: $(HACK_SRC)/screenhackI.h
 gflux.o: $(UTILS_SRC)/colors.h
+gflux.o: $(UTILS_SRC)/erase.h
 gflux.o: $(UTILS_SRC)/grabscreen.h
 gflux.o: $(UTILS_SRC)/hsv.h
 gflux.o: $(UTILS_SRC)/resources.h
 gflux.o: $(UTILS_SRC)/usleep.h
 gflux.o: $(UTILS_SRC)/visual.h
-gflux.o: $(UTILS_SRC)/xshm.h
 gflux.o: $(UTILS_SRC)/yarandom.h
 gflux.o: $(HACK_SRC)/xlockmoreI.h
 gflux.o: $(HACK_SRC)/xlockmore.h
@@ -1751,12 +1771,12 @@ glblur.o: $(srcdir)/gltrackball.h
 glblur.o: $(srcdir)/rotator.h
 glblur.o: $(HACK_SRC)/screenhackI.h
 glblur.o: $(UTILS_SRC)/colors.h
+glblur.o: $(UTILS_SRC)/erase.h
 glblur.o: $(UTILS_SRC)/grabscreen.h
 glblur.o: $(UTILS_SRC)/hsv.h
 glblur.o: $(UTILS_SRC)/resources.h
 glblur.o: $(UTILS_SRC)/usleep.h
 glblur.o: $(UTILS_SRC)/visual.h
-glblur.o: $(UTILS_SRC)/xshm.h
 glblur.o: $(UTILS_SRC)/yarandom.h
 glblur.o: $(HACK_SRC)/xlockmoreI.h
 glblur.o: $(HACK_SRC)/xlockmore.h
@@ -1764,12 +1784,12 @@ glcells.o: ../../config.h
 glcells.o: $(HACK_SRC)/fps.h
 glcells.o: $(HACK_SRC)/screenhackI.h
 glcells.o: $(UTILS_SRC)/colors.h
+glcells.o: $(UTILS_SRC)/erase.h
 glcells.o: $(UTILS_SRC)/grabscreen.h
 glcells.o: $(UTILS_SRC)/hsv.h
 glcells.o: $(UTILS_SRC)/resources.h
 glcells.o: $(UTILS_SRC)/usleep.h
 glcells.o: $(UTILS_SRC)/visual.h
-glcells.o: $(UTILS_SRC)/xshm.h
 glcells.o: $(UTILS_SRC)/yarandom.h
 glcells.o: $(HACK_SRC)/xlockmoreI.h
 glcells.o: $(HACK_SRC)/xlockmore.h
@@ -1778,12 +1798,12 @@ gleidescope.o: $(HACK_SRC)/fps.h
 gleidescope.o: $(srcdir)/grab-ximage.h
 gleidescope.o: $(HACK_SRC)/screenhackI.h
 gleidescope.o: $(UTILS_SRC)/colors.h
+gleidescope.o: $(UTILS_SRC)/erase.h
 gleidescope.o: $(UTILS_SRC)/grabscreen.h
 gleidescope.o: $(UTILS_SRC)/hsv.h
 gleidescope.o: $(UTILS_SRC)/resources.h
 gleidescope.o: $(UTILS_SRC)/usleep.h
 gleidescope.o: $(UTILS_SRC)/visual.h
-gleidescope.o: $(UTILS_SRC)/xshm.h
 gleidescope.o: $(UTILS_SRC)/yarandom.h
 gleidescope.o: $(HACK_SRC)/xlockmoreI.h
 gleidescope.o: $(HACK_SRC)/xlockmore.h
@@ -1795,12 +1815,12 @@ glforestfire.o: $(HACK_SRC)/images/ground.xpm
 glforestfire.o: $(HACK_SRC)/images/tree.xpm
 glforestfire.o: $(HACK_SRC)/screenhackI.h
 glforestfire.o: $(UTILS_SRC)/colors.h
+glforestfire.o: $(UTILS_SRC)/erase.h
 glforestfire.o: $(UTILS_SRC)/grabscreen.h
 glforestfire.o: $(UTILS_SRC)/hsv.h
 glforestfire.o: $(UTILS_SRC)/resources.h
 glforestfire.o: $(UTILS_SRC)/usleep.h
 glforestfire.o: $(UTILS_SRC)/visual.h
-glforestfire.o: $(UTILS_SRC)/xshm.h
 glforestfire.o: $(UTILS_SRC)/yarandom.h
 glforestfire.o: $(HACK_SRC)/xlockmoreI.h
 glforestfire.o: $(HACK_SRC)/xlockmore.h
@@ -1810,12 +1830,12 @@ glhanoi.o: $(HACK_SRC)/fps.h
 glhanoi.o: $(srcdir)/rotator.h
 glhanoi.o: $(HACK_SRC)/screenhackI.h
 glhanoi.o: $(UTILS_SRC)/colors.h
+glhanoi.o: $(UTILS_SRC)/erase.h
 glhanoi.o: $(UTILS_SRC)/grabscreen.h
 glhanoi.o: $(UTILS_SRC)/hsv.h
 glhanoi.o: $(UTILS_SRC)/resources.h
 glhanoi.o: $(UTILS_SRC)/usleep.h
 glhanoi.o: $(UTILS_SRC)/visual.h
-glhanoi.o: $(UTILS_SRC)/xshm.h
 glhanoi.o: $(UTILS_SRC)/yarandom.h
 glhanoi.o: $(HACK_SRC)/xlockmoreI.h
 glhanoi.o: $(HACK_SRC)/xlockmore.h
@@ -1826,12 +1846,12 @@ glknots.o: $(srcdir)/rotator.h
 glknots.o: $(HACK_SRC)/screenhackI.h
 glknots.o: $(srcdir)/tube.h
 glknots.o: $(UTILS_SRC)/colors.h
+glknots.o: $(UTILS_SRC)/erase.h
 glknots.o: $(UTILS_SRC)/grabscreen.h
 glknots.o: $(UTILS_SRC)/hsv.h
 glknots.o: $(UTILS_SRC)/resources.h
 glknots.o: $(UTILS_SRC)/usleep.h
 glknots.o: $(UTILS_SRC)/visual.h
-glknots.o: $(UTILS_SRC)/xshm.h
 glknots.o: $(UTILS_SRC)/yarandom.h
 glknots.o: $(HACK_SRC)/xlockmoreI.h
 glknots.o: $(HACK_SRC)/xlockmore.h
@@ -1842,12 +1862,12 @@ glmatrix.o: $(HACK_SRC)/fps.h
 glmatrix.o: $(HACK_SRC)/images/matrix3.xpm
 glmatrix.o: $(HACK_SRC)/screenhackI.h
 glmatrix.o: $(UTILS_SRC)/colors.h
+glmatrix.o: $(UTILS_SRC)/erase.h
 glmatrix.o: $(UTILS_SRC)/grabscreen.h
 glmatrix.o: $(UTILS_SRC)/hsv.h
 glmatrix.o: $(UTILS_SRC)/resources.h
 glmatrix.o: $(UTILS_SRC)/usleep.h
 glmatrix.o: $(UTILS_SRC)/visual.h
-glmatrix.o: $(UTILS_SRC)/xshm.h
 glmatrix.o: $(UTILS_SRC)/yarandom.h
 glmatrix.o: $(HACK_SRC)/xlockmoreI.h
 glmatrix.o: $(HACK_SRC)/xlockmore.h
@@ -1861,12 +1881,12 @@ glplanet.o: $(srcdir)/rotator.h
 glplanet.o: $(HACK_SRC)/screenhackI.h
 glplanet.o: $(srcdir)/sphere.h
 glplanet.o: $(UTILS_SRC)/colors.h
+glplanet.o: $(UTILS_SRC)/erase.h
 glplanet.o: $(UTILS_SRC)/grabscreen.h
 glplanet.o: $(UTILS_SRC)/hsv.h
 glplanet.o: $(UTILS_SRC)/resources.h
 glplanet.o: $(UTILS_SRC)/usleep.h
 glplanet.o: $(UTILS_SRC)/visual.h
-glplanet.o: $(UTILS_SRC)/xshm.h
 glplanet.o: $(UTILS_SRC)/yarandom.h
 glplanet.o: $(HACK_SRC)/xlockmoreI.h
 glplanet.o: $(HACK_SRC)/xlockmore.h
@@ -1886,12 +1906,12 @@ glschool.o: $(srcdir)/glschool_gl.h
 glschool.o: $(srcdir)/glschool.h
 glschool.o: $(HACK_SRC)/screenhackI.h
 glschool.o: $(UTILS_SRC)/colors.h
+glschool.o: $(UTILS_SRC)/erase.h
 glschool.o: $(UTILS_SRC)/grabscreen.h
 glschool.o: $(UTILS_SRC)/hsv.h
 glschool.o: $(UTILS_SRC)/resources.h
 glschool.o: $(UTILS_SRC)/usleep.h
 glschool.o: $(UTILS_SRC)/visual.h
-glschool.o: $(UTILS_SRC)/xshm.h
 glschool.o: $(UTILS_SRC)/yarandom.h
 glschool.o: $(HACK_SRC)/xlockmoreI.h
 glschool.o: $(HACK_SRC)/xlockmore.h
@@ -1901,12 +1921,12 @@ glslideshow.o: $(srcdir)/grab-ximage.h
 glslideshow.o: $(HACK_SRC)/screenhackI.h
 glslideshow.o: $(srcdir)/texfont.h
 glslideshow.o: $(UTILS_SRC)/colors.h
+glslideshow.o: $(UTILS_SRC)/erase.h
 glslideshow.o: $(UTILS_SRC)/grabscreen.h
 glslideshow.o: $(UTILS_SRC)/hsv.h
 glslideshow.o: $(UTILS_SRC)/resources.h
 glslideshow.o: $(UTILS_SRC)/usleep.h
 glslideshow.o: $(UTILS_SRC)/visual.h
-glslideshow.o: $(UTILS_SRC)/xshm.h
 glslideshow.o: $(UTILS_SRC)/yarandom.h
 glslideshow.o: $(HACK_SRC)/xlockmoreI.h
 glslideshow.o: $(HACK_SRC)/xlockmore.h
@@ -1915,18 +1935,19 @@ glsnake.o: $(HACK_SRC)/fps.h
 glsnake.o: $(HACK_SRC)/screenhackI.h
 glsnake.o: $(srcdir)/texfont.h
 glsnake.o: $(UTILS_SRC)/colors.h
+glsnake.o: $(UTILS_SRC)/erase.h
 glsnake.o: $(UTILS_SRC)/grabscreen.h
 glsnake.o: $(UTILS_SRC)/hsv.h
 glsnake.o: $(UTILS_SRC)/resources.h
 glsnake.o: $(UTILS_SRC)/usleep.h
 glsnake.o: $(UTILS_SRC)/visual.h
-glsnake.o: $(UTILS_SRC)/xshm.h
 glsnake.o: $(UTILS_SRC)/yarandom.h
 glsnake.o: $(HACK_SRC)/xlockmoreI.h
 glsnake.o: $(HACK_SRC)/xlockmore.h
 gltext.o: ../../config.h
 gltext.o: $(HACK_SRC)/fps.h
 gltext.o: $(srcdir)/gltrackball.h
+gltext.o: $(srcdir)/glut_mroman.h
 gltext.o: $(srcdir)/glut_roman.h
 gltext.o: $(srcdir)/glutstroke.h
 gltext.o: $(srcdir)/rotator.h
@@ -1934,6 +1955,7 @@ gltext.o: $(HACK_SRC)/screenhackI.h
 gltext.o: $(srcdir)/sphere.h
 gltext.o: $(srcdir)/tube.h
 gltext.o: $(UTILS_SRC)/colors.h
+gltext.o: $(UTILS_SRC)/erase.h
 gltext.o: $(UTILS_SRC)/grabscreen.h
 gltext.o: $(UTILS_SRC)/hsv.h
 gltext.o: $(UTILS_SRC)/resources.h
@@ -1941,7 +1963,6 @@ gltext.o: $(UTILS_SRC)/textclient.h
 gltext.o: $(UTILS_SRC)/usleep.h
 gltext.o: $(UTILS_SRC)/utf8wc.h
 gltext.o: $(UTILS_SRC)/visual.h
-gltext.o: $(UTILS_SRC)/xshm.h
 gltext.o: $(UTILS_SRC)/yarandom.h
 gltext.o: $(HACK_SRC)/xlockmoreI.h
 gltext.o: $(HACK_SRC)/xlockmore.h
@@ -1965,12 +1986,12 @@ hexstrut.o: $(srcdir)/normals.h
 hexstrut.o: $(srcdir)/rotator.h
 hexstrut.o: $(HACK_SRC)/screenhackI.h
 hexstrut.o: $(UTILS_SRC)/colors.h
+hexstrut.o: $(UTILS_SRC)/erase.h
 hexstrut.o: $(UTILS_SRC)/grabscreen.h
 hexstrut.o: $(UTILS_SRC)/hsv.h
 hexstrut.o: $(UTILS_SRC)/resources.h
 hexstrut.o: $(UTILS_SRC)/usleep.h
 hexstrut.o: $(UTILS_SRC)/visual.h
-hexstrut.o: $(UTILS_SRC)/xshm.h
 hexstrut.o: $(UTILS_SRC)/yarandom.h
 hexstrut.o: $(HACK_SRC)/xlockmoreI.h
 hexstrut.o: $(HACK_SRC)/xlockmore.h
@@ -1982,12 +2003,12 @@ hilbert.o: $(HACK_SRC)/screenhackI.h
 hilbert.o: $(srcdir)/sphere.h
 hilbert.o: $(srcdir)/tube.h
 hilbert.o: $(UTILS_SRC)/colors.h
+hilbert.o: $(UTILS_SRC)/erase.h
 hilbert.o: $(UTILS_SRC)/grabscreen.h
 hilbert.o: $(UTILS_SRC)/hsv.h
 hilbert.o: $(UTILS_SRC)/resources.h
 hilbert.o: $(UTILS_SRC)/usleep.h
 hilbert.o: $(UTILS_SRC)/visual.h
-hilbert.o: $(UTILS_SRC)/xshm.h
 hilbert.o: $(UTILS_SRC)/yarandom.h
 hilbert.o: $(HACK_SRC)/xlockmoreI.h
 hilbert.o: $(HACK_SRC)/xlockmore.h
@@ -1998,12 +2019,12 @@ hydrostat.o: $(srcdir)/normals.h
 hydrostat.o: $(HACK_SRC)/screenhackI.h
 hydrostat.o: $(srcdir)/sphere.h
 hydrostat.o: $(UTILS_SRC)/colors.h
+hydrostat.o: $(UTILS_SRC)/erase.h
 hydrostat.o: $(UTILS_SRC)/grabscreen.h
 hydrostat.o: $(UTILS_SRC)/hsv.h
 hydrostat.o: $(UTILS_SRC)/resources.h
 hydrostat.o: $(UTILS_SRC)/usleep.h
 hydrostat.o: $(UTILS_SRC)/visual.h
-hydrostat.o: $(UTILS_SRC)/xshm.h
 hydrostat.o: $(UTILS_SRC)/yarandom.h
 hydrostat.o: $(HACK_SRC)/xlockmoreI.h
 hydrostat.o: $(HACK_SRC)/xlockmore.h
@@ -2012,12 +2033,12 @@ hypertorus.o: $(HACK_SRC)/fps.h
 hypertorus.o: $(srcdir)/gltrackball.h
 hypertorus.o: $(HACK_SRC)/screenhackI.h
 hypertorus.o: $(UTILS_SRC)/colors.h
+hypertorus.o: $(UTILS_SRC)/erase.h
 hypertorus.o: $(UTILS_SRC)/grabscreen.h
 hypertorus.o: $(UTILS_SRC)/hsv.h
 hypertorus.o: $(UTILS_SRC)/resources.h
 hypertorus.o: $(UTILS_SRC)/usleep.h
 hypertorus.o: $(UTILS_SRC)/visual.h
-hypertorus.o: $(UTILS_SRC)/xshm.h
 hypertorus.o: $(UTILS_SRC)/yarandom.h
 hypertorus.o: $(HACK_SRC)/xlockmoreI.h
 hypertorus.o: $(HACK_SRC)/xlockmore.h
@@ -2026,12 +2047,12 @@ hypnowheel.o: $(HACK_SRC)/fps.h
 hypnowheel.o: $(srcdir)/rotator.h
 hypnowheel.o: $(HACK_SRC)/screenhackI.h
 hypnowheel.o: $(UTILS_SRC)/colors.h
+hypnowheel.o: $(UTILS_SRC)/erase.h
 hypnowheel.o: $(UTILS_SRC)/grabscreen.h
 hypnowheel.o: $(UTILS_SRC)/hsv.h
 hypnowheel.o: $(UTILS_SRC)/resources.h
 hypnowheel.o: $(UTILS_SRC)/usleep.h
 hypnowheel.o: $(UTILS_SRC)/visual.h
-hypnowheel.o: $(UTILS_SRC)/xshm.h
 hypnowheel.o: $(UTILS_SRC)/yarandom.h
 hypnowheel.o: $(HACK_SRC)/xlockmoreI.h
 hypnowheel.o: $(HACK_SRC)/xlockmore.h
@@ -2053,12 +2074,12 @@ jigglypuff.o: $(srcdir)/gltrackball.h
 jigglypuff.o: $(HACK_SRC)/images/jigglymap.xpm
 jigglypuff.o: $(HACK_SRC)/screenhackI.h
 jigglypuff.o: $(UTILS_SRC)/colors.h
+jigglypuff.o: $(UTILS_SRC)/erase.h
 jigglypuff.o: $(UTILS_SRC)/grabscreen.h
 jigglypuff.o: $(UTILS_SRC)/hsv.h
 jigglypuff.o: $(UTILS_SRC)/resources.h
 jigglypuff.o: $(UTILS_SRC)/usleep.h
 jigglypuff.o: $(UTILS_SRC)/visual.h
-jigglypuff.o: $(UTILS_SRC)/xshm.h
 jigglypuff.o: $(UTILS_SRC)/yarandom.h
 jigglypuff.o: $(HACK_SRC)/xlockmoreI.h
 jigglypuff.o: $(HACK_SRC)/xlockmore.h
@@ -2072,13 +2093,13 @@ jigsaw.o: $(srcdir)/rotator.h
 jigsaw.o: $(HACK_SRC)/screenhackI.h
 jigsaw.o: $(srcdir)/texfont.h
 jigsaw.o: $(UTILS_SRC)/colors.h
+jigsaw.o: $(UTILS_SRC)/erase.h
 jigsaw.o: $(UTILS_SRC)/grabscreen.h
 jigsaw.o: $(UTILS_SRC)/hsv.h
 jigsaw.o: $(UTILS_SRC)/resources.h
 jigsaw.o: $(UTILS_SRC)/spline.h
 jigsaw.o: $(UTILS_SRC)/usleep.h
 jigsaw.o: $(UTILS_SRC)/visual.h
-jigsaw.o: $(UTILS_SRC)/xshm.h
 jigsaw.o: $(UTILS_SRC)/yarandom.h
 jigsaw.o: $(HACK_SRC)/xlockmoreI.h
 jigsaw.o: $(HACK_SRC)/xlockmore.h
@@ -2091,12 +2112,12 @@ juggler3d.o: $(srcdir)/sphere.h
 juggler3d.o: $(srcdir)/texfont.h
 juggler3d.o: $(srcdir)/tube.h
 juggler3d.o: $(UTILS_SRC)/colors.h
+juggler3d.o: $(UTILS_SRC)/erase.h
 juggler3d.o: $(UTILS_SRC)/grabscreen.h
 juggler3d.o: $(UTILS_SRC)/hsv.h
 juggler3d.o: $(UTILS_SRC)/resources.h
 juggler3d.o: $(UTILS_SRC)/usleep.h
 juggler3d.o: $(UTILS_SRC)/visual.h
-juggler3d.o: $(UTILS_SRC)/xshm.h
 juggler3d.o: $(UTILS_SRC)/yarandom.h
 juggler3d.o: $(HACK_SRC)/xlockmoreI.h
 juggler3d.o: $(HACK_SRC)/xlockmore.h
@@ -2107,12 +2128,12 @@ kaleidocycle.o: $(srcdir)/normals.h
 kaleidocycle.o: $(srcdir)/rotator.h
 kaleidocycle.o: $(HACK_SRC)/screenhackI.h
 kaleidocycle.o: $(UTILS_SRC)/colors.h
+kaleidocycle.o: $(UTILS_SRC)/erase.h
 kaleidocycle.o: $(UTILS_SRC)/grabscreen.h
 kaleidocycle.o: $(UTILS_SRC)/hsv.h
 kaleidocycle.o: $(UTILS_SRC)/resources.h
 kaleidocycle.o: $(UTILS_SRC)/usleep.h
 kaleidocycle.o: $(UTILS_SRC)/visual.h
-kaleidocycle.o: $(UTILS_SRC)/xshm.h
 kaleidocycle.o: $(UTILS_SRC)/yarandom.h
 kaleidocycle.o: $(HACK_SRC)/xlockmoreI.h
 kaleidocycle.o: $(HACK_SRC)/xlockmore.h
@@ -2122,12 +2143,12 @@ klein.o: $(HACK_SRC)/fps.h
 klein.o: $(srcdir)/gltrackball.h
 klein.o: $(HACK_SRC)/screenhackI.h
 klein.o: $(UTILS_SRC)/colors.h
+klein.o: $(UTILS_SRC)/erase.h
 klein.o: $(UTILS_SRC)/grabscreen.h
 klein.o: $(UTILS_SRC)/hsv.h
 klein.o: $(UTILS_SRC)/resources.h
 klein.o: $(UTILS_SRC)/usleep.h
 klein.o: $(UTILS_SRC)/visual.h
-klein.o: $(UTILS_SRC)/xshm.h
 klein.o: $(UTILS_SRC)/yarandom.h
 klein.o: $(HACK_SRC)/xlockmoreI.h
 klein.o: $(HACK_SRC)/xlockmore.h
@@ -2142,12 +2163,12 @@ lament.o: $(srcdir)/normals.h
 lament.o: $(srcdir)/rotator.h
 lament.o: $(HACK_SRC)/screenhackI.h
 lament.o: $(UTILS_SRC)/colors.h
+lament.o: $(UTILS_SRC)/erase.h
 lament.o: $(UTILS_SRC)/grabscreen.h
 lament.o: $(UTILS_SRC)/hsv.h
 lament.o: $(UTILS_SRC)/resources.h
 lament.o: $(UTILS_SRC)/usleep.h
 lament.o: $(UTILS_SRC)/visual.h
-lament.o: $(UTILS_SRC)/xshm.h
 lament.o: $(UTILS_SRC)/yarandom.h
 lament.o: $(HACK_SRC)/xlockmoreI.h
 lament.o: $(HACK_SRC)/xlockmore.h
@@ -2159,12 +2180,12 @@ lavalite.o: $(srcdir)/marching.h
 lavalite.o: $(srcdir)/rotator.h
 lavalite.o: $(HACK_SRC)/screenhackI.h
 lavalite.o: $(UTILS_SRC)/colors.h
+lavalite.o: $(UTILS_SRC)/erase.h
 lavalite.o: $(UTILS_SRC)/grabscreen.h
 lavalite.o: $(UTILS_SRC)/hsv.h
 lavalite.o: $(UTILS_SRC)/resources.h
 lavalite.o: $(UTILS_SRC)/usleep.h
 lavalite.o: $(UTILS_SRC)/visual.h
-lavalite.o: $(UTILS_SRC)/xshm.h
 lavalite.o: $(UTILS_SRC)/yarandom.h
 lavalite.o: $(HACK_SRC)/xlockmoreI.h
 lavalite.o: $(HACK_SRC)/xlockmore.h
@@ -2173,12 +2194,12 @@ lockward.o: ../../config.h
 lockward.o: $(HACK_SRC)/fps.h
 lockward.o: $(HACK_SRC)/screenhackI.h
 lockward.o: $(UTILS_SRC)/colors.h
+lockward.o: $(UTILS_SRC)/erase.h
 lockward.o: $(UTILS_SRC)/grabscreen.h
 lockward.o: $(UTILS_SRC)/hsv.h
 lockward.o: $(UTILS_SRC)/resources.h
 lockward.o: $(UTILS_SRC)/usleep.h
 lockward.o: $(UTILS_SRC)/visual.h
-lockward.o: $(UTILS_SRC)/xshm.h
 lockward.o: $(UTILS_SRC)/yarandom.h
 lockward.o: $(HACK_SRC)/xlockmoreI.h
 lockward.o: $(HACK_SRC)/xlockmore.h
@@ -2191,12 +2212,12 @@ menger.o: $(srcdir)/gltrackball.h
 menger.o: $(srcdir)/rotator.h
 menger.o: $(HACK_SRC)/screenhackI.h
 menger.o: $(UTILS_SRC)/colors.h
+menger.o: $(UTILS_SRC)/erase.h
 menger.o: $(UTILS_SRC)/grabscreen.h
 menger.o: $(UTILS_SRC)/hsv.h
 menger.o: $(UTILS_SRC)/resources.h
 menger.o: $(UTILS_SRC)/usleep.h
 menger.o: $(UTILS_SRC)/visual.h
-menger.o: $(UTILS_SRC)/xshm.h
 menger.o: $(UTILS_SRC)/yarandom.h
 menger.o: $(HACK_SRC)/xlockmoreI.h
 menger.o: $(HACK_SRC)/xlockmore.h
@@ -2206,12 +2227,12 @@ mirrorblob.o: $(srcdir)/gltrackball.h
 mirrorblob.o: $(srcdir)/grab-ximage.h
 mirrorblob.o: $(HACK_SRC)/screenhackI.h
 mirrorblob.o: $(UTILS_SRC)/colors.h
+mirrorblob.o: $(UTILS_SRC)/erase.h
 mirrorblob.o: $(UTILS_SRC)/grabscreen.h
 mirrorblob.o: $(UTILS_SRC)/hsv.h
 mirrorblob.o: $(UTILS_SRC)/resources.h
 mirrorblob.o: $(UTILS_SRC)/usleep.h
 mirrorblob.o: $(UTILS_SRC)/visual.h
-mirrorblob.o: $(UTILS_SRC)/xshm.h
 mirrorblob.o: $(UTILS_SRC)/yarandom.h
 mirrorblob.o: $(HACK_SRC)/xlockmoreI.h
 mirrorblob.o: $(HACK_SRC)/xlockmore.h
@@ -2223,12 +2244,12 @@ moebiusgears.o: $(srcdir)/normals.h
 moebiusgears.o: $(srcdir)/rotator.h
 moebiusgears.o: $(HACK_SRC)/screenhackI.h
 moebiusgears.o: $(UTILS_SRC)/colors.h
+moebiusgears.o: $(UTILS_SRC)/erase.h
 moebiusgears.o: $(UTILS_SRC)/grabscreen.h
 moebiusgears.o: $(UTILS_SRC)/hsv.h
 moebiusgears.o: $(UTILS_SRC)/resources.h
 moebiusgears.o: $(UTILS_SRC)/usleep.h
 moebiusgears.o: $(UTILS_SRC)/visual.h
-moebiusgears.o: $(UTILS_SRC)/xshm.h
 moebiusgears.o: $(UTILS_SRC)/yarandom.h
 moebiusgears.o: $(HACK_SRC)/xlockmoreI.h
 moebiusgears.o: $(HACK_SRC)/xlockmore.h
@@ -2240,12 +2261,12 @@ moebius.o: $(HACK_SRC)/screenhackI.h
 moebius.o: $(srcdir)/sphere.h
 moebius.o: $(srcdir)/tube.h
 moebius.o: $(UTILS_SRC)/colors.h
+moebius.o: $(UTILS_SRC)/erase.h
 moebius.o: $(UTILS_SRC)/grabscreen.h
 moebius.o: $(UTILS_SRC)/hsv.h
 moebius.o: $(UTILS_SRC)/resources.h
 moebius.o: $(UTILS_SRC)/usleep.h
 moebius.o: $(UTILS_SRC)/visual.h
-moebius.o: $(UTILS_SRC)/xshm.h
 moebius.o: $(UTILS_SRC)/yarandom.h
 moebius.o: $(HACK_SRC)/xlockmoreI.h
 moebius.o: $(HACK_SRC)/xlockmore.h
@@ -2259,12 +2280,12 @@ molecule.o: $(srcdir)/sphere.h
 molecule.o: $(srcdir)/texfont.h
 molecule.o: $(srcdir)/tube.h
 molecule.o: $(UTILS_SRC)/colors.h
+molecule.o: $(UTILS_SRC)/erase.h
 molecule.o: $(UTILS_SRC)/grabscreen.h
 molecule.o: $(UTILS_SRC)/hsv.h
 molecule.o: $(UTILS_SRC)/resources.h
 molecule.o: $(UTILS_SRC)/usleep.h
 molecule.o: $(UTILS_SRC)/visual.h
-molecule.o: $(UTILS_SRC)/xshm.h
 molecule.o: $(UTILS_SRC)/yarandom.h
 molecule.o: $(HACK_SRC)/xlockmoreI.h
 molecule.o: $(HACK_SRC)/xlockmore.h
@@ -2272,12 +2293,12 @@ morph3d.o: ../../config.h
 morph3d.o: $(HACK_SRC)/fps.h
 morph3d.o: $(HACK_SRC)/screenhackI.h
 morph3d.o: $(UTILS_SRC)/colors.h
+morph3d.o: $(UTILS_SRC)/erase.h
 morph3d.o: $(UTILS_SRC)/grabscreen.h
 morph3d.o: $(UTILS_SRC)/hsv.h
 morph3d.o: $(UTILS_SRC)/resources.h
 morph3d.o: $(UTILS_SRC)/usleep.h
 morph3d.o: $(UTILS_SRC)/visual.h
-morph3d.o: $(UTILS_SRC)/xshm.h
 morph3d.o: $(UTILS_SRC)/yarandom.h
 morph3d.o: $(HACK_SRC)/xlockmoreI.h
 morph3d.o: $(HACK_SRC)/xlockmore.h
@@ -2285,12 +2306,12 @@ noof.o: ../../config.h
 noof.o: $(HACK_SRC)/fps.h
 noof.o: $(HACK_SRC)/screenhackI.h
 noof.o: $(UTILS_SRC)/colors.h
+noof.o: $(UTILS_SRC)/erase.h
 noof.o: $(UTILS_SRC)/grabscreen.h
 noof.o: $(UTILS_SRC)/hsv.h
 noof.o: $(UTILS_SRC)/resources.h
 noof.o: $(UTILS_SRC)/usleep.h
 noof.o: $(UTILS_SRC)/visual.h
-noof.o: $(UTILS_SRC)/xshm.h
 noof.o: $(UTILS_SRC)/yarandom.h
 noof.o: $(HACK_SRC)/xlockmoreI.h
 noof.o: $(HACK_SRC)/xlockmore.h
@@ -2303,12 +2324,12 @@ photopile.o: $(srcdir)/grab-ximage.h
 photopile.o: $(HACK_SRC)/screenhackI.h
 photopile.o: $(srcdir)/texfont.h
 photopile.o: $(UTILS_SRC)/colors.h
+photopile.o: $(UTILS_SRC)/erase.h
 photopile.o: $(UTILS_SRC)/grabscreen.h
 photopile.o: $(UTILS_SRC)/hsv.h
 photopile.o: $(UTILS_SRC)/resources.h
 photopile.o: $(UTILS_SRC)/usleep.h
 photopile.o: $(UTILS_SRC)/visual.h
-photopile.o: $(UTILS_SRC)/xshm.h
 photopile.o: $(UTILS_SRC)/yarandom.h
 photopile.o: $(HACK_SRC)/xlockmoreI.h
 photopile.o: $(HACK_SRC)/xlockmore.h
@@ -2320,12 +2341,12 @@ pinion.o: $(srcdir)/normals.h
 pinion.o: $(HACK_SRC)/screenhackI.h
 pinion.o: $(srcdir)/texfont.h
 pinion.o: $(UTILS_SRC)/colors.h
+pinion.o: $(UTILS_SRC)/erase.h
 pinion.o: $(UTILS_SRC)/grabscreen.h
 pinion.o: $(UTILS_SRC)/hsv.h
 pinion.o: $(UTILS_SRC)/resources.h
 pinion.o: $(UTILS_SRC)/usleep.h
 pinion.o: $(UTILS_SRC)/visual.h
-pinion.o: $(UTILS_SRC)/xshm.h
 pinion.o: $(UTILS_SRC)/yarandom.h
 pinion.o: $(HACK_SRC)/xlockmoreI.h
 pinion.o: $(HACK_SRC)/xlockmore.h
@@ -2339,12 +2360,12 @@ pipes.o: $(HACK_SRC)/screenhackI.h
 pipes.o: $(srcdir)/sphere.h
 pipes.o: $(srcdir)/teapot.h
 pipes.o: $(UTILS_SRC)/colors.h
+pipes.o: $(UTILS_SRC)/erase.h
 pipes.o: $(UTILS_SRC)/grabscreen.h
 pipes.o: $(UTILS_SRC)/hsv.h
 pipes.o: $(UTILS_SRC)/resources.h
 pipes.o: $(UTILS_SRC)/usleep.h
 pipes.o: $(UTILS_SRC)/visual.h
-pipes.o: $(UTILS_SRC)/xshm.h
 pipes.o: $(UTILS_SRC)/yarandom.h
 pipes.o: $(HACK_SRC)/xlockmoreI.h
 pipes.o: $(HACK_SRC)/xlockmore.h
@@ -2358,12 +2379,12 @@ polyhedra-gl.o: $(HACK_SRC)/screenhackI.h
 polyhedra-gl.o: $(srcdir)/teapot.h
 polyhedra-gl.o: $(srcdir)/texfont.h
 polyhedra-gl.o: $(UTILS_SRC)/colors.h
+polyhedra-gl.o: $(UTILS_SRC)/erase.h
 polyhedra-gl.o: $(UTILS_SRC)/grabscreen.h
 polyhedra-gl.o: $(UTILS_SRC)/hsv.h
 polyhedra-gl.o: $(UTILS_SRC)/resources.h
 polyhedra-gl.o: $(UTILS_SRC)/usleep.h
 polyhedra-gl.o: $(UTILS_SRC)/visual.h
-polyhedra-gl.o: $(UTILS_SRC)/xshm.h
 polyhedra-gl.o: $(UTILS_SRC)/yarandom.h
 polyhedra-gl.o: $(HACK_SRC)/xlockmoreI.h
 polyhedra-gl.o: $(HACK_SRC)/xlockmore.h
@@ -2374,12 +2395,12 @@ polytopes.o: $(HACK_SRC)/fps.h
 polytopes.o: $(srcdir)/gltrackball.h
 polytopes.o: $(HACK_SRC)/screenhackI.h
 polytopes.o: $(UTILS_SRC)/colors.h
+polytopes.o: $(UTILS_SRC)/erase.h
 polytopes.o: $(UTILS_SRC)/grabscreen.h
 polytopes.o: $(UTILS_SRC)/hsv.h
 polytopes.o: $(UTILS_SRC)/resources.h
 polytopes.o: $(UTILS_SRC)/usleep.h
 polytopes.o: $(UTILS_SRC)/visual.h
-polytopes.o: $(UTILS_SRC)/xshm.h
 polytopes.o: $(UTILS_SRC)/yarandom.h
 polytopes.o: $(HACK_SRC)/xlockmoreI.h
 polytopes.o: $(HACK_SRC)/xlockmore.h
@@ -2389,12 +2410,12 @@ projectiveplane.o: $(HACK_SRC)/fps.h
 projectiveplane.o: $(srcdir)/gltrackball.h
 projectiveplane.o: $(HACK_SRC)/screenhackI.h
 projectiveplane.o: $(UTILS_SRC)/colors.h
+projectiveplane.o: $(UTILS_SRC)/erase.h
 projectiveplane.o: $(UTILS_SRC)/grabscreen.h
 projectiveplane.o: $(UTILS_SRC)/hsv.h
 projectiveplane.o: $(UTILS_SRC)/resources.h
 projectiveplane.o: $(UTILS_SRC)/usleep.h
 projectiveplane.o: $(UTILS_SRC)/visual.h
-projectiveplane.o: $(UTILS_SRC)/xshm.h
 projectiveplane.o: $(UTILS_SRC)/yarandom.h
 projectiveplane.o: $(HACK_SRC)/xlockmoreI.h
 projectiveplane.o: $(HACK_SRC)/xlockmore.h
@@ -2403,12 +2424,12 @@ providence.o: $(HACK_SRC)/fps.h
 providence.o: $(srcdir)/gltrackball.h
 providence.o: $(HACK_SRC)/screenhackI.h
 providence.o: $(UTILS_SRC)/colors.h
+providence.o: $(UTILS_SRC)/erase.h
 providence.o: $(UTILS_SRC)/grabscreen.h
 providence.o: $(UTILS_SRC)/hsv.h
 providence.o: $(UTILS_SRC)/resources.h
 providence.o: $(UTILS_SRC)/usleep.h
 providence.o: $(UTILS_SRC)/visual.h
-providence.o: $(UTILS_SRC)/xshm.h
 providence.o: $(UTILS_SRC)/yarandom.h
 providence.o: $(HACK_SRC)/xlockmoreI.h
 providence.o: $(HACK_SRC)/xlockmore.h
@@ -2416,12 +2437,12 @@ pulsar.o: ../../config.h
 pulsar.o: $(HACK_SRC)/fps.h
 pulsar.o: $(HACK_SRC)/screenhackI.h
 pulsar.o: $(UTILS_SRC)/colors.h
+pulsar.o: $(UTILS_SRC)/erase.h
 pulsar.o: $(UTILS_SRC)/grabscreen.h
 pulsar.o: $(UTILS_SRC)/hsv.h
 pulsar.o: $(UTILS_SRC)/resources.h
 pulsar.o: $(UTILS_SRC)/usleep.h
 pulsar.o: $(UTILS_SRC)/visual.h
-pulsar.o: $(UTILS_SRC)/xshm.h
 pulsar.o: $(UTILS_SRC)/yarandom.h
 pulsar.o: $(HACK_SRC)/xlockmoreI.h
 pulsar.o: $(HACK_SRC)/xlockmore.h
@@ -2431,12 +2452,12 @@ quasicrystal.o: $(HACK_SRC)/fps.h
 quasicrystal.o: $(srcdir)/rotator.h
 quasicrystal.o: $(HACK_SRC)/screenhackI.h
 quasicrystal.o: $(UTILS_SRC)/colors.h
+quasicrystal.o: $(UTILS_SRC)/erase.h
 quasicrystal.o: $(UTILS_SRC)/grabscreen.h
 quasicrystal.o: $(UTILS_SRC)/hsv.h
 quasicrystal.o: $(UTILS_SRC)/resources.h
 quasicrystal.o: $(UTILS_SRC)/usleep.h
 quasicrystal.o: $(UTILS_SRC)/visual.h
-quasicrystal.o: $(UTILS_SRC)/xshm.h
 quasicrystal.o: $(UTILS_SRC)/yarandom.h
 quasicrystal.o: $(HACK_SRC)/xlockmoreI.h
 quasicrystal.o: $(HACK_SRC)/xlockmore.h
@@ -2446,12 +2467,12 @@ queens.o: $(HACK_SRC)/fps.h
 queens.o: $(srcdir)/gltrackball.h
 queens.o: $(HACK_SRC)/screenhackI.h
 queens.o: $(UTILS_SRC)/colors.h
+queens.o: $(UTILS_SRC)/erase.h
 queens.o: $(UTILS_SRC)/grabscreen.h
 queens.o: $(UTILS_SRC)/hsv.h
 queens.o: $(UTILS_SRC)/resources.h
 queens.o: $(UTILS_SRC)/usleep.h
 queens.o: $(UTILS_SRC)/visual.h
-queens.o: $(UTILS_SRC)/xshm.h
 queens.o: $(UTILS_SRC)/yarandom.h
 queens.o: $(HACK_SRC)/xlockmoreI.h
 queens.o: $(HACK_SRC)/xlockmore.h
@@ -2461,12 +2482,12 @@ raverhoop.o: $(srcdir)/gltrackball.h
 raverhoop.o: $(srcdir)/rotator.h
 raverhoop.o: $(HACK_SRC)/screenhackI.h
 raverhoop.o: $(UTILS_SRC)/colors.h
+raverhoop.o: $(UTILS_SRC)/erase.h
 raverhoop.o: $(UTILS_SRC)/grabscreen.h
 raverhoop.o: $(UTILS_SRC)/hsv.h
 raverhoop.o: $(UTILS_SRC)/resources.h
 raverhoop.o: $(UTILS_SRC)/usleep.h
 raverhoop.o: $(UTILS_SRC)/visual.h
-raverhoop.o: $(UTILS_SRC)/xshm.h
 raverhoop.o: $(UTILS_SRC)/yarandom.h
 raverhoop.o: $(HACK_SRC)/xlockmoreI.h
 raverhoop.o: $(HACK_SRC)/xlockmore.h
@@ -2480,12 +2501,12 @@ romanboy.o: $(HACK_SRC)/fps.h
 romanboy.o: $(srcdir)/gltrackball.h
 romanboy.o: $(HACK_SRC)/screenhackI.h
 romanboy.o: $(UTILS_SRC)/colors.h
+romanboy.o: $(UTILS_SRC)/erase.h
 romanboy.o: $(UTILS_SRC)/grabscreen.h
 romanboy.o: $(UTILS_SRC)/hsv.h
 romanboy.o: $(UTILS_SRC)/resources.h
 romanboy.o: $(UTILS_SRC)/usleep.h
 romanboy.o: $(UTILS_SRC)/visual.h
-romanboy.o: $(UTILS_SRC)/xshm.h
 romanboy.o: $(UTILS_SRC)/yarandom.h
 romanboy.o: $(HACK_SRC)/xlockmoreI.h
 romanboy.o: $(HACK_SRC)/xlockmore.h
@@ -2498,12 +2519,12 @@ rubikblocks.o: $(srcdir)/gltrackball.h
 rubikblocks.o: $(srcdir)/rotator.h
 rubikblocks.o: $(HACK_SRC)/screenhackI.h
 rubikblocks.o: $(UTILS_SRC)/colors.h
+rubikblocks.o: $(UTILS_SRC)/erase.h
 rubikblocks.o: $(UTILS_SRC)/grabscreen.h
 rubikblocks.o: $(UTILS_SRC)/hsv.h
 rubikblocks.o: $(UTILS_SRC)/resources.h
 rubikblocks.o: $(UTILS_SRC)/usleep.h
 rubikblocks.o: $(UTILS_SRC)/visual.h
-rubikblocks.o: $(UTILS_SRC)/xshm.h
 rubikblocks.o: $(UTILS_SRC)/yarandom.h
 rubikblocks.o: $(HACK_SRC)/xlockmoreI.h
 rubikblocks.o: $(HACK_SRC)/xlockmore.h
@@ -2512,12 +2533,12 @@ rubik.o: $(HACK_SRC)/fps.h
 rubik.o: $(srcdir)/gltrackball.h
 rubik.o: $(HACK_SRC)/screenhackI.h
 rubik.o: $(UTILS_SRC)/colors.h
+rubik.o: $(UTILS_SRC)/erase.h
 rubik.o: $(UTILS_SRC)/grabscreen.h
 rubik.o: $(UTILS_SRC)/hsv.h
 rubik.o: $(UTILS_SRC)/resources.h
 rubik.o: $(UTILS_SRC)/usleep.h
 rubik.o: $(UTILS_SRC)/visual.h
-rubik.o: $(UTILS_SRC)/xshm.h
 rubik.o: $(UTILS_SRC)/yarandom.h
 rubik.o: $(HACK_SRC)/xlockmoreI.h
 rubik.o: $(HACK_SRC)/xlockmore.h
@@ -2542,12 +2563,12 @@ sballs.o: $(HACK_SRC)/images/sball-bg.xpm
 sballs.o: $(HACK_SRC)/images/sball.xpm
 sballs.o: $(HACK_SRC)/screenhackI.h
 sballs.o: $(UTILS_SRC)/colors.h
+sballs.o: $(UTILS_SRC)/erase.h
 sballs.o: $(UTILS_SRC)/grabscreen.h
 sballs.o: $(UTILS_SRC)/hsv.h
 sballs.o: $(UTILS_SRC)/resources.h
 sballs.o: $(UTILS_SRC)/usleep.h
 sballs.o: $(UTILS_SRC)/visual.h
-sballs.o: $(UTILS_SRC)/xshm.h
 sballs.o: $(UTILS_SRC)/yarandom.h
 sballs.o: $(HACK_SRC)/xlockmoreI.h
 sballs.o: $(HACK_SRC)/xlockmore.h
@@ -2571,12 +2592,12 @@ sierpinski3d.o: $(srcdir)/gltrackball.h
 sierpinski3d.o: $(srcdir)/rotator.h
 sierpinski3d.o: $(HACK_SRC)/screenhackI.h
 sierpinski3d.o: $(UTILS_SRC)/colors.h
+sierpinski3d.o: $(UTILS_SRC)/erase.h
 sierpinski3d.o: $(UTILS_SRC)/grabscreen.h
 sierpinski3d.o: $(UTILS_SRC)/hsv.h
 sierpinski3d.o: $(UTILS_SRC)/resources.h
 sierpinski3d.o: $(UTILS_SRC)/usleep.h
 sierpinski3d.o: $(UTILS_SRC)/visual.h
-sierpinski3d.o: $(UTILS_SRC)/xshm.h
 sierpinski3d.o: $(UTILS_SRC)/yarandom.h
 sierpinski3d.o: $(HACK_SRC)/xlockmoreI.h
 sierpinski3d.o: $(HACK_SRC)/xlockmore.h
@@ -2588,12 +2609,12 @@ skytentacles.o: $(srcdir)/normals.h
 skytentacles.o: $(srcdir)/rotator.h
 skytentacles.o: $(HACK_SRC)/screenhackI.h
 skytentacles.o: $(UTILS_SRC)/colors.h
+skytentacles.o: $(UTILS_SRC)/erase.h
 skytentacles.o: $(UTILS_SRC)/grabscreen.h
 skytentacles.o: $(UTILS_SRC)/hsv.h
 skytentacles.o: $(UTILS_SRC)/resources.h
 skytentacles.o: $(UTILS_SRC)/usleep.h
 skytentacles.o: $(UTILS_SRC)/visual.h
-skytentacles.o: $(UTILS_SRC)/xshm.h
 skytentacles.o: $(UTILS_SRC)/yarandom.h
 skytentacles.o: $(HACK_SRC)/xlockmoreI.h
 skytentacles.o: $(HACK_SRC)/xlockmore.h
@@ -2622,13 +2643,13 @@ sonar.o: $(srcdir)/sonar.h
 sonar.o: $(srcdir)/texfont.h
 sonar.o: $(UTILS_SRC)/aligned_malloc.h
 sonar.o: $(UTILS_SRC)/colors.h
+sonar.o: $(UTILS_SRC)/erase.h
 sonar.o: $(UTILS_SRC)/grabscreen.h
 sonar.o: $(UTILS_SRC)/hsv.h
 sonar.o: $(UTILS_SRC)/resources.h
 sonar.o: $(UTILS_SRC)/thread_util.h
 sonar.o: $(UTILS_SRC)/usleep.h
 sonar.o: $(UTILS_SRC)/visual.h
-sonar.o: $(UTILS_SRC)/xshm.h
 sonar.o: $(UTILS_SRC)/yarandom.h
 sonar.o: $(HACK_SRC)/xlockmoreI.h
 sonar.o: $(HACK_SRC)/xlockmore.h
@@ -2651,12 +2672,12 @@ spheremonics.o: $(srcdir)/rotator.h
 spheremonics.o: $(HACK_SRC)/screenhackI.h
 spheremonics.o: $(srcdir)/texfont.h
 spheremonics.o: $(UTILS_SRC)/colors.h
+spheremonics.o: $(UTILS_SRC)/erase.h
 spheremonics.o: $(UTILS_SRC)/grabscreen.h
 spheremonics.o: $(UTILS_SRC)/hsv.h
 spheremonics.o: $(UTILS_SRC)/resources.h
 spheremonics.o: $(UTILS_SRC)/usleep.h
 spheremonics.o: $(UTILS_SRC)/visual.h
-spheremonics.o: $(UTILS_SRC)/xshm.h
 spheremonics.o: $(UTILS_SRC)/yarandom.h
 spheremonics.o: $(HACK_SRC)/xlockmoreI.h
 spheremonics.o: $(HACK_SRC)/xlockmore.h
@@ -2670,6 +2691,7 @@ splitflap.o: $(srcdir)/rotator.h
 splitflap.o: $(HACK_SRC)/screenhackI.h
 splitflap.o: $(srcdir)/texfont.h
 splitflap.o: $(UTILS_SRC)/colors.h
+splitflap.o: $(UTILS_SRC)/erase.h
 splitflap.o: $(UTILS_SRC)/grabscreen.h
 splitflap.o: $(UTILS_SRC)/hsv.h
 splitflap.o: $(UTILS_SRC)/resources.h
@@ -2677,7 +2699,6 @@ splitflap.o: $(UTILS_SRC)/textclient.h
 splitflap.o: $(UTILS_SRC)/usleep.h
 splitflap.o: $(UTILS_SRC)/utf8wc.h
 splitflap.o: $(UTILS_SRC)/visual.h
-splitflap.o: $(UTILS_SRC)/xshm.h
 splitflap.o: $(UTILS_SRC)/yarandom.h
 splitflap.o: $(HACK_SRC)/xlockmoreI.h
 splitflap.o: $(HACK_SRC)/xlockmore.h
@@ -2691,12 +2712,12 @@ splodesic.o: $(srcdir)/normals.h
 splodesic.o: $(srcdir)/rotator.h
 splodesic.o: $(HACK_SRC)/screenhackI.h
 splodesic.o: $(UTILS_SRC)/colors.h
+splodesic.o: $(UTILS_SRC)/erase.h
 splodesic.o: $(UTILS_SRC)/grabscreen.h
 splodesic.o: $(UTILS_SRC)/hsv.h
 splodesic.o: $(UTILS_SRC)/resources.h
 splodesic.o: $(UTILS_SRC)/usleep.h
 splodesic.o: $(UTILS_SRC)/visual.h
-splodesic.o: $(UTILS_SRC)/xshm.h
 splodesic.o: $(UTILS_SRC)/yarandom.h
 splodesic.o: $(HACK_SRC)/xlockmoreI.h
 splodesic.o: $(HACK_SRC)/xlockmore.h
@@ -2706,12 +2727,12 @@ sproingies.o: $(srcdir)/gllist.h
 sproingies.o: $(HACK_SRC)/screenhackI.h
 sproingies.o: $(srcdir)/sproingies.h
 sproingies.o: $(UTILS_SRC)/colors.h
+sproingies.o: $(UTILS_SRC)/erase.h
 sproingies.o: $(UTILS_SRC)/grabscreen.h
 sproingies.o: $(UTILS_SRC)/hsv.h
 sproingies.o: $(UTILS_SRC)/resources.h
 sproingies.o: $(UTILS_SRC)/usleep.h
 sproingies.o: $(UTILS_SRC)/visual.h
-sproingies.o: $(UTILS_SRC)/xshm.h
 sproingies.o: $(UTILS_SRC)/yarandom.h
 sproingies.o: $(HACK_SRC)/xlockmoreI.h
 sproingiewrap.o: ../../config.h
@@ -2719,12 +2740,12 @@ sproingiewrap.o: $(HACK_SRC)/fps.h
 sproingiewrap.o: $(HACK_SRC)/screenhackI.h
 sproingiewrap.o: $(srcdir)/sproingies.h
 sproingiewrap.o: $(UTILS_SRC)/colors.h
+sproingiewrap.o: $(UTILS_SRC)/erase.h
 sproingiewrap.o: $(UTILS_SRC)/grabscreen.h
 sproingiewrap.o: $(UTILS_SRC)/hsv.h
 sproingiewrap.o: $(UTILS_SRC)/resources.h
 sproingiewrap.o: $(UTILS_SRC)/usleep.h
 sproingiewrap.o: $(UTILS_SRC)/visual.h
-sproingiewrap.o: $(UTILS_SRC)/xshm.h
 sproingiewrap.o: $(UTILS_SRC)/yarandom.h
 sproingiewrap.o: $(HACK_SRC)/xlockmoreI.h
 sproingiewrap.o: $(HACK_SRC)/xlockmore.h
@@ -2735,12 +2756,12 @@ stairs.o: $(HACK_SRC)/images/wood.xpm
 stairs.o: $(HACK_SRC)/screenhackI.h
 stairs.o: $(srcdir)/sphere.h
 stairs.o: $(UTILS_SRC)/colors.h
+stairs.o: $(UTILS_SRC)/erase.h
 stairs.o: $(UTILS_SRC)/grabscreen.h
 stairs.o: $(UTILS_SRC)/hsv.h
 stairs.o: $(UTILS_SRC)/resources.h
 stairs.o: $(UTILS_SRC)/usleep.h
 stairs.o: $(UTILS_SRC)/visual.h
-stairs.o: $(UTILS_SRC)/xshm.h
 stairs.o: $(UTILS_SRC)/yarandom.h
 stairs.o: $(HACK_SRC)/xlockmoreI.h
 stairs.o: $(HACK_SRC)/xlockmore.h
@@ -2753,6 +2774,7 @@ starwars.o: $(HACK_SRC)/screenhackI.h
 starwars.o: $(srcdir)/starwars.h
 starwars.o: $(srcdir)/texfont.h
 starwars.o: $(UTILS_SRC)/colors.h
+starwars.o: $(UTILS_SRC)/erase.h
 starwars.o: $(UTILS_SRC)/grabscreen.h
 starwars.o: $(UTILS_SRC)/hsv.h
 starwars.o: $(UTILS_SRC)/resources.h
@@ -2760,7 +2782,6 @@ starwars.o: $(UTILS_SRC)/textclient.h
 starwars.o: $(UTILS_SRC)/usleep.h
 starwars.o: $(UTILS_SRC)/utf8wc.h
 starwars.o: $(UTILS_SRC)/visual.h
-starwars.o: $(UTILS_SRC)/xshm.h
 starwars.o: $(UTILS_SRC)/yarandom.h
 starwars.o: $(HACK_SRC)/xlockmoreI.h
 starwars.o: $(HACK_SRC)/xlockmore.h
@@ -2777,12 +2798,12 @@ stonerview.o: $(srcdir)/stonerview.h
 stonerview.o: $(srcdir)/stonerview-move.h
 stonerview.o: $(srcdir)/stonerview-osc.h
 stonerview.o: $(UTILS_SRC)/colors.h
+stonerview.o: $(UTILS_SRC)/erase.h
 stonerview.o: $(UTILS_SRC)/grabscreen.h
 stonerview.o: $(UTILS_SRC)/hsv.h
 stonerview.o: $(UTILS_SRC)/resources.h
 stonerview.o: $(UTILS_SRC)/usleep.h
 stonerview.o: $(UTILS_SRC)/visual.h
-stonerview.o: $(UTILS_SRC)/xshm.h
 stonerview.o: $(UTILS_SRC)/yarandom.h
 stonerview.o: $(HACK_SRC)/xlockmoreI.h
 stonerview.o: $(HACK_SRC)/xlockmore.h
@@ -2799,12 +2820,12 @@ superquadrics.o: ../../config.h
 superquadrics.o: $(HACK_SRC)/fps.h
 superquadrics.o: $(HACK_SRC)/screenhackI.h
 superquadrics.o: $(UTILS_SRC)/colors.h
+superquadrics.o: $(UTILS_SRC)/erase.h
 superquadrics.o: $(UTILS_SRC)/grabscreen.h
 superquadrics.o: $(UTILS_SRC)/hsv.h
 superquadrics.o: $(UTILS_SRC)/resources.h
 superquadrics.o: $(UTILS_SRC)/usleep.h
 superquadrics.o: $(UTILS_SRC)/visual.h
-superquadrics.o: $(UTILS_SRC)/xshm.h
 superquadrics.o: $(UTILS_SRC)/yarandom.h
 superquadrics.o: $(HACK_SRC)/xlockmoreI.h
 superquadrics.o: $(HACK_SRC)/xlockmore.h
@@ -2814,12 +2835,12 @@ surfaces.o: $(srcdir)/gltrackball.h
 surfaces.o: $(srcdir)/rotator.h
 surfaces.o: $(HACK_SRC)/screenhackI.h
 surfaces.o: $(UTILS_SRC)/colors.h
+surfaces.o: $(UTILS_SRC)/erase.h
 surfaces.o: $(UTILS_SRC)/grabscreen.h
 surfaces.o: $(UTILS_SRC)/hsv.h
 surfaces.o: $(UTILS_SRC)/resources.h
 surfaces.o: $(UTILS_SRC)/usleep.h
 surfaces.o: $(UTILS_SRC)/visual.h
-surfaces.o: $(UTILS_SRC)/xshm.h
 surfaces.o: $(UTILS_SRC)/yarandom.h
 surfaces.o: $(HACK_SRC)/xlockmoreI.h
 surfaces.o: $(HACK_SRC)/xlockmore.h
@@ -2828,12 +2849,12 @@ swim.o: ../../config.h
 swim.o: $(HACK_SRC)/fps.h
 swim.o: $(HACK_SRC)/screenhackI.h
 swim.o: $(UTILS_SRC)/colors.h
+swim.o: $(UTILS_SRC)/erase.h
 swim.o: $(UTILS_SRC)/grabscreen.h
 swim.o: $(UTILS_SRC)/hsv.h
 swim.o: $(UTILS_SRC)/resources.h
 swim.o: $(UTILS_SRC)/usleep.h
 swim.o: $(UTILS_SRC)/visual.h
-swim.o: $(UTILS_SRC)/xshm.h
 swim.o: $(UTILS_SRC)/yarandom.h
 swim.o: $(HACK_SRC)/xlockmoreI.h
 tangram.o: ../../config.h
@@ -2842,12 +2863,12 @@ tangram.o: $(HACK_SRC)/screenhackI.h
 tangram.o: $(srcdir)/tangram_shapes.h
 tangram.o: $(srcdir)/texfont.h
 tangram.o: $(UTILS_SRC)/colors.h
+tangram.o: $(UTILS_SRC)/erase.h
 tangram.o: $(UTILS_SRC)/grabscreen.h
 tangram.o: $(UTILS_SRC)/hsv.h
 tangram.o: $(UTILS_SRC)/resources.h
 tangram.o: $(UTILS_SRC)/usleep.h
 tangram.o: $(UTILS_SRC)/visual.h
-tangram.o: $(UTILS_SRC)/xshm.h
 tangram.o: $(UTILS_SRC)/yarandom.h
 tangram.o: $(HACK_SRC)/xlockmoreI.h
 tangram.o: $(HACK_SRC)/xlockmore.h
@@ -2872,13 +2893,13 @@ timetunnel.o: $(HACK_SRC)/images/tunnelstar.xpm
 timetunnel.o: $(srcdir)/rotator.h
 timetunnel.o: $(HACK_SRC)/screenhackI.h
 timetunnel.o: $(UTILS_SRC)/colors.h
+timetunnel.o: $(UTILS_SRC)/erase.h
 timetunnel.o: $(UTILS_SRC)/grabscreen.h
 timetunnel.o: $(UTILS_SRC)/hsv.h
 timetunnel.o: $(UTILS_SRC)/images/logo-180.xpm
 timetunnel.o: $(UTILS_SRC)/resources.h
 timetunnel.o: $(UTILS_SRC)/usleep.h
 timetunnel.o: $(UTILS_SRC)/visual.h
-timetunnel.o: $(UTILS_SRC)/xshm.h
 timetunnel.o: $(UTILS_SRC)/yarandom.h
 timetunnel.o: $(HACK_SRC)/xlockmoreI.h
 timetunnel.o: $(HACK_SRC)/xlockmore.h
@@ -2911,12 +2932,12 @@ topblock.o: $(srcdir)/sphere.h
 topblock.o: $(srcdir)/topblock.h
 topblock.o: $(srcdir)/tube.h
 topblock.o: $(UTILS_SRC)/colors.h
+topblock.o: $(UTILS_SRC)/erase.h
 topblock.o: $(UTILS_SRC)/grabscreen.h
 topblock.o: $(UTILS_SRC)/hsv.h
 topblock.o: $(UTILS_SRC)/resources.h
 topblock.o: $(UTILS_SRC)/usleep.h
 topblock.o: $(UTILS_SRC)/visual.h
-topblock.o: $(UTILS_SRC)/xshm.h
 topblock.o: $(UTILS_SRC)/yarandom.h
 topblock.o: $(HACK_SRC)/xlockmoreI.h
 topblock.o: $(HACK_SRC)/xlockmore.h
@@ -2936,12 +2957,12 @@ tronbit.o: $(srcdir)/rotator.h
 tronbit.o: $(HACK_SRC)/screenhackI.h
 tronbit.o: $(srcdir)/sphere.h
 tronbit.o: $(UTILS_SRC)/colors.h
+tronbit.o: $(UTILS_SRC)/erase.h
 tronbit.o: $(UTILS_SRC)/grabscreen.h
 tronbit.o: $(UTILS_SRC)/hsv.h
 tronbit.o: $(UTILS_SRC)/resources.h
 tronbit.o: $(UTILS_SRC)/usleep.h
 tronbit.o: $(UTILS_SRC)/visual.h
-tronbit.o: $(UTILS_SRC)/xshm.h
 tronbit.o: $(UTILS_SRC)/yarandom.h
 tronbit.o: $(HACK_SRC)/xlockmoreI.h
 tronbit.o: $(HACK_SRC)/xlockmore.h
@@ -2954,12 +2975,12 @@ tunnel_draw.o: $(HACK_SRC)/fps.h
 tunnel_draw.o: $(HACK_SRC)/screenhackI.h
 tunnel_draw.o: $(srcdir)/tunnel_draw.h
 tunnel_draw.o: $(UTILS_SRC)/colors.h
+tunnel_draw.o: $(UTILS_SRC)/erase.h
 tunnel_draw.o: $(UTILS_SRC)/grabscreen.h
 tunnel_draw.o: $(UTILS_SRC)/hsv.h
 tunnel_draw.o: $(UTILS_SRC)/resources.h
 tunnel_draw.o: $(UTILS_SRC)/usleep.h
 tunnel_draw.o: $(UTILS_SRC)/visual.h
-tunnel_draw.o: $(UTILS_SRC)/xshm.h
 tunnel_draw.o: $(UTILS_SRC)/yarandom.h
 tunnel_draw.o: $(HACK_SRC)/xlockmoreI.h
 unicrud.o: ../../config.h
@@ -2969,13 +2990,13 @@ unicrud.o: $(srcdir)/rotator.h
 unicrud.o: $(HACK_SRC)/screenhackI.h
 unicrud.o: $(srcdir)/texfont.h
 unicrud.o: $(UTILS_SRC)/colors.h
+unicrud.o: $(UTILS_SRC)/erase.h
 unicrud.o: $(UTILS_SRC)/grabscreen.h
 unicrud.o: $(UTILS_SRC)/hsv.h
 unicrud.o: $(UTILS_SRC)/resources.h
 unicrud.o: $(UTILS_SRC)/usleep.h
 unicrud.o: $(UTILS_SRC)/utf8wc.h
 unicrud.o: $(UTILS_SRC)/visual.h
-unicrud.o: $(UTILS_SRC)/xshm.h
 unicrud.o: $(UTILS_SRC)/yarandom.h
 unicrud.o: $(HACK_SRC)/xlockmoreI.h
 unicrud.o: $(HACK_SRC)/xlockmore.h
@@ -2984,12 +3005,12 @@ unknownpleasures.o: $(HACK_SRC)/fps.h
 unknownpleasures.o: $(srcdir)/gltrackball.h
 unknownpleasures.o: $(HACK_SRC)/screenhackI.h
 unknownpleasures.o: $(UTILS_SRC)/colors.h
+unknownpleasures.o: $(UTILS_SRC)/erase.h
 unknownpleasures.o: $(UTILS_SRC)/grabscreen.h
 unknownpleasures.o: $(UTILS_SRC)/hsv.h
 unknownpleasures.o: $(UTILS_SRC)/resources.h
 unknownpleasures.o: $(UTILS_SRC)/usleep.h
 unknownpleasures.o: $(UTILS_SRC)/visual.h
-unknownpleasures.o: $(UTILS_SRC)/xshm.h
 unknownpleasures.o: $(UTILS_SRC)/yarandom.h
 unknownpleasures.o: $(HACK_SRC)/xlockmoreI.h
 unknownpleasures.o: $(HACK_SRC)/xlockmore.h
@@ -3000,12 +3021,12 @@ vigilance.o: $(srcdir)/gltrackball.h
 vigilance.o: $(srcdir)/normals.h
 vigilance.o: $(HACK_SRC)/screenhackI.h
 vigilance.o: $(UTILS_SRC)/colors.h
+vigilance.o: $(UTILS_SRC)/erase.h
 vigilance.o: $(UTILS_SRC)/grabscreen.h
 vigilance.o: $(UTILS_SRC)/hsv.h
 vigilance.o: $(UTILS_SRC)/resources.h
 vigilance.o: $(UTILS_SRC)/usleep.h
 vigilance.o: $(UTILS_SRC)/visual.h
-vigilance.o: $(UTILS_SRC)/xshm.h
 vigilance.o: $(UTILS_SRC)/yarandom.h
 vigilance.o: $(HACK_SRC)/xlockmoreI.h
 vigilance.o: $(HACK_SRC)/xlockmore.h
@@ -3014,12 +3035,12 @@ voronoi.o: ../../config.h
 voronoi.o: $(HACK_SRC)/fps.h
 voronoi.o: $(HACK_SRC)/screenhackI.h
 voronoi.o: $(UTILS_SRC)/colors.h
+voronoi.o: $(UTILS_SRC)/erase.h
 voronoi.o: $(UTILS_SRC)/grabscreen.h
 voronoi.o: $(UTILS_SRC)/hsv.h
 voronoi.o: $(UTILS_SRC)/resources.h
 voronoi.o: $(UTILS_SRC)/usleep.h
 voronoi.o: $(UTILS_SRC)/visual.h
-voronoi.o: $(UTILS_SRC)/xshm.h
 voronoi.o: $(UTILS_SRC)/yarandom.h
 voronoi.o: $(HACK_SRC)/xlockmoreI.h
 voronoi.o: $(HACK_SRC)/xlockmore.h
@@ -3044,13 +3065,13 @@ winduprobot.o: $(HACK_SRC)/screenhackI.h
 winduprobot.o: $(srcdir)/sphere.h
 winduprobot.o: $(srcdir)/texfont.h
 winduprobot.o: $(UTILS_SRC)/colors.h
+winduprobot.o: $(UTILS_SRC)/erase.h
 winduprobot.o: $(UTILS_SRC)/grabscreen.h
 winduprobot.o: $(UTILS_SRC)/hsv.h
 winduprobot.o: $(UTILS_SRC)/resources.h
 winduprobot.o: $(UTILS_SRC)/textclient.h
 winduprobot.o: $(UTILS_SRC)/usleep.h
 winduprobot.o: $(UTILS_SRC)/visual.h
-winduprobot.o: $(UTILS_SRC)/xshm.h
 winduprobot.o: $(UTILS_SRC)/yarandom.h
 winduprobot.o: $(HACK_SRC)/xlockmoreI.h
 winduprobot.o: $(HACK_SRC)/xlockmore.h
@@ -3060,12 +3081,12 @@ xlock-gl-utils.o: $(HACK_SRC)/fps.h
 xlock-gl-utils.o: $(HACK_SRC)/screenhackI.h
 xlock-gl-utils.o: $(srcdir)/texfont.h
 xlock-gl-utils.o: $(UTILS_SRC)/colors.h
+xlock-gl-utils.o: $(UTILS_SRC)/erase.h
 xlock-gl-utils.o: $(UTILS_SRC)/grabscreen.h
 xlock-gl-utils.o: $(UTILS_SRC)/hsv.h
 xlock-gl-utils.o: $(UTILS_SRC)/resources.h
 xlock-gl-utils.o: $(UTILS_SRC)/usleep.h
 xlock-gl-utils.o: $(UTILS_SRC)/visual.h
-xlock-gl-utils.o: $(UTILS_SRC)/xshm.h
 xlock-gl-utils.o: $(UTILS_SRC)/yarandom.h
 xlock-gl-utils.o: $(HACK_SRC)/xlockmoreI.h
 xpm-ximage.o: ../../config.h
index bb6927d1902cd1b0433ba2cd512c0044d0019178..ad3bef56ef15b7172e1ce6b5787bbd923b9e0045 100644 (file)
@@ -19,7 +19,7 @@
 #define DEFAULTS           "*delay:   20000   \n" \
                            "*showFPS: False   \n"
 
-# define refresh_antinspect 0
+# define free_antinspect 0
 # define release_antinspect 0
 #include "xlockmore.h"
 #else
@@ -549,10 +549,17 @@ static Bool draw_antinspect_strip(ModeInfo * mi)
 ENTRYPOINT void reshape_antinspect(ModeInfo * mi, int width, int height) 
 {
   double h = (GLfloat) height / (GLfloat) width;  
+  int y = 0;
   antinspectstruct *mp = &antinspect[MI_SCREEN(mi)];
   mp->linewidth = (width / 512) + 1;
 
-  glViewport(0, 0, mp->WindW = (GLint) width, mp->WindH = (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport(0, y, mp->WindW = (GLint) width, mp->WindH = (GLint) height);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
 
@@ -605,7 +612,7 @@ ENTRYPOINT void init_antinspect(ModeInfo * mi)
 {
   antinspectstruct *mp;
   
-  MI_INIT(mi, antinspect, NULL);
+  MI_INIT(mi, antinspect);
   mp = &antinspect[MI_SCREEN(mi)];
   mp->step = NRAND(90);
   mp->ant_position = NRAND(90);
index 229257b9576fc7680ab606e862ce8eabf6d8fa01..79b7e0b997330579b9924846edfb47581902c226 100644 (file)
@@ -25,7 +25,7 @@ static const char sccsid[] = "@(#)antmaze.c   5.01 2001/03/01 xlockmore";
                        "*showFPS:      False   \n" \
                        "*fpsSolid:     True    \n"
 
-# define refresh_antmaze 0
+# define free_antmaze 0
 # define release_antmaze 0
 # include "xlockmore.h"                /* from the xscreensaver distribution */
 #else /* !STANDALONE */
@@ -1329,7 +1329,7 @@ ENTRYPOINT void init_antmaze(ModeInfo * mi)
 
   antmazestruct *mp;
   
-  MI_INIT(mi, antmaze, NULL);
+  MI_INIT(mi, antmaze);
   mp = &antmaze[MI_SCREEN(mi)];
   mp->step = NRAND(90);
   mp->ant_position = NRAND(90);
index 6b3897a360a4717ad374f0b17882f4b170e6dd92..55bb80cd51158d03db785e586be717a6fef5bcf5 100644 (file)
@@ -19,7 +19,7 @@
                            "*showFPS: False   \n" \
                             "*useSHM:  True    \n"
 
-# define refresh_antspotlight 0
+# define free_antspotlight 0
 # define release_antspotlight 0
 #include "xlockmore.h"
 #else
@@ -552,8 +552,16 @@ static void draw_antspotlight_strip(ModeInfo *mi)
 ENTRYPOINT void reshape_antspotlight(ModeInfo * mi, int width, int height)
 {
   double h = (GLfloat) height / (GLfloat) width;  
+  int y = 0;
   int size = 2;
-  glViewport(0, 0, width, height);
+
+  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();
 
@@ -697,7 +705,7 @@ ENTRYPOINT void init_antspotlight(ModeInfo *mi)
 
   antspotlightstruct *mp;
   
-  MI_INIT(mi, antspotlight, NULL);
+  MI_INIT(mi, antspotlight);
   mp = &antspotlight[MI_SCREEN(mi)];
   mp->rot = make_rotator (rot_speed, rot_speed, rot_speed, 1, 0, True);
   mp->trackball = gltrackball_init (False);
index c310a69a770a803be4660df2e9ce0062e9131251..44bc6eb69488bf1d2abe98ab684a1c86f425368b 100644 (file)
@@ -113,7 +113,7 @@ static const char sccsid[] = "@(#)atlantis.c        5.08 2003/04/09 xlockmore";
                         "*size:        6000 \n" \
                         "*wireframe:  False \n"
 # define release_atlantis 0
-# define atlantis_handle_event 0
+# define atlantis_handle_event xlockmore_no_events
 # include "xlockmore.h"                /* from the xscreensaver distribution */
 #else  /* !STANDALONE */
 # include "xlock.h"            /* from the xlockmore distribution */
@@ -157,7 +157,7 @@ ENTRYPOINT ModeSpecOpt atlantis_opts =
 #ifdef USE_MODULES
 ModStruct   atlantis_description =
 {"atlantis", "init_atlantis", "draw_atlantis", NULL,
- "refresh_atlantis", "change_atlantis", NULL, &atlantis_opts,
+ "refresh_atlantis", "change_atlantis", "free_atlantis", &atlantis_opts,
  1000, NUM_SHARKS, SHARKSPEED, SHARKSIZE, 64, 1.0, "",
  "Shows moving sharks/whales/dolphin", 0, NULL};
 
@@ -322,14 +322,22 @@ Init(ModeInfo *mi)
 ENTRYPOINT void
 reshape_atlantis(ModeInfo * mi, int width, int height)
 {
-       atlantisstruct *ap = &atlantis[MI_SCREEN(mi)];
+  double h = (GLfloat) height / (GLfloat) width;  
+  atlantisstruct *ap = &atlantis[MI_SCREEN(mi)];
+  int y = 0;
+
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
 
-       glViewport(0, 0, ap->WinW = (GLint) width, ap->WinH = (GLint) height);
+  glViewport(0, y, ap->WinW = (GLint) width, ap->WinH = (GLint) height);
 
-       glMatrixMode(GL_PROJECTION);
-       glLoadIdentity();
-       gluPerspective(400.0, (GLdouble) width / (GLdouble) height, 1.0, 2000000.0);
-       glMatrixMode(GL_MODELVIEW);
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  gluPerspective(400.0, 1/h, 1.0, 2000000.0);
+  glMatrixMode(GL_MODELVIEW);
 }
 
 
@@ -368,6 +376,9 @@ clear_tank (atlantisstruct * ap)
           glVertex3f ( 1,  1, 1); glVertex3f (-1,  1, 1);
           glEnd();
           glEnable (GL_LIGHTING);
+
+          /* Need to reset this because jwzgles conflates color and material */
+          glColor3f (0.0, 0.1, 0.2);
         }
         glPopMatrix();
       }
@@ -435,8 +446,6 @@ AllDisplay(atlantisstruct * ap)
  *-----------------------------------------------------------------------------
  */
 
-static void free_atlantis(ModeInfo * mi);
-
 /*
  *-----------------------------------------------------------------------------
  *    Initialize atlantis.  Called each time the window changes.
@@ -451,7 +460,7 @@ init_atlantis(ModeInfo * mi)
        Display    *display = MI_DISPLAY(mi);
        Window      window = MI_WINDOW(mi);
 
-       MI_INIT(mi, atlantis, free_atlantis);
+       MI_INIT(mi, atlantis);
        ap = &atlantis[screen];
        ap->num_sharks = MI_COUNT(mi);
        if (ap->sharks == NULL) {
@@ -534,7 +543,7 @@ draw_atlantis(ModeInfo * mi)
  *-----------------------------------------------------------------------------
  */
 
-static void
+ENTRYPOINT void
 free_atlantis(ModeInfo * mi)
 {
 #if 0
@@ -545,12 +554,12 @@ free_atlantis(ModeInfo * mi)
 #endif
 }
 
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_atlantis(ModeInfo * mi)
 {
 }
 
-#ifndef STANDALONE
 ENTRYPOINT void
 change_atlantis(ModeInfo * mi)
 {
index 8ee10aeb0b78549db06c8ca45c0f04b5927e3fb0..04391a13e19cde28b46761204a320d29b0d99e81 100644 (file)
@@ -43,7 +43,6 @@ static const char sccsid[] = "@(#)atunnel.c   5.13 2004/05/25 xlockmore";
                                 "*showFPS:  False   \n" \
                                                                "*suppressRotationAnimation: True\n" \
 
-# define refresh_atunnel 0
 # define release_atunnel 0
 # define atunnel_handle_event 0
 #define MODE_atunnel
@@ -120,7 +119,7 @@ ENTRYPOINT ModeSpecOpt atunnel_opts = {countof(opts), opts, countof(vars), vars,
 #ifdef USE_MODULES
 ModStruct   atunnel_description =
 {"atunnel", "init_atunnel", "draw_atunnel", NULL,
- "draw_atunnel", "init_atunnel", NULL, &atunnel_opts,
+ "draw_atunnel", "init_atunnel", "free_atunnel", &atunnel_opts,
  1000, 1, 2, 1, 4, 1.0, "",
  "OpenGL advanced tunnel screensaver", 0, NULL};
 #endif
@@ -251,14 +250,20 @@ static void Init(ModeInfo * mi)
 ENTRYPOINT void
 reshape_atunnel(ModeInfo *mi, int width, int height)
 {
-       float a;
+  double h = (GLfloat) height / (GLfloat) width;  
+  int y = 0;
 
-       glViewport(0, 0, width, height);
-       glMatrixMode(GL_PROJECTION);
-       glLoadIdentity();
-       a = (float)width/(float)height;
-       glFrustum(-0.1*a, 0.1*a, -0.1, 0.1, 0.1, 10);
-       glMatrixMode(GL_MODELVIEW);
+  if (width > height * 2) {   /* tiny window: show middle */
+    height = width;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport(0, y, width, height);
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  glFrustum(-0.1*(1/h), 0.1*(1/h), -0.1, 0.1, 0.1, 10);
+  glMatrixMode(GL_MODELVIEW);
 }
 
 /* draw the screensaver once */
@@ -288,15 +293,13 @@ ENTRYPOINT void draw_atunnel(ModeInfo * mi)
 }
 
 
-static void free_atunnel(ModeInfo * mi);
-
 /* xscreensaver initialization routine */
 ENTRYPOINT void init_atunnel(ModeInfo * mi)
 {
   int screen = MI_SCREEN(mi);
   atunnelstruct *sa;
 
-  MI_INIT(mi, Atunnel, free_atunnel);
+  MI_INIT(mi, Atunnel);
   sa = &Atunnel[screen];
 
   sa->window = MI_WINDOW(mi);
@@ -310,7 +313,7 @@ ENTRYPOINT void init_atunnel(ModeInfo * mi)
 }
 
 /* all sorts of nice cleanup code should go here! */
-static void free_atunnel(ModeInfo * mi)
+ENTRYPOINT void free_atunnel(ModeInfo * mi)
 {
 #if 0
   atunnelstruct *sa = &Atunnel[MI_SCREEN(mi)];
index a6236c64a9320cf4ec4a664323b8bf1984d8e22d..cdc829e1b476a5927757e872e0a115ae3ce29c9c 100644 (file)
@@ -41,9 +41,8 @@ struct glb_config glb_config =
 # define DEFAULTS      "*delay:        10000   \n"     \
                        "*showFPS:      False   \n"
 
-# define refresh_bubble3d 0
 # define release_bubble3d 0
-# define bubble3d_handle_event 0
+# define bubble3d_handle_event xlockmore_no_events
 #include "xlockmore.h"
 #else
 #include "xlock.h"
@@ -83,7 +82,7 @@ ModStruct   bubbles3d_description =
  NULL,
  "change_bubble3d",
  "init_bubble3d",
NULL,
"free_bubble3d",
  &bubble3d_opts,
  1000, 1, 2, 1, 64, 1.0, "",
  "Richard Jones's GL bubbles",
@@ -139,15 +138,23 @@ init(struct context *c)
 }
 
 ENTRYPOINT void
-reshape_bubble3d(ModeInfo *mi, int w, int h)
+reshape_bubble3d(ModeInfo *mi, int width, int height)
 {
-       glViewport(0, 0, (GLsizei) w, (GLsizei) h);
-       glMatrixMode(GL_PROJECTION);
-       glLoadIdentity();
-       gluPerspective(45, (GLdouble) w / (GLdouble) h, 3, 8);
-       glMatrixMode(GL_MODELVIEW);
-       glLoadIdentity();
-       glTranslatef(0, 0, -5);
+  double 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, 0, width, height);
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  gluPerspective(45, 1/h, 3, 8);
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+  glTranslatef(0, 0, -5);
 }
 
 static void
@@ -156,8 +163,6 @@ do_display(struct context *c)
        glb_draw_step(c->draw_context);
 }
 
-static void free_bubble3d(ModeInfo * mi);
-
 ENTRYPOINT void
 init_bubble3d(ModeInfo * mi)
 {
@@ -166,7 +171,7 @@ init_bubble3d(ModeInfo * mi)
        int         screen = MI_SCREEN(mi);
        struct context *c;
 
-       MI_INIT (mi, contexts, free_bubble3d);
+       MI_INIT (mi, contexts);
        c = &contexts[screen];
        c->glx_context = init_GL(mi);
        init_colors(mi);
@@ -224,7 +229,7 @@ change_bubble3d(ModeInfo * mi)
 }
 #endif /* !STANDALONE */
 
-static void
+ENTRYPOINT void
 free_bubble3d(ModeInfo * mi)
 {
   struct context *c = &contexts[MI_SCREEN(mi)];
index f90f7feff222822440d491d73e78644cd911eb1e..f777371162afafa958c84cb8d8ab4c39f8c98742 100644 (file)
@@ -16,9 +16,9 @@
                        "*wireframe:    False            \n" \
                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_ball 0
+# define free_ball 0
 # define release_ball 0
-# define ball_handle_event 0
+# define ball_handle_event xlockmore_no_events
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
 
@@ -232,8 +232,15 @@ ENTRYPOINT void
 reshape_ball (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   gluPerspective (30.0, 1/h, 1.0, 100.0);
@@ -296,7 +303,7 @@ init_ball (ModeInfo *mi)
   int wire = MI_IS_WIREFRAME(mi);
   blinkboxstruct *bp;
   
-  MI_INIT (mi, blinkbox, NULL);
+  MI_INIT (mi, blinkbox);
   bp = &blinkbox[MI_SCREEN(mi)];
 
   if ((bp->glx_context = init_GL(mi)) != NULL) {
index 682b64390e05eb8da7e3e99198e9a511b962c6af..3ff5cdb3d37139269178c4bde0c3f2aa1a124dbe 100644 (file)
@@ -18,9 +18,8 @@
                        "*showFPS:      False           \n" \
                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_blocktube 0
 # define release_blocktube 0
-# define blocktube_handle_event 0
+# define blocktube_handle_event xlockmore_no_events
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
 
@@ -111,7 +110,7 @@ ENTRYPOINT ModeSpecOpt blocktube_opts = {countof(opts), opts, countof(vars), var
 #ifdef USE_MODULES
 ModStruct blocktube_description =
     {"blocktube", "init_blocktube", "draw_blocktube", (char *)NULL,
-     "draw_blocktube", "init_blocktube", (char *)NULL, &blocktube_opts,
+     "draw_blocktube", "init_blocktube", "free_blocktube", &blocktube_opts,
      40000, 30, 1, 1, 64, 1.0, "",
      "A shifting tunnel of reflective blocks", 0, NULL};
 #endif /* USE_MODULES */
@@ -205,7 +204,6 @@ static void tick(blocktube_configuration *lp)
 static int cube_vertices(float x, float y, float z, int wire);
 
 ENTRYPOINT void reshape_blocktube (ModeInfo *mi, int width, int height);
-static void free_blocktube (ModeInfo *mi);
 
 ENTRYPOINT void init_blocktube (ModeInfo *mi)
 {
@@ -214,7 +212,7 @@ ENTRYPOINT void init_blocktube (ModeInfo *mi)
     blocktube_configuration *lp;
     int wire = MI_IS_WIREFRAME(mi);
 
-    MI_INIT(mi, lps, free_blocktube);
+    MI_INIT(mi, lps);
 
     lp = &lps[MI_SCREEN(mi)];
     lp->glx_context = init_GL(mi);
@@ -289,7 +287,7 @@ ENTRYPOINT void init_blocktube (ModeInfo *mi)
     glFlush();
 }
 
-static void free_blocktube (ModeInfo *mi)
+ENTRYPOINT void free_blocktube (ModeInfo *mi)
 {
   blocktube_configuration *lp = &lps[MI_SCREEN(mi)];
 # if defined ( I_HAVE_XPM )
@@ -308,10 +306,17 @@ ENTRYPOINT void reshape_blocktube (ModeInfo *mi, int width, int height)
 {
     blocktube_configuration *lp = &lps[MI_SCREEN(mi)];
     GLfloat h = (GLfloat) height / (GLfloat) width;
+    int y = 0;
 
     glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(lp->glx_context));
 
-    glViewport(0, 0, (GLint) width, (GLint) height);
+    if (width > height * 5) {   /* tiny window: show middle */
+      height = width;
+      y = -height/2;
+      h = height / (GLfloat) width;
+    }
+
+    glViewport(0, y, (GLint) width, (GLint) height);
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
     gluPerspective(45.0, 1/h, 1.0, 100.0);
index 22d512bf808ae1219c323751bfe0967f0d0d3655..55a05f3d4c67a98c94bdc50b832e9e62a5bdcb46 100644 (file)
@@ -25,7 +25,7 @@
                        "*showFPS:      False            \n" \
                        "*wireframe:    False            \n" \
 
-# define refresh_boing 0
+# define free_boing 0
 # define release_boing 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -455,11 +455,18 @@ ENTRYPOINT void
 reshape_boing (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
   h *= 4.0 / 3.0;   /* Back in the caveman days we couldn't even afford
                        square pixels! */
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 3/4;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -502,7 +509,7 @@ init_boing (ModeInfo *mi)
   boing_configuration *bp;
   int wire = MI_IS_WIREFRAME(mi);
 
-  MI_INIT (mi, bps, NULL);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
index 0773414dd79e737734a4bf1780bb903693d72a50..2229f7157d13c1a043e74bc6fd4901267112e221 100644 (file)
@@ -16,7 +16,7 @@
                        "*showFPS:      False       \n" \
                        "*wireframe:    False       \n" \
 
-# define refresh_cow 0
+# define free_cow 0
 # define release_cow 0
 #define DEF_SPEED       "1.0"
 #define DEF_TEXTURE     "(none)"
@@ -156,8 +156,15 @@ ENTRYPOINT void
 reshape_cow (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -239,7 +246,7 @@ init_cow (ModeInfo *mi)
   int i;
   Bool tex_p = False;
 
-  MI_INIT (mi, bps, NULL);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
index 1791052602042a21944acddc82b25f538883aaa4..136d468ebceebbf88548e49cee0ac68156403a91 100644 (file)
@@ -45,9 +45,8 @@ static const char sccsid[] = "@(#)boxed.c     0.9 01/09/26 xlockmore";
                        "*showFPS:   False   \n" \
                        "*wireframe: False   \n"
 
-# define refresh_boxed 0
 # define release_boxed 0
-# define boxed_handle_event 0
+# define boxed_handle_event xlockmore_no_events
 # include "xlockmore.h"                /* from the xscreensaver distribution */
 #else  /* !STANDALONE */
 # include "xlock.h"            /* from the xlockmore distribution */
@@ -99,7 +98,7 @@ ENTRYPOINT ModeSpecOpt boxed_opts = {countof(opts), opts, countof(vars), vars, N
 
 ModStruct   boxed_description = { 
      "boxed", "init_boxed", "draw_boxed", NULL,
-     "draw_boxed", "init_boxed", NULL, &boxed_opts,
+     "draw_boxed", "init_boxed", "free_boxed", &boxed_opts,
      1000, 1, 2, 1, 4, 1.0, "",
      "Shows GL's boxed balls", 0, NULL};
 
@@ -1170,8 +1169,15 @@ static void draw(ModeInfo * mi)
 ENTRYPOINT void reshape_boxed(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, 0, (GLint) width, (GLint) height);
+   glViewport(0, y, (GLint) width, (GLint) height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(50.0,1/h,2.0,1000.0);
@@ -1283,8 +1289,6 @@ pinit(ModeInfo * mi)
 
  
 
-static void free_boxed(ModeInfo * mi);
-
 ENTRYPOINT void
 init_boxed(ModeInfo * mi)
 {
@@ -1294,7 +1298,7 @@ init_boxed(ModeInfo * mi)
    /* Boolean     rgba, doublebuffer, cmap_installed; */
    boxedstruct *gp;
 
-   MI_INIT(mi, boxed, free_boxed);
+   MI_INIT(mi, boxed);
    gp = &boxed[screen];
    gp->window = MI_WINDOW(mi);
    
index 3590f8600f3221b80be4b302d91135d637581fb2..654510d28e51f15f159e7a69965a4e8f1cbea6d9 100644 (file)
@@ -82,9 +82,9 @@ static const char sccsid[] = "@(#)cage.c      5.01 2001/03/01 xlockmore";
                                                        "*wireframe:    False   \n"                     \
                                                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_cage 0
+# define free_cage 0
 # define release_cage 0
-# define cage_handle_event 0
+# define cage_handle_event xlockmore_no_events
 # include "xlockmore.h"                /* from the xscreensaver distribution */
 #else /* !STANDALONE */
 # include "xlock.h"            /* from the xlockmore distribution */
@@ -296,8 +296,14 @@ reshape_cage(ModeInfo * mi, int width, int height)
 {
        cagestruct *cp = &cage[MI_SCREEN(mi)];
        int i;
+    int y = 0;
 
-       glViewport(0, 0, cp->WindW = (GLint) width, cp->WindH = (GLint) height);
+    if (width > height * 5) {   /* tiny window: show middle */
+      height = width * 9/16;
+      y = -height/2;
+    }
+
+       glViewport(0, y, cp->WindW = (GLint) width, cp->WindH = (GLint) height);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0);
@@ -387,7 +393,7 @@ init_cage (ModeInfo * mi)
 {
        cagestruct *cp;
 
-       MI_INIT (mi, cage, NULL);
+       MI_INIT (mi, cage);
        cp = &cage[MI_SCREEN(mi)];
 
        cp->step = NRAND(90);
index 7f7a8da628a267761048e3f9aaecf21a2ea4c06e..119c9bb6bdbdf130f64e6e87a0b6ff87044ecaf7 100644 (file)
@@ -24,7 +24,7 @@
                  "*grabDesktopImages:   False \n" \
                  "*chooseRandomImages:  True  \n"
 
-# define refresh_carousel 0
+# define free_carousel 0
 # define release_carousel 0
 # include "xlockmore.h"
 
@@ -232,6 +232,11 @@ load_image (ModeInfo *mi, image_frame *frame)
       int h = (MI_HEIGHT(mi) / 2) - 1;
       if (w <= 10) w = 10;
       if (h <= 10) h = 10;
+
+      if (w > h * 5) {   /* tiny window: use 16:9 boxes */
+        h = w * 9/16;
+      }
+
       load_texture_async (mi->xgwa.screen, mi->window, *ss->glx_context, w, h,
                           mipmap_p, frame->loading.texid, 
                           image_loaded_cb, frame);
@@ -399,8 +404,15 @@ ENTRYPOINT void
 reshape_carousel (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, 0, (GLint) width, (GLint) height);
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -563,7 +575,7 @@ init_carousel (ModeInfo *mi)
   carousel_state *ss;
   int wire = MI_IS_WIREFRAME(mi);
   
-  MI_INIT (mi, sss, NULL);
+  MI_INIT (mi, sss);
   ss = &sss[screen];
 
   if ((ss->glx_context = init_GL(mi)) != NULL) {
index e5723d5aec417f2c6e387d157ef6312e1fdfa93a..744e4b68a341cf58e64078928078055608bd8e60 100644 (file)
@@ -35,9 +35,8 @@
                        "*suppressRotationAnimation: True\n" \
                "*componentFont: -*-courier-bold-r-normal-*-*-140-*-*-*-*-*-*"
 
-# define refresh_circuit 0
 # define release_circuit 0
-# define circuit_handle_event 0
+# define circuit_handle_event xlockmore_no_events
 # include "xlockmore.h"                         /* from the xscreensaver distribution */
 #else  /* !STANDALONE */
 # include "xlock.h"                                     /* from the xlockmore distribution */
@@ -94,7 +93,7 @@ ENTRYPOINT ModeSpecOpt circuit_opts = {countof(opts), opts, countof(vars), vars,
 #ifdef USE_MODULES
 ModStruct   circuit_description =
 {"circuit", "init_circuit", "draw_circuit", NULL,
- "draw_circuit", "init_circuit", NULL, &circuit_opts,
+ "draw_circuit", "init_circuit", "free_circuit", &circuit_opts,
  1000, 1, 2, 1, 4, 1.0, "",
  "Flying electronic components", 0, NULL};
 
@@ -2000,8 +1999,16 @@ static void reorder(Component *c[])
 ENTRYPOINT void reshape_circuit(ModeInfo *mi, int width, int height)
 {
  Circuit *ci = &circuit[MI_SCREEN(mi)];
+ int y = 0;
  GLfloat h = (GLfloat) height / (GLfloat) width;
- glViewport(0,0,(GLint)width, (GLint) height);
+
+ if (width > height * 5) {   /* tiny window: show middle */
+   height = width * 9/16;
+   y = -height/2;
+   h = height / (GLfloat) width;
+ }
+
+ glViewport(0,y,(GLint)width, (GLint) height);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glFrustum(-1.0,1.0,-h,h,1.5,35.0);
@@ -2012,14 +2019,12 @@ ENTRYPOINT void reshape_circuit(ModeInfo *mi, int width, int height)
 }
 
 
-static void free_circuit(ModeInfo *mi);
-
 ENTRYPOINT void init_circuit(ModeInfo *mi)
 {
 int screen = MI_SCREEN(mi);
 Circuit *ci;
 
- MI_INIT(mi, circuit, free_circuit);
+ MI_INIT(mi, circuit);
  ci = &circuit[screen];
  ci->window = MI_WINDOW(mi);
 
@@ -2076,7 +2081,7 @@ ENTRYPOINT void draw_circuit(ModeInfo *mi)
   glXSwapBuffers(disp, w);
 }
 
-static void free_circuit(ModeInfo *mi)
+ENTRYPOINT void free_circuit(ModeInfo *mi)
 {
   Circuit *ci = &circuit[MI_SCREEN(mi)];
   if (ci->font)
index ae1397d6dad951d91359a9bb9a1495dce04f2698..2b3bd4fcea33af810fb1c502d169de385e5cc9c1 100644 (file)
@@ -14,7 +14,7 @@
                        "*showFPS:      False       \n" \
                        "*wireframe:    False       \n" \
 
-# define refresh_cube 0
+# define free_cube 0
 # define release_cube 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -99,8 +99,15 @@ ENTRYPOINT void
 reshape_cube (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 2) {   /* tiny window: show middle */
+    height = width;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -290,7 +297,7 @@ init_cube (ModeInfo *mi)
   int i;
   cube_configuration *cc;
 
-  MI_INIT (mi, ccs, NULL);
+  MI_INIT (mi, ccs);
 
   cc = &ccs[MI_SCREEN(mi)];
 
index 10dd959b0cc3fa7451548a2895be70b7196180e9..8b6f8bfd719892163aadc743ca7e859875d6c963 100644 (file)
@@ -26,7 +26,7 @@
 /* #define DEBUG */
 
 
-# define refresh_cube 0
+# define free_cube 0
 # define release_cube 0
 #define DEF_SPEED  "1.0"
 #define DEF_SPIN   "False"
@@ -348,8 +348,15 @@ ENTRYPOINT void
 reshape_cube (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -394,7 +401,7 @@ init_cube (ModeInfo *mi)
   int wire = MI_IS_WIREFRAME(mi);
   int i;
 
-  MI_INIT (mi, bps, NULL);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
index dcbe481bfa9b47502d36eb2a25784e2d4711f8e6..74c691570e2b46d87c2b23303cb353bf4dd25fa2 100644 (file)
@@ -10,7 +10,6 @@
                     "*showFPS:      False       \n" \
                    "*wireframe:    False       \n" \
 
-# define refresh_crackberg 0
 # define release_crackberg 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -1167,7 +1166,6 @@ static inline double drunken_rando(double cur_val, double max, double width)
  ** */
 
 ENTRYPOINT void reshape_crackberg (ModeInfo *mi, int w, int h);
-static void free_crackberg (ModeInfo *mi);
 
 ENTRYPOINT void init_crackberg (ModeInfo *mi)
 {
@@ -1175,7 +1173,7 @@ ENTRYPOINT void init_crackberg (ModeInfo *mi)
 
     nsubdivs %= 16; /* just in case.. */
 
-    MI_INIT(mi, cbergs, free_crackberg);
+    MI_INIT(mi, cbergs);
 
     if (visibility > 1.0 || visibility < 0.2) {
         printf("visibility must be in range [0.2 .. 1.0]\n");
@@ -1457,7 +1455,7 @@ ENTRYPOINT void draw_crackberg (ModeInfo *mi)
 }
 
 /* uh */
-static void free_crackberg (ModeInfo *mi)
+ENTRYPOINT void free_crackberg (ModeInfo *mi)
 {
   cberg_state *cberg = &cbergs[MI_SCREEN(mi)];
   if (cberg->norms)
index 0cfd2123f62d80091a42030feaa9293f40b676b2..a29b47dc7fa29d4dea3c2589a0042f28f590a32f 100644 (file)
@@ -45,7 +45,7 @@
                    "*showFPS:       False         \n" \
                    "*wireframe:     False         \n"
 
-# define refresh_cube21 0
+# define free_cube21 0
 # define release_cube21 0
 #include "xlockmore.h"
 
@@ -846,9 +846,18 @@ static void init_cp(cube21_conf *cp)
 ENTRYPOINT void reshape_cube21(ModeInfo *mi, int width, int height) 
 {
   cube21_conf *cp = &cube21[MI_SCREEN(mi)];
+  int y = 0;
   if(!height) height = 1;
   cp->ratio = (GLfloat)width/(GLfloat)height;
-  glViewport(0, 0, (GLint) width, (GLint) height);
+
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width;
+    y = -height/2;
+    cp->ratio = width / (GLfloat) height;
+    cp->posarg = 0;
+  }
+
+  glViewport(0, y, (GLint) width, (GLint) height);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   gluPerspective(30.0, cp->ratio, 1.0, 100.0);
@@ -873,7 +882,7 @@ cube21_handle_event (ModeInfo *mi, XEvent *event)
 ENTRYPOINT void init_cube21(ModeInfo *mi) 
 {
   cube21_conf *cp;
-  MI_INIT(mi, cube21, NULL);
+  MI_INIT(mi, cube21);
   cp = &cube21[MI_SCREEN(mi)];
 
   cp->trackball = gltrackball_init (False);
index 95d8b6518d127fe1f9cd8a2daef8784c01d1c194..cc9b0d607250c43380f1848b518ae65836c60064 100644 (file)
@@ -15,7 +15,7 @@
                        "*wireframe:    False       \n" \
                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_cube 0
+# define free_cube 0
 # define release_cube 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -187,8 +187,15 @@ ENTRYPOINT void
 reshape_cube (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -392,7 +399,7 @@ init_cube (ModeInfo *mi)
   cube_configuration *cc;
   int wire = MI_IS_WIREFRAME(mi);
 
-  MI_INIT (mi, ccs, NULL);
+  MI_INIT (mi, ccs);
 
   cc = &ccs[MI_SCREEN(mi)];
 
index ee630dedfc580162fc3cbf802cee53da012ad661..70883f6870720d636a073eb5b5381ff923aa6b62 100644 (file)
@@ -14,7 +14,7 @@
                        "*wireframe:    False       \n" \
                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_cube 0
+# define free_cube 0
 # define release_cube 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -287,8 +287,15 @@ ENTRYPOINT void
 reshape_cube (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -347,7 +354,7 @@ init_cube (ModeInfo *mi)
   cube_configuration *bp;
   int wire = MI_IS_WIREFRAME(mi);
 
-  MI_INIT (mi, bps, NULL);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
index 3137c862dcac747a1b8d2e4462233695597d77fc..4ef7fd1b4c5eb24671be4857ab044eb8377c049f 100644 (file)
@@ -17,7 +17,7 @@
                        "*suppressRotationAnimation: True\n" \
 
 
-# define refresh_cube 0
+# define free_cube 0
 # define release_cube 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -162,8 +162,15 @@ ENTRYPOINT void
 reshape_cube (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -226,7 +233,7 @@ init_cube (ModeInfo *mi)
   int wire = MI_IS_WIREFRAME(mi);
   int i;
 
-  MI_INIT (mi, bps, NULL);
+  MI_INIT (mi, bps);
 
 # ifdef HAVE_JWZGLES
   dbuf_p = True;
index 6e11f01faec68d9d3aafebab69ef87bc624873d8..61af2879219bc564d2379a29d0bd54d4ac83d3c2 100644 (file)
@@ -14,7 +14,6 @@
                        "*wireframe:    False       \n" \
                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_cube 0
 # define release_cube 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -341,8 +340,15 @@ ENTRYPOINT void
 reshape_cube (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -417,15 +423,13 @@ cube_handle_event (ModeInfo *mi, XEvent *event)
 }
 
 
-static void free_cube (ModeInfo *mi);
-
 ENTRYPOINT void 
 init_cube (ModeInfo *mi)
 {
   cube_configuration *bp;
   int wire = MI_IS_WIREFRAME(mi);
 
-  MI_INIT (mi, bps, free_cube);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
@@ -566,7 +570,7 @@ draw_cube (ModeInfo *mi)
   glXSwapBuffers(dpy, window);
 }
 
-static void
+ENTRYPOINT void
 free_cube (ModeInfo *mi)
 {
   cube_configuration *bp = &bps[MI_SCREEN(mi)];
index 262b4e41bd418bba999eb7eebcbceae5d565cbbd..34b6c34aed604b91d1d993ecca680343de4b2dbd 100644 (file)
@@ -24,7 +24,7 @@
                    "*wireframe:     False         \n" \
                   "*suppressRotationAnimation: True\n" \
 
-# define refresh_cubicgrid 0
+# define free_cubicgrid 0
 # define release_cubicgrid 0
 #include "xlockmore.h"
 
@@ -192,9 +192,17 @@ static void init_gl(ModeInfo *mi)
 ENTRYPOINT void reshape_cubicgrid(ModeInfo *mi, int width, int height) 
 {
   cubicgrid_conf *cp = &cubicgrid[MI_SCREEN(mi)];
+  int y = 0;
   if(!height) height = 1;
   cp->ratio = (GLfloat)width/(GLfloat)height;
-  glViewport(0, 0, (GLint) width, (GLint) height);
+
+  if (width > height * 3) {   /* tiny window: show middle */
+    height = width;
+    y = -height/2;
+    cp->ratio = (GLfloat)width/(GLfloat)height;
+  }
+
+  glViewport(0, y, (GLint) width, (GLint) height);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   gluPerspective(30.0, cp->ratio, 1.0, 100.0);
@@ -205,7 +213,7 @@ ENTRYPOINT void reshape_cubicgrid(ModeInfo *mi, int width, int height)
 ENTRYPOINT void init_cubicgrid(ModeInfo *mi) 
 {
   cubicgrid_conf *cp;
-  MI_INIT(mi, cubicgrid, NULL);
+  MI_INIT(mi, cubicgrid);
   cp = &cubicgrid[MI_SCREEN(mi)];
 
   if ((cp->glx_context = init_GL(mi)) != NULL) {
index ec39fbe34f0b59dfb9ea279453137c6481faae55..e40ccc531df8731aa37176564ffd9461880dff86 100644 (file)
@@ -15,7 +15,7 @@
                        "*wireframe:    False       \n" \
                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_ball 0
+# define free_ball 0
 # define release_ball 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -89,8 +89,15 @@ ENTRYPOINT void
 reshape_ball (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -204,7 +211,7 @@ init_ball (ModeInfo *mi)
   ball_configuration *bp;
   int wire = MI_IS_WIREFRAME(mi);
 
-  MI_INIT (mi, bps, 0);
+  MI_INIT (mi, bps);
   bp = &bps[MI_SCREEN(mi)];
 
   bp->glx_context = init_GL(mi);
index 015c59a50f5405ed46e64a2d711d98319396885e..4085c56d124b3ec5fe977c9eb21fb7c2c227a35b 100644 (file)
@@ -14,7 +14,6 @@
                        "*showFPS:      False       \n" \
                        "*wireframe:    False       \n" \
 
-# define refresh_ball 0
 # define release_ball 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -499,8 +498,15 @@ ENTRYPOINT void
 reshape_ball (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -538,16 +544,13 @@ ball_handle_event (ModeInfo *mi, XEvent *event)
 }
 
 
-static void free_ball (ModeInfo *mi);
-
-
 ENTRYPOINT void 
 init_ball (ModeInfo *mi)
 {
   ball_configuration *bp;
   int wire = MI_IS_WIREFRAME(mi);
 
-  MI_INIT (mi, bps, free_ball);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
@@ -686,7 +689,7 @@ draw_ball (ModeInfo *mi)
 }
 
 
-static void
+ENTRYPOINT void
 free_ball (ModeInfo *mi)
 {
   ball_configuration *bp = &bps[MI_SCREEN(mi)];
index f9a55ef92110418e17858aa47eac1394f578f9cd..36246176aac7a25f695db27a18559487da933790 100644 (file)
@@ -1,4 +1,4 @@
-/* DNA Logo, Copyright (c) 2001-2016 Jamie Zawinski <jwz@jwz.org>
+/* DNA Logo, Copyright (c) 2001-2017 Jamie Zawinski <jwz@jwz.org>
  *
  *      DNA Lounge
  *
@@ -67,7 +67,7 @@
 #  define CWFONT "-*-helvetica-medium-r-normal-*-*-240-*-*-*-*-*-*"
 # endif
 
-# define refresh_logo 0
+# define free_logo 0
 # define release_logo 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -107,7 +107,9 @@ typedef enum {
   HELIX_IN, HELIX, HELIX_OUT,
   PIZZA_IN, PIZZA, PIZZA_OUT,
   HELIX_AND_PIZZA,
+# ifdef CW
   CODEWORD_IN, CODEWORD, CODEWORD_OUT, CODEWORD_BLANK
+# endif
 } glyph_mode;
 
 typedef struct {
@@ -150,6 +152,7 @@ typedef struct {
   GLfloat frame_thickness;
   GLfloat triangle_size;
 
+# ifdef CW
   int codeword_facets, codeword_disc_facets;
   GLfloat codeword_spread, codeword_line_width, codeword_thickness;
   GLfloat codeword_cap_size;
@@ -162,6 +165,7 @@ typedef struct {
   XYZ *codeword_guides;
   GLfloat codeword_color[4], codeword_bg[4];
   texture_font_data *font;
+# endif
 
   GLfloat speed;
   glyph_mode mode;
@@ -170,7 +174,9 @@ typedef struct {
 
   spinner gasket_spinnerx, gasket_spinnery, gasket_spinnerz;
   spinner scene_spinnerx,  scene_spinnery;     /* for DNA */
+# ifdef CW
   rotator *scene_rot;                          /* for Codeword */
+# endif
   spinner helix_spinnerz;
   spinner pizza_spinnery, pizza_spinnerz;
   spinner frame_spinner;
@@ -190,9 +196,11 @@ static XrmOptionDescRec opts[] = {
   { "-pizza",    ".mode",   XrmoptionNoArg,  "pizza"    },
   { "-helix",    ".mode",   XrmoptionNoArg,  "helix"    },
   { "-both",     ".mode",   XrmoptionNoArg,  "both"     },
+# ifdef CW
   { "-codeword", ".mode",   XrmoptionNoArg,  "codeword" },
   { "-cw",       ".mode",   XrmoptionNoArg,  "codeword" },
   { "-text",     ".text",   XrmoptionSepArg, 0          },
+# endif
 };
 
 ENTRYPOINT ModeSpecOpt logo_opts = {countof(opts), opts, 0, NULL, NULL};
@@ -501,6 +509,9 @@ vector_angle (double ax, double ay, double az,
   return (angle);
 }
 
+
+# ifdef CW
+
 static void
 normalize (XYZ *p)
 {
@@ -524,6 +535,8 @@ dot (const XYZ u, const XYZ v)
   return (u.x * v.x) + (u.y * v.y) + (u.z * v.z);
 }
 
+#endif /* CW */
+
 \f
 /* Make the helix
  */
@@ -1916,6 +1929,8 @@ make_pizza (logo_configuration *dc, int facetted, int wire)
 }
 
 
+# ifdef CW
+
 /* Upcase string, convert Unicrud to ASCII, remove any non-letters.
  */
 static char *
@@ -2713,6 +2728,7 @@ draw_codeword_path (ModeInfo *mi)
   return polys;
 }
 
+#endif /* CW */
 
 \f
 /* Window management, etc
@@ -2790,7 +2806,7 @@ init_logo (ModeInfo *mi)
       exit (1);
     }
 
-  MI_INIT (mi, dcs, NULL);
+  MI_INIT (mi, dcs);
 
   dc = &dcs[MI_SCREEN(mi)];
 
@@ -2820,6 +2836,7 @@ init_logo (ModeInfo *mi)
   dc->triangle_size   = get_float_resource(mi->dpy, "triangleSize",   "Float");
 
   dc->speed           = get_float_resource(mi->dpy, "speed",          "Float");
+# ifdef CW
   dc->codeword_text   = get_string_resource(mi->dpy, "text",         "String");
   dc->codeword_text   = codeword_simplify_text (dc->codeword_text);
   dc->codeword_text_out =
@@ -2835,6 +2852,7 @@ init_logo (ModeInfo *mi)
   dc->codeword_line_width = get_float_resource(mi->dpy, "cwLineWidth", "Float");
   dc->codeword_thickness  = get_float_resource(mi->dpy, "cwThickness", "Float");
   dc->codeword_cap_size = get_float_resource(mi->dpy, "cwCapSize",     "Float");
+# endif
 
   {
     char *s = get_string_resource (MI_DISPLAY (mi), "mode", "String");
@@ -2844,12 +2862,14 @@ init_logo (ModeInfo *mi)
       dc->mode = PIZZA;
     else if (!strcasecmp (s, "both"))
       dc->mode = HELIX_AND_PIZZA;
+# ifdef CW
     else if (!strcasecmp (s, "codeword"))
       dc->mode = CODEWORD_IN;
+# endif
     else
       {
         fprintf (stderr,
-               "%s: mode must be helix, pizza, both or codeword, not \"%s\"\n", 
+               "%s: mode must be helix, pizza or both, not \"%s\"\n", 
                  progname, s);
         exit (1);
       }
@@ -2861,8 +2881,10 @@ init_logo (ModeInfo *mi)
     dc->anim_ratio = 0;
   }
 
+# ifdef CW
   if (dc->mode == CODEWORD_IN)
     dc->font = load_texture_font (MI_DISPLAY(mi), "cwFont");
+# endif
 
   {
     XColor xcolor;
@@ -2900,6 +2922,7 @@ init_logo (ModeInfo *mi)
         exit (1);
       }
 
+# ifdef CW
     dc->codeword_color[0] = xcolor.red   / 65535.0;
     dc->codeword_color[1] = xcolor.green / 65535.0;
     dc->codeword_color[2] = xcolor.blue  / 65535.0;
@@ -2922,6 +2945,7 @@ init_logo (ModeInfo *mi)
     dc->codeword_bg[1] = xcolor.green / 65535.0;
     dc->codeword_bg[2] = xcolor.blue  / 65535.0;
     dc->codeword_bg[3] = 1.0;
+# endif /* CW */
   }
 
   dc->trackball = gltrackball_init (False);
@@ -2949,11 +2973,13 @@ init_logo (ModeInfo *mi)
   dc->scene_spinnerx.easement     = 0.1;
   dc->scene_spinnery.easement     = 0.1;
 
+# ifdef CW
   if (dc->mode == CODEWORD_IN)
     {
       double tilt_speed = 0.003;
       dc->scene_rot = make_rotator (0, 0, 0, 0, tilt_speed, True);
     }
+# endif
 
   /* start the frame off-screen */
   dc->frame_spinner.spinning_p = True;
@@ -3076,8 +3102,9 @@ init_logo (ModeInfo *mi)
   if (do_frame) dc->polys[6] += make_frame (dc, 1);
   glEndList ();
 
+# ifdef CW
   make_codeword_path (mi);
-
+# endif
 
   /* When drawing both solid and wireframe objects,
      make sure the wireframe actually shows up! */
@@ -3111,10 +3138,12 @@ logo_handle_event (ModeInfo *mi, XEvent *event)
             dc->anim_state = PIZZA_OUT;
             dc->anim_ratio = 0.0;
             return True;
+# ifdef CW
           case CODEWORD:
             dc->anim_state = CODEWORD_OUT;
             dc->anim_ratio = 0.0;
             return True;
+# endif
           default:
             break;
           }
@@ -3201,7 +3230,9 @@ draw_logo (ModeInfo *mi)
   GLfloat specular[]  = {0.8, 0.8, 0.8, 1.0};
   GLfloat shininess   = 50.0;
   Bool pizza_p;
+# ifdef CW
   Bool codeword_p;
+# endif
 
   if (!dc->glx_context)
     return;
@@ -3278,6 +3309,7 @@ draw_logo (ModeInfo *mi)
       break;
 
 
+# ifdef CW
     case CODEWORD_IN:
       dc->scene_spinnerx.probability = 0.2;
       dc->scene_spinnery.probability = 0.05;
@@ -3325,6 +3357,7 @@ draw_logo (ModeInfo *mi)
           dc->anim_state = CODEWORD_IN;
         }
       break;
+# endif /* CW */
 
     default:
       abort();
@@ -3335,10 +3368,12 @@ draw_logo (ModeInfo *mi)
              dc->anim_state == PIZZA_IN ||
              dc->anim_state == PIZZA_OUT);
 
+# ifdef CW
   codeword_p = (dc->anim_state == CODEWORD ||
                 dc->anim_state == CODEWORD_IN ||
                 dc->anim_state == CODEWORD_OUT ||
                 dc->anim_state == CODEWORD_BLANK);
+# endif
 
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
@@ -3352,7 +3387,9 @@ draw_logo (ModeInfo *mi)
 
 
     /* Draw frame before trackball rotation */
+# ifdef CW
     if (! codeword_p)
+# endif
       {
         GLfloat p = (dc->frame_spinner.position_eased >= 0
                      ? dc->frame_spinner.position_eased
@@ -3393,7 +3430,9 @@ draw_logo (ModeInfo *mi)
     glRotatef(90, 1, 0, 0);
     glRotatef(90, 0, 0, 1);
 
+# ifdef CW
     if (! codeword_p)
+# endif
       {
         glRotatef (360 * dc->scene_spinnerx.position_eased, 0, 1, 0);
         glRotatef (360 * dc->scene_spinnery.position_eased, 0, 0, 1);
@@ -3492,19 +3531,20 @@ draw_logo (ModeInfo *mi)
             mi->polygon_count += dc->polys[0];
           }
       }
+# ifdef CW
     else       /* codeword_p */
       {
-# if 0
+#  if 0
         double max = 70;  /* face front */
         double x, y, z;
         get_position (dc->scene_rot, &x, &y, &z, !dc->button_down_p);
         glRotatef (max/2 - x*max, 0, 0, 1);
         glRotatef (max/2 - y*max, 0, 1, 0);
         /* glRotatef (max/2 - z*max, 1, 0, 0); */
-# else
+#  else
         glRotatef (360 * dc->scene_spinnerx.position_eased, 0, 1, 0);
         glRotatef (360 * dc->scene_spinnery.position_eased, 0, 0, 1);
-# endif
+#  endif
 
         glClearColor (dc->codeword_bg[0],
                       dc->codeword_bg[1],
@@ -3512,6 +3552,7 @@ draw_logo (ModeInfo *mi)
                       dc->codeword_bg[3]);
         mi->polygon_count += draw_codeword_path (mi);
       }
+# endif /* CW */
   }
   glPopMatrix();
 
index 60fb94f60bcfef835785bf01361b54f11c09ffc5..60843e1aa7a507bd52a7604522acc369a3bf8350 100644 (file)
@@ -21,7 +21,6 @@
                    "*showFPS:          False   \n" \
                    "*wireframe:        False   \n" \
                    "*labelFont:  " LABEL_FONT "\n"
-# define refresh_planet 0
 # define release_planet 0
 # include "xlockmore.h"                    /* from the xscreensaver distribution */
 #else  /* !STANDALONE */
@@ -90,7 +89,7 @@ ENTRYPOINT ModeSpecOpt planet_opts = {countof(opts), opts, countof(vars), vars,
 #ifdef USE_MODULES
 ModStruct   planet_description =
 {"planet", "init_planet", "draw_planet", NULL,
- "draw_planet", "init_planet", NULL, &planet_opts,
+ "draw_planet", "init_planet", "free_planet", &planet_opts,
  1000, 1, 2, 1, 4, 1.0, "",
  "Buckminster Fuller's unwrapped icosahedral globe", 0, NULL};
 #endif
@@ -770,9 +769,6 @@ planet_handle_event (ModeInfo *mi, XEvent *event)
 }
 
 
-static void free_planet (ModeInfo * mi);
-
-
 ENTRYPOINT void
 init_planet (ModeInfo * mi)
 {
@@ -780,7 +776,7 @@ init_planet (ModeInfo * mi)
   int screen = MI_SCREEN(mi);
   Bool wire = MI_IS_WIREFRAME(mi);
 
-  MI_INIT (mi, planets, free_planet);
+  MI_INIT (mi, planets);
   gp = &planets[screen];
 
   if ((gp->glx_context = init_GL(mi)) != NULL) {
@@ -1005,7 +1001,7 @@ draw_planet (ModeInfo * mi)
 }
 
 
-static void
+ENTRYPOINT void
 free_planet (ModeInfo * mi)
 {
   planetstruct *gp = &planets[MI_SCREEN(mi)];
index e69a21c0ec3bbcfad70570ee2ebb1c9e55f55a0f..ddba7f9c34a43119fcd41e4e81442dc1f8d99739 100644 (file)
@@ -20,7 +20,7 @@
                        "*showFPS:   False \n" \
                       "*wireframe: False \n" \
 
-# define refresh_chess 0
+# define free_chess 0
 # define release_chess 0
 # include "xlockmore.h"
 
@@ -787,7 +787,15 @@ static void display(ModeInfo *mi, Chesscreen *cs)
 ENTRYPOINT void reshape_chess(ModeInfo *mi, int width, int height) 
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
-  glViewport(0,0, width, height);
+  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(45, 1/h, 2.0, 30.0);
@@ -800,7 +808,7 @@ ENTRYPOINT void init_chess(ModeInfo *mi)
   Chesscreen *cs;
   int screen = MI_SCREEN(mi);
 
-  MI_INIT(mi, qs, NULL);
+  MI_INIT(mi, qs);
   
   cs = &qs[screen];
   cs->window = MI_WINDOW(mi);
index 3136a2435d5c38dd0c9e819e46c362b5acd3aecd..0f0bc26de93bc5a4e988b9baeeab2f7e48d9e11b 100644 (file)
@@ -17,7 +17,6 @@
       "*showFPS:      False       \n" \
       "*wireframe:    False       \n" \
 
-# define refresh_stream 0
 # define release_stream 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -308,15 +307,13 @@ static void render_flare_stream (flare_stream *s, float cur_time, Vector *vx, Ve
   glEnd ();
 }
 
-static void free_stream (ModeInfo * mi);
-
 ENTRYPOINT void
 init_stream (ModeInfo *mi)
 {
   stream_configuration *es;
   streamtime current_time;
 
-  MI_INIT (mi, ess, free_stream);
+  MI_INIT (mi, ess);
 
   es = &ess[MI_SCREEN(mi)];
 
@@ -364,7 +361,7 @@ init_stream (ModeInfo *mi)
   }
 }
 
-static void
+ENTRYPOINT void
 free_stream (ModeInfo * mi)
 {
   stream_configuration *es = &ess[MI_SCREEN(mi)];
index f26f68d10ae86359885ff8169ed74f3850157cb5..0f39b8da7af640d7308a7fb42ba032085832053d 100644 (file)
@@ -27,7 +27,7 @@
                        "*suppressRotationAnimation: True\n" \
        "*titleFont:  -*-helvetica-medium-r-normal-*-*-180-*-*-*-*-*-*\n" \
 
-# define refresh_engine 0
+# define free_engine 0
 # define release_engine 0
 # include "xlockmore.h"              /* from the xscreensaver distribution */
 #else  /* !STANDALONE */
@@ -847,11 +847,19 @@ static int makeshaft (Engine *e)
 ENTRYPOINT void reshape_engine(ModeInfo *mi, int width, int height)
 {
  Engine *e = &engine[MI_SCREEN(mi)];
- glViewport(0,0,(GLint)width, (GLint) height);
+ double 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();
-/* glFrustum(-1.0,1.0,-1.0,1.0,1.5,70.0);*/
- gluPerspective(40.0,((GLdouble)width)/height,1.5,70.0);
+ gluPerspective(40, 1/h, 1.5, 70.0);
  glMatrixMode(GL_MODELVIEW);
  e->win_h = height; 
  e->win_w = width;
@@ -863,7 +871,7 @@ ENTRYPOINT void init_engine(ModeInfo *mi)
   int screen = MI_SCREEN(mi);
   Engine *e;
 
- MI_INIT(mi, engine, NULL);
+ MI_INIT(mi, engine);
  e = &engine[screen];
  e->window = MI_WINDOW(mi);
 
diff --git a/hacks/glx/erase-gl.c b/hacks/glx/erase-gl.c
new file mode 100644 (file)
index 0000000..8515dd9
--- /dev/null
@@ -0,0 +1,38 @@
+/* Copyright (c) 2017 Dave Odell <dmo2118@gmail.com>
+ *
+ * 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.
+ *
+ * xlockmore.c has references to erase_window, but it never calls these when
+ * running OpenGL hacks. Using this in place of regular utils/erase.c saves a
+ * tiny bit of code/disk space with a native X11 build, where everything is
+ * statically linked together.
+ *
+ * (Linux, amd64, CFLAGS='-O2 -g')
+ * Before: -rwxr-xr-x 1 david david 545848 Aug  9 20:42 hilbert
+ * After:  -rwxr-xr-x 1 david david 519344 Aug  9 20:41 hilbert
+ *
+ * (Linux, amd64, CFLAGS=-O2)
+ * Before: -rwxr-xr-x 1 david david 150168 Aug  9 20:40 hilbert
+ * After:  -rwxr-xr-x 1 david david 141256 Aug  9 20:39 hilbert
+ */
+
+#include "utils.h"
+#include "erase.h"
+
+void
+eraser_free (eraser_state *st)
+{
+}
+
+
+eraser_state *
+erase_window (Display *dpy, Window window, eraser_state *st)
+{
+  return st;
+}
diff --git a/hacks/glx/esper.c b/hacks/glx/esper.c
new file mode 100644 (file)
index 0000000..20efa32
--- /dev/null
@@ -0,0 +1,2408 @@
+/* esper, Copyright (c) 2017 Jamie Zawinski <jwz@jwz.org>
+ * Enhance 224 to 176. Pull out track right. Center in pull back.
+ * Pull back. Wait a minute. Go right. Stop. Enhance 57 19. Track 45 left.
+ * Gimme a hardcopy right there.
+ *
+ * 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.
+ */
+
+/*
+  The Esper machine has a 4:3 display, about 12" diagonal.
+  The display is overlayed with a 10x7 grid of blue lines.
+  The scene goes approximately like this:
+
+      "Enhance 224 To 176."
+
+          ZM 0000  NS 0000  EW 0000
+
+      The reticle is displayed centered.
+      It moves in 8 steps with 3 frame blur to move to around to grid 1,4.
+
+          ZM 0000  NS 0000  EW 0000
+          ZM 0000  NS 0001  EW 0001
+          ZM 0000  NS 0001  EW 0002
+          ZM 0000  NS 0002  EW 0003
+          ZM 0000  NS 0003  EW 0005
+          ZM 0000  NS 0004  EW 0008
+          ZM 0000  NS 0015  EW 0011
+
+      These numbers appear to have little relation to what we are
+      actually seeing on the screen.  Also the same numbers are
+      repeated later when looking at totally different parts of
+      the photograph.
+
+          ZM 0000  NS 0117  EW 0334
+
+      The box appears: 8 steps, final box is 1.5x2.25 at -0.5,4.0.
+
+          ZM 4086  NS 0117  EW 0334
+
+      The box blinks yellow 5x.
+      The image's zoom-and-pan takes 8 steps, with no text on the screen.
+      The zoom is in discreet steps, with flashes.
+      The grid stays the same size the whole time.
+      The flashes look like solarization to blue.
+      When the zoom is finished, there is still no text.
+
+      "Enhance."  Goes 4 more ticks down the same hole?
+      "Stop."  Moves up a little bit at the end.
+
+      Then with no instructions, it goes 20 ticks by itself, off camera.
+
+      "Move in."  10 ticks.
+      "Stop."  (We are looking at a fist in the picture.)
+      "Pull out track right."
+      "Stop."  (We are looking at a newspaper.)
+      "Center and pull back."
+      "Stop."  (We just passed the round mirror.)
+      "Track 45 right."
+      "Stop."
+      "Center and stop."
+
+      This time there was no grid until it stopped, then the grid showed up.
+      There is video tearing at the bottom.
+
+      "Enhance 34 to 36."
+
+          ZM 0000  NS 0063  EW 0185
+          ZM 0000  NS 0197  EW 0334
+          ZM 3841  NS 0197  EW 0334
+
+      It kind of zooms in to the center wobbly and willy-nilly.
+      We are now looking at a glass.
+
+      "Pan right and pull back."  (There is no grid while moving again.)
+      "Stop."
+
+      Ok, at this point, we enter fantasy-land.  From here on, the images
+      shown are very high resolution with no noise.  And suddenly the 
+      UI on the Esper is *way* higher resolution.  My theory is that from
+      this point on in the scene, we are not looking at the literal Esper
+      machine, but instead the movie is presenting Decard's perception of
+      it.  We're seeing the room, not the photo of the room.  The map has
+      become the territory. 
+
+      "Enhance 34 to 46."
+
+          ZM 0000  NS 0197  EW 0334
+
+      This has the reticle and box only, no grid, ends with no grid.
+
+      "Pull back."
+      "Wait a minute. Go right."
+      "Stop."
+      Now it's going around the corner or something.
+
+      "Enhance 57 19."
+      This has a reticle then box, but the image started zooming early.
+
+      "Track 45 left."
+      zooms out and moves left
+
+      "Stop."  (O hai Zhora.)
+      "Enhance 15 to 23."
+
+          ZM 3852  NS 0197  EW 0334
+
+      "Gimme a hardcopy right there."
+
+      The printer polaroid is WAY lower resolution than the image we see on
+      the "screen" -- in keeping with my theory that we were not seeing the
+      screen.
+
+
+  TODO:
+
+  * There's a glitch at the top/bottom of the texfont textures.
+  * "Pull back" isn't quite symmetric: zoom origin is slightly off.
+  * Maybe display text like "Pull right" and "Stop".
+*/
+
+
+/* Use a small point size to keep it nice and grainy. */
+#if defined(HAVE_COCOA) || defined(HAVE_ANDROID)
+# define TITLE_FONT "OCR A Std 10, Lucida Console 10, Monaco 10"
+#else  /* real X11 */
+# define TITLE_FONT "-*-courier-bold-r-*-*-*-100-*-*-m-*-*-*"
+#endif
+
+#define DEFAULTS  "*delay:           20000                \n" \
+                 "*wireframe:       False                \n" \
+                  "*showFPS:         False                \n" \
+                  "*fpsTop:          True                 \n" \
+                 "*useSHM:          True                 \n" \
+                  "*titleFont: "     TITLE_FONT          "\n" \
+                  "*desktopGrabber:  xscreensaver-getimage -no-desktop %s\n" \
+                 "*grabDesktopImages:   False \n" \
+                 "*chooseRandomImages:  True  \n" \
+                 "*gridColor:    #4444FF\n" \
+                 "*reticleColor: #FFFF77\n" \
+                 "*textColor:    #FFFFBB\n" \
+
+# define free_esper 0
+# define refresh_esper 0
+# define release_esper 0
+# include "xlockmore.h"
+
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+#undef RANDSIGN
+#define RANDSIGN() ((random() & 1) ? 1 : -1)
+#undef BELLRAND
+#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3)
+
+#ifdef USE_GL
+
+#undef SMOOTH
+
+# define DEF_GRID_SIZE      "11"
+# define DEF_GRID_THICKNESS "15"
+# define DEF_TITLES         "True"
+# define DEF_SPEED          "1.0"
+# define DEF_DEBUG          "False"
+
+#include "grab-ximage.h"
+#include "texfont.h"
+
+#ifdef HAVE_XSHM_EXTENSION
+# include "xshm.h"  /* to get <sys/shm.h> */
+#endif
+
+
+typedef struct {
+  double x, y, w, h;
+} rect;
+
+typedef struct {
+  ModeInfo *mi;
+  unsigned long id;               /* unique */
+  char *title;                    /* the filename of this image */
+  int w, h;                       /* size in pixels of the image */
+  int tw, th;                     /* size in pixels of the texture */
+  XRectangle geom;                /* where in the image the bits are */
+  Bool loaded_p;                  /* whether the image has finished loading */
+  Bool used_p;                    /* whether the image has yet appeared
+                                      on screen */
+  GLuint texid;                           /* which texture contains the image */
+  int refcount;                           /* how many sprites refer to this image */
+} image;
+
+
+typedef enum {
+  BLANK,
+  GRID_ON,
+  IMAGE_LOAD,
+  IMAGE_UNLOAD,
+  IMAGE_FORCE_UNLOAD,
+  REPOSITION,
+  RETICLE_ON,
+  RETICLE_MOVE,
+  BOX_MOVE,
+  IMAGE_ZOOM,
+  MANUAL_RETICLE_ON,
+  MANUAL_RETICLE,
+  MANUAL_BOX_ON,
+  MANUAL_BOX,
+} anim_state;
+
+typedef enum { NEW, IN, FULL, OUT, DEAD } sprite_state;
+typedef enum { IMAGE, RETICLE, BOX, GRID, FLASH, TEXT } sprite_type;
+
+typedef struct {
+  unsigned long id;               /* unique */
+  sprite_type type;
+  image *img;                     /* type = IMAGE */
+  unsigned long text_id;          /* type = TEXT */
+  char *text;
+  GLfloat opacity;
+  GLfloat thickness_scale;        /* line and image types */
+  Bool throb_p;
+  double start_time;              /* when this animation began */
+  double duration;                /* lifetime of sprite in seconds; 0 = inf */
+  double fade_duration;                   /* speed of fade in and fade out */
+  double pause_duration;          /* delay before fade-in starts */
+  Bool remain_p;                  /* pause forever before fade-out */
+  rect from, to, current;         /* the journey this image is taking */
+  sprite_state state;             /* the state we're in right now */
+  double state_time;              /* time of last state change */
+  int frame_count;                /* frames since last state change */
+  Bool fatbits_p;                 /* For image texture rendering */    
+  Bool back_p;                    /* If BOX, zooming out, not in */
+} sprite;
+
+
+typedef struct {
+  GLXContext *glx_context;
+  int nimages;                 /* how many images are loaded or loading now */
+  image *images[10];           /* pointers to the images */
+
+  int nsprites;                        /* how many sprites are animating right now */
+  sprite *sprites[100];                /* pointers to the live sprites */
+
+  double now;                  /* current time in seconds */
+  double dawn_of_time;         /* when the program launched */
+  double image_load_time;      /* time when we last loaded a new image */
+
+  texture_font_data *font_data;
+
+  int sprite_id, image_id;      /* debugging id counters */
+
+  GLfloat grid_color[4], reticle_color[4], text_color[4];
+
+  anim_state anim_state;       /* Counters for global animation state, */
+  double anim_start, anim_duration;
+
+  Bool button_down_p;
+
+} esper_state;
+
+static esper_state *sss = NULL;
+
+
+/* Command-line arguments
+ */
+static int grid_size;
+static int grid_thickness;
+
+static Bool do_titles;     /* Display image titles. */
+static GLfloat speed;
+static Bool debug_p;       /* Be loud and do weird things. */
+
+
+static XrmOptionDescRec opts[] = {
+  { "-speed",      ".speed",     XrmoptionSepArg, 0 },
+  { "-titles",     ".titles",    XrmoptionNoArg, "True"  },
+  { "-no-titles",  ".titles",    XrmoptionNoArg, "False" },
+  { "-debug",      ".debug",     XrmoptionNoArg, "True"  },
+};
+
+static argtype vars[] = {
+  { &grid_size,     "gridSize",     "GridSize",     DEF_GRID_SIZE,      t_Int},
+  { &grid_thickness,"gridThickness","GridThickness",DEF_GRID_THICKNESS, t_Int},
+  { &do_titles,     "titles",       "Titles",       DEF_TITLES,        t_Bool},
+  { &speed,         "speed",        "Speed",        DEF_SPEED,        t_Float},
+  { &debug_p,       "debug",        "Debug",        DEF_DEBUG,         t_Bool},
+};
+
+ENTRYPOINT ModeSpecOpt esper_opts = {countof(opts), opts, countof(vars), vars, NULL};
+
+
+/* Returns the current time in seconds as a double.
+ */
+static double
+double_time (void)
+{
+  struct timeval now;
+# ifdef GETTIMEOFDAY_TWO_ARGS
+  struct timezone tzp;
+  gettimeofday(&now, &tzp);
+# else
+  gettimeofday(&now);
+# endif
+
+  return (now.tv_sec + ((double) now.tv_usec * 0.000001));
+}
+
+static const char *
+state_name (anim_state s)
+{
+  switch (s) {
+  case BLANK:         return "BLANK";
+  case GRID_ON:       return "GRID_ON";
+  case IMAGE_LOAD:    return "IMAGE_LOAD";
+  case IMAGE_UNLOAD:  return "IMAGE_UNLOAD";
+  case IMAGE_FORCE_UNLOAD: return "IMAGE_FORCE_UNLOAD";
+  case REPOSITION:    return "REPOSITION";
+  case RETICLE_ON:    return "RETICLE_ON";
+  case RETICLE_MOVE:  return "RETICLE_MOVE";
+  case BOX_MOVE:      return "BOX_MOVE";
+  case IMAGE_ZOOM:    return "IMAGE_ZOOM";
+  case MANUAL_BOX_ON: return "MANUAL_BOX_ON";
+  case MANUAL_BOX:    return "MANUAL_BOX";
+  case MANUAL_RETICLE_ON: return "MANUAL_RETICLE_ON";
+  case MANUAL_RETICLE:    return "MANUAL_RETICLE";
+  default:            return "UNKNOWN";
+  }
+}
+
+
+static void image_loaded_cb (const char *filename, XRectangle *geom,
+                             int image_width, int image_height,
+                             int texture_width, int texture_height,
+                             void *closure);
+
+
+/* Allocate an image structure and start a file loading in the background.
+ */
+static image *
+alloc_image (ModeInfo *mi)
+{
+  esper_state *ss = &sss[MI_SCREEN(mi)];
+  int wire = MI_IS_WIREFRAME(mi);
+  image *img = (image *) calloc (1, sizeof (*img));
+
+  img->id = ++ss->image_id;
+  img->loaded_p = False;
+  img->used_p = False;
+  img->mi = mi;
+
+  glGenTextures (1, &img->texid);
+  if (img->texid <= 0) abort();
+
+  ss->image_load_time = ss->now;
+
+  if (wire)
+    image_loaded_cb (0, 0, 0, 0, 0, 0, img);
+  else
+    {
+      /* If possible, load images at much higher resolution than the window,
+         to facilitate deep zooms.
+       */
+      int max_max = 4096;  /* ~12 megapixels */
+      int max = 0;
+
+# if defined(HAVE_XSHM_EXTENSION) && \
+     !defined(HAVE_MOBILE) && \
+     !defined(HAVE_COCOA)
+
+      /* Try not to ask for an image larger than the SHM segment size.
+         If XSHM fails in a real-X11 world, it can take a staggeringly long
+         time to transfer the image bits from the server over Xproto -- like,
+         *18 seconds* for 4096 px and 8 seconds for 3072 px on MacOS XQuartz.
+         What madness is this?
+       */
+      unsigned long shmmax = 0;
+
+#  if defined(SHMMAX)
+      /* Linux 2.6 defines this to be 0x2000000, but on CentOS 6.9,
+         "sysctl kernel.shmmax" reports a luxurious 0x1000000000. */
+      shmmax = SHMMAX;
+#  elif defined(__APPLE__)
+      /* MacOS 10.13 "sysctl kern.sysv.shmmax" is paltry: */
+      shmmax = 0x400000;
+#  endif /* !SHMMAX */
+
+      if (shmmax)
+        {
+          /* Roughly, bytes => NxN. b = (n/8)*4n = n*n*4, so n^2 = 2b, so: */
+          unsigned long n = sqrt(shmmax)/2;
+          if (n < max_max)
+            max_max = n;
+        }
+# endif /* HAVE_XSHM_EXTENSION and real X11 */
+
+      glGetIntegerv (GL_MAX_TEXTURE_SIZE, &max);
+      if (max > max_max) max = max_max;
+
+      /* Never ask for an image smaller than the window, even if that
+         will make XSHM fall back to Xproto. */
+      if (max < MI_WIDTH(mi) || max < MI_HEIGHT(mi))
+        max = 0;
+
+      load_texture_async (mi->xgwa.screen, mi->window, *ss->glx_context,
+                          max, max, False, img->texid, image_loaded_cb, img);
+    }
+
+  ss->images[ss->nimages++] = img;
+  if (ss->nimages >= countof(ss->images)) abort();
+
+  return img;
+}
+
+
+/* Callback that tells us that the texture has been loaded.
+ */
+static void
+image_loaded_cb (const char *filename, XRectangle *geom,
+                 int image_width, int image_height,
+                 int texture_width, int texture_height,
+                 void *closure)
+{
+  image *img = (image *) closure;
+  ModeInfo *mi = img->mi;
+  int ow, oh;
+  /* esper_state *ss = &sss[MI_SCREEN(mi)]; */
+
+  int wire = MI_IS_WIREFRAME(mi);
+
+  if (wire)
+    {
+      img->w = MI_WIDTH (mi) * (0.5 + frand (1.0));
+      img->h = MI_HEIGHT (mi);
+      img->geom.width  = img->w;
+      img->geom.height = img->h;
+      goto DONE;
+    }
+
+  if (image_width == 0 || image_height == 0)
+    exit (1);
+
+  img->w  = image_width;
+  img->h  = image_height;
+  img->tw = texture_width;
+  img->th = texture_height;
+  img->geom = *geom;
+  img->title = (filename ? strdup (filename) : 0);
+
+  ow = img->geom.width;
+  oh = img->geom.height;
+
+  /* If the image's width doesn't come back as the width of the screen,
+     then the image must have been scaled down (due to insufficient
+     texture memory.)  Scale up the coordinates to stretch the image
+     to fill the window.
+   */
+  if (img->w != MI_WIDTH(mi))
+    {
+      double scale = (double) MI_WIDTH(mi) / img->w;
+      img->w  *= scale;
+      img->h  *= scale;
+      img->tw *= scale;
+      img->th *= scale;
+      img->geom.x      *= scale;
+      img->geom.y      *= scale;
+      img->geom.width  *= scale;
+      img->geom.height *= scale;
+    }
+
+  /* xscreensaver-getimage returns paths relative to the image directory
+     now, so leave the sub-directory part in.  Unless it's an absolute path.
+  */
+  if (img->title && img->title[0] == '/')
+    {
+      /* strip filename to part between last "/" and last ".". */
+      char *s = strrchr (img->title, '/');
+      if (s) strcpy (img->title, s+1);
+      s = strrchr (img->title, '.');
+      if (s) *s = 0;
+    }
+
+# if !(__APPLE__ && TARGET_IPHONE_SIMULATOR || !defined(__OPTIMIZE__))
+  if (debug_p)
+# endif
+    fprintf (stderr, "%s: loaded %lu \"%s\" %dx%d\n",
+             progname, img->id, (img->title ? img->title : "(null)"),
+             ow, oh);
+ DONE:
+
+  img->loaded_p = True;
+}
+
+
+
+/* Free the image and texture, after nobody is referencing it.
+ */
+static void
+destroy_image (ModeInfo *mi, image *img)
+{
+  esper_state *ss = &sss[MI_SCREEN(mi)];
+  Bool freed_p = False;
+  int i;
+
+  if (!img) abort();
+  if (!img->loaded_p) abort();
+  if (!img->used_p) abort();
+  if (img->texid <= 0) abort();
+  if (img->refcount != 0) abort();
+
+  for (i = 0; i < ss->nimages; i++)            /* unlink it from the list */
+    if (ss->images[i] == img)
+      {
+        int j;
+        for (j = i; j < ss->nimages-1; j++)    /* pull remainder forward */
+          ss->images[j] = ss->images[j+1];
+        ss->images[j] = 0;
+        ss->nimages--;
+        freed_p = True;
+        break;
+      }
+
+  if (!freed_p) abort();
+
+  if (debug_p)
+    fprintf (stderr, "%s: unloaded img %2lu: \"%s\"\n",
+             progname, img->id, (img->title ? img->title : "(null)"));
+
+  if (img->title) free (img->title);
+  glDeleteTextures (1, &img->texid);
+  free (img);
+}
+
+
+/* Return an image to use for a sprite.
+   If it's time for a new one, get a new one.
+   Otherwise, use an old one.
+   Might return 0 if the machine is really slow.
+ */
+static image *
+get_image (ModeInfo *mi)
+{
+  esper_state *ss = &sss[MI_SCREEN(mi)];
+  image *img = 0;
+  image *loading_img = 0;
+  int i;
+
+  for (i = 0; i < ss->nimages; i++)
+    {
+      image *img2 = ss->images[i];
+      if (!img2) abort();
+      if (!img2->loaded_p)
+        loading_img = img2;
+      else
+        img = img2;
+    }
+
+  /* Make sure that there is always one unused image in the pipe.
+   */
+  if (!img && !loading_img)
+    alloc_image (mi);
+
+  return img;
+}
+
+
+/* Allocate a new sprite and start its animation going.
+ */
+static sprite *
+new_sprite (ModeInfo *mi, sprite_type type)
+{
+  esper_state *ss = &sss[MI_SCREEN(mi)];
+  image *img = (type == IMAGE ? get_image (mi) : 0);
+  sprite *sp;
+
+  if (type == IMAGE && !img)
+    {
+      /* Oops, no images yet!  The machine is probably hurting bad.
+         Let's give it some time before thrashing again. */
+      usleep (250000);
+      return 0;
+    }
+
+  sp = (sprite *) calloc (1, sizeof (*sp));
+  sp->id = ++ss->sprite_id;
+  sp->type = type;
+  sp->start_time = ss->now;
+  sp->state_time = sp->start_time;
+  sp->thickness_scale = 1;
+  sp->throb_p = True;
+  sp->to.x = 0.5;
+  sp->to.y = 0.5;
+  sp->to.w = 1.0;
+  sp->to.h = 1.0;
+
+  if (img)
+    {
+      sp->img = img;
+      sp->img->refcount++;
+      sp->img->used_p = True;
+      sp->duration = 0;   /* forever, until further notice */
+      sp->fade_duration = 0.5;
+
+      /* Scale the sprite so that the image bits fill the window. */
+      {
+        double w = MI_WIDTH(mi);
+        double h = MI_HEIGHT(mi);
+        double r;
+        r = ((img->geom.height / (double) img->geom.width) * (w / h));
+        if (r > 1)
+          sp->to.h *= r;
+        else
+          sp->to.w /= r;
+      }
+
+      /* Pan to a random spot */
+      if (sp->to.h > 1)
+        sp->to.y += frand ((sp->to.h - 1) / 2) * RANDSIGN();
+      if (sp->to.w > 1)
+        sp->to.x += frand ((sp->to.w - 1) / 2) * RANDSIGN();
+    }
+
+  sp->from = sp->current = sp->to;
+
+  ss->sprites[ss->nsprites++] = sp;
+  if (ss->nsprites >= countof(ss->sprites)) abort();
+
+  return sp;
+}
+
+
+static sprite *
+copy_sprite (ModeInfo *mi, sprite *old)
+{
+  sprite *sp = new_sprite (mi, (sprite_type) ~0L);
+  int id;
+  double tt = sp->start_time;
+  if (!sp) abort();
+  id = sp->id;
+  memcpy (sp, old, sizeof(*sp));
+  sp->id = id;
+  sp->state = NEW;
+  sp->state_time = sp->start_time = tt;
+  if (sp->img)
+    sp->img->refcount++;
+  return sp;
+}
+
+
+/* Free the given sprite, and decrement the reference count on its image.
+ */
+static void
+destroy_sprite (ModeInfo *mi, sprite *sp)
+{
+  esper_state *ss = &sss[MI_SCREEN(mi)];
+  Bool freed_p = False;
+  image *img;
+  int i;
+
+  if (!sp) abort();
+  if (sp->state != DEAD) abort();
+  img = sp->img;
+
+  if (sp->type != IMAGE)
+    {
+      if (img) abort();
+    }
+  else
+    {
+      if (!img) abort();
+      if (!img->loaded_p) abort();
+      if (!img->used_p) abort();
+      if (img->refcount <= 0) abort();
+    }
+
+  for (i = 0; i < ss->nsprites; i++)           /* unlink it from the list */
+    if (ss->sprites[i] == sp)
+      {
+        int j;
+        for (j = i; j < ss->nsprites-1; j++)   /* pull remainder forward */
+          ss->sprites[j] = ss->sprites[j+1];
+        ss->sprites[j] = 0;
+        ss->nsprites--;
+        freed_p = True;
+        break;
+      }
+
+  if (!freed_p) abort();
+  if (sp->text) free (sp->text);
+  free (sp);
+  sp = 0;
+
+  if (img)
+    {
+      img->refcount--;
+      if (img->refcount < 0) abort();
+      if (img->refcount == 0)
+        destroy_image (mi, img);
+    }
+}
+
+
+/* Updates the sprite for the current frame of the animation based on
+   its creation time compared to the current wall clock.
+ */
+static void
+tick_sprite (ModeInfo *mi, sprite *sp)
+{
+  esper_state *ss = &sss[MI_SCREEN(mi)];
+  image *img = sp->img;
+  double now = ss->now;
+  double secs;
+  double ratio;
+  GLfloat visible = sp->duration + sp->fade_duration * 2;
+  GLfloat total = sp->pause_duration + visible;
+
+  if (sp->type != IMAGE)
+    {
+      if (sp->img) abort();
+    }
+  else
+    {
+      if (! sp->img) abort();
+      if (! img->loaded_p) abort();
+    }
+
+  /*          pause        fade  duration        fade
+     |------------|------------|---------|-----------|
+                   ....----====##########====----....
+               from             current            to
+   */
+
+  secs = now - sp->start_time;
+  ratio = (visible <= 0 ? 1 : ((secs - sp->pause_duration) / visible));
+  if (ratio < 0) ratio = 0;
+  else if (ratio > 1) ratio = 1;
+
+  sp->current.x = sp->from.x + ratio * (sp->to.x - sp->from.x);
+  sp->current.y = sp->from.y + ratio * (sp->to.y - sp->from.y);
+  sp->current.w = sp->from.w + ratio * (sp->to.w - sp->from.w);
+  sp->current.h = sp->from.h + ratio * (sp->to.h - sp->from.h);
+
+  sp->thickness_scale = 1;
+
+  if (secs < sp->pause_duration)
+    {
+      sp->state = IN;
+      sp->opacity = 0;
+    }
+  else if (secs < sp->pause_duration + sp->fade_duration)
+    {
+      sp->state = IN;
+      sp->opacity = (secs - sp->pause_duration) / (GLfloat) sp->fade_duration;
+    }
+  else if (sp->duration == 0 ||  /* 0 means infinite lifetime */
+           sp->remain_p ||
+           secs < sp->pause_duration + sp->fade_duration + sp->duration)
+    {
+      sp->state = FULL;
+      sp->opacity = 1;
+
+      /* Just after reaching full opacity, pulse the width up and down. */
+      if (sp->fade_duration > 0 &&
+          secs < sp->pause_duration + sp->fade_duration * 2)
+        {
+          GLfloat f = ((secs - (sp->pause_duration + sp->fade_duration)) /
+                       sp->fade_duration);
+          if (sp->throb_p)
+            sp->thickness_scale = 1 + 3 * (f > 0.5 ? 1-f : f);
+        }
+    }
+  else if (secs < total)
+    {
+      sp->state = OUT;
+      sp->opacity = (total - secs) / sp->fade_duration;
+    }
+  else
+    {
+      sp->state = DEAD;
+      sp->opacity = 0;
+    }
+
+  sp->frame_count++;
+}
+
+
+/* Draw the given sprite at the phase of its animation dictated by
+   its creation time compared to the current wall clock.
+ */
+static void
+draw_image_sprite (ModeInfo *mi, sprite *sp)
+{
+  /* esper_state *ss = &sss[MI_SCREEN(mi)]; */
+  int wire = MI_IS_WIREFRAME(mi);
+  image *img = sp->img;
+
+  if (! sp->img) abort();
+  if (! img->loaded_p) abort();
+
+  glPushMatrix();
+  {
+    GLfloat s = 1 + (sp->thickness_scale - 1) / 40.0;
+    glTranslatef (0.5, 0.5, 0);
+    glScalef (s, s, 1);
+    glTranslatef (-0.5, -0.5, 0);
+
+    glTranslatef (sp->current.x, sp->current.y, 0);
+    glScalef (sp->current.w, sp->current.h, 1);
+
+    glTranslatef (-0.5, -0.5, 0);
+
+    if (wire)                  /* Draw a grid inside the box */
+      {
+        GLfloat dy = 0.1;
+        GLfloat dx = dy * img->w / img->h;
+        GLfloat x, y;
+
+        if (sp->id & 1)
+          glColor4f (sp->opacity, 0, 0, 1);
+        else
+          glColor4f (0, 0, sp->opacity, 1);
+
+        glBegin(GL_LINES);
+        glVertex3f (0, 0, 0); glVertex3f (1, 1, 0);
+        glVertex3f (1, 0, 0); glVertex3f (0, 1, 0);
+
+        for (y = 0; y < 1+dy; y += dy)
+          {
+            GLfloat yy = (y > 1 ? 1 : y);
+            for (x = 0.5; x < 1+dx; x += dx)
+              {
+                GLfloat xx = (x > 1 ? 1 : x);
+                glVertex3f (0, xx, 0); glVertex3f (1, xx, 0);
+                glVertex3f (yy, 0, 0); glVertex3f (yy, 1, 0);
+              }
+            for (x = 0.5; x > -dx; x -= dx)
+              {
+                GLfloat xx = (x < 0 ? 0 : x);
+                glVertex3f (0, xx, 0); glVertex3f (1, xx, 0);
+                glVertex3f (yy, 0, 0); glVertex3f (yy, 1, 0);
+              }
+          }
+        glEnd();
+      }
+    else                       /* Draw the texture quad */
+      {
+        GLfloat texw  = img->geom.width  / (GLfloat) img->tw;
+        GLfloat texh  = img->geom.height / (GLfloat) img->th;
+        GLfloat texx1 = img->geom.x / (GLfloat) img->tw;
+        GLfloat texy1 = img->geom.y / (GLfloat) img->th;
+        GLfloat texx2 = texx1 + texw;
+        GLfloat texy2 = texy1 + texh;
+        GLfloat o = sp->opacity;
+        GLint mag = (sp->fatbits_p ? GL_NEAREST : GL_LINEAR);
+
+        glBindTexture (GL_TEXTURE_2D, img->texid);
+
+        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag);
+        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mag);
+
+        /* o = 1 - sin ((1 - o*o*o) * M_PI/2); */
+        glColor4f (1, 1, 1, o);
+
+        glNormal3f (0, 0, 1);
+        glBegin (GL_QUADS);
+        glTexCoord2f (texx1, texy2); glVertex3f (0, 0, 0);
+        glTexCoord2f (texx2, texy2); glVertex3f (1, 0, 0);
+        glTexCoord2f (texx2, texy1); glVertex3f (1, 1, 0);
+        glTexCoord2f (texx1, texy1); glVertex3f (0, 1, 0);
+        glEnd();
+
+        if (debug_p)           /* Draw a border around the image */
+          {
+            if (!wire) glDisable (GL_TEXTURE_2D);
+            glColor4f (sp->opacity, 0, 0, 1);
+            glBegin (GL_LINE_LOOP);
+            glVertex3f (0, 0, 0);
+            glVertex3f (0, 1, 0);
+            glVertex3f (1, 1, 0);
+            glVertex3f (1, 0, 0);
+            glEnd();
+            if (!wire) glEnable (GL_TEXTURE_2D);
+          }
+      }
+  }
+  glPopMatrix();
+}
+
+
+static void
+draw_line_sprite (ModeInfo *mi, sprite *sp)
+{
+  esper_state *ss = &sss[MI_SCREEN(mi)];
+  int wire = MI_IS_WIREFRAME(mi);
+  int w = MI_WIDTH(mi);
+  int h = MI_HEIGHT(mi);
+  int wh = (w > h ? w : h);
+  int gs = (sp->type == RETICLE ? grid_size+1 : grid_size);
+  int sx = wh / (gs + 1);
+  int sy;
+  int k;
+  GLfloat t = grid_thickness * sp->thickness_scale;
+  int fade;
+  GLfloat color[4];
+
+  GLfloat x  = w * sp->current.x;
+  GLfloat y  = h * sp->current.y;
+  GLfloat bw = w * sp->current.w;
+  GLfloat bh = h * sp->current.h;
+
+  if (sx < 10) sx = 10;
+  sy = sx;
+
+  if (t > sx/3) t = sx/3;
+  if (t < 1) t = 1;
+  fade = t;
+  if (fade < 1) fade = 1;
+
+  if (t <= 0 || sp->opacity <= 0) return;
+
+  glPushMatrix();
+  glLoadIdentity();
+
+  if (debug_p)
+    {
+      GLfloat s = 0.75;
+      glScalef (s, s, s);
+    }
+
+  glOrtho (0, w, 0, h, -1, 1);
+
+  switch (sp->type) {
+  case GRID:    memcpy (color, ss->grid_color,    sizeof(color)); break;
+  case RETICLE: memcpy (color, ss->reticle_color, sizeof(color)); break;
+  case BOX:     memcpy (color, ss->reticle_color, sizeof(color)); break;
+  default: abort();
+  }
+
+  if (sp->type == GRID)
+    {
+      GLfloat s = 1 + (sp->thickness_scale - 1) / 120.0;
+      glTranslatef (w/2, h/2, 0);
+      glScalef (s, s, 1);
+      glTranslatef (-w/2, -h/2, 0);
+    }
+
+  glColor4fv (color);
+
+  if (!wire) glDisable (GL_TEXTURE_2D);
+
+  for (k = 0; k < fade; k++)
+    {
+      GLfloat t2 = t * (1 - (k / (fade * 1.0)));
+      if (t2 <= 0) break;
+      color[3] = sp->opacity / fade;
+      glColor4fv (color);
+
+      glBegin (wire ? GL_LINES : GL_QUADS);
+
+      switch (sp->type) {
+      case GRID:
+        {
+          GLfloat xoff = (w - sx * (w / sx)) / 2.0;
+          GLfloat yoff = (h - sy * (h / sy)) / 2.0;
+          for (y = -sy/2+t2/2; y < h; y += sy)
+            for (x = -sx/2-t2/2; x < w; x += sx)
+              {
+                glVertex3f (xoff+x+t2, yoff+y,       0);
+                glVertex3f (xoff+x+t2, yoff+y+sy-t2, 0);
+                glVertex3f (xoff+x,    yoff+y+sy-t2, 0);
+                glVertex3f (xoff+x,    yoff+y,       0);
+                mi->polygon_count++;
+
+                glVertex3f (xoff+x,    yoff+y-t2, 0);
+                glVertex3f (xoff+x+sx, yoff+y-t2, 0);
+                glVertex3f (xoff+x+sx, yoff+y,    0);
+                glVertex3f (xoff+x,    yoff+y,    0);
+                mi->polygon_count++;
+              }
+        }
+        break;
+
+      case BOX:
+        glVertex3f (x-bw/2-t2/2, y-bh/2-t2/2, 0);
+        glVertex3f (x+bw/2+t2/2, y-bh/2-t2/2, 0);
+        glVertex3f (x+bw/2+t2/2, y-bh/2+t2/2, 0);
+        glVertex3f (x-bw/2-t2/2, y-bh/2+t2/2, 0);
+        mi->polygon_count++;
+
+        glVertex3f (x-bw/2-t2/2, y+bh/2-t2/2, 0);
+        glVertex3f (x+bw/2+t2/2, y+bh/2-t2/2, 0);
+        glVertex3f (x+bw/2+t2/2, y+bh/2+t2/2, 0);
+        glVertex3f (x-bw/2-t2/2, y+bh/2+t2/2, 0);
+        mi->polygon_count++;
+
+        glVertex3f (x-bw/2+t2/2, y-bh/2+t2/2, 0);
+        glVertex3f (x-bw/2+t2/2, y+bh/2-t2/2, 0);
+        glVertex3f (x-bw/2-t2/2, y+bh/2-t2/2, 0);
+        glVertex3f (x-bw/2-t2/2, y-bh/2+t2/2, 0);
+        mi->polygon_count++;
+
+        glVertex3f (x+bw/2+t2/2, y-bh/2+t2/2, 0);
+        glVertex3f (x+bw/2+t2/2, y+bh/2-t2/2, 0);
+        glVertex3f (x+bw/2-t2/2, y+bh/2-t2/2, 0);
+        glVertex3f (x+bw/2-t2/2, y-bh/2+t2/2, 0);
+        mi->polygon_count++;
+        break;
+
+      case RETICLE:
+        glVertex3f (x+t2/2, y+sy/2-t2/2, 0);
+        glVertex3f (x+t2/2, h,           0);
+        glVertex3f (x-t2/2, h,           0);
+        glVertex3f (x-t2/2, y+sy/2-t2/2, 0);
+        mi->polygon_count++;
+
+        glVertex3f (x-t2/2, y-sy/2+t2/2, 0);
+        glVertex3f (x-t2/2, 0,           0);
+        glVertex3f (x+t2/2, 0,           0);
+        glVertex3f (x+t2/2, y-sy/2+t2/2, 0);
+        mi->polygon_count++;
+
+        glVertex3f (x-sx/2+t2/2, y+t2/2, 0);
+        glVertex3f (0,           y+t2/2, 0);
+        glVertex3f (0,           y-t2/2, 0);
+        glVertex3f (x-sx/2+t2/2, y-t2/2, 0);
+        mi->polygon_count++;
+
+        glVertex3f (x+sx/2-t2/2, y-t2/2, 0);
+        glVertex3f (w,           y-t2/2, 0);
+        glVertex3f (w,           y+t2/2, 0);
+        glVertex3f (x+sx/2-t2/2, y+t2/2, 0);
+        mi->polygon_count++;
+        break;
+
+      default: abort();
+      }
+      glEnd();
+    }
+
+  glPopMatrix();
+
+  if (!wire) glEnable (GL_TEXTURE_2D);
+}
+
+
+static sprite * find_newest_sprite (ModeInfo *, sprite_type);
+static void compute_image_rect (rect *, sprite *, Bool);
+
+static void
+draw_text_sprite (ModeInfo *mi, sprite *sp)
+{
+  esper_state *ss = &sss[MI_SCREEN(mi)];
+  int wire = MI_IS_WIREFRAME(mi);
+  GLfloat w = MI_WIDTH(mi);
+  GLfloat h = MI_HEIGHT(mi);
+  GLfloat s;
+  int x, y, z;
+  XCharStruct e;
+  sprite *target = 0;
+  char text[255];
+  GLfloat color[4];
+  int i;
+
+  if (sp->opacity <= 0)
+    return;
+
+  for (i = 0; i < ss->nsprites; i++)
+    {
+      sprite *sp2 = ss->sprites[i];
+      if (sp2->id == sp->text_id && sp2->state != DEAD)
+        {
+          target = sp2;
+          break;
+        }
+    }
+
+  if (target)
+    {
+      rect r;
+      sprite *img;
+
+      if (target->opacity <= 0 && 
+          (target->state == NEW || target->state == IN))
+        return;
+
+      r = target->current;
+
+      img = find_newest_sprite (mi, IMAGE);
+      if (img)
+        compute_image_rect (&r, img, target->back_p);
+
+      mi->recursion_depth = (img
+                             ? MIN (img->current.w, img->current.h)
+                             : 0);
+
+      x = abs ((int) (r.x * 10000)) % 10000;
+      y = abs ((int) (r.y * 10000)) % 10000;
+      z = abs ((int) (r.w * 10000)) % 10000;
+
+      sprintf (text, "ZM %04d  NS %04d  EW %04d", z, y, x);
+
+      if ((x == 0 || x == 5000) &&             /* startup */
+          (y == 0 || y == 5000) &&
+          (z == 0 || z == 5000))
+        *text = 0;
+
+      if (do_titles && 
+          target->type == IMAGE &&
+          target->remain_p)  /* The initial background image */
+        {
+          char *s = (target->img &&
+                     target->img->title && *target->img->title
+                     ? target->img->title
+                     : "Loading");
+          int L = strlen (s);
+          int i = (L > 23 ? L-23 : 0);
+          sprintf (text, ">>%-23s", target->img->title + i);
+          for (s = text; *s; s++)
+            if (*s >= 'a' && *s <= 'z') *s += ('A'-'a');
+            else if (*s == '/' || *s == '-' || *s == '.') *s = '_';
+        }
+
+      if (!*text) return;
+
+      if (sp->text) free (sp->text);
+      sp->text = strdup (text);
+    }
+  else if (sp->text && *sp->text)
+    /* The target sprite might be dead, but we saved our last text. */
+    strcpy (text, sp->text);
+  else
+    /* No target, no saved text. */
+    return;
+
+  texture_string_metrics (ss->font_data, text, &e, 0, 0);
+
+  glPushMatrix();
+  glLoadIdentity();
+  glOrtho (0, 1, 0, 1, -1, 1);
+
+  /* Scale the text to fit N characters horizontally. */
+  {
+# ifdef HAVE_MOBILE
+    GLfloat c = 25;
+# else /* desktop */
+    GLfloat c = (MI_WIDTH(mi) <= 640  ? 25 :
+                 MI_WIDTH(mi) <= 1280 ? 32 : 64);
+# endif
+    s = w / (e.ascent * c);
+  }
+  w /= s;
+  h /= s;
+  x = (w - e.width) / 2;
+  y = e.ascent + e.descent * 2;
+
+  glScalef (1.0/w, 1.0/h, 1);
+  glTranslatef (x, y, 0);
+
+  memcpy (color, ss->text_color, sizeof(color));
+  color[3] = sp->opacity;
+  glColor4fv (color);
+
+  if (wire)
+    glEnable (GL_TEXTURE_2D);
+
+  print_texture_string (ss->font_data, text);
+  mi->polygon_count++;
+
+  if (wire)
+    glDisable (GL_TEXTURE_2D);
+  glPopMatrix();
+}
+
+
+static void
+draw_flash_sprite (ModeInfo *mi, sprite *sp)
+{
+  /* esper_state *ss = &sss[MI_SCREEN(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);
+  glColorMask (0, 0, 1, 1); /* write only into blue and alpha channels */
+  glBegin (GL_QUADS);
+  glVertex3f (0, 0, 0);
+  glVertex3f (1, 0, 0);
+  glVertex3f (1, 1, 0);
+  glVertex3f (0, 1, 0);
+  glEnd();
+  glColorMask (1, 1, 1, 1);
+  if (!wire)
+    glEnable (GL_TEXTURE_2D);
+  glPopMatrix();
+}
+
+
+static void
+draw_sprite (ModeInfo *mi, sprite *sp)
+{
+  switch (sp->type) {
+  case IMAGE:
+    draw_image_sprite (mi, sp);
+    break;
+  case RETICLE:
+  case BOX:
+  case GRID:
+    draw_line_sprite (mi, sp);
+    break;
+  case TEXT:
+    draw_text_sprite (mi, sp);
+    break;
+  case FLASH:
+    draw_flash_sprite (mi, sp);
+    break;
+  default:
+    abort();
+  }
+}
+
+
+static void
+tick_sprites (ModeInfo *mi)
+{
+  esper_state *ss = &sss[MI_SCREEN(mi)];
+  int i;
+  for (i = 0; i < ss->nsprites; i++)
+    tick_sprite (mi, ss->sprites[i]);
+
+  for (i = 0; i < ss->nsprites; i++)
+    {
+      sprite *sp = ss->sprites[i];
+      if (sp->state == DEAD)
+        {
+          destroy_sprite (mi, sp);
+          i--;
+        }
+    }
+}
+
+
+static void
+draw_sprites (ModeInfo *mi)
+{
+  esper_state *ss = &sss[MI_SCREEN(mi)];
+  int i;
+
+  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  glPushMatrix();
+
+/*
+  {
+    GLfloat rot = current_device_rotation();
+    glTranslatef (0.5, 0.5, 0);
+    glRotatef(rot, 0, 0, 1);
+    if ((rot >  45 && rot <  135) ||
+        (rot < -45 && rot > -135))
+      {
+        GLfloat s = MI_WIDTH(mi) / (GLfloat) MI_HEIGHT(mi);
+        glScalef (s, 1/s, 1);
+      }
+    glTranslatef (-0.5, -0.5, 0);
+  }
+*/
+
+  /* Draw the images first, then the overlays. */
+  for (i = 0; i < ss->nsprites; i++)
+    if (ss->sprites[i]->type == IMAGE)
+      draw_sprite (mi, ss->sprites[i]);
+  for (i = 0; i < ss->nsprites; i++)
+    if (ss->sprites[i]->type != IMAGE)
+      draw_sprite (mi, ss->sprites[i]);
+
+  glPopMatrix();
+
+  if (debug_p)                         /* draw a white box (the "screen") */
+    {
+      int wire = MI_IS_WIREFRAME(mi);
+
+      if (!wire) glDisable (GL_TEXTURE_2D);
+
+      glColor4f (1, 1, 1, 1);
+      glBegin (GL_LINE_LOOP);
+      glVertex3f (0, 0, 0);
+      glVertex3f (0, 1, 0);
+      glVertex3f (1, 1, 0);
+      glVertex3f (1, 0, 0);
+      glEnd();
+
+      if (!wire) glEnable (GL_TEXTURE_2D);
+    }
+}
+
+
+static void
+fadeout_sprite (ModeInfo *mi, sprite *sp)
+{
+  esper_state *ss = &sss[MI_SCREEN(mi)];
+
+  /* If it hasn't faded in yet, don't fade out. */
+  if (ss->now <= sp->start_time + sp->pause_duration)
+    sp->fade_duration = 0;
+
+  /* Pretend it's at the point where it should fade out. */
+  sp->pause_duration = 0;
+  sp->duration = 9999;
+  sp->remain_p = False;
+  sp->start_time = ss->now - sp->duration;
+}
+
+static void
+fadeout_sprites (ModeInfo *mi, sprite_type type)
+{
+  esper_state *ss = &sss[MI_SCREEN(mi)];
+  int i;
+  for (i = 0; i < ss->nsprites; i++)
+    {
+      sprite *sp = ss->sprites[i];
+      if (sp->type == type)
+        fadeout_sprite (mi, sp);
+    }
+}
+
+
+static sprite *
+find_newest_sprite (ModeInfo *mi, sprite_type type)
+{
+  esper_state *ss = &sss[MI_SCREEN(mi)];
+  sprite *sp = 0;
+  int i;
+  for (i = 0; i < ss->nsprites; i++)
+    {
+      sprite *sp2 = ss->sprites[i];
+      if (sp2->type == type &&
+          (!sp || 
+           (sp->start_time < sp2->start_time &&
+            ss->now >= sp2->start_time + sp2->pause_duration)))
+        sp = sp2;
+    }
+  return sp;
+}
+
+
+/* Enqueue a text sprite describing the given sprite that runs at the 
+   same time.
+ */
+static sprite *
+push_text_sprite (ModeInfo *mi, sprite *sp)
+{
+  /* esper_state *ss = &sss[MI_SCREEN(mi)]; */
+  sprite *sp2 = new_sprite (mi, TEXT);
+  if (!sp2) abort();
+  sp2->text_id = sp->id;
+  sp2->fade_duration  = sp->fade_duration;
+  sp2->duration       = sp->duration;
+  sp2->pause_duration = sp->pause_duration;
+  return sp2;
+}
+
+
+/* Enqueue a flash sprite that fires at the same time.
+ */
+#ifndef SMOOTH
+static sprite *
+push_flash_sprite (ModeInfo *mi, sprite *sp)
+{
+  /* esper_state *ss = &sss[MI_SCREEN(mi)]; */
+  sprite *sp2 = new_sprite (mi, FLASH);
+  if (!sp2) abort();
+  if (sp->type != IMAGE) abort();
+  sp2->text_id = sp->id;
+  sp2->duration       = MAX (0.07 / speed, 0.07);
+  sp2->fade_duration  = 0;  /* Fading these is too fast to see */
+  sp2->pause_duration = sp->pause_duration + (sp->fade_duration * 0.3);
+  return sp2;
+}
+#endif /* !SMOOTH */
+
+
+/* Set the sprite's duration based on distance travelled.
+ */
+static void
+compute_sprite_duration (ModeInfo *mi, sprite *sp, Bool blink_p)
+{
+  /* Compute max distance traveled by any point (corners or center). */
+  /* (cpp is the devil) */
+# define L(F)    (sp->F.x - sp->F.w/2)   /* delta of left edge, from/to */
+# define R(F) (1-(sp->F.x + sp->F.w/2))  /* right */
+# define B(F)    (sp->F.y - sp->F.h/2)   /* top */
+# define T(F) (1-(sp->F.y + sp->F.h/2))  /* bottom */
+# define D(F,G) sqrt(F(from)*F(from) + G(to)*G(to))  /* corner traveled */
+  double BL = D(B,L);
+  double BR = D(B,R);
+  double TL = D(T,L);
+  double TR = D(T,R);
+  double cx = sp->to.x - sp->from.x;
+  double cy = sp->to.y - sp->from.y;
+  double C  = sqrt(cx*cx + cy*cy);
+  double dist = MAX (BL, MAX (BR, MAX (TL, MAX (TR, C))));
+# undef L
+# undef R
+# undef B
+# undef T
+# undef D
+
+  int steps = 1 + dist * 28;
+  if (steps > 10) steps = 10;
+
+  sp->duration = steps * 0.2 / speed;
+
+# ifndef SMOOTH
+  sp->duration += 1.5 / speed;  /* For linger added by animate_sprite_path() */
+  if (blink_p) sp->duration += 0.6 / speed;
+# endif
+}
+
+
+/* Convert the sprite to a jerky transition.
+   Instead of smoothly animating, move in discrete steps,
+   using multiple staggered sprites.
+ */
+static void
+animate_sprite_path (ModeInfo *mi, sprite *sp, Bool blink_p)
+{
+# ifndef SMOOTH
+  /* esper_state *ss = &sss[MI_SCREEN(mi)]; */
+  double dx = sp->to.x - sp->from.x;
+  double dy = sp->to.y - sp->from.y;
+  double dw = sp->to.w - sp->from.w;
+  double dh = sp->to.h - sp->from.h;
+  double linger  = 1.5 / speed;
+  double blinger = 0.6 / speed;
+  double dur = sp->duration - linger - (blink_p ? blinger : 0);
+  int steps = dur / 0.3 * speed;  /* step duration in seconds */
+  int i;
+
+  if (sp->type == IMAGE)
+    steps *= 0.8;
+
+  if (steps < 2)  steps = 2;
+  if (steps > 10) steps = 10;
+
+  /* if (dur <= 0.01) abort(); */
+  if (dur < 0.01)
+    linger = blinger = 0;
+
+  for (i = 0; i <= steps; i++)
+    {
+      sprite *sp2 = copy_sprite (mi, sp);
+      if (!sp2) abort();
+
+      sp2->to.x = (sp->current.x + i * dx / steps);
+      sp2->to.y = (sp->current.y + i * dy / steps);
+      sp2->to.w = (sp->current.w + i * dw / steps);
+      sp2->to.h = (sp->current.h + i * dh / steps);
+      sp2->current = sp2->from = sp2->to;
+      sp2->duration = dur / steps;
+      sp2->pause_duration += i * sp2->duration;
+      sp2->remain_p = False;
+      sp2->fatbits_p = True;
+
+      if (i == steps)
+        sp2->duration += linger;       /* last one lingers for a bit */
+
+      if (i == steps && !blink_p)
+        {
+          sp2->remain_p = sp->remain_p;
+          sp2->fatbits_p = False;
+        }
+
+      if (sp2->type == IMAGE && i > 0)
+        push_flash_sprite (mi, sp2);
+
+      if (sp2->type == RETICLE || sp2->type == BOX)
+        {
+          sp2 = push_text_sprite (mi, sp2);
+          if (i == steps)
+            sp2->duration += linger * 2;
+        }
+    }
+
+  if (blink_p && blinger)              /* last one blinks before vanishing */
+    {
+      int blinkers = 3;
+      for (i = 1; i <= blinkers; i++)
+        {
+          sprite *sp2 = copy_sprite (mi, sp);
+          if (!sp2) abort();
+
+          sp2->current = sp2->from = sp->to;
+          sp2->duration = blinger / blinkers;
+          sp2->pause_duration += dur + linger + i * sp2->duration;
+          sp2->remain_p = False;
+          if (i == blinkers)
+            {
+              sp2->remain_p = sp->remain_p;
+              sp2->fatbits_p = False;
+            }
+        }
+    }
+
+  /* Fade out the template sprite. It might not have even appeared yet. */
+  fadeout_sprite (mi, sp);
+# endif
+}
+
+
+/* Input rect is of a reticle or box.
+   Output rect is what the image's rect should be so that the only part
+   visible is the part indicated by the input rect.
+ */
+static void
+compute_image_rect (rect *r, sprite *img, Bool inverse_p)
+{
+  double scale = (inverse_p ? 1/r->w : r->w);
+  double dx = r->x - 0.5;
+  double dy = r->y - 0.5;
+
+  /* Adjust size and center by zoom factor */
+  r->w = img->current.w / scale;
+  r->h = img->current.h / scale;
+  r->x = 0.5 + (img->current.x - 0.5) / scale;
+  r->y = 0.5 + (img->current.y - 0.5) / scale;
+
+  /* Move center */
+
+  if (inverse_p)
+    {
+      dx = -dx;                /* #### Close but not quite right */
+      dy = -dy;
+    }
+
+  r->x -= dx / scale;
+  r->y -= dy / scale;
+}
+
+
+/* Sets 'to' such that the image zooms out so that the only part visible
+   is the part indicated by the box.
+ */
+static void
+track_box_with_image (ModeInfo *mi, sprite *sp, sprite *img)
+{
+  rect r = sp->current;
+  compute_image_rect (&r, img, sp->back_p);
+  img->to = r;
+
+  /* Never zoom out too far. */
+  if (img->to.w < 1 && img->to.h < 1)
+    {
+      if (img->to.w > img->to.h)
+        {
+          img->to.w = img->to.w / img->to.h;
+          img->to.h = 1;
+        }
+      else
+        {
+          img->to.h = img->to.h / img->to.w;
+          img->to.w = 1;
+        }
+    }
+
+  /* Never pan beyond the bounds of the image. */
+  if (img->to.x < -img->to.w/2+1) img->to.x = -img->to.w/2+1;
+  if (img->to.x >  img->to.w/2)   img->to.x =  img->to.w/2;
+  if (img->to.y < -img->to.h/2+1) img->to.y = -img->to.h/2+1;
+  if (img->to.y >  img->to.h/2)   img->to.y =  img->to.h/2;
+}
+
+
+static void
+tick_animation (ModeInfo *mi)
+{
+  esper_state *ss = &sss[MI_SCREEN(mi)];
+  anim_state prev_state = ss->anim_state;
+  sprite *sp = 0;
+  int i;
+
+  switch (ss->anim_state) {
+  case BLANK:
+    ss->anim_state = GRID_ON;
+    break;
+  case GRID_ON:
+    ss->anim_state = IMAGE_LOAD;
+    break;
+  case IMAGE_LOAD:
+    /* Only advance once an image has loaded. */
+    if (find_newest_sprite (mi, IMAGE))
+      ss->anim_state = RETICLE_ON;
+    else
+      ss->anim_state = IMAGE_LOAD;
+    break;
+  case RETICLE_ON:
+    ss->anim_state = RETICLE_MOVE;
+    break;
+  case RETICLE_MOVE:
+    if (random() % 6)
+      ss->anim_state = BOX_MOVE;
+    else
+      ss->anim_state = IMAGE_ZOOM;
+    break;
+  case BOX_MOVE:
+    ss->anim_state = IMAGE_ZOOM;
+    break;
+  case IMAGE_ZOOM:
+    {
+      sprite *sp = find_newest_sprite (mi, IMAGE);
+      double depth = (sp
+                      ? MIN (sp->current.w, sp->current.h)
+                      : 0);
+      if (depth > 20)
+        ss->anim_state = IMAGE_UNLOAD;
+      else
+        ss->anim_state = RETICLE_ON;
+    }
+    break;
+  case IMAGE_FORCE_UNLOAD:
+    ss->anim_state = IMAGE_UNLOAD;
+    break;
+  case IMAGE_UNLOAD:
+    ss->anim_state = IMAGE_LOAD;
+    break;
+  case MANUAL_BOX_ON:
+    ss->anim_state = MANUAL_BOX;
+    break;
+  case MANUAL_BOX:
+    break;
+  case MANUAL_RETICLE_ON:
+    ss->anim_state = MANUAL_RETICLE;
+    break;
+  case MANUAL_RETICLE:
+    break;
+  default:
+    abort();
+    break;
+  }
+
+  ss->anim_start = ss->now;
+  ss->anim_duration = 0;
+
+  if (debug_p)
+    fprintf (stderr, "%s: entering %s\n",
+             progname, state_name (ss->anim_state));
+
+  switch (ss->anim_state) {
+
+  case GRID_ON:                /* Start the grid fading in. */
+    if (! find_newest_sprite (mi, GRID))
+      {
+        sp = new_sprite (mi, GRID);
+        if (!sp) abort();
+        sp->fade_duration = 1.0 / speed;
+        sp->duration = 2.0 / speed;
+        sp->remain_p = True;
+        ss->anim_duration = (sp->pause_duration + sp->fade_duration * 2 +
+                             sp->duration);
+      }
+    break;
+
+  case IMAGE_LOAD:
+    fadeout_sprites (mi, IMAGE);
+    sp = new_sprite (mi, IMAGE);
+    if (! sp) 
+      {
+        if (debug_p) fprintf (stderr, "%s: image load failed\n", progname);
+        break;
+      }
+
+    sp->fade_duration = 0.5 / speed;
+    sp->duration = sp->fade_duration * 3;
+    sp->remain_p = True;
+    /* If we zoom in, we lose the pulse at the end. */
+    /* sp->from.w = sp->from.h = 0.0001; */
+    sp->current = sp->from;
+
+    ss->anim_duration = (sp->pause_duration + sp->fade_duration * 2 +
+                         sp->duration);
+
+    sp = push_text_sprite (mi, sp);
+    sp->fade_duration = 0.2 / speed;
+    sp->pause_duration = 0;
+    sp->duration = 2.5 / speed;
+    break;
+
+  case IMAGE_FORCE_UNLOAD:
+    break;
+
+  case IMAGE_UNLOAD:
+    sp = find_newest_sprite (mi, IMAGE);    
+    if (sp)
+      sp->fade_duration = ((prev_state == IMAGE_FORCE_UNLOAD ? 0.2 : 3.0)
+                           / speed);
+    fadeout_sprites (mi, IMAGE);
+    fadeout_sprites (mi, RETICLE);
+    fadeout_sprites (mi, BOX);
+    fadeout_sprites (mi, TEXT);
+    ss->anim_duration = (sp ? sp->fade_duration : 0) + 3.5 / speed;
+    break;
+
+  case RETICLE_ON:             /* Display reticle at center. */
+    fadeout_sprites (mi, TEXT);
+    sp = new_sprite (mi, RETICLE);
+    if (!sp) abort();
+    sp->fade_duration  = 0.2 / speed;
+    sp->pause_duration = 1.0 / speed;
+    sp->duration       = 1.5 / speed;
+    ss->anim_duration = (sp->pause_duration + sp->fade_duration * 2 +
+                         sp->duration);
+    ss->anim_duration -= sp->fade_duration * 2;
+    break;
+
+  case RETICLE_MOVE:
+    /* Reticle has faded in.  Now move it to somewhere else.
+       Create N new reticle sprites, wih staggered pause_durations.
+     */
+    {
+      GLfloat ox = 0.5;
+      GLfloat oy = 0.5;
+      GLfloat nx, ny, dist;
+
+      do {             /* pick a new position not too near the old */
+        nx = 0.3 + BELLRAND(0.4);
+        ny = 0.3 + BELLRAND(0.4);
+        dist = sqrt ((nx-ox)*(nx-ox) + (ny-oy)*(ny-oy));
+      } while (dist < 0.1);
+
+      sp = new_sprite (mi, RETICLE);
+      if (!sp) abort();
+
+      sp->from.x = ox;
+      sp->from.y = oy;
+      sp->current = sp->to = sp->from;
+      sp->to.x = nx;
+      sp->to.y = ny;
+      sp->fade_duration  = 0.2 / speed;
+      sp->pause_duration = 0;
+      compute_sprite_duration (mi, sp, False);
+
+      ss->anim_duration = (sp->pause_duration + sp->fade_duration * 2 +
+                           sp->duration - 0.1);
+      animate_sprite_path (mi, sp, False);
+    }
+    break;
+
+  case BOX_MOVE:
+    /* Reticle has moved, and faded out.
+       Start the box zooming into place.
+     */
+    {
+      GLfloat ox = 0.5;
+      GLfloat oy = 0.5;
+      GLfloat nx, ny;
+      GLfloat z;
+
+      /* Find the last-added reticle, for our destination position. */
+      sp = 0;
+      for (i = 0; i < ss->nsprites; i++)
+        {
+          sprite *sp2 = ss->sprites[i];
+          if (sp2->type == RETICLE &&
+              (!sp || sp->start_time < sp2->start_time))
+            sp = sp2;
+        }
+      if (sp)
+        {
+          nx = sp->to.x;
+          ny = sp->to.y;
+        }
+      else
+        {
+          nx = ny = 0.5;
+          if (debug_p)
+            fprintf (stderr, "%s: no reticle before box?\n", progname);
+        }
+
+      z = 0.3 + frand(0.5);
+
+      /* Ensure that the selected box is contained within the screen */
+      {
+        double margin = 0.005;
+        double maxw = 2 * MIN (1 - margin - nx, nx - margin);
+        double maxh = 2 * MIN (1 - margin - ny, ny - margin);
+        double max = MIN (maxw, maxh);
+        if (z > max) z = max;
+      }
+
+      sp = new_sprite (mi, BOX);
+      if (!sp) abort();
+      sp->from.x = ox;
+      sp->from.y = oy;
+      sp->from.w = 1.0;
+      sp->from.h = 1.0;
+      sp->current = sp->from;
+      sp->to.x = nx;
+      sp->to.y = ny;
+      sp->to.w = z;
+      sp->to.h = z;
+
+      /* Maybe zoom out instead of in.
+       */
+      {
+        sprite *img = find_newest_sprite (mi, IMAGE);
+        double depth = MIN (img->current.w, img->current.h);
+        if (depth > 1 &&  /* if zoomed in */
+            (depth < 6 ?  !(random() % 5) :   /* 20% */
+             depth < 12 ? !(random() % 2) :   /* 50% */
+             (random() % 3)))                 /* 66% */
+          {
+            sp->back_p = True;
+            if (depth < 1.5 && z < 0.8)
+              {
+                z = 0.8;       /* don't zoom out much past 100% */
+                sp->to.w = z;
+                sp->to.h = z;
+              }
+          }
+      }
+
+      sp->fade_duration  = 0.2 / speed;
+      sp->pause_duration = 2.0 / speed;
+      compute_sprite_duration (mi, sp, True);
+      ss->anim_duration = (sp->pause_duration + sp->fade_duration * 2 +
+                           sp->duration - 0.1);
+      animate_sprite_path (mi, sp, True);
+    }
+    break;
+
+  case IMAGE_ZOOM:
+
+    /* Box has moved, and faded out.
+       Or, if no box, then just a reticle.
+       Zoom the underlying image to track the box's position. */
+    {
+      sprite *img, *img2;
+
+      /* Find latest box or reticle, for our destination position. */
+      sp = find_newest_sprite (mi, BOX);
+      if (! sp)
+        sp = find_newest_sprite (mi, RETICLE);
+      if (! sp)
+        {
+          if (debug_p)
+            fprintf (stderr, "%s: no box or reticle before image\n",
+                     progname);
+          break;
+        }
+
+      img = find_newest_sprite (mi, IMAGE);
+      if (!img)
+        {
+          if (debug_p)
+            fprintf (stderr, "%s: no image?\n", progname);
+          break;
+        }
+
+      img2 = copy_sprite (mi, img);
+      if (!img2) abort();
+
+      img2->from = img->current;
+
+      fadeout_sprite (mi, img);
+
+      track_box_with_image (mi, sp, img2);
+
+      img2->fade_duration  = 0.2 / speed;
+      img2->pause_duration = 0.5 / speed;
+      img2->remain_p = True;
+      img2->throb_p = False;
+      compute_sprite_duration (mi, img2, False);
+
+      img->start_time += img2->pause_duration;
+
+      ss->anim_duration = (img2->pause_duration + img2->fade_duration * 2 +
+                           img2->duration);
+      animate_sprite_path (mi, img2, False);
+      fadeout_sprites (mi, TEXT);
+    }
+    break;
+
+  case MANUAL_BOX_ON:
+  case MANUAL_RETICLE_ON:
+    break;
+
+  case MANUAL_BOX:
+  case MANUAL_RETICLE:
+    {
+      sprite_type tt = (ss->anim_state == MANUAL_BOX ? BOX : RETICLE);
+      sprite *osp = find_newest_sprite (mi, tt);
+      fadeout_sprites (mi, RETICLE);
+      fadeout_sprites (mi, BOX);
+
+      sp = new_sprite (mi, tt);
+      if (!sp) abort();
+      if (osp)
+        sp->from = osp->current;
+      else
+        {
+          sp->from.x = 0.5;
+          sp->from.y = 0.5;
+          sp->from.w = 0.5;
+          sp->from.h = 0.5;
+        }
+      sp->to = sp->current = sp->from;
+      sp->fade_duration = 0.2 / speed;
+      sp->duration = 0.2 / speed;
+      sp->remain_p = True;
+      sp->throb_p = False;
+      ss->anim_duration = 9999;
+    }
+    break;
+
+  default:
+    fprintf (stderr,"%s: unknown state %d\n",
+             progname, (int) ss->anim_state);
+    abort();
+  }
+}
+
+
+/* Copied from gltrackball.c, sigh.
+ */
+static void
+adjust_for_device_rotation (double *x, double *y, double *w, double *h)
+{
+  int rot = (int) current_device_rotation();
+  int swap;
+
+  while (rot <= -180) rot += 360;
+  while (rot >   180) rot -= 360;
+
+  if (rot > 135 || rot < -135)         /* 180 */
+    {
+      *x = *w - *x;
+      *y = *h - *y;
+    }
+  else if (rot > 45)                   /* 90 */
+    {
+      swap = *x; *x = *y; *y = swap;
+      swap = *w; *w = *h; *h = swap;
+      *x = *w - *x;
+    }
+  else if (rot < -45)                  /* 270 */
+    {
+      swap = *x; *x = *y; *y = swap;
+      swap = *w; *w = *h; *h = swap;
+      *y = *h - *y;
+    }
+}
+
+
+ENTRYPOINT Bool
+esper_handle_event (ModeInfo *mi, XEvent *event)
+{
+  esper_state *ss = &sss[MI_SCREEN(mi)];
+
+  if (event->xany.type == Expose ||
+      event->xany.type == GraphicsExpose ||
+      event->xany.type == VisibilityNotify)
+    {
+      return False;
+    }
+  else if (event->xany.type == KeyPress)
+    {
+      KeySym keysym;
+      char c = 0;
+      sprite *sp = 0;
+      double delta = 0.025;
+      double margin = 0.005;
+      Bool ok = False;
+
+      XLookupString (&event->xkey, &c, 1, &keysym, 0);
+
+      if (c == '\t')
+        {
+          ss->anim_state = IMAGE_FORCE_UNLOAD;
+          return True;
+        }
+
+      if (! find_newest_sprite (mi, IMAGE))
+        return False;  /* Too early */
+
+      ss->now = double_time();
+
+# define BONK() do {                                 \
+       if (ss->anim_state != MANUAL_BOX_ON &&        \
+           ss->anim_state != MANUAL_BOX) {           \
+         ss->anim_state = MANUAL_BOX_ON;             \
+         tick_animation (mi);                        \
+       }                                             \
+       sp = find_newest_sprite (mi, BOX);            \
+       if (!sp) abort() ;                            \
+       sp->from = sp->current;                       \
+       sp->to = sp->from;                            \
+       sp->start_time = ss->now - sp->fade_duration; \
+       ok = True;                                    \
+      } while(0)
+
+      if (keysym == XK_Left || c == ',' || c == '<')
+        {
+          BONK();
+          sp->to.x -= delta;
+        }
+      else if (keysym == XK_Right || c == '.' || c == '>')
+        {
+          BONK();
+          sp->to.x += delta;
+        }
+      else if (keysym == XK_Down || c == '-')
+        {
+          BONK();
+          sp->to.y -= delta;
+        }
+      else if (keysym == XK_Up || c == '=')
+        {
+          BONK();
+          sp->to.y += delta, ok = True;
+        }
+      else if (keysym == XK_Prior || c == '+')
+        {
+          BONK();
+          sp->to.w += delta;
+          sp->to.h = sp->to.w * sp->from.w / sp->from.h;
+        }
+      else if (keysym == XK_Next || c == '_')
+        {
+          BONK();
+          sp->to.w -= delta;
+          sp->to.h = sp->to.w * sp->from.w / sp->from.h;
+        }
+      else if ((c == ' ' || c == '\t') && debug_p &&
+               ss->anim_state == MANUAL_BOX)
+        {
+          BONK();     /* Null motion: just flash the current image. */
+        }
+      else if ((keysym == XK_Home || c == ' ' || c == '\t') &&
+               ss->anim_state == MANUAL_BOX)
+        {
+          BONK();
+          sp->to.x = 0.5;
+          sp->to.y = 0.5;
+          sp->to.w = 0.5;
+          sp->to.h = 0.5;
+        }
+      else if ((c == '\r' || c == '\n' || c == 033) &&
+               ss->anim_state == MANUAL_BOX)
+        {
+          BONK();
+          ss->anim_state = BOX_MOVE;
+          ss->anim_duration = 9999;
+          ss->anim_start = ss->now - ss->anim_duration;
+          fadeout_sprite (mi, sp);
+          return True;
+        }
+      else
+        return False;
+
+      if (! ok)
+        return False;
+
+      /* Keep it on screen */
+      if (sp->to.w > 1 - margin)
+        {
+          GLfloat r = sp->to.h / sp->to.w;
+          sp->to.w = 1-margin;
+          sp->to.h = (1-margin) * r;
+        }
+      if (sp->to.h > 1)
+        {
+          GLfloat r = sp->to.h / sp->to.w;
+          sp->to.w = (1-margin) / r;
+          sp->to.h = 1-margin;
+        }
+
+      if (sp->to.x - sp->to.w/2 < margin)
+        sp->to.x = sp->to.w/2 + margin;
+      if (sp->to.y - sp->to.h/2 < margin)
+        sp->to.y = sp->to.h/2 + margin;
+
+      if (sp->to.x + sp->to.w/2 >= 1 + margin)
+        sp->to.x = 1 - (sp->to.w/2 + margin);
+      if (sp->to.y + sp->to.h/2 >= 1 + margin)
+        sp->to.y = 1 - (sp->to.h/2 + margin);
+
+      /* Now let's give a momentary glimpse of what the image would do. */
+      if (debug_p)
+        {
+          sprite *img;
+          int i;
+
+          /* Find the lingering image */
+          /* img = find__sprite (mi, IMAGE); */
+          for (i = 0; i < ss->nsprites; i++)
+            {
+              sprite *sp2 = ss->sprites[i];
+              if (sp2->type == IMAGE &&
+                  sp2->remain_p &&
+                  (!img || 
+                   (img->start_time < sp2->start_time &&
+                    ss->now >= sp2->start_time + sp2->pause_duration)))
+                img = sp2;
+            }
+
+          if (!img) abort();
+          img = copy_sprite (mi, img);
+          img->pause_duration = 0;
+          img->fade_duration = 0.1 / speed;
+          img->duration = 0.5 / speed;
+          img->start_time = ss->now;
+          img->remain_p = False;
+          track_box_with_image (mi, sp, img);
+          img->from = img->current = img->to;
+        }
+
+      return True;
+    }
+  else if (event->xany.type == ButtonPress &&
+           event->xbutton.button == Button1)
+    {
+      ss->button_down_p = 1;
+      return True;
+    }
+  else if (event->xany.type == ButtonRelease &&
+           event->xbutton.button == Button1)
+    {
+      ss->button_down_p = 0;
+
+      if (ss->anim_state == MANUAL_BOX)
+        {
+          sprite *sp = find_newest_sprite (mi, BOX);
+          if (sp) fadeout_sprite (mi, sp);
+          ss->anim_state = BOX_MOVE;
+          ss->anim_duration = 9999;
+          ss->anim_start = ss->now - ss->anim_duration;
+        }
+      else if (ss->anim_state == MANUAL_RETICLE)
+        {
+          sprite *sp = find_newest_sprite (mi, RETICLE);
+          if (sp) fadeout_sprite (mi, sp);
+          ss->anim_state = RETICLE_MOVE;
+          ss->anim_duration = 9999;
+          ss->anim_start = ss->now - ss->anim_duration;
+        }
+      return True;
+    }
+  else if (event->xany.type == MotionNotify &&
+           ss->button_down_p &&
+           (ss->anim_state == MANUAL_RETICLE ||
+            ss->anim_state == RETICLE_MOVE))
+    {
+      sprite *sp = 0;
+      double x = event->xmotion.x;
+      double y = event->xmotion.y;
+      double w = MI_WIDTH(mi);
+      double h = MI_HEIGHT(mi);
+
+      adjust_for_device_rotation (&x, &y, &w, &h);
+      x = x/w;
+      y = 1-y/h;
+
+      if (ss->anim_state != MANUAL_RETICLE_ON &&
+          ss->anim_state != MANUAL_RETICLE)
+        {
+         ss->anim_state = MANUAL_RETICLE_ON;
+         tick_animation (mi);
+       }
+      sp = find_newest_sprite (mi, RETICLE);
+      if (!sp) abort();
+      sp->from = sp->current;
+      sp->to = sp->from;
+      sp->start_time = ss->now - sp->fade_duration;
+      sp->remain_p = True;
+
+      sp->current.x = MIN (0.95, MAX (0.05, x));
+      sp->current.y = MIN (0.95, MAX (0.05, y));
+      sp->from = sp->to = sp->current;
+
+      /* Don't update the text sprite more often than once a second. */
+      {
+        sprite *sp2 = find_newest_sprite (mi, TEXT);
+        if (!sp2 || sp2->start_time < ss->now-1)
+          {
+            fadeout_sprites (mi, TEXT);
+            sp = push_text_sprite (mi, sp);
+            sp->remain_p = True;
+          }
+      }
+
+      return True;
+    }
+  else if (event->xany.type == MotionNotify &&
+           ss->button_down_p &&
+           (ss->anim_state == MANUAL_BOX ||
+            ss->anim_state == BOX_MOVE))
+    {
+      sprite *sp = 0;
+      double x = event->xmotion.x;
+      double y = event->xmotion.y;
+      double w = MI_WIDTH(mi);
+      double h = MI_HEIGHT(mi);
+      double max;
+      Bool ok = True;
+
+      adjust_for_device_rotation (&x, &y, &w, &h);
+      x = x/w;
+      y = 1-y/h;
+
+      BONK();
+      max = (2 * (0.5 - MAX (fabs (sp->current.x - 0.5),
+                             fabs (sp->current.y - 0.5)))
+             * 0.95);
+
+      x = fabs (x - sp->current.x);
+      y = fabs (y - sp->current.y);
+
+      if (x > y)
+        sp->current.w = sp->current.h = MIN (max, MAX (0.05, 2*x));
+      else
+        sp->current.w = sp->current.h = MIN (max, MAX (0.05, 2*y));
+      sp->from = sp->to = sp->current;
+
+      /* Don't update the text sprite more often than once a second. */
+      {
+        sprite *sp2 = find_newest_sprite (mi, TEXT);
+        if (!sp2 || sp2->start_time < ss->now-1)
+          {
+            fadeout_sprites (mi, TEXT);
+            sp = push_text_sprite (mi, sp);
+            sp->remain_p = True;
+          }
+      }
+
+      return True;
+    }
+  else if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
+    {
+      ss->anim_state = IMAGE_FORCE_UNLOAD;
+      return True;
+    }
+# undef BONK
+
+  return False;
+}
+
+
+ENTRYPOINT void
+reshape_esper (ModeInfo *mi, int width, int height)
+{
+  GLfloat s;
+
+  glViewport (0, 0, width, height);
+  glMatrixMode (GL_PROJECTION);
+  glLoadIdentity();
+  glRotatef (current_device_rotation(), 0, 0, 1);
+  glMatrixMode (GL_MODELVIEW);
+  glLoadIdentity();
+
+  s = 2;
+
+  if (debug_p)
+    {
+      s *= 0.75;
+      if (s < 0.1) s = 0.1;
+    }
+
+  glScalef (s, s, s);
+  glTranslatef (-0.5, -0.5, 0);
+
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  /* Stretch each existing image to match new window aspect. */
+  {
+    esper_state *ss = &sss[MI_SCREEN(mi)];
+    int i;
+    for (i = 0; i < ss->nsprites; i++)
+      {
+        sprite *sp = ss->sprites[i];
+        if (sp && sp->type == IMAGE && sp->img && sp->img->loaded_p)
+          {
+            GLfloat sp_asp  = sp->current.h / sp->current.w;
+            GLfloat img_asp = (sp->img->geom.height /
+                               (GLfloat) sp->img->geom.width);
+            GLfloat new_win = (MI_WIDTH(mi) / (double) MI_HEIGHT(mi));
+            GLfloat old_win = sp_asp / img_asp;
+            GLfloat r = old_win / new_win;
+            if (img_asp > 1)
+              {
+                sp->from.h    /= r;
+                sp->current.h /= r;
+                sp->to.h      /= r;
+              }
+            else
+              {
+                sp->from.w    *= r;
+                sp->current.w *= r;
+                sp->to.w      *= r;
+              }
+          }
+      }
+  }
+}
+
+
+static void
+parse_color (ModeInfo *mi, char *key, GLfloat color[4])
+{
+  XColor xcolor;
+  char *string = get_string_resource (mi->dpy, key, "EsperColor");
+  if (!XParseColor (mi->dpy, mi->xgwa.colormap, string, &xcolor))
+    {
+      fprintf (stderr, "%s: unparsable color in %s: %s\n", progname,
+               key, string);
+      exit (1);
+    }
+
+  color[0] = xcolor.red   / 65536.0;
+  color[1] = xcolor.green / 65536.0;
+  color[2] = xcolor.blue  / 65536.0;
+  color[3] = 1;
+}
+
+
+ENTRYPOINT void
+init_esper (ModeInfo *mi)
+{
+  int screen = MI_SCREEN(mi);
+  esper_state *ss;
+  int wire = MI_IS_WIREFRAME(mi);
+  
+  MI_INIT (mi, sss);
+  ss = &sss[screen];
+
+  if ((ss->glx_context = init_GL(mi)) != NULL) {
+    reshape_esper (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+  } else {
+    MI_CLEARWINDOW(mi);
+  }
+
+  parse_color (mi, "gridColor", ss->grid_color);
+  parse_color (mi, "reticleColor", ss->reticle_color);
+  parse_color (mi, "textColor", ss->text_color);
+
+  glDisable (GL_LIGHTING);
+  glDisable (GL_DEPTH_TEST);
+  glDepthMask (GL_FALSE);
+  glEnable (GL_CULL_FACE);
+  glCullFace (GL_BACK);
+
+  if (! wire)
+    {
+      glEnable (GL_TEXTURE_2D);
+      glShadeModel (GL_SMOOTH);
+      glEnable (GL_BLEND);
+      glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    }
+
+  ss->font_data = load_texture_font (mi->dpy, "titleFont");
+
+  ss->now = double_time();
+  ss->dawn_of_time = ss->now;
+
+  alloc_image (mi);
+
+  ss->anim_state = BLANK;
+  ss->anim_start = 0;
+  ss->anim_duration = 0;
+}
+
+
+ENTRYPOINT void
+draw_esper (ModeInfo *mi)
+{
+  esper_state *ss = &sss[MI_SCREEN(mi)];
+
+  if (!ss->glx_context)
+    return;
+
+  glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(ss->glx_context));
+
+  mi->polygon_count = 0;
+
+  ss->now = double_time();
+
+  tick_sprites (mi);
+  draw_sprites (mi);
+  if (ss->now >= ss->anim_start + ss->anim_duration)
+    tick_animation (mi);
+
+  if (mi->fps_p) do_fps (mi);
+
+  glFinish();
+  glXSwapBuffers (MI_DISPLAY (mi), MI_WINDOW(mi));
+}
+
+XSCREENSAVER_MODULE ("Esper", esper)
+
+#endif /* USE_GL */
diff --git a/hacks/glx/esper.man b/hacks/glx/esper.man
new file mode 100644 (file)
index 0000000..4d994d9
--- /dev/null
@@ -0,0 +1,68 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+esper - Enhance 224 to 176. Go right. Enhance 57 19. Track 45 left.
+.SH SYNOPSIS
+.B esper
+[\-display \fIhost:display.screen\fP]
+[\-visual \fIvisual\fP]
+[\-window]
+[\-root]
+[\-delay \fInumber\fP]
+[\-speed \fInumber\fP]
+[\-titles]
+[\-fps]
+.SH DESCRIPTION
+"Enhance 224 to 176. Pull out track right. Center in pull back. Pull back.
+Wait a minute. Go right. Stop. Enhance 57 19. Track 45 left. Gimme a
+hardcopy right there." 
+
+The Esper Machine was a voice-controlled forensic device used by LAPD
+in 2019, as documented in the 1982 film, \fIBlade Runner.\fP  It was
+capable of enhancing photographs to an extreme degree, including
+reconstructing different viewpoints within the space from the
+reflections on various objects in the photograph.
+.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: 20000 (0.02 seconds).
+.TP 8
+.B \-speed \fInumber\fP
+Animation speed.  2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-titles | \-no-titles
+Show file names.  Boolean.
+.TP 8
+.B \-fps | \-no-fps
+Whether to show a frames-per-second display at the top of the screen.
+.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 2017 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.
index c61f27a3ed9d1093ebb03fc05ed75f665bb1b532..b175ee4dec5e64ceeac91d2a0b525792d9a25bb3 100644 (file)
@@ -31,7 +31,7 @@
                                        "*showFPS:       False  \n" \
                                        "*wireframe: False   \n"
 
-# define refresh_extrusion 0
+# define free_extrusion 0
 # define release_extrusion 0
 # include "xlockmore.h"                                /* from the xscreensaver distribution */
 #else /* !STANDALONE */
@@ -383,8 +383,15 @@ ENTRYPOINT void
 reshape_extrusion (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -530,7 +537,7 @@ init_extrusion (ModeInfo * mi)
 
   if (MI_IS_WIREFRAME(mi)) do_light = 0;
 
-  MI_INIT(mi, Extrusion, NULL);
+  MI_INIT(mi, Extrusion);
   gp = &Extrusion[screen];
 
   gp->window = MI_WINDOW(mi);
index 02ec2d570266864cbf1ca9c89f732da0bf50fa29..c26458c2dc1cb22283514114fe8cefafb38c62a5 100644 (file)
@@ -43,7 +43,6 @@
                        "*showFPS:   False     \n" \
                        "*wireframe: False     \n"
 
-# define refresh_flipflop 0
 # define release_flipflop 0
 # include "xlockmore.h"
 
@@ -96,7 +95,7 @@ ENTRYPOINT ModeSpecOpt flipflop_opts = {countof(opts), opts, countof(vars), vars
 #ifdef USE_MODULES
 ModStruct   flipflop_description =
     {"flipflop", "init_flipflop", "draw_flipflop", NULL,
-     "draw_flipflop", "init_flipflop", NULL, &flipflop_opts,
+     "draw_flipflop", "init_flipflop", "free_flipflop", &flipflop_opts,
      1000, 1, 2, 1, 4, 1.0, "",
      "Flipflop", 0, NULL};
 
@@ -284,12 +283,20 @@ display(ModeInfo *mi)
 ENTRYPOINT void
 reshape_flipflop(ModeInfo *mi, int width, int height)
 {
-    GLfloat h = (GLfloat) height / (GLfloat) width;
-    glViewport(0,0, width, height);
-    glMatrixMode(GL_PROJECTION);
-    glLoadIdentity();
-    gluPerspective(45, 1/h, 1.0, 300.0);
-    glMatrixMode(GL_MODELVIEW);
+  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(45, 1/h, 1.0, 300.0);
+  glMatrixMode(GL_MODELVIEW);
 }
 
 static void
@@ -348,8 +355,6 @@ get_texture(ModeInfo *modeinfo)
                       image_loaded_cb, c);
 }
 
-static void free_flipflop(ModeInfo *mi);
-
 ENTRYPOINT void
 init_flipflop(ModeInfo *mi)
 {
@@ -395,7 +400,7 @@ init_flipflop(ModeInfo *mi)
     screen = MI_SCREEN(mi);
     wire = MI_IS_WIREFRAME(mi);
 
-    MI_INIT(mi, qs, free_flipflop);
+    MI_INIT(mi, qs);
 
     c = &qs[screen];
     c->window = MI_WINDOW(mi);
@@ -465,7 +470,7 @@ draw_flipflop(ModeInfo *mi)
 
 }
 
-static void
+ENTRYPOINT void
 free_flipflop(ModeInfo *mi)
 {
   Flipflopcreen *c = &qs[MI_SCREEN(mi)];
index 9bd6995650328eeddb4049edd6812787f740d0e7..e4db5df1bf4870536f5b8adbda2ca637e776f9f4 100644 (file)
@@ -21,7 +21,7 @@
                  "*useSHM:    True  \n" \
                 "*suppressRotationAnimation: True\n" \
 
-# define refresh_screenflip 0
+# define free_screenflip 0
 # define release_screenflip 0
 # include "xlockmore.h"                         /* from the xscreensaver distribution */
 # include "gltrackball.h"
@@ -306,7 +306,7 @@ static void drawgrid(void)
 static void display(Screenflip *c, int wire)
 {
   int frozen;
-/*  GLfloat rot = current_device_rotation();*/
+  GLfloat rot = current_device_rotation();
 
   glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
   glLoadIdentity();
@@ -335,9 +335,9 @@ static void display(Screenflip *c, int wire)
       if (random() % 2)
         c->dgamma = 1/60 - (float)(random() % 100)/3000;
     }
-/*    glRotatef(-rot, 0, 0, 1);*/
+    glRotatef(rot, 0, 0, 1);
     gltrackball_rotate (c->trackball);
-/*    glRotatef(rot, 0, 0, 1);*/
+    glRotatef(-rot, 0, 0, 1);
     if (rotate) glRotatef(c->rot, c->rx, c->ry, c->rz);
 /* update variables with each frame */
     if(!c->button_down_p && !c->fadetime) {
@@ -439,7 +439,7 @@ ENTRYPOINT void init_screenflip(ModeInfo *mi)
   int screen = MI_SCREEN(mi);
   Screenflip *c;
 
- MI_INIT(mi, screenflip, NULL);
+ MI_INIT(mi, screenflip);
  c = &screenflip[screen];
  c->window = MI_WINDOW(mi);
 
index d35706cb2a5ad0325c22c865f9341f72f2271c43..c233e8b5250af91ccdd630c1b4dc8b54c3f29730 100644 (file)
@@ -26,9 +26,8 @@
                 ".foreground: " DEF_COLOR "\n" \
                 "*program: xscreensaver-text --cols 0"  /* don't wrap */
 
-# define refresh_fliptext 0
 # define release_fliptext 0
-# define fliptext_handle_event 0
+# define fliptext_handle_event xlockmore_no_events
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
 
@@ -768,8 +767,15 @@ reshape_fliptext (ModeInfo *mi, int width, int height)
 {
   fliptext_configuration *sc = &scs[MI_SCREEN(mi)];
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -788,9 +794,6 @@ reshape_fliptext (ModeInfo *mi, int width, int height)
 }
 
 
-static void free_fliptext (ModeInfo *mi);
-
-
 ENTRYPOINT void 
 init_fliptext (ModeInfo *mi)
 {
@@ -798,7 +801,7 @@ init_fliptext (ModeInfo *mi)
 
   fliptext_configuration *sc;
 
-  MI_INIT(mi, scs, free_fliptext);
+  MI_INIT(mi, scs);
 
   sc = &scs[MI_SCREEN(mi)];
   sc->lines = (line **) calloc (max_lines+1, sizeof(char *));
@@ -982,7 +985,7 @@ draw_fliptext (ModeInfo *mi)
   glXSwapBuffers(dpy, window);
 }
 
-static void
+ENTRYPOINT void
 free_fliptext (ModeInfo *mi)
 {
   fliptext_configuration *sc = &scs[MI_SCREEN(mi)];
index e6d1b22699b2eaf28ac3efbf18565c9fadf84007..c9008a9471ed428f4500ee4c6da2c7e811e2569b 100644 (file)
@@ -47,9 +47,8 @@ static const char sccsid[] = "@(#)flurry.c    4.07 97/11/24 xlockmore";
 # define DEFAULTS              "*delay:      10000 \n" \
                                                "*showFPS:    False \n"
 
-# define refresh_flurry 0
 # define release_flurry 0
-# define flurry_handle_event 0
+# define flurry_handle_event xlockmore_no_events
 # include "xlockmore.h"                /* from the xscreensaver distribution */
 
 #ifdef USE_GL
@@ -76,7 +75,7 @@ ModStruct   flurry_description = {
     NULL,
     "draw_flurry",
     "init_flurry",
-    NULL,
+    "free_flurry",
     &flurry_opts,
     1000, 1, 2, 1, 4, 1.0,
     "",
@@ -326,8 +325,6 @@ ENTRYPOINT void reshape_flurry(ModeInfo *mi, int width, int height)
     GLResize(global, (float)width, (float)height);
 }
 
-static void free_flurry(ModeInfo * mi);
-
 ENTRYPOINT void
 init_flurry(ModeInfo * mi)
 {
@@ -345,7 +342,7 @@ init_flurry(ModeInfo * mi)
         PRESET_MAX
     } preset_num;
 
-    MI_INIT (mi, flurry_info, free_flurry);
+    MI_INIT (mi, flurry_info);
 
     global = &flurry_info[screen];
 
@@ -532,7 +529,7 @@ draw_flurry(ModeInfo * mi)
     glXSwapBuffers(display, window);
 }
 
-static void
+ENTRYPOINT void
 free_flurry(ModeInfo * mi)
 {
     global_info_t *global = &flurry_info[MI_SCREEN(mi)];
index d53a09ec8cd0c380bf8dba697e4733de3202a8f3..17339ae9d70a41288d373e9b28bb5560b590a3da 100644 (file)
@@ -32,7 +32,7 @@
 
 /* #define DEBUG */
 
-# define refresh_toasters 0
+# define free_toasters 0
 # define release_toasters 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -291,8 +291,15 @@ ENTRYPOINT void
 reshape_toasters (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -397,7 +404,7 @@ init_toasters (ModeInfo *mi)
   int wire = MI_IS_WIREFRAME(mi);
   int i;
 
-  MI_INIT (mi, bps, NULL);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
index 0c292a2eae8ef04f1d6369c88b71875cad22ec21..3976f2f13ef98211b63983217cae7dd799323075 100644 (file)
@@ -18,7 +18,7 @@
                        "*wireframe:    False       \n" \
                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_gears 0
+# define free_gears 0
 # define release_gears 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -86,8 +86,15 @@ ENTRYPOINT void
 reshape_gears (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -698,7 +705,7 @@ init_gears (ModeInfo *mi)
   int wire = MI_IS_WIREFRAME(mi);
   int i;
 
-  MI_INIT (mi, bps, NULL);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
index 6f4ed4bf1af9d261297ea359ea11e51257700d87..9ef269680899247142faa97f1cb326c339f84aa5 100644 (file)
@@ -14,7 +14,7 @@
                        "*showFPS:      False       \n" \
                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_geodesic 0
+# define free_geodesic 0
 # define release_geodesic 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -456,8 +456,15 @@ ENTRYPOINT void
 reshape_geodesic (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -488,7 +495,7 @@ init_geodesic (ModeInfo *mi)
   geodesic_configuration *bp;
   int wire = MI_IS_WIREFRAME(mi);
 
-  MI_INIT (mi, bps, NULL);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
index 47acee88fa4606febcabd52031f955a43dc5f989..ecc7f26c05ec8e9e25154920c9952b262019c63a 100644 (file)
@@ -20,7 +20,6 @@
                        "*suppressRotationAnimation: True\n" \
                "*font:  -*-helvetica-medium-r-normal-*-*-160-*-*-*-*-*-*\n" \
 
-# define refresh_geodesic 0
 # define release_geodesic 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -1318,10 +1317,17 @@ reshape_geodesic (ModeInfo *mi, int width, int height)
 {
   geodesic_configuration *bp = &bps[MI_SCREEN(mi)];
   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;
+  }
 
   glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context));
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -1402,7 +1408,6 @@ pick_shape (ModeInfo *mi, time_t last)
 }
 
 
-static void free_geodesic (ModeInfo *mi);
 
 ENTRYPOINT void 
 init_geodesic (ModeInfo *mi)
@@ -1410,7 +1415,7 @@ init_geodesic (ModeInfo *mi)
   geodesic_configuration *bp;
   int wire = MI_IS_WIREFRAME(mi);
 
-  MI_INIT (mi, bps, free_geodesic);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
@@ -1779,7 +1784,7 @@ draw_geodesic (ModeInfo *mi)
   glXSwapBuffers(dpy, window);
 }
 
-static void
+ENTRYPOINT void
 free_geodesic (ModeInfo *mi)
 {
   geodesic_configuration *bp = &bps[MI_SCREEN(mi)];
index 69636f276d18f9a8f436f8b0978565addfda9426..dbbb11c097e462f8093a214976109811ee54f384 100644 (file)
@@ -46,7 +46,7 @@
                                         "*useSHM:       True \n" \
                                                                                "*suppressRotationAnimation: True\n" \
 
-# define refresh_gflux 0
+# define free_gflux 0
 # define release_gflux 0
 # include "xlockmore.h"                                /* from the xscreensaver distribution */
 #else /* !STANDALONE */
@@ -359,7 +359,7 @@ ENTRYPOINT void init_gflux(ModeInfo * mi)
     int screen = MI_SCREEN(mi);
     gfluxstruct *gp;
 
-    MI_INIT(mi, gfluxes, NULL);
+    MI_INIT(mi, gfluxes);
     gp = &gfluxes[screen];
 
     gp->trackball = gltrackball_init (True);
index 3b25456734eba6ae06fcf1479b772b48c92220f8..36f38624526d41cbf13040b9bfeba866d585343c 100644 (file)
@@ -27,7 +27,7 @@
                        "*fpsSolid: True  \n" \
                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_glblur 0
+# define free_glblur 0
 # define release_glblur 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -367,7 +367,7 @@ init_glblur (ModeInfo *mi)
   glblur_configuration *bp;
   int wire = MI_IS_WIREFRAME(mi);
 
-  MI_INIT (mi, bps, NULL);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
index c0cbbbf077e983da3a2aa2baf17bb68914dab880..adf98666a7fa25cc0ac7bb2a5760cd45158d74ae 100644 (file)
@@ -36,9 +36,8 @@
 #define INDEX_OFFSET 100000
 #define NUM_CELL_SHAPES 10
 
-#define refresh_glcells 0
 #define release_glcells 0
-#define glcells_handle_event 0
+#define glcells_handle_event xlockmore_no_events
 
 #define DEF_DELAY     "20000"
 #define DEF_MAXCELLS  "800"
@@ -1267,15 +1266,13 @@ reshape_glcells( ModeInfo *mi, int width, int height )
 # endif
 }
 
-static void free_glcells( ModeInfo *mi );
-
 ENTRYPOINT void 
 init_glcells( ModeInfo *mi )
 {
   int i, divisions;
   State *st=0;
   
-  MI_INIT(mi, sstate, free_glcells);
+  MI_INIT(mi, sstate);
   st = &sstate[MI_SCREEN(mi)];
   
   st->glx_context = init_GL(mi);
@@ -1363,7 +1360,7 @@ draw_glcells( ModeInfo *mi )
   glXSwapBuffers( dpy, window );
 }
 
-static void
+ENTRYPOINT void 
 free_glcells( ModeInfo *mi )
 {
   int i;
index dd6533a6779d227c3d38e1e5ebbb4bb696c27e57..7e1d73d049bb17c47f113a0c32d8a6671178cab3 100644 (file)
@@ -77,7 +77,6 @@
                "*useSHM:               True            \n" \
                "*suppressRotationAnimation: True\n" \
 
-# define refresh_gleidescope 0
 # define release_gleidescope 0
 # include "xlockmore.h"                                /* from the xscreensaver distribution */
 #else  /* !STANDALONE */
@@ -183,8 +182,8 @@ ENTRYPOINT ModeSpecOpt gleidescope_opts = {
 #ifdef USE_MODULES
 ModStruct   gleidescope_description = { 
      "gleidescope", "init_gleidescope", "draw_gleidescope", NULL,
-     "draw_gleidescope", "init_gleidescope", NULL, &gleidescope_opts,
-     1000, 1, 2, 1, 4, 1.0, "",
+     "draw_gleidescope", "init_gleidescope", "free_gleidescope",
+     &gleidescope_opts, 1000, 1, 2, 1, 4, 1.0, "",
      "GL Kaleidescope", 0, NULL};
 #endif
 
@@ -1399,9 +1398,17 @@ ENTRYPOINT void reshape_gleidescope(ModeInfo *mi, int width, int height)
        gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
        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;
+    }
+
        glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(gp->glx_context));
 
-       glViewport(0, 0, (GLint) width, (GLint) height);
+       glViewport(0, y, (GLint) width, (GLint) height);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(50.0, 1/h, 0.1, 2000.0);
@@ -1525,15 +1532,13 @@ printf("phases [%d, %d, %d]\n", gp->cam_x_phase, gp->cam_y_phase, gp->cam_z_phas
 #endif
 }
 
-static void free_gleidescope(ModeInfo * mi);
-
 ENTRYPOINT void
 init_gleidescope(ModeInfo * mi)
 {
        gleidestruct *gp;
        int screen = MI_SCREEN(mi);
 
-       MI_INIT(mi, gleidescope, free_gleidescope);
+       MI_INIT(mi, gleidescope);
        gp = &gleidescope[screen];
        gp->window = MI_WINDOW(mi);
     gp->size = -1;
@@ -1601,7 +1606,7 @@ draw_gleidescope(ModeInfo * mi)
        }
 }
 
-static void
+ENTRYPOINT void
 free_gleidescope(ModeInfo * mi)
 {
        gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
index e81d51167f497be514660ceef31cf34bc24556f5..5ee4c0b97f333b9371ccecf007a2c577d99f539c 100644 (file)
@@ -81,7 +81,6 @@ static const char sccsid[] = "@(#)fire.c      5.02 2001/09/26 xlockmore";
                "*showFPS:    False \n" \
                "*wireframe:  False \n" \
 
-# define refresh_fire 0
 #define MODE_fire
 #include "xlockmore.h"         /* from the xscreensaver distribution */
 #include "gltrackball.h"
@@ -887,9 +886,11 @@ static Bool Init(ModeInfo * mi)
  */
 
 
-static void
-free_fire(firestruct *fs)
+ENTRYPOINT void
+free_fire(ModeInfo * mi)
 {
+       firestruct *fs = &fire[MI_SCREEN(mi)];
+
        if (mode_font != None && fs->fontbase != None) {
                glDeleteLists(fs->fontbase, mode_font->max_char_or_byte2 -
                        mode_font->min_char_or_byte2 + 1);
@@ -931,7 +932,7 @@ init_fire(ModeInfo * mi)
 {
     firestruct *fs;
 
-    MI_INIT (mi, fire, 0);
+    MI_INIT (mi, fire);
     fs = &fire[MI_SCREEN(mi)];
     fs->np = MI_COUNT(mi);
     fs->fog = do_fog;
@@ -939,14 +940,14 @@ init_fire(ModeInfo * mi)
     /* initialise fire particles if any */
     if ((fs->np)&&(fs->p == NULL)) {
        if ((fs->p = (part *) calloc(fs->np, sizeof(part))) == NULL) {
-           free_fire(fs);
+           free_fire(mi);
            return;
        }
     }
     else if (fs->r == NULL) {
         /* initialise rain particles if no fire particles */
        if ((fs->r = (rain *) calloc(NUMPART, sizeof(part))) == NULL) {
-           free_fire(fs);
+           free_fire(mi);
            return;
        }
     }
@@ -969,7 +970,7 @@ init_fire(ModeInfo * mi)
 #endif
        glDrawBuffer(GL_BACK);
        if (!Init(mi)) {
-               free_fire(fs);
+               free_fire(mi);
                return;
        }
     } else {
@@ -1038,13 +1039,6 @@ ENTRYPOINT void draw_fire(ModeInfo * mi)
 
 ENTRYPOINT void release_fire(ModeInfo * mi)
 {
-    if (fire != NULL) {
-    int screen;
-       for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
-               free_fire(&fire[screen]);
-       (void) free((void *) fire);
-       fire = (firestruct *) NULL;
-    }
     if (mode_font != None)
     {
        /* only free-ed when there are no more screens used */
index e390f688c0663fa4f72a1f8281fee88b2968b687..865930f6736065653a841a6cd1ed57e0a5df37e1 100644 (file)
@@ -28,7 +28,6 @@
                                 "*showFPS:   False\n" \
                                 "*wireframe: False\n"
                                 
-# define refresh_glhanoi 0
 # define release_glhanoi 0
 
 /* polygon resolution of poles and disks */
@@ -237,7 +236,7 @@ ENTRYPOINT ModeSpecOpt glhanoi_opts = { countof(opts), opts, countof(vars), vars
 
 ModStruct glhanoi_description = {
        "glhanoi", "init_glhanoi", "draw_glhanoi", NULL,
-       "draw_glhanoi", "init_glhanoi", NULL, &glhanoi_opts,
+       "draw_glhanoi", "init_glhanoi", "free_glhanoi", &glhanoi_opts,
        1000, 1, 2, 1, 4, 1.0, "",
        "Towers of Hanoi", 0, NULL
 };
@@ -1847,13 +1846,22 @@ static int drawTrails(glhcfg *glhanoi) {
 ENTRYPOINT void reshape_glhanoi(ModeInfo * mi, int width, int height)
 {
        glhcfg *glhanoi = &glhanoi_cfg[MI_SCREEN(mi)];
+    double 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;
+    }
+
        glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(glhanoi->glx_context));
 
-       glViewport(0, 0, (GLint) width, (GLint) height);
+       glViewport(0, y, (GLint) width, (GLint) height);
 
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
-       gluPerspective(30.0, (GLdouble) width / (GLdouble) height, 1.0,
+       gluPerspective(30.0, 1/h, 1.0,
                                   2 * MAX_CAMERA_RADIUS);
 
        glMatrixMode(GL_MODELVIEW);
@@ -1862,12 +1870,10 @@ ENTRYPOINT void reshape_glhanoi(ModeInfo * mi, int width, int height)
        glClear(GL_COLOR_BUFFER_BIT);
 }
 
-static void free_glhanoi(ModeInfo * mi);
-
 ENTRYPOINT void init_glhanoi(ModeInfo * mi)
 {
        glhcfg *glhanoi;
-       MI_INIT(mi, glhanoi_cfg, free_glhanoi);
+       MI_INIT(mi, glhanoi_cfg);
 
        glhanoi = &glhanoi_cfg[MI_SCREEN(mi)];
        glhanoi->glx_context = init_GL(mi);
@@ -2052,7 +2058,7 @@ ENTRYPOINT Bool glhanoi_handle_event(ModeInfo * mi, XEvent * event)
        return False;
 }
 
-static void free_glhanoi(ModeInfo * mi)
+ENTRYPOINT void free_glhanoi(ModeInfo * mi)
 {
        int i;
        int j;
index 15c67dee56c5acd471eb31ef14cb0e42e78bb3ac..730cadb19ec9274708b49f8402879ca38b8504df 100644 (file)
@@ -18,7 +18,7 @@
                        "*wireframe:    False       \n" \
                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_knot 0
+# define free_knot 0
 # define release_knot 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -178,8 +178,15 @@ ENTRYPOINT void
 reshape_knot (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -257,7 +264,7 @@ init_knot (ModeInfo *mi)
   knot_configuration *bp;
   int wire = MI_IS_WIREFRAME(mi);
 
-  MI_INIT (mi, bps, NULL);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
index 4782c1cc7f65ce912822f00a26e8d9caa8ae1a4f..7683c39ffe614331adce6e5f4922259a18fc418a 100644 (file)
@@ -20,7 +20,7 @@
                        "*showFPS:      False         \n" \
                        "*wireframe:    False         \n" \
 
-# define refresh_matrix 0
+# define free_matrix 0
 # define release_matrix 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -572,8 +572,15 @@ ENTRYPOINT void
 reshape_matrix (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -822,7 +829,7 @@ init_matrix (ModeInfo *mi)
   if (wire)
     do_texture = False;
 
-  MI_INIT (mi, mps, NULL);
+  MI_INIT (mi, mps);
 
   mp = &mps[MI_SCREEN(mi)];
   mp->glx_context = init_GL(mi);
index 4b21dd118e591ee570706ba959ec2ec2c6a151bf..0e94270134dd6588d574090d20216a7c18c307da 100644 (file)
@@ -38,7 +38,6 @@
                                        "*imageBackground:      Blue    \n" \
                                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_planet 0
 # define release_planet 0
 # include "xlockmore.h"                                /* from the xscreensaver distribution */
 #else  /* !STANDALONE */
@@ -115,7 +114,7 @@ ENTRYPOINT ModeSpecOpt planet_opts = {countof(opts), opts, countof(vars), vars,
 #ifdef USE_MODULES
 ModStruct   planet_description =
 {"planet", "init_planet", "draw_planet", NULL,
- "draw_planet", "init_planet", NULL, &planet_opts,
+ "draw_planet", "init_planet", "free_planet", &planet_opts,
  1000, 1, 2, 1, 4, 1.0, "",
  "Animates texture mapped sphere (planet)", 0, NULL};
 #endif
@@ -365,9 +364,6 @@ planet_handle_event (ModeInfo *mi, XEvent *event)
 }
 
 
-static void free_planet (ModeInfo * mi);
-
-
 ENTRYPOINT void
 init_planet (ModeInfo * mi)
 {
@@ -375,7 +371,7 @@ init_planet (ModeInfo * mi)
   int screen = MI_SCREEN(mi);
   Bool wire = MI_IS_WIREFRAME(mi);
 
-  MI_INIT (mi, planets, free_planet);
+  MI_INIT (mi, planets);
   gp = &planets[screen];
 
   gp->window = MI_WINDOW(mi);
@@ -638,7 +634,7 @@ draw_planet (ModeInfo * mi)
 }
 
 
-static void
+ENTRYPOINT void
 free_planet (ModeInfo * mi)
 {
   planetstruct *gp = &planets[MI_SCREEN(mi)];
index c8f6e2c1490ae1160bfc5cbb3c9549457f9f3d54..49cfc1154a66025919fb6beaaac0804db1da5e4f 100644 (file)
@@ -16,9 +16,9 @@
                     "*showFPS:      False       \n" \
                     "*wireframe:    False       \n" \
 
-#define refresh_glschool               (0)
+#define free_glschool                  (0)
 #define release_glschool               (0)
-#define glschool_handle_event  (0)
+#define glschool_handle_event  (xlockmore_no_events)
 
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -142,7 +142,7 @@ init_glschool(ModeInfo *mi)
        Bool                                    wire = MI_IS_WIREFRAME(mi);
        glschool_configuration  *sc;
 
-       MI_INIT (mi, scs, NULL);
+       MI_INIT (mi, scs);
        sc = &scs[MI_SCREEN(mi)];
 
        sc->drawGoal = DoDrawGoal;
index a6a56905e597d975d00eb63e43615c947d6cf912..64b1494cbfd15532d542e79f54b6c42671f319f2 100644 (file)
@@ -78,7 +78,7 @@
                  "*grabDesktopImages:   False \n" \
                  "*chooseRandomImages:  True  \n"
 
-# define refresh_slideshow 0
+# define free_slideshow 0
 # define release_slideshow 0
 # include "xlockmore.h"
 
@@ -1079,7 +1079,7 @@ init_slideshow (ModeInfo *mi)
   slideshow_state *ss;
   int wire = MI_IS_WIREFRAME(mi);
   
-  MI_INIT (mi, sss, NULL);
+  MI_INIT (mi, sss);
   ss = &sss[screen];
 
   if ((ss->glx_context = init_GL(mi)) != NULL) {
index 1d8ef965a10a73c398d5125e300d8ebd0d5cec13..5f20421537ae6d69eca1e3f8691d48e940dcffc8 100644 (file)
@@ -144,9 +144,9 @@ static GLfloat angvel;
 #define glsnake_init    init_glsnake
 #define glsnake_display draw_glsnake
 #define glsnake_reshape reshape_glsnake
-#define refresh_glsnake 0
+#define free_glsnake 0
 #define release_glsnake 0
-#define glsnake_handle_event 0
+#define glsnake_handle_event xlockmore_no_events
 
 /* xscreensaver defaults */
 #define DEFAULTS "*delay:          30000                      \n" \
@@ -1461,7 +1461,7 @@ ModeInfo * mi
     struct glsnake_cfg * bp;
 
     /* set up the conf struct and glx contexts */
-    MI_INIT(mi, glc, NULL);
+    MI_INIT(mi, glc);
     bp = &glc[MI_SCREEN(mi)];
 
     if ((bp->glx_context = init_GL(mi)) != NULL) {
@@ -1768,20 +1768,29 @@ ENTRYPOINT void glsnake_reshape(
 #ifndef HAVE_GLUT
                     ModeInfo * mi,
 #endif
-                    int w, int h
+                    int width, int height
 {
-    glViewport(0, 0, (GLint) w, (GLint) h);
+    double h = (GLfloat) height / (GLfloat) width;  
+    int y = 0;
+
+    if (width > height * 5) {   /* tiny window: show middle */
+      height = width;
+      y = -height/2;
+      h = height / (GLfloat) width;
+    }
+
+    glViewport(0, y, width, height);
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
     /* jwz: 0.05 was too close (left black rectangles) */
-    gluPerspective(zoom, (GLdouble) w / (GLdouble) h, 1.0, 100.0);
+    gluPerspective(zoom, 1/h, 1.0, 100.0);
     gluLookAt(0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
     glMatrixMode(GL_MODELVIEW);
     /*gluLookAt(0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);*/
     glLoadIdentity();
 #ifdef HAVE_GLUT
-    bp->width = w;
-    bp->height = h;
+    bp->width = width;
+    bp->height = height;
 #endif
 }
 
index cc39bc928fe3e5f8bd6ea79cf4a3f9f3bb225ac5..276c44898293dbe175e3286106b3d944eb480ebf 100644 (file)
@@ -1,4 +1,4 @@
-/* gltext, Copyright (c) 2001-2014 Jamie Zawinski <jwz@jwz.org>
+/* gltext, Copyright (c) 2001-2017 Jamie Zawinski <jwz@jwz.orgq2
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -14,7 +14,6 @@
                        "*wireframe:    False        \n" \
                        "*usePty:       False        \n" \
 
-# define refresh_text 0
 # define release_text 0
 #define SMOOTH_TUBE       /* whether to have smooth or faceted tubes */
 
 
 #ifdef USE_GL /* whole file */
 
-#define DEF_TEXT        "(default)"
-#define DEF_PROGRAM     "(default)"
-#define DEF_SPIN        "XYZ"
-#define DEF_WANDER      "True"
-#define DEF_FACE_FRONT  "True"
+#define DEF_TEXT          "(default)"
+#define DEF_PROGRAM       "(default)"
+#define DEF_SCALE_FACTOR  "0.01"
+#define DEF_WANDER_SPEED  "0.02"
+#define DEF_MAX_LINES     "8"
+#define DEF_SPIN          "XYZ"
+#define DEF_WANDER        "True"
+#define DEF_FACE_FRONT    "True"
+#define DEF_USE_MONOSPACE "False"
 
 #ifdef HAVE_UNAME
 # include <sys/utsname.h>
 
 #include "glutstroke.h"
 #include "glut_roman.h"
-#define GLUT_FONT (&glutStrokeRoman)
+#include "glut_mroman.h"
+#define GLUT_VARI_FONT (&glutStrokeRoman)
+#define GLUT_MONO_FONT (&glutStrokeMonoRoman)
+#define GLUT_FONT ((use_monospace) ? GLUT_MONO_FONT : GLUT_VARI_FONT)
 
 
 typedef struct {
@@ -79,29 +85,42 @@ typedef struct {
 
 static text_configuration *tps = NULL;
 
-static char *text_fmt;
-static char *program_str;
-static char *do_spin;
-static Bool do_wander;
-static Bool face_front_p;
+static char   *text_fmt;
+static char   *program_str;
+static float  scale_factor;
+static int    max_no_lines;
+static float  wander_speed;
+static char   *do_spin;
+static Bool   do_wander;
+static Bool   face_front_p;
+static Bool   use_monospace;
 
 static XrmOptionDescRec opts[] = {
-  { "-text",    ".text",      XrmoptionSepArg, 0 },
-  { "-program", ".program",   XrmoptionSepArg, 0 },
-  { "-spin",    ".spin",      XrmoptionSepArg, 0 },
-  { "+spin",    ".spin",      XrmoptionNoArg, "" },
-  { "-wander",  ".wander",    XrmoptionNoArg, "True" },
-  { "+wander",  ".wander",    XrmoptionNoArg, "False" },
-  { "-front",   ".faceFront", XrmoptionNoArg, "True" },
-  { "+front",   ".faceFront", XrmoptionNoArg, "False" }
+  { "-text",         ".text",         XrmoptionSepArg, 0 },
+  { "-program",      ".program",      XrmoptionSepArg, 0 },
+  { "-scale",        ".scaleFactor",  XrmoptionSepArg, 0 },
+  { "-maxlines",     ".maxLines",     XrmoptionSepArg, 0 },
+  { "-wander-speed", ".wanderSpeed",  XrmoptionSepArg, 0 },
+  { "-spin",         ".spin",         XrmoptionSepArg, 0 },
+  { "+spin",         ".spin",         XrmoptionNoArg, "" },
+  { "-wander",       ".wander",       XrmoptionNoArg, "True" },
+  { "+wander",       ".wander",       XrmoptionNoArg, "False" },
+  { "-front",        ".faceFront",    XrmoptionNoArg, "True" },
+  { "+front",        ".faceFront",    XrmoptionNoArg, "False" },
+  { "-mono",         ".useMonoSpace", XrmoptionNoArg, "True" },
+  { "+mono",         ".useMonoSpace", XrmoptionNoArg, "False" }
 };
 
 static argtype vars[] = {
-  {&text_fmt,     "text",      "Text",      DEF_TEXT,       t_String},
-  {&program_str,  "program",   "Program",   DEF_PROGRAM,    t_String},
-  {&do_spin,      "spin",      "Spin",      DEF_SPIN,       t_String},
-  {&do_wander,    "wander",    "Wander",    DEF_WANDER,     t_Bool},
-  {&face_front_p, "faceFront", "FaceFront", DEF_FACE_FRONT, t_Bool},
+  {&text_fmt,      "text",         "Text",         DEF_TEXT,          t_String},
+  {&program_str,   "program",      "Program",      DEF_PROGRAM,       t_String},
+  {&do_spin,       "spin",         "Spin",         DEF_SPIN,          t_String},
+  {&scale_factor,  "scaleFactor",  "ScaleFactor",  DEF_SCALE_FACTOR,  t_Float},
+  {&max_no_lines,  "maxLines",     "MaxLines",     DEF_MAX_LINES,     t_Int},
+  {&wander_speed,  "wanderSpeed",  "WanderSpeed",  DEF_WANDER_SPEED,  t_Float},
+  {&do_wander,     "wander",       "Wander",       DEF_WANDER,        t_Bool},
+  {&face_front_p,  "faceFront",    "FaceFront",    DEF_FACE_FRONT,    t_Bool},
+  {&use_monospace, "useMonoSpace", "UseMonoSpace", DEF_USE_MONOSPACE, t_Bool},
 };
 
 ENTRYPOINT ModeSpecOpt text_opts = {countof(opts), opts, countof(vars), vars, NULL};
@@ -113,8 +132,15 @@ ENTRYPOINT void
 reshape_text (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -169,8 +195,8 @@ parse_text (ModeInfo *mi)
 
   if (program_str && *program_str && !!strcmp(program_str, "(default)"))
     {
-      int max_lines = 8;
-      char buf[1024];
+      int max_lines = max_no_lines;
+      char buf[4096];
       char *p = buf;
       int lines = 0;
 
@@ -317,16 +343,13 @@ text_handle_event (ModeInfo *mi, XEvent *event)
 }
 
 
-static void free_text(ModeInfo * mi);
-
-
 ENTRYPOINT void 
 init_text (ModeInfo *mi)
 {
   text_configuration *tp;
   int i;
 
-  MI_INIT (mi, tps, free_text);
+  MI_INIT (mi, tps);
 
   tp = &tps[MI_SCREEN(mi)];
 
@@ -611,7 +634,7 @@ draw_text (ModeInfo *mi)
 
   glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color);
 
-  glScalef(0.01, 0.01, 0.01);
+  glScalef(scale_factor, scale_factor, scale_factor);
 
   mi->polygon_count = fill_string(tp->text, wire);
 
index 3ab2265b4b549cfb593fbe28521dbbf34d991506..0d30c5fff17c73f5860884615a5b336479d4d129 100644 (file)
@@ -75,12 +75,31 @@ short.  You might try:
 -program 'xscreensaver-text --cols 20'
 .EE
 .TP 8
+.B \-maxlines
+Set the number of lines of text to display.  By default, 
+.I gltext
+will print 8 lines of text at a time.  Use this option to increase or
+decrease that number.  Be aware that 
+.I gltext
+is designed to work with a fairly small amount of text, so setting this
+value too high might result in slow performance or strange behaviour
+stemming from buffer overflows.  Increase at your own risk.
+.TP 8
+.B \-mono
+Display the text in a monospace font.  Default is a variable-width font.
+.TP 8
+.B \-no\-mono
+Display the text in a variable-width font.  This is the default.  
+.TP 8
 .B \-wander
 Move the text around the screen.  This is the default.
 .TP 8
 .B \-no\-wander
 Keep the text centered on the screen.
 .TP 8
+.B \-wander\-speed
+Sets the speed at which the text wanders around.  Default is 0.02.  
+.TP 8
 .B \-spin
 Which axes around which the text should spin.  The default is "XYZ",
 meaning rotate it freely in space.  "\fB\-spin Z\fP" would rotate the
@@ -102,6 +121,11 @@ Render in wireframe instead of solid.
 .TP 8
 .B \-fps
 Display the current frame rate, CPU load, and polygon count.
+.TP 8
+.B \-scale
+Sets the scale at which the text is rendered.  Bigger values will result
+in bigger text; smaller values will result in smaller text.  The default
+value is 0.01.  
 .SH ENVIRONMENT
 .PP
 .TP 8
diff --git a/hacks/glx/glut_mroman.h b/hacks/glx/glut_mroman.h
new file mode 100644 (file)
index 0000000..39eb171
--- /dev/null
@@ -0,0 +1,2456 @@
+/* Roman monospaced simplex stroke font copyright (c) 1989, 1990, 1991
+ * by Sun Microsystems, Inc. and the X Consortium.
+ * Originally part of the GLUT library by Mark J. Kilgard.
+ * I have changed names so that this can be a .h rather than a .c file without
+ * causing name clashes with glut_roman.h
+ */
+
+#include "glutstroke.h"
+
+/* char: 33 '!' */
+
+static const CoordRec monoChar33_stroke0[] = {
+    { 52.381, 100 },
+    { 52.381, 33.3333 },
+};
+
+static const CoordRec monoChar33_stroke1[] = {
+    { 52.381, 9.5238 },
+    { 47.6191, 4.7619 },
+    { 52.381, 0 },
+    { 57.1429, 4.7619 },
+    { 52.381, 9.5238 },
+};
+
+static const StrokeRec monoChar33[] = {
+   { 2, monoChar33_stroke0 },
+   { 5, monoChar33_stroke1 },
+};
+
+/* char: 34 '"' */
+
+static const CoordRec monoChar34_stroke0[] = {
+    { 33.3334, 100 },
+    { 33.3334, 66.6667 },
+};
+
+static const CoordRec monoChar34_stroke1[] = {
+    { 71.4286, 100 },
+    { 71.4286, 66.6667 },
+};
+
+static const StrokeRec monoChar34[] = {
+   { 2, monoChar34_stroke0 },
+   { 2, monoChar34_stroke1 },
+};
+
+/* char: 35 '#' */
+
+static const CoordRec monoChar35_stroke0[] = {
+    { 54.7619, 119.048 },
+    { 21.4286, -33.3333 },
+};
+
+static const CoordRec monoChar35_stroke1[] = {
+    { 83.3334, 119.048 },
+    { 50, -33.3333 },
+};
+
+static const CoordRec monoChar35_stroke2[] = {
+    { 21.4286, 57.1429 },
+    { 88.0952, 57.1429 },
+};
+
+static const CoordRec monoChar35_stroke3[] = {
+    { 16.6667, 28.5714 },
+    { 83.3334, 28.5714 },
+};
+
+static const StrokeRec monoChar35[] = {
+   { 2, monoChar35_stroke0 },
+   { 2, monoChar35_stroke1 },
+   { 2, monoChar35_stroke2 },
+   { 2, monoChar35_stroke3 },
+};
+
+/* char: 36 '$' */
+
+static const CoordRec monoChar36_stroke0[] = {
+    { 42.8571, 119.048 },
+    { 42.8571, -19.0476 },
+};
+
+static const CoordRec monoChar36_stroke1[] = {
+    { 61.9047, 119.048 },
+    { 61.9047, -19.0476 },
+};
+
+static const CoordRec monoChar36_stroke2[] = {
+    { 85.7143, 85.7143 },
+    { 76.1905, 95.2381 },
+    { 61.9047, 100 },
+    { 42.8571, 100 },
+    { 28.5714, 95.2381 },
+    { 19.0476, 85.7143 },
+    { 19.0476, 76.1905 },
+    { 23.8095, 66.6667 },
+    { 28.5714, 61.9048 },
+    { 38.0952, 57.1429 },
+    { 66.6666, 47.619 },
+    { 76.1905, 42.8571 },
+    { 80.9524, 38.0952 },
+    { 85.7143, 28.5714 },
+    { 85.7143, 14.2857 },
+    { 76.1905, 4.7619 },
+    { 61.9047, 0 },
+    { 42.8571, 0 },
+    { 28.5714, 4.7619 },
+    { 19.0476, 14.2857 },
+};
+
+static const StrokeRec monoChar36[] = {
+   { 2, monoChar36_stroke0 },
+   { 2, monoChar36_stroke1 },
+   { 20, monoChar36_stroke2 },
+};
+
+/* char: 37 '%' */
+
+static const CoordRec monoChar37_stroke0[] = {
+    { 95.2381, 100 },
+    { 9.5238, 0 },
+};
+
+static const CoordRec monoChar37_stroke1[] = {
+    { 33.3333, 100 },
+    { 42.8571, 90.4762 },
+    { 42.8571, 80.9524 },
+    { 38.0952, 71.4286 },
+    { 28.5714, 66.6667 },
+    { 19.0476, 66.6667 },
+    { 9.5238, 76.1905 },
+    { 9.5238, 85.7143 },
+    { 14.2857, 95.2381 },
+    { 23.8095, 100 },
+    { 33.3333, 100 },
+    { 42.8571, 95.2381 },
+    { 57.1428, 90.4762 },
+    { 71.4286, 90.4762 },
+    { 85.7143, 95.2381 },
+    { 95.2381, 100 },
+};
+
+static const CoordRec monoChar37_stroke2[] = {
+    { 76.1905, 33.3333 },
+    { 66.6667, 28.5714 },
+    { 61.9048, 19.0476 },
+    { 61.9048, 9.5238 },
+    { 71.4286, 0 },
+    { 80.9524, 0 },
+    { 90.4762, 4.7619 },
+    { 95.2381, 14.2857 },
+    { 95.2381, 23.8095 },
+    { 85.7143, 33.3333 },
+    { 76.1905, 33.3333 },
+};
+
+static const StrokeRec monoChar37[] = {
+   { 2, monoChar37_stroke0 },
+   { 16, monoChar37_stroke1 },
+   { 11, monoChar37_stroke2 },
+};
+
+/* char: 38 '&' */
+
+static const CoordRec monoChar38_stroke0[] = {
+    { 100, 57.1429 },
+    { 100, 61.9048 },
+    { 95.2381, 66.6667 },
+    { 90.4762, 66.6667 },
+    { 85.7143, 61.9048 },
+    { 80.9524, 52.381 },
+    { 71.4286, 28.5714 },
+    { 61.9048, 14.2857 },
+    { 52.3809, 4.7619 },
+    { 42.8571, 0 },
+    { 23.8095, 0 },
+    { 14.2857, 4.7619 },
+    { 9.5238, 9.5238 },
+    { 4.7619, 19.0476 },
+    { 4.7619, 28.5714 },
+    { 9.5238, 38.0952 },
+    { 14.2857, 42.8571 },
+    { 47.619, 61.9048 },
+    { 52.3809, 66.6667 },
+    { 57.1429, 76.1905 },
+    { 57.1429, 85.7143 },
+    { 52.3809, 95.2381 },
+    { 42.8571, 100 },
+    { 33.3333, 95.2381 },
+    { 28.5714, 85.7143 },
+    { 28.5714, 76.1905 },
+    { 33.3333, 61.9048 },
+    { 42.8571, 47.619 },
+    { 66.6667, 14.2857 },
+    { 76.1905, 4.7619 },
+    { 85.7143, 0 },
+    { 95.2381, 0 },
+    { 100, 4.7619 },
+    { 100, 9.5238 },
+};
+
+static const StrokeRec monoChar38[] = {
+   { 34, monoChar38_stroke0 },
+};
+
+/* char: 39 ''' */
+
+static const CoordRec monoChar39_stroke0[] = {
+    { 52.381, 100 },
+    { 52.381, 66.6667 },
+};
+
+static const StrokeRec monoChar39[] = {
+   { 2, monoChar39_stroke0 },
+};
+
+/* char: 40 '(' */
+
+static const CoordRec monoChar40_stroke0[] = {
+    { 69.0476, 119.048 },
+    { 59.5238, 109.524 },
+    { 50, 95.2381 },
+    { 40.4762, 76.1905 },
+    { 35.7143, 52.381 },
+    { 35.7143, 33.3333 },
+    { 40.4762, 9.5238 },
+    { 50, -9.5238 },
+    { 59.5238, -23.8095 },
+    { 69.0476, -33.3333 },
+};
+
+static const StrokeRec monoChar40[] = {
+   { 10, monoChar40_stroke0 },
+};
+
+/* char: 41 ')' */
+
+static const CoordRec monoChar41_stroke0[] = {
+    { 35.7143, 119.048 },
+    { 45.2381, 109.524 },
+    { 54.7619, 95.2381 },
+    { 64.2857, 76.1905 },
+    { 69.0476, 52.381 },
+    { 69.0476, 33.3333 },
+    { 64.2857, 9.5238 },
+    { 54.7619, -9.5238 },
+    { 45.2381, -23.8095 },
+    { 35.7143, -33.3333 },
+};
+
+static const StrokeRec monoChar41[] = {
+   { 10, monoChar41_stroke0 },
+};
+
+/* char: 42 '*' */
+
+static const CoordRec monoChar42_stroke0[] = {
+    { 52.381, 71.4286 },
+    { 52.381, 14.2857 },
+};
+
+static const CoordRec monoChar42_stroke1[] = {
+    { 28.5715, 57.1429 },
+    { 76.1905, 28.5714 },
+};
+
+static const CoordRec monoChar42_stroke2[] = {
+    { 76.1905, 57.1429 },
+    { 28.5715, 28.5714 },
+};
+
+static const StrokeRec monoChar42[] = {
+   { 2, monoChar42_stroke0 },
+   { 2, monoChar42_stroke1 },
+   { 2, monoChar42_stroke2 },
+};
+
+/* char: 43 '+' */
+
+static const CoordRec monoChar43_stroke0[] = {
+    { 52.3809, 85.7143 },
+    { 52.3809, 0 },
+};
+
+static const CoordRec monoChar43_stroke1[] = {
+    { 9.5238, 42.8571 },
+    { 95.2381, 42.8571 },
+};
+
+static const StrokeRec monoChar43[] = {
+   { 2, monoChar43_stroke0 },
+   { 2, monoChar43_stroke1 },
+};
+
+/* char: 44 ',' */
+
+static const CoordRec monoChar44_stroke0[] = {
+    { 57.1429, 4.7619 },
+    { 52.381, 0 },
+    { 47.6191, 4.7619 },
+    { 52.381, 9.5238 },
+    { 57.1429, 4.7619 },
+    { 57.1429, -4.7619 },
+    { 52.381, -14.2857 },
+    { 47.6191, -19.0476 },
+};
+
+static const StrokeRec monoChar44[] = {
+   { 8, monoChar44_stroke0 },
+};
+
+/* char: 45 '-' */
+
+static const CoordRec monoChar45_stroke0[] = {
+    { 9.5238, 42.8571 },
+    { 95.2381, 42.8571 },
+};
+
+static const StrokeRec monoChar45[] = {
+   { 2, monoChar45_stroke0 },
+};
+
+/* char: 46 '.' */
+
+static const CoordRec monoChar46_stroke0[] = {
+    { 52.381, 9.5238 },
+    { 47.6191, 4.7619 },
+    { 52.381, 0 },
+    { 57.1429, 4.7619 },
+    { 52.381, 9.5238 },
+};
+
+static const StrokeRec monoChar46[] = {
+   { 5, monoChar46_stroke0 },
+};
+
+/* char: 47 '/' */
+
+static const CoordRec monoChar47_stroke0[] = {
+    { 19.0476, -14.2857 },
+    { 85.7143, 100 },
+};
+
+static const StrokeRec monoChar47[] = {
+   { 2, monoChar47_stroke0 },
+};
+
+/* char: 48 '0' */
+
+static const CoordRec monoChar48_stroke0[] = {
+    { 47.619, 100 },
+    { 33.3333, 95.2381 },
+    { 23.8095, 80.9524 },
+    { 19.0476, 57.1429 },
+    { 19.0476, 42.8571 },
+    { 23.8095, 19.0476 },
+    { 33.3333, 4.7619 },
+    { 47.619, 0 },
+    { 57.1428, 0 },
+    { 71.4286, 4.7619 },
+    { 80.9524, 19.0476 },
+    { 85.7143, 42.8571 },
+    { 85.7143, 57.1429 },
+    { 80.9524, 80.9524 },
+    { 71.4286, 95.2381 },
+    { 57.1428, 100 },
+    { 47.619, 100 },
+};
+
+static const StrokeRec monoChar48[] = {
+   { 17, monoChar48_stroke0 },
+};
+
+/* char: 49 '1' */
+
+static const CoordRec monoChar49_stroke0[] = {
+    { 40.4762, 80.9524 },
+    { 50, 85.7143 },
+    { 64.2857, 100 },
+    { 64.2857, 0 },
+};
+
+static const StrokeRec monoChar49[] = {
+   { 4, monoChar49_stroke0 },
+};
+
+/* char: 50 '2' */
+
+static const CoordRec monoChar50_stroke0[] = {
+    { 23.8095, 76.1905 },
+    { 23.8095, 80.9524 },
+    { 28.5714, 90.4762 },
+    { 33.3333, 95.2381 },
+    { 42.8571, 100 },
+    { 61.9047, 100 },
+    { 71.4286, 95.2381 },
+    { 76.1905, 90.4762 },
+    { 80.9524, 80.9524 },
+    { 80.9524, 71.4286 },
+    { 76.1905, 61.9048 },
+    { 66.6666, 47.619 },
+    { 19.0476, 0 },
+    { 85.7143, 0 },
+};
+
+static const StrokeRec monoChar50[] = {
+   { 14, monoChar50_stroke0 },
+};
+
+/* char: 51 '3' */
+
+static const CoordRec monoChar51_stroke0[] = {
+    { 28.5714, 100 },
+    { 80.9524, 100 },
+    { 52.3809, 61.9048 },
+    { 66.6666, 61.9048 },
+    { 76.1905, 57.1429 },
+    { 80.9524, 52.381 },
+    { 85.7143, 38.0952 },
+    { 85.7143, 28.5714 },
+    { 80.9524, 14.2857 },
+    { 71.4286, 4.7619 },
+    { 57.1428, 0 },
+    { 42.8571, 0 },
+    { 28.5714, 4.7619 },
+    { 23.8095, 9.5238 },
+    { 19.0476, 19.0476 },
+};
+
+static const StrokeRec monoChar51[] = {
+   { 15, monoChar51_stroke0 },
+};
+
+/* char: 52 '4' */
+
+static const CoordRec monoChar52_stroke0[] = {
+    { 64.2857, 100 },
+    { 16.6667, 33.3333 },
+    { 88.0952, 33.3333 },
+};
+
+static const CoordRec monoChar52_stroke1[] = {
+    { 64.2857, 100 },
+    { 64.2857, 0 },
+};
+
+static const StrokeRec monoChar52[] = {
+   { 3, monoChar52_stroke0 },
+   { 2, monoChar52_stroke1 },
+};
+
+/* char: 53 '5' */
+
+static const CoordRec monoChar53_stroke0[] = {
+    { 76.1905, 100 },
+    { 28.5714, 100 },
+    { 23.8095, 57.1429 },
+    { 28.5714, 61.9048 },
+    { 42.8571, 66.6667 },
+    { 57.1428, 66.6667 },
+    { 71.4286, 61.9048 },
+    { 80.9524, 52.381 },
+    { 85.7143, 38.0952 },
+    { 85.7143, 28.5714 },
+    { 80.9524, 14.2857 },
+    { 71.4286, 4.7619 },
+    { 57.1428, 0 },
+    { 42.8571, 0 },
+    { 28.5714, 4.7619 },
+    { 23.8095, 9.5238 },
+    { 19.0476, 19.0476 },
+};
+
+static const StrokeRec monoChar53[] = {
+   { 17, monoChar53_stroke0 },
+};
+
+/* char: 54 '6' */
+
+static const CoordRec monoChar54_stroke0[] = {
+    { 78.5714, 85.7143 },
+    { 73.8096, 95.2381 },
+    { 59.5238, 100 },
+    { 50, 100 },
+    { 35.7143, 95.2381 },
+    { 26.1905, 80.9524 },
+    { 21.4286, 57.1429 },
+    { 21.4286, 33.3333 },
+    { 26.1905, 14.2857 },
+    { 35.7143, 4.7619 },
+    { 50, 0 },
+    { 54.7619, 0 },
+    { 69.0476, 4.7619 },
+    { 78.5714, 14.2857 },
+    { 83.3334, 28.5714 },
+    { 83.3334, 33.3333 },
+    { 78.5714, 47.619 },
+    { 69.0476, 57.1429 },
+    { 54.7619, 61.9048 },
+    { 50, 61.9048 },
+    { 35.7143, 57.1429 },
+    { 26.1905, 47.619 },
+    { 21.4286, 33.3333 },
+};
+
+static const StrokeRec monoChar54[] = {
+   { 23, monoChar54_stroke0 },
+};
+
+/* char: 55 '7' */
+
+static const CoordRec monoChar55_stroke0[] = {
+    { 85.7143, 100 },
+    { 38.0952, 0 },
+};
+
+static const CoordRec monoChar55_stroke1[] = {
+    { 19.0476, 100 },
+    { 85.7143, 100 },
+};
+
+static const StrokeRec monoChar55[] = {
+   { 2, monoChar55_stroke0 },
+   { 2, monoChar55_stroke1 },
+};
+
+/* char: 56 '8' */
+
+static const CoordRec monoChar56_stroke0[] = {
+    { 42.8571, 100 },
+    { 28.5714, 95.2381 },
+    { 23.8095, 85.7143 },
+    { 23.8095, 76.1905 },
+    { 28.5714, 66.6667 },
+    { 38.0952, 61.9048 },
+    { 57.1428, 57.1429 },
+    { 71.4286, 52.381 },
+    { 80.9524, 42.8571 },
+    { 85.7143, 33.3333 },
+    { 85.7143, 19.0476 },
+    { 80.9524, 9.5238 },
+    { 76.1905, 4.7619 },
+    { 61.9047, 0 },
+    { 42.8571, 0 },
+    { 28.5714, 4.7619 },
+    { 23.8095, 9.5238 },
+    { 19.0476, 19.0476 },
+    { 19.0476, 33.3333 },
+    { 23.8095, 42.8571 },
+    { 33.3333, 52.381 },
+    { 47.619, 57.1429 },
+    { 66.6666, 61.9048 },
+    { 76.1905, 66.6667 },
+    { 80.9524, 76.1905 },
+    { 80.9524, 85.7143 },
+    { 76.1905, 95.2381 },
+    { 61.9047, 100 },
+    { 42.8571, 100 },
+};
+
+static const StrokeRec monoChar56[] = {
+   { 29, monoChar56_stroke0 },
+};
+
+/* char: 57 '9' */
+
+static const CoordRec monoChar57_stroke0[] = {
+    { 83.3334, 66.6667 },
+    { 78.5714, 52.381 },
+    { 69.0476, 42.8571 },
+    { 54.7619, 38.0952 },
+    { 50, 38.0952 },
+    { 35.7143, 42.8571 },
+    { 26.1905, 52.381 },
+    { 21.4286, 66.6667 },
+    { 21.4286, 71.4286 },
+    { 26.1905, 85.7143 },
+    { 35.7143, 95.2381 },
+    { 50, 100 },
+    { 54.7619, 100 },
+    { 69.0476, 95.2381 },
+    { 78.5714, 85.7143 },
+    { 83.3334, 66.6667 },
+    { 83.3334, 42.8571 },
+    { 78.5714, 19.0476 },
+    { 69.0476, 4.7619 },
+    { 54.7619, 0 },
+    { 45.2381, 0 },
+    { 30.9524, 4.7619 },
+    { 26.1905, 14.2857 },
+};
+
+static const StrokeRec monoChar57[] = {
+   { 23, monoChar57_stroke0 },
+};
+
+/* char: 58 ':' */
+
+static const CoordRec monoChar58_stroke0[] = {
+    { 52.381, 66.6667 },
+    { 47.6191, 61.9048 },
+    { 52.381, 57.1429 },
+    { 57.1429, 61.9048 },
+    { 52.381, 66.6667 },
+};
+
+static const CoordRec monoChar58_stroke1[] = {
+    { 52.381, 9.5238 },
+    { 47.6191, 4.7619 },
+    { 52.381, 0 },
+    { 57.1429, 4.7619 },
+    { 52.381, 9.5238 },
+};
+
+static const StrokeRec monoChar58[] = {
+   { 5, monoChar58_stroke0 },
+   { 5, monoChar58_stroke1 },
+};
+
+/* char: 59 ';' */
+
+static const CoordRec monoChar59_stroke0[] = {
+    { 52.381, 66.6667 },
+    { 47.6191, 61.9048 },
+    { 52.381, 57.1429 },
+    { 57.1429, 61.9048 },
+    { 52.381, 66.6667 },
+};
+
+static const CoordRec monoChar59_stroke1[] = {
+    { 57.1429, 4.7619 },
+    { 52.381, 0 },
+    { 47.6191, 4.7619 },
+    { 52.381, 9.5238 },
+    { 57.1429, 4.7619 },
+    { 57.1429, -4.7619 },
+    { 52.381, -14.2857 },
+    { 47.6191, -19.0476 },
+};
+
+static const StrokeRec monoChar59[] = {
+   { 5, monoChar59_stroke0 },
+   { 8, monoChar59_stroke1 },
+};
+
+/* char: 60 '<' */
+
+static const CoordRec monoChar60_stroke0[] = {
+    { 90.4762, 85.7143 },
+    { 14.2857, 42.8571 },
+    { 90.4762, 0 },
+};
+
+static const StrokeRec monoChar60[] = {
+   { 3, monoChar60_stroke0 },
+};
+
+/* char: 61 '=' */
+
+static const CoordRec monoChar61_stroke0[] = {
+    { 9.5238, 57.1429 },
+    { 95.2381, 57.1429 },
+};
+
+static const CoordRec monoChar61_stroke1[] = {
+    { 9.5238, 28.5714 },
+    { 95.2381, 28.5714 },
+};
+
+static const StrokeRec monoChar61[] = {
+   { 2, monoChar61_stroke0 },
+   { 2, monoChar61_stroke1 },
+};
+
+/* char: 62 '>' */
+
+static const CoordRec monoChar62_stroke0[] = {
+    { 14.2857, 85.7143 },
+    { 90.4762, 42.8571 },
+    { 14.2857, 0 },
+};
+
+static const StrokeRec monoChar62[] = {
+   { 3, monoChar62_stroke0 },
+};
+
+/* char: 63 '?' */
+
+static const CoordRec monoChar63_stroke0[] = {
+    { 23.8095, 76.1905 },
+    { 23.8095, 80.9524 },
+    { 28.5714, 90.4762 },
+    { 33.3333, 95.2381 },
+    { 42.8571, 100 },
+    { 61.9047, 100 },
+    { 71.4285, 95.2381 },
+    { 76.1905, 90.4762 },
+    { 80.9524, 80.9524 },
+    { 80.9524, 71.4286 },
+    { 76.1905, 61.9048 },
+    { 71.4285, 57.1429 },
+    { 52.3809, 47.619 },
+    { 52.3809, 33.3333 },
+};
+
+static const CoordRec monoChar63_stroke1[] = {
+    { 52.3809, 9.5238 },
+    { 47.619, 4.7619 },
+    { 52.3809, 0 },
+    { 57.1428, 4.7619 },
+    { 52.3809, 9.5238 },
+};
+
+static const StrokeRec monoChar63[] = {
+   { 14, monoChar63_stroke0 },
+   { 5, monoChar63_stroke1 },
+};
+
+/* char: 64 '@' */
+
+static const CoordRec monoChar64_stroke0[] = {
+    { 64.2857, 52.381 },
+    { 54.7619, 57.1429 },
+    { 45.2381, 57.1429 },
+    { 40.4762, 47.619 },
+    { 40.4762, 42.8571 },
+    { 45.2381, 33.3333 },
+    { 54.7619, 33.3333 },
+    { 64.2857, 38.0952 },
+};
+
+static const CoordRec monoChar64_stroke1[] = {
+    { 64.2857, 57.1429 },
+    { 64.2857, 38.0952 },
+    { 69.0476, 33.3333 },
+    { 78.5714, 33.3333 },
+    { 83.3334, 42.8571 },
+    { 83.3334, 47.619 },
+    { 78.5714, 61.9048 },
+    { 69.0476, 71.4286 },
+    { 54.7619, 76.1905 },
+    { 50, 76.1905 },
+    { 35.7143, 71.4286 },
+    { 26.1905, 61.9048 },
+    { 21.4286, 47.619 },
+    { 21.4286, 42.8571 },
+    { 26.1905, 28.5714 },
+    { 35.7143, 19.0476 },
+    { 50, 14.2857 },
+    { 54.7619, 14.2857 },
+    { 69.0476, 19.0476 },
+};
+
+static const StrokeRec monoChar64[] = {
+   { 8, monoChar64_stroke0 },
+   { 19, monoChar64_stroke1 },
+};
+
+/* char: 65 'A' */
+
+static const CoordRec monoChar65_stroke0[] = {
+    { 52.3809, 100 },
+    { 14.2857, 0 },
+};
+
+static const CoordRec monoChar65_stroke1[] = {
+    { 52.3809, 100 },
+    { 90.4762, 0 },
+};
+
+static const CoordRec monoChar65_stroke2[] = {
+    { 28.5714, 33.3333 },
+    { 76.1905, 33.3333 },
+};
+
+static const StrokeRec monoChar65[] = {
+   { 2, monoChar65_stroke0 },
+   { 2, monoChar65_stroke1 },
+   { 2, monoChar65_stroke2 },
+};
+
+/* char: 66 'B' */
+
+static const CoordRec monoChar66_stroke0[] = {
+    { 19.0476, 100 },
+    { 19.0476, 0 },
+};
+
+static const CoordRec monoChar66_stroke1[] = {
+    { 19.0476, 100 },
+    { 61.9047, 100 },
+    { 76.1905, 95.2381 },
+    { 80.9524, 90.4762 },
+    { 85.7143, 80.9524 },
+    { 85.7143, 71.4286 },
+    { 80.9524, 61.9048 },
+    { 76.1905, 57.1429 },
+    { 61.9047, 52.381 },
+};
+
+static const CoordRec monoChar66_stroke2[] = {
+    { 19.0476, 52.381 },
+    { 61.9047, 52.381 },
+    { 76.1905, 47.619 },
+    { 80.9524, 42.8571 },
+    { 85.7143, 33.3333 },
+    { 85.7143, 19.0476 },
+    { 80.9524, 9.5238 },
+    { 76.1905, 4.7619 },
+    { 61.9047, 0 },
+    { 19.0476, 0 },
+};
+
+static const StrokeRec monoChar66[] = {
+   { 2, monoChar66_stroke0 },
+   { 9, monoChar66_stroke1 },
+   { 10, monoChar66_stroke2 },
+};
+
+/* char: 67 'C' */
+
+static const CoordRec monoChar67_stroke0[] = {
+    { 88.0952, 76.1905 },
+    { 83.3334, 85.7143 },
+    { 73.8096, 95.2381 },
+    { 64.2857, 100 },
+    { 45.2381, 100 },
+    { 35.7143, 95.2381 },
+    { 26.1905, 85.7143 },
+    { 21.4286, 76.1905 },
+    { 16.6667, 61.9048 },
+    { 16.6667, 38.0952 },
+    { 21.4286, 23.8095 },
+    { 26.1905, 14.2857 },
+    { 35.7143, 4.7619 },
+    { 45.2381, 0 },
+    { 64.2857, 0 },
+    { 73.8096, 4.7619 },
+    { 83.3334, 14.2857 },
+    { 88.0952, 23.8095 },
+};
+
+static const StrokeRec monoChar67[] = {
+   { 18, monoChar67_stroke0 },
+};
+
+/* char: 68 'D' */
+
+static const CoordRec monoChar68_stroke0[] = {
+    { 19.0476, 100 },
+    { 19.0476, 0 },
+};
+
+static const CoordRec monoChar68_stroke1[] = {
+    { 19.0476, 100 },
+    { 52.3809, 100 },
+    { 66.6666, 95.2381 },
+    { 76.1905, 85.7143 },
+    { 80.9524, 76.1905 },
+    { 85.7143, 61.9048 },
+    { 85.7143, 38.0952 },
+    { 80.9524, 23.8095 },
+    { 76.1905, 14.2857 },
+    { 66.6666, 4.7619 },
+    { 52.3809, 0 },
+    { 19.0476, 0 },
+};
+
+static const StrokeRec monoChar68[] = {
+   { 2, monoChar68_stroke0 },
+   { 12, monoChar68_stroke1 },
+};
+
+/* char: 69 'E' */
+
+static const CoordRec monoChar69_stroke0[] = {
+    { 21.4286, 100 },
+    { 21.4286, 0 },
+};
+
+static const CoordRec monoChar69_stroke1[] = {
+    { 21.4286, 100 },
+    { 83.3334, 100 },
+};
+
+static const CoordRec monoChar69_stroke2[] = {
+    { 21.4286, 52.381 },
+    { 59.5238, 52.381 },
+};
+
+static const CoordRec monoChar69_stroke3[] = {
+    { 21.4286, 0 },
+    { 83.3334, 0 },
+};
+
+static const StrokeRec monoChar69[] = {
+   { 2, monoChar69_stroke0 },
+   { 2, monoChar69_stroke1 },
+   { 2, monoChar69_stroke2 },
+   { 2, monoChar69_stroke3 },
+};
+
+/* char: 70 'F' */
+
+static const CoordRec monoChar70_stroke0[] = {
+    { 21.4286, 100 },
+    { 21.4286, 0 },
+};
+
+static const CoordRec monoChar70_stroke1[] = {
+    { 21.4286, 100 },
+    { 83.3334, 100 },
+};
+
+static const CoordRec monoChar70_stroke2[] = {
+    { 21.4286, 52.381 },
+    { 59.5238, 52.381 },
+};
+
+static const StrokeRec monoChar70[] = {
+   { 2, monoChar70_stroke0 },
+   { 2, monoChar70_stroke1 },
+   { 2, monoChar70_stroke2 },
+};
+
+/* char: 71 'G' */
+
+static const CoordRec monoChar71_stroke0[] = {
+    { 88.0952, 76.1905 },
+    { 83.3334, 85.7143 },
+    { 73.8096, 95.2381 },
+    { 64.2857, 100 },
+    { 45.2381, 100 },
+    { 35.7143, 95.2381 },
+    { 26.1905, 85.7143 },
+    { 21.4286, 76.1905 },
+    { 16.6667, 61.9048 },
+    { 16.6667, 38.0952 },
+    { 21.4286, 23.8095 },
+    { 26.1905, 14.2857 },
+    { 35.7143, 4.7619 },
+    { 45.2381, 0 },
+    { 64.2857, 0 },
+    { 73.8096, 4.7619 },
+    { 83.3334, 14.2857 },
+    { 88.0952, 23.8095 },
+    { 88.0952, 38.0952 },
+};
+
+static const CoordRec monoChar71_stroke1[] = {
+    { 64.2857, 38.0952 },
+    { 88.0952, 38.0952 },
+};
+
+static const StrokeRec monoChar71[] = {
+   { 19, monoChar71_stroke0 },
+   { 2, monoChar71_stroke1 },
+};
+
+/* char: 72 'H' */
+
+static const CoordRec monoChar72_stroke0[] = {
+    { 19.0476, 100 },
+    { 19.0476, 0 },
+};
+
+static const CoordRec monoChar72_stroke1[] = {
+    { 85.7143, 100 },
+    { 85.7143, 0 },
+};
+
+static const CoordRec monoChar72_stroke2[] = {
+    { 19.0476, 52.381 },
+    { 85.7143, 52.381 },
+};
+
+static const StrokeRec monoChar72[] = {
+   { 2, monoChar72_stroke0 },
+   { 2, monoChar72_stroke1 },
+   { 2, monoChar72_stroke2 },
+};
+
+/* char: 73 'I' */
+
+static const CoordRec monoChar73_stroke0[] = {
+    { 52.381, 100 },
+    { 52.381, 0 },
+};
+
+static const StrokeRec monoChar73[] = {
+   { 2, monoChar73_stroke0 },
+};
+
+/* char: 74 'J' */
+
+static const CoordRec monoChar74_stroke0[] = {
+    { 76.1905, 100 },
+    { 76.1905, 23.8095 },
+    { 71.4286, 9.5238 },
+    { 66.6667, 4.7619 },
+    { 57.1429, 0 },
+    { 47.6191, 0 },
+    { 38.0953, 4.7619 },
+    { 33.3334, 9.5238 },
+    { 28.5715, 23.8095 },
+    { 28.5715, 33.3333 },
+};
+
+static const StrokeRec monoChar74[] = {
+   { 10, monoChar74_stroke0 },
+};
+
+/* char: 75 'K' */
+
+static const CoordRec monoChar75_stroke0[] = {
+    { 19.0476, 100 },
+    { 19.0476, 0 },
+};
+
+static const CoordRec monoChar75_stroke1[] = {
+    { 85.7143, 100 },
+    { 19.0476, 33.3333 },
+};
+
+static const CoordRec monoChar75_stroke2[] = {
+    { 42.8571, 57.1429 },
+    { 85.7143, 0 },
+};
+
+static const StrokeRec monoChar75[] = {
+   { 2, monoChar75_stroke0 },
+   { 2, monoChar75_stroke1 },
+   { 2, monoChar75_stroke2 },
+};
+
+/* char: 76 'L' */
+
+static const CoordRec monoChar76_stroke0[] = {
+    { 23.8095, 100 },
+    { 23.8095, 0 },
+};
+
+static const CoordRec monoChar76_stroke1[] = {
+    { 23.8095, 0 },
+    { 80.9524, 0 },
+};
+
+static const StrokeRec monoChar76[] = {
+   { 2, monoChar76_stroke0 },
+   { 2, monoChar76_stroke1 },
+};
+
+/* char: 77 'M' */
+
+static const CoordRec monoChar77_stroke0[] = {
+    { 14.2857, 100 },
+    { 14.2857, 0 },
+};
+
+static const CoordRec monoChar77_stroke1[] = {
+    { 14.2857, 100 },
+    { 52.3809, 0 },
+};
+
+static const CoordRec monoChar77_stroke2[] = {
+    { 90.4762, 100 },
+    { 52.3809, 0 },
+};
+
+static const CoordRec monoChar77_stroke3[] = {
+    { 90.4762, 100 },
+    { 90.4762, 0 },
+};
+
+static const StrokeRec monoChar77[] = {
+   { 2, monoChar77_stroke0 },
+   { 2, monoChar77_stroke1 },
+   { 2, monoChar77_stroke2 },
+   { 2, monoChar77_stroke3 },
+};
+
+/* char: 78 'N' */
+
+static const CoordRec monoChar78_stroke0[] = {
+    { 19.0476, 100 },
+    { 19.0476, 0 },
+};
+
+static const CoordRec monoChar78_stroke1[] = {
+    { 19.0476, 100 },
+    { 85.7143, 0 },
+};
+
+static const CoordRec monoChar78_stroke2[] = {
+    { 85.7143, 100 },
+    { 85.7143, 0 },
+};
+
+static const StrokeRec monoChar78[] = {
+   { 2, monoChar78_stroke0 },
+   { 2, monoChar78_stroke1 },
+   { 2, monoChar78_stroke2 },
+};
+
+/* char: 79 'O' */
+
+static const CoordRec monoChar79_stroke0[] = {
+    { 42.8571, 100 },
+    { 33.3333, 95.2381 },
+    { 23.8095, 85.7143 },
+    { 19.0476, 76.1905 },
+    { 14.2857, 61.9048 },
+    { 14.2857, 38.0952 },
+    { 19.0476, 23.8095 },
+    { 23.8095, 14.2857 },
+    { 33.3333, 4.7619 },
+    { 42.8571, 0 },
+    { 61.9047, 0 },
+    { 71.4286, 4.7619 },
+    { 80.9524, 14.2857 },
+    { 85.7143, 23.8095 },
+    { 90.4762, 38.0952 },
+    { 90.4762, 61.9048 },
+    { 85.7143, 76.1905 },
+    { 80.9524, 85.7143 },
+    { 71.4286, 95.2381 },
+    { 61.9047, 100 },
+    { 42.8571, 100 },
+};
+
+static const StrokeRec monoChar79[] = {
+   { 21, monoChar79_stroke0 },
+};
+
+/* char: 80 'P' */
+
+static const CoordRec monoChar80_stroke0[] = {
+    { 19.0476, 100 },
+    { 19.0476, 0 },
+};
+
+static const CoordRec monoChar80_stroke1[] = {
+    { 19.0476, 100 },
+    { 61.9047, 100 },
+    { 76.1905, 95.2381 },
+    { 80.9524, 90.4762 },
+    { 85.7143, 80.9524 },
+    { 85.7143, 66.6667 },
+    { 80.9524, 57.1429 },
+    { 76.1905, 52.381 },
+    { 61.9047, 47.619 },
+    { 19.0476, 47.619 },
+};
+
+static const StrokeRec monoChar80[] = {
+   { 2, monoChar80_stroke0 },
+   { 10, monoChar80_stroke1 },
+};
+
+/* char: 81 'Q' */
+
+static const CoordRec monoChar81_stroke0[] = {
+    { 42.8571, 100 },
+    { 33.3333, 95.2381 },
+    { 23.8095, 85.7143 },
+    { 19.0476, 76.1905 },
+    { 14.2857, 61.9048 },
+    { 14.2857, 38.0952 },
+    { 19.0476, 23.8095 },
+    { 23.8095, 14.2857 },
+    { 33.3333, 4.7619 },
+    { 42.8571, 0 },
+    { 61.9047, 0 },
+    { 71.4286, 4.7619 },
+    { 80.9524, 14.2857 },
+    { 85.7143, 23.8095 },
+    { 90.4762, 38.0952 },
+    { 90.4762, 61.9048 },
+    { 85.7143, 76.1905 },
+    { 80.9524, 85.7143 },
+    { 71.4286, 95.2381 },
+    { 61.9047, 100 },
+    { 42.8571, 100 },
+};
+
+static const CoordRec monoChar81_stroke1[] = {
+    { 57.1428, 19.0476 },
+    { 85.7143, -9.5238 },
+};
+
+static const StrokeRec monoChar81[] = {
+   { 21, monoChar81_stroke0 },
+   { 2, monoChar81_stroke1 },
+};
+
+/* char: 82 'R' */
+
+static const CoordRec monoChar82_stroke0[] = {
+    { 19.0476, 100 },
+    { 19.0476, 0 },
+};
+
+static const CoordRec monoChar82_stroke1[] = {
+    { 19.0476, 100 },
+    { 61.9047, 100 },
+    { 76.1905, 95.2381 },
+    { 80.9524, 90.4762 },
+    { 85.7143, 80.9524 },
+    { 85.7143, 71.4286 },
+    { 80.9524, 61.9048 },
+    { 76.1905, 57.1429 },
+    { 61.9047, 52.381 },
+    { 19.0476, 52.381 },
+};
+
+static const CoordRec monoChar82_stroke2[] = {
+    { 52.3809, 52.381 },
+    { 85.7143, 0 },
+};
+
+static const StrokeRec monoChar82[] = {
+   { 2, monoChar82_stroke0 },
+   { 10, monoChar82_stroke1 },
+   { 2, monoChar82_stroke2 },
+};
+
+/* char: 83 'S' */
+
+static const CoordRec monoChar83_stroke0[] = {
+    { 85.7143, 85.7143 },
+    { 76.1905, 95.2381 },
+    { 61.9047, 100 },
+    { 42.8571, 100 },
+    { 28.5714, 95.2381 },
+    { 19.0476, 85.7143 },
+    { 19.0476, 76.1905 },
+    { 23.8095, 66.6667 },
+    { 28.5714, 61.9048 },
+    { 38.0952, 57.1429 },
+    { 66.6666, 47.619 },
+    { 76.1905, 42.8571 },
+    { 80.9524, 38.0952 },
+    { 85.7143, 28.5714 },
+    { 85.7143, 14.2857 },
+    { 76.1905, 4.7619 },
+    { 61.9047, 0 },
+    { 42.8571, 0 },
+    { 28.5714, 4.7619 },
+    { 19.0476, 14.2857 },
+};
+
+static const StrokeRec monoChar83[] = {
+   { 20, monoChar83_stroke0 },
+};
+
+/* char: 84 'T' */
+
+static const CoordRec monoChar84_stroke0[] = {
+    { 52.3809, 100 },
+    { 52.3809, 0 },
+};
+
+static const CoordRec monoChar84_stroke1[] = {
+    { 19.0476, 100 },
+    { 85.7143, 100 },
+};
+
+static const StrokeRec monoChar84[] = {
+   { 2, monoChar84_stroke0 },
+   { 2, monoChar84_stroke1 },
+};
+
+/* char: 85 'U' */
+
+static const CoordRec monoChar85_stroke0[] = {
+    { 19.0476, 100 },
+    { 19.0476, 28.5714 },
+    { 23.8095, 14.2857 },
+    { 33.3333, 4.7619 },
+    { 47.619, 0 },
+    { 57.1428, 0 },
+    { 71.4286, 4.7619 },
+    { 80.9524, 14.2857 },
+    { 85.7143, 28.5714 },
+    { 85.7143, 100 },
+};
+
+static const StrokeRec monoChar85[] = {
+   { 10, monoChar85_stroke0 },
+};
+
+/* char: 86 'V' */
+
+static const CoordRec monoChar86_stroke0[] = {
+    { 14.2857, 100 },
+    { 52.3809, 0 },
+};
+
+static const CoordRec monoChar86_stroke1[] = {
+    { 90.4762, 100 },
+    { 52.3809, 0 },
+};
+
+static const StrokeRec monoChar86[] = {
+   { 2, monoChar86_stroke0 },
+   { 2, monoChar86_stroke1 },
+};
+
+/* char: 87 'W' */
+
+static const CoordRec monoChar87_stroke0[] = {
+    { 4.7619, 100 },
+    { 28.5714, 0 },
+};
+
+static const CoordRec monoChar87_stroke1[] = {
+    { 52.3809, 100 },
+    { 28.5714, 0 },
+};
+
+static const CoordRec monoChar87_stroke2[] = {
+    { 52.3809, 100 },
+    { 76.1905, 0 },
+};
+
+static const CoordRec monoChar87_stroke3[] = {
+    { 100, 100 },
+    { 76.1905, 0 },
+};
+
+static const StrokeRec monoChar87[] = {
+   { 2, monoChar87_stroke0 },
+   { 2, monoChar87_stroke1 },
+   { 2, monoChar87_stroke2 },
+   { 2, monoChar87_stroke3 },
+};
+
+/* char: 88 'X' */
+
+static const CoordRec monoChar88_stroke0[] = {
+    { 19.0476, 100 },
+    { 85.7143, 0 },
+};
+
+static const CoordRec monoChar88_stroke1[] = {
+    { 85.7143, 100 },
+    { 19.0476, 0 },
+};
+
+static const StrokeRec monoChar88[] = {
+   { 2, monoChar88_stroke0 },
+   { 2, monoChar88_stroke1 },
+};
+
+/* char: 89 'Y' */
+
+static const CoordRec monoChar89_stroke0[] = {
+    { 14.2857, 100 },
+    { 52.3809, 52.381 },
+    { 52.3809, 0 },
+};
+
+static const CoordRec monoChar89_stroke1[] = {
+    { 90.4762, 100 },
+    { 52.3809, 52.381 },
+};
+
+static const StrokeRec monoChar89[] = {
+   { 3, monoChar89_stroke0 },
+   { 2, monoChar89_stroke1 },
+};
+
+/* char: 90 'Z' */
+
+static const CoordRec monoChar90_stroke0[] = {
+    { 85.7143, 100 },
+    { 19.0476, 0 },
+};
+
+static const CoordRec monoChar90_stroke1[] = {
+    { 19.0476, 100 },
+    { 85.7143, 100 },
+};
+
+static const CoordRec monoChar90_stroke2[] = {
+    { 19.0476, 0 },
+    { 85.7143, 0 },
+};
+
+static const StrokeRec monoChar90[] = {
+   { 2, monoChar90_stroke0 },
+   { 2, monoChar90_stroke1 },
+   { 2, monoChar90_stroke2 },
+};
+
+/* char: 91 '[' */
+
+static const CoordRec monoChar91_stroke0[] = {
+    { 35.7143, 119.048 },
+    { 35.7143, -33.3333 },
+};
+
+static const CoordRec monoChar91_stroke1[] = {
+    { 40.4762, 119.048 },
+    { 40.4762, -33.3333 },
+};
+
+static const CoordRec monoChar91_stroke2[] = {
+    { 35.7143, 119.048 },
+    { 69.0476, 119.048 },
+};
+
+static const CoordRec monoChar91_stroke3[] = {
+    { 35.7143, -33.3333 },
+    { 69.0476, -33.3333 },
+};
+
+static const StrokeRec monoChar91[] = {
+   { 2, monoChar91_stroke0 },
+   { 2, monoChar91_stroke1 },
+   { 2, monoChar91_stroke2 },
+   { 2, monoChar91_stroke3 },
+};
+
+/* char: 92 '\' */
+
+static const CoordRec monoChar92_stroke0[] = {
+    { 19.0476, 100 },
+    { 85.7143, -14.2857 },
+};
+
+static const StrokeRec monoChar92[] = {
+   { 2, monoChar92_stroke0 },
+};
+
+/* char: 93 ']' */
+
+static const CoordRec monoChar93_stroke0[] = {
+    { 64.2857, 119.048 },
+    { 64.2857, -33.3333 },
+};
+
+static const CoordRec monoChar93_stroke1[] = {
+    { 69.0476, 119.048 },
+    { 69.0476, -33.3333 },
+};
+
+static const CoordRec monoChar93_stroke2[] = {
+    { 35.7143, 119.048 },
+    { 69.0476, 119.048 },
+};
+
+static const CoordRec monoChar93_stroke3[] = {
+    { 35.7143, -33.3333 },
+    { 69.0476, -33.3333 },
+};
+
+static const StrokeRec monoChar93[] = {
+   { 2, monoChar93_stroke0 },
+   { 2, monoChar93_stroke1 },
+   { 2, monoChar93_stroke2 },
+   { 2, monoChar93_stroke3 },
+};
+
+/* char: 94 '^' */
+
+static const CoordRec monoChar94_stroke0[] = {
+    { 52.3809, 109.524 },
+    { 14.2857, 42.8571 },
+};
+
+static const CoordRec monoChar94_stroke1[] = {
+    { 52.3809, 109.524 },
+    { 90.4762, 42.8571 },
+};
+
+static const StrokeRec monoChar94[] = {
+   { 2, monoChar94_stroke0 },
+   { 2, monoChar94_stroke1 },
+};
+
+/* char: 95 '_' */
+
+static const CoordRec monoChar95_stroke0[] = {
+    { 0, -33.3333 },
+    { 104.762, -33.3333 },
+    { 104.762, -28.5714 },
+    { 0, -28.5714 },
+    { 0, -33.3333 },
+};
+
+static const StrokeRec monoChar95[] = {
+   { 5, monoChar95_stroke0 },
+};
+
+/* char: 96 '`' */
+
+static const CoordRec monoChar96_stroke0[] = {
+    { 42.8572, 100 },
+    { 66.6667, 71.4286 },
+};
+
+static const CoordRec monoChar96_stroke1[] = {
+    { 42.8572, 100 },
+    { 38.0953, 95.2381 },
+    { 66.6667, 71.4286 },
+};
+
+static const StrokeRec monoChar96[] = {
+   { 2, monoChar96_stroke0 },
+   { 3, monoChar96_stroke1 },
+};
+
+/* char: 97 'a' */
+
+static const CoordRec monoChar97_stroke0[] = {
+    { 80.9524, 66.6667 },
+    { 80.9524, 0 },
+};
+
+static const CoordRec monoChar97_stroke1[] = {
+    { 80.9524, 52.381 },
+    { 71.4285, 61.9048 },
+    { 61.9047, 66.6667 },
+    { 47.619, 66.6667 },
+    { 38.0952, 61.9048 },
+    { 28.5714, 52.381 },
+    { 23.8095, 38.0952 },
+    { 23.8095, 28.5714 },
+    { 28.5714, 14.2857 },
+    { 38.0952, 4.7619 },
+    { 47.619, 0 },
+    { 61.9047, 0 },
+    { 71.4285, 4.7619 },
+    { 80.9524, 14.2857 },
+};
+
+static const StrokeRec monoChar97[] = {
+   { 2, monoChar97_stroke0 },
+   { 14, monoChar97_stroke1 },
+};
+
+/* char: 98 'b' */
+
+static const CoordRec monoChar98_stroke0[] = {
+    { 23.8095, 100 },
+    { 23.8095, 0 },
+};
+
+static const CoordRec monoChar98_stroke1[] = {
+    { 23.8095, 52.381 },
+    { 33.3333, 61.9048 },
+    { 42.8571, 66.6667 },
+    { 57.1428, 66.6667 },
+    { 66.6666, 61.9048 },
+    { 76.1905, 52.381 },
+    { 80.9524, 38.0952 },
+    { 80.9524, 28.5714 },
+    { 76.1905, 14.2857 },
+    { 66.6666, 4.7619 },
+    { 57.1428, 0 },
+    { 42.8571, 0 },
+    { 33.3333, 4.7619 },
+    { 23.8095, 14.2857 },
+};
+
+static const StrokeRec monoChar98[] = {
+   { 2, monoChar98_stroke0 },
+   { 14, monoChar98_stroke1 },
+};
+
+/* char: 99 'c' */
+
+static const CoordRec monoChar99_stroke0[] = {
+    { 80.9524, 52.381 },
+    { 71.4285, 61.9048 },
+    { 61.9047, 66.6667 },
+    { 47.619, 66.6667 },
+    { 38.0952, 61.9048 },
+    { 28.5714, 52.381 },
+    { 23.8095, 38.0952 },
+    { 23.8095, 28.5714 },
+    { 28.5714, 14.2857 },
+    { 38.0952, 4.7619 },
+    { 47.619, 0 },
+    { 61.9047, 0 },
+    { 71.4285, 4.7619 },
+    { 80.9524, 14.2857 },
+};
+
+static const StrokeRec monoChar99[] = {
+   { 14, monoChar99_stroke0 },
+};
+
+/* char: 100 'd' */
+
+static const CoordRec monoChar100_stroke0[] = {
+    { 80.9524, 100 },
+    { 80.9524, 0 },
+};
+
+static const CoordRec monoChar100_stroke1[] = {
+    { 80.9524, 52.381 },
+    { 71.4285, 61.9048 },
+    { 61.9047, 66.6667 },
+    { 47.619, 66.6667 },
+    { 38.0952, 61.9048 },
+    { 28.5714, 52.381 },
+    { 23.8095, 38.0952 },
+    { 23.8095, 28.5714 },
+    { 28.5714, 14.2857 },
+    { 38.0952, 4.7619 },
+    { 47.619, 0 },
+    { 61.9047, 0 },
+    { 71.4285, 4.7619 },
+    { 80.9524, 14.2857 },
+};
+
+static const StrokeRec monoChar100[] = {
+   { 2, monoChar100_stroke0 },
+   { 14, monoChar100_stroke1 },
+};
+
+/* char: 101 'e' */
+
+static const CoordRec monoChar101_stroke0[] = {
+    { 23.8095, 38.0952 },
+    { 80.9524, 38.0952 },
+    { 80.9524, 47.619 },
+    { 76.1905, 57.1429 },
+    { 71.4285, 61.9048 },
+    { 61.9047, 66.6667 },
+    { 47.619, 66.6667 },
+    { 38.0952, 61.9048 },
+    { 28.5714, 52.381 },
+    { 23.8095, 38.0952 },
+    { 23.8095, 28.5714 },
+    { 28.5714, 14.2857 },
+    { 38.0952, 4.7619 },
+    { 47.619, 0 },
+    { 61.9047, 0 },
+    { 71.4285, 4.7619 },
+    { 80.9524, 14.2857 },
+};
+
+static const StrokeRec monoChar101[] = {
+   { 17, monoChar101_stroke0 },
+};
+
+/* char: 102 'f' */
+
+static const CoordRec monoChar102_stroke0[] = {
+    { 71.4286, 100 },
+    { 61.9048, 100 },
+    { 52.381, 95.2381 },
+    { 47.6191, 80.9524 },
+    { 47.6191, 0 },
+};
+
+static const CoordRec monoChar102_stroke1[] = {
+    { 33.3334, 66.6667 },
+    { 66.6667, 66.6667 },
+};
+
+static const StrokeRec monoChar102[] = {
+   { 5, monoChar102_stroke0 },
+   { 2, monoChar102_stroke1 },
+};
+
+/* char: 103 'g' */
+
+static const CoordRec monoChar103_stroke0[] = {
+    { 80.9524, 66.6667 },
+    { 80.9524, -9.5238 },
+    { 76.1905, -23.8095 },
+    { 71.4285, -28.5714 },
+    { 61.9047, -33.3333 },
+    { 47.619, -33.3333 },
+    { 38.0952, -28.5714 },
+};
+
+static const CoordRec monoChar103_stroke1[] = {
+    { 80.9524, 52.381 },
+    { 71.4285, 61.9048 },
+    { 61.9047, 66.6667 },
+    { 47.619, 66.6667 },
+    { 38.0952, 61.9048 },
+    { 28.5714, 52.381 },
+    { 23.8095, 38.0952 },
+    { 23.8095, 28.5714 },
+    { 28.5714, 14.2857 },
+    { 38.0952, 4.7619 },
+    { 47.619, 0 },
+    { 61.9047, 0 },
+    { 71.4285, 4.7619 },
+    { 80.9524, 14.2857 },
+};
+
+static const StrokeRec monoChar103[] = {
+   { 7, monoChar103_stroke0 },
+   { 14, monoChar103_stroke1 },
+};
+
+/* char: 104 'h' */
+
+static const CoordRec monoChar104_stroke0[] = {
+    { 26.1905, 100 },
+    { 26.1905, 0 },
+};
+
+static const CoordRec monoChar104_stroke1[] = {
+    { 26.1905, 47.619 },
+    { 40.4762, 61.9048 },
+    { 50, 66.6667 },
+    { 64.2857, 66.6667 },
+    { 73.8095, 61.9048 },
+    { 78.5715, 47.619 },
+    { 78.5715, 0 },
+};
+
+static const StrokeRec monoChar104[] = {
+   { 2, monoChar104_stroke0 },
+   { 7, monoChar104_stroke1 },
+};
+
+/* char: 105 'i' */
+
+static const CoordRec monoChar105_stroke0[] = {
+    { 47.6191, 100 },
+    { 52.381, 95.2381 },
+    { 57.1429, 100 },
+    { 52.381, 104.762 },
+    { 47.6191, 100 },
+};
+
+static const CoordRec monoChar105_stroke1[] = {
+    { 52.381, 66.6667 },
+    { 52.381, 0 },
+};
+
+static const StrokeRec monoChar105[] = {
+   { 5, monoChar105_stroke0 },
+   { 2, monoChar105_stroke1 },
+};
+
+/* char: 106 'j' */
+
+static const CoordRec monoChar106_stroke0[] = {
+    { 57.1429, 100 },
+    { 61.9048, 95.2381 },
+    { 66.6667, 100 },
+    { 61.9048, 104.762 },
+    { 57.1429, 100 },
+};
+
+static const CoordRec monoChar106_stroke1[] = {
+    { 61.9048, 66.6667 },
+    { 61.9048, -14.2857 },
+    { 57.1429, -28.5714 },
+    { 47.6191, -33.3333 },
+    { 38.0953, -33.3333 },
+};
+
+static const StrokeRec monoChar106[] = {
+   { 5, monoChar106_stroke0 },
+   { 5, monoChar106_stroke1 },
+};
+
+/* char: 107 'k' */
+
+static const CoordRec monoChar107_stroke0[] = {
+    { 26.1905, 100 },
+    { 26.1905, 0 },
+};
+
+static const CoordRec monoChar107_stroke1[] = {
+    { 73.8095, 66.6667 },
+    { 26.1905, 19.0476 },
+};
+
+static const CoordRec monoChar107_stroke2[] = {
+    { 45.2381, 38.0952 },
+    { 78.5715, 0 },
+};
+
+static const StrokeRec monoChar107[] = {
+   { 2, monoChar107_stroke0 },
+   { 2, monoChar107_stroke1 },
+   { 2, monoChar107_stroke2 },
+};
+
+/* char: 108 'l' */
+
+static const CoordRec monoChar108_stroke0[] = {
+    { 52.381, 100 },
+    { 52.381, 0 },
+};
+
+static const StrokeRec monoChar108[] = {
+   { 2, monoChar108_stroke0 },
+};
+
+/* char: 109 'm' */
+
+static const CoordRec monoChar109_stroke0[] = {
+    { 0, 66.6667 },
+    { 0, 0 },
+};
+
+static const CoordRec monoChar109_stroke1[] = {
+    { 0, 47.619 },
+    { 14.2857, 61.9048 },
+    { 23.8095, 66.6667 },
+    { 38.0952, 66.6667 },
+    { 47.619, 61.9048 },
+    { 52.381, 47.619 },
+    { 52.381, 0 },
+};
+
+static const CoordRec monoChar109_stroke2[] = {
+    { 52.381, 47.619 },
+    { 66.6667, 61.9048 },
+    { 76.1905, 66.6667 },
+    { 90.4762, 66.6667 },
+    { 100, 61.9048 },
+    { 104.762, 47.619 },
+    { 104.762, 0 },
+};
+
+static const StrokeRec monoChar109[] = {
+   { 2, monoChar109_stroke0 },
+   { 7, monoChar109_stroke1 },
+   { 7, monoChar109_stroke2 },
+};
+
+/* char: 110 'n' */
+
+static const CoordRec monoChar110_stroke0[] = {
+    { 26.1905, 66.6667 },
+    { 26.1905, 0 },
+};
+
+static const CoordRec monoChar110_stroke1[] = {
+    { 26.1905, 47.619 },
+    { 40.4762, 61.9048 },
+    { 50, 66.6667 },
+    { 64.2857, 66.6667 },
+    { 73.8095, 61.9048 },
+    { 78.5715, 47.619 },
+    { 78.5715, 0 },
+};
+
+static const StrokeRec monoChar110[] = {
+   { 2, monoChar110_stroke0 },
+   { 7, monoChar110_stroke1 },
+};
+
+/* char: 111 'o' */
+
+static const CoordRec monoChar111_stroke0[] = {
+    { 45.2381, 66.6667 },
+    { 35.7143, 61.9048 },
+    { 26.1905, 52.381 },
+    { 21.4286, 38.0952 },
+    { 21.4286, 28.5714 },
+    { 26.1905, 14.2857 },
+    { 35.7143, 4.7619 },
+    { 45.2381, 0 },
+    { 59.5238, 0 },
+    { 69.0476, 4.7619 },
+    { 78.5714, 14.2857 },
+    { 83.3334, 28.5714 },
+    { 83.3334, 38.0952 },
+    { 78.5714, 52.381 },
+    { 69.0476, 61.9048 },
+    { 59.5238, 66.6667 },
+    { 45.2381, 66.6667 },
+};
+
+static const StrokeRec monoChar111[] = {
+   { 17, monoChar111_stroke0 },
+};
+
+/* char: 112 'p' */
+
+static const CoordRec monoChar112_stroke0[] = {
+    { 23.8095, 66.6667 },
+    { 23.8095, -33.3333 },
+};
+
+static const CoordRec monoChar112_stroke1[] = {
+    { 23.8095, 52.381 },
+    { 33.3333, 61.9048 },
+    { 42.8571, 66.6667 },
+    { 57.1428, 66.6667 },
+    { 66.6666, 61.9048 },
+    { 76.1905, 52.381 },
+    { 80.9524, 38.0952 },
+    { 80.9524, 28.5714 },
+    { 76.1905, 14.2857 },
+    { 66.6666, 4.7619 },
+    { 57.1428, 0 },
+    { 42.8571, 0 },
+    { 33.3333, 4.7619 },
+    { 23.8095, 14.2857 },
+};
+
+static const StrokeRec monoChar112[] = {
+   { 2, monoChar112_stroke0 },
+   { 14, monoChar112_stroke1 },
+};
+
+/* char: 113 'q' */
+
+static const CoordRec monoChar113_stroke0[] = {
+    { 80.9524, 66.6667 },
+    { 80.9524, -33.3333 },
+};
+
+static const CoordRec monoChar113_stroke1[] = {
+    { 80.9524, 52.381 },
+    { 71.4285, 61.9048 },
+    { 61.9047, 66.6667 },
+    { 47.619, 66.6667 },
+    { 38.0952, 61.9048 },
+    { 28.5714, 52.381 },
+    { 23.8095, 38.0952 },
+    { 23.8095, 28.5714 },
+    { 28.5714, 14.2857 },
+    { 38.0952, 4.7619 },
+    { 47.619, 0 },
+    { 61.9047, 0 },
+    { 71.4285, 4.7619 },
+    { 80.9524, 14.2857 },
+};
+
+static const StrokeRec monoChar113[] = {
+   { 2, monoChar113_stroke0 },
+   { 14, monoChar113_stroke1 },
+};
+
+/* char: 114 'r' */
+
+static const CoordRec monoChar114_stroke0[] = {
+    { 33.3334, 66.6667 },
+    { 33.3334, 0 },
+};
+
+static const CoordRec monoChar114_stroke1[] = {
+    { 33.3334, 38.0952 },
+    { 38.0953, 52.381 },
+    { 47.6191, 61.9048 },
+    { 57.1429, 66.6667 },
+    { 71.4286, 66.6667 },
+};
+
+static const StrokeRec monoChar114[] = {
+   { 2, monoChar114_stroke0 },
+   { 5, monoChar114_stroke1 },
+};
+
+/* char: 115 's' */
+
+static const CoordRec monoChar115_stroke0[] = {
+    { 78.5715, 52.381 },
+    { 73.8095, 61.9048 },
+    { 59.5238, 66.6667 },
+    { 45.2381, 66.6667 },
+    { 30.9524, 61.9048 },
+    { 26.1905, 52.381 },
+    { 30.9524, 42.8571 },
+    { 40.4762, 38.0952 },
+    { 64.2857, 33.3333 },
+    { 73.8095, 28.5714 },
+    { 78.5715, 19.0476 },
+    { 78.5715, 14.2857 },
+    { 73.8095, 4.7619 },
+    { 59.5238, 0 },
+    { 45.2381, 0 },
+    { 30.9524, 4.7619 },
+    { 26.1905, 14.2857 },
+};
+
+static const StrokeRec monoChar115[] = {
+   { 17, monoChar115_stroke0 },
+};
+
+/* char: 116 't' */
+
+static const CoordRec monoChar116_stroke0[] = {
+    { 47.6191, 100 },
+    { 47.6191, 19.0476 },
+    { 52.381, 4.7619 },
+    { 61.9048, 0 },
+    { 71.4286, 0 },
+};
+
+static const CoordRec monoChar116_stroke1[] = {
+    { 33.3334, 66.6667 },
+    { 66.6667, 66.6667 },
+};
+
+static const StrokeRec monoChar116[] = {
+   { 5, monoChar116_stroke0 },
+   { 2, monoChar116_stroke1 },
+};
+
+/* char: 117 'u' */
+
+static const CoordRec monoChar117_stroke0[] = {
+    { 26.1905, 66.6667 },
+    { 26.1905, 19.0476 },
+    { 30.9524, 4.7619 },
+    { 40.4762, 0 },
+    { 54.7619, 0 },
+    { 64.2857, 4.7619 },
+    { 78.5715, 19.0476 },
+};
+
+static const CoordRec monoChar117_stroke1[] = {
+    { 78.5715, 66.6667 },
+    { 78.5715, 0 },
+};
+
+static const StrokeRec monoChar117[] = {
+   { 7, monoChar117_stroke0 },
+   { 2, monoChar117_stroke1 },
+};
+
+/* char: 118 'v' */
+
+static const CoordRec monoChar118_stroke0[] = {
+    { 23.8095, 66.6667 },
+    { 52.3809, 0 },
+};
+
+static const CoordRec monoChar118_stroke1[] = {
+    { 80.9524, 66.6667 },
+    { 52.3809, 0 },
+};
+
+static const StrokeRec monoChar118[] = {
+   { 2, monoChar118_stroke0 },
+   { 2, monoChar118_stroke1 },
+};
+
+/* char: 119 'w' */
+
+static const CoordRec monoChar119_stroke0[] = {
+    { 14.2857, 66.6667 },
+    { 33.3333, 0 },
+};
+
+static const CoordRec monoChar119_stroke1[] = {
+    { 52.3809, 66.6667 },
+    { 33.3333, 0 },
+};
+
+static const CoordRec monoChar119_stroke2[] = {
+    { 52.3809, 66.6667 },
+    { 71.4286, 0 },
+};
+
+static const CoordRec monoChar119_stroke3[] = {
+    { 90.4762, 66.6667 },
+    { 71.4286, 0 },
+};
+
+static const StrokeRec monoChar119[] = {
+   { 2, monoChar119_stroke0 },
+   { 2, monoChar119_stroke1 },
+   { 2, monoChar119_stroke2 },
+   { 2, monoChar119_stroke3 },
+};
+
+/* char: 120 'x' */
+
+static const CoordRec monoChar120_stroke0[] = {
+    { 26.1905, 66.6667 },
+    { 78.5715, 0 },
+};
+
+static const CoordRec monoChar120_stroke1[] = {
+    { 78.5715, 66.6667 },
+    { 26.1905, 0 },
+};
+
+static const StrokeRec monoChar120[] = {
+   { 2, monoChar120_stroke0 },
+   { 2, monoChar120_stroke1 },
+};
+
+/* char: 121 'y' */
+
+static const CoordRec monoChar121_stroke0[] = {
+    { 26.1905, 66.6667 },
+    { 54.7619, 0 },
+};
+
+static const CoordRec monoChar121_stroke1[] = {
+    { 83.3334, 66.6667 },
+    { 54.7619, 0 },
+    { 45.2381, -19.0476 },
+    { 35.7143, -28.5714 },
+    { 26.1905, -33.3333 },
+    { 21.4286, -33.3333 },
+};
+
+static const StrokeRec monoChar121[] = {
+   { 2, monoChar121_stroke0 },
+   { 6, monoChar121_stroke1 },
+};
+
+/* char: 122 'z' */
+
+static const CoordRec monoChar122_stroke0[] = {
+    { 78.5715, 66.6667 },
+    { 26.1905, 0 },
+};
+
+static const CoordRec monoChar122_stroke1[] = {
+    { 26.1905, 66.6667 },
+    { 78.5715, 66.6667 },
+};
+
+static const CoordRec monoChar122_stroke2[] = {
+    { 26.1905, 0 },
+    { 78.5715, 0 },
+};
+
+static const StrokeRec monoChar122[] = {
+   { 2, monoChar122_stroke0 },
+   { 2, monoChar122_stroke1 },
+   { 2, monoChar122_stroke2 },
+};
+
+/* char: 123 '{' */
+
+static const CoordRec monoChar123_stroke0[] = {
+    { 64.2857, 119.048 },
+    { 54.7619, 114.286 },
+    { 50, 109.524 },
+    { 45.2381, 100 },
+    { 45.2381, 90.4762 },
+    { 50, 80.9524 },
+    { 54.7619, 76.1905 },
+    { 59.5238, 66.6667 },
+    { 59.5238, 57.1429 },
+    { 50, 47.619 },
+};
+
+static const CoordRec monoChar123_stroke1[] = {
+    { 54.7619, 114.286 },
+    { 50, 104.762 },
+    { 50, 95.2381 },
+    { 54.7619, 85.7143 },
+    { 59.5238, 80.9524 },
+    { 64.2857, 71.4286 },
+    { 64.2857, 61.9048 },
+    { 59.5238, 52.381 },
+    { 40.4762, 42.8571 },
+    { 59.5238, 33.3333 },
+    { 64.2857, 23.8095 },
+    { 64.2857, 14.2857 },
+    { 59.5238, 4.7619 },
+    { 54.7619, 0 },
+    { 50, -9.5238 },
+    { 50, -19.0476 },
+    { 54.7619, -28.5714 },
+};
+
+static const CoordRec monoChar123_stroke2[] = {
+    { 50, 38.0952 },
+    { 59.5238, 28.5714 },
+    { 59.5238, 19.0476 },
+    { 54.7619, 9.5238 },
+    { 50, 4.7619 },
+    { 45.2381, -4.7619 },
+    { 45.2381, -14.2857 },
+    { 50, -23.8095 },
+    { 54.7619, -28.5714 },
+    { 64.2857, -33.3333 },
+};
+
+static const StrokeRec monoChar123[] = {
+   { 10, monoChar123_stroke0 },
+   { 17, monoChar123_stroke1 },
+   { 10, monoChar123_stroke2 },
+};
+
+/* char: 124 '|' */
+
+static const CoordRec monoChar124_stroke0[] = {
+    { 52.381, 119.048 },
+    { 52.381, -33.3333 },
+};
+
+static const StrokeRec monoChar124[] = {
+   { 2, monoChar124_stroke0 },
+};
+
+/* char: 125 '}' */
+
+static const CoordRec monoChar125_stroke0[] = {
+    { 40.4762, 119.048 },
+    { 50, 114.286 },
+    { 54.7619, 109.524 },
+    { 59.5238, 100 },
+    { 59.5238, 90.4762 },
+    { 54.7619, 80.9524 },
+    { 50, 76.1905 },
+    { 45.2381, 66.6667 },
+    { 45.2381, 57.1429 },
+    { 54.7619, 47.619 },
+};
+
+static const CoordRec monoChar125_stroke1[] = {
+    { 50, 114.286 },
+    { 54.7619, 104.762 },
+    { 54.7619, 95.2381 },
+    { 50, 85.7143 },
+    { 45.2381, 80.9524 },
+    { 40.4762, 71.4286 },
+    { 40.4762, 61.9048 },
+    { 45.2381, 52.381 },
+    { 64.2857, 42.8571 },
+    { 45.2381, 33.3333 },
+    { 40.4762, 23.8095 },
+    { 40.4762, 14.2857 },
+    { 45.2381, 4.7619 },
+    { 50, 0 },
+    { 54.7619, -9.5238 },
+    { 54.7619, -19.0476 },
+    { 50, -28.5714 },
+};
+
+static const CoordRec monoChar125_stroke2[] = {
+    { 54.7619, 38.0952 },
+    { 45.2381, 28.5714 },
+    { 45.2381, 19.0476 },
+    { 50, 9.5238 },
+    { 54.7619, 4.7619 },
+    { 59.5238, -4.7619 },
+    { 59.5238, -14.2857 },
+    { 54.7619, -23.8095 },
+    { 50, -28.5714 },
+    { 40.4762, -33.3333 },
+};
+
+static const StrokeRec monoChar125[] = {
+   { 10, monoChar125_stroke0 },
+   { 17, monoChar125_stroke1 },
+   { 10, monoChar125_stroke2 },
+};
+
+/* char: 126 '~' */
+
+static const CoordRec monoChar126_stroke0[] = {
+    { 9.5238, 28.5714 },
+    { 9.5238, 38.0952 },
+    { 14.2857, 52.381 },
+    { 23.8095, 57.1429 },
+    { 33.3333, 57.1429 },
+    { 42.8571, 52.381 },
+    { 61.9048, 38.0952 },
+    { 71.4286, 33.3333 },
+    { 80.9524, 33.3333 },
+    { 90.4762, 38.0952 },
+    { 95.2381, 47.619 },
+};
+
+static const CoordRec monoChar126_stroke1[] = {
+    { 9.5238, 38.0952 },
+    { 14.2857, 47.619 },
+    { 23.8095, 52.381 },
+    { 33.3333, 52.381 },
+    { 42.8571, 47.619 },
+    { 61.9048, 33.3333 },
+    { 71.4286, 28.5714 },
+    { 80.9524, 28.5714 },
+    { 90.4762, 33.3333 },
+    { 95.2381, 47.619 },
+    { 95.2381, 57.1429 },
+};
+
+static const StrokeRec monoChar126[] = {
+   { 11, monoChar126_stroke0 },
+   { 11, monoChar126_stroke1 },
+};
+
+/* char: 127 */
+
+static const CoordRec monoChar127_stroke0[] = {
+    { 71.4286, 100 },
+    { 33.3333, -33.3333 },
+};
+
+static const CoordRec monoChar127_stroke1[] = {
+    { 47.619, 66.6667 },
+    { 33.3333, 61.9048 },
+    { 23.8095, 52.381 },
+    { 19.0476, 38.0952 },
+    { 19.0476, 23.8095 },
+    { 23.8095, 14.2857 },
+    { 33.3333, 4.7619 },
+    { 47.619, 0 },
+    { 57.1428, 0 },
+    { 71.4286, 4.7619 },
+    { 80.9524, 14.2857 },
+    { 85.7143, 28.5714 },
+    { 85.7143, 42.8571 },
+    { 80.9524, 52.381 },
+    { 71.4286, 61.9048 },
+    { 57.1428, 66.6667 },
+    { 47.619, 66.6667 },
+};
+
+static const StrokeRec monoChar127[] = {
+   { 2, monoChar127_stroke0 },
+   { 17, monoChar127_stroke1 },
+};
+
+static const StrokeCharRec monoChars[] = {
+    { 0, /* monoChar0 */ 0, 0, 0 },
+    { 0, /* monoChar1 */ 0, 0, 0 },
+    { 0, /* monoChar2 */ 0, 0, 0 },
+    { 0, /* monoChar3 */ 0, 0, 0 },
+    { 0, /* monoChar4 */ 0, 0, 0 },
+    { 0, /* monoChar5 */ 0, 0, 0 },
+    { 0, /* monoChar6 */ 0, 0, 0 },
+    { 0, /* monoChar7 */ 0, 0, 0 },
+    { 0, /* monoChar8 */ 0, 0, 0 },
+    { 0, /* monoChar9 */ 0, 0, 0 },
+    { 0, /* monoChar10 */ 0, 0, 0 },
+    { 0, /* monoChar11 */ 0, 0, 0 },
+    { 0, /* monoChar12 */ 0, 0, 0 },
+    { 0, /* monoChar13 */ 0, 0, 0 },
+    { 0, /* monoChar14 */ 0, 0, 0 },
+    { 0, /* monoChar15 */ 0, 0, 0 },
+    { 0, /* monoChar16 */ 0, 0, 0 },
+    { 0, /* monoChar17 */ 0, 0, 0 },
+    { 0, /* monoChar18 */ 0, 0, 0 },
+    { 0, /* monoChar19 */ 0, 0, 0 },
+    { 0, /* monoChar20 */ 0, 0, 0 },
+    { 0, /* monoChar21 */ 0, 0, 0 },
+    { 0, /* monoChar22 */ 0, 0, 0 },
+    { 0, /* monoChar23 */ 0, 0, 0 },
+    { 0, /* monoChar24 */ 0, 0, 0 },
+    { 0, /* monoChar25 */ 0, 0, 0 },
+    { 0, /* monoChar26 */ 0, 0, 0 },
+    { 0, /* monoChar27 */ 0, 0, 0 },
+    { 0, /* monoChar28 */ 0, 0, 0 },
+    { 0, /* monoChar29 */ 0, 0, 0 },
+    { 0, /* monoChar30 */ 0, 0, 0 },
+    { 0, /* monoChar31 */ 0, 0, 0 },
+    { 0, /* monoChar32 */ 0, 52.381, 104.762 },
+    { 2, monoChar33, 52.381, 104.762 },
+    { 2, monoChar34, 52.381, 104.762 },
+    { 4, monoChar35, 52.381, 104.762 },
+    { 3, monoChar36, 52.381, 104.762 },
+    { 3, monoChar37, 52.381, 104.762 },
+    { 1, monoChar38, 52.381, 104.762 },
+    { 1, monoChar39, 52.381, 104.762 },
+    { 1, monoChar40, 52.381, 104.762 },
+    { 1, monoChar41, 52.381, 104.762 },
+    { 3, monoChar42, 52.381, 104.762 },
+    { 2, monoChar43, 52.381, 104.762 },
+    { 1, monoChar44, 52.381, 104.762 },
+    { 1, monoChar45, 52.381, 104.762 },
+    { 1, monoChar46, 52.381, 104.762 },
+    { 1, monoChar47, 52.381, 104.762 },
+    { 1, monoChar48, 52.381, 104.762 },
+    { 1, monoChar49, 52.381, 104.762 },
+    { 1, monoChar50, 52.381, 104.762 },
+    { 1, monoChar51, 52.381, 104.762 },
+    { 2, monoChar52, 52.381, 104.762 },
+    { 1, monoChar53, 52.381, 104.762 },
+    { 1, monoChar54, 52.381, 104.762 },
+    { 2, monoChar55, 52.381, 104.762 },
+    { 1, monoChar56, 52.381, 104.762 },
+    { 1, monoChar57, 52.381, 104.762 },
+    { 2, monoChar58, 52.381, 104.762 },
+    { 2, monoChar59, 52.381, 104.762 },
+    { 1, monoChar60, 52.381, 104.762 },
+    { 2, monoChar61, 52.381, 104.762 },
+    { 1, monoChar62, 52.381, 104.762 },
+    { 2, monoChar63, 52.381, 104.762 },
+    { 2, monoChar64, 52.381, 104.762 },
+    { 3, monoChar65, 52.381, 104.762 },
+    { 3, monoChar66, 52.381, 104.762 },
+    { 1, monoChar67, 52.381, 104.762 },
+    { 2, monoChar68, 52.381, 104.762 },
+    { 4, monoChar69, 52.381, 104.762 },
+    { 3, monoChar70, 52.381, 104.762 },
+    { 2, monoChar71, 52.381, 104.762 },
+    { 3, monoChar72, 52.381, 104.762 },
+    { 1, monoChar73, 52.381, 104.762 },
+    { 1, monoChar74, 52.381, 104.762 },
+    { 3, monoChar75, 52.381, 104.762 },
+    { 2, monoChar76, 52.381, 104.762 },
+    { 4, monoChar77, 52.381, 104.762 },
+    { 3, monoChar78, 52.381, 104.762 },
+    { 1, monoChar79, 52.381, 104.762 },
+    { 2, monoChar80, 52.381, 104.762 },
+    { 2, monoChar81, 52.381, 104.762 },
+    { 3, monoChar82, 52.381, 104.762 },
+    { 1, monoChar83, 52.381, 104.762 },
+    { 2, monoChar84, 52.381, 104.762 },
+    { 1, monoChar85, 52.381, 104.762 },
+    { 2, monoChar86, 52.381, 104.762 },
+    { 4, monoChar87, 52.381, 104.762 },
+    { 2, monoChar88, 52.381, 104.762 },
+    { 2, monoChar89, 52.381, 104.762 },
+    { 3, monoChar90, 52.381, 104.762 },
+    { 4, monoChar91, 52.381, 104.762 },
+    { 1, monoChar92, 52.381, 104.762 },
+    { 4, monoChar93, 52.381, 104.762 },
+    { 2, monoChar94, 52.381, 104.762 },
+    { 1, monoChar95, 52.381, 104.762 },
+    { 2, monoChar96, 52.381, 104.762 },
+    { 2, monoChar97, 52.381, 104.762 },
+    { 2, monoChar98, 52.381, 104.762 },
+    { 1, monoChar99, 52.381, 104.762 },
+    { 2, monoChar100, 52.381, 104.762 },
+    { 1, monoChar101, 52.381, 104.762 },
+    { 2, monoChar102, 52.381, 104.762 },
+    { 2, monoChar103, 52.381, 104.762 },
+    { 2, monoChar104, 52.381, 104.762 },
+    { 2, monoChar105, 52.381, 104.762 },
+    { 2, monoChar106, 52.381, 104.762 },
+    { 3, monoChar107, 52.381, 104.762 },
+    { 1, monoChar108, 52.381, 104.762 },
+    { 3, monoChar109, 52.381, 104.762 },
+    { 2, monoChar110, 52.381, 104.762 },
+    { 1, monoChar111, 52.381, 104.762 },
+    { 2, monoChar112, 52.381, 104.762 },
+    { 2, monoChar113, 52.381, 104.762 },
+    { 2, monoChar114, 52.381, 104.762 },
+    { 1, monoChar115, 52.381, 104.762 },
+    { 2, monoChar116, 52.381, 104.762 },
+    { 2, monoChar117, 52.381, 104.762 },
+    { 2, monoChar118, 52.381, 104.762 },
+    { 4, monoChar119, 52.381, 104.762 },
+    { 2, monoChar120, 52.381, 104.762 },
+    { 2, monoChar121, 52.381, 104.762 },
+    { 3, monoChar122, 52.381, 104.762 },
+    { 3, monoChar123, 52.381, 104.762 },
+    { 1, monoChar124, 52.381, 104.762 },
+    { 3, monoChar125, 52.381, 104.762 },
+    { 2, monoChar126, 52.381, 104.762 },
+    { 2, monoChar127, 52.381, 104.762 },
+};
+
+static
+StrokeFontRec glutStrokeMonoRoman = { "Roman", 128, monoChars, 119.048, -33.3333 };
+
index fcf079ec9a672734e3409b6915f6a3bc9126ced8..0f718476e75d7b4e909b7f9b24e7622d74855e51 100644 (file)
@@ -665,9 +665,10 @@ load_texture_async (Screen *screen, Window window,
   data->pix_height = xgwa.height;
   data->pix_depth  = xgwa.depth;
 
-  if (desired_width  && desired_width  < xgwa.width)
+  /* Allow the pixmap to be larger than the window. Esper wants this. */
+  if (desired_width /* && desired_width  < xgwa.width */)
     data->pix_width  = desired_width;
-  if (desired_height && desired_height < xgwa.height)
+  if (desired_height /* && desired_height < xgwa.height */)
     data->pix_height = desired_height;
 
   data->pixmap = XCreatePixmap (dpy, window, data->pix_width, data->pix_height,
index fc6d30970682e554df95fa4ca624a63b09033f69..a547a76ca1fe22c2c74872f8459c3d6f51a35d33 100644 (file)
@@ -15,7 +15,6 @@
                        "*count:        20          \n" \
                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_hexstrut 0
 # define release_hexstrut 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -333,8 +332,15 @@ ENTRYPOINT void
 reshape_hexstrut (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 3) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -386,14 +392,12 @@ hexstrut_handle_event (ModeInfo *mi, XEvent *event)
 }
 
 
-static void free_hexstrut (ModeInfo *mi);
-
 ENTRYPOINT void 
 init_hexstrut (ModeInfo *mi)
 {
   hexstrut_configuration *bp;
 
-  MI_INIT (mi, bps, free_hexstrut);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
@@ -488,7 +492,7 @@ draw_hexstrut (ModeInfo *mi)
 }
 
 
-static void
+ENTRYPOINT void
 free_hexstrut (ModeInfo *mi)
 {
   hexstrut_configuration *bp = &bps[MI_SCREEN(mi)];
index 3caae97f6f8d0b89d25c7a67b85beb3a0c28e0ba..dbb2ce6741d6bbd17ac8c12a793e72858b53007a 100644 (file)
@@ -21,7 +21,7 @@
                        "*geometry:     800x800\n" \
                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_hilbert 0
+# define free_hilbert 0
 # define release_hilbert 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -757,8 +757,15 @@ ENTRYPOINT void
 reshape_hilbert (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -838,7 +845,7 @@ init_hilbert (ModeInfo *mi)
   int wire = MI_IS_WIREFRAME(mi);
   int i;
 
-  MI_INIT (mi, bps, NULL);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
index 776df0a7db3229ef4a222199d6f723ccd17fc7f2..2254483784460a9111ad392c82ff5556e70bfb24 100644 (file)
@@ -33,7 +33,6 @@
                        "*wireframe:    False       \n" \
                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_hydrostat 0
 # define release_hydrostat 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -641,8 +640,6 @@ hydrostat_handle_event (ModeInfo *mi, XEvent *event)
 }
 
 
-static void free_hydrostat (ModeInfo *mi);
-
 ENTRYPOINT void 
 init_hydrostat (ModeInfo *mi)
 {
@@ -650,7 +647,7 @@ init_hydrostat (ModeInfo *mi)
   hydrostat_configuration *bp;
   int i;
 
-  MI_INIT (mi, bps, free_hydrostat);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
@@ -759,7 +756,7 @@ draw_hydrostat (ModeInfo *mi)
 }
 
 
-static void
+ENTRYPOINT void
 free_hydrostat (ModeInfo *mi)
 {
   hydrostat_configuration *bp = &bps[MI_SCREEN(mi)];
index 7e1cc3e7651839b2fbefb45f6ae3ce64ee57257d..3ae6aadfc1676be19ae2e2a209d8ae313c8184d6 100644 (file)
@@ -89,7 +89,7 @@ static const char sccsid[] = "@(#)hypertorus.c  1.2 05/09/28 xlockmore";
                             "*showFPS:    False \n" \
                            "*suppressRotationAnimation: True\n" \
 
-# define refresh_hypertorus 0
+# define free_hypertorus 0
 # define release_hypertorus 0
 # include "xlockmore.h"         /* from the xscreensaver distribution */
 #else  /* !STANDALONE */
@@ -744,11 +744,19 @@ static void display_hypertorus(ModeInfo *mi)
 ENTRYPOINT void reshape_hypertorus(ModeInfo *mi, int width, int height)
 {
   hypertorusstruct *hp = &hyper[MI_SCREEN(mi)];
+  double 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;
+  }
 
   hp->WindW = (GLint)width;
   hp->WindH = (GLint)height;
-  glViewport(0,0,width,height);
-  hp->aspect = (GLfloat)width/(GLfloat)height;
+  glViewport(0,y,width,height);
+  hp->aspect = h;
 }
 
 
@@ -830,7 +838,7 @@ ENTRYPOINT void init_hypertorus(ModeInfo *mi)
 {
   hypertorusstruct *hp;
 
-  MI_INIT(mi, hyper, NULL);
+  MI_INIT(mi, hyper);
   hp = &hyper[MI_SCREEN(mi)];
 
   
index 4a8fe5e2a0c93183c923918aced8296f3569c1b5..0602e6e4e423970125bb7a3afa06255f9ca6f29d 100644 (file)
@@ -24,7 +24,7 @@
                        "*wireframe:    False       \n" \
                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_hypnowheel 0
+# define free_hypnowheel 0
 # define release_hypnowheel 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -137,8 +137,15 @@ ENTRYPOINT void
 reshape_hypnowheel (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 3) {   /* tiny window: show middle */
+    height = width;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -169,7 +176,7 @@ init_hypnowheel (ModeInfo *mi)
   int wire = MI_IS_WIREFRAME(mi);
   int i;
 
-  MI_INIT (mi, bps, NULL);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
index 4a77c8c562687b8992f5dc816d6c02bcd0ebe9d9..8556a5beceeab8e8fbf7b97c54175ca682081983 100644 (file)
@@ -41,7 +41,7 @@
                             "*wireframe: False\n" \
                            "*suppressRotationAnimation: True\n" \
 
-# define refresh_jigglypuff 0
+# define free_jigglypuff 0
 # define release_jigglypuff 0
 # include "xlockmore.h"
 #else
@@ -940,13 +940,19 @@ ENTRYPOINT Bool jigglypuff_handle_event(ModeInfo *mi, XEvent *event)
 
 ENTRYPOINT void reshape_jigglypuff(ModeInfo *mi, int width, int height)
 {
-    GLfloat aspect = (GLfloat)width / (GLfloat)height;
-
-    glViewport(0, 0, width, height);
-    glMatrixMode(GL_PROJECTION);
-    glLoadIdentity();
-    glFrustum(-0.5*aspect, 0.5*aspect, -0.5, 0.5, 1, 20);
-/*    glTranslatef(0, 0, -10);*/
+  double 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();
+  glFrustum(-0.5*(1/h), 0.5*(1/h), -0.5, 0.5, 1, 20);
 }
 
 ENTRYPOINT void draw_jigglypuff(ModeInfo *mi)
@@ -1010,7 +1016,7 @@ ENTRYPOINT void init_jigglypuff(ModeInfo *mi)
     jigglystruct *js;
     int subdivs;
 
-    MI_INIT(mi, jss, NULL);
+    MI_INIT(mi, jss);
 
     js = &jss[MI_SCREEN(mi)];
 
index 5a415b1756b32d9dff81113a363e3cb8f0ea9f38..5185f9b55fe135149cf1c8c8d80dccd5af3e612a 100644 (file)
@@ -59,7 +59,7 @@
                  "*suppressRotationAnimation: True\n" \
 
 
-# define refresh_jigsaw 0
+# define free_jigsaw 0
 # define release_jigsaw 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -1325,8 +1325,15 @@ reshape_jigsaw (ModeInfo *mi, int width, int height)
 {
   jigsaw_configuration *jc = &sps[MI_SCREEN(mi)];
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -1378,7 +1385,7 @@ init_jigsaw (ModeInfo *mi)
   jigsaw_configuration *jc;
   int wire = MI_IS_WIREFRAME(mi);
 
-  MI_INIT (mi, sps, NULL);
+  MI_INIT (mi, sps);
   jc = &sps[MI_SCREEN(mi)];
   jc->glx_context = init_GL(mi);
 
index 61b68eea14a0975780d76f6e2b538dcf498276a4..031502912cc5584eede216f33ddf86bfec725e9c 100644 (file)
                        "*showFPS:      False   \n" \
                        "*wireframe:    False   \n" \
 
-# define refresh_juggle 0
 # define release_juggle 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -637,7 +636,7 @@ trajectory_destroy(Trajectory *t) {
   REMOVE(t); /* Unlink and free */
 }
 
-static void
+ENTRYPOINT void
 free_juggle(ModeInfo *mi) {
   jugglestruct *sp = &juggles[MI_SCREEN(mi)];
 
@@ -2636,7 +2635,7 @@ init_juggle (ModeInfo * mi)
   jugglestruct *sp = 0;
   int wire = MI_IS_WIREFRAME(mi);
 
-  MI_INIT (mi, juggles, free_juggle);
+  MI_INIT (mi, juggles);
 
   sp = &juggles[MI_SCREEN(mi)];
 
index 679151ffa5957e9888aea07161ca384d7262e4c2..884400f8c65256554ac7fb0419b59fc3dc25be5d 100644 (file)
@@ -21,7 +21,7 @@
                        "*wireframe:    False       \n" \
                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_kaleidocycle 0
+# define free_kaleidocycle 0
 # define release_kaleidocycle 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -90,8 +90,15 @@ ENTRYPOINT void
 reshape_kaleidocycle (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -167,7 +174,7 @@ init_kaleidocycle (ModeInfo *mi)
   int wire = MI_IS_WIREFRAME(mi);
   int i;
 
-  MI_INIT (mi, bps, NULL);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
index 8c4a467b656832012786568d0b03d69429377e28..1c042da51b264d0de89ad33e3bb169aaf105cf1e 100644 (file)
@@ -137,7 +137,7 @@ static const char sccsid[] = "@(#)klein.c  1.1 08/10/04 xlockmore";
 # define DEFAULTS           "*delay:      10000 \n" \
                             "*showFPS:    False \n" \
 
-# define refresh_klein 0
+# define free_klein 0
 # define release_klein 0
 # include "xlockmore.h"         /* from the xscreensaver distribution */
 #else  /* !STANDALONE */
@@ -1857,7 +1857,7 @@ ENTRYPOINT void init_klein(ModeInfo *mi)
 {
   kleinstruct *kb;
 
-  MI_INIT(mi, klein, NULL);
+  MI_INIT(mi, klein);
   kb = &klein[MI_SCREEN(mi)];
 
   
index f29b4322daa6ca85c7a58a54cd663f329cdbc21a..777a5c648722f1c75c59b469efa5fca6df3d330f 100644 (file)
@@ -32,7 +32,7 @@
                        "*wireframe:    False   \n"     \
                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_lament 0
+# define free_lament 0
 # define release_lament 0
 #include "xlockmore.h"
 
@@ -325,6 +325,9 @@ scale_for_window (ModeInfo *mi)
   if (MI_WIDTH(mi) > MI_HEIGHT(mi))
     scale /= MI_WIDTH(mi) / (GLfloat) MI_HEIGHT(mi);
 
+  /* If the window is super wide, make it bigger. */
+  if (scale < 8) scale = 8;
+
   /* Constrain it to roughly life-sized on the screen, not huge.
    */
 # ifdef HAVE_MOBILE
@@ -1705,7 +1708,7 @@ init_lament (ModeInfo *mi)
 {
   lament_configuration *lc;
   int i;
-  MI_INIT (mi, lcs, NULL);
+  MI_INIT (mi, lcs);
 
   lc = &lcs[MI_SCREEN(mi)];
 
index b1604a2212829b623850e7be27dde2a78cc2f831..6f57bf7d0d592284972bff53df522a81c5ddc6b0 100644 (file)
@@ -70,7 +70,7 @@
                        "*geometry:     600x900\n"      \
                        "*count:      " DEF_COUNT " \n" \
 
-# define refresh_lavalite 0
+# define free_lavalite 0
 # define release_lavalite 0
 
 
@@ -300,8 +300,15 @@ ENTRYPOINT void
 reshape_lavalite (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 3;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -1274,7 +1281,7 @@ init_lavalite (ModeInfo *mi)
   lavalite_configuration *bp;
   int wire = MI_IS_WIREFRAME(mi);
 
-  MI_INIT (mi, bps, NULL);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
index 404a49fd561389842e3a1da2f132dffb1b165b34..f15374b213824ba9e86a1e442385cd6c1e8dce08 100644 (file)
@@ -39,7 +39,6 @@
 #define        DEFAULTS        "*delay:        20000   \n"\
                        "*showFPS:      False   \n"
 
-#define        refresh_lockward        0
 #define        release_lockward        0
 
 
@@ -137,7 +136,7 @@ typedef struct lockward_context {
 /***************************************************************************
  * Prototypes.
  */
-static void free_lockward (ModeInfo *mi);
+ENTRYPOINT void free_lockward (ModeInfo *mi);
 
 
 /***************************************************************************
@@ -206,11 +205,18 @@ reshape_lockward (ModeInfo *mi, int width, int height)
 {
        lockward_context *ctx = &g_ctx[MI_SCREEN (mi)];
        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;
+        }
 
        glXMakeCurrent (MI_DISPLAY (mi), MI_WINDOW (mi),
                        *(ctx->glx_context));
 
-       glViewport (0, 0, (GLint) width, (GLint) height);
+       glViewport (0, y, (GLint) width, (GLint) height);
 
        glMatrixMode (GL_PROJECTION);
        glLoadIdentity ();
@@ -832,7 +838,7 @@ init_lockward (ModeInfo *mi)
        lockward_context        *ctx;
        int             i, n;
 
-       MI_INIT (mi, g_ctx, free_lockward);
+       MI_INIT (mi, g_ctx);
        ctx = &g_ctx[MI_SCREEN (mi)];
 
        ctx->glx_context = init_GL (mi);
@@ -850,7 +856,8 @@ init_lockward (ModeInfo *mi)
        /* ctx->blades_inner    = glGenLists (NRADII); */
        ctx->rings              = glGenLists (NRADII - 1);
        ctx->blendmode          = 0;
-       ctx->fps                = 1000000 / MI_DELAY (mi);
+/* WTF?        ctx->fps                = 1000000 / MI_DELAY (mi); */
+        ctx->fps = 60;
        ctx->nextblink          = calc_interval_frames
                                   (ctx, g_blinkidle_min, g_blinkidle_max);
        ctx->blink.drawfunc     = NULL;
@@ -924,7 +931,7 @@ init_lockward (ModeInfo *mi)
        }
 }
 
-static void
+ENTRYPOINT void
 free_lockward (ModeInfo *mi)
 {
        lockward_context        *ctx = &g_ctx[MI_SCREEN (mi)];
index c5108a28d93c4725dc618e9127f0875d52a042fc..249d224013f6e5d6611580587fe3040b93b45542 100644 (file)
@@ -56,7 +56,7 @@
                        "*suppressRotationAnimation: True\n" \
 
 
-# define refresh_sponge 0
+# define free_sponge 0
 # define release_sponge 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -128,8 +128,15 @@ ENTRYPOINT void
 reshape_sponge (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -401,7 +408,7 @@ init_sponge (ModeInfo *mi)
   sponge_configuration *sp;
   int wire = MI_IS_WIREFRAME(mi);
 
-  MI_INIT (mi, sps, NULL);
+  MI_INIT (mi, sps);
 
   sp = &sps[MI_SCREEN(mi)];
 
index 7595e70d243ea6170c6ac1c798e232e14f6bc748..eb746d1a101e433d3972a84a5d6326beb54052a4 100644 (file)
@@ -44,7 +44,6 @@
                  "*chooseRandomImages:  True  \n"                           \
                 "*suppressRotationAnimation: True\n"                       \
 
-# define refresh_mirrorblob 0
 # define release_mirrorblob 0
 # include "xlockmore.h"
 #else /* !STANDALONE */
@@ -179,7 +178,7 @@ ENTRYPOINT ModeSpecOpt mirrorblob_opts = {countof(opts), opts, countof(vars), va
 #ifdef USE_MODULES
 ModStruct   mirrorblob_description =
 {"mirrorblob", "init_mirrorblob", "draw_mirrorblob", NULL,
- "draw_mirrorblob", "init_mirrorblob", "handle_event", &mirrorblob_opts,
+ "draw_mirrorblob", "init_mirrorblob", "free_mirrorblob", &mirrorblob_opts,
  1000, 1, 2, 1, 4, 1.0, "",
  "OpenGL mirrorblob", 0, NULL};
 #endif
@@ -1786,8 +1785,6 @@ mirrorblob_handle_event (ModeInfo * mi, XEvent * event)
   return False;
 }
 
-static void free_mirrorblob(ModeInfo * mi);
-
 /******************************************************************************
  *
  * XMirrorblob initialise entry
@@ -1799,7 +1796,7 @@ init_mirrorblob(ModeInfo * mi)
 
   mirrorblobstruct *gp;
 
-  MI_INIT(mi, Mirrorblob, free_mirrorblob);
+  MI_INIT(mi, Mirrorblob);
   gp = &Mirrorblob[screen];
 
   gp->window = MI_WINDOW(mi);
@@ -1825,7 +1822,7 @@ init_mirrorblob(ModeInfo * mi)
  *
  * XMirrorblob cleanup entry
  */
-static void
+ENTRYPOINT void
 free_mirrorblob(ModeInfo * mi)
 {
   mirrorblobstruct *gp = &Mirrorblob[MI_SCREEN(mi)];
index 80a8246381a171d7c2036ce94e9238187d1ae0d2..5fe2d9b8a8c4f43438ee51932eff61010bd6ff5a 100644 (file)
@@ -79,7 +79,7 @@ static const char sccsid[] = "@(#)moebius.c   5.01 2001/03/01 xlockmore";
 
 #ifdef STANDALONE
 # define MODE_moebius
-# define refresh_moebius 0
+# define free_moebius 0
 # define release_moebius 0
 # define DEFAULTS                      "*delay:                20000   \n"                     \
                                                        "*showFPS:      False   \n"                     \
@@ -564,8 +564,14 @@ ENTRYPOINT void
 reshape_moebius (ModeInfo * mi, int width, int height)
 {
        moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
+    int y = 0;
 
-       glViewport(0, 0, mp->WindW = (GLint) width, mp->WindH = (GLint) height);
+    if (width > height * 5) {   /* tiny window: show middle */
+      height = width;
+      y = -height/2;
+    }
+
+       glViewport(0, y, mp->WindW = (GLint) width, mp->WindH = (GLint) height);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0);
@@ -673,7 +679,7 @@ init_moebius (ModeInfo * mi)
 {
        moebiusstruct *mp;
 
-       MI_INIT (mi, moebius, NULL);
+       MI_INIT (mi, moebius);
        mp = &moebius[MI_SCREEN(mi)];
        mp->step = NRAND(90);
        mp->ant_position = NRAND(90);
index 0716cdcb858dc566de96560b5272a19636adf6d0..0f058b81e603f43c037c5cbce772302855250762 100644 (file)
@@ -15,7 +15,7 @@
                        "*wireframe:    False       \n" \
                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_mgears 0
+# define free_mgears 0
 # define release_mgears 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -92,8 +92,15 @@ ENTRYPOINT void
 reshape_mgears (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -236,7 +243,7 @@ init_mgears (ModeInfo *mi)
   mgears_configuration *bp;
   int wire = MI_IS_WIREFRAME(mi);
 
-  MI_INIT (mi, bps, NULL);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
index 57827b2b3d2e6fdbbbf30e374454653218ed5639..d8bc1d854ccf6ab42ae201a134f8194eb01a2d67 100644 (file)
@@ -33,7 +33,7 @@
                        "*wireframeThreshold:  150    \n" \
                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_molecule 0
+# define free_molecule 0
 # define release_molecule 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -1187,8 +1187,15 @@ ENTRYPOINT void
 reshape_molecule (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -1288,7 +1295,7 @@ init_molecule (ModeInfo *mi)
   molecule_configuration *mc;
   int wire;
 
-  MI_INIT (mi, mcs, NULL);
+  MI_INIT (mi, mcs);
 
   mc = &mcs[MI_SCREEN(mi)];
 
index 4bea5766f90002f2545eb7a9dd62b7a5d1c87e07..078044496b5fa57d31990b708f740b7adc8a6cab 100644 (file)
@@ -58,9 +58,9 @@ static const char sccsid[] = "@(#)morph3d.c   5.01 2001/03/01 xlockmore";
                                                "*count:                0               \n"             \
                                                "*suppressRotationAnimation: True\n" \
 
-# define refresh_morph3d 0
+# define free_morph3d 0
 # define release_morph3d 0
-# define morph3d_handle_event 0
+# define morph3d_handle_event xlockmore_no_events
 # include "xlockmore.h"                /* from the xscreensaver distribution */
 #else /* !STANDALONE */
 # include "xlock.h"            /* from the xlockmore distribution */
@@ -595,8 +595,14 @@ ENTRYPOINT void
 reshape_morph3d(ModeInfo * mi, int width, int height)
 {
        morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
+    int y = 0;
 
-       glViewport(0, 0, mp->WindW = (GLint) width, mp->WindH = (GLint) height);
+    if (width > height * 5) {   /* tiny window: show middle */
+      height = width;
+      y = -height/2;
+    }
+
+       glViewport(0, y, mp->WindW = (GLint) width, mp->WindH = (GLint) height);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0);
@@ -719,7 +725,7 @@ init_morph3d(ModeInfo * mi)
 {
        morph3dstruct *mp;
 
-       MI_INIT (mi, morph3d, NULL);
+       MI_INIT (mi, morph3d);
        mp = &morph3d[MI_SCREEN(mi)];
        mp->step = NRAND(90);
        mp->VisibleSpikes = 1;
index ab483f9ab6ce2ff237d3eae5bd7331106e1612e2..4b23035d050e908ade91a8c9b19a50b11b23ac6d 100644 (file)
@@ -19,7 +19,7 @@
                        "*doubleBuffer: False       \n" \
                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_noof 0
+# define free_noof 0
 # define release_noof 0
 # define noof_handle_event 0
 #include "xlockmore.h"
@@ -444,7 +444,7 @@ init_noof (ModeInfo *mi)
   int i;
   noof_configuration *bp;
 
-  MI_INIT (mi, bps, NULL);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
index 0f6312febf6a96b74a288a0b39f4dd5012e9e80f..fecef1d8f9aa3ccb302304bf6b1f17be170bf673 100644 (file)
@@ -29,9 +29,9 @@
                   "*chooseRandomImages:  True  \n" \
                  "*suppressRotationAnimation: True\n" \
 
-# define refresh_photopile 0
+# define free_photopile 0
 # define release_photopile 0
-# define photopile_handle_event 0
+# define photopile_handle_event xlockmore_no_events
 
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -480,7 +480,7 @@ init_photopile (ModeInfo *mi)
   photopile_state *ss;
   int wire = MI_IS_WIREFRAME(mi);
 
-  MI_INIT (mi, sss, NULL);
+  MI_INIT (mi, sss);
   ss = &sss[screen];
   ss->mi = mi;
 
index f368da2280a97aa01da51863e92a9b3fce771d19..f6793eb446b01366bc2802965983707c7b9f6601 100644 (file)
@@ -16,7 +16,7 @@
            "*titleFont2: -*-helvetica-medium-r-normal-*-*-120-*-*-*-*-*-*\n" \
            "*titleFont3: -*-helvetica-medium-r-normal-*-*-80-*-*-*-*-*-*\n"  \
 
-# define refresh_pinion 0
+# define free_pinion 0
 # define release_pinion 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -1246,10 +1246,17 @@ find_mouse_gear (ModeInfo *mi)
 ENTRYPOINT void
 reshape_pinion (ModeInfo *mi, int width, int height)
 {
-  GLfloat h = (GLfloat) height / (GLfloat) width;
   pinion_configuration *pp = &pps[MI_SCREEN(mi)];
+  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, 0, (GLint) width, (GLint) height);
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -1315,7 +1322,7 @@ init_pinion (ModeInfo *mi)
 {
   pinion_configuration *pp;
 
-  MI_INIT (mi, pps, NULL);
+  MI_INIT (mi, pps);
 
   pp = &pps[MI_SCREEN(mi)];
 
index 77be33e1fce2ed41c40b4ea451b4e3f0aea39df0..24f9a2a093bf9602c7699a1481b77ed5cf19d403 100644 (file)
@@ -68,7 +68,6 @@ static const char sccsid[] = "@(#)pipes.c     4.07 97/11/24 xlockmore";
                        "*wireframe:    False   \n"                 \
                                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_pipes 0
 # define release_pipes 0
 # include "xlockmore.h"                                /* from the xscreensaver distribution */
 #else  /* !STANDALONE */
@@ -135,7 +134,7 @@ ENTRYPOINT ModeSpecOpt pipes_opts =
 ModStruct   pipes_description =
 {"pipes", "init_pipes", "draw_pipes", NULL,
  "draw_pipes",
- "change_pipes", NULL, &pipes_opts,
+ "change_pipes", "free_pipes", &pipes_opts,
  1000, 2, 5, 500, 4, 1.0, "",
  "Shows a selfbuilding pipe system", 0, NULL};
 
@@ -656,12 +655,20 @@ pinit(ModeInfo * mi, int zera)
 ENTRYPOINT void
 reshape_pipes(ModeInfo * mi, int width, int height)
 {
-       glViewport(0, 0, width, (GLint) height);
-       glMatrixMode(GL_PROJECTION);
-       glLoadIdentity();
-       /*glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0); */
-       gluPerspective(65.0, (GLfloat) width / (GLfloat) height, 0.1, 20.0);
-       glMatrixMode(GL_MODELVIEW);
+  double 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, (GLint) height);
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  /*glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0); */
+  gluPerspective(65.0, 1/h, 0.1, 20.0);
+  glMatrixMode(GL_MODELVIEW);
 
   glClear(GL_COLOR_BUFFER_BIT);
 }
@@ -689,15 +696,13 @@ pipes_handle_event (ModeInfo *mi, XEvent *event)
 static void generate_system (ModeInfo *);
 
 
-static void free_pipes (ModeInfo *);
-
 ENTRYPOINT void
 init_pipes (ModeInfo * mi)
 {
        int         screen = MI_SCREEN(mi);
        pipesstruct *pp;
 
-       MI_INIT (mi, pipes, free_pipes);
+       MI_INIT (mi, pipes);
        pp = &pipes[screen];
 
        pp->window = MI_WINDOW(mi);
@@ -1167,7 +1172,7 @@ change_pipes (ModeInfo * mi)
 #endif /* !STANDALONE */
 
 
-static void
+ENTRYPOINT void
 free_pipes (ModeInfo * mi)
 {
        pipesstruct *pp = &pipes[MI_SCREEN(mi)];
index a46453348f6ba7b861ee65f26f7a4a0e1cfdb149..507d295790768be406a9086e3f4f0e7feb427589 100644 (file)
@@ -24,7 +24,7 @@
        "*suppressRotationAnimation: True\n" \
 
 
-# define refresh_polyhedra 0
+# define free_polyhedra 0
 # define release_polyhedra 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -201,8 +201,15 @@ ENTRYPOINT void
 reshape_polyhedra (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -462,7 +469,7 @@ init_polyhedra (ModeInfo *mi)
   wire = 0;
 # endif
 
-  MI_INIT (mi, bps, NULL);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
index 0b4d68481d7c7718d2f496075540fa26a5cb3168..76c1287363a10ba537a13d1ad85d7c57bd152b29 100644 (file)
@@ -93,7 +93,7 @@ static const char sccsid[] = "@(#)polytopes.c  1.2 05/09/28 xlockmore";
                             "*showFPS:    False \n" \
                            "*suppressRotationAnimation: True\n" \
 
-# define refresh_polytopes 0
+# define free_polytopes 0
 # define release_polytopes 0
 # include "xlockmore.h"         /* from the xscreensaver distribution */
 #else  /* !STANDALONE */
@@ -2863,10 +2863,16 @@ static void display_polytopes(ModeInfo *mi)
 ENTRYPOINT void reshape_polytopes(ModeInfo *mi, int width, int height)
 {
   polytopesstruct *pp = &poly[MI_SCREEN(mi)];
+  int y = 0;
+
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width;
+    y = -height/2;
+  }
 
   pp->WindW = (GLint)width;
   pp->WindH = (GLint)height;
-  glViewport(0,0,width,height);
+  glViewport(0,y,width,height);
   pp->aspect = (GLfloat)width/(GLfloat)height;
 }
 
@@ -2949,7 +2955,7 @@ ENTRYPOINT void init_polytopes(ModeInfo *mi)
 {
   polytopesstruct *pp;
 
-  MI_INIT(mi, poly, NULL);
+  MI_INIT(mi, poly);
   pp = &poly[MI_SCREEN(mi)];
 
   pp->trackballs[0] = gltrackball_init(True);
index 0fe29fa32a0fb9fad17976fb55b8787d497d4681..2a1e56604c92cdaa1dad2b67222e7322d4ea85db 100644 (file)
@@ -219,7 +219,7 @@ static const char sccsid[] = "@(#)projectiveplane.c  1.1 14/01/01 xlockmore";
 # define DEFAULTS           "*delay:      10000 \n" \
                             "*showFPS:    False \n" \
 
-# define refresh_projectiveplane 0
+# define free_projectiveplane 0
 # define release_projectiveplane 0
 # include "xlockmore.h"         /* from the xscreensaver distribution */
 #else  /* !STANDALONE */
@@ -1321,7 +1321,7 @@ ENTRYPOINT void init_projectiveplane(ModeInfo *mi)
 {
   projectiveplanestruct *pp;
 
-  MI_INIT(mi, projectiveplane, NULL);
+  MI_INIT(mi, projectiveplane);
   pp = &projectiveplane[MI_SCREEN(mi)];
 
   
index 2d49bb4a956b635b8fb58de7b1b3b9751a8177a2..d628845e6d567f17f7fcb7ca1f8283a0758a6645 100644 (file)
@@ -19,7 +19,7 @@
                            "*showFPS: False   \n" \
                            "*wireframe: False \n"
 
-# define refresh_providence 0
+# define free_providence 0
 # define release_providence 0
 #include "xlockmore.h"
 #else
@@ -596,10 +596,17 @@ static void draw_providence_strip(ModeInfo *mi)
 
 ENTRYPOINT void reshape_providence(ModeInfo * mi, int width, int height) 
 {
-  double h = (GLfloat) height / (GLfloat) width;  
   providencestruct *mp = &providence[MI_SCREEN(mi)];
+  double h = (GLfloat) height / (GLfloat) width;  
+  int y = 0;
+
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 3;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
 
-  glViewport(0, 0, mp->WindW = (GLint) width, mp->WindH = (GLint) height);
+  glViewport(0, y, mp->WindW = (GLint) width, mp->WindH = (GLint) height);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
 
@@ -660,7 +667,7 @@ ENTRYPOINT void init_providence(ModeInfo *mi)
 {
   providencestruct *mp;
   
-  MI_INIT(mi, providence, NULL);
+  MI_INIT(mi, providence);
   mp = &providence[MI_SCREEN(mi)];
   mp->trackball = gltrackball_init (False);
 
index c229090d2279ef7b5210f84521a69786d927f61e..869933b6e24a4c89e11935b5d062eaf87187a4fa 100644 (file)
@@ -44,9 +44,8 @@
 #define        DEFAULTS                        "*delay:                        10000   \n" \
                                                                                "*showFPS:          False   \n" \
 
-# define refresh_pulsar 0
 # define release_pulsar 0
-# define pulsar_handle_event 0
+# define pulsar_handle_event xlockmore_no_events
 # include "xlockmore.h"                                /* from the xpulsar distribution */
 #else /* !STANDALONE */
 # include "xlock.h"                                    /* from the xlockmore distribution */
@@ -162,7 +161,7 @@ ENTRYPOINT ModeSpecOpt pulsar_opts = {countof(opts), opts, countof(vars), vars,
 #ifdef USE_MODULES
 ModStruct   pulsar_description =
 {"pulsar", "init_pulsar", "draw_pulsar", NULL,
- "draw_pulsar", "init_pulsar", NULL, &pulsar_opts,
+ "draw_pulsar", "init_pulsar", "free_pulsar", &pulsar_opts,
  1000, 1, 2, 1, 4, 1.0, "",
  "OpenGL pulsar", 0, NULL};
 #endif
@@ -482,8 +481,6 @@ reshape_pulsar(ModeInfo *mi, int width, int height)
   resetProjection();
 }
 
-static void free_pulsar(ModeInfo * mi);
-
 ENTRYPOINT void
 init_pulsar(ModeInfo * mi)
 {
@@ -491,7 +488,7 @@ init_pulsar(ModeInfo * mi)
 
   pulsarstruct *gp;
 
-  MI_INIT (mi, Pulsar, free_pulsar);
+  MI_INIT (mi, Pulsar);
   gp = &Pulsar[screen];
 
   gp->window = MI_WINDOW(mi);
@@ -508,7 +505,7 @@ init_pulsar(ModeInfo * mi)
 
 
 /* all sorts of nice cleanup code should go here! */
-static void free_pulsar(ModeInfo * mi)
+ENTRYPOINT void free_pulsar(ModeInfo * mi)
 {
   pulsarstruct *gp = &Pulsar[MI_SCREEN(mi)];
   free(gp->quads);
index 2e761e358e2cc4f4663c9fd7c5b6c0da685bbed6..5190da32586dde74df95c5b6c97e15ee5dcba3b7 100644 (file)
@@ -24,7 +24,7 @@
                        "*wireframe:    False       \n" \
                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_quasicrystal 0
+# define free_quasicrystal 0
 # define release_quasicrystal 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -192,7 +192,7 @@ init_quasicrystal (ModeInfo *mi)
   int tex_width;
   int i;
 
-  MI_INIT (mi, bps, NULL);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
index cd3867cf9af87498d8367146ff71aeb490aafef3..bc9b2029d228f8894673e28db90930851b35841c 100644 (file)
@@ -22,7 +22,8 @@
                        "*showFPS:     False \n" \
                       "*wireframe:   False \n" \
 
-# define refresh_queens 0
+# define free_queens 0
+# define release_queens 0
 # include "xlockmore.h"
 
 #else
@@ -519,7 +520,14 @@ static int draw_model(int chunks, const GLfloat model[][3], int r)
 ENTRYPOINT void reshape_queens(ModeInfo *mi, int width, int height) 
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
-  glViewport(0,0, width, height);
+  int y = 0;
+
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+  glViewport(0,y, width, height);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   gluPerspective(45, 1/h, 2.0, 30.0);
@@ -537,7 +545,7 @@ ENTRYPOINT void init_queens(ModeInfo *mi)
   wire = 0;
 # endif
 
-  MI_INIT (mi, qss, NULL);
+  MI_INIT (mi, qss);
   
   qs = &qss[screen];
   qs->window = MI_WINDOW(mi);
@@ -597,15 +605,6 @@ ENTRYPOINT void draw_queens(ModeInfo *mi)
   glXSwapBuffers(disp, w);
 }
 
-ENTRYPOINT void release_queens(ModeInfo *mi) 
-{
-  if(qss)
-    free((void *) qss);
-  qss = 0;
-
-  FreeAllGL(mi);
-}
-
 XSCREENSAVER_MODULE ("Queens", queens)
 
 #endif
index 71d2c8d003fa492523893e06c4bf22f1693f58e3..5cf35f7fccf6f0f91eebb4b254ecf3cbf863cfe7 100644 (file)
@@ -16,7 +16,7 @@
                        "*showFPS:      False       \n" \
                        "*wireframe:    False       \n" \
 
-# define refresh_hoop 0
+# define free_hoop 0
 # define release_hoop 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -591,8 +591,15 @@ ENTRYPOINT void
 reshape_hoop (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -649,7 +656,7 @@ init_hoop (ModeInfo *mi)
   hoop_configuration *bp;
   int wire = MI_IS_WIREFRAME(mi);
 
-  MI_INIT (mi, bps, NULL);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
index c6ae79f3340ca479c48ff47127f75fae19c79afe..9ad12f0c7e9e0456e3b54b8dec4286a59736a882 100644 (file)
@@ -205,7 +205,6 @@ static const char sccsid[] = "@(#)romanboy.c  1.1 14/10/03 xlockmore";
 # define DEFAULTS           "*delay:      10000 \n" \
                             "*showFPS:    False \n" \
 
-# define refresh_romanboy 0
 # define release_romanboy 0
 # include "xlockmore.h"         /* from the xscreensaver distribution */
 #else  /* !STANDALONE */
@@ -227,7 +226,7 @@ static const char sccsid[] = "@(#)romanboy.c  1.1 14/10/03 xlockmore";
 ModStruct romanboy_description =
 {"romanboy", "init_romanboy", "draw_romanboy",
  NULL, "draw_romanboy", "change_romanboy",
NULL, &romanboy_opts, 25000, 1, 1, 1, 1.0, 4, "",
"free_romanboy", &romanboy_opts, 25000, 1, 1, 1, 1.0, 4, "",
  "Rotate a 3d immersion of the real projective plane in 3d or walk on it",
  0, NULL};
 
@@ -1270,10 +1269,16 @@ static void display_romanboy(ModeInfo *mi)
 ENTRYPOINT void reshape_romanboy(ModeInfo *mi, int width, int height)
 {
   romanboystruct *pp = &romanboy[MI_SCREEN(mi)];
+  int y = 0;
+
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width;
+    y = -height/2;
+  }
 
   pp->WindW = (GLint)width;
   pp->WindH = (GLint)height;
-  glViewport(0,0,width,height);
+  glViewport(0,y,width,height);
   pp->aspect = (GLfloat)width/(GLfloat)height;
 }
 
@@ -1314,8 +1319,6 @@ ENTRYPOINT Bool romanboy_handle_event(ModeInfo *mi, XEvent *event)
  *-----------------------------------------------------------------------------
  */
 
-static void free_romanboy(ModeInfo *mi);
-
 /*
  *-----------------------------------------------------------------------------
  *    Initialize romanboy.  Called each time the window changes.
@@ -1326,7 +1329,7 @@ ENTRYPOINT void init_romanboy(ModeInfo *mi)
 {
   romanboystruct *pp;
 
-  MI_INIT (mi, romanboy, free_romanboy);
+  MI_INIT (mi, romanboy);
   pp = &romanboy[MI_SCREEN(mi)];
 
   if (surface_order < 2)
@@ -1517,7 +1520,7 @@ ENTRYPOINT void draw_romanboy(ModeInfo *mi)
  *-----------------------------------------------------------------------------
  */
 
-static void free_romanboy(ModeInfo *mi)
+ENTRYPOINT void free_romanboy(ModeInfo *mi)
 {
   romanboystruct *pp = &romanboy[MI_SCREEN(mi)];
 
index 7d43bd856a1fe61d08ed1b8b097442974bc4dd58..ed06645aedce34379cda5132ad4c4d0f6e804e31 100644 (file)
@@ -112,7 +112,6 @@ static const char sccsid[] = "@(#)rubik.c   5.01 2001/03/01 xlockmore";
                                        "*size:  -6 \n"         \
                                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_rubik 0
 # define release_rubik 0
 # include "xlockmore.h"                                /* from the xscreensaver distribution */
 #else /* !STANDALONE */
@@ -165,7 +164,7 @@ ENTRYPOINT ModeSpecOpt rubik_opts =
 #ifdef USE_MODULES
 ModStruct   rubik_description =
 {"rubik", "init_rubik", "draw_rubik", (char *) NULL,
- "draw_rubik", "change_rubik", (char *) NULL, &rubik_opts,
+ "draw_rubik", "change_rubik", "free_rubik", &rubik_opts,
  10000, -30, 5, -6, 64, 1.0, "",
  "Shows an auto-solving Rubik's Cube", 0, NULL};
 
@@ -1814,8 +1813,14 @@ ENTRYPOINT void
 reshape_rubik(ModeInfo * mi, int width, int height)
 {
        rubikstruct *rp = &rubik[MI_SCREEN(mi)];
+    int y = 0;
 
-       glViewport(0, 0, rp->WindW = (GLint) width, rp->WindH = (GLint) height);
+    if (width > height * 5) {   /* tiny window: show middle */
+      height = width;
+      y = -height/2;
+    }
+
+       glViewport(0, y, rp->WindW = (GLint) width, rp->WindH = (GLint) height);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0);
@@ -1869,7 +1874,7 @@ pinit(ModeInfo * mi)
        return (shuffle(mi));
 }
 
-static void
+ENTRYPOINT void
 free_rubik(ModeInfo *mi)
 {
        rubikstruct *rp = &rubik[MI_SCREEN(mi)];
@@ -1896,7 +1901,7 @@ init_rubik(ModeInfo * mi)
 {
        rubikstruct *rp;
 
-       MI_INIT (mi, rubik, free_rubik);
+       MI_INIT (mi, rubik);
        rp = &rubik[MI_SCREEN(mi)];
        rp->step = NRAND(90);
        rp->PX = ((float) LRAND() / (float) MAXRAND) * 2.0 - 1.0;
index 9a6ecbdc06ae4794f0b4971ef326e5c09e40bebb..1dbde24c010353f15a23d76973df1709d4c8c017 100644 (file)
@@ -22,7 +22,7 @@
                    "*wireframe:     False         \n" \
                   "*suppressRotationAnimation: True\n" \
 
-# define refresh_rubikblocks 0
+# define free_rubikblocks 0
 # define release_rubikblocks 0
 #include "xlockmore.h"
 #include "rotator.h"
@@ -542,9 +542,15 @@ ENTRYPOINT void
 reshape_rubikblocks(ModeInfo *mi, int width, int height) 
 {
   rubikblocks_conf *cp = &rubikblocks[MI_SCREEN(mi)];
+  int y = 0;
+
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width;
+    y = -height/2;
+  }
   if(!height) height = 1;
   cp->ratio = (GLfloat)width/(GLfloat)height;
-  glViewport(0, 0, (GLint) width, (GLint) height);
+  glViewport(0, y, (GLint) width, (GLint) height);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   gluPerspective(30.0, cp->ratio, 1.0, 100.0);
@@ -556,7 +562,7 @@ ENTRYPOINT void
 init_rubikblocks(ModeInfo *mi) 
 {
   rubikblocks_conf *cp;
-  MI_INIT(mi, rubikblocks, NULL);
+  MI_INIT(mi, rubikblocks);
   cp = &rubikblocks[MI_SCREEN(mi)];
 
   if(tex)
index bae0b78902a5d7569495c7f8e2d48417971d5fc0..4c1ff9290ec8bee7a0941878f217bc9fc0316bfa 100644 (file)
@@ -47,7 +47,6 @@ static const char sccsid[] = "@(#)sballs.c    5.02 2001/03/10 xlockmore";
                        "*showFPS:      False \n" \
                        "*wireframe:    False \n" \
 
-# define refresh_sballs 0
 # define release_sballs 0
 #define MODE_sballs
 #include "xlockmore.h"         /* from the xscreensaver distribution */
@@ -119,7 +118,7 @@ ENTRYPOINT ModeSpecOpt sballs_opts =
 #ifdef USE_MODULES
 ModStruct sballs_description =
     { "sballs", "init_sballs", "draw_sballs", NULL,
-    "draw_sballs", "change_sballs", (char *) NULL, &sballs_opts,
+    "draw_sballs", "change_sballs", "free_sballs", &sballs_opts,
     /*
     delay,count,cycles,size,ncolors,sat
      */
@@ -526,6 +525,12 @@ ENTRYPOINT void reshape_sballs(ModeInfo * mi, int width, int height)
         sb->WIDTH = (size > MI_WIDTH(mi)) ? MI_WIDTH(mi) : size;
         sb->HEIGHT = (size > MI_HEIGHT(mi)) ? MI_HEIGHT(mi) : size;
     }
+
+    if (width > height * 5) {   /* tiny window: show middle */
+      sb->WIDTH = width;
+      sb->HEIGHT = sb->WIDTH*0.75;
+    }
+
     glViewport((MI_WIDTH(mi) - sb->WIDTH) / 2, (MI_HEIGHT(mi) - sb->HEIGHT) / 2, sb->WIDTH, sb->HEIGHT);
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
@@ -686,8 +691,6 @@ static void Init(ModeInfo * mi)
  *-----------------------------------------------------------------------------
  */
 
-static void free_sballs(ModeInfo * mi);
-
 /*
  *-----------------------------------------------------------------------------
  *    Initialize sballs.  Called each time the window changes.
@@ -698,7 +701,7 @@ ENTRYPOINT void init_sballs(ModeInfo * mi)
 {
     sballsstruct *sb;
 
-    MI_INIT(mi, sballs, free_sballs);
+    MI_INIT(mi, sballs);
     sb = &sballs[MI_SCREEN(mi)];
 
     sb->trackball = gltrackball_init (True);
@@ -757,7 +760,7 @@ ENTRYPOINT void draw_sballs(ModeInfo * mi)
  *-----------------------------------------------------------------------------
  */
 
-static void free_sballs(ModeInfo * mi)
+ENTRYPOINT void free_sballs(ModeInfo * mi)
 {
     sballsstruct *sb = &sballs[MI_SCREEN(mi)];
     if (sb->glx_context)
index 3b80fc2b498d499a453498d55928832d19933584..0317299ab25d24dcdbefeb4bfdd08369fadd6022 100644 (file)
@@ -32,7 +32,6 @@ static const char sccsid[] = "@(#)sierpinski3D.c      00.01 99/11/04 xlockmore";
                                                                        "*wireframe:    False   \n"                     \
                                                                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_gasket 0
 # define release_gasket 0
 # include "xlockmore.h"                /* from the xscreensaver distribution */
 #else  /* !STANDALONE */
@@ -79,7 +78,7 @@ ENTRYPOINT ModeSpecOpt gasket_opts = {countof(opts), opts, countof(vars), vars,
 #ifdef USE_MODULES
 ModStruct   gasket_description =
 {"gasket", "init_gasket", "draw_gasket", NULL,
- "draw_gasket", "init_gasket", NULL, &gasket_opts,
+ "draw_gasket", "init_gasket", "free_gasket", &gasket_opts,
  1000, 1, 2, 1, 4, 1.0, "",
  "Shows GL's Sierpinski gasket", 0, NULL};
 
@@ -386,8 +385,15 @@ ENTRYPOINT void
 reshape_gasket(ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport(0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport(0, y, (GLint) width, (GLint) height);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   gluPerspective (30.0, 1/h, 1.0, 100.0);
@@ -467,16 +473,13 @@ gasket_handle_event (ModeInfo *mi, XEvent *event)
 }
 
 
-static void free_gasket(ModeInfo * mi);
-
-
 ENTRYPOINT void
 init_gasket(ModeInfo *mi)
 {
   int           screen = MI_SCREEN(mi);
   gasketstruct *gp;
 
-  MI_INIT (mi, gasket, free_gasket);
+  MI_INIT (mi, gasket);
   gp = &gasket[screen];
 
   gp->window = MI_WINDOW(mi);
index ce61cf0160b82d988178a4550314112a29ad956b..9072f8f9abf0dc4807b7eedecec6987e0b13f71e 100644 (file)
@@ -14,7 +14,7 @@
                        "*showFPS:      False       \n" \
                        "*wireframe:    False       \n" \
 
-# define refresh_tentacles 0
+# define free_tentacles 0
 # define release_tentacles 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -171,8 +171,15 @@ reshape_tentacles (ModeInfo *mi, int width, int height)
 {
   tentacles_configuration *tc = &tcs[MI_SCREEN(mi)];
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -851,7 +858,7 @@ init_tentacles (ModeInfo *mi)
   int wire = MI_IS_WIREFRAME(mi);
   int i;
 
-  MI_INIT (mi, tcs, NULL);
+  MI_INIT (mi, tcs);
 
   tc = &tcs[MI_SCREEN(mi)];
 
index 42bcdc8e7d6cc4ddb3d8afff039dff1535c00f2a..218a62269e1506e05a49697f789345869c0d8b52 100644 (file)
@@ -76,7 +76,6 @@
                        THREAD_DEFAULTS_XLOCK
 
 
-# define refresh_sonar 0
 # define release_sonar 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -785,8 +784,15 @@ reshape_sonar (ModeInfo *mi, int width, int height)
 {
   sonar_configuration *sp = &sps[MI_SCREEN(mi)];
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -817,14 +823,12 @@ sonar_handle_event (ModeInfo *mi, XEvent *event)
   return False;
 }
 
-static void free_sonar (ModeInfo *mi);
-
 ENTRYPOINT void 
 init_sonar (ModeInfo *mi)
 {
   sonar_configuration *sp;
 
-  MI_INIT (mi, sps, free_sonar);
+  MI_INIT (mi, sps);
   sp = &sps[MI_SCREEN(mi)];
   sp->glx_context = init_GL(mi);
 
@@ -1218,7 +1222,7 @@ draw_sonar (ModeInfo *mi)
 # endif /* TEST_ASYNC_NETDB */
 }
 
-static void
+ENTRYPOINT void
 free_sonar (ModeInfo *mi)
 {
 #if 0
index 658b6e456022f12b38d8c6c3eefc6f0ff05b9537..9cefbf3dbb322b196c9cb8d446b1ff85edf38877 100644 (file)
@@ -66,7 +66,7 @@
                 "*suppressRotationAnimation: True\n" \
         "*labelfont:   -*-helvetica-medium-r-normal-*-*-180-*-*-*-*-*-*\n"
 
-# define refresh_spheremonics 0
+# define free_spheremonics 0
 # define release_spheremonics 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -166,8 +166,15 @@ ENTRYPOINT void
 reshape_spheremonics (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -695,7 +702,7 @@ init_spheremonics (ModeInfo *mi)
 {
   spheremonics_configuration *cc;
 
-  MI_INIT (mi, ccs, NULL);
+  MI_INIT (mi, ccs);
 
   cc = &ccs[MI_SCREEN(mi)];
 
index 35a05f929a0da9fdec6ffd6018ecbc6d931b7efa..cf4e762339af1c6e3cf8bdd13b2965ef1ceee2a7 100644 (file)
@@ -26,7 +26,6 @@
                        "*program:      xscreensaver-text\n" \
                        "*usePty:       False\n"
 
-# define refresh_splitflap 0
 # define release_splitflap 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -293,7 +292,6 @@ parse_color (ModeInfo *mi, char *key, GLfloat color[4])
 
 
 static int draw_outer_frame (ModeInfo *mi);
-static void free_splitflap (ModeInfo *mi);
 
 ENTRYPOINT void 
 init_splitflap (ModeInfo *mi)
@@ -301,7 +299,7 @@ init_splitflap (ModeInfo *mi)
   splitflap_configuration *bp;
   int wire = MI_IS_WIREFRAME(mi);
   int i;
-  MI_INIT (mi, bps, free_splitflap);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
   bp->glx_context = init_GL(mi);
@@ -1395,12 +1393,13 @@ draw_splitflap (ModeInfo *mi)
   glXSwapBuffers(dpy, window);
 }
 
-static void
+ENTRYPOINT void
 free_splitflap (ModeInfo *mi)
 {
   splitflap_configuration *bp = &bps[MI_SCREEN(mi)];
   if (bp->tc)
     textclient_close (bp->tc);
+  bp->tc = 0;
   /* #### bp->texinfo */
 }
 
index 1d8f95c43154e6c98b26f21ffc375be4fc0852d9..9e17278dcb8143b716a13557c2b776446e164ec5 100644 (file)
@@ -14,7 +14,6 @@
                        "*wireframe:    False       \n" \
                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_splodesic 0
 # define release_splodesic 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -436,8 +435,15 @@ ENTRYPOINT void
 reshape_splodesic (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -489,15 +495,13 @@ splodesic_handle_event (ModeInfo *mi, XEvent *event)
 }
 
 
-static void free_splodesic (ModeInfo *mi);
-
 ENTRYPOINT void 
 init_splodesic (ModeInfo *mi)
 {
   splodesic_configuration *bp;
   int wire = MI_IS_WIREFRAME(mi);
 
-  MI_INIT (mi, bps, free_splodesic);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
@@ -619,7 +623,7 @@ draw_splodesic (ModeInfo *mi)
 }
 
 
-static void
+ENTRYPOINT void
 free_splodesic (ModeInfo *mi)
 {
   splodesic_configuration *bp = &bps[MI_SCREEN(mi)];
index 41a31a1590ff070af9f4b1af3b31705fa994d25f..1860b11eaf574baef8134920d0b5d306acf44c7c 100644 (file)
@@ -728,14 +728,23 @@ NextSproingieDisplay(sp_instance *si)
 }
 
 void
-ReshapeSproingies(int w, int h)
+ReshapeSproingies(int width, int height)
 {
-       glViewport(0, 0, w, h);
-       glMatrixMode(GL_PROJECTION);
-       glLoadIdentity();
-       gluPerspective(65.0, (GLfloat) w / (GLfloat) h, 0.1, 2000.0);   /* was 200000.0 */
-       glMatrixMode(GL_MODELVIEW);
-       glLoadIdentity();
+  double 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(65.0, 1/h, 0.1, 2000.0);      /* was 200000.0 */
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
 }
 
 void
index 722b725b90995232ad3b5aeb26ec37cf90a6f016..7089f9c1c90ab9a76ef9c8fc196ec6c49cd8a3e9 100644 (file)
@@ -53,7 +53,6 @@ static const char sccsid[] = "@(#)sproingiewrap.c     4.07 97/11/24 xlockmore";
                                        "*fpsTop:       True    \n"                     \
                                        "*wireframe:    False   \n"
 
-# define refresh_sproingies 0
 # define release_sproingies 0
 # define sproingies_handle_event 0
 # include "xlockmore.h"                                /* from the xscreensaver distribution */
@@ -87,7 +86,7 @@ ENTRYPOINT ModeSpecOpt sproingies_opts =
 #ifdef USE_MODULES
 ModStruct   sproingies_description =
 {"sproingies", "init_sproingies", "draw_sproingies", NULL,
- "refresh_sproingies", "init_sproingies", NULL, &sproingies_opts,
+ "refresh_sproingies", "init_sproingies", "free_sproingies", &sproingies_opts,
  1000, 5, 0, 400, 4, 1.0, "",
  "Shows Sproingies!  Nontoxic.  Safe for pets and small children", 0, NULL};
 
@@ -112,9 +111,6 @@ typedef struct {
 static sproingiesstruct *sproingies = NULL;
 
 
-static void free_sproingies (ModeInfo * mi);
-
-
 ENTRYPOINT void
 init_sproingies (ModeInfo * mi)
 {
@@ -127,7 +123,7 @@ init_sproingies (ModeInfo * mi)
        sproingiesstruct *sp;
        int         wfmode = 0, grnd = 0, mspr, w, h;
 
-       MI_INIT (mi, sproingies, free_sproingies);
+       MI_INIT (mi, sproingies);
        sp = &sproingies[screen];
 
        sp->mono = (MI_IS_MONO(mi) ? 1 : 0);
@@ -216,7 +212,7 @@ reshape_sproingies (ModeInfo *mi, int w, int h)
 }
 
 
-static void
+ENTRYPOINT void
 free_sproingies (ModeInfo * mi)
 {
        sproingiesstruct *sp = &sproingies[MI_SCREEN(mi)];
index 2dd78b873d40f28096c46803896756e347051bca..49a1542fc81509a26867916824757714ea846c0d 100644 (file)
@@ -59,7 +59,6 @@ static const char sccsid[] = "@(#)stairs.c    4.07 97/11/24 xlockmore";
 # define DEFAULTS                      "*delay:                20000   \n" \
                                                        "*showFPS:      False   \n"
 
-# define refresh_stairs 0
 # define release_stairs 0
 # include "xlockmore.h"                /* from the xscreensaver distribution */
 #else /* !STANDALONE */
@@ -85,7 +84,7 @@ ENTRYPOINT ModeSpecOpt stairs_opts =
 #ifdef USE_MODULES
 ModStruct   stairs_description =
 {"stairs", "init_stairs", "draw_stairs", NULL,
- "draw_stairs", "change_stairs", NULL, &stairs_opts,
+ "draw_stairs", "change_stairs", "free_stairs", &stairs_opts,
  1000, 1, 1, 1, 4, 1.0, "",
  "Shows Infinite Stairs, an Escher-like scene", 0, NULL};
 
@@ -321,8 +320,14 @@ ENTRYPOINT void
 reshape_stairs (ModeInfo * mi, int width, int height)
 {
        stairsstruct *sp = &stairs[MI_SCREEN(mi)];
+    int y = 0;
 
-       glViewport(0, 0, sp->WindW = (GLint) width, sp->WindH = (GLint) height);
+    if (width > height * 5) {   /* tiny window: show middle */
+      height = width;
+      y = -height/2;
+    }
+
+       glViewport(0, y, sp->WindW = (GLint) width, sp->WindH = (GLint) height);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0);
@@ -432,15 +437,13 @@ pinit(ModeInfo *mi)
        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular);
 }
 
-static void free_stairs (ModeInfo * mi);
-
 ENTRYPOINT void
 init_stairs (ModeInfo * mi)
 {
        int         screen = MI_SCREEN(mi);
        stairsstruct *sp;
 
-       MI_INIT (mi, stairs, free_stairs);
+       MI_INIT (mi, stairs);
        sp = &stairs[screen];
 
        sp->step = 0.0;
@@ -577,7 +580,7 @@ change_stairs (ModeInfo * mi)
 }
 #endif /* !STANDALONE */
 
-static void
+ENTRYPOINT void
 free_stairs (ModeInfo * mi)
 {
        stairsstruct *sp = &stairs[MI_SCREEN(mi)];
index 9ee8cc3f05ed11e00cdb993ae1beeac83c0842d7..d75f014c12a449827561f9683bbdf7ec6e0b3d0f 100644 (file)
@@ -46,9 +46,8 @@
                 "*textLiteral: " DEF_TEXT "\n" \
                 "*program: xscreensaver-text --cols 0"  /* don't wrap */
 
-# define refresh_sws 0
 # define release_sws 0
-# define sws_handle_event 0
+# define sws_handle_event xlockmore_no_events
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
 
@@ -717,9 +716,6 @@ gl_init (ModeInfo *mi)
 }
 
 
-static void free_sws (ModeInfo *mi);
-
-
 ENTRYPOINT void 
 init_sws (ModeInfo *mi)
 {
@@ -727,7 +723,7 @@ init_sws (ModeInfo *mi)
 
   sws_configuration *sc = 0;
 
-  MI_INIT (mi, scs, free_sws);
+  MI_INIT (mi, scs);
 
   sc = &scs[MI_SCREEN(mi)];
 
@@ -1051,7 +1047,7 @@ draw_sws (ModeInfo *mi)
   sc->star_theta += star_spin;
 }
 
-static void
+ENTRYPOINT void
 free_sws (ModeInfo *mi)
 {
   sws_configuration *sc = &scs[MI_SCREEN(mi)];
index 6ce58bb05595c1044967fe5fcef7eb275ccc1966..880ef01b78cc1c9e48a197489ea3e4df621fd3b8 100644 (file)
@@ -24,7 +24,6 @@
                        "*showFPS:      False       \n" \
                        "*wireframe:    False       \n"
 
-# define refresh_stonerview 0
 # define release_stonerview 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -77,16 +76,12 @@ reshape_stonerview (ModeInfo *mi, int width, int height)
 }
 
 
-static void
-free_stonerview (ModeInfo *mi);
-
-
 ENTRYPOINT void 
 init_stonerview (ModeInfo *mi)
 {
   stonerview_configuration *bp;
 
-  MI_INIT (mi, bps, free_stonerview);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
@@ -133,7 +128,7 @@ draw_stonerview (ModeInfo *mi)
   glXSwapBuffers(MI_DISPLAY (mi), MI_WINDOW(mi));
 }
 
-static void
+ENTRYPOINT void
 free_stonerview (ModeInfo *mi)
 {
   stonerview_configuration *bp = &bps[MI_SCREEN(mi)];
index 5ab7ef5109353ba4ac6eab5b389e18079b8f60c2..3c0833543deedcefd181a6f37b100540316a65cb 100644 (file)
@@ -78,6 +78,7 @@ static const char sccsid[] = "@(#)superquadrics.c     4.07 97/11/24 xlockmore";
                                        "*wireframe:    False   \n"                     \
                                        "*suppressRotationAnimation: True\n" \
 
+# define free_superquadrics 0
 # define release_superquadrics 0
 # define superquadrics_handle_event 0
 # include "xlockmore.h"                                /* from the xscreensaver distribution */
@@ -618,7 +619,14 @@ ReshapeSuperquadrics(int w, int h)
                glViewport(0, 0, w, h);
        }
 #else
-    glViewport(0, 0, w, h);
+    int y = 0;
+
+    if (w > h * 5) {   /* tiny window: show middle */
+      h = w;
+      y = -h/2;
+    }
+
+    glViewport(0, y, w, h);
 #endif
 
        glMatrixMode(GL_PROJECTION);
@@ -727,7 +735,7 @@ init_superquadrics(ModeInfo * mi)
 
        superquadricsstruct *sp;
 
-       MI_INIT (mi, superquadrics, NULL);
+       MI_INIT (mi, superquadrics);
        sp = &superquadrics[screen];
        sp->mono = (MI_IS_MONO(mi) ? 1 : 0);
 
@@ -777,11 +785,13 @@ draw_superquadrics(ModeInfo * mi)
        glXSwapBuffers(display, window);
 }
 
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_superquadrics(ModeInfo * mi)
 {
        /* Nothing happens here */
 }
+#endif
 
 ENTRYPOINT void
 reshape_superquadrics(ModeInfo * mi, int width, int height)
index 165264895d15b0838f3771f75a48ff3261d12569..4c7974038f48cd4cda9f0beb0b08ae83cff9ddf9 100644 (file)
@@ -46,7 +46,7 @@
                                     "*showFPS:      False   \n" \
                                   "*suppressRotationAnimation: True\n" \
 
-# define refresh_surface 0
+# define free_surface 0
 # define release_surface 0
 # include "xlockmore.h"     /* from the xscreensaver distribution */
 #else  /* !STANDALONE */
@@ -421,10 +421,17 @@ ENTRYPOINT void reshape_surface(ModeInfo *mi, int width, int height)
 {
   surfacestruct *sp = &surface[MI_SCREEN(mi)];
   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;
+  }
 
   glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(sp->glx_context));
 
-  glViewport(0, 0, (GLint) width, (GLint) height);
+  glViewport(0, y, (GLint) width, (GLint) height);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   gluPerspective (30.0, 1/h, 1.0, 100.0);
@@ -463,7 +470,7 @@ ENTRYPOINT void init_surface(ModeInfo *mi)
   int    screen = MI_SCREEN(mi);
   surfacestruct *sp;
 
-  MI_INIT (mi, surface, NULL);
+  MI_INIT (mi, surface);
   sp = &surface[screen];
 
   sp->window = MI_WINDOW(mi);
index 82a1f4102e18ba143ad50942d39cff97bdde7000..c250f5455ea6d7176d91fdd037c21a870f2a70c2 100644 (file)
@@ -22,7 +22,7 @@
        "*titleFont2: -*-helvetica-medium-r-normal-*-*-120-*-*-*-*-*-*\n" \
        "*titleFont3: -*-helvetica-medium-r-normal-*-*-80-*-*-*-*-*-*\n"  \
 
-# define refresh_tangram 0
+# define free_tangram 0
 # define release_tangram 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -779,7 +779,14 @@ static void draw_shapes(ModeInfo * mi)
 
 ENTRYPOINT void reshape_tangram(ModeInfo * mi, int w, int h)
 {
-    glViewport(0, 0, w, h);
+  int y = 0;
+
+  if (w > h * 5) {   /* tiny window: show middle */
+    h = w;
+    y = -h/2;
+  }
+
+  glViewport(0, y, w, h);
 }
 
 static void set_camera(tangram_configuration *tp)
@@ -877,7 +884,7 @@ ENTRYPOINT void init_tangram(ModeInfo * mi)
 {
     tangram_configuration *tp;
 
-    MI_INIT (mi, tps, NULL);
+    MI_INIT (mi, tps);
 
     tp = &tps[MI_SCREEN(mi)];
 
index 5388efd4f75f94b3d35c28a5cba52fb832433dbd..2128790a78d5cffd0112567a8e5aa2f8b1728947 100644 (file)
@@ -274,7 +274,7 @@ load_texture_font (Display *dpy, char *res)
   if (!res || !*res) abort();
 
   if (!strcmp (res, "fpsFont")) {  /* Kludge. */
-    def1 = "-*-courier-bold-r-normal-*-*-140-*-*-*-*-*-*";
+    def1 = "-*-courier-bold-r-normal-*-*-180-*-*-*-*-*-*"; /* also fps.c */
     cache_size = 0;  /* No need for a cache on FPS: already throttled. */
   }
 
index 1dd5065ddc86f1a5d479defd90fbdca10daf3fc0..106f6a64c588b98a14950530a8545cdf716ff624 100644 (file)
@@ -23,7 +23,7 @@
 
 
 
-# define refresh_tunnel 0
+# define free_tunnel 0
 # define release_tunnel 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -352,8 +352,15 @@ ENTRYPOINT void
 reshape_tunnel (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -1031,7 +1038,7 @@ init_tunnel (ModeInfo *mi)
   wire = 0;
 # endif
 
-  MI_INIT (mi, tconf, NULL);
+  MI_INIT (mi, tconf);
 
   tc = &tconf[MI_SCREEN(mi)];
 
index ddf1eb1cd113c2cb6a5cfcaf7ba2af36c1aa72cc..9161d38d16d6f364c1e38e2a9770b367f5277f82 100644 (file)
@@ -28,7 +28,6 @@ History
 
 #include <math.h>
 
-# define refresh_topBlock 0
 # define release_topBlock 0
 
 #define DEFAULTS       "*delay:        10000       \n" \
@@ -159,7 +158,14 @@ ENTRYPOINT void
 reshape_topBlock (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  int y = 0;
+
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width*1.5;
+    y = -height*0.2;
+    h = height / (GLfloat) width;
+  }
+  glViewport (0, y, (GLint) width, (GLint) height);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   gluPerspective (60.0, 1/h, 1.0, 1000.0);
@@ -169,7 +175,7 @@ reshape_topBlock (ModeInfo *mi, int width, int height)
 }
 
 /* clean up on exit, not required ... */
-static void
+ENTRYPOINT void
 free_topBlock(ModeInfo *mi)
 {
   topBlockSTATE *tb = &tbs[MI_SCREEN(mi)];
@@ -189,7 +195,7 @@ init_topBlock (ModeInfo *mi)
   topBlockSTATE *tb;
   int wire = MI_IS_WIREFRAME(mi);
 
-  MI_INIT (mi, tbs, free_topBlock);
+  MI_INIT (mi, tbs);
 
   tb = &tbs[MI_SCREEN(mi)];
 
index 832d329d1d65cec4f7f2e2fd75df03aa601c7b08..b79309cd85f19d975b0815c128e1ba12cd6f010b 100644 (file)
@@ -14,7 +14,7 @@
                        "*showFPS:      False       \n" \
                        "*wireframe:    False       \n"
 
-# define refresh_bit 0
+# define free_bit 0
 # define release_bit 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -407,7 +407,7 @@ init_bit (ModeInfo *mi)
   bit_configuration *bp;
   int i;
 
-  MI_INIT (mi, bps, NULL);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
@@ -515,6 +515,11 @@ draw_bit (ModeInfo *mi)
     double ratio = 1 - ((bp->last_time + bp->frequency) - now) / bp->frequency;
     if (ratio > 1) ratio = 1;
     mi->polygon_count += draw_histogram (mi, ratio);
+
+    if (MI_WIDTH(mi) > MI_HEIGHT(mi) * 5) {   /* wide window: scale up */
+      glScalef (8, 8, 8);
+    }
+
     mi->polygon_count += animate_bits (mi, omodel, nmodel, ratio);
     tick_bit (mi, now);
   }
index dae95f1bd5b5272c745c7ba3c59ff9cd5b19a8de..52a3cf691b241f4a8483a3f8e96305594e176e69 100644 (file)
@@ -15,7 +15,7 @@
        "*titleFont: -*-helvetica-bold-r-normal-*-*-180-*-*-*-*-*-*\n" \
        "*font:      -*-helvetica-bold-r-normal-*-*-2400-*-*-*-*-iso10646-1\n" \
 
-# define refresh_unicrud 0
+# define free_unicrud 0
 # define release_unicrud 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -702,8 +702,15 @@ ENTRYPOINT void
 reshape_unicrud (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width * 9/16;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
@@ -757,7 +764,7 @@ init_unicrud (ModeInfo *mi)
 {
   unicrud_configuration *bp;
 
-  MI_INIT (mi, bps, NULL);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
index eac67f44ae74c5c6f828fc097b3fc10936eb89ca..98025663cb2c5ef699d3dc582339cd3f7a22b77b 100644 (file)
@@ -41,7 +41,7 @@
                        "*wireframe:    False       \n" \
                        "*geometry:    =800x800"   "\n" \
 
-# define refresh_unk 0
+# define free_unk 0
 # define release_unk 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -92,8 +92,15 @@ reshape_unk (ModeInfo *mi, int width, int height)
 {
   unk_configuration *bp = &bps[MI_SCREEN(mi)];
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, (GLint) width, (GLint) height);
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width*1.5;
+    y = -height/2;
+    h = height / (GLfloat) width;
+  }
+
+  glViewport (0, y, (GLint) width, (GLint) height);
 
   if (bp->orthop)
     {
@@ -175,7 +182,7 @@ init_unk (ModeInfo *mi)
 {
   unk_configuration *bp;
 
-  MI_INIT (mi, bps, NULL);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
@@ -372,7 +379,7 @@ draw_unk (ModeInfo *mi)
     xinc *= 2;
 */
 
-# endif /* USE_MOBILE */
+# endif /* HAVE_MOBILE */
 
 
   /* Make the image fill the screen a little more fully */
index e276bd75bd3dc9ffbff065fe3d4c9d2eeb978eda..c4f590f889b0c0efcb878fa0d2d2d4a6973b93ae 100644 (file)
@@ -22,7 +22,7 @@
                        "*lensColor:    #000000"   "\n" \
                        "*groundColor:  #004400"   "\n" \
 
-# define refresh_camera 0
+# define free_camera 0
 # define release_camera 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -136,7 +136,15 @@ ENTRYPOINT void
 reshape_camera (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
-  glViewport (0, 0, width, height);
+  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 (30.0, 1/h, 1.0, 200);
@@ -216,7 +224,7 @@ init_camera (ModeInfo *mi)
   camera_configuration *bp;
   int wire = MI_IS_WIREFRAME(mi);
   int i;
-  MI_INIT (mi, bps, 0);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
@@ -879,8 +887,10 @@ tick_camera (ModeInfo *mi, camera *c)
             which = i-2;
           else if (i >= 1 && which == 1)
             which = i-1;
-          else if (i < bp->ncameras-1 && which == 2)
+          else if (i < bp->ncameras-2 && which == 2)
             which = i+2;
+          else if (i == bp->ncameras-1)
+            which = i-1;
           else /* (i < bp->ncameras-2 && which == 3) */
             which = i+1;
 
index 3844d95719d69b89969d12d90cdc0f7933f51d04..957dc3cd6fd1ec135e4cf5655ce90004a2bf24ed 100644 (file)
@@ -13,7 +13,7 @@
                         "*showFPS:      False              \n" \
                        "*suppressRotationAnimation: True\n" \
 
-# define refresh_voronoi 0
+# define free_voronoi 0
 # define release_voronoi 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -478,7 +478,7 @@ init_voronoi (ModeInfo *mi)
 {
   voronoi_configuration *vp;
 
-  MI_INIT (mi, vps, NULL);
+  MI_INIT (mi, vps);
 
   vp = &vps[MI_SCREEN(mi)];
 
index c90d07359687098ffe5db5f038213a6667c8b18e..d8b7f649be421bce409b5c5bb1155073579cf1ed 100644 (file)
@@ -68,7 +68,6 @@
 #undef DEBUG
 #define WORDBUBBLES
 
-# define refresh_robot 0
 # define release_robot 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -237,8 +236,15 @@ ENTRYPOINT void
 reshape_robot (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
 
-  glViewport (0, 0, width, height);
+  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();
@@ -344,7 +350,6 @@ load_textures (ModeInfo *mi)
 static int unit_gear (ModeInfo *, GLfloat color[4]);
 static int draw_ground (ModeInfo *, GLfloat color[4]);
 static void init_walker (ModeInfo *, walker *);
-static void free_robot (ModeInfo *mi);
 
 static void
 parse_color (ModeInfo *mi, char *key, GLfloat color[4])
@@ -371,7 +376,7 @@ init_robot (ModeInfo *mi)
   robot_configuration *bp;
   int wire = MI_IS_WIREFRAME(mi);
   int i;
-  MI_INIT (mi, bps, free_robot);
+  MI_INIT (mi, bps);
 
   bp = &bps[MI_SCREEN(mi)];
 
@@ -2469,7 +2474,7 @@ draw_robot (ModeInfo *mi)
   glXSwapBuffers(dpy, window);
 }
 
-static void
+ENTRYPOINT void
 free_robot (ModeInfo *mi)
 {
 # ifdef WORDBUBBLES
index b7b977e59034e74ed5440f0e02035f60a941b3b8..36d724c9e675004f9ffa08d18b7f60953903a3da 100644 (file)
@@ -52,12 +52,16 @@ init_GL(ModeInfo * mi)
   Window window = mi->window;
   Screen *screen = mi->xgwa.screen;
   Visual *visual = mi->xgwa.visual;
-  GLXContext glx_context = 0;
   XVisualInfo vi_in, *vi_out;
   int out_count;
 
+  if (mi->glx_context) {
+    glXMakeCurrent (dpy, window, mi->glx_context);
+    return &mi->glx_context;
+  }
+
 # ifdef HAVE_JWZGLES
-  jwzgles_reset();
+  jwzgles_make_current(jwzgles_make_state(state));
 # endif
 
   vi_in.screen = screen_number (screen);
@@ -69,23 +73,23 @@ init_GL(ModeInfo * mi)
   {
     XSync (dpy, False);
     orig_ehandler = XSetErrorHandler (BadValue_ehandler);
-    glx_context = glXCreateContext (dpy, vi_out, 0, GL_TRUE);
+    mi->glx_context = glXCreateContext (dpy, vi_out, 0, GL_TRUE);
     XSync (dpy, False);
     XSetErrorHandler (orig_ehandler);
     if (got_error)
-      glx_context = 0;
+      mi->glx_context = 0;
   }
 
   XFree((char *) vi_out);
 
-  if (!glx_context)
+  if (!mi->glx_context)
     {
       fprintf(stderr, "%s: couldn't create GL context for visual 0x%x.\n",
              progname, (unsigned int) XVisualIDFromVisual (visual));
       exit(1);
     }
 
-  glXMakeCurrent (dpy, window, glx_context);
+  glXMakeCurrent (dpy, window, mi->glx_context);
 
   {
     GLboolean rgba_mode = 0;
@@ -139,11 +143,7 @@ init_GL(ModeInfo * mi)
   /* GLXContext is already a pointer type.
      Why this function returns a pointer to a pointer, I have no idea...
    */
-  {
-    GLXContext *ptr = (GLXContext *) malloc(sizeof(GLXContext));
-    *ptr = glx_context;
-    return ptr;
-  }
+  return &mi->glx_context;
 }
 
 \f
index 0f5c139e34968bbf89536ffa4b3ed067332b4c65..62b704ecce82af34fa4348a94d3c4494ebff9eba 100644 (file)
@@ -264,6 +264,10 @@ make_layer (Display *dpy, Window window, int width, int height, int nblobs)
   layer->blobs = (struct blob **) malloc(sizeof(*layer->blobs)*layer->nblobs);
 
   blob_max = (width < height ? width : height) / 2;
+
+  if (width < 100 || height < 100) /* tiny window */
+    blob_max *= 10;
+
   blob_min = (blob_max * 2) / 3;
   for (i = 0; i < layer->nblobs; i++){
     int j = blob_max - blob_min;
index c899fa99b0f63dc0155699439054bbdd3a9b5f9a..305b8e81b8bcfe778e76008b5fae68881ce98e5c 100644 (file)
@@ -34,6 +34,7 @@ static const char sccsid[] = "@(#)grav.c      5.00 2000/11/01 xlockmore";
                                        "*ncolors: 64 \n" \
                                        "*fpsSolid: true \n" \
                                        "*ignoreRotation: True \n" \
+                                   "*lowrez: True \n" \
 
 #define BRIGHT_COLORS
 # define release_grav 0
@@ -75,7 +76,7 @@ ENTRYPOINT ModeSpecOpt grav_opts =
 #ifdef USE_MODULES
 ModStruct   grav_description =
 {"grav", "init_grav", "draw_grav", (char *) NULL,
- "refresh_grav", "init_grav", (char *) NULL, &grav_opts,
+ "refresh_grav", "init_grav", "free_grav", &grav_opts,
  10000, -12, 1, 1, 64, 1.0, "",
  "Shows orbiting planets", 0, NULL};
 
@@ -140,9 +141,6 @@ static gravstruct *gravs = (gravstruct *) NULL;
 static void
 init_planet(ModeInfo * mi, planetstruct * planet)
 {
-       Display    *display = MI_DISPLAY(mi);
-       Window      window = MI_WINDOW(mi);
-       GC          gc = MI_GC(mi);
        gravstruct *gp = &gravs[MI_SCREEN(mi)];
 
 # ifdef HAVE_JWXYZ
@@ -171,9 +169,6 @@ init_planet(ModeInfo * mi, planetstruct * planet)
        VEL(X) = FLOATRAND(-VR, VR);
        VEL(Y) = FLOATRAND(-VR, VR);
        VEL(Z) = FLOATRAND(-VR, VR);
-
-       /* Draw planets */
-       Planet(planet->xi, planet->yi);
 }
 
 static void
@@ -236,17 +231,13 @@ draw_planet(ModeInfo * mi, planetstruct * planet)
        Planet(gp->x, gp->y);
 }
 
-static void free_grav(ModeInfo * mi);
-
 ENTRYPOINT void
 init_grav(ModeInfo * mi)
 {
-       Display    *display = MI_DISPLAY(mi);
-       GC          gc = MI_GC(mi);
        unsigned char ball;
        gravstruct *gp;
 
-       MI_INIT (mi, gravs, free_grav);
+       MI_INIT (mi, gravs);
        gp = &gravs[MI_SCREEN(mi)];
 
        gp->width = MI_WIDTH(mi);
@@ -276,11 +267,6 @@ init_grav(ModeInfo * mi)
                gp->starcolor = MI_WHITE_PIXEL(mi);
        for (ball = 0; ball < (unsigned char) gp->nplanets; ball++)
                init_planet(mi, &gp->planets[ball]);
-
-       /* Draw centrepoint */
-       XDrawArc(display, MI_WINDOW(mi), gc,
-                gp->width / 2 - gp->sr / 2, gp->height / 2 - gp->sr / 2, gp->sr, gp->sr,
-                0, 23040);
 }
 
 ENTRYPOINT void
@@ -298,6 +284,20 @@ draw_grav(ModeInfo * mi)
        if (gp->planets == NULL)
                return;
 
+       if (!MI_IS_DRAWN(mi)) {
+               for (ball = 0; ball < (unsigned char) gp->nplanets; ball++) {
+                       planetstruct *planet = &gp->planets[ball];
+
+                       /* Draw planets */
+                       Planet(planet->xi, planet->yi);
+               }
+
+               /* Draw centrepoint */
+               XDrawArc(display, MI_WINDOW(mi), gc,
+                        gp->width / 2 - gp->sr / 2, gp->height / 2 - gp->sr / 2, gp->sr, gp->sr,
+                        0, 23040);
+       }
+
        MI_IS_DRAWN(mi) = True;
        /* Mask centrepoint */
        XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
@@ -335,7 +335,7 @@ reshape_grav(ModeInfo * mi, int width, int height)
     XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi));
 }
 
-static void
+ENTRYPOINT void
 free_grav(ModeInfo * mi)
 {
        gravstruct *gp = &gravs[MI_SCREEN(mi)];
@@ -343,11 +343,13 @@ free_grav(ModeInfo * mi)
                (void) free((void *) gp->planets);
 }
 
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_grav(ModeInfo * mi)
 {
        MI_CLEARWINDOW(mi);
 }
+#endif
 
 XSCREENSAVER_MODULE ("Grav", grav)
 
index f0093a3952e212fe8f49369fe5093949ee212989..d3cc7df0cbdc5461f9e20ec0ddd263d21295c2c0 100644 (file)
@@ -62,8 +62,8 @@ static const char sccsid[] = "@(#)hop.c       5.00 2000/11/01 xlockmore";
 # define SMOOTH_COLORS
 # define reshape_hop 0
 # define release_hop 0
+# define hop_handle_event 0
 # include "xlockmore.h"                /* in xscreensaver distribution */
-# include "erase.h"
 #else /* STANDALONE */
 # include "xlock.h"            /* in xlockmore distribution */
 #endif /* STANDALONE */
@@ -154,7 +154,7 @@ ENTRYPOINT ModeSpecOpt hop_opts =
 #ifdef USE_MODULES
 ModStruct   hop_description =
 {"hop", "init_hop", "draw_hop", (char *) NULL,
- "refresh_hop", "init_hop", (char *) NULL, &hop_opts,
+ "refresh_hop", "init_hop", "free_hop", &hop_opts,
  10000, 1000, 2500, 1, 64, 1.0, "",
  "Shows real plane iterated fractals", 0, NULL};
 
@@ -187,15 +187,10 @@ typedef struct {
        int         count;
        int         bufsize;
        XPoint     *pointBuffer;        /* pointer for XDrawPoints */
-#ifdef STANDALONE
-  eraser_state *eraser;
-#endif
 } hopstruct;
 
 static hopstruct *hops = (hopstruct *) NULL;
 
-static void free_hop(ModeInfo * mi);
-
 ENTRYPOINT void
 init_hop(ModeInfo * mi)
 {
@@ -204,7 +199,7 @@ init_hop(ModeInfo * mi)
        double      range;
        hopstruct  *hp;
 
-       MI_INIT (mi, hops, free_hop);
+       MI_INIT (mi, hops);
        hp = &hops[MI_SCREEN(mi)];
 
        hp->centerx = MI_WIDTH(mi) / 2;
@@ -387,9 +382,7 @@ init_hop(ModeInfo * mi)
                        return;
        }
 
-#ifndef STANDALONE
        MI_CLEARWINDOW(mi);
-#endif
 
        XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
        hp->count = 0;
@@ -408,15 +401,6 @@ draw_hop(ModeInfo * mi)
                return;
        hp = &hops[MI_SCREEN(mi)];
 
-#ifdef STANDALONE
-    if (hp->eraser) {
-      hp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), hp->eraser);
-      if (!hp->eraser)
-        init_hop(mi);
-      return;
-    }
-#endif
-
 
        if (hp->pointBuffer == NULL)
                return;
@@ -545,15 +529,11 @@ draw_hop(ModeInfo * mi)
        XDrawPoints(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi),
                    hp->pointBuffer, hp->bufsize, CoordModeOrigin);
        if (++hp->count > MI_CYCLES(mi)) {
-#ifdef STANDALONE
-      hp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), hp->eraser);
-#else /* !STANDALONE */
                init_hop(mi);
-#endif
        }
 }
 
-static void
+ENTRYPOINT void
 free_hop(ModeInfo * mi)
 {
        hopstruct  *hp = &hops[MI_SCREEN(mi)];
@@ -562,25 +542,13 @@ free_hop(ModeInfo * mi)
                (void) free((void *) hp->pointBuffer);
 }
 
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_hop(ModeInfo * mi)
 {
        MI_CLEARWINDOW(mi);
 }
-
-ENTRYPOINT Bool
-hop_handle_event (ModeInfo *mi, XEvent *event)
-{
-  if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
-    {
-      MI_CLEARWINDOW(mi);
-      init_hop (mi);
-      return True;
-    }
-  return False;
-}
-
-
+#endif
 
 XSCREENSAVER_MODULE_2 ("Hopalong", hopalong, hop)
 
index 9adbdf2f2c54b7fa74ba87b30ff7d23189fec6c3..ad8af952139d2704a5ae5e3130ea9ad2df2c5a30 100644 (file)
@@ -90,6 +90,7 @@ myrandom(float up)
 }
 
 static const char *ifs_defaults [] = {
+  ".lowrez:             true",
   ".background:                Black",
   "*lensnum:           3",
   "*fpsSolid:          true",
index 9dfd7dde6e901b384970565e04dde06f72a7cf83..9a0ae6bbc1712d8abeab6e648e7ecda02833ae98 100644 (file)
@@ -1,11 +1,33 @@
-; By DMSC - daniel.serpell@gmail.com
 ;
-; This demo was programmed in ACME:
-;     http://www.esw-heim.tu-clausthal.de/~marco/smorbrod/acme/
+; 6502 Assembler Demo.
+; Copyright (C) 2007  Daniel Serpell <daniel.serpell@gmail.com>
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are met:
+;
+; 1. Redistributions of source code must retain the above copyright notice,
+; this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright notice,
+; this list of conditions and the following disclaimer in the documentation
+; and/or other materials provided with the distribution.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+; ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+; POSSIBILITY OF SUCH DAMAGE.
+;
+; By DMSC - daniel.serpell@gmail.com
 ;
-; If you want the source code, send me an email :-)
+; See xscreensaver/hacks/images/m6502/dsmc.txt for the source
 ;
-
  dcb  76, 94, 11,133, 32,162,  8,160,  8,145, 16,136,208,251,165, 16
  dcb  24,105, 32,133, 16,165, 17,105,  0,133, 17,165, 32,202,208,231
  dcb  96,230, 48,165, 48, 41, 63,133, 48,170,189,106,  6,170,189,  8
diff --git a/hacks/images/m6502/dmsc.txt b/hacks/images/m6502/dmsc.txt
new file mode 100644 (file)
index 0000000..7e19f6b
--- /dev/null
@@ -0,0 +1,768 @@
+;
+; 6502 Assembler Demo.
+; Copyright (C) 2007  Daniel Serpell <daniel.serpell@gmail.com>
+;
+; Redistribution and use in source and binary forms, with or without
+; modification, are permitted provided that the following conditions are met:
+;
+; 1. Redistributions of source code must retain the above copyright notice,
+; this list of conditions and the following disclaimer.
+;
+; 2. Redistributions in binary form must reproduce the above copyright notice,
+; this list of conditions and the following disclaimer in the documentation
+; and/or other materials provided with the distribution.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+; ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+; POSSIBILITY OF SUCH DAMAGE.
+;
+
+; Variable definitions
+    temp0 = $20
+    temp1 = $21
+    temp2 = $22
+    temp3 = $23
+    temp4 = $24
+    temp5 = $25
+    
+    param0 = $10
+    param1 = $11
+    param2 = $12
+    param3 = $13
+
+
+; Output file
+    !to "all.bin", plain
+
+; Start of code
+    *= $600
+    jmp main
+
+; Used in "gira" and "circ"
+
+    gira_pos = $30
+    gira_scr = $200
+    circ_pos = $30
+    circ_scr = $210
+    show_pos = $31
+    show_source = $a000
+    show_dest = $500
+    text_state = $40
+    text_scr = $a000
+;    text_scr = $480
+    moire_buf = $a000
+    moire_scr = $200
+    moire_temp = $20
+
+; Include routines and macros
+
+: ===========================================================================
+:    !source "fillRect.asm"
+: ===========================================================================
+
+    !zone {
+    
+; Uses the following:
+;  params: param0, param1
+;  temps: temp0
+
+
+; Locals
+    .color = temp0
+
+; Params
+    fillRect_buffer = param0
+    .buf = fillRect_buffer
+
+; fillRect:
+;   Fill a rectangle of 8x8 pixels with a color.
+; input: A  = color index
+;        .buffer = output buffer (address)
+    !macro fillRect .buffer {
+        ldx  #<.buffer
+        stx  fillRect_buffer
+        ldx  #>.buffer
+        stx  fillRect_buffer+1
+        jsr  fillRect_code
+    }
+
+; fillRect:
+;   Fill a rectangle of 8x8 pixels with a color.
+; input: .color  = color index
+;        .buffer = output buffer (address)    
+    !macro fillRect .buffer, .color {
+        lda  #.color
+        +fillRect .buffer
+    }
+    
+fillRect_code:
+       sta     .color
+       ldx     #8
+--
+       ldy     #8
+-
+       sta     (.buf),y
+       dey
+       bne     -
+
+       lda     .buf
+       clc
+       adc     #32
+       sta     .buf
+    lda .buf+1
+    adc #0
+    sta .buf+1
+       lda     .color
+       dex
+       bne     --
+
+       rts
+
+}
+
+
+: ===========================================================================
+:    !source "gira.asm"
+: ===========================================================================
+
+    !zone {
+
+;
+; define "gira_pos" and "gira_scr" before including
+;
+    .pos = gira_pos
+    .scr00 = gira_scr
+    .scr01 = gira_scr + $8
+    .scr10 = gira_scr + $100
+    .scr11 = gira_scr + $108
+
+; gira:
+    !macro gira {
+        jsr  gira_code
+    }
+
+; init code:
+    !macro giraInit {
+        +fillRect gira_scr-1, 1
+        +fillRect gira_scr+7, 2
+        +fillRect gira_scr+$107, 3
+    }
+
+gira_code:
+
+    inc  .pos
+    lda  .pos
+    and  #63
+    sta  .pos
+    tax
+
+    lda  .tabla,x
+    tax
+    lda  .scr11,x
+    adc  #1
+    and  #3
+    sta  .scr11,x    
+    txa
+    eor  #$E7
+    tax
+    lda  .scr00,x
+    adc  #1
+    and  #3
+    sta  .scr00,x
+
+    lda  .pos
+    eor #63
+    tax
+    lda  .tabla,x
+    eor  #$E0
+    tax
+    lda  .scr01,x
+    adc  #1
+    and  #3
+    sta  .scr01,x
+
+    txa
+    eor  #$E7
+    tax
+    lda  .scr10,x
+    adc  #1
+    and  #3
+    sta  .scr10,x
+
+    rts
+
+.tabla
+    !byte 224, 192, 160, 128,  96, 225,  64, 193, 161, 226, 129,  32, 194,  97, 162, 227
+    !byte 195, 130, 228,  65, 163, 196,  98, 229, 131, 164, 197, 230, 231, 132, 165, 198
+    !byte  99,  66,  33,   0, 199, 166, 133, 100, 167,  67, 134, 101, 135,  34,  68, 102
+    !byte 103,  69,  35,  70,  71,  36,   1,  37,  38,  39,   2,   3,   4,   5,   6,   7
+
+}
+
+: ===========================================================================
+:    !source "circ.asm"
+: ===========================================================================
+
+    !zone {
+;
+; define "circ_pos" before including
+;
+
+    .pos = circ_pos
+    .scr00 = circ_scr
+    .scr01 = circ_scr + $8
+    .scr10 = circ_scr + $100
+    .scr11 = circ_scr + $108
+
+; circ:
+    !macro circ {
+        jsr  circ_code
+    }
+
+circ_code:
+
+       ldx     .pos
+    lda .tabla,x
+    tax
+       inc     .scr11,x
+    eor #07
+    tax
+       inc     .scr10,x
+    eor #$e7
+    tax
+       inc     .scr01,x
+    eor #07
+    tax
+       inc     .scr00,x
+
+    rts
+
+.tabla
+       !byte   0,  32,   1,  33,  64,   2,  65,  34,  96,  66,   3,  97,  35,  98,  67, 128
+       !byte   4, 129,  36,  99, 130,  68, 160,   5, 161, 131, 100,  37, 162,  69, 132, 192
+       !byte 163, 101,   6, 193,  38, 194,  70, 164, 133, 195, 102, 224,   7, 225,  39, 165
+       !byte 226, 196, 134,  71, 227, 103, 197, 166, 228, 135, 198, 229, 167, 230, 199, 231
+
+}
+
+
+: ===========================================================================
+    !source "mapcopy.asm"
+: ===========================================================================
+
+    !zone {
+
+;
+; define "show_pos" and "show_scr" before including
+;
+    .pos = show_pos
+    .source = show_source
+    .dest = show_dest
+
+; show:
+    !macro show {
+        jsr  show_code
+    }
+
+show_code
+    ldx .pos
+    lda .tabla,x
+    tax
+.source_label
+    lda .source,x
+.dest_label
+    sta .dest,x
+    inc .pos
+    rts
+
+    show_source_addr = .source_label + 1
+    show_dest_addr = .dest_label + 1
+
+.tabla
+    !byte 195, 227, 194, 162, 228,  97, 226, 128, 129, 130, 225,  64, 161, 163, 224,  96
+    !byte 160, 193, 196,  32,  98, 192,  65,   0, 131, 229, 164,  33,  99, 197,  66, 132
+    !byte   1, 230,  34, 165,  67, 100, 198,   2,   3,  68,   6,  35, 133, 166,   5, 101
+    !byte   4, 199,   7,  36, 231,  69, 134, 167,  37,  38, 102, 135,  70, 232,  71,  39
+    !byte 103, 136, 200, 168,   8,  11,  10, 169, 233, 104,   9,  12, 137, 201,  13,  40
+    !byte  44,  72,  43, 170,  42,  45,  41, 105,  73, 202,  14, 138, 234,  74,  75, 106
+    !byte 203,  76, 171,  46,  77, 235, 107, 139,  15, 108, 172, 174, 140, 173, 141, 142
+    !byte 204, 109, 206, 207, 205,  78, 175,  47, 236, 239, 143, 237, 238, 110, 240, 241
+    !byte 111, 208,  16,  79, 176, 209, 242,  48, 144, 243,  80, 177, 244, 112, 210,  17
+    !byte  49, 178, 179,  52,  53, 147,  18,  81, 211, 145,  19, 146,  51,  85, 180,  20
+    !byte  54, 113, 148,  22,  50,  84, 212,  21,  55, 115, 245,  83, 114, 116,  23,  82
+    !byte  86,  88,  89,  87, 118, 117, 119, 149, 213,  56,  57, 181, 214,  90, 121, 122
+    !byte 150, 151, 182, 183, 215, 246,  58, 120, 247,  24, 153, 184, 152, 216,  25,  26
+    !byte  59,  91, 248, 123, 185,  27,  60, 217, 154,  28,  92, 249,  29, 155, 186,  61
+    !byte 218,  93, 124, 250, 187,  30, 251,  62, 156,  94, 125, 219, 188,  31, 252, 254
+    !byte 220, 253,  63, 126, 255, 157, 221,  95, 159, 191, 222, 127, 189, 223, 158, 190
+
+}
+
+
+: ===========================================================================
+    !source "text.asm"
+: ===========================================================================
+
+    !zone {
+
+;
+; define:
+;  "text_state": 8 bytes of internal state
+;  "text_scr"  : output screen address
+;  "text_data" : text character data
+;
+    text_char  = text_state + 0
+    .fps = text_state + 1
+    text_pixel = text_state + 2
+    text_skip  = text_state + 3
+    .cb  = text_state + 4
+    .fsz = text_state + 5
+    text_endFlag = text_state + 6
+    .scr = text_scr
+    .data = text_data    
+    
+    ; abbreviations
+    .pos = text_char
+    .cxy = text_pixel
+    .skp = text_skip
+
+; "pos" pointer to the next character
+; "cxy" screen position
+; "fps" position in font data of current character
+; "fsz" remaining bytes of current character
+; "skp" skip data, used in spaces, begining and ending
+; "cb"  current output byte (8 bits, one column)
+
+; text:
+    !macro text {
+        jsr  text_code
+    }
+
+    !macro textInit1 {
+        lda #$1f
+        sta text_pixel
+        lda #0
+        sta text_endFlag
+        sta text_skip
+        sta text_char
+        lda #1
+        sta text_base_color
+        lda #<text_scr
+        sta text_dest_addr
+        lda #>text_scr
+        sta text_dest_addr+1
+    }
+
+    !macro textInit2 .scrOut {
+        lda #$1f
+        sta text_pixel
+        lda #0
+        sta text_endFlag
+        sta text_skip
+        sta text_base_color
+        lda #<.scrOut
+        sta text_dest_addr
+        lda #>.scrOut
+        sta text_dest_addr+1
+    }
+
+
+text_code
+
+    lda .cxy
+    and #$e0
+    bne .putpixel     ; If we have more pixels, put them
+
+    ; To next x coord
+    lda .cxy
+    clc
+    adc #1
+    and #$1f
+    sta .cxy
+
+    ; If we are in "skip" mode, skip :-)
+    lda .skp
+    beq .noskip
+
+.doSkip
+    ; skip this step (filling with blanks)
+    dec .skp
+    
+.storeColumn0
+    lda #0
+    jmp .storeColumn
+    
+.noskip
+    ; Continue font data
+    dec .fsz
+
+    ; Skip just one column if just at the end of character
+    beq .storeColumn0
+    
+    bpl .nextcolumn ; More columns
+    
+    ; Get next character
+    ldx .pos
+    inc .pos
+    lda .data, x
+    bpl .fontdata
+    
+    ; A > 128, skip "A-128" characters
+    and #$7F
+    sta .skp
+    
+    ; If skip == 127 (value=255), signal the end of text data
+    eor #$7F
+    bne .storeColumn0
+    
+    lda #1
+    sta text_endFlag
+    jmp .storeColumn0
+    
+.fontdata
+    tax
+       lda .font_size,x
+       sta .fsz
+       dec .fsz
+
+       lda .font_pos,x
+       sta .fps
+    
+.nextcolumn
+    ldx .fps
+    inc .fps
+    lda .font_data, x
+
+.storeColumn
+    sta .cb
+    ; skip over to putpixel
+
+.putpixel
+    lda .cxy
+    clc
+    adc #$e0
+       sta .cxy
+    ldx .cxy
+.base_color
+       lda #1
+       ror .cb
+       rol
+.dest_label
+       sta .scr,x
+       rts
+
+    text_base_color = .base_color + 1
+    text_dest_addr  = .dest_label + 1
+    
+; font
+.font_size:
+       !byte 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 2, 3, 3, 3, 3, 3, 1, 2, 3, 1
+       !byte 5, 3, 3, 3, 3, 3, 2, 2, 3, 3, 5, 4, 3, 3, 5, 4, 4, 4, 3, 3, 4, 4
+       !byte 1, 3, 4, 3, 5, 5, 5, 4, 5, 4, 4, 3, 4, 4, 7, 4, 4, 4, 2, 1
+.font_pos:
+       !byte   0,   3,   6,   9,  12,  15,  18,  21,  24,  27,  30,  32,  35
+       !byte  35,  38,  40,  43,  46,  49,  50,  52,   4,  55,  55,  60,  63
+       !byte  65,  68,  71,  73,  75,  78,  78,  33,  83,  86,  89,  94,  98
+       !byte 102, 106, 109, 112, 116,  94, 120, 123, 127, 130, 134, 139, 144
+       !byte 148, 153, 157, 161, 164, 167, 171, 178, 171, 182, 186,   5
+.font_data:
+       !byte  56, 68, 56, 36,124,  4, 76, 84, 36, 68, 84, 40, 24, 40,124,100
+       !byte  84, 88, 56, 84, 72, 76, 80, 96, 40, 84, 40, 36, 84, 56, 44, 28
+       !byte 124, 36, 24, 24, 36,124, 24, 52, 16, 60, 80, 24, 37, 30,124, 32
+       !byte  28,188,  1,190,124, 24, 36, 60, 32, 28, 32, 28, 24, 36, 24, 63
+       !byte  36, 24, 36, 63, 60, 16, 32, 52, 44,120, 36, 56,  4, 60, 56,  4
+       !byte  56,  4, 56, 57,  6, 56, 44, 52, 36, 12, 48,208, 48, 12,252,164
+       !byte 164, 88,120,132,132, 72,252,132,132,120,252,164,132,252,160,128
+       !byte 120,132,164, 56,252, 32, 32,252,  8,  4,248,252, 48, 80,140,252
+       !byte   4, 4, 252, 64, 60, 64,252, 64, 48,  8,252,120,132,132,132,120
+       !byte 252,144,144, 96,120,132,134,133,120,252,144,144,108, 68,164,164
+       !byte 152,128,252,128,248,  4,  4,248,  4,  8,240,224, 28, 16,224, 28
+       !byte  16,224,204, 48, 48,204,140,148,164,196,  0,  0
+
+
+text_data
+    !byte (128+5), 41, 10, 28, 29, 63, 63, 63
+    !byte (128+8), 15, 10, 28, 29, 14, 27, 63, 63, 63
+    !byte (128+4), 55, 17, 18, 28, 62, 18, 28, 62, 10
+    !byte (128+8), 27, 14, 10, 21, 21, 34
+    !byte (128+15), 15, 10, 28, 29
+    !byte (128+14), 39, 40, 48, 50
+    !byte (128+21)
+    !byte (128+17), 10, 23, 13, 62, 23, 24, 32
+    !byte (128+8), 28, 24, 22, 14
+    !byte (128+8), 11, 14, 10, 30, 29, 18, 15, 30, 21
+    !byte (128+0), 14, 15, 15, 14, 12, 29, 28, 63, 63, 63
+    !byte (128+16)
+    !byte (128+31)
+    !byte 255
+    !byte       55, 17, 18, 28, 62, 18, 28, 62, 10, 21, 21
+    !byte (128+1), 15, 24, 27, 62, 23, 24, 32
+    !byte (128+8), 11, 34, 14, 63, 63, 63
+    !byte (128+13), 63, 63, 63, 11, 34, 14
+    !byte (128+22)
+    !byte (128+31)
+    !byte (128+15), 11, 34, 62, 39, 48, 54, 38
+    !byte       2, 0, 0, 7, 63, 5, 63, 2, 9
+    !byte       11, 34, 62, 39, 48, 54, 38
+    !byte       2, 0, 0, 7, 63, 5, 63, 2, 9
+    !byte       11, 34, 62, 39, 48, 54, 38
+    !byte       2, 0, 0, 7, 63, 5, 63, 2, 9
+    !byte (128+15)
+    !byte (128+31)
+    !byte 255
+
+}
+
+
+: ===========================================================================
+    !source "moireSmooth.asm"
+: ===========================================================================
+
+    !zone {
+
+; Parameters (consts)
+    .scr = moire_scr
+    .buf = moire_buf
+; Variables
+    .p1 = moire_temp
+    .o1 = moire_temp + 2
+    .o2 = moire_temp + 4
+    .o3 = moire_temp + 6
+    .o4 = moire_temp + 8
+    .iter = moire_temp + 10
+    .valStartX = moire_temp + 11
+    .deltaX = moire_temp + 12
+    .deltaY = moire_temp + 13
+    .yPos = moire_temp + 14
+    
+; moire!:
+    !macro moire {
+        jsr  moire_code
+    }
+
+    !macro add16 .var, .value {
+        lda .var
+        clc
+        adc #<.value
+        sta .var
+        lda .var+1
+        adc #>.value
+        sta .var+1
+    }
+    
+    !macro sto16 .var, .value {
+        lda #<.value
+        sta .var
+        lda #>.value
+        sta .var+1
+    }
+
+moire_code:
+    
+    lda #0
+    sta .iter
+
+.loop:
+
+    lda #1
+    sta .deltaX
+    sta .deltaY
+
+    +sto16 .p1, .buf
+
+    lda .iter
+    sta .valStartX
+
+    ldx #15
+--
+    ldy #15
+-
+    sta (.p1),y
+    clc
+    adc .deltaX
+    inc .deltaX
+    dey
+    bpl -
+
+    +add16 .p1, $0020
+
+    lda #1
+    sta .deltaX
+    
+    lda .valStartX
+    clc
+    adc .deltaY
+    sta .valStartX
+    inc .deltaY
+
+    dex
+    bpl --
+    
+
+; update screen
+    +sto16 .p1, .buf
+    +sto16 .o1, .scr + $01E0
+    +sto16 .o2, .scr + $0200
+    +sto16 .o3, .scr + $01F0
+    +sto16 .o4, .scr + $0210
+
+    lda #15
+    sta .yPos
+--
+    ldy #15
+-
+    lda (.p1),y
+    lsr
+    lsr
+    lsr
+    lsr
+    tax
+    lda .tabCol,x
+
+    cmp (.o1),y
+    beq .noCopy
+    sta (.o1),y
+    sta (.o2),y
+    tax
+    tya
+    eor #15
+    tay
+    txa
+    sta (.o3),y
+    sta (.o4),y
+    tya
+    eor #15
+    tay
+.noCopy:
+    dey
+    bpl -
+
+    +add16 .p1, $0020
+    +add16 .o1, $FFE0
+    +add16 .o2, $0020
+    +add16 .o3, $FFE0
+    +add16 .o4, $0020
+
+    dec .yPos
+    bpl --
+
+    inc .iter
+    lda .iter
+    and #$3f
+    beq +
+    jmp .loop
++
+    rts
+
+.tabCol
+    !byte 0,11,12,15,1,15,12,11
+    !byte 0,11,12,15,1,15,12,11
+    !byte 0,11,12,15,1,15,12,11
+    !byte 0,11,12,15,1,15,12,11
+
+}
+
+: ===========================================================================
+
+
+; Main loop
+
+main
+    
+    +giraInit
+    +textInit1
+    lda #63
+    sta gira_pos
+    
+    ; Start show-pos from middle of screen
+    lda #128
+    sta show_pos
+    
+    ; First color is 3
+    lda #3
+    sta text_base_color
+
+    ; Clear old text image
+    lda #0
+    tax
+-
+    sta text_scr,x
+    inx
+    bne -
+    
+loop
+    +gira
+    +circ
+    +show
+    +text
+    
+    lda text_pixel
+    eor #$1f
+    bne notChangeTextColor
+    lda text_base_color
+    clc
+    adc #2
+    and #3
+    adc #3
+    sta text_base_color
+    
+notChangeTextColor
+
+    lda show_pos
+    bne loop
+    
+    lda show_dest_addr+1
+    eor #1
+    sta show_dest_addr+1
+
+    lda text_endFlag
+    beq loop
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; End of first text, do moire!
+    jsr clearScr
+    +moire
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; End of moire, do ending text
+    +textInit2 $300
+    jsr clearScr
+    
+; loop text output
+-
+    +text
+
+    lda text_pixel
+    eor #$1f
+    bne -
+    lda text_dest_addr+1
+    eor #7
+    sta text_dest_addr+1
+
+    lda text_endFlag
+    beq -
+
+    jmp main
+
+clearScr    
+    ; Clear screen
+    lda #0
+    tax
+-
+    sta $200,x
+    sta $300,x
+    sta $400,x
+    sta $500,x
+    inx
+    bne -
+    rts
+
diff --git a/hacks/images/m6502/texture.asm b/hacks/images/m6502/texture.asm
new file mode 100644 (file)
index 0000000..b63d0a2
--- /dev/null
@@ -0,0 +1,393 @@
+; -*- mode: c; tab-width: 4; fill-column: 128 -*-
+; vi: set ts=4 tw=128:
+
+; Texture, Copyright (c) 2017 Dave Odell <dmo2118@gmail.com>
+;
+; 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.
+
+; A port of 20 year old QBasic code to a much more modern platform.
+
+
+
+
+
+       lda $fe
+       sta src_row
+
+       ldy #0
+top_loop:
+       lda $fe
+       and #$f
+       sbc #$8
+       adc src_row,y
+       iny
+       sta src_row,y
+       cpy #31
+       bne top_loop
+
+lda #$00
+sta $0
+lda #$02
+sta $1
+
+init_loop:
+       jsr tex
+       clc
+       lda $0
+       adc #$20
+       sta $0
+       lda $1
+       adc #0
+       sta $1
+       cmp #$06
+       bne init_loop
+
+lda #$e0
+sta $0
+lda #$05
+sta $1
+
+loop:
+       ;jmp skip_blit
+
+       clc
+       lda #0
+       blit_loop2:
+               tay
+               lda $0220,y
+               sta $0200,y
+               lda $0221,y
+               sta $0201,y
+               lda $0222,y
+               sta $0202,y
+               lda $0223,y
+               sta $0203,y
+               lda $0224,y
+               sta $0204,y
+               lda $0225,y
+               sta $0205,y
+               lda $0226,y
+               sta $0206,y
+               lda $0227,y
+               sta $0207,y
+
+               tya
+               adc #8
+       bne blit_loop2
+
+       clc
+       lda #0
+       blit_loop3:
+               tay
+               lda $0320,y
+               sta $0300,y
+               lda $0321,y
+               sta $0301,y
+               lda $0322,y
+               sta $0302,y
+               lda $0323,y
+               sta $0303,y
+               lda $0324,y
+               sta $0304,y
+               lda $0325,y
+               sta $0305,y
+               lda $0326,y
+               sta $0306,y
+               lda $0327,y
+               sta $0307,y
+
+               tya
+               adc #8
+       bne blit_loop3
+
+       clc
+       lda #0
+       blit_loop4:
+               tay
+               lda $0420,y
+               sta $0400,y
+               lda $0421,y
+               sta $0401,y
+               lda $0422,y
+               sta $0402,y
+               lda $0423,y
+               sta $0403,y
+               lda $0424,y
+               sta $0404,y
+               lda $0425,y
+               sta $0405,y
+               lda $0426,y
+               sta $0406,y
+               lda $0427,y
+               sta $0407,y
+
+               tya
+               adc #8
+       bne blit_loop4
+
+       lda #0
+       blit_loop5:
+               tay
+               lda $0520,y
+               sta $0500,y
+               lda $0521,y
+               sta $0501,y
+               lda $0522,y
+               sta $0502,y
+               lda $0523,y
+               sta $0503,y
+               lda $0524,y
+               sta $0504,y
+               lda $0525,y
+               sta $0505,y
+               lda $0526,y
+               sta $0506,y
+               lda $0527,y
+               sta $0507,y
+
+               tya
+               clc
+               adc #8
+               cmp #$e0
+       bne blit_loop5
+
+       skip_blit:
+
+       jsr tex
+jmp loop
+
+tex:
+       lda $fe
+       and #$f
+       sbc #$8
+       adc src_row
+       sta src_row
+
+       ldy #0
+       tax
+       lda pal0,x
+       sta ($0),y
+       tex_loop0:
+               lda $fe
+               and #$f
+               sbc #$8
+               ;clc
+               adc src_row,y
+               iny
+               ;clc
+               adc src_row,y
+               ror
+               sta src_row,y
+
+               tax
+               lda pal0,x
+               sta ($0),y
+
+               cpy #31
+       bne tex_loop0
+       rts
+
+pal0:
+       dcb $00, $00, $00, $00, $00, $00, $00, $00
+       dcb $00, $00, $0b, $0b, $0b, $0b, $0b, $0b
+       dcb $0b, $0b, $0b, $0b, $0b, $0b, $0b, $0b
+       dcb $0c, $0c, $0c, $0c, $0c, $0c, $0c, $0c
+       dcb $0c, $0c, $0c, $0c, $0c, $0c, $0c, $0c
+       dcb $0f, $0f, $0f, $0f, $0f, $0f, $0f, $0f
+       dcb $0f, $0f, $0f, $0f, $0f, $0f, $0f, $0f
+       dcb $0f, $01, $01, $01, $01, $01, $01, $01
+       dcb $01, $01, $01, $01, $01, $01, $01, $01
+       dcb $0f, $0f, $0f, $0f, $0f, $0f, $0f, $0f
+       dcb $0f, $0f, $0f, $0f, $0f, $0f, $0f, $0f
+       dcb $0f, $0c, $0c, $0c, $0c, $0c, $0c, $0c
+       dcb $0c, $0c, $0c, $0c, $0c, $0c, $0c, $0c
+       dcb $0c, $0b, $0b, $0b, $0b, $0b, $0b, $0b
+       dcb $0b, $0b, $0b, $0b, $0b, $0b, $0b, $00
+       dcb $00, $00, $00, $00, $00, $00, $00, $00
+       dcb $00, $00, $00, $00, $00, $00, $00, $00
+       dcb $00, $00, $00, $00, $00, $00, $00, $00
+       dcb $0b, $0b, $0b, $0b, $0b, $0b, $0b, $0b
+       dcb $0b, $0b, $0b, $0b, $0b, $0b, $0b, $0b
+       dcb $0b, $0b, $0b, $0b, $0b, $0b, $05, $05
+       dcb $05, $05, $05, $05, $05, $05, $05, $05
+       dcb $05, $05, $05, $05, $05, $05, $05, $05
+       dcb $0d, $0d, $0d, $0d, $0d, $0d, $0d, $0d
+       dcb $0d, $0d, $0d, $0d, $0d, $0d, $0d, $0d
+       dcb $0d, $05, $05, $05, $05, $05, $05, $05
+       dcb $05, $05, $05, $05, $05, $05, $05, $05
+       dcb $05, $05, $05, $0b, $0b, $0b, $0b, $0b
+       dcb $0b, $0b, $0b, $0b, $0b, $0b, $0b, $0b
+       dcb $0b, $0b, $0b, $0b, $0b, $0b, $0b, $0b
+       dcb $0b, $00, $00, $00, $00, $00, $00, $00
+       dcb $00, $00, $00, $00, $00, $00, $00, $00
+
+src_row:
+       ; (32 bytes)
+
+; A full-resolution version of the same thing. Not perhaps the most interesting thing to look at.
+
+;#include "screenhack.h"
+;
+;#include <inttypes.h>
+;
+;struct texture
+;{
+;      unsigned width, height;
+;      Colormap colormap;
+;      GC gc;
+;      unsigned long palette[128];
+;      XImage *image;
+;      uint8_t *row;
+;      unsigned graininess;
+;      unsigned lines;
+;};
+;
+;#define GRAIN(self) (NRAND((self)->graininess * 2 + 1) - (self)->graininess)
+;
+;static void _put_line(struct texture *self, Display *dpy, Window window, unsigned y)
+;{
+;      unsigned x;
+;      for(x = 0; x != self->width; ++x)
+;      {
+;              unsigned c1 = self->row[x];
+;              unsigned c0 = c1;
+;              if(c0 & 64)
+;                      c0 ^= 127;
+;              XPutPixel(self->image, x, 0, self->palette[(c0 & 63) | ((c1 & 0x80) >> 1)]);
+;      }
+;
+;      XPutImage(dpy, window, self->gc, self->image, 0, 0, 0, y, self->width, 1);
+;
+;      *self->row += GRAIN(self);
+;
+;      for(x = 1; x != self->width; ++x);
+;      {
+;              unsigned avg = self->row[x - 1] + self->row[x];
+;              self->row[x] = ((avg + ((avg & 2) >> 1)) >> 1) + GRAIN(self);
+;      }
+;
+;
+;}
+;
+;static void texture_reshape(Display *dpy, Window window, void *self_raw, unsigned w, unsigned h)
+;{
+;      struct texture *self = self_raw;
+;      unsigned x, y;
+;
+;      if(w == self->width && h == self->height)
+;              return;
+;
+;      self->image->bytes_per_line = 0;
+;      self->image->width = w;
+;      XInitImage(self->image);
+;
+;      free(self->row);
+;      self->row = malloc(w);
+;      free(self->image->data);
+;      self->image->data = malloc(w * self->image->bytes_per_line);
+;
+;      self->width = w;
+;      self->height = h;
+;
+;      *self->row = NRAND(0xff);
+;      for(x = 1; x != self->width; ++x)
+;              self->row[x] = self->row[x - 1] + GRAIN(self);
+;
+;      for(y = 0; y != self->height; ++y)
+;              _put_line(self, dpy, window, y);
+;}
+;
+;static void *texture_init(Display *dpy, Window window)
+;{
+;      static const XGCValues gcv_src = {GXcopy};
+;      XGCValues gcv = gcv_src;
+;      struct texture *self = malloc(sizeof(*self));
+;      XWindowAttributes xwa;
+;      unsigned i;
+;
+;      XGetWindowAttributes(dpy, window, &xwa);
+;      self->width = 0;
+;      self->height = 0;
+;      self->colormap = xwa.colormap;
+;
+;      self->graininess = get_integer_resource(dpy, "graininess", "Graininess");
+;      self->lines = get_integer_resource(dpy, "speed", "Speed");
+;
+;      for(i = 0; i != 64; ++i)
+;      {
+;              XColor color;
+;              unsigned short a = i * (0x10000 / 64);
+;
+;              color.red   = a;
+;              color.green = a;
+;              color.blue  = a;
+;              if(!XAllocColor(dpy, xwa.colormap, &color))
+;                      abort();
+;              self->palette[i] = color.pixel;
+;
+;              color.red   = 0;
+;              color.green = a;
+;              color.blue  = 0;
+;              if(!XAllocColor(dpy, xwa.colormap, &color))
+;                      abort();
+;              self->palette[i | 64] = color.pixel;
+;      }
+;
+;      self->gc = XCreateGC(dpy, window, GCFunction, &gcv);
+;      self->image = XCreateImage(dpy, xwa.visual, xwa.depth, ZPixmap, 0, NULL, 0, 1, 32, 0);
+;      self->row = NULL;
+;
+;      texture_reshape(dpy, window, self, xwa.width, xwa.height);
+;
+;      return self;
+;}
+;
+;static unsigned long texture_draw(Display *dpy, Window window, void *self_raw)
+;{
+;      struct texture *self = self_raw;
+;      unsigned y;
+;      XCopyArea(dpy, window, window, self->gc, 0, self->lines, self->width, self->height - self->lines, 0, 0);
+;      for(y = 0; y != self->lines; ++y)
+;              _put_line(self, dpy, window, self->height - self->lines + y);
+;      return 16667;
+;}
+;
+;static Bool texture_event (Display *dpy, Window window, void *self_raw, XEvent *event)
+;{
+;      return False;
+;}
+;
+;static void texture_free(Display *dpy, Window window, void *self_raw)
+;{
+;      struct texture *self = self_raw;
+;
+;      XFreeGC(dpy, self->gc);
+;      XFreeColors(dpy, self->colormap, self->palette, 128, 0);
+;      XDestroyImage(self->image);
+;      free(self->row);
+;      free(self);
+;}
+;
+;static const char *texture_defaults[] =
+;{
+;      "*speed:      2",
+;      "*graininess: 1",
+;      "*fpsSolid:   True",
+;      "*fpsTop:     True",
+;      0
+;};
+;
+;static XrmOptionDescRec texture_options[] =
+;{
+;      {"-speed",      ".speed",      XrmoptionSepArg, 0},
+;      {"-graininess", ".graininess", XrmoptionSepArg, 0},
+;      {0, 0, 0, 0}
+;};
+;
+;XSCREENSAVER_MODULE("Texture", texture)
diff --git a/hacks/images/ransomware.xpm b/hacks/images/ransomware.xpm
new file mode 100644 (file)
index 0000000..c36bdb8
--- /dev/null
@@ -0,0 +1,109 @@
+/* XPM */
+static char * ransomware_xpm[] = {
+"94 94 12 1",
+"      c None",
+".     c #FDFFFB",
+"+     c #D49091",
+"@     c #CD8C8F",
+"#     c #DBB8B8",
+"$     c #E3D7D4",
+"%     c #C73A3F",
+"&     c #CF6F6F",
+"*     c #BD1921",
+"=     c #AD1D21",
+"-     c #A53932",
+";     c #B06B6C",
+"..............................................................................................",
+"..............................................................................................",
+"..+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+..",
+"..++@@@@@@@++@@+@@++@@@@@++@@@@@@++@++@++@+@@@@@@@@@+@@++@@+@@++@@@@@++@@@@@++@@+@@@++@+@@+@..",
+"..+@+@@++@@@@@+@@+@@@+@+++@@++@@@@@@+@@@@@+++++++++@@@@@@@@@+@@@@+@++@@@+++@@+@+@@@+@@+@@@+@..",
+"..+@+@@++++@+@+@++@+@@+@@+@@+@@+++@@@@#$$$........$$$$#++@@+@@@@@@+@@+@@+@+++@+@+@@++++++++@..",
+"..++@@@@@@@@@@@@@@@@@@@++@@@@@@++@@#$...................$$#+@@+@@@@++@@@@@@@@@@@@@@@@@@@@@+@..",
+"..+@@@@++@@@+@@@++@@@@@+++@@+@@@+$.........................$#+@+@@@+@@@@@+@@+@@@+@@@@@@+@@+@..",
+"..+@@@@+@@@+@@+@++@@@@@@@+++@++#$............................$#@@@@++@@@@@++@@@+@@+@@@@@@@+@..",
+"..+@@@@@+@@+@+@@++@++@@@@@@@@@$................................$+@@@@@@@+@++@++@+@++@@@@@++@..",
+"..+@@@+@@+@@+@+@@@+@@+@@@@+++$...................................#+@@@@+@+@@+@@++@@+@@@@@@+@..",
+"..+@@@@++@@@@+@@@@@++@@@@+@@$....................................$++@@@@+@@@@++@@++@@@@@@@+@..",
+"..+@@@@@@@@@@@@@@@@@@@@@@+@$......................................$@+@@@@@@@@@@@@@@@@@@@@@+@..",
+"..+@@@@@@@@@@@@@@@@@@@@@+@#..............$##+##++##$...............#+@@@@@@@@@@@@@@@@@@@@@+@..",
+"..+@@@@@@@@@@@@@@@@@@@@+++.............#+@@@@@@@@@@@@#.............$@+@@@@@@@@@@@@@@@@@@@@+@..",
+"..+@@@@@@@@@@@@@@@@@@@@@+#...........$#@@@@@@@@@@@@@@@#$............#+@@@@@@@@@@@@@@@@@@@@+@..",
+"..+@@@@@@@@@@@@@@@@@@@@+@$..........$@@@+@@@@@@@@@@@@@@@$...........#+@@@@@@@@@@@@@@@@@@@@+@..",
+"..+@@@@@@@@@@@@@@@@@@@@+#..........$@@@@@@@@@@@@@@@@@@@@@$..........#+@@@@@@@@@@@@@@@@@@@@+@..",
+"..+@@@@@@@@@@@@@@@@@@@@+$.........$@@@@@@@@@@@@@@@@@@@@@@#..........$@@@@@@@@@@@@@@@@@@@@@+@..",
+"..+@@@@@@@@@@@@@@@@@@@+@$.........#@@@@@@@@@@@@@@@@@@@@@@@$.........$++@@@@@@@@@@@@@@@@@@@@@..",
+"..+++++++++++++++++++++#.........$+@@@@@@@@@@@@@@@@@@@@@@@#.........$@@+++++++++++++++++++++..",
+"..+++++++++++++++++++++#.........$@@@@@@@@@@@@@@@@@@@@@@@@@$........$@++++++++++++++++++++++..",
+"..+++++++++++++++++++++#.........#@@@@@@@@@@@@@@@@@@@@@@@@@$........$@++++++++++++++++++++++..",
+"..+++++++++++++++++++++#.........#@@@@@@@@@@@@@@@@@@@@@@@@@#........$@++++++++++++++++++++++..",
+"..+++++++++++++++++++++#.........#@@@@@@@@@@@@@@@@@@@@@@@@@#........$@++++++++++++++++++++++..",
+"..+++++++++++++++++++++#.........#@@@@@@@@@@@@@@@@@@@@@@@@@#........$@++++++++++++++++++++++..",
+"..+++++++++++++++++++++#.........#@@@@@@@@@@@@@@@@@@@@@@@@@#........$@++++++++++++++++++++++..",
+"..+++++++++++++++++++++#.........#@@@@@@@@@@@@@@@@@@@@@@@@@#........$@++++++++++++++++++++++..",
+"..+++++++++++++++++++++#.........#@@@@@@@@@@@@@@@@@@@@@@@@@#........$@++++++++++++++++++++++..",
+"..+++++++++++++++++++++#.........#@@@@@@@@@@@@@@@@@@@@@@@@@#........$@++++++++++++++++++++++..",
+"..+++++++++++++++++++++#.........#@@@@@@@@@@@@@@@@@@@@@@@@@#........$@++++++++++++++++++++++..",
+"..+++++++++++++++++++++#.........#@@@@@@@@@@@@@@@@@@@@@@@@@#........$+++++++++++++++++++++++..",
+"..+++++++++++++++++++++#.........#@@@@@@@@@@@@@@@@@@@@@@@@@#........$+++++++++++++++++++++++..",
+"..+++++++++++++++++++++#.........#@@@@@@@@@@@@@@@@@@@@@@@@@#........$@++++++++++++++++++++++..",
+"..+++++++++++++++++++++#.........#@@@@@@@@@@@@@@@@@@@@@@@@@#........$@++++++++++++++++++++++..",
+"..+++++++++++++++++++++#.........#@@@@@@@@@@@@@@@@@@@@@@@@@#........$+++++++++++++++++++++++..",
+"..+++++++++++++++++++++#.........#@@@@@@@@@@@@@@@@@@@@@@@@@#........$+++++++++++++++++++++++..",
+"..%&+++++++++++++++++++#.........#@@@@@@@@@@@@@@@@@@@@@@@@@#........$+++++++++++++++++++++++..",
+"..*==%%&&&++@++++++++++#.........#@@@@@@@@@@@@@@@@@@@@@@@@@#........$+++++++++++++++++++++++..",
+"..*=*=====-%&&&++++++++#.........#@@@@@@@@@@@@@@@@@@@@@@@@@#........$+++++++++++++++++++++++..",
+"..*=======*=*==%=-%&&&++.........#@@@@@@@@@@@@@@@@@@@@@@@@@#........$+++++++++++++++++++++++..",
+"..*==================*=&.........#@@@@@@@@@@@@@@@@@@@@@@@@@#........$+++++++++++++++++++++++..",
+"..*===================*%.........@&;@@@@@@@@@@@@@@@@@@@@@@@#........$@++++++++++++++++++++++..",
+"..*===================*&.........;==-----;;&;@@@@@@@@@@@@@@#........$@++++++++++++++++++++++..",
+"..*===================*%.........&==============-----&&;;;;#........$@++++++++++++++++++++++..",
+"..*===============*===*&.........;-----------------------;&+........$@@++@&&+++++++++++@@@++..",
+"..*===============%+####.........$###########$$$$$$$$$$#$$$$.........$$$$+%=%--%%%%%&&&&&&&&..",
+"..*=============*&........................................................#%==============*=..",
+"..*==============#.........................................................&*==============%..",
+"..*==============#.........................................................&*==============%..",
+"..*==============#.........................................................&*==============%..",
+"..*==============#.........................................................&*==============%..",
+"..*==============#.........................................................&*==============%..",
+"..*==*=*====*====#.........................................................&*==*===========%..",
+"..*===*=======*==#.........................................................&*=*==*==*==*==*%..",
+"..*==========*=*=#.........................................................&*==============%..",
+"..*=====*=====*==#.........................#@;;+$..........................&**===*=*=*==*==%..",
+"..*=*=**=***=*===#........................@=====-#.........................&*=*=***=*==****%..",
+"..*=*==*==*====*=#.......................@=======-$........................&*==*===*=**=*=*%..",
+"..**=************#......................#-========@........................&***************%..",
+"..***********=***#......................@=========-$.......................&****=**********%..",
+"..**********=****#......................@=====-===-$.......................&***********=***%..",
+"..***************#......................@=========-$.......................&********=******%..",
+"..***************#......................#-========&........................&***************%..",
+"..***************#.......................;==-=====#........................&***************%..",
+"..***************#.......................$-======+.........................&***************%..",
+"..***************#........................&=====-$.........................&***************%..",
+"..***************#.......................$-======#.........................&***************%..",
+"..***************#.......................$-==-===@.........................&***************%..",
+"..***************#.......................#=======&.........................&***************%..",
+"..***************#.......................@===-===-.........................&***************%..",
+"..***************#.......................;==-====-$........................&***************%..",
+"..***************#.......................-====-==-#........................&***************%..",
+"..***************#......................$-========#........................&***************%..",
+"..***************#......................#-=-=-=-==@........................&***************%..",
+"..***************#......................@=========;........................&***************%..",
+"..***************#......................;=========-$.......................&***************%..",
+"..***************#......................@---------&$.......................&***************%..",
+"..***************#.........................................................&***************%..",
+"..***************#.........................................................&***************%..",
+"..***************#.........................................................&***************%..",
+"..***************#.........................................................&***************%..",
+"..***************#.........................................................&***************%..",
+"..***************#.........................................................&***************%..",
+"..***************#.........................................................&***************%..",
+"..***************#........................................................$&***************%..",
+"..***************%$.......................................................@****************%..",
+"..****************%++++++++++++++++++++++++++++++++++++++++++++++++++++++&*****************%..",
+"..*****************************************************************************************%..",
+"..*****************************************************************************************%..",
+"..******************************************************************************************..",
+"..%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%..",
+"..............................................................................................",
+".............................................................................................."};
index 96c6b29dbdb0c7ffb1e6d01036eebf7a01942cda..4e65b765864e76beafda1157a3bfceab198e4beb 100644 (file)
@@ -548,6 +548,7 @@ intermomentary_free (Display *dpy, Window window, void *closure)
 
 
 static const char *intermomentary_defaults[] = {
+    ".lowrez: true",
     ".background: black",
     ".foreground: yellow",
     "*drawDelay: 30000",
index a2dce5e0ab46fbfd41a90ab962e3a322be7420b9..07e52fe51dbed1c587b4c5cf60dddf46a3df5409 100644 (file)
@@ -137,7 +137,8 @@ static const char sccsid[] = "@(#)juggle.c  5.10 2003/09/02 xlockmore";
                                        "*font:    -*-helvetica-bold-r-normal-*-180-*\n" \
                                        "*fpsSolid: true\n" \
 
-# define refresh_juggle 0
+# define release_juggle 0
+# define reshape_juggle 0
 # define juggle_handle_event 0
 # undef SMOOTH_COLORS
 # include "xlockmore.h"                /* in xscreensaver distribution */
@@ -257,8 +258,8 @@ ENTRYPOINT ModeSpecOpt juggle_opts =
 
 #ifdef USE_MODULES
 ModStruct   juggle_description = {
-       "juggle", "init_juggle", "draw_juggle", "release_juggle",
-       "draw_juggle", "change_juggle", (char *) NULL, &juggle_opts,
+       "juggle", "init_juggle", "draw_juggle", (char *) NULL,
+       "draw_juggle", "change_juggle", "free_juggle", &juggle_opts,
        10000, 200, 1000, 1, 64, 1.0, "",
        "Shows a Juggler, juggling", 0, NULL
 };
@@ -660,8 +661,10 @@ trajectory_destroy(Trajectory *t) {
   REMOVE(t); /* Unlink and free */
 }
 
-static void
-free_juggle(jugglestruct *sp) {
+ENTRYPOINT void
+free_juggle(ModeInfo * mi) {
+  jugglestruct *sp = &juggles[MI_SCREEN(mi)];
+
   if (sp->head != NULL) {
        while (sp->head->next != sp->head) {
          trajectory_destroy(sp->head->next);
@@ -695,13 +698,14 @@ free_juggle(jugglestruct *sp) {
 }
 
 static Bool
-add_throw(jugglestruct *sp, char type, int h, Notation n, const char* name)
+add_throw(ModeInfo *mi, char type, int h, Notation n, const char* name)
 {
+  jugglestruct *sp = &juggles[MI_SCREEN(mi)];
   Trajectory *t;
 
   ADD_ELEMENT(Trajectory, t, sp->head->prev);
   if(t == NULL){ /* Out of Memory */
-       free_juggle(sp);
+       free_juggle(mi);
        return False;
   }
   t->object = NULL;
@@ -723,7 +727,6 @@ add_throw(jugglestruct *sp, char type, int h, Notation n, const char* name)
 static Bool
 program(ModeInfo *mi, const char *patn, const char *name, int cycles)
 {
-  jugglestruct *sp = &juggles[MI_SCREEN(mi)];
   const char *p;
   int w, h, i, seen;
   Notation notation;
@@ -775,7 +778,7 @@ program(ModeInfo *mi, const char *patn, const char *name, int cycles)
                case ' ':
                  if (seen) {
                        i++;
-                       if (!add_throw(sp, type, h, notation, title))
+                       if (!add_throw(mi, type, h, notation, title))
                                return False;
                        title = NULL;
                        type=' ';
@@ -795,7 +798,7 @@ program(ModeInfo *mi, const char *patn, const char *name, int cycles)
          }
        }
        if (seen) { /* end of sequence */
-         if (!add_throw(sp, type, h, notation, title))
+         if (!add_throw(mi, type, h, notation, title))
                return False;
          title = NULL;
        }
@@ -896,8 +899,9 @@ name(jugglestruct *sp)
 /* ..nm.. -> .. LTn LC RTm RC .. */
 
 static Bool
-part(jugglestruct *sp)
+part(ModeInfo *mi)
 {
+  jugglestruct *sp = &juggles[MI_SCREEN(mi)];
   Trajectory *t, *nt, *p;
   Hand hand = (LRAND() & 1) ? RIGHT : LEFT;
 
@@ -942,7 +946,7 @@ part(jugglestruct *sp)
          t->action = CATCH;
          ADD_ELEMENT(Trajectory, nt, p);
          if(nt == NULL){
-               free_juggle(sp);
+               free_juggle(mi);
                return False;
          }
          nt->object = NULL;
@@ -2295,19 +2299,6 @@ show_bball(ModeInfo *mi, unsigned long color, Trace *s)
  **************************************************************************/
 
 
-ENTRYPOINT void
-release_juggle (ModeInfo * mi)
-{
-  if (juggles != NULL) {
-       int screen;
-
-       for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
-         free_juggle(&juggles[screen]);
-       free(juggles);
-       juggles = (jugglestruct *) NULL;
-  }
-}
-
 /* FIXME: refill_juggle currently just appends new throws to the
  * programme.  This is fine if the programme is empty, but if there
  * are still some trajectories left then it really should take these
@@ -2423,7 +2414,7 @@ refill_juggle(ModeInfo * mi)
 
   name(sp);
 
-  if (!part(sp))
+  if (!part(mi))
        return;
 
   lob(mi);
@@ -2433,7 +2424,7 @@ refill_juggle(ModeInfo * mi)
   positions(sp);
 
   if (!projectile(sp)) {
-       free_juggle(sp);
+       free_juggle(mi);
        return;
   }
 
@@ -2481,7 +2472,7 @@ init_juggle (ModeInfo * mi)
   jugglestruct *sp = 0;
   int i;
 
-  MI_INIT (mi, juggles, 0);
+  MI_INIT (mi, juggles);
   sp = &juggles[MI_SCREEN(mi)];
 
   if (only && *only && strcmp(only, " ")) {
@@ -2530,21 +2521,21 @@ init_juggle (ModeInfo * mi)
        /* create circular trajectory list */
        ADD_ELEMENT(Trajectory, sp->head, sp->head);
        if(sp->head == NULL){
-         free_juggle(sp);
+         free_juggle(mi);
          return;
        }
 
        /* create circular object list */
        ADD_ELEMENT(Object, sp->objects, sp->objects);
        if(sp->objects == NULL){
-         free_juggle(sp);
+         free_juggle(mi);
          return;
        }
 
        /* create circular wander list */
        ADD_ELEMENT(Wander, sp->wander, sp->wander);
        if(sp->wander == NULL){
-         free_juggle(sp);
+         free_juggle(mi);
          return;
        }
        (void)wander(sp, 0); /* Initialize wander */
@@ -2610,12 +2601,6 @@ init_juggle (ModeInfo * mi)
   }
 }
 
-ENTRYPOINT void
-reshape_juggle (ModeInfo * mi, int width, int height)
-{
-  init_juggle(mi);
-}
-
 ENTRYPOINT void
 draw_juggle (ModeInfo * mi)
 {
@@ -2802,7 +2787,6 @@ draw_juggle (ModeInfo * mi)
   if (future < sp->time + 100 * THROW_CATCH_INTERVAL) {
        refill_juggle(mi);
   } else if (sp->time > 1<<30) { /* Hard Reset before the clock wraps */
-       release_juggle(mi);
        init_juggle(mi);
   }
 }
index c41aba517f52844c0fae9172354014a5d62408fe..7311ce72023e777351c8ef6482322b0661e3832f 100644 (file)
@@ -47,6 +47,7 @@ static const char sccsid[] = "@(#)julia.c     4.03 97/04/10 xlockmore";
 
 # define UNIFORM_COLORS
 # define release_julia 0
+# define reshape_julia 0
 # include "xlockmore.h"                                /* in xscreensaver distribution */
 #else  /* !STANDALONE */
 # include "xlock.h"                                    /* in xlockmore distribution */
@@ -153,8 +154,6 @@ incr(ModeInfo * mi, juliastruct * jp)
          }
 }
 
-static void free_julia (ModeInfo * mi);
-
 ENTRYPOINT void
 init_julia(ModeInfo * mi)
 {
@@ -164,7 +163,7 @@ init_julia(ModeInfo * mi)
        XGCValues   gcv;
        int         i;
 
-       MI_INIT (mi, julias, free_julia);
+       MI_INIT (mi, julias);
        jp = &julias[MI_SCREEN(mi)];
 
        jp->centerx = MI_WIN_WIDTH(mi) / 2;
@@ -253,13 +252,6 @@ init_julia(ModeInfo * mi)
 }
 
 
-static void
-reshape_julia (ModeInfo *mi, int w, int h)
-{
-  init_julia (mi);
-}
-
-
 ENTRYPOINT Bool
 julia_handle_event (ModeInfo *mi, XEvent *event)
 {
@@ -413,7 +405,7 @@ draw_julia (ModeInfo * mi)
        }
 }
 
-static void
+ENTRYPOINT void
 free_julia (ModeInfo * mi)
 {
        Display    *display = MI_DISPLAY(mi);
@@ -436,6 +428,7 @@ free_julia (ModeInfo * mi)
 #endif
 }
 
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_julia (ModeInfo * mi)
 {
@@ -444,5 +437,6 @@ refresh_julia (ModeInfo * mi)
        jp->redrawing = 1;
        jp->redrawpos = 0;
 }
+#endif
 
 XSCREENSAVER_MODULE ("Julia", julia)
index 20915419687b1057e212a897b76bb6be9af7ef47..8ee02193e4043a1770af2b1579f8b05a1ab8873e 100644 (file)
@@ -35,6 +35,7 @@ static const char sccsid[] = "@(#)laser.c     5.00 2000/11/01 xlockmore";
                                        "*fpsSolid: true \n" \
 
 # define BRIGHT_COLORS
+# define release_laser 0
 # define reshape_laser 0
 # define laser_handle_event 0
 # include "xlockmore.h"                /* in xscreensaver distribution */
@@ -49,8 +50,8 @@ ENTRYPOINT ModeSpecOpt laser_opts =
 
 #ifdef USE_MODULES
 ModStruct   laser_description =
-{"laser", "init_laser", "draw_laser", "release_laser",
- "refresh_laser", "init_laser", (char *) NULL, &laser_opts,
+{"laser", "init_laser", "draw_laser", (char *) NULL,
+ "refresh_laser", "init_laser", "free_laser", &laser_opts,
  20000, -10, 200, 1, 64, 1.0, "",
  "Shows spinning lasers", 0, NULL};
 
@@ -106,9 +107,12 @@ typedef struct {
 
 static lasersstruct *lasers = (lasersstruct *) NULL;
 
-static void
-free_laser(Display *display, lasersstruct *lp)
+ENTRYPOINT void
+free_laser(ModeInfo * mi)
 {
+       Display *display = MI_DISPLAY(mi);
+       lasersstruct *lp = &lasers[MI_SCREEN(mi)];
+
        if (lp->laser != NULL) {
                (void) free((void *) lp->laser);
                lp->laser = (laserstruct *) NULL;
@@ -126,7 +130,7 @@ init_laser(ModeInfo * mi)
        int         i, c = 0;
        lasersstruct *lp;
 
-       MI_INIT (mi, lasers, 0);
+       MI_INIT (mi, lasers);
        lp = &lasers[MI_SCREEN(mi)];
 
        lp->width = MI_WIDTH(mi);
@@ -147,7 +151,7 @@ init_laser(ModeInfo * mi)
        if (lp->laser == NULL) {
                if ((lp->laser = (laserstruct *) malloc(lp->ln *
                                sizeof (laserstruct))) == NULL) {
-                       free_laser(display, lp);
+                       free_laser(mi);
                        return;
                }
        }
@@ -159,7 +163,7 @@ init_laser(ModeInfo * mi)
                lp->gcv_black.foreground = MI_BLACK_PIXEL(mi);
                if ((lp->stippledGC = XCreateGC(display, MI_WINDOW(mi),
                                GCForeground | GCBackground, &gcv)) == None) {
-                       free_laser(display, lp);
+                       free_laser(mi);
                        return;
                }
 # ifdef HAVE_JWXYZ
@@ -338,24 +342,13 @@ draw_laser(ModeInfo * mi)
                init_laser(mi);
 }
 
-ENTRYPOINT void
-release_laser(ModeInfo * mi)
-{
-       if (lasers != NULL) {
-               int         screen;
-
-               for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
-                       free_laser(MI_DISPLAY(mi), &lasers[screen]);
-               (void) free((void *) lasers);
-               lasers = (lasersstruct *) NULL;
-       }
-}
-
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_laser(ModeInfo * mi)
 {
        MI_CLEARWINDOW(mi);
 }
+#endif
 
 XSCREENSAVER_MODULE ("Laser", laser)
 
index 1f5d70234231f58477f9181371d55d47e0980dc1..027bc7521781ec85f592f705f228f96078ecea7f 100644 (file)
@@ -33,6 +33,8 @@ static const char sccsid[] = "@(#)lightning.c 5.00 2000/11/01 xlockmore";
                   "*ncolors: 64  \n"
 
 # define BRIGHT_COLORS
+# define free_lightning 0
+# define release_lightning 0
 # define reshape_lightning 0
 # define lightning_handle_event 0
 # include "xlockmore.h"                /* in xscreensaver distribution */
@@ -47,7 +49,7 @@ ENTRYPOINT ModeSpecOpt lightning_opts =
 
 #ifdef USE_MODULES
 ModStruct   lightning_description =
-{"lightning", "init_lightning", "draw_lightning", "release_lightning",
+{"lightning", "init_lightning", "draw_lightning", (char *) NULL,
  "refresh_lightning", "init_lightning", (char *) NULL, &lightning_opts,
  10000, 1, 1, 1, 64, 0.6, "",
  "Shows Keith's fractal lightning bolts", 0, NULL};
@@ -518,7 +520,7 @@ init_lightning (ModeInfo * mi)
 {
        Storm      *st;
 
-       MI_INIT (mi, Helga, 0);
+       MI_INIT (mi, Helga);
        st = &Helga[MI_SCREEN(mi)];
 
        st->scr_width = MI_WIDTH(mi);
@@ -543,9 +545,7 @@ draw_lightning (ModeInfo * mi)
        MI_IS_DRAWN(mi) = True;
        switch (st->stage) {
                case 0:
-                       MI_IS_DRAWN(mi) = False;
-                       MI_CLEARWINDOW(mi);
-                       MI_IS_DRAWN(mi) = True;
+                       XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi));
 
                        st->color = NRAND(MI_NPIXELS(mi));
                        st->draw_time = 0;
@@ -571,9 +571,7 @@ draw_lightning (ModeInfo * mi)
                        }
                        break;
                case 3:
-                       MI_IS_DRAWN(mi) = False;
-                       MI_CLEARWINDOW(mi);
-                       MI_IS_DRAWN(mi) = True;
+                       XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi));
 
                        if (storm_active(st))
                                st->stage = 1;
@@ -589,20 +587,13 @@ draw_lightning (ModeInfo * mi)
        }
 }
 
-ENTRYPOINT void
-release_lightning(ModeInfo * mi)
-{
-       if (Helga != NULL) {
-               (void) free((void *) Helga);
-               Helga = (Storm *) NULL;
-       }
-}
-
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_lightning(ModeInfo * mi)
 {
        /* Do nothing, it will refresh by itself */
 }
+#endif
 
 XSCREENSAVER_MODULE ("Lightning", lightning)
 
index 1a1159f62cdfadc9d4840033b6801d98d2b89497..d0303b80c20a3a2a1c7359df3b3791ce908aa346 100644 (file)
@@ -58,10 +58,12 @@ static const char sccsid[] = "@(#)lisa.c    5.00 2000/11/01 xlockmore";
                                        "*size: 500 \n" \
                                        "*ncolors: 64 \n" \
                                        "*fpsSolid: true \n" \
+                                   "*lowrez: True \n" \
 
 # define UNIFORM_COLORS
+# define release_lisa 0
 # define reshape_lisa 0
-# define lisa_handle_event 0
+# define lisa_handle_event xlockmore_no_events
 # include "xlockmore.h"                /* in xscreensaver distribution */
 #else /* STANDALONE */
 #include "xlock.h"          /* in xlockmore distribution */
@@ -95,8 +97,8 @@ ENTRYPOINT ModeSpecOpt lisa_opts =
 
 #ifdef USE_MODULES
 ModStruct   lisa_description =
-{"lisa", "init_lisa", "draw_lisa", "release_lisa",
- "refresh_lisa", "change_lisa", (char *) NULL, &lisa_opts,
+{"lisa", "init_lisa", "draw_lisa", (char *) NULL,
+ "refresh_lisa", "change_lisa", "free_lisa", &lisa_opts,
  17000, 1, 768, -1, 64, 1.0, "",
  "Shows animated lissajous figures", 0, NULL};
 
@@ -256,9 +258,10 @@ static lisafuncs Function[NUMSTDFUNCS] =
 
 int xMaxLines;
 
-static void
-free_lisa(lisacons *lc)
+ENTRYPOINT void
+free_lisa(ModeInfo * mi)
 {
+       lisacons   *lc = &Lisa[MI_SCREEN(mi)];
        while (lc->lissajous) {
                int    lctr;
 
@@ -286,7 +289,7 @@ drawlisa(ModeInfo * mi, lisas * loop)
 
        /* Allocate the np (new point) array (with padding) */
        if ((np = (XPoint *) calloc(loop->nsteps+extra_points, sizeof (XPoint))) == NULL) {
-               free_lisa(lc);
+               free_lisa(mi);
                return False;
        }
 
@@ -511,7 +514,7 @@ initlisa(ModeInfo * mi, lisas * loop)
   
   if ((lp = loop->lastpoint = (XPoint *)
           calloc(loop->nsteps+extra_points, sizeof (XPoint))) == NULL) {
-       free_lisa(lc);
+       free_lisa(mi);
        return False;
   }
   phase = lc->loopcount % loop->nsteps;
@@ -615,6 +618,7 @@ refreshlisa(ModeInfo * mi)
        }
 }
 
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_lisa(ModeInfo * mi)
 {
@@ -632,6 +636,7 @@ refresh_lisa(ModeInfo * mi)
                refreshlisa(mi);
        }
 }
+#endif
 
 static void
 change_lisa(ModeInfo * mi)
@@ -681,7 +686,7 @@ init_lisa (ModeInfo * mi)
        int         lctr;
        lisacons   *lc;
 
-       MI_INIT (mi, Lisa, 0);
+       MI_INIT (mi, Lisa);
        lc = &Lisa[MI_SCREEN(mi)];
        lc->width = MI_WIDTH(mi);
        lc->height = MI_HEIGHT(mi);
@@ -729,19 +734,6 @@ draw_lisa (ModeInfo * mi)
        refreshlisa(mi);
 }
 
-ENTRYPOINT void
-release_lisa (ModeInfo * mi)
-{
-       if (Lisa) {
-               int    screen;
-
-               for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
-                       free_lisa(&Lisa[screen]);
-               (void) free(Lisa);
-               Lisa = (lisacons *) NULL;
-       }
-}
-
 XSCREENSAVER_MODULE ("Lisa", lisa)
 
 #endif /* MODE_lisa */
index f968421b201525dc7d0258e0c38353da873c55d6..bb631b29be4839289b207776b0083cdc8fb53f0f 100644 (file)
@@ -40,6 +40,7 @@ static const char sccsid[] = "@(#)lissie.c    5.00 2000/11/01 xlockmore";
                                        "*fpsSolid: true \n" \
 
 # define SMOOTH_COLORS
+# define release_lissie 0
 # define reshape_lissie 0
 # define lissie_handle_event 0
 # include "xlockmore.h"                /* in xscreensaver distribution */
@@ -54,8 +55,8 @@ ENTRYPOINT ModeSpecOpt lissie_opts =
 
 #ifdef USE_MODULES
 ModStruct   lissie_description =
-{"lissie", "init_lissie", "draw_lissie", "release_lissie",
- "refresh_lissie", "init_lissie", (char *) NULL, &lissie_opts,
+{"lissie", "init_lissie", "draw_lissie", (char *) NULL,
+ "refresh_lissie", "init_lissie", "free_lissie", &lissie_opts,
  10000, 1, 2000, -200, 64, 0.6, "",
  "Shows lissajous worms", 0, NULL};
 
@@ -211,8 +212,6 @@ initlissie(ModeInfo * mi, lissiestruct * lissie)
 
        for (i = 0; i < MAXLISSIELEN; i++)
                lissie->loc[i].x = lissie->loc[i].y = 0;
-       /* Draw lissie */
-       drawlissie(mi, lissie);
 }
 
 ENTRYPOINT void
@@ -221,7 +220,7 @@ init_lissie (ModeInfo * mi)
        lissstruct *lp;
        unsigned char ball;
 
-       MI_INIT (mi, lisses, 0);
+       MI_INIT (mi, lisses);
        lp = &lisses[MI_SCREEN(mi)];
 
        lp->width = MI_WIDTH(mi);
@@ -281,24 +280,21 @@ draw_lissie (ModeInfo * mi)
 }
 
 ENTRYPOINT void
-release_lissie (ModeInfo * mi)
+free_lissie (ModeInfo * mi)
 {
-       if (lisses != NULL) {
-               int         screen;
+       lissstruct *lp;
 
-               for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
-                       lissstruct *lp = &lisses[screen];
+       if (lisses == NULL)
+               return;
+       lp = &lisses[MI_SCREEN(mi)];
 
-                       if (lp->lissie != NULL) {
-                               (void) free((void *) lp->lissie);
-                               /* lp->lissie = NULL; */
-                       }
-               }
-               (void) free((void *) lisses);
-               lisses = (lissstruct *) NULL;
+       if (lp->lissie != NULL) {
+               (void) free((void *) lp->lissie);
+               /* lp->lissie = NULL; */
        }
 }
 
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_lissie(ModeInfo * mi)
 {
@@ -319,6 +315,7 @@ refresh_lissie(ModeInfo * mi)
                }
        }
 }
+#endif
 
 XSCREENSAVER_MODULE ("Lissie", lissie)
 
index fd27fd167c63c84a96f66e9efde8c593d461ae8d..77f518131434bdcee3f3be3bbb44239da6b99da2 100644 (file)
@@ -93,6 +93,8 @@ static const char sccsid[] = "@(#)loop.c      5.01 2000/03/15 xlockmore";
                                        "*fpsSolid: true     \n" \
                                        "*ignoreRotation: True \n" \
 
+# define reshape_loop 0
+# define loop_handle_event 0
 # define UNIFORM_COLORS
 # include "xlockmore.h"                /* in xscreensaver distribution */
 #else /* STANDALONE */
@@ -131,7 +133,7 @@ ENTRYPOINT ModeSpecOpt loop_opts =
 #ifdef USE_MODULES
 ModStruct   loop_description =
 {"loop", "init_loop", "draw_loop", "release_loop",
- "refresh_loop", "init_loop", (char *) NULL, &loop_opts,
+ "refresh_loop", "init_loop", "free_loop", &loop_opts,
  100000, 5, 1600, -12, 64, 1.0, "",
  "Shows Langton's self-producing loops", 0, NULL};
 
@@ -188,7 +190,8 @@ static int  local_neighbors = 0;
 #define HEX_ADAM_LOOPY 7
 #endif
 #define HEX_MINGRIDSIZE (6*HEX_ADAM_LOOPX)
-#define MINSIZE ((MI_NPIXELS(mi)>=COLORS)?1:(2+(local_neighbors==6)))
+/* #define MINSIZE ((MI_NPIXELS(mi)>=COLORS)?1:(2+(local_neighbors==6))) */
+#define MINSIZE 5
 #define NEIGHBORKINDS 2
 #define ANGLES 360
 #define MAXNEIGHBORS 6
@@ -916,7 +919,7 @@ free_list(loopstruct * lp)
                free_state(lp, state);
 }
 
-static void
+ENTRYPOINT void
 free_loop(ModeInfo * mi)
 {
        Display    *display = MI_DISPLAY(mi);
@@ -1441,11 +1444,14 @@ init_loop (ModeInfo * mi)
 
     stop_warning_about_triangleUnit_already = (void *) &triangleUnit;
 
-       MI_INIT (mi, loops, free_loop);
+       MI_INIT (mi, loops);
        lp = &loops[MI_SCREEN(mi)];
 
        lp->redrawing = 0;
 
+    if (MI_WIDTH(mi) < 100 || MI_HEIGHT(mi) < 100)  /* tiny window */
+      size = MIN(MI_WIDTH(mi), MI_HEIGHT(mi));
+
 #ifdef DO_STIPPLE
        if ((MI_NPIXELS(mi) < COLORS) && (lp->init_bits == 0)) {
           Window      window = MI_WINDOW(mi);
@@ -1666,13 +1672,7 @@ draw_loop (ModeInfo * mi)
        }
 }
 
-ENTRYPOINT void
-reshape_loop(ModeInfo * mi, int width, int height)
-{
-  XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi));
-  init_loop (mi);
-}
-
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_loop (ModeInfo * mi)
 {
@@ -1686,17 +1686,7 @@ refresh_loop (ModeInfo * mi)
        lp->redrawing = 1;
        lp->redrawpos = lp->by * lp->ncols + lp->bx;
 }
-
-ENTRYPOINT Bool
-loop_handle_event (ModeInfo *mi, XEvent *event)
-{
-  if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
-    {
-      reshape_loop (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
-      return True;
-    }
-  return False;
-}
+#endif
 
 XSCREENSAVER_MODULE ("Loop", loop)
 
index 47822abebfc6ae5c76fe221d1e46627395fa2a25..ce18e9d3d9af074e85182ff49f327f59787e9432 100644 (file)
@@ -63,11 +63,14 @@ struct state {
   int pixh;/* pixel height */
   int topb;/* top boarder */
   int field_ntsc[4];/* used for clearing the screen*/ 
-  int dt;/* how long to wait before changing the demo*/
+  double dt;/* how long to wait before changing the demo*/
   int which;/* the program to run*/
   int demos;/* number of demos included */
-  struct timeval start_time; 
+  double start_time;
   int reset_p;
+  char *file;
+  double last_frame, last_delay;
+  unsigned ips;
 };
 
 static void
@@ -92,42 +95,27 @@ start_rand_bin_prog(machine_6502 *machine, struct state *st){
 
 \f
 /*
- * get_time ()
+ * double_time ()
  *
- * returns the total time elapsed since the beginning of the demo
+ * returns the current time as a floating-point value
  */
-static double get_time(struct state *st) {
+static double double_time(void) {
   struct timeval t;
-  float f;
+  double f;
 #if GETTIMEOFDAY_TWO_ARGS
   gettimeofday(&t, NULL);
 #else
   gettimeofday(&t);
 #endif
-  t.tv_sec -= st->start_time.tv_sec;
   f = ((double)t.tv_sec) + t.tv_usec*1e-6;
   return f;
 }
 
-/*
- * init_time ()
- *
- * initialises the timing structures
- */
-static void init_time(struct state *st) {
-#if GETTIMEOFDAY_TWO_ARGS
-  gettimeofday(&st->start_time, NULL);
-#else
-  gettimeofday(&st->start_time);
-#endif
-}
-
 static void *
 m6502_init (Display *dpy, Window window)
 {
   struct state *st = (struct state *) calloc (1, sizeof(*st));
-  unsigned int x, y;
-  int n = get_integer_resource(dpy, "displaytime", "Displaytime");
+  int n = get_float_resource(dpy, "displaytime", "Displaytime");
   int dh;
   st->demos = countof(demo_files);
   st->which = random() % st->demos;
@@ -151,17 +139,15 @@ m6502_init (Display *dpy, Window window)
   dh = SCREEN_H % 32;
   st->topb = dh / 2;
 
-  init_time(st);
-  
-  {
+  st->last_frame = double_time();
+  st->last_delay = 0;
+  st->ips = get_integer_resource(dpy, "ips", "IPS");
+
 #ifdef READ_FILES
-    char *s = get_string_resource (dpy, "file", "File");
-    if (strlen(s) > 0)
-      m6502_start_eval_file(st->machine,s, plot6502, st);
-  else
+  st->file = get_string_resource (dpy, "file", "File");
 #endif
-    start_rand_bin_prog(st->machine,st);
-  }
+
+  st->reset_p = 1;
 
   analogtv_lcp_to_ntsc(ANALOGTV_BLACK_LEVEL, 0.0, 0.0, st->field_ntsc);
 
@@ -170,10 +156,6 @@ m6502_init (Display *dpy, Window window)
                       ANALOGTV_TOP, ANALOGTV_BOT,
                       st->field_ntsc);
 
-  for(x = 0; x < 32; x++)
-    for(y = 0; y < 32; y++)
-      st->pixels[x][y] = 0;
-
   return st;
 }
 
@@ -229,10 +211,30 @@ m6502_draw (Display *dpy, Window window, void *closure)
 {
   struct state *st = (struct state *) closure;
   unsigned int x = 0, y = 0;
-  double te;
+  double now, last_delay = st->last_delay >= 0 ? st->last_delay : 0;
+  double insno = st->ips * ((1 / 29.97) + last_delay - st->last_delay);
   const analogtv_reception *reception = &st->reception;
 
-  m6502_next_eval(st->machine,500);
+  if (st->reset_p){ /* do something more interesting here XXX */
+    st->reset_p = 0;
+    for(x = 0; x < 32; x++)
+      for(y = 0; y < 32; y++)
+        st->pixels[x][y] = 0;
+    st->start_time = st->last_frame + last_delay;
+
+#ifdef READ_FILES
+    if (st->file && *st->file)
+      m6502_start_eval_file(st->machine, st->file, plot6502, st);
+    else
+#endif
+      start_rand_bin_prog(st->machine,st);
+  }
+
+  if (insno < 10)
+    insno = 10;
+  else if (insno > 100000) /* Real 6502 went no faster than 3 MHz. */
+    insno = 100000;
+  m6502_next_eval(st->machine,insno);
 
   for (x = 0; x < 32; x++)
     for (y = 0; y < 32; y++)
@@ -240,22 +242,14 @@ m6502_draw (Display *dpy, Window window, void *closure)
   
   analogtv_reception_update(&st->reception);
   analogtv_draw(st->tv, 0.04, &reception, 1);
-  te = get_time(st);
-  
-  if (st->reset_p || te > st->dt){ /* do something more interesting here XXX */
-    st->reset_p = 0;
-    for(x = 0; x < 32; x++)
-      for(y = 0; y < 32; y++)
-       st->pixels[x][y] = 0;
-    init_time(st);
-    start_rand_bin_prog(st->machine,st);
-  }
+  now = double_time();
+  st->last_delay = (1 / 29.97) + st->last_frame + last_delay - now;
+  st->last_frame = now;
 
-#ifdef HAVE_MOBILE
-  return 0;
-#else
-  return 5000;
-#endif
+  if (now - st->start_time > st->dt)
+    st->reset_p = 1;
+
+  return st->last_delay >= 0 ? st->last_delay * 1e6 : 0;
 }
 
 
@@ -265,7 +259,10 @@ static const char *m6502_defaults [] = {
   ".background:      black",
   ".foreground:      white",
   "*file:",
-  "*displaytime:     20",
+  "*displaytime:     30.0",     /* demoscene: 24s, dmsc: 48s, sierpinsky: 26s
+                                   sflake, two runs: 35s
+                                 */
+  "*ips:             15000",    /* Actual MOS 6502 ran at least 1 MHz. */
   ANALOGTV_DEFAULTS
   0
 };
@@ -273,6 +270,7 @@ static const char *m6502_defaults [] = {
 static XrmOptionDescRec m6502_options [] = {
   { "-file",           ".file",     XrmoptionSepArg, 0 },
   { "-displaytime",    ".displaytime", XrmoptionSepArg, 0},
+  { "-ips",            ".ips",         XrmoptionSepArg, 0},
   ANALOGTV_OPTIONS
   { 0, 0, 0, 0 }
 };
@@ -302,6 +300,7 @@ m6502_free (Display *dpy, Window window, void *closure)
 {
   struct state *st = (struct state *) closure;
   analogtv_release(st->tv);
+  free (st->file);
   free (st);
 }
 
index d2e8806bc62a00780fd27325b7181be0c520dede..3a2ae73ede3b31d37739c6f318d247226ca50072 100644 (file)
@@ -254,6 +254,10 @@ static void Initialize( struct state *st )
         if (st->radius >= 128) /* should use UCHAR_MAX? */
           st->radius = 127; /* st->dradius should fit in u_char */
 
+        if (st->iWinWidth < 100 || st->iWinHeight < 100) /* tiny window */
+          if (st->radius < 20)
+            st->radius = 20;
+
        st->dradius = st->radius * 2;
        st->sradius = st->radius * st->radius;
 
index 0b6c9cd62b80d46ebfc16080973441df0b668131..dad9d660a8f28b724ca0005ab5e39824a6030a2c 100644 (file)
@@ -323,6 +323,7 @@ moire2_free (Display *dpy, Window window, void *closure)
 }
 
 static const char *moire2_defaults [] = {
+  ".lowrez:            true",
   ".background:                black",
   ".foreground:                white",
   "*delay:             50000",
index dcabbe54db3d9a412af2c9f20ddf2d1deed8e51e..541b18735beb798da4da25c08594b219e2521f27 100644 (file)
@@ -36,6 +36,8 @@ static const char sccsid[] = "@(#)mountain.c  5.00 2000/11/01 xlockmore";
 
 # define SMOOTH_COLORS
 # define release_mountain 0
+# define reshape_mountain 0
+# define mountain_handle_event 0
 # include "xlockmore.h"                /* in xscreensaver distribution */
 #else /* STANDALONE */
 # include "xlock.h"            /* in xlockmore distribution */
@@ -49,7 +51,7 @@ ENTRYPOINT ModeSpecOpt mountain_opts =
 #ifdef USE_MODULES
 ModStruct   mountain_description =
 {"mountain", "init_mountain", "draw_mountain", (char *) NULL,
- "refresh_mountain", "init_mountain", (char *) NULL, &mountain_opts,
+ "refresh_mountain", "init_mountain", "free_mountain", &mountain_opts,
  1000, 30, 4000, 1, 64, 1.0, "",
  "Shows Papo's mountain range", 0, NULL};
 
@@ -162,8 +164,6 @@ drawamountain(ModeInfo * mi)
                mp->stage++;
 }
 
-static void free_mountain (ModeInfo * mi);
-
 ENTRYPOINT void
 init_mountain (ModeInfo * mi)
 {
@@ -171,7 +171,7 @@ init_mountain (ModeInfo * mi)
        XGCValues   gcv;
        mountainstruct *mp;
 
-       MI_INIT (mi, mountains, free_mountain);
+       MI_INIT (mi, mountains);
        mp = &mountains[MI_SCREEN(mi)];
 
        mp->width = MI_WIDTH(mi);
@@ -253,14 +253,6 @@ draw_mountain (ModeInfo * mi)
 }
 
 ENTRYPOINT void
-reshape_mountain(ModeInfo * mi, int width, int height)
-{
-  XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi));
-  init_mountain (mi);
-}
-
-
-static void
 free_mountain (ModeInfo * mi)
 {
        mountainstruct *mp = &mountains[MI_SCREEN(mi)];
@@ -269,6 +261,7 @@ free_mountain (ModeInfo * mi)
                XFreeGC(MI_DISPLAY(mi), mp->stippledGC);
 }
 
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_mountain(ModeInfo * mi)
 {
@@ -282,17 +275,7 @@ refresh_mountain(ModeInfo * mi)
        mp->x = 0;
        mp->y = 0;
 }
-
-ENTRYPOINT Bool
-mountain_handle_event (ModeInfo *mi, XEvent *event)
-{
-  if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
-    {
-      init_mountain (mi);
-      return True;
-    }
-  return False;
-}
+#endif
 
 XSCREENSAVER_MODULE ("Mountain", mountain)
 
index a76e4e42ca3445f94265839e558f23c459525e62..836731a76e241eb0c5f200d24c1235a59982c54d 100644 (file)
@@ -127,7 +127,8 @@ static void calc_logwidths (struct state *st)
      window, it's too big.  Mismunched squares that big make things
      look too noisy. */
 
-  if (st->window_height < st->window_width) {
+  if (st->window_height < st->window_width &&
+      st->window_width < st->window_height * 5) {
     st->logmaxwidth = (int)dumb_log_2(st->window_height * 0.8);
   } else {
     st->logmaxwidth = (int)dumb_log_2(st->window_width * 0.8);
@@ -167,7 +168,7 @@ static muncher *make_muncher (struct state *st)
   m->atX = (random() % (xgwa.width <= m->width ? 1
                         : xgwa.width - m->width));
   m->atY = (random() % (xgwa.height <= m->width ? 1
-                        : xgwa.width - m->width));
+                        : xgwa.height - m->width));
 
   /* wrap-around by these values; no need to % as we end up doing that
      later anyway */
@@ -443,6 +444,7 @@ munch_free (Display *dpy, Window window, void *closure)
 
 
 static const char *munch_defaults [] = {
+  ".lowrez:           true",
   ".background:       black",
   ".foreground:       white",
   "*fpsSolid:        true",
@@ -454,6 +456,7 @@ static const char *munch_defaults [] = {
 #ifdef HAVE_MOBILE
   "*ignoreRotation:   True",
 #endif
+
   0
 };
 
index de3398ef93635cb6e85e7cd3c139f3869cd7af84..ae1b029bc9b71fb767e64f4eca57795aeda07e7e 100644 (file)
@@ -152,7 +152,7 @@ ModStruct pacman_description = {
     (char *) NULL,              /* *release_name; */
     "refresh_pacman",           /* *refresh_name; */
     "change_pacman",            /* *change_name; */
-    (char *) NULL,              /* *unused_name; */
+    "free_pacman",              /* *free_name; */
     &pacman_opts,               /* *msopts */
     10000, 4, 1, 0, 64, 1.0, "", "Shows Pacman(tm)", 0, NULL
 };
@@ -166,7 +166,7 @@ static void repopulate (ModeInfo * mi);
 static void drawlevel (ModeInfo * mi);
 
 
-static void
+ENTRYPOINT void
 free_pacman (ModeInfo * mi)
 {
     Display * display = MI_DISPLAY (mi);
@@ -207,7 +207,7 @@ reset_level (ModeInfo * mi, int n, int pac_init)
     pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)];
     unsigned int ghost;
 
-    MI_CLEARWINDOW (mi);
+    XClearWindow (MI_DISPLAY(mi), MI_WINDOW(mi));
     drawlevel (mi);
 
     pp->gamestate = GHOST_DANGER;
@@ -1490,7 +1490,7 @@ init_pacman (ModeInfo * mi)
     int dir, mouth;
 #endif
 
-    MI_INIT (mi, pacman_games, free_pacman);
+    MI_INIT (mi, pacman_games);
     pp = &pacman_games[MI_SCREEN (mi)];
 
     pp->width = (unsigned short) MI_WIDTH (mi);
@@ -1519,9 +1519,15 @@ init_pacman (ModeInfo * mi)
     if (size == 0 ||
         MINGRIDSIZE * size > (int) pp->width ||
         MINGRIDSIZE * size > (int) pp->height) {
-
-        pp->ys = pp->xs = MAX (MIN (pp->width / LEVWIDTH,
-                                    pp->height / LEVHEIGHT), 1);
+        double scale = MIN (pp->width / LEVWIDTH, pp->height / LEVHEIGHT);
+
+        if (pp->width > pp->height * 5 ||  /* weird window aspect ratio */
+            pp->height > pp->width * 5)
+            scale = 0.8 * (pp->width / pp->height
+                           ? pp->width / (double) pp->height
+                           : pp->height / (double) pp->width);
+        pp->ys = MAX (scale, 1);
+        pp->xs = pp->ys;
     }
     else {
         if (size < -MINSIZE)
@@ -1539,6 +1545,7 @@ init_pacman (ModeInfo * mi)
         pp->xs = pp->ys;
     }
 
+
     pp->wallwidth = (unsigned int) (pp->xs + pp->ys) >> 4;
     if (pp->wallwidth < 1)
         pp->wallwidth = 1;
@@ -1692,7 +1699,7 @@ init_pacman (ModeInfo * mi)
 
     pp->pacman.mouthstage = MAXMOUTH - 1;
 
-    MI_CLEARWINDOW (mi);
+    XClearWindow (MI_DISPLAY(mi), MI_WINDOW(mi));
     repopulate (mi);
 }
 
@@ -1748,6 +1755,7 @@ draw_pacman (ModeInfo * mi)
     pacman_tick (mi);
 }
 
+#ifndef STANDALONE
 /* Refresh current level. */
 ENTRYPOINT void
 refresh_pacman (ModeInfo * mi)
@@ -1755,6 +1763,7 @@ refresh_pacman (ModeInfo * mi)
     drawlevel (mi);
     pacman_tick (mi);
 }
+#endif
 
 ENTRYPOINT void
 reshape_pacman(ModeInfo * mi, int width, int height)
@@ -1764,7 +1773,7 @@ reshape_pacman(ModeInfo * mi, int width, int height)
     pp->height = height;
     pp->xb = (pp->width  - pp->ncols * pp->xs) >> 1;
     pp->yb = (pp->height - pp->nrows * pp->ys) >> 1;
-    MI_CLEARWINDOW (mi);
+    XClearWindow (MI_DISPLAY(mi), MI_WINDOW(mi));
     /* repopulate (mi); */
     drawlevel (mi);
 }
@@ -1774,7 +1783,7 @@ reshape_pacman(ModeInfo * mi, int width, int height)
 ENTRYPOINT void
 change_pacman (ModeInfo * mi)
 {
-    MI_CLEARWINDOW (mi);
+    XClearWindow (MI_DISPLAY(mi), MI_WINDOW(mi));
     repopulate (mi);
 }
 #endif /* !STANDALONE */
index b2b17e3b4383834f086161719330d4feec77dbda..a58efa21b3bf5883be211667114b98b895b2023b 100644 (file)
@@ -968,6 +968,7 @@ penetrate_free (Display *dpy, Window window, void *closure)
 
 
 static const char *penetrate_defaults [] = {
+  ".lowrez:     true",
   ".background:        black",
   ".foreground:        white",
   "*fpsTop:    true",
index 0836ee7326792f2202059e10bddeeed6fda8585e..a0afd6e5720a97681a2f5eecdba745fe4fe8d88f 100644 (file)
@@ -89,8 +89,8 @@ If one of these are hit penrose will reinitialize.
                                        "*fpsSolid: true \n" \
                                        "*ignoreRotation: True \n" \
 
-# define refresh_penrose 0
 # define release_penrose 0
+# define penrose_handle_event 0
 # include "xlockmore.h"                /* from the xscreensaver distribution */
 #else /* !STANDALONE */
 # include "xlock.h"            /* from the xlockmore distribution */
@@ -121,8 +121,8 @@ ENTRYPOINT ModeSpecOpt penrose_opts =
 
 #ifdef USE_MODULES
 ModStruct   penrose_description =
-{"penrose", "init_penrose", "draw_penrose", "release_penrose",
- "init_penrose", "init_penrose", (char *) NULL, &penrose_opts,
+{"penrose", "init_penrose", "draw_penrose", (char *) NULL,
+ "init_penrose", "init_penrose", "free_penrose", &penrose_opts,
  10000, 1, 1, -40, 64, 1.0, "",
  "Shows Penrose's quasiperiodic tilings", 0, NULL};
 
@@ -402,7 +402,7 @@ fived_to_loc(int fived[], tiling_c * tp, XPoint *pt)
 
 
 /* Mop up dynamic data for one screen. */
-static void
+ENTRYPOINT void
 free_penrose(ModeInfo * mi)
 {
        tiling_c * tp = &tilings[MI_SCREEN(mi)];
@@ -435,7 +435,7 @@ init_penrose(ModeInfo * mi)
        fringe_node_c *fp;
        int         i, size;
 
-       MI_INIT (mi, tilings, free_penrose);
+       MI_INIT (mi, tilings);
        tp = &tilings[MI_SCREEN(mi)];
 
 #if 0 /* if you do this, then the -ammann and -no-ammann options don't work.
@@ -530,6 +530,8 @@ init_penrose(ModeInfo * mi)
        fp->fived[i] = 2 * NRAND(2) - 1;
        fived_to_loc(fp->fived, tp, &(fp->loc));
        /* That's it!  We have created our first edge. */
+
+       MI_CLEARWINDOW(mi);
 }
 
 /*-
@@ -958,9 +960,13 @@ alloc_vertex(ModeInfo * mi, angle_c dir, fringe_node_c * from, tiling_c * tp)
        fived_to_loc(v->fived, tp, &(v->loc));
        if (v->loc.x < 0 || v->loc.y < 0
            || v->loc.x >= tp->width || v->loc.y >= tp->height) {
+        int ww = tp->width;
+        int hh = tp->height;
+        if (ww < 200) ww = 200;  /* tiny window */
+        if (hh < 200) hh = 200;
                v->off_screen = True;
-               if (v->loc.x < -tp->width || v->loc.y < -tp->height
-                 || v->loc.x >= 2 * tp->width || v->loc.y >= 2 * tp->height)
+               if (v->loc.x < -ww || v->loc.y < -hh ||
+            v->loc.x >= 2 * ww || v->loc.y >= 2 * hh)
                        tp->done = True;
        } else {
                v->off_screen = False;
@@ -1280,8 +1286,6 @@ draw_penrose(ModeInfo * mi)
        if (tp->fringe.nodes->prev == tp->fringe.nodes->next) {
                vertex_type_c vtype = (unsigned char) (VT_TOTAL_MASK & LRAND());
 
-               MI_CLEARWINDOW(mi);
-
                if (!add_tile(mi, tp->fringe.nodes, S_LEFT, vtype))
                        free_penrose(mi);
                return;
@@ -1334,18 +1338,6 @@ reshape_penrose(ModeInfo * mi, int width, int height)
        tp->height = height;
 }
 
-ENTRYPOINT Bool
-penrose_handle_event (ModeInfo *mi, XEvent *event)
-{
-  if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
-    {
-      init_penrose (mi);
-      return True;
-    }
-  return False;
-}
-
-
 XSCREENSAVER_MODULE ("Penrose", penrose)
 
 #endif /* MODE_penrose */
index a8469b0a58ac830d1ce1043233005a9c7bcaaf1e..0e448f1593224f2c7672e35b6c461f77bbcc4c44 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1999-2016 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1999-2017 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
@@ -70,6 +70,7 @@ typedef struct {
   const char *program;
   int grid_width, grid_height;
   int char_width, char_height;
+  int xmargin, ymargin;
   int saved_x, saved_y;
   int scale;
   int ticks;
@@ -211,8 +212,20 @@ phosphor_init (Display *dpy, Window window)
       state->char_height = font->max_bounds.ascent + font->max_bounds.descent;
     }
 
-  state->grid_width = state->xgwa.width / (state->char_width * state->scale);
-  state->grid_height = state->xgwa.height /(state->char_height * state->scale);
+# ifdef USE_IPHONE
+  /* Stupid iPhone X bezel.
+     #### This is the worst of all possible ways to do this!  But how else?
+   */
+  if (state->xgwa.width == 2436 || state->xgwa.height == 2436) {
+    state->xmargin = 96;
+    state->ymargin = state->xmargin;
+  }
+# endif
+
+  state->grid_width = ((state->xgwa.width - state->xmargin * 2) /
+                       (state->char_width * state->scale));
+  state->grid_height = ((state->xgwa.height - state->ymargin * 2) /
+                        (state->char_height * state->scale));
   state->cells = (p_cell *) calloc (sizeof(p_cell),
                                     state->grid_width * state->grid_height);
   state->chars = (p_char **) calloc (sizeof(p_char *), 256);
@@ -324,8 +337,8 @@ phosphor_init (Display *dpy, Window window)
 
   state->tc = textclient_open (dpy);
   textclient_reshape (state->tc,
-                      state->xgwa.width,
-                      state->xgwa.height,
+                      state->xgwa.width  - state->xmargin * 2,
+                      state->xgwa.height - state->ymargin * 2,
                       state->grid_width  - 1,
                       state->grid_height - 1,
                       0);
@@ -346,8 +359,17 @@ resize_grid (p_state *state)
 
   XGetWindowAttributes (state->dpy, state->window, &state->xgwa);
 
-  state->grid_width = state->xgwa.width   /(state->char_width  * state->scale);
-  state->grid_height = state->xgwa.height /(state->char_height * state->scale);
+  /* Would like to ensure here that
+     state->char_height * state->scale <= state->xgwa.height
+     but changing scale requires regenerating the bitmaps. */
+
+  state->grid_width  = ((state->xgwa.width - state->xmargin * 2) /
+                        (state->char_width  * state->scale));
+  state->grid_height = ((state->xgwa.height - state->ymargin * 2) /
+                        (state->char_height * state->scale));
+
+  if (state->grid_width  < 2) state->grid_width  = 2;
+  if (state->grid_height < 2) state->grid_height = 2;
 
   if (ow == state->grid_width &&
       oh == state->grid_height)
@@ -1238,10 +1260,10 @@ update_display (p_state *state, Bool changed_only)
         if (changed_only && !cell->changed)
           continue;
 
-        width = state->char_width * state->scale;
+        width  = state->char_width  * state->scale;
         height = state->char_height * state->scale;
-        tx = x * width;
-        ty = y * height;
+        tx = x * width  + state->xmargin;
+        ty = y * height + state->ymargin;
 
         if (cell->state == BLANK || cell->p_char->blank_p)
           {
@@ -1307,7 +1329,9 @@ phosphor_reshape (Display *dpy, Window window, void *closure,
 
   if (! changed_p) return;
 
-  textclient_reshape (state->tc, w, h,
+  textclient_reshape (state->tc,
+                      w - state->xmargin * 2,
+                      h - state->ymargin * 2,
                       state->grid_width  - 1,
                       state->grid_height - 1,
                       0);
@@ -1343,6 +1367,7 @@ phosphor_free (Display *dpy, Window window, void *closure)
 
 
 static const char *phosphor_defaults [] = {
+/*  ".lowrez:                true",*/
   ".background:                   Black",
   ".foreground:                   #00FF00",
   "*fpsSolid:             true",
index c89fb31f4c42c5d8be190299204f4e288de26bda..b87c3d33dc85e6fab7e41ffae7306d8a4b9808f5 100644 (file)
@@ -40,10 +40,10 @@ static const char sccsid[] = "@(#)polyominoes.c 5.01 2000/12/18 xlockmore";
                                        "*fpsSolid: true \n" \
 
 # define release_polyominoes 0
+# define reshape_polyominoes 0
 # define polyominoes_handle_event 0
 # define SMOOTH_COLORS
 # include "xlockmore.h"                /* in xscreensaver distribution */
-# include "erase.h"
 #else /* STANDALONE */
 # include "xlock.h"            /* in xlockmore distribution */
 #endif /* STANDALONE */
@@ -83,8 +83,8 @@ ENTRYPOINT ModeSpecOpt polyominoes_opts =
 #ifdef USE_MODULES
 ModStruct   polyominoes_description = {
   "polyominoes", "init_polyominoes", "draw_polyominoes", (char *) NULL,
-  "refresh_polyominoes", "init_polyominoes", (char *) NULL, &polyominoes_opts,
-  6000, 1, 8192, 1, 64, 1.0, "",
+  "refresh_polyominoes", "init_polyominoes", "free_polyominoes",
+  &polyominoes_opts, 6000, 1, 8192, 1, 64, 1.0, "",
   "Shows attempts to place polyominoes into a rectangle", 0, NULL
 };
 
@@ -177,10 +177,6 @@ typedef struct _polyominoesstruct{
   int *reason_to_not_attach;
 
   int counter;
-
-#ifdef STANDALONE
-  eraser_state *eraser;
-#endif
 } polyominoesstruct;
 
 #define ARRAY(x,y)         (sp->array[(x)*sp->height+(y)])
@@ -1053,7 +1049,7 @@ static void free_bitmaps(polyominoesstruct *sp)
 
 #define deallocate(p,t) if ((p)!=NULL) {free(p); p=(t*)NULL;}
 
-static void free_polyominoes(ModeInfo * mi)
+ENTRYPOINT void free_polyominoes(ModeInfo * mi)
 {
   polyominoesstruct *sp = &polyominoeses[MI_SCREEN(mi)];
   int n;
@@ -2099,7 +2095,7 @@ init_polyominoes (ModeInfo * mi)
   int box1, box2;
   int *perm;
 
-  MI_INIT (mi, polyominoeses, free_polyominoes);
+  MI_INIT (mi, polyominoeses);
   sp = &polyominoeses[MI_SCREEN(mi)];
 
   sp->rot180 = 0;
@@ -2176,6 +2172,12 @@ init_polyominoes (ModeInfo * mi)
     }
   }
 
+  if (MI_HEIGHT(mi) > MI_WIDTH(mi)) {  /* rotate if portrait */
+    int swap = sp->height;
+    sp->height = sp->width;
+    sp->width = swap;
+  }
+
   allocate(sp->attach_list,int,sp->nr_polyominoes*sizeof(int));
   sp->nr_attached = 0;
 
@@ -2197,6 +2199,13 @@ init_polyominoes (ModeInfo * mi)
   else
     sp->box = box2;
 
+  if (MI_WIDTH(mi) > MI_HEIGHT(mi) * 5 ||  /* weird window aspect ratio */
+      MI_HEIGHT(mi) > MI_WIDTH(mi)* 5) {
+    sp->box *= (MI_WIDTH(mi) > MI_HEIGHT(mi)
+                ? MI_WIDTH(mi) / (double) MI_HEIGHT(mi)
+                : MI_HEIGHT(mi) / (double) MI_WIDTH(mi));
+  }
+
   if (sp->box >= 12) {
     sp->box = (sp->box/12)*12;
     create_bitmaps(mi,sp);
@@ -2242,10 +2251,8 @@ init_polyominoes (ModeInfo * mi)
 
   sp->wait = 0;
 
-#ifndef STANDALONE
   /* Clear the background. */
   MI_CLEARWINDOW(mi);
-#endif
   
 }
 
@@ -2261,32 +2268,15 @@ draw_polyominoes (ModeInfo * mi)
     return;
   sp = &polyominoeses[MI_SCREEN(mi)];
 
-#ifdef STANDALONE
-    if (sp->eraser) {
-      sp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), sp->eraser);
-      if (!sp->eraser)
-        init_polyominoes(mi);
-      return;
-    }
-#endif
-
   if (MI_CYCLES(mi) != 0) {
     if (++sp->counter > MI_CYCLES(mi)) {
-#ifdef STANDALONE
-      sp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), sp->eraser);
-#else /* !STANDALONE */
       init_polyominoes(mi);
-#endif /* !STANDALONE */
       return;
     }
   }
 
   if (sp->box == 0) {
-#ifdef STANDALONE
-    sp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), sp->eraser);
-#else /* !STANDALONE */
     init_polyominoes(mi);
-#endif
     return;
   }
 
@@ -2365,18 +2355,13 @@ draw_polyominoes (ModeInfo * mi)
     sp->wait = 0;
 }
 
-ENTRYPOINT void
-reshape_polyominoes(ModeInfo * mi, int width, int height)
-{
-  XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi));
-  init_polyominoes (mi);
-}
-
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_polyominoes (ModeInfo * mi)
 {
   MI_CLEARWINDOW(mi);
 }
+#endif
 
 XSCREENSAVER_MODULE ("Polyominoes", polyominoes)
 
index 065ad06d4e9189642e06dffb75826d20a57ccf1b..3b83fd768be60b57db5601d42b288341ef508cc3 100644 (file)
@@ -35,7 +35,7 @@ struct state {
   Display *dpy;
   Window window;
 
-   int delay, subdivision, border, ncolors, twitch, dbuf;
+   int delay, subdivisionx, subdivisiony, border, ncolors, twitch, dbuf;
     XWindowAttributes xgwa;
     GC gc; 
     XColor *colors;
@@ -47,6 +47,73 @@ struct state {
 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
 };
 
+static void
+popsquares_reshape (Display *dpy, Window window, void *closure, 
+                 unsigned int w, unsigned int h)
+{
+  struct state *st = (struct state *) closure;
+  int s = get_integer_resource(st->dpy, "subdivision", "Integer");
+  int x, y;
+  XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
+
+  if (st->xgwa.width < 100 || st->xgwa.height < 100) /* tiny window */
+    {
+      int ss = (st->xgwa.width < st->xgwa.height
+                ? st->xgwa.width : st->xgwa.height);
+      s = ss / 15;
+      if (s < 1) s = 1;
+    }
+
+  if (st->xgwa.width > st->xgwa.height * 5 ||  /* weird aspect ratio */
+      st->xgwa.height > st->xgwa.width * 5)
+    {
+      double r = st->xgwa.width / (double) st->xgwa.height;
+      if (r > 1)
+        {
+          st->subdivisiony = s;
+          st->subdivisionx = s * r;
+        }
+      else
+        {
+          st->subdivisionx = s;
+          st->subdivisiony = s / r;
+        }
+    }
+  else
+    {
+      st->subdivisionx = st->subdivisiony = s;
+    }
+
+  st->sw = st->xgwa.width / st->subdivisionx;
+  st->sh = st->xgwa.height / st->subdivisiony;
+  st->gw = st->sw ? st->xgwa.width / st->sw : 0;
+  st->gh = st->sh ? st->xgwa.height / st->sh : 0;
+  st->nsquares = st->gw * st->gh;
+  free (st->squares);
+  if (st->nsquares < 1) st->nsquares = 1;
+  st->squares = (square *) calloc (st->nsquares, sizeof(square));
+
+  for (y = 0; y < st->gh; y++)
+    for (x = 0; x < st->gw; x++) 
+      {
+        square *s = (square *) &st->squares[st->gw * y + x];
+        s->w = st->sw;
+        s->h = st->sh;
+        s->x = x * st->sw;
+        s->y = y * st->sh;
+      }
+
+  randomize_square_colors(st->squares, st->nsquares, st->ncolors);
+
+  if (st->dbuf) {
+    XFreePixmap (dpy, st->ba);
+    XFreePixmap (dpy, st->bb);
+    st->ba = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height, st->xgwa.depth);
+    st->bb = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height, st->xgwa.depth);
+    st->b = st->ba;
+  }
+}
+
 static void *
 popsquares_init (Display *dpy, Window window)
 {
@@ -63,7 +130,8 @@ popsquares_init (Display *dpy, Window window)
   st->window = window;
 
   st->delay = get_integer_resource (st->dpy, "delay", "Integer");
-  st->subdivision = get_integer_resource(st->dpy, "subdivision", "Integer");
+  st->subdivisionx = get_integer_resource(st->dpy, "subdivision", "Integer");
+  st->subdivisiony = st->subdivisionx;
   st->border = get_integer_resource(st->dpy, "border", "Integer");
   st->ncolors = get_integer_resource(st->dpy, "ncolors", "Integer");
   st->twitch = get_boolean_resource(st->dpy, "twitch", "Boolean");
@@ -81,8 +149,8 @@ popsquares_init (Display *dpy, Window window)
   XQueryColor (st->dpy, st->xgwa.colormap, &fg);
   XQueryColor (st->dpy, st->xgwa.colormap, &bg);
 
-  st->sw = st->xgwa.width / st->subdivision;
-  st->sh = st->xgwa.height / st->subdivision;
+  st->sw = st->xgwa.width / st->subdivisionx;
+  st->sh = st->xgwa.height / st->subdivisiony;
   st->gw = st->sw ? st->xgwa.width / st->sw : 0;
   st->gh = st->sh ? st->xgwa.height / st->sh : 0;
   st->nsquares = st->gw * st->gh;
@@ -139,6 +207,8 @@ popsquares_init (Display *dpy, Window window)
       st->b = st->window;
     }
 
+  popsquares_reshape (dpy, window, st, st->xgwa.width, st->xgwa.height);
+
   return st;
 }
 
@@ -185,43 +255,6 @@ popsquares_draw (Display *dpy, Window window, void *closure)
 }
 
 
-static void
-popsquares_reshape (Display *dpy, Window window, void *closure, 
-                 unsigned int w, unsigned int h)
-{
-  struct state *st = (struct state *) closure;
-  int x, y;
-  XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
-  st->sw = st->xgwa.width / st->subdivision;
-  st->sh = st->xgwa.height / st->subdivision;
-  st->gw = st->sw ? st->xgwa.width / st->sw : 0;
-  st->gh = st->sh ? st->xgwa.height / st->sh : 0;
-  st->nsquares = st->gw * st->gh;
-  free (st->squares);
-  if (st->nsquares < 1) st->nsquares = 1;
-  st->squares = (square *) calloc (st->nsquares, sizeof(square));
-
-  for (y = 0; y < st->gh; y++)
-    for (x = 0; x < st->gw; x++) 
-      {
-        square *s = (square *) &st->squares[st->gw * y + x];
-        s->w = st->sw;
-        s->h = st->sh;
-        s->x = x * st->sw;
-        s->y = y * st->sh;
-      }
-
-  randomize_square_colors(st->squares, st->nsquares, st->ncolors);
-
-  if (st->dbuf) {
-    XFreePixmap (dpy, st->ba);
-    XFreePixmap (dpy, st->bb);
-    st->ba = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height, st->xgwa.depth);
-    st->bb = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height, st->xgwa.depth);
-    st->b = st->ba;
-  }
-}
-
 static Bool
 popsquares_event (Display *dpy, Window window, void *closure, XEvent *event)
 {
index 1c46a85fa8bd6f683e27f5df33f76d5262c3568c..442ea7f0da67ddb5a6a416b7793c088767bf5e1a 100644 (file)
@@ -346,6 +346,7 @@ pyro_free (Display *dpy, Window window, void *closure)
 \f
 
 static const char *pyro_defaults [] = {
+  ".lowrez:     true",
   ".background:        black",
   ".foreground:        white",
   "*fpsSolid:  true",
index 51379ed0a2ce2fa4903004233f4e4e2b0ff09c1c..091b9180b7386a6f01796e4350c4878af9a8cefe 100644 (file)
@@ -307,13 +307,15 @@ screenhack_record_anim_free (record_anim_state *st)
 
   sprintf (cmd,
            "ffmpeg"
+           " -hide_banner"
+           " -v 16"
            " -framerate 30"    /* rate of input: must be before -i */
            " -i '%s-%%06d.%s'"
            " -r 30",           /* rate of output: must be after -i */
            progname, type);
   if (soundtrack)
     sprintf (cmd + strlen(cmd),
-             " -i '%s' -map 0:v:0 -map 1:a:0 -acodec libfaac",
+             " -i '%s' -map 0:v:0 -map 1:a:0 -acodec aac",
              soundtrack);
   sprintf (cmd + strlen(cmd),
            " -c:v libx264"
@@ -321,7 +323,7 @@ screenhack_record_anim_free (record_anim_state *st)
            " -crf 18"
            " -pix_fmt yuv420p"
            " '%s'"
-           " 2>&-",
+           /*" 2>&-"*/,
            fn);
   fprintf (stderr, "%s: exec: %s\n", progname, cmd);
   system (cmd);
index 7e82b24db8e70e02fc0802ce21712bde9b022be3..5a976df65fcd308000aa10d827977f97eefaf0be 100644 (file)
@@ -510,6 +510,7 @@ rocks_free (Display *dpy, Window window, void *closure)
 \f
 
 static const char *rocks_defaults [] = {
+  ".lowrez:     true",
   ".background:        Black",
   ".foreground:        #E9967A",
   "*fpsSolid:  true",
index 293b273cb58bfbfc4b108c191d5c6cba5c8ec0dd..c22479b9f4d4ee7ff684a6c49ba60baa75e99791 100644 (file)
@@ -39,8 +39,10 @@ static const char sccsid[] = "@(#)rotor.c    5.00 2000/11/01 xlockmore";
                                        "*size: -6 \n" \
                                        "*ncolors: 200 \n" \
                                        "*fpsSolid: true \n" \
+                                   "*lowrez: True \n" \
 
 # define SMOOTH_COLORS
+# define release_rotor 0
 # define reshape_rotor 0
 # define rotor_handle_event 0
 # include "xlockmore.h"                /* in xscreensaver distribution */
@@ -55,8 +57,8 @@ ENTRYPOINT ModeSpecOpt rotor_opts =
 
 #ifdef USE_MODULES
 ModStruct   rotor_description =
-{"rotor", "init_rotor", "draw_rotor", "release_rotor",
- "refresh_rotor", "init_rotor", (char *) NULL, &rotor_opts,
+{"rotor", "init_rotor", "draw_rotor", (char *) NULL,
+ "refresh_rotor", "init_rotor", "free_rotor", &rotor_opts,
  100, 4, 100, -6, 64, 0.3, "",
  "Shows Tom's Roto-Rooter", 0, NULL};
 
@@ -106,9 +108,10 @@ typedef struct {
 
 static rotorstruct *rotors = (rotorstruct *) NULL;
 
-static void
-free_rotor(rotorstruct *rp)
+ENTRYPOINT void
+free_rotor(ModeInfo * mi)
 {
+       rotorstruct *rp = &rotors[MI_SCREEN(mi)];
        if (rp->elements != NULL) {
                (void) free((void *) rp->elements);
                rp->elements = (elem *) NULL;
@@ -127,7 +130,7 @@ init_rotor (ModeInfo * mi)
        unsigned char wasiconified;
        rotorstruct *rp;
 
-       MI_INIT (mi, rotors, 0);
+       MI_INIT (mi, rotors);
        rp = &rotors[MI_SCREEN(mi)];
 
 #ifdef HAVE_JWXYZ
@@ -175,7 +178,7 @@ init_rotor (ModeInfo * mi)
                if (rp->elements == NULL)
                        if ((rp->elements = (elem *) calloc(rp->num,
                                        sizeof (elem))) == NULL) {
-                               free_rotor(rp);
+                               free_rotor(mi);
                                return;
                        }
                rp->nsave = MI_CYCLES(mi);
@@ -184,7 +187,7 @@ init_rotor (ModeInfo * mi)
                if (rp->save == NULL)
                        if ((rp->save = (XPoint *) malloc(rp->nsave *
                                        sizeof (XPoint))) == NULL) {
-                               free_rotor(rp);
+                               free_rotor(mi);
                                return;
                        }
                for (x = 0; x < rp->nsave; x++) {
@@ -365,19 +368,7 @@ draw_rotor (ModeInfo * mi)
                           LineSolid, CapButt, JoinMiter);
 }
 
-ENTRYPOINT void
-release_rotor (ModeInfo * mi)
-{
-       if (rotors != NULL) {
-               int         screen;
-
-               for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
-                       free_rotor(&rotors[screen]);
-               (void) free((void *) rotors);
-               rotors = (rotorstruct *) NULL;
-       }
-}
-
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_rotor (ModeInfo * mi)
 {
@@ -391,6 +382,7 @@ refresh_rotor (ModeInfo * mi)
        rp->redrawing = 1;
        rp->redrawpos = 1;
 }
+#endif
 
 XSCREENSAVER_MODULE ("Rotor", rotor)
 
index 4850911db59bb5415c966d692e7905d17a846f90..addc960ebbfa938c4e3e97a957577fa279d25a26 100644 (file)
@@ -555,10 +555,12 @@ run_screenhack_table (Display *dpy,
 
   void *closure = init_cb (dpy, window, ft->setup_arg);
   fps_state *fpst = fps_init (dpy, window);
+  unsigned long delay = 0;
 
 #ifdef DEBUG_PAIR
   void *closure2 = 0;
   fps_state *fpst2 = 0;
+  unsigned long delay2 = 0;
   if (window2) closure2 = init_cb (dpy, window2, ft->setup_arg);
   if (window2) fpst2 = fps_init (dpy, window2);
 #endif
@@ -570,17 +572,6 @@ run_screenhack_table (Display *dpy,
 
   while (1)
     {
-      unsigned long delay = ft->draw_cb (dpy, window, closure);
-#ifdef DEBUG_PAIR
-      unsigned long delay2 = 0;
-      if (window2) delay2 = ft->draw_cb (dpy, window2, closure2);
-#endif
-
-      if (fpst) fps_cb (dpy, window, fpst, closure);
-#ifdef DEBUG_PAIR
-      if (fpst2) fps_cb (dpy, window2, fpst2, closure2);
-#endif
-
       if (! usleep_and_process_events (dpy, ft,
                                        window, fpst, closure, delay
 #ifdef DEBUG_PAIR
@@ -591,6 +582,17 @@ run_screenhack_table (Display *dpy,
 #endif
                                        ))
         break;
+
+      delay = ft->draw_cb (dpy, window, closure);
+#ifdef DEBUG_PAIR
+      delay2 = 0;
+      if (window2) delay2 = ft->draw_cb (dpy, window2, closure2);
+#endif
+
+      if (fpst) fps_cb (dpy, window, fpst, closure);
+#ifdef DEBUG_PAIR
+      if (fpst2) fps_cb (dpy, window2, fpst2, closure2);
+#endif
     }
 
 #ifdef HAVE_RECORD_ANIM
index 3e3d89b30a6ea0b500ee1f40394954b3b1015011..ceaca2b8017f951ac7c94bf3ac879865c47ad25c 100644 (file)
@@ -40,9 +40,11 @@ static const char sccsid[] = "@(#)sierpinski.c       5.00 2000/11/01 xlockmore";
                                        "*ncolors: 64 \n" \
                                        "*fpsSolid: true \n" \
                                        "*ignoreRotation: True \n" \
+                                   "*lowrez: True \n" \
 
 # define BRIGHT_COLORS
 # define release_sierpinski 0
+# define reshape_sierpinski 0
 # define sierpinski_handle_event 0
 # include "xlockmore.h"                /* in xscreensaver distribution */
 #else /* STANDALONE */
@@ -57,7 +59,7 @@ ENTRYPOINT ModeSpecOpt sierpinski_opts =
 #ifdef USE_MODULES
 ModStruct   sierpinski_description =
 {"sierpinski", "init_sierpinski", "draw_sierpinski", (char *) NULL,
- "refresh_sierpinski", "init_sierpinski", (char *) NULL, &sierpinski_opts,
+ "refresh_sierpinski", "init_sierpinski", "free_sierpinski", &sierpinski_opts,
  400000, 2000, 100, 1, 64, 1.0, "",
  "Shows Sierpinski's triangle", 0, NULL};
 
@@ -115,7 +117,7 @@ startover(ModeInfo * mi)
        MI_CLEARWINDOW(mi);
 }
 
-static void
+ENTRYPOINT void
 free_sierpinski(ModeInfo * mi)
 {
        sierpinskistruct *sp = &tris[MI_SCREEN(mi)];
@@ -134,7 +136,7 @@ init_sierpinski(ModeInfo * mi)
        int         i;
        sierpinskistruct *sp;
 
-       MI_INIT (mi, tris, free_sierpinski);
+       MI_INIT (mi, tris);
        sp = &tris[MI_SCREEN(mi)];
 
        sp->width = MI_WIDTH(mi);
@@ -198,18 +200,13 @@ draw_sierpinski(ModeInfo * mi)
                startover(mi);
 }
 
-ENTRYPOINT void
-reshape_sierpinski(ModeInfo * mi, int width, int height)
-{
-  XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi));
-  init_sierpinski (mi);
-}
-
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_sierpinski(ModeInfo * mi)
 {
        MI_CLEARWINDOW(mi);
 }
+#endif
 
 XSCREENSAVER_MODULE ("Sierpinski", sierpinski)
 
index 313f0eecff0ad5bce43621e379bf91e9095caf62..190f50711f8f8a205932ebb306dba3955a987fad 100644 (file)
@@ -198,6 +198,16 @@ draw_grid (struct state *st)
   st->bitmap_w = xgwa.width;
   st->bitmap_h = xgwa.height;
 
+  if (xgwa.width < 50 || xgwa.height < 50) /* tiny window */
+    {
+      int s = (xgwa.width < xgwa.height ? xgwa.width : xgwa.height);
+      border = 1;
+      st->grid_size = s / 2;
+      if (st->grid_size < 16) st->grid_size = 16;
+      if (st->bitmap_w < st->grid_size*2) st->bitmap_w = st->grid_size*2;
+      if (st->bitmap_h < st->grid_size*2) st->bitmap_h = st->grid_size*2;
+    }
+
   st->grid_w = st->bitmap_w / st->grid_size;
   st->grid_h = st->bitmap_h / st->grid_size;
   st->hole_x = random () % st->grid_w;
index 6537086b731aab668da321c51a8709b7a2dcaea4..04a306371f72d6d46aafc607fbec0a8a75927cc8 100644 (file)
@@ -34,7 +34,7 @@ static const char sccsid[] = "@(#)slip.c      5.00 2000/11/01 xlockmore";
                                        "*fpsSolid:     true \n" \
                                        "*ignoreRotation: True \n" \
 
-# define refresh_slip 0
+# define free_slip 0
 # define release_slip 0
 # include "xlockmore.h"                /* in xscreensaver distribution */
 #else /* STANDALONE */
@@ -118,7 +118,7 @@ image_loaded_cb (Screen *screen, Window w, Drawable d,
 }
 #endif /* STANDALONE */
 
-static void
+static Bool
 prepare_screen(ModeInfo * mi, slipstruct * sp)
 {
 
@@ -129,12 +129,17 @@ prepare_screen(ModeInfo * mi, slipstruct * sp)
 
        sp->backwards = (int) (LRAND() & 1);    /* jwz: go the other way sometimes */
 
-       if (sp->first_time || !halfrandom(sp, 10)) {
-               MI_CLEARWINDOW(mi);
+       if (sp->first_time) {
+               XClearWindow (display, MI_WINDOW(mi));
                n = 300;
+       } else if (!sp->image_loading_p && !halfrandom(sp, 10)) {
+               sp->first_time = 1;
+               sp->nblits_remaining = 0;
+               MI_CLEARWINDOW(mi);
+               return False;
        } else {
                if (halfrandom(sp, 5))
-                       return;
+                       return True;
                if (halfrandom(sp, 5))
                        n = 100;
                else
@@ -180,6 +185,8 @@ prepare_screen(ModeInfo * mi, slipstruct * sp)
                         MI_WINDOW(mi), p, image_loaded_cb, mi);
        }
 #endif
+
+       return True;
 }
 
 static int
@@ -211,7 +218,7 @@ init_slip (ModeInfo * mi)
 {
        slipstruct *sp;
 
-       MI_INIT (mi, slips, 0);
+       MI_INIT (mi, slips);
        sp = &slips[MI_SCREEN(mi)];
 
        sp->nblits_remaining = 0;
@@ -239,8 +246,6 @@ draw_slip (ModeInfo * mi)
 
        timer = MI_COUNT(mi) * MI_CYCLES(mi);
 
-       MI_IS_DRAWN(mi) = True;
-
        while (timer--) {
                int         xi = halfrandom(sp, MAX(sp->width - sp->blit_width, 1));
                int         yi = halfrandom(sp, MAX(sp->height - sp->blit_height, 1));
@@ -249,7 +254,9 @@ draw_slip (ModeInfo * mi)
                if (0 == sp->nblits_remaining--) {
                        static const int lut[] = {0, 0, 0, 1, 1, 1, 2};
 
-                       prepare_screen(mi, sp);
+                       if (!prepare_screen(mi, sp))
+                               break;
+                       MI_IS_DRAWN(mi) = True;
                        sp->nblits_remaining = MI_COUNT(mi) *
                                (2000 + halfrandom(sp, 1000) + halfrandom(sp, 1000));
                        if (sp->mode == 2)
index edeaa8f7597b8df6d2f4eb7090dcd700604e80f6..d35720e9e66d21ee3b89513f15c257bd5d0814a5 100644 (file)
@@ -65,6 +65,7 @@ static const char sccsid[] = "@(#)sphere.c    5.00 2000/11/01 xlockmore";
                                        "*fpsSolid: true \n" \
 
 # define BRIGHT_COLORS
+# define release_sphere 0
 # define reshape_sphere 0
 # define sphere_handle_event 0
 # include "xlockmore.h"                /* from the xscreensaver distribution */
@@ -79,8 +80,8 @@ ENTRYPOINT ModeSpecOpt sphere_opts =
 
 #ifdef USE_MODULES
 ModStruct   sphere_description =
-{"sphere", "init_sphere", "draw_sphere", "release_sphere",
- "refresh_sphere", "init_sphere", (char *) NULL, &sphere_opts,
+{"sphere", "init_sphere", "draw_sphere", (char *) NULL,
+ "refresh_sphere", "init_sphere", "free_sphere", &sphere_opts,
  5000, 1, 20, 0, 64, 1.0, "",
  "Shows a bunch of shaded spheres", 0, NULL};
 
@@ -115,7 +116,7 @@ init_sphere(ModeInfo * mi)
 {
        spherestruct *sp;
 
-       MI_INIT (mi, spheres, 0);
+       MI_INIT (mi, spheres);
        sp = &spheres[MI_SCREEN(mi)];
 
        if (sp->points != NULL) {
@@ -267,24 +268,21 @@ draw_sphere(ModeInfo * mi)
 }
 
 ENTRYPOINT void
-release_sphere(ModeInfo * mi)
+free_sphere(ModeInfo * mi)
 {
-       if (spheres != NULL) {
-               int         screen;
+       spherestruct *sp;
 
-               for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
-                       spherestruct *sp = &spheres[screen];
+       if (spheres == NULL)
+               return;
+       sp = &spheres[MI_SCREEN(mi)];
 
-                       if (sp->points) {
-                               (void) free((void *) sp->points);
-                               /* sp->points = NULL; */
-                       }
-               }
-               (void) free((void *) spheres);
-               spheres = (spherestruct *) NULL;
+       if (sp->points) {
+               (void) free((void *) sp->points);
+               /* sp->points = NULL; */
        }
 }
 
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_sphere(ModeInfo * mi)
 {
@@ -298,6 +296,7 @@ refresh_sphere(ModeInfo * mi)
 
        sp->x = -sp->radius;
 }
+#endif
 
 XSCREENSAVER_MODULE ("Sphere", sphere)
 
index fc73104ca7800d141d03dadfa0b3caee23b4870f..3d8159beaf46e90c223710ffd92e826a6a729e86 100644 (file)
@@ -42,6 +42,7 @@ static const char sccsid[] = "@(#)spiral.c    5.00 2000/11/01 xlockmore";
                                        "*fpsSolid: true \n" \
 
 # define SMOOTH_COLORS
+# define release_spiral 0
 # define reshape_spiral 0
 # define spiral_handle_event 0
 # include "xlockmore.h"                /* from the xscreensaver distribution */
@@ -56,8 +57,8 @@ ENTRYPOINT ModeSpecOpt spiral_opts =
 
 #ifdef USE_MODULES
 ModStruct   spiral_description =
-{"spiral", "init_spiral", "draw_spiral", "release_spiral",
- "refresh_spiral", "init_spiral", (char *) NULL, &spiral_opts,
+{"spiral", "init_spiral", "draw_spiral", (char *) NULL,
+ "refresh_spiral", "init_spiral", "free_spiral", &spiral_opts,
  5000, -40, 350, 1, 64, 1.0, "",
  "Shows a helical locus of points", 0, NULL};
 
@@ -127,7 +128,7 @@ init_spiral(ModeInfo * mi)
        spiralstruct *sp;
        int         i;
 
-       MI_INIT (mi, spirals, 0);
+       MI_INIT (mi, spirals);
        sp = &spirals[MI_SCREEN(mi)];
 
 #ifdef HAVE_JWXYZ
@@ -296,22 +297,19 @@ draw_spiral(ModeInfo * mi)
 }
 
 ENTRYPOINT void
-release_spiral(ModeInfo * mi)
+free_spiral(ModeInfo * mi)
 {
-       if (spirals != NULL) {
-               int         screen;
+       spiralstruct *sp;
 
-               for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
-                       spiralstruct *sp = &spirals[screen];
+       if (spirals == NULL)
+               return;
+       sp = &spirals[MI_SCREEN(mi)];
 
-                       if (sp->traildots)
-                               (void) free((void *) sp->traildots);
-               }
-               (void) free((void *) spirals);
-               spirals = (spiralstruct *) NULL;
-       }
+       if (sp->traildots)
+               (void) free((void *) sp->traildots);
 }
 
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_spiral(ModeInfo * mi)
 {
@@ -325,6 +323,7 @@ refresh_spiral(ModeInfo * mi)
        sp->redrawing = 1;
        sp->redrawpos = 0;
 }
+#endif
 
 XSCREENSAVER_MODULE ("Spiral", spiral)
 
index 48cd5f8c9049e11b5560973d0e0820a89bff58e1..a38e0603dd28fa85bc366b47916c0edfdb8652b6 100644 (file)
@@ -258,6 +258,7 @@ squiral_free (Display *dpy, Window window, void *closure)
 
 
 static const char *squiral_defaults[] = {
+  ".lowrez:     true",
   ".background: black",
   ".foreground: white",
   "*fpsSolid:  true",
index 5fa3395e9aa979f72ab07752df1a47f326096185..5e94144401a4d51ce67e681f8481a2ca0b720534 100644 (file)
@@ -322,6 +322,13 @@ make_window_starfish (struct state *st)
   size = (xgwa.width < xgwa.height ? xgwa.width : xgwa.height);
   if (st->blob_p) size /= 2;
   else size *= 1.3;
+
+  if (xgwa.width < 100 || xgwa.height < 100) /* tiny window */
+    {
+      size = (xgwa.width > xgwa.height ? xgwa.width : xgwa.height);
+      if (size < 100) size = 100;
+    }
+
   return make_starfish (st, xgwa.width, xgwa.height, size);
 }
 
index 5e59ba4a0df0f5009b9b2e3f491d3e27e11da5a0..89e9a3bc455cc677c291913a9666728abca01b51 100644 (file)
@@ -55,10 +55,12 @@ static const char sccsid[] = "@(#)strange.c 5.00 2000/11/01 xlockmore";
                                        "*ignoreRotation: True \n" \
                                        "*useSHM: True \n" \
                                        "*useThreads: True \n" \
+                                   "*lowrez: True \n" \
 
 # define SMOOTH_COLORS
-# define refresh_strange 0
 # define release_strange 0
+# define reshape_strange 0
+# define strange_handle_event 0
 # include "xlockmore.h"                /* from the xscreensaver distribution */
 #else /* !STANDALONE */
 # include "xlock.h"            /* from the xlockmore distribution */
@@ -68,6 +70,7 @@ static const char sccsid[] = "@(#)strange.c   5.00 2000/11/01 xlockmore";
 #include <errno.h>
 #include "pow2.h"
 #include "thread_util.h"
+#include "xshm.h"
 
 #ifdef HAVE_INTTYPES_H
 # include <inttypes.h>
@@ -123,7 +126,7 @@ sizeof vars / sizeof vars[0], vars, desc};
 #ifdef USE_MODULES
 ModStruct   strange_description =
 {"strange", "init_strange", "draw_strange", (char *) NULL,
-"init_strange", "init_strange", (char *) NULL, &strange_opts,
+"init_strange", "init_strange", "free_strange", &strange_opts,
 10000, 1, 1, 1, 64, 1.0, "",
 "Shows strange attractors", 0, NULL};
 #endif
@@ -415,7 +418,7 @@ static void (*Funcs[2]) (const ATTRACTOR *, PRM, PRM, PRM *, PRM *) = {
 
 /***************************************************************/
 
-static void
+ENTRYPOINT void
 free_strange(ModeInfo *mi)
 {
        Display *display = MI_DISPLAY(mi);
@@ -1086,7 +1089,7 @@ init_strange(ModeInfo * mi)
 
        if (curve <= 0) curve = 10;
 
-       MI_INIT (mi, Root, free_strange);
+       MI_INIT (mi, Root);
        Attractor = &Root[MI_SCREEN(mi)];
 
        if (Attractor->Fold == NULL) {
@@ -1329,28 +1332,9 @@ init_strange(ModeInfo * mi)
        XSetGraphicsExposures(display, MI_GC(mi), False);
 }
 
-ENTRYPOINT void
-reshape_strange(ModeInfo * mi, int width, int height)
-{
-  XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi));
-  init_strange (mi);
-}
-
 /***************************************************************/
 
 #ifdef STANDALONE
-ENTRYPOINT Bool
-strange_handle_event (ModeInfo *mi, XEvent *event)
-{
-  if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
-    {
-      reshape_strange (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
-      return True;
-    }
-  return False;
-}
-
-
 XSCREENSAVER_MODULE ("Strange", strange)
 #endif
 
index 96a4e6338228d56dd6d39a8236d57b587d4b51d1..5a2e97b7d5f959cab96739f18240364fc3578153 100644 (file)
@@ -41,6 +41,8 @@ static const char sccsid[] = "@(#)swirl.c     4.00 97/01/01 xlockmore";
 # define SMOOTH_COLORS
 # define WRITABLE_COLORS
 # define release_swirl 0
+# define reshape_swirl 0
+# define swirl_handle_event 0
 # include "xlockmore.h"                                /* from the xscreensaver distribution */
 # include "xshm.h"
 #else  /* !STANDALONE */
@@ -1212,8 +1214,6 @@ next_point(SWIRL_P swirl)
 
 /****************************************************************/
 
-static void free_swirl (ModeInfo * mi);
-
 /* 
  * init_swirl
  *
@@ -1228,7 +1228,7 @@ init_swirl(ModeInfo * mi)
        Window      window = MI_WINDOW(mi);
        SWIRL_P     swirl;
 
-       MI_INIT (mi, swirls, free_swirl);
+       MI_INIT (mi, swirls);
        swirl = &(swirls[MI_SCREEN(mi)]);
     initialise_swirl(mi, swirl);
                 
@@ -1403,16 +1403,9 @@ draw_swirl(ModeInfo * mi)
        }
 }
 
-ENTRYPOINT void
-reshape_swirl(ModeInfo * mi, int width, int height)
-{
-  XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi));
-  init_swirl (mi);
-}
-
 /****************************************************************/
 
-static void
+ENTRYPOINT void
 free_swirl (ModeInfo * mi)
 {
        SWIRL_P     swirl = &(swirls[MI_SCREEN(mi)]);
@@ -1434,6 +1427,7 @@ free_swirl (ModeInfo * mi)
 
 /****************************************************************/
 
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_swirl (ModeInfo * mi)
 {
@@ -1445,16 +1439,6 @@ refresh_swirl (ModeInfo * mi)
                swirl->drawing = False;
        }
 }
-
-ENTRYPOINT Bool
-swirl_handle_event (ModeInfo *mi, XEvent *event)
-{
-  if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
-    {
-      reshape_swirl (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
-      return True;
-    }
-  return False;
-}
+#endif
 
 XSCREENSAVER_MODULE ("Swirl", swirl)
index 554c704e4e1bfd87b5407d10482e91bc4e30d39a..7932a3736fb483c7b98705c875cf19a761d502bf 100644 (file)
@@ -16,6 +16,8 @@
 
 #include "screenhack.h"
 #include "glx/rotator.h"
+#include "colorbars.h"
+#include "erase.h"
 
 #include <assert.h>
 #include <errno.h>
@@ -50,6 +52,7 @@ enum
   mode_images,
   mode_copy,
   mode_preserve,
+  mode_erase,
 
   mode_count
 };
@@ -95,6 +98,8 @@ struct testx11 {
 
   Pixmap preserve[2];
 
+  eraser_state *erase;
+
   rotator *rot;
 };
 
@@ -211,6 +216,14 @@ make_clip_mask (struct testx11 *st)
 }
 
 
+static void
+colorbars (struct testx11 *st)
+{
+  draw_colorbars (st->xgwa.screen, st->xgwa.visual, st->win,
+                  st->xgwa.colormap, 0, 0, st->xgwa.width, st->xgwa.height);
+}
+
+
 static void *
 testx11_init (Display *dpy, Window win)
 {
@@ -315,7 +328,7 @@ testx11_init (Display *dpy, Window win)
 
   {
     static const char text[] = "Welcome from testx11_init().";
-    XClearWindow (dpy, win);
+    colorbars (st);
     XDrawString (dpy, win, st->copy_gc, 16, 16, text, countof (text) - 1);
   }
 
@@ -840,6 +853,12 @@ testx11_draw (Display *dpy, Window win, void *st_raw)
                preserve_size, preserve_size,
                w - preserve_size / 2, preserve_size);
     break;
+
+  case mode_erase:
+    if (!st->erase)
+      colorbars (st);
+    st->erase = erase_window(st->dpy, st->win, st->erase);
+    break;
   }
 
   /* Mode toggle buttons */
index 2ebbf17297db01dcda1ee404c6c6cb4e4af0e437..07e0cbde5e5dd06dc5ed6e366b97e962dc4e24b2 100644 (file)
@@ -37,9 +37,11 @@ static const char sccsid[] = "@(#)thornbird.c        5.00 2000/11/01 xlockmore";
                                         "*ncolors: 64    \n" \
                                         "*fpsSolid: true    \n" \
                                        "*ignoreRotation: True \n" \
+                                   "*lowrez: True \n" \
 
 # define BRIGHT_COLORS
 # define release_thornbird 0
+# define reshape_thornbird 0
 # define thornbird_handle_event 0
 # include "xlockmore.h"                /* in xscreensaver distribution */
 #else /* STANDALONE */
@@ -54,7 +56,7 @@ ENTRYPOINT ModeSpecOpt thornbird_opts =
 #ifdef USE_MODULES
 ModStruct   thornbird_description =
 {"thornbird", "init_thornbird", "draw_thornbird", (char *) NULL,
- "refresh_thornbird", "init_thornbird", (char *) NULL, &thornbird_opts,
+ "refresh_thornbird", "init_thornbird", "free_thornbird", &thornbird_opts,
  1000, 800, 16, 1, 64, 1.0, "",
  "Shows an animated Bird in a Thorn Bush fractal map", 0, NULL};
 
@@ -91,7 +93,7 @@ typedef struct {
 
 static thornbirdstruct *thornbirds = (thornbirdstruct *) NULL;
 
-static void
+ENTRYPOINT void
 free_thornbird(ModeInfo * mi)
 {
        thornbirdstruct *hp = &thornbirds[MI_SCREEN(mi)];
@@ -111,7 +113,7 @@ init_thornbird (ModeInfo * mi)
 {
        thornbirdstruct *hp;
 
-       MI_INIT (mi, thornbirds, free_thornbird);
+       MI_INIT (mi, thornbirds);
        hp = &thornbirds[MI_SCREEN(mi)];
 
 
@@ -248,18 +250,13 @@ draw_thornbird(ModeInfo * mi)
        hp->inc++;
 }
 
-ENTRYPOINT void
-reshape_thornbird(ModeInfo * mi, int width, int height)
-{
-  XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi));
-  init_thornbird (mi);
-}
-
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_thornbird (ModeInfo * mi)
 {
        MI_CLEARWINDOW(mi);
 }
+#endif
 
 
 XSCREENSAVER_MODULE ("Thornbird", thornbird)
index d73c1226f547bbc040b10391e5c7af967971d727..e48c0870e6847cfd7a964962ecd0d99f16ef0cad 100644 (file)
@@ -51,7 +51,10 @@ static const char sccsid[] = "@(#)triangle.c 4.04 97/07/28 xlockmore";
                                        "*fpsSolid: true \n" \
 
 # define SMOOTH_COLORS
+# define free_triangle 0
 # define release_triangle 0
+# define reshape_triangle 0
+# define triangle_handle_event 0
 # include "xlockmore.h"                /* in xscreensaver distribution */
 #else /* STANDALONE */
 # include "xlock.h"                    /* in xlockmore distribution */
@@ -223,7 +226,7 @@ init_triangle (ModeInfo * mi)
        short      *tmp;
        int         i, dim, one;
 
-       MI_INIT (mi, triangles, 0);
+       MI_INIT (mi, triangles);
        tp = &triangles[MI_SCREEN(mi)];
 
        tp->width = MI_WIN_WIDTH(mi);
@@ -340,29 +343,12 @@ draw_triangle (ModeInfo * mi)
        }
 }
 
-ENTRYPOINT void
-reshape_triangle(ModeInfo * mi, int width, int height)
-{
-  XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi));
-  init_triangle (mi);
-}
-
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_triangle (ModeInfo * mi)
 {
        /* Do nothing, it will refresh by itself */
 }
-
-ENTRYPOINT Bool
-triangle_handle_event (ModeInfo *mi, XEvent *event)
-{
-  if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
-    {
-      reshape_triangle (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
-      return True;
-    }
-  return False;
-}
-
+#endif
 
 XSCREENSAVER_MODULE ("Triangle", triangle)
index ca28c6bbfb7f2cbd542bd29e57c043e517f0be5d..936479161bcee3032fedbc83e36f102e2177a17c 100644 (file)
@@ -438,10 +438,6 @@ maininit (struct state *st)
       st->instring = sampleStrings[n].str;
       st->speed = sampleStrings[n].speed;
     }
-  if (st->speed == 0)
-    {
-         st->speed = 200;
-    }
   st->boxh = 10;
   st->boxw = 10;
   st->gridden = 0;
@@ -773,12 +769,8 @@ vermiculate_init (Display *d, Window w)
     st->instring = 0;
 
   st->max_ticks = get_integer_resource (st->dpy, "ticks", "Integer");
-  {
-    int temp = get_integer_resource (st->dpy, "speed", "Speed");
-    if (temp != 0)
-      st->speed = temp;
-  }
-
+  st->speed = get_integer_resource (st->dpy, "speed", "Speed");
+  if (st->speed <= 0) st->speed = 1;
   st->mycolors[0].pixel = BlackPixel (st->dpy, DefaultScreen (st->dpy));
 
   XSetWindowBackground (st->dpy, st->window,
@@ -1207,10 +1199,11 @@ vermiculate_free (Display *dpy, Window window, void *closure)
 
 
 static const char *vermiculate_defaults[] = {
+  ".lowrez: true",
   ".background: Black",
   "*ticks: 20000",
   "*fpsSolid:  true",
-  "*speed: 0",
+  "*speed: 1",
   "*instring: ",
 #ifdef HAVE_MOBILE
   "*ignoreRotation: True",
index 1abf29916de8add2071b45dbb50070ea4f798f76..7f519b4b57b0049531be88ba89d06bd4a8f34626 100644 (file)
@@ -49,11 +49,13 @@ static const char sccsid[] = "@(#)vines.c   5.00 2000/11/01 xlockmore";
                                        "*count: 0 \n" \
                                        "*ncolors: 64 \n" \
                                        "*fpsSolid: true \n" \
+                                   "*lowrez: True \n" \
 
 # include "xlockmore.h"                /* in xscreensaver distribution */
+# define free_vines 0
+# define release_vines 0
 # define reshape_vines 0
 # define vines_handle_event 0
-# include "erase.h"
 #else /* STANDALONE */
 # include "xlock.h"            /* in xlockmore distribution */
 #endif /* STANDALONE */
@@ -65,7 +67,7 @@ ENTRYPOINT ModeSpecOpt vines_opts =
 
 #ifdef USE_MODULES
 ModStruct   vines_description =
-{"vines", "init_vines", "draw_vines", "release_vines",
+{"vines", "init_vines", "draw_vines", (char *) NULL,
  "refresh_vines", "init_vines", (char *) NULL, &vines_opts,
  200000, 0, 1, 1, 64, 1.0, "",
  "Shows fractals", 0, NULL};
@@ -85,34 +87,31 @@ typedef struct {
        int         ang;
        int         centerx;
        int         centery;
-#ifdef STANDALONE
-  eraser_state *eraser;
-#endif
 } vinestruct;
 
 static vinestruct *vines = (vinestruct *) NULL;
 
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_vines(ModeInfo * mi)
 {
        MI_CLEARWINDOW(mi);
 }                              /* refresh_vines */
+#endif
 
 ENTRYPOINT void
 init_vines(ModeInfo * mi)
 {
        vinestruct *fp;
 
-       MI_INIT (mi, vines, 0);
+       MI_INIT (mi, vines);
        fp = &vines[MI_SCREEN(mi)];
 
        fp->i = 0;
        fp->length = 0;
        fp->iterations = 30 + NRAND(100);
 
-#ifndef STANDALONE
        MI_CLEARWINDOW(mi);
-#endif
 }                              /* init_vines */
 
 ENTRYPOINT void
@@ -127,20 +126,11 @@ draw_vines(ModeInfo * mi)
                return;
        fp = &vines[MI_SCREEN(mi)];
 
-#ifdef STANDALONE
-    if (fp->eraser) {
-      fp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), fp->eraser);
-      return;
-    }
-#endif
-
-       /* MI_IS_DRAWN(mi) = True; */
+       MI_IS_DRAWN(mi) = True;
        if (fp->i >= fp->length) {
                if (--(fp->iterations) == 0) {
-#ifdef STANDALONE
-         fp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), fp->eraser);
-#endif /* STANDALONE */
                        init_vines(mi);
+                       return;
                }
                fp->centerx = NRAND(MI_WIDTH(mi));
                fp->centery = NRAND(MI_HEIGHT(mi));
@@ -183,15 +173,6 @@ draw_vines(ModeInfo * mi)
        }
 }                              /* draw_vines */
 
-ENTRYPOINT void
-release_vines(ModeInfo * mi)
-{
-       if (vines != NULL) {
-               (void) free((void *) vines);
-               vines = (vinestruct *) NULL;
-       }
-}                              /* release_vines */
-
 
 XSCREENSAVER_MODULE ("Vines", vines)
 
index 1ac0c6cff2dabd4ee93d525f3fc22f1d5448b3a1..50fe255f45844b131fc19b9dc0183d89a56051d8 100644 (file)
@@ -246,6 +246,7 @@ wander_free (Display *dpy, Window window, void *closure)
 
 static const char *wander_defaults [] =
 {
+    ".lowrez:     true",
     ".background: black",
     ".foreground: white",
     ".fpsSolid:          true",
index 63353a9aef645fdd2fe2066015f01621e358ca65..f53804b855de45916fac9b62f20060d9a4f4d25f 100755 (executable)
@@ -1,6 +1,6 @@
 #!/usr/bin/perl -w
 #
-# webcollage, Copyright © 1999-2016 by Jamie Zawinski <jwz@jwz.org>
+# webcollage, Copyright © 1999-2017 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."
 #
 #     webcollage --size '800x600' --imagemap $HOME/www/webcollage/index
 #
 #
+# Requires that either the provided "webcollage-helper" program or
+# ImageMagick's "convert" be available on $PATH.
+#
+#
 # If you have the "driftnet" program installed, webcollage can display a
 # collage of images sniffed off your local ethernet, instead of pulled out
 # of search engines: in that way, your screensaver can display the images
@@ -56,8 +60,8 @@ use LWP::UserAgent;
 
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my ($version) = ('$Revision: 1.176 $' =~ m/\s(\d[.\d]+)\s/s);
-my $copyright = "WebCollage $version, Copyright (c) 1999-2015" .
+my ($version) = ('$Revision: 1.181 $' =~ 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";
 
@@ -68,25 +72,30 @@ my @search_methods = (
                       # a short-running screen saver, but not as a batch job.
                       # I haven't found a workaround.
                       #
-                        7, "googlephotos",  \&pick_from_google_image_photos,
-                        5, "googleimgs",    \&pick_from_google_images,
-                        5, "googlenums",    \&pick_from_google_image_numbers,
+                        5, "googlephotos",  \&pick_from_google_image_photos,
+                        3, "googleimgs",    \&pick_from_google_images,
+                        3, "googlenums",    \&pick_from_google_image_numbers,
 
                       # So let's try Bing instead. No rate limiting yet!
                       #
-                       14, "bingphotos",    \&pick_from_bing_image_photos,
-                       12, "bingimgs",      \&pick_from_bing_images,
-                       11, "bingnums",      \&pick_from_bing_image_numbers,
+                       13, "bingphotos",    \&pick_from_bing_image_photos,
+                       11, "bingimgs",      \&pick_from_bing_images,
+                       10, "bingnums",      \&pick_from_bing_image_numbers,
+
+                       20, "flickr_recent", \&pick_from_flickr_recent,
+                       15, "flickr_random", \&pick_from_flickr_random,
+                        6, "livejournal",   \&pick_from_livejournal_images,
+
+                       11, "imgur",         \&pick_from_imgur,
 
-                       21, "flickr_recent", \&pick_from_flickr_recent,
-                       16, "flickr_random", \&pick_from_flickr_random,
-                        9, "livejournal",   \&pick_from_livejournal_images,
+                     # Tumblr doesn't have an "or" search, so this isn't great.
+                        3, "tumblr",        \&pick_from_tumblr,
 
                      # I ran out of usable access tokens, May 2017
-                     # 23, "instagram",     \&pick_from_instagram,
+                     #  0, "instagram",     \&pick_from_instagram,
 
                      # No longer exists, as of Apr 2014
-                     #  4, "yahoorand",     \&pick_from_yahoo_random_link,
+                     #  0, "yahoorand",     \&pick_from_yahoo_random_link,
 
                      # Twitter destroyed their whole API in 2013.
                      #  0, "twitpic",       \&pick_from_twitpic_images,
@@ -160,28 +169,17 @@ my @root_displayers = (
 my %cookies = (
   "www.altavista.com"  =>  "AV_ALL=1",   # request uncensored searches
   "web.altavista.com"  =>  "AV_ALL=1",
-
-                                         # log in as "cipherpunk"
-  "www.nytimes.com"    =>  'NYT-S=18cHMIlJOn2Y1bu5xvEG3Ufuk6E1oJ.' .
-                           'FMxWaQV0igaB5Yi/Q/guDnLeoL.pe7i1oakSb' .
-                           '/VqfdUdb2Uo27Vzt1jmPn3cpYRlTw9',
-
   "ircimages.com"      =>  'disclaimer=1',
 );
 
 
 # If this is set, it's a helper program to use for pasting images together:
-# this is a lot faster and more efficient than using PPM pipelines, which is
-# what we do if this program doesn't exist.  (We check for "webcollage-helper"
-# on $PATH at startup, and set this variable appropriately.)
+# this is somewhat faster than using ImageMagick.
 #
 my $webcollage_helper = undef;
+my $convert_cmd = 'convert';
 
-
-# If we have the webcollage-helper program, then it will paste the images
-# together with transparency!  0.0 is invisible, 1.0 is totally opaque.
-#
-my $opacity = 0.85;
+my $opacity = 0.85;  # Opacity when pasting images together.
 
 
 # Some sites have  managed to poison the search engines.  These are they.
@@ -244,9 +242,10 @@ my %warningless_sites = (
   "ljplus.ru"               => 1,
   "yandex.ru"               => 1,
   "imgur.com"               => 1,
+  "tumblr.com"              => 1,
   "yfrog.com"               => 1,
   "cdninstagram.com"        => 1,
-  "encrypted-tbn3.gstatic.com" => 1,
+  "gstatic.com"                    => 1,
 
   "yimg.com"                => 1,  # This is where dailynews.yahoo.com stores
   "eimg.com"                => 1,  # its images, so pick_from_yahoo_news_text()
@@ -262,6 +261,7 @@ my %warningless_sites = (
 
 
 # For decoding HTML-encoded character entities to URLs.
+# In This Modern World, probably we should use HTML::Entities instead.
 #
 my %entity_table = (
    "apos"   => '\'',
@@ -333,7 +333,7 @@ my $verbose_warnings = 0;       # print out warnings when things go wrong
 my $verbose_load = 0;           # diagnostics about loading of URLs
 my $verbose_filter = 0;         # diagnostics about page selection/rejection
 my $verbose_net = 0;            # diagnostics about network I/O
-my $verbose_pbm = 0;            # diagnostics about PBM pipelines
+my $verbose_decode = 0;         # diagnostics about img conversion pipelines
 my $verbose_http = 0;           # diagnostics about all HTTP activity
 my $verbose_exec = 0;           # diagnostics about executing programs
 
@@ -821,21 +821,25 @@ sub pick_image_from_body($$) {
 # and the image.
 
 sub pick_image_from_rss($$) {
-  my ( $url, $body ) = @_;
-  my @suitable = ($body =~ m/<enclosure url="(.*?)"/g);
+  my ($url, $body) = @_;
+
+  my ($base) = ($body =~ m@<link>([^<>]+)</link>@si);  # root link
 
-  my ($base) = ($body =~ m@<link>([^<>]+)</link>@i);
+  my @items = ($body =~ m@<item\b[^<>]*>(.*?)</item>@gsi);
+  return unless @items;
+
+  my $n = @items;
+  my $i = int(rand($n));
+  my $item = $items[$i];
+
+  $base = $1 if ($item =~ m@<link>([^<>]+)</link>@si); # item link
   $base = $url unless $base;
+  
+  ($url) = ($item =~ m/<enclosure\b[^<>]*\burl="(.*?)"/si);
+  return unless $url;
 
-  # pick a random element of the table
-  if (@suitable) {
-    my $i = int(rand(scalar @suitable));
-    my $url = $suitable[$i];
-    LOG ($verbose_load, "picked image " .($i+1) . "/" . 
-                        ($#suitable+1) . ": $url");
-    return ($base, $url);
-  }
-  return;
+  LOG ($verbose_load, "picked image $i/$n: $url");
+  return ($base, $url);
 }
 
 \f
@@ -1323,7 +1327,7 @@ sub pick_from_security_camera($) {
   my @candidates = ();
   my %referers;
   foreach my $u (@subpages) {
-    next if ($u =~ m@[/.]google\.com\b@i);        # skip google builtins (most links)
+    next if ($u =~ m@[/.]google\.com\b@i); # skip google builtins (most links)
     next unless ($u =~ m@jpg/image.jpg\?r=@i);    #  All pics contain this
 
     LOG ($verbose_filter, "  candidate: $u");
@@ -2198,7 +2202,8 @@ sub pick_from_flickr_recent($) {
 #
 ############################################################################
 
-my $flickr_rss_base = ("http://www.flickr.com/services/feeds/photos_public.gne".
+my $flickr_rss_base = ("http://www.flickr.com/services/feeds/" .
+                       "photos_public.gne" .
                        "?format=rss_200_enc&tagmode=any&tags=");
 
 # Picks a random RSS feed; picks a random image from that feed;
@@ -2308,6 +2313,106 @@ sub pick_from_instagram($) {
   return ($url, $img);
 }
 
+\f
+############################################################################
+#
+# Pick images from Imgur.
+#
+############################################################################
+
+my $imgur_base = 'http://imgur.com/search?qs=thumb&q_any=';
+
+sub pick_from_imgur($) {
+  my $timeout = shift;
+
+  my $words = random_words('%20');
+  $last_search = $imgur_base . $words;
+
+  $_ = $words;
+  s/%20/ /g;
+
+  print STDERR "\n\n" if ($verbose_load);
+  LOG ($verbose_load, "words: $_");
+  LOG ($verbose_load, "URL: $last_search");
+
+  $suppress_audit = 1;
+
+  my ( $base, $body ) = get_document ($last_search, undef, $timeout);
+  if (!$base || !$body) {
+    $body = undef;
+    return;
+  }
+
+  my @imgs = ($body =~ m@\bHREF=[\"\']([^\'\"<>]*/gallery/[^\'\"<>]+)@gsi);
+  return () unless @imgs;
+
+  my $n = @imgs;
+  my $i = int(rand($n));
+  my $page = $imgs[$i];
+  $page =~ s/[?&].*$//s;
+  $page = "http://imgur.com$page" if ($page =~ m@^/@s);
+
+  my ($id) = ($page =~ m@([^/?&]+)$@s);
+  my $img = "http://i.imgur.com/$id.jpg";
+
+  LOG ($verbose_load, "picked image " .($i+1) . "/$n: $img");
+
+  return ($page, $img);
+}
+
+\f
+############################################################################
+#
+# Pick images from Tumblr.
+#
+############################################################################
+
+my $tumblr_base = 'https://www.tumblr.com/search/';
+
+sub pick_from_tumblr($) {
+  my $timeout = shift;
+
+  # Tumblr doesn't have an "or" search, which means our vocabulary is
+  # a bit too extensive to work well...
+
+  my $words = random_word();
+  $last_search = $tumblr_base . $words;
+
+  print STDERR "\n\n" if ($verbose_load);
+  LOG ($verbose_load, "words: $words");
+  LOG ($verbose_load, "URL: $last_search");
+
+  $suppress_audit = 1;
+
+  my ( $base, $body ) = get_document ($last_search, undef, $timeout);
+  if (!$base || !$body) {
+    $body = undef;
+    return;
+  }
+
+  my @imgs0 = ($body =~ m@<IMG\b([^<>]*)>@gsi);
+  return () unless @imgs0;
+  my @imgs;
+  foreach my $img (@imgs0) {
+    my ($src)  = ($img =~ m@\bsrc=[\"\'](.*?)[\"\']@si);
+    my ($href) = ($img =~ m@\bdata-pin-url=[\"\'](.*?)[\"\']@si);
+    next unless ($src && $href);
+    next if ($src =~ m/^data:/s);
+    foreach ($src, $href) { $_ = "http://www.tumblr.com$_" if (m@^/@s); }
+    push @imgs, [$href, $src];
+  }
+  return () unless @imgs;
+
+  my $n = @imgs;
+  my $i = int(rand($n));
+  my $page = $imgs[$i]->[0];
+  my $img  = $imgs[$i]->[1];
+
+  LOG ($verbose_load, "picked image " .($i+1) . "/$n: $img");
+
+  return ($page, $img);
+}
+
 \f
 ############################################################################
 #
@@ -2839,6 +2944,15 @@ sub png_size($) {
 }
 
 
+# Given the raw body of a PNM document, returns the dimensions of the image.
+#
+sub pnm_size($) {
+  my ($body) = @_;
+  return () unless ($body =~ m/^P[1-6]\r?\n(\d+) +(\d+)\r?\n/s);
+  return ($1, $2);
+}
+
+
 # Given the raw body of a GIF, JPEG, or PNG document, returns the dimensions
 # of the image.
 #
@@ -2849,6 +2963,8 @@ sub image_size($) {
   ($w, $h) = jpeg_size ($body);
   if ($w && $h) { return ($w, $h); }
   return png_size ($body);
+  if ($w && $h) { return ($w, $h); }
+  return pnm_size ($body);
 }
 
 
@@ -2919,15 +3035,15 @@ sub url_only_output() {
 #
 ##############################################################################
 
-my ($image_ppm, $image_tmp1, $image_tmp2);
+my ($image_png, $image_tmp1, $image_tmp2);
 {
   my $seed = rand(0xFFFFFFFF);
-  $image_ppm = sprintf ("%s/webcollage-%08x",
+  $image_png = sprintf ("%s/webcollage-%08x",
                         ($ENV{TMPDIR} ? $ENV{TMPDIR} : "/tmp"),
                         $seed);
-  $image_tmp1 = $image_ppm . '-1.ppm';
-  $image_tmp2 = $image_ppm . '-2.ppm';
-  $image_ppm .= '.ppm';
+  $image_tmp1 = $image_png . '-1.png';
+  $image_tmp2 = $image_png . '-2.png';
+  $image_png .= '.png';
 }
 
 
@@ -2946,7 +3062,7 @@ my $img_height;
 my $delay = 2;
 
 sub x_cleanup() {
-  unlink $image_ppm, $image_tmp1, $image_tmp2;
+  unlink $image_png, $image_tmp1, $image_tmp2;
   unlink $imagemap_html_tmp, $imagemap_jpg_tmp
     if (defined ($imagemap_html_tmp));
 }
@@ -2984,125 +3100,23 @@ sub nontrapping_system(@) {
 }
 
 
-# Given the URL of a GIF, JPEG, or PNG image, and the body of that image,
-# writes a PPM to the given output file.  Returns the width/height of the
-# image if successful.
+# Creates a solid-colored PNG.
 #
-sub image_to_pnm($$$) {
-  my ($url, $body, $output) = @_;
-  my ($cmd, $cmd2, $w, $h);
-
-  if ((@_ = gif_size ($body))) {
-    ($w, $h) = @_;
-    $cmd = "giftopnm";
-  } elsif ((@_ = jpeg_size ($body))) {
-    ($w, $h) = @_;
-    $cmd = "djpeg";
-  } elsif ((@_ = png_size ($body))) {
-    ($w, $h) = @_;
-    $cmd = "pngtopnm";
-  } else {
-    LOG (($verbose_pbm || $verbose_load),
-         "not a GIF, JPG, or PNG" .
-         (($body =~ m@<(base|html|head|body|script|table|a href)\b@i)
-          ? " (looks like HTML)" : "") .
-         ": $url");
-    $suppress_audit = 1;
-    return ();
-  }
-
-  $cmd2 = "exec $cmd";        # yes, this really is necessary.  if we don't
-                              # do this, the process doesn't die properly.
-  if (!$verbose_pbm) {
-    #
-    # We get a "giftopnm: got a 'Application Extension' extension"
-    # warning any time it's an animgif.
-    #
-    # Note that "giftopnm: EOF / read error on image data" is not
-    # always a fatal error -- sometimes the image looks fine anyway.
-    #
-    $cmd2 .= " 2>/dev/null";
-  }
-
-  # There exist corrupted GIF and JPEG files that can make giftopnm and
-  # djpeg lose their minds and go into a loop.  So this gives those programs
-  # a small timeout -- if they don't complete in time, kill them.
-  #
-  my $pid;
-  @_ = eval {
-    my $timed_out;
-
-    local $SIG{ALRM}  = sub {
-      LOG ($verbose_pbm,
-           "timed out ($cvt_timeout) for $cmd on \"$url\" in pid $pid");
-      kill ('TERM', $pid) if ($pid);
-      $timed_out = 1;
-      $body = undef;
-    };
-
-    if (($pid = open (my $pipe, "| $cmd2 > $output"))) {
-      $timed_out = 0;
-      alarm $cvt_timeout;
-      print $pipe $body;
-      $body = undef;
-      close $pipe;
-
-      LOG ($verbose_exec, "awaiting $pid");
-      waitpid ($pid, 0);
-      LOG ($verbose_exec, "$pid completed");
-
-      my $size = (stat($output))[7];
-      $size = -1 unless defined($size);
-      if ($size < 5) {
-        LOG ($verbose_pbm, "$cmd on ${w}x$h \"$url\" failed ($size bytes)");
-        return ();
-      }
-
-      LOG ($verbose_pbm, "created ${w}x$h $output ($cmd)");
-      return ($w, $h);
-    } else {
-      print STDERR blurb() . "$cmd failed: $!\n";
-      return ();
-    }
-  };
-  die if ($@ && $@ ne "alarm\n");       # propagate errors
-  if ($@) {
-    # timed out
-    $body = undef;
-    return ();
-  } else {
-    # didn't
-    alarm 0;
-    $body = undef;
-    return @_;
-  }
-}
-
-
-# Same as the "ppmmake" command: creates a solid-colored PPM.
-# Does not understand the rgb.txt color names except "black" and "white".
-#
-sub ppmmake($$$$) {
+sub pngmake($$$$) {
   my ($outfile, $bgcolor, $w, $h) = @_;
 
-  my ($r, $g, $b);
-  if ($bgcolor =~ m/^\#?([\dA-F][\dA-F])([\dA-F][\dA-F])([\dA-F][\dA-F])$/i ||
-      $bgcolor =~ m/^\#?([\dA-F])([\dA-F])([\dA-F])$/i) {
-    ($r, $g, $b) = (hex($1), hex($2), hex($3));
-  } elsif ($bgcolor =~ m/^black$/i) {
-    ($r, $g, $b) = (0, 0, 0);
-  } elsif ($bgcolor =~ m/^white$/i) {
-    ($r, $g, $b) = (0xFF, 0xFF, 0xFF);
+  my @cmd;
+  if ($webcollage_helper) {
+    @cmd = ($webcollage_helper, $bgcolor, $w, $h, $outfile);
   } else {
-    error ("unparsable color name: $bgcolor");
+    @cmd = ($convert_cmd, '-size', "${w}x${h}", "xc:$bgcolor", $outfile);
+  }
+    
+  my $rc = nontrapping_system (@cmd);
+  if ($rc != 0) {
+    LOG(0, "failed to create $bgcolor image: \"$outfile\"");
+    exit(1);
   }
-
-  my $pixel = pack('CCC', $r, $g, $b);
-  my $bits = "P6\n$w $h\n255\n" . ($pixel x ($w * $h));
-
-  open (my $out, '>', $outfile) || error ("$outfile: $!");
-  print $out $bits;
-  close $out;
 }
 
 
@@ -3130,10 +3144,10 @@ sub pick_root_displayer() {
 }
 
 
-my $ppm_to_root_window_cmd = undef;
+my $png_to_root_window_cmd = undef;
 
 
-sub x_or_pbm_output($) {
+sub x_or_image_output($) {
   my ($window_id) = @_;
 
   # Adjust the PATH for OS X 10.10.
@@ -3143,65 +3157,54 @@ sub x_or_pbm_output($) {
   s/([^a-zA-Z0-9._\-+\/])/\\$1/g;
   $ENV{PATH} = "$_:$ENV{PATH}";
 
-  # Check for our helper program, to see whether we need to use PPM pipelines.
+  # Check for our helper program, to see whether we need to use imagemagick.
   #
   $_ = "webcollage-helper";
 
   if (! defined ($webcollage_helper)) {
-    $webcollage_helper = which ($_);
+#    $webcollage_helper = which ($_);
   }
 
   if (defined ($webcollage_helper)) {
-    LOG ($verbose_pbm, "found \"$webcollage_helper\"");
-    $webcollage_helper = "'$webcollage_helper' -v";
+    LOG ($verbose_decode, "found \"$webcollage_helper\"");
   } else {
-    LOG (($verbose_pbm || $verbose_load), "no $_ program");
+    LOG (($verbose_decode || $verbose_load), "no $_ program");
   }
 
   if ($cocoa_p && !defined ($webcollage_helper)) {
     error ("webcollage-helper not found in Cocoa-mode!");
   }
 
+  if (!$cocoa_p && defined ($webcollage_helper)) {
+    foreach ($image_png, $image_tmp1, $image_tmp2) {
+      s/\.png$/.jpg/si;
+    }
+  }
 
   # make sure the various programs we execute exist, right up front.
   #
   my @progs = ();
 
-  if (!defined($webcollage_helper)) {
-    # Only need these others if we don't have the helper.
-    @progs = (@progs,
-              "giftopnm", "pngtopnm", "djpeg",
-              "pnmpaste", "pnmscale", "pnmcut");
-  }
+  push @progs, $convert_cmd unless defined($webcollage_helper);
 
   foreach (@progs) {
     which ($_) || error "$_ not found on \$PATH.";
   }
 
-  # If we're using webcollage-helper and not a filter, then the tmp files
-  # are JPEGs, not PPMs.
-  #
-  if (defined ($webcollage_helper) && !defined ($filter_cmd)) {
-    foreach ($image_ppm, $image_tmp1, $image_tmp2) {
-      s/\.ppm$/.jpg/s;
-    }
-  }
-
-
   # find a root-window displayer program.
   #
   if (!$no_output_p) {
-    $ppm_to_root_window_cmd = pick_root_displayer();
+    $png_to_root_window_cmd = pick_root_displayer();
   }
 
   if (defined ($window_id)) {
     error ("-window-id only works if xscreensaver-getimage is installed")
-      unless ($ppm_to_root_window_cmd =~ m/^xscreensaver-getimage\b/);
+      unless ($png_to_root_window_cmd =~ m/^xscreensaver-getimage\b/);
 
     error ("unparsable window id: $window_id")
       unless ($window_id =~ m/^\d+$|^0x[\da-f]+$/i);
-    $ppm_to_root_window_cmd =~ s/--?root\b/$window_id/ ||
-      error ("unable to munge displayer: $ppm_to_root_window_cmd");
+    $png_to_root_window_cmd =~ s/--?root\b/$window_id/ ||
+      error ("unable to munge displayer: $png_to_root_window_cmd");
   }
 
   if (!$img_width || !$img_height) {
@@ -3253,55 +3256,17 @@ sub x_or_pbm_output($) {
 
   # Create the sold-colored base image.
   #
-  LOG ($verbose_pbm, "creating base image: ${img_width}x${img_height}");
-  $_ = ppmmake ($image_ppm, $bgcolor, $img_width, $img_height);
+  LOG ($verbose_decode, "creating base image: ${img_width}x${img_height}");
+  $_ = pngmake ($image_png, $bgcolor, $img_width, $img_height);
 
   # Paste the default background image in the middle of it.
   #
   if ($bgimage) {
-    my ($iw, $ih);
-
-    my $body = "";
-    open (my $imgf, '<:raw', $bgimage) || error "couldn't open $bgimage: $!";
+    open (my $in, '<:raw', $bgimage) || error ("$bgimage: $!");
     local $/ = undef;  # read entire file
-    $body = <$imgf>;
-    close ($imgf);
-
-    my $cmd;
-    if ((@_ = gif_size ($body))) {
-      ($iw, $ih) = @_;
-      $cmd = "giftopnm |";
-
-    } elsif ((@_ = jpeg_size ($body))) {
-      ($iw, $ih) = @_;
-      $cmd = "djpeg |";
-
-    } elsif ((@_ = png_size ($body))) {
-      ($iw, $ih) = @_;
-      $cmd = "pngtopnm |";
-
-    } elsif ($body =~ m/^P\d\n(\d+) (\d+)\n/) {
-      $iw = $1;
-      $ih = $2;
-      $cmd = "";
-
-    } else {
-      error "$bgimage is not a GIF, JPEG, PNG, or PPM.";
-    }
-
-    my $x = int (($img_width  - $iw) / 2);
-    my $y = int (($img_height - $ih) / 2);
-    LOG ($verbose_pbm,
-         "pasting $bgimage (${iw}x$ih) into base image at $x,$y");
-
-    $cmd .= "pnmpaste - $x $y $image_ppm > $image_tmp1";
-    open ($imgf, "| $cmd") || error "running $cmd: $!";
-    print $imgf $body;
-    $body = undef;
-    close ($imgf);
-    LOG ($verbose_exec, "subproc exited normally.");
-    rename ($image_tmp1, $image_ppm) ||
-      error "renaming $image_tmp1 to $image_ppm: $!";
+    my $body = <$in>;
+    close ($in) || error ("$bgimage: $!");
+    paste_image ('init', $image_png, $body, 'init', 1);
   }
 
   clearlog();
@@ -3325,60 +3290,40 @@ sub x_or_pbm_output($) {
   }
 }
 
-sub paste_image($$$$) {
-  my ($base, $img, $body, $source) = @_;
+sub paste_image($$$$;$) {
+  my ($base, $img, $body, $source, $init_p) = @_;
 
   $current_state = "paste";
 
   $suppress_audit = 0;
 
-  LOG ($verbose_pbm, "got $img (" . length($body) . ")");
+  LOG ($verbose_decode, "got $img (" . length($body) . ")");
 
-  my ($iw, $ih);
-
-  # If we are using the webcollage-helper, then we do not need to convert this
-  # image to a PPM.  But, if we're using a filter command, we still must, since
-  # that's what the filters expect (webcollage-helper can read PPMs, so that's
-  # fine.)
-  #
-  if (defined ($webcollage_helper) &&
-      !defined ($filter_cmd)) {
-
-    ($iw, $ih) = image_size ($body);
-    if (!$iw || !$ih) {
-      LOG (($verbose_pbm || $verbose_load),
-           "not a GIF, JPG, or PNG" .
-           (($body =~ m@<(base|html|head|body|script|table|a href)>@i)
-            ? " (looks like HTML)" : "") .
-           ": $img");
-      $suppress_audit = 1;
-      $body = undef;
-      return 0;
-    }
-
-    if ($iw <= 0 || $ih <= 0 || $iw > 9999 || $ih > 9999) {
-      LOG (($verbose_pbm || $verbose_load),
-           "ludicrous image dimensions: $iw x $ih (" . length($body) .
-           "): $img");
-      $body = undef;
-      return 0;
-    }
-
-    open (my $out, '>:raw', $image_tmp1) || error ("writing $image_tmp1: $!");
-    (print $out $body) || error ("writing $image_tmp1: $!");
-    close ($out) || error ("writing $image_tmp1: $!");
+  my ($iw, $ih) = image_size ($body);
+  if (!$iw || !$ih) {
+    LOG (($verbose_decode || $verbose_load),
+         "not a GIF, JPG, or PNG" .
+         (($body =~ m@<(base|html|head|body|script|table|a href)>@i)
+          ? " (looks like HTML)" : "") .
+         ": $img");
+    $suppress_audit = 1;
+    $body = undef;
+    return 0;
+  }
 
-  } else {
-    ($iw, $ih) = image_to_pnm ($img, $body, $image_tmp1);
+  if ($iw <= 0 || $ih <= 0 || $iw > 9999 || $ih > 9999) {
+    LOG (($verbose_decode || $verbose_load),
+         "ludicrous image dimensions: $iw x $ih (" . length($body) .
+         "): $img");
     $body = undef;
-    if (!$iw || !$ih) {
-      LOG ($verbose_pbm, "unable to make PBM from $img");
-      return 0;
-    }
+    return 0;
   }
 
-  record_success ($load_method, $img, $base);
+  open (my $out, '>:raw', $image_tmp1) || error ("writing $image_tmp1: $!");
+  (print $out $body) || error ("writing $image_tmp1: $!");
+  close ($out) || error ("writing $image_tmp1: $!");
 
+  record_success ($load_method, $img, $base);
 
   my $ow = $iw;  # used only for error messages
   my $oh = $ih;
@@ -3386,218 +3331,240 @@ sub paste_image($$$$) {
   # don't just tack this onto the front of the pipeline -- we want it to
   # be able to change the size of the input image.
   #
-  if ($filter_cmd) {
-    LOG ($verbose_pbm, "running $filter_cmd");
+  if ($filter_cmd && !$init_p) {
+    LOG ($verbose_decode, "running $filter_cmd");
+
+    # #### Historically, $filter_cmd read and write PPM files.
+    #      This is doing PNG or JPEG now.  I'll bet nobody uses this.
 
     my $rc = nontrapping_system "($filter_cmd) < $image_tmp1 >$image_tmp2";
     if ($rc != 0) {
-      LOG(($verbose_pbm || $verbose_load), "failed command: \"$filter_cmd\"");
-      LOG(($verbose_pbm || $verbose_load), "failed URL: \"$img\" (${ow}x$oh)");
+      LOG(($verbose_decode || $verbose_load),
+          "failed command: \"$filter_cmd\"");
+      LOG(($verbose_decode || $verbose_load),
+          "failed URL: \"$img\" (${ow}x$oh)");
       return;
     }
     rename ($image_tmp2, $image_tmp1);
 
     # re-get the width/height in case the filter resized it.
     open (my $imgf, '<:raw', $image_tmp1) || return 0;
-    $_ = <$imgf>;
-    $_ = <$imgf>;
-    ($iw, $ih) = m/^(\d+) (\d+)$/;
-    close ($imgf);
+    my $b = '';
+    sysread ($imgf, $b, 10240);
+    close $imgf;
+    ($iw, $ih) = image_size ($b);
     return 0 unless ($iw && $ih);
   }
 
   my $target_w = $img_width;   # max rectangle into which the image must fit
   my $target_h = $img_height;
 
-  my $cmd = "";
   my $scale = 1.0;
 
-
-  # Usually scale the image to fit on the screen -- but sometimes scale it
-  # to fit on half or a quarter of the screen.  (We do this by reducing the
-  # size of the target rectangle.)  Note that the image is not merely scaled
-  # to fit; we instead cut the image in half repeatedly until it fits in the
-  # target rectangle -- that gives a wider distribution of sizes.
-  #
-  if (rand() < 0.3) { $target_w /= 2; $target_h /= 2; } # reduce target rect
-  if (rand() < 0.3) { $target_w /= 2; $target_h /= 2; }
-
-  if ($iw > $target_w || $ih > $target_h) {
-    while ($iw > $target_w ||
-           $ih > $target_h) {
-      $iw = int($iw / 2);
-      $ih = int($ih / 2);
-      $scale /= 2;
-    }
-    if ($iw <= 10 || $ih <= 10) {
-      LOG ($verbose_pbm, "scaling to ${iw}x$ih would have been bogus.");
-      return 0;
-    }
-
-    LOG ($verbose_pbm, "scaling to ${iw}x$ih ($scale)");
-
-    $cmd .= " | pnmscale -xsize $iw -ysize $ih";
-  }
-
-
-  my $src = $image_tmp1;
-
   my $crop_x = 0;     # the sub-rectangle of the image
   my $crop_y = 0;     # that we will actually paste.
   my $crop_w = $iw;
   my $crop_h = $ih;
+  my $x = 0;
+  my $y = 0;
 
-  # The chance that we will randomly crop out a section of an image starts
-  # out fairly low, but goes up for images that are very large, or images
-  # that have ratios that make them look like banners (we try to avoid
-  # banner images entirely, but they slip through when the IMG tags didn't
-  # have WIDTH and HEIGHT specified.)
-  #
-  my $crop_chance = 0.2;
-  if ($iw > $img_width * 0.4 || $ih > $img_height * 0.4) {
-    $crop_chance += 0.2;
-  }
-  if ($iw > $img_width * 0.7 || $ih > $img_height * 0.7) {
-    $crop_chance += 0.2;
-  }
-  if ($min_ratio && ($iw * $min_ratio) > $ih) {
-    $crop_chance += 0.7;
-  }
+  if (!$init_p) {
 
-  if ($crop_chance > 0.1) {
-    LOG ($verbose_pbm, "crop chance: $crop_chance");
-  }
+    # Usually scale the image to fit on the screen -- but sometimes scale it
+    # to fit on half or a quarter of the screen.  (We do this by reducing the
+    # size of the target rectangle.)  Note that the image is not merely scaled
+    # to fit; we instead cut the image in half repeatedly until it fits in the
+    # target rectangle -- that gives a wider distribution of sizes.
+    #
+    if (rand() < 0.3) { $target_w /= 2; $target_h /= 2; } # reduce target rect
+    if (rand() < 0.3) { $target_w /= 2; $target_h /= 2; }
+
+    if ($iw > $target_w || $ih > $target_h) {
+      while ($iw > $target_w ||
+             $ih > $target_h) {
+        $iw = int($iw / 2);
+        $ih = int($ih / 2);
+        $scale /= 2;
+      }
+      if ($iw <= 10 || $ih <= 10) {
+        LOG ($verbose_decode, "scaling ${ow}x${oh} to ${iw}x$ih" .
+             " would have been bogus.");
+        return 0;
+      }
+
+      $crop_w = $iw;
+      $crop_h = $ih;
+
+      LOG ($verbose_decode, "scaling ${ow}x${oh} to ${iw}x$ih ($scale)");
+    }
 
-  if (rand() < $crop_chance) {
 
-    my $ow = $crop_w;
-    my $oh = $crop_h;
+    my $src = $image_tmp1;
 
-    if ($crop_w > $min_width) {
-      # if it's a banner, select the width linearly.
-      # otherwise, select a bell.
-      my $r = (($min_ratio && ($iw * $min_ratio) > $ih)
-               ? rand()
-               : bellrand());
-      $crop_w = $min_width + int ($r * ($crop_w - $min_width));
-      $crop_x = int (rand() * ($ow - $crop_w));
+    # The chance that we will randomly crop out a section of an image starts
+    # out fairly low, but goes up for images that are very large, or images
+    # that have ratios that make them look like banners (we try to avoid
+    # banner images entirely, but they slip through when the IMG tags didn't
+    # have WIDTH and HEIGHT specified.)
+    #
+    my $crop_chance = 0.2;
+    if ($iw > $img_width * 0.4 || $ih > $img_height * 0.4) {
+      $crop_chance += 0.2;
+    }
+    if ($iw > $img_width * 0.7 || $ih > $img_height * 0.7) {
+      $crop_chance += 0.2;
     }
-    if ($crop_h > $min_height) {
-      # height always selects as a bell.
-      $crop_h = $min_height + int (bellrand() * ($crop_h - $min_height));
-      $crop_y = int (rand() * ($oh - $crop_h));
+    if ($min_ratio && ($iw * $min_ratio) > $ih) {
+      $crop_chance += 0.7;
     }
 
-    if ($crop_x != 0   || $crop_y != 0 ||
-        $crop_w != $iw || $crop_h != $ih) {
-      LOG ($verbose_pbm,
-           "randomly cropping to ${crop_w}x$crop_h \@ $crop_x,$crop_y");
+    if ($crop_chance > 0.1) {
+      LOG ($verbose_decode, "crop chance: $crop_chance");
     }
-  }
 
-  # Where the image should logically land -- this might be negative.
-  #
-  my $x = int((rand() * ($img_width  + $crop_w/2)) - $crop_w*3/4);
-  my $y = int((rand() * ($img_height + $crop_h/2)) - $crop_h*3/4);
+    if (rand() < $crop_chance) {
 
-  # if we have chosen to paste the image outside of the rectangle of the
-  # screen, then we need to crop it.
-  #
-  if ($x < 0 ||
-      $y < 0 ||
-      $x + $crop_w > $img_width ||
-      $y + $crop_h > $img_height) {
+      my $ow = $crop_w;
+      my $oh = $crop_h;
 
-    LOG ($verbose_pbm,
-         "cropping for effective paste of ${crop_w}x$crop_h \@ $x,$y");
+      if ($crop_w > $min_width) {
+        # if it's a banner, select the width linearly.
+        # otherwise, select a bell.
+        my $r = (($min_ratio && ($iw * $min_ratio) > $ih)
+                 ? rand()
+                 : bellrand());
+        $crop_w = $min_width + int ($r * ($crop_w - $min_width));
+        $crop_x = int (rand() * ($ow - $crop_w));
+      }
+      if ($crop_h > $min_height) {
+        # height always selects as a bell.
+        $crop_h = $min_height + int (bellrand() * ($crop_h - $min_height));
+        $crop_y = int (rand() * ($oh - $crop_h));
+      }
 
-    if ($x < 0) { $crop_x -= $x; $crop_w += $x; $x = 0; }
-    if ($y < 0) { $crop_y -= $y; $crop_h += $y; $y = 0; }
+      # Clip it to the actual post-scaling image size.
+      if ($crop_x + $crop_w > $iw) { $crop_w = $iw - $crop_x; }
+      if ($crop_y + $crop_h > $ih) { $crop_h = $ih - $crop_y; }
+      if ($crop_x < 0) { $crop_w += $crop_x; $crop_x = 0; }
+      if ($crop_y < 0) { $crop_h += $crop_y; $crop_y = 0; }
 
-    if ($x + $crop_w >= $img_width)  { $crop_w = $img_width  - $x - 1; }
-    if ($y + $crop_h >= $img_height) { $crop_h = $img_height - $y - 1; }
-  }
+      if ($crop_x != 0   || $crop_y != 0 ||
+          $crop_w != $iw || $crop_h != $ih) {
+        LOG ($verbose_decode,
+             "randomly cropping to ${crop_w}x$crop_h \@ $crop_x,$crop_y");
+      }
+    }
 
-  # If any cropping needs to happen, add pnmcut.
-  #
-  if ($crop_x != 0   || $crop_y != 0 ||
-      $crop_w != $iw || $crop_h != $ih) {
-    $iw = $crop_w;
-    $ih = $crop_h;
-    $cmd .= " | pnmcut $crop_x $crop_y $iw $ih";
-    LOG ($verbose_pbm, "cropping to ${crop_w}x$crop_h \@ $crop_x,$crop_y");
-  }
+    # Where the image should logically land -- this might be negative.
+    #
+    $x = int((rand() * ($img_width  + $crop_w/2)) - $crop_w*3/4);
+    $y = int((rand() * ($img_height + $crop_h/2)) - $crop_h*3/4);
 
-  LOG ($verbose_pbm, "pasting ${iw}x$ih \@ $x,$y in $image_ppm");
+    # if we have chosen to paste the image outside of the rectangle of the
+    # screen, then we need to crop it.
+    #
+    if ($x < 0 ||
+        $y < 0 ||
+        $x + $crop_w > $img_width ||
+        $y + $crop_h > $img_height) {
 
-  $cmd .= " | pnmpaste - $x $y $image_ppm";
+      LOG ($verbose_decode,
+           "cropping for effective paste of ${crop_w}x${crop_h} \@ $x,$y");
 
-  $cmd =~ s@^ *\| *@@;
+      if ($x < 0) { $crop_x -= $x; $crop_w += $x; $x = 0; }
+      if ($y < 0) { $crop_y -= $y; $crop_h += $y; $y = 0; }
 
-  if (defined ($webcollage_helper)) {
-    $cmd = "$webcollage_helper $image_tmp1 $image_ppm " .
-                              "$scale $opacity " .
-                              "$crop_x $crop_y $x $y " .
-                              "$iw $ih";
-    $_ = $cmd;
+      if ($x + $crop_w >= $img_width)  { $crop_w = $img_width  - $x - 1; }
+      if ($y + $crop_h >= $img_height) { $crop_h = $img_height - $y - 1; }
+    }
 
-  } else {
-    # use a PPM pipeline
-    $_ = "($cmd)";
-    $_ .= " < $image_tmp1 > $image_tmp2";
-  }
+    # If any cropping needs to happen, add pnmcut.
+    #
+    if ($crop_x != 0   || $crop_y != 0 ||
+        $crop_w != $iw || $crop_h != $ih) {
+      $iw = $crop_w;
+      $ih = $crop_h;
+      LOG ($verbose_decode, "cropping to ${crop_w}x$crop_h \@ " .
+           "$crop_x,$crop_y");
+    }
 
-  if ($verbose_pbm) {
-    $_ = "($_) 2>&1 | sed s'/^/" . blurb() . "/'";
-  } else {
-    $_ .= " 2> /dev/null";
+    LOG ($verbose_decode, "pasting ${iw}x$ih \@ $x,$y in $image_png");
   }
 
-  my $rc = nontrapping_system ($_);
-
-  if (defined ($webcollage_helper) && -z $image_ppm) {
-    LOG (1, "failed command: \"$cmd\"");
+  my @cmd;
+  if (defined ($webcollage_helper)) {
+    @cmd = ($webcollage_helper,
+            $image_tmp1, $image_png,
+            $scale, $opacity,
+            $crop_x, $crop_y, $x, $y,
+            $iw, $ih);
+  } else {
+    @cmd = ($convert_cmd,
+            $image_png,
+            '(',
+            $image_tmp1 . '[0]', 
+            '-scale', sprintf("%.2f%%", 100 * $scale),
+            '-crop', "${iw}x${ih}+${crop_x}+${crop_y}",
+            '-geometry', "+${x}+${y}",
+
+            ($init_p ? () :
+             (
+              # Blurry edges with rounded corners
+              '-alpha', 'set',
+              '-virtual-pixel', 'transparent',
+              '-channel', 'A',
+              '-blur', '0x12',
+              '-level', '50%,100%',
+
+              # Overall transparency
+              '-evaluate', 'multiply', $opacity,
+
+              '+channel',
+             )),
+            ')',
+            '-composite',
+            '+repage',
+            '-strip',
+            $image_png);
+  }
+
+  #### $verbose_decode should mean 2>/dev/null
+
+  my $rc = nontrapping_system (@cmd);
+
+  if (-z $image_png) {
+    LOG (1, "failed command: \"@cmd\"");
     print STDERR "\naudit log:\n\n\n";
     print STDERR ("#" x 78) . "\n";
-    print STDERR blurb() . "$image_ppm has zero size\n";
+    print STDERR blurb() . "$image_png has zero size\n";
     showlog();
     print STDERR "\n\n";
     exit (1);
   }
 
   if ($rc != 0) {
-    LOG (($verbose_pbm || $verbose_load), "failed command: \"$cmd\"");
-    LOG (($verbose_pbm || $verbose_load), "failed URL: \"$img\" (${ow}x$oh)");
+    LOG (($verbose_decode || $verbose_load), "failed command: \"@cmd\"");
+    LOG (($verbose_decode || $verbose_load),
+         "failed URL: \"$img\" (${ow}x$oh)");
     return;
   }
 
-  if (!defined ($webcollage_helper)) {
-    rename ($image_tmp2, $image_ppm) || return;
-  }
-
-  my $target = "$image_ppm";
+  my $target = "$image_png";
 
   # don't just tack this onto the end of the pipeline -- we don't want it
-  # to end up in $image_ppm, because we don't want the results to be
+  # to end up in $image_png, because we don't want the results to be
   # cumulative.
   #
   if ($post_filter_cmd) {
 
-    my $cmd;
+    # #### Historically, $post_filter_cmd read and write PPM files.
+    #      This is doing PNG or JPEG now.  I'll bet nobody uses this.
 
     $target = $image_tmp1;
-    if (!defined ($webcollage_helper)) {
-      $cmd = "($post_filter_cmd) < $image_ppm > $target";
-    } else {
-      # Blah, my scripts need the JPEG data, but some other folks need
-      # the PPM data -- what to do?  Ignore the problem, that's what!
-#     $cmd = "djpeg < $image_ppm | ($post_filter_cmd) > $target";
-      $cmd = "($post_filter_cmd) < $image_ppm > $target";
-    }
-
+    my $cmd = "($post_filter_cmd) < $image_png > $target";
     $rc = nontrapping_system ($cmd);
     if ($rc != 0) {
-      LOG ($verbose_pbm, "filter failed: \"$post_filter_cmd\"\n");
+      LOG ($verbose_decode, "filter failed: \"$post_filter_cmd\"\n");
       return;
     }
   }
@@ -3605,7 +3572,7 @@ sub paste_image($$$$) {
   if (!$no_output_p) {
     my $tsize = (stat($target))[7];
     if ($tsize > 200) {
-      $cmd = "$ppm_to_root_window_cmd $target";
+      my $cmd = "$png_to_root_window_cmd $target";
 
       # xv seems to hate being killed.  it tends to forget to clean
       # up after itself, and leaves windows around and colors allocated.
@@ -3622,21 +3589,23 @@ sub paste_image($$$$) {
       $rc = nontrapping_system ($cmd);
 
       if ($rc != 0) {
-        LOG (($verbose_pbm || $verbose_load), "display failed: \"$cmd\"");
+        LOG (($verbose_decode || $verbose_load), "display failed: \"$cmd\"");
         return;
       }
 
     } else {
-      LOG ($verbose_pbm, "$target size is $tsize");
+      LOG ($verbose_decode, "$target size is $tsize");
     }
   }
 
-  $source .= "-" . stats_of($source);
-  print STDOUT "image: ${iw}x${ih} @ $x,$y $base $source\n"
-    if ($verbose_imgmap);
-  if ($imagemap_base) {
-    update_imagemap ($base, $x, $y, $iw, $ih,
-                     $image_ppm, $img_width, $img_height);
+  if (defined($source)) {
+    $source .= "-" . stats_of($source);
+    print STDOUT "image: ${iw}x${ih} @ $x,$y $base $source\n"
+      if ($verbose_imgmap);
+    if ($imagemap_base) {
+      update_imagemap ($base, $x, $y, $iw, $ih,
+                       $image_png, $img_width, $img_height);
+    }
   }
 
   clearlog();
@@ -3646,22 +3615,16 @@ sub paste_image($$$$) {
 
 
 sub update_imagemap($$$$$$$$) {
-  my ($url, $x, $y, $w, $h, $image_ppm, $image_width, $image_height) = @_;
+  my ($url, $x, $y, $w, $h, $image_png, $image_width, $image_height) = @_;
 
   $current_state = "imagemap";
 
   my $max_areas = 200;
 
   $url = html_quote ($url);
-  my $x2 = $x + $w;
-  my $y2 = $y + $h;
-  my $area = "<AREA SHAPE=RECT COORDS=\"$x,$y,$x2,$y2\" HREF=\"$url\">";
-  unshift @imagemap_areas, $area;      # put one on the front
-  if ($#imagemap_areas >= $max_areas) {
-    pop @imagemap_areas;               # take one off the back.
-  }
-
-  LOG ($verbose_pbm, "area: $x,$y,$x2,$y2 (${w}x$h)");
+  push @imagemap_areas, [$x, $y, $w, $h, $url];
+  shift @imagemap_areas if (@imagemap_areas > $max_areas);
+  LOG ($verbose_decode, "area: $x,$y,$w,$h");
 
   my $map_name = $imagemap_base;
   $map_name =~ s@^.*/@@;
@@ -3685,29 +3648,80 @@ sub update_imagemap($$$$$$$$) {
       local $/ = undef;  # read entire file
       $template_html = <$in>;
       close $in;
-      LOG ($verbose_pbm, "read template $imagemap_html");
+      LOG ($verbose_decode, "read template $imagemap_html");
     }
 
-    if ($template_html =~ m/^\s*$/s) {
-      $template_html = ("<MAP NAME=\"$map_name\"></MAP>\n" .
-                        "<IMG SRC=\"$imagemap_jpg2\"" .
-                        " USEMAP=\"$map_name\">\n");
-      LOG ($verbose_pbm, "created dummy template");
+    if (! ($template_html =~ m/\.webcollage_box\b/s)) {  # missing or old
+      $template_html =
+       '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+         "http://www.w3.org/TR/html4/loose.dtd">
+<HTML>
+ <HEAD>
+  <BASE TARGET="_new">
+  <meta HTTP-EQUIV="Refresh" content="60" />
+  <TITLE>WebCollage</TITLE>
+  <STYLE TYPE="text/css">
+   <!--
+    body { color: #FFF; max-width: 100%; }
+    .webcollage_date, .webcollage_size {
+      display: block; margin-top: 4px; font-size: 7pt; color: #888;
+    }
+    .webcollage_date { float: left; }
+    .webcollage_size { float: right; }
+
+    .webcollage_frame {
+      overflow: hidden;
+      position: relative;
+      padding-bottom: 56.25%;
+      padding-bottom: 75%; /* 4:3 aspect ratio */
+      border: 1px solid #888;
+      background: #000;
+    }
+
+    .webcollage_box {
+       position: absolute; top: 0; left: 0;
+       border: 0; margin: 0; padding: 0;
+       width:  100%;
+       height: 100%;
+    }
+
+    .webcollage_box > img { width: 100%; height: 100%; border: 0; }
+
+    .webcollage_frame > a {
+      display: block;
+      position: absolute;
+      border-radius: 16px;
+    }
+
+    .webcollage_frame > a:hover {
+      background: rgba(1,1,1,.25);
+    }
+   -->
+  </STYLE>
+ </HEAD>
+ <BODY>
+  <DIV CLASS="webcollage_frame">
+  </DIV>
+ </BODY>
+</HTML>
+';
+
+      LOG ($verbose_decode, "created dummy template");
     }
   }
 
   # Write the jpg to a tmp file
   #
   {
-    my $cmd;
-    if (defined ($webcollage_helper)) {
-      $cmd = "cp -p $image_ppm $imagemap_jpg_tmp";
+    my @cmd;
+    if (defined($webcollage_helper)) {
+      @cmd = ('cp', '-p', $image_png, $imagemap_jpg_tmp);
     } else {
-      $cmd = "cjpeg < $image_ppm > $imagemap_jpg_tmp";
+      @cmd = ($convert_cmd, $image_png, 'jpeg:' . $imagemap_jpg_tmp);
     }
-    my $rc = nontrapping_system ($cmd);
+    my $rc = nontrapping_system (@cmd);
     if ($rc != 0) {
-      error ("imagemap jpeg failed: \"$cmd\"\n");
+      error ("imagemap jpeg failed: \"@cmd\"\n");
     }
   }
 
@@ -3715,14 +3729,28 @@ sub update_imagemap($$$$$$$$) {
   #
   {
     my $body = $template_html;
-    my $areas = join ("\n\t", @imagemap_areas);
-    my $map = ("<MAP NAME=\"$map_name\">\n\t$areas\n</MAP>");
-    my $img = ("<IMG SRC=\"$imagemap_jpg2\" " .
-               "BORDER=0 " .
-               "WIDTH=$image_width HEIGHT=$image_height " .
-               "USEMAP=\"#$map_name\">");
-    $body =~ s@(<MAP\s+NAME=\"[^\"]*\"\s*>).*?(</MAP>)@$map@is;
-    $body =~ s@<IMG\b[^<>]*\bUSEMAP\b[^<>]*>@$img@is;
+    my $img = ("   <DIV CLASS=\"webcollage_box\">" .
+                    "<IMG SRC=\"$imagemap_jpg2\">" .
+                   "</DIV>\n");
+    foreach my $a (@imagemap_areas) {
+      my ($x, $y, $w, $h, $u) = @$a;
+      $x /= $img_width  / 100;
+      $y /= $img_height / 100;
+      $w /= $img_width  / 100;
+      $h /= $img_height / 100;
+      foreach ($x, $y, $w, $h) { $_ = sprintf("%.1f%%", $_); }
+      $u = html_quote($u);
+      $img .= ("   <A HREF=\"$u\" STYLE=\"" .
+               "left:$x;top:$y;width:$w;height:$h\"/>\n");
+    }
+
+    $img = ("<DIV CLASS=\"webcollage_frame\">\n" .
+            $img .
+            "  </DIV>\n");
+    $body =~ s@<DIV \s+ CLASS=[\"\']webcollage_frame[\"\']>
+                .*? </DIV> .*? </DIV>@$img@sex ||
+      error ("$imagemap_html_tmp: unable to splice image");
+
 
     # if there are magic webcollage spans in the html, update those too.
     #
@@ -3734,20 +3762,23 @@ sub update_imagemap($$$$$$$$) {
       $body =~ s@(<SPAN\s+CLASS=\"webcollage_size\">).*?(</SPAN>)@$1$size$2@si;
     }
 
-    open (my $out, '>', $imagemap_html_tmp) || error ("$imagemap_html_tmp: $!");
-    (print $out $body)                      || error ("$imagemap_html_tmp: $!");
-    close ($out)                            || error ("$imagemap_html_tmp: $!");
-    LOG ($verbose_pbm, "wrote $imagemap_html_tmp");
+    open (my $out, '>', $imagemap_html_tmp) || error("$imagemap_html_tmp: $!");
+    (print $out $body)                      || error("$imagemap_html_tmp: $!");
+    close ($out)                            || error("$imagemap_html_tmp: $!");
+    LOG ($verbose_decode, "wrote $imagemap_html_tmp");
   }
 
   # Rename the two tmp files to the real files
   #
   rename ($imagemap_html_tmp, $imagemap_html) ||
     error "renaming $imagemap_html_tmp to $imagemap_html";
-  LOG ($verbose_pbm, "wrote $imagemap_html");
-  rename ($imagemap_jpg_tmp,  $imagemap_jpg) ||
-    error "renaming $imagemap_jpg_tmp to $imagemap_jpg";
-  LOG ($verbose_pbm, "wrote $imagemap_jpg");
+  LOG ($verbose_decode, "wrote $imagemap_html");
+
+  if ($imagemap_jpg_tmp ne $image_png) {
+    rename ($imagemap_jpg_tmp,  $imagemap_jpg) ||
+      error "renaming $imagemap_jpg_tmp to $imagemap_jpg";
+    LOG ($verbose_decode, "wrote $imagemap_jpg");
+  }
 }
 
 
@@ -3803,7 +3834,7 @@ sub init_signals() {
   $SIG{KILL} = \&signal_cleanup;
   $SIG{TERM} = \&signal_cleanup;
 
-  # Need this so that if giftopnm dies, we don't die.
+  # Need this so that if subprocess filters die, we don't die.
   $SIG{PIPE} = 'IGNORE';
 }
 
@@ -3963,7 +3994,7 @@ sub main() {
     $verbose_load     = 1;
     $verbose_filter   = 1;
     $verbose_net      = 1;
-    $verbose_pbm      = 1;
+    $verbose_decode   = 1;
 
   } elsif ($verbose == 6) {
     $verbose_imgmap   = 1;
@@ -3971,7 +4002,7 @@ sub main() {
     $verbose_load     = 1;
     $verbose_filter   = 1;
     $verbose_net      = 1;
-    $verbose_pbm      = 1;
+    $verbose_decode   = 1;
     $verbose_http     = 1;
 
   } elsif ($verbose >= 7) {
@@ -3980,7 +4011,7 @@ sub main() {
     $verbose_load     = 1;
     $verbose_filter   = 1;
     $verbose_net      = 1;
-    $verbose_pbm      = 1;
+    $verbose_decode   = 1;
     $verbose_http     = 1;
     $verbose_exec     = 1;
   }
@@ -4009,7 +4040,7 @@ sub main() {
   if ($urls_only_p) {
     url_only_output ();
   } else {
-    x_or_pbm_output ($window_id);
+    x_or_image_output ($window_id);
   }
 }
 
index f85b7071f9258d6ba4d8308b2b22e9e445460a46..ffebfa6c33e6a783496a100bcd2136c9367d0a6f 100644 (file)
@@ -1,5 +1,5 @@
 /* webcollage-helper-cocoa --- scales and pastes one image into another
- * xscreensaver, Copyright (c) 2002-2014 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 2002-2017 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
@@ -284,6 +284,61 @@ paste (const char *paste_file,
 }
 
 
+static NSColor *
+parse_color (const char *s)
+{
+  static const char hex[128] =
+    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+     0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
+     0, 10,11,12,13,14,15,0, 0, 0, 0, 0, 0, 0, 0, 0,
+     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+     0, 10,11,12,13,14,15,0, 0, 0, 0, 0, 0, 0, 0, 0,
+     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+  unsigned char r=0, g=0, b=0;
+
+  if      (!strcasecmp (s, "black")) ;
+  else if (!strcasecmp (s, "white")) r = g = b = 0xFF;
+  else if (!strcasecmp (s, "red"))   r = 0xFF;
+  else if (!strcasecmp (s, "green")) g = 0xFF;
+  else if (!strcasecmp (s, "blue"))  b = 0xFF;
+  else
+    {
+      if (*s != '#' || strlen(s) != 7)
+        {
+          fprintf (stderr, "%s: unparsable color: \"%s\"\n", progname, s);
+          exit (1);
+        }
+      s++;
+      r = (hex[(int) s[0]] << 4) | hex[(int) s[1]], s += 2;
+      g = (hex[(int) s[0]] << 4) | hex[(int) s[1]], s += 2;
+      b = (hex[(int) s[0]] << 4) | hex[(int) s[1]], s += 2;
+    }
+
+  return [NSColor colorWithRed: r / 255.0
+                         green: g / 255.0
+                          blue: b / 255.0
+                         alpha: 1.0];
+}
+
+
+static void
+create (const char *color,
+        int w, int h,
+        const char *file)
+{
+  NSColor *c = parse_color (color);
+  NSImage *img = [[NSImage alloc] initWithSize:NSMakeSize(w, h)];
+  [img lockFocus];
+  [c drawSwatchInRect:NSMakeRect(0, 0, w, h)];
+  [img unlockFocus];
+  write_image (img, file);
+  [img release];
+}
+
+
 static void
 write_image (NSImage *img, const char *file)
 {
@@ -334,14 +389,18 @@ write_image (NSImage *img, const char *file)
 static void
 usage (void)
 {
-  fprintf (stderr, "usage: %s [-v] paste-file base-file\n"
+  fprintf (stderr,
+           "\nusage: %s [-v] paste-file base-file\n"
            "\t from-scale opacity\n"
            "\t from-x from-y to-x to-y w h\n"
            "\n"
            "\t Pastes paste-file into base-file.\n"
            "\t base-file will be overwritten (with JPEG data.)\n"
-           "\t scaling is applied first: coordinates apply to scaled image.\n",
-           progname);
+           "\t scaling is applied first: coordinates apply to scaled image.\n"
+           "\n"
+           "usage: %s [-v] color width height output-file\n"
+           "\t Creates a new image of a solid color.\n\n",
+           progname, progname);
   exit (1);
 }
 
@@ -359,44 +418,6 @@ main (int argc, char **argv)
   s = strrchr (progname, '/');
   if (s) progname = s+1;
 
-  if (argc != 11 && argc != 12) usage();
-
-  if (!strcmp(argv[i], "-v"))
-    verbose_p++, i++;
-
-  paste_file = argv[i++];
-  base_file = argv[i++];
-
-  if (*paste_file == '-') usage();
-  if (*base_file == '-') usage();
-
-  s = argv[i++];
-  if (1 != sscanf (s, " %lf %c", &from_scale, &dummy)) usage();
-  if (from_scale <= 0 || from_scale > 100) usage();
-
-  s = argv[i++];
-  if (1 != sscanf (s, " %lf %c", &opacity, &dummy)) usage();
-  if (opacity <= 0 || opacity > 1) usage();
-
-  s = argv[i++]; if (1 != sscanf (s, " %d %c", &from_x, &dummy)) usage();
-  s = argv[i++]; if (1 != sscanf (s, " %d %c", &from_y, &dummy)) usage();
-  s = argv[i++]; if (1 != sscanf (s, " %d %c", &to_x, &dummy)) usage();
-  s = argv[i++]; if (1 != sscanf (s, " %d %c", &to_y, &dummy)) usage();
-  s = argv[i++]; if (1 != sscanf (s, " %d %c", &w, &dummy)) usage();
-  s = argv[i];   if (1 != sscanf (s, " %d %c", &h, &dummy)) usage();
-
-  bevel_pct = 10; /* #### */
-
-  if (w < 0) usage();
-  if (h < 0) usage();
-
-  if (w == 0 || h == 0 || 
-      w > 10240 || h > 10240) {
-    fprintf (stderr, "%s: absurd size: %d x %d\n", progname, w, h);
-    exit (1);
-  }
-
-
   // Much of Cocoa needs one of these to be available.
   NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 
@@ -404,10 +425,62 @@ main (int argc, char **argv)
   NSApp = [NSApplication sharedApplication];
   [NSApp autorelease];
 
-  paste (paste_file, base_file,
-         from_scale, opacity, bevel_pct,
-         from_x, from_y, to_x, to_y,
-         w, h);
+  if (!strcmp(argv[i], "-v"))
+    verbose_p++, i++;
+
+  if (argc == 11 || argc == 12)
+    {
+      paste_file = argv[i++];
+      base_file = argv[i++];
+
+      if (*paste_file == '-') usage();
+      if (*base_file == '-') usage();
+
+      s = argv[i++];
+      if (1 != sscanf (s, " %lf %c", &from_scale, &dummy)) usage();
+      if (from_scale <= 0 || from_scale > 100) usage();
+
+      s = argv[i++];
+      if (1 != sscanf (s, " %lf %c", &opacity, &dummy)) usage();
+      if (opacity <= 0 || opacity > 1) usage();
+
+      s = argv[i++]; if (1 != sscanf (s, " %d %c", &from_x, &dummy)) usage();
+      s = argv[i++]; if (1 != sscanf (s, " %d %c", &from_y, &dummy)) usage();
+      s = argv[i++]; if (1 != sscanf (s, " %d %c", &to_x, &dummy)) usage();
+      s = argv[i++]; if (1 != sscanf (s, " %d %c", &to_y, &dummy)) usage();
+      s = argv[i++]; if (1 != sscanf (s, " %d %c", &w, &dummy)) usage();
+      s = argv[i];   if (1 != sscanf (s, " %d %c", &h, &dummy)) usage();
+
+      bevel_pct = 10; /* #### */
+
+      if (w < 0) usage();
+      if (h < 0) usage();
+
+      if (w == 0 || h == 0 || 
+          w > 10240 || h > 10240) {
+        fprintf (stderr, "%s: absurd size: %d x %d\n", progname, w, h);
+        exit (1);
+      }
+
+      paste (paste_file, base_file,
+             from_scale, opacity, bevel_pct,
+             from_x, from_y, to_x, to_y,
+             w, h);
+    }
+  else if (argc == 4 || argc == 5)
+    {
+      char *color = argv[i++];
+      s = argv[i++]; if (1 != sscanf (s, " %d %c", &w, &dummy)) usage();
+      s = argv[i++]; if (1 != sscanf (s, " %d %c", &h, &dummy)) usage();
+      paste_file = argv[i++];
+      if (*paste_file == '-') usage();
+
+      create (color, w, h, paste_file);
+    }
+  else
+    {
+      usage();
+    }
 
   [pool release];
 
index 19786ba129f3204bdc08e5a293bc0fec631a9801..46ec608a8056d5abdf20b9151f80239c7b415887 100644 (file)
@@ -1,5 +1,5 @@
 /* webcollage-helper --- scales and pastes one image into another
- * xscreensaver, Copyright (c) 2002-2005 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 2002-2017 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
@@ -329,6 +329,72 @@ paste (const char *paste_file,
 }
 
 
+static guint32
+parse_color (const char *s)
+{
+  static const char hex[128] =
+    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+     0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
+     0, 10,11,12,13,14,15,0, 0, 0, 0, 0, 0, 0, 0, 0,
+     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+     0, 10,11,12,13,14,15,0, 0, 0, 0, 0, 0, 0, 0, 0,
+     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+  unsigned char r=0, g=0, b=0;
+
+  if      (!strcasecmp (s, "black")) ;
+  else if (!strcasecmp (s, "white")) r = g = b = 0xFF;
+  else if (!strcasecmp (s, "red"))   r = 0xFF;
+  else if (!strcasecmp (s, "green")) g = 0xFF;
+  else if (!strcasecmp (s, "blue"))  b = 0xFF;
+  else
+    {
+      if (*s != '#' || strlen(s) != 7)
+        {
+          fprintf (stderr, "%s: unparsable color: \"%s\"\n", progname, s);
+          exit (1);
+        }
+      s++;
+      r = (hex[(int) s[0]] << 4) | hex[(int) s[1]], s += 2;
+      g = (hex[(int) s[0]] << 4) | hex[(int) s[1]], s += 2;
+      b = (hex[(int) s[0]] << 4) | hex[(int) s[1]], s += 2;
+    }
+
+  return (r << 16) | (g << 8) | b;
+}
+
+
+static void
+create (const char *color,
+        int w, int h,
+        const char *file)
+{
+  int i;
+  GdkPixbuf *pb;
+  guint32 pixel = parse_color (color);
+  unsigned char *bytes = malloc (w * h * 3);
+  if (!bytes) abort();
+  for (i = 0; i < w * h * 3; i += 3)
+    {
+      bytes[i]   = 0xFF & (pixel >> 16);
+      bytes[i+1] = 0xFF & (pixel >> 8);
+      bytes[i+2] = 0xFF & (pixel);
+    }
+
+  pb = gdk_pixbuf_new_from_data (bytes, GDK_COLORSPACE_RGB,
+                                 FALSE, 8, /* alpha, sample size */
+                                 w, h,
+                                 w * 3,   /* rowstride */
+                                 NULL, 0);
+  if (!pb) abort();
+  write_pixbuf (pb, file);
+  g_object_unref (pb);
+  free (bytes);
+}
+
+
 static void
 write_pixbuf (GdkPixbuf *pb, const char *file)
 {
@@ -434,14 +500,18 @@ add_jpeg_comment (struct jpeg_compress_struct *cinfo)
 static void
 usage (void)
 {
-  fprintf (stderr, "usage: %s [-v] paste-file base-file\n"
+  fprintf (stderr,
+           "\nusage: %s [-v] paste-file base-file\n"
            "\t from-scale opacity\n"
            "\t from-x from-y to-x to-y w h\n"
            "\n"
            "\t Pastes paste-file into base-file.\n"
            "\t base-file will be overwritten (with JPEG data.)\n"
-           "\t scaling is applied first: coordinates apply to scaled image.\n",
-           progname);
+           "\t scaling is applied first: coordinates apply to scaled image.\n"
+           "\n"
+           "usage: %s [-v] color width height output-file\n"
+           "\t Creates a new image of a solid color.\n\n",
+           progname, progname);
   exit (1);
 }
 
@@ -459,47 +529,63 @@ main (int argc, char **argv)
   s = strrchr (progname, '/');
   if (s) progname = s+1;
 
-  if (argc != 11 && argc != 12) usage();
-
   if (!strcmp(argv[i], "-v"))
     verbose_p++, i++;
 
-  paste_file = argv[i++];
-  base_file = argv[i++];
-
-  if (*paste_file == '-') usage();
-  if (*base_file == '-') usage();
-
-  s = argv[i++];
-  if (1 != sscanf (s, " %lf %c", &from_scale, &dummy)) usage();
-  if (from_scale <= 0 || from_scale > 100) usage();
-
-  s = argv[i++];
-  if (1 != sscanf (s, " %lf %c", &opacity, &dummy)) usage();
-  if (opacity <= 0 || opacity > 1) usage();
-
-  s = argv[i++]; if (1 != sscanf (s, " %d %c", &from_x, &dummy)) usage();
-  s = argv[i++]; if (1 != sscanf (s, " %d %c", &from_y, &dummy)) usage();
-  s = argv[i++]; if (1 != sscanf (s, " %d %c", &to_x, &dummy)) usage();
-  s = argv[i++]; if (1 != sscanf (s, " %d %c", &to_y, &dummy)) usage();
-  s = argv[i++]; if (1 != sscanf (s, " %d %c", &w, &dummy)) usage();
-  s = argv[i++]; if (1 != sscanf (s, " %d %c", &h, &dummy)) usage();
-
-  bevel_pct = 10; /* #### */
-
-  if (w < 0) usage();
-  if (h < 0) usage();
+  if (argc == 11 || argc == 12)
+    {
+      paste_file = argv[i++];
+      base_file = argv[i++];
+
+      if (*paste_file == '-') usage();
+      if (*base_file == '-') usage();
+
+      s = argv[i++];
+      if (1 != sscanf (s, " %lf %c", &from_scale, &dummy)) usage();
+      if (from_scale <= 0 || from_scale > 100) usage();
+
+      s = argv[i++];
+      if (1 != sscanf (s, " %lf %c", &opacity, &dummy)) usage();
+      if (opacity <= 0 || opacity > 1) usage();
+
+      s = argv[i++]; if (1 != sscanf (s, " %d %c", &from_x, &dummy)) usage();
+      s = argv[i++]; if (1 != sscanf (s, " %d %c", &from_y, &dummy)) usage();
+      s = argv[i++]; if (1 != sscanf (s, " %d %c", &to_x, &dummy)) usage();
+      s = argv[i++]; if (1 != sscanf (s, " %d %c", &to_y, &dummy)) usage();
+      s = argv[i++]; if (1 != sscanf (s, " %d %c", &w, &dummy)) usage();
+      s = argv[i];   if (1 != sscanf (s, " %d %c", &h, &dummy)) usage();
+
+      bevel_pct = 10; /* #### */
+
+      if (w < 0) usage();
+      if (h < 0) usage();
+
+# ifdef HAVE_GTK2
+#  if !GLIB_CHECK_VERSION(2, 36 ,0)
+      g_type_init ();
+#  endif
+# endif /* HAVE_GTK2 */
+
+      paste (paste_file, base_file,
+             from_scale, opacity, bevel_pct,
+             from_x, from_y, to_x, to_y,
+             w, h);
+    }
+  else if (argc == 4 || argc == 5)
+    {
+      char *color = argv[i++];
+      s = argv[i++]; if (1 != sscanf (s, " %d %c", &w, &dummy)) usage();
+      s = argv[i++]; if (1 != sscanf (s, " %d %c", &h, &dummy)) usage();
+      paste_file = argv[i++];
+      if (*paste_file == '-') usage();
 
-#ifdef HAVE_GTK2
-#if !GLIB_CHECK_VERSION(2, 36 ,0)
-  g_type_init ();
-#endif
-#endif /* HAVE_GTK2 */
+      create (color, w, h, paste_file);
+    }
+  else
+    {
+      usage();
+    }
 
-  paste (paste_file, base_file,
-         from_scale, opacity, bevel_pct,
-         from_x, from_y, to_x, to_y,
-         w, h);
   exit (0);
 }
 
index 1989b3ab1ed2e14de8e853b1f446908b6c478818..452ae12dd4e20b7f4baf7585f205d9903dffda16 100644 (file)
@@ -52,6 +52,7 @@ static const char sccsid[] = "@(#)worm.c      4.04 97/07/28 xlockmore";
                                        "*fpsSolid:  true \n" \
 
 # define SMOOTH_COLORS
+# define release_worm 0
 # define reshape_worm 0
 # define worm_handle_event 0
 # include "xlockmore.h"                /* in xscreensaver distribution */
@@ -240,11 +241,16 @@ worm_doit(ModeInfo * mi, int which, unsigned long color)
        }
 }
 
-static void
-free_worms(wormstruct * wp)
+ENTRYPOINT void
+free_worm(ModeInfo * mi)
 {
+       wormstruct *wp;
        int         wn;
 
+       if(!worms)
+               return;
+       wp = &worms[MI_SCREEN(mi)];
+
        if (wp->worm) {
                for (wn = 0; wn < wp->nw; wn++) {
                        if (wp->worm[wn].circ)
@@ -272,7 +278,7 @@ init_worm (ModeInfo * mi)
        int         size = MI_SIZE(mi);
        int         i, j;
 
-       MI_INIT (mi, worms, 0);
+       MI_INIT (mi, worms);
        wp = &worms[MI_SCREEN(mi)];
        if (MI_NPIXELS(mi) <= 2 || MI_WIN_IS_USE3D(mi))
                wp->nc = 2;
@@ -281,7 +287,7 @@ init_worm (ModeInfo * mi)
        if (wp->nc > NUMCOLORS)
                wp->nc = NUMCOLORS;
 
-       free_worms(wp);
+       free_worm(mi);
        wp->nw = MI_BATCHCOUNT(mi);
        if (wp->nw < -MINWORMS)
                wp->nw = NRAND(-wp->nw - MINWORMS + 1) + MINWORMS;
@@ -403,19 +409,7 @@ draw_worm (ModeInfo * mi)
                wp->chromo = 0;
 }
 
-ENTRYPOINT void
-release_worm(ModeInfo * mi)
-{
-       if (worms != NULL) {
-               int         screen;
-
-               for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
-                       free_worms(&worms[screen]);
-               (void) free((void *) worms);
-               worms = NULL;
-       }
-}
-
+#ifndef STANDALONE
 ENTRYPOINT void
 refresh_worm (ModeInfo * mi)
 {
@@ -434,5 +428,6 @@ refresh_worm (ModeInfo * mi)
                }
        }
 }
+#endif
 
 XSCREENSAVER_MODULE ("Worm", worm)
index c8cdfcdac746ad3d3b837958d89c7f5bacbb9c7b..f28c5b2514640688032bdefd7be59347ab772dcd 100644 (file)
@@ -703,6 +703,7 @@ wormhole_free (Display *dpy, Window window, void *closure)
 
 
 static const char *wormhole_defaults [] = {
+  ".lowrez:     true",
   ".background:        Black",
   ".foreground:        #E9967A",
   "*delay:     10000",
index 29e1eb6d8c897b7116a5e79adbf18196db247448..72caa104e7c09dfff8d66183400fd65c3c6d43ea 100644 (file)
@@ -238,6 +238,28 @@ xlockmore_setup (struct xscreensaver_function_table *xsft, void *arg)
 }
 
 
+static void
+xlockmore_release_screens (ModeInfo *mi)
+{
+  struct xlockmore_function_table *xlmft = mi->xlmft;
+
+  /* 2. Call release_##, if it exists. */
+  if (xlmft->hack_release)
+    xlmft->hack_release (mi);
+
+  /* 3. Free the state array. */
+  if (xlmft->state_array) {
+    free(*xlmft->state_array);
+    *xlmft->state_array = NULL;
+    xlmft->state_array = NULL;
+  }
+
+  /* 4. Pretend FreeAllGL(mi) gets called here. */
+
+  mi->xlmft->got_init = 0;
+}
+
+
 static void
 xlockmore_free_screens (ModeInfo *mi)
 {
@@ -250,29 +272,16 @@ xlockmore_free_screens (ModeInfo *mi)
   /* Order is important here: */
 
   /* 1. Call free_## for all screens. */
-  if (xlmft->hack_free_state) {
+  if (xlmft->hack_free) {
     int old_screen = mi->screen_number;
     for (mi->screen_number = 0; mi->screen_number < XLOCKMORE_NUM_SCREENS;
          ++mi->screen_number) {
-      xlmft->hack_free_state (mi);
+      xlmft->hack_free (mi);
     }
     mi->screen_number = old_screen;
   }
 
-  /* 2. Call release_##, if it exists. */
-  if (xlmft->hack_release)
-    xlmft->hack_release (mi);
-
-  /* 3. Free the state array. */
-  if (xlmft->state_array) {
-    free(*xlmft->state_array);
-    *xlmft->state_array = NULL;
-    xlmft->state_array = NULL;
-  }
-
-  /* 4. Pretend FreeAllGL(mi) gets called here. */
-
-  mi->xlmft->got_init = 0;
+  xlockmore_release_screens (mi);
 }
 
 
@@ -558,12 +567,40 @@ xlockmore_init (Display *dpy, Window window,
   return mi;
 }
 
-static void xlockmore_do_init (ModeInfo *mi)
+
+static void
+xlockmore_do_init (ModeInfo *mi)
 {
-  if (! (mi->xlmft->got_init & (1 << mi->screen_number))) {
-    mi->xlmft->got_init |= 1 << mi->screen_number;
-    XClearWindow (mi->dpy, mi->window);
-    mi->xlmft->hack_init (mi);
+  mi->xlmft->got_init |= 1 << mi->screen_number;
+  XClearWindow (mi->dpy, mi->window);
+  mi->xlmft->hack_init (mi);
+}
+
+
+static Bool
+xlockmore_got_init (ModeInfo *mi)
+{
+  return mi->xlmft->got_init & (1 << mi->screen_number);
+}
+
+
+static void
+xlockmore_abort_erase (ModeInfo *mi)
+{
+  if (mi->eraser) {
+    eraser_free (mi->eraser);
+    mi->eraser = NULL;
+  }
+  mi->needs_clear = False;
+}
+
+
+static void
+xlockmore_check_init (ModeInfo *mi)
+{
+  if (! xlockmore_got_init (mi)) {
+    xlockmore_abort_erase (mi);
+    xlockmore_do_init (mi);
   }
 }
 
@@ -575,12 +612,27 @@ xlockmore_draw (Display *dpy, Window window, void *closure)
   unsigned long orig_pause = mi->pause;
   unsigned long this_pause;
 
-  xlockmore_do_init (mi);
+  if (mi->needs_clear) {
+    /* OpenGL hacks never get here. */
+    if (!mi->is_drawn) {
+      XClearWindow (dpy, window);
+    } else {
+      mi->eraser = erase_window (dpy, window, mi->eraser);
+      /* Delay calls to xlockmore hooks while the erase animation is running. */
+      if (mi->eraser)
+        return 33333;
+    }
+    mi->needs_clear = False;
+  }
+
+  xlockmore_check_init (mi);
+  if (mi->needs_clear)
+    return 0;
   mi->xlmft->hack_draw (mi);
 
   this_pause = mi->pause;
   mi->pause  = orig_pause;
-  return this_pause;
+  return mi->needs_clear ? 0 : this_pause;
 }
 
 
@@ -589,24 +641,55 @@ xlockmore_reshape (Display *dpy, Window window, void *closure,
                  unsigned int w, unsigned int h)
 {
   ModeInfo *mi = (ModeInfo *) closure;
-  if (mi && mi->xlmft->hack_reshape)
-    {
-      XGetWindowAttributes (dpy, window, &mi->xgwa);
-      xlockmore_do_init (mi);
+  if (mi) {
+    /* Ignore spurious resize events, because xlockmore_do_init usually clears
+       the screen, and there's no reason to do that if we don't have to.
+     */
+# ifndef HAVE_MOBILE
+    /* These are not spurious on mobile: they are rotations. */
+    if (mi->xgwa.width == w && mi->xgwa.height == h)
+      return;
+# endif
+    mi->xgwa.width = w;
+    mi->xgwa.height = h;
+
+    /* Finish any erase operations. */
+    if (mi->needs_clear) {
+      xlockmore_abort_erase (mi);
+      XClearWindow (dpy, window);
+    }
+
+    /* If there hasn't been an init yet, init now, but don't call reshape_##.
+     */
+    if (xlockmore_got_init (mi) && mi->xlmft->hack_reshape) {
       mi->xlmft->hack_reshape (mi, mi->xgwa.width, mi->xgwa.height);
+    } else {
+      mi->is_drawn = False;
+      xlockmore_do_init (mi);
     }
+  }
 }
 
 static Bool
 xlockmore_event (Display *dpy, Window window, void *closure, XEvent *event)
 {
   ModeInfo *mi = (ModeInfo *) closure;
-  if (mi && mi->xlmft->hack_handle_events) {
-    xlockmore_do_init (mi);
-    return mi->xlmft->hack_handle_events (mi, event);
-  } else {
-    return False;
+  if (mi) {
+    if (mi->xlmft->hack_handle_events) {
+      xlockmore_check_init (mi);
+      return mi->xlmft->hack_handle_events (mi, event);
+    }
+
+    if (screenhack_event_helper (mi->dpy, mi->window, event)) {
+      /* If a clear is in progress, don't interrupt or restart it. */
+      if (mi->needs_clear)
+        mi->xlmft->got_init &= ~(1ul << mi->screen_number);
+      else
+        mi->xlmft->hack_init (mi);
+      return True;
+    }
   }
+  return False;
 }
 
 void
@@ -623,11 +706,22 @@ xlockmore_free (Display *dpy, Window window, void *closure)
 {
   ModeInfo *mi = (ModeInfo *) closure;
 
+  if (mi->eraser)
+    eraser_free (mi->eraser);
+
+  /* Some hacks may need to do things with their Display * on cleanup. And
+     under JWXYZ, the Display * for this hack gets cleaned up right after
+     xlockmore_free returns. Thus, hack_free has to happen now, rather than
+     after the final screen has been released.
+   */
+  if (mi->xlmft->hack_free)
+    mi->xlmft->hack_free (mi);
+
   /* Find us in live_displays and clear that slot. */
   assert (mi->xlmft->live_displays & (1ul << mi->screen_number));
   mi->xlmft->live_displays &= ~(1ul << mi->screen_number);
   if (!mi->xlmft->live_displays)
-    xlockmore_free_screens (mi);
+    xlockmore_release_screens (mi);
 
   XFreeGC (dpy, mi->gc);
   free_colors (mi->xgwa.screen, mi->xgwa.colormap, mi->colors, mi->npixels);
@@ -639,8 +733,7 @@ xlockmore_free (Display *dpy, Window window, void *closure)
 
 
 void
-xlockmore_mi_init (ModeInfo *mi, size_t state_size, void **state_array,
-                         void (*hack_free_state) (ModeInfo *))
+xlockmore_mi_init (ModeInfo *mi, size_t state_size, void **state_array)
 {
   struct xlockmore_function_table *xlmft = mi->xlmft;
 
@@ -651,11 +744,6 @@ xlockmore_mi_init (ModeInfo *mi, size_t state_size, void **state_array,
   assert ((!xlmft->state_array && !*state_array) ||
           xlmft->state_array == state_array);
   xlmft->state_array = state_array;
-  assert (!xlmft->state_size || xlmft->state_size == state_size);
-  xlmft->state_size = state_size;
-  assert (!xlmft->hack_free_state ||
-          xlmft->hack_free_state == hack_free_state);
-  xlmft->hack_free_state = hack_free_state;
 
   if (!*xlmft->state_array) {
     *xlmft->state_array = calloc (XLOCKMORE_NUM_SCREENS, state_size);
@@ -673,9 +761,16 @@ xlockmore_mi_init (ModeInfo *mi, size_t state_size, void **state_array,
 
   /* Find the appropriate state object, clear it, and we're done. */
   {
-    if (xlmft->hack_free_state)
-      xlmft->hack_free_state (mi);
+    if (xlmft->hack_free)
+      xlmft->hack_free (mi);
     memset ((char *)(*xlmft->state_array) + mi->screen_number * state_size, 0,
             state_size);
   }
 }
+
+
+Bool
+xlockmore_no_events (ModeInfo *mi, XEvent *event)
+{
+  return False;
+}
index fe09961481869246ad0aea95c34c5233580d76c2..6b604c5f8219277d2debdd13fc888236281229d0 100644 (file)
@@ -1,5 +1,5 @@
 /* xlockmore.h --- xscreensaver compatibility layer for xlockmore modules.
- * xscreensaver, Copyright (c) 1997-2012 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1997-2017 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
@@ -88,7 +88,18 @@ ERROR!  Sorry, xlockmore.h requires ANSI C (gcc, for example.)
 #define MI_IS_DEBUG(MI)                (False)
 #define MI_IS_MOUSE(MI)                (False)
 
-#define MI_CLEARWINDOW(mi) XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi))
+/* Under xlockmore, MI_CLEARWINDOW runs immediately, and for animated clears
+   it delays execution while the animation runs. This doesn't work on
+   XScreenSaver, which has mandatory double-buffering on macOS/iOS/Android.
+
+   Tricky: As a result, MI_CLEARWINDOW doesn't clear the window until after
+   init_##() or draw_##() finishes.
+ */
+#ifdef USE_GL
+# define MI_CLEARWINDOW(mi) XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi))
+#else
+# define MI_CLEARWINDOW(mi) ((mi)->needs_clear = True)
+#endif
 
 /* MI_INIT and MI_ABORT are XScreenSaver extensions. These exist primarily for
    the sake of ports to macOS, iOS, and Android, all of which need to restart
@@ -110,14 +121,12 @@ ERROR!  Sorry, xlockmore.h requires ANSI C (gcc, for example.)
    hack_free_state(mi);
    memset(&state_array[MI_SCREEN(mi)], 0, sizeof(*state_array));
 
-   It also enables hack_free_state to run when a screen is no longer in use.
-   This is called at some point after the last call to draw_##, but before
-   release_##.
+   MI_INIT also assumes ownership of the state_array over to xlockmore.c,
+   which frees it after all screens (or "screens") are closed.
  */
 
-#define MI_INIT(mi, state_array, hack_free_state) \
-  xlockmore_mi_init ((mi), sizeof(*(state_array)), (void **)&(state_array), \
-                     hack_free_state)
+#define MI_INIT(mi, state_array) \
+  xlockmore_mi_init ((mi), sizeof(*(state_array)), (void **)&(state_array))
 
 /* Use MI_ABORT if an init_## or draw_## hook needs to shut everything down.
    This replaces explicit calls to release_## hooks when things go wrong from
@@ -214,8 +223,8 @@ ERROR!  Sorry, xlockmore.h requires ANSI C (gcc, for example.)
           init_    ## PREFIX,                                          \
           draw_    ## PREFIX,                                          \
           reshape_ ## PREFIX,                                          \
-          refresh_ ## PREFIX,                                          \
           release_ ## PREFIX,                                          \
+          free_    ## PREFIX,                                          \
           PREFIX   ## _handle_event,                                   \
           & PREFIX ## _opts                                            \
   };                                                                   \
index 432e600c39f82652e29d65f0c9a504e9ec8d53ad..bf0adbf46550a4fcd67468bd659072bd5e33989a 100644 (file)
@@ -1,5 +1,5 @@
 /* xlockmore.h --- xscreensaver compatibility layer for xlockmore modules.
- * xscreensaver, Copyright (c) 1997-2014 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1997-2017 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
 #include <time.h>
 
 #include "screenhackI.h"
-#include "xshm.h"
+#include "erase.h"
 
 
 typedef struct ModeInfo ModeInfo;
 
-#ifdef USE_GL
+#ifdef HAVE_GL
 
 /* I'm told that the Sun version of OpenGL needs to have the constant
    SUN_OGL_NO_VERTEX_MACROS defined in order for morph3d to compile
@@ -53,7 +53,10 @@ typedef struct ModeInfo ModeInfo;
 # ifdef HAVE_JWZGLES
 #  include "jwzgles.h"
 # endif /* HAVE_JWZGLES */
+#endif /* HAVE_GL */
+
 
+#ifdef USE_GL
 
   extern GLXContext *init_GL (ModeInfo *);
   extern void xlockmore_reset_gl_state(void);
@@ -63,7 +66,7 @@ typedef struct ModeInfo ModeInfo;
   extern Visual *xlockmore_pick_gl_visual (Screen *);
   extern Bool xlockmore_validate_gl_visual (Screen *, const char *, Visual *);
 
-#endif /* !USE_GL */
+#endif /* USE_GL */
 
 /* These are only used in GL mode, but I don't understand why XCode
    isn't seeing the prototypes for them in glx/fps-gl.c... */
@@ -75,10 +78,8 @@ extern void xlockmore_gl_draw_fps (ModeInfo *);
 
 extern void xlockmore_setup (struct xscreensaver_function_table *, void *);
 extern void xlockmore_do_fps (Display *, Window, fps_state *, void *);
-
-
-extern void xlockmore_mi_init (ModeInfo *, size_t, void **,
-                               void (*) (ModeInfo *));
+extern void xlockmore_mi_init (ModeInfo *, size_t, void **);
+extern Bool xlockmore_no_events (ModeInfo *, XEvent *);
 
 
 /* The xlockmore RNG API is implemented in utils/yarandom.h. */
@@ -111,12 +112,17 @@ struct ModeInfo {
   long threed_delta;
   Bool wireframe_p;
   Bool is_drawn;
+  eraser_state *eraser;
+  Bool needs_clear;
 
   /* Used only by OpenGL programs, since FPS is tricky there. */
   fps_state *fpst;
   Bool fps_p;
   unsigned long polygon_count;  /* These values are for -fps display only */
   double recursion_depth;
+#if !defined HAVE_JWXYZ && defined HAVE_GL
+  GLXContext glx_context;
+#endif
 };
 
 typedef enum {  t_String, t_Float, t_Int, t_Bool } xlockmore_type;
@@ -152,14 +158,12 @@ struct xlockmore_function_table {
   void (*hack_init) (ModeInfo *);
   void (*hack_draw) (ModeInfo *);
   void (*hack_reshape) (ModeInfo *, int, int);
-  void (*hack_refresh) (ModeInfo *);
   void (*hack_release) (ModeInfo *);
+  void (*hack_free) (ModeInfo *);
   Bool (*hack_handle_events) (ModeInfo *, XEvent *);
   ModeSpecOpt *opts;
 
-  size_t state_size;
   void **state_array;
-  void (*hack_free_state) (ModeInfo *);
   unsigned long live_displays, got_init;
 };
 
index adccb0c66dd091a696bcd9a2e903c5fca6fa81a5..9f97bb773205cde19267a905b0d2170b35ea0f4b 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1999-2015 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1999-2017 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
@@ -1331,6 +1331,33 @@ hack_text (m_state *state)
       state->typing_delay = state->typing_char_delay;
       if (state->typing_cursor_p)
         set_cursor (state, True);
+
+# ifdef USE_IPHONE
+  /* Stupid iPhone X bezel.
+     #### This is the worst of all possible ways to do this!  But how else?
+   */
+  if (state->xgwa.width == 2436 || state->xgwa.height == 2436)
+    switch (state->mode) 
+      {
+      case TRACE_TEXT_A:
+      case TRACE_TEXT_B:
+      case KNOCK:
+      case NMAP:
+        {
+          int off = 5 * (state->small_p ? 2 : 1);
+          if (state->xgwa.width > state->xgwa.height)
+            {
+              state->typing_left_margin += off;
+              state->cursor_x += off;
+            }
+          else
+            {
+              state->cursor_y += off;
+            }
+        }
+      default: break;
+      }
+# endif
     }
   else
     {
index 464fa7a601cc0f7a25c5e8487179a41237496fbd..678c7b042eea9fd82175e3c286f85f377f3c206b 100644 (file)
@@ -60,6 +60,7 @@ from the X Consortium.
  **********************************************************************/
 
 static const char *xrayswarm_defaults [] ={
+        ".lowrez:               true",
        ".background:           black",
        "*delay:                20000",
        "*fpsSolid:             true",
index 99a652a54cd5f5d9abc9842fbece4bc37904e4f0..e0499674d086ad3c4baed2f3300443b55c80661b 100644 (file)
@@ -106,6 +106,12 @@ zoom_init (Display *dpy, Window window)
   st->pixspacey = get_integer_resource(st->dpy, "pixspacey", "Integer");
   if (st->pixspacey < 0)
     st->pixspacey = 0;
+
+  if (st->sizex < 50 || st->sizey < 50) {  /* tiny window */
+    st->pixwidth = 10;
+    st->pixheight = 10;
+  }
+
   st->lenses = get_boolean_resource(st->dpy, "lenses", "Boolean");
   st->lensoffsetx = get_integer_resource(st->dpy, "lensoffsetx", "Integer");
   st->lensoffsetx = MAX(0, MIN(st->pixwidth, st->lensoffsetx));
index 34cda469566be5ca2e82f7dac9452ac0f9d38f55..281c6c1a509fd58c47686a6339eaab21932ccf0e 100644 (file)
@@ -134,7 +134,6 @@ distdepend:: compile_axp.com compile_decc.com
 #
 # DO NOT DELETE: updated by make distdepend
 
-jwxyz-android.o: ../config.h
 jwxyz-common.o: ../config.h
 jwxyz-timers.o: ../config.h
 jwzgles.o: ../config.h
index 6559b69be3b66a54edc117428bfeee876d13e5b2..eb990389c7f0f6257174813ba99ea9d8c9333c84 100644 (file)
@@ -16,8 +16,6 @@
  *   - It is how the jwxyz.java class calls into C to run the hacks.
  */
 
-#include "config.h"
-
 #ifdef HAVE_ANDROID /* whole file */
 
 #include <stdarg.h>
@@ -30,6 +28,7 @@
 #include <GLES/gl.h>
 #include <jni.h>
 #include <android/log.h>
+#include <android/native_window_jni.h>
 #include <pthread.h>
 
 #include "screenhackI.h"
@@ -160,30 +159,34 @@ create_pixmap (Window win, Drawable p)
   Assert (p->frame.width, "p->frame.width");
   Assert (p->frame.height, "p->frame.height");
 
-  struct running_hack *rh = win->window.rh;
+  if (win->window.rh->jwxyz_gl_p) {
+    struct running_hack *rh = win->window.rh;
 
-  if (rh->gl_fbo_p) {
-    glGenTextures (1, &p->texture);
-    glBindTexture (GL_TEXTURE_2D, p->texture);
+    if (rh->gl_fbo_p) {
+      glGenTextures (1, &p->texture);
+      glBindTexture (GL_TEXTURE_2D, p->texture);
 
-    glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA,
-                  to_pow2(p->frame.width), to_pow2(p->frame.height),
-                  0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+      glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA,
+                    to_pow2(p->frame.width), to_pow2(p->frame.height),
+                    0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
 
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    } else {
+      EGLint attribs[5];
+      attribs[0] = EGL_WIDTH;
+      attribs[1] = p->frame.width;
+      attribs[2] = EGL_HEIGHT;
+      attribs[3] = p->frame.height;
+      attribs[4] = EGL_NONE;
+
+      p->egl_surface = eglCreatePbufferSurface(rh->egl_display, rh->egl_config,
+                                             attribs);
+      Assert (p->egl_surface != EGL_NO_SURFACE,
+              "XCreatePixmap: got EGL_NO_SURFACE");
+    }
   } else {
-    EGLint attribs[5];
-    attribs[0] = EGL_WIDTH;
-    attribs[1] = p->frame.width;
-    attribs[2] = EGL_HEIGHT;
-    attribs[3] = p->frame.height;
-    attribs[4] = EGL_NONE;
-
-    p->egl_surface = eglCreatePbufferSurface(rh->egl_display, rh->egl_config,
-                                           attribs);
-    Assert (p->egl_surface != EGL_NO_SURFACE,
-            "XCreatePixmap: got EGL_NO_SURFACE");
+    p->image_data = malloc (p->frame.width * p->frame.height * 4);
   }
 }
 
@@ -191,33 +194,34 @@ create_pixmap (Window win, Drawable p)
 static void
 free_pixmap (struct running_hack *rh, Pixmap p)
 {
-  if (rh->gl_fbo_p) {
-    glDeleteTextures (1, &p->texture);
+  if (rh->jwxyz_gl_p) {
+    if (rh->gl_fbo_p) {
+      glDeleteTextures (1, &p->texture);
+    } else {
+      eglDestroySurface(rh->egl_display, p->egl_surface);
+    }
   } else {
-    eglDestroySurface(rh->egl_display, p->egl_surface);
+    free (p->image_data);
   }
 }
 
 
 static void
-restore_surface (struct running_hack *rh)
+prepare_context (struct running_hack *rh)
 {
-  /* This is necessary because GLSurfaceView (in Java) will call
-     eglSwapBuffers under the (ordinarily reasonable) assumption that the EGL
-     surface associated with the EGL context hasn't been changed.
-   */
-  eglMakeCurrent (rh->egl_display, rh->egl_surface, rh->egl_surface,
-                  rh->egl_ctx);
-  rh->current_drawable = NULL;
-}
-
+  if (rh->jwxyz_gl_p) {
+    /* TODO: Adreno recommends against doing this every frame. */
+    Assert (eglMakeCurrent(rh->egl_display, rh->egl_surface, rh->egl_surface,
+                           rh->egl_ctx),
+            "eglMakeCurrent failed");
+
+    /* Don't set matrices here; set them when an Xlib call triggers
+       jwxyz_bind_drawable/jwxyz_set_matrices.
+     */
+    rh->current_drawable = NULL;
+  }
 
-static void
-get_egl_surface (struct running_hack *rh)
-{
-  rh->egl_surface = eglGetCurrentSurface(EGL_DRAW);
-  Assert(eglGetCurrentSurface(EGL_READ) == rh->egl_surface,
-         "doinit: EGL_READ != EGL_DRAW");
+  jwzgles_make_current (rh->gles_state);
 }
 
 
@@ -226,7 +230,7 @@ get_egl_surface (struct running_hack *rh)
 static void
 doinit (jobject jwxyz_obj, struct running_hack *rh, JNIEnv *env,
         const struct function_table_entry *chosen,
-        jobject defaults, jint w, jint h)
+        jobject defaults, jint w, jint h, jobject jni_surface)
 {
   if (setjmp (jmp_target)) goto END;  // Jump here from jwxyz_abort and return.
 
@@ -335,110 +339,169 @@ doinit (jobject jwxyz_obj, struct running_hack *rh, JNIEnv *env,
   (*env)->DeleteLocalRef (env, c);
   if ((*env)->ExceptionOccurred(env)) abort();
 
-  // GL init. Must come after resource processing.
 
-  rh->egl_ctx = eglGetCurrentContext();
-  Assert(rh->egl_ctx != EGL_NO_CONTEXT, "doinit: EGL_NO_CONTEXT");
+  /* Note: https://source.android.com/devices/graphics/arch-egl-opengl */
 
-  get_egl_surface (rh);
+  /* TODO: This is lame, use a resource. */
+  rh->jwxyz_gl_p =
+    strcmp (progname, "kumppa") &&
+    strcmp (progname, "petri") &&
+    strcmp (progname, "slip") &&
+    strcmp (progname, "testx11");
 
-  rh->egl_display = eglGetCurrentDisplay();
-  Assert(rh->egl_display != EGL_NO_DISPLAY, "doinit: EGL_NO_DISPLAY");
+  Log ("init: %s @ %dx%d: using JWXYZ_%s", progname, w, h,
+       rh->jwxyz_gl_p ? "GL" : "IMAGE");
 
-  unsigned egl_major, egl_minor;
-  if (sscanf ((const char *)eglQueryString(rh->egl_display, EGL_VERSION),
-              "%u.%u", &egl_major, &egl_minor) < 2)
-  {
-    egl_major = 1;
-    egl_minor = 0;
-  }
+  if (rh->jwxyz_gl_p) {
+  // GL init. Must come after resource processing.
 
-  EGLint config_attribs[3];
-  config_attribs[0] = EGL_CONFIG_ID;
-  eglQueryContext(rh->egl_display, rh->egl_ctx, EGL_CONFIG_ID,
-                  &config_attribs[1]);
-  config_attribs[2] = EGL_NONE;
-
-  EGLint num_config;
-  eglChooseConfig(rh->egl_display, config_attribs,
-                  &rh->egl_config, 1, &num_config);
-  Assert(num_config == 1, "no EGL config chosen");
-
-  const GLubyte *extensions = glGetString (GL_EXTENSIONS);
-  rh->gl_fbo_p = jwzgles_gluCheckExtension (
-    (const GLubyte *)"GL_OES_framebuffer_object", extensions);
-
-  if (rh->gl_fbo_p) {
-    PFNGLGENFRAMEBUFFERSOESPROC glGenFramebuffersOES =
-      (PFNGLGENFRAMEBUFFERSOESPROC)
-        eglGetProcAddress ("glGenFramebuffersOES");
-
-    rh->glBindFramebufferOES = (PFNGLBINDFRAMEBUFFEROESPROC)
-        eglGetProcAddress ("glBindFramebufferOES");
-    rh->glFramebufferTexture2DOES = (PFNGLFRAMEBUFFERTEXTURE2DOESPROC)
-      eglGetProcAddress ("glFramebufferTexture2DOES");
-
-    glGetIntegerv (GL_FRAMEBUFFER_BINDING_OES, &rh->fb_default);
-    Assert (!rh->fb_default, "default framebuffer not current framebuffer");
-    glGenFramebuffersOES (1, &rh->fb_pixmap);
-    wnd->texture = 0;
-  } else {
-    wnd->egl_surface = rh->egl_surface;
-  }
+    rh->egl_display = eglGetDisplay (EGL_DEFAULT_DISPLAY);
+    Assert (rh->egl_display != EGL_NO_DISPLAY, "init: EGL_NO_DISPLAY");
+
+    int egl_major, egl_minor;
+    Assert (eglInitialize (rh->egl_display, &egl_major, &egl_minor),
+            "eglInitialize failed");
+
+    // TODO: Skip depth and (probably) alpha for Xlib.
+    // TODO: Could ask for EGL_SWAP_BEHAVIOR_PRESERVED_BIT here...maybe?
+    // TODO: Probably should try to ask for EGL_PBUFFER_BIT.
+    // TODO: Do like visual-gl.c and work from a list of configs.
+    /* Probably don't need EGL_FRAMEBUFFER_TARGET_ANDROID here if GLSurfaceView
+       doesn't use it.
+     */
+    EGLint config_attribs[] = {
+       EGL_RED_SIZE, 8,
+       EGL_GREEN_SIZE, 8,
+       EGL_BLUE_SIZE, 8,
+       EGL_ALPHA_SIZE, 8,
+       EGL_DEPTH_SIZE, 16,
+       EGL_NONE
+    };
+
+    EGLint num_config;
+    Assert (eglChooseConfig (rh->egl_display, config_attribs,
+                             &rh->egl_config, 1, &num_config),
+            "eglChooseConfig failed");
+    Assert (num_config == 1, "no EGL config chosen");
+
+    EGLint no_attribs[] = {EGL_NONE};
+    rh->egl_ctx = eglCreateContext (rh->egl_display, rh->egl_config,
+                                    EGL_NO_CONTEXT, no_attribs);
+    Assert (rh->egl_ctx != EGL_NO_CONTEXT, "init: EGL_NO_CONTEXT");
+
+    ANativeWindow *native_window =
+      ANativeWindow_fromSurface (env, jni_surface);
+
+    rh->egl_surface = eglCreateWindowSurface (rh->egl_display, rh->egl_config,
+                                              native_window, no_attribs);
+    Assert (rh->egl_surface != EGL_NO_SURFACE, "init: EGL_NO_SURFACE");
+
+    ANativeWindow_release (native_window);
+
+    prepare_context (rh);
+
+    Log ("init %s / %s / %s",
+         glGetString (GL_VENDOR),
+         glGetString (GL_RENDERER),
+         glGetString (GL_VERSION));
+
+    const GLubyte *extensions = glGetString (GL_EXTENSIONS);
+    rh->gl_fbo_p = jwzgles_gluCheckExtension (
+      (const GLubyte *)"GL_OES_framebuffer_object", extensions);
+
+    if (rh->gl_fbo_p) {
+      PFNGLGENFRAMEBUFFERSOESPROC glGenFramebuffersOES =
+        (PFNGLGENFRAMEBUFFERSOESPROC)
+          eglGetProcAddress ("glGenFramebuffersOES");
+
+      rh->glBindFramebufferOES = (PFNGLBINDFRAMEBUFFEROESPROC)
+          eglGetProcAddress ("glBindFramebufferOES");
+      rh->glFramebufferTexture2DOES = (PFNGLFRAMEBUFFERTEXTURE2DOESPROC)
+        eglGetProcAddress ("glFramebufferTexture2DOES");
+
+      glGetIntegerv (GL_FRAMEBUFFER_BINDING_OES, &rh->fb_default);
+      Assert (!rh->fb_default, "default framebuffer not current framebuffer");
+      glGenFramebuffersOES (1, &rh->fb_pixmap);
+      wnd->texture = 0;
+    } else {
+      wnd->egl_surface = rh->egl_surface;
+    }
 
-  /* TODO: Maybe ask for EGL_SWAP_BEHAVIOR_PRESERVED_BIT on the Java side of
-           things via EGLConfigChooser. I (Dave) seem to automatically get
-           this (n = 1), but maybe other devices won't.
-   */
-  rh->frontbuffer_p = False;
+    rh->frontbuffer_p = False;
 
-  if (rh->api == API_XLIB ||
-      (rh->api == API_GL &&
-       strcmp("True", get_string_resource_window(wnd, "doubleBuffer")))) {
+    if (rh->api == API_XLIB ||
+        (rh->api == API_GL &&
+         strcmp("True", get_string_resource_window(wnd, "doubleBuffer")))) {
 
-    rh->frontbuffer_p = True;
+      rh->frontbuffer_p = True;
 
 # if 0 /* Might need to be 0 for Adreno...? */
-    if (egl_major > 1 || (egl_major == 1 && egl_minor >= 2)) {
-      EGLint surface_type;
-      eglGetConfigAttrib(rh->egl_display, rh->egl_config, EGL_SURFACE_TYPE,
-                         &surface_type);
-      if(surface_type & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) {
-        eglSurfaceAttrib(rh->egl_display, rh->egl_surface, EGL_SWAP_BEHAVIOR,
-                         EGL_BUFFER_PRESERVED);
-        rh->frontbuffer_p = False;
+      if (egl_major > 1 || (egl_major == 1 && egl_minor >= 2)) {
+        EGLint surface_type;
+        eglGetConfigAttrib(rh->egl_display, rh->egl_config, EGL_SURFACE_TYPE,
+                           &surface_type);
+        if(surface_type & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) {
+          eglSurfaceAttrib(rh->egl_display, rh->egl_surface, EGL_SWAP_BEHAVIOR,
+                           EGL_BUFFER_PRESERVED);
+          rh->frontbuffer_p = False;
+        }
       }
-    }
 # endif
 
-    if (rh->frontbuffer_p) {
-      /* create_pixmap needs rh->gl_fbo_p and wnd->frame. */
-      create_pixmap (wnd, wnd);
+      if (rh->frontbuffer_p) {
+        /* create_pixmap needs rh->gl_fbo_p and wnd->frame. */
+        create_pixmap (wnd, wnd);
+
+        /* No preserving backbuffers, so manual blit from back to "front". */
+        rh->frontbuffer.type = PIXMAP;
+        rh->frontbuffer.frame = wnd->frame;
+        rh->frontbuffer.pixmap.depth = visual_depth (NULL, NULL);
+
+        if(rh->gl_fbo_p) {
+          rh->frontbuffer.texture = 0;
+        } else {
+          Assert (wnd->egl_surface != rh->egl_surface,
+                  "oops: wnd->egl_surface == rh->egl_surface");
+          rh->frontbuffer.egl_surface = rh->egl_surface;
+        }
+      }
+    }
 
-      /* No preserving backbuffers, so manual blit from back to "front". */
-      rh->frontbuffer.type = PIXMAP;
-      rh->frontbuffer.frame = wnd->frame;
-      rh->frontbuffer.pixmap.depth = visual_depth (NULL, NULL);
+    rh->dpy = jwxyz_gl_make_display(wnd);
 
-      if(rh->gl_fbo_p) {
-        rh->frontbuffer.texture = 0;
-      } else {
-        Assert (wnd->egl_surface != rh->egl_surface,
-                "oops: wnd->egl_surface == rh->egl_surface");
-        rh->frontbuffer.egl_surface = rh->egl_surface;
-      }
+  } else {
+
+    rh->native_window = ANativeWindow_fromSurface (env, jni_surface);
+
+    int result = ANativeWindow_setBuffersGeometry (rh->native_window, w, h,
+                                                   WINDOW_FORMAT_RGBX_8888);
+    if (result < 0) {
+      // Maybe check this earlier?
+      Log ("can't set format (%d), surface may be invalid.", result);
+      (*env)->ThrowNew (env,
+        (*env)->FindClass(env, "org/jwz/xscreensaver/jwxyz$SurfaceLost"),
+        "Surface lost");
+
+      ANativeWindow_release (rh->native_window);
+      rh->native_window = NULL;
+      return;
     }
+
+    create_pixmap (wnd, wnd);
+
+    static const unsigned char rgba_bytes[] = {0, 1, 2, 3};
+    rh->dpy = jwxyz_image_make_display(wnd, rgba_bytes);
+
   }
 
-  rh->dpy = jwxyz_make_display(wnd);
   Assert(wnd == XRootWindow(rh->dpy, 0), "Wrong root window.");
   // TODO: Zero looks right, but double-check that is the right number
 
   /* Requires valid rh->dpy. */
-  rh->copy_gc = XCreateGC (rh->dpy, &rh->frontbuffer, 0, NULL);
+  if (rh->jwxyz_gl_p)
+    rh->copy_gc = XCreateGC (rh->dpy, &rh->frontbuffer, 0, NULL);
+
   rh->gles_state = jwzgles_make_state();
-  restore_surface(rh);
  END: ;
 }
 
@@ -477,18 +540,24 @@ drawXScreenSaver (JNIEnv *env, struct running_hack *rh)
 
   if (setjmp (jmp_target)) goto END;  // Jump here from jwxyz_abort and return.
 
-  /* There is some kind of weird redisplay race condition between Settings
-     and the launching hack: e.g., Abstractile does XClearWindow at init,
-     but the screen is getting filled with random bits.  So let's wait a
-     few frames before really starting up.
-   */
-  if (++rh->frame_count < 8) {
-    /* glClearColor (1.0, 0.0, 1.0, 0.0); */
-    glClear (GL_COLOR_BUFFER_BIT); /* We always need to draw *something*. */
-    goto END;
-  }
+  Window wnd = rh->window;
+
+  if (rh->jwxyz_gl_p) {
+    prepare_context (rh);
 
-  prepare_context(rh);
+    /* There is some kind of weird redisplay race condition between Settings
+       and the launching hack: e.g., Abstractile does XClearWindow at init,
+       but the screen is getting filled with random bits.  So let's wait a
+       few frames before really starting up.
+
+       TODO: Is this still true?
+     */
+    if (++rh->frame_count < 8) {
+      /* glClearColor (1.0, 0.0, 1.0, 0.0); */
+      glClear (GL_COLOR_BUFFER_BIT); /* We always need to draw *something*. */
+      goto END;
+    }
+  }
 
 # ifdef DEBUG_FPS
   fps1 = double_time();
@@ -504,10 +573,10 @@ drawXScreenSaver (JNIEnv *env, struct running_hack *rh)
 
     unsigned int bg =
       get_pixel_resource (rh->dpy, 0, "background", "Background");
-    XSetWindowBackground (rh->dpy, rh->window, bg);
-    XClearWindow (rh->dpy, rh->window);
+    XSetWindowBackground (rh->dpy, wnd, bg);
+    XClearWindow (rh->dpy, wnd);
 
-    rh->closure = init_cb (rh->dpy, rh->window, rh->xsft->setup_arg);
+    rh->closure = init_cb (rh->dpy, wnd, rh->xsft->setup_arg);
     rh->initted_p = True;
 
     /* ignore_rotation_p doesn't quite work at the moment. */
@@ -518,7 +587,7 @@ drawXScreenSaver (JNIEnv *env, struct running_hack *rh)
 */
 
     if (get_boolean_resource (rh->dpy, "doFPS", "DoFPS")) {
-      rh->fpst = fps_init (rh->dpy, rh->window);
+      rh->fpst = fps_init (rh->dpy, wnd);
       if (! rh->xsft->fps_cb) rh->xsft->fps_cb = screenhack_do_fps;
     } else {
       rh->fpst = NULL;
@@ -534,27 +603,63 @@ drawXScreenSaver (JNIEnv *env, struct running_hack *rh)
 
   // Apparently events don't come in on the drawing thread, and JNI flips
   // out.  So we queue them there and run them here.
+  // TODO: Events should be coming in on the drawing thread now, so dump this.
   send_queued_events (rh);
 
 # ifdef DEBUG_FPS
   fps3 = double_time();
 # endif
 
-  delay = rh->xsft->draw_cb(rh->dpy, rh->window, rh->closure);
+  delay = rh->xsft->draw_cb(rh->dpy, wnd, rh->closure);
+
+  if (rh->jwxyz_gl_p)
+    jwxyz_gl_flush (rh->dpy);
 
 # ifdef DEBUG_FPS
   fps4 = double_time();
 # endif
   if (rh->fpst && rh->xsft->fps_cb)
-    rh->xsft->fps_cb (rh->dpy, rh->window, rh->fpst, rh->closure);
+    rh->xsft->fps_cb (rh->dpy, wnd, rh->fpst, rh->closure);
 
-  if (rh->frontbuffer_p) {
-    jwxyz_copy_area (rh->dpy, rh->window, &rh->frontbuffer, rh->copy_gc,
-                     0, 0, rh->window->frame.width, rh->window->frame.height,
-                     0, 0);
-  }
+  if (rh->jwxyz_gl_p) {
+    if (rh->frontbuffer_p) {
+      jwxyz_gl_copy_area (rh->dpy, wnd, &rh->frontbuffer, rh->copy_gc,
+                          0, 0, wnd->frame.width, wnd->frame.height,
+                          0, 0);
+    }
+
+    // TODO: Getting crashes here after resize, sometimes. Log sez:
+    // W/Adreno-EGLSUB(18428): <DequeueBuffer:607>: dequeue native buffer fail: No such device, buffer=0x5f93bf5c, handle=0x0
+    Assert (eglSwapBuffers(rh->egl_display, rh->egl_surface),
+            "eglSwapBuffers failed");
+  } else {
+    ANativeWindow_Buffer buffer;
+    ARect rect = {0, 0, wnd->frame.width, wnd->frame.height};
+    int32_t result = ANativeWindow_lock(rh->native_window, &buffer, &rect);
+    if (result) {
+      Log ("ANativeWindow_lock failed (result = %d), frame dropped", result);
+    } else {
+      /* Android can resize surfaces asynchronously. */
+      if (wnd->frame.width != buffer.width ||
+          wnd->frame.height != buffer.height) {
+        Log ("buffer/window size mismatch: %dx%d (format = %d), wnd: %dx%d",
+             buffer.width, buffer.height, buffer.format,
+             wnd->frame.width, wnd->frame.height);
+      }
+
+      Assert (buffer.format == WINDOW_FORMAT_RGBA_8888 ||
+              buffer.format == WINDOW_FORMAT_RGBX_8888,
+              "bad buffer format");
 
-  restore_surface (rh);
+      jwxyz_blit (wnd->image_data, jwxyz_image_pitch (wnd), 0, 0,
+                  buffer.bits, buffer.stride * 4, 0, 0,
+                  MIN(wnd->frame.width, buffer.width),
+                  MIN(wnd->frame.height, buffer.height));
+      // TODO: Clear any area to sides and bottom.
+
+      ANativeWindow_unlockAndPost (rh->native_window);
+    }
+  }
 
  END: ;
 
@@ -603,7 +708,8 @@ acquireClass (JNIEnv *env, const char *className, jobject *globalRef)
 JNIEXPORT void JNICALL
 Java_org_jwz_xscreensaver_jwxyz_nativeInit (JNIEnv *env, jobject thiz,
                                             jstring jhack, jobject defaults,
-                                            jint w, jint h)
+                                            jint w, jint h,
+                                            jobject jni_surface)
 {
   pthread_mutex_lock(&mutg);
 
@@ -663,7 +769,8 @@ Java_org_jwz_xscreensaver_jwxyz_nativeInit (JNIEnv *env, jobject thiz,
 
   (*env)->ReleaseStringUTFChars(env, jhack, hack);
 
-  doinit (thiz, rh, env, &function_table[chosen], defaults, w, h);
+  doinit (thiz, rh, env, &function_table[chosen], defaults, w, h,
+          jni_surface);
 
   pthread_mutex_unlock(&mutg);
 }
@@ -682,14 +789,22 @@ Java_org_jwz_xscreensaver_jwxyz_nativeResize (JNIEnv *env, jobject thiz,
 
   struct running_hack *rh = getRunningHack(env, thiz);
 
+  if (rh->jwxyz_gl_p) {
+    prepare_context (rh);
+    glViewport (0, 0, w, h);
+  } else {
+    int result = ANativeWindow_setBuffersGeometry (rh->native_window, w, h,
+                                                   WINDOW_FORMAT_RGBX_8888);
+    if (result < 0)
+      Log ("failed to resize surface (%d)", result);
+  }
+
   Window wnd = rh->window;
   wnd->frame.x = 0;
   wnd->frame.y = 0;
   wnd->frame.width  = w;
   wnd->frame.height = h;
 
-  glViewport (0, 0, w, h);
-
   if (ignore_rotation_p(rh->dpy) &&
       rot != 0 && rot != 180 && rot != -180) {
     int swap = w;
@@ -699,29 +814,34 @@ Java_org_jwz_xscreensaver_jwxyz_nativeResize (JNIEnv *env, jobject thiz,
     wnd->frame.height = h;
   }
 
-  get_egl_surface (rh);
-  if (rh->frontbuffer_p) {
+  if (rh->jwxyz_gl_p) {
+    if (rh->frontbuffer_p) {
+      free_pixmap (rh, wnd);
+      create_pixmap (wnd, wnd);
+
+      rh->frontbuffer.frame = wnd->frame;
+      if (!rh->gl_fbo_p)
+        rh->frontbuffer.egl_surface = rh->egl_surface;
+    }
+
+    jwxyz_window_resized (rh->dpy);
+  } else {
     free_pixmap (rh, wnd);
     create_pixmap (wnd, wnd);
-
-    rh->frontbuffer.frame = wnd->frame;
-    if (!rh->gl_fbo_p)
-      rh->frontbuffer.egl_surface = rh->egl_surface;
   }
 
-  jwxyz_window_resized (rh->dpy);
+  XClearWindow (rh->dpy, wnd); // TODO: This is lame.
+
   if (rh->initted_p)
     rh->xsft->reshape_cb (rh->dpy, rh->window, rh->closure,
                           wnd->frame.width, wnd->frame.height);
 
-  if (rh->api == API_GL) {
+  if (rh->jwxyz_gl_p && rh->api == API_GL) {
     glMatrixMode (GL_PROJECTION);
     glRotatef (-rot, 0, 0, 1);
     glMatrixMode (GL_MODELVIEW);
   }
 
-  restore_surface (rh);
-
  END:
   pthread_mutex_unlock(&mutg);
 }
@@ -751,9 +871,23 @@ Java_org_jwz_xscreensaver_jwxyz_nativeDone (JNIEnv *env, jobject thiz)
 
   if (rh->initted_p)
     rh->xsft->free_cb (rh->dpy, rh->window, rh->closure);
-  XFreeGC (rh->dpy, rh->copy_gc);
+  if (rh->jwxyz_gl_p)
+    XFreeGC (rh->dpy, rh->copy_gc);
   jwzgles_free_state ();
-  jwxyz_free_display(rh->dpy);
+
+  if (rh->jwxyz_gl_p) {
+    jwxyz_gl_free_display(rh->dpy);
+    // eglDestroy* probably isn't necessary here.
+    eglMakeCurrent (rh->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
+                    EGL_NO_CONTEXT);
+    eglDestroySurface (rh->egl_display, rh->egl_surface);
+    eglDestroyContext (rh->egl_display, rh->egl_ctx);
+    eglTerminate (rh->egl_display);
+  } else {
+    jwxyz_image_free_display(rh->dpy);
+    if (rh->native_window)
+      ANativeWindow_release (rh->native_window);
+  }
 
   free(rh);
   (*env)->SetLongField(env, thiz, runningHackField, 0);
@@ -901,21 +1035,10 @@ Java_org_jwz_xscreensaver_jwxyz_sendKeyEvent (JNIEnv *env, jobject thiz,
 }
 
 
-
 /***************************************************************************
   Backend functions for jwxyz-gl.c
  */
 
-void
-prepare_context (struct running_hack *rh)
-{
-  /* Don't set matrices here; set them when an Xlib call triggers
-     jwxyz_bind_drawable/jwxyz_set_matrices.
-   */
-  rh->current_drawable = NULL;
-  jwzgles_make_current (rh->gles_state);
-}
-
 static void
 finish_bind_drawable (Display *dpy, Drawable dst)
 {
@@ -955,57 +1078,24 @@ jwxyz_bind_drawable (Display *dpy, Window w, Drawable d)
   }
 }
 
-
-const XRectangle *
-jwxyz_frame (Drawable d)
-{
-  return &d->frame;
-}
-
-
-unsigned int
-jwxyz_drawable_depth (Drawable d)
-{
-  return (d->type == WINDOW
-          ? visual_depth (NULL, NULL)
-          : d->pixmap.depth);
-}
-
-
 void
-jwxyz_get_pos (Window w, XPoint *xvpos, XPoint *xp)
-{
-  xvpos->x = 0;
-  xvpos->y = 0;
-
-  if (xp) {
-    xp->x = w->window.last_mouse_x;
-    xp->y = w->window.last_mouse_y;
-  }
-}
-
-
-static void
-screenhack_do_fps (Display *dpy, Window w, fps_state *fpst, void *closure)
-{
-  fps_compute (fpst, 0, -1);
-  fps_draw (fpst);
-}
-
-
-void
-jwxyz_copy_area (Display *dpy, Drawable src, Drawable dst, GC gc,
-                 int src_x, int src_y, unsigned int width, unsigned int height,
-                 int dst_x, int dst_y)
+jwxyz_gl_copy_area (Display *dpy, Drawable src, Drawable dst, GC gc,
+                    int src_x, int src_y,
+                    unsigned int width, unsigned int height,
+                    int dst_x, int dst_y)
 {
   Window w = XRootWindow (dpy, 0);
   struct running_hack *rh = w->window.rh;
 
+  jwxyz_gl_flush (dpy);
+
   if (rh->gl_fbo_p && src->texture && src != dst) {
     bind_drawable_fbo (rh, dst);
     finish_bind_drawable (dpy, dst);
     rh->current_drawable = NULL;
 
+    jwxyz_gl_set_gc (dpy, gc);
+
     glBindTexture (GL_TEXTURE_2D, src->texture);
 
     jwxyz_gl_draw_image (GL_TEXTURE_2D, to_pow2(src->frame.width),
@@ -1059,6 +1149,60 @@ jwxyz_assert_gl (void)
 }
 
 
+/***************************************************************************
+  Backend functions for jwxyz-image.c
+ */
+
+ptrdiff_t
+jwxyz_image_pitch (Drawable d)
+{
+  return d->frame.width * 4;
+}
+
+void *
+jwxyz_image_data (Drawable d)
+{
+  return d->image_data;
+}
+
+
+const XRectangle *
+jwxyz_frame (Drawable d)
+{
+  return &d->frame;
+}
+
+
+unsigned int
+jwxyz_drawable_depth (Drawable d)
+{
+  return (d->type == WINDOW
+          ? visual_depth (NULL, NULL)
+          : d->pixmap.depth);
+}
+
+
+void
+jwxyz_get_pos (Window w, XPoint *xvpos, XPoint *xp)
+{
+  xvpos->x = 0;
+  xvpos->y = 0;
+
+  if (xp) {
+    xp->x = w->window.last_mouse_x;
+    xp->y = w->window.last_mouse_y;
+  }
+}
+
+
+static void
+screenhack_do_fps (Display *dpy, Window w, fps_state *fpst, void *closure)
+{
+  fps_compute (fpst, 0, -1);
+  fps_draw (fpst);
+}
+
+
 Pixmap
 XCreatePixmap (Display *dpy, Drawable d,
                unsigned int width, unsigned int height, unsigned int depth)
@@ -1079,9 +1223,11 @@ XCreatePixmap (Display *dpy, Drawable d,
   create_pixmap (win, p);
 
   /* For debugging. */
+# if 0
   jwxyz_bind_drawable (dpy, win, p);
   glClearColor (frand(1), frand(1), frand(1), 0);
   glClear (GL_COLOR_BUFFER_BIT);
+# endif
 
   return p;
 }
@@ -1091,8 +1237,13 @@ int
 XFreePixmap (Display *d, Pixmap p)
 {
   struct running_hack *rh = XRootWindow(d, 0)->window.rh;
-  if (rh->current_drawable == p)
-    rh->current_drawable = NULL;
+
+  if (rh->jwxyz_gl_p) {
+    jwxyz_gl_flush (d);
+
+    if (rh->current_drawable == p)
+      rh->current_drawable = NULL;
+  }
 
   free_pixmap (rh, p);
   free (p);
@@ -1203,6 +1354,7 @@ textclient_mobile_url_string (Display *dpy, const char *url)
 float
 jwxyz_scale (Window main_window)
 {
+  // TODO: Use the actual device resolution.
   return 2;
 }
 
@@ -1306,7 +1458,7 @@ static void dump_reference_tables(JNIEnv *env)
 //
 void
 jwxyz_render_text (Display *dpy, void *native_font,
-                   const char *str, size_t len, int utf8,
+                   const char *str, size_t len, Bool utf8, Bool antialias_p,
                    XCharStruct *cs, char **pixmap_ret)
 {
   Window window = RootWindow (dpy, 0);
@@ -1338,14 +1490,15 @@ jwxyz_render_text (Display *dpy, void *native_font,
   jstring jstr  = (*env)->NewStringUTF (env, s2);
   jclass      c = (*env)->GetObjectClass (env, obj);
   jmethodID   m = (*env)->GetMethodID (env, c, "renderText",
-    "(Landroid/graphics/Paint;Ljava/lang/String;Z)Ljava/nio/ByteBuffer;");
+    "(Landroid/graphics/Paint;Ljava/lang/String;ZZ)Ljava/nio/ByteBuffer;");
   if ((*env)->ExceptionOccurred(env)) abort();
   jobject buf =
     (m
      ? (*env)->CallObjectMethod (env, obj, m,
                                  (jobject) native_font,
                                  jstr,
-                                 (pixmap_ret ? JNI_TRUE : JNI_FALSE))
+                                 (pixmap_ret ? JNI_TRUE : JNI_FALSE),
+                                 antialias_p)
      : NULL);
   (*env)->DeleteLocalRef (env, c);
   (*env)->DeleteLocalRef (env, jstr);
@@ -1426,7 +1579,7 @@ jwxyz_load_random_image (Display *dpy,
                          char **name_ret)
 {
 
-  /* This function needs to be implemented for Android */
+  /* TODO: This function needs to be implemented for Android */
   return 0;
 
   Window window = RootWindow (dpy, 0);
index 14bfc7feaf29fe7970ded19cff60f9931c0c61d0..49586d009e8a0181d672b495fed0877575d303be 100644 (file)
@@ -29,8 +29,12 @@ struct jwxyz_Drawable {
   enum { WINDOW, PIXMAP } type;
   XRectangle frame;
   union {
+    /* JWXYZ_GL */
     EGLSurface egl_surface;
     GLuint texture; /* If this is 0, it's the default framebuffer. */
+
+    /* JWXYZ_IMAGE */
+    void *image_data;
   };
   union {
     struct {
@@ -53,7 +57,9 @@ struct running_hack {
   JNIEnv *jni_env;
   jobject jobject;
 
-  /* These are set up in Java by the GLSurfaceView. */
+  Bool jwxyz_gl_p;
+
+  /* JWXYZ_GL */
   EGLContext egl_ctx;
   EGLSurface egl_surface;
   EGLDisplay egl_display;
@@ -70,6 +76,10 @@ struct running_hack {
   GLuint fb_pixmap;
 
   Drawable current_drawable;
+
+  /* JWXYZ_IMAGE */
+  ANativeWindow *native_window;
+
   Bool ignore_rotation_p;
 
   jwzgles_state *gles_state;
@@ -80,16 +90,14 @@ struct running_hack {
 };
 
 
-extern void prepare_context (struct running_hack *rh);
-
-
 // Methods of the Java class org.jwz.jwxyz that are implemented in C.
 
 JNIEXPORT void JNICALL
 Java_org_jwz_xscreensaver_jwxyz_nativeInit (JNIEnv *, jobject thiz,
                                             jstring jhack,
                                             jobject defaults,
-                                            jint w, jint h);
+                                            jint w, jint h,
+                                            jobject jni_surface);
 
 JNIEXPORT void JNICALL
 Java_org_jwz_xscreensaver_jwxyz_nativeResize (JNIEnv *, jobject thiz,
@@ -101,19 +109,6 @@ Java_org_jwz_xscreensaver_jwxyz_nativeRender (JNIEnv *, jobject thiz);
 JNIEXPORT void JNICALL
 Java_org_jwz_xscreensaver_jwxyz_nativeDone (JNIEnv *, jobject thiz);
 
-JNIEXPORT void JNICALL
-Java_org_jwz_xscreensaver_jwxyz_allnativeSettings (JNIEnv *, jobject thiz,
-                                                   jstring jhack,
-                                                   jstring hackPref,
-                                                   jint draw, jstring key);
-
-JNIEXPORT jboolean JNICALL
-Java_org_jwz_xscreensaver_jwxyz_ignoreRotation (JNIEnv *, jobject thiz);
-
-JNIEXPORT jboolean JNICALL
-Java_org_jwz_xscreensaver_jwxyz_suppressRotationAnimation (JNIEnv *,
-                                                           jobject thiz);
-
 JNIEXPORT void JNICALL
 Java_org_jwz_xscreensaver_jwxyz_sendButtonEvent (JNIEnv *, jobject thiz,
                                                  int x, int y, jboolean down);
index 4585e6584ce231202379e5ef32a529bf0ea6d9f9..079c4ff22a8a82181eb5d049dd58b94f6404720c 100644 (file)
@@ -41,6 +41,8 @@
 #import <CoreText/CTLine.h>
 #import <CoreText/CTRun.h>
 
+#define VTBL JWXYZ_VTBL(dpy)
+
 /* OS X/iOS-specific JWXYZ implementation. */
 
 void
@@ -109,7 +111,13 @@ jwxyz_scale (Window main_window)
   scale = main_window->window.view.hackedContentScaleFactor;
   if (scale < 1) // iPad Pro magnifies the backbuffer by 3x, which makes text
     scale = 1;   // excessively blurry in BSOD.
-# endif
+
+# else  // !USE_IPHONE
+
+  /* Desktop retina displays also need fonts doubled. */
+  scale = main_window->window.view.hackedContentScaleFactor;
+
+# endif // !USE_IPHONE
 
   return scale;
 }
@@ -528,7 +536,7 @@ nsstring_from(const char *str, size_t len, int utf8_p)
 
 void
 jwxyz_render_text (Display *dpy, void *native_font,
-                   const char *str, size_t len, int utf8_p,
+                   const char *str, size_t len, Bool utf8_p, Bool antialias_p,
                    XCharStruct *cs_ret, char **pixmap_ret)
 {
   utf8_metrics (dpy, (NSFont *)native_font, nsstring_from (str, len, utf8_p),
@@ -679,19 +687,19 @@ create_framebuffer (GLuint *gl_framebuffer, GLuint *gl_renderbuffer)
 static void
 push_bg_gc (Display *dpy, Drawable d, GC gc, Bool fill_p)
 {
-  XGCValues *gcv = jwxyz_gc_gcv (gc);
+  XGCValues *gcv = VTBL->gc_gcv (gc);
   push_color_gc (dpy, d, gc, gcv->background, gcv->antialias_p, fill_p);
 }
 
 
 void
-jwxyz_copy_area (Display *dpy, Drawable src, Drawable dst, GC gc,
-                 int src_x, int src_y,
-                 unsigned int width, unsigned int height,
-                 int dst_x, int dst_y)
+jwxyz_quartz_copy_area (Display *dpy, Drawable src, Drawable dst, GC gc,
+                        int src_x, int src_y,
+                        unsigned int width, unsigned int height,
+                        int dst_x, int dst_y)
 {
   XRectangle src_frame = src->frame, dst_frame = dst->frame;
-  XGCValues *gcv = jwxyz_gc_gcv (gc);
+  XGCValues *gcv = VTBL->gc_gcv (gc);
 
   BOOL mask_p = src->type == PIXMAP && src->pixmap.depth == 1;
 
@@ -710,30 +718,12 @@ jwxyz_copy_area (Display *dpy, Drawable src, Drawable dst, GC gc,
            !dst_frame.y,
            "unexpected non-zero origin");
 
-    ptrdiff_t src_pitch = CGBitmapContextGetBytesPerRow(src->cgc);
-    ptrdiff_t dst_pitch = CGBitmapContextGetBytesPerRow(dst->cgc);
-    char *src_data = seek_xy (CGBitmapContextGetData (src->cgc), src_pitch,
-                              src_x, src_y);
-    char *dst_data = seek_xy (CGBitmapContextGetData (dst->cgc), dst_pitch,
-                              dst_x, dst_y);
-
-    size_t bytes = width * 4;
-
-    if (src == dst && dst_y > src_y) {
-      // Copy upwards if the areas might overlap.
-      src_data += src_pitch * (height - 1);
-      dst_data += dst_pitch * (height - 1);
-      src_pitch = -src_pitch;
-      dst_pitch = -dst_pitch;
-    }
+    jwxyz_blit (CGBitmapContextGetData (src->cgc),
+                CGBitmapContextGetBytesPerRow (src->cgc), src_x, src_y,
+                CGBitmapContextGetData (dst->cgc),
+                CGBitmapContextGetBytesPerRow (dst->cgc), dst_x, dst_y,
+                width, height);
 
-    while (height) {
-      // memcpy is an alias for memmove on OS X.
-      memmove(dst_data, src_data, bytes);
-      src_data += src_pitch;
-      dst_data += dst_pitch;
-      --height;
-    }
   } else {
     CGRect
     src_rect = CGRectMake(src_x, src_y, width, height),
@@ -787,7 +777,7 @@ jwxyz_copy_area (Display *dpy, Drawable src, Drawable dst, GC gc,
 
       // then fill in a solid rectangle of the fg color, using the image as an
       // alpha mask.  (the image has only values of BlackPixel or WhitePixel.)
-      set_color (dpy, cgc, gcv->foreground, jwxyz_gc_depth (gc),
+      set_color (dpy, cgc, gcv->foreground, VTBL->gc_depth (gc),
                  gcv->alpha_allowed_p, YES);
       CGContextClipToMask (cgc, dst_rect, cgi);
       CGContextFillRect (cgc, dst_rect);
index 20deb4400c37ef0675149e372be10b5291417890..849c4567881677114550b36b9cb619c8ee5482ce 100644 (file)
@@ -29,6 +29,7 @@
 #include <stdio.h>
 
 #include "jwxyzI.h"
+#include "pow2.h"
 #include "utf8wc.h"
 #include "xft.h"
 
@@ -36,6 +37,7 @@
 #define assert_window(dpy, w) \
   Assert (w == RootWindow (dpy, 0), "not a window")
 
+#define VTBL JWXYZ_VTBL(dpy)
 
 struct jwxyz_Font {
   Display *dpy;
@@ -97,6 +99,25 @@ XDisplayHeightMM (Display *dpy, int screen)
   return size_mm (dpy, XDisplayHeight (dpy, screen));
 }
 
+unsigned long
+XBlackPixelOfScreen(Screen *screen)
+{
+  return DefaultVisualOfScreen (screen)->rgba_masks[3];
+}
+
+unsigned long
+XWhitePixelOfScreen(Screen *screen)
+{
+  const unsigned long *masks = DefaultVisualOfScreen (screen)->rgba_masks;
+  return masks[0] | masks[1] | masks[2] | masks[3];
+}
+
+unsigned long
+XCellsOfScreen(Screen *screen)
+{
+  const unsigned long *masks = DefaultVisualOfScreen (screen)->rgba_masks;
+  return masks[0] | masks[1] | masks[2];
+}
 
 void
 jwxyz_validate_pixel (Display *dpy, unsigned long pixel, unsigned int depth,
@@ -127,12 +148,12 @@ Bool
 jwxyz_dumb_drawing_mode(Display *dpy, Drawable d, GC gc,
                         int x, int y, unsigned width, unsigned height)
 {
-  XGCValues *gcv = jwxyz_gc_gcv (gc);
+  XGCValues *gcv = VTBL->gc_gcv (gc);
 
   if (gcv->function == GXset || gcv->function == GXclear) {
     // "set" and "clear" are dumb drawing modes that ignore the source
     // bits and just draw solid rectangles.
-    unsigned depth = jwxyz_gc_depth (gc);
+    unsigned depth = VTBL->gc_depth (gc);
     jwxyz_fill_rect (dpy, d, 0, x, y, width, height,
                      (gcv->function == GXset
                       ? (depth == 1 ? 1 : WhitePixel(dpy,0))
@@ -226,7 +247,7 @@ XCopyArea (Display *dpy, Drawable src, Drawable dst, GC gc,
     width0  = 0;
     height0 = 0;
   } else {
-    jwxyz_copy_area (dpy, src, dst, gc,
+    VTBL->copy_area (dpy, src, dst, gc,
                      src_x, src_y, width0, height0, dst_x, dst_y);
   }
 
@@ -283,11 +304,11 @@ XCopyArea (Display *dpy, Drawable src, Drawable dst, GC gc,
       ++rects_end;
     }
 
-    XGCValues *gcv = jwxyz_gc_gcv (gc);
+    XGCValues *gcv = VTBL->gc_gcv (gc);
     int old_function = gcv->function;
     gcv->function = GXcopy;
-    jwxyz_fill_rects (dpy, dst, gc, rects, rects_end - rects,
-                      jwxyz_window_background (dpy));
+    VTBL->fill_rects (dpy, dst, gc, rects, rects_end - rects,
+                      *VTBL->window_background (dpy));
     gcv->function = old_function;
   }
 
@@ -295,13 +316,44 @@ XCopyArea (Display *dpy, Drawable src, Drawable dst, GC gc,
 }
 
 
+void
+jwxyz_blit (const void *src_data, ptrdiff_t src_pitch,
+            unsigned src_x, unsigned src_y,
+            void *dst_data, ptrdiff_t dst_pitch,
+            unsigned dst_x, unsigned dst_y,
+            unsigned width, unsigned height)
+{
+  Bool same = src_data == dst_data;
+  src_data = SEEK_XY (src_data, src_pitch, src_x, src_y);
+  dst_data = SEEK_XY (dst_data, dst_pitch, dst_x, dst_y);
+
+  size_t bytes = width * 4;
+
+  if (same && dst_y > src_y) {
+    // Copy upwards if the areas might overlap.
+    src_data += src_pitch * (height - 1);
+    dst_data += dst_pitch * (height - 1);
+    src_pitch = -src_pitch;
+    dst_pitch = -dst_pitch;
+  }
+
+  while (height) {
+    // memcpy is an alias for memmove on macOS.
+    memmove (dst_data, src_data, bytes);
+    src_data += src_pitch;
+    dst_data += dst_pitch;
+    --height;
+  }
+}
+
+
 int
 XCopyPlane (Display *dpy, Drawable src, Drawable dest, GC gc,
             int src_x, int src_y,
             unsigned width, int height,
             int dest_x, int dest_y, unsigned long plane)
 {
-  Assert ((jwxyz_gc_depth (gc) == 1 || plane == 1), "hairy plane mask!");
+  Assert ((VTBL->gc_depth (gc) == 1 || plane == 1), "hairy plane mask!");
   
   // This isn't right: XCopyPlane() is supposed to map 1/0 to fg/bg,
   // not to white/black.
@@ -310,13 +362,35 @@ XCopyPlane (Display *dpy, Drawable src, Drawable dest, GC gc,
 }
 
 
+int
+XDrawLine (Display *dpy, Drawable d, GC gc, int x1, int y1, int x2, int y2)
+{
+  XSegment segment;
+  segment.x1 = x1;
+  segment.y1 = y1;
+  segment.x2 = x2;
+  segment.y2 = y2;
+  XDrawSegments (dpy, d, gc, &segment, 1);
+  return 0;
+}
+
+
+int
+XSetWindowBackground (Display *dpy, Window w, unsigned long pixel)
+{
+  Assert (w == XRootWindow (dpy,0), "not a window");
+  jwxyz_validate_pixel (dpy, pixel, visual_depth (NULL, NULL), False);
+  *VTBL->window_background (dpy) = pixel;
+  return 0;
+}
+
 void
 jwxyz_fill_rect (Display *dpy, Drawable d, GC gc,
                  int x, int y, unsigned int width, unsigned int height,
                  unsigned long pixel)
 {
   XRectangle r = {x, y, width, height};
-  jwxyz_fill_rects (dpy, d, gc, &r, 1, pixel);
+  VTBL->fill_rects (dpy, d, gc, &r, 1, pixel);
 }
 
 int
@@ -324,7 +398,7 @@ XFillRectangle (Display *dpy, Drawable d, GC gc, int x, int y,
                 unsigned int width, unsigned int height)
 {
   jwxyz_fill_rect (dpy, d, gc, x, y, width, height,
-                   jwxyz_gc_gcv (gc)->foreground);
+                   VTBL->gc_gcv (gc)->foreground);
   return 0;
 }
 
@@ -347,7 +421,17 @@ XDrawRectangle (Display *dpy, Drawable d, GC gc, int x, int y,
 int
 XFillRectangles (Display *dpy, Drawable d, GC gc, XRectangle *rects, int n)
 {
-  jwxyz_fill_rects (dpy, d, gc, rects, n, jwxyz_gc_gcv (gc)->foreground);
+  VTBL->fill_rects (dpy, d, gc, rects, n, VTBL->gc_gcv (gc)->foreground);
+  return 0;
+}
+
+
+int
+XClearArea (Display *dpy, Window win, int x, int y, int w, int h, Bool exp)
+{
+  Assert(win == XRootWindow(dpy,0), "XClearArea: not a window");
+  Assert(!exp, "XClearArea: exposures unsupported");
+  jwxyz_fill_rect (dpy, win, 0, x, y, w, h, *VTBL->window_background (dpy));
   return 0;
 }
 
@@ -356,7 +440,7 @@ int
 XDrawArc (Display *dpy, Drawable d, GC gc, int x, int y,
           unsigned int width, unsigned int height, int angle1, int angle2)
 {
-  return jwxyz_draw_arc (dpy, d, gc, x, y, width, height, angle1, angle2,
+  return VTBL->draw_arc (dpy, d, gc, x, y, width, height, angle1, angle2,
                          False);
 }
 
@@ -364,7 +448,7 @@ int
 XFillArc (Display *dpy, Drawable d, GC gc, int x, int y,
           unsigned int width, unsigned int height, int angle1, int angle2)
 {
-  return jwxyz_draw_arc (dpy, d, gc, x, y, width, height, angle1, angle2,
+  return VTBL->draw_arc (dpy, d, gc, x, y, width, height, angle1, angle2,
                          True);
 }
 
@@ -373,7 +457,7 @@ XDrawArcs (Display *dpy, Drawable d, GC gc, XArc *arcs, int narcs)
 {
   int i;
   for (i = 0; i < narcs; i++)
-    jwxyz_draw_arc (dpy, d, gc,
+    VTBL->draw_arc (dpy, d, gc,
                     arcs[i].x, arcs[i].y,
                     arcs[i].width, arcs[i].height,
                     arcs[i].angle1, arcs[i].angle2,
@@ -386,7 +470,7 @@ XFillArcs (Display *dpy, Drawable d, GC gc, XArc *arcs, int narcs)
 {
   int i;
   for (i = 0; i < narcs; i++)
-    jwxyz_draw_arc (dpy, d, gc,
+    VTBL->draw_arc (dpy, d, gc,
                     arcs[i].x, arcs[i].y,
                     arcs[i].width, arcs[i].height,
                     arcs[i].angle1, arcs[i].angle2,
@@ -418,8 +502,8 @@ XChangeGC (Display *dpy, GC gc, unsigned long mask, XGCValues *from)
   Assert (gc && from, "no gc");
   if (!gc || !from) return 0;
 
-  XGCValues *to = jwxyz_gc_gcv (gc);
-  unsigned depth = jwxyz_gc_depth (gc);
+  XGCValues *to = VTBL->gc_gcv (gc);
+  unsigned depth = VTBL->gc_depth (gc);
 
   if (mask & GCFunction)        to->function            = from->function;
   if (mask & GCForeground)      to->foreground          = from->foreground;
@@ -432,8 +516,8 @@ XChangeGC (Display *dpy, GC gc, unsigned long mask, XGCValues *from)
   if (mask & GCClipYOrigin)     to->clip_y_origin       = from->clip_y_origin;
   if (mask & GCSubwindowMode)   to->subwindow_mode      = from->subwindow_mode;
 
-  if (mask & GCClipMask)       XSetClipMask (0, gc, from->clip_mask);
-  if (mask & GCFont)           XSetFont (0, gc, from->font);
+  if (mask & GCClipMask)       XSetClipMask (dpy, gc, from->clip_mask);
+  if (mask & GCFont)           XSetFont (dpy, gc, from->font);
 
   if (mask & GCForeground)
     jwxyz_validate_pixel (dpy, from->foreground, depth, to->alpha_allowed_p);
@@ -494,11 +578,13 @@ XGetGeometry (Display *dpy, Drawable d, Window *root_ret,
 Status
 XAllocColor (Display *dpy, Colormap cmap, XColor *color)
 {
-  color->pixel = jwxyz_alloc_color (dpy,
-                                    color->red,
-                                    color->green,
-                                    color->blue,
-                                    0xFFFF);
+  const unsigned long *masks =
+    DefaultVisualOfScreen(DefaultScreenOfDisplay(dpy))->rgba_masks;
+  color->pixel =
+    (((color->red   << 16) >> (31 - i_log2(masks[0]))) & masks[0]) |
+    (((color->green << 16) >> (31 - i_log2(masks[1]))) & masks[1]) |
+    (((color->blue  << 16) >> (31 - i_log2(masks[2]))) & masks[2]) |
+    masks[3];
   return 1;
 }
 
@@ -590,11 +676,11 @@ int
 XQueryColor (Display *dpy, Colormap cmap, XColor *color)
 {
   jwxyz_validate_pixel (dpy, color->pixel, visual_depth (NULL, NULL), False);
-  uint8_t rgba[4];
-  jwxyz_query_color (dpy, color->pixel, rgba);
-  color->red   = (rgba[0] << 8) | rgba[0];
-  color->green = (rgba[1] << 8) | rgba[1];
-  color->blue  = (rgba[2] << 8) | rgba[2];
+  uint16_t rgba[4];
+  JWXYZ_QUERY_COLOR (dpy, color->pixel, 0xffffull, rgba);
+  color->red   = rgba[0];
+  color->green = rgba[1];
+  color->blue  = rgba[2];
   color->flags = DoRed|DoGreen|DoBlue;
   return 0;
 }
@@ -683,9 +769,9 @@ XCreateImage (Display *dpy, Visual *visual, unsigned int depth,
   ximage->bitmap_pad = bitmap_pad;
   ximage->depth = depth;
   Visual *v = DefaultVisualOfScreen (DefaultScreenOfDisplay (dpy));
-  ximage->red_mask   = (depth == 1 ? 0 : v->red_mask);
-  ximage->green_mask = (depth == 1 ? 0 : v->green_mask);
-  ximage->blue_mask  = (depth == 1 ? 0 : v->blue_mask);
+  ximage->red_mask   = (depth == 1 ? 0 : v->rgba_masks[0]);
+  ximage->green_mask = (depth == 1 ? 0 : v->rgba_masks[1]);
+  ximage->blue_mask  = (depth == 1 ? 0 : v->rgba_masks[2]);
   ximage->bits_per_pixel = (depth == 1 ? 1 : visual_depth (NULL, NULL));
   ximage->bytes_per_line = bytes_per_line;
 
@@ -843,7 +929,7 @@ query_font (Font fid)
   for (int i = first; i <= last; i++) {
     XCharStruct *cs = &f->per_char[i-first];
     char s = (char) i;
-    jwxyz_render_text (dpy, native_font, &s, 1, False, cs, 0);
+    jwxyz_render_text (dpy, native_font, &s, 1, False, False, cs, 0);
 
     max->width    = MAX (max->width,    cs->width);
     max->ascent   = MAX (max->ascent,   cs->ascent);
@@ -1145,16 +1231,11 @@ XLoadFont (Display *dpy, const char *name)
   if (! fid->native_font)
     try_xlfd_font (dpy, name, fid);
 
-  //Log("parsed \"%s\" to %s %.1f", name, fid->ps_name, fid->size);
-
-  /*
-  fid->native_font = jwxyz_load_native_font (dpy, name,
-                                             &fid->ascent, &fid->descent);
   if (!fid->native_font) {
     free (fid);
     return 0;
   }
-   */
+
   query_font (fid);
 
   return fid;
@@ -1218,7 +1299,7 @@ XFreeFont (Display *dpy, XFontStruct *f)
 int
 XSetFont (Display *dpy, GC gc, Font fid)
 {
-  XGCValues *gcv = jwxyz_gc_gcv(gc);
+  XGCValues *gcv = VTBL->gc_gcv(gc);
   Font font2 = copy_font (fid);
   if (gcv->font)
     XUnloadFont (dpy, gcv->font);
@@ -1283,7 +1364,7 @@ XTextExtents (XFontStruct *f, const char *s, int length,
 
   Font ff = f->fid;
   Display *dpy = ff->dpy;
-  jwxyz_render_text (dpy, ff->native_font, s, length, False, cs, 0);
+  jwxyz_render_text (dpy, ff->native_font, s, length, False, False, cs, 0);
   *dir_ret = 0;
   *ascent_ret  = f->ascent;
   *descent_ret = f->descent;
@@ -1319,7 +1400,7 @@ XTextExtents16 (XFontStruct *f, const XChar2b *s, int length,
     Font ff = f->fid;
     Display *dpy = ff->dpy;
     jwxyz_render_text (dpy, ff->native_font, utf8, strlen(utf8),
-                       True, cs, 0);
+                       True, False, cs, 0);
   }
 
   *dir_ret = 0;
@@ -1359,7 +1440,8 @@ Xutf8TextExtents (XFontSet set, const char *str, int len,
   XCharStruct cs;
   Font f = set->font->fid;
 
-  jwxyz_render_text (f->dpy, f->native_font, str, len, True, &cs, NULL);
+  jwxyz_render_text (f->dpy, f->native_font, str, len, True, False, &cs,
+                     NULL);
 
   /* "The overall_logical_return is the bounding box that provides minimum
    spacing to other graphical features for the string. Other graphical
@@ -1379,11 +1461,72 @@ Xutf8TextExtents (XFontSet set, const char *str, int len,
 }
 
 
+int
+jwxyz_draw_string (Display *dpy, Drawable d, GC gc, int x, int y,
+                   const char *str, size_t len, int utf8_p)
+{
+  const XGCValues *gcv = VTBL->gc_gcv (gc);
+  Font ff = gcv->font;
+  XCharStruct cs;
+
+  char *data = 0;
+  jwxyz_render_text (dpy, jwxyz_native_font (ff), str, len, utf8_p,
+                     gcv->antialias_p, &cs, &data);
+  int w = cs.rbearing - cs.lbearing;
+  int h = cs.ascent + cs.descent;
+
+  if (w < 0 || h < 0) abort();
+  if (w == 0 || h == 0) {
+    if (data) free(data);
+    return 0;
+  }
+
+  XImage *img = XCreateImage (dpy, VTBL->visual (dpy), 32,
+                              ZPixmap, 0, data, w, h, 0, 0);
+
+  /* The image of text is a 32-bit image, in white.
+     Take the green channel for intensity and use that as alpha.
+     replace RGB with the GC's foreground color.
+     This expects that XPutImage respects alpha and only writes
+     the bits that are not masked out.
+   */
+  {
+# define ROTL(x, rot) (((x) << ((rot) & 31)) | ((x) >> (32 - ((rot) & 31))))
+
+    const unsigned long *masks =
+      DefaultVisualOfScreen (DefaultScreenOfDisplay(dpy))->rgba_masks;
+    unsigned shift = (i_log2 (masks[3]) - i_log2 (masks[1])) & 31;
+    uint32_t mask = ROTL(masks[1], shift) & masks[3],
+             color = gcv->foreground & ~masks[3];
+    uint32_t *s = (uint32_t *)data;
+    uint32_t *end = s + (w * h);
+    while (s < end) {
+
+      *s = (ROTL(*s, shift) & mask) | color;
+      ++s;
+    }
+  }
+
+  {
+    Bool old_alpha = gcv->alpha_allowed_p;
+    jwxyz_XSetAlphaAllowed (dpy, gc, True);
+    XPutImage (dpy, d, gc, img, 0, 0,
+               x + cs.lbearing,
+               y - cs.ascent,
+               w, h);
+    jwxyz_XSetAlphaAllowed (dpy, gc, old_alpha);
+    XDestroyImage (img);
+  }
+
+  return 0;
+}
+
+
 int
 XDrawString (Display *dpy, Drawable d, GC gc, int x, int y,
              const char  *str, int len)
 {
-  return jwxyz_draw_string (dpy, d, gc, x, y, str, len, False);
+  return VTBL->draw_string (dpy, d, gc, x, y, str, len, False);
 }
 
 
@@ -1398,7 +1541,7 @@ XDrawString16 (Display *dpy, Drawable d, GC gc, int x, int y,
   b2[len].byte1 = b2[len].byte2 = 0;
   s2 = XChar2b_to_utf8 (b2, 0);
   free (b2);
-  ret = jwxyz_draw_string (dpy, d, gc, x, y, s2, strlen(s2), True);
+  ret = VTBL->draw_string (dpy, d, gc, x, y, s2, strlen(s2), True);
   free (s2);
   return ret;
 }
@@ -1408,7 +1551,7 @@ void
 Xutf8DrawString (Display *dpy, Drawable d, XFontSet set, GC gc,
                  int x, int y, const char *str, int len)
 {
-  jwxyz_draw_string (dpy, d, gc, x, y, str, len, True);
+  VTBL->draw_string (dpy, d, gc, x, y, str, len, True);
 }
 
 
@@ -1418,7 +1561,7 @@ XDrawImageString (Display *dpy, Drawable d, GC gc, int x, int y,
 {
   int ascent, descent, dir;
   XCharStruct cs;
-  XTextExtents (&jwxyz_gc_gcv (gc)->font->metrics, str, len,
+  XTextExtents (&VTBL->gc_gcv (gc)->font->metrics, str, len,
                 &dir, &ascent, &descent, &cs);
   jwxyz_fill_rect (dpy, d, gc,
                    x + MIN (0, cs.lbearing),
@@ -1427,7 +1570,7 @@ XDrawImageString (Display *dpy, Drawable d, GC gc, int x, int y,
                         MIN (0, cs.lbearing),
                         cs.width),
                    MAX (0, ascent) + MAX (0, descent),
-                   jwxyz_gc_gcv(gc)->background);
+                   VTBL->gc_gcv(gc)->background);
   return XDrawString (dpy, d, gc, x, y, str, len);
 }
 
@@ -1442,8 +1585,8 @@ jwxyz_native_font (Font f)
 int
 XSetForeground (Display *dpy, GC gc, unsigned long fg)
 {
-  XGCValues *gcv = jwxyz_gc_gcv (gc);
-  jwxyz_validate_pixel (dpy, fg, jwxyz_gc_depth (gc), gcv->alpha_allowed_p);
+  XGCValues *gcv = VTBL->gc_gcv (gc);
+  jwxyz_validate_pixel (dpy, fg, VTBL->gc_depth (gc), gcv->alpha_allowed_p);
   gcv->foreground = fg;
   return 0;
 }
@@ -1452,8 +1595,8 @@ XSetForeground (Display *dpy, GC gc, unsigned long fg)
 int
 XSetBackground (Display *dpy, GC gc, unsigned long bg)
 {
-  XGCValues *gcv = jwxyz_gc_gcv (gc);
-  jwxyz_validate_pixel (dpy, bg, jwxyz_gc_depth (gc), gcv->alpha_allowed_p);
+  XGCValues *gcv = VTBL->gc_gcv (gc);
+  jwxyz_validate_pixel (dpy, bg, VTBL->gc_depth (gc), gcv->alpha_allowed_p);
   gcv->background = bg;
   return 0;
 }
@@ -1461,14 +1604,14 @@ XSetBackground (Display *dpy, GC gc, unsigned long bg)
 int
 jwxyz_XSetAlphaAllowed (Display *dpy, GC gc, Bool allowed)
 {
-  jwxyz_gc_gcv (gc)->alpha_allowed_p = allowed;
+  VTBL->gc_gcv (gc)->alpha_allowed_p = allowed;
   return 0;
 }
 
 int
 jwxyz_XSetAntiAliasing (Display *dpy, GC gc, Bool antialias_p)
 {
-  jwxyz_gc_gcv (gc)->antialias_p = antialias_p;
+  VTBL->gc_gcv (gc)->antialias_p = antialias_p;
   return 0;
 }
 
@@ -1477,7 +1620,7 @@ int
 XSetLineAttributes (Display *dpy, GC gc, unsigned int line_width,
                     int line_style, int cap_style, int join_style)
 {
-  XGCValues *gcv = jwxyz_gc_gcv (gc);
+  XGCValues *gcv = VTBL->gc_gcv (gc);
   gcv->line_width = line_width;
   Assert (line_style == LineSolid, "only LineSolid implemented");
 //  gc->gcv.line_style = line_style;
@@ -1495,14 +1638,14 @@ XSetGraphicsExposures (Display *dpy, GC gc, Bool which)
 int
 XSetFunction (Display *dpy, GC gc, int which)
 {
-  jwxyz_gc_gcv (gc)->function = which;
+  VTBL->gc_gcv (gc)->function = which;
   return 0;
 }
 
 int
 XSetSubwindowMode (Display *dpy, GC gc, int which)
 {
-  jwxyz_gc_gcv (gc)->subwindow_mode = which;
+  VTBL->gc_gcv (gc)->subwindow_mode = which;
   return 0;
 }
 
@@ -1617,7 +1760,7 @@ visual_depth (Screen *s, Visual *v)
 int
 visual_cells (Screen *s, Visual *v)
 {
-  return (int)(v->red_mask | v->green_mask | v->blue_mask);
+  return (int)(v->rgba_masks[0] | v->rgba_masks[1] | v->rgba_masks[2]);
 }
 
 int
@@ -1630,9 +1773,9 @@ void
 visual_rgb_masks (Screen *s, Visual *v, unsigned long *red_mask,
                   unsigned long *green_mask, unsigned long *blue_mask)
 {
-  *red_mask = v->red_mask;
-  *green_mask = v->green_mask;
-  *blue_mask = v->blue_mask;
+  *red_mask = v->rgba_masks[0];
+  *green_mask = v->rgba_masks[1];
+  *blue_mask = v->rgba_masks[2];
 }
 
 int
index 0766a4521f884f73dc107b3eacf9e87ed4f8036f..41006033b7ebeb2a83da6fedf21e8413bce6d85c 100644 (file)
    and iOS is in jwxyz.m.
  */
 
-/* Be advised, this is all very much a work in progress.
-
-   TODO: The following should be implemented before OpenGL can be considered
-   practical here:
-   - Above all, pick the smallest not-yet working hack that utilizes the
-     needed functionality.
-     - Half-ass the drawing functions.
-   - [OK] What Interference needs
-   - Fast Pixmaps
-   - Whatever clipping is used in XScreenSaver (shape and/or bitmap clipping)
-   - Delayed context creation to support anti-aliasing/multisampling
-   - Everything these hacks need:
-     - FuzzyFlakes (needs wide lines)
-     - Greynetic
-     - [OK] Deluxe
-   - [OK] Get DangerBall going.
-   - [OK] iOS.
-     - [Interference, so far...] And fast, too.
-   - And text really needs to work for the FPS display. */
-
-/* Also, Take note that OS X can actually run with 256 colors. */
+/* Be advised, this is all very much a work in progress. */
+
+/* FWIW, at one point macOS 10.x could actually run with 256 colors. It might
+   not be able to do this anymore, though.
+ */
 
 /* TODO:
    - malloc error checking
@@ -51,7 +35,6 @@
    - iOS: OpenGL ES 2.0 isn't always available. Use OpenGL ES 1.1.
    - OS X: Drivers can go back to OpenGL 1.1 (GeForce 2 MX on 10.5.8).
    - Use stencil buffers (OpenGL 1.0+) for bitmap clipping masks.
-   - glLogicOp is an actual thing that should work for GCs.
    - Pixmaps can be any of the following, depending on GL implementation.
      - This requires offscreen rendering. Fortunately, this is always
        available.
  */
 
 /* OpenGL hacks call a number of X11 functions, including
- * XCopyArea, XDrawString, XGetImage
- * XCreatePixmap, XCreateGC, XCreateImage
- * XPutPixel
- * Check these, of course. */
+   XCopyArea, XDrawString, XGetImage
+   XCreatePixmap, XCreateGC, XCreateImage
+   XPutPixel
+   Check these, of course.
+ */
 
 #ifdef JWXYZ_GL /* entire file */
 
 #  import <QuartzCore/QuartzCore.h>
 #  include <OpenGLES/ES1/gl.h>
 #  include <OpenGLES/ES1/glext.h>
-
-#  define NSView  UIView
-#  define NSRect  CGRect
-#  define NSPoint CGPoint
-#  define NSSize  CGSize
-#  define NSColor UIColor
-#  define NSImage UIImage
-#  define NSEvent UIEvent
-#  define NSFont  UIFont
-#  define NSGlyph CGGlyph
-#  define NSWindow UIWindow
-#  define NSMakeSize   CGSizeMake
-#  define NSBezierPath UIBezierPath
-#  define colorWithDeviceRed colorWithRed
-
-#  define NSFontTraitMask      UIFontDescriptorSymbolicTraits
-// The values for the flags for NSFontTraitMask and
-// UIFontDescriptorSymbolicTraits match up, not that it really matters here.
-#  define NSBoldFontMask       UIFontDescriptorTraitBold
-#  define NSFixedPitchFontMask UIFontDescriptorTraitMonoSpace
-#  define NSItalicFontMask     UIFontDescriptorTraitItalic
-
-#  define NSOpenGLContext EAGLContext
-
 # else
 #  include <OpenGL/glu.h>
 # endif
 # include "jwzglesI.h"
 #endif
 
-#ifdef HAVE_ANDROID
-# include <android/log.h>
-#endif
-
 #include "jwxyzI.h"
 #include "jwxyz-timers.h"
 #include "yarandom.h"
 #include "xft.h"
 #include "pow2.h"
 
-#if defined HAVE_COCOA
-# include <CoreGraphics/CGGeometry.h>
-#else
-
-struct CGPoint {
-    float x;
-    float y;
-};
-typedef struct CGPoint CGPoint;
-
-struct CGSize {
-    float width;
-    float height;
-};
-typedef struct CGSize CGSize;
-
-struct CGRect {
-    CGPoint origin;
-    CGSize size;
-};
-typedef struct CGRect CGRect;
-
-#endif
-
-# undef MAX
-# undef MIN
-# define MAX(a,b) ((a)>(b)?(a):(b))
-# define MIN(a,b) ((a)<(b)?(a):(b))
-
-union color_bytes
-{
-  /* On 64-bit systems, high bits of the 32-bit pixel are available as scratch
-     space. I doubt if any screen savers need it, but just in case... */
-  unsigned long pixel;
+union color_bytes {
+  uint32_t pixel;
   uint8_t bytes[4];
 };
 
 struct jwxyz_Display {
+  const struct jwxyz_vtbl *vtbl; // Must come first.
+
   Window main_window;
-  Screen *screen;
+  GLenum pixel_format, pixel_type;
+  Visual visual;
   struct jwxyz_sources_data *timers_data;
 
   Bool gl_texture_npot_p;
@@ -197,23 +124,22 @@ struct jwxyz_Display {
 // #endif
 
   unsigned long window_background;
-};
 
-struct jwxyz_Screen {
-  Display *dpy;
-  GLenum pixel_format, pixel_type;
-  unsigned long black, white;
-  Visual *visual;
+  int gc_function;
+  Bool gc_alpha_allowed_p;
+
+  // Alternately, there could be one queue per pixmap.
+  size_t queue_size, queue_capacity;
+  Drawable queue_drawable;
+  GLint queue_mode;
+  GLshort *queue_vertex;
+  uint32_t *queue_color;
+  Bool queue_line_cap;
 };
 
 struct jwxyz_GC {
   XGCValues gcv;
   unsigned int depth;
-  // CGImageRef clip_mask;  // CGImage copy of the Pixmap in gcv.clip_mask
-};
-
-struct jwxyz_XFontSet {
-  XFontStruct *font;
 };
 
 struct jwxyz_linked_point {
@@ -221,66 +147,6 @@ struct jwxyz_linked_point {
     linked_point *next;
 };
 
-/* XGetImage in CoreGraphics JWXYZ has to deal with funky pixel formats
-   necessitating fast & flexible pixel conversion. OpenGL does image format
-   conversion itself, so alloc_color and query_color are mercifully simple.
- */
-uint32_t
-jwxyz_alloc_color (Display *dpy,
-                   uint16_t r, uint16_t g, uint16_t b, uint16_t a)
-{
-  union color_bytes color;
-
-  /* Instead of (int)(c / 256.0), another possibility is
-     (int)(c * 255.0 / 65535.0 + 0.5). This can be calculated using only
-     uint8_t integer_math(uint16_t c) {
-       unsigned c0 = c + 128;
-       return (c0 - (c0 >> 8)) >> 8;
-     }
-   */
-
-  color.bytes[0] = r >> 8;
-  color.bytes[1] = g >> 8;
-  color.bytes[2] = b >> 8;
-  color.bytes[3] = a >> 8;
-
-  if (dpy->screen->pixel_format == GL_BGRA_EXT) {
-    color.pixel = color.bytes[2] |
-                  (color.bytes[1] << 8) |
-                  (color.bytes[0] << 16) |
-                  (color.bytes[3] << 24);
-  } else {
-    Assert(dpy->screen->pixel_format == GL_RGBA,
-           "jwxyz_alloc_color: Unknown pixel_format");
-  }
-
-  return (uint32_t)color.pixel;
-}
-
-// Converts an array of pixels ('src') from one format to another, placing the
-// result in 'dest', according to the pixel conversion mode 'mode'.
-void
-jwxyz_query_color (Display *dpy, unsigned long pixel, uint8_t *rgba)
-{
-  union color_bytes color;
-
-  if(dpy->screen->pixel_format == GL_RGBA)
-  {
-    color.pixel = pixel;
-    for (unsigned i = 0; i != 4; ++i)
-      rgba[i] = color.bytes[i];
-    return;
-  }
-
-  Assert (dpy->screen->pixel_format == GL_BGRA_EXT,
-          "jwxyz_query_color: Unknown pixel format");
-  /* TODO: Cross-check with XAllocColor. */
-  rgba[0] = (pixel >> 16) & 0xFF;
-  rgba[1] = (pixel >>  8) & 0xFF;
-  rgba[2] = (pixel >>  0) & 0xFF;
-  rgba[3] = (pixel >> 24) & 0xFF;
-}
-
 
 void
 jwxyz_assert_display(Display *dpy)
@@ -344,30 +210,16 @@ gl_check_ver (const struct gl_version *caps,
            (caps->major == gl_major && caps->minor >= gl_minor);
 }
 
-/*
-static GLboolean gl_check_ext(const struct gl_caps *caps,
-                              unsigned gl_major,
-                              unsigned gl_minor,
-                              const char *extension)
-{
-  return
-    gl_check_ver(caps, gl_major, gl_minor) ||
-    gluCheckExtension(extension, caps->extensions);
-}
-*/
-
 #endif
 
 
-// NSOpenGLContext *jwxyz_debug_context;
-
+extern const struct jwxyz_vtbl gl_vtbl;
 
 Display *
-jwxyz_make_display (Window w)
+jwxyz_gl_make_display (Window w)
 {
   Display *d = (Display *) calloc (1, sizeof(*d));
-  d->screen = (Screen *) calloc (1, sizeof(Screen));
-  d->screen->dpy = d;
+  d->vtbl = &gl_vtbl;
 
 # ifndef HAVE_JWZGLES
   struct gl_version version;
@@ -397,29 +249,30 @@ jwxyz_make_display (Window w)
   // you're gonna get for getting a texture onto the screen.
 # ifdef HAVE_JWZGLES
   /* TODO: Make BGRA work on iOS. As it is, it breaks XPutImage. (glTexImage2D, AFAIK) */
-  d->screen->pixel_format = GL_RGBA; /*
+  d->pixel_format = GL_RGBA; /*
     gluCheckExtension ((const GLubyte *) "GL_APPLE_texture_format_BGRA8888",
                        extensions) ? GL_BGRA_EXT : GL_RGBA; */
-  d->screen->pixel_type = GL_UNSIGNED_BYTE;
+  d->pixel_type = GL_UNSIGNED_BYTE;
   // See also OES_read_format.
 # else  // !HAVE_JWZGLES
   if (gl_check_ver (&version, 1, 2) ||
       (gluCheckExtension ((const GLubyte *) "GL_EXT_bgra", extensions) &&
        gluCheckExtension ((const GLubyte *) "GL_APPLE_packed_pixels",
                           extensions))) {
-    d->screen->pixel_format = GL_BGRA_EXT;
+    // APPLE_packed_pixels is only ever available on iOS, never Android.
+    d->pixel_format = GL_BGRA_EXT;
     // Both Intel and PowerPC-era docs say to use GL_UNSIGNED_INT_8_8_8_8_REV.
-    d->screen->pixel_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+    d->pixel_type = GL_UNSIGNED_INT_8_8_8_8_REV;
   } else {
-    d->screen->pixel_format = GL_RGBA;
-    d->screen->pixel_type = GL_UNSIGNED_BYTE;
+    d->pixel_format = GL_RGBA;
+    d->pixel_type = GL_UNSIGNED_BYTE;
   }
   // GL_ABGR_EXT/GL_UNSIGNED_BYTE is another possibilty that may have made more
   // sense on PowerPC.
 # endif // !HAVE_JWZGLES
 
-  // On really old systems, it would make sense to split the texture
-  // into subsections.
+  // On really old systems, it would make sense to split textures
+  // into subsections, to work around the maximum texture size.
 # ifndef HAVE_JWZGLES
   d->gl_texture_npot_p = gluCheckExtension ((const GLubyte *)
                                             "GL_ARB_texture_rectangle",
@@ -438,15 +291,23 @@ jwxyz_make_display (Window w)
   d->gl_texture_target = GL_TEXTURE_2D;
 # endif
 
-  d->screen->black = jwxyz_alloc_color (d, 0x0000, 0x0000, 0x0000, 0xFFFF);
-  d->screen->white = jwxyz_alloc_color (d, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF);
-
-  Visual *v = (Visual *) calloc (1, sizeof(Visual));
+  Visual *v = &d->visual;
   v->class      = TrueColor;
-  v->red_mask   = jwxyz_alloc_color (d, 0xFFFF, 0x0000, 0x0000, 0x0000);
-  v->green_mask = jwxyz_alloc_color (d, 0x0000, 0xFFFF, 0x0000, 0x0000);
-  v->blue_mask  = jwxyz_alloc_color (d, 0x0000, 0x0000, 0xFFFF, 0x0000);
-  d->screen->visual = v;
+  if (d->pixel_format == GL_BGRA_EXT) {
+    v->rgba_masks[0] = 0x00ff0000;
+    v->rgba_masks[1] = 0x0000ff00;
+    v->rgba_masks[2] = 0x000000ff;
+    v->rgba_masks[3] = 0xff000000;
+  } else {
+    Assert(d->pixel_format == GL_RGBA,
+           "jwxyz_gl_make_display: Unknown pixel_format");
+    for (unsigned i = 0; i != 4; ++i) {
+      union color_bytes color;
+      color.pixel = 0;
+      color.bytes[i] = 0xff;
+      v->rgba_masks[i] = color.pixel;
+    }
+  }
 
   d->timers_data = jwxyz_sources_init (XtDisplayToApplicationContext (d));
 
@@ -454,16 +315,9 @@ jwxyz_make_display (Window w)
 
   d->main_window = w;
   {
-    fputs((char *)glGetString(GL_VENDOR), stderr);
-    fputc(' ', stderr);
-    fputs((char *)glGetString(GL_RENDERER), stderr);
-    fputc(' ', stderr);
-    fputs((char *)glGetString(GL_VERSION), stderr);
-    fputc('\n', stderr);
-//  puts(caps.extensions);
     GLint max_texture_size;
     glGetIntegerv (GL_MAX_TEXTURE_SIZE, &max_texture_size);
-    printf ("GL_MAX_TEXTURE_SIZE: %d\n", max_texture_size);
+    Log ("GL_MAX_TEXTURE_SIZE: %d\n", max_texture_size);
   }
  
   // In case a GL hack wants to use X11 to draw offscreen, the rect_texture is available.
@@ -490,44 +344,27 @@ jwxyz_make_display (Window w)
   glTexParameteri (d->gl_texture_target, GL_TEXTURE_WRAP_S, wrap);
   glTexParameteri (d->gl_texture_target, GL_TEXTURE_WRAP_T, wrap);
 
+  d->gc_function = GXcopy;
+  d->gc_alpha_allowed_p = False;
+
   jwxyz_assert_display(d);
   return d;
 }
 
 void
-jwxyz_free_display (Display *dpy)
+jwxyz_gl_free_display (Display *dpy)
 {
   /* TODO: Go over everything. */
 
+  free (dpy->queue_vertex);
+  free (dpy->queue_color);
+
   jwxyz_sources_free (dpy->timers_data);
 
-  free (dpy->screen->visual);
-  free (dpy->screen);
   free (dpy);
 }
 
 
-/* Call this after any modification to the bits on a Pixmap or Window.
-   Most Pixmaps are used frequently as sources and infrequently as
-   destinations, so it pays to cache the data as a CGImage as needed.
- */
-static void
-invalidate_drawable_cache (Drawable d)
-{
-  /* TODO: Kill this outright. jwxyz_bind_drawable handles any potential 
-     invalidation.
-   */
-
-  /*
-  if (d && d->cgi) {
-    abort();
-    CGImageRelease (d->cgi);
-    d->cgi = 0;
-  }
- */
-}
-
-
 /* Call this when the View changes size or position.
  */
 void
@@ -545,6 +382,7 @@ jwxyz_window_resized (Display *dpy)
 
   Log("resize: %d, %d\n", new_width, new_height);
 
+  jwxyz_gl_flush (dpy);
   jwxyz_bind_drawable (dpy, dpy->main_window, dpy->main_window);
 
   // TODO: What does the iPhone need?
@@ -569,125 +407,114 @@ jwxyz_window_resized (Display *dpy)
   // Stylish and attractive purple!
   // glClearColor (1, 0, 1, 0.5);
   // glClear (GL_COLOR_BUFFER_BIT);
-  
-  invalidate_drawable_cache (dpy->main_window);
 }
 
 
-jwxyz_sources_data *
+static jwxyz_sources_data *
 display_sources_data (Display *dpy)
 {
   return dpy->timers_data;
 }
 
 
-Window
-XRootWindow (Display *dpy, int screen)
+static Window
+root (Display *dpy)
 {
-  return dpy ? dpy->main_window : 0;
+  return dpy->main_window;
 }
 
-Screen *
-XDefaultScreenOfDisplay (Display *dpy)
+static Visual *
+visual (Display *dpy)
 {
-  return dpy ? dpy->screen : 0;
+  return &dpy->visual;
 }
 
-Visual *
-XDefaultVisualOfScreen (Screen *screen)
-{
-  return screen ? screen->visual : 0;
-}
 
-Display *
-XDisplayOfScreen (Screen *s)
-{
-  return s ? s->dpy : 0;
-}
+/* GC attributes by usage and OpenGL implementation:
 
-int
-XDisplayNumberOfScreen (Screen *s)
-{
-  return 0;
-}
+   All drawing functions:
+   function                                | glLogicOp w/ GL_COLOR_LOGIC_OP
+   clip_x_origin, clip_y_origin, clip_mask | Stencil mask
 
-int
-XScreenNumberOfScreen (Screen *s)
-{
-  return 0;
-}
+   Shape drawing functions:
+   foreground, background                  | glColor*
 
-unsigned long
-XBlackPixelOfScreen(Screen *screen)
-{
-  return screen->black;
-}
+   XDrawLines, XDrawRectangles, XDrawSegments:
+   line_width, cap_style, join_style       | Lotsa vertices
 
-unsigned long
-XWhitePixelOfScreen(Screen *screen)
-{
-  return screen->white;
-}
+   XFillPolygon:
+   fill_rule                               | Multiple GL_TRIANGLE_FANs
 
-unsigned long
-XCellsOfScreen(Screen *screen)
-{
-  Visual *v = screen->visual;
-  return v->red_mask | v->green_mask | v->blue_mask;
-}
+   XDrawText:
+   font                                    | Cocoa, then OpenGL display lists.
 
+   alpha_allowed_p                         | GL_BLEND
 
-/* GC attributes by usage and OpenGL implementation:
- *
- * All drawing functions:
- * function                                | glLogicOp w/ GL_COLOR_LOGIC_OP
- * clip_x_origin, clip_y_origin, clip_mask | Stencil mask
- *
- * Shape drawing functions:
- * foreground, background                  | glColor*
- *
- * XDrawLines, XDrawRectangles, XDrawSegments:
- * line_width, cap_style, join_style       | Lotsa vertices
- *
- * XFillPolygon:
- * fill_rule                               | Multiple GL_TRIANGLE_FANs
- *
- * XDrawText:
- * font                                    | Cocoa, then OpenGL display lists.
- *
- * alpha_allowed_p                         | TODO
- * antialias_p                             | TODO
- *
- * Nothing, really:
- * subwindow_mode
-*/
+   antialias_p                             | Well, there's options:
+   * Multisampling would work, but that's something that would need to be set
+     per-Pixmap, not per-GC.
+   * GL_POINT, LINE, and POLYGON_SMOOTH are the old-school way of doing
+     this, but POINT_SMOOTH is unnecessary, and POLYGON_SMOOTH is missing from
+     GLES 1. All three are missing from GLES 2. Word on the street is that
+     these are deprecated anyway.
+   * Tiny textures with bilinear filtering to get the same effect as LINE_ and
+     POLYGON_SMOOTH. A bit tricky.
+   * Do nothing. Android hardware is very often high-DPI enough that
+     anti-aliasing doesn't matter all that much.
 
-static void
-set_clip_mask (GC gc)
+   Nothing, really:
+   subwindow_mode
+ */
+
+static GLshort *
+enqueue (Display *dpy, Drawable d, GC gc, int mode, size_t count)
 {
-  Assert (!gc->gcv.clip_mask, "set_gc: TODO");
+  if (dpy->queue_size &&
+      (dpy->gc_function != gc->gcv.function ||
+       dpy->gc_alpha_allowed_p != gc->gcv.alpha_allowed_p ||
+       dpy->queue_mode != mode ||
+       dpy->queue_drawable != d)) {
+    jwxyz_gl_flush (dpy);
+  }
+
+  jwxyz_bind_drawable (dpy, dpy->main_window, d);
+  jwxyz_gl_set_gc (dpy, gc);
+
+  // TODO: Use glColor when we can get away with it.
+  size_t old_size = dpy->queue_size;
+  dpy->queue_size += count;
+  if (dpy->queue_size > dpy->queue_capacity) {
+    dpy->queue_capacity = dpy->queue_size * 2;
+
+    uint32_t *new_color = realloc (
+      dpy->queue_color, sizeof(*dpy->queue_color) * dpy->queue_capacity);
+    GLshort *new_vertex = realloc (
+      dpy->queue_vertex, sizeof(*dpy->queue_vertex) * 2 * dpy->queue_capacity);
+
+    if (!new_color || !new_vertex)
+      return NULL;
+
+    dpy->queue_color = new_color;
+    dpy->queue_vertex = new_vertex;
+  }
+
+  dpy->queue_mode = mode;
+  dpy->queue_drawable = d;
+
+  union color_bytes color;
+  // TODO: validate color
+  JWXYZ_QUERY_COLOR (dpy, gc->gcv.foreground, 0xffull, color.bytes);
+  for (size_t i = 0; i != count; ++i) // TODO: wmemset when applicable.
+    dpy->queue_color[i + old_size] = color.pixel;
+
+  return dpy->queue_vertex + old_size * 2;
 }
 
+
 static void
-set_function (int function)
+set_clip_mask (GC gc)
 {
-  Assert (function == GXcopy, "set_gc: (TODO) Stubbed gcv function");
-  
-  /* TODO: The GL_COLOR_LOGIC_OP extension is exactly what is needed here. (OpenGL 1.1)
-   Fun fact: The glLogicOp opcode constants are the same as the X11 GX* function constants | GL_CLEAR.
-   */
-  
-#if 0
-  switch (gc->gcv.function) {
-    case GXset:
-    case GXclear:
-    case GXcopy:/*CGContextSetBlendMode (cgc, kCGBlendModeNormal);*/   break;
-    case GXxor:   CGContextSetBlendMode (cgc, kCGBlendModeDifference); break;
-    case GXor:    CGContextSetBlendMode (cgc, kCGBlendModeLighten);    break;
-    case GXand:   CGContextSetBlendMode (cgc, kCGBlendModeDarken);     break;
-    default: Assert(0, "unknown gcv function"); break;
-  }
-#endif
+  Assert (!gc->gcv.clip_mask, "set_clip_mask: TODO");
 }
 
 
@@ -701,55 +528,92 @@ set_color (Display *dpy, unsigned long pixel, unsigned int depth,
     GLfloat f = pixel;
     glColor4f (f, f, f, 1);
   } else {
-    /* TODO: alpha_allowed_p */
-    uint8_t rgba[4];
-    jwxyz_query_color (dpy, pixel, rgba);
-#ifdef HAVE_JWZGLES
-    glColor4f (rgba[0] / 255.0f, rgba[1] / 255.0f,
-               rgba[2] / 255.0f, rgba[3] / 255.0f);
-#else
-    glColor4ubv (rgba);
-#endif
+    GLfloat rgba[4];
+    JWXYZ_QUERY_COLOR (dpy, pixel, 1.0f, rgba);
+    glColor4f (rgba[0], rgba[1], rgba[2], rgba[3]);
   }
 }
 
-/* Pushes a GC context; sets Function, ClipMask, and color.
- */
-static void
-set_color_gc (Display *dpy, GC gc, unsigned long color)
+/* Pushes a GC context; sets Function and ClipMask. */
+void
+jwxyz_gl_set_gc (Display *dpy, GC gc)
 {
-  // GC is NULL for XClearArea and XClearWindow.
-  unsigned int depth;
   int function;
+  Bool alpha_allowed_p;
+
+  // GC is NULL for XClearArea and XClearWindow.
   if (gc) {
     function = gc->gcv.function;
-    depth = gc->depth;
+    alpha_allowed_p = gc->gcv.alpha_allowed_p;
     set_clip_mask (gc);
   } else {
     function = GXcopy;
-    depth = visual_depth (NULL, NULL);
-    // TODO: Set null clip mask here.
+    alpha_allowed_p = False;
+    // TODO: Set null clip mask for NULL GC here.
+  }
+
+  /* GL_COLOR_LOGIC_OP: OpenGL 1.1. */
+  if (function != dpy->gc_function) {
+    dpy->gc_function = function;
+    if (function != GXcopy) {
+      /* Fun fact: The glLogicOp opcode constants are the same as the X11 GX*
+         function constants | GL_CLEAR.
+       */
+      glEnable (GL_COLOR_LOGIC_OP);
+      glLogicOp (gc->gcv.function | GL_CLEAR);
+    } else {
+      glDisable (GL_COLOR_LOGIC_OP);
+    }
+  }
+
+  /* Cocoa uses add/subtract/difference blending in place of logical ops.
+     It looks nice, but implementing difference blending in OpenGL appears to
+     require GL_KHR_blend_equation_advanced, and support for this is not
+     widespread.
+   */
+
+  if (alpha_allowed_p != dpy->gc_alpha_allowed_p) {
+    dpy->gc_alpha_allowed_p = alpha_allowed_p;
+    if (gc && gc->gcv.alpha_allowed_p) {
+      // TODO: Maybe move glBlendFunc to XCreatePixmap?
+      glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+      glEnable (GL_BLEND);
+    } else {
+      glDisable (GL_BLEND);
+    }
   }
+}
 
-  set_function (function);
 
-  switch (function) {
-    case GXset:   color = (depth == 1 ? 1 : WhitePixel(dpy,0)); break;
-    case GXclear: color = (depth == 1 ? 0 : BlackPixel(dpy,0)); break;
+static void
+set_color_gc (Display *dpy, Drawable d, GC gc, unsigned long color)
+{
+  jwxyz_gl_flush (dpy);
+  jwxyz_bind_drawable (dpy, dpy->main_window, d);
+  jwxyz_gl_set_gc (dpy, gc);
+
+  unsigned int depth;
+
+  if (gc) {
+    depth = gc->depth;
+
+    switch (gc->gcv.function) {
+      case GXset:   color = (depth == 1 ? 1 : WhitePixel(dpy,0)); break;
+      case GXclear: color = (depth == 1 ? 0 : BlackPixel(dpy,0)); break;
+    }
+  } else {
+    depth = visual_depth (NULL, NULL);
   }
 
   set_color (dpy, color, depth, gc ? gc->gcv.alpha_allowed_p : False);
-  
-  /* TODO: Antialiasing. */
-  /* CGContextSetShouldAntialias (cgc, antialias_p); */
 }
 
 /* Pushes a GC context; sets color to the foreground color.
  */
 static void
-set_fg_gc (Display *dpy, GC gc)
+set_fg_gc (Display *dpy, Drawable d, GC gc)
 {
-  set_color_gc (dpy, gc, gc->gcv.foreground);
+  set_color_gc (dpy, d, gc, gc->gcv.foreground);
 }
 
 static void
@@ -770,72 +634,49 @@ next_point(short *v, XPoint p, int mode)
   }
 }
 
-int
-XDrawPoints (Display *dpy, Drawable d, GC gc, 
-             XPoint *points, int count, int mode)
+static int
+DrawPoints (Display *dpy, Drawable d, GC gc,
+            XPoint *points, int count, int mode)
 {
-  jwxyz_bind_drawable (dpy, dpy->main_window, d);
-  set_fg_gc (dpy, gc);
-
-/*
-  
-  glBegin(GL_POINTS);
-  for (unsigned i = 0; i < count; i++) {
-    next_point(v, points[i], mode);
-    glVertex2f(v[0] + 0.5f, v[1] + 0.5f);
-  }
-  glEnd();
- */
-
   short v[2] = {0, 0};
 
   // TODO: XPoints can be fed directly to OpenGL.
-  GLshort *gl_points = malloc (count * 2 * sizeof(GLshort)); // TODO: malloc returns NULL.
+  GLshort *gl_points = enqueue (dpy, d, gc, GL_POINTS, count); // TODO: enqueue returns NULL.
   for (unsigned i = 0; i < count; i++) {
     next_point (v, points[i], mode);
     gl_points[2 * i] = v[0];
     gl_points[2 * i + 1] = v[1];
   }
-  
-  glMatrixMode (GL_MODELVIEW);
-  glTranslatef (0.5, 0.5, 0);
-  
-  glEnableClientState (GL_VERTEX_ARRAY);
-  glDisableClientState (GL_TEXTURE_COORD_ARRAY);
-  glVertexPointer (2, GL_SHORT, 0, gl_points);
-  glDrawArrays (GL_POINTS, 0, count);
-  
-  free (gl_points);
-  
-  glLoadIdentity ();
-  
+
   return 0;
 }
 
 
 static GLint
-texture_internalformat(Display *dpy)
+texture_internalformat (Display *dpy)
 {
 #ifdef HAVE_JWZGLES
-  return dpy->screen->pixel_format;
+  return dpy->pixel_format;
 #else
   return GL_RGBA;
 #endif
 }
 
-static GLenum gl_pixel_type(const Display *dpy)
+static GLenum
+gl_pixel_type (const Display *dpy)
 {
-  return dpy->screen->pixel_type;
+  return dpy->pixel_type;
 }
 
 static void
 clear_texture (Display *dpy)
 {
   glTexImage2D (dpy->gl_texture_target, 0, texture_internalformat(dpy), 0, 0,
-                0, dpy->screen->pixel_format, gl_pixel_type (dpy), NULL);
+                0, dpy->pixel_format, gl_pixel_type (dpy), NULL);
 }
 
-static void set_white (void)
+static void
+set_white (void)
 {
 #ifdef HAVE_JWZGLES
   glColor4f (1, 1, 1, 1);
@@ -845,6 +686,51 @@ static void set_white (void)
 }
 
 
+void
+jwxyz_gl_flush (Display *dpy)
+{
+  if (!dpy->queue_size)
+    return;
+
+  // jwxyz_bind_drawable() and jwxyz_gl_set_gc() is called in enqueue().
+
+  glEnableClientState (GL_COLOR_ARRAY);
+  glEnableClientState (GL_VERTEX_ARRAY);
+  glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+
+  // TODO: Use glColor instead of glColorPointer if there's just one color.
+  // TODO: Does OpenGL use both GL_COLOR_ARRAY and glColor at the same time?
+  set_white();
+
+  Bool shifted = dpy->queue_mode == GL_POINTS || dpy->queue_mode == GL_LINES;
+  if (shifted) {
+    glMatrixMode (GL_MODELVIEW);
+    glTranslatef (0.5, 0.5, 0);
+  }
+
+  glColorPointer (4, GL_UNSIGNED_BYTE, 0, dpy->queue_color);
+  glVertexPointer (2, GL_SHORT, 0, dpy->queue_vertex);
+  glDrawArrays (dpy->queue_mode, 0, dpy->queue_size);
+
+  // TODO: This is right, right?
+  if (dpy->queue_mode == GL_LINES && dpy->queue_line_cap) {
+    Assert (!(dpy->queue_size % 2), "bad count for GL_LINES");
+    glColorPointer (4, GL_UNSIGNED_BYTE, sizeof(GLubyte) * 8,
+                    dpy->queue_color);
+    glVertexPointer (2, GL_SHORT, sizeof(GLshort) * 4, dpy->queue_vertex + 2);
+    glDrawArrays (GL_POINTS, 0, dpy->queue_size / 2);
+  }
+
+  if (shifted)
+    glLoadIdentity ();
+
+  glDisableClientState (GL_COLOR_ARRAY);
+  glDisableClientState (GL_VERTEX_ARRAY);
+
+  dpy->queue_size = 0;
+}
+
+
 void
 jwxyz_gl_copy_area_read_tex_image (Display *dpy, unsigned src_height,
                                    int src_x, int src_y,
@@ -873,7 +759,7 @@ jwxyz_gl_copy_area_read_tex_image (Display *dpy, unsigned src_height,
                       src_x, src_height - src_y - height, width, height, 0);
   } else {
     glTexImage2D (dpy->gl_texture_target, 0, internalformat, tex_w, tex_h,
-                  0, dpy->screen->pixel_format, gl_pixel_type(dpy), NULL);
+                  0, dpy->pixel_format, gl_pixel_type(dpy), NULL);
     glCopyTexSubImage2D (dpy->gl_texture_target, 0, 0, 0,
                          src_x, src_height - src_y - height, width, height);
   }
@@ -884,7 +770,7 @@ jwxyz_gl_copy_area_write_tex_image (Display *dpy, GC gc, int src_x, int src_y,
                                     unsigned int width, unsigned int height,
                                     int dst_x, int dst_y)
 {
-  Assert(gc->gcv.function == GXcopy, "XCopyArea: Unknown function");
+  jwxyz_gl_set_gc (dpy, gc);
 
   /* TODO: Copy-pasted from read_tex_image. */
   unsigned tex_w = width, tex_h = height;
@@ -967,82 +853,11 @@ jwxyz_gl_copy_area_read_pixels (Display *dpy, Drawable src, Drawable dst,
 }
 
 
-#if 0
-// TODO: Make sure offset works in super-sampled mode.
-static void
-adjust_point_for_line (GC gc, CGPoint *p)
-{
-  // Here's the authoritative discussion on how X draws lines:
-  // http://www.x.org/releases/current/doc/xproto/x11protocol.html#requests:CreateGC:line-width
-  if (gc->gcv.line_width <= 1) {
-    /* Thin lines are "drawn using an unspecified, device-dependent
-       algorithm", but seriously though, Bresenham's algorithm. Bresenham's
-       algorithm runs to and from pixel centers.
-
-       There's a few screenhacks (Maze, at the very least) that set line_width
-       to 1 when it probably should be set to 0, so it's line_width <= 1
-       instead of < 1.
-     */
-    p->x += 0.5;
-    p->y -= 0.5;
-  } else {
-    /* Thick lines OTOH run from the upper-left corners of pixels. This means
-       that a horizontal thick line of width 1 straddles two scan lines.
-       Aliasing requires one of these scan lines be chosen; the following
-       nudges the point so that the right choice is made. */
-    p->y -= 1e-3;
-  }
-}
-#endif
-
-
-int
-XDrawLine (Display *dpy, Drawable d, GC gc, int x1, int y1, int x2, int y2)
-{
-  // TODO: XDrawLine == XDrawSegments(nlines == 1), also in jwxyz.m
-  XSegment segment;
-  segment.x1 = x1;
-  segment.y1 = y1;
-  segment.x2 = x2;
-  segment.y2 = y2;
-  XDrawSegments (dpy, d, gc, &segment, 1);
-
-  // when drawing a zero-length line, obey line-width and cap-style.
-/* if (x1 == x2 && y1 == y2) {
-    int w = gc->gcv.line_width;
-    x1 -= w/2;
-    y1 -= w/2;
-    if (gc->gcv.line_width > 1 && gc->gcv.cap_style == CapRound)
-      return XFillArc (dpy, d, gc, x1, y1, w, w, 0, 360*64);
-    else {
-      if (!w)
-        w = 1; // Actually show zero-length lines.
-      return XFillRectangle (dpy, d, gc, x1, y1, w, w);
-    }
-  }
-
-  CGPoint p = point_for_line (d, gc, x1, y1);
-
-  push_fg_gc (dpy, d, gc, NO);
-
-  CGContextRef cgc = d->cgc;
-  set_line_mode (cgc, &gc->gcv);
-  CGContextBeginPath (cgc);
-  CGContextMoveToPoint (cgc, p.x, p.y);
-  p = point_for_line(d, gc, x2, y2);
-  CGContextAddLineToPoint (cgc, p.x, p.y);
-  CGContextStrokePath (cgc);
-  pop_gc (d, gc);
-  invalidate_drawable_cache (d); */
-  return 0;
-}
-
-int
-XDrawLines (Display *dpy, Drawable d, GC gc, XPoint *points, int count,
-            int mode)
+static int
+DrawLines (Display *dpy, Drawable d, GC gc, XPoint *points, int count,
+           int mode)
 {
-  jwxyz_bind_drawable (dpy, dpy->main_window, d);
-  set_fg_gc (dpy, gc);
+  set_fg_gc (dpy, d, gc);
 
   /* TODO: Thick lines
    * Zero-length line segments
@@ -1085,84 +900,121 @@ XDrawLines (Display *dpy, Drawable d, GC gc, XPoint *points, int count,
 }
 
 
-int
-XDrawSegments (Display *dpy, Drawable d, GC gc, XSegment *segments, int count)
+// Turn line segment into parallelogram based on line_width
+//
+// TODO: Fix epicycle hack with large thickness, and truchet line segment ends
+//
+static void drawThickLine(int line_width, XSegment *segments)
 {
-  jwxyz_bind_drawable (dpy, dpy->main_window, d);
-  set_fg_gc (dpy, gc);
-  
-  /* TODO: Thick lines. */
+    double dx, dy, di, m, angle;
+    int sx1, sx2, sy1, sy2;
+
+    sx1 = segments->x1;
+    sy1 = segments->y1;
+    sx2 = segments->x2;
+    sy2 = segments->y2;
+
+    dx = sx1 - sx2;
+    dy = sy1 - sy2;
+    di = sqrt(dx * dx + dy * dy);
+    dx = dx / di;
+    dy = dy / di;
+    m = dy / dx;
+
+    angle = atan(m); 
+
+    float sn = sin(angle);
+    float cs = cos(angle);
+    float line_width_f = (float) line_width;
+
+    float wsn = line_width_f * (sn/2);
+    float csn = line_width_f * (cs/2);
+
+    float x3 = sx1 - wsn;
+    float y3 = sy1 + csn;
+    float x4 = sx1 + wsn;
+    float y4 = sy1 - csn;
+
+    float x5 = sx2 - wsn;
+    float y5 = sy2 + csn;
+    float x6 = sx2 + wsn;
+    float y6 = sy2 - csn;
+
+    GLfloat coords[4][2] =
+    {
+      {x3, y3},
+      {x4, y4},
+      {x6, y6},
+      {x5, y5}
+    };
+
+    glEnableClientState (GL_VERTEX_ARRAY);
+    glVertexPointer (2, GL_FLOAT, 0, coords);
+    jwxyz_assert_gl ();
+    glDrawArrays (GL_TRIANGLE_FAN, 0, 4);
+    jwxyz_assert_gl ();
+}
+
+
+static int
+DrawSegments (Display *dpy, Drawable d, GC gc, XSegment *segments, int count)
+{
+  /* TODO: Caps on thick lines. */
   /* Thin lines <= 1px are offset by +0.5; thick lines are not. */
-  
-  glMatrixMode (GL_MODELVIEW);
-  glTranslatef (0.5, 0.5, 0);
 
-  glEnableClientState (GL_VERTEX_ARRAY);
-  glDisableClientState (GL_TEXTURE_COORD_ARRAY);
-  
-  Assert (sizeof(XSegment) == sizeof(short) * 4, "XDrawSegments: Data alignment mix-up."); // TODO: Static assert here.
-  Assert (sizeof(GLshort) == sizeof(short), "XDrawSegments: Data alignment mix-up."); // TODO: Static assert here.
-  Assert (offsetof(XSegment, x1) == 0, "XDrawSegments: Data alignment mix-up.");
-  Assert (offsetof(XSegment, x2) == 4, "XDrawSegments: Data alignment mix-up.");
-  glVertexPointer (2, GL_SHORT, 0, segments);
-  glDrawArrays (GL_LINES, 0, count * 2);
-  
-  if (gc->gcv.cap_style != CapNotLast) {
-    glVertexPointer (2, GL_SHORT, sizeof(GLshort) * 4, (const GLshort *)segments + 2);
-    glDrawArrays (GL_POINTS, 0, count);
+  if (count == 1 && gc->gcv.line_width > 1) {
+    set_fg_gc (dpy, d, gc);
+    drawThickLine(gc->gcv.line_width,segments);
   }
-  
-  glLoadIdentity ();
-  
-/* CGRect wr = d->frame;
-  push_fg_gc (dpy, d, gc, NO);
-  set_line_mode (cgc, &gc->gcv);
-  CGContextBeginPath (cgc);
-  for (i = 0; i < count; i++) {
-    CGPoint p = point_for_line (d, gc, segments->x1, segments->y1);
-    CGContextMoveToPoint (cgc, p.x, p.y);
-    p = point_for_line (d, gc, segments->x2, segments->y2);
-    CGContextAddLineToPoint (cgc, p.x, p.y);
-    segments++;
+  else {
+    if (dpy->queue_line_cap != (gc->gcv.cap_style != CapNotLast))
+      jwxyz_gl_flush (dpy);
+    dpy->queue_line_cap = gc->gcv.cap_style != CapNotLast;
+
+    // TODO: Static assert here.
+    Assert (sizeof(XSegment) == sizeof(short) * 4 &&
+            sizeof(GLshort) == sizeof(short) &&
+            offsetof(XSegment, x1) == 0 &&
+            offsetof(XSegment, x2) == 4,
+            "XDrawSegments: Data alignment mix-up.");
+
+    memcpy (enqueue(dpy, d, gc, GL_LINES, count * 2), segments,
+            count * sizeof(XSegment));
   }
-  CGContextStrokePath (cgc);
-  pop_gc (d, gc);
-  invalidate_drawable_cache (d); */
+
   return 0;
 }
 
 
-int
-XClearWindow (Display *dpy, Window win)
+static int
+ClearWindow (Display *dpy, Window win)
 {
   Assert (win == dpy->main_window, "not a window");
-  const XRectangle *wr = jwxyz_frame (win);
-  /* TODO: Use glClear if there's no background pixmap. */
-  return XClearArea (dpy, win, 0, 0, wr->width, wr->height, 0);
-}
 
-unsigned long
-jwxyz_window_background (Display *dpy)
-{
-  return dpy->window_background;
+  jwxyz_gl_flush (dpy);
+  jwxyz_bind_drawable (dpy, win, win);
+
+  GLfloat color[4];
+  JWXYZ_QUERY_COLOR (dpy, dpy->window_background, 1.0f, color);
+
+  glClearColor (color[0], color[1], color[2], 1);
+  glClear (GL_COLOR_BUFFER_BIT);
+  return True;
 }
 
-int
-XSetWindowBackground (Display *dpy, Window w, unsigned long pixel)
+static unsigned long *
+window_background (Display *dpy)
 {
-  Assert (w == dpy->main_window, "not a window");
-  jwxyz_validate_pixel (dpy, pixel, visual_depth (NULL, NULL), False);
-  dpy->window_background = pixel;
-  return 0;
+  return &dpy->window_background;
 }
 
-void
-jwxyz_fill_rects (Display *dpy, Drawable d, GC gc,
-                  const XRectangle *rectangles, unsigned long nrectangles,
-                  unsigned long pixel)
+static void
+fill_rects (Display *dpy, Drawable d, GC gc,
+            const XRectangle *rectangles, unsigned long nrectangles,
+            unsigned long pixel)
 {
-  jwxyz_bind_drawable (dpy, dpy->main_window, d);
-  set_color_gc (dpy, gc, pixel);
+  set_color_gc (dpy, d, gc, pixel);
+
 /*
   glBegin(GL_QUADS);
   for (unsigned i = 0; i != nrectangles; ++i) {
@@ -1172,7 +1024,8 @@ jwxyz_fill_rects (Display *dpy, Drawable d, GC gc,
     glVertex2i(r->x + r->width, r->y + r->height);
     glVertex2i(r->x + r->width, r->y);
   }
-  glEnd(); */
+  glEnd();
+*/
   
   glEnableClientState (GL_VERTEX_ARRAY);
   glDisableClientState (GL_TEXTURE_COORD_ARRAY);
@@ -1198,23 +1051,11 @@ jwxyz_fill_rects (Display *dpy, Drawable d, GC gc,
 }
 
 
-int
-XClearArea (Display *dpy, Window win, int x, int y, int w, int h, Bool exp)
+static int
+FillPolygon (Display *dpy, Drawable d, GC gc,
+             XPoint *points, int npoints, int shape, int mode)
 {
-  Assert(win == dpy->main_window, "XClearArea: not a window");
-  Assert(!exp, "XClearArea: exposures unsupported");
-
-  jwxyz_fill_rect (dpy, win, 0, x, y, w, h, dpy->window_background);
-  return 0;
-}
-
-
-int
-XFillPolygon (Display *dpy, Drawable d, GC gc, 
-              XPoint *points, int npoints, int shape, int mode)
-{
-  jwxyz_bind_drawable (dpy, dpy->main_window, d);
-  set_fg_gc(dpy, gc);
+  set_fg_gc(dpy, d, gc);
   
   // TODO: Re-implement the GLU tesselation functions.
 
@@ -1232,36 +1073,36 @@ XFillPolygon (Display *dpy, Drawable d, GC gc,
 
   if (shape == Convex) {
 
-  GLshort *vertices = malloc(npoints * sizeof(GLshort) * 2); // TODO: Oh look, another unchecked malloc.
-  short v[2] = {0, 0};
+    GLshort *vertices = malloc(npoints * sizeof(GLshort) * 2); // TODO: Oh look, another unchecked malloc.
+    short v[2] = {0, 0};
   
-  for (unsigned i = 0; i < npoints; i++) {
-    next_point(v, points[i], mode);
-    vertices[2 * i] = v[0];
-    vertices[2 * i + 1] = v[1];
-  }
+    for (unsigned i = 0; i < npoints; i++) {
+      next_point(v, points[i], mode);
+      vertices[2 * i] = v[0];
+      vertices[2 * i + 1] = v[1];
+    }
 
-  glEnableClientState (GL_VERTEX_ARRAY);
-  glDisableClientState (GL_TEXTURE_COORD_ARRAY);
-  
-  glVertexPointer (2, GL_SHORT, 0, vertices);
-  glDrawArrays (GL_TRIANGLE_FAN, 0, npoints);
-  
-  free(vertices);
+    glEnableClientState (GL_VERTEX_ARRAY);
+    glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+
+    glVertexPointer (2, GL_SHORT, 0, vertices);
+    glDrawArrays (GL_TRIANGLE_FAN, 0, npoints);
+
+    free(vertices);
 
   } else if (shape == Nonconvex) {
 
-  // TODO: assert that x,y of first and last point match, as that is assumed
+    // TODO: assert that x,y of first and last point match, as that is assumed
 
-  linked_point *root;
-  root = (linked_point *) malloc( sizeof(linked_point) );
-  set_points_list(points,npoints,root);
-  traverse_points_list(root);
+    linked_point *root;
+    root = (linked_point *) malloc( sizeof(linked_point) );
+    set_points_list(points,npoints,root);
+    traverse_points_list(root);
 
   } else {
-    Assert((shape == Convex || shape == Nonconvex), "XFillPolygon: (TODO) Unimplemented shape");
+    Assert((shape == Convex || shape == Nonconvex),
+           "XFillPolygon: (TODO) Unimplemented shape");
   }
-  
 
   return 0;
 }
@@ -1285,13 +1126,42 @@ mod_neg(int a, unsigned b)
   return a < 0 ? (b - 1) - (-(a + 1) % b) : a % b;
 }
 
+/* TODO: Fill in arcs with line width > 1 */
+static int
+draw_arc (Display *dpy, Drawable d, GC gc, int x, int y,
+          unsigned int width, unsigned int height,
+          int angle1, int angle2, Bool fill_p)
+{
+    int gglw = gc->gcv.line_width;
+
+    if (fill_p || gglw <= 1) {
+        draw_arc_gl (dpy, d, gc, x, y, width, height, angle1, angle2, fill_p);
+    }
+    else {
+        int w1, w2, h1, h2, gglwh;
+        w1 = width + gglw;
+        h1 = height + gglw;
+        h2 = height - gglw;
+        w2 = width - gglw;
+        gglwh = gglw / 2;
+        int x1 = x - gglwh;
+        int x2 = x + gglwh;
+        int y1 = y - gglwh;
+        int y2 = y + gglwh;
+        //draw_arc_gl (dpy, d, gc, x, y, width, height, angle1, angle2, fill_p);
+        draw_arc_gl (dpy, d, gc, x1, y1, w1, h1, angle1, angle2, fill_p);
+        draw_arc_gl (dpy, d, gc, x2, y2, w2, h2, angle1, angle2, fill_p);
+    }
+    return 0;
+}
+
+
 int
-jwxyz_draw_arc (Display *dpy, Drawable d, GC gc, int x, int y,
-                unsigned int width, unsigned int height,
-                int angle1, int angle2, Bool fill_p)
+draw_arc_gl (Display *dpy, Drawable d, GC gc, int x, int y,
+          unsigned int width, unsigned int height,
+          int angle1, int angle2, Bool fill_p)
 {
-  jwxyz_bind_drawable (dpy, dpy->main_window, d);
-  set_fg_gc(dpy, gc);
+  set_fg_gc(dpy, d, gc);
 
   /* Let's say the number of line segments needed to make a convincing circle is
      4*sqrt(radius). (But these arcs aren't necessarily circular arcs...) */
@@ -1415,22 +1285,22 @@ jwxyz_draw_arc (Display *dpy, Drawable d, GC gc, int x, int y,
 }
 
 
-XGCValues *
-jwxyz_gc_gcv (GC gc)
+static XGCValues *
+gc_gcv (GC gc)
 {
   return &gc->gcv;
 }
 
 
-unsigned int
-jwxyz_gc_depth (GC gc)
+static unsigned int
+gc_depth (GC gc)
 {
   return gc->depth;
 }
 
 
-GC
-XCreateGC (Display *dpy, Drawable d, unsigned long mask, XGCValues *xgcv)
+static GC
+CreateGC (Display *dpy, Drawable d, unsigned long mask, XGCValues *xgcv)
 {
   struct jwxyz_GC *gc = (struct jwxyz_GC *) calloc (1, sizeof(*gc));
   gc->depth = jwxyz_drawable_depth (d);
@@ -1441,8 +1311,8 @@ XCreateGC (Display *dpy, Drawable d, unsigned long mask, XGCValues *xgcv)
 }
 
 
-int
-XFreeGC (Display *dpy, GC gc)
+static int
+FreeGC (Display *dpy, GC gc)
 {
   if (gc->gcv.font)
     XUnloadFont (dpy, gc->gcv.font);
@@ -1461,54 +1331,10 @@ XFreeGC (Display *dpy, GC gc)
 }
 
 
-/*
-static void
-flipbits (unsigned const char *in, unsigned char *out, int length)
-{
-  static const unsigned char table[256] = {
-    0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 
-    0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, 
-    0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 
-    0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 
-    0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 
-    0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, 
-    0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 
-    0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, 
-    0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 
-    0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, 
-    0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 
-    0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, 
-    0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 
-    0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, 
-    0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 
-    0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 
-    0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 
-    0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, 
-    0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 
-    0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, 
-    0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 
-    0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, 
-    0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 
-    0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, 
-    0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 
-    0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, 
-    0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
-    0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, 
-    0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 
-    0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, 
-    0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 
-    0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
-  };
-  while (length-- > 0)
-    *out++ = table[*in++];
-}
-*/
-
-
-int
-XPutImage (Display *dpy, Drawable d, GC gc, XImage *ximage,
-           int src_x, int src_y, int dest_x, int dest_y,
-           unsigned int w, unsigned int h)
+static int
+PutImage (Display *dpy, Drawable d, GC gc, XImage *ximage,
+          int src_x, int src_y, int dest_x, int dest_y,
+          unsigned int w, unsigned int h)
 {
   jwxyz_assert_display (dpy);
  
@@ -1557,181 +1383,169 @@ XPutImage (Display *dpy, Drawable d, GC gc, XImage *ximage,
   if (jwxyz_dumb_drawing_mode(dpy, d, gc, dest_x, dest_y, w, h))
     return 0;
 
+  jwxyz_gl_flush (dpy);
   jwxyz_bind_drawable (dpy, dpy->main_window, d);
+  jwxyz_gl_set_gc (dpy, gc);
+
   int bpl = ximage->bytes_per_line;
   int bpp = ximage->bits_per_pixel;
-  /* int bsize = bpl * h; */
-  char *data = ximage->data;
 
-/*
-  CGRect r;
-  r.origin.x = wr->x + dest_x;
-  r.origin.y = wr->y + wr->height - dest_y - h;
-  r.size.width = w;
-  r.size.height = h;
-*/
+  char *tex_data;
+  unsigned src_w;
+  GLint tex_internalformat;
+  GLenum tex_format, tex_type;
 
-  Assert (gc->gcv.function == GXcopy, "XPutImage: (TODO) GC function not supported");
-  Assert (!gc->gcv.clip_mask, "XPutImage: (TODO) GC clip mask not supported");
-  
   if (bpp == 32) {
-
-    /* Take advantage of the fact that it's ok for (bpl != w * bpp)
-       to create a CGImage from a sub-rectagle of the XImage.
-     */
-    data += (src_y * bpl) + (src_x * 4);
+    tex_data = ximage->data + src_y * bpl + (src_x * 4);
 
     jwxyz_assert_display(dpy);
     
     /* There probably won't be any hacks that do this, but... */
     Assert (!(bpl % 4), "XPutImage: bytes_per_line not divisible by four.");
     
-    unsigned src_w = bpl / 4;
+    tex_internalformat = texture_internalformat(dpy);
+    tex_format = dpy->pixel_format;
+    tex_type = gl_pixel_type(dpy);
 
     /* GL_UNPACK_ROW_LENGTH is not allowed to be negative. (sigh) */
 # ifndef HAVE_JWZGLES
-    glPixelStorei (GL_UNPACK_ROW_LENGTH, src_w);
     src_w = w;
+    glPixelStorei (GL_UNPACK_ROW_LENGTH, src_w);
+# else
+    src_w = bpl / 4;
 # endif
 
-    glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
+    // glPixelStorei (GL_UNPACK_ALIGNMENT, 4); // Probably unnecessary.
 
-# if 1 // defined HAVE_JWZGLES
-    // Regular OpenGL uses GL_TEXTURE_RECTANGLE_EXT in place of GL_TEXTURE_2D.
-    // TODO: Make use of OES_draw_texture.
-    // TODO: Coords might be wrong; things might be upside-down or backwards
-    //       or whatever.
-
-    unsigned tex_w = src_w, tex_h = h;
-    if (!dpy->gl_texture_npot_p) {
-      tex_w = to_pow2(tex_w);
-      tex_h = to_pow2(tex_h);
-    }
+    set_white ();
+  } else {
+    Assert (bpp == 1, "expected 1 or 32 bpp");
+    Assert ((src_x % 8) == 0,
+            "XPutImage with non-byte-aligned 1bpp X offset not implemented");
 
-    GLint internalformat = texture_internalformat(dpy);
+    const char *src_data = ximage->data + src_y * bpl + (src_x / 8);
+    unsigned w8 = (w + 7) / 8;
 
-    glBindTexture (dpy->gl_texture_target, dpy->rect_texture);
+    src_w = w8 * 8;
 
-    if (tex_w == src_w && tex_h == h) {
-      glTexImage2D (dpy->gl_texture_target, 0, internalformat, tex_w, tex_h,
-                    0, dpy->screen->pixel_format, gl_pixel_type(dpy), data);
-    } else {
-      // TODO: Sampling the last row might be a problem if src_x != 0.
-      glTexImage2D (dpy->gl_texture_target, 0, internalformat, tex_w, tex_h,
-                    0, dpy->screen->pixel_format, gl_pixel_type(dpy), NULL);
-      glTexSubImage2D (dpy->gl_texture_target, 0, 0, 0, src_w, h,
-                       dpy->screen->pixel_format, gl_pixel_type(dpy), data);
+    tex_data = malloc(src_w * h);
+
+    uint32_t *data_out = (uint32_t *)tex_data;
+    for(unsigned y = h; y; --y) {
+      for(unsigned x = 0; x != w8; ++x) {
+        // TODO: Does big endian work here?
+        uint8_t byte = src_data[x];
+        uint32_t word = byte;
+        word = (word & 0x3) | ((word & 0xc) << 14);
+        word = (word & 0x00010001) | ((word & 0x00020002) << 7);
+        data_out[x << 1] = (word << 8) - word;
+
+        word = byte >> 4;
+        word = (word & 0x3) | ((word & 0xc) << 14);
+        word = (word & 0x00010001) | ((word & 0x00020002) << 7);
+        data_out[(x << 1) | 1] = (word << 8) - word;
+      }
+      src_data += bpl;
+      data_out += src_w / 4;
     }
-    
-    set_white ();
-    // glEnable (dpy->gl_texture_target);
-    // glColor4f (0.5, 0, 1, 1);
-    glEnable (dpy->gl_texture_target);
-    glEnableClientState (GL_VERTEX_ARRAY);
-    glEnableClientState (GL_TEXTURE_COORD_ARRAY);
 
-    // TODO: Why are these ever turned on in the first place?
-    glDisableClientState (GL_COLOR_ARRAY);
-    glDisableClientState (GL_NORMAL_ARRAY);
-    // glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+    tex_internalformat = GL_LUMINANCE;
+    tex_format = GL_LUMINANCE;
+    tex_type = GL_UNSIGNED_BYTE;
 
-    GLfloat vertices[4][2] =
-    {
-      {dest_x, dest_y},
-      {dest_x, dest_y + h},
-      {dest_x + w, dest_y + h},
-      {dest_x + w, dest_y}
-    };
+    // glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
+
+    set_color (dpy, gc->gcv.foreground, gc->depth, gc->gcv.alpha_allowed_p);
+    // TODO: Deal with the background color.
+  }
+
+# if 1 // defined HAVE_JWZGLES
+  // Regular OpenGL uses GL_TEXTURE_RECTANGLE_EXT in place of GL_TEXTURE_2D.
+  // TODO: Make use of OES_draw_texture.
+
+  unsigned tex_w = src_w, tex_h = h;
+  if (!dpy->gl_texture_npot_p) {
+    tex_w = to_pow2(tex_w);
+    tex_h = to_pow2(tex_h);
+  }
 
-    GLfloat texcoord_w, texcoord_h;
+  glBindTexture (dpy->gl_texture_target, dpy->rect_texture);
+
+  // A fun project: reimplement xshm.c by means of a PBO using
+  // GL_MAP_UNSYNCHRONIZED_BIT.
+
+  // TODO: Would using glTexSubImage2D exclusively be faster?
+  if (tex_w == src_w && tex_h == h) {
+    glTexImage2D (dpy->gl_texture_target, 0, tex_internalformat, tex_w, tex_h,
+                  0, tex_format, tex_type, tex_data);
+  } else {
+    // TODO: Sampling the last row might be a problem if src_x != 0.
+    glTexImage2D (dpy->gl_texture_target, 0, tex_internalformat, tex_w, tex_h,
+                  0, tex_format, tex_type, NULL);
+    glTexSubImage2D (dpy->gl_texture_target, 0, 0, 0, src_w, h,
+                     tex_format, tex_type, tex_data);
+  }
+
+  if (bpp == 1)
+    free(tex_data);
+
+  // TODO: This looks a lot like jwxyz_gl_draw_image. Refactor.
+
+  // glEnable (dpy->gl_texture_target);
+  // glColor4f (0.5, 0, 1, 1);
+  glEnable (dpy->gl_texture_target);
+  glEnableClientState (GL_VERTEX_ARRAY);
+  glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+
+  // TODO: Why are these ever turned on in the first place?
+  glDisableClientState (GL_COLOR_ARRAY);
+  glDisableClientState (GL_NORMAL_ARRAY);
+  // glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+
+  GLfloat vertices[4][2] =
+  {
+    {dest_x, dest_y},
+    {dest_x, dest_y + h},
+    {dest_x + w, dest_y + h},
+    {dest_x + w, dest_y}
+  };
+
+  GLfloat texcoord_w, texcoord_h;
 #  ifndef HAVE_JWZGLES
-    if (dpy->gl_texture_target == GL_TEXTURE_RECTANGLE_EXT) {
-      texcoord_w = w;
-      texcoord_h = h;
-    } else
+  if (dpy->gl_texture_target == GL_TEXTURE_RECTANGLE_EXT) {
+    texcoord_w = w;
+    texcoord_h = h;
+  } else
 #  endif /* HAVE_JWZGLES */
-    {
-      texcoord_w = (double)w / tex_w;
-      texcoord_h = (double)h / tex_h;
-    }
-
-    GLfloat tex_coords[4][2];
-    tex_coords[0][0] = 0;
-    tex_coords[0][1] = 0;
-    tex_coords[1][0] = 0;
-    tex_coords[1][1] = texcoord_h;
-    tex_coords[2][0] = texcoord_w;
-    tex_coords[2][1] = texcoord_h;
-    tex_coords[3][0] = texcoord_w;
-    tex_coords[3][1] = 0;
-
-    glVertexPointer (2, GL_FLOAT, 0, vertices);
-    glTexCoordPointer (2, GL_FLOAT, 0, tex_coords);
-
-    // Respect the alpha channel in the XImage if we're using alpha.
-    if (gc->gcv.alpha_allowed_p) {
-      glEnable (GL_BLEND);
-      glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-    }
+  {
+    texcoord_w = (double)w / tex_w;
+    texcoord_h = (double)h / tex_h;
+  }
 
-    glDrawArrays (GL_TRIANGLE_FAN, 0, 4);
+  GLfloat tex_coords[4][2];
+  tex_coords[0][0] = 0;
+  tex_coords[0][1] = 0;
+  tex_coords[1][0] = 0;
+  tex_coords[1][1] = texcoord_h;
+  tex_coords[2][0] = texcoord_w;
+  tex_coords[2][1] = texcoord_h;
+  tex_coords[3][0] = texcoord_w;
+  tex_coords[3][1] = 0;
 
-    if (gc->gcv.alpha_allowed_p)
-      glDisable (GL_BLEND);
+  glVertexPointer (2, GL_FLOAT, 0, vertices);
+  glTexCoordPointer (2, GL_FLOAT, 0, tex_coords);
+  glDrawArrays (GL_TRIANGLE_FAN, 0, 4);
 
-//  clear_texture();
-    glDisable (dpy->gl_texture_target);
+//clear_texture();
+  glDisable (dpy->gl_texture_target);
 # else
-    glRasterPos2i (dest_x, dest_y);
-    glPixelZoom (1, -1);
-    jwxyz_assert_display (dpy);
-    glDrawPixels (w, h, dpy->screen->pixel_format, gl_pixel_type(dpy), data);
+  glRasterPos2i (dest_x, dest_y);
+  glPixelZoom (1, -1);
+  jwxyz_assert_display (dpy);
+  glDrawPixels (w, h, dpy->pixel_format, gl_pixel_type(dpy), data);
 # endif
-  } else {   // (bpp == 1)
-
-    // Assert(FALSE, "XPutImage: TODO");
-    // Check out ximage_(get|put)pixel_1
-    
-#if 0
-    /* To draw a 1bpp image, we use it as a mask and fill two rectangles.
-
-       #### However, the bit order within a byte in a 1bpp XImage is
-            the wrong way around from what Quartz expects, so first we
-            have to copy the data to reverse it.  Shit!  Maybe it
-            would be worthwhile to go through the hacks and #ifdef
-            each one that diddles 1bpp XImage->data directly...
-     */
-    Assert ((src_x % 8) == 0,
-            "XPutImage with non-byte-aligned 1bpp X offset not implemented");
 
-    data += (src_y * bpl) + (src_x / 8);   // move to x,y within the data
-    unsigned char *flipped = (unsigned char *) malloc (bsize);
-
-    flipbits ((unsigned char *) data, flipped, bsize);
-
-    CGDataProviderRef prov = 
-      CGDataProviderCreateWithData (NULL, flipped, bsize, NULL);
-    CGImageRef mask = CGImageMaskCreate (w, h, 
-                                         1, bpp, bpl,
-                                         prov,
-                                         NULL,  /* decode[] */
-                                         GL_FALSE); /* interpolate */
-    push_fg_gc (dpy, d, gc, GL_TRUE);
-
-    CGContextFillRect (cgc, r);                                // foreground color
-    CGContextClipToMask (cgc, r, mask);
-    set_color (dpy, cgc, gc->gcv.background, gc->depth, GL_FALSE, GL_TRUE);
-    CGContextFillRect (cgc, r);                                // background color
-    pop_gc (d, gc);
-
-    free (flipped);
-    CGDataProviderRelease (prov);
-    CGImageRelease (mask);
-#endif
-  }
   jwxyz_assert_gl ();
-  invalidate_drawable_cache (d);
 
   return 0;
 }
@@ -1740,17 +1554,18 @@ XPutImage (Display *dpy, Drawable d, GC gc, XImage *ximage,
 /* #### Twang calls XGetImage on the window intending to get a
    buffer full of black.  This is returning a buffer full of white
    instead of black for some reason. */
-XImage *
-XGetSubImage (Display *dpy, Drawable d, int x, int y,
-              unsigned int width, unsigned int height,
-              unsigned long plane_mask, int format,
-              XImage *dest_image, int dest_x, int dest_y)
+static XImage *
+GetSubImage (Display *dpy, Drawable d, int x, int y,
+             unsigned int width, unsigned int height,
+             unsigned long plane_mask, int format,
+             XImage *dest_image, int dest_x, int dest_y)
 {
   Assert ((width  < 65535), "improbably large width");
   Assert ((height < 65535), "improbably large height");
   Assert ((x < 65535 && x > -65535), "improbably large x");
   Assert ((y < 65535 && y > -65535), "improbably large y");
 
+  jwxyz_gl_flush (dpy);
   jwxyz_bind_drawable (dpy, dpy->main_window, d);
   
   // TODO: What if this reads off the edge? What is supposed to happen?
@@ -1785,7 +1600,7 @@ XGetSubImage (Display *dpy, Drawable d, int x, int y,
     uint32_t *dest_data = (uint32_t *)dest_image->data + pixels_per_line * dest_y + dest_x;
     
     glReadPixels (x, jwxyz_frame (d)->height - (y + height), width, height,
-                  dpy->screen->pixel_format, gl_pixel_type(dpy), dest_data);
+                  dpy->pixel_format, gl_pixel_type(dpy), dest_data);
 
     /* Flip this upside down. :( */
     uint32_t *top = dest_data;
@@ -1817,178 +1632,6 @@ XGetSubImage (Display *dpy, Drawable d, int x, int y,
 }
 
 
-/* Returns a transformation matrix to do rotation as per the provided
-   EXIF "Orientation" value.
- */
-/*
-static CGAffineTransform
-exif_rotate (int rot, CGSize rect)
-{
-  CGAffineTransform trans = CGAffineTransformIdentity;
-  switch (rot) {
-  case 2:              // flip horizontal
-    trans = CGAffineTransformMakeTranslation (rect.width, 0);
-    trans = CGAffineTransformScale (trans, -1, 1);
-    break;
-
-  case 3:              // rotate 180
-    trans = CGAffineTransformMakeTranslation (rect.width, rect.height);
-    trans = CGAffineTransformRotate (trans, M_PI);
-    break;
-
-  case 4:              // flip vertical
-    trans = CGAffineTransformMakeTranslation (0, rect.height);
-    trans = CGAffineTransformScale (trans, 1, -1);
-    break;
-
-  case 5:              // transpose (UL-to-LR axis)
-    trans = CGAffineTransformMakeTranslation (rect.height, rect.width);
-    trans = CGAffineTransformScale (trans, -1, 1);
-    trans = CGAffineTransformRotate (trans, 3 * M_PI / 2);
-    break;
-
-  case 6:              // rotate 90
-    trans = CGAffineTransformMakeTranslation (0, rect.width);
-    trans = CGAffineTransformRotate (trans, 3 * M_PI / 2);
-    break;
-
-  case 7:              // transverse (UR-to-LL axis)
-    trans = CGAffineTransformMakeScale (-1, 1);
-    trans = CGAffineTransformRotate (trans, M_PI / 2);
-    break;
-
-  case 8:              // rotate 270
-    trans = CGAffineTransformMakeTranslation (rect.height, 0);
-    trans = CGAffineTransformRotate (trans, M_PI / 2);
-    break;
-
-  default: 
-    break;
-  }
-
-  return trans;
-}
-*/
-
-void
-jwxyz_draw_NSImage_or_CGImage (Display *dpy, Drawable d, 
-                                Bool nsimg_p, void *img_arg,
-                               XRectangle *geom_ret, int exif_rotation)
-{
-  Assert (False, "jwxyz_draw_NSImage_or_CGImage: TODO stub");
-#if 0
-  CGImageRef cgi;
-# ifndef USE_IPHONE
-  CGImageSourceRef cgsrc;
-# endif // USE_IPHONE
-  NSSize imgr;
-
-  CGContextRef cgc = d->cgc;
-
-  if (nsimg_p) {
-
-    NSImage *nsimg = (NSImage *) img_arg;
-    imgr = [nsimg size];
-
-# ifndef USE_IPHONE
-    // convert the NSImage to a CGImage via the toll-free-bridging 
-    // of NSData and CFData...
-    //
-    NSData *nsdata = [NSBitmapImageRep
-                       TIFFRepresentationOfImageRepsInArray:
-                         [nsimg representations]];
-    CFDataRef cfdata = (CFDataRef) nsdata;
-    cgsrc = CGImageSourceCreateWithData (cfdata, NULL);
-    cgi = CGImageSourceCreateImageAtIndex (cgsrc, 0, NULL);
-# else  // USE_IPHONE
-    cgi = nsimg.CGImage;
-# endif // USE_IPHONE
-
-  } else {
-    cgi = (CGImageRef) img_arg;
-    imgr.width  = CGImageGetWidth (cgi);
-    imgr.height = CGImageGetHeight (cgi);
-  }
-
-  Bool rot_p = (exif_rotation >= 5);
-
-  if (rot_p)
-    imgr = NSMakeSize (imgr.height, imgr.width);
-
-  CGRect winr = d->frame;
-  float rw = winr.size.width  / imgr.width;
-  float rh = winr.size.height / imgr.height;
-  float r = (rw < rh ? rw : rh);
-
-  CGRect dst, dst2;
-  dst.size.width  = imgr.width  * r;
-  dst.size.height = imgr.height * r;
-  dst.origin.x = (winr.size.width  - dst.size.width)  / 2;
-  dst.origin.y = (winr.size.height - dst.size.height) / 2;
-
-  dst2.origin.x = dst2.origin.y = 0;
-  if (rot_p) {
-    dst2.size.width = dst.size.height; 
-    dst2.size.height = dst.size.width;
-  } else {
-    dst2.size = dst.size;
-  }
-
-  // Clear the part not covered by the image to background or black.
-  //
-  if (d->type == WINDOW)
-    XClearWindow (dpy, d);
-  else {
-    jwxyz_fill_rect (dpy, d, 0, 0, 0, winr.size.width, winr.size.height,
-                     drawable_depth (d) == 1 ? 0 : BlackPixel(dpy,0));
-  }
-
-  CGAffineTransform trans = 
-    exif_rotate (exif_rotation, rot_p ? dst2.size : dst.size);
-
-  CGContextSaveGState (cgc);
-  CGContextConcatCTM (cgc, 
-                      CGAffineTransformMakeTranslation (dst.origin.x,
-                                                        dst.origin.y));
-  CGContextConcatCTM (cgc, trans);
-  //Assert (CGImageGetColorSpace (cgi) == dpy->colorspace, "bad colorspace");
-  CGContextDrawImage (cgc, dst2, cgi);
-  CGContextRestoreGState (cgc);
-
-# ifndef USE_IPHONE
-  if (nsimg_p) {
-    CFRelease (cgsrc);
-    CGImageRelease (cgi);
-  }
-# endif // USE_IPHONE
-
-  if (geom_ret) {
-    geom_ret->x = dst.origin.x;
-    geom_ret->y = dst.origin.y;
-    geom_ret->width  = dst.size.width;
-    geom_ret->height = dst.size.height;
-  }
-
-  invalidate_drawable_cache (d);
-#endif
-}
-
-#ifndef HAVE_JWZGLES
-
-/*
-static void
-create_rectangle_texture (GLuint *texture)
-{
-  glGenTextures(1, texture);
-  glBindTexture(GL_TEXTURE_RECTANGLE_EXT, *texture);
-  glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-  glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-}
-*/
-
-#endif
-
-
 #if 0
 static Pixmap
 copy_pixmap (Display *dpy, Pixmap p)
@@ -2021,91 +1664,20 @@ copy_pixmap (Display *dpy, Pixmap p)
 #endif
 
 
-int
-jwxyz_draw_string (Display *dpy, Drawable d, GC gc, int x, int y,
-                   const char *str, size_t len, int utf8_p)
+static int
+SetClipMask (Display *dpy, GC gc, Pixmap m)
 {
-  Font ff = gc->gcv.font;
-  XCharStruct cs;
-
-  char *data = 0;
-  jwxyz_render_text (dpy, jwxyz_native_font (ff), str, len, utf8_p, &cs, &data);
-  int w = cs.rbearing - cs.lbearing;
-  int h = cs.ascent + cs.descent;
-
-  if (w < 0 || h < 0) abort();
-  if (w == 0 || h == 0) {
-    if (data) free(data);
-    return 0;
-  }
-
-  XImage *img = XCreateImage (dpy, dpy->screen->visual, 32,
-                              ZPixmap, 0, data, w, h, 0, 0);
-
-  /* The image of text is a 32-bit image, in white.
-     Take the red channel for intensity and use that as alpha.
-     replace RGB with the GC's foreground color.
-     This expects that XPutImage respects alpha and only writes
-     the bits that are not masked out.
-     This also assumes that XPutImage expects ARGB.
+  Log ("TODO: No clip masks yet");
+  /* Protip: Do glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+     clearing just the stencil buffer in a packed depth/stencil arrangement is
+     slower than the above. Adreno recommends this, but other GPUs probably
+     benefit as well.
    */
-  {
-    char *s = data;
-    char *end = s + (w * h * 4);
-    uint8_t rgba[4];
-    jwxyz_query_color (dpy, gc->gcv.foreground, rgba);
-    while (s < end) {
-
-      s[3] = s[1];
-      s[0] = rgba[0];
-      s[1] = rgba[1];
-      s[2] = rgba[2];
-      s += 4;
-    }
-  }
-
-  {
-    Bool old_alpha = gc->gcv.alpha_allowed_p;
-    jwxyz_XSetAlphaAllowed (dpy, gc, True);
-    XPutImage (dpy, d, gc, img, 0, 0,
-               x + cs.lbearing,
-               y - cs.ascent,
-               w, h);
-    jwxyz_XSetAlphaAllowed (dpy, gc, old_alpha);
-    XDestroyImage (img);
-  }
-
-  return 0;
-}
-
-
-int
-XSetClipMask (Display *dpy, GC gc, Pixmap m)
-{
-//####  abort();
-/*
-  TODO
-
-  Assert (!!gc->gcv.clip_mask == !!gc->clip_mask, "GC clip mask mixup");
-
-  if (gc->gcv.clip_mask) {
-    XFreePixmap (dpy, gc->gcv.clip_mask);
-    CGImageRelease (gc->clip_mask);
-  }
-
-  gc->gcv.clip_mask = copy_pixmap (dpy, m);
-  if (gc->gcv.clip_mask)
-    gc->clip_mask =
-      CGBitmapContextCreateImage (gc->gcv.clip_mask->cgc);
-  else
-    gc->clip_mask = 0;
-*/
-  
   return 0;
 }
 
-int
-XSetClipOrigin (Display *dpy, GC gc, int x, int y)
+static int
+SetClipOrigin (Display *dpy, GC gc, int x, int y)
 {
   gc->gcv.clip_x_origin = x;
   gc->gcv.clip_y_origin = y;
@@ -2273,5 +1845,31 @@ void traverse_points_list(linked_point * root)
 }
 
 
+const struct jwxyz_vtbl gl_vtbl = {
+  root,
+  visual,
+  display_sources_data,
+
+  window_background,
+  draw_arc,
+  fill_rects,
+  gc_gcv,
+  gc_depth,
+  jwxyz_draw_string,
+
+  jwxyz_gl_copy_area,
+
+  DrawPoints,
+  DrawSegments,
+  CreateGC,
+  FreeGC,
+  ClearWindow,
+  SetClipMask,
+  SetClipOrigin,
+  FillPolygon,
+  DrawLines,
+  PutImage,
+  GetSubImage
+};
 
 #endif /* JWXYZ_GL -- entire file */
index a849b2a9b919af56b26b7d380492b8e8db54e153..97ab29c629ee473dea9263a86be08975ed7364ab 100644 (file)
@@ -70,6 +70,9 @@ XtDisplayToApplicationContext (Display *dpy)
 
 #define app_to_display(APP) ((Display *) (APP))
 
+#define DISPLAY_SOURCES_DATA(APP) \
+  JWXYZ_VTBL(app_to_display (APP))->display_sources_data (app_to_display (APP))
+
 
 struct jwxyz_sources_data {
   int fd_count;
@@ -124,7 +127,7 @@ XtIntervalId
 XtAppAddTimeOut (XtAppContext app, unsigned long msecs,
                  XtTimerCallbackProc cb, XtPointer closure)
 {
-  jwxyz_sources_data *td = display_sources_data (app_to_display (app));
+  jwxyz_sources_data *td = DISPLAY_SOURCES_DATA (app);
   XtIntervalId data = (XtIntervalId) calloc (1, sizeof(*data));
   double now = double_time();
   data->app = app;
@@ -149,7 +152,7 @@ XtAppAddTimeOut (XtAppContext app, unsigned long msecs,
 void
 XtRemoveTimeOut (XtIntervalId data)
 {
-  jwxyz_sources_data *td = display_sources_data (app_to_display (data->app));
+  jwxyz_sources_data *td = DISPLAY_SOURCES_DATA (data->app);
 
   LOGT("timer  0x%08lX: remove", (unsigned long) data);
   ASSERT_RET (data->refcount > 0, "already freed");
@@ -188,7 +191,7 @@ XtInputId
 XtAppAddInput (XtAppContext app, int fd, XtPointer flags,
                XtInputCallbackProc cb, XtPointer closure)
 {
-  jwxyz_sources_data *td = display_sources_data (app_to_display (app));
+  jwxyz_sources_data *td = DISPLAY_SOURCES_DATA (app);
   XtInputId data = (XtInputId) calloc (1, sizeof(*data));
   data->cb = cb;
   data->fd = fd;
@@ -210,7 +213,7 @@ XtAppAddInput (XtAppContext app, int fd, XtPointer flags,
 void
 XtRemoveInput (XtInputId id)
 {
-  jwxyz_sources_data *td = display_sources_data (app_to_display (id->app));
+  jwxyz_sources_data *td = DISPLAY_SOURCES_DATA (id->app);
 
   LOGI("source 0x%08lX %2d: remove", (unsigned long) id, id->fd);
   ASSERT_RET (id->refcount > 0, "sources corrupted");
@@ -343,7 +346,7 @@ XtAppPending (XtAppContext app)
 void
 XtAppProcessEvent (XtAppContext app, XtInputMask mask)
 {
-  jwxyz_sources_data *td = display_sources_data (app_to_display (app));
+  jwxyz_sources_data *td = DISPLAY_SOURCES_DATA (app);
   if (mask & XtIMAlternateInput)
     jwxyz_sources_run (td);
   if (mask & XtIMTimer)
index adcd5e9d82632f0bfde8f2182a6861cca1bf8bda..ef0a202e84865053dee695fde90ef31c547ad013 100644 (file)
@@ -49,7 +49,7 @@ typedef unsigned int KeyCode;
 typedef unsigned long Atom; /* Must be as large as a char *. */
 
 typedef struct jwxyz_Display           Display;
-typedef struct jwxyz_Screen            Screen;
+typedef struct jwxyz_Display           Screen;
 typedef struct jwxyz_Visual            Visual;
 typedef struct jwxyz_Drawable *                Drawable;
 typedef struct jwxyz_Colormap *                Colormap;
@@ -311,13 +311,11 @@ typedef struct jwxyz_linked_point linked_point;
 #define XHeightOfScreen(s) (DisplayHeight(DisplayOfScreen(s),0))
 #define XWidthMMOfScreen(s) (XDisplayWidthMM(DisplayOfScreen(s),0))
 #define XHeightMMOfScreen(s) (XDisplayHeightMM(DisplayOfScreen(s),0))
+#define XDefaultScreenOfDisplay(d) (d)
+#define XDisplayOfScreen(s) (s)
+#define XDisplayNumberOfScreen(s) 0
+#define XScreenNumberOfScreen(s) 0
 
-extern Window XRootWindow (Display *, int screen);
-extern Screen *XDefaultScreenOfDisplay (Display *);
-extern Visual *XDefaultVisualOfScreen (Screen *);
-extern Display *XDisplayOfScreen (Screen *);
-extern int XDisplayNumberOfScreen (Screen *);
-extern int XScreenNumberOfScreen (Screen *);
 extern int XDisplayWidth (Display *, int);
 extern int XDisplayHeight (Display *, int);
 extern int XDisplayWidthMM (Display *, int);
@@ -328,14 +326,9 @@ unsigned long XWhitePixelOfScreen(Screen *);
 unsigned long XCellsOfScreen(Screen *);
 
 extern int XDrawPoint (Display *, Drawable, GC, int x, int y);
-extern int XDrawPoints (Display *, Drawable, GC, XPoint *, int n, int mode);
-extern int XDrawSegments (Display *, Drawable, GC, XSegment *, int n);
 
-extern GC XCreateGC (Display *, Drawable, unsigned long mask, XGCValues *);
 extern int XChangeGC (Display *, GC, unsigned long mask, XGCValues *);
-extern int XFreeGC (Display *, GC);
 
-extern int XClearWindow (Display *, Window);
 extern int XClearArea (Display *, Window, int x, int y, int w, int h,Bool exp);
 extern int XSetWindowBackground (Display *, Window, unsigned long);
 extern Status XGetWindowAttributes (Display *, Window, XWindowAttributes *);
@@ -361,8 +354,6 @@ extern int XSetFunction (Display *, GC, int);
 extern int XSetSubwindowMode (Display *, GC, int);
 extern int XSetLineAttributes (Display *, GC, unsigned int line_width,
                                int line_style, int cap_style, int join_style);
-extern int XSetClipMask (Display *, GC, Pixmap);
-extern int XSetClipOrigin (Display *, GC, int x, int y);
 extern int jwxyz_XSetAlphaAllowed (Display *, GC, Bool);
 extern int jwxyz_XSetAntiAliasing (Display *, GC, Bool);
 
@@ -370,8 +361,6 @@ extern int XFlush (Display *);
 extern int XSync (Display *, Bool);
 extern int XFreeColors (Display *, Colormap, unsigned long *px, int n,
                         unsigned long planes);
-extern int XFillPolygon (Display *, Drawable, GC, 
-                         XPoint * points, int npoints, int shape, int mode);
 extern int XCopyArea (Display *, Drawable src, Drawable dest, GC, 
                       int src_x, int src_y, 
                       unsigned int width, unsigned int height, 
@@ -383,7 +372,6 @@ extern int XCopyPlane (Display *, Drawable, Drawable, GC,
                        unsigned long plane);
 
 extern int XDrawLine (Display *, Drawable, GC, int x1, int y1, int x2, int y2);
-extern int XDrawLines (Display *, Drawable, GC, XPoint *, int n, int mode);
 extern int XDrawArc (Display *, Drawable, GC, int x, int y, 
                      unsigned int width, unsigned int height,
                      int angle1, int angle2);
@@ -425,13 +413,6 @@ extern XImage *XSubImage (XImage *, int x, int y,
 extern unsigned long XGetPixel (XImage *, int x, int y);
 extern int XPutPixel (XImage *, int x, int y, unsigned long);
 extern int XDestroyImage (XImage *);
-extern int XPutImage (Display *, Drawable, GC, XImage *, 
-                      int src_x, int src_y, int dest_x, int dest_y,
-                      unsigned int w, unsigned int h);
-extern XImage *XGetSubImage (Display *dpy, Drawable d, int x, int y,
-                             unsigned int width, unsigned int height,
-                             unsigned long plane_mask, int format,
-                             XImage *dest_image, int dest_x, int dest_y);
 extern XImage *XGetImage (Display *, Drawable, int x, int y,
                           unsigned int w, unsigned int h,
                           unsigned long pm, int fmt);
@@ -498,6 +479,10 @@ extern Bool is_same_slope(linked_point * a);
 extern Bool is_an_ear(linked_point * a);
 extern Bool is_three_point_loop(linked_point * head);
 
+extern int draw_arc_gl(Display *dpy, Drawable d, GC gc, int x, int y,
+                   unsigned int width, unsigned int height,
+                   int angle1, int angle2, Bool fill_p);
+
 // Log()/Logv(), for debugging JWXYZ. Screenhacks should still use
 // fprintf(stderr, ...).
 extern void Log(const char *format, ...)
@@ -521,7 +506,6 @@ extern XtInputId XtAppAddInput (XtAppContext, int fd, XtPointer flags,
 extern void XtRemoveInput (XtInputId);
 extern XtInputMask XtAppPending (XtAppContext);
 extern void XtAppProcessEvent (XtAppContext, XtInputMask);
-extern struct jwxyz_sources_data *display_sources_data (Display *);
 
 // Some GLX stuff that also doesn't technically belong here...
 // from XScreenSaverGLView.m
@@ -551,7 +535,7 @@ extern void check_gl_error (const char *type);
 // Only utils/xft.c uses this, out of necessity.
 struct jwxyz_Visual {
   int class;           /* class of screen (monochrome, etc.) */
-  unsigned long red_mask, green_mask, blue_mask;       /* mask values */
+  unsigned long rgba_masks[4]; /* mask values */
 };
 
 struct jwxyz_XGCValues {
@@ -838,4 +822,81 @@ struct jwxyz_XChar2b {
   unsigned char byte2;
 };
 
+
+struct jwxyz_vtbl {
+  Window (*root) (Display *);
+  Visual *(*visual) (Display *);
+  struct jwxyz_sources_data *(*display_sources_data) (Display *);
+
+  unsigned long *(*window_background) (Display *);
+  int (*draw_arc) (Display *dpy, Drawable d, GC gc, int x, int y,
+                   unsigned int width, unsigned int height,
+                   int angle1, int angle2, Bool fill_p);
+  void (*fill_rects) (Display *dpy, Drawable d, GC gc,
+                      const XRectangle *rectangles,
+                      unsigned long nrects, unsigned long pixel);
+  XGCValues *(*gc_gcv) (GC gc);
+  unsigned int (*gc_depth) (GC gc);
+  int (*draw_string) (Display *dpy, Drawable d, GC gc, int x, int y,
+                      const char *str, size_t len, Bool utf8);
+
+  void (*copy_area) (Display *dpy, Drawable src, Drawable dst, GC gc,
+                     int src_x, int src_y,
+                     unsigned int width, unsigned int height,
+                     int dst_x, int dst_y);
+
+  int (*DrawPoints) (Display *, Drawable, GC, XPoint *, int n, int mode);
+  int (*DrawSegments) (Display *, Drawable, GC, XSegment *, int n);
+  GC (*CreateGC) (Display *, Drawable, unsigned long mask, XGCValues *);
+  int (*FreeGC) (Display *, GC);
+  int (*ClearWindow) (Display *, Window);
+  int (*SetClipMask) (Display *, GC, Pixmap);
+  int (*SetClipOrigin) (Display *, GC, int x, int y);
+  int (*FillPolygon) (Display *, Drawable, GC,
+                      XPoint * points, int npoints, int shape, int mode);
+  int (*DrawLines) (Display *, Drawable, GC, XPoint *, int n, int mode);
+
+  int (*PutImage) (Display *, Drawable, GC, XImage *,
+                    int src_x, int src_y, int dest_x, int dest_y,
+                    unsigned int w, unsigned int h);
+  XImage *(*GetSubImage) (Display *dpy, Drawable d, int x, int y,
+                          unsigned int width, unsigned int height,
+                          unsigned long plane_mask, int format,
+                          XImage *dest_image, int dest_x, int dest_y);
+};
+
+#define JWXYZ_VTBL(dpy) (*(struct jwxyz_vtbl **)(dpy))
+
+#define XRootWindow(dpy, screen) \
+  ((dpy) ? JWXYZ_VTBL(dpy)->root(dpy) : 0)
+#define XDefaultVisualOfScreen(screen) \
+  ((screen) ? JWXYZ_VTBL(screen)->visual(screen) : 0)
+
+#define XDrawPoints(dpy, d, gc, points, n, mode) \
+  (JWXYZ_VTBL(dpy)->DrawPoints (dpy, d, gc, points, n, mode))
+#define XDrawSegments(dpy, d, gc, segments, n) \
+  (JWXYZ_VTBL(dpy)->DrawSegments (dpy, d, gc, segments, n))
+#define XCreateGC(dpy, d, mask, gcv) \
+  (JWXYZ_VTBL(dpy)->CreateGC (dpy, d, mask, gcv))
+#define XFreeGC(dpy, gc) \
+  (JWXYZ_VTBL(dpy)->FreeGC (dpy, gc))
+#define XClearWindow(dpy, win) \
+  (JWXYZ_VTBL(dpy)->ClearWindow(dpy, win))
+#define XSetClipMask(dpy, gc, m) \
+  (JWXYZ_VTBL(dpy)->SetClipMask (dpy, gc, m))
+#define XSetClipOrigin(dpy, gc, x, y) \
+  (JWXYZ_VTBL(dpy)->SetClipOrigin (dpy, gc, x, y))
+#define XFillPolygon(dpy, d, gc, points, npoints, shape, mode) \
+  (JWXYZ_VTBL(dpy)->FillPolygon (dpy, d, gc, points, npoints, shape, mode))
+#define XDrawLines(dpy, d, gc, points, n, mode) \
+  (JWXYZ_VTBL(dpy)->DrawLines (dpy, d, gc, points, n, mode))
+#define XPutImage(dpy, d, gc, image, src_x, src_y, dest_x, dest_y, w, h) \
+  (JWXYZ_VTBL(dpy)->PutImage (dpy, d, gc, image, src_x, src_y, \
+                              dest_x, dest_y, w, h))
+#define XGetSubImage(dpy, d, x, y, width, height, plane_mask, \
+                     format, dest_image, dest_x, dest_y) \
+  (JWXYZ_VTBL(dpy)->GetSubImage (dpy, d, x, y, width, height, plane_mask, \
+                                 format, dest_image, dest_x, dest_y))
+
+
 #endif /* __JWXYZ_H__ */
index 109394f2022f0d75643e63011f9cb992583c8604..a9ee89c0f44773d7ac9d3e149cb2dee204c0c86c 100644 (file)
 
 
 struct jwxyz_Display {
+  const struct jwxyz_vtbl *vtbl; // Must come first.
+
   Window main_window;
-  Screen *screen;
+  CGBitmapInfo bitmap_info;
+  Visual visual;
   struct jwxyz_sources_data *timers_data;
 
 # ifndef USE_IPHONE
@@ -76,13 +79,6 @@ struct jwxyz_Display {
   unsigned long window_background;
 };
 
-struct jwxyz_Screen {
-  Display *dpy;
-  CGBitmapInfo bitmap_info;
-  unsigned long black, white;
-  Visual *visual;
-};
-
 struct jwxyz_GC {
   XGCValues gcv;
   unsigned int depth;
@@ -170,9 +166,9 @@ convert_row (uint32_t *dest, const void *src, size_t count,
        2. Clang's warning for this, -Wshift-count-overflow, only works when the
           shift count is a literal constant, as opposed to an arbitrary
           expression that is optimized down to a constant.
-       Put together, this means that the assertions in jwxyz_make_display with
-       convert_px break with the above naive rotation, but only for a release
-       build.
+       Put together, this means that the assertions in
+       jwxyz_quartz_make_display with convert_px break with the above naive
+       rotation, but only for a release build.
 
        http://blog.regehr.org/archives/1063
        http://llvm.org/bugs/show_bug.cgi?id=17332
@@ -285,64 +281,24 @@ union color_bytes
 };
 
 
-uint32_t
-jwxyz_alloc_color (Display *dpy,
-                   uint16_t r, uint16_t g, uint16_t b, uint16_t a)
-{
-  union color_bytes color;
-
-  /* Instead of (int)(c / 256.0), another possibility is
-     (int)(c * 255.0 / 65535.0 + 0.5). This can be calculated using only
-     uint8_t integer_math(uint16_t c) {
-       unsigned c0 = c + 128;
-       return (c0 - (c0 >> 8)) >> 8;
-     }
-   */
-
-  color.bytes[0] = r >> 8;
-  color.bytes[1] = g >> 8;
-  color.bytes[2] = b >> 8;
-  color.bytes[3] = a >> 8;
-
-  return
-    convert_px (color.pixel,
-      convert_mode_invert (convert_mode_to_rgba (dpy->screen->bitmap_info)));
-}
-
-
-void
-jwxyz_query_color (Display *dpy, unsigned long pixel, uint8_t *rgba)
-{
-  union color_bytes color;
-  color.pixel = convert_px ((uint32_t)pixel,
-                            convert_mode_to_rgba (dpy->screen->bitmap_info));
-  for (unsigned i = 0; i != 4; ++i)
-    rgba[i] = color.bytes[i];
-}
-
-
 static void
-query_color_float (Display *dpy, unsigned long pixel, float *rgba)
+query_color_float (Display *dpy, unsigned long pixel, CGFloat *rgba)
 {
-  uint8_t rgba8[4];
-  jwxyz_query_color (dpy, pixel, rgba8);
-  for (unsigned i = 0; i != 4; ++i)
-    rgba[i] = rgba8[i] * (1.0f / 255.0f);
+  JWXYZ_QUERY_COLOR (dpy, pixel, (CGFloat)1, rgba);
 }
 
 
+extern const struct jwxyz_vtbl quartz_vtbl;
+
 Display *
-jwxyz_make_display (Window w)
+jwxyz_quartz_make_display (Window w)
 {
   CGContextRef cgc = w->cgc;
 
   Display *d = (Display *) calloc (1, sizeof(*d));
-  d->screen = (Screen *) calloc (1, sizeof(Screen));
-  d->screen->dpy = d;
-  
-  d->screen->bitmap_info = CGBitmapContextGetBitmapInfo (cgc);
-  d->screen->black = jwxyz_alloc_color (d, 0x0000, 0x0000, 0x0000, 0xFFFF);
-  d->screen->white = jwxyz_alloc_color (d, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF);
+  d->vtbl = &quartz_vtbl;
+
+  d->bitmap_info = CGBitmapContextGetBitmapInfo (cgc);
 
 # if 0
   // Tests for the image conversion modes.
@@ -368,17 +324,23 @@ jwxyz_make_display (Window w)
   }
 # endif
 
-  Visual *v = (Visual *) calloc (1, sizeof(Visual));
+  Visual *v = &d->visual;
   v->class      = TrueColor;
-  v->red_mask   = jwxyz_alloc_color (d, 0xFFFF, 0x0000, 0x0000, 0x0000);
-  v->green_mask = jwxyz_alloc_color (d, 0x0000, 0xFFFF, 0x0000, 0x0000);
-  v->blue_mask  = jwxyz_alloc_color (d, 0x0000, 0x0000, 0xFFFF, 0x0000);
-  CGBitmapInfo byte_order = d->screen->bitmap_info & kCGBitmapByteOrderMask;
-  Assert ( ! (d->screen->bitmap_info & kCGBitmapFloatComponents) &&
+
+  union color_bytes color;
+  convert_mode_t mode =
+    convert_mode_invert (convert_mode_to_rgba (d->bitmap_info));
+  for (unsigned i = 0; i != 4; ++i) {
+    color.pixel = 0;
+    color.bytes[i] = 0xff;
+    v->rgba_masks[i] = convert_px (color.pixel, mode);
+  }
+
+  CGBitmapInfo byte_order = d->bitmap_info & kCGBitmapByteOrderMask;
+  Assert ( ! (d->bitmap_info & kCGBitmapFloatComponents) &&
           (byte_order == kCGBitmapByteOrder32Little ||
            byte_order == kCGBitmapByteOrder32Big),
           "invalid bits per channel");
-  d->screen->visual = v;
   
   d->timers_data = jwxyz_sources_init (XtDisplayToApplicationContext (d));
 
@@ -391,12 +353,10 @@ jwxyz_make_display (Window w)
 }
 
 void
-jwxyz_free_display (Display *dpy)
+jwxyz_quartz_free_display (Display *dpy)
 {
   jwxyz_sources_free (dpy->timers_data);
   
-  free (dpy->screen->visual);
-  free (dpy->screen);
   free (dpy);
 }
 
@@ -469,66 +429,23 @@ jwxyz_flush_context (Display *dpy)
   CGContextFlush(dpy->main_window->cgc);
 }
 
-jwxyz_sources_data *
+static jwxyz_sources_data *
 display_sources_data (Display *dpy)
 {
   return dpy->timers_data;
 }
 
 
-Window
-XRootWindow (Display *dpy, int screen)
-{
-  return dpy ? dpy->main_window : 0;
-}
-
-Screen *
-XDefaultScreenOfDisplay (Display *dpy)
-{
-  return dpy ? dpy->screen : 0;
-}
-
-Visual *
-XDefaultVisualOfScreen (Screen *screen)
-{
-  return screen ? screen->visual : 0;
-}
-
-Display *
-XDisplayOfScreen (Screen *s)
-{
-  return s ? s->dpy : 0;
-}
-
-int
-XDisplayNumberOfScreen (Screen *s)
-{
-  return 0;
-}
-
-int
-XScreenNumberOfScreen (Screen *s)
-{
-  return 0;
-}
-
-unsigned long
-XBlackPixelOfScreen(Screen *screen)
-{
-  return screen->black;
-}
-
-unsigned long
-XWhitePixelOfScreen(Screen *screen)
+static Window
+root (Display *dpy)
 {
-  return screen->white;
+  return dpy->main_window;
 }
 
-unsigned long
-XCellsOfScreen(Screen *screen)
+static Visual *
+visual (Display *dpy)
 {
-  Visual *v = screen->visual;
-  return v->red_mask | v->green_mask | v->blue_mask;
+  return &dpy->visual;
 }
 
 
@@ -543,7 +460,7 @@ set_color (Display *dpy, CGContextRef cgc, unsigned long argb,
     else
       CGContextSetGrayStrokeColor (cgc, (argb ? 1.0 : 0.0), 1.0);
   } else {
-    float rgba[4];
+    CGFloat rgba[4];
     query_color_float (dpy, argb, rgba);
     if (fill_p)
       CGContextSetRGBFillColor   (cgc, rgba[0], rgba[1], rgba[2], rgba[3]);
@@ -663,9 +580,9 @@ bitmap_context_p (Drawable d)
  */
 #define XDRAWPOINTS_CGDATA
 
-int
-XDrawPoints (Display *dpy, Drawable d, GC gc, 
-             XPoint *points, int count, int mode)
+static int
+DrawPoints (Display *dpy, Drawable d, GC gc,
+            XPoint *points, int count, int mode)
 {
   int i;
   XRectangle wr = d->frame;
@@ -736,7 +653,7 @@ XDrawPoints (Display *dpy, Drawable d, GC gc,
                                     dpy->colorspace, 
                                     /* Host-ordered, since we're using the
                                        address of an int as the color data. */
-                                    dpy->screen->bitmap_info,
+                                    dpy->bitmap_info,
                                     prov, 
                                     NULL,  /* decode[] */
                                     NO, /* interpolate */
@@ -840,41 +757,8 @@ point_for_line (Drawable d, GC gc, int x, int y)
 }
 
 
-int
-XDrawLine (Display *dpy, Drawable d, GC gc, int x1, int y1, int x2, int y2)
-{
-  // when drawing a zero-length line, obey line-width and cap-style.
-  if (x1 == x2 && y1 == y2) {
-    int w = gc->gcv.line_width;
-    x1 -= w/2;
-    y1 -= w/2;
-    if (gc->gcv.line_width > 1 && gc->gcv.cap_style == CapRound)
-      return XFillArc (dpy, d, gc, x1, y1, w, w, 0, 360*64);
-    else {
-      if (!w)
-        w = 1; // Actually show zero-length lines.
-      return XFillRectangle (dpy, d, gc, x1, y1, w, w);
-    }
-  }
-  
-  CGPoint p = point_for_line (d, gc, x1, y1);
-
-  push_fg_gc (dpy, d, gc, NO);
-
-  CGContextRef cgc = d->cgc;
-  set_line_mode (cgc, &gc->gcv);
-  CGContextBeginPath (cgc);
-  CGContextMoveToPoint (cgc, p.x, p.y);
-  p = point_for_line(d, gc, x2, y2);
-  CGContextAddLineToPoint (cgc, p.x, p.y);
-  CGContextStrokePath (cgc);
-  pop_gc (d, gc);
-  invalidate_drawable_cache (d);
-  return 0;
-}
-
-int
-XDrawLines (Display *dpy, Drawable d, GC gc, XPoint *points, int count,
+static int
+DrawLines (Display *dpy, Drawable d, GC gc, XPoint *points, int count,
             int mode)
 {
   int i;
@@ -913,8 +797,8 @@ XDrawLines (Display *dpy, Drawable d, GC gc, XPoint *points, int count,
 }
 
 
-int
-XDrawSegments (Display *dpy, Drawable d, GC gc, XSegment *segments, int count)
+static int
+DrawSegments (Display *dpy, Drawable d, GC gc, XSegment *segments, int count)
 {
   int i;
 
@@ -924,10 +808,25 @@ XDrawSegments (Display *dpy, Drawable d, GC gc, XSegment *segments, int count)
   set_line_mode (cgc, &gc->gcv);
   CGContextBeginPath (cgc);
   for (i = 0; i < count; i++) {
-    CGPoint p = point_for_line (d, gc, segments->x1, segments->y1);
-    CGContextMoveToPoint (cgc, p.x, p.y);
-    p = point_for_line (d, gc, segments->x2, segments->y2);
-    CGContextAddLineToPoint (cgc, p.x, p.y);
+    // when drawing a zero-length line, obey line-width and cap-style.
+    if (segments->x1 == segments->x2 && segments->y1 == segments->y2) {
+      int w = gc->gcv.line_width;
+      int x1 = segments->x1 - w/2;
+      int y1 = segments->y1 - w/2;
+      if (gc->gcv.line_width > 1 && gc->gcv.cap_style == CapRound)
+        XFillArc (dpy, d, gc, x1, y1, w, w, 0, 360*64);
+      else {
+        if (!w)
+          w = 1; // Actually show zero-length lines.
+        XFillRectangle (dpy, d, gc, x1, y1, w, w);
+      }
+    } else {
+      CGPoint p = point_for_line (d, gc, segments->x1, segments->y1);
+      CGContextMoveToPoint (cgc, p.x, p.y);
+      p = point_for_line (d, gc, segments->x2, segments->y2);
+      CGContextAddLineToPoint (cgc, p.x, p.y);
+    }
+
     segments++;
   }
   CGContextStrokePath (cgc);
@@ -937,33 +836,24 @@ XDrawSegments (Display *dpy, Drawable d, GC gc, XSegment *segments, int count)
 }
 
 
-int
-XClearWindow (Display *dpy, Window win)
+static int
+ClearWindow (Display *dpy, Window win)
 {
   Assert (win && win->type == WINDOW, "not a window");
   XRectangle wr = win->frame;
   return XClearArea (dpy, win, 0, 0, wr.width, wr.height, 0);
 }
 
-unsigned long
-jwxyz_window_background (Display *dpy)
+static unsigned long *
+window_background (Display *dpy)
 {
-  return dpy->window_background;
+  return &dpy->window_background;
 }
 
-int
-XSetWindowBackground (Display *dpy, Window w, unsigned long pixel)
-{
-  Assert (w && w->type == WINDOW, "not a window");
-  jwxyz_validate_pixel (dpy, pixel, 32, NO);
-  dpy->window_background = pixel;
-  return 0;
-}
-
-void
-jwxyz_fill_rects (Display *dpy, Drawable d, GC gc,
-                  const XRectangle *rectangles, unsigned long nrectangles,
-                  unsigned long pixel)
+static void
+fill_rects (Display *dpy, Drawable d, GC gc,
+            const XRectangle *rectangles, unsigned long nrectangles,
+            unsigned long pixel)
 {
   Assert (!gc || gc->depth == jwxyz_drawable_depth (d), "depth mismatch");
 
@@ -1021,7 +911,7 @@ jwxyz_fill_rects (Display *dpy, Drawable d, GC gc,
         pixel = pixel ? WhitePixel(dpy, 0) : BlackPixel(dpy, 0);
 
       size_t dst_bytes_per_row = CGBitmapContextGetBytesPerRow (d->cgc);
-      void *dst = seek_xy (CGBitmapContextGetData (d->cgc),
+      void *dst = SEEK_XY (CGBitmapContextGetData (d->cgc),
                            dst_bytes_per_row, x, y);
 
       Assert(sizeof(wchar_t) == 4, "somebody changed the ABI");
@@ -1048,18 +938,9 @@ jwxyz_fill_rects (Display *dpy, Drawable d, GC gc,
 }
 
 
-int
-XClearArea (Display *dpy, Window win, int x, int y, int w, int h, Bool exp)
-{
-  Assert (win && win->type == WINDOW, "not a window");
-  jwxyz_fill_rect (dpy, win, 0, x, y, w, h, dpy->window_background);
-  return 0;
-}
-
-
-int
-XFillPolygon (Display *dpy, Drawable d, GC gc, 
-              XPoint *points, int npoints, int shape, int mode)
+static int
+FillPolygon (Display *dpy, Drawable d, GC gc,
+             XPoint *points, int npoints, int shape, int mode)
 {
   XRectangle wr = d->frame;
   int i;
@@ -1094,8 +975,8 @@ XFillPolygon (Display *dpy, Drawable d, GC gc,
 #define radians(DEG) ((DEG) * M_PI / 180.0)
 #define degrees(RAD) ((RAD) * 180.0 / M_PI)
 
-int
-jwxyz_draw_arc (Display *dpy, Drawable d, GC gc, int x, int y,
+static int
+draw_arc (Display *dpy, Drawable d, GC gc, int x, int y,
                 unsigned int width, unsigned int height,
                 int angle1, int angle2, Bool fill_p)
 {
@@ -1145,22 +1026,22 @@ jwxyz_draw_arc (Display *dpy, Drawable d, GC gc, int x, int y,
 }
 
 
-XGCValues *
-jwxyz_gc_gcv (GC gc)
+static XGCValues *
+gc_gcv (GC gc)
 {
   return &gc->gcv;
 }
 
 
-unsigned int
-jwxyz_gc_depth (GC gc)
+static unsigned int
+gc_depth (GC gc)
 {
   return gc->depth;
 }
 
 
-GC
-XCreateGC (Display *dpy, Drawable d, unsigned long mask, XGCValues *xgcv)
+static GC
+CreateGC (Display *dpy, Drawable d, unsigned long mask, XGCValues *xgcv)
 {
   struct jwxyz_GC *gc = (struct jwxyz_GC *) calloc (1, sizeof(*gc));
   gc->depth = jwxyz_drawable_depth (d);
@@ -1171,8 +1052,8 @@ XCreateGC (Display *dpy, Drawable d, unsigned long mask, XGCValues *xgcv)
 }
 
 
-int
-XFreeGC (Display *dpy, GC gc)
+static int
+FreeGC (Display *dpy, GC gc)
 {
   if (gc->gcv.font)
     XUnloadFont (dpy, gc->gcv.font);
@@ -1230,10 +1111,10 @@ flipbits (unsigned const char *in, unsigned char *out, int length)
 }
 
 
-int
-XPutImage (Display *dpy, Drawable d, GC gc, XImage *ximage,
-           int src_x, int src_y, int dest_x, int dest_y,
-           unsigned int w, unsigned int h)
+static int
+PutImage (Display *dpy, Drawable d, GC gc, XImage *ximage,
+          int src_x, int src_y, int dest_x, int dest_y,
+          unsigned int w, unsigned int h)
 {
   XRectangle wr = d->frame;
 
@@ -1303,7 +1184,7 @@ XPutImage (Display *dpy, Drawable d, GC gc, XImage *ximage,
     CGImageRef cgi = CGImageCreate (w, h,
                                     bpp/4, bpp, bpl,
                                     dpy->colorspace, 
-                                    dpy->screen->bitmap_info,
+                                    dpy->bitmap_info,
                                     prov, 
                                     NULL,  /* decode[] */
                                     NO, /* interpolate */
@@ -1357,11 +1238,11 @@ XPutImage (Display *dpy, Drawable d, GC gc, XImage *ximage,
 }
 
 
-XImage *
-XGetSubImage (Display *dpy, Drawable d, int x, int y,
-              unsigned int width, unsigned int height,
-              unsigned long plane_mask, int format,
-              XImage *image, int dest_x, int dest_y)
+static XImage *
+GetSubImage (Display *dpy, Drawable d, int x, int y,
+             unsigned int width, unsigned int height,
+             unsigned long plane_mask, int format,
+             XImage *image, int dest_x, int dest_y)
 {
   const unsigned char *data = 0;
   size_t depth, ibpp, ibpl;
@@ -1376,7 +1257,7 @@ XGetSubImage (Display *dpy, Drawable d, int x, int y,
 
   {
     depth = jwxyz_drawable_depth (d);
-    mode = convert_mode_to_rgba (dpy->screen->bitmap_info);
+    mode = convert_mode_to_rgba (dpy->bitmap_info);
     ibpp = CGBitmapContextGetBitsPerPixel (cgc);
     ibpl = CGBitmapContextGetBytesPerRow (cgc);
     data = CGBitmapContextGetData (cgc);
@@ -1422,7 +1303,7 @@ XGetSubImage (Display *dpy, Drawable d, int x, int y,
 
     mode = convert_mode_merge (mode,
              convert_mode_invert (
-               convert_mode_to_rgba (dpy->screen->bitmap_info)));
+               convert_mode_to_rgba (dpy->bitmap_info)));
 
     for (yy = 0; yy < height; yy++) {
 
@@ -1538,6 +1419,16 @@ jwxyz_draw_NSImage_or_CGImage (Display *dpy, Drawable d,
   float rh = winr.height / imgr.height;
   float r = (rw < rh ? rw : rh);
 
+  /* If the window is a goofy aspect ratio, take a middle slice of
+     the image instead. */
+  if (winr.width > winr.height * 5 ||
+      winr.width > winr.width * 5) {
+    r *= (winr.width > winr.height
+         ? winr.width  / (double) winr.height
+         : winr.height / (double) winr.width);
+    // NSLog (@"weird aspect: scaling by %.1f\n", r);
+  }
+
   CGRect dst, dst2;
   dst.size.width  = imgr.width  * r;
   dst.size.height = imgr.height * r;
@@ -1615,7 +1506,7 @@ XCreatePixmap (Display *dpy, Drawable d,
                                   8, /* bits per component */
                                   width * 4, /* bpl */
                                   dpy->colorspace,
-                                  dpy->screen->bitmap_info);
+                                  dpy->bitmap_info);
   Assert (p->cgc, "could not create CGBitmapContext");
   return p;
 }
@@ -1692,9 +1583,9 @@ jwxyz_unicode_character_name (Display *dpy, Font fid, unsigned long uc)
 }
 
 
-int
-jwxyz_draw_string (Display *dpy, Drawable d, GC gc, int x, int y,
-                   const char *str, size_t len, int utf8_p)
+static int
+draw_string (Display *dpy, Drawable d, GC gc, int x, int y,
+             const char *str, size_t len, int utf8_p)
 {
   NSString *nsstr = nsstring_from (str, len, utf8_p);
 
@@ -1705,7 +1596,7 @@ jwxyz_draw_string (Display *dpy, Drawable d, GC gc, int x, int y,
 
   unsigned long argb = gc->gcv.foreground;
   if (gc->depth == 1) argb = (argb ? WhitePixel(dpy,0) : BlackPixel(dpy,0));
-  float rgba[4];
+  CGFloat rgba[4];
   query_color_float (dpy, argb, rgba);
   NSColor *fg = [NSColor colorWithDeviceRed:rgba[0]
                                       green:rgba[1]
@@ -1767,8 +1658,8 @@ jwxyz_draw_string (Display *dpy, Drawable d, GC gc, int x, int y,
 }
 
 
-int
-XSetClipMask (Display *dpy, GC gc, Pixmap m)
+static int
+SetClipMask (Display *dpy, GC gc, Pixmap m)
 {
   Assert (!!gc->gcv.clip_mask == !!gc->clip_mask, "GC clip mask mixup");
 
@@ -1787,12 +1678,40 @@ XSetClipMask (Display *dpy, GC gc, Pixmap m)
   return 0;
 }
 
-int
-XSetClipOrigin (Display *dpy, GC gc, int x, int y)
+static int
+SetClipOrigin (Display *dpy, GC gc, int x, int y)
 {
   gc->gcv.clip_x_origin = x;
   gc->gcv.clip_y_origin = y;
   return 0;
 }
 
+
+const struct jwxyz_vtbl quartz_vtbl = {
+  root,
+  visual,
+  display_sources_data,
+
+  window_background,
+  draw_arc,
+  fill_rects,
+  gc_gcv,
+  gc_depth,
+  draw_string,
+
+  jwxyz_quartz_copy_area,
+
+  DrawPoints,
+  DrawSegments,
+  CreateGC,
+  FreeGC,
+  ClearWindow,
+  SetClipMask,
+  SetClipOrigin,
+  FillPolygon,
+  DrawLines,
+  PutImage,
+  GetSubImage
+};
+
 #endif // JWXYZ_QUARTZ -- entire file
index f82d6148a857a816bf688cbbc7fe4656cddd1bb4..5d0181eed51bb34a763a9480e23905d8b8ad6932 100644 (file)
@@ -13,6 +13,7 @@
 #define __JWXYZ_I_H__
 
 #include <inttypes.h>
+#include <stddef.h>
 
 #include "jwxyz.h"
 
 #define JWXYZ_STYLE_ITALIC      2
 #define JWXYZ_STYLE_MONOSPACE   4
 
-/* jwxyz.m, jwxyz-gl.c */
-extern Display *jwxyz_make_display (Window w);
-extern void jwxyz_free_display (Display *);
+#define JWXYZ_QUERY_COLOR(dpy, pixel, mult, rgba) \
+  { \
+    const unsigned long *_MASKS = \
+       DefaultVisualOfScreen (DefaultScreenOfDisplay (dpy))->rgba_masks; \
+    for (unsigned i = 0; i != 4; ++i) \
+      (rgba)[i] = ((pixel) & _MASKS[i]) * (mult) / _MASKS[i]; \
+  }
+
+/* jwxyz.m, jwxyz-gl.c, jwxyz-image.c */
 extern void jwxyz_window_resized (Display *);
-extern uint32_t jwxyz_alloc_color (Display *dpy, uint16_t r, uint16_t g,
-                                   uint16_t b, uint16_t a);
-extern void jwxyz_query_color (Display *dpy, unsigned long pixel,
-                               uint8_t *rgba);
-extern unsigned long jwxyz_window_background (Display *);
-extern int jwxyz_draw_arc (Display *dpy, Drawable d, GC gc, int x, int y,
-                           unsigned int width, unsigned int height,
-                           int angle1, int angle2, Bool fill_p);
-extern void jwxyz_fill_rects (Display *dpy, Drawable d, GC gc,
-                              const XRectangle *rectangles,
-                              unsigned long nrects,
-                              unsigned long pixel);
-extern XGCValues *jwxyz_gc_gcv (GC gc);
-extern unsigned int jwxyz_gc_depth (GC gc);
-extern int jwxyz_draw_string (Display *dpy, Drawable d, GC gc, int x, int y,
-                              const char *str, size_t len, Bool utf8);
 
 /* jwxyz-cocoa.m, jwxyz-android.c */
 extern const XRectangle *jwxyz_frame (Drawable d); /* XGetGeometry sux. */
@@ -70,14 +61,13 @@ extern void *jwxyz_load_native_font (Window main_window,
                                      char **family_name_ret,
                                      int *ascent_ret, int *descent_ret);
 extern void jwxyz_release_native_font (Display *, void *native_font);
+
+/* Text metrics for aliased and antialiased text must match. */
 extern void jwxyz_render_text (Display *, void *native_font,
-                               const char *str, size_t len, int utf8_p,
-                               XCharStruct *cs_ret, char **pixmap_ret);
+                               const char *str, size_t len, Bool utf8_p,
+                               Bool antialias_p, XCharStruct *cs_ret,
+                               char **pixmap_ret);
 extern void jwxyz_get_pos (Window w, XPoint *vpos, XPoint *p);
-extern void jwxyz_copy_area (Display *dpy, Drawable src, Drawable dst, GC gc,
-                             int src_x, int src_y,
-                             unsigned int width, unsigned int height,
-                             int dst_x, int dst_y);
 #ifndef current_device_rotation
 extern double current_device_rotation (void);
 extern Bool ignore_rotation_p (Display *);
@@ -89,18 +79,30 @@ extern void jwxyz_validate_pixel (Display *dpy, unsigned long pixel,
 extern Bool jwxyz_dumb_drawing_mode(Display *dpy, Drawable d, GC gc,
                                     int x, int y,
                                     unsigned width, unsigned height);
+extern void jwxyz_blit (const void *src_data, ptrdiff_t src_pitch,
+                        unsigned src_x, unsigned src_y,
+                        void *dst_data, ptrdiff_t dst_pitch,
+                        unsigned dst_x, unsigned dst_y,
+                        unsigned width, unsigned height);
 extern void jwxyz_fill_rect (Display *, Drawable, GC,
                              int x, int y,
                              unsigned int width, unsigned int height,
                              unsigned long pixel);
 extern void jwxyz_gcv_defaults (Display *dpy, XGCValues *gcv, int depth);
+extern int jwxyz_draw_string (Display *dpy, Drawable d, GC gc, int x, int y,
+                              const char *str, size_t len, int utf8_p);
 extern void *jwxyz_native_font (Font f);
 
-# if defined JWXYZ_QUARTZ
+#define SEEK_XY(dst, dst_pitch, x, y) \
+  ((uint32_t *)((char *)dst + dst_pitch * y + x * 4))
+
+# ifdef JWXYZ_QUARTZ
 
 #  include <CoreGraphics/CGGeometry.h>
 #  include <CoreGraphics/CGContext.h>
 
+extern Display *jwxyz_quartz_make_display (Window w);
+extern void jwxyz_quartz_free_display (Display *);
 extern void jwxyz_flush_context (Display *);
 
 #  define jwxyz_assert_display(dpy)
@@ -116,13 +118,16 @@ extern void push_color_gc (Display *dpy, Drawable d, GC gc,
                            unsigned long color,
                            Bool antialias_p, Bool fill_p);
 extern CGPoint map_point (Drawable d, int x, int y);
-
-#define seek_xy(dst, dst_pitch, x, y) \
-  ((void *)((char *)dst + dst_pitch * y + x * 4))
+extern void jwxyz_quartz_copy_area (Display *dpy, Drawable src, Drawable dst,
+                                    GC gc, int src_x, int src_y,
+                                    unsigned int width, unsigned int height,
+                                    int dst_x, int dst_y);
 
 #define pop_gc(d,gc) CGContextRestoreGState (d->cgc)
 
-# elif defined JWXYZ_GL
+# endif /* JWXYZ_QUARTZ */
+
+# ifdef JWXYZ_GL
 
 #  if defined(USE_IPHONE)
 #   include <OpenGLES/ES1/gl.h>
@@ -135,9 +140,16 @@ extern CGPoint map_point (Drawable d, int x, int y);
 #  endif
 
 /* utils/jwxyz-gl.c */
-extern void jwxyz_prepare_context (Display *dpy);
+extern Display *jwxyz_gl_make_display (Window w);
+extern void jwxyz_gl_free_display (Display *);
 extern void jwxyz_set_matrices (Display *dpy, unsigned width, unsigned height,
                                 Bool screen_p);
+extern void jwxyz_gl_flush (Display *dpy);
+extern void jwxyz_gl_set_gc (Display *dpy, GC gc);
+extern void jwxyz_gl_copy_area (Display *dpy, Drawable src, Drawable dst,
+                                GC gc, int src_x, int src_y,
+                                unsigned int width, unsigned int height,
+                                int dst_x, int dst_y);
 
 /* Only works if both drawables share OpenGL objects. OpenGL context sharing
    works on OS X, iOS, and some (but not all!) EGL implementations. This would
@@ -179,4 +191,15 @@ extern void jwxyz_assert_gl (void);
 
 # endif /* JWXYZ_GL */
 
+# ifdef JWXYZ_IMAGE
+
+extern Display *jwxyz_image_make_display (Window w,
+                                          const unsigned char *rgba_bytes);
+extern void jwxyz_image_free_display (Display *);
+
+extern ptrdiff_t jwxyz_image_pitch (Drawable d);
+extern void *jwxyz_image_data (Drawable d);
+
+# endif /* JWXYZ_IMAGE */
+
 #endif
index 7a8ef81287bb73951b427a3891cbeafad6f07cf9..c025aa9880bc0bb47996260eeba7237a98bc5a59 100644 (file)
@@ -1,4 +1,4 @@
-# Auto-generated: Wed Jul  5 10:52:59 PDT 2017
+# Auto-generated: Wed Dec 20 11:14:25 PST 2017
 driver/demo-Gtk-conf.c
 driver/demo-Gtk.c
 driver/screensaver-properties.desktop.in
@@ -68,6 +68,7 @@ hacks/config/energystream.xml
 hacks/config/engine.xml
 hacks/config/epicycle.xml
 hacks/config/eruption.xml
+hacks/config/esper.xml
 hacks/config/euler2d.xml
 hacks/config/extrusion.xml
 hacks/config/fadeplot.xml
index 1720643dc7bf38424a8f7f9e23b6048d9793e4b7..dd99ebdbcf6b269be574112b7dab418557bafcd1 100644 (file)
--- a/po/ru.po
+++ b/po/ru.po
@@ -5,515 +5,24 @@ msgid ""
 msgstr ""
 "Project-Id-Version: xscreensaver 4.09\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2006-02-13 12:26+0100\n"
+"POT-Creation-Date: 2017-11-03 21:11+0300\n"
 "PO-Revision-Date: 2003-05-17 16:53+0300\n"
 "Last-Translator: \"Andrew W. Nosenko\" <awn@bcs.zp.ua>\n"
 "Language-Team: Russian\n"
+"Language: \n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: driver/demo-Gtk-conf.c:818
+#: ../driver/demo-Gtk-conf.c:884
 msgid "Browse..."
 msgstr "Обзор..."
 
-#: driver/demo-Gtk-conf.c:1110
+#: ../driver/demo-Gtk-conf.c:1087
 msgid "Select file."
-msgstr ""
-
-#: driver/demo-Gtk-support.c:135
-#, c-format
-msgid "Couldn't find pixmap file: %s"
-msgstr "Не удалось найти файл изображения: %s"
-
-#: driver/demo-Gtk-support.c:147 driver/demo-Gtk-support.c:179
-#, c-format
-msgid "Error loading pixmap file: %s"
-msgstr "Ошибка загрузки файла изображения: %s"
-
-#: driver/demo-Gtk-support.c:182
-#, c-format
-msgid "reason: %s\n"
-msgstr ""
-
-#: driver/demo-Gtk-widgets.c:161 driver/xscreensaver-demo.glade2.h:71
-msgid "XScreenSaver"
-msgstr "Хранитель экрана"
-
-#: driver/demo-Gtk-widgets.c:182 driver/xscreensaver-demo.glade2.h:84
-msgid "_File"
-msgstr "_Файл"
-
-#: driver/demo-Gtk-widgets.c:202 driver/xscreensaver-demo.glade2.h:76
-msgid "_Blank Screen Now"
-msgstr "_Активировать хранитель экрана немедленно"
-
-#: driver/demo-Gtk-widgets.c:211
-msgid ""
-"Activate the XScreenSaver daemon now (locking the screen if so configured.)"
-msgstr ""
-"Активировать XscreenSaver демон немедленно (кроме того, экран будет "
-"заблокирован, если включен соответствующий параметр в конфигурации)."
-
-#: driver/demo-Gtk-widgets.c:215 driver/xscreensaver-demo.glade2.h:89
-msgid "_Lock Screen Now"
-msgstr "_Заблокировать экран немедленно"
-
-#: driver/demo-Gtk-widgets.c:224
-msgid "Lock the screen now (even if \"Lock Screen\" is unchecked.)"
-msgstr ""
-"Заблокировать экран немедленно (даже если параметр \"Блокировать экран\" "
-"выключен)."
-
-#: driver/demo-Gtk-widgets.c:228 driver/xscreensaver-demo.glade2.h:87
-msgid "_Kill Daemon"
-msgstr "_Убить демон"
-
-#: driver/demo-Gtk-widgets.c:237
-msgid "Tell the running XScreenSaver daemon to exit."
-msgstr "Завершает работающий XScreenSaver демон."
-
-#: driver/demo-Gtk-widgets.c:241 driver/xscreensaver-demo.glade2.h:98
-msgid "_Restart Daemon"
-msgstr "_Перезапустить демон"
-
-#: driver/demo-Gtk-widgets.c:250
-msgid "Kill and re-launch the XScreenSaver daemon."
-msgstr "Убить, после чего повторно запустить XScreenSaver демон."
-
-#: driver/demo-Gtk-widgets.c:263
-msgid "_Exit"
-msgstr "_Выход"
-
-#: driver/demo-Gtk-widgets.c:272
-msgid ""
-"Exit the xscreensaver-demo program (but leave the XScreenSaver daemon "
-"running in the background.)"
-msgstr ""
-"Выйти из программы xscreensaver-demo (но оставить XScreenSaver демон "
-"работающим в фоновом режиме)."
-
-#: driver/demo-Gtk-widgets.c:276 driver/xscreensaver-demo.glade2.h:85
-msgid "_Help"
-msgstr "_Справка"
-
-#: driver/demo-Gtk-widgets.c:296 driver/xscreensaver-demo.glade2.h:72
-msgid "_About..."
-msgstr "_О программе..."
-
-#: driver/demo-Gtk-widgets.c:305
-msgid "Display version information."
-msgstr "Показать информацию о версии программы."
-
-#: driver/demo-Gtk-widgets.c:309 driver/xscreensaver-demo.glade2.h:83
-msgid "_Documentation..."
-msgstr "_Документация..."
-
-#: driver/demo-Gtk-widgets.c:318
-msgid "Go to the documentation on the XScreenSaver web page."
-msgstr "Перейти к документации, расположенной на веб-странице XScreenSaver'а"
-
-#: driver/demo-Gtk-widgets.c:348
-msgid "Cycle After"
-msgstr "Смена через"
-
-#: driver/demo-Gtk-widgets.c:370 driver/xscreensaver-demo.glade2.h:63
-msgid "Whether a password should be required to un-blank the screen."
-msgstr "Должен ли требоваться пароль для разблокировки экрана."
-
-#: driver/demo-Gtk-widgets.c:372
-msgid "Lock Screen After"
-msgstr "Запирать экран через"
-
-#: driver/demo-Gtk-widgets.c:380
-msgid "Blank After"
-msgstr "Активация через"
-
-#: driver/demo-Gtk-widgets.c:403 driver/demo-Gtk-widgets.c:453
-#: driver/demo-Gtk-widgets.c:467 driver/demo-Gtk-widgets.c:1016
-msgid "How long before the monitor goes completely black."
-msgstr ""
-"Через какое время монитор должен начать показывать только \"черный экран\"."
-
-#: driver/demo-Gtk-widgets.c:407 driver/demo-Gtk-widgets.c:419
-#: driver/demo-Gtk-widgets.c:431 driver/demo-Gtk-widgets.c:1020
-#: driver/demo-Gtk-widgets.c:1032 driver/demo-Gtk-widgets.c:1044
-#: driver/xscreensaver-demo.glade2.h:106
-msgid "minutes"
-msgstr "минут(ы)"
-
-#: driver/demo-Gtk-widgets.c:482 driver/demo-Gtk.c:3233
-msgid "Preview"
-msgstr "Предпросмотр"
-
-#: driver/demo-Gtk-widgets.c:490 driver/xscreensaver-demo.glade2.h:10
-msgid ""
-"Demo the selected screen saver in full-screen mode (click the mouse to "
-"return.)"
-msgstr ""
-"Показать выбранный хранитель в полноэкранном режиме (возврат обратно по "
-"щелчку мыши)."
-
-#: driver/demo-Gtk-widgets.c:492
-msgid "Settings..."
-msgstr "Настройки..."
-
-#: driver/demo-Gtk-widgets.c:500 driver/xscreensaver-demo.glade2.h:7
-msgid "Customization and explanation of the selected screen saver."
-msgstr "Настройка и объяснение выбранного хранителя экрана."
-
-#: driver/demo-Gtk-widgets.c:521
-msgid "Mode:"
-msgstr "Режим:"
-
-#: driver/demo-Gtk-widgets.c:539
-msgid "Disable Screen Saver"
-msgstr "Запретить хранитель экрана"
-
-#: driver/demo-Gtk-widgets.c:542
-msgid "Blank Screen Only"
-msgstr "Только очищать экран"
-
-#: driver/demo-Gtk-widgets.c:545
-msgid "Only One Screen Saver"
-msgstr "Один постоянный хранитель экрана"
-
-#: driver/demo-Gtk-widgets.c:548
-msgid "Random Screen Saver"
-msgstr "Случайный хранитель экрана"
-
-#: driver/demo-Gtk-widgets.c:571 driver/demo-Gtk.c:2419
-msgid "Use"
-msgstr "Использовать"
-
-#: driver/demo-Gtk-widgets.c:591 driver/demo-Gtk.c:2429
-msgid "Screen Saver"
-msgstr "Хранитель экрана"
-
-#: driver/demo-Gtk-widgets.c:644
-msgid "\\/"
-msgstr "\\/"
-
-#: driver/demo-Gtk-widgets.c:652 driver/xscreensaver-demo.glade2.h:39
-msgid ""
-"Run the next screen saver in the list in full-screen mode (click the mouse "
-"to return.)"
-msgstr ""
-"Исполнить следующий в списке хранитель экрана в полноэкранном режиме "
-"(возврат обратно по щелчку мыши)."
-
-#: driver/demo-Gtk-widgets.c:654
-msgid "/\\"
-msgstr "/\\"
-
-#: driver/demo-Gtk-widgets.c:662 driver/xscreensaver-demo.glade2.h:40
-msgid ""
-"Run the previous screen saver in the list in full-screen mode (click the "
-"mouse to return.)"
-msgstr ""
-"Исполнить предыдущий в списке хранитель экрана в полноэкранном режиме "
-"(возврат обратно по щелчку мыши)."
-
-#: driver/demo-Gtk-widgets.c:664 driver/demo-Gtk-widgets.c:1607
-#: driver/xscreensaver-demo.glade2.h:11
-msgid "Description"
-msgstr "Описание"
-
-#: driver/demo-Gtk-widgets.c:691
-msgid "Display Modes"
-msgstr "Режимы экрана"
-
-#: driver/demo-Gtk-widgets.c:707
-msgid "Diagnostics"
-msgstr "Диагностика"
-
-#: driver/demo-Gtk-widgets.c:751
-msgid "Whether the daemon should print lots of debugging information."
-msgstr "Должен ли демон выводить большое количество отладочной информации."
-
-#: driver/demo-Gtk-widgets.c:753
-msgid "Verbose Diagnostics"
-msgstr "Расширенная диагностика"
-
-#: driver/demo-Gtk-widgets.c:768
-msgid ""
-"Whether any error output of the display modes should be redirected to the "
-"screen."
-msgstr ""
-"Должны ли сообщения об ошибках от различных заставок-хранителей выводиться "
-"на экран."
-
-#: driver/demo-Gtk-widgets.c:770
-msgid "Display Subprocess Errors"
-msgstr "Показывать ошибки подпроцессов"
-
-#: driver/demo-Gtk-widgets.c:785
-msgid ""
-"Whether the splash screen (with the version number and `Help' button) should "
-"be momentarily displayed when the daemon first starts up."
-msgstr ""
-"Показывать ли в момент первого старта демона окно-заставку (с номером версии "
-"и кнопкой `Справка')?"
-
-#: driver/demo-Gtk-widgets.c:787
-msgid "Display Splash Screen at Startup"
-msgstr "Показывать окно-заставку при запуске"
-
-#: driver/demo-Gtk-widgets.c:796
-msgid "Colormaps"
-msgstr "Цветовые палитры"
-
-#: driver/demo-Gtk-widgets.c:840 driver/xscreensaver-demo.glade2.h:70
-msgid ""
-"Whether to install a private colormap when running in 8-bit mode on the "
-"default Visual."
-msgstr ""
-"Устанавливать ли собственную цветовую палитру при работе с 8-битным цветом в "
-"оптическом классе \"по умолчанию\"."
-
-#: driver/demo-Gtk-widgets.c:842
-msgid "Install Colormap"
-msgstr "Устанавливать цветовую палитру"
-
-#: driver/demo-Gtk-widgets.c:865 driver/xscreensaver-demo.glade2.h:69
-msgid ""
-"Whether the screen should slowly fade to black when the screen saver "
-"activates."
-msgstr ""
-"Должен ли экран плавно \"снижать яркость\", \"гаснуть\" до черного при "
-"активации хранителя экрана."
-
-#: driver/demo-Gtk-widgets.c:867
-msgid "Fade To Black When Blanking"
-msgstr "Переход к черному при активации"
-
-#: driver/demo-Gtk-widgets.c:882 driver/xscreensaver-demo.glade2.h:68
-msgid ""
-"Whether the screen should slowly fade in from black when the screen saver "
-"deactivates."
-msgstr ""
-"Должен ли экран плавно \"набирать яркость\" от черного до нормального при де-"
-"активации хранителя экрана."
-
-#: driver/demo-Gtk-widgets.c:884
-msgid "Fade From Black When Unblanking"
-msgstr "Переход от черного при де-активации"
-
-#: driver/demo-Gtk-widgets.c:910
-msgid "Fade Duration"
-msgstr "Продолжительность перехода"
-
-#: driver/demo-Gtk-widgets.c:928 driver/xscreensaver-demo.glade2.h:26
-msgid "How long it should take for the screen to fade in and out."
-msgstr "Как долго должен длиться переход \"к черному\" или \"от черного\"."
-
-#: driver/demo-Gtk-widgets.c:932 driver/xscreensaver-demo.glade2.h:111
-msgid "seconds"
-msgstr "секунд(ы)"
-
-#: driver/demo-Gtk-widgets.c:942 driver/xscreensaver-demo.glade2.h:13
-msgid "Display Power Management"
-msgstr "Управление питанием монитора"
-
-#: driver/demo-Gtk-widgets.c:986 driver/xscreensaver-demo.glade2.h:67
-msgid "Whether the monitor should be powered down after a while."
-msgstr ""
-"Должен ли монитор снижать энергопотребление или отключаться через какое-то "
-"время."
-
-#: driver/demo-Gtk-widgets.c:988
-msgid "Power Management Enabled"
-msgstr "Управление питанием разрешено"
-
-#: driver/demo-Gtk-widgets.c:1056
-msgid "Off After"
-msgstr "Выключать через"
-
-#: driver/demo-Gtk-widgets.c:1069
-msgid "Suspend After"
-msgstr "Режим Suspend через"
-
-#: driver/demo-Gtk-widgets.c:1082
-msgid "Standby After"
-msgstr "Режим Standby через"
-
-#: driver/demo-Gtk-widgets.c:1105 driver/xscreensaver-demo.glade2.h:28
-msgid "How long until the monitor goes into power-saving mode."
-msgstr "Через какое время монитор должен перейти в режим энергосбережения."
-
-#: driver/demo-Gtk-widgets.c:1119 driver/xscreensaver-demo.glade2.h:29
-msgid "How long until the monitor powers down."
-msgstr "Через какое время монитор должен отключиться."
-
-#: driver/demo-Gtk-widgets.c:1123 driver/xscreensaver-demo.glade2.h:30
-msgid "Image Manipulation"
-msgstr "Манипуляции с изображениями"
-
-#: driver/demo-Gtk-widgets.c:1167 driver/xscreensaver-demo.glade2.h:64
-msgid ""
-"Whether the image-manipulating modes should be allowed to operate on an "
-"image of your desktop."
-msgstr ""
-"Позволяется ли заставкам-хранителям, манипулирующим изображениями, работать "
-"с изображением вашего рабочего стола."
-
-#: driver/demo-Gtk-widgets.c:1169
-msgid "Grab Desktop Images"
-msgstr "Захватывать изображения с рабочего стола"
-
-#: driver/demo-Gtk-widgets.c:1184
-msgid ""
-"Whether the image-manipulating modes should operate on images captured from "
-"the system's video input (if there is one)."
-msgstr ""
-"Должны ли заставки-хранители, манипулирующие изображениями, работать с "
-"изображениями, захваченными с системного видео входа (если таковой имеется)."
-
-#: driver/demo-Gtk-widgets.c:1186
-msgid "Grab Video Frames"
-msgstr "Захватывать видео кадры"
-
-#: driver/demo-Gtk-widgets.c:1201 driver/xscreensaver-demo.glade2.h:66
-msgid ""
-"Whether the image-manipulating modes should operate on random images loaded "
-"from disk."
-msgstr ""
-"Должны ли заставки-хранители, манипулирующим изображениями, работать со "
-"случайными изображениями, загруженными с диска."
-
-#: driver/demo-Gtk-widgets.c:1203
-msgid "Choose Random Image:"
-msgstr "Выбирать случайное изображение:"
-
-#: driver/demo-Gtk-widgets.c:1236 driver/xscreensaver-demo.glade2.h:53
-msgid "The directory from which images will be randomly chosen."
-msgstr "Каталог, из которого случайным образом будут выбираться изображения."
-
-#: driver/demo-Gtk-widgets.c:1238
-msgid "Browse"
-msgstr "Обзор"
-
-#: driver/demo-Gtk-widgets.c:1246 driver/demo-Gtk-widgets.c:1599
-#: driver/xscreensaver-demo.glade2.h:2
-msgid "Advanced"
-msgstr "Расширенные"
-
-#: driver/demo-Gtk-widgets.c:1444
-msgid "XScreenSaver: Mode-Specific Settings"
-msgstr ""
-
-#: driver/demo-Gtk-widgets.c:1466 driver/xscreensaver-demo.glade2.h:41
-msgid "Settings"
-msgstr "Настройки"
-
-#: driver/demo-Gtk-widgets.c:1495 driver/xscreensaver-demo.glade2.h:43
-msgid "Standard"
-msgstr "Стандартные"
-
-#: driver/demo-Gtk-widgets.c:1532
-msgid "Visual:"
-msgstr "Оптический класс:"
-
-#: driver/demo-Gtk-widgets.c:1550 driver/demo-Gtk-widgets.c:1573
-#: driver/demo-Gtk.c:1695 driver/demo-Gtk.c:3252
-#: driver/xscreensaver-demo.glade2.h:3
-msgid "Any"
-msgstr "Любой"
-
-#: driver/demo-Gtk-widgets.c:1551 driver/xscreensaver-demo.glade2.h:4
-msgid "Best"
-msgstr "Наилучший"
-
-#: driver/demo-Gtk-widgets.c:1552 driver/xscreensaver-demo.glade2.h:8
-msgid "Default"
-msgstr "По умолчанию"
-
-#: driver/demo-Gtk-widgets.c:1553 driver/xscreensaver-demo.glade2.h:9
-msgid "Default-N"
-msgstr "По умолчанию-N"
-
-#: driver/demo-Gtk-widgets.c:1554 driver/xscreensaver-demo.glade2.h:18
-msgid "GL"
-msgstr "GL"
-
-#: driver/demo-Gtk-widgets.c:1555 driver/xscreensaver-demo.glade2.h:54
-msgid "TrueColor"
-msgstr "TrueColor"
-
-#: driver/demo-Gtk-widgets.c:1556 driver/xscreensaver-demo.glade2.h:38
-msgid "PseudoColor"
-msgstr "PseudoColor"
-
-#: driver/demo-Gtk-widgets.c:1557 driver/xscreensaver-demo.glade2.h:44
-msgid "StaticGray"
-msgstr "StaticGray"
-
-#: driver/demo-Gtk-widgets.c:1558 driver/xscreensaver-demo.glade2.h:22
-msgid "GrayScale"
-msgstr "GrayScale"
-
-#: driver/demo-Gtk-widgets.c:1559 driver/xscreensaver-demo.glade2.h:12
-msgid "DirectColor"
-msgstr "DirectColor"
-
-#: driver/demo-Gtk-widgets.c:1560 driver/xscreensaver-demo.glade2.h:6
-#: hacks/config/fuzzyflakes.xml.h:3
-msgid "Color"
-msgstr "Color"
-
-#: driver/demo-Gtk-widgets.c:1561 driver/xscreensaver-demo.glade2.h:21
-msgid "Gray"
-msgstr "Gray"
-
-#: driver/demo-Gtk-widgets.c:1562 driver/xscreensaver-demo.glade2.h:32
-msgid "Mono"
-msgstr "Mono"
-
-#: driver/demo-Gtk-widgets.c:1572
-msgid ""
-"The X visual type that this demo will require.  If that visual is available "
-"it will be used, otherwise, this demo will not be run."
-msgstr ""
-
-#: driver/demo-Gtk-widgets.c:1575
-msgid "Command Line:"
-msgstr "Командная строка:"
-
-#: driver/demo-Gtk-widgets.c:1647
-msgid "Documentation..."
-msgstr "Документация..."
-
-#: driver/demo-Gtk-widgets.c:1655
-msgid "Click here to read the manual for this display mode, if it has one."
-msgstr ""
-"Показать документацию на данную заставку-хранитель, если, конечно, эта "
-"документация существует и доступна."
-
-#: driver/demo-Gtk-widgets.c:1680
-msgid "Advanced >>"
-msgstr "Расширенные >>"
-
-#: driver/demo-Gtk-widgets.c:1688
-msgid "Edit the command line directly."
-msgstr "Редактировать командную строку напрямую."
-
-#: driver/demo-Gtk-widgets.c:1690
-msgid "Standard <<"
-msgstr "Стандартные <<"
-
-#: driver/demo-Gtk-widgets.c:1698
-msgid "Back to the graphical configuration options."
-msgstr "Обратно к управлению параметрами через графический интерфейс."
-
-#: driver/demo-Gtk-widgets.c:1709 driver/demo-Gtk.c:832
-msgid "OK"
-msgstr "OK"
+msgstr "Выберите файл"
 
-#: driver/demo-Gtk-widgets.c:1718
-msgid "Cancel"
-msgstr "Отменить"
-
-#: driver/demo-Gtk.c:692 driver/demo-Gtk.c:4282
+#: ../driver/demo-Gtk.c:755 ../driver/demo-Gtk.c:4484
 #, c-format
 msgid ""
 "Warning:\n"
@@ -526,11 +35,15 @@ msgstr ""
 "XScreenSaver демон, похоже, не запущен\n"
 "для экрана \"%s\".  Запустить его сейчас?"
 
-#: driver/demo-Gtk.c:740
-msgid "For updates, check http://www.jwz.org/xscreensaver/"
-msgstr "Для обновлений см. http://www.jwz.org/xscreensaver/"
+#: ../driver/demo-Gtk.c:804
+msgid "For updates, check https://www.jwz.org/xscreensaver/"
+msgstr "Для обновлений см. https://www.jwz.org/xscreensaver/"
+
+#: ../driver/demo-Gtk.c:902
+msgid "OK"
+msgstr "OK"
 
-#: driver/demo-Gtk.c:870
+#: ../driver/demo-Gtk.c:940
 msgid ""
 "Error:\n"
 "\n"
@@ -540,7 +53,7 @@ msgstr ""
 "\n"
 "URL для файлов помощи не указан.\n"
 
-#: driver/demo-Gtk.c:967
+#: ../driver/demo-Gtk.c:1037
 msgid ""
 "Error:\n"
 "\n"
@@ -549,10 +62,10 @@ msgid ""
 msgstr ""
 "Ошибка:\n"
 "\n"
-"Демон xscreensaver не запущен или запущен не правильно.\n"
+"Демон xscreensaver не запущен или запущен неправильно.\n"
 "\n"
 
-#: driver/demo-Gtk.c:979
+#: ../driver/demo-Gtk.c:1049
 msgid ""
 "You are running as root.  This usually means that xscreensaver\n"
 "was unable to contact your X server because access control is\n"
@@ -570,12 +83,28 @@ msgid ""
 "You shouldn't run X as root. Instead, you should log in as a\n"
 "normal user, and `su' as necessary."
 msgstr ""
+"Вы работаете под root.  Обычно это означает, что xscreensaver\n"
+"не смог подключиться к вашему X-серверу из-за включенного\n"
+"контроля доступа.  Попробуйте выполнить эту команду:\n"
+"\n"
+"                        xhost +localhost\n"
+"\n"
+"а затем выбрать `Файл / Перезапустить демон'.\n"
+"\n"
+"Важно: отключение контроля доступа позволит любому пользователю\n"
+"вашего компьютера получить доступ к вашему экрану, что может быть\n"
+"расценено как проблема с безопасностью.  Пожалуйста, прочитайте\n"
+"мануал xscreensaver, а также вопросы и ответы для более подробной\n"
+"информации.\n"
+"\n"
+"Не стоит запускать X от root. Вместо этого, вам нужно войти в\n"
+"систему от обычного пользователя, и `su' при необходимости."
 
-#: driver/demo-Gtk.c:995
+#: ../driver/demo-Gtk.c:1065
 msgid "Please check your $PATH and permissions."
 msgstr "Проверьте значение переменной $PATH и права доступа."
 
-#: driver/demo-Gtk.c:1033
+#: ../driver/demo-Gtk.c:1103
 msgid ""
 "Error:\n"
 "\n"
@@ -585,7 +114,7 @@ msgstr ""
 "\n"
 "Не удалось определить имя инициализационного файла!\n"
 
-#: driver/demo-Gtk.c:1038
+#: ../driver/demo-Gtk.c:1108
 #, c-format
 msgid ""
 "Error:\n"
@@ -596,7 +125,7 @@ msgstr ""
 "\n"
 "Не удалось записать %s\n"
 
-#: driver/demo-Gtk.c:1101
+#: ../driver/demo-Gtk.c:1171
 msgid ""
 "Error:\n"
 "\n"
@@ -606,7 +135,7 @@ msgstr ""
 "\n"
 "Ресурс `manualCommand' не установлен."
 
-#: driver/demo-Gtk.c:1284
+#: ../driver/demo-Gtk.c:1354
 #, c-format
 msgid ""
 "Error:\n"
@@ -617,7 +146,12 @@ msgstr ""
 "\n"
 "Невозможно определить формат времени: \"%s\"\n"
 
-#: driver/demo-Gtk.c:1991
+#: ../driver/demo-Gtk.c:1793 ../driver/demo-Gtk.c:3370
+#: ../driver/xscreensaver-demo.glade2.in.h:102
+msgid "Any"
+msgstr "Любой"
+
+#: ../driver/demo-Gtk.c:2091
 #, c-format
 msgid ""
 "Error:\n"
@@ -628,8 +162,8 @@ msgstr ""
 "\n"
 "Каталога не существует: \"%s\"\n"
 
-#: driver/demo-Gtk.c:2021 driver/demo-Gtk.c:2052
-#, fuzzy, c-format
+#: ../driver/demo-Gtk.c:2121 ../driver/demo-Gtk.c:2152
+#, c-format
 msgid ""
 "Error:\n"
 "\n"
@@ -637,30 +171,42 @@ msgid ""
 msgstr ""
 "Ошибка:\n"
 "\n"
-"Ð\9aаÑ\82алога не существует: \"%s\"\n"
+"Файла не существует: \"%s\"\n"
 
-#: driver/demo-Gtk.c:2877
+#: ../driver/demo-Gtk.c:2533
+msgid "Use"
+msgstr "Использовать"
+
+#: ../driver/demo-Gtk.c:2543
+msgid "Screen Saver"
+msgstr "Хранитель экрана"
+
+#: ../driver/demo-Gtk.c:2995
 msgid "Descriptions not available: no XML support compiled in."
 msgstr "Описание недоступно: поддержка XML не была включена при компиляции."
 
-#: driver/demo-Gtk.c:2882
+#: ../driver/demo-Gtk.c:3000
 msgid "No description available."
 msgstr "Описание отсутствует."
 
-#: driver/demo-Gtk.c:3204
+#: ../driver/demo-Gtk.c:3322
 msgid "Blank Screen"
 msgstr "Пустой экран"
 
-#: driver/demo-Gtk.c:3210
+#: ../driver/demo-Gtk.c:3328
 msgid "Screen Saver Disabled"
-msgstr "Хранитель экрана запрещен"
+msgstr "Хранитель экрана отключен"
+
+#: ../driver/demo-Gtk.c:3351
+msgid "Preview"
+msgstr "Предпросмотр"
 
-#: driver/demo-Gtk.c:3243
+#: ../driver/demo-Gtk.c:3361
 #, c-format
 msgid "%s: %.100s Settings"
-msgstr ""
+msgstr "Настройки %s: %.100s"
 
-#: driver/demo-Gtk.c:3407
+#: ../driver/demo-Gtk.c:3525
 #, c-format
 msgid ""
 "Warning:\n"
@@ -671,23 +217,23 @@ msgstr ""
 "\n"
 "Файл \"%s\" изменился и будет перезагружен.\n"
 
-#: driver/demo-Gtk.c:3492
+#: ../driver/demo-Gtk.c:3612
 msgid "No Preview"
 msgstr "Предпросмотр не"
 
-#: driver/demo-Gtk.c:3492
+#: ../driver/demo-Gtk.c:3612
 msgid "Available"
 msgstr "доступен"
 
-#: driver/demo-Gtk.c:3493
+#: ../driver/demo-Gtk.c:3613
 msgid "Not"
 msgstr ""
 
-#: driver/demo-Gtk.c:3493
+#: ../driver/demo-Gtk.c:3613
 msgid "Installed"
 msgstr ""
 
-#: driver/demo-Gtk.c:4292
+#: ../driver/demo-Gtk.c:4494
 #, c-format
 msgid ""
 "Warning:\n"
@@ -705,8 +251,22 @@ msgid ""
 "\n"
 "Restart the xscreensaver daemon now?\n"
 msgstr ""
+"Внимание!\n"
+"\n"
+"%s запущен от имени пользователя \"%s\" на хосте \"%s\".\n"
+"Но xscreensaver управляет дисплеем \"%s\"\n"
+"и запущен от имени пользователя \"%s\" на хосте \"%s\".\n"
+"\n"
+"Это различные пользователи, и они не смогут читать/записывать\n"
+"один и тот же файл ~/.xscreensaver , и %s\n"
+"будет работать некорректно.\n"
+"\n"
+"Вам нужно перезапустить либо %s от \"%s\", либо\n"
+"xscreensaver от \"%s\".\n"
+"\n"
+"Перезапустить демон xscreensaver сейчас?\n"
 
-#: driver/demo-Gtk.c:4317
+#: ../driver/demo-Gtk.c:4519
 #, c-format
 msgid ""
 "Warning:\n"
@@ -721,8 +281,19 @@ msgid ""
 "\n"
 "Restart the daemon on \"%s\" as \"%s\" now?\n"
 msgstr ""
+"Внимание!\n"
+"\n"
+"%s запущен от имени пользователя \"%s\" на хосте \"%s\".\n"
+"Но xscreensaver управляет дисплеем \"%s\"\n"
+"и запущен от имени пользователя \"%s\" на хосте \"%s\".\n"
+"\n"
+"Если у этих двух машин нет общей файловой системы (т.е.,\n"
+"если они не видят один и тот же файл ~%s/.xscreensaver), то\n"
+"%s будет работать некорректно.\n"
+"\n"
+"Перезапустить демон на \"%s\" от \"%s\" сейчас?\n"
 
-#: driver/demo-Gtk.c:4339
+#: ../driver/demo-Gtk.c:4541
 #, c-format
 msgid ""
 "Warning:\n"
@@ -733,8400 +304,9764 @@ msgid ""
 "\n"
 "Restart the xscreensaver daemon now?\n"
 msgstr ""
+"Внимание!\n"
+"\n"
+"Это %s версия %s.\n"
+"Но xscreensaver управляет дисплеем \"%s\"\n"
+"версии %s.  Это может вызвать проблемы.\n"
+"\n"
+"Перезапустить демон xscreensaver сейчас?\n"
+
+#: ../driver/demo-Gtk.c:4569
+msgid ""
+"Warning:\n"
+"\n"
+"The GNOME screensaver daemon appears to be running.\n"
+"It must be stopped for XScreenSaver to work properly.\n"
+"\n"
+"Stop the GNOME screen saver daemon now?\n"
+msgstr ""
+"Внимание!\n"
+"\n"
+"Запущен демон хранителя экрана GNOME.\n"
+"Его нужно остановить для корректной работы XScreenSaver.\n"
+"\n"
+"Остановить демон хранителя экрана GNOME сейчас?\n"
 
-#: driver/demo-Gtk.c:4800
+#: ../driver/demo-Gtk.c:4578
+msgid ""
+"Warning:\n"
+"\n"
+"The KDE screen saver daemon appears to be running.\n"
+"It must be stopped for XScreenSaver to work properly.\n"
+"\n"
+"Stop the KDE screen saver daemon now?\n"
+msgstr ""
+"Внимание!\n"
+"\n"
+"Запущен демон хранителя экрана KDE.\n"
+"Его нужно остановить для корректной работы XScreenSaver.\n"
+"\n"
+"Остановить демон хранителя экрана KDE сейчас?\n"
+
+#: ../driver/demo-Gtk.c:5030
 #, c-format
 msgid "%s: unknown option: %s\n"
 msgstr "%s: неизвестный параметр: %s\n"
 
-#: driver/demo-Gtk.c:4865
-#, fuzzy
+#: ../driver/demo-Gtk.c:5095
 msgid "Screensaver Preferences"
 msgstr "Хранитель экрана"
 
-#: driver/screensaver-properties.desktop.in.h:1
-msgid "Change screensaver properties"
+#: ../driver/demo-Gtk.c:5297
+msgid ""
+"Warning:\n"
+"\n"
+"This version of xscreensaver is VERY OLD!\n"
+"Please upgrade!\n"
+"\n"
+"https://www.jwz.org/xscreensaver/\n"
+"\n"
+"(If this is the latest version that your distro ships, then\n"
+"your distro is doing you a disservice. Build from source.)\n"
 msgstr ""
+"Внимание!\n"
+"\n"
+"Эта версия xscreensaver ОЧЕНЬ СТАРАЯ!\n"
+"Пожалуйста, обновите ее!\n"
+"\n"
+"https://www.jwz.org/xscreensaver/\n"
+"\n"
+"(Если это последняя версия программы, поставляемая вашим дистрибутивом, \n"
+"то он оказывает вам плохую услугу. Соберите ее из исходного кода.)\n"
 
-#: driver/screensaver-properties.desktop.in.h:2
+#: ../driver/screensaver-properties.desktop.in.h:1
 msgid "Screensaver"
 msgstr "Хранитель экрана"
 
-#: driver/xscreensaver-demo.glade2.h:1
-msgid "*"
-msgstr "*"
-
-#: driver/xscreensaver-demo.glade2.h:5
-msgid "Choose _Random Image:"
-msgstr "Выбирать случайное изображение:"
-
-#: driver/xscreensaver-demo.glade2.h:14
-msgid "F_ade Duration"
-msgstr "_Продолжительность перехода"
-
-#: driver/xscreensaver-demo.glade2.h:15
-msgid "Fade from Black When _Unblanking"
-msgstr "Переход от черного при _де-активации"
-
-#: driver/xscreensaver-demo.glade2.h:16
-msgid "Fade to Black when _Blanking"
-msgstr "Переход к черному при _активации"
-
-#: driver/xscreensaver-demo.glade2.h:17
-#, fuzzy
-msgid "Fading and Colormaps"
-msgstr "Цветовые палитры"
-
-#: driver/xscreensaver-demo.glade2.h:19
-msgid "Grab Desktop _Images"
-msgstr "Захватывать _изображения с рабочего стола"
-
-#: driver/xscreensaver-demo.glade2.h:20
-msgid "Grab _Video Frames"
-msgstr "Захватывать _видео кадры"
-
-#: driver/xscreensaver-demo.glade2.h:23
-msgid "How long after the screen blanks until a password will be required."
-msgstr ""
-
-#: driver/xscreensaver-demo.glade2.h:24
-#, fuzzy
-msgid "How long before the screen saver activates."
-msgstr "Как долго должен длиться переход \"к черному\" или \"от черного\"."
-
-#: driver/xscreensaver-demo.glade2.h:25
-msgid ""
-"How long each display mode should run before choosing a new one (in Random "
-"mode.)"
-msgstr ""
-
-#: driver/xscreensaver-demo.glade2.h:27
-#, fuzzy
-msgid "How long until the monitor goes completely black."
+#: ../driver/screensaver-properties.desktop.in.h:2
+msgid "Change screensaver properties"
 msgstr ""
-"Через какое время монитор должен начать показывать только \"черный экран\"."
-
-#: driver/xscreensaver-demo.glade2.h:31
-msgid "Install _Colormap"
-msgstr "Устанавливать _цветовую палитру"
 
-#: driver/xscreensaver-demo.glade2.h:33
-msgid "Never blank the screen or power down the monitor."
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:1
+msgid "XScreenSaver"
+msgstr "Хранитель экрана"
 
-#: driver/xscreensaver-demo.glade2.h:34
-msgid ""
-"No Preview\n"
-"Available"
-msgstr ""
-"Предпросмотр\n"
-"недоступен"
+#: ../driver/xscreensaver-demo.glade2.in.h:2
+msgid "_File"
+msgstr "_Файл"
 
-#: driver/xscreensaver-demo.glade2.h:36
-msgid ""
-"Not\n"
-"Installed"
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:3
+msgid "_Blank Screen Now"
+msgstr "_Активировать хранитель экрана немедленно"
 
-#: driver/xscreensaver-demo.glade2.h:42
-msgid "Stand_by After"
-msgstr "Режим Standby через"
+#: ../driver/xscreensaver-demo.glade2.in.h:4
+msgid "_Lock Screen Now"
+msgstr "_Заблокировать экран немедленно"
 
-#: driver/xscreensaver-demo.glade2.h:45
-msgid "Sus_pend After"
-msgstr "Режим Suspend через"
+#: ../driver/xscreensaver-demo.glade2.in.h:5
+msgid "_Kill Daemon"
+msgstr "_Убить демон"
 
-#: driver/xscreensaver-demo.glade2.h:46
-#, fuzzy
-msgid "Text Manipulation"
-msgstr "Манипуляции с изображениями"
+#: ../driver/xscreensaver-demo.glade2.in.h:6
+msgid "_Restart Daemon"
+msgstr "_Перезапустить демон"
 
-#: driver/xscreensaver-demo.glade2.h:47
-msgid "Text _file"
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:7
+msgid "_Quit"
+msgstr "_Выход"
 
-#: driver/xscreensaver-demo.glade2.h:48
-msgid ""
-"Text-displaying modes will display the contents of this URL (HTML or RSS)."
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:8
+msgid "_Help"
+msgstr "_Справка"
 
-#: driver/xscreensaver-demo.glade2.h:49
-msgid "Text-displaying modes will display the contents of this file."
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:9
+msgid "_About..."
+msgstr "_О программе..."
 
-#: driver/xscreensaver-demo.glade2.h:50
-msgid "Text-displaying modes will display the local host name, date, and time."
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:10
+msgid "_Documentation..."
+msgstr "_Документация..."
 
-#: driver/xscreensaver-demo.glade2.h:51
-msgid "Text-displaying modes will display the output of this program."
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:11
+msgid "_Cycle After"
+msgstr "С_мена через"
 
-#: driver/xscreensaver-demo.glade2.h:52
-msgid "Text-displaying modes will display the text typed here."
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:12
+msgid "Whether a password should be required to un-blank the screen."
+msgstr "Должен ли требоваться пароль для разблокировки экрана."
 
-#: driver/xscreensaver-demo.glade2.h:55
-msgid ""
-"Very few (or no) screen savers appear to be available.\n"
-"\n"
-"This probably means that the \"xscreensaver-extras\" and\n"
-"\"xscreensaver-gl-extras\" packages are not installed."
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:13
+msgid "_Lock Screen After  "
+msgstr "_Заблокировать экран через  "
 
-#: driver/xscreensaver-demo.glade2.h:59
-msgid "When idle or locked, blacken the screen only."
+#: ../driver/xscreensaver-demo.glade2.in.h:14
+msgid "Lock Screen"
 msgstr ""
 
-#: driver/xscreensaver-demo.glade2.h:60
-msgid ""
-"When idle or locked, choose a random display mode from among the checked "
-"items in the list below."
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:15
+msgid "How long before the screen saver activates."
+msgstr "Время до запуска хранителя экрана."
 
-#: driver/xscreensaver-demo.glade2.h:61
-msgid ""
-"When idle or locked, choose a random display mode from among the checked "
-"items in the list below.  Run that same mode on each monitor."
+#: ../driver/xscreensaver-demo.glade2.in.h:16
+msgid "How long after the screen blanks until a password will be required."
 msgstr ""
+"Время после очистки экрана, через которое для входа в систему требуется "
+"пароль."
 
-#: driver/xscreensaver-demo.glade2.h:62
-msgid "When idle or locked, run the display mode selected below."
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:17
+msgid "Lock Screen After"
+msgstr "Запирать экран через"
 
-#: driver/xscreensaver-demo.glade2.h:65
-#, fuzzy
+#: ../driver/xscreensaver-demo.glade2.in.h:18
 msgid ""
-"Whether the image-manipulating modes should operate on images captured from "
-"the system's video input (if there is one.)"
+"How long each display mode should run before choosing a new one (in Random "
+"mode.)"
 msgstr ""
-"Ð\94олжнÑ\8b Ð»Ð¸ Ð·Ð°Ñ\81Ñ\82авки-Ñ\85Ñ\80аниÑ\82ели, Ð¼Ð°Ð½Ð¸Ð¿Ñ\83лиÑ\80Ñ\83Ñ\8eÑ\89ие Ð¸Ð·Ð¾Ð±Ñ\80ажениÑ\8fми, Ñ\80абоÑ\82аÑ\82Ñ\8c Ñ\81 "
-"изображениями, захваченными с системного видео входа (если таковой имеется)."
+"Ð\92Ñ\80емÑ\8f Ñ\80абоÑ\82Ñ\8b ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ Ñ\80ежима Ð´Ð¸Ñ\81плеÑ\8f Ð´Ð¾ Ð²Ñ\8bбоÑ\80а Ð½Ð¾Ð²Ð¾Ð³Ð¾ (в Ñ\80ежиме "
+"\"Случайный хранитель экрана\".)"
 
-#: driver/xscreensaver-demo.glade2.h:73
-msgid "_Advanced"
-msgstr "Рас_ширенные"
-
-#: driver/xscreensaver-demo.glade2.h:74
-msgid "_Advanced >>"
-msgstr "Рас_ширенные >>"
+#: ../driver/xscreensaver-demo.glade2.in.h:19
+msgid "minutes"
+msgstr "минут(ы)"
 
-#: driver/xscreensaver-demo.glade2.h:75
+#: ../driver/xscreensaver-demo.glade2.in.h:20
 msgid "_Blank After"
-msgstr "_Активация после"
-
-#: driver/xscreensaver-demo.glade2.h:77
-#, fuzzy
-msgid "_Blank Screen Only"
-msgstr "Только очищать экран"
-
-#: driver/xscreensaver-demo.glade2.h:78
-msgid "_Browse"
-msgstr "_Обзор"
-
-#: driver/xscreensaver-demo.glade2.h:79
-msgid "_Command Line:"
-msgstr "_Командная строка:"
+msgstr "_Активировать через"
 
-#: driver/xscreensaver-demo.glade2.h:80
-msgid "_Cycle After"
-msgstr "С_мена через"
-
-#: driver/xscreensaver-demo.glade2.h:81
-#, fuzzy
-msgid "_Disable Screen Saver"
-msgstr "Запретить хранитель экрана"
-
-#: driver/xscreensaver-demo.glade2.h:82
-msgid "_Display Modes"
-msgstr "Режимы _экрана"
-
-#: driver/xscreensaver-demo.glade2.h:86
-msgid "_Host Name and Time"
+#: ../driver/xscreensaver-demo.glade2.in.h:21
+msgid ""
+"Demo the selected screen saver in full-screen mode (click the mouse to "
+"return.)"
 msgstr ""
+"Показать выбранный хранитель в полноэкранном режиме (возврат обратно по "
+"щелчку мыши)."
 
-#: driver/xscreensaver-demo.glade2.h:88
-#, fuzzy
-msgid "_Lock Screen After  "
-msgstr "_Запирать экран после"
-
-#: driver/xscreensaver-demo.glade2.h:90
-msgid "_Mode:"
-msgstr "_Режим:"
-
-#: driver/xscreensaver-demo.glade2.h:91
-msgid "_Off After"
-msgstr "_Выключать через"
-
-#: driver/xscreensaver-demo.glade2.h:92
-#, fuzzy
-msgid "_Only One Screen Saver"
-msgstr "Один постоянный хранитель экрана"
-
-#: driver/xscreensaver-demo.glade2.h:93
-msgid "_Power Management Enabled"
-msgstr "_Управление питанием разрешено"
-
-#: driver/xscreensaver-demo.glade2.h:94
+#: ../driver/xscreensaver-demo.glade2.in.h:22
 msgid "_Preview"
 msgstr "_Предпросмотр"
 
-#: driver/xscreensaver-demo.glade2.h:95
-msgid "_Program"
-msgstr ""
-
-#: driver/xscreensaver-demo.glade2.h:96
-msgid "_Quit"
-msgstr "_Выход"
-
-#: driver/xscreensaver-demo.glade2.h:97
-#, fuzzy
-msgid "_Random Screen Saver"
-msgstr "Случайный хранитель экрана"
-
-#: driver/xscreensaver-demo.glade2.h:99
-#, fuzzy
-msgid "_Same Random Savers"
-msgstr "Случайный хранитель экрана"
-
-#: driver/xscreensaver-demo.glade2.h:100
-msgid "_Settings..."
-msgstr "_Настройки..."
-
-#: driver/xscreensaver-demo.glade2.h:101
-msgid "_Standard <<"
-msgstr "_Стандартные <<"
-
-#: driver/xscreensaver-demo.glade2.h:102
-#, fuzzy
-msgid "_Text"
-msgstr "Наилучший"
-
-#: driver/xscreensaver-demo.glade2.h:103
-msgid "_URL"
-msgstr ""
-
-#: driver/xscreensaver-demo.glade2.h:104
-msgid "_Visual:"
-msgstr "О_птический класс:"
-
-#: driver/xscreensaver-demo.glade2.h:105
-msgid "dialog1"
-msgstr ""
-
-#: driver/xscreensaver-demo.glade2.h:107
-#, fuzzy
-msgid "no preview"
-msgstr "Предпросмотр"
-
-#: driver/xscreensaver-demo.glade2.h:108
-msgid "not installed"
-msgstr ""
-
-#: driver/xscreensaver-demo.glade2.h:109
-#, fuzzy
-msgid "nothing"
-msgstr "Длинный"
+#: ../driver/xscreensaver-demo.glade2.in.h:23
+msgid "Customization and explanation of the selected screen saver."
+msgstr "Настройка и объяснение выбранного хранителя экрана."
 
-#: driver/xscreensaver-demo.glade2.h:110
-#, fuzzy
-msgid "preview"
-msgstr "Предпросмотр"
+#: ../driver/xscreensaver-demo.glade2.in.h:24
+msgid "_Settings..."
+msgstr "_Настройки..."
 
-#: hacks/config/anemone.xml.h:1
-msgid "Anemone"
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:25
+msgid "_Mode:"
+msgstr "_Режим:"
 
-#: hacks/config/anemone.xml.h:2 hacks/config/fuzzyflakes.xml.h:1
-msgid "Arms"
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:26
+msgid "Never blank the screen or power down the monitor."
+msgstr "Никогда не гасить экран и не отключать монитор."
 
-#: hacks/config/anemone.xml.h:3 hacks/config/anemotaxis.xml.h:5
-#: hacks/config/ant.xml.h:6 hacks/config/antinspect.xml.h:4
-#: hacks/config/antmaze.xml.h:3 hacks/config/antspotlight.xml.h:3
-#: hacks/config/apollonian.xml.h:5 hacks/config/atlantis.xml.h:4
-#: hacks/config/attraction.xml.h:8 hacks/config/atunnel.xml.h:3
-#: hacks/config/barcode.xml.h:4 hacks/config/blaster.xml.h:3
-#: hacks/config/blinkbox.xml.h:5 hacks/config/blitspin.xml.h:4
-#: hacks/config/blocktube.xml.h:4 hacks/config/boing.xml.h:2
-#: hacks/config/bouboule.xml.h:3 hacks/config/bouncingcow.xml.h:6
-#: hacks/config/boxed.xml.h:6 hacks/config/boxfit.xml.h:8
-#: hacks/config/braid.xml.h:4 hacks/config/bubble3d.xml.h:4
-#: hacks/config/bubbles.xml.h:8 hacks/config/bumps.xml.h:3
-#: hacks/config/cage.xml.h:2 hacks/config/carousel.xml.h:5
-#: hacks/config/ccurve.xml.h:7 hacks/config/celtic.xml.h:3
-#: hacks/config/circuit.xml.h:4 hacks/config/cloudlife.xml.h:3
-#: hacks/config/compass.xml.h:3 hacks/config/coral.xml.h:7
-#: hacks/config/critical.xml.h:3 hacks/config/crystal.xml.h:6
-#: hacks/config/cube21.xml.h:6 hacks/config/cubenetic.xml.h:8
-#: hacks/config/cubestorm.xml.h:4 hacks/config/cynosure.xml.h:4
-#: hacks/config/dangerball.xml.h:3 hacks/config/decayscreen.xml.h:2
-#: hacks/config/deluxe.xml.h:4 hacks/config/demon.xml.h:4
-#: hacks/config/discrete.xml.h:2 hacks/config/distort.xml.h:4
-#: hacks/config/drift.xml.h:3 hacks/config/endgame.xml.h:3
-#: hacks/config/engine.xml.h:8 hacks/config/epicycle.xml.h:5
-#: hacks/config/eruption.xml.h:5 hacks/config/euler2d.xml.h:3
-#: hacks/config/extrusion.xml.h:3 hacks/config/fadeplot.xml.h:4
-#: hacks/config/fireworkx.xml.h:3 hacks/config/flag.xml.h:2
-#: hacks/config/flame.xml.h:6 hacks/config/flipflop.xml.h:1
-#: hacks/config/flipscreen3d.xml.h:1 hacks/config/fliptext.xml.h:3
-#: hacks/config/flow.xml.h:2 hacks/config/fluidballs.xml.h:5
-#: hacks/config/flyingtoasters.xml.h:5 hacks/config/fontglide.xml.h:4
-#: hacks/config/forest.xml.h:1 hacks/config/fuzzyflakes.xml.h:7
-#: hacks/config/galaxy.xml.h:3 hacks/config/gears.xml.h:2
-#: hacks/config/gflux.xml.h:6 hacks/config/glblur.xml.h:4
-#: hacks/config/glforestfire.xml.h:4 hacks/config/glhanoi.xml.h:3
-#: hacks/config/glknots.xml.h:3 hacks/config/glmatrix.xml.h:8
-#: hacks/config/glplanet.xml.h:2 hacks/config/glsnake.xml.h:6
-#: hacks/config/gltext.xml.h:4 hacks/config/goop.xml.h:4
-#: hacks/config/grav.xml.h:2 hacks/config/greynetic.xml.h:1
-#: hacks/config/halo.xml.h:2 hacks/config/hopalong.xml.h:9
-#: hacks/config/hyperball.xml.h:2 hacks/config/hypercube.xml.h:2
-#: hacks/config/hypertorus.xml.h:6 hacks/config/ifs.xml.h:4
-#: hacks/config/interaggregate.xml.h:1 hacks/config/interference.xml.h:7
-#: hacks/config/intermomentary.xml.h:1 hacks/config/jigglypuff.xml.h:6
-#: hacks/config/jigsaw.xml.h:3 hacks/config/juggle.xml.h:2
-#: hacks/config/juggler3d.xml.h:2 hacks/config/julia.xml.h:2
-#: hacks/config/kaleidescope.xml.h:2 hacks/config/klein.xml.h:2
-#: hacks/config/kumppa.xml.h:3 hacks/config/lament.xml.h:2
-#: hacks/config/laser.xml.h:3 hacks/config/lavalite.xml.h:10
-#: hacks/config/lightning.xml.h:1 hacks/config/lisa.xml.h:2
-#: hacks/config/lissie.xml.h:3 hacks/config/lmorph.xml.h:3
-#: hacks/config/loop.xml.h:1 hacks/config/maze.xml.h:4
-#: hacks/config/memscroller.xml.h:5 hacks/config/menger.xml.h:3
-#: hacks/config/metaballs.xml.h:4 hacks/config/mirrorblob.xml.h:11
-#: hacks/config/mismunch.xml.h:2 hacks/config/moebius.xml.h:3
-#: hacks/config/moire2.xml.h:2 hacks/config/molecule.xml.h:11
-#: hacks/config/morph3d.xml.h:3 hacks/config/mountain.xml.h:2
-#: hacks/config/munch.xml.h:3 hacks/config/nerverot.xml.h:9
-#: hacks/config/noof.xml.h:2 hacks/config/pacman.xml.h:1
-#: hacks/config/penetrate.xml.h:3 hacks/config/penrose.xml.h:3
-#: hacks/config/petri.xml.h:5 hacks/config/phosphor.xml.h:4
-#: hacks/config/piecewise.xml.h:4 hacks/config/pinion.xml.h:5
-#: hacks/config/pipes.xml.h:5 hacks/config/polyhedra.xml.h:17
-#: hacks/config/polyominoes.xml.h:2 hacks/config/polytopes.xml.h:11
-#: hacks/config/pong.xml.h:1 hacks/config/popsquares.xml.h:3
-#: hacks/config/providence.xml.h:2 hacks/config/pulsar.xml.h:11
-#: hacks/config/pyro.xml.h:4 hacks/config/qix.xml.h:7
-#: hacks/config/queens.xml.h:1 hacks/config/rd-bomb.xml.h:9
-#: hacks/config/ripples.xml.h:4 hacks/config/rocks.xml.h:4
-#: hacks/config/rotor.xml.h:3 hacks/config/rubik.xml.h:3
-#: hacks/config/sballs.xml.h:4 hacks/config/shadebobs.xml.h:3
-#: hacks/config/sierpinski.xml.h:2 hacks/config/sierpinski3d.xml.h:2
-#: hacks/config/slidescreen.xml.h:2 hacks/config/slip.xml.h:2
-#: hacks/config/speedmine.xml.h:3 hacks/config/sphere.xml.h:2
-#: hacks/config/spheremonics.xml.h:5 hacks/config/spiral.xml.h:3
-#: hacks/config/spotlight.xml.h:2 hacks/config/sproingies.xml.h:2
-#: hacks/config/squiral.xml.h:4 hacks/config/stairs.xml.h:1
-#: hacks/config/starfish.xml.h:3 hacks/config/starwars.xml.h:6
-#: hacks/config/strange.xml.h:1 hacks/config/substrate.xml.h:7
-#: hacks/config/superquadrics.xml.h:4 hacks/config/swirl.xml.h:2
-#: hacks/config/t3d.xml.h:6 hacks/config/tangram.xml.h:2
-#: hacks/config/thornbird.xml.h:2 hacks/config/triangle.xml.h:1
-#: hacks/config/truchet.xml.h:1 hacks/config/twang.xml.h:3
-#: hacks/config/vines.xml.h:1 hacks/config/worm.xml.h:3
-#: hacks/config/wormhole.xml.h:2 hacks/config/xearth.xml.h:7
-#: hacks/config/xfishtank.xml.h:3 hacks/config/xflame.xml.h:4
-#: hacks/config/xjack.xml.h:1 hacks/config/xmatrix.xml.h:5
-#: hacks/config/xmountains.xml.h:13 hacks/config/xplanet.xml.h:8
-#: hacks/config/xrayswarm.xml.h:2 hacks/config/zoom.xml.h:2
-msgid "Fast"
-msgstr "Быстро"
+#: ../driver/xscreensaver-demo.glade2.in.h:27
+msgid "_Disable Screen Saver"
+msgstr "_Отключить хранитель экрана"
 
-#: hacks/config/anemone.xml.h:4 hacks/config/anemotaxis.xml.h:6
-#: hacks/config/blaster.xml.h:4 hacks/config/bouboule.xml.h:4
-#: hacks/config/boxed.xml.h:7 hacks/config/coral.xml.h:8
-#: hacks/config/cubenetic.xml.h:9 hacks/config/eruption.xml.h:6
-#: hacks/config/euler2d.xml.h:4 hacks/config/fiberlamp.xml.h:2
-#: hacks/config/flame.xml.h:7 hacks/config/fluidballs.xml.h:6
-#: hacks/config/fuzzyflakes.xml.h:8 hacks/config/kaleidescope.xml.h:3
-#: hacks/config/lisa.xml.h:3 hacks/config/pedal.xml.h:4
-#: hacks/config/petri.xml.h:7 hacks/config/qix.xml.h:8
-#: hacks/config/substrate.xml.h:8 hacks/config/thornbird.xml.h:3
-#: hacks/config/whirlwindwarp.xml.h:1 hacks/config/wormhole.xml.h:3
-#: hacks/config/xfishtank.xml.h:4
-msgid "Few"
-msgstr "Мало"
+#: ../driver/xscreensaver-demo.glade2.in.h:28
+msgid "When idle or locked, blacken the screen only."
+msgstr "Только гасить экран во время простоя или блокировки."
 
-#: hacks/config/anemone.xml.h:5 hacks/config/anemotaxis.xml.h:7
-#: hacks/config/ant.xml.h:9 hacks/config/apollonian.xml.h:7
-#: hacks/config/attraction.xml.h:18 hacks/config/blaster.xml.h:6
-#: hacks/config/bouboule.xml.h:5 hacks/config/braid.xml.h:7
-#: hacks/config/coral.xml.h:9 hacks/config/critical.xml.h:4
-#: hacks/config/crystal.xml.h:8 hacks/config/cubenetic.xml.h:13
-#: hacks/config/cynosure.xml.h:6 hacks/config/deco.xml.h:5
-#: hacks/config/deluxe.xml.h:6 hacks/config/demon.xml.h:6
-#: hacks/config/discrete.xml.h:4 hacks/config/drift.xml.h:9
-#: hacks/config/epicycle.xml.h:8 hacks/config/eruption.xml.h:12
-#: hacks/config/euler2d.xml.h:8 hacks/config/fadeplot.xml.h:6
-#: hacks/config/fiberlamp.xml.h:6 hacks/config/flag.xml.h:5
-#: hacks/config/flame.xml.h:11 hacks/config/flow.xml.h:7
-#: hacks/config/fluidballs.xml.h:13 hacks/config/forest.xml.h:3
-#: hacks/config/fuzzyflakes.xml.h:12 hacks/config/galaxy.xml.h:6
-#: hacks/config/grav.xml.h:4 hacks/config/halo.xml.h:4
-#: hacks/config/hopalong.xml.h:15 hacks/config/ifs.xml.h:8
-#: hacks/config/imsmap.xml.h:9 hacks/config/interference.xml.h:14
-#: hacks/config/julia.xml.h:6 hacks/config/kaleidescope.xml.h:5
-#: hacks/config/laser.xml.h:6 hacks/config/lightning.xml.h:3
-#: hacks/config/lisa.xml.h:5 hacks/config/lissie.xml.h:6
-#: hacks/config/loop.xml.h:4 hacks/config/metaballs.xml.h:6
-#: hacks/config/mismunch.xml.h:4 hacks/config/moire.xml.h:5
-#: hacks/config/moire2.xml.h:3 hacks/config/mountain.xml.h:4
-#: hacks/config/nerverot.xml.h:15 hacks/config/pedal.xml.h:6
-#: hacks/config/penrose.xml.h:4 hacks/config/petri.xml.h:11
-#: hacks/config/polyominoes.xml.h:5 hacks/config/qix.xml.h:14
-#: hacks/config/rd-bomb.xml.h:12 hacks/config/ripples.xml.h:8
-#: hacks/config/rocks.xml.h:5 hacks/config/rotor.xml.h:6
-#: hacks/config/shadebobs.xml.h:5 hacks/config/sierpinski.xml.h:4
-#: hacks/config/slip.xml.h:4 hacks/config/sphere.xml.h:3
-#: hacks/config/spiral.xml.h:6 hacks/config/squiral.xml.h:9
-#: hacks/config/starfish.xml.h:5 hacks/config/strange.xml.h:2
-#: hacks/config/swirl.xml.h:3 hacks/config/thornbird.xml.h:4
-#: hacks/config/triangle.xml.h:3 hacks/config/vines.xml.h:2
-#: hacks/config/whirlwindwarp.xml.h:4 hacks/config/worm.xml.h:4
-#: hacks/config/xearth.xml.h:12 hacks/config/xfishtank.xml.h:8
-msgid "Many"
-msgstr "Много"
+#: ../driver/xscreensaver-demo.glade2.in.h:29
+msgid "_Blank Screen Only"
+msgstr "_Только пустой экран"
 
-#: hacks/config/anemone.xml.h:6 hacks/config/ant.xml.h:11
-#: hacks/config/apollonian.xml.h:8 hacks/config/attraction.xml.h:19
-#: hacks/config/bouboule.xml.h:6 hacks/config/braid.xml.h:9
-#: hacks/config/critical.xml.h:5 hacks/config/crystal.xml.h:10
-#: hacks/config/cynosure.xml.h:7 hacks/config/deco.xml.h:8
-#: hacks/config/deluxe.xml.h:7 hacks/config/demon.xml.h:7
-#: hacks/config/discrete.xml.h:6 hacks/config/drift.xml.h:10
-#: hacks/config/epicycle.xml.h:9 hacks/config/eruption.xml.h:14
-#: hacks/config/euler2d.xml.h:9 hacks/config/fadeplot.xml.h:7
-#: hacks/config/flag.xml.h:6 hacks/config/flame.xml.h:12
-#: hacks/config/flow.xml.h:8 hacks/config/forest.xml.h:4
-#: hacks/config/galaxy.xml.h:7 hacks/config/grav.xml.h:5
-#: hacks/config/halo.xml.h:6 hacks/config/hopalong.xml.h:17
-#: hacks/config/imsmap.xml.h:10 hacks/config/interference.xml.h:15
-#: hacks/config/julia.xml.h:7 hacks/config/laser.xml.h:8
-#: hacks/config/lightning.xml.h:4 hacks/config/lisa.xml.h:6
-#: hacks/config/lissie.xml.h:7 hacks/config/loop.xml.h:5
-#: hacks/config/metaballs.xml.h:10 hacks/config/moire.xml.h:7
-#: hacks/config/moire2.xml.h:5 hacks/config/mountain.xml.h:6
-#: hacks/config/penrose.xml.h:5 hacks/config/polyominoes.xml.h:6
-#: hacks/config/popsquares.xml.h:4 hacks/config/rd-bomb.xml.h:13
-#: hacks/config/rocks.xml.h:6 hacks/config/rotor.xml.h:7
-#: hacks/config/shadebobs.xml.h:6 hacks/config/sierpinski.xml.h:5
-#: hacks/config/slip.xml.h:5 hacks/config/sphere.xml.h:4
-#: hacks/config/spiral.xml.h:8 hacks/config/squiral.xml.h:10
-#: hacks/config/starfish.xml.h:6 hacks/config/strange.xml.h:3
-#: hacks/config/swirl.xml.h:5 hacks/config/thornbird.xml.h:5
-#: hacks/config/triangle.xml.h:4 hacks/config/vines.xml.h:3
-#: hacks/config/worm.xml.h:5 hacks/config/xearth.xml.h:17
-#: hacks/config/xfishtank.xml.h:9
-msgid "Number of Colors"
-msgstr "Количество цветов"
+#: ../driver/xscreensaver-demo.glade2.in.h:30
+msgid "When idle or locked, run the display mode selected below."
+msgstr "Запустить выбранный ниже режим дисплея во время простоя или блокировки."
 
-#: hacks/config/anemone.xml.h:7 hacks/config/fireflies.xml.h:32
-#: hacks/config/pyro.xml.h:8
-msgid "Often"
-msgstr "Часто"
+#: ../driver/xscreensaver-demo.glade2.in.h:31
+msgid "_Only One Screen Saver"
+msgstr "Один _постоянный хранитель экрана"
 
-#: hacks/config/anemone.xml.h:8
-msgid "Rarely"
+#: ../driver/xscreensaver-demo.glade2.in.h:32
+msgid ""
+"When idle or locked, choose a random display mode from among the checked "
+"items in the list below."
 msgstr ""
+"Выбрать случайный режим дисплея среди отмеченных элементов в списке ниже "
+"во время простоя или блокировки."
 
-#: hacks/config/anemone.xml.h:9 hacks/config/anemotaxis.xml.h:10
-#: hacks/config/ant.xml.h:15 hacks/config/antinspect.xml.h:6
-#: hacks/config/antmaze.xml.h:5 hacks/config/antspotlight.xml.h:5
-#: hacks/config/apollonian.xml.h:11 hacks/config/atlantis.xml.h:13
-#: hacks/config/attraction.xml.h:26 hacks/config/atunnel.xml.h:6
-#: hacks/config/barcode.xml.h:6 hacks/config/blaster.xml.h:8
-#: hacks/config/blinkbox.xml.h:8 hacks/config/blitspin.xml.h:7
-#: hacks/config/blocktube.xml.h:9 hacks/config/boing.xml.h:10
-#: hacks/config/bouboule.xml.h:8 hacks/config/bouncingcow.xml.h:10
-#: hacks/config/boxed.xml.h:15 hacks/config/boxfit.xml.h:12
-#: hacks/config/braid.xml.h:11 hacks/config/bubble3d.xml.h:6
-#: hacks/config/bubbles.xml.h:10 hacks/config/bumps.xml.h:4
-#: hacks/config/cage.xml.h:4 hacks/config/carousel.xml.h:14
-#: hacks/config/ccurve.xml.h:11 hacks/config/celtic.xml.h:8
-#: hacks/config/circuit.xml.h:10 hacks/config/cloudlife.xml.h:11
-#: hacks/config/compass.xml.h:4 hacks/config/coral.xml.h:12
-#: hacks/config/critical.xml.h:6 hacks/config/crystal.xml.h:11
-#: hacks/config/cube21.xml.h:16 hacks/config/cubenetic.xml.h:22
-#: hacks/config/cubestorm.xml.h:8 hacks/config/cynosure.xml.h:9
-#: hacks/config/dangerball.xml.h:5 hacks/config/decayscreen.xml.h:17
-#: hacks/config/deluxe.xml.h:8 hacks/config/demon.xml.h:8
-#: hacks/config/discrete.xml.h:7 hacks/config/distort.xml.h:11
-#: hacks/config/drift.xml.h:12 hacks/config/endgame.xml.h:5
-#: hacks/config/engine.xml.h:15 hacks/config/epicycle.xml.h:10
-#: hacks/config/eruption.xml.h:19 hacks/config/euler2d.xml.h:14
-#: hacks/config/extrusion.xml.h:11 hacks/config/fadeplot.xml.h:8
-#: hacks/config/fireworkx.xml.h:9 hacks/config/flag.xml.h:7
-#: hacks/config/flame.xml.h:14 hacks/config/flipflop.xml.h:5
-#: hacks/config/flipscreen3d.xml.h:6 hacks/config/fliptext.xml.h:13
-#: hacks/config/flow.xml.h:10 hacks/config/fluidballs.xml.h:18
-#: hacks/config/flyingtoasters.xml.h:11 hacks/config/fontglide.xml.h:13
-#: hacks/config/forest.xml.h:5 hacks/config/fuzzyflakes.xml.h:15
-#: hacks/config/galaxy.xml.h:11 hacks/config/gears.xml.h:7
-#: hacks/config/gflux.xml.h:12 hacks/config/glblur.xml.h:14
-#: hacks/config/glforestfire.xml.h:14 hacks/config/glhanoi.xml.h:8
-#: hacks/config/glknots.xml.h:17 hacks/config/glmatrix.xml.h:18
-#: hacks/config/glplanet.xml.h:8 hacks/config/glsnake.xml.h:12
-#: hacks/config/gltext.xml.h:15 hacks/config/goop.xml.h:10
-#: hacks/config/grav.xml.h:8 hacks/config/greynetic.xml.h:3
-#: hacks/config/halo.xml.h:10 hacks/config/hopalong.xml.h:21
-#: hacks/config/hyperball.xml.h:8 hacks/config/hypercube.xml.h:7
-#: hacks/config/hypertorus.xml.h:18 hacks/config/ifs.xml.h:13
-#: hacks/config/interaggregate.xml.h:4 hacks/config/interference.xml.h:17
-#: hacks/config/intermomentary.xml.h:4 hacks/config/jigglypuff.xml.h:16
-#: hacks/config/jigsaw.xml.h:5 hacks/config/juggle.xml.h:8
-#: hacks/config/juggler3d.xml.h:12 hacks/config/julia.xml.h:8
-#: hacks/config/kaleidescope.xml.h:7 hacks/config/klein.xml.h:7
-#: hacks/config/kumppa.xml.h:8 hacks/config/lament.xml.h:6
-#: hacks/config/laser.xml.h:10 hacks/config/lavalite.xml.h:27
-#: hacks/config/lightning.xml.h:5 hacks/config/lisa.xml.h:8
-#: hacks/config/lissie.xml.h:9 hacks/config/lmorph.xml.h:11
-#: hacks/config/loop.xml.h:7 hacks/config/maze.xml.h:14
-#: hacks/config/memscroller.xml.h:7 hacks/config/menger.xml.h:16
-#: hacks/config/metaballs.xml.h:13 hacks/config/mirrorblob.xml.h:18
-#: hacks/config/mismunch.xml.h:10 hacks/config/moebius.xml.h:7
-#: hacks/config/moire2.xml.h:6 hacks/config/molecule.xml.h:23
-#: hacks/config/morph3d.xml.h:6 hacks/config/mountain.xml.h:7
-#: hacks/config/munch.xml.h:7 hacks/config/nerverot.xml.h:20
-#: hacks/config/noof.xml.h:5 hacks/config/pacman.xml.h:5
-#: hacks/config/penetrate.xml.h:6 hacks/config/penrose.xml.h:8
-#: hacks/config/petri.xml.h:23 hacks/config/phosphor.xml.h:7
-#: hacks/config/piecewise.xml.h:9 hacks/config/pinion.xml.h:13
-#: hacks/config/pipes.xml.h:15 hacks/config/polyhedra.xml.h:111
-#: hacks/config/polyominoes.xml.h:10 hacks/config/polytopes.xml.h:20
-#: hacks/config/pong.xml.h:4 hacks/config/popsquares.xml.h:5
-#: hacks/config/providence.xml.h:5 hacks/config/pulsar.xml.h:15
-#: hacks/config/pyro.xml.h:13 hacks/config/qix.xml.h:19
-#: hacks/config/queens.xml.h:4 hacks/config/rd-bomb.xml.h:17
-#: hacks/config/ripples.xml.h:12 hacks/config/rocks.xml.h:9
-#: hacks/config/rotor.xml.h:11 hacks/config/rubik.xml.h:9
-#: hacks/config/sballs.xml.h:13 hacks/config/shadebobs.xml.h:9
-#: hacks/config/sierpinski.xml.h:7 hacks/config/sierpinski3d.xml.h:8
-#: hacks/config/slidescreen.xml.h:6 hacks/config/slip.xml.h:7
-#: hacks/config/speedmine.xml.h:13 hacks/config/sphere.xml.h:5
-#: hacks/config/spheremonics.xml.h:19 hacks/config/spiral.xml.h:9
-#: hacks/config/spotlight.xml.h:4 hacks/config/sproingies.xml.h:6
-#: hacks/config/squiral.xml.h:14 hacks/config/stairs.xml.h:3
-#: hacks/config/starfish.xml.h:8 hacks/config/starwars.xml.h:12
-#: hacks/config/strange.xml.h:4 hacks/config/substrate.xml.h:15
-#: hacks/config/superquadrics.xml.h:8 hacks/config/swirl.xml.h:6
-#: hacks/config/t3d.xml.h:11 hacks/config/tangram.xml.h:4
-#: hacks/config/thornbird.xml.h:7 hacks/config/triangle.xml.h:5
-#: hacks/config/truchet.xml.h:2 hacks/config/twang.xml.h:9
-#: hacks/config/vines.xml.h:4 hacks/config/worm.xml.h:7
-#: hacks/config/wormhole.xml.h:5 hacks/config/xearth.xml.h:22
-#: hacks/config/xfishtank.xml.h:10 hacks/config/xflame.xml.h:5
-#: hacks/config/xjack.xml.h:2 hacks/config/xmatrix.xml.h:15
-#: hacks/config/xplanet.xml.h:59 hacks/config/xrayswarm.xml.h:3
-#: hacks/config/zoom.xml.h:6
-msgid "Slow"
-msgstr "Медленно"
-
-#: hacks/config/anemone.xml.h:10 hacks/config/anemotaxis.xml.h:12
-#: hacks/config/ant.xml.h:17 hacks/config/antinspect.xml.h:7
-#: hacks/config/antmaze.xml.h:6 hacks/config/antspotlight.xml.h:6
-#: hacks/config/apollonian.xml.h:12 hacks/config/attraction.xml.h:28
-#: hacks/config/atunnel.xml.h:7 hacks/config/barcode.xml.h:7
-#: hacks/config/blaster.xml.h:9 hacks/config/blinkbox.xml.h:9
-#: hacks/config/blocktube.xml.h:11 hacks/config/boing.xml.h:12
-#: hacks/config/bouboule.xml.h:9 hacks/config/boxfit.xml.h:14
-#: hacks/config/braid.xml.h:12 hacks/config/bubble3d.xml.h:7
-#: hacks/config/bubbles.xml.h:11 hacks/config/bumps.xml.h:5
-#: hacks/config/cage.xml.h:6 hacks/config/celtic.xml.h:9
-#: hacks/config/circuit.xml.h:11 hacks/config/cloudlife.xml.h:13
-#: hacks/config/compass.xml.h:5 hacks/config/coral.xml.h:14
-#: hacks/config/critical.xml.h:7 hacks/config/crystal.xml.h:12
-#: hacks/config/cubenetic.xml.h:24 hacks/config/cynosure.xml.h:10
-#: hacks/config/dangerball.xml.h:6 hacks/config/decayscreen.xml.h:18
-#: hacks/config/deluxe.xml.h:9 hacks/config/demon.xml.h:10
-#: hacks/config/discrete.xml.h:9 hacks/config/distort.xml.h:13
-#: hacks/config/drift.xml.h:13 hacks/config/endgame.xml.h:6
-#: hacks/config/engine.xml.h:16 hacks/config/epicycle.xml.h:11
-#: hacks/config/eruption.xml.h:20 hacks/config/euler2d.xml.h:15
-#: hacks/config/extrusion.xml.h:13 hacks/config/fadeplot.xml.h:10
-#: hacks/config/fireworkx.xml.h:11 hacks/config/flag.xml.h:9
-#: hacks/config/flame.xml.h:15 hacks/config/flipflop.xml.h:7
-#: hacks/config/flipscreen3d.xml.h:7 hacks/config/fliptext.xml.h:14
-#: hacks/config/flow.xml.h:12 hacks/config/fluidballs.xml.h:20
-#: hacks/config/forest.xml.h:6 hacks/config/fuzzyflakes.xml.h:17
-#: hacks/config/galaxy.xml.h:12 hacks/config/glblur.xml.h:16
-#: hacks/config/glforestfire.xml.h:15 hacks/config/glplanet.xml.h:10
-#: hacks/config/gltext.xml.h:17 hacks/config/goop.xml.h:11
-#: hacks/config/grav.xml.h:9 hacks/config/greynetic.xml.h:4
-#: hacks/config/halo.xml.h:11 hacks/config/hopalong.xml.h:23
-#: hacks/config/hyperball.xml.h:9 hacks/config/hypercube.xml.h:8
-#: hacks/config/ifs.xml.h:14 hacks/config/interaggregate.xml.h:5
-#: hacks/config/intermomentary.xml.h:5 hacks/config/jigsaw.xml.h:7
-#: hacks/config/juggle.xml.h:9 hacks/config/julia.xml.h:10
-#: hacks/config/kaleidescope.xml.h:8 hacks/config/klein.xml.h:8
-#: hacks/config/kumppa.xml.h:9 hacks/config/lament.xml.h:7
-#: hacks/config/laser.xml.h:11 hacks/config/lavalite.xml.h:30
-#: hacks/config/lightning.xml.h:6 hacks/config/lisa.xml.h:9
-#: hacks/config/lissie.xml.h:11 hacks/config/lmorph.xml.h:12
-#: hacks/config/loop.xml.h:9 hacks/config/memscroller.xml.h:8
-#: hacks/config/menger.xml.h:18 hacks/config/metaballs.xml.h:15
-#: hacks/config/mirrorblob.xml.h:20 hacks/config/mismunch.xml.h:12
-#: hacks/config/moebius.xml.h:10 hacks/config/moire2.xml.h:7
-#: hacks/config/molecule.xml.h:25 hacks/config/morph3d.xml.h:7
-#: hacks/config/mountain.xml.h:8 hacks/config/munch.xml.h:9
-#: hacks/config/nerverot.xml.h:22 hacks/config/noof.xml.h:6
-#: hacks/config/pacman.xml.h:6 hacks/config/penrose.xml.h:9
-#: hacks/config/petri.xml.h:25 hacks/config/phosphor.xml.h:8
-#: hacks/config/piecewise.xml.h:11 hacks/config/pipes.xml.h:16
-#: hacks/config/polyominoes.xml.h:11 hacks/config/pong.xml.h:5
-#: hacks/config/popsquares.xml.h:6 hacks/config/providence.xml.h:7
-#: hacks/config/pulsar.xml.h:17 hacks/config/qix.xml.h:22
-#: hacks/config/queens.xml.h:6 hacks/config/rotor.xml.h:12
-#: hacks/config/rubik.xml.h:11 hacks/config/sballs.xml.h:14
-#: hacks/config/shadebobs.xml.h:10 hacks/config/sierpinski.xml.h:9
-#: hacks/config/sierpinski3d.xml.h:10 hacks/config/slidescreen.xml.h:7
-#: hacks/config/slip.xml.h:9 hacks/config/speedmine.xml.h:15
-#: hacks/config/sphere.xml.h:6 hacks/config/spheremonics.xml.h:22
-#: hacks/config/spiral.xml.h:10 hacks/config/spotlight.xml.h:5
-#: hacks/config/sproingies.xml.h:8 hacks/config/squiral.xml.h:16
-#: hacks/config/stairs.xml.h:5 hacks/config/starfish.xml.h:9
-#: hacks/config/strange.xml.h:5 hacks/config/substrate.xml.h:16
-#: hacks/config/superquadrics.xml.h:10 hacks/config/swirl.xml.h:7
-#: hacks/config/t3d.xml.h:13 hacks/config/tangram.xml.h:5
-#: hacks/config/thornbird.xml.h:8 hacks/config/triangle.xml.h:6
-#: hacks/config/truchet.xml.h:3 hacks/config/twang.xml.h:10
-#: hacks/config/vines.xml.h:5 hacks/config/whirlygig.xml.h:13
-#: hacks/config/worm.xml.h:8 hacks/config/xearth.xml.h:25
-#: hacks/config/xflame.xml.h:6 hacks/config/xjack.xml.h:3
-#: hacks/config/xmatrix.xml.h:18 hacks/config/xplanet.xml.h:60
-#: hacks/config/xrayswarm.xml.h:4 hacks/config/zoom.xml.h:7
-msgid "Speed"
-msgstr "Скорость"
+#: ../driver/xscreensaver-demo.glade2.in.h:33
+msgid "_Random Screen Saver"
+msgstr "_Случайный хранитель экрана"
 
-#: hacks/config/anemone.xml.h:11
-msgid "Tentacles"
+#: ../driver/xscreensaver-demo.glade2.in.h:34
+msgid ""
+"When idle or locked, choose a random display mode from among the checked "
+"items in the list below.  Run that same mode on each monitor."
 msgstr ""
 
-#: hacks/config/anemone.xml.h:12 hacks/config/cubestorm.xml.h:11
-#: hacks/config/deluxe.xml.h:10 hacks/config/fuzzyflakes.xml.h:18
-#: hacks/config/glknots.xml.h:19 hacks/config/lmorph.xml.h:13
-#: hacks/config/pong.xml.h:7 hacks/config/starfish.xml.h:11
-#: hacks/config/thornbird.xml.h:9
-msgid "Thick"
+#: ../driver/xscreensaver-demo.glade2.in.h:35
+msgid "_Same Random Savers"
 msgstr ""
 
-#: hacks/config/anemone.xml.h:13 hacks/config/fuzzyflakes.xml.h:19
-#: hacks/config/glknots.xml.h:20 hacks/config/moire2.xml.h:8
-#: hacks/config/thornbird.xml.h:10
-msgid "Thickness"
+#: ../driver/xscreensaver-demo.glade2.in.h:36
+msgid ""
+"Run the next screen saver in the list in full-screen mode (click the mouse "
+"to return.)"
 msgstr ""
+"Исполнить следующий в списке хранитель экрана в полноэкранном режиме "
+"(возврат обратно по щелчку мыши)."
 
-#: hacks/config/anemone.xml.h:14 hacks/config/cubestorm.xml.h:12
-#: hacks/config/deluxe.xml.h:11 hacks/config/fuzzyflakes.xml.h:20
-#: hacks/config/glknots.xml.h:21 hacks/config/lmorph.xml.h:14
-#: hacks/config/pong.xml.h:8 hacks/config/starfish.xml.h:12
-#: hacks/config/thornbird.xml.h:11
-msgid "Thin"
+#: ../driver/xscreensaver-demo.glade2.in.h:37
+msgid ""
+"Run the previous screen saver in the list in full-screen mode (click the "
+"mouse to return.)"
 msgstr ""
+"Исполнить предыдущий в списке хранитель экрана в полноэкранном режиме "
+"(возврат обратно по щелчку мыши)."
 
-#: hacks/config/anemone.xml.h:15
-msgid "Turn speed"
+#: ../driver/xscreensaver-demo.glade2.in.h:38
+msgid "preview"
 msgstr ""
 
-#: hacks/config/anemone.xml.h:16 hacks/config/ant.xml.h:22
-#: hacks/config/apollonian.xml.h:13 hacks/config/attraction.xml.h:32
-#: hacks/config/bouboule.xml.h:11 hacks/config/braid.xml.h:13
-#: hacks/config/critical.xml.h:8 hacks/config/crystal.xml.h:13
-#: hacks/config/cynosure.xml.h:11 hacks/config/deco.xml.h:10
-#: hacks/config/deluxe.xml.h:14 hacks/config/demon.xml.h:13
-#: hacks/config/discrete.xml.h:11 hacks/config/drift.xml.h:14
-#: hacks/config/epicycle.xml.h:13 hacks/config/euler2d.xml.h:17
-#: hacks/config/fadeplot.xml.h:12 hacks/config/flag.xml.h:13
-#: hacks/config/flame.xml.h:16 hacks/config/flow.xml.h:15
-#: hacks/config/forest.xml.h:8 hacks/config/galaxy.xml.h:14
-#: hacks/config/grav.xml.h:11 hacks/config/halo.xml.h:13
-#: hacks/config/hopalong.xml.h:25 hacks/config/imsmap.xml.h:15
-#: hacks/config/interference.xml.h:19 hacks/config/julia.xml.h:12
-#: hacks/config/laser.xml.h:12 hacks/config/lightning.xml.h:8
-#: hacks/config/lisa.xml.h:12 hacks/config/lissie.xml.h:13
-#: hacks/config/loop.xml.h:12 hacks/config/metaballs.xml.h:16
-#: hacks/config/moire.xml.h:11 hacks/config/moire2.xml.h:9
-#: hacks/config/mountain.xml.h:9 hacks/config/nerverot.xml.h:23
-#: hacks/config/penrose.xml.h:10 hacks/config/polyominoes.xml.h:12
-#: hacks/config/rd-bomb.xml.h:20 hacks/config/rocks.xml.h:12
-#: hacks/config/rotor.xml.h:13 hacks/config/shadebobs.xml.h:12
-#: hacks/config/sierpinski.xml.h:12 hacks/config/slip.xml.h:12
-#: hacks/config/sphere.xml.h:8 hacks/config/spiral.xml.h:12
-#: hacks/config/squiral.xml.h:18 hacks/config/starfish.xml.h:14
-#: hacks/config/strange.xml.h:8 hacks/config/swirl.xml.h:9
-#: hacks/config/thornbird.xml.h:13 hacks/config/triangle.xml.h:8
-#: hacks/config/vines.xml.h:7 hacks/config/worm.xml.h:9
-#: hacks/config/xearth.xml.h:28 hacks/config/xfishtank.xml.h:11
-msgid "Two"
-msgstr "Два"
-
-#: hacks/config/anemone.xml.h:17
-msgid "Wiggling tentacles. By Gabriel Finch."
+#: ../driver/xscreensaver-demo.glade2.in.h:39
+msgid ""
+"No Preview\n"
+"Available"
 msgstr ""
+"Предпросмотр\n"
+"недоступен"
 
-#: hacks/config/anemone.xml.h:18
-msgid "Withdraw freqency"
+#: ../driver/xscreensaver-demo.glade2.in.h:41
+msgid "no preview"
 msgstr ""
 
-#: hacks/config/anemotaxis.xml.h:1
-msgid "Anemotaxis"
+#: ../driver/xscreensaver-demo.glade2.in.h:42
+msgid ""
+"Not\n"
+"Installed"
+msgstr "Не установлен"
+
+#: ../driver/xscreensaver-demo.glade2.in.h:44
+msgid "not installed"
 msgstr ""
 
-#: hacks/config/anemotaxis.xml.h:2
+#: ../driver/xscreensaver-demo.glade2.in.h:45
 msgid ""
-"Anemotaxis demonstrates a search algorithm designed for locating a source of "
-"odor in turbulent atmosphere. The searcher is able to sense the odor and "
-"determine local instantaneous wind direction. The goal is to find the source "
-"in the shortest mean time. Written by Eugene Balkovsky."
+"Very few (or no) screen savers appear to be available.\n"
+"\n"
+"This probably means that the \"xscreensaver-extras\" and\n"
+"\"xscreensaver-gl-extras\" packages are not installed."
 msgstr ""
+"Доступно очень мало хранителей экрана (или они не доступны вообще).\n"
+"\n"
+"Возможно, не установлены пакеты \"xscreensaver-extras\" и\n"
+"\"xscreensaver-gl-extras\"."
 
-#: hacks/config/anemotaxis.xml.h:3
-msgid "Distance"
+#: ../driver/xscreensaver-demo.glade2.in.h:49
+msgid "nothing"
 msgstr ""
 
-#: hacks/config/anemotaxis.xml.h:4 hacks/config/hyperball.xml.h:1
-#: hacks/config/hypercube.xml.h:1
-msgid "Far"
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:50
+msgid "Description"
+msgstr "Описание"
 
-#: hacks/config/anemotaxis.xml.h:8 hacks/config/hyperball.xml.h:7
-#: hacks/config/hypercube.xml.h:6
-msgid "Near"
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:51
+msgid "_Display Modes"
+msgstr "Режимы _экрана"
 
-#: hacks/config/anemotaxis.xml.h:9
-msgid "Searchers"
+#: ../driver/xscreensaver-demo.glade2.in.h:52
+msgid ""
+"Whether the image-manipulating modes should be allowed to operate on an "
+"image of your desktop."
 msgstr ""
+"Разрешено ли хранителям экрана, управляющим изображениями, работать с "
+"изображением вашего рабочего стола."
 
-#: hacks/config/anemotaxis.xml.h:11
-msgid "Sources"
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:53
+msgid "Grab Desktop _Images"
+msgstr "Захватывать _изображения с рабочего стола"
 
-#: hacks/config/ant.xml.h:1
+#: ../driver/xscreensaver-demo.glade2.in.h:54
 msgid ""
-"A cellular automaton that is really a two-dimensional Turing machine: as the "
-"heads (``ants'') walk along the screen, they change pixel values in their "
-"path. Then, as they pass over changed pixels, their behavior is influenced. "
-"Written by David Bagley."
+"Whether the image-manipulating modes should operate on images captured from "
+"the system's video input (if there is one.)"
 msgstr ""
+"Должны ли хранители экрана, управляющие изображениями, работать с "
+"изображениями, захваченными с системного видеовхода (если таковой имеется)."
 
-#: hacks/config/ant.xml.h:2
-msgid "Ant"
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:55
+msgid "Grab _Video Frames"
+msgstr "Захватывать кадры _видео"
 
-#: hacks/config/ant.xml.h:3
-msgid "Ant Size"
+#: ../driver/xscreensaver-demo.glade2.in.h:56
+msgid "Whether the image-manipulating modes should load image files."
 msgstr ""
+"Должны ли хранители экрана, управляющие изображениями, загружать файлы "
+"изображений с диска."
 
-#: hacks/config/ant.xml.h:4
-msgid "Ants Count"
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:57
+msgid "Choose _Random Image:"
+msgstr "Выбирать случайное изображение:"
 
-#: hacks/config/ant.xml.h:5
-msgid "Draw Eyes"
+#: ../driver/xscreensaver-demo.glade2.in.h:58
+msgid ""
+"The local directory, RSS feed or Atom feed from which images will be "
+"randomly chosen."
 msgstr ""
+"Локальный каталог, канал RSS или Atom, из которого случайным образом будут "
+"выбираться изображения."
 
-#: hacks/config/ant.xml.h:7
-msgid "Four Sided Cells"
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:59
+msgid "_Browse"
+msgstr "_Обзор"
 
-#: hacks/config/ant.xml.h:8 hacks/config/attraction.xml.h:13
-#: hacks/config/cloudlife.xml.h:7 hacks/config/cube21.xml.h:8
-#: hacks/config/cubenetic.xml.h:11 hacks/config/demon.xml.h:5
-#: hacks/config/discrete.xml.h:3 hacks/config/distort.xml.h:5
-#: hacks/config/fadeplot.xml.h:5 hacks/config/flag.xml.h:4
-#: hacks/config/flow.xml.h:4 hacks/config/fluidballs.xml.h:12
-#: hacks/config/fuzzyflakes.xml.h:10 hacks/config/gleidescope.xml.h:7
-#: hacks/config/halftone.xml.h:8 hacks/config/hopalong.xml.h:13
-#: hacks/config/interference.xml.h:11 hacks/config/julia.xml.h:5
-#: hacks/config/lissie.xml.h:4 hacks/config/loop.xml.h:2
-#: hacks/config/moire.xml.h:4 hacks/config/piecewise.xml.h:5
-#: hacks/config/rd-bomb.xml.h:11 hacks/config/rorschach.xml.h:5
-#: hacks/config/rubik.xml.h:4 hacks/config/sierpinski.xml.h:3
-#: hacks/config/slip.xml.h:3
-msgid "Large"
-msgstr "Большой"
+#: ../driver/xscreensaver-demo.glade2.in.h:60
+msgid "Local directory, or RSS feed URL."
+msgstr "Локальный каталог или URL канала RSS."
 
-#: hacks/config/ant.xml.h:10
-msgid "Nine Sided Cells"
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:61
+msgid "Image Manipulation"
+msgstr "Управление изображениями"
 
-#: hacks/config/ant.xml.h:12
-msgid "Random Cell Shape"
+#: ../driver/xscreensaver-demo.glade2.in.h:62
+msgid "Text-displaying modes will display the text typed here."
 msgstr ""
+"Хранитель экрана, управляющий текстом, будет отображать набранный здесь "
+"текст."
 
-#: hacks/config/ant.xml.h:13 hacks/config/speedmine.xml.h:11
-msgid "Sharp Turns"
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:63
+msgid "_Text"
+msgstr "_Текст"
 
-#: hacks/config/ant.xml.h:14
-msgid "Six Sided Cells"
+#: ../driver/xscreensaver-demo.glade2.in.h:64
+msgid "Text-displaying modes will display the contents of this file."
 msgstr ""
+"Хранитель экрана, управляющий текстом, будет отображать содержимое данного "
+"файла."
 
-#: hacks/config/ant.xml.h:16 hacks/config/attraction.xml.h:27
-#: hacks/config/cloudlife.xml.h:12 hacks/config/cube21.xml.h:17
-#: hacks/config/cubenetic.xml.h:23 hacks/config/demon.xml.h:9
-#: hacks/config/discrete.xml.h:8 hacks/config/distort.xml.h:12
-#: hacks/config/fadeplot.xml.h:9 hacks/config/flag.xml.h:8
-#: hacks/config/flow.xml.h:11 hacks/config/fluidballs.xml.h:19
-#: hacks/config/fuzzyflakes.xml.h:16 hacks/config/gleidescope.xml.h:12
-#: hacks/config/halftone.xml.h:14 hacks/config/hopalong.xml.h:22
-#: hacks/config/interference.xml.h:18 hacks/config/julia.xml.h:9
-#: hacks/config/lissie.xml.h:10 hacks/config/loop.xml.h:8
-#: hacks/config/metaballs.xml.h:14 hacks/config/moire.xml.h:9
-#: hacks/config/piecewise.xml.h:10 hacks/config/rd-bomb.xml.h:18
-#: hacks/config/rorschach.xml.h:8 hacks/config/rubik.xml.h:10
-#: hacks/config/sierpinski.xml.h:8 hacks/config/slip.xml.h:8
-msgid "Small"
-msgstr "Маленький"
+#: ../driver/xscreensaver-demo.glade2.in.h:65
+msgid "Text _file"
+msgstr "Текстовый _файл"
 
-#: hacks/config/ant.xml.h:18
-msgid "Three Sided Cells"
+#: ../driver/xscreensaver-demo.glade2.in.h:66
+msgid "Text-displaying modes will display the output of this program."
 msgstr ""
+"Хранитель экрана, управляющий текстом, будет отображать вывод данной "
+"программы."
 
-#: hacks/config/ant.xml.h:19 hacks/config/demon.xml.h:12
-#: hacks/config/discrete.xml.h:10 hacks/config/fadeplot.xml.h:11
-#: hacks/config/flag.xml.h:12 hacks/config/flow.xml.h:14
-#: hacks/config/lissie.xml.h:12 hacks/config/loop.xml.h:11
-#: hacks/config/rubik.xml.h:12 hacks/config/sierpinski.xml.h:11
-#: hacks/config/slip.xml.h:11
-msgid "Timeout"
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:67
+msgid "_Program"
+msgstr "_Программа"
 
-#: hacks/config/ant.xml.h:20
-msgid "Truchet Lines"
+#: ../driver/xscreensaver-demo.glade2.in.h:68
+msgid ""
+"Text-displaying modes will display the contents of this URL (HTML or RSS)."
 msgstr ""
+"Хранитель экрана, управляющий текстом, будет отображать содержимое данного "
+"URL (HTML или RSS)."
 
-#: hacks/config/ant.xml.h:21
-msgid "Twelve Sided Cells"
+#: ../driver/xscreensaver-demo.glade2.in.h:69
+msgid "_URL"
 msgstr ""
 
-#: hacks/config/antinspect.xml.h:1
-msgid "AntInspect"
+#: ../driver/xscreensaver-demo.glade2.in.h:70
+msgid "Text-displaying modes will display the local host name, date, and time."
 msgstr ""
+"Хранитель экрана, управляющий текстом, будет отображать локальное имя хоста, "
+"дату и время."
 
-#: hacks/config/antinspect.xml.h:2
-msgid "Draw Shadows"
-msgstr ""
-
-#: hacks/config/antinspect.xml.h:3
-msgid ""
-"Draws a trio of ants moving their spheres around a circle. Written by Blair "
-"Tennessy."
-msgstr ""
-
-#: hacks/config/antinspect.xml.h:5 hacks/config/antmaze.xml.h:4
-#: hacks/config/antspotlight.xml.h:4 hacks/config/atlantis.xml.h:11
-#: hacks/config/atunnel.xml.h:5 hacks/config/blocktube.xml.h:8
-#: hacks/config/boing.xml.h:8 hacks/config/boxed.xml.h:14
-#: hacks/config/bubble3d.xml.h:5 hacks/config/cage.xml.h:3
-#: hacks/config/carousel.xml.h:12 hacks/config/circuit.xml.h:9
-#: hacks/config/cube21.xml.h:13 hacks/config/cubenetic.xml.h:21
-#: hacks/config/cubestorm.xml.h:7 hacks/config/dangerball.xml.h:4
-#: hacks/config/endgame.xml.h:4 hacks/config/engine.xml.h:14
-#: hacks/config/extrusion.xml.h:10 hacks/config/flipflop.xml.h:4
-#: hacks/config/flipscreen3d.xml.h:5 hacks/config/fliptext.xml.h:12
-#: hacks/config/fluidballs.xml.h:17 hacks/config/flurry.xml.h:9
-#: hacks/config/flyingtoasters.xml.h:10 hacks/config/gears.xml.h:6
-#: hacks/config/gflux.xml.h:11 hacks/config/glblur.xml.h:13
-#: hacks/config/gleidescope.xml.h:10 hacks/config/glforestfire.xml.h:13
-#: hacks/config/glhanoi.xml.h:7 hacks/config/glknots.xml.h:16
-#: hacks/config/glmatrix.xml.h:17 hacks/config/glplanet.xml.h:7
-#: hacks/config/glslideshow.xml.h:19 hacks/config/glsnake.xml.h:10
-#: hacks/config/gltext.xml.h:14 hacks/config/hypertorus.xml.h:17
-#: hacks/config/jigglypuff.xml.h:15 hacks/config/juggler3d.xml.h:11
-#: hacks/config/klein.xml.h:6 hacks/config/lament.xml.h:5
-#: hacks/config/lavalite.xml.h:26 hacks/config/menger.xml.h:15
-#: hacks/config/mirrorblob.xml.h:17 hacks/config/moebius.xml.h:6
-#: hacks/config/molecule.xml.h:22 hacks/config/morph3d.xml.h:5
-#: hacks/config/noof.xml.h:4 hacks/config/pinion.xml.h:12
-#: hacks/config/pipes.xml.h:14 hacks/config/polyhedra.xml.h:110
-#: hacks/config/polytopes.xml.h:18 hacks/config/providence.xml.h:4
-#: hacks/config/pulsar.xml.h:14 hacks/config/queens.xml.h:3
-#: hacks/config/rubik.xml.h:6 hacks/config/sballs.xml.h:12
-#: hacks/config/sierpinski3d.xml.h:6 hacks/config/spheremonics.xml.h:18
-#: hacks/config/sproingies.xml.h:4 hacks/config/stairs.xml.h:2
-#: hacks/config/starwars.xml.h:11 hacks/config/superquadrics.xml.h:7
-#: hacks/config/timetunnel.xml.h:9
-msgid "Show Frames-per-Second"
-msgstr "Показывать количество кадров в секунду"
-
-#: hacks/config/antmaze.xml.h:1
-msgid "AntMaze"
+#: ../driver/xscreensaver-demo.glade2.in.h:71
+msgid "_Host Name and Time"
+msgstr "_Имя хоста и время"
+
+#: ../driver/xscreensaver-demo.glade2.in.h:72
+msgid "Text Manipulation"
+msgstr "Управление текстом"
+
+#: ../driver/xscreensaver-demo.glade2.in.h:73
+msgid "Whether the monitor should be powered down after a while."
 msgstr ""
+"Должен ли монитор снижать энергопотребление или отключаться через какое-то "
+"время."
+
+#: ../driver/xscreensaver-demo.glade2.in.h:74
+msgid "_Power Management Enabled"
+msgstr "_Управление питанием включено"
+
+#: ../driver/xscreensaver-demo.glade2.in.h:75
+msgid "Stand_by After"
+msgstr "Режим Standby через"
+
+#: ../driver/xscreensaver-demo.glade2.in.h:76
+msgid "Sus_pend After"
+msgstr "Режим Suspend через"
+
+#: ../driver/xscreensaver-demo.glade2.in.h:77
+msgid "_Off After"
+msgstr "_Выключать через"
+
+#: ../driver/xscreensaver-demo.glade2.in.h:78
+msgid "How long until the monitor powers down."
+msgstr "Время до отключения монитора."
+
+#: ../driver/xscreensaver-demo.glade2.in.h:79
+msgid "How long until the monitor goes into power-saving mode."
+msgstr "Время до перехода монитора в режим энергосбережения."
+
+#: ../driver/xscreensaver-demo.glade2.in.h:80
+msgid "How long until the monitor goes completely black."
+msgstr "Время, через которое монитор начнет показывать \"черный экран\"."
 
-#: hacks/config/antmaze.xml.h:2
+#: ../driver/xscreensaver-demo.glade2.in.h:81
 msgid ""
-"Antmaze draws a few views of a few ants walking around in a simple maze. "
-"Written by Blair Tennessy."
+"Whether the monitor should be powered off immediately in \"Blank Screen Only"
+"\" mode, regardless of the above power-management timeouts."
 msgstr ""
+"Нужно ли сразу же выключать монитор в режиме \"Только пустой экран\", "
+"независимо от вышеперечисленных настроек управления питанием."
 
-#: hacks/config/antspotlight.xml.h:1
-msgid "AntSpotlight"
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:82
+msgid "_Quick Power-off in Blank Only Mode"
+msgstr "_Быстрое отключение питания в режиме пустого экрана"
+
+#: ../driver/xscreensaver-demo.glade2.in.h:83
+msgid "Display Power Management"
+msgstr "Управление питанием монитора"
 
-#: hacks/config/antspotlight.xml.h:2
+#: ../driver/xscreensaver-demo.glade2.in.h:84
 msgid ""
-"Antspotlight draws an ant (with a headlight) who walks on top of an image of "
-"your desktop or other image. Written by Blair Tennessy."
+"Whether the screen should slowly fade to black when the screen saver "
+"activates."
 msgstr ""
+"Должен ли экран плавно \"снижать яркость\", \"гаснуть\" до черного при "
+"активации хранителя экрана."
 
-#: hacks/config/apollonian.xml.h:1
-msgid "Apollonian"
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:85
+msgid "Fade to Black when _Blanking"
+msgstr "Переход к черному при _активации"
 
-#: hacks/config/apollonian.xml.h:2
-msgid "Deep"
+#: ../driver/xscreensaver-demo.glade2.in.h:86
+msgid ""
+"Whether the screen should slowly fade in from black when the screen saver "
+"deactivates."
 msgstr ""
+"Должен ли экран плавно \"набирать яркость\" от черного до нормального при "
+"деактивации хранителя экрана."
 
-#: hacks/config/apollonian.xml.h:3
-msgid "Depth"
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:87
+msgid "Fade from Black When _Unblanking"
+msgstr "Переход от черного при _деактивации"
 
-#: hacks/config/apollonian.xml.h:4
-msgid "Draw Labels"
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:88
+msgid "F_ade Duration"
+msgstr "_Продолжительность перехода"
 
-#: hacks/config/apollonian.xml.h:6
-msgid "Include Alternate Geometries"
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:89
+msgid "How long it should take for the screen to fade in and out."
+msgstr "Как долго должен длиться переход \"к черному\" или \"от черного\"."
+
+#: ../driver/xscreensaver-demo.glade2.in.h:90
+msgid "seconds"
+msgstr "секунд(ы)"
 
-#: hacks/config/apollonian.xml.h:9
+#: ../driver/xscreensaver-demo.glade2.in.h:91
 msgid ""
-"Packs a large circle with smaller circles, demonstrating the Descartes "
-"Circle Theorem. Written by Allan R. Wilks and David Bagley."
+"Whether to install a private colormap when running in 8-bit mode on the "
+"default Visual."
 msgstr ""
+"Устанавливать ли собственную цветовую палитру при работе с 8-битным цветом в "
+"оптическом классе \"по умолчанию\"."
 
-#: hacks/config/apollonian.xml.h:10
-msgid "Shallow"
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:92
+msgid "Install _Colormap"
+msgstr "Устанавливать _цветовую палитру"
 
-#: hacks/config/apple2.xml.h:1
-msgid "Apple ]["
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:93
+msgid "Fading and Colormaps"
+msgstr "Переход и цветовые палитры"
 
-#: hacks/config/apple2.xml.h:2
-msgid "Basic Programming Mode"
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:94
+msgid "_Advanced"
+msgstr "Рас_ширенные"
 
-#: hacks/config/apple2.xml.h:3 hacks/config/halo.xml.h:8
-#: hacks/config/imsmap.xml.h:11
-msgid "Random Mode"
+#: ../driver/xscreensaver-demo.glade2.in.h:95
+msgid "dialog1"
 msgstr ""
 
-#: hacks/config/apple2.xml.h:4
-msgid ""
-"Simulates an original Apple ][ Plus computer in all its 1979 glory. It also "
-"reproduces the appearance of display on a color television set of the "
-"period. In \"Text Mode\", it displays the output of a program, or the "
-"contents of a file or URL, as configured on the \"Advanced\" tab of the main "
-"Screensaver Preferences window. In \"Slideshow Mode\", it chooses a number "
-"of images from the image source you configured into XScreenSaver and "
-"displays them within the limitations of the Apple ][ display hardware. (Six "
-"available colors in hi-res mode!) In \"Basic Programming Mode\", a simulated "
-"user types in a BASIC program and runs it. By Trevor Blackwell."
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:96
+msgid "_Advanced >>"
+msgstr "Рас_ширенные >>"
 
-#: hacks/config/apple2.xml.h:5
-msgid "Slideshow Mode"
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:97
+msgid "_Standard <<"
+msgstr "_Стандартные <<"
 
-#: hacks/config/apple2.xml.h:6
-msgid "Text Mode"
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:98
+msgid "_Reset to Defaults"
+msgstr "_По умолчанию"
 
-#: hacks/config/apple2.xml.h:7 hacks/config/fliptext.xml.h:17
-#: hacks/config/fontglide.xml.h:15 hacks/config/noseguy.xml.h:7
-#: hacks/config/phosphor.xml.h:9 hacks/config/starwars.xml.h:17
-msgid "Text Program"
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:99
+msgid "Standard"
+msgstr "Стандартные"
 
-#: hacks/config/atlantis.xml.h:1
-msgid "Agressive"
-msgstr "Агрессивно"
+#: ../driver/xscreensaver-demo.glade2.in.h:100
+msgid "_Command Line:"
+msgstr "_Командная строка:"
 
-#: hacks/config/atlantis.xml.h:2
-msgid "Atlantis"
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:101
+msgid "_Visual:"
+msgstr "О_птический класс:"
 
-#: hacks/config/atlantis.xml.h:3
-msgid "Clear Water"
-msgstr "ЧиÑ\81Ñ\82аÑ\8f Ð²Ð¾Ð´Ð°"
+#: ../driver/xscreensaver-demo.glade2.in.h:103
+msgid "Best"
+msgstr "Ð\9dаилÑ\83Ñ\87Ñ\88ий"
 
-#: hacks/config/atlantis.xml.h:5
-msgid "Flat Background"
-msgstr "Ð\9fлоÑ\81кий Ñ\84он"
+#: ../driver/xscreensaver-demo.glade2.in.h:104
+msgid "Default"
+msgstr "Ð\9fо Ñ\83молÑ\87аниÑ\8e"
 
-#: hacks/config/atlantis.xml.h:6
-msgid "Gradient Background"
-msgstr "Ð\93Ñ\80адиенÑ\82нÑ\8bй Ñ\84он"
+#: ../driver/xscreensaver-demo.glade2.in.h:105
+msgid "Default-N"
+msgstr "Ð\9fо Ñ\83молÑ\87аниÑ\8e-N"
 
-#: hacks/config/atlantis.xml.h:7
-msgid "Number of Sharks"
-msgstr "Количество акул"
+#: ../driver/xscreensaver-demo.glade2.in.h:106
+msgid "GL"
+msgstr "GL"
 
-#: hacks/config/atlantis.xml.h:8
-msgid "Shark Proximity"
-msgstr "Поведение акулы"
+#: ../driver/xscreensaver-demo.glade2.in.h:107
+msgid "TrueColor"
+msgstr "TrueColor"
 
-#: hacks/config/atlantis.xml.h:9
-msgid "Shark Speed"
-msgstr "Скорость акулы"
+#: ../driver/xscreensaver-demo.glade2.in.h:108
+msgid "PseudoColor"
+msgstr "PseudoColor"
 
-#: hacks/config/atlantis.xml.h:10
-msgid "Shimmering Water"
-msgstr "Мерцающая вода"
+#: ../driver/xscreensaver-demo.glade2.in.h:109
+msgid "StaticGray"
+msgstr "StaticGray"
 
-#: hacks/config/atlantis.xml.h:12
-msgid "Shy"
-msgstr "Пугливо"
+#: ../driver/xscreensaver-demo.glade2.in.h:110
+msgid "GrayScale"
+msgstr "GrayScale"
 
-#: hacks/config/atlantis.xml.h:14 hacks/config/cage.xml.h:5
-#: hacks/config/extrusion.xml.h:12 hacks/config/gears.xml.h:8
-#: hacks/config/glplanet.xml.h:9 hacks/config/glsnake.xml.h:13
-#: hacks/config/gltext.xml.h:16 hacks/config/menger.xml.h:17
-#: hacks/config/mismunch.xml.h:11 hacks/config/molecule.xml.h:24
-#: hacks/config/munch.xml.h:8 hacks/config/providence.xml.h:6
-#: hacks/config/sierpinski3d.xml.h:9 hacks/config/speedmine.xml.h:14
-#: hacks/config/spheremonics.xml.h:21 hacks/config/sproingies.xml.h:7
-#: hacks/config/stairs.xml.h:4 hacks/config/stonerview.xml.h:2
-#: hacks/config/superquadrics.xml.h:9 hacks/config/webcollage.xml.h:8
-msgid "Solid"
-msgstr "Сплошной"
+#: ../driver/xscreensaver-demo.glade2.in.h:111
+msgid "DirectColor"
+msgstr "DirectColor"
 
-#: hacks/config/atlantis.xml.h:15
-msgid ""
-"This is xfishtank writ large: a GL animation of a number of sharks, "
-"dolphins, and whales. The swimming motions are great. Originally written by "
-"Mark Kilgard."
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:112
+msgid "Color"
+msgstr "Color"
 
-#: hacks/config/atlantis.xml.h:16
-msgid "Whale Speed"
-msgstr "Скорость кита"
+#: ../driver/xscreensaver-demo.glade2.in.h:113
+msgid "Gray"
+msgstr "Gray"
 
-#: hacks/config/atlantis.xml.h:17 hacks/config/atunnel.xml.h:10
-#: hacks/config/blinkbox.xml.h:10 hacks/config/blocktube.xml.h:13
-#: hacks/config/boing.xml.h:15 hacks/config/boxed.xml.h:17
-#: hacks/config/cage.xml.h:9 hacks/config/crackberg.xml.h:23
-#: hacks/config/cube21.xml.h:28 hacks/config/cubestorm.xml.h:14
-#: hacks/config/dangerball.xml.h:11 hacks/config/extrusion.xml.h:19
-#: hacks/config/flipflop.xml.h:8 hacks/config/flyingtoasters.xml.h:14
-#: hacks/config/gears.xml.h:11 hacks/config/glforestfire.xml.h:20
-#: hacks/config/glhanoi.xml.h:10 hacks/config/glknots.xml.h:23
-#: hacks/config/glplanet.xml.h:15 hacks/config/glsnake.xml.h:15
-#: hacks/config/gltext.xml.h:21 hacks/config/jigglypuff.xml.h:25
-#: hacks/config/juggler3d.xml.h:13 hacks/config/lament.xml.h:9
-#: hacks/config/lavalite.xml.h:32 hacks/config/menger.xml.h:21
-#: hacks/config/mirrorblob.xml.h:23 hacks/config/moebius.xml.h:11
-#: hacks/config/molecule.xml.h:27 hacks/config/pinion.xml.h:15
-#: hacks/config/polyhedra.xml.h:166 hacks/config/providence.xml.h:9
-#: hacks/config/pulsar.xml.h:20 hacks/config/queens.xml.h:7
-#: hacks/config/sballs.xml.h:18 hacks/config/sierpinski3d.xml.h:12
-#: hacks/config/speedmine.xml.h:18 hacks/config/spheremonics.xml.h:26
-#: hacks/config/sproingies.xml.h:10 hacks/config/stairs.xml.h:7
-#: hacks/config/stonerview.xml.h:4 hacks/config/superquadrics.xml.h:12
-#: hacks/config/tangram.xml.h:8
-msgid "Wireframe"
-msgstr "Каркасное изображение"
+#: ../driver/xscreensaver-demo.glade2.in.h:114
+msgid "Mono"
+msgstr "Mono"
 
-#: hacks/config/attraction.xml.h:1
-msgid "Attraction"
-msgstr ""
+#: ../driver/xscreensaver-demo.glade2.in.h:115
+msgid "Advanced"
+msgstr "Расширенные"
 
-#: hacks/config/attraction.xml.h:2
-msgid "Ball Count"
-msgstr "Ð\9aолиÑ\87еÑ\81Ñ\82во Ð¼Ñ\8fÑ\87ей"
+#: ../driver/xscreensaver-demo.glade2.in.h:116
+msgid "Settings"
+msgstr "Ð\9dаÑ\81Ñ\82Ñ\80ойки"
 
-#: hacks/config/attraction.xml.h:3
-msgid "Ball Mass"
-msgstr ""
+#: ../hacks/config/abstractile.xml.h:1
+msgid "Abstractile"
+msgstr ""
+
+#: ../hacks/config/abstractile.xml.h:2 ../hacks/config/anemone.xml.h:2
+#: ../hacks/config/apollonian.xml.h:13 ../hacks/config/atlantis.xml.h:5
+#: ../hacks/config/attraction.xml.h:24 ../hacks/config/blitspin.xml.h:2
+#: ../hacks/config/boing.xml.h:5 ../hacks/config/bouncingcow.xml.h:5
+#: ../hacks/config/boxed.xml.h:5 ../hacks/config/carousel.xml.h:5
+#: ../hacks/config/ccurve.xml.h:5 ../hacks/config/circuit.xml.h:8
+#: ../hacks/config/cityflow.xml.h:9 ../hacks/config/companioncube.xml.h:5
+#: ../hacks/config/cube21.xml.h:8 ../hacks/config/cubenetic.xml.h:17
+#: ../hacks/config/cubestack.xml.h:5 ../hacks/config/cubestorm.xml.h:5
+#: ../hacks/config/cubetwist.xml.h:5 ../hacks/config/cubicgrid.xml.h:5
+#: ../hacks/config/dangerball.xml.h:5 ../hacks/config/discoball.xml.h:5
+#: ../hacks/config/dymaxionmap.xml.h:5 ../hacks/config/energystream.xml.h:2
+#: ../hacks/config/eruption.xml.h:10 ../hacks/config/fliptext.xml.h:5
+#: ../hacks/config/flyingtoasters.xml.h:5 ../hacks/config/fontglide.xml.h:5
+#: ../hacks/config/fuzzyflakes.xml.h:5 ../hacks/config/gears.xml.h:5
+#: ../hacks/config/geodesic.xml.h:14 ../hacks/config/gflux.xml.h:5
+#: ../hacks/config/glcells.xml.h:25 ../hacks/config/glknots.xml.h:5
+#: ../hacks/config/glmatrix.xml.h:8 ../hacks/config/glsnake.xml.h:11
+#: ../hacks/config/goop.xml.h:5 ../hacks/config/hexadrop.xml.h:5
+#: ../hacks/config/hexstrut.xml.h:5 ../hacks/config/hilbert.xml.h:8
+#: ../hacks/config/hydrostat.xml.h:5 ../hacks/config/hyperball.xml.h:9
+#: ../hacks/config/hypercube.xml.h:9 ../hacks/config/hypnowheel.xml.h:2
+#: ../hacks/config/interference.xml.h:5 ../hacks/config/jigglypuff.xml.h:14
+#: ../hacks/config/jigsaw.xml.h:5 ../hacks/config/juggle.xml.h:5
+#: ../hacks/config/juggler3d.xml.h:5 ../hacks/config/kaleidocycle.xml.h:8
+#: ../hacks/config/moebiusgears.xml.h:5 ../hacks/config/penetrate.xml.h:2
+#: ../hacks/config/petri.xml.h:16 ../hacks/config/phosphor.xml.h:6
+#: ../hacks/config/photopile.xml.h:12 ../hacks/config/piecewise.xml.h:8
+#: ../hacks/config/pinion.xml.h:5 ../hacks/config/polyhedra.xml.h:5
+#: ../hacks/config/pong.xml.h:2 ../hacks/config/pyro.xml.h:2
+#: ../hacks/config/quasicrystal.xml.h:5 ../hacks/config/raverhoop.xml.h:11
+#: ../hacks/config/rd-bomb.xml.h:2 ../hacks/config/rdbomb.xml.h:2
+#: ../hacks/config/rocks.xml.h:8 ../hacks/config/rubik.xml.h:6
+#: ../hacks/config/rubikblocks.xml.h:8 ../hacks/config/skytentacles.xml.h:15
+#: ../hacks/config/slidescreen.xml.h:11 ../hacks/config/sonar.xml.h:5
+#: ../hacks/config/speedmine.xml.h:5 ../hacks/config/splitflap.xml.h:5
+#: ../hacks/config/superquadrics.xml.h:5 ../hacks/config/tangram.xml.h:8
+#: ../hacks/config/topblock.xml.h:5 ../hacks/config/tronbit.xml.h:5
+#: ../hacks/config/twang.xml.h:8 ../hacks/config/unicrud.xml.h:5
+#: ../hacks/config/unknownpleasures.xml.h:8 ../hacks/config/vigilance.xml.h:5
+#: ../hacks/config/voronoi.xml.h:2 ../hacks/config/winduprobot.xml.h:5
+#: ../hacks/config/wormhole.xml.h:5 ../hacks/config/xjack.xml.h:2
+msgid "Slow"
+msgstr "Медленно"
 
-#: hacks/config/attraction.xml.h:4 hacks/config/fluidballs.xml.h:3
-msgid "Balls"
-msgstr "Мячи"
+#: ../hacks/config/abstractile.xml.h:3 ../hacks/config/anemone.xml.h:3
+#: ../hacks/config/apollonian.xml.h:14 ../hacks/config/attraction.xml.h:25
+#: ../hacks/config/boing.xml.h:6 ../hacks/config/boxed.xml.h:6
+#: ../hacks/config/cubestorm.xml.h:6 ../hacks/config/cubicgrid.xml.h:6
+#: ../hacks/config/discoball.xml.h:6 ../hacks/config/energystream.xml.h:3
+#: ../hacks/config/fliptext.xml.h:6 ../hacks/config/fontglide.xml.h:6
+#: ../hacks/config/fuzzyflakes.xml.h:6 ../hacks/config/gears.xml.h:6
+#: ../hacks/config/glknots.xml.h:6 ../hacks/config/goop.xml.h:6
+#: ../hacks/config/hexadrop.xml.h:6 ../hacks/config/hexstrut.xml.h:6
+#: ../hacks/config/hilbert.xml.h:11 ../hacks/config/hypnowheel.xml.h:5
+#: ../hacks/config/jigsaw.xml.h:6 ../hacks/config/juggle.xml.h:6
+#: ../hacks/config/juggler3d.xml.h:6 ../hacks/config/kaleidocycle.xml.h:9
+#: ../hacks/config/moebiusgears.xml.h:6 ../hacks/config/polyhedra.xml.h:6
+#: ../hacks/config/quasicrystal.xml.h:6 ../hacks/config/skytentacles.xml.h:18
+#: ../hacks/config/sonar.xml.h:6 ../hacks/config/splitflap.xml.h:6
+#: ../hacks/config/tessellimage.xml.h:6
+#: ../hacks/config/unknownpleasures.xml.h:9 ../hacks/config/vigilance.xml.h:6
+#: ../hacks/config/xjack.xml.h:3
+msgid "Speed"
+msgstr "Скорость"
 
-#: hacks/config/attraction.xml.h:5
-msgid "Bounce Off Walls"
-msgstr "Отскакивать от стен"
+#: ../hacks/config/abstractile.xml.h:4 ../hacks/config/anemone.xml.h:4
+#: ../hacks/config/apollonian.xml.h:15 ../hacks/config/atlantis.xml.h:7
+#: ../hacks/config/attraction.xml.h:26 ../hacks/config/blitspin.xml.h:4
+#: ../hacks/config/boing.xml.h:7 ../hacks/config/bouncingcow.xml.h:7
+#: ../hacks/config/boxed.xml.h:7 ../hacks/config/carousel.xml.h:7
+#: ../hacks/config/ccurve.xml.h:7 ../hacks/config/circuit.xml.h:10
+#: ../hacks/config/cityflow.xml.h:11 ../hacks/config/companioncube.xml.h:7
+#: ../hacks/config/cube21.xml.h:10 ../hacks/config/cubenetic.xml.h:19
+#: ../hacks/config/cubestack.xml.h:7 ../hacks/config/cubestorm.xml.h:7
+#: ../hacks/config/cubetwist.xml.h:7 ../hacks/config/cubicgrid.xml.h:7
+#: ../hacks/config/dangerball.xml.h:7 ../hacks/config/discoball.xml.h:7
+#: ../hacks/config/dymaxionmap.xml.h:7 ../hacks/config/energystream.xml.h:4
+#: ../hacks/config/eruption.xml.h:12 ../hacks/config/fliptext.xml.h:7
+#: ../hacks/config/flyingtoasters.xml.h:7 ../hacks/config/fontglide.xml.h:7
+#: ../hacks/config/fuzzyflakes.xml.h:7 ../hacks/config/gears.xml.h:7
+#: ../hacks/config/geodesic.xml.h:16 ../hacks/config/gflux.xml.h:7
+#: ../hacks/config/glknots.xml.h:7 ../hacks/config/glmatrix.xml.h:10
+#: ../hacks/config/glsnake.xml.h:13 ../hacks/config/goop.xml.h:7
+#: ../hacks/config/hexadrop.xml.h:7 ../hacks/config/hexstrut.xml.h:7
+#: ../hacks/config/hilbert.xml.h:10 ../hacks/config/hydrostat.xml.h:7
+#: ../hacks/config/hyperball.xml.h:11 ../hacks/config/hypercube.xml.h:11
+#: ../hacks/config/hypnowheel.xml.h:4 ../hacks/config/interference.xml.h:7
+#: ../hacks/config/jigglypuff.xml.h:16 ../hacks/config/jigsaw.xml.h:7
+#: ../hacks/config/juggle.xml.h:7 ../hacks/config/juggler3d.xml.h:7
+#: ../hacks/config/kaleidocycle.xml.h:10 ../hacks/config/moebiusgears.xml.h:7
+#: ../hacks/config/penetrate.xml.h:4 ../hacks/config/petri.xml.h:18
+#: ../hacks/config/phosphor.xml.h:8 ../hacks/config/photopile.xml.h:14
+#: ../hacks/config/piecewise.xml.h:10 ../hacks/config/pinion.xml.h:7
+#: ../hacks/config/polyhedra.xml.h:7 ../hacks/config/pong.xml.h:4
+#: ../hacks/config/pyro.xml.h:4 ../hacks/config/quasicrystal.xml.h:7
+#: ../hacks/config/raverhoop.xml.h:13 ../hacks/config/rd-bomb.xml.h:4
+#: ../hacks/config/rdbomb.xml.h:4 ../hacks/config/rocks.xml.h:10
+#: ../hacks/config/rubik.xml.h:8 ../hacks/config/rubikblocks.xml.h:10
+#: ../hacks/config/skytentacles.xml.h:17 ../hacks/config/slidescreen.xml.h:13
+#: ../hacks/config/sonar.xml.h:7 ../hacks/config/speedmine.xml.h:7
+#: ../hacks/config/splitflap.xml.h:7 ../hacks/config/starwars.xml.h:5
+#: ../hacks/config/superquadrics.xml.h:7 ../hacks/config/tangram.xml.h:10
+#: ../hacks/config/topblock.xml.h:7 ../hacks/config/tronbit.xml.h:7
+#: ../hacks/config/unicrud.xml.h:7 ../hacks/config/unknownpleasures.xml.h:10
+#: ../hacks/config/vigilance.xml.h:7 ../hacks/config/voronoi.xml.h:4
+#: ../hacks/config/winduprobot.xml.h:7 ../hacks/config/wormhole.xml.h:7
+#: ../hacks/config/xjack.xml.h:4
+msgid "Fast"
+msgstr "Быстро"
 
-#: hacks/config/attraction.xml.h:6 hacks/config/hopalong.xml.h:1
-#: hacks/config/interference.xml.h:5 hacks/config/qix.xml.h:2
-#: hacks/config/wander.xml.h:3
-msgid "Color Contrast"
-msgstr ""
+#: ../hacks/config/abstractile.xml.h:5 ../hacks/config/ccurve.xml.h:2
+#: ../hacks/config/flame.xml.h:5 ../hacks/config/maze.xml.h:13
+msgid "0 seconds"
+msgstr "0 секунд"
 
-#: hacks/config/attraction.xml.h:7
-msgid "Environmental Viscosity"
+#: ../hacks/config/abstractile.xml.h:6 ../hacks/config/boxed.xml.h:17
+#: ../hacks/config/celtic.xml.h:6 ../hacks/config/coral.xml.h:6
+#: ../hacks/config/cube21.xml.h:22 ../hacks/config/epicycle.xml.h:9
+#: ../hacks/config/flame.xml.h:6 ../hacks/config/glcells.xml.h:6
+#: ../hacks/config/helix.xml.h:6 ../hacks/config/imsmap.xml.h:6
+#: ../hacks/config/rorschach.xml.h:9 ../hacks/config/rubikblocks.xml.h:16
+#: ../hacks/config/tangram.xml.h:6 ../hacks/config/xlyap.xml.h:6
+#: ../hacks/config/xspirograph.xml.h:6
+msgid "Linger"
+msgstr "Задержка"
+
+#: ../hacks/config/abstractile.xml.h:7 ../hacks/config/voronoi.xml.h:16
+msgid "60 seconds"
+msgstr "60 секунд"
+
+#: ../hacks/config/abstractile.xml.h:8
+msgid "Random tile layout"
+msgstr "Случайная раскладка плиток"
+
+#: ../hacks/config/abstractile.xml.h:9
+msgid "Flat tiles"
+msgstr "Плоские плитки"
+
+#: ../hacks/config/abstractile.xml.h:10
+msgid "Thin tiles"
+msgstr "Тонкие плитки"
+
+#: ../hacks/config/abstractile.xml.h:11
+msgid "Outline tiles"
+msgstr "Контурные плитки"
+
+#: ../hacks/config/abstractile.xml.h:12
+msgid "Block tiles"
+msgstr "Блочные плитки"
+
+#: ../hacks/config/abstractile.xml.h:13
+msgid "Neon tiles"
+msgstr "Неоновые плитки"
+
+#: ../hacks/config/abstractile.xml.h:14
+msgid "Tiled tiles"
+msgstr "Черепичные плитки"
+
+#. #### -graphmode [none]
+#. #### -mother_ship_color1 [white]
+#. #### -size_factor_max [2.05]
+#. #### -size [-7]
+#. #### -spring_constant [5]
+#. <boolean id="db" _label="Double buffer" arg-set="-db"/>
+#. <boolean id="shm" _label="Use shared memory" arg-unset="-no-shm"/>
+#. #### -background [black]
+#. #### -right3d [Red]
+#. #### -cycle
+#. <boolean id="shm" _label="Use shared memory" arg-unset="-no-shm"/>
+#.
+#. <number id="ncolors" type="slider" arg="-ncolors %"
+#. _label="Number of colors" _low-label="Two" _high-label="Many"
+#. low="2" high="255" default="64"/>
+#.
+#. #### -anim-step-size [3]
+#. #### -3d
+#. #### -font []
+#. #### -w []
+#: ../hacks/config/abstractile.xml.h:15 ../hacks/config/anemone.xml.h:16
+#: ../hacks/config/anemotaxis.xml.h:12 ../hacks/config/ant.xml.h:22
+#: ../hacks/config/antinspect.xml.h:5 ../hacks/config/antmaze.xml.h:5
+#: ../hacks/config/antspotlight.xml.h:5 ../hacks/config/apollonian.xml.h:16
+#: ../hacks/config/apple2.xml.h:9 ../hacks/config/atlantis.xml.h:19
+#: ../hacks/config/attraction.xml.h:32 ../hacks/config/atunnel.xml.h:8
+#: ../hacks/config/barcode.xml.h:9 ../hacks/config/blaster.xml.h:11
+#: ../hacks/config/blinkbox.xml.h:12 ../hacks/config/blitspin.xml.h:9
+#: ../hacks/config/blocktube.xml.h:11 ../hacks/config/boing.xml.h:14
+#: ../hacks/config/bouboule.xml.h:11 ../hacks/config/bouncingcow.xml.h:12
+#: ../hacks/config/boxed.xml.h:23 ../hacks/config/boxfit.xml.h:15
+#: ../hacks/config/braid.xml.h:13 ../hacks/config/bsod.xml.h:5
+#: ../hacks/config/bubble3d.xml.h:11 ../hacks/config/bubbles.xml.h:11
+#: ../hacks/config/bumps.xml.h:11 ../hacks/config/cage.xml.h:6
+#: ../hacks/config/carousel.xml.h:18 ../hacks/config/ccurve.xml.h:11
+#: ../hacks/config/celtic.xml.h:9 ../hacks/config/circuit.xml.h:14
+#: ../hacks/config/cityflow.xml.h:17 ../hacks/config/cloudlife.xml.h:12
+#: ../hacks/config/companioncube.xml.h:14 ../hacks/config/compass.xml.h:5
+#: ../hacks/config/coral.xml.h:14 ../hacks/config/crackberg.xml.h:18
+#: ../hacks/config/critical.xml.h:8 ../hacks/config/crystal.xml.h:15
+#: ../hacks/config/cube21.xml.h:26 ../hacks/config/cubenetic.xml.h:26
+#: ../hacks/config/cubestack.xml.h:16 ../hacks/config/cubestorm.xml.h:17
+#: ../hacks/config/cubetwist.xml.h:18 ../hacks/config/cubicgrid.xml.h:12
+#: ../hacks/config/cwaves.xml.h:9 ../hacks/config/cynosure.xml.h:11
+#: ../hacks/config/dangerball.xml.h:14 ../hacks/config/decayscreen.xml.h:23
+#: ../hacks/config/deco.xml.h:14 ../hacks/config/deluxe.xml.h:16
+#: ../hacks/config/demon.xml.h:15 ../hacks/config/discoball.xml.h:14
+#: ../hacks/config/discrete.xml.h:11 ../hacks/config/distort.xml.h:22
+#: ../hacks/config/dnalogo.xml.h:10 ../hacks/config/drift.xml.h:11
+#: ../hacks/config/dymaxionmap.xml.h:14 ../hacks/config/endgame.xml.h:6
+#: ../hacks/config/energystream.xml.h:7 ../hacks/config/engine.xml.h:19
+#: ../hacks/config/epicycle.xml.h:14 ../hacks/config/eruption.xml.h:22
+#: ../hacks/config/euler2d.xml.h:29 ../hacks/config/extrusion.xml.h:17
+#: ../hacks/config/fadeplot.xml.h:14 ../hacks/config/fiberlamp.xml.h:11
+#: ../hacks/config/fireworkx.xml.h:10 ../hacks/config/flag.xml.h:13
+#: ../hacks/config/flame.xml.h:14 ../hacks/config/flipflop.xml.h:14
+#: ../hacks/config/flipscreen3d.xml.h:6 ../hacks/config/fliptext.xml.h:15
+#: ../hacks/config/flow.xml.h:21 ../hacks/config/fluidballs.xml.h:22
+#: ../hacks/config/flurry.xml.h:2 ../hacks/config/flyingtoasters.xml.h:14
+#: ../hacks/config/fontglide.xml.h:16 ../hacks/config/forest.xml.h:8
+#: ../hacks/config/fuzzyflakes.xml.h:12 ../hacks/config/galaxy.xml.h:13
+#: ../hacks/config/gears.xml.h:14 ../hacks/config/geodesic.xml.h:10
+#: ../hacks/config/geodesicgears.xml.h:13 ../hacks/config/gflux.xml.h:19
+#: ../hacks/config/glblur.xml.h:17 ../hacks/config/glcells.xml.h:32
+#: ../hacks/config/gleidescope.xml.h:14 ../hacks/config/glforestfire.xml.h:16
+#: ../hacks/config/glhanoi.xml.h:16 ../hacks/config/glknots.xml.h:24
+#: ../hacks/config/glmatrix.xml.h:20 ../hacks/config/glplanet.xml.h:13
+#: ../hacks/config/glschool.xml.h:17 ../hacks/config/glslideshow.xml.h:20
+#: ../hacks/config/glsnake.xml.h:18 ../hacks/config/gltext.xml.h:19
+#: ../hacks/config/goop.xml.h:13 ../hacks/config/grav.xml.h:12
+#: ../hacks/config/greynetic.xml.h:6 ../hacks/config/halftone.xml.h:17
+#: ../hacks/config/halo.xml.h:14 ../hacks/config/helix.xml.h:8
+#: ../hacks/config/hexadrop.xml.h:22 ../hacks/config/hexstrut.xml.h:17
+#: ../hacks/config/hilbert.xml.h:20 ../hacks/config/hopalong.xml.h:23
+#: ../hacks/config/hydrostat.xml.h:29 ../hacks/config/hyperball.xml.h:8
+#: ../hacks/config/hypercube.xml.h:8 ../hacks/config/hypertorus.xml.h:5
+#: ../hacks/config/hypnowheel.xml.h:8 ../hacks/config/ifs.xml.h:68
+#: ../hacks/config/imsmap.xml.h:18 ../hacks/config/interaggregate.xml.h:8
+#: ../hacks/config/interference.xml.h:21 ../hacks/config/intermomentary.xml.h:8
+#: ../hacks/config/jigglypuff.xml.h:10 ../hacks/config/jigsaw.xml.h:15
+#: ../hacks/config/juggle.xml.h:21 ../hacks/config/juggler3d.xml.h:21
+#: ../hacks/config/julia.xml.h:14 ../hacks/config/kaleidescope.xml.h:13
+#: ../hacks/config/kaleidocycle.xml.h:21 ../hacks/config/klein.xml.h:45
+#: ../hacks/config/kumppa.xml.h:8 ../hacks/config/lament.xml.h:7
+#: ../hacks/config/laser.xml.h:12 ../hacks/config/lavalite.xml.h:16
+#: ../hacks/config/lcdscrub.xml.h:7 ../hacks/config/lightning.xml.h:8
+#: ../hacks/config/lisa.xml.h:16 ../hacks/config/lissie.xml.h:15
+#: ../hacks/config/lmorph.xml.h:17 ../hacks/config/lockward.xml.h:9
+#: ../hacks/config/loop.xml.h:12 ../hacks/config/m6502.xml.h:6
+#: ../hacks/config/maze.xml.h:12 ../hacks/config/memscroller.xml.h:9
+#: ../hacks/config/menger.xml.h:20 ../hacks/config/metaballs.xml.h:16
+#: ../hacks/config/mirrorblob.xml.h:25 ../hacks/config/mismunch.xml.h:13
+#: ../hacks/config/moebius.xml.h:7 ../hacks/config/moebiusgears.xml.h:14
+#: ../hacks/config/moire.xml.h:12 ../hacks/config/moire2.xml.h:9
+#: ../hacks/config/molecule.xml.h:15 ../hacks/config/morph3d.xml.h:11
+#: ../hacks/config/mountain.xml.h:11 ../hacks/config/munch.xml.h:16
+#: ../hacks/config/nerverot.xml.h:21 ../hacks/config/noof.xml.h:5
+#: ../hacks/config/noseguy.xml.h:2 ../hacks/config/pacman.xml.h:6
+#: ../hacks/config/pedal.xml.h:9 ../hacks/config/penetrate.xml.h:8
+#: ../hacks/config/penrose.xml.h:12 ../hacks/config/petri.xml.h:5
+#: ../hacks/config/phosphor.xml.h:13 ../hacks/config/photopile.xml.h:22
+#: ../hacks/config/piecewise.xml.h:15 ../hacks/config/pinion.xml.h:16
+#: ../hacks/config/pipes.xml.h:20 ../hacks/config/polyhedra.xml.h:168
+#: ../hacks/config/polyominoes.xml.h:12 ../hacks/config/polytopes.xml.h:18
+#: ../hacks/config/pong.xml.h:9 ../hacks/config/popsquares.xml.h:21
+#: ../hacks/config/projectiveplane.xml.h:43 ../hacks/config/providence.xml.h:7
+#: ../hacks/config/pulsar.xml.h:14 ../hacks/config/pyro.xml.h:14
+#: ../hacks/config/qix.xml.h:24 ../hacks/config/quasicrystal.xml.h:13
+#: ../hacks/config/queens.xml.h:6 ../hacks/config/raverhoop.xml.h:20
+#: ../hacks/config/rd-bomb.xml.h:17 ../hacks/config/rdbomb.xml.h:17
+#: ../hacks/config/ripples.xml.h:18 ../hacks/config/rocks.xml.h:17
+#: ../hacks/config/romanboy.xml.h:41 ../hacks/config/rorschach.xml.h:11
+#: ../hacks/config/rotor.xml.h:13 ../hacks/config/rotzoomer.xml.h:15
+#: ../hacks/config/rubik.xml.h:11 ../hacks/config/rubikblocks.xml.h:20
+#: ../hacks/config/sballs.xml.h:16 ../hacks/config/shadebobs.xml.h:16
+#: ../hacks/config/sierpinski.xml.h:13 ../hacks/config/sierpinski3d.xml.h:10
+#: ../hacks/config/skytentacles.xml.h:25 ../hacks/config/slidescreen.xml.h:18
+#: ../hacks/config/slip.xml.h:13 ../hacks/config/sonar.xml.h:34
+#: ../hacks/config/speedmine.xml.h:17 ../hacks/config/sphere.xml.h:8
+#: ../hacks/config/spheremonics.xml.h:22 ../hacks/config/spiral.xml.h:11
+#: ../hacks/config/splitflap.xml.h:25 ../hacks/config/splodesic.xml.h:11
+#: ../hacks/config/spotlight.xml.h:11 ../hacks/config/sproingies.xml.h:9
+#: ../hacks/config/squiral.xml.h:17 ../hacks/config/stairs.xml.h:5
+#: ../hacks/config/starfish.xml.h:17 ../hacks/config/starwars.xml.h:15
+#: ../hacks/config/stonerview.xml.h:7 ../hacks/config/strange.xml.h:23
+#: ../hacks/config/substrate.xml.h:19 ../hacks/config/superquadrics.xml.h:13
+#: ../hacks/config/surfaces.xml.h:27 ../hacks/config/swirl.xml.h:11
+#: ../hacks/config/t3d.xml.h:15 ../hacks/config/tangram.xml.h:16
+#: ../hacks/config/tessellimage.xml.h:16 ../hacks/config/testx11.xml.h:2
+#: ../hacks/config/thornbird.xml.h:16 ../hacks/config/timetunnel.xml.h:8
+#: ../hacks/config/topblock.xml.h:24 ../hacks/config/triangle.xml.h:8
+#: ../hacks/config/tronbit.xml.h:11 ../hacks/config/truchet.xml.h:6
+#: ../hacks/config/twang.xml.h:18 ../hacks/config/unicrud.xml.h:10
+#: ../hacks/config/unknownpleasures.xml.h:14
+#: ../hacks/config/vermiculate.xml.h:5 ../hacks/config/vidwhacker.xml.h:6
+#: ../hacks/config/vines.xml.h:8 ../hacks/config/voronoi.xml.h:11
+#: ../hacks/config/wander.xml.h:13 ../hacks/config/webcollage.xml.h:11
+#: ../hacks/config/whirlwindwarp.xml.h:8 ../hacks/config/whirlygig.xml.h:31
+#: ../hacks/config/winduprobot.xml.h:22 ../hacks/config/worm.xml.h:11
+#: ../hacks/config/wormhole.xml.h:11 ../hacks/config/xanalogtv.xml.h:2
+#: ../hacks/config/xflame.xml.h:7 ../hacks/config/xjack.xml.h:6
+#: ../hacks/config/xlyap.xml.h:9 ../hacks/config/xmatrix.xml.h:21
+#: ../hacks/config/xrayswarm.xml.h:5 ../hacks/config/xspirograph.xml.h:9
+#: ../hacks/config/zoom.xml.h:15
+msgid "Show frame rate"
+msgstr "Показывать частоту кадров"
+
+#: ../hacks/config/abstractile.xml.h:16
+msgid ""
+"Mosaic patterns of interlocking tiles. Written by Steve Sundstrom; 2004."
+msgstr ""
+
+#: ../hacks/config/anemone.xml.h:1
+msgid "Anemone"
 msgstr ""
 
-#: hacks/config/attraction.xml.h:9
-msgid "Filled Splines"
-msgstr "Заполненные сплайны"
+#: ../hacks/config/anemone.xml.h:5 ../hacks/config/anemotaxis.xml.h:8
+#: ../hacks/config/binaryring.xml.h:8 ../hacks/config/blaster.xml.h:7
+#: ../hacks/config/bouboule.xml.h:5 ../hacks/config/boxed.xml.h:8
+#: ../hacks/config/cityflow.xml.h:5 ../hacks/config/coral.xml.h:11
+#: ../hacks/config/crackberg.xml.h:8 ../hacks/config/cubenetic.xml.h:5
+#: ../hacks/config/cubestorm.xml.h:8 ../hacks/config/dangerball.xml.h:8
+#: ../hacks/config/eruption.xml.h:5 ../hacks/config/euler2d.xml.h:5
+#: ../hacks/config/fiberlamp.xml.h:5 ../hacks/config/flame.xml.h:8
+#: ../hacks/config/flow.xml.h:5 ../hacks/config/fluidballs.xml.h:5
+#: ../hacks/config/fuzzyflakes.xml.h:8 ../hacks/config/glcells.xml.h:8
+#: ../hacks/config/glschool.xml.h:5 ../hacks/config/goop.xml.h:8
+#: ../hacks/config/grav.xml.h:5 ../hacks/config/halftone.xml.h:5
+#: ../hacks/config/halo.xml.h:5 ../hacks/config/hydrostat.xml.h:14
+#: ../hacks/config/interaggregate.xml.h:5 ../hacks/config/interference.xml.h:11
+#: ../hacks/config/jigsaw.xml.h:8 ../hacks/config/julia.xml.h:5
+#: ../hacks/config/kaleidescope.xml.h:5 ../hacks/config/lisa.xml.h:5
+#: ../hacks/config/lmorph.xml.h:5 ../hacks/config/nerverot.xml.h:8
+#: ../hacks/config/pedal.xml.h:5 ../hacks/config/petri.xml.h:10
+#: ../hacks/config/piecewise.xml.h:5 ../hacks/config/qix.xml.h:5
+#: ../hacks/config/rocks.xml.h:5 ../hacks/config/sierpinski.xml.h:5
+#: ../hacks/config/slip.xml.h:5 ../hacks/config/spiral.xml.h:5
+#: ../hacks/config/substrate.xml.h:8 ../hacks/config/swirl.xml.h:5
+#: ../hacks/config/thornbird.xml.h:5 ../hacks/config/topblock.xml.h:13
+#: ../hacks/config/unknownpleasures.xml.h:5 ../hacks/config/voronoi.xml.h:5
+#: ../hacks/config/whirlwindwarp.xml.h:2 ../hacks/config/wormhole.xml.h:8
+msgid "Few"
+msgstr "Мало"
 
-#: hacks/config/attraction.xml.h:10 hacks/config/carousel.xml.h:7
-#: hacks/config/ccurve.xml.h:9 hacks/config/cloudlife.xml.h:5
-#: hacks/config/cubenetic.xml.h:10 hacks/config/euler2d.xml.h:5
-#: hacks/config/flame.xml.h:9 hacks/config/fliptext.xml.h:9
-#: hacks/config/glslideshow.xml.h:13 hacks/config/goop.xml.h:6
-#: hacks/config/halftone.xml.h:7 hacks/config/hopalong.xml.h:10
-#: hacks/config/hyperball.xml.h:3 hacks/config/hypercube.xml.h:3
-#: hacks/config/interference.xml.h:8 hacks/config/jigglypuff.xml.h:8
-#: hacks/config/kumppa.xml.h:4 hacks/config/lavalite.xml.h:12
-#: hacks/config/nerverot.xml.h:11 hacks/config/petri.xml.h:8
-#: hacks/config/pyro.xml.h:5 hacks/config/qix.xml.h:10
-#: hacks/config/speedmine.xml.h:5 hacks/config/spheremonics.xml.h:6
-#: hacks/config/spiral.xml.h:4 hacks/config/squiral.xml.h:6
-#: hacks/config/superquadrics.xml.h:5 hacks/config/t3d.xml.h:7
-#: hacks/config/twang.xml.h:5 hacks/config/wander.xml.h:8
-#: hacks/config/xmountains.xml.h:17
-msgid "High"
-msgstr "Высокое"
+#: ../hacks/config/anemone.xml.h:6 ../hacks/config/fuzzyflakes.xml.h:20
+#: ../hacks/config/hypnowheel.xml.h:13
+msgid "Arms"
+msgstr "Части"
+
+#.
+#. On a 2.93 gHz iMac i7, I get these rates with -delay 0:
+#.
+#. detail 3:  invisible
+#. detail 4:  barely visible
+#. detail 5:  1000+ fps, looks like noise at -delay 0, ok at -delay 20000
+#. detail 8:  ~700+ fps
+#. detail 9:  ~400 fps
+#. detail 10: ~300 fps
+#. detail 11: ~100 fps
+#. detail 12:  ~50 fps
+#. detail 13:  ~17 fps
+#. detail 14:   ~8 fps
+#. detail 15:   ~2 fps
+#.
+#. With the default -delay, CPU load only starts causing the frame rate
+#. to drop below 30 fps detail 12 or higher.
+#.
+#. #### -color [random]
+#: ../hacks/config/anemone.xml.h:7 ../hacks/config/anemotaxis.xml.h:10
+#: ../hacks/config/ant.xml.h:13 ../hacks/config/apollonian.xml.h:12
+#: ../hacks/config/attraction.xml.h:19 ../hacks/config/blaster.xml.h:9
+#: ../hacks/config/bouboule.xml.h:7 ../hacks/config/braid.xml.h:10
+#: ../hacks/config/cityflow.xml.h:7 ../hacks/config/coral.xml.h:13
+#: ../hacks/config/critical.xml.h:7 ../hacks/config/crystal.xml.h:7
+#: ../hacks/config/cubenetic.xml.h:7 ../hacks/config/cubestorm.xml.h:10
+#: ../hacks/config/cynosure.xml.h:7 ../hacks/config/deco.xml.h:7
+#: ../hacks/config/deluxe.xml.h:13 ../hacks/config/demon.xml.h:13
+#: ../hacks/config/discrete.xml.h:10 ../hacks/config/drift.xml.h:10
+#: ../hacks/config/epicycle.xml.h:7 ../hacks/config/eruption.xml.h:7
+#: ../hacks/config/euler2d.xml.h:7 ../hacks/config/fadeplot.xml.h:13
+#: ../hacks/config/fiberlamp.xml.h:7 ../hacks/config/flag.xml.h:11
+#: ../hacks/config/flame.xml.h:10 ../hacks/config/flow.xml.h:7
+#: ../hacks/config/fluidballs.xml.h:7 ../hacks/config/forest.xml.h:7
+#: ../hacks/config/fuzzyflakes.xml.h:10 ../hacks/config/galaxy.xml.h:11
+#: ../hacks/config/glcells.xml.h:10 ../hacks/config/goop.xml.h:10
+#: ../hacks/config/grav.xml.h:7 ../hacks/config/halftone.xml.h:7
+#: ../hacks/config/halo.xml.h:7 ../hacks/config/hopalong.xml.h:11
+#: ../hacks/config/hydrostat.xml.h:10 ../hacks/config/ifs.xml.h:64
+#: ../hacks/config/imsmap.xml.h:13 ../hacks/config/interaggregate.xml.h:7
+#: ../hacks/config/interference.xml.h:13 ../hacks/config/jigsaw.xml.h:10
+#: ../hacks/config/julia.xml.h:13 ../hacks/config/kaleidescope.xml.h:7
+#: ../hacks/config/laser.xml.h:11 ../hacks/config/lightning.xml.h:7
+#: ../hacks/config/lisa.xml.h:7 ../hacks/config/lissie.xml.h:10
+#: ../hacks/config/lmorph.xml.h:7 ../hacks/config/loop.xml.h:10
+#: ../hacks/config/metaballs.xml.h:10 ../hacks/config/mismunch.xml.h:10
+#: ../hacks/config/moire.xml.h:7 ../hacks/config/moire2.xml.h:7
+#: ../hacks/config/mountain.xml.h:10 ../hacks/config/munch.xml.h:10
+#: ../hacks/config/nerverot.xml.h:10 ../hacks/config/pedal.xml.h:7
+#: ../hacks/config/penrose.xml.h:7 ../hacks/config/petri.xml.h:12
+#: ../hacks/config/piecewise.xml.h:7 ../hacks/config/polyominoes.xml.h:11
+#: ../hacks/config/qix.xml.h:7 ../hacks/config/rd-bomb.xml.h:16
+#: ../hacks/config/rdbomb.xml.h:16 ../hacks/config/rocks.xml.h:7
+#: ../hacks/config/rotor.xml.h:10 ../hacks/config/shadebobs.xml.h:10
+#: ../hacks/config/sierpinski.xml.h:7 ../hacks/config/slip.xml.h:7
+#: ../hacks/config/sphere.xml.h:7 ../hacks/config/spiral.xml.h:7
+#: ../hacks/config/squiral.xml.h:15 ../hacks/config/starfish.xml.h:16
+#: ../hacks/config/strange.xml.h:22 ../hacks/config/swirl.xml.h:7
+#: ../hacks/config/thornbird.xml.h:7 ../hacks/config/topblock.xml.h:15
+#: ../hacks/config/triangle.xml.h:7 ../hacks/config/unknownpleasures.xml.h:7
+#: ../hacks/config/vines.xml.h:7 ../hacks/config/voronoi.xml.h:7
+#: ../hacks/config/whirlwindwarp.xml.h:4 ../hacks/config/worm.xml.h:7
+msgid "Many"
+msgstr "Много"
 
-#: hacks/config/attraction.xml.h:11
-msgid "Ignore Screen Edges"
-msgstr "Игнорировать границы экрана"
+#: ../hacks/config/anemone.xml.h:8 ../hacks/config/skytentacles.xml.h:3
+msgid "Tentacles"
+msgstr "Щупальца"
+
+#: ../hacks/config/anemone.xml.h:9 ../hacks/config/cubestack.xml.h:8
+#: ../hacks/config/cubestorm.xml.h:11 ../hacks/config/cubetwist.xml.h:8
+#: ../hacks/config/deluxe.xml.h:5 ../hacks/config/fadeplot.xml.h:5
+#: ../hacks/config/fuzzyflakes.xml.h:21 ../hacks/config/glknots.xml.h:19
+#: ../hacks/config/hexstrut.xml.h:11 ../hacks/config/hilbert.xml.h:15
+#: ../hacks/config/hydrostat.xml.h:16 ../hacks/config/lmorph.xml.h:11
+#: ../hacks/config/skytentacles.xml.h:8 ../hacks/config/starfish.xml.h:11
+#: ../hacks/config/thornbird.xml.h:8
+msgid "Thin"
+msgstr "Тонкая"
 
-#: hacks/config/attraction.xml.h:12
-msgid "Inward"
-msgstr ""
+#: ../hacks/config/anemone.xml.h:10 ../hacks/config/cubestack.xml.h:9
+#: ../hacks/config/cubetwist.xml.h:9 ../hacks/config/fadeplot.xml.h:6
+#: ../hacks/config/fuzzyflakes.xml.h:22 ../hacks/config/glknots.xml.h:20
+#: ../hacks/config/hydrostat.xml.h:17 ../hacks/config/moire2.xml.h:8
+#: ../hacks/config/skytentacles.xml.h:9 ../hacks/config/thornbird.xml.h:9
+msgid "Thickness"
+msgstr "Толщина"
+
+#: ../hacks/config/anemone.xml.h:11 ../hacks/config/cubestack.xml.h:10
+#: ../hacks/config/cubestorm.xml.h:13 ../hacks/config/cubetwist.xml.h:10
+#: ../hacks/config/deluxe.xml.h:7 ../hacks/config/fadeplot.xml.h:7
+#: ../hacks/config/fuzzyflakes.xml.h:23 ../hacks/config/glknots.xml.h:21
+#: ../hacks/config/hexstrut.xml.h:13 ../hacks/config/hilbert.xml.h:17
+#: ../hacks/config/hydrostat.xml.h:18 ../hacks/config/lmorph.xml.h:13
+#: ../hacks/config/skytentacles.xml.h:10 ../hacks/config/starfish.xml.h:13
+#: ../hacks/config/thornbird.xml.h:10
+msgid "Thick"
+msgstr "Толстая"
 
-#: hacks/config/attraction.xml.h:14
-msgid ""
-"Like qix, this uses a simple simple motion model to generate many different "
-"display modes. The control points attract each other up to a certain "
-"distance, and then begin to repel each other. The attraction/repulsion is "
-"proportional to the distance between any two particles, similar to the "
-"strong and weak nuclear forces. One of the most interesting ways to watch "
-"this hack is simply as bouncing balls, because their motions and "
-"interactions with each other are so odd. Sometimes two balls will get into a "
-"tight orbit around each other, to be interrupted later by a third, or by the "
-"edge of the screen. It looks quite chaotic. Written by Jamie Zawinski, based "
-"on Lisp code by John Pezaris."
-msgstr ""
+#: ../hacks/config/anemone.xml.h:12 ../hacks/config/pyro.xml.h:10
+#: ../hacks/config/splodesic.xml.h:7 ../hacks/config/winduprobot.xml.h:19
+msgid "Often"
+msgstr "Часто"
 
-#: hacks/config/attraction.xml.h:15 hacks/config/deluxe.xml.h:5
-#: hacks/config/lmorph.xml.h:7 hacks/config/pedal.xml.h:5
-#: hacks/config/starfish.xml.h:4 hacks/config/whirlygig.xml.h:10
-msgid "Lines"
-msgstr "Линии"
+#: ../hacks/config/anemone.xml.h:13
+msgid "Withdraw freqency"
+msgstr "Частота прорисовки"
 
-#: hacks/config/attraction.xml.h:16 hacks/config/blocktube.xml.h:5
-#: hacks/config/braid.xml.h:6 hacks/config/celtic.xml.h:4
-#: hacks/config/crackberg.xml.h:13 hacks/config/cube21.xml.h:9
-#: hacks/config/cynosure.xml.h:5 hacks/config/drift.xml.h:8
-#: hacks/config/eruption.xml.h:11 hacks/config/euler2d.xml.h:6
-#: hacks/config/fiberlamp.xml.h:5 hacks/config/fireflies.xml.h:21
-#: hacks/config/flow.xml.h:6 hacks/config/fontglide.xml.h:8
-#: hacks/config/galaxy.xml.h:5 hacks/config/juggle.xml.h:4
-#: hacks/config/klein.xml.h:4 hacks/config/laser.xml.h:5
-#: hacks/config/menger.xml.h:4 hacks/config/metaballs.xml.h:5
-#: hacks/config/mismunch.xml.h:3 hacks/config/munch.xml.h:4
-#: hacks/config/nerverot.xml.h:13 hacks/config/petri.xml.h:9
-#: hacks/config/polyominoes.xml.h:4 hacks/config/rotor.xml.h:5
-#: hacks/config/shadebobs.xml.h:4 hacks/config/sierpinski3d.xml.h:3
-#: hacks/config/spheremonics.xml.h:7 hacks/config/substrate.xml.h:11
-#: hacks/config/timetunnel.xml.h:6 hacks/config/wander.xml.h:10
-#: hacks/config/whirlwindwarp.xml.h:3
-msgid "Long"
-msgstr "Длинный"
-
-#: hacks/config/attraction.xml.h:17 hacks/config/carousel.xml.h:9
-#: hacks/config/ccurve.xml.h:10 hacks/config/cloudlife.xml.h:8
-#: hacks/config/cubenetic.xml.h:12 hacks/config/euler2d.xml.h:7
-#: hacks/config/flame.xml.h:10 hacks/config/fliptext.xml.h:10
-#: hacks/config/glslideshow.xml.h:16 hacks/config/goop.xml.h:7
-#: hacks/config/halftone.xml.h:9 hacks/config/hopalong.xml.h:14
-#: hacks/config/hyperball.xml.h:6 hacks/config/hypercube.xml.h:5
-#: hacks/config/interference.xml.h:12 hacks/config/jigglypuff.xml.h:11
-#: hacks/config/kumppa.xml.h:6 hacks/config/lavalite.xml.h:14
-#: hacks/config/nerverot.xml.h:14 hacks/config/petri.xml.h:10
-#: hacks/config/pyro.xml.h:7 hacks/config/qix.xml.h:13
-#: hacks/config/speedmine.xml.h:6 hacks/config/spheremonics.xml.h:8
-#: hacks/config/spiral.xml.h:5 hacks/config/squiral.xml.h:8
-#: hacks/config/superquadrics.xml.h:6 hacks/config/t3d.xml.h:8
-#: hacks/config/twang.xml.h:7 hacks/config/wander.xml.h:11
-msgid "Low"
-msgstr "Низкое"
+#: ../hacks/config/anemone.xml.h:14
+msgid "Rarely"
+msgstr "Редко"
 
-#: hacks/config/attraction.xml.h:20
-msgid "Orbital Mode"
-msgstr "Ð\9eÑ\80биÑ\82алÑ\8cнÑ\8bй Ñ\80ежим"
+#: ../hacks/config/anemone.xml.h:15
+msgid "Turn speed"
+msgstr "СкоÑ\80оÑ\81Ñ\82Ñ\8c Ð²Ñ\80аÑ\89ениÑ\8f"
 
-#: hacks/config/attraction.xml.h:21
-msgid "Outward"
+#: ../hacks/config/anemone.xml.h:17
+msgid "Wiggling tentacles. Written by Gabriel Finch; 2002."
 msgstr ""
 
-#: hacks/config/attraction.xml.h:22
-msgid "Polygons"
-msgstr "Многоугольники"
+#: ../hacks/config/anemotaxis.xml.h:1
+msgid "Anemotaxis"
+msgstr ""
 
-#: hacks/config/attraction.xml.h:23 hacks/config/fuzzyflakes.xml.h:13
-#: hacks/config/spotlight.xml.h:3 hacks/config/xplanet.xml.h:55
-msgid "Radius"
-msgstr "Радиус"
+#. #### -colorcount [64]
+#: ../hacks/config/anemotaxis.xml.h:2 ../hacks/config/ant.xml.h:2
+#: ../hacks/config/antinspect.xml.h:2 ../hacks/config/antmaze.xml.h:2
+#: ../hacks/config/antspotlight.xml.h:2 ../hacks/config/apple2.xml.h:10
+#: ../hacks/config/atlantis.xml.h:2 ../hacks/config/attraction.xml.h:11
+#: ../hacks/config/atunnel.xml.h:2 ../hacks/config/barcode.xml.h:2
+#: ../hacks/config/binaryring.xml.h:2 ../hacks/config/blaster.xml.h:2
+#: ../hacks/config/blinkbox.xml.h:2 ../hacks/config/blocktube.xml.h:2
+#: ../hacks/config/bouboule.xml.h:2 ../hacks/config/bouncingcow.xml.h:2
+#: ../hacks/config/boxed.xml.h:2 ../hacks/config/boxfit.xml.h:2
+#: ../hacks/config/braid.xml.h:2 ../hacks/config/bubble3d.xml.h:2
+#: ../hacks/config/bubbles.xml.h:2 ../hacks/config/bumps.xml.h:3
+#: ../hacks/config/cage.xml.h:2 ../hacks/config/carousel.xml.h:2
+#: ../hacks/config/ccurve.xml.h:8 ../hacks/config/celtic.xml.h:2
+#: ../hacks/config/circuit.xml.h:2 ../hacks/config/cityflow.xml.h:2
+#: ../hacks/config/cloudlife.xml.h:2 ../hacks/config/companioncube.xml.h:2
+#: ../hacks/config/compass.xml.h:2 ../hacks/config/coral.xml.h:2
+#: ../hacks/config/crackberg.xml.h:2 ../hacks/config/critical.xml.h:2
+#: ../hacks/config/crystal.xml.h:2 ../hacks/config/cube21.xml.h:2
+#: ../hacks/config/cubenetic.xml.h:2 ../hacks/config/cubestack.xml.h:2
+#: ../hacks/config/cubestorm.xml.h:2 ../hacks/config/cubetwist.xml.h:2
+#: ../hacks/config/cubicgrid.xml.h:2 ../hacks/config/cwaves.xml.h:2
+#: ../hacks/config/cynosure.xml.h:2 ../hacks/config/dangerball.xml.h:2
+#: ../hacks/config/decayscreen.xml.h:2 ../hacks/config/deluxe.xml.h:2
+#: ../hacks/config/demon.xml.h:2 ../hacks/config/discoball.xml.h:2
+#: ../hacks/config/discrete.xml.h:2 ../hacks/config/distort.xml.h:2
+#: ../hacks/config/dnalogo.xml.h:2 ../hacks/config/drift.xml.h:2
+#: ../hacks/config/dymaxionmap.xml.h:2 ../hacks/config/endgame.xml.h:2
+#: ../hacks/config/engine.xml.h:2 ../hacks/config/epicycle.xml.h:2
+#: ../hacks/config/eruption.xml.h:2 ../hacks/config/euler2d.xml.h:2
+#: ../hacks/config/extrusion.xml.h:2 ../hacks/config/fadeplot.xml.h:2
+#: ../hacks/config/fiberlamp.xml.h:2 ../hacks/config/fireworkx.xml.h:2
+#: ../hacks/config/flag.xml.h:3 ../hacks/config/flame.xml.h:2
+#: ../hacks/config/flipflop.xml.h:2 ../hacks/config/flipscreen3d.xml.h:2
+#: ../hacks/config/fliptext.xml.h:2 ../hacks/config/flow.xml.h:2
+#: ../hacks/config/fluidballs.xml.h:2 ../hacks/config/flyingtoasters.xml.h:2
+#: ../hacks/config/fontglide.xml.h:2 ../hacks/config/forest.xml.h:2
+#: ../hacks/config/fuzzyflakes.xml.h:2 ../hacks/config/galaxy.xml.h:2
+#: ../hacks/config/gears.xml.h:2 ../hacks/config/geodesic.xml.h:11
+#: ../hacks/config/geodesicgears.xml.h:2 ../hacks/config/gflux.xml.h:2
+#: ../hacks/config/glblur.xml.h:2 ../hacks/config/glcells.xml.h:2
+#: ../hacks/config/gleidescope.xml.h:2 ../hacks/config/glforestfire.xml.h:2
+#: ../hacks/config/glhanoi.xml.h:2 ../hacks/config/glknots.xml.h:2
+#: ../hacks/config/glmatrix.xml.h:2 ../hacks/config/glplanet.xml.h:2
+#: ../hacks/config/glschool.xml.h:2 ../hacks/config/glslideshow.xml.h:2
+#: ../hacks/config/glsnake.xml.h:2 ../hacks/config/gltext.xml.h:2
+#: ../hacks/config/goop.xml.h:2 ../hacks/config/grav.xml.h:2
+#: ../hacks/config/greynetic.xml.h:2 ../hacks/config/halftone.xml.h:2
+#: ../hacks/config/halo.xml.h:2 ../hacks/config/helix.xml.h:2
+#: ../hacks/config/hexadrop.xml.h:2 ../hacks/config/hexstrut.xml.h:2
+#: ../hacks/config/hopalong.xml.h:2 ../hacks/config/hydrostat.xml.h:2
+#: ../hacks/config/hyperball.xml.h:2 ../hacks/config/hypercube.xml.h:2
+#: ../hacks/config/hypertorus.xml.h:2 ../hacks/config/hypnowheel.xml.h:14
+#: ../hacks/config/ifs.xml.h:2 ../hacks/config/imsmap.xml.h:2
+#: ../hacks/config/interaggregate.xml.h:2 ../hacks/config/interference.xml.h:2
+#: ../hacks/config/intermomentary.xml.h:2 ../hacks/config/jigglypuff.xml.h:11
+#: ../hacks/config/jigsaw.xml.h:2 ../hacks/config/juggle.xml.h:2
+#: ../hacks/config/juggler3d.xml.h:2 ../hacks/config/julia.xml.h:2
+#: ../hacks/config/kaleidescope.xml.h:2 ../hacks/config/kaleidocycle.xml.h:2
+#: ../hacks/config/klein.xml.h:42 ../hacks/config/kumppa.xml.h:2
+#: ../hacks/config/lament.xml.h:2 ../hacks/config/laser.xml.h:2
+#: ../hacks/config/lavalite.xml.h:2 ../hacks/config/lcdscrub.xml.h:2
+#: ../hacks/config/lightning.xml.h:2 ../hacks/config/lisa.xml.h:2
+#: ../hacks/config/lissie.xml.h:2 ../hacks/config/lmorph.xml.h:2
+#: ../hacks/config/lockward.xml.h:2 ../hacks/config/loop.xml.h:2
+#: ../hacks/config/m6502.xml.h:7 ../hacks/config/maze.xml.h:2
+#: ../hacks/config/memscroller.xml.h:2 ../hacks/config/menger.xml.h:2
+#: ../hacks/config/metaballs.xml.h:2 ../hacks/config/mirrorblob.xml.h:2
+#: ../hacks/config/mismunch.xml.h:2 ../hacks/config/moebius.xml.h:2
+#: ../hacks/config/moebiusgears.xml.h:2 ../hacks/config/moire2.xml.h:2
+#: ../hacks/config/molecule.xml.h:2 ../hacks/config/morph3d.xml.h:2
+#: ../hacks/config/mountain.xml.h:2 ../hacks/config/munch.xml.h:2
+#: ../hacks/config/nerverot.xml.h:2 ../hacks/config/noof.xml.h:2
+#: ../hacks/config/pacman.xml.h:2 ../hacks/config/penrose.xml.h:2
+#: ../hacks/config/petri.xml.h:2 ../hacks/config/phosphor.xml.h:2
+#: ../hacks/config/photopile.xml.h:15 ../hacks/config/piecewise.xml.h:2
+#: ../hacks/config/pinion.xml.h:2 ../hacks/config/pipes.xml.h:2
+#: ../hacks/config/polyhedra.xml.h:2 ../hacks/config/polyominoes.xml.h:3
+#: ../hacks/config/polytopes.xml.h:24 ../hacks/config/pong.xml.h:10
+#: ../hacks/config/popsquares.xml.h:2 ../hacks/config/projectiveplane.xml.h:35
+#: ../hacks/config/providence.xml.h:2 ../hacks/config/pulsar.xml.h:2
+#: ../hacks/config/pyro.xml.h:11 ../hacks/config/qix.xml.h:2
+#: ../hacks/config/quasicrystal.xml.h:2 ../hacks/config/queens.xml.h:2
+#: ../hacks/config/raverhoop.xml.h:2 ../hacks/config/ripples.xml.h:2
+#: ../hacks/config/rocks.xml.h:2 ../hacks/config/romanboy.xml.h:38
+#: ../hacks/config/rotor.xml.h:2 ../hacks/config/rotzoomer.xml.h:2
+#: ../hacks/config/rubik.xml.h:2 ../hacks/config/rubikblocks.xml.h:2
+#: ../hacks/config/sballs.xml.h:2 ../hacks/config/shadebobs.xml.h:2
+#: ../hacks/config/sierpinski.xml.h:2 ../hacks/config/sierpinski3d.xml.h:2
+#: ../hacks/config/skytentacles.xml.h:11 ../hacks/config/slidescreen.xml.h:2
+#: ../hacks/config/slip.xml.h:2 ../hacks/config/sonar.xml.h:2
+#: ../hacks/config/speedmine.xml.h:2 ../hacks/config/sphere.xml.h:2
+#: ../hacks/config/spheremonics.xml.h:2 ../hacks/config/spiral.xml.h:2
+#: ../hacks/config/splitflap.xml.h:2 ../hacks/config/splodesic.xml.h:2
+#: ../hacks/config/spotlight.xml.h:2 ../hacks/config/sproingies.xml.h:2
+#: ../hacks/config/squiral.xml.h:2 ../hacks/config/stairs.xml.h:2
+#: ../hacks/config/starfish.xml.h:5 ../hacks/config/stonerview.xml.h:2
+#: ../hacks/config/strange.xml.h:2 ../hacks/config/substrate.xml.h:2
+#: ../hacks/config/superquadrics.xml.h:2 ../hacks/config/surfaces.xml.h:2
+#: ../hacks/config/swirl.xml.h:2 ../hacks/config/t3d.xml.h:2
+#: ../hacks/config/tangram.xml.h:2 ../hacks/config/tessellimage.xml.h:2
+#: ../hacks/config/thornbird.xml.h:2 ../hacks/config/topblock.xml.h:2
+#: ../hacks/config/triangle.xml.h:2 ../hacks/config/tronbit.xml.h:2
+#: ../hacks/config/truchet.xml.h:2 ../hacks/config/twang.xml.h:2
+#: ../hacks/config/unicrud.xml.h:2 ../hacks/config/unknownpleasures.xml.h:2
+#: ../hacks/config/vigilance.xml.h:2 ../hacks/config/vines.xml.h:2
+#: ../hacks/config/wander.xml.h:2 ../hacks/config/whirlygig.xml.h:4
+#: ../hacks/config/winduprobot.xml.h:2 ../hacks/config/worm.xml.h:2
+#: ../hacks/config/wormhole.xml.h:2 ../hacks/config/xanalogtv.xml.h:3
+#: ../hacks/config/xflame.xml.h:2 ../hacks/config/xlyap.xml.h:2
+#: ../hacks/config/xmatrix.xml.h:15 ../hacks/config/xrayswarm.xml.h:2
+#: ../hacks/config/xspirograph.xml.h:2 ../hacks/config/zoom.xml.h:2
+msgid "Low"
+msgstr "Низкая"
+
+#. #### -colorcount [64]
+#: ../hacks/config/anemotaxis.xml.h:3 ../hacks/config/ant.xml.h:3
+#: ../hacks/config/antinspect.xml.h:3 ../hacks/config/antmaze.xml.h:3
+#: ../hacks/config/antspotlight.xml.h:3 ../hacks/config/atlantis.xml.h:3
+#: ../hacks/config/atunnel.xml.h:3 ../hacks/config/barcode.xml.h:3
+#: ../hacks/config/blaster.xml.h:3 ../hacks/config/blinkbox.xml.h:3
+#: ../hacks/config/blocktube.xml.h:3 ../hacks/config/bouboule.xml.h:3
+#: ../hacks/config/bouncingcow.xml.h:3 ../hacks/config/boxed.xml.h:3
+#: ../hacks/config/boxfit.xml.h:3 ../hacks/config/braid.xml.h:3
+#: ../hacks/config/bubble3d.xml.h:3 ../hacks/config/bubbles.xml.h:3
+#: ../hacks/config/bumps.xml.h:5 ../hacks/config/cage.xml.h:3
+#: ../hacks/config/carousel.xml.h:3 ../hacks/config/celtic.xml.h:3
+#: ../hacks/config/circuit.xml.h:3 ../hacks/config/cityflow.xml.h:3
+#: ../hacks/config/cloudlife.xml.h:3 ../hacks/config/companioncube.xml.h:3
+#: ../hacks/config/compass.xml.h:3 ../hacks/config/coral.xml.h:3
+#: ../hacks/config/crackberg.xml.h:3 ../hacks/config/critical.xml.h:3
+#: ../hacks/config/crystal.xml.h:3 ../hacks/config/cube21.xml.h:3
+#: ../hacks/config/cubenetic.xml.h:3 ../hacks/config/cubestack.xml.h:3
+#: ../hacks/config/cubestorm.xml.h:3 ../hacks/config/cubetwist.xml.h:3
+#: ../hacks/config/cubicgrid.xml.h:3 ../hacks/config/cwaves.xml.h:3
+#: ../hacks/config/cynosure.xml.h:3 ../hacks/config/dangerball.xml.h:3
+#: ../hacks/config/decayscreen.xml.h:3 ../hacks/config/deluxe.xml.h:3
+#: ../hacks/config/demon.xml.h:3 ../hacks/config/discoball.xml.h:3
+#: ../hacks/config/discrete.xml.h:3 ../hacks/config/distort.xml.h:3
+#: ../hacks/config/drift.xml.h:3 ../hacks/config/dymaxionmap.xml.h:3
+#: ../hacks/config/endgame.xml.h:3 ../hacks/config/engine.xml.h:3
+#: ../hacks/config/epicycle.xml.h:3 ../hacks/config/eruption.xml.h:3
+#: ../hacks/config/euler2d.xml.h:3 ../hacks/config/extrusion.xml.h:3
+#: ../hacks/config/fadeplot.xml.h:3 ../hacks/config/fiberlamp.xml.h:3
+#: ../hacks/config/fireworkx.xml.h:3 ../hacks/config/flag.xml.h:4
+#: ../hacks/config/flame.xml.h:3 ../hacks/config/flipflop.xml.h:3
+#: ../hacks/config/flipscreen3d.xml.h:3 ../hacks/config/fliptext.xml.h:3
+#: ../hacks/config/flow.xml.h:3 ../hacks/config/fluidballs.xml.h:3
+#: ../hacks/config/flyingtoasters.xml.h:3 ../hacks/config/fontglide.xml.h:3
+#: ../hacks/config/forest.xml.h:3 ../hacks/config/fuzzyflakes.xml.h:3
+#: ../hacks/config/galaxy.xml.h:3 ../hacks/config/gears.xml.h:3
+#: ../hacks/config/geodesic.xml.h:12 ../hacks/config/geodesicgears.xml.h:3
+#: ../hacks/config/gflux.xml.h:3 ../hacks/config/glblur.xml.h:3
+#: ../hacks/config/glcells.xml.h:3 ../hacks/config/gleidescope.xml.h:3
+#: ../hacks/config/glforestfire.xml.h:3 ../hacks/config/glhanoi.xml.h:3
+#: ../hacks/config/glknots.xml.h:3 ../hacks/config/glmatrix.xml.h:3
+#: ../hacks/config/glplanet.xml.h:3 ../hacks/config/glschool.xml.h:3
+#: ../hacks/config/glslideshow.xml.h:3 ../hacks/config/glsnake.xml.h:3
+#: ../hacks/config/gltext.xml.h:3 ../hacks/config/goop.xml.h:3
+#: ../hacks/config/grav.xml.h:3 ../hacks/config/greynetic.xml.h:3
+#: ../hacks/config/halftone.xml.h:3 ../hacks/config/halo.xml.h:3
+#: ../hacks/config/helix.xml.h:3 ../hacks/config/hexadrop.xml.h:3
+#: ../hacks/config/hexstrut.xml.h:3 ../hacks/config/hilbert.xml.h:9
+#: ../hacks/config/hopalong.xml.h:3 ../hacks/config/hydrostat.xml.h:3
+#: ../hacks/config/hyperball.xml.h:3 ../hacks/config/hypercube.xml.h:3
+#: ../hacks/config/hypertorus.xml.h:3 ../hacks/config/hypnowheel.xml.h:3
+#: ../hacks/config/ifs.xml.h:3 ../hacks/config/imsmap.xml.h:3
+#: ../hacks/config/interaggregate.xml.h:3 ../hacks/config/interference.xml.h:3
+#: ../hacks/config/intermomentary.xml.h:3 ../hacks/config/jigglypuff.xml.h:12
+#: ../hacks/config/jigsaw.xml.h:3 ../hacks/config/juggle.xml.h:3
+#: ../hacks/config/juggler3d.xml.h:3 ../hacks/config/julia.xml.h:3
+#: ../hacks/config/kaleidescope.xml.h:3 ../hacks/config/kaleidocycle.xml.h:3
+#: ../hacks/config/klein.xml.h:43 ../hacks/config/kumppa.xml.h:3
+#: ../hacks/config/lament.xml.h:3 ../hacks/config/laser.xml.h:3
+#: ../hacks/config/lavalite.xml.h:3 ../hacks/config/lcdscrub.xml.h:3
+#: ../hacks/config/lightning.xml.h:3 ../hacks/config/lisa.xml.h:3
+#: ../hacks/config/lissie.xml.h:3 ../hacks/config/lmorph.xml.h:3
+#: ../hacks/config/lockward.xml.h:3 ../hacks/config/loop.xml.h:3
+#: ../hacks/config/maze.xml.h:3 ../hacks/config/memscroller.xml.h:3
+#: ../hacks/config/menger.xml.h:3 ../hacks/config/metaballs.xml.h:3
+#: ../hacks/config/mirrorblob.xml.h:3 ../hacks/config/mismunch.xml.h:3
+#: ../hacks/config/moebius.xml.h:3 ../hacks/config/moebiusgears.xml.h:3
+#: ../hacks/config/moire2.xml.h:3 ../hacks/config/molecule.xml.h:3
+#: ../hacks/config/morph3d.xml.h:3 ../hacks/config/mountain.xml.h:3
+#: ../hacks/config/munch.xml.h:3 ../hacks/config/nerverot.xml.h:3
+#: ../hacks/config/noof.xml.h:3 ../hacks/config/pacman.xml.h:3
+#: ../hacks/config/penrose.xml.h:3 ../hacks/config/petri.xml.h:3
+#: ../hacks/config/phosphor.xml.h:3 ../hacks/config/photopile.xml.h:16
+#: ../hacks/config/piecewise.xml.h:3 ../hacks/config/pinion.xml.h:3
+#: ../hacks/config/pipes.xml.h:3 ../hacks/config/polyhedra.xml.h:3
+#: ../hacks/config/polyominoes.xml.h:4 ../hacks/config/polytopes.xml.h:25
+#: ../hacks/config/popsquares.xml.h:3 ../hacks/config/projectiveplane.xml.h:36
+#: ../hacks/config/providence.xml.h:3 ../hacks/config/pulsar.xml.h:3
+#: ../hacks/config/pyro.xml.h:3 ../hacks/config/qix.xml.h:3
+#: ../hacks/config/quasicrystal.xml.h:3 ../hacks/config/queens.xml.h:3
+#: ../hacks/config/raverhoop.xml.h:3 ../hacks/config/rd-bomb.xml.h:3
+#: ../hacks/config/rdbomb.xml.h:3 ../hacks/config/ripples.xml.h:3
+#: ../hacks/config/rocks.xml.h:3 ../hacks/config/romanboy.xml.h:39
+#: ../hacks/config/rotor.xml.h:3 ../hacks/config/rotzoomer.xml.h:3
+#: ../hacks/config/rubik.xml.h:3 ../hacks/config/rubikblocks.xml.h:3
+#: ../hacks/config/sballs.xml.h:3 ../hacks/config/shadebobs.xml.h:3
+#: ../hacks/config/sierpinski.xml.h:3 ../hacks/config/sierpinski3d.xml.h:3
+#: ../hacks/config/skytentacles.xml.h:16 ../hacks/config/slidescreen.xml.h:3
+#: ../hacks/config/slip.xml.h:3 ../hacks/config/sonar.xml.h:3
+#: ../hacks/config/speedmine.xml.h:3 ../hacks/config/sphere.xml.h:3
+#: ../hacks/config/spheremonics.xml.h:3 ../hacks/config/spiral.xml.h:3
+#: ../hacks/config/splitflap.xml.h:3 ../hacks/config/splodesic.xml.h:3
+#: ../hacks/config/spotlight.xml.h:3 ../hacks/config/sproingies.xml.h:3
+#: ../hacks/config/squiral.xml.h:3 ../hacks/config/stairs.xml.h:3
+#: ../hacks/config/starfish.xml.h:6 ../hacks/config/stonerview.xml.h:3
+#: ../hacks/config/strange.xml.h:3 ../hacks/config/substrate.xml.h:3
+#: ../hacks/config/superquadrics.xml.h:3 ../hacks/config/surfaces.xml.h:3
+#: ../hacks/config/swirl.xml.h:3 ../hacks/config/t3d.xml.h:3
+#: ../hacks/config/tangram.xml.h:3 ../hacks/config/tessellimage.xml.h:3
+#: ../hacks/config/thornbird.xml.h:3 ../hacks/config/topblock.xml.h:3
+#: ../hacks/config/triangle.xml.h:3 ../hacks/config/tronbit.xml.h:3
+#: ../hacks/config/truchet.xml.h:3 ../hacks/config/twang.xml.h:3
+#: ../hacks/config/unicrud.xml.h:3 ../hacks/config/unknownpleasures.xml.h:3
+#: ../hacks/config/vigilance.xml.h:3 ../hacks/config/vines.xml.h:3
+#: ../hacks/config/voronoi.xml.h:3 ../hacks/config/wander.xml.h:3
+#: ../hacks/config/winduprobot.xml.h:3 ../hacks/config/worm.xml.h:3
+#: ../hacks/config/wormhole.xml.h:3 ../hacks/config/xflame.xml.h:3
+#: ../hacks/config/xlyap.xml.h:3 ../hacks/config/xmatrix.xml.h:16
+#: ../hacks/config/xrayswarm.xml.h:3 ../hacks/config/xspirograph.xml.h:3
+#: ../hacks/config/zoom.xml.h:3
+msgid "Frame rate"
+msgstr "Частота кадров"
+
+#. #### -colorcount [64]
+#: ../hacks/config/anemotaxis.xml.h:4 ../hacks/config/ant.xml.h:4
+#: ../hacks/config/antinspect.xml.h:4 ../hacks/config/antmaze.xml.h:4
+#: ../hacks/config/antspotlight.xml.h:4 ../hacks/config/apple2.xml.h:12
+#: ../hacks/config/atlantis.xml.h:4 ../hacks/config/attraction.xml.h:13
+#: ../hacks/config/atunnel.xml.h:4 ../hacks/config/barcode.xml.h:4
+#: ../hacks/config/binaryring.xml.h:4 ../hacks/config/blaster.xml.h:4
+#: ../hacks/config/blinkbox.xml.h:4 ../hacks/config/blocktube.xml.h:4
+#: ../hacks/config/bouboule.xml.h:4 ../hacks/config/bouncingcow.xml.h:4
+#: ../hacks/config/boxed.xml.h:4 ../hacks/config/boxfit.xml.h:4
+#: ../hacks/config/braid.xml.h:4 ../hacks/config/bubble3d.xml.h:4
+#: ../hacks/config/bubbles.xml.h:4 ../hacks/config/bumps.xml.h:7
+#: ../hacks/config/cage.xml.h:4 ../hacks/config/carousel.xml.h:4
+#: ../hacks/config/ccurve.xml.h:10 ../hacks/config/celtic.xml.h:4
+#: ../hacks/config/circuit.xml.h:4 ../hacks/config/cityflow.xml.h:4
+#: ../hacks/config/cloudlife.xml.h:4 ../hacks/config/companioncube.xml.h:4
+#: ../hacks/config/compass.xml.h:4 ../hacks/config/coral.xml.h:4
+#: ../hacks/config/crackberg.xml.h:4 ../hacks/config/critical.xml.h:4
+#: ../hacks/config/crystal.xml.h:4 ../hacks/config/cube21.xml.h:4
+#: ../hacks/config/cubenetic.xml.h:4 ../hacks/config/cubestack.xml.h:4
+#: ../hacks/config/cubestorm.xml.h:4 ../hacks/config/cubetwist.xml.h:4
+#: ../hacks/config/cubicgrid.xml.h:4 ../hacks/config/cwaves.xml.h:4
+#: ../hacks/config/cynosure.xml.h:4 ../hacks/config/dangerball.xml.h:4
+#: ../hacks/config/decayscreen.xml.h:4 ../hacks/config/deluxe.xml.h:4
+#: ../hacks/config/demon.xml.h:4 ../hacks/config/discoball.xml.h:4
+#: ../hacks/config/discrete.xml.h:4 ../hacks/config/distort.xml.h:4
+#: ../hacks/config/dnalogo.xml.h:4 ../hacks/config/drift.xml.h:4
+#: ../hacks/config/dymaxionmap.xml.h:4 ../hacks/config/endgame.xml.h:4
+#: ../hacks/config/engine.xml.h:4 ../hacks/config/epicycle.xml.h:4
+#: ../hacks/config/eruption.xml.h:4 ../hacks/config/euler2d.xml.h:4
+#: ../hacks/config/extrusion.xml.h:4 ../hacks/config/fadeplot.xml.h:4
+#: ../hacks/config/fiberlamp.xml.h:4 ../hacks/config/fireworkx.xml.h:4
+#: ../hacks/config/flag.xml.h:5 ../hacks/config/flame.xml.h:4
+#: ../hacks/config/flipflop.xml.h:4 ../hacks/config/flipscreen3d.xml.h:4
+#: ../hacks/config/fliptext.xml.h:4 ../hacks/config/flow.xml.h:4
+#: ../hacks/config/fluidballs.xml.h:4 ../hacks/config/flyingtoasters.xml.h:4
+#: ../hacks/config/fontglide.xml.h:4 ../hacks/config/forest.xml.h:4
+#: ../hacks/config/fuzzyflakes.xml.h:4 ../hacks/config/galaxy.xml.h:4
+#: ../hacks/config/gears.xml.h:4 ../hacks/config/geodesic.xml.h:13
+#: ../hacks/config/geodesicgears.xml.h:4 ../hacks/config/gflux.xml.h:4
+#: ../hacks/config/glblur.xml.h:4 ../hacks/config/glcells.xml.h:4
+#: ../hacks/config/gleidescope.xml.h:4 ../hacks/config/glforestfire.xml.h:4
+#: ../hacks/config/glhanoi.xml.h:4 ../hacks/config/glknots.xml.h:4
+#: ../hacks/config/glmatrix.xml.h:4 ../hacks/config/glplanet.xml.h:4
+#: ../hacks/config/glschool.xml.h:4 ../hacks/config/glslideshow.xml.h:4
+#: ../hacks/config/glsnake.xml.h:4 ../hacks/config/gltext.xml.h:4
+#: ../hacks/config/goop.xml.h:4 ../hacks/config/grav.xml.h:4
+#: ../hacks/config/greynetic.xml.h:4 ../hacks/config/halftone.xml.h:4
+#: ../hacks/config/halo.xml.h:4 ../hacks/config/helix.xml.h:4
+#: ../hacks/config/hexadrop.xml.h:4 ../hacks/config/hexstrut.xml.h:4
+#: ../hacks/config/hopalong.xml.h:4 ../hacks/config/hydrostat.xml.h:4
+#: ../hacks/config/hyperball.xml.h:4 ../hacks/config/hypercube.xml.h:4
+#: ../hacks/config/hypertorus.xml.h:4 ../hacks/config/hypnowheel.xml.h:16
+#: ../hacks/config/ifs.xml.h:4 ../hacks/config/imsmap.xml.h:4
+#: ../hacks/config/interaggregate.xml.h:4 ../hacks/config/interference.xml.h:4
+#: ../hacks/config/intermomentary.xml.h:4 ../hacks/config/jigglypuff.xml.h:13
+#: ../hacks/config/jigsaw.xml.h:4 ../hacks/config/juggle.xml.h:4
+#: ../hacks/config/juggler3d.xml.h:4 ../hacks/config/julia.xml.h:4
+#: ../hacks/config/kaleidescope.xml.h:4 ../hacks/config/kaleidocycle.xml.h:4
+#: ../hacks/config/klein.xml.h:44 ../hacks/config/kumppa.xml.h:4
+#: ../hacks/config/lament.xml.h:4 ../hacks/config/laser.xml.h:4
+#: ../hacks/config/lavalite.xml.h:4 ../hacks/config/lcdscrub.xml.h:4
+#: ../hacks/config/lightning.xml.h:4 ../hacks/config/lisa.xml.h:4
+#: ../hacks/config/lissie.xml.h:4 ../hacks/config/lmorph.xml.h:4
+#: ../hacks/config/lockward.xml.h:4 ../hacks/config/loop.xml.h:4
+#: ../hacks/config/m6502.xml.h:9 ../hacks/config/maze.xml.h:4
+#: ../hacks/config/memscroller.xml.h:4 ../hacks/config/menger.xml.h:4
+#: ../hacks/config/metaballs.xml.h:4 ../hacks/config/mirrorblob.xml.h:4
+#: ../hacks/config/mismunch.xml.h:4 ../hacks/config/moebius.xml.h:4
+#: ../hacks/config/moebiusgears.xml.h:4 ../hacks/config/moire2.xml.h:4
+#: ../hacks/config/molecule.xml.h:4 ../hacks/config/morph3d.xml.h:4
+#: ../hacks/config/mountain.xml.h:4 ../hacks/config/munch.xml.h:4
+#: ../hacks/config/nerverot.xml.h:4 ../hacks/config/noof.xml.h:4
+#: ../hacks/config/pacman.xml.h:4 ../hacks/config/penrose.xml.h:4
+#: ../hacks/config/petri.xml.h:4 ../hacks/config/phosphor.xml.h:4
+#: ../hacks/config/photopile.xml.h:17 ../hacks/config/piecewise.xml.h:4
+#: ../hacks/config/pinion.xml.h:4 ../hacks/config/pipes.xml.h:4
+#: ../hacks/config/polyhedra.xml.h:4 ../hacks/config/polyominoes.xml.h:5
+#: ../hacks/config/polytopes.xml.h:26 ../hacks/config/pong.xml.h:12
+#: ../hacks/config/popsquares.xml.h:4 ../hacks/config/projectiveplane.xml.h:37
+#: ../hacks/config/providence.xml.h:4 ../hacks/config/pulsar.xml.h:4
+#: ../hacks/config/pyro.xml.h:13 ../hacks/config/qix.xml.h:4
+#: ../hacks/config/quasicrystal.xml.h:4 ../hacks/config/queens.xml.h:4
+#: ../hacks/config/raverhoop.xml.h:4 ../hacks/config/ripples.xml.h:4
+#: ../hacks/config/rocks.xml.h:4 ../hacks/config/romanboy.xml.h:40
+#: ../hacks/config/rotor.xml.h:4 ../hacks/config/rotzoomer.xml.h:4
+#: ../hacks/config/rubik.xml.h:4 ../hacks/config/rubikblocks.xml.h:4
+#: ../hacks/config/sballs.xml.h:4 ../hacks/config/shadebobs.xml.h:4
+#: ../hacks/config/sierpinski.xml.h:4 ../hacks/config/sierpinski3d.xml.h:4
+#: ../hacks/config/skytentacles.xml.h:13 ../hacks/config/slidescreen.xml.h:4
+#: ../hacks/config/slip.xml.h:4 ../hacks/config/sonar.xml.h:4
+#: ../hacks/config/speedmine.xml.h:4 ../hacks/config/sphere.xml.h:4
+#: ../hacks/config/spheremonics.xml.h:4 ../hacks/config/spiral.xml.h:4
+#: ../hacks/config/splitflap.xml.h:4 ../hacks/config/splodesic.xml.h:4
+#: ../hacks/config/spotlight.xml.h:4 ../hacks/config/sproingies.xml.h:4
+#: ../hacks/config/squiral.xml.h:4 ../hacks/config/stairs.xml.h:4
+#: ../hacks/config/starfish.xml.h:7 ../hacks/config/starwars.xml.h:3
+#: ../hacks/config/stonerview.xml.h:4 ../hacks/config/strange.xml.h:4
+#: ../hacks/config/substrate.xml.h:4 ../hacks/config/superquadrics.xml.h:4
+#: ../hacks/config/surfaces.xml.h:4 ../hacks/config/swirl.xml.h:4
+#: ../hacks/config/t3d.xml.h:4 ../hacks/config/tangram.xml.h:4
+#: ../hacks/config/tessellimage.xml.h:4 ../hacks/config/thornbird.xml.h:4
+#: ../hacks/config/topblock.xml.h:4 ../hacks/config/triangle.xml.h:4
+#: ../hacks/config/tronbit.xml.h:4 ../hacks/config/truchet.xml.h:4
+#: ../hacks/config/twang.xml.h:4 ../hacks/config/unicrud.xml.h:4
+#: ../hacks/config/unknownpleasures.xml.h:4 ../hacks/config/vigilance.xml.h:4
+#: ../hacks/config/vines.xml.h:4 ../hacks/config/wander.xml.h:4
+#: ../hacks/config/whirlygig.xml.h:6 ../hacks/config/winduprobot.xml.h:4
+#: ../hacks/config/worm.xml.h:4 ../hacks/config/wormhole.xml.h:4
+#: ../hacks/config/xanalogtv.xml.h:5 ../hacks/config/xflame.xml.h:4
+#: ../hacks/config/xlyap.xml.h:4 ../hacks/config/xmatrix.xml.h:17
+#: ../hacks/config/xrayswarm.xml.h:4 ../hacks/config/xspirograph.xml.h:4
+#: ../hacks/config/zoom.xml.h:4
+msgid "High"
+msgstr "Высокая"
 
-#: hacks/config/attraction.xml.h:24
-msgid "Repulsion Threshold"
-msgstr ""
-
-#: hacks/config/attraction.xml.h:25 hacks/config/blocktube.xml.h:7
-#: hacks/config/braid.xml.h:10 hacks/config/celtic.xml.h:7
-#: hacks/config/crackberg.xml.h:17 hacks/config/cube21.xml.h:12
-#: hacks/config/cynosure.xml.h:8 hacks/config/drift.xml.h:11
-#: hacks/config/eruption.xml.h:18 hacks/config/euler2d.xml.h:12
-#: hacks/config/fiberlamp.xml.h:7 hacks/config/fireflies.xml.h:34
-#: hacks/config/flow.xml.h:9 hacks/config/galaxy.xml.h:9
-#: hacks/config/juggle.xml.h:7 hacks/config/klein.xml.h:5
-#: hacks/config/laser.xml.h:9 hacks/config/menger.xml.h:14
-#: hacks/config/metaballs.xml.h:12 hacks/config/mismunch.xml.h:8
-#: hacks/config/munch.xml.h:6 hacks/config/nerverot.xml.h:19
-#: hacks/config/petri.xml.h:22 hacks/config/polyominoes.xml.h:9
-#: hacks/config/rotor.xml.h:9 hacks/config/shadebobs.xml.h:8
-#: hacks/config/sierpinski3d.xml.h:5 hacks/config/spheremonics.xml.h:17
-#: hacks/config/substrate.xml.h:14 hacks/config/timetunnel.xml.h:8
-#: hacks/config/wander.xml.h:12 hacks/config/whirlwindwarp.xml.h:6
-msgid "Short"
-msgstr "Короткий"
+#: ../hacks/config/anemotaxis.xml.h:5 ../hacks/config/hyperball.xml.h:5
+#: ../hacks/config/hypercube.xml.h:5
+msgid "Near"
+msgstr "Близко"
 
-#: hacks/config/attraction.xml.h:29
-msgid "Splines"
-msgstr "СплайнÑ\8b"
+#: ../hacks/config/anemotaxis.xml.h:6
+msgid "Distance"
+msgstr "РаÑ\81Ñ\81Ñ\82оÑ\8fние"
 
-#: hacks/config/attraction.xml.h:30 hacks/config/fireflies.xml.h:42
-msgid "Tails"
-msgstr "Хвосты"
+#: ../hacks/config/anemotaxis.xml.h:7 ../hacks/config/cubicgrid.xml.h:10
+#: ../hacks/config/hyperball.xml.h:7 ../hacks/config/hypercube.xml.h:7
+msgid "Far"
+msgstr "Далеко"
 
-#: hacks/config/attraction.xml.h:31 hacks/config/euler2d.xml.h:16
-#: hacks/config/juggle.xml.h:10
-msgid "Trail Length"
-msgstr "Длинна следа"
+#: ../hacks/config/anemotaxis.xml.h:9
+msgid "Sources"
+msgstr "Источники"
 
-#: hacks/config/atunnel.xml.h:1
-msgid "Atunnel"
-msgstr ""
+#: ../hacks/config/anemotaxis.xml.h:11
+msgid "Searchers"
+msgstr "Искатели"
 
-#: hacks/config/atunnel.xml.h:2
+#: ../hacks/config/anemotaxis.xml.h:13
 msgid ""
-"Draws an animation of a textured tunnel in GL. Requires OpenGL, and a "
-"machine with fast hardware support for texture maps. Written by Eric "
-"Lassauge and Roman Podobedov."
+"Searches for a source of odor in a turbulent atmosphere. The searcher is "
+"able to sense the odor and determine local instantaneous wind direction. The "
+"goal is to find the source in the shortest mean time. https://en.wikipedia."
+"org/wiki/Anemotaxis Written by Eugene Balkovsky; 2004."
 msgstr ""
 
-#: hacks/config/atunnel.xml.h:4 hacks/config/distort.xml.h:9
-#: hacks/config/glforestfire.xml.h:10 hacks/config/lament.xml.h:4
-#: hacks/config/sballs.xml.h:6
-msgid "Normal"
+#: ../hacks/config/ant.xml.h:1
+msgid "Ant"
 msgstr ""
 
-#: hacks/config/atunnel.xml.h:8 hacks/config/cube21.xml.h:24
-#: hacks/config/glforestfire.xml.h:18 hacks/config/lament.xml.h:8
-#: hacks/config/sballs.xml.h:17
-msgid "Untextured"
-msgstr ""
+#. #### -slow
+#: ../hacks/config/ant.xml.h:5 ../hacks/config/attraction.xml.h:21
+#: ../hacks/config/blinkbox.xml.h:5 ../hacks/config/cityflow.xml.h:12
+#: ../hacks/config/cloudlife.xml.h:9 ../hacks/config/cube21.xml.h:5
+#: ../hacks/config/cubenetic.xml.h:20 ../hacks/config/demon.xml.h:8
+#: ../hacks/config/discoball.xml.h:8 ../hacks/config/discrete.xml.h:5
+#: ../hacks/config/distort.xml.h:9 ../hacks/config/fadeplot.xml.h:8
+#: ../hacks/config/flag.xml.h:6 ../hacks/config/flow.xml.h:8
+#: ../hacks/config/fluidballs.xml.h:8 ../hacks/config/fuzzyflakes.xml.h:25
+#: ../hacks/config/glcells.xml.h:11 ../hacks/config/gleidescope.xml.h:5
+#: ../hacks/config/halftone.xml.h:8 ../hacks/config/hexadrop.xml.h:8
+#: ../hacks/config/hexstrut.xml.h:8 ../hacks/config/hopalong.xml.h:5
+#: ../hacks/config/hydrostat.xml.h:11 ../hacks/config/interference.xml.h:8
+#: ../hacks/config/julia.xml.h:8 ../hacks/config/lisa.xml.h:10
+#: ../hacks/config/lissie.xml.h:5 ../hacks/config/loop.xml.h:5
+#: ../hacks/config/metaballs.xml.h:12 ../hacks/config/moire.xml.h:8
+#: ../hacks/config/penrose.xml.h:8 ../hacks/config/photopile.xml.h:2
+#: ../hacks/config/piecewise.xml.h:11 ../hacks/config/rd-bomb.xml.h:11
+#: ../hacks/config/rdbomb.xml.h:11 ../hacks/config/rorschach.xml.h:2
+#: ../hacks/config/rubikblocks.xml.h:5 ../hacks/config/sierpinski.xml.h:8
+#: ../hacks/config/slidescreen.xml.h:14 ../hacks/config/slip.xml.h:8
+#: ../hacks/config/spotlight.xml.h:8 ../hacks/config/topblock.xml.h:8
+#: ../hacks/config/twang.xml.h:14
+msgid "Small"
+msgstr "Маленький"
 
-#: hacks/config/atunnel.xml.h:9
-msgid "Use light"
-msgstr ""
+#: ../hacks/config/ant.xml.h:6 ../hacks/config/demon.xml.h:9
+#: ../hacks/config/discrete.xml.h:6 ../hacks/config/flag.xml.h:7
+#: ../hacks/config/flow.xml.h:9 ../hacks/config/lissie.xml.h:6
+#: ../hacks/config/loop.xml.h:6 ../hacks/config/sierpinski.xml.h:9
+#: ../hacks/config/slip.xml.h:9
+msgid "Timeout"
+msgstr "Тайм-аут"
+
+#. #### -slow
+#: ../hacks/config/ant.xml.h:7 ../hacks/config/attraction.xml.h:23
+#: ../hacks/config/blinkbox.xml.h:7 ../hacks/config/cityflow.xml.h:14
+#: ../hacks/config/cloudlife.xml.h:11 ../hacks/config/cube21.xml.h:7
+#: ../hacks/config/cubenetic.xml.h:22 ../hacks/config/demon.xml.h:10
+#: ../hacks/config/discoball.xml.h:10 ../hacks/config/discrete.xml.h:7
+#: ../hacks/config/distort.xml.h:13 ../hacks/config/fadeplot.xml.h:10
+#: ../hacks/config/flag.xml.h:8 ../hacks/config/flow.xml.h:10
+#: ../hacks/config/fluidballs.xml.h:10 ../hacks/config/fuzzyflakes.xml.h:27
+#: ../hacks/config/glcells.xml.h:27 ../hacks/config/gleidescope.xml.h:7
+#: ../hacks/config/halftone.xml.h:12 ../hacks/config/hexadrop.xml.h:10
+#: ../hacks/config/hexstrut.xml.h:10 ../hacks/config/hopalong.xml.h:7
+#: ../hacks/config/hydrostat.xml.h:13 ../hacks/config/interference.xml.h:10
+#: ../hacks/config/julia.xml.h:10 ../hacks/config/lisa.xml.h:12
+#: ../hacks/config/lissie.xml.h:7 ../hacks/config/loop.xml.h:7
+#: ../hacks/config/moire.xml.h:10 ../hacks/config/penrose.xml.h:10
+#: ../hacks/config/photopile.xml.h:4 ../hacks/config/piecewise.xml.h:13
+#: ../hacks/config/rd-bomb.xml.h:13 ../hacks/config/rdbomb.xml.h:13
+#: ../hacks/config/rorschach.xml.h:4 ../hacks/config/rubikblocks.xml.h:7
+#: ../hacks/config/sierpinski.xml.h:10 ../hacks/config/slidescreen.xml.h:16
+#: ../hacks/config/slip.xml.h:10 ../hacks/config/spotlight.xml.h:10
+#: ../hacks/config/topblock.xml.h:10 ../hacks/config/twang.xml.h:16
+msgid "Large"
+msgstr "Большой"
 
-#: hacks/config/barcode.xml.h:1
-#, fuzzy
-msgid "Barcode"
-msgstr "Обзор"
+#: ../hacks/config/ant.xml.h:8
+msgid "Sharp turns"
+msgstr ""
+
+#: ../hacks/config/ant.xml.h:9
+msgid "Truchet lines"
+msgstr ""
+
+#: ../hacks/config/ant.xml.h:10
+msgid "Draw eyes"
+msgstr ""
+
+#: ../hacks/config/ant.xml.h:11
+msgid "Three"
+msgstr ""
+
+#.
+#. On a 2.93 gHz iMac i7, I get these rates with -delay 0:
+#.
+#. detail 3:  invisible
+#. detail 4:  barely visible
+#. detail 5:  1000+ fps, looks like noise at -delay 0, ok at -delay 20000
+#. detail 8:  ~700+ fps
+#. detail 9:  ~400 fps
+#. detail 10: ~300 fps
+#. detail 11: ~100 fps
+#. detail 12:  ~50 fps
+#. detail 13:  ~17 fps
+#. detail 14:   ~8 fps
+#. detail 15:   ~2 fps
+#.
+#. With the default -delay, CPU load only starts causing the frame rate
+#. to drop below 30 fps detail 12 or higher.
+#.
+#. #### -color [random]
+#: ../hacks/config/ant.xml.h:12 ../hacks/config/apollonian.xml.h:11
+#: ../hacks/config/attraction.xml.h:18 ../hacks/config/bouboule.xml.h:9
+#: ../hacks/config/braid.xml.h:9 ../hacks/config/critical.xml.h:6
+#: ../hacks/config/crystal.xml.h:6 ../hacks/config/cynosure.xml.h:6
+#: ../hacks/config/deco.xml.h:6 ../hacks/config/deluxe.xml.h:12
+#: ../hacks/config/demon.xml.h:12 ../hacks/config/discrete.xml.h:9
+#: ../hacks/config/drift.xml.h:9 ../hacks/config/epicycle.xml.h:6
+#: ../hacks/config/eruption.xml.h:6 ../hacks/config/euler2d.xml.h:28
+#: ../hacks/config/fadeplot.xml.h:12 ../hacks/config/flag.xml.h:10
+#: ../hacks/config/flame.xml.h:13 ../hacks/config/flow.xml.h:12
+#: ../hacks/config/forest.xml.h:6 ../hacks/config/galaxy.xml.h:10
+#: ../hacks/config/grav.xml.h:9 ../hacks/config/halo.xml.h:9
+#: ../hacks/config/hopalong.xml.h:10 ../hacks/config/ifs.xml.h:45
+#: ../hacks/config/imsmap.xml.h:12 ../hacks/config/interference.xml.h:16
+#: ../hacks/config/julia.xml.h:12 ../hacks/config/laser.xml.h:10
+#: ../hacks/config/lightning.xml.h:6 ../hacks/config/lisa.xml.h:9
+#: ../hacks/config/lissie.xml.h:9 ../hacks/config/loop.xml.h:9
+#: ../hacks/config/metaballs.xml.h:9 ../hacks/config/moire.xml.h:6
+#: ../hacks/config/moire2.xml.h:6 ../hacks/config/mountain.xml.h:9
+#: ../hacks/config/penrose.xml.h:6 ../hacks/config/polyominoes.xml.h:10
+#: ../hacks/config/popsquares.xml.h:7 ../hacks/config/rd-bomb.xml.h:15
+#: ../hacks/config/rdbomb.xml.h:15 ../hacks/config/rocks.xml.h:15
+#: ../hacks/config/rotor.xml.h:9 ../hacks/config/shadebobs.xml.h:8
+#: ../hacks/config/sierpinski.xml.h:12 ../hacks/config/slip.xml.h:12
+#: ../hacks/config/sphere.xml.h:6 ../hacks/config/spiral.xml.h:10
+#: ../hacks/config/squiral.xml.h:14 ../hacks/config/starfish.xml.h:15
+#: ../hacks/config/strange.xml.h:21 ../hacks/config/swirl.xml.h:9
+#: ../hacks/config/triangle.xml.h:6 ../hacks/config/vines.xml.h:6
+#: ../hacks/config/worm.xml.h:6
+msgid "Number of colors"
+msgstr "Количество цветов"
 
-#: hacks/config/barcode.xml.h:2
-msgid "Barcode Clock (24 Hour)"
+#: ../hacks/config/ant.xml.h:14
+msgid "Ants count"
 msgstr ""
 
-#: hacks/config/barcode.xml.h:3
-msgid "Barcode Clock (AM/PM)"
+#: ../hacks/config/ant.xml.h:15
+msgid "Ant size"
 msgstr ""
 
-#: hacks/config/barcode.xml.h:5
-msgid "Scrolling Barcodes"
+#: ../hacks/config/ant.xml.h:16
+msgid "Random cell shape"
 msgstr ""
 
-#: hacks/config/barcode.xml.h:8
-msgid ""
-"This draws a random sequence of colorful barcodes scrolling across your "
-"screen. CONSUME! By Dan Bornstein."
+#: ../hacks/config/ant.xml.h:17
+msgid "Three sided cells"
 msgstr ""
 
-#: hacks/config/blaster.xml.h:1
-msgid "Blaster"
+#: ../hacks/config/ant.xml.h:18
+msgid "Four sided cells"
 msgstr ""
 
-#: hacks/config/blaster.xml.h:2
-msgid ""
-"Draws a simulation of flying space-combat robots (cleverly disguised as "
-"colored circles) doing battle in front of a moving star field. Written by "
-"Jonathan Lin."
+#: ../hacks/config/ant.xml.h:19
+msgid "Six sided cells"
 msgstr ""
 
-#: hacks/config/blaster.xml.h:5 hacks/config/penetrate.xml.h:4
-msgid "Lasers"
+#: ../hacks/config/ant.xml.h:20
+msgid "Nine sided cells"
 msgstr ""
 
-#: hacks/config/blaster.xml.h:7
-msgid "Robots"
+#: ../hacks/config/ant.xml.h:21
+msgid "Twelve sided cells"
 msgstr ""
 
-#: hacks/config/blaster.xml.h:10 hacks/config/glplanet.xml.h:11
-msgid "Stars"
+#: ../hacks/config/ant.xml.h:24
+#, no-c-format
+msgid ""
+"This screen saver was removed from the XScreenSaver distribution as of "
+"version 4.22. A cellular automaton that is really a two-dimensional Turing "
+"machine: as the heads (\"ants\") walk along the screen, they change pixel "
+"values in their path. Then, as they pass over changed pixels, their behavior "
+"is influenced. https://en.wikipedia.org/wiki/Langton%27s_ant https://en."
+"wikipedia.org/wiki/Turing_machine Written by David Bagley; 1997."
 msgstr ""
 
-#: hacks/config/blinkbox.xml.h:1
-msgid "BlinkBox"
+#: ../hacks/config/antinspect.xml.h:1
+msgid "AntInspect"
 msgstr ""
 
-#: hacks/config/blinkbox.xml.h:2
-#, fuzzy
-msgid "Box Size"
-msgstr "Размер"
+#: ../hacks/config/antinspect.xml.h:6
+msgid "Draw shadows"
+msgstr "Прорисовывать тени"
 
-#: hacks/config/blinkbox.xml.h:3
-msgid "Dissolve"
+#: ../hacks/config/antinspect.xml.h:7
+msgid "Ants move spheres around a circle. Written by Blair Tennessy; 2004."
 msgstr ""
 
-#: hacks/config/blinkbox.xml.h:4 hacks/config/phosphor.xml.h:3
-msgid "Fade"
+#: ../hacks/config/antmaze.xml.h:1
+msgid "AntMaze"
 msgstr ""
 
-#: hacks/config/blinkbox.xml.h:6
-#, fuzzy
-msgid "Motion Blur"
-msgstr "Скорость анимации"
-
-#: hacks/config/blinkbox.xml.h:7
-msgid ""
-"Shows a ball contained inside of a bounding box. Colored blocks blink in "
-"when the ball hits the edges. Written by Jeremy English."
+#: ../hacks/config/antmaze.xml.h:6
+msgid "Ants walk around a simple maze. Written by Blair Tennessy; 2005."
 msgstr ""
 
-#: hacks/config/blitspin.xml.h:1
-#, fuzzy
-msgid "90 deg Rotation Speed"
-msgstr "Скорость анимации"
-
-#: hacks/config/blitspin.xml.h:2
-msgid "Bitmap to rotate"
+#: ../hacks/config/antspotlight.xml.h:1
+msgid "AntSpotlight"
 msgstr ""
 
-#: hacks/config/blitspin.xml.h:3
-msgid "BlitSpin"
+#: ../hacks/config/antspotlight.xml.h:6
+msgid "An ant walks over an image. Written by Blair Tennessy; 2003."
 msgstr ""
 
-#: hacks/config/blitspin.xml.h:5
-msgid "Fuzzy Rotation Speed"
+#: ../hacks/config/apollonian.xml.h:1
+msgid "Apollonian"
 msgstr ""
 
-#: hacks/config/blitspin.xml.h:6
-msgid "Grab Screen"
-msgstr ""
+#: ../hacks/config/apollonian.xml.h:2 ../hacks/config/tangram.xml.h:13
+msgid "Draw labels"
+msgstr "Прорисовывать метки"
+
+#: ../hacks/config/apollonian.xml.h:3
+msgid "Include alternate geometries"
+msgstr "Включать альтернативную геометрию"
+
+#. don't know what -count does
+#: ../hacks/config/apollonian.xml.h:5 ../hacks/config/tessellimage.xml.h:11
+msgid "Shallow"
+msgstr "Низкая"
+
+#. don't know what -count does
+#: ../hacks/config/apollonian.xml.h:7 ../hacks/config/flipflop.xml.h:11
+#: ../hacks/config/geodesic.xml.h:18 ../hacks/config/splodesic.xml.h:8
+msgid "Depth"
+msgstr "Глубина"
+
+#. don't know what -count does
+#: ../hacks/config/apollonian.xml.h:9 ../hacks/config/tessellimage.xml.h:13
+msgid "Deep"
+msgstr "Высокая"
+
+#. #### -color [random]
+#: ../hacks/config/apollonian.xml.h:10 ../hacks/config/attraction.xml.h:17
+#: ../hacks/config/bouboule.xml.h:8 ../hacks/config/braid.xml.h:8
+#: ../hacks/config/critical.xml.h:5 ../hacks/config/crystal.xml.h:5
+#: ../hacks/config/cynosure.xml.h:5 ../hacks/config/deco.xml.h:5
+#: ../hacks/config/deluxe.xml.h:11 ../hacks/config/demon.xml.h:11
+#: ../hacks/config/discrete.xml.h:8 ../hacks/config/drift.xml.h:8
+#: ../hacks/config/epicycle.xml.h:5 ../hacks/config/euler2d.xml.h:27
+#: ../hacks/config/fadeplot.xml.h:11 ../hacks/config/flag.xml.h:9
+#: ../hacks/config/flame.xml.h:12 ../hacks/config/flow.xml.h:11
+#: ../hacks/config/forest.xml.h:5 ../hacks/config/galaxy.xml.h:9
+#: ../hacks/config/grav.xml.h:8 ../hacks/config/halo.xml.h:8
+#: ../hacks/config/hopalong.xml.h:9 ../hacks/config/imsmap.xml.h:11
+#: ../hacks/config/interference.xml.h:15 ../hacks/config/julia.xml.h:11
+#: ../hacks/config/laser.xml.h:9 ../hacks/config/lightning.xml.h:5
+#: ../hacks/config/lisa.xml.h:8 ../hacks/config/lissie.xml.h:8
+#: ../hacks/config/loop.xml.h:8 ../hacks/config/metaballs.xml.h:8
+#: ../hacks/config/moire.xml.h:5 ../hacks/config/moire2.xml.h:5
+#: ../hacks/config/mountain.xml.h:8 ../hacks/config/nerverot.xml.h:11
+#: ../hacks/config/penrose.xml.h:5 ../hacks/config/polyominoes.xml.h:9
+#: ../hacks/config/rd-bomb.xml.h:14 ../hacks/config/rdbomb.xml.h:14
+#: ../hacks/config/rocks.xml.h:14 ../hacks/config/rotor.xml.h:8
+#: ../hacks/config/shadebobs.xml.h:6 ../hacks/config/sierpinski.xml.h:11
+#: ../hacks/config/slip.xml.h:11 ../hacks/config/sphere.xml.h:5
+#: ../hacks/config/spiral.xml.h:9 ../hacks/config/squiral.xml.h:13
+#: ../hacks/config/starfish.xml.h:14 ../hacks/config/strange.xml.h:20
+#: ../hacks/config/swirl.xml.h:8 ../hacks/config/triangle.xml.h:5
+#: ../hacks/config/vines.xml.h:5 ../hacks/config/worm.xml.h:5
+msgid "Two"
+msgstr "Два"
 
-#: hacks/config/blitspin.xml.h:8
+#: ../hacks/config/apollonian.xml.h:18
+#, no-c-format
 msgid ""
-"The ``blitspin'' hack repeatedly rotates a bitmap by 90 degrees by using "
-"logical operations: the bitmap is divided into quadrants, and the quadrants "
-"are shifted clockwise. Then the same thing is done again with progressively "
-"smaller quadrants, except that all sub-quadrants of a given size are rotated "
-"in parallel. Written by Jamie Zawinski based on some cool SmallTalk code "
-"seen in in Byte Magazine in 1981. As you watch it, the image appears to "
-"dissolve into static and then reconstitute itself, but rotated. You can "
-"provide the image to use, as an XBM or XPM file, or tell it to grab a screen "
-"image and rotate that."
+"A fractal packing of circles with smaller circles, demonstrating Descartes's "
+"theorem. https://en.wikipedia.org/wiki/Apollonian_gasket https://en."
+"wikipedia.org/wiki/Descartes%27_theorem Written by Allan R. Wilks and David "
+"Bagley; 2002."
 msgstr ""
 
-#: hacks/config/blocktube.xml.h:1
-msgid "BlockTube"
+#: ../hacks/config/apple2.xml.h:1
+msgid "Apple2"
 msgstr ""
 
-#: hacks/config/blocktube.xml.h:2 hacks/config/timetunnel.xml.h:3
-msgid "Color Change Time"
-msgstr ""
+#: ../hacks/config/apple2.xml.h:2
+msgid "Choose display mode randomly"
+msgstr "Случайный выбор режима дисплея"
 
-#: hacks/config/blocktube.xml.h:3
-msgid "Color Hold Time"
-msgstr ""
+#: ../hacks/config/apple2.xml.h:3
+msgid "Display scrolling text"
+msgstr "Дисплей с прокруткой текста"
 
-#: hacks/config/blocktube.xml.h:6
-msgid "Reflective Blocks"
-msgstr ""
+#: ../hacks/config/apple2.xml.h:4
+msgid "Display images"
+msgstr "Изображения экрана"
 
-#: hacks/config/blocktube.xml.h:10
-msgid "Solid Blocks"
-msgstr ""
+#: ../hacks/config/apple2.xml.h:5
+msgid "Run basic programs"
+msgstr "Запуск базовых программ"
 
-#: hacks/config/blocktube.xml.h:12
-msgid ""
-"This hack draws a swirling, falling tunnel of reflective slabs. They fade "
-"from hue to hue. Written by Lars R. Damerow."
-msgstr ""
+#: ../hacks/config/apple2.xml.h:6 ../hacks/config/blitspin.xml.h:6
+#: ../hacks/config/bumps.xml.h:8 ../hacks/config/decayscreen.xml.h:5
+#: ../hacks/config/distort.xml.h:5 ../hacks/config/flame.xml.h:7
+#: ../hacks/config/gleidescope.xml.h:8 ../hacks/config/glslideshow.xml.h:5
+#: ../hacks/config/maze.xml.h:15 ../hacks/config/ripples.xml.h:5
+#: ../hacks/config/rotzoomer.xml.h:5 ../hacks/config/slidescreen.xml.h:8
+#: ../hacks/config/spotlight.xml.h:5 ../hacks/config/tessellimage.xml.h:8
+#: ../hacks/config/twang.xml.h:5 ../hacks/config/zoom.xml.h:5
+msgid "10 seconds"
+msgstr "10 секунд"
 
-#: hacks/config/boing.xml.h:1
-#, fuzzy
-msgid "Boing"
-msgstr "Длинный"
+#.
+#. <number id="eulerpower" type="slider" arg="-eulerpower %"
+#. _label="Power" _low-label="Low" _high-label="High"
+#. low="0.5" high="3.0" default="1.0"/>
+#.
+#: ../hacks/config/apple2.xml.h:7 ../hacks/config/blitspin.xml.h:7
+#: ../hacks/config/braid.xml.h:6 ../hacks/config/bsod.xml.h:3
+#: ../hacks/config/bumps.xml.h:9 ../hacks/config/cynosure.xml.h:9
+#: ../hacks/config/decayscreen.xml.h:6 ../hacks/config/deco.xml.h:3
+#: ../hacks/config/distort.xml.h:6 ../hacks/config/drift.xml.h:6
+#: ../hacks/config/eruption.xml.h:20 ../hacks/config/euler2d.xml.h:26
+#: ../hacks/config/galaxy.xml.h:7 ../hacks/config/geodesicgears.xml.h:6
+#: ../hacks/config/glsnake.xml.h:6 ../hacks/config/hopalong.xml.h:6
+#: ../hacks/config/laser.xml.h:7 ../hacks/config/menger.xml.h:6
+#: ../hacks/config/metaballs.xml.h:6 ../hacks/config/mismunch.xml.h:6
+#: ../hacks/config/moire.xml.h:3 ../hacks/config/molecule.xml.h:6
+#: ../hacks/config/munch.xml.h:6 ../hacks/config/nerverot.xml.h:6
+#: ../hacks/config/pedal.xml.h:3 ../hacks/config/polyhedra.xml.h:9
+#: ../hacks/config/polyominoes.xml.h:7 ../hacks/config/ripples.xml.h:6
+#: ../hacks/config/rotzoomer.xml.h:6 ../hacks/config/shadebobs.xml.h:14
+#: ../hacks/config/sierpinski3d.xml.h:6 ../hacks/config/slidescreen.xml.h:9
+#: ../hacks/config/spheremonics.xml.h:6 ../hacks/config/spotlight.xml.h:6
+#: ../hacks/config/starfish.xml.h:9 ../hacks/config/substrate.xml.h:6
+#: ../hacks/config/superquadrics.xml.h:10 ../hacks/config/surfaces.xml.h:6
+#: ../hacks/config/tessellimage.xml.h:9 ../hacks/config/twang.xml.h:6
+#: ../hacks/config/vermiculate.xml.h:3 ../hacks/config/vidwhacker.xml.h:3
+#: ../hacks/config/wander.xml.h:7 ../hacks/config/zoom.xml.h:6
+msgid "Duration"
+msgstr "Продолжительность"
 
-#: hacks/config/boing.xml.h:3 hacks/config/boxed.xml.h:8
-#: hacks/config/fireflies.xml.h:17 hacks/config/pinion.xml.h:7
-msgid "Huge"
+#: ../hacks/config/apple2.xml.h:8 ../hacks/config/blitspin.xml.h:8
+#: ../hacks/config/bumps.xml.h:10 ../hacks/config/decayscreen.xml.h:7
+#: ../hacks/config/distort.xml.h:7 ../hacks/config/ripples.xml.h:7
+#: ../hacks/config/rotzoomer.xml.h:7 ../hacks/config/slidescreen.xml.h:10
+#: ../hacks/config/spotlight.xml.h:7 ../hacks/config/tessellimage.xml.h:10
+#: ../hacks/config/twang.xml.h:7 ../hacks/config/zoom.xml.h:7
+msgid "10 minutes"
+msgstr "10 минут"
+
+#: ../hacks/config/apple2.xml.h:11 ../hacks/config/m6502.xml.h:8
+#: ../hacks/config/xanalogtv.xml.h:4
+msgid "Color Knob"
+msgstr "Цвет пикселя"
+
+#: ../hacks/config/apple2.xml.h:13 ../hacks/config/m6502.xml.h:10
+#: ../hacks/config/xanalogtv.xml.h:6
+msgid "Tint Knob"
+msgstr "Оттенок пикселя"
+
+#: ../hacks/config/apple2.xml.h:14 ../hacks/config/m6502.xml.h:11
+#: ../hacks/config/pong.xml.h:11 ../hacks/config/xanalogtv.xml.h:7
+msgid "Brightness Knob"
+msgstr "Яркость пикселя"
+
+#: ../hacks/config/apple2.xml.h:15 ../hacks/config/m6502.xml.h:12
+#: ../hacks/config/pong.xml.h:13 ../hacks/config/xanalogtv.xml.h:8
+msgid "Contrast Knob"
+msgstr "Контраст пикселя"
+
+#: ../hacks/config/apple2.xml.h:16
+msgid ""
+"An Apple ][+ computer simulation, in all its 1979 glory. It also reproduces "
+"the appearance of display on a color television set of the period. In "
+"\"Basic Programming Mode\", a simulated user types in a BASIC program and "
+"runs it. In \"Text Mode\", it displays the output of a program, or the "
+"contents of a file or URL. In \"Slideshow Mode\", it chooses random images "
+"and displays them within the limitations of the Apple ][ display hardware. "
+"(Six available colors in hi-res mode!) On MacOS and Linux, this program is "
+"also a fully-functional VT100 emulator! Run it as an application instead of "
+"as a screen saver and you can use it as a terminal. https://en.wikipedia.org/"
+"wiki/Apple_II_series Written by Trevor Blackwell and Jamie Zawinski; 2003."
+msgstr ""
+
+#: ../hacks/config/atlantis.xml.h:1
+msgid "Atlantis"
 msgstr ""
 
-#: hacks/config/boing.xml.h:4 hacks/config/crackberg.xml.h:12
-msgid "Lighting"
-msgstr ""
+#: ../hacks/config/atlantis.xml.h:6
+msgid "Whale speed"
+msgstr "Скорость кита"
 
-#: hacks/config/boing.xml.h:5
-msgid "Meridians"
-msgstr ""
+#: ../hacks/config/atlantis.xml.h:8
+msgid "Shy"
+msgstr "Пугливо"
 
-#: hacks/config/boing.xml.h:6
-msgid "Parallels"
-msgstr ""
+#: ../hacks/config/atlantis.xml.h:9
+msgid "Shark proximity"
+msgstr "Поведение акулы"
 
-#: hacks/config/boing.xml.h:7
-#, fuzzy
-msgid "Scanlines"
-msgstr "Сплайны"
+#: ../hacks/config/atlantis.xml.h:10
+msgid "Agressive"
+msgstr "Агрессивно"
 
-#: hacks/config/boing.xml.h:9 hacks/config/galaxy.xml.h:10
-#: hacks/config/lisa.xml.h:7 hacks/config/lissie.xml.h:8
-#: hacks/config/loop.xml.h:6 hacks/config/penrose.xml.h:7
-#: hacks/config/pong.xml.h:3 hacks/config/rotor.xml.h:10
-#: hacks/config/rubik.xml.h:8 hacks/config/sproingies.xml.h:5
-#: hacks/config/wander.xml.h:13 hacks/config/worm.xml.h:6
-msgid "Size"
-msgstr "РазмеÑ\80"
+#: ../hacks/config/atlantis.xml.h:11 ../hacks/config/boxed.xml.h:20
+#: ../hacks/config/flyingtoasters.xml.h:8 ../hacks/config/glschool.xml.h:8
+#: ../hacks/config/glslideshow.xml.h:16 ../hacks/config/jigglypuff.xml.h:18
+#: ../hacks/config/juggle.xml.h:11 ../hacks/config/juggler3d.xml.h:11
+#: ../hacks/config/mirrorblob.xml.h:11 ../hacks/config/pipes.xml.h:11
+#: ../hacks/config/webcollage.xml.h:2
+msgid "None"
+msgstr "Ð\9eÑ\82Ñ\81Ñ\83Ñ\82Ñ\81Ñ\82вÑ\83еÑ\82"
 
-#: hacks/config/boing.xml.h:11
-msgid "Smoothing"
-msgstr ""
+#: ../hacks/config/atlantis.xml.h:12
+msgid "Number of sharks"
+msgstr "Количество акул"
 
-#: hacks/config/boing.xml.h:13
-msgid ""
-"This bouncing ball is a clone of the first graphics demo for the Amiga 1000, "
-"which was written by Dale Luck and RJ Mical during a break at the 1984 "
-"Consumer Electronics Show (or so the legend goes.) This looks like the "
-"original Amiga demo if you turn off \"smoothing\" and \"lighting\" and turn "
-"on \"scanlines\". Written by Jamie Zawinski."
+#: ../hacks/config/atlantis.xml.h:13 ../hacks/config/companioncube.xml.h:10
+#: ../hacks/config/deluxe.xml.h:10 ../hacks/config/demon.xml.h:7
+#: ../hacks/config/gears.xml.h:10 ../hacks/config/glhanoi.xml.h:11
+#: ../hacks/config/lisa.xml.h:15 ../hacks/config/lissie.xml.h:13
+#: ../hacks/config/skytentacles.xml.h:4
+msgid "20"
 msgstr ""
 
-#: hacks/config/boing.xml.h:14 hacks/config/boxed.xml.h:16
-#: hacks/config/fireflies.xml.h:43 hacks/config/pinion.xml.h:14
-msgid "Tiny"
-msgstr ""
+#: ../hacks/config/atlantis.xml.h:14
+msgid "Shimmering water"
+msgstr "Мерцающая вода"
 
-#: hacks/config/bouboule.xml.h:1
-msgid "Bouboule"
-msgstr ""
+#: ../hacks/config/atlantis.xml.h:15
+msgid "Clear water"
+msgstr "Чистая вода"
 
-#: hacks/config/bouboule.xml.h:2 hacks/config/rocks.xml.h:3
-msgid "Do Red/Blue 3D separation"
-msgstr ""
+#: ../hacks/config/atlantis.xml.h:16
+msgid "Flat background"
+msgstr "Плоский фон"
 
-#: hacks/config/bouboule.xml.h:7
-msgid "Number of Spots"
-msgstr ""
+#: ../hacks/config/atlantis.xml.h:17
+msgid "Gradient background"
+msgstr "Градиентный фон"
 
-#: hacks/config/bouboule.xml.h:10
-msgid ""
-"This draws what looks like a spinning, deforming balloon with varying-sized "
-"spots painted on its invisible surface. Written by Jeremie Petit."
+#. #### -mipmap
+#: ../hacks/config/atlantis.xml.h:18 ../hacks/config/atunnel.xml.h:7
+#: ../hacks/config/blinkbox.xml.h:11 ../hacks/config/blocktube.xml.h:10
+#: ../hacks/config/boing.xml.h:13 ../hacks/config/bouncingcow.xml.h:11
+#: ../hacks/config/boxed.xml.h:24 ../hacks/config/cage.xml.h:5
+#: ../hacks/config/cityflow.xml.h:16 ../hacks/config/companioncube.xml.h:13
+#: ../hacks/config/crackberg.xml.h:17 ../hacks/config/cube21.xml.h:25
+#: ../hacks/config/cubenetic.xml.h:25 ../hacks/config/cubestack.xml.h:15
+#: ../hacks/config/cubestorm.xml.h:16 ../hacks/config/cubetwist.xml.h:17
+#: ../hacks/config/dangerball.xml.h:13 ../hacks/config/discoball.xml.h:13
+#: ../hacks/config/dnalogo.xml.h:9 ../hacks/config/dymaxionmap.xml.h:13
+#: ../hacks/config/extrusion.xml.h:16 ../hacks/config/flipflop.xml.h:13
+#: ../hacks/config/flyingtoasters.xml.h:13 ../hacks/config/gears.xml.h:13
+#: ../hacks/config/geodesic.xml.h:6 ../hacks/config/geodesicgears.xml.h:10
+#: ../hacks/config/glcells.xml.h:33 ../hacks/config/glforestfire.xml.h:15
+#: ../hacks/config/glhanoi.xml.h:15 ../hacks/config/glknots.xml.h:23
+#: ../hacks/config/glmatrix.xml.h:19 ../hacks/config/glplanet.xml.h:12
+#: ../hacks/config/glschool.xml.h:13 ../hacks/config/glsnake.xml.h:17
+#: ../hacks/config/gltext.xml.h:18 ../hacks/config/hexstrut.xml.h:16
+#: ../hacks/config/hilbert.xml.h:21 ../hacks/config/hydrostat.xml.h:28
+#: ../hacks/config/hypertorus.xml.h:6 ../hacks/config/jigglypuff.xml.h:9
+#: ../hacks/config/kaleidocycle.xml.h:20 ../hacks/config/lament.xml.h:6
+#: ../hacks/config/lavalite.xml.h:15 ../hacks/config/menger.xml.h:19
+#: ../hacks/config/mirrorblob.xml.h:26 ../hacks/config/moebiusgears.xml.h:13
+#: ../hacks/config/molecule.xml.h:11 ../hacks/config/pinion.xml.h:15
+#: ../hacks/config/pipes.xml.h:21 ../hacks/config/polyhedra.xml.h:166
+#: ../hacks/config/providence.xml.h:6 ../hacks/config/queens.xml.h:5
+#: ../hacks/config/rubikblocks.xml.h:19 ../hacks/config/sballs.xml.h:15
+#: ../hacks/config/sierpinski3d.xml.h:9 ../hacks/config/speedmine.xml.h:16
+#: ../hacks/config/spheremonics.xml.h:21 ../hacks/config/splitflap.xml.h:24
+#: ../hacks/config/sproingies.xml.h:8 ../hacks/config/stonerview.xml.h:5
+#: ../hacks/config/superquadrics.xml.h:12 ../hacks/config/tangram.xml.h:14
+#: ../hacks/config/topblock.xml.h:23 ../hacks/config/tronbit.xml.h:10
+#: ../hacks/config/unknownpleasures.xml.h:13
+msgid "Wireframe"
+msgstr "Каркасное изображение"
+
+#: ../hacks/config/atlantis.xml.h:20
+msgid "Sharks, dolphins and whales. Written by Mark Kilgard; 1998."
 msgstr ""
 
-#: hacks/config/bouncingcow.xml.h:1
-msgid "A Cow. A Trampoline. Together, they fight crime. By Jamie Zawinski."
+#: ../hacks/config/attraction.xml.h:1
+msgid "Attraction"
 msgstr ""
 
-#: hacks/config/bouncingcow.xml.h:2 hacks/config/boxed.xml.h:1
-#: hacks/config/carousel.xml.h:3 hacks/config/ccurve.xml.h:3
-#: hacks/config/cubestorm.xml.h:1 hacks/config/flyingtoasters.xml.h:3
-#: hacks/config/fontglide.xml.h:1 hacks/config/gears.xml.h:1
-#: hacks/config/gflux.xml.h:1 hacks/config/glknots.xml.h:1
-#: hacks/config/glmatrix.xml.h:1 hacks/config/jigglypuff.xml.h:1
-#: hacks/config/pinion.xml.h:3 hacks/config/polyhedra.xml.h:3
-#: hacks/config/pyro.xml.h:1 hacks/config/rd-bomb.xml.h:6
-#: hacks/config/rocks.xml.h:1 hacks/config/starwars.xml.h:1
-#: hacks/config/wormhole.xml.h:1 hacks/config/xfishtank.xml.h:1
-msgid "Animation Speed"
-msgstr "Скорость анимации"
+#: ../hacks/config/attraction.xml.h:2 ../hacks/config/juggle.xml.h:13
+#: ../hacks/config/juggler3d.xml.h:13
+msgid "Balls"
+msgstr "Мячи"
 
-#: hacks/config/bouncingcow.xml.h:3
-msgid "Beefy Cow"
-msgstr ""
+#: ../hacks/config/attraction.xml.h:3 ../hacks/config/deluxe.xml.h:6
+#: ../hacks/config/lmorph.xml.h:12 ../hacks/config/pedal.xml.h:6
+#: ../hacks/config/starfish.xml.h:12 ../hacks/config/surfaces.xml.h:23
+#: ../hacks/config/whirlygig.xml.h:3
+msgid "Lines"
+msgstr "Линии"
 
-#: hacks/config/bouncingcow.xml.h:4
-#, fuzzy
-msgid "Bounce Speed"
-msgstr "Скорость решения"
+#: ../hacks/config/attraction.xml.h:4
+msgid "Tails"
+msgstr "Хвосты"
 
-#: hacks/config/bouncingcow.xml.h:5
-msgid "BouncingCow"
-msgstr ""
+#: ../hacks/config/attraction.xml.h:5
+msgid "Polygons"
+msgstr "Многоугольники"
 
-#: hacks/config/bouncingcow.xml.h:7
-msgid "Herd"
-msgstr ""
+#: ../hacks/config/attraction.xml.h:6
+msgid "Splines"
+msgstr "Сплайны"
 
-#: hacks/config/bouncingcow.xml.h:8
-#, fuzzy
-msgid "Moo"
-msgstr "Mono"
+#: ../hacks/config/attraction.xml.h:7
+msgid "Filled splines"
+msgstr "Заполненные сплайны"
 
-#: hacks/config/bouncingcow.xml.h:9
-#, fuzzy
-msgid "Number of Cows"
-msgstr "Количество цветов"
+#: ../hacks/config/attraction.xml.h:8
+msgid "Bounce off walls"
+msgstr "Отскакивать от стен"
 
-#: hacks/config/bouncingcow.xml.h:11
-#, fuzzy
-msgid "Wireframe Cow"
-msgstr "Каркасное изображение"
+#: ../hacks/config/attraction.xml.h:9
+msgid "Ignore screen edges"
+msgstr "Игнорировать границы экрана"
 
-#: hacks/config/boxed.xml.h:2 hacks/config/fluidballs.xml.h:2
-msgid "Ball Size"
-msgstr ""
+#: ../hacks/config/attraction.xml.h:10
+msgid "Ball count"
+msgstr "Количество мячей"
 
-#: hacks/config/boxed.xml.h:3
-msgid "Boxed"
-msgstr ""
+#: ../hacks/config/attraction.xml.h:12
+msgid "Environmental viscosity"
+msgstr "Вязкость окружения"
+
+#.
+#. <number id="eulerpower" type="slider" arg="-eulerpower %"
+#. _label="Power" _low-label="Low" _high-label="High"
+#. low="0.5" high="3.0" default="1.0"/>
+#.
+#: ../hacks/config/attraction.xml.h:14 ../hacks/config/binaryring.xml.h:5
+#: ../hacks/config/blocktube.xml.h:5 ../hacks/config/braid.xml.h:5
+#: ../hacks/config/celtic.xml.h:5 ../hacks/config/cube21.xml.h:21
+#: ../hacks/config/cynosure.xml.h:8 ../hacks/config/drift.xml.h:5
+#: ../hacks/config/eruption.xml.h:19 ../hacks/config/euler2d.xml.h:13
+#: ../hacks/config/fiberlamp.xml.h:8 ../hacks/config/flow.xml.h:13
+#: ../hacks/config/galaxy.xml.h:6 ../hacks/config/glcells.xml.h:5
+#: ../hacks/config/hydrostat.xml.h:19 ../hacks/config/juggle.xml.h:8
+#: ../hacks/config/juggler3d.xml.h:8 ../hacks/config/laser.xml.h:6
+#: ../hacks/config/menger.xml.h:5 ../hacks/config/metaballs.xml.h:5
+#: ../hacks/config/mismunch.xml.h:5 ../hacks/config/munch.xml.h:5
+#: ../hacks/config/nerverot.xml.h:5 ../hacks/config/petri.xml.h:22
+#: ../hacks/config/photopile.xml.h:18 ../hacks/config/pipes.xml.h:8
+#: ../hacks/config/polyominoes.xml.h:6 ../hacks/config/rotor.xml.h:5
+#: ../hacks/config/rubikblocks.xml.h:15 ../hacks/config/shadebobs.xml.h:13
+#: ../hacks/config/sierpinski3d.xml.h:5 ../hacks/config/skytentacles.xml.h:5
+#: ../hacks/config/slidescreen.xml.h:5 ../hacks/config/sonar.xml.h:24
+#: ../hacks/config/spheremonics.xml.h:5 ../hacks/config/substrate.xml.h:5
+#: ../hacks/config/superquadrics.xml.h:9 ../hacks/config/surfaces.xml.h:5
+#: ../hacks/config/vermiculate.xml.h:2 ../hacks/config/wander.xml.h:6
+#: ../hacks/config/whirlwindwarp.xml.h:5
+msgid "Short"
+msgstr "Короткая"
+
+#: ../hacks/config/attraction.xml.h:15 ../hacks/config/euler2d.xml.h:14
+#: ../hacks/config/juggle.xml.h:12 ../hacks/config/juggler3d.xml.h:12
+#: ../hacks/config/sonar.xml.h:25
+msgid "Trail length"
+msgstr "Длина следа"
+
+#.
+#. <number id="eulerpower" type="slider" arg="-eulerpower %"
+#. _label="Power" _low-label="Low" _high-label="High"
+#. low="0.5" high="3.0" default="1.0"/>
+#.
+#: ../hacks/config/attraction.xml.h:16 ../hacks/config/binaryring.xml.h:7
+#: ../hacks/config/blocktube.xml.h:7 ../hacks/config/braid.xml.h:7
+#: ../hacks/config/celtic.xml.h:7 ../hacks/config/cube21.xml.h:23
+#: ../hacks/config/cynosure.xml.h:10 ../hacks/config/drift.xml.h:7
+#: ../hacks/config/eruption.xml.h:21 ../hacks/config/euler2d.xml.h:20
+#: ../hacks/config/fiberlamp.xml.h:10 ../hacks/config/flow.xml.h:15
+#: ../hacks/config/fontglide.xml.h:10 ../hacks/config/galaxy.xml.h:8
+#: ../hacks/config/glcells.xml.h:7 ../hacks/config/hydrostat.xml.h:21
+#: ../hacks/config/juggle.xml.h:10 ../hacks/config/juggler3d.xml.h:10
+#: ../hacks/config/laser.xml.h:8 ../hacks/config/menger.xml.h:7
+#: ../hacks/config/metaballs.xml.h:7 ../hacks/config/mismunch.xml.h:7
+#: ../hacks/config/munch.xml.h:7 ../hacks/config/nerverot.xml.h:7
+#: ../hacks/config/petri.xml.h:24 ../hacks/config/photopile.xml.h:20
+#: ../hacks/config/pipes.xml.h:10 ../hacks/config/polyominoes.xml.h:8
+#: ../hacks/config/raverhoop.xml.h:17 ../hacks/config/rotor.xml.h:7
+#: ../hacks/config/rubikblocks.xml.h:17 ../hacks/config/shadebobs.xml.h:15
+#: ../hacks/config/sierpinski3d.xml.h:7 ../hacks/config/skytentacles.xml.h:7
+#: ../hacks/config/slidescreen.xml.h:7 ../hacks/config/sonar.xml.h:26
+#: ../hacks/config/spheremonics.xml.h:7 ../hacks/config/substrate.xml.h:7
+#: ../hacks/config/superquadrics.xml.h:11 ../hacks/config/surfaces.xml.h:7
+#: ../hacks/config/tangram.xml.h:7 ../hacks/config/vermiculate.xml.h:4
+#: ../hacks/config/wander.xml.h:8 ../hacks/config/whirlwindwarp.xml.h:7
+#: ../hacks/config/xlyap.xml.h:7
+msgid "Long"
+msgstr "Длинная"
 
-#: hacks/config/boxed.xml.h:4
-msgid ""
-"Draws a box full of 3D bouncing balls that explode. Written by Sander van "
-"Grieken."
-msgstr ""
+#: ../hacks/config/attraction.xml.h:20
+msgid "Ball mass"
+msgstr "Размер мяча"
 
-#: hacks/config/boxed.xml.h:5
-#, fuzzy
-msgid "Explosion Force"
-msgstr "Режимы экрана"
+#: ../hacks/config/attraction.xml.h:22
+msgid "Repulsion threshold"
+msgstr "Порог отскока"
 
-#: hacks/config/boxed.xml.h:9 hacks/config/pipes.xml.h:9
-#: hacks/config/substrate.xml.h:12 hacks/config/wormhole.xml.h:4
-msgid "Lots"
-msgstr ""
+#: ../hacks/config/attraction.xml.h:27
+msgid "Orbital mode"
+msgstr "Орбитальный режим"
 
-#: hacks/config/boxed.xml.h:10 hacks/config/cubestorm.xml.h:5
-#: hacks/config/fontglide.xml.h:9 hacks/config/glknots.xml.h:6
-#: hacks/config/polyhedra.xml.h:84
-#, fuzzy
-msgid "Motion Speed"
-msgstr "Скорость анимации"
+#: ../hacks/config/attraction.xml.h:28 ../hacks/config/fuzzyflakes.xml.h:26
+msgid "Radius"
+msgstr "Радиус"
 
-#: hacks/config/boxed.xml.h:11
-msgid "Nuke"
-msgstr ""
+#: ../hacks/config/attraction.xml.h:29
+msgid "Outward"
+msgstr "Наружу"
 
-#: hacks/config/boxed.xml.h:12
-#, fuzzy
-msgid "Number of Balls"
-msgstr "Количество цветов"
+#: ../hacks/config/attraction.xml.h:30
+msgid "Inward"
+msgstr "Внутрь"
 
-#: hacks/config/boxed.xml.h:13 hacks/config/hopalong.xml.h:18
-msgid "Popcorn"
+#: ../hacks/config/attraction.xml.h:33
+msgid ""
+"Points attract each other up to a certain distance, and then begin to repel "
+"each other. The attraction/repulsion is proportional to the distance between "
+"any two particles, similar to the strong and weak nuclear forces. Written by "
+"Jamie Zawinski and John Pezaris; 1992."
 msgstr ""
 
-#: hacks/config/boxfit.xml.h:1 hacks/config/popsquares.xml.h:1
-msgid "Border"
+#: ../hacks/config/atunnel.xml.h:1
+msgid "Atunnel"
 msgstr ""
 
-#: hacks/config/boxfit.xml.h:2
-msgid "BoxFit"
-msgstr ""
+#: ../hacks/config/atunnel.xml.h:5 ../hacks/config/blocktube.xml.h:9
+#: ../hacks/config/cubenetic.xml.h:24 ../hacks/config/glmatrix.xml.h:18
+#: ../hacks/config/lament.xml.h:5 ../hacks/config/sballs.xml.h:14
+msgid "Textured"
+msgstr "Текстуры"
 
-#: hacks/config/boxfit.xml.h:3 hacks/config/cubenetic.xml.h:1
-msgid "Boxes"
-msgstr ""
+#: ../hacks/config/atunnel.xml.h:6 ../hacks/config/boing.xml.h:11
+#: ../hacks/config/crackberg.xml.h:12
+msgid "Lighting"
+msgstr "Освещение"
 
-#: hacks/config/boxfit.xml.h:4
-msgid "Boxes Only"
+#: ../hacks/config/atunnel.xml.h:9
+msgid ""
+"Zooming through a textured tunnel. Written by Eric Lassauge and Roman "
+"Podobedov; 2003."
 msgstr ""
 
-#: hacks/config/boxfit.xml.h:5
-msgid "Boxes or Circles"
+#: ../hacks/config/barcode.xml.h:1
+msgid "Barcode"
 msgstr ""
 
-#: hacks/config/boxfit.xml.h:6
-msgid "Circles Only"
-msgstr ""
+#: ../hacks/config/barcode.xml.h:5
+msgid "Scrolling barcodes"
+msgstr "Движущиеся штрих-коды"
 
-#: hacks/config/boxfit.xml.h:7
-msgid "Color Gradient"
-msgstr ""
+#: ../hacks/config/barcode.xml.h:6
+msgid "Barcode grid"
+msgstr "Сетка штрих-кодов"
 
-#: hacks/config/boxfit.xml.h:9
-#, fuzzy
-msgid "Grab Images"
-msgstr "Захватывать изображения с рабочего стола"
+#: ../hacks/config/barcode.xml.h:7
+msgid "Barcode clock (AM/PM)"
+msgstr "Часы в виде штрих-кода (AM/PM)"
 
-#: hacks/config/boxfit.xml.h:10
-msgid "Grow By"
-msgstr ""
+#: ../hacks/config/barcode.xml.h:8
+msgid "Barcode clock (24 hour)"
+msgstr "Часы в виде штрих-кода (24 часа)"
 
-#: hacks/config/boxfit.xml.h:11
+#: ../hacks/config/barcode.xml.h:10
 msgid ""
-"Packs the screen with growing squares or circles, colored according to a "
-"horizontal or vertical gradient, or according to the colors of the desktop "
-"or a loaded image file. The objects grow until they touch, then stop. When "
-"the screen is full, they shrink away and the process restarts. Written by "
-"Jamie Zawinski."
+"Colorful scrolling barcodes. CONSUME! The barcodes follow the UPC-A, UPC-E, "
+"EAN-8 or EAN-13 standards. https://en.wikipedia.org/wiki/"
+"Universal_Product_Code https://en.wikipedia.org/wiki/European_Article_Number "
+"Written by Dan Bornstein and Jamie Zawinski; 2003."
 msgstr ""
 
-#: hacks/config/boxfit.xml.h:13 hacks/config/xearth.xml.h:23
-msgid "Spacing"
+#: ../hacks/config/binaryring.xml.h:1
+msgid "BinaryRing"
 msgstr ""
 
-#: hacks/config/braid.xml.h:1
-msgid "Braid"
-msgstr ""
+#: ../hacks/config/binaryring.xml.h:3
+msgid "Growth delay"
+msgstr "Задержка роста"
 
-#: hacks/config/braid.xml.h:2
-msgid ""
-"Draws random color-cycling inter-braided concentric circles. Written by John "
-"Neil."
-msgstr ""
-
-#: hacks/config/braid.xml.h:3 hacks/config/bsod.xml.h:9
-#: hacks/config/coral.xml.h:6 hacks/config/cynosure.xml.h:3
-#: hacks/config/deco.xml.h:4 hacks/config/drift.xml.h:2
-#: hacks/config/epicycle.xml.h:3 hacks/config/eruption.xml.h:3
-#: hacks/config/euler2d.xml.h:1 hacks/config/flame.xml.h:5
-#: hacks/config/galaxy.xml.h:2 hacks/config/glsnake.xml.h:5
-#: hacks/config/helix.xml.h:3 hacks/config/hopalong.xml.h:2
-#: hacks/config/imsmap.xml.h:6 hacks/config/klein.xml.h:1
-#: hacks/config/laser.xml.h:2 hacks/config/menger.xml.h:2
-#: hacks/config/metaballs.xml.h:3 hacks/config/mismunch.xml.h:1
-#: hacks/config/moire.xml.h:3 hacks/config/molecule.xml.h:10
-#: hacks/config/munch.xml.h:2 hacks/config/nerverot.xml.h:8
-#: hacks/config/pedal.xml.h:3 hacks/config/polyhedra.xml.h:16
-#: hacks/config/polyominoes.xml.h:1 hacks/config/rorschach.xml.h:3
-#: hacks/config/rotzoomer.xml.h:5 hacks/config/shadebobs.xml.h:2
-#: hacks/config/sierpinski3d.xml.h:1 hacks/config/spheremonics.xml.h:4
-#: hacks/config/starfish.xml.h:2 hacks/config/substrate.xml.h:6
-#: hacks/config/vidwhacker.xml.h:3 hacks/config/wander.xml.h:7
-#: hacks/config/xspirograph.xml.h:3
-msgid "Duration"
-msgstr "Продолжительность"
+#: ../hacks/config/binaryring.xml.h:6
+msgid "Ring Radius"
+msgstr "Радиус кольца"
 
-#: hacks/config/braid.xml.h:5 hacks/config/epicycle.xml.h:7
-#: hacks/config/nerverot.xml.h:12
-msgid "Line Thickness"
+#: ../hacks/config/binaryring.xml.h:9 ../hacks/config/eruption.xml.h:9
+msgid "Number of particles"
+msgstr "Количество частиц"
+
+#: ../hacks/config/binaryring.xml.h:10 ../hacks/config/boxed.xml.h:10
+#: ../hacks/config/circuit.xml.h:7 ../hacks/config/glschool.xml.h:7
+#: ../hacks/config/julia.xml.h:7 ../hacks/config/mountain.xml.h:7
+#: ../hacks/config/pipes.xml.h:13 ../hacks/config/sproingies.xml.h:6
+#: ../hacks/config/substrate.xml.h:10 ../hacks/config/vigilance.xml.h:10
+#: ../hacks/config/winduprobot.xml.h:10 ../hacks/config/wormhole.xml.h:10
+msgid "Lots"
+msgstr "Много"
+
+#: ../hacks/config/binaryring.xml.h:11
+msgid "Fade with colors"
+msgstr "Переход с цветами"
+
+#: ../hacks/config/binaryring.xml.h:12
+msgid ""
+"A system of path tracing particles evolves continuously from an initial "
+"creation, alternating dark and light colors. Written by J. Tarbell and "
+"Emilio Del Tessandoro; 2014."
 msgstr ""
 
-#: hacks/config/braid.xml.h:8
-msgid "Max Rings"
+#: ../hacks/config/blaster.xml.h:1
+msgid "Blaster"
 msgstr ""
 
-#: hacks/config/bsod.xml.h:1 hacks/config/molecule.xml.h:1
-#: hacks/config/vidwhacker.xml.h:1
-msgid "2 minutes"
-msgstr "2 минуты"
+#: ../hacks/config/blaster.xml.h:5
+msgid "Robots"
+msgstr "Роботы"
 
-#: hacks/config/bsod.xml.h:2 hacks/config/molecule.xml.h:2
-msgid "5 seconds"
-msgstr "5 секунд"
+#: ../hacks/config/blaster.xml.h:6 ../hacks/config/penetrate.xml.h:5
+msgid "Lasers"
+msgstr "Лазеры"
 
-#: hacks/config/bsod.xml.h:3
-msgid "AmigaDOS"
-msgstr "AmigaDOS"
+#: ../hacks/config/blaster.xml.h:8 ../hacks/config/dymaxionmap.xml.h:12
+#: ../hacks/config/glplanet.xml.h:11
+msgid "Stars"
+msgstr "Звезды"
 
-#: hacks/config/bsod.xml.h:4
-msgid "Apple II"
+#: ../hacks/config/blaster.xml.h:12
+msgid ""
+"Flying space-combat robots (cleverly disguised as colored circles) do battle "
+"in front of a moving star field. Written by Jonathan Lin; 1999."
 msgstr ""
 
-#: hacks/config/bsod.xml.h:5
-msgid "Atari"
-msgstr "Atari"
+#: ../hacks/config/blinkbox.xml.h:1
+msgid "BlinkBox"
+msgstr ""
 
-#: hacks/config/bsod.xml.h:6
-msgid "BSD"
-msgstr "BSD"
+#: ../hacks/config/blinkbox.xml.h:6
+msgid "Box size"
+msgstr "Размер коробки"
 
-#: hacks/config/bsod.xml.h:7
-msgid "BSOD"
+#: ../hacks/config/blinkbox.xml.h:8 ../hacks/config/phosphor.xml.h:7
+msgid "Fade"
+msgstr "Затухание"
+
+#: ../hacks/config/blinkbox.xml.h:9 ../hacks/config/strange.xml.h:18
+msgid "Motion blur"
+msgstr "Размытие в движении"
+
+#: ../hacks/config/blinkbox.xml.h:10
+msgid "Dissolve"
+msgstr "Схлопывание"
+
+#: ../hacks/config/blinkbox.xml.h:13
+msgid ""
+"A motion-blurred ball bounces inside a box whose tiles only become visible "
+"upon impact. Written by Jeremy English; 2003."
+msgstr ""
+
+#: ../hacks/config/blitspin.xml.h:1
+msgid "BlitSpin"
 msgstr ""
 
-#: hacks/config/bsod.xml.h:8
+#: ../hacks/config/blitspin.xml.h:3
+msgid "Fuzzy rotation speed"
+msgstr "Скорость неопределенного поворота"
+
+#: ../hacks/config/blitspin.xml.h:5
+msgid "90 degree rotation speed"
+msgstr "Скорость поворота на 90 градусов"
+
+#: ../hacks/config/blitspin.xml.h:10
 msgid ""
-"BSOD stands for ``Blue Screen of Death.'' The finest in personal computer "
-"emulation, this hack simulates popular screen savers from a number of less "
-"robust operating systems. Written by Jamie Zawinski."
+"Repeatedly rotates a bitmap by 90 degrees by using logical operations: the "
+"bitmap is divided into quadrants, and the quadrants are shifted clockwise. "
+"Then the same thing is done again with progressively smaller quadrants, "
+"except that all sub-quadrants of a given size are rotated in parallel. As "
+"you watch it, the image appears to dissolve into static and then "
+"reconstitute itself, but rotated. Written by Jamie Zawinski; 1992."
 msgstr ""
 
-#: hacks/config/bsod.xml.h:10
-msgid "HPUX"
+#: ../hacks/config/blocktube.xml.h:1
+msgid "BlockTube"
 msgstr ""
 
-#: hacks/config/bsod.xml.h:11
-msgid "HVX/GCOS6"
-msgstr ""
+#: ../hacks/config/blocktube.xml.h:6
+msgid "Color hold time"
+msgstr "Время задержки цвета"
 
-#: hacks/config/bsod.xml.h:12
-msgid "Linux (fsck)"
-msgstr ""
+#: ../hacks/config/blocktube.xml.h:8
+msgid "Color change time"
+msgstr "Время изменения цвета"
 
-#: hacks/config/bsod.xml.h:13
-msgid "Linux (hppa)"
+#: ../hacks/config/blocktube.xml.h:12
+msgid ""
+"A swirling, falling tunnel of reflective slabs. They fade from hue to hue. "
+"Written by Lars R. Damerow; 2003."
 msgstr ""
 
-#: hacks/config/bsod.xml.h:14
-msgid "Linux (sparc)"
+#: ../hacks/config/boing.xml.h:1
+msgid "Boing"
 msgstr ""
 
-#: hacks/config/bsod.xml.h:15
-msgid "MS-DOS"
-msgstr ""
+#: ../hacks/config/boing.xml.h:2 ../hacks/config/boxed.xml.h:11
+#: ../hacks/config/pinion.xml.h:9 ../hacks/config/sonar.xml.h:21
+#: ../hacks/config/winduprobot.xml.h:11
+msgid "Tiny"
+msgstr "Маленький"
 
-#: hacks/config/bsod.xml.h:16
-msgid "Mac Bomb"
-msgstr ""
+#: ../hacks/config/boing.xml.h:3 ../hacks/config/discoball.xml.h:9
+#: ../hacks/config/lisa.xml.h:11 ../hacks/config/lissie.xml.h:14
+#: ../hacks/config/loop.xml.h:11 ../hacks/config/rotor.xml.h:12
+#: ../hacks/config/rubik.xml.h:9 ../hacks/config/wander.xml.h:12
+#: ../hacks/config/worm.xml.h:9
+msgid "Size"
+msgstr "Размер"
 
-#: hacks/config/bsod.xml.h:17
-msgid "MacOS X"
-msgstr ""
+#: ../hacks/config/boing.xml.h:4 ../hacks/config/boxed.xml.h:13
+#: ../hacks/config/glcells.xml.h:13 ../hacks/config/pinion.xml.h:11
+#: ../hacks/config/sonar.xml.h:23 ../hacks/config/winduprobot.xml.h:13
+msgid "Huge"
+msgstr "Большой"
 
-#: hacks/config/bsod.xml.h:18
-msgid "MacsBug"
-msgstr ""
+#: ../hacks/config/boing.xml.h:8
+msgid "Meridians"
+msgstr "Меридианы"
 
-#: hacks/config/bsod.xml.h:19
-msgid "NCD X Terminal  "
-msgstr ""
+#: ../hacks/config/boing.xml.h:9
+msgid "Parallels"
+msgstr "Параллели"
 
-#: hacks/config/bsod.xml.h:20
-msgid "Nvidia"
-msgstr ""
+#: ../hacks/config/boing.xml.h:10
+msgid "Smoothing"
+msgstr "Сглаживание"
 
-#: hacks/config/bsod.xml.h:21
-msgid "OS/2"
-msgstr ""
+#: ../hacks/config/boing.xml.h:12 ../hacks/config/unknownpleasures.xml.h:6
+msgid "Scanlines"
+msgstr "Растровые строки"
 
-#: hacks/config/bsod.xml.h:22
-msgid "OS/390"
+#: ../hacks/config/boing.xml.h:15
+msgid ""
+"A clone of the first graphics demo for the Amiga 1000, which was written by "
+"Dale Luck and RJ Mical during a break at the 1984 Consumer Electronics Show "
+"(or so the legend goes.) This looks like the original Amiga demo if you turn "
+"off \"smoothing\" and \"lighting\" and turn on \"scanlines\", and is "
+"somewhat more modern otherwise. https://en.wikipedia.org/wiki/"
+"Amiga#Boing_Ball Written by Jamie Zawinski; 2005."
 msgstr ""
 
-#: hacks/config/bsod.xml.h:23
-msgid "SCO"
-msgstr "SCO"
-
-#: hacks/config/bsod.xml.h:24
-msgid "Sad Mac"
+#: ../hacks/config/bouboule.xml.h:1
+msgid "Bouboule"
 msgstr ""
 
-#: hacks/config/bsod.xml.h:25
-msgid "Solaris"
-msgstr "Solaris"
+#: ../hacks/config/bouboule.xml.h:6
+msgid "Number of spots"
+msgstr "Количество точек"
 
-#: hacks/config/bsod.xml.h:26
-msgid "Tru64"
-msgstr ""
+#: ../hacks/config/bouboule.xml.h:10 ../hacks/config/rocks.xml.h:13
+msgid "Do Red/Blue 3D separation"
+msgstr "Разделять красное/синее 3D"
 
-#: hacks/config/bsod.xml.h:27
-msgid "VMS"
+#: ../hacks/config/bouboule.xml.h:12
+msgid ""
+"A deforming balloon with varying-sized spots painted on its invisible "
+"surface. Written by Jeremie Petit; 1997."
 msgstr ""
 
-#: hacks/config/bsod.xml.h:28
-#, fuzzy
-msgid "Windows 2000  "
-msgstr "Windows 2000"
+#: ../hacks/config/bouncingcow.xml.h:1
+msgid "BouncingCow"
+msgstr ""
 
-#: hacks/config/bsod.xml.h:29
-#, fuzzy
-msgid "Windows 3.1"
-msgstr "Windows NT"
+#: ../hacks/config/bouncingcow.xml.h:6
+msgid "Bounce speed"
+msgstr "Скорость прыжков"
 
-#: hacks/config/bsod.xml.h:30
-msgid "Windows NT"
-msgstr "Windows NT"
+#: ../hacks/config/bouncingcow.xml.h:8
+msgid "Moo"
+msgstr "Му-у!"
 
-#: hacks/config/bubble3d.xml.h:1
-#, fuzzy
-msgid "Bubble Color"
-msgstr "DirectColor"
+#: ../hacks/config/bouncingcow.xml.h:9
+msgid "Number of cows"
+msgstr "Количество коров"
 
-#: hacks/config/bubble3d.xml.h:2
-msgid "Bubble3D"
-msgstr ""
+#: ../hacks/config/bouncingcow.xml.h:10
+msgid "Herd"
+msgstr "Стадо"
 
-#: hacks/config/bubble3d.xml.h:3
+#: ../hacks/config/bouncingcow.xml.h:13
 msgid ""
-"Draws a stream of rising, undulating 3D bubbles, rising toward the top of "
-"the screen, with nice specular reflections. Written by Richard Jones."
+"A Cow. A Trampoline. Together, they fight crime. Written by Jamie Zawinski; "
+"2003."
 msgstr ""
 
-#: hacks/config/bubble3d.xml.h:8
-msgid "Transparent Bubbles"
+#: ../hacks/config/boxed.xml.h:1
+msgid "Boxed"
 msgstr ""
 
-#: hacks/config/bubbles.xml.h:1 hacks/config/xfishtank.xml.h:2
-msgid "Bubbles"
-msgstr ""
+#: ../hacks/config/boxed.xml.h:9 ../hacks/config/fluidballs.xml.h:6
+msgid "Number of balls"
+msgstr "Количество мячей"
 
-#: hacks/config/bubbles.xml.h:2
-msgid "Bubbles Fall"
-msgstr ""
+#: ../hacks/config/boxed.xml.h:12 ../hacks/config/fluidballs.xml.h:9
+msgid "Ball size"
+msgstr "Размер мяча"
 
-#: hacks/config/bubbles.xml.h:3
-msgid "Bubbles Float"
-msgstr ""
+#: ../hacks/config/boxed.xml.h:14 ../hacks/config/hopalong.xml.h:14
+msgid "Popcorn"
+msgstr "Поп-корн"
 
-#: hacks/config/bubbles.xml.h:4
-msgid "Bubbles Rise"
-msgstr ""
+#: ../hacks/config/boxed.xml.h:15
+msgid "Explosion force"
+msgstr "Сила взрыва"
 
-#: hacks/config/bubbles.xml.h:5
-msgid "Bubbles exist in three dimensions"
-msgstr ""
+#: ../hacks/config/boxed.xml.h:16
+msgid "Nuke"
+msgstr "Ядерная бомба"
 
-#: hacks/config/bubbles.xml.h:6
-msgid "Don't hide bubbles when they pop"
-msgstr ""
+#: ../hacks/config/boxed.xml.h:18
+msgid "Explosion decay"
+msgstr "Задержка взрыва"
 
-#: hacks/config/bubbles.xml.h:7
-msgid "Draw circles instead of pixmap bubbles"
-msgstr ""
+#: ../hacks/config/boxed.xml.h:19
+msgid "Pop!"
+msgstr "Бум!"
 
-#: hacks/config/bubbles.xml.h:9
-msgid "Leave Trails"
-msgstr ""
+#: ../hacks/config/boxed.xml.h:21
+msgid "Explosion momentum"
+msgstr "Импульс взрыва"
 
-#: hacks/config/bubbles.xml.h:12
-msgid ""
-"This simulates the kind of bubble formation that happens when water boils:"
-"small bubbles appear, and as they get closer to each other, they combine to "
-"form larger bubbles, which eventually pop. Written by James Macnicol."
-msgstr ""
+#: ../hacks/config/boxed.xml.h:22 ../hacks/config/xmatrix.xml.h:20
+msgid "Full"
+msgstr "Полный"
 
-#: hacks/config/bumps.xml.h:1
+#: ../hacks/config/boxed.xml.h:25
 msgid ""
-"A bit like `Spotlight', except that instead of merely exposing part of your "
-"desktop, it creates a bump map from it. Basically, it 3D-izes a roaming "
-"section of your desktop, based on color intensity. Written by Shane Smit."
+"A box full of 3D bouncing balls that explode. Written by Sander van Grieken; "
+"2002."
 msgstr ""
 
-#: hacks/config/bumps.xml.h:2
-msgid "Bumps"
+#: ../hacks/config/boxfit.xml.h:1
+msgid "BoxFit"
 msgstr ""
 
-#: hacks/config/cage.xml.h:1
-msgid "Cage"
-msgstr ""
+#: ../hacks/config/boxfit.xml.h:5 ../hacks/config/cityflow.xml.h:6
+#: ../hacks/config/cubenetic.xml.h:6
+msgid "Boxes"
+msgstr "Коробки"
 
-#: hacks/config/cage.xml.h:7 hacks/config/cube21.xml.h:22
-msgid "Textured"
-msgstr ""
+#: ../hacks/config/boxfit.xml.h:6
+msgid "Grow by"
+msgstr "Рост по"
 
-#: hacks/config/cage.xml.h:8
-msgid ""
-"This draws Escher's ``Impossible Cage,'' a 3d analog of a moebius strip, and "
-"rotates it in three dimensions. Written by Marcelo Vianna."
-msgstr ""
+#: ../hacks/config/boxfit.xml.h:7
+msgid "Spacing"
+msgstr "Пространство"
 
-#: hacks/config/carousel.xml.h:1 hacks/config/coral.xml.h:1
-#: hacks/config/deco.xml.h:1 hacks/config/helix.xml.h:1
-#: hacks/config/imsmap.xml.h:1 hacks/config/jigsaw.xml.h:2
-#: hacks/config/moire.xml.h:1 hacks/config/pedal.xml.h:1
-#: hacks/config/rorschach.xml.h:1 hacks/config/wander.xml.h:2
-#: hacks/config/xspirograph.xml.h:1
-msgid "1 Minute"
-msgstr "1 минута"
+#: ../hacks/config/boxfit.xml.h:8 ../hacks/config/popsquares.xml.h:6
+msgid "Border"
+msgstr "Граница"
 
-#: hacks/config/carousel.xml.h:2
-#, fuzzy
-msgid "5 Seconds"
-msgstr "0 секунд"
+#: ../hacks/config/boxfit.xml.h:9
+msgid "Boxes or circles"
+msgstr "Коробки или круги"
 
-#: hacks/config/carousel.xml.h:4
-msgid "Carousel"
-msgstr ""
+#: ../hacks/config/boxfit.xml.h:10
+msgid "Boxes only"
+msgstr "Только коробки"
 
-#: hacks/config/carousel.xml.h:6 hacks/config/electricsheep.xml.h:7
-#: hacks/config/fliptext.xml.h:8
-msgid "Frame Rate"
-msgstr ""
+#: ../hacks/config/boxfit.xml.h:11
+msgid "Circles only"
+msgstr "Только круги"
+
+#: ../hacks/config/boxfit.xml.h:12
+msgid "Color gradient"
+msgstr "Градиент цвета"
+
+#: ../hacks/config/boxfit.xml.h:13
+msgid "Grab images"
+msgstr "Захватывать изображения с рабочего стола"
+
+#: ../hacks/config/boxfit.xml.h:14
+msgid "Peek at underlying images"
+msgstr "Переводить фокус на основные изображения"
 
-#: hacks/config/carousel.xml.h:8
+#: ../hacks/config/boxfit.xml.h:16
 msgid ""
-"Loads several random images, and displays them flying in a circular "
-"formation. The circle changes speed and direction randomly, tilts on its "
-"axis, and the images move in and out. To tell it where to find the images to "
-"display, go to the \"Advanced\" tab on the Screensaver Preferences window. "
-"Select \"Choose Random Images\", and enter your image directory in the text "
-"field right below that. (Note: not the the \"Advanced\" button at the bottom "
-"of this window: the tab at the top of the *other* window.) This program "
-"requires a good video card capable of supporting large textures. Written by "
-"Jamie Zawinski."
+"Packs the screen with growing squares or circles, colored according to a "
+"horizontal or vertical gradient, or according to the colors of a loaded "
+"image. The objects grow until they touch, then stop. When the screen is "
+"full, they shrink away and the process restarts. Written by Jamie Zawinski; "
+"2005."
 msgstr ""
 
-#: hacks/config/carousel.xml.h:10
-msgid "No Tilting"
+#: ../hacks/config/braid.xml.h:1
+msgid "Braid"
 msgstr ""
 
-#: hacks/config/carousel.xml.h:11
-#, fuzzy
-msgid "Number of Images:"
-msgstr "Количество цветов"
+#: ../hacks/config/braid.xml.h:11
+msgid "Number of rings"
+msgstr "Количество колец"
 
-#: hacks/config/carousel.xml.h:13 hacks/config/glslideshow.xml.h:20
-msgid "Show Image Titles"
-msgstr ""
+#: ../hacks/config/braid.xml.h:12 ../hacks/config/epicycle.xml.h:11
+#: ../hacks/config/hilbert.xml.h:16 ../hacks/config/nerverot.xml.h:20
+msgid "Line thickness"
+msgstr "Толщина линии"
 
-#: hacks/config/carousel.xml.h:15
-msgid "Tilt In/Out Only"
+#: ../hacks/config/braid.xml.h:14
+msgid "Inter-braided concentric circles. Written by John Neil; 1997."
 msgstr ""
 
-#: hacks/config/carousel.xml.h:16
-msgid "Tilt In/Out and Left/Right"
+#: ../hacks/config/bsod.xml.h:1
+msgid "BSOD"
 msgstr ""
 
-#: hacks/config/carousel.xml.h:17
-msgid "Tilt Left/Right Only"
+#: ../hacks/config/bsod.xml.h:2 ../hacks/config/carousel.xml.h:8
+#: ../hacks/config/geodesicgears.xml.h:5 ../hacks/config/m6502.xml.h:2
+#: ../hacks/config/molecule.xml.h:5
+msgid "5 seconds"
+msgstr "5 секунд"
+
+#: ../hacks/config/bsod.xml.h:4 ../hacks/config/geodesicgears.xml.h:7
+#: ../hacks/config/m6502.xml.h:4 ../hacks/config/molecule.xml.h:7
+#: ../hacks/config/vidwhacker.xml.h:4
+msgid "2 minutes"
+msgstr "2 минуты"
+
+#: ../hacks/config/bsod.xml.h:6
+msgid "Windows 3.1"
 msgstr ""
 
-#: hacks/config/carousel.xml.h:18 hacks/config/glslideshow.xml.h:21
-#: hacks/config/mirrorblob.xml.h:21
-msgid "Time until loading a new image:"
+#: ../hacks/config/bsod.xml.h:7
+msgid "Windows NT"
 msgstr ""
 
-#: hacks/config/carousel.xml.h:19
-msgid "Zoom In/Out"
+#: ../hacks/config/bsod.xml.h:8
+msgid "Windows 2000"
 msgstr ""
 
-#: hacks/config/ccurve.xml.h:1
-msgid "0 seconds"
+#: ../hacks/config/bsod.xml.h:9
+msgid "Windows 10"
 msgstr ""
 
-#: hacks/config/ccurve.xml.h:2 hacks/config/polyhedra.xml.h:2
-#, fuzzy
-msgid "30 seconds"
-msgstr "2 секунды"
+#: ../hacks/config/bsod.xml.h:10
+msgid "MS-DOS"
+msgstr ""
 
-#: hacks/config/ccurve.xml.h:4
-msgid "C Curve"
+#: ../hacks/config/bsod.xml.h:11
+msgid "AmigaDOS"
 msgstr ""
 
-#: hacks/config/ccurve.xml.h:5
-msgid "Change Image Every"
+#: ../hacks/config/bsod.xml.h:12
+msgid "GLaDOS"
 msgstr ""
 
-#: hacks/config/ccurve.xml.h:6 hacks/config/coral.xml.h:5
-#: hacks/config/imsmap.xml.h:5 hacks/config/kumppa.xml.h:1
-#: hacks/config/qix.xml.h:6 hacks/config/squiral.xml.h:2
-#: hacks/config/wander.xml.h:4 hacks/config/xmatrix.xml.h:2
-msgid "Density"
-msgstr "Плотность"
+#: ../hacks/config/bsod.xml.h:13
+msgid "Android"
+msgstr ""
 
-#: hacks/config/ccurve.xml.h:8
-msgid ""
-"Generates self-similar linear fractals, including the classic ``C Curve.'' "
-"Written by Rick Campbell."
+#: ../hacks/config/bsod.xml.h:14
+msgid "Apple ]["
 msgstr ""
 
-#: hacks/config/celtic.xml.h:1
-msgid "Celtic"
+#: ../hacks/config/bsod.xml.h:15
+msgid "VMware"
 msgstr ""
 
-#: hacks/config/celtic.xml.h:2
-msgid "Draw Graph"
+#: ../hacks/config/bsod.xml.h:16
+msgid "NVidia"
 msgstr ""
 
-#: hacks/config/celtic.xml.h:5
-msgid "Pause"
+#: ../hacks/config/bsod.xml.h:17
+msgid "OS/2"
 msgstr ""
 
-#: hacks/config/celtic.xml.h:6
-msgid ""
-"Repeatedly draws random Celtic cross-stitch patterns. By Max Froumentin."
+#: ../hacks/config/bsod.xml.h:18
+msgid "Sad Mac"
 msgstr ""
 
-#: hacks/config/circuit.xml.h:1
-msgid "Animates a number of 3D electronic components. Written by Ben Buxton."
+#: ../hacks/config/bsod.xml.h:19
+msgid "Mac bomb"
 msgstr ""
 
-#: hacks/config/circuit.xml.h:2
-msgid "Circuit"
+#: ../hacks/config/bsod.xml.h:20
+msgid "MacsBug"
 msgstr ""
 
-#: hacks/config/circuit.xml.h:3 hacks/config/gflux.xml.h:4
-#: hacks/config/pulsar.xml.h:2
-msgid "Directional Lighting"
+#: ../hacks/config/bsod.xml.h:21
+msgid "Atari"
 msgstr ""
 
-#: hacks/config/circuit.xml.h:5
-msgid "Flat Coloring"
+#: ../hacks/config/bsod.xml.h:22
+msgid "MacOS X"
 msgstr ""
 
-#: hacks/config/circuit.xml.h:6
-msgid "Parts"
+#: ../hacks/config/bsod.xml.h:23
+msgid "OS/390"
 msgstr ""
 
-#: hacks/config/circuit.xml.h:7 hacks/config/flipscreen3d.xml.h:4
-#: hacks/config/gleidescope.xml.h:9 hacks/config/glplanet.xml.h:6
-#: hacks/config/ifs.xml.h:10
-msgid "Rotate"
+#: ../hacks/config/bsod.xml.h:24
+msgid "VMS"
 msgstr ""
 
-#: hacks/config/circuit.xml.h:8 hacks/config/pinion.xml.h:10
-msgid "Rotation Speed"
+#: ../hacks/config/bsod.xml.h:25
+msgid "HVX/GCOS6"
 msgstr ""
 
-#: hacks/config/circuit.xml.h:12 hacks/config/cube21.xml.h:18
-#: hacks/config/cubestorm.xml.h:9 hacks/config/dangerball.xml.h:9
-#: hacks/config/engine.xml.h:17 hacks/config/klein.xml.h:9
-#: hacks/config/polyhedra.xml.h:145 hacks/config/whirlygig.xml.h:14
-msgid "Spin"
-msgstr "Вращение"
+#: ../hacks/config/bsod.xml.h:26
+msgid "NCD X Terminal  "
+msgstr ""
 
-#: hacks/config/cloudlife.xml.h:1 hacks/config/demon.xml.h:2
-#: hacks/config/petri.xml.h:1
-msgid "Cell Size"
+#: ../hacks/config/bsod.xml.h:27
+msgid "ATM"
 msgstr ""
 
-#: hacks/config/cloudlife.xml.h:2
-msgid "CloudLife"
+#: ../hacks/config/bsod.xml.h:28
+msgid "BSD"
 msgstr ""
 
-#: hacks/config/cloudlife.xml.h:4
-msgid ""
-"Generates cloud-like formations based on a variant of Conway's Life. The "
-"difference is that cells have a maximum age, after which they count as 3 for "
-"populating the next generation. This makes long-lived formations explode "
-"instead of just sitting there burning a hole in your screen. Written by Don "
-"Marti."
+#: ../hacks/config/bsod.xml.h:29
+msgid "Linux (fsck)"
 msgstr ""
 
-#: hacks/config/cloudlife.xml.h:6
-#, fuzzy
-msgid "Initial Density"
-msgstr "Плотность"
+#: ../hacks/config/bsod.xml.h:30
+msgid "Linux (sparc)"
+msgstr ""
 
-#: hacks/config/cloudlife.xml.h:9
-msgid "Max Age"
+#: ../hacks/config/bsod.xml.h:31
+msgid "Linux (hppa)"
 msgstr ""
 
-#: hacks/config/cloudlife.xml.h:10
-msgid "Old"
+#: ../hacks/config/bsod.xml.h:32
+msgid "Solaris"
 msgstr ""
 
-#: hacks/config/cloudlife.xml.h:14
-#, fuzzy
-msgid "Young"
-msgstr "Длинный"
+#: ../hacks/config/bsod.xml.h:33
+msgid "SCO"
+msgstr ""
 
-#: hacks/config/compass.xml.h:1
-msgid "Compass"
+#: ../hacks/config/bsod.xml.h:34
+msgid "HPUX"
 msgstr ""
 
-#: hacks/config/compass.xml.h:2 hacks/config/deluxe.xml.h:3
-#: hacks/config/fontglide.xml.h:3 hacks/config/fuzzyflakes.xml.h:5
-#: hacks/config/interference.xml.h:6 hacks/config/kumppa.xml.h:2
-#: hacks/config/nerverot.xml.h:6 hacks/config/piecewise.xml.h:3
-#: hacks/config/pipes.xml.h:4
-msgid "Double Buffer"
+#: ../hacks/config/bsod.xml.h:35
+msgid "Tru64"
 msgstr ""
 
-#: hacks/config/compass.xml.h:6
+#.
+#. <hgroup>
+#. <vgroup>
+#. <number id="tvcolor" type="slider" arg="-tv-color %"
+#. _label="Color Knob" _low-label="Low" _high-label="High"
+#. low="0" high="1000" default="70"/>
+#. <number id="tvtint" type="slider" arg="-tv-tint %"
+#. _label="Tint Knob" _low-label="Low" _high-label="High"
+#. low="0" high="100" default="5"/>
+#. </vgroup>
+#. <vgroup>
+#. <number id="tvbrightness" type="slider" arg="-tv-brightness %"
+#. _label="Brightness Knob" _low-label="Low" _high-label="High"
+#. low="0" high="200" default="150"/>
+#. <number id="tvcontrast" type="slider" arg="-tv-contrast %"
+#. _label="Contrast Knob" _low-label="Low" _high-label="High"
+#. low="0" high="1500" default="1000"/>
+#. </vgroup>
+#. </hgroup>
+#.
+#: ../hacks/config/bsod.xml.h:57
+#, no-c-format
 msgid ""
-"This draws a compass, with all elements spinning about randomly, for that "
-"``lost and nauseous'' feeling. Written by Jamie Zawinski."
+"BSOD stands for \"Blue Screen of Death\". The finest in personal computer "
+"emulation, BSOD simulates popular screen savers from a number of less robust "
+"operating systems. https://en.wikipedia.org/wiki/Blue_Screen_of_Death "
+"https://en.wikipedia.org/wiki/Screen_of_death https://en.wikipedia.org/wiki/"
+"Guru_Meditation https://en.wikipedia.org/wiki/Row_of_Bombs https://en."
+"wikipedia.org/wiki/Bomb_%28symbol%29 Written by Jamie Zawinski; 1998."
 msgstr ""
 
-#: hacks/config/coral.xml.h:2 hacks/config/deco.xml.h:2
-#: hacks/config/glslideshow.xml.h:1 hacks/config/helix.xml.h:2
-#: hacks/config/imsmap.xml.h:2 hacks/config/moire.xml.h:2
-#: hacks/config/pedal.xml.h:2 hacks/config/rorschach.xml.h:2
-#: hacks/config/xspirograph.xml.h:2
-msgid "1 Second"
-msgstr "1 секунда"
-
-#: hacks/config/coral.xml.h:3
-msgid "Coral"
+#: ../hacks/config/bubble3d.xml.h:1
+msgid "Bubble3D"
 msgstr ""
 
-#: hacks/config/coral.xml.h:4 hacks/config/fireworkx.xml.h:2
-#: hacks/config/gflux.xml.h:3 hacks/config/glblur.xml.h:2
-#: hacks/config/glmatrix.xml.h:3 hacks/config/imsmap.xml.h:4
-#: hacks/config/lavalite.xml.h:6 hacks/config/pyro.xml.h:2
-#: hacks/config/qix.xml.h:5 hacks/config/squiral.xml.h:1
-#: hacks/config/xearth.xml.h:4
-msgid "Dense"
-msgstr "Плотно"
+#: ../hacks/config/bubble3d.xml.h:5
+msgid "Transparent bubbles"
+msgstr "Прозрачные пузыри"
 
-#: hacks/config/coral.xml.h:10 hacks/config/squiral.xml.h:13
-msgid "Seeds"
-msgstr "Зерна"
+#: ../hacks/config/bubble3d.xml.h:6 ../hacks/config/flurry.xml.h:10
+#: ../hacks/config/rotzoomer.xml.h:9 ../hacks/config/sballs.xml.h:5
+#: ../hacks/config/starfish.xml.h:2
+msgid "Random"
+msgstr "Случайный"
 
-#: hacks/config/coral.xml.h:11
-msgid ""
-"Simulates coral growth, albeit somewhat slowly. Written by Frederick Roeber."
-msgstr ""
+#. DarkOrange is probably the closest named color.
+#: ../hacks/config/bubble3d.xml.h:7 ../hacks/config/phosphor.xml.h:11
+msgid "Amber"
+msgstr "Янтарный"
 
-#: hacks/config/coral.xml.h:13 hacks/config/fireworkx.xml.h:10
-#: hacks/config/gflux.xml.h:13 hacks/config/glblur.xml.h:15
-#: hacks/config/glmatrix.xml.h:19 hacks/config/imsmap.xml.h:13
-#: hacks/config/lavalite.xml.h:29 hacks/config/pyro.xml.h:14
-#: hacks/config/qix.xml.h:21 hacks/config/squiral.xml.h:15
-#: hacks/config/xearth.xml.h:24 hacks/config/xmatrix.xml.h:17
-msgid "Sparse"
-msgstr "Редко"
+#: ../hacks/config/bubble3d.xml.h:8 ../hacks/config/fuzzyflakes.xml.h:16
+#: ../hacks/config/phosphor.xml.h:9
+msgid "Green"
+msgstr "Зеленый"
 
-#: hacks/config/cosmos.xml.h:1
-msgid "Cosmos"
-msgstr ""
+#: ../hacks/config/bubble3d.xml.h:9 ../hacks/config/fuzzyflakes.xml.h:18
+msgid "Blue"
+msgstr "Синий"
 
-#: hacks/config/cosmos.xml.h:2
-msgid ""
-"Draws fireworks and zooming, fading flares. By Tom Campbell. You can find it "
-"at &lt;http://www.cosmosx.org/&gt;"
-msgstr ""
+#: ../hacks/config/bubble3d.xml.h:10 ../hacks/config/cube21.xml.h:13
+#: ../hacks/config/phosphor.xml.h:12
+msgid "White"
+msgstr "Белый"
 
-#: hacks/config/crackberg.xml.h:1
-msgid "Confused"
+#: ../hacks/config/bubble3d.xml.h:12
+msgid ""
+"Rising, undulating 3D bubbles, with transparency and specular reflections. "
+"Written by Richard Jones; 1998."
 msgstr ""
 
-#: hacks/config/crackberg.xml.h:2
-msgid "Crackberg"
+#: ../hacks/config/bubbles.xml.h:1
+msgid "Bubbles"
 msgstr ""
 
-#: hacks/config/crackberg.xml.h:3
-#, fuzzy
-msgid "Display FPS"
-msgstr "Режимы экрана"
-
-#: hacks/config/crackberg.xml.h:4
-msgid "Eagle Nest"
+#: ../hacks/config/bubbles.xml.h:5
+msgid "Draw circles instead of bubble images"
 msgstr ""
 
-#: hacks/config/crackberg.xml.h:5
-msgid "Flat Shading"
+#: ../hacks/config/bubbles.xml.h:6
+msgid "Don't hide bubbles when they pop"
 msgstr ""
 
-#: hacks/config/crackberg.xml.h:6
-msgid ""
-"Flies through height maps, optionally animating the creation and destruction "
-"of generated tiles; tiles `grow' into place."
+#: ../hacks/config/bubbles.xml.h:7
+msgid "Leave trails"
 msgstr ""
 
-#: hacks/config/crackberg.xml.h:7
-#, fuzzy
-msgid "Frame Delay"
-msgstr "Задержка перед решением"
-
-#: hacks/config/crackberg.xml.h:8
-#, fuzzy
-msgid "Growing"
-msgstr "Длинный"
-
-#: hacks/config/crackberg.xml.h:9
-msgid "Ice"
+#: ../hacks/config/bubbles.xml.h:8
+msgid "Bubbles rise"
 msgstr ""
 
-#: hacks/config/crackberg.xml.h:10
-msgid "Immediate"
+#: ../hacks/config/bubbles.xml.h:9
+msgid "Bubbles float"
 msgstr ""
 
-#: hacks/config/crackberg.xml.h:11 hacks/config/glslideshow.xml.h:14
-msgid "Letterbox"
+#: ../hacks/config/bubbles.xml.h:10
+msgid "Bubbles fall"
 msgstr ""
 
-#: hacks/config/crackberg.xml.h:14
-msgid "Mouse Hole"
+#: ../hacks/config/bubbles.xml.h:12
+msgid ""
+"This screen saver was removed from the XScreenSaver distribution as of "
+"version 5.08. This simulates the kind of bubble formation that happens when "
+"water boils: small bubbles appear, and as they get closer to each other, "
+"they combine to form larger bubbles, which eventually pop. Written by James "
+"Macnicol; 1996."
 msgstr ""
 
-#: hacks/config/crackberg.xml.h:15
-msgid "Plain"
+#: ../hacks/config/bumps.xml.h:1 ../hacks/config/mirrorblob.xml.h:15
+msgid "Bumps"
 msgstr ""
 
-#: hacks/config/crackberg.xml.h:16 hacks/config/flurry.xml.h:8
-#: hacks/config/fontglide.xml.h:12 hacks/config/jigglypuff.xml.h:13
-#: hacks/config/sballs.xml.h:10 hacks/config/whirlygig.xml.h:12
-msgid "Random"
+#: ../hacks/config/bumps.xml.h:12
+msgid ""
+"A spotlight roams across an embossed version of a loaded image. Written by "
+"Shane Smit; 1999."
 msgstr ""
 
-#: hacks/config/crackberg.xml.h:18
-msgid "Subdivisions"
+#: ../hacks/config/cage.xml.h:1
+msgid "Cage"
 msgstr ""
 
-#: hacks/config/crackberg.xml.h:19
-msgid "Swampy"
+#: ../hacks/config/cage.xml.h:7
+msgid ""
+"Escher's \"Impossible Cage\", a 3d analog of a moebius strip, and rotates it "
+"in three dimensions. https://en.wikipedia.org/wiki/Maurits_Cornelis_Escher "
+"Written by Marcelo Vianna; 1998."
 msgstr ""
 
-#: hacks/config/crackberg.xml.h:20
-msgid "Visibility"
+#: ../hacks/config/carousel.xml.h:1
+msgid "Carousel"
 msgstr ""
 
-#: hacks/config/crackberg.xml.h:21
-msgid "Vomit"
-msgstr ""
+#: ../hacks/config/carousel.xml.h:6 ../hacks/config/ccurve.xml.h:6
+#: ../hacks/config/cubestack.xml.h:6 ../hacks/config/cubetwist.xml.h:6
+#: ../hacks/config/dymaxionmap.xml.h:6 ../hacks/config/geodesic.xml.h:15
+#: ../hacks/config/hydrostat.xml.h:6 ../hacks/config/photopile.xml.h:13
+#: ../hacks/config/tronbit.xml.h:6 ../hacks/config/unicrud.xml.h:6
+msgid "Animation speed"
+msgstr "Скорость анимации"
 
-#: hacks/config/crackberg.xml.h:22 hacks/config/flurry.xml.h:11
-#, fuzzy
-msgid "Water"
-msgstr "Ð\9fеÑ\80емеÑ\89ение"
+#: ../hacks/config/carousel.xml.h:9 ../hacks/config/glslideshow.xml.h:6
+#: ../hacks/config/mirrorblob.xml.h:9 ../hacks/config/photopile.xml.h:19
+msgid "Time until loading a new image"
+msgstr "Ð\92Ñ\80емÑ\8f Ð´Ð¾ Ð·Ð°Ð³Ñ\80Ñ\83зки Ð½Ð¾Ð²Ð¾Ð³Ð¾ Ð¸Ð·Ð¾Ð±Ñ\80ажениÑ\8f"
 
-#: hacks/config/critical.xml.h:1
-msgid "Critical"
-msgstr ""
+#: ../hacks/config/carousel.xml.h:10 ../hacks/config/coral.xml.h:7
+#: ../hacks/config/deco.xml.h:4 ../hacks/config/helix.xml.h:7
+#: ../hacks/config/moire.xml.h:4 ../hacks/config/pedal.xml.h:4
+#: ../hacks/config/rorschach.xml.h:10 ../hacks/config/xspirograph.xml.h:7
+msgid "1 minute"
+msgstr "1 минута"
 
-#: hacks/config/critical.xml.h:2
-msgid ""
-"Draws a system of self-organizing lines. It starts out as random squiggles, "
-"but after a few iterations, order begins to appear. Written by Martin Pool."
-msgstr ""
+#: ../hacks/config/carousel.xml.h:11 ../hacks/config/photopile.xml.h:8
+msgid "Number of images"
+msgstr "Количество изображений"
 
-#: hacks/config/crystal.xml.h:1
-msgid "Center on Screen"
-msgstr ""
+#: ../hacks/config/carousel.xml.h:12
+msgid "Tilt in/out and left/right"
+msgstr "Наклонять внутрь/наружу и влево/вправо"
 
-#: hacks/config/crystal.xml.h:2 hacks/config/deluxe.xml.h:1
-#: hacks/config/fadeplot.xml.h:1 hacks/config/flow.xml.h:1
-#: hacks/config/galaxy.xml.h:1 hacks/config/glforestfire.xml.h:1
-#: hacks/config/grav.xml.h:1 hacks/config/julia.xml.h:1
-#: hacks/config/laser.xml.h:1 hacks/config/lisa.xml.h:1
-#: hacks/config/lissie.xml.h:2 hacks/config/morph3d.xml.h:2
-#: hacks/config/mountain.xml.h:1 hacks/config/piecewise.xml.h:2
-#: hacks/config/qix.xml.h:4 hacks/config/rocks.xml.h:2
-#: hacks/config/rotor.xml.h:2 hacks/config/rubik.xml.h:1
-#: hacks/config/shadebobs.xml.h:1 hacks/config/sierpinski.xml.h:1
-#: hacks/config/slip.xml.h:1 hacks/config/spiral.xml.h:1
-#: hacks/config/sproingies.xml.h:1 hacks/config/superquadrics.xml.h:1
-#: hacks/config/swirl.xml.h:1 hacks/config/worm.xml.h:2
-msgid "Count"
-msgstr "Количество"
+#: ../hacks/config/carousel.xml.h:13
+msgid "Tilt in/out only"
+msgstr "Наклонять только внутрь/наружу"
 
-#: hacks/config/crystal.xml.h:3
-msgid "Crystal"
-msgstr ""
+#: ../hacks/config/carousel.xml.h:14
+msgid "Tilt left/right only"
+msgstr "Наклонять только влево/вправо"
 
-#: hacks/config/crystal.xml.h:4
-msgid "Draw Cell"
-msgstr ""
+#: ../hacks/config/carousel.xml.h:15
+msgid "No tilting"
+msgstr "Не наклонять"
 
-#: hacks/config/crystal.xml.h:5 hacks/config/spheremonics.xml.h:3
-#: hacks/config/xearth.xml.h:6
-msgid "Draw Grid"
-msgstr ""
+#: ../hacks/config/carousel.xml.h:16
+msgid "Zoom in/out"
+msgstr "Увеличивать/уменьшать"
 
-#: hacks/config/crystal.xml.h:7
-msgid "Horizontal Symmetries"
-msgstr ""
+#: ../hacks/config/carousel.xml.h:17 ../hacks/config/glslideshow.xml.h:19
+#: ../hacks/config/photopile.xml.h:21
+msgid "Show file names"
+msgstr "Показывать имена файлов"
 
-#: hacks/config/crystal.xml.h:9
+#: ../hacks/config/carousel.xml.h:19
 msgid ""
-"Moving polygons, similar to a kaleidescope (more like a kaleidescope than "
-"the hack called `kaleid,' actually.) This one by Jouk Jansen."
+"Loads several random images, and displays them flying in a circular "
+"formation. The formation changes speed and direction randomly, and images "
+"periodically drop out to be replaced by new ones. Written by Jamie Zawinski; "
+"2005."
 msgstr ""
 
-#: hacks/config/crystal.xml.h:14
-msgid "Vertical Symmetries"
+#: ../hacks/config/ccurve.xml.h:1
+msgid "CCurve"
 msgstr ""
 
-#: hacks/config/cube21.xml.h:1
-msgid ""
-"Animates a Rubik-like puzzle known as Cube 21 or Square-1. The rotations are "
-"chosen randomly. Requires OpenGL. Written by Vasek Potocek."
-msgstr ""
+#: ../hacks/config/ccurve.xml.h:3
+msgid "Change image every"
+msgstr "Изменять изображение каждые"
 
-#: hacks/config/cube21.xml.h:2
-msgid "Classic Edition"
-msgstr ""
+#: ../hacks/config/ccurve.xml.h:4 ../hacks/config/epicycle.xml.h:10
+#: ../hacks/config/glslideshow.xml.h:15 ../hacks/config/glsnake.xml.h:7
+#: ../hacks/config/polyhedra.xml.h:10 ../hacks/config/starfish.xml.h:10
+msgid "30 seconds"
+msgstr "30 секунд"
 
-#: hacks/config/cube21.xml.h:3
-msgid "Cube 21"
-msgstr ""
+#: ../hacks/config/ccurve.xml.h:9 ../hacks/config/coral.xml.h:9
+#: ../hacks/config/imsmap.xml.h:9 ../hacks/config/kumppa.xml.h:5
+#: ../hacks/config/qix.xml.h:9 ../hacks/config/quasicrystal.xml.h:8
+#: ../hacks/config/squiral.xml.h:11 ../hacks/config/superquadrics.xml.h:8
+#: ../hacks/config/wander.xml.h:5 ../hacks/config/xmatrix.xml.h:19
+msgid "Density"
+msgstr "Плотность"
 
-#: hacks/config/cube21.xml.h:4
-msgid "Cube size"
+#: ../hacks/config/ccurve.xml.h:12
+msgid ""
+"Generates self-similar linear fractals, including the classic \"C Curve\". "
+"https://en.wikipedia.org/wiki/Levy_C_curve Written by Rick Campbell; 1999."
 msgstr ""
 
-#: hacks/config/cube21.xml.h:5
-msgid "Delay in ending position"
+#: ../hacks/config/celtic.xml.h:1
+msgid "Celtic"
 msgstr ""
 
-#: hacks/config/cube21.xml.h:7
-#, fuzzy
-msgid "Global speed"
-msgstr "Скорость акулы"
+#: ../hacks/config/celtic.xml.h:8
+msgid "Draw graph"
+msgstr "Прорисовывать граф"
 
-#: hacks/config/cube21.xml.h:10
-msgid "Random color"
+#: ../hacks/config/celtic.xml.h:10
+msgid ""
+"Repeatedly draws random Celtic cross-stitch patterns. https://en.wikipedia."
+"org/wiki/Celtic_knot https://en.wikipedia.org/wiki/Knots_and_graphs Written "
+"by Max Froumentin; 2005."
 msgstr ""
 
-#: hacks/config/cube21.xml.h:11 hacks/config/rocks.xml.h:8
-msgid "Rotation"
+#: ../hacks/config/circuit.xml.h:1
+msgid "Circuit"
 msgstr ""
 
-#: hacks/config/cube21.xml.h:14
-msgid "Silver Edition"
-msgstr ""
+#: ../hacks/config/circuit.xml.h:5 ../hacks/config/hydrostat.xml.h:8
+#: ../hacks/config/mismunch.xml.h:8 ../hacks/config/mountain.xml.h:5
+#: ../hacks/config/munch.xml.h:8 ../hacks/config/pipes.xml.h:5
+#: ../hacks/config/shadebobs.xml.h:11 ../hacks/config/sproingies.xml.h:5
+#: ../hacks/config/vigilance.xml.h:8 ../hacks/config/winduprobot.xml.h:8
+msgid "One"
+msgstr "Один"
 
-#: hacks/config/cube21.xml.h:15
-msgid "Six random colors"
-msgstr ""
+#: ../hacks/config/circuit.xml.h:6
+msgid "Parts"
+msgstr "Части"
 
-#: hacks/config/cube21.xml.h:19
-#, fuzzy
-msgid "Spinning"
+#: ../hacks/config/circuit.xml.h:9 ../hacks/config/jigglypuff.xml.h:15
+#: ../hacks/config/pinion.xml.h:6
+msgid "Rotation speed"
+msgstr "Скорость вращения"
+
+#: ../hacks/config/circuit.xml.h:11 ../hacks/config/companioncube.xml.h:11
+#: ../hacks/config/cube21.xml.h:19 ../hacks/config/cubestorm.xml.h:15
+#: ../hacks/config/cubetwist.xml.h:16 ../hacks/config/dangerball.xml.h:12
+#: ../hacks/config/discoball.xml.h:12 ../hacks/config/energystream.xml.h:6
+#: ../hacks/config/engine.xml.h:18 ../hacks/config/flipflop.xml.h:6
+#: ../hacks/config/gears.xml.h:12 ../hacks/config/geodesic.xml.h:9
+#: ../hacks/config/geodesicgears.xml.h:12 ../hacks/config/hexstrut.xml.h:15
+#: ../hacks/config/hilbert.xml.h:19 ../hacks/config/moebiusgears.xml.h:11
+#: ../hacks/config/polyhedra.xml.h:164 ../hacks/config/raverhoop.xml.h:19
+#: ../hacks/config/rubikblocks.xml.h:13 ../hacks/config/splodesic.xml.h:10
+#: ../hacks/config/surfaces.xml.h:26 ../hacks/config/tronbit.xml.h:8
+#: ../hacks/config/unicrud.xml.h:9
+msgid "Spin"
 msgstr "Вращение"
 
-#: hacks/config/cube21.xml.h:20
-#, fuzzy
-msgid "Start as cube"
-msgstr "Скорость акулы"
+#: ../hacks/config/circuit.xml.h:12
+msgid "Flat coloring"
+msgstr "Плоское окрашивание"
 
-#: hacks/config/cube21.xml.h:21
-msgid "Start as random shape"
-msgstr ""
+#: ../hacks/config/circuit.xml.h:13 ../hacks/config/gflux.xml.h:16
+msgid "Directional lighting"
+msgstr "Направленное освещение"
 
-#: hacks/config/cube21.xml.h:23
-msgid "Two random colors"
+#: ../hacks/config/circuit.xml.h:15
+msgid "Electronic components float around. Written by Ben Buxton; 2001."
 msgstr ""
 
-#: hacks/config/cube21.xml.h:25
-#, fuzzy
-msgid "Wander on screen"
-msgstr "Скорость блуждания"
-
-#: hacks/config/cube21.xml.h:26
-#, fuzzy
-msgid "Wandering"
-msgstr "Перемещение"
-
-#: hacks/config/cube21.xml.h:27
-#, fuzzy
-msgid "White"
-msgstr "Перемещение"
-
-#: hacks/config/cubenetic.xml.h:2
-msgid "Cubenetic"
+#: ../hacks/config/cityflow.xml.h:1
+msgid "Cityflow"
 msgstr ""
 
-#: hacks/config/cubenetic.xml.h:3
-msgid "Display Solid Colors"
-msgstr ""
+#: ../hacks/config/cityflow.xml.h:8
+msgid "Skew"
+msgstr "Скос"
 
-#: hacks/config/cubenetic.xml.h:4
-msgid "Display Surface Patterns"
-msgstr ""
+#: ../hacks/config/cityflow.xml.h:10 ../hacks/config/gflux.xml.h:6
+#: ../hacks/config/interference.xml.h:6
+msgid "Wave speed"
+msgstr "Скорость волны"
 
-#: hacks/config/cubenetic.xml.h:5
-msgid "Display Wireframe"
-msgstr ""
+#: ../hacks/config/cityflow.xml.h:13
+msgid "Wave overlap"
+msgstr "Разброс волны"
 
-#: hacks/config/cubenetic.xml.h:6 hacks/config/glblur.xml.h:3
-#: hacks/config/glknots.xml.h:2 hacks/config/gltext.xml.h:3
-#: hacks/config/lavalite.xml.h:7 hacks/config/menger.xml.h:1
-#: hacks/config/molecule.xml.h:4 hacks/config/spheremonics.xml.h:1
-#: hacks/config/tangram.xml.h:1
-msgid "Don't Rotate"
-msgstr ""
+#: ../hacks/config/cityflow.xml.h:15
+msgid "Wave complexity"
+msgstr "Сложность волны"
 
-#: hacks/config/cubenetic.xml.h:7
+#: ../hacks/config/cityflow.xml.h:18
 msgid ""
-"Draws a pulsating set of overlapping boxes with ever-chaning blobby patterns "
-"undulating across their surfaces. It's sort of a cubist Lavalite. Written by "
-"Jamie Zawinski."
-msgstr ""
-
-#: hacks/config/cubenetic.xml.h:14 hacks/config/glblur.xml.h:6
-#: hacks/config/glknots.xml.h:8 hacks/config/gltext.xml.h:7
-#: hacks/config/lavalite.xml.h:19 hacks/config/menger.xml.h:7
-#: hacks/config/molecule.xml.h:15 hacks/config/spheremonics.xml.h:10
-msgid "Rotate around X and Y axes"
+"Waves move across a sea of boxes. The city swells. The walls are closing in. "
+"Written by Jamie Zawinski; 2014."
 msgstr ""
 
-#: hacks/config/cubenetic.xml.h:15 hacks/config/glblur.xml.h:7
-#: hacks/config/glknots.xml.h:9 hacks/config/gltext.xml.h:8
-#: hacks/config/lavalite.xml.h:20 hacks/config/menger.xml.h:8
-#: hacks/config/molecule.xml.h:16 hacks/config/spheremonics.xml.h:11
-msgid "Rotate around X and Z axes"
+#: ../hacks/config/cloudlife.xml.h:1
+msgid "CloudLife"
 msgstr ""
 
-#: hacks/config/cubenetic.xml.h:16 hacks/config/glblur.xml.h:8
-#: hacks/config/glknots.xml.h:10 hacks/config/gltext.xml.h:9
-#: hacks/config/lavalite.xml.h:21 hacks/config/menger.xml.h:9
-#: hacks/config/molecule.xml.h:17 hacks/config/spheremonics.xml.h:12
-msgid "Rotate around X axis"
-msgstr ""
+#: ../hacks/config/cloudlife.xml.h:5
+msgid "Young"
+msgstr "Молодой"
 
-#: hacks/config/cubenetic.xml.h:17 hacks/config/glblur.xml.h:9
-#: hacks/config/glknots.xml.h:11 hacks/config/gltext.xml.h:10
-#: hacks/config/lavalite.xml.h:22 hacks/config/menger.xml.h:10
-#: hacks/config/molecule.xml.h:18 hacks/config/spheremonics.xml.h:13
-msgid "Rotate around Y and Z axes"
-msgstr ""
+#: ../hacks/config/cloudlife.xml.h:6
+msgid "Max age"
+msgstr "Максимальный возраст"
 
-#: hacks/config/cubenetic.xml.h:18 hacks/config/glblur.xml.h:10
-#: hacks/config/glknots.xml.h:12 hacks/config/gltext.xml.h:11
-#: hacks/config/lavalite.xml.h:23 hacks/config/menger.xml.h:11
-#: hacks/config/molecule.xml.h:19 hacks/config/spheremonics.xml.h:14
-msgid "Rotate around Y axis"
-msgstr ""
+#: ../hacks/config/cloudlife.xml.h:7
+msgid "Old"
+msgstr "Старый"
 
-#: hacks/config/cubenetic.xml.h:19 hacks/config/glblur.xml.h:11
-#: hacks/config/glknots.xml.h:13 hacks/config/gltext.xml.h:12
-#: hacks/config/lavalite.xml.h:24 hacks/config/menger.xml.h:12
-#: hacks/config/molecule.xml.h:20 hacks/config/spheremonics.xml.h:15
-msgid "Rotate around Z axis"
-msgstr ""
+#: ../hacks/config/cloudlife.xml.h:8
+msgid "Initial density"
+msgstr "Начальная плотность"
 
-#: hacks/config/cubenetic.xml.h:20 hacks/config/glblur.xml.h:12
-#: hacks/config/glknots.xml.h:14 hacks/config/gltext.xml.h:13
-#: hacks/config/lavalite.xml.h:25 hacks/config/menger.xml.h:13
-#: hacks/config/molecule.xml.h:21 hacks/config/spheremonics.xml.h:16
-msgid "Rotate around all three axes"
-msgstr ""
+#: ../hacks/config/cloudlife.xml.h:10 ../hacks/config/demon.xml.h:14
+#: ../hacks/config/petri.xml.h:26 ../hacks/config/slidescreen.xml.h:15
+msgid "Cell size"
+msgstr "Размер ячейки"
 
-#: hacks/config/cubenetic.xml.h:25
-msgid "Surface Pattern Complexity"
+#: ../hacks/config/cloudlife.xml.h:14
+#, no-c-format
+msgid ""
+"Generates cloud-like formations based on a variant of Conway's Life. The "
+"difference is that cells have a maximum age, after which they count as 3 for "
+"populating the next generation. This makes long-lived formations explode "
+"instead of just sitting there. https://en.wikipedia.org/wiki/Conway"
+"%27s_Game_of_Life Written by Don Marti; 2003."
 msgstr ""
 
-#: hacks/config/cubenetic.xml.h:26
-msgid "Surface Pattern Overlap"
+#: ../hacks/config/companioncube.xml.h:1
+msgid "CompanionCube"
 msgstr ""
 
-#: hacks/config/cubenetic.xml.h:27
-msgid "Surface Pattern Speed"
+#: ../hacks/config/companioncube.xml.h:6 ../hacks/config/distort.xml.h:17
+msgid "Bounce"
+msgstr "Прыжок"
+
+#: ../hacks/config/companioncube.xml.h:8 ../hacks/config/deluxe.xml.h:8
+#: ../hacks/config/geodesic.xml.h:17 ../hacks/config/gflux.xml.h:11
+#: ../hacks/config/glcells.xml.h:28 ../hacks/config/glhanoi.xml.h:9
+#: ../hacks/config/glsnake.xml.h:5 ../hacks/config/hypnowheel.xml.h:9
+#: ../hacks/config/lavalite.xml.h:8 ../hacks/config/lisa.xml.h:13
+#: ../hacks/config/lissie.xml.h:11 ../hacks/config/projectiveplane.xml.h:32
+#: ../hacks/config/raverhoop.xml.h:5 ../hacks/config/skytentacles.xml.h:2
+#: ../hacks/config/strange.xml.h:9
+msgid "1"
 msgstr ""
 
-#: hacks/config/cubenetic.xml.h:28 hacks/config/cubestorm.xml.h:13
-#: hacks/config/dangerball.xml.h:10 hacks/config/engine.xml.h:20
-#: hacks/config/glblur.xml.h:18 hacks/config/glforestfire.xml.h:19
-#: hacks/config/glknots.xml.h:22 hacks/config/glplanet.xml.h:14
-#: hacks/config/gltext.xml.h:20 hacks/config/lavalite.xml.h:31
-#: hacks/config/menger.xml.h:20 hacks/config/molecule.xml.h:26
-#: hacks/config/polyhedra.xml.h:165 hacks/config/spheremonics.xml.h:25
-#: hacks/config/wander.xml.h:15
+#: ../hacks/config/companioncube.xml.h:9
+msgid "Number of cubes"
+msgstr "Количество кубов"
+
+#. #### -no-optimize
+#: ../hacks/config/companioncube.xml.h:12 ../hacks/config/cube21.xml.h:20
+#: ../hacks/config/cubenetic.xml.h:8 ../hacks/config/cubestack.xml.h:14
+#: ../hacks/config/cubestorm.xml.h:14 ../hacks/config/cubetwist.xml.h:15
+#: ../hacks/config/dangerball.xml.h:11 ../hacks/config/discoball.xml.h:11
+#: ../hacks/config/dymaxionmap.xml.h:10 ../hacks/config/energystream.xml.h:5
+#: ../hacks/config/engine.xml.h:17 ../hacks/config/gears.xml.h:11
+#: ../hacks/config/geodesic.xml.h:8 ../hacks/config/geodesicgears.xml.h:11
+#: ../hacks/config/glblur.xml.h:8 ../hacks/config/glforestfire.xml.h:11
+#: ../hacks/config/glknots.xml.h:22 ../hacks/config/glplanet.xml.h:8
+#: ../hacks/config/gltext.xml.h:9 ../hacks/config/hexstrut.xml.h:14
+#: ../hacks/config/hilbert.xml.h:18 ../hacks/config/hypnowheel.xml.h:6
+#: ../hacks/config/kaleidocycle.xml.h:19 ../hacks/config/lavalite.xml.h:14
+#: ../hacks/config/menger.xml.h:10 ../hacks/config/moebiusgears.xml.h:10
+#: ../hacks/config/molecule.xml.h:16 ../hacks/config/polyhedra.xml.h:165
+#: ../hacks/config/raverhoop.xml.h:18 ../hacks/config/rubikblocks.xml.h:14
+#: ../hacks/config/spheremonics.xml.h:9 ../hacks/config/splitflap.xml.h:23
+#: ../hacks/config/splodesic.xml.h:9 ../hacks/config/surfaces.xml.h:25
+#: ../hacks/config/tronbit.xml.h:9 ../hacks/config/unicrud.xml.h:8
+#: ../hacks/config/wander.xml.h:1
 msgid "Wander"
 msgstr "Перемещение"
 
-#: hacks/config/cubestorm.xml.h:2
-msgid "CubeStorm"
-msgstr ""
-
-#: hacks/config/cubestorm.xml.h:3
+#: ../hacks/config/companioncube.xml.h:16
+#, no-c-format
 msgid ""
-"Draws a series of rotating 3D boxes that intersect each other and eventually "
-"fill space. Written by Jamie Zawinski."
+"The symptoms most commonly produced by Enrichment Center testing are "
+"superstition, perceiving inanimate objects as alive, and hallucinations. The "
+"Enrichment Center reminds you that the weighted companion cube will never "
+"threaten to stab you and, in fact, cannot speak. In the event that the "
+"Weighted Companion Cube does speak, the Enrichment Center urges you to "
+"disregard its advice. https://en.wikipedia.org/wiki/Portal_%28video_game%29 "
+"Written by Jamie Zawinski; 2011."
 msgstr ""
 
-#: hacks/config/cubestorm.xml.h:6
-#, fuzzy
-msgid "Number of Cubes"
-msgstr "Количество цветов"
-
-#: hacks/config/cubestorm.xml.h:10
-msgid "Strut Thickness"
+#: ../hacks/config/compass.xml.h:1
+msgid "Compass"
 msgstr ""
 
-#: hacks/config/cynosure.xml.h:1
+#: ../hacks/config/compass.xml.h:6
 msgid ""
-"A hack similar to `greynetic', but less frenetic. The first implementation "
-"was by Stephen Linhart; then Ozymandias G. Desiderata wrote a Java applet "
-"clone. That clone was discovered by Jamie Zawinski, and ported to C for "
-"inclusion here."
+"A compass, with all elements spinning about randomly, for that \"lost and "
+"nauseous\" feeling. Written by Jamie Zawinski; 1999."
 msgstr ""
 
-#: hacks/config/cynosure.xml.h:2
-msgid "Cynosure"
+#: ../hacks/config/coral.xml.h:1
+msgid "Coral"
 msgstr ""
 
-#: hacks/config/dangerball.xml.h:1
-msgid "DangerBall"
-msgstr ""
+#: ../hacks/config/coral.xml.h:5 ../hacks/config/deco.xml.h:2
+#: ../hacks/config/epicycle.xml.h:8 ../hacks/config/glslideshow.xml.h:13
+#: ../hacks/config/helix.xml.h:5 ../hacks/config/moire.xml.h:2
+#: ../hacks/config/pedal.xml.h:2 ../hacks/config/polyhedra.xml.h:8
+#: ../hacks/config/rorschach.xml.h:8 ../hacks/config/starfish.xml.h:8
+#: ../hacks/config/xspirograph.xml.h:5
+msgid "1 second"
+msgstr "1 секунда"
+
+#: ../hacks/config/coral.xml.h:8 ../hacks/config/fireworkx.xml.h:7
+#: ../hacks/config/gflux.xml.h:8 ../hacks/config/glblur.xml.h:5
+#: ../hacks/config/glmatrix.xml.h:5 ../hacks/config/imsmap.xml.h:8
+#: ../hacks/config/lavalite.xml.h:5 ../hacks/config/pyro.xml.h:5
+#: ../hacks/config/qix.xml.h:8 ../hacks/config/raverhoop.xml.h:8
+#: ../hacks/config/squiral.xml.h:10 ../hacks/config/xmatrix.xml.h:18
+msgid "Sparse"
+msgstr "Редко"
+
+#: ../hacks/config/coral.xml.h:10 ../hacks/config/fireworkx.xml.h:5
+#: ../hacks/config/gflux.xml.h:10 ../hacks/config/glblur.xml.h:7
+#: ../hacks/config/glmatrix.xml.h:7 ../hacks/config/imsmap.xml.h:10
+#: ../hacks/config/lavalite.xml.h:7 ../hacks/config/pyro.xml.h:7
+#: ../hacks/config/qix.xml.h:10 ../hacks/config/raverhoop.xml.h:10
+#: ../hacks/config/squiral.xml.h:12
+msgid "Dense"
+msgstr "Плотно"
 
-#: hacks/config/dangerball.xml.h:2
+#: ../hacks/config/coral.xml.h:12 ../hacks/config/glcells.xml.h:29
+#: ../hacks/config/squiral.xml.h:6
+msgid "Seeds"
+msgstr "Зерна"
+
+#: ../hacks/config/coral.xml.h:15
 msgid ""
-"Draws a ball that periodically extrudes many random spikes. Ouch! Written by "
-"Jamie Zawinski."
+"Simulates coral growth, albeit somewhat slowly. Written by Frederick Roeber; "
+"1997."
 msgstr ""
 
-#: hacks/config/dangerball.xml.h:7
-msgid "Spike Count"
+#: ../hacks/config/crackberg.xml.h:1
+msgid "Crackberg"
 msgstr ""
 
-#: hacks/config/dangerball.xml.h:8
-msgid "Spike Growth"
-msgstr ""
+#: ../hacks/config/crackberg.xml.h:5
+msgid "Mouse hole"
+msgstr "Мышиная нора"
 
-#: hacks/config/decayscreen.xml.h:1
-msgid "DecayScreen"
-msgstr ""
+#: ../hacks/config/crackberg.xml.h:6
+msgid "Visibility"
+msgstr "Видимость"
 
-#: hacks/config/decayscreen.xml.h:3
-msgid "Fuzzy Melt"
-msgstr ""
+#: ../hacks/config/crackberg.xml.h:7
+msgid "Eagle nest"
+msgstr "Орлиное гнездо"
 
-#: hacks/config/decayscreen.xml.h:4
-msgid "Melt Away From Center"
-msgstr ""
+#: ../hacks/config/crackberg.xml.h:9
+msgid "Subdivisions"
+msgstr "Разделения"
 
-#: hacks/config/decayscreen.xml.h:5
-msgid "Melt Down"
-msgstr ""
+#: ../hacks/config/crackberg.xml.h:10
+msgid "Hurt me"
+msgstr "Сделай мне больно"
 
-#: hacks/config/decayscreen.xml.h:6
-msgid "Melt Down, Left"
-msgstr ""
+#: ../hacks/config/crackberg.xml.h:11 ../hacks/config/cubetwist.xml.h:14
+msgid "Flat shading"
+msgstr "Плоское затенение"
 
-#: hacks/config/decayscreen.xml.h:7
-msgid "Melt Down, Right"
-msgstr ""
+#: ../hacks/config/crackberg.xml.h:13 ../hacks/config/flurry.xml.h:6
+msgid "Water"
+msgstr "Вода"
 
-#: hacks/config/decayscreen.xml.h:8
-msgid "Melt Left"
-msgstr ""
+#: ../hacks/config/crackberg.xml.h:14
+msgid "Confused"
+msgstr "Возмущение"
 
-#: hacks/config/decayscreen.xml.h:9
-msgid "Melt Right"
-msgstr ""
+#: ../hacks/config/crackberg.xml.h:15
+msgid "Immediate"
+msgstr "Немедленный"
 
-#: hacks/config/decayscreen.xml.h:10
-msgid "Melt Towards Center"
-msgstr ""
+#: ../hacks/config/crackberg.xml.h:16 ../hacks/config/glslideshow.xml.h:18
+msgid "Letterbox"
+msgstr "Почтовый ящик"
 
-#: hacks/config/decayscreen.xml.h:11
-msgid "Melt Up"
-msgstr ""
+#: ../hacks/config/crackberg.xml.h:19 ../hacks/config/imsmap.xml.h:14
+#: ../hacks/config/klein.xml.h:18 ../hacks/config/projectiveplane.xml.h:10
+#: ../hacks/config/romanboy.xml.h:22
+msgid "Random coloration"
+msgstr "Случайное окрашивание"
 
-#: hacks/config/decayscreen.xml.h:12
-msgid "Melt Up, Left"
-msgstr ""
+#: ../hacks/config/crackberg.xml.h:20
+msgid "Earthy coloration"
+msgstr "Окрашивание (земля)"
 
-#: hacks/config/decayscreen.xml.h:13
-msgid "Melt Up, Right"
-msgstr ""
+#: ../hacks/config/crackberg.xml.h:21
+msgid "Icy coloration"
+msgstr "Окрашивание (лед)"
 
-#: hacks/config/decayscreen.xml.h:14
-msgid "Melty Melt"
-msgstr ""
+#: ../hacks/config/crackberg.xml.h:22
+msgid "Swampy coloration"
+msgstr "Окрашивание (болото)"
 
-#: hacks/config/decayscreen.xml.h:15
-msgid "Random Melt Style"
-msgstr ""
+#: ../hacks/config/crackberg.xml.h:23
+msgid "Vomitous coloration"
+msgstr "Окрашивание (извержение)"
 
-#: hacks/config/decayscreen.xml.h:16
-msgid "Shuffle Melt"
+#: ../hacks/config/crackberg.xml.h:24
+msgid ""
+"Flies through height maps, optionally animating the creation and destruction "
+"of generated tiles; tiles `grow' into place. Written by Matus Telgarsky; "
+"2005."
 msgstr ""
 
-#: hacks/config/decayscreen.xml.h:19
-msgid "Stretchy Melt"
+#: ../hacks/config/critical.xml.h:1
+msgid "Critical"
 msgstr ""
 
-#: hacks/config/decayscreen.xml.h:20
+#: ../hacks/config/critical.xml.h:9
 msgid ""
-"This takes an image and makes it melt. You've no doubt seen this effect "
-"before, but no screensaver would really be complete without it. It works "
-"best if there's something colorful visible. Warning, if the effect continues "
-"after the screen saver is off, seek medical attention. Written by David "
-"Wald, Vivek Khera, Jamie Zawinski, and Vince Levey."
+"This screen saver was removed from the XScreenSaver distribution as of "
+"version 5.08. Draws a system of self-organizing lines. It starts out as "
+"random squiggles, but after a few iterations, order begins to appear. "
+"Written by Martin Pool; 1999."
 msgstr ""
 
-#: hacks/config/deco.xml.h:3
-msgid "Deco"
+#: ../hacks/config/crystal.xml.h:1
+msgid "Crystal"
 msgstr ""
 
-#: hacks/config/deco.xml.h:6 hacks/config/menger.xml.h:5
-#: hacks/config/sierpinski3d.xml.h:4
-msgid "Max Depth"
-msgstr ""
+#. #### -shift (color cycling)
+#: ../hacks/config/crystal.xml.h:9
+msgid "Number of crystals"
+msgstr "Количество кристаллов"
 
-#: hacks/config/deco.xml.h:7
-msgid "Min Size"
-msgstr ""
+#: ../hacks/config/crystal.xml.h:10
+msgid "Horizontal symmetries"
+msgstr "Горизонтальные симметрии"
 
-#: hacks/config/deco.xml.h:9
-msgid ""
-"This one subdivides and colors rectangles randomly. It looks kind of like "
-"Brady-Bunch-era rec-room wall paneling. (Raven says: ``this screensaver is "
-"ugly enough to peel paint.'') Written by Jamie Zawinski, inspired by Java "
-"code by Michael Bayne."
-msgstr ""
+#: ../hacks/config/crystal.xml.h:11
+msgid "Vertical symmetries"
+msgstr "Вертикальные симметрии"
 
-#: hacks/config/deco.xml.h:11 hacks/config/rd-bomb.xml.h:23
-#: hacks/config/whirlygig.xml.h:20 hacks/config/xearth.xml.h:33
-#: hacks/config/zoom.xml.h:10
-msgid "x"
-msgstr ""
+#: ../hacks/config/crystal.xml.h:12 ../hacks/config/spheremonics.xml.h:19
+msgid "Draw grid"
+msgstr "Прорисовывать сетку"
 
-#: hacks/config/deluxe.xml.h:2
-msgid "Deluxe"
-msgstr ""
+#: ../hacks/config/crystal.xml.h:13
+msgid "Draw cell"
+msgstr "Прорисовывать ячейку"
 
-#: hacks/config/deluxe.xml.h:12
+#: ../hacks/config/crystal.xml.h:14
+msgid "Center on screen"
+msgstr "В центре экрана"
+
+#: ../hacks/config/crystal.xml.h:16
 msgid ""
-"This draws a pulsing sequence of stars, circles, and lines. It would look "
-"better if it was faster, but as far as I can tell, there is no way to make "
-"this be both: fast, and flicker-free. Yet another reason X sucks. Written by "
-"Jamie Zawinski."
+"Moving polygons, similar to a kaleidoscope. See also the \"Kaleidescope\" "
+"and \"GLeidescope\" screen savers. https://en.wikipedia.org/wiki/"
+"Kaleidoscope Written by Jouk Jansen; 1998."
 msgstr ""
 
-#: hacks/config/deluxe.xml.h:13
-msgid "Transparency"
+#: ../hacks/config/cube21.xml.h:1
+msgid "Cube21"
 msgstr ""
 
-#: hacks/config/demon.xml.h:1
-msgid ""
-"A cellular automaton that starts with a random field, and organizes it into "
-"stripes and spirals. Written by David Bagley."
-msgstr ""
+#: ../hacks/config/cube21.xml.h:6 ../hacks/config/rubikblocks.xml.h:6
+msgid "Cube size"
+msgstr "Размер куба"
 
-#: hacks/config/demon.xml.h:3
-msgid "Demon"
-msgstr ""
+#: ../hacks/config/cube21.xml.h:9 ../hacks/config/quasicrystal.xml.h:11
+#: ../hacks/config/rocks.xml.h:11 ../hacks/config/rubik.xml.h:7
+#: ../hacks/config/rubikblocks.xml.h:9 ../hacks/config/topblock.xml.h:16
+msgid "Rotation"
+msgstr "Вращение"
 
-#: hacks/config/demon.xml.h:11
-msgid "States"
-msgstr ""
+#: ../hacks/config/cube21.xml.h:11 ../hacks/config/rubikblocks.xml.h:11
+msgid "Start as cube"
+msgstr "Начинать с куба"
 
-#: hacks/config/discrete.xml.h:1
-msgid "Discrete"
-msgstr ""
+#: ../hacks/config/cube21.xml.h:12 ../hacks/config/rubikblocks.xml.h:12
+msgid "Start as random shape"
+msgstr "Начинать со случайной фигуры"
 
-#: hacks/config/discrete.xml.h:5
-msgid ""
-"More ``discrete map'' systems, including new variants of Hopalong and Julia, "
-"and a few others. Written by Tim Auckland."
-msgstr ""
+#: ../hacks/config/cube21.xml.h:14
+msgid "Random color"
+msgstr "Случайный цвет"
 
-#: hacks/config/distort.xml.h:1
-msgid "Black Hole"
-msgstr ""
+#: ../hacks/config/cube21.xml.h:15
+msgid "Silver edition"
+msgstr "Серебряная версия"
 
-#: hacks/config/distort.xml.h:2
-msgid "Bounce"
-msgstr ""
+#: ../hacks/config/cube21.xml.h:16
+msgid "Two random colors"
+msgstr "Два случайных цвета"
 
-#: hacks/config/distort.xml.h:3
-msgid "Distort"
-msgstr ""
+#: ../hacks/config/cube21.xml.h:17
+msgid "Classic edition"
+msgstr "Классическая версия"
 
-#: hacks/config/distort.xml.h:6
-msgid "Lens Count"
-msgstr "ЧиÑ\81ло Ð»Ð¸Ð½Ð·"
+#: ../hacks/config/cube21.xml.h:18
+msgid "Six random colors"
+msgstr "ШеÑ\81Ñ\82Ñ\8c Ñ\81лÑ\83Ñ\87айнÑ\8bÑ\85 Ñ\86веÑ\82ов"
 
-#: hacks/config/distort.xml.h:7
-msgid "Lens Size"
-msgstr "РазмеÑ\80 Ð»Ð¸Ð½Ð·ы"
+#: ../hacks/config/cube21.xml.h:24 ../hacks/config/rubikblocks.xml.h:18
+msgid "Outlines"
+msgstr "Ð\9aонÑ\82Ñ\83Ñ\80ы"
 
-#: hacks/config/distort.xml.h:8
-msgid "Magnify"
+#: ../hacks/config/cube21.xml.h:28
+#, no-c-format
+msgid ""
+"The \"Cube 21\" Rubik-like puzzle, also known as \"Square-1\". The rotations "
+"are chosen randomly. See also the \"Rubik\", \"RubikBlocks\" and \"GLSnake\" "
+"screen savers. https://en.wikipedia.org/wiki/Square_One_%28puzzle%29 Written "
+"by Vasek Potocek; 2005."
 msgstr ""
 
-#: hacks/config/distort.xml.h:10
-msgid "Reflect"
+#: ../hacks/config/cubenetic.xml.h:1
+msgid "Cubenetic"
 msgstr ""
 
-#: hacks/config/distort.xml.h:14
-msgid "Swamp Thing"
-msgstr ""
+#: ../hacks/config/cubenetic.xml.h:9 ../hacks/config/glblur.xml.h:9
+#: ../hacks/config/glknots.xml.h:8 ../hacks/config/gltext.xml.h:10
+#: ../hacks/config/kaleidocycle.xml.h:11 ../hacks/config/menger.xml.h:11
+#: ../hacks/config/molecule.xml.h:17 ../hacks/config/spheremonics.xml.h:10
+#: ../hacks/config/splitflap.xml.h:15
+msgid "Don't rotate"
+msgstr "Не вращать"
 
-#: hacks/config/distort.xml.h:15
-msgid ""
-"This hack grabs an image of the screen, and then lets a transparent lens "
-"wander around the screen, magnifying whatever is underneath. Written by "
-"Jonas Munsin."
-msgstr ""
+#: ../hacks/config/cubenetic.xml.h:10 ../hacks/config/glblur.xml.h:10
+#: ../hacks/config/glknots.xml.h:9 ../hacks/config/gltext.xml.h:11
+#: ../hacks/config/kaleidocycle.xml.h:12 ../hacks/config/lavalite.xml.h:23
+#: ../hacks/config/menger.xml.h:12 ../hacks/config/molecule.xml.h:18
+#: ../hacks/config/spheremonics.xml.h:11 ../hacks/config/splitflap.xml.h:16
+msgid "Rotate around X axis"
+msgstr "Вращать вокруг оси X"
 
-#: hacks/config/distort.xml.h:16 hacks/config/moire.xml.h:12
-#: hacks/config/rd-bomb.xml.h:21 hacks/config/ripples.xml.h:16
-#: hacks/config/rotzoomer.xml.h:10 hacks/config/swirl.xml.h:10
-#: hacks/config/twang.xml.h:15 hacks/config/xflame.xml.h:7
-msgid "Use Shared Memory"
-msgstr "Использовать разделяемую память"
+#: ../hacks/config/cubenetic.xml.h:11 ../hacks/config/glblur.xml.h:11
+#: ../hacks/config/glknots.xml.h:10 ../hacks/config/gltext.xml.h:12
+#: ../hacks/config/kaleidocycle.xml.h:13 ../hacks/config/lavalite.xml.h:24
+#: ../hacks/config/menger.xml.h:13 ../hacks/config/molecule.xml.h:19
+#: ../hacks/config/spheremonics.xml.h:12 ../hacks/config/splitflap.xml.h:17
+msgid "Rotate around Y axis"
+msgstr "Вращать вокруг оси Y"
 
-#: hacks/config/distort.xml.h:17
-msgid "Vortex"
-msgstr ""
+#: ../hacks/config/cubenetic.xml.h:12 ../hacks/config/glblur.xml.h:12
+#: ../hacks/config/glknots.xml.h:11 ../hacks/config/gltext.xml.h:13
+#: ../hacks/config/kaleidocycle.xml.h:14 ../hacks/config/lavalite.xml.h:25
+#: ../hacks/config/menger.xml.h:14 ../hacks/config/molecule.xml.h:20
+#: ../hacks/config/spheremonics.xml.h:13 ../hacks/config/splitflap.xml.h:18
+msgid "Rotate around Z axis"
+msgstr "Вращать вокруг оси Z"
 
-#: hacks/config/drift.xml.h:1
-msgid "Drift"
-msgstr ""
+#: ../hacks/config/cubenetic.xml.h:13 ../hacks/config/glblur.xml.h:13
+#: ../hacks/config/glknots.xml.h:12 ../hacks/config/gltext.xml.h:14
+#: ../hacks/config/kaleidocycle.xml.h:15 ../hacks/config/lavalite.xml.h:26
+#: ../hacks/config/menger.xml.h:15 ../hacks/config/molecule.xml.h:21
+#: ../hacks/config/spheremonics.xml.h:14 ../hacks/config/splitflap.xml.h:19
+msgid "Rotate around X and Y axes"
+msgstr "Вращать вокруг осей X и Y"
 
-#: hacks/config/drift.xml.h:4
-msgid "Fractal Growth"
-msgstr ""
+#: ../hacks/config/cubenetic.xml.h:14 ../hacks/config/glblur.xml.h:14
+#: ../hacks/config/glknots.xml.h:13 ../hacks/config/gltext.xml.h:15
+#: ../hacks/config/kaleidocycle.xml.h:16 ../hacks/config/lavalite.xml.h:27
+#: ../hacks/config/menger.xml.h:16 ../hacks/config/molecule.xml.h:22
+#: ../hacks/config/spheremonics.xml.h:15 ../hacks/config/splitflap.xml.h:20
+msgid "Rotate around X and Z axes"
+msgstr "Вращать вокруг осей X и Z"
 
-#: hacks/config/drift.xml.h:5
-msgid "High Dimensional Sphere"
-msgstr ""
+#: ../hacks/config/cubenetic.xml.h:15 ../hacks/config/glblur.xml.h:15
+#: ../hacks/config/glknots.xml.h:14 ../hacks/config/gltext.xml.h:16
+#: ../hacks/config/kaleidocycle.xml.h:17 ../hacks/config/lavalite.xml.h:28
+#: ../hacks/config/menger.xml.h:17 ../hacks/config/molecule.xml.h:23
+#: ../hacks/config/spheremonics.xml.h:16 ../hacks/config/splitflap.xml.h:21
+msgid "Rotate around Y and Z axes"
+msgstr "Вращать вокруг осей Y и Z"
 
-#: hacks/config/drift.xml.h:6
-msgid ""
-"How could one possibly describe this except as ``drifting recursive fractal "
-"cosmic flames?'' Another fine hack from the Scott Draves collection of fine "
-"hacks."
-msgstr ""
+#: ../hacks/config/cubenetic.xml.h:16 ../hacks/config/glblur.xml.h:16
+#: ../hacks/config/glknots.xml.h:15 ../hacks/config/gltext.xml.h:17
+#: ../hacks/config/kaleidocycle.xml.h:18 ../hacks/config/lavalite.xml.h:29
+#: ../hacks/config/menger.xml.h:18 ../hacks/config/molecule.xml.h:24
+#: ../hacks/config/spheremonics.xml.h:17 ../hacks/config/splitflap.xml.h:22
+msgid "Rotate around all three axes"
+msgstr "Вращать вокруг всех трех осей"
 
-#: hacks/config/drift.xml.h:7
-msgid "Lissojous Figures"
-msgstr ""
+#: ../hacks/config/cubenetic.xml.h:18
+msgid "Surface pattern speed"
+msgstr "Скорость паттерна поверхности"
 
-#: hacks/config/electricsheep.xml.h:1
-msgid "1 Gbyte cache"
-msgstr ""
+#: ../hacks/config/cubenetic.xml.h:21
+msgid "Surface pattern overlap"
+msgstr "Разброс паттерна поверхности"
 
-#: hacks/config/electricsheep.xml.h:2
-msgid "100 Mbyte cache"
-msgstr ""
+#: ../hacks/config/cubenetic.xml.h:23
+msgid "Surface pattern complexity"
+msgstr "Сложность паттерна поверхности"
 
-#: hacks/config/electricsheep.xml.h:3
-msgid "3 Gbyte cache"
+#: ../hacks/config/cubenetic.xml.h:27
+msgid ""
+"A cubist Lavalite, sort of. A pulsating set of overlapping boxes with ever-"
+"changing blobby patterns undulating across their surfaces. Written by Jamie "
+"Zawinski; 2002."
 msgstr ""
 
-#: hacks/config/electricsheep.xml.h:4
-msgid "300 Mbyte cache"
+#: ../hacks/config/cubestack.xml.h:1
+msgid "CubeStack"
 msgstr ""
 
-#: hacks/config/electricsheep.xml.h:5
-msgid "ElectricSheep"
-msgstr ""
+#: ../hacks/config/cubestack.xml.h:11 ../hacks/config/hypertorus.xml.h:8
+#: ../hacks/config/qix.xml.h:21 ../hacks/config/webcollage.xml.h:8
+msgid "Transparent"
+msgstr "Прозрачный"
+
+#: ../hacks/config/cubestack.xml.h:12
+msgid "Opacity"
+msgstr "ПРозрачность"
+
+#: ../hacks/config/cubestack.xml.h:13 ../hacks/config/mirrorblob.xml.h:19
+#: ../hacks/config/webcollage.xml.h:10
+msgid "Opaque"
+msgstr "Непрозрачный"
 
-#: hacks/config/electricsheep.xml.h:6
+#: ../hacks/config/cubestack.xml.h:17
 msgid ""
-"ElectricSheep is an xscreensaver module that displays mpeg video of an "
-"animated fractal flame. In the background, it contributes render cycles to "
-"the next animation. Periodically it uploades completed frames to the server, "
-"where they are compressed for distribution to all clients. This program is "
-"recommended only if you have a high bandwidth, always-on connection to the "
-"Internet. By Scott Draves. You can find it at &lt;http://www.electricsheep."
-"org/&gt;."
+"An endless stack of unfolding, translucent cubes. Written by Jamie Zawinski; "
+"2016."
 msgstr ""
 
-#: hacks/config/electricsheep.xml.h:8
-msgid "Nickname"
+#: ../hacks/config/cubestorm.xml.h:1
+msgid "CubeStorm"
 msgstr ""
 
-#: hacks/config/electricsheep.xml.h:9
-#, fuzzy
-msgid "No Animation"
-msgstr "Скорость анимации"
+#: ../hacks/config/cubestorm.xml.h:9
+msgid "Cubes"
+msgstr "Кубы"
 
-#: hacks/config/electricsheep.xml.h:10
-msgid "No Network"
-msgstr ""
+#: ../hacks/config/cubestorm.xml.h:12
+msgid "Struts"
+msgstr "Распорки"
 
-#: hacks/config/electricsheep.xml.h:11
-msgid "Repititions of each Sheep"
+#: ../hacks/config/cubestorm.xml.h:18
+msgid ""
+"Boxes change shape and intersect each other, filling space. Written by Jamie "
+"Zawinski; 2003."
 msgstr ""
 
-#: hacks/config/electricsheep.xml.h:12
-msgid "URL"
+#: ../hacks/config/cubetwist.xml.h:1
+msgid "CubeTwist"
 msgstr ""
 
-#: hacks/config/electricsheep.xml.h:13
-msgid "Unlimited"
-msgstr ""
+#: ../hacks/config/cubetwist.xml.h:11 ../hacks/config/glsnake.xml.h:8
+msgid "Tight"
+msgstr "Узкое"
 
-#: hacks/config/electricsheep.xml.h:14 hacks/config/gleidescope.xml.h:13
-#: hacks/config/hyperball.xml.h:16 hacks/config/hypercube.xml.h:16
-#: hacks/config/zoom.xml.h:8
-msgid "Zoom"
-msgstr ""
+#: ../hacks/config/cubetwist.xml.h:12 ../hacks/config/quasicrystal.xml.h:10
+msgid "Displacement"
+msgstr "Замещение"
+
+#: ../hacks/config/cubetwist.xml.h:13
+msgid "Wide"
+msgstr "Широкое"
 
-#: hacks/config/endgame.xml.h:1
+#: ../hacks/config/cubetwist.xml.h:19
 msgid ""
-"Black slips out of three mating nets, but the fourth one holds him tight! A "
-"brilliant composition! Written by Blair Tennessy."
+"A series of nested cubes rotate and slide recursively. Written by Jamie "
+"Zawinski; 2016."
 msgstr ""
 
-#: hacks/config/endgame.xml.h:2
-msgid "Endgame"
+#: ../hacks/config/cubicgrid.xml.h:1
+msgid "CubicGrid"
 msgstr ""
 
-#: hacks/config/engine.xml.h:1
-msgid "Audi Quattro (5 cylinders)"
-msgstr ""
+#: ../hacks/config/cubicgrid.xml.h:8
+msgid "Close"
+msgstr "Близко"
 
-#: hacks/config/engine.xml.h:2
-msgid "BMW M3 (4 cylinders)"
-msgstr ""
+#: ../hacks/config/cubicgrid.xml.h:9
+msgid "Dot spacing"
+msgstr "Пространство между точками"
 
-#: hacks/config/engine.xml.h:3
-msgid "BMW M5 (6 cylinders)"
-msgstr ""
+#: ../hacks/config/cubicgrid.xml.h:11
+msgid "Big dots"
+msgstr "Большие точки"
 
-#: hacks/config/engine.xml.h:4
-msgid "Corvette Z06 (8 cylinders, V)"
+#: ../hacks/config/cubicgrid.xml.h:13
+msgid "A rotating lattice of colored points. Written by Vasek Potocek; 2007."
 msgstr ""
 
-#: hacks/config/engine.xml.h:5
-msgid "Dodge Viper (10 cylinders, V)"
+#: ../hacks/config/cwaves.xml.h:1
+msgid "CWaves"
 msgstr ""
 
-#: hacks/config/engine.xml.h:6
-#, fuzzy
-msgid ""
-"Draws a simple model of an engine that floats around the screen. Written by "
-"Ben Buxton and Ed Beroset."
-msgstr ""
-"Рисует простую модель двигателя, которая перемещается по экрану.  Авторы: "
-"Ben Buxton и Ed Beroset."
+#: ../hacks/config/cwaves.xml.h:5 ../hacks/config/flame.xml.h:11
+#: ../hacks/config/jigglypuff.xml.h:21 ../hacks/config/tessellimage.xml.h:12
+msgid "Complexity"
+msgstr "Сложность"
 
-#: hacks/config/engine.xml.h:7
-msgid "Engine"
-msgstr ""
+#: ../hacks/config/cwaves.xml.h:6
+msgid "Rough"
+msgstr "Жесткий"
 
-#: hacks/config/engine.xml.h:9
-msgid "Honda Insight (3 cylinders)"
-msgstr ""
+#: ../hacks/config/cwaves.xml.h:7
+msgid "Color transitions"
+msgstr "Переходы цветов"
 
-#: hacks/config/engine.xml.h:10
-msgid "Jaguar XKE (12 cylinders, V)"
-msgstr ""
+#: ../hacks/config/cwaves.xml.h:8 ../hacks/config/glknots.xml.h:18
+#: ../hacks/config/jigsaw.xml.h:13 ../hacks/config/lavalite.xml.h:13
+#: ../hacks/config/skytentacles.xml.h:24
+msgid "Smooth"
+msgstr "Мягкий"
 
-#: hacks/config/engine.xml.h:11
-msgid "Porsche 911 (6 cylinders, flat)"
+#: ../hacks/config/cwaves.xml.h:10
+msgid ""
+"A field of sinusoidal colors languidly scrolls. It's relaxing. Written by "
+"Jamie Zawinski; 2007."
 msgstr ""
 
-#: hacks/config/engine.xml.h:12
-msgid "Random Engine"
+#: ../hacks/config/cynosure.xml.h:1
+msgid "Cynosure"
 msgstr ""
 
-#: hacks/config/engine.xml.h:13
-msgid "Show Engine Name"
+#: ../hacks/config/cynosure.xml.h:12
+msgid ""
+"Random dropshadowed rectangles pop onto the screen in lockstep. Written by "
+"Ozymandias G. Desiderata, Jamie Zawinski, and Stephen Linhart; 1998."
 msgstr ""
 
-#: hacks/config/engine.xml.h:18
-msgid "Subaru XT (6 cylinders, V)"
+#: ../hacks/config/dangerball.xml.h:1
+msgid "DangerBall"
 msgstr ""
 
-#: hacks/config/engine.xml.h:19
-msgid "VW Beetle (4 cylinders, flat)"
-msgstr ""
+#: ../hacks/config/dangerball.xml.h:6
+msgid "Spike growth"
+msgstr "Рост шипов"
 
-#: hacks/config/epicycle.xml.h:1
-msgid "1 minute"
-msgstr ""
+#: ../hacks/config/dangerball.xml.h:9
+msgid "Number of spikes"
+msgstr "Количество шипов"
 
-#: hacks/config/epicycle.xml.h:2 hacks/config/polyhedra.xml.h:1
-msgid "1 second"
-msgstr ""
+#: ../hacks/config/dangerball.xml.h:10
+msgid "Ouch"
+msgstr "Ой!"
 
-#: hacks/config/epicycle.xml.h:4
-msgid "Epicycle"
+#: ../hacks/config/dangerball.xml.h:15
+msgid "A spiky ball. Ouch! Written by Jamie Zawinski; 2001."
 msgstr ""
 
-#: hacks/config/epicycle.xml.h:6
-msgid "Harmonics"
+#: ../hacks/config/decayscreen.xml.h:1
+msgid "DecayScreen"
 msgstr ""
 
-#: hacks/config/epicycle.xml.h:12
-msgid ""
-"This program draws the path traced out by a point on the edge of a circle. "
-"That circle rotates around a point on the rim of another circle, and so on, "
-"several times. These were the basis for the pre-heliocentric model of "
-"planetary motion. Written by James Youngman."
-msgstr ""
+#: ../hacks/config/decayscreen.xml.h:8
+msgid "Random melt style"
+msgstr "Случайный метод растворения"
 
-#: hacks/config/eruption.xml.h:1
-msgid "An exposive version of XFlame. By W.P. van Paassen."
-msgstr ""
+#: ../hacks/config/decayscreen.xml.h:9
+msgid "Shuffle melt"
+msgstr "Смешанное растворение"
 
-#: hacks/config/eruption.xml.h:2
-msgid "Cooling factor"
-msgstr ""
+#: ../hacks/config/decayscreen.xml.h:10
+msgid "Melt up"
+msgstr "Растворение вверх"
 
-#: hacks/config/eruption.xml.h:4
-#, fuzzy
-msgid "Eruption"
-msgstr "Описание"
+#: ../hacks/config/decayscreen.xml.h:11
+msgid "Melt down"
+msgstr "Растворение вниз"
 
-#: hacks/config/eruption.xml.h:7 hacks/config/fluidballs.xml.h:9
-#: hacks/config/qix.xml.h:9 hacks/config/speedmine.xml.h:4
-msgid "Gravity"
-msgstr ""
+#: ../hacks/config/decayscreen.xml.h:12
+msgid "Melt left"
+msgstr "Растворение влево"
 
-#: hacks/config/eruption.xml.h:8
-msgid "Heat"
-msgstr ""
+#: ../hacks/config/decayscreen.xml.h:13
+msgid "Melt right"
+msgstr "Растворение вправо"
 
-#: hacks/config/eruption.xml.h:9
-msgid "Inferno"
-msgstr ""
+#: ../hacks/config/decayscreen.xml.h:14
+msgid "Melt up, left"
+msgstr "Растворение вверх и влево"
 
-#: hacks/config/eruption.xml.h:10
-msgid "Little"
-msgstr ""
+#: ../hacks/config/decayscreen.xml.h:15
+msgid "Melt up, right"
+msgstr "Растворение вверх и вправо"
 
-#: hacks/config/eruption.xml.h:13
-msgid "Negative"
-msgstr ""
+#: ../hacks/config/decayscreen.xml.h:16
+msgid "Melt down, left"
+msgstr "Растворение вниз и влево"
 
-#: hacks/config/eruption.xml.h:15
-#, fuzzy
-msgid "Number of Particles"
-msgstr "Количество акул"
+#: ../hacks/config/decayscreen.xml.h:17
+msgid "Melt down, right"
+msgstr "Растворение вниз и вправо"
 
-#: hacks/config/eruption.xml.h:16
-msgid "Pleasant"
-msgstr ""
+#: ../hacks/config/decayscreen.xml.h:18
+msgid "Melt towards center"
+msgstr "Растворение к центру"
 
-#: hacks/config/eruption.xml.h:17
-msgid "Positive"
-msgstr ""
+#: ../hacks/config/decayscreen.xml.h:19
+msgid "Melt away from center"
+msgstr "Растворение от центра"
 
-#: hacks/config/euler2d.xml.h:2
-msgid "Euler2d"
-msgstr ""
+#: ../hacks/config/decayscreen.xml.h:20
+msgid "Melty melt"
+msgstr "Сильное растворение"
 
-#: hacks/config/euler2d.xml.h:10 hacks/config/whirlwindwarp.xml.h:5
-msgid "Particles"
-msgstr ""
+#: ../hacks/config/decayscreen.xml.h:21
+msgid "Stretchy melt"
+msgstr "Равномерное растворение"
 
-#: hacks/config/euler2d.xml.h:11
-msgid "Power"
-msgstr ""
+#: ../hacks/config/decayscreen.xml.h:22
+msgid "Fuzzy melt"
+msgstr "Медленное растворение"
 
-#: hacks/config/euler2d.xml.h:13
+#: ../hacks/config/decayscreen.xml.h:24
 msgid ""
-"Simulates two dimensional Incompressible Inviscid Fluid Flow. Written by "
-"Stephen Montgomery-Smith."
+"Melts an image in various ways. Warning, if the effect continues after the "
+"screen saver is off, seek medical attention. Written by David Wald, Vivek "
+"Khera, Jamie Zawinski, and Vince Levey; 1993."
 msgstr ""
 
-#: hacks/config/extrusion.xml.h:1
-msgid ""
-"Draws various rotating extruded shapes that twist around, lengthen, and turn "
-"inside out. Created by David Konerding from the samples that come with the "
-"GL Extrusion library by Linas Vepstas."
+#: ../hacks/config/deco.xml.h:1
+msgid "Deco"
 msgstr ""
 
-#: hacks/config/extrusion.xml.h:2
-msgid "Extrusion"
-msgstr ""
+#: ../hacks/config/deco.xml.h:8
+msgid "Minimum width"
+msgstr "Минимальная ширина"
 
-#: hacks/config/extrusion.xml.h:4
-msgid "Helix 2"
-msgstr ""
+#: ../hacks/config/deco.xml.h:9
+msgid "Minimum height"
+msgstr "Минимальная высота"
 
-#: hacks/config/extrusion.xml.h:5
-msgid "Helix 3"
-msgstr ""
+#: ../hacks/config/deco.xml.h:10
+msgid "Maximum depth"
+msgstr "Максимальная глубина"
 
-#: hacks/config/extrusion.xml.h:6
-msgid "Helix 4"
-msgstr ""
+#: ../hacks/config/deco.xml.h:11
+msgid "Smooth colors"
+msgstr "Мягкие цвета"
 
-#: hacks/config/extrusion.xml.h:7
-msgid "Join Offset"
-msgstr ""
+#: ../hacks/config/deco.xml.h:12
+msgid "Golden ratio"
+msgstr "Золотое сечение"
 
-#: hacks/config/extrusion.xml.h:8 hacks/config/polytopes.xml.h:16
-msgid "Random Object"
-msgstr ""
+#: ../hacks/config/deco.xml.h:13
+msgid "Mondrian"
+msgstr "Мондриан"
 
-#: hacks/config/extrusion.xml.h:9
-msgid "Screw"
+#: ../hacks/config/deco.xml.h:15
+msgid ""
+"Subdivides and colors rectangles randomly, for a Mondrian-esque effect. "
+"https://en.wikipedia.org/wiki/Piet_Mondrian#Paris_1919.E2.80.931938 Written "
+"by Jamie Zawinski and Michael Bayne; 1997."
 msgstr ""
 
-#: hacks/config/extrusion.xml.h:14
-msgid "Taper"
+#: ../hacks/config/deluxe.xml.h:1
+msgid "Deluxe"
 msgstr ""
 
-#: hacks/config/extrusion.xml.h:15
-msgid "Texture Image"
-msgstr ""
+#: ../hacks/config/deluxe.xml.h:9
+msgid "Shapes"
+msgstr "Фигуры"
 
-#: hacks/config/extrusion.xml.h:16
-msgid "Twistoid"
-msgstr ""
+#. #### -speed [15]
+#: ../hacks/config/deluxe.xml.h:15 ../hacks/config/mirrorblob.xml.h:18
+msgid "Transparency"
+msgstr "Прозрачность"
 
-#: hacks/config/extrusion.xml.h:17 hacks/config/glplanet.xml.h:12
-#: hacks/config/pulsar.xml.h:19
-msgid "Use Flat Coloring"
+#: ../hacks/config/deluxe.xml.h:17
+msgid "Pulsing stars, circles, and lines. Written by Jamie Zawinski; 1999."
 msgstr ""
 
-#: hacks/config/extrusion.xml.h:18 hacks/config/glplanet.xml.h:13
-msgid "Use Lighting"
+#: ../hacks/config/demon.xml.h:1
+msgid "Demon"
 msgstr ""
 
-#: hacks/config/fadeplot.xml.h:2
-msgid ""
-"Draws what looks like a waving ribbon following a sinusoidal path. Written "
-"by Bas van Gaalen and Charles Vidal."
+#: ../hacks/config/demon.xml.h:5 ../hacks/config/gears.xml.h:8
+#: ../hacks/config/glhanoi.xml.h:5 ../hacks/config/interference.xml.h:18
+#: ../hacks/config/voronoi.xml.h:8
+msgid "0"
 msgstr ""
 
-#: hacks/config/fadeplot.xml.h:3
-msgid "FadePlot"
-msgstr ""
+#: ../hacks/config/demon.xml.h:6
+msgid "States"
+msgstr "Состояния"
 
-#: hacks/config/fiberlamp.xml.h:1
-msgid "Draws a groovy rotating fiber optic lamp. Written by Tim Auckland."
+#: ../hacks/config/demon.xml.h:17
+#, no-c-format
+msgid ""
+"A cellular automaton that starts with a random field, and organizes it into "
+"stripes and spirals. https://en.wikipedia.org/wiki/Maxwell%27s_demon Written "
+"by David Bagley; 1999."
 msgstr ""
 
-#: hacks/config/fiberlamp.xml.h:3
-msgid "Fiberlamp"
+#: ../hacks/config/discoball.xml.h:1
+msgid "Discoball"
 msgstr ""
 
-#: hacks/config/fiberlamp.xml.h:4
-#, fuzzy
-msgid "Fibers"
-msgstr "_Файл"
-
-#: hacks/config/fiberlamp.xml.h:8
-msgid "Time between Knocks"
+#: ../hacks/config/discoball.xml.h:15
+msgid "A dusty, dented disco ball. Woop woop. Written by Jamie Zawinski; 2016."
 msgstr ""
 
-#: hacks/config/fireflies.xml.h:1
-msgid "10 times"
+#: ../hacks/config/discrete.xml.h:1
+msgid "Discrete"
 msgstr ""
 
-#: hacks/config/fireflies.xml.h:2
+#: ../hacks/config/discrete.xml.h:12
 msgid ""
-"A bunch of fireflies chase a few baits around the screen, leaving colorful "
-"tails which get blown around by the wind. Written by Matt Perry. This "
-"program is not included with the XScreenSaver package, but if you don't have "
-"it already, you can find it at &lt;http://somewhere.fscked.org/fireflies/"
-"&gt;."
+"Discrete map fractal systems, including variants of Hopalong, Julia, and "
+"others. Written by Tim Auckland; 1998."
 msgstr ""
 
-#: hacks/config/fireflies.xml.h:3
-msgid "Add some fireflies"
+#: ../hacks/config/distort.xml.h:1
+msgid "Distort"
 msgstr ""
 
-#: hacks/config/fireflies.xml.h:4
-msgid "Bait accel"
-msgstr ""
+#. #### -slow
+#: ../hacks/config/distort.xml.h:11
+msgid "Lens size"
+msgstr "Размер линзы"
 
-#: hacks/config/fireflies.xml.h:5
-msgid "Bait speed"
-msgstr ""
+#: ../hacks/config/distort.xml.h:14
+msgid "Lens count"
+msgstr "Количество линз"
 
-#: hacks/config/fireflies.xml.h:6
-msgid "Color cycle speed"
-msgstr ""
+#: ../hacks/config/distort.xml.h:15
+msgid "Normal"
+msgstr "Обычная"
 
-#: hacks/config/fireflies.xml.h:7
-msgid "Draw baits"
-msgstr ""
+#: ../hacks/config/distort.xml.h:16
+msgid "Swamp thing"
+msgstr "Болотная тварь"
 
-#: hacks/config/fireflies.xml.h:8
-msgid "Faded colors"
-msgstr ""
+#: ../hacks/config/distort.xml.h:18
+msgid "Reflect"
+msgstr "Отражение"
 
-#: hacks/config/fireflies.xml.h:9
-msgid "Fast Forward speed"
-msgstr ""
+#: ../hacks/config/distort.xml.h:19
+msgid "Magnify"
+msgstr "Увеличение"
 
-#: hacks/config/fireflies.xml.h:10
-#, fuzzy
-msgid "Fireflies"
-msgstr "Заполненные сплайны"
+#: ../hacks/config/distort.xml.h:20
+msgid "Black hole"
+msgstr "Черная дыра"
+
+#: ../hacks/config/distort.xml.h:21
+msgid "Vortex"
+msgstr "Вихрь"
 
-#: hacks/config/fireflies.xml.h:11
-msgid "Firefly accel"
+#: ../hacks/config/distort.xml.h:23
+msgid ""
+"Wandering lenses distort the screen image in various ways. Written by Jonas "
+"Munsin; 1998."
 msgstr ""
 
-#: hacks/config/fireflies.xml.h:12
-msgid "Firefly size"
+#: ../hacks/config/dnalogo.xml.h:1
+msgid "DNA Logo"
 msgstr ""
 
-#: hacks/config/fireflies.xml.h:13
-msgid "Firefly speed"
+#: ../hacks/config/dnalogo.xml.h:3
+msgid "Frame Rate"
 msgstr ""
 
-#: hacks/config/fireflies.xml.h:14
-#, fuzzy
-msgid "Frames per sec"
-msgstr "Показывать количество кадров в секунду"
-
-#: hacks/config/fireflies.xml.h:15
-msgid "Glow factor"
+#: ../hacks/config/dnalogo.xml.h:5
+msgid "DNA Lounge logo"
 msgstr ""
 
-#: hacks/config/fireflies.xml.h:16
-msgid "Half"
+#: ../hacks/config/dnalogo.xml.h:6
+msgid "DNA Pizza logo"
 msgstr ""
 
-#: hacks/config/fireflies.xml.h:18 hacks/config/fluidballs.xml.h:10
-msgid "Hurricane"
+#: ../hacks/config/dnalogo.xml.h:7
+msgid "DNA Lounge and DNA Pizza logos"
 msgstr ""
 
-#: hacks/config/fireflies.xml.h:19
-msgid "Invisible"
+#: ../hacks/config/dnalogo.xml.h:8
+msgid "Codeword logo"
 msgstr ""
 
-#: hacks/config/fireflies.xml.h:20
-msgid "Kill some fireflies"
+#: ../hacks/config/dnalogo.xml.h:11
+msgid ""
+"DNA Lounge Restaurant -- Bar -- Nightclub -- Cafe -- Est. 1985. 375 Eleventh "
+"Street San Francisco, CA 94103 Codeword Restaurant -- Bar -- Nightclub -- "
+"Cafe -- Est. 2015. 917 Folsom Street San Francisco, CA 94107 https://www."
+"dnalounge.com/ http://www.dnapizza.com/ https://www.codeword-sf.com/ Written "
+"by Jamie Zawinski; 2001."
 msgstr ""
 
-#: hacks/config/fireflies.xml.h:22
-msgid "Make all swarms do something"
+#: ../hacks/config/drift.xml.h:1
+msgid "Drift"
 msgstr ""
 
-#: hacks/config/fireflies.xml.h:23
-msgid "Matrix (pause and rotate)"
+#: ../hacks/config/drift.xml.h:12
+msgid ""
+"Drifting recursive fractal cosmic flames. Written by Scott Draves; 1997."
 msgstr ""
 
-#: hacks/config/fireflies.xml.h:24
-msgid "Maximum baits"
+#: ../hacks/config/dymaxionmap.xml.h:1
+msgid "DymaxionMap"
 msgstr ""
 
-#: hacks/config/fireflies.xml.h:25
-msgid "Maximum flies"
-msgstr ""
+#. #### -no-texture
+#: ../hacks/config/dymaxionmap.xml.h:9
+msgid "Image file"
+msgstr "Файл изображения"
 
-#: hacks/config/fireflies.xml.h:26
-msgid "Merge two swarms"
-msgstr ""
+#: ../hacks/config/dymaxionmap.xml.h:11 ../hacks/config/glplanet.xml.h:10
+#: ../hacks/config/moebiusgears.xml.h:12
+msgid "Roll"
+msgstr "Поворачивать"
 
-#: hacks/config/fireflies.xml.h:27
-msgid "Minimum baits"
+#: ../hacks/config/dymaxionmap.xml.h:15
+msgid ""
+"Buckminster Fuller's map of the Earth projected onto the surface of an "
+"unfolded icosahedron. It depicts the Earth's continents as one island, or "
+"nearly contiguous land masses. https://en.wikipedia.org/wiki/Dymaxion_map "
+"https://en.wikipedia.org/wiki/Buckminster_Fuller Written by Jamie Zawinski; "
+"2016."
 msgstr ""
 
-#: hacks/config/fireflies.xml.h:28
-msgid "Minimum flies"
+#: ../hacks/config/endgame.xml.h:1
+msgid "Endgame"
 msgstr ""
 
-#: hacks/config/fireflies.xml.h:29
-msgid "Narrow"
-msgstr ""
+#: ../hacks/config/endgame.xml.h:5
+msgid "Low resolution chess pieces"
+msgstr "Шахматные фигуры в низком разрешении"
 
-#: hacks/config/fireflies.xml.h:30
-msgid "Never"
+#: ../hacks/config/endgame.xml.h:7
+msgid ""
+"Black slips out of three mating nets, but the fourth one holds him tight! A "
+"brilliant composition! See also the \"Queens\" screen saver. https://en."
+"wikipedia.org/wiki/Chess_endgame Written by Blair Tennessy and Jamie "
+"Zawinski; 2002."
 msgstr ""
 
-#: hacks/config/fireflies.xml.h:31
-msgid "Normal swarm motion"
+#: ../hacks/config/energystream.xml.h:1
+msgid "EnergyStream"
 msgstr ""
 
-#: hacks/config/fireflies.xml.h:33
-msgid "Opaque"
+#: ../hacks/config/energystream.xml.h:8
+msgid ""
+"A flow of particles which form an energy stream. Written by Eugene "
+"Sandulenko and Konrad \"Yoghurt\" Zagorowicz; 2016."
 msgstr ""
 
-#: hacks/config/fireflies.xml.h:35
-msgid "Split a swarm"
+#: ../hacks/config/engine.xml.h:1
+msgid "Engine"
 msgstr ""
 
-#: hacks/config/fireflies.xml.h:36 hacks/config/fluidballs.xml.h:21
-#: hacks/config/glforestfire.xml.h:16
-msgid "Still"
-msgstr ""
+#: ../hacks/config/engine.xml.h:5
+msgid "Random engine"
+msgstr "Случайный двигатель"
 
-#: hacks/config/fireflies.xml.h:37
-msgid "Swarm bursts into rainbow               "
-msgstr ""
+#: ../hacks/config/engine.xml.h:6
+msgid "Honda Insight (3 cylinders)"
+msgstr "Honda Insight (3 цилиндра)"
 
-#: hacks/config/fireflies.xml.h:38
-msgid "Swarm comes to a halt"
-msgstr ""
+#: ../hacks/config/engine.xml.h:7
+msgid "BMW M3 (4 cylinders)"
+msgstr "BMW M3 (4 цилиндра)"
 
-#: hacks/config/fireflies.xml.h:39
-msgid "Swarm does loops"
-msgstr ""
+#: ../hacks/config/engine.xml.h:8
+msgid "VW Beetle (4 cylinders, flat)"
+msgstr "VW Beetle (4 цилиндра, расположенных горизонтально)"
 
-#: hacks/config/fireflies.xml.h:40
-msgid "Swarm hyperspeed"
-msgstr ""
+#: ../hacks/config/engine.xml.h:9
+msgid "Audi Quattro (5 cylinders)"
+msgstr "Audi Quattro (5 цилиндров)"
 
-#: hacks/config/fireflies.xml.h:41
-msgid "Swarm tails glow"
-msgstr ""
+#: ../hacks/config/engine.xml.h:10
+msgid "BMW M5 (6 cylinders)"
+msgstr "BMW M5 (6 цилиндров)"
 
-#: hacks/config/fireflies.xml.h:44
-#, fuzzy
-msgid "Wide"
-msgstr "Перемещение"
+#: ../hacks/config/engine.xml.h:11
+msgid "Subaru XT (6 cylinders, V)"
+msgstr "Subaru XT (6 цилиндров, V-образный)"
 
-#: hacks/config/fireflies.xml.h:45 hacks/config/fluidballs.xml.h:23
-msgid "Wind"
-msgstr ""
+#: ../hacks/config/engine.xml.h:12
+msgid "Porsche 911 (6 cylinders, flat)"
+msgstr "Porsche 911 (6 цилиндров, расположенных горизонтально)"
 
-#: hacks/config/fireflies.xml.h:46
-msgid "Wind picks up"
-msgstr ""
+#: ../hacks/config/engine.xml.h:13
+msgid "Corvette Z06 (8 cylinders, V)"
+msgstr "Corvette Z06 (8 цилиндров, V-образный)"
 
-#: hacks/config/fireworkx.xml.h:1 hacks/config/lavalite.xml.h:3
-msgid "Activity"
-msgstr "Активность"
+#: ../hacks/config/engine.xml.h:14
+msgid "Dodge Viper (10 cylinders, V)"
+msgstr "Dodge Viper (10 цилиндров, V-образный)"
 
-#: hacks/config/fireworkx.xml.h:4
-#, fuzzy
-msgid "Fireworkx"
-msgstr "_Файл"
+#: ../hacks/config/engine.xml.h:15
+msgid "Jaguar XKE (12 cylinders, V)"
+msgstr "Jaguar XKE (12 цилиндров, V-образный)"
 
-#: hacks/config/fireworkx.xml.h:5
-msgid "Light Flash"
-msgstr ""
+#: ../hacks/config/engine.xml.h:16
+msgid "Show engine name"
+msgstr "Показывать название двигателя"
 
-#: hacks/config/fireworkx.xml.h:6
+#: ../hacks/config/engine.xml.h:20
 msgid ""
-"Pyrotechnics simulation eye-candy, MMX optimized. Turn off Light for speed. "
-"Clicks on the preview window Explodes..! Written by Rony B Chandran. http://"
-"www.ronybc.8k.com"
+"Internal combusion engines. https://en.wikipedia.org/wiki/"
+"Internal_combustion_engine#Operation Written by Ben Buxton, Ed Beroset and "
+"Jamie Zawinski; 2001."
 msgstr ""
 
-#: hacks/config/fireworkx.xml.h:7
-msgid "Self Glowing Smoke!"
-msgstr ""
-
-#: hacks/config/fireworkx.xml.h:8
-msgid "Shoot The Shells up"
+#: ../hacks/config/epicycle.xml.h:1
+msgid "Epicycle"
 msgstr ""
 
-#: hacks/config/flag.xml.h:1
-msgid "Bitmap for Flag"
-msgstr ""
+#: ../hacks/config/epicycle.xml.h:12
+msgid "Harmonics"
+msgstr "Гармоники"
 
-#: hacks/config/flag.xml.h:3
-msgid "Flag"
+#: ../hacks/config/epicycle.xml.h:15
+msgid ""
+"A pre-heliocentric model of planetary motion. This draws the path traced out "
+"by a point on the edge of a circle. That circle rotates around a point on "
+"the rim of another circle, and so on, several times. https://en.wikipedia."
+"org/wiki/Deferent_and_epicycle Written by James Youngman; 1998."
 msgstr ""
 
-#: hacks/config/flag.xml.h:10
-msgid "Text for Flag"
+#: ../hacks/config/eruption.xml.h:1
+msgid "Eruption"
 msgstr ""
 
-#: hacks/config/flag.xml.h:11
-msgid ""
-"This draws a waving colored flag, that undulates its way around the screen. "
-"The trick is the flag can contain arbitrary text and images. By default, it "
-"displays either the current system name and OS type, or a picture of "
-"``Bob,'' but you can replace the text or the image with a command-line "
-"option. Written by Charles Vidal and Jamie Zawinski."
-msgstr ""
+#: ../hacks/config/eruption.xml.h:8
+msgid "Little"
+msgstr "Мало"
 
-#: hacks/config/flame.xml.h:1 hacks/config/jigsaw.xml.h:1
-#: hacks/config/maze.xml.h:1 hacks/config/wander.xml.h:1
-msgid "0 Seconds"
-msgstr "0 секунд"
+#: ../hacks/config/eruption.xml.h:11
+msgid "Cooling factor"
+msgstr "Фактор охлаждения"
 
-#: hacks/config/flame.xml.h:2 hacks/config/gleidescope.xml.h:1
-#: hacks/config/glslideshow.xml.h:2 hacks/config/maze.xml.h:2
-#: hacks/config/mirrorblob.xml.h:1
-msgid "10 Seconds"
-msgstr "10 секунд"
+#: ../hacks/config/eruption.xml.h:13
+msgid "Pleasant"
+msgstr "Приятный"
 
-#: hacks/config/flame.xml.h:3
-msgid "Another iterative fractal generator. Written by Scott Draves."
-msgstr ""
+#: ../hacks/config/eruption.xml.h:14
+msgid "Heat"
+msgstr "Жар"
 
-#: hacks/config/flame.xml.h:4 hacks/config/jigglypuff.xml.h:4
-msgid "Complexity"
-msgstr ""
+#: ../hacks/config/eruption.xml.h:15
+msgid "Inferno"
+msgstr "Адский"
 
-#: hacks/config/flame.xml.h:8
-msgid "Flame"
-msgstr ""
+#: ../hacks/config/eruption.xml.h:16
+msgid "Negative"
+msgstr "Отрицательная"
 
-#: hacks/config/flame.xml.h:13
-msgid "Number of Fractals"
-msgstr ""
+#: ../hacks/config/eruption.xml.h:17 ../hacks/config/fluidballs.xml.h:12
+#: ../hacks/config/hydrostat.xml.h:23 ../hacks/config/qix.xml.h:23
+#: ../hacks/config/speedmine.xml.h:9
+msgid "Gravity"
+msgstr "Гравитация"
 
-#: hacks/config/flipflop.xml.h:2
-msgid "FlipFlop"
-msgstr ""
+#: ../hacks/config/eruption.xml.h:18
+msgid "Positive"
+msgstr "Положительная"
 
-#: hacks/config/flipflop.xml.h:3
+#: ../hacks/config/eruption.xml.h:23
 msgid ""
-"Flipflop draws a grid of 3D colored tiles that change positions with each "
-"other. Written by Kevin Ogden."
+"Exploding fireworks. See also the \"Fireworkx\", \"XFlame\" and \"Pyro\" "
+"screen savers. Written by W.P. van Paassen; 2003."
 msgstr ""
 
-#: hacks/config/flipflop.xml.h:6
-#, fuzzy
-msgid "Solid Tiles"
-msgstr "Сплошной"
-
-#: hacks/config/flipscreen3d.xml.h:2
-msgid "Flipscreen3d"
+#: ../hacks/config/euler2d.xml.h:1
+msgid "Euler2D"
 msgstr ""
 
-#: hacks/config/flipscreen3d.xml.h:3
+#: ../hacks/config/euler2d.xml.h:6 ../hacks/config/whirlwindwarp.xml.h:3
+msgid "Particles"
+msgstr "Частицы"
+
+#: ../hacks/config/euler2d.xml.h:31
+#, no-c-format
 msgid ""
-"Grabs an image of the desktop, turns it into a GL texture map, and spins it "
-"around and deforms it in various ways. Written by Ben Buxton."
+"Simulates two dimensional incompressible inviscid fluid flow. https://en."
+"wikipedia.org/wiki/Euler_equations_%28fluid_dynamics%29 https://en.wikipedia."
+"org/wiki/Inviscid_flow Written by Stephen Montgomery-Smith; 2002."
 msgstr ""
 
-#: hacks/config/fliptext.xml.h:1 hacks/config/starwars.xml.h:3
-msgid "Centered Text"
+#: ../hacks/config/extrusion.xml.h:1
+msgid "Extrusion"
 msgstr ""
 
-#: hacks/config/fliptext.xml.h:2
-msgid ""
-"Draws successive pages of text. The lines flip in and out in a soothing 3D "
-"pattern. The text can be the output of a program or the contents of a file "
-"or URL, as configured on the \"Advanced\" tab of the main Screensaver "
-"Preferences window. Written by Jamie Zawinski."
-msgstr ""
+#: ../hacks/config/extrusion.xml.h:5 ../hacks/config/morph3d.xml.h:5
+#: ../hacks/config/polytopes.xml.h:5
+msgid "Random object"
+msgstr "Случайный объект"
 
-#: hacks/config/fliptext.xml.h:4
-msgid "FlipText"
-msgstr ""
+#: ../hacks/config/extrusion.xml.h:6
+msgid "Helix 2"
+msgstr "Спираль 2"
 
-#: hacks/config/fliptext.xml.h:5 hacks/config/starwars.xml.h:7
-msgid "Flush Left Text"
-msgstr ""
+#: ../hacks/config/extrusion.xml.h:7
+msgid "Helix 3"
+msgstr "Спираль 3"
 
-#: hacks/config/fliptext.xml.h:6 hacks/config/starwars.xml.h:8
-msgid "Flush Right Text"
-msgstr ""
+#: ../hacks/config/extrusion.xml.h:8
+msgid "Helix 4"
+msgstr "Спираль 4"
 
-#: hacks/config/fliptext.xml.h:7 hacks/config/starwars.xml.h:9
-msgid "Font Point Size"
-msgstr ""
+#: ../hacks/config/extrusion.xml.h:9
+msgid "Join offset"
+msgstr "Смещение"
 
-#: hacks/config/fliptext.xml.h:11
-msgid "Random Text Alignment"
-msgstr ""
+#: ../hacks/config/extrusion.xml.h:10
+msgid "Screw"
+msgstr "Винт"
 
-#: hacks/config/fliptext.xml.h:15 hacks/config/starwars.xml.h:15
-msgid "Text Columns"
-msgstr ""
+#: ../hacks/config/extrusion.xml.h:11
+msgid "Taper"
+msgstr "Конус"
 
-#: hacks/config/fliptext.xml.h:16 hacks/config/starwars.xml.h:16
-msgid "Text Lines"
-msgstr ""
+#: ../hacks/config/extrusion.xml.h:12
+msgid "Twistoid"
+msgstr "Твистоид"
 
-#: hacks/config/flow.xml.h:3
-msgid "Flow"
-msgstr ""
+#: ../hacks/config/extrusion.xml.h:13
+msgid "Use flat coloring"
+msgstr "Использовать плоское окрашивание"
 
-#: hacks/config/flow.xml.h:5
-msgid "Length of trails"
-msgstr ""
+#: ../hacks/config/extrusion.xml.h:14
+msgid "Use lighting"
+msgstr "Использовать освещение"
 
-#: hacks/config/flow.xml.h:13
+#: ../hacks/config/extrusion.xml.h:18
 msgid ""
-"Strange attractors formed of flows in a 3D differential equation phase "
-"space. Written by Tim Auckland."
+"Various extruded shapes twist and turn inside out. Written by Linas Vepstas, "
+"David Konerding, and Jamie Zawinski; 1999."
 msgstr ""
 
-#: hacks/config/flow.xml.h:16
-msgid "turn on/off bounding box."
+#: ../hacks/config/fadeplot.xml.h:1
+msgid "FadePlot"
 msgstr ""
 
-#: hacks/config/flow.xml.h:17
-msgid "turn on/off double buffering."
-msgstr ""
+#: ../hacks/config/fadeplot.xml.h:9 ../hacks/config/lcdscrub.xml.h:6
+#: ../hacks/config/spiral.xml.h:8
+msgid "Cycles"
+msgstr "Циклы"
 
-#: hacks/config/flow.xml.h:18
-msgid "turn on/off periodic attractors."
+#: ../hacks/config/fadeplot.xml.h:15
+msgid ""
+"A waving ribbon follows a sinusoidal path. Written by Bas van Gaalen and "
+"Charles Vidal; 1997."
 msgstr ""
 
-#: hacks/config/flow.xml.h:19
-msgid "turn on/off ride in the flow."
+#: ../hacks/config/fiberlamp.xml.h:1
+msgid "Fiberlamp"
 msgstr ""
 
-#: hacks/config/flow.xml.h:20
-msgid "turn on/off rotating around attractor."
-msgstr ""
+#: ../hacks/config/fiberlamp.xml.h:6
+msgid "Fibers"
+msgstr "Провода"
 
-#: hacks/config/flow.xml.h:21
-msgid "turn on/off search for new attractors."
-msgstr ""
+#: ../hacks/config/fiberlamp.xml.h:9
+msgid "Time between knocks"
+msgstr "Время между ударами"
 
-#: hacks/config/fluidballs.xml.h:1
-msgid "      Freefall"
+#: ../hacks/config/fiberlamp.xml.h:12
+msgid "A fiber-optic lamp. Groovy. Written by Tim Auckland; 2005."
 msgstr ""
 
-#: hacks/config/fluidballs.xml.h:4
-msgid "Clay"
+#: ../hacks/config/fireworkx.xml.h:1
+msgid "Fireworkx"
 msgstr ""
 
-#: hacks/config/fluidballs.xml.h:7
-msgid "FluidBalls"
+#: ../hacks/config/fireworkx.xml.h:6 ../hacks/config/lavalite.xml.h:6
+msgid "Activity"
+msgstr "Активность"
+
+#: ../hacks/config/fireworkx.xml.h:8
+msgid "Light flash"
+msgstr "Вспышка света"
+
+#: ../hacks/config/fireworkx.xml.h:9
+msgid "Shells upward"
+msgstr "Запускать фейерверки вверх"
+
+#: ../hacks/config/fireworkx.xml.h:11
+msgid ""
+"Exploding fireworks. See also the \"Eruption\", \"XFlame\" and \"Pyro\" "
+"screen savers. Written by Rony B Chandran; 2004."
 msgstr ""
 
-#: hacks/config/fluidballs.xml.h:8 hacks/config/twang.xml.h:4
-msgid "Friction"
+#: ../hacks/config/flag.xml.h:1
+msgid "Flag"
 msgstr ""
 
-#: hacks/config/fluidballs.xml.h:11
-msgid "Jupiter"
+#: ../hacks/config/flag.xml.h:2
+msgid "Text for flag"
 msgstr ""
 
-#: hacks/config/fluidballs.xml.h:14
+#: ../hacks/config/flag.xml.h:14
 msgid ""
-"Models the physics of bouncing balls, or of particles in a gas or fluid, "
-"depending on the settings. If \"Shake Box\" is selected, then every now and "
-"then, the box will be rotated, changing which direction is down (in order to "
-"keep the settled balls in motion.) By Peter Birtles and Jamie Zawinski."
+"This screen saver was removed from the XScreenSaver distribution as of "
+"version 5.08. This draws a waving colored flag, that undulates its way "
+"around the screen. The flag can contain arbitrary text and images. By "
+"default, it displays either the current system name and OS type, or a "
+"picture of \"Bob\". Written by Charles Vidal and Jamie Zawinski; 1997."
 msgstr ""
 
-#: hacks/config/fluidballs.xml.h:15
-msgid "Rubber"
+#: ../hacks/config/flame.xml.h:1
+msgid "Flame"
 msgstr ""
 
-#: hacks/config/fluidballs.xml.h:16
-msgid "Shake Box"
-msgstr ""
+#: ../hacks/config/flame.xml.h:9
+msgid "Number of fractals"
+msgstr "Количество фракталов"
 
-#: hacks/config/fluidballs.xml.h:22
-msgid "Various Ball Sizes"
+#: ../hacks/config/flame.xml.h:15
+msgid "Iterative fractals. Written by Scott Draves; 1993."
 msgstr ""
 
-#: hacks/config/flurry.xml.h:1
-msgid "Binary"
+#: ../hacks/config/flipflop.xml.h:1
+msgid "FlipFlop"
 msgstr ""
 
-#: hacks/config/flurry.xml.h:2
-msgid "Classic"
-msgstr ""
+#: ../hacks/config/flipflop.xml.h:5
+msgid "Stopped"
+msgstr "Остановлено"
 
-#: hacks/config/flurry.xml.h:3
-#, fuzzy
-msgid "Fire"
-msgstr "_Файл"
+#: ../hacks/config/flipflop.xml.h:7
+msgid "Whirlwind"
+msgstr "Вихрь"
 
-#: hacks/config/flurry.xml.h:4
-msgid "Flurry"
-msgstr ""
+#: ../hacks/config/flipflop.xml.h:8
+msgid "Draw Tiles"
+msgstr "Прорисовывать плитки"
 
-#: hacks/config/flurry.xml.h:5
-msgid "Insane"
-msgstr ""
+#: ../hacks/config/flipflop.xml.h:9
+msgid "Draw Sticks"
+msgstr "Прорисовывать палки"
 
-#: hacks/config/flurry.xml.h:6
-msgid "Psychedelic"
-msgstr ""
+#: ../hacks/config/flipflop.xml.h:10
+msgid "Width"
+msgstr "Ширина"
 
-#: hacks/config/flurry.xml.h:7
-msgid "RGB"
-msgstr ""
+#: ../hacks/config/flipflop.xml.h:12
+msgid "Load image"
+msgstr "Загружать изображение"
 
-#: hacks/config/flurry.xml.h:10
+#: ../hacks/config/flipflop.xml.h:15
 msgid ""
-"This port of the OSX screensaver of the same name draws a colourful star"
-"(fish)like flurry of particles. xscreensaver port by Tobias Sargeant &lt;"
-"tobias.sargeant@bigpond.com&gt; Original Mac version by Calum Robinson &lt;"
-"calumr@mac.com&gt; http://homepage.mac.com/calumr"
+"Colored tiles swap with each other. Written by Kevin Ogden and Sergio "
+"Gutierrez; 2003."
 msgstr ""
 
-#: hacks/config/flyingtoasters.xml.h:1
-msgid ""
-"A fleet of 3d space-age jet-powered flying toasters (and toast!) Inspired by "
-"the ancient Berkeley Systems After Dark flying toasters. By Jamie Zawinski "
-"and Baconmonkey."
+#: ../hacks/config/flipscreen3d.xml.h:1
+msgid "FlipScreen3D"
 msgstr ""
 
-#: hacks/config/flyingtoasters.xml.h:2
-#, fuzzy
-msgid "Air Speed"
-msgstr "Скорость"
+#: ../hacks/config/flipscreen3d.xml.h:5 ../hacks/config/gleidescope.xml.h:12
+#: ../hacks/config/glplanet.xml.h:9 ../hacks/config/ifs.xml.h:67
+#: ../hacks/config/tangram.xml.h:15 ../hacks/config/topblock.xml.h:17
+msgid "Rotate"
+msgstr "Поворачивать"
 
-#: hacks/config/flyingtoasters.xml.h:4
-msgid "Chrome Toasters"
+#: ../hacks/config/flipscreen3d.xml.h:7
+msgid ""
+"Spins and deforms an image. Written by Ben Buxton and Jamie Zawinski; 2001."
 msgstr ""
 
-#: hacks/config/flyingtoasters.xml.h:6
-msgid "Flying Toasters"
+#: ../hacks/config/fliptext.xml.h:1
+msgid "FlipText"
 msgstr ""
 
-#: hacks/config/flyingtoasters.xml.h:7 hacks/config/glslideshow.xml.h:17
-#: hacks/config/jigglypuff.xml.h:12 hacks/config/juggle.xml.h:5
-#: hacks/config/mirrorblob.xml.h:15 hacks/config/pipes.xml.h:10
-msgid "None"
-msgstr "Отсутствует"
+#: ../hacks/config/fliptext.xml.h:8
+msgid "Random text alignment"
+msgstr "Случайное выравнивание текста"
 
-#: hacks/config/flyingtoasters.xml.h:8
-#, fuzzy
-msgid "Number of Slices"
-msgstr "Количество цветов"
+#: ../hacks/config/fliptext.xml.h:9 ../hacks/config/starwars.xml.h:7
+msgid "Flush left text"
+msgstr "Выравнивание по левому краю"
 
-#: hacks/config/flyingtoasters.xml.h:9
-#, fuzzy
-msgid "Number of Toasters"
-msgstr "Количество акул"
+#: ../hacks/config/fliptext.xml.h:10 ../hacks/config/starwars.xml.h:8
+msgid "Centered text"
+msgstr "Выравнивание по центру"
 
-#: hacks/config/flyingtoasters.xml.h:12
-msgid "Solid Colors"
-msgstr ""
+#: ../hacks/config/fliptext.xml.h:11 ../hacks/config/starwars.xml.h:9
+msgid "Flush right text"
+msgstr "Выравнивание по правому краю"
 
-#: hacks/config/flyingtoasters.xml.h:13
-msgid "Swarm"
-msgstr ""
+#: ../hacks/config/fliptext.xml.h:12 ../hacks/config/starwars.xml.h:17
+msgid "Font point size"
+msgstr "Размер шрифта"
 
-#: hacks/config/fontglide.xml.h:2
-msgid "Brief"
-msgstr ""
+#: ../hacks/config/fliptext.xml.h:13
+msgid "Text columns"
+msgstr "Столбцы текста"
 
-#: hacks/config/fontglide.xml.h:5
-msgid "Font Border Thickness"
-msgstr ""
+#: ../hacks/config/fliptext.xml.h:14 ../hacks/config/starwars.xml.h:16
+msgid "Text lines"
+msgstr "Строки текста"
 
-#: hacks/config/fontglide.xml.h:6
-msgid "FontGlide"
+#: ../hacks/config/fliptext.xml.h:16
+msgid ""
+"Successive pages of text flip in and out in a soothing 3D pattern. Written "
+"by Jamie Zawinski; 2005."
 msgstr ""
 
-#: hacks/config/fontglide.xml.h:7
-msgid "Horizontally scrolling text"
+#: ../hacks/config/flow.xml.h:1
+msgid "Flow"
 msgstr ""
 
-#: hacks/config/fontglide.xml.h:10
-msgid "Pages of text"
-msgstr ""
+#: ../hacks/config/flow.xml.h:6 ../hacks/config/galaxy.xml.h:5
+#: ../hacks/config/glforestfire.xml.h:6 ../hacks/config/julia.xml.h:6
+#: ../hacks/config/kaleidocycle.xml.h:6 ../hacks/config/laser.xml.h:5
+#: ../hacks/config/lisa.xml.h:14 ../hacks/config/lissie.xml.h:12
+#: ../hacks/config/piecewise.xml.h:6 ../hacks/config/qix.xml.h:18
+#: ../hacks/config/rocks.xml.h:6 ../hacks/config/rotor.xml.h:11
+#: ../hacks/config/rubik.xml.h:5 ../hacks/config/shadebobs.xml.h:12
+#: ../hacks/config/slip.xml.h:6 ../hacks/config/spiral.xml.h:6
+#: ../hacks/config/swirl.xml.h:6 ../hacks/config/worm.xml.h:8
+msgid "Count"
+msgstr "Количество"
 
-#: hacks/config/fontglide.xml.h:11
-msgid ""
-"Puts text on the screen using large characters that glide in from the edges, "
-"assemble, then disperse. Alternately, it can simply scroll whole sentences "
-"from right to left. The text can be the output of a program or the contents "
-"of a file or URL, as configured on the \"Advanced\" tab of the main "
-"Screensaver Preferences window. Written Jamie Zawinski."
-msgstr ""
+#: ../hacks/config/flow.xml.h:14
+msgid "Length of trails"
+msgstr "Длина следов"
 
-#: hacks/config/fontglide.xml.h:14
-msgid "Text Linger"
-msgstr ""
+#: ../hacks/config/flow.xml.h:16
+msgid "Rotating around attractor"
+msgstr "Вращение вокруг аттрактора"
 
-#: hacks/config/fontglide.xml.h:16
-msgid "Vapor Trails"
-msgstr ""
+#: ../hacks/config/flow.xml.h:17
+msgid "Ride in the flow"
+msgstr "Передвижение в потоке"
 
-#: hacks/config/forest.xml.h:2 hacks/config/glforestfire.xml.h:6
-msgid "Forest"
-msgstr ""
+#: ../hacks/config/flow.xml.h:18 ../hacks/config/glschool.xml.h:16
+#: ../hacks/config/molecule.xml.h:10 ../hacks/config/spheremonics.xml.h:20
+msgid "Draw bounding box"
+msgstr "Прорисовывать окружающую коробку"
 
-#: hacks/config/forest.xml.h:7
-msgid ""
-"This draws fractal trees. Written by Peter Baumung. Everybody loves "
-"fractals, right?"
-msgstr ""
+#: ../hacks/config/flow.xml.h:19
+msgid "Periodic attractors"
+msgstr "Периодические аттракторы"
 
-#: hacks/config/fuzzyflakes.xml.h:2
-msgid "Border Thickness"
-msgstr ""
+#: ../hacks/config/flow.xml.h:20
+msgid "Search for new attractors"
+msgstr "Искать новые аттракторы"
 
-#: hacks/config/fuzzyflakes.xml.h:4
-msgid "Delay"
+#: ../hacks/config/flow.xml.h:22
+msgid ""
+"Strange attractors formed of flows in a 3D differential equation phase "
+"space. Features the popular attractors described by Lorentz, Roessler, "
+"Birkhoff and Duffing, and can discover entirely new attractors by itself. "
+"https://en.wikipedia.org/wiki/Attractor#Strange_attractor Written by Tim "
+"Auckland; 1998."
 msgstr ""
 
-#: hacks/config/fuzzyflakes.xml.h:6
-msgid "Falling colored snowflake/flower shapes. Written by Barry Dmytro."
+#: ../hacks/config/fluidballs.xml.h:1
+msgid "FluidBalls"
 msgstr ""
 
-#: hacks/config/fuzzyflakes.xml.h:9
-msgid "FuzzyFlakes"
-msgstr ""
+#: ../hacks/config/fluidballs.xml.h:11
+msgid "      Freefall"
+msgstr "Свободное падение"
 
-#: hacks/config/fuzzyflakes.xml.h:11 hacks/config/xspirograph.xml.h:4
-msgid "Layers"
-msgstr ""
+#: ../hacks/config/fluidballs.xml.h:13
+msgid "Jupiter"
+msgstr "Юпитер"
 
-#: hacks/config/fuzzyflakes.xml.h:14
-msgid "Random Colors"
-msgstr ""
+#: ../hacks/config/fluidballs.xml.h:14
+msgid "Still"
+msgstr "Спокойный"
 
-#: hacks/config/galaxy.xml.h:4
-msgid "Galaxy"
-msgstr ""
+#: ../hacks/config/fluidballs.xml.h:15
+msgid "Wind"
+msgstr "Ветер"
 
-#: hacks/config/galaxy.xml.h:8
-msgid "Rotate Viewpoint"
-msgstr ""
+#: ../hacks/config/fluidballs.xml.h:16
+msgid "Hurricane"
+msgstr "Ураган"
 
-#: hacks/config/galaxy.xml.h:13
-msgid ""
-"This draws spinning galaxies, which then collide and scatter their stars to "
-"the, uh, four winds or something. Originally an Amiga program by Uli "
-"Siegmund."
-msgstr ""
+#: ../hacks/config/fluidballs.xml.h:17
+msgid "Clay"
+msgstr "Глина"
 
-#: hacks/config/gears.xml.h:3
-msgid "Gears"
-msgstr ""
+#: ../hacks/config/fluidballs.xml.h:18 ../hacks/config/twang.xml.h:11
+msgid "Friction"
+msgstr "Взаимодействие"
 
-#: hacks/config/gears.xml.h:4
-msgid "Planetary Gear System"
-msgstr ""
+#: ../hacks/config/fluidballs.xml.h:19
+msgid "Rubber"
+msgstr "Резина"
 
-#: hacks/config/gears.xml.h:5 hacks/config/goop.xml.h:9
-msgid "Rotational Speed"
-msgstr ""
+#: ../hacks/config/fluidballs.xml.h:20
+msgid "Various ball sizes"
+msgstr "Различные размеры мячей"
 
-#: hacks/config/gears.xml.h:9
+#: ../hacks/config/fluidballs.xml.h:21
+msgid "Shake box"
+msgstr "Трясти коробку"
+
+#: ../hacks/config/fluidballs.xml.h:23
 msgid ""
-"This draws sets of turning, interlocking gears, rotating in three "
-"dimensions. Another GL hack, by Danny Sung, Brian Paul, Ed Mackey, and Jamie "
-"Zawinski."
+"Models the physics of bouncing balls, or of particles in a gas or fluid, "
+"depending on the settings. If \"Shake Box\" is selected, then every now and "
+"then, the box will be rotated, changing which direction is down (in order to "
+"keep the settled balls in motion.) Written by Peter Birtles and Jamie "
+"Zawinski; 2002."
 msgstr ""
 
-#: hacks/config/gears.xml.h:10
-msgid "Three Gear System"
+#: ../hacks/config/flurry.xml.h:1
+msgid "Flurry"
 msgstr ""
 
-#: hacks/config/gflux.xml.h:2
-msgid "Checkerboard"
-msgstr ""
+#: ../hacks/config/flurry.xml.h:3
+msgid "Classic"
+msgstr "Классический"
 
-#: hacks/config/gflux.xml.h:5
-msgid ""
-"Draws a rippling waves on a rotating wireframe grid, using GL. Written by "
-"Josiah Pease."
+#: ../hacks/config/flurry.xml.h:4
+msgid "RGB"
 msgstr ""
 
-#: hacks/config/gflux.xml.h:7
-msgid "Flat Lighting"
-msgstr ""
+#: ../hacks/config/flurry.xml.h:5
+msgid "Fire"
+msgstr "Огонь"
 
-#: hacks/config/gflux.xml.h:8
-msgid "GFlux"
-msgstr ""
+#: ../hacks/config/flurry.xml.h:7
+msgid "Binary"
+msgstr "Двоичный"
 
-#: hacks/config/gflux.xml.h:9
-msgid "Mesh Density"
-msgstr ""
+#: ../hacks/config/flurry.xml.h:8
+msgid "Psychedelic"
+msgstr "Психоделический"
 
-#: hacks/config/gflux.xml.h:10
-msgid "Screen Image"
-msgstr "Ð\98зобÑ\80ажение Ñ\8dкÑ\80ана"
+#: ../hacks/config/flurry.xml.h:9
+msgid "Insane"
+msgstr "Ð\91езÑ\83мнÑ\8bй"
 
-#: hacks/config/gflux.xml.h:14 hacks/config/interference.xml.h:21
-msgid "Wave Speed"
+#: ../hacks/config/flurry.xml.h:11
+msgid ""
+"A colourful star(fish)like flurry of particles. Written by Calum Robinson "
+"and Tobias Sargeant; 2002."
 msgstr ""
 
-#: hacks/config/gflux.xml.h:15 hacks/config/glmatrix.xml.h:20
-msgid "Waves"
+#: ../hacks/config/flyingtoasters.xml.h:1
+msgid "FlyingToasters"
 msgstr ""
 
-#: hacks/config/gflux.xml.h:16
-msgid "Wire Mesh"
-msgstr ""
+#: ../hacks/config/flyingtoasters.xml.h:6
+msgid "Air speed"
+msgstr "Скорость"
 
-#: hacks/config/glblur.xml.h:1
-msgid "Blur Smoothness"
-msgstr ""
+#: ../hacks/config/flyingtoasters.xml.h:9
+msgid "Number of toasters"
+msgstr "Количество тостеров"
 
-#: hacks/config/glblur.xml.h:5
-msgid "GLBlur"
-msgstr ""
+#: ../hacks/config/flyingtoasters.xml.h:10
+msgid "Swarm"
+msgstr "Рой"
 
-#: hacks/config/glblur.xml.h:17
-msgid ""
-"This program draws a box and a few line segments, and generates a radial "
-"blur outward from it. This creates flowing field effects. This is done by "
-"rendering the scene into a small texture, then repeatedly rendering "
-"increasingly-enlarged and increasingly-transparent versions of that texture "
-"onto the frame buffer. As such, it's quite graphics intensive: don't bother "
-"trying to run this if you don't have hardware-accelerated OpenGL texture "
-"support. It will hurt your machine bad."
-msgstr ""
+#: ../hacks/config/flyingtoasters.xml.h:11
+msgid "Number of slices"
+msgstr "Количество кусков хлеба"
 
-#: hacks/config/gleidescope.xml.h:2 hacks/config/glslideshow.xml.h:6
-#: hacks/config/mirrorblob.xml.h:3
-#, fuzzy
-msgid "5 Minutes"
-msgstr "1 минута"
+#: ../hacks/config/flyingtoasters.xml.h:12 ../hacks/config/jigglypuff.xml.h:6
+#: ../hacks/config/winduprobot.xml.h:20
+msgid "Chrome"
+msgstr "Хром"
 
-#: hacks/config/gleidescope.xml.h:3
+#: ../hacks/config/flyingtoasters.xml.h:16
+#, no-c-format
 msgid ""
-"An OpenGL kaleidescope that operates on your desktop image, or on image "
-"files loaded from disk. Written by andrew dean."
+"A fleet of 3d space-age jet-powered flying toasters (and toast!) Inspired by "
+"the ancient Berkeley Systems After Dark flying toasters. https://en."
+"wikipedia.org/wiki/After_Dark_%28software%29#Flying_Toasters Written by "
+"Jamie Zawinski and Devon Dossett; 2003."
 msgstr ""
 
-#: hacks/config/gleidescope.xml.h:4
-msgid "Gleidescope"
+#: ../hacks/config/fontglide.xml.h:1
+msgid "FontGlide"
 msgstr ""
 
-#: hacks/config/gleidescope.xml.h:5
-#, fuzzy
-msgid "Image Duration"
-msgstr "Ð\9fÑ\80одолжиÑ\82елÑ\8cноÑ\81Ñ\82Ñ\8c Ð¿ÐµÑ\80еÑ\85ода"
+#: ../hacks/config/fontglide.xml.h:8 ../hacks/config/raverhoop.xml.h:15
+#: ../hacks/config/tangram.xml.h:5 ../hacks/config/xlyap.xml.h:5
+msgid "Brief"
+msgstr "Ð\9aоÑ\80оÑ\82каÑ\8f"
 
-#: hacks/config/gleidescope.xml.h:6
-msgid "Image file"
-msgstr ""
+#: ../hacks/config/fontglide.xml.h:9
+msgid "Page linger"
+msgstr "Длина страницы"
 
-#: hacks/config/gleidescope.xml.h:8
-#, fuzzy
-msgid "Move"
-msgstr "Режим:"
+#: ../hacks/config/fontglide.xml.h:11
+msgid "Pages of text"
+msgstr "Страницы текста"
 
-#: hacks/config/gleidescope.xml.h:11
-msgid "Size of tube"
+#: ../hacks/config/fontglide.xml.h:12
+msgid "Horizontally scrolling text"
+msgstr "Горизонтальная прокрутка текста"
+
+#: ../hacks/config/fontglide.xml.h:13
+msgid "Random display style"
+msgstr "Случальный стиль отображения"
+
+#: ../hacks/config/fontglide.xml.h:14
+msgid "Font border thickness"
+msgstr "Толщина границы шрифта"
+
+#: ../hacks/config/fontglide.xml.h:15
+msgid "Vapor trails"
+msgstr "Следы испарения"
+
+#: ../hacks/config/fontglide.xml.h:17
+msgid ""
+"Puts text on the screen using large characters that glide in from the edges, "
+"assemble, then disperse. Alternately, it can simply scroll whole sentences "
+"from right to left. Written by Jamie Zawinski; 2003."
 msgstr ""
 
-#: hacks/config/glforestfire.xml.h:2
-msgid "Desert"
+#: ../hacks/config/forest.xml.h:1 ../hacks/config/glforestfire.xml.h:10
+msgid "Forest"
 msgstr ""
 
-#: hacks/config/glforestfire.xml.h:3
+#: ../hacks/config/forest.xml.h:9
 msgid ""
-"Draws an animation of sprinkling fire-like 3D triangles in a landscape "
-"filled with trees. Requires OpenGL, and a machine with fast hardware support "
-"for texture maps. Written by Eric Lassauge &lt;lassauge@users.sourceforge."
-"net&gt;."
+"This screen saver was removed from the XScreenSaver distribution as of "
+"version 5.08. Fractal trees. Written by Peter Baumung; 1997."
 msgstr ""
 
-#: hacks/config/glforestfire.xml.h:5 hacks/config/glmatrix.xml.h:9
-msgid "Fog"
+#: ../hacks/config/fuzzyflakes.xml.h:1
+msgid "FuzzyFlakes"
 msgstr ""
 
-#: hacks/config/glforestfire.xml.h:7
-msgid "GLForestFire"
-msgstr ""
+#: ../hacks/config/fuzzyflakes.xml.h:9 ../hacks/config/hypnowheel.xml.h:10
+#: ../hacks/config/xspirograph.xml.h:8
+msgid "Layers"
+msgstr "Слои"
 
-#: hacks/config/glforestfire.xml.h:8
-msgid "Huge Fire"
-msgstr ""
+#: ../hacks/config/fuzzyflakes.xml.h:11
+msgid "Random colors"
+msgstr "Случайные цвета"
 
-#: hacks/config/glforestfire.xml.h:9
-msgid "No shadow"
-msgstr ""
+#: ../hacks/config/fuzzyflakes.xml.h:13
+msgid "Red"
+msgstr "Красный"
 
-#: hacks/config/glforestfire.xml.h:11
-msgid "Number of trees"
-msgstr ""
+#: ../hacks/config/fuzzyflakes.xml.h:14
+msgid "Pink"
+msgstr "Розовый"
 
-#: hacks/config/glforestfire.xml.h:12
-msgid "Rain"
-msgstr ""
+#: ../hacks/config/fuzzyflakes.xml.h:15
+msgid "Yellow"
+msgstr "Желтый"
 
-#: hacks/config/glforestfire.xml.h:17
-msgid "Track mouse"
-msgstr ""
+#: ../hacks/config/fuzzyflakes.xml.h:17
+msgid "Cyan"
+msgstr "Голубой"
 
-#: hacks/config/glhanoi.xml.h:1
-#, fuzzy
-msgid "Enable fog"
-msgstr "Разрешить вспышки"
+#: ../hacks/config/fuzzyflakes.xml.h:19
+msgid "Magenta"
+msgstr "Пурпурный"
 
-#: hacks/config/glhanoi.xml.h:2
-#, fuzzy
-msgid "Enable lighting"
-msgstr "Разрешить вспышки"
+#: ../hacks/config/fuzzyflakes.xml.h:24
+msgid "Border thickness"
+msgstr "Толщина границ"
 
-#: hacks/config/glhanoi.xml.h:4
-#, fuzzy
-msgid "Frame Delay (us)"
-msgstr "Показывать количество кадров в секунду"
+#: ../hacks/config/fuzzyflakes.xml.h:28
+msgid ""
+"Falling colored snowflake/flower shapes. https://en.wikipedia.org/wiki/"
+"Snowflake Written by Barry Dmytro; 2004."
+msgstr ""
 
-#: hacks/config/glhanoi.xml.h:5
-msgid "GLHanoi"
+#: ../hacks/config/galaxy.xml.h:1
+msgid "Galaxy"
 msgstr ""
 
-#: hacks/config/glhanoi.xml.h:6
-#, fuzzy
-msgid "Number of Disks"
-msgstr "Количество цветов"
+#: ../hacks/config/galaxy.xml.h:12
+msgid "Rotate viewpoint"
+msgstr "Поворачивать точку обзора"
 
-#: hacks/config/glhanoi.xml.h:9
+#: ../hacks/config/galaxy.xml.h:14
 msgid ""
-"Solves the Towers of Hanoi puzzle. Move N disks from one pole to another, "
-"one disk at a time, with no disk ever resting on a disk smaller than itself. "
-"Written by Dave Atkinson."
+"Spinning galaxies collide. Written by Uli Siegmund, Harald Backert, and "
+"Hubert Feyrer; 1997."
 msgstr ""
 
-#: hacks/config/glknots.xml.h:4
-msgid "GLKnots"
+#: ../hacks/config/gears.xml.h:1
+msgid "Gears"
 msgstr ""
 
-#: hacks/config/glknots.xml.h:5
+#: ../hacks/config/gears.xml.h:9
+msgid "Gear count"
+msgstr "Количество шестеренок"
+
+#: ../hacks/config/gears.xml.h:15
 msgid ""
-"Generates some twisting 3d knot patterns. Spins 'em around. Written by Jamie "
-"Zawinski."
+"Interlocking gears. See also the \"Pinion\" and \"MoebiusGears\" screen "
+"savers. https://en.wikipedia.org/wiki/Involute_gear https://en.wikipedia.org/"
+"wiki/Epicyclic_gearing Written by Jamie Zawinski; 2007."
 msgstr ""
 
-#: hacks/config/glknots.xml.h:7 hacks/config/lavalite.xml.h:17
-#: hacks/config/spheremonics.xml.h:9
-msgid "Resolution"
-msgstr "Разрешение"
-
-#: hacks/config/glknots.xml.h:15
-msgid "Segmented"
+#: ../hacks/config/geodesic.xml.h:1
+msgid "Geodesic"
 msgstr ""
 
-#: hacks/config/glknots.xml.h:18 hacks/config/lavalite.xml.h:28
-#: hacks/config/xmountains.xml.h:25
-msgid "Smooth"
-msgstr ""
+#: ../hacks/config/geodesic.xml.h:2
+msgid "Mesh faces"
+msgstr "Ячеистая поверхность"
 
-#: hacks/config/glmatrix.xml.h:2 hacks/config/xmatrix.xml.h:1
-msgid "Binary Encoding"
-msgstr ""
+#: ../hacks/config/geodesic.xml.h:3
+msgid "Solid faces"
+msgstr "Сплошная поверхность"
+
+#: ../hacks/config/geodesic.xml.h:4
+msgid "Stellated faces"
+msgstr "Звездообразная поверхность"
 
-#: hacks/config/glmatrix.xml.h:4
-msgid "Draw Glyphs"
+#: ../hacks/config/geodesic.xml.h:5
+msgid "Inverse Stellated"
+msgstr "Вывернутая звездообразная поверхность"
+
+#: ../hacks/config/geodesic.xml.h:7
+msgid "Random face style"
+msgstr "Случайный стиль поверхности"
+
+#: ../hacks/config/geodesic.xml.h:19 ../hacks/config/kaleidocycle.xml.h:5
+#: ../hacks/config/strange.xml.h:11
+msgid "8"
 msgstr ""
 
-#: hacks/config/glmatrix.xml.h:5
-msgid "Draw Outlines"
+#: ../hacks/config/geodesic.xml.h:20
+msgid ""
+"A mesh geodesic sphere of increasing and decreasing complexity. A geodesic "
+"sphere is an icosohedron whose equilateral faces are sub-divided into non-"
+"equilateral triangles to more closely approximate a sphere. The animation "
+"shows the equilateral triangles subdivided into four coplanar equilateral "
+"triangles; and then inflated outward, causing the sub-triangles to no longer "
+"be equilateral, but to more closely approximate the surface of a sphere. "
+"https://en.wikipedia.org/wiki/Geodesic_dome https://en.wikipedia.org/wiki/"
+"Buckminster_Fuller Written by Jamie Zawinski; 2013."
 msgstr ""
 
-#: hacks/config/glmatrix.xml.h:6
-msgid "Draw Solid Boxes"
+#: ../hacks/config/geodesicgears.xml.h:1
+msgid "GeodesicGears"
 msgstr ""
 
-#: hacks/config/glmatrix.xml.h:7
+#: ../hacks/config/geodesicgears.xml.h:8
+msgid "Describe gears"
+msgstr "Описание шестеренок"
+
+#: ../hacks/config/geodesicgears.xml.h:9
+msgid "Number gears"
+msgstr "Количество шестеренок"
+
+#: ../hacks/config/geodesicgears.xml.h:14
 msgid ""
-"Draws 3D dropping characters similar to what is seen in the title sequence "
-"of \"The Matrix\". See also \"xmatrix\" for a 2D rendering of the similar "
-"effect that appeared on the computer monitors actually *in* the movie. "
-"Written by Jamie Zawinski."
+"A set of meshed gears arranged on the surface of a sphere. https://en."
+"wikipedia.org/wiki/Geodesic_dome https://en.wikipedia.org/wiki/Involute_gear "
+"https://en.wikipedia.org/wiki/Buckminster_Fuller Written by Jamie Zawinski; "
+"2014."
 msgstr ""
 
-#: hacks/config/glmatrix.xml.h:10
-msgid "GLMatrix"
+#: ../hacks/config/gflux.xml.h:1
+msgid "GFlux"
 msgstr ""
 
-#: hacks/config/glmatrix.xml.h:11 hacks/config/xmatrix.xml.h:7
-msgid "Genetic Encoding"
+#: ../hacks/config/gflux.xml.h:9
+msgid "Mesh density"
+msgstr "Плотность ячеек"
+
+#: ../hacks/config/gflux.xml.h:12 ../hacks/config/glmatrix.xml.h:16
+msgid "Waves"
+msgstr "Волны"
+
+#: ../hacks/config/gflux.xml.h:13 ../hacks/config/glhanoi.xml.h:13
+#: ../hacks/config/hilbert.xml.h:14 ../hacks/config/lavalite.xml.h:10
+#: ../hacks/config/strange.xml.h:19
+msgid "10"
 msgstr ""
 
-#: hacks/config/glmatrix.xml.h:12
-#, fuzzy
-msgid "Glyph Density"
-msgstr "Плотность"
+#: ../hacks/config/gflux.xml.h:14
+msgid "Wire mesh"
+msgstr "Ячейки"
 
-#: hacks/config/glmatrix.xml.h:13
-#, fuzzy
-msgid "Glyph Speed"
-msgstr "Скорость решения"
+#: ../hacks/config/gflux.xml.h:15
+msgid "Flat lighting"
+msgstr "Плоское освещение"
 
-#: hacks/config/glmatrix.xml.h:14 hacks/config/xmatrix.xml.h:8
-msgid "Hexadecimal Encoding"
-msgstr ""
+#: ../hacks/config/gflux.xml.h:17
+msgid "Checkerboard"
+msgstr "Шахматная доска"
 
-#: hacks/config/glmatrix.xml.h:15 hacks/config/xmatrix.xml.h:11
-msgid "Matrix Encoding"
+#: ../hacks/config/gflux.xml.h:18
+msgid "Picture"
+msgstr "Изображение"
+
+#: ../hacks/config/gflux.xml.h:20
+msgid "Undulating waves on a rotating grid. Written by Josiah Pease; 2000."
 msgstr ""
 
-#: hacks/config/glmatrix.xml.h:16
-msgid "Panning"
+#: ../hacks/config/glblur.xml.h:1
+msgid "GLBlur"
 msgstr ""
 
-#: hacks/config/glplanet.xml.h:1
+#: ../hacks/config/glblur.xml.h:6
+msgid "Blur smoothness"
+msgstr "Степень размытия"
+
+#: ../hacks/config/glblur.xml.h:18
 msgid ""
-"Draws a planet bouncing around in space. Written by David Konerding. The "
-"built-in image is a map of the earth (extracted from `xearth'), but you can "
-"wrap any texture around the sphere, e.g., the planetary textures that come "
-"with `ssystem'."
+"Flowing field effects from the vapor trails around a moving object. This is "
+"done by rendering the scene into a small texture, then repeatedly rendering "
+"increasingly-enlarged and increasingly-transparent versions of that texture "
+"onto the frame buffer. As such, it's quite GPU-intensive: if you don't have "
+"a very good graphics card, it will hurt your machine bad. Written by Jamie "
+"Zawinski; 2002."
 msgstr ""
 
-#: hacks/config/glplanet.xml.h:3
-msgid "GLPlanet"
+#: ../hacks/config/glcells.xml.h:1
+msgid "GLCells"
 msgstr ""
 
-#: hacks/config/glplanet.xml.h:4
-msgid "Image File"
-msgstr ""
+#: ../hacks/config/glcells.xml.h:9
+msgid "Max cells"
+msgstr "Максимум клеток"
 
-#: hacks/config/glplanet.xml.h:5
-msgid "Roll"
-msgstr ""
+#: ../hacks/config/glcells.xml.h:12
+msgid "Cell radius"
+msgstr "Радиус клеток"
 
-#: hacks/config/glslideshow.xml.h:4 hacks/config/rd-bomb.xml.h:5
-#: hacks/config/substrate.xml.h:4 hacks/config/xplanet.xml.h:4
-#, no-c-format
-msgid "100%"
-msgstr "100%"
+#: ../hacks/config/glcells.xml.h:14
+msgid "Lowest sphere detail"
+msgstr "Низкая детализация"
 
-#: hacks/config/glslideshow.xml.h:5 hacks/config/glsnake.xml.h:2
-#: hacks/config/mirrorblob.xml.h:2
-msgid "30 Seconds"
-msgstr ""
+#: ../hacks/config/glcells.xml.h:15
+msgid "Medium sphere detail"
+msgstr "Средняя детализация"
 
-#: hacks/config/glslideshow.xml.h:8
-#, no-c-format
-msgid "50%"
-msgstr ""
+#: ../hacks/config/glcells.xml.h:16
+msgid "Normal sphere detail"
+msgstr "Нормальная детализация"
 
-#: hacks/config/glslideshow.xml.h:9
-msgid "Always show at least this much of the image:"
-msgstr ""
+#: ../hacks/config/glcells.xml.h:17
+msgid "More sphere detail"
+msgstr "Улучшенная детализация"
 
-#: hacks/config/glslideshow.xml.h:10 hacks/config/mirrorblob.xml.h:6
-#, fuzzy
-msgid "Crossfade Duration:"
-msgstr "Продолжительность перехода"
+#: ../hacks/config/glcells.xml.h:18
+msgid "Highest sphere detail"
+msgstr "Высочайшая детализация"
 
-#: hacks/config/glslideshow.xml.h:11
-msgid "Frame Rate:"
-msgstr ""
+#: ../hacks/config/glcells.xml.h:19
+msgid "Starve"
+msgstr "Голодный"
 
-#: hacks/config/glslideshow.xml.h:12
-msgid "GLSlideshow"
-msgstr ""
+#: ../hacks/config/glcells.xml.h:20
+msgid "Min food"
+msgstr "Минимум поедаемых клеток"
 
-#: hacks/config/glslideshow.xml.h:15
-msgid ""
-"Loads a random sequence of images and smoothly scans and zooms around in "
-"each, fading from pan to pan. To tell it where to find the images to "
-"display, go to the \"Advanced\" tab on the Screensaver Preferences window. "
-"Select \"Choose Random Images\", and enter your image directory in the text "
-"field right below that. (Note: not the the \"Advanced\" button at the bottom "
-"of this window: the tab at the top of the *other* window.) This program "
-"requires a good video card capable of supporting large textures. Written by "
-"Jamie Zawinski and Mike Oliphant."
-msgstr ""
-
-#: hacks/config/glslideshow.xml.h:18
-#, fuzzy
-msgid "Pan/Zoom Duration:"
-msgstr "Продолжительность перехода"
+#: ../hacks/config/glcells.xml.h:21
+msgid "Gorge"
+msgstr "Сыт по горло"
 
-#: hacks/config/glsnake.xml.h:1 hacks/config/lavalite.xml.h:1
-msgid "1"
-msgstr ""
+#: ../hacks/config/glcells.xml.h:22
+msgid "Max food"
+msgstr "Максимум поедаемых клеток"
+
+#: ../hacks/config/glcells.xml.h:23
+msgid "Quick"
+msgstr "Быстро"
+
+#: ../hacks/config/glcells.xml.h:24
+msgid "Cell division"
+msgstr "Деление клеток"
 
-#: hacks/config/glsnake.xml.h:3
-msgid "Angular Velocity"
+#: ../hacks/config/glcells.xml.h:26
+msgid "Min distance"
+msgstr "Минимальное расстояние"
+
+#: ../hacks/config/glcells.xml.h:30
+msgid "15"
 msgstr ""
 
-#: hacks/config/glsnake.xml.h:4
+#: ../hacks/config/glcells.xml.h:31
+msgid "Keep dead cells"
+msgstr "Сохранять мертвые клетки"
+
+#: ../hacks/config/glcells.xml.h:34
 msgid ""
-"Draws a simulation of the Rubik's Snake puzzle. Written by Jamie Wilkinson, "
-"Andrew Bennetts, and Peter Aylett."
+"Cells growing, dividing and dying on your screen. Microscopic pathos. "
+"Written by Matthias Toussaint; 2007."
 msgstr ""
 
-#: hacks/config/glsnake.xml.h:7
-msgid "GlSnake"
+#: ../hacks/config/gleidescope.xml.h:1
+msgid "Gleidescope"
 msgstr ""
 
-#: hacks/config/glsnake.xml.h:8
-msgid "Loose"
-msgstr ""
+#: ../hacks/config/gleidescope.xml.h:6
+msgid "Size of tube"
+msgstr "Размер трубы"
 
-#: hacks/config/glsnake.xml.h:9
-msgid "Packing"
-msgstr ""
+#: ../hacks/config/gleidescope.xml.h:9
+msgid "Image duration"
+msgstr "Продолжительность перехода"
 
-#: hacks/config/glsnake.xml.h:11
-msgid "Show Titles"
-msgstr ""
+#: ../hacks/config/gleidescope.xml.h:10 ../hacks/config/glslideshow.xml.h:7
+msgid "5 minutes"
+msgstr "5 минут"
 
-#: hacks/config/glsnake.xml.h:14
-msgid "Tight"
-msgstr ""
+#: ../hacks/config/gleidescope.xml.h:11
+msgid "Move"
+msgstr "Двигать"
+
+#: ../hacks/config/gleidescope.xml.h:13 ../hacks/config/hyperball.xml.h:6
+#: ../hacks/config/hypercube.xml.h:6 ../hacks/config/mirrorblob.xml.h:6
+#: ../hacks/config/strange.xml.h:14 ../hacks/config/zoom.xml.h:1
+msgid "Zoom"
+msgstr "Масштабировать"
 
-#: hacks/config/glsnake.xml.h:16
-msgid "Y Angular Velocity"
+#: ../hacks/config/gleidescope.xml.h:15
+msgid ""
+"A kaleidoscope that operates on a loaded image. https://en.wikipedia.org/"
+"wiki/Kaleidoscope Written by Andrew Dean; 2003."
 msgstr ""
 
-#: hacks/config/glsnake.xml.h:17
-msgid "Z Angular Velocity"
+#: ../hacks/config/glforestfire.xml.h:1
+msgid "GLForestFire"
 msgstr ""
 
-#: hacks/config/gltext.xml.h:1
-msgid "Always face front"
+#: ../hacks/config/glforestfire.xml.h:5
+msgid "Rain"
 msgstr ""
 
-#: hacks/config/gltext.xml.h:2
-msgid ""
-"Displays a few lines of text spinning around in a solid 3D font. Written by "
-"Jamie Zawinski."
+#: ../hacks/config/glforestfire.xml.h:7
+msgid "Huge fire"
 msgstr ""
 
-#: hacks/config/gltext.xml.h:5
-msgid "GLText"
+#: ../hacks/config/glforestfire.xml.h:8
+msgid "Desert"
 msgstr ""
 
-#: hacks/config/gltext.xml.h:6
-msgid "Program"
+#: ../hacks/config/glforestfire.xml.h:9
+msgid "Number of trees"
 msgstr ""
 
-#: hacks/config/gltext.xml.h:18
-msgid "Spin all the way around"
+#: ../hacks/config/glforestfire.xml.h:12
+msgid "Textures"
 msgstr ""
 
-#: hacks/config/gltext.xml.h:19 hacks/config/noseguy.xml.h:5
-msgid "Text"
+#: ../hacks/config/glforestfire.xml.h:13
+msgid "Shadows"
 msgstr ""
 
-#: hacks/config/goban.xml.h:1
-msgid "Goban"
+#: ../hacks/config/glforestfire.xml.h:14 ../hacks/config/glmatrix.xml.h:15
+#: ../hacks/config/glschool.xml.h:14
+msgid "Fog"
 msgstr ""
 
-#: hacks/config/goban.xml.h:2
+#: ../hacks/config/glforestfire.xml.h:17
 msgid ""
-"Replays historical games of go (aka wei-chi and baduk) on the screen. By "
-"Scott Draves. You can find it at &lt;http://www.draves.org/goban/&gt;."
+"This screen saver was removed from the XScreenSaver distribution as of "
+"version 5.08. Draws an animation of sprinkling fire-like 3D triangles in a "
+"landscape filled with trees. Written by Eric Lassauge; 2002."
 msgstr ""
 
-#: hacks/config/goop.xml.h:1
-msgid "Additive Colors (reflected light)"
+#: ../hacks/config/glhanoi.xml.h:1
+msgid "GLHanoi"
 msgstr ""
 
-#: hacks/config/goop.xml.h:2
-msgid "Blob Count"
-msgstr ""
+#: ../hacks/config/glhanoi.xml.h:6
+msgid "Number of disks"
+msgstr "Количество дисков"
 
-#: hacks/config/goop.xml.h:3
-msgid "Elasticity"
+#: ../hacks/config/glhanoi.xml.h:7
+msgid "31"
 msgstr ""
 
-#: hacks/config/goop.xml.h:5
-msgid "Goop"
-msgstr ""
+#: ../hacks/config/glhanoi.xml.h:8
+msgid "Number of poles"
+msgstr "Количество шестов"
 
-#: hacks/config/goop.xml.h:8
-msgid "Opaque Blobs"
-msgstr ""
+#: ../hacks/config/glhanoi.xml.h:10
+msgid "Speed (of smallest disks)"
+msgstr "Скорость (самых маленьких дисков)"
 
-#: hacks/config/goop.xml.h:12
-msgid "Speed Limit"
-msgstr ""
+#: ../hacks/config/glhanoi.xml.h:12
+msgid "Length of disk trails"
+msgstr "Длина следов дисков"
 
-#: hacks/config/goop.xml.h:13
-msgid "Subtractive Colors (transmitted light)"
-msgstr ""
+#: ../hacks/config/glhanoi.xml.h:14 ../hacks/config/pulsar.xml.h:7
+msgid "Enable fog"
+msgstr "Включить туман"
 
-#: hacks/config/goop.xml.h:14
+#: ../hacks/config/glhanoi.xml.h:17 ../hacks/config/pulsar.xml.h:6
+msgid "Enable lighting"
+msgstr "Включить освещение"
+
+#: ../hacks/config/glhanoi.xml.h:18
 msgid ""
-"This draws set of animating, transparent, amoeba-like blobs. The blobs "
-"change shape as they wander around the screen, and they are translucent, so "
-"you can see the lower blobs through the higher ones, and when one passes "
-"over another, their colors merge. I got the idea for this from a cool mouse "
-"pad I have, which achieves the same kind of effect in real life by having "
-"several layers plastic with colored oil between them. Written by Jamie "
-"Zawinski."
+"Solves the Towers of Hanoi puzzle. Move N disks from one pole to another, "
+"one disk at a time, with no disk ever resting on a disk smaller than itself. "
+"https://en.wikipedia.org/wiki/Tower_of_Hanoi Written by Dave Atkinson; 2005."
 msgstr ""
 
-#: hacks/config/goop.xml.h:15
-msgid "Transparent Blobs"
+#: ../hacks/config/glknots.xml.h:1
+msgid "GLKnots"
 msgstr ""
 
-#: hacks/config/goop.xml.h:16
-msgid "XOR Blobs"
-msgstr ""
+#: ../hacks/config/glknots.xml.h:16
+msgid "Segmented"
+msgstr "Пиксельный"
 
-#: hacks/config/grav.xml.h:3
-msgid "Grav"
-msgstr ""
+#: ../hacks/config/glknots.xml.h:17 ../hacks/config/jigsaw.xml.h:12
+#: ../hacks/config/lavalite.xml.h:11 ../hacks/config/mirrorblob.xml.h:14
+#: ../hacks/config/spheremonics.xml.h:8
+#: ../hacks/config/unknownpleasures.xml.h:11
+msgid "Resolution"
+msgstr "Разрешение"
 
-#: hacks/config/grav.xml.h:6
-msgid "Object Trails"
+#: ../hacks/config/glknots.xml.h:25
+msgid ""
+"Generates some twisting 3d knot patterns. Spins 'em around. https://en."
+"wikipedia.org/wiki/Knot_theory Written by Jamie Zawinski; 2003."
 msgstr ""
 
-#: hacks/config/grav.xml.h:7
-msgid "Orbital Decay"
+#: ../hacks/config/glmatrix.xml.h:1
+msgid "GLMatrix"
 msgstr ""
 
-#: hacks/config/grav.xml.h:10
-msgid ""
-"This program draws a simple orbital simulation. If you turn on trails, it "
-"looks kind of like a cloud-chamber photograph. Written by Greg Bowering."
-msgstr ""
+#: ../hacks/config/glmatrix.xml.h:6
+msgid "Glyph density"
+msgstr "Плотность иероглифов"
 
-#: hacks/config/greynetic.xml.h:2
-msgid "Greynetic"
-msgstr ""
+#: ../hacks/config/glmatrix.xml.h:9
+msgid "Glyph speed"
+msgstr "Скорость иероглифов"
+
+#: ../hacks/config/glmatrix.xml.h:11 ../hacks/config/xmatrix.xml.h:4
+msgid "Matrix encoding"
+msgstr "Кодировка Матрицы"
+
+#: ../hacks/config/glmatrix.xml.h:12 ../hacks/config/xmatrix.xml.h:5
+msgid "Binary encoding"
+msgstr "Двоичная кодировка"
+
+#: ../hacks/config/glmatrix.xml.h:13 ../hacks/config/xmatrix.xml.h:6
+msgid "Hexadecimal encoding"
+msgstr "Шестнадцатиричная кодировка"
 
-#: hacks/config/greynetic.xml.h:5
+#: ../hacks/config/glmatrix.xml.h:14 ../hacks/config/xmatrix.xml.h:7
+msgid "Genetic encoding"
+msgstr "Генетическая кодировка"
+
+#: ../hacks/config/glmatrix.xml.h:17
+msgid "Panning"
+msgstr "Панорамирование"
+
+#: ../hacks/config/glmatrix.xml.h:21
 msgid ""
-"This draws random colored and stippled rectangles. Written by Jamie Zawinski."
+"The 3D \"digital rain\" effect, as seen in the title sequence of \"The Matrix"
+"\". See also \"xmatrix\" for a 2D rendering of the similar effect that "
+"appeared on the computer monitors actually *in* the movie. https://en."
+"wikipedia.org/wiki/Matrix_digital_rain Written by Jamie Zawinski; 2003."
 msgstr ""
 
-#: hacks/config/halftone.xml.h:1
-msgid "Delay (Large = low cpu load)"
+#: ../hacks/config/glplanet.xml.h:1
+msgid "GLPlanet"
 msgstr ""
 
-#: hacks/config/halftone.xml.h:2
-msgid "Dot fill factor"
-msgstr ""
+#. #### -no-texture
+#: ../hacks/config/glplanet.xml.h:6
+msgid "Day image"
+msgstr "Дневное изображение"
 
-#: hacks/config/halftone.xml.h:3
-msgid "Dot size"
-msgstr ""
+#: ../hacks/config/glplanet.xml.h:7
+msgid "Night image"
+msgstr "Ночное изображение"
 
-#: hacks/config/halftone.xml.h:4
+#: ../hacks/config/glplanet.xml.h:14
 msgid ""
-"Draws the gravity force in each point on the screen seen through a halftone "
-"dot pattern. The gravity force is calculated from a set of moving mass "
-"points. View it from a distance for best effect. Written by Peter Jaric &lt;"
-"peter@jaric.org&gt;."
+"The Earth, bouncing around in space. If you would like it to display a "
+"different planet, the texture maps that come with \"ssystem\" work well. "
+"Written by David Konerding and Jamie Zawinski; 1998."
 msgstr ""
 
-#: hacks/config/halftone.xml.h:5
-msgid "Gravity points"
+#: ../hacks/config/glschool.xml.h:1
+msgid "GLSchool"
 msgstr ""
 
-#: hacks/config/halftone.xml.h:6
-msgid "Halftone"
-msgstr ""
+#: ../hacks/config/glschool.xml.h:6
+msgid "Fish count"
+msgstr "Количество рыб"
 
-#: hacks/config/halftone.xml.h:10
-msgid "Maximum mass"
-msgstr ""
+#: ../hacks/config/glschool.xml.h:9
+msgid "Avoidance"
+msgstr "Отклонение"
 
-#: hacks/config/halftone.xml.h:11
-msgid "Maximum speed"
-msgstr ""
+#: ../hacks/config/glschool.xml.h:10
+msgid "Velocity matching"
+msgstr "Соответствие скорости"
 
-#: hacks/config/halftone.xml.h:12
-msgid "Minimum mass"
-msgstr ""
+#: ../hacks/config/glschool.xml.h:11
+msgid "Centering"
+msgstr "Центрирование"
 
-#: hacks/config/halftone.xml.h:13
-msgid "Minimum speed"
-msgstr ""
+#: ../hacks/config/glschool.xml.h:12
+msgid "Goal following"
+msgstr "Следование цели"
 
-#: hacks/config/halo.xml.h:1
-msgid "Animate Circles"
-msgstr ""
+#: ../hacks/config/glschool.xml.h:15
+msgid "Draw goal"
+msgstr "Прорисовывать цель"
 
-#: hacks/config/halo.xml.h:3
-msgid "Halo"
+#: ../hacks/config/glschool.xml.h:18
+msgid ""
+"A school of fish, using the classic \"Boids\" algorithm by Craig Reynolds. "
+"https://en.wikipedia.org/wiki/Boids Written by David C. Lambert and Jamie "
+"Zawinski; 2006."
 msgstr ""
 
-#: hacks/config/halo.xml.h:5
-msgid "Number of Circles"
+#: ../hacks/config/glslideshow.xml.h:1
+msgid "GLSlideshow"
 msgstr ""
 
-#: hacks/config/halo.xml.h:7
-msgid "Ramp Mode"
+#: ../hacks/config/glslideshow.xml.h:9
+#, no-c-format
+msgid "50%"
 msgstr ""
 
-#: hacks/config/halo.xml.h:9
-msgid "Seuss Mode"
-msgstr ""
+#: ../hacks/config/glslideshow.xml.h:10
+msgid "Always show at least this much of the image"
+msgstr "Всегда показывать минимум такую часть изображения"
 
-#: hacks/config/halo.xml.h:12
-msgid ""
-"This draws trippy psychedelic circular patterns that hurt to look at. It can "
-"also animate the control-points, but that takes a lot of CPU and bandwidth. "
-"Written by Jamie Zawinski."
+#: ../hacks/config/glslideshow.xml.h:12 ../hacks/config/rd-bomb.xml.h:10
+#: ../hacks/config/rdbomb.xml.h:10 ../hacks/config/substrate.xml.h:15
+#, no-c-format
+msgid "100%"
 msgstr ""
 
-#: hacks/config/helix.xml.h:4
-msgid "Helix"
-msgstr ""
+#: ../hacks/config/glslideshow.xml.h:14
+msgid "Pan/zoom duration"
+msgstr "Продолжительность панорамирования/масштабирования"
+
+#: ../hacks/config/glslideshow.xml.h:17
+msgid "Crossfade duration"
+msgstr "Продолжительность проявления"
 
-#: hacks/config/helix.xml.h:5
+#: ../hacks/config/glslideshow.xml.h:21
 msgid ""
-"This repeatedly generates spirally string-art-ish patterns. Written by Jamie "
-"Zawinski."
+"Loads a random sequence of images and smoothly scans and zooms around in "
+"each, fading from pan to pan. Written by Jamie Zawinski and Mike Oliphant; "
+"2003."
 msgstr ""
 
-#: hacks/config/hopalong.xml.h:3
-msgid "EJK1"
+#: ../hacks/config/glsnake.xml.h:1
+msgid "GLSnake"
 msgstr ""
 
-#: hacks/config/hopalong.xml.h:4
-msgid "EJK2"
-msgstr ""
+#: ../hacks/config/glsnake.xml.h:9
+msgid "Packing"
+msgstr "Сжатие"
 
-#: hacks/config/hopalong.xml.h:5
-msgid "EJK3"
-msgstr ""
+#: ../hacks/config/glsnake.xml.h:10
+msgid "Loose"
+msgstr "Свободное"
 
-#: hacks/config/hopalong.xml.h:6
-msgid "EJK4"
-msgstr ""
+#: ../hacks/config/glsnake.xml.h:12
+msgid "Angular velocity"
+msgstr "Угловая скорость"
 
-#: hacks/config/hopalong.xml.h:7
-msgid "EJK5"
-msgstr ""
+#: ../hacks/config/glsnake.xml.h:14
+msgid "Y angular velocity"
+msgstr "Угловая скорость Y"
 
-#: hacks/config/hopalong.xml.h:8
-msgid "EJK6"
-msgstr ""
+#: ../hacks/config/glsnake.xml.h:15
+msgid "Z angular velocity"
+msgstr "Угловая скорость Z"
 
-#: hacks/config/hopalong.xml.h:11
-msgid "Hopalong"
-msgstr ""
+#: ../hacks/config/glsnake.xml.h:16 ../hacks/config/unicrud.xml.h:11
+msgid "Show titles"
+msgstr "Показывать названия"
 
-#: hacks/config/hopalong.xml.h:12
-msgid "Jong"
+#: ../hacks/config/glsnake.xml.h:20
+#, no-c-format
+msgid ""
+"The \"Rubik's Snake\" puzzle. See also the \"Rubik\" and \"Cube21\" screen "
+"savers. https://en.wikipedia.org/wiki/Rubik%27s_Snake Written by Jamie "
+"Wilkinson, Andrew Bennetts, and Peter Aylett; 2002."
 msgstr ""
 
-#: hacks/config/hopalong.xml.h:16
-msgid "Martin"
+#: ../hacks/config/gltext.xml.h:1
+msgid "GLText"
 msgstr ""
 
-#: hacks/config/hopalong.xml.h:19
-msgid "RR"
-msgstr ""
+#: ../hacks/config/gltext.xml.h:5
+msgid "Display system information"
+msgstr "Показать информацию о версии системы"
 
-#: hacks/config/hopalong.xml.h:20
-msgid "Sine"
-msgstr ""
+#: ../hacks/config/gltext.xml.h:6
+msgid "Display date and time"
+msgstr "Показать дату и время"
+
+#: ../hacks/config/gltext.xml.h:7 ../hacks/config/splitflap.xml.h:13
+msgid "Always face front"
+msgstr "Всегда показывать спереди"
+
+#: ../hacks/config/gltext.xml.h:8 ../hacks/config/splitflap.xml.h:14
+msgid "Spin all the way around"
+msgstr "Вращать во все стороны"
 
-#: hacks/config/hopalong.xml.h:24
+#: ../hacks/config/gltext.xml.h:20
 msgid ""
-"This draws lacy fractal patterns, based on iteration in the imaginary plane, "
-"from a 1986 Scientific American article. Mostly written by Patrick Naughton."
+"Displays a few lines of text spinning around in a solid 3D font. The text "
+"can use strftime() escape codes to display the current date and time. "
+"Written by Jamie Zawinski; 2001."
 msgstr ""
 
-#: hacks/config/hyperball.xml.h:4
-msgid "Hyperball"
+#: ../hacks/config/goop.xml.h:1
+msgid "Goop"
 msgstr ""
 
-#: hacks/config/hyperball.xml.h:5
+#: ../hacks/config/goop.xml.h:9
+msgid "Blobs"
+msgstr "Сгустки"
+
+#: ../hacks/config/goop.xml.h:11
+msgid "Elasticity"
+msgstr "Эластичность"
+
+#: ../hacks/config/goop.xml.h:12
+msgid "Speed limit"
+msgstr "Ограничение скорости"
+
+#: ../hacks/config/goop.xml.h:14
+msgid "Transparent blobs"
+msgstr "Прозрачные сгустки"
+
+#: ../hacks/config/goop.xml.h:15
+msgid "Opaque blobs"
+msgstr "Непрозрачные сгустки"
+
+#: ../hacks/config/goop.xml.h:16
+msgid "XOR blobs"
+msgstr "Сгустки XOR"
+
+#: ../hacks/config/goop.xml.h:17
+msgid "Additive colors (transmitted light)"
+msgstr "Добавление цветов (пропущенный свет)"
+
+#: ../hacks/config/goop.xml.h:18
+msgid "Subtractive colors (reflected light)"
+msgstr "Вычитание цветов (отраженный свет)"
+
+#: ../hacks/config/goop.xml.h:19
 msgid ""
-"Hyperball is to hypercube as dodecahedron is to cube: this displays a 2D "
-"projection of the sequence of 3D objects which are the projections of the 4D "
-"analog to the dodecahedron. Technically, it is a \"120 cell polytope.\" "
-"Written by Joe Keane. See also the \"polytopes\" hack for a more general "
-"version of this using OpenGL."
+"Amoeba-like blobs change shape as they wander around the screen. They are "
+"translucent, so you can see the lower blobs through the higher ones, and "
+"when one passes over another, their colors merge. I got the idea for this "
+"from a mouse pad I had once, which achieved the same kind of effect in real "
+"life by having several layers of plastic with colored oil between them. "
+"Written by Jamie Zawinski; 1997."
 msgstr ""
 
-#: hacks/config/hyperball.xml.h:10 hacks/config/hypercube.xml.h:10
-msgid "XW Rotation"
+#: ../hacks/config/grav.xml.h:1
+msgid "Grav"
 msgstr ""
 
-#: hacks/config/hyperball.xml.h:11 hacks/config/hypercube.xml.h:11
-msgid "XY Rotation"
-msgstr ""
+#: ../hacks/config/grav.xml.h:6
+msgid "Number of objects"
+msgstr "Количество объектов"
 
-#: hacks/config/hyperball.xml.h:12 hacks/config/hypercube.xml.h:12
-msgid "XZ Rotation"
-msgstr ""
+#: ../hacks/config/grav.xml.h:10
+msgid "Orbital decay"
+msgstr "Орбитальное притяжение"
 
-#: hacks/config/hyperball.xml.h:13 hacks/config/hypercube.xml.h:13
-msgid "YW Rotation"
-msgstr ""
+#: ../hacks/config/grav.xml.h:11
+msgid "Object trails"
+msgstr "Количество объектов"
 
-#: hacks/config/hyperball.xml.h:14 hacks/config/hypercube.xml.h:14
-msgid "YZ Rotation"
+#: ../hacks/config/grav.xml.h:13
+msgid ""
+"An orbital simulation. With trails enabled, it looks kind of like a cloud-"
+"chamber photograph. Written by Greg Bowering; 1997."
 msgstr ""
 
-#: hacks/config/hyperball.xml.h:15 hacks/config/hypercube.xml.h:15
-msgid "ZW Rotation"
+#: ../hacks/config/greynetic.xml.h:1
+msgid "Greynetic"
 msgstr ""
 
-#: hacks/config/hypercube.xml.h:4
-msgid "Hypercube"
-msgstr ""
+#: ../hacks/config/greynetic.xml.h:5
+msgid "Grey"
+msgstr "Серость"
 
-#: hacks/config/hypercube.xml.h:9
+#: ../hacks/config/greynetic.xml.h:7
 msgid ""
-"This displays 2D projections of the sequence of 3D objects which are the "
-"projections of the 4D analog to the cube: as a square is composed of four "
-"lines, each touching two others; and a cube is composed of six squares, each "
-"touching four others; a hypercube is composed of eight cubes, each touching "
-"six others. To make it easier to visualize the rotation, it uses a different "
-"color for the edges of each face. Don't think about it too long, or your "
-"brain will melt. Written by Joe Keane, Fritz Mueller, and Jamie Zawinski. "
-"See also the \"polytopes\" hack for a more general version of this using "
-"OpenGL."
+"Colored, stippled and transparent rectangles. Written by Jamie Zawinski; "
+"1992."
 msgstr ""
 
-#: hacks/config/hypertorus.xml.h:1 hacks/config/polytopes.xml.h:1
-msgid "-4.0"
+#: ../hacks/config/halftone.xml.h:1
+msgid "Halftone"
 msgstr ""
 
-#: hacks/config/hypertorus.xml.h:2 hacks/config/polytopes.xml.h:5
-msgid "4.0"
-msgstr ""
+#: ../hacks/config/halftone.xml.h:6
+msgid "Gravity points"
+msgstr "Очки притяжения"
 
-#: hacks/config/hypertorus.xml.h:3
-msgid "4D Hypertorus"
-msgstr ""
+#: ../hacks/config/halftone.xml.h:9
+msgid "Dot size"
+msgstr "Размер точек"
 
-#: hacks/config/hypertorus.xml.h:4
-#, fuzzy
-msgid "Color Wheel"
-msgstr "Color"
+#: ../hacks/config/halftone.xml.h:10 ../hacks/config/metaballs.xml.h:14
+msgid "Big"
+msgstr "Большой"
 
-#: hacks/config/hypertorus.xml.h:5 hacks/config/polytopes.xml.h:10
-#, fuzzy
-msgid "Display Speed"
-msgstr "Режимы экрана"
+#: ../hacks/config/halftone.xml.h:11
+msgid "Dot fill factor"
+msgstr "Фактор заполнения точек"
 
-#: hacks/config/hypertorus.xml.h:7 hacks/config/polytopes.xml.h:12
-msgid "Orthographic 3d"
-msgstr ""
+#: ../hacks/config/halftone.xml.h:13
+msgid "Minimum speed"
+msgstr "Минимальная скорость"
 
-#: hacks/config/hypertorus.xml.h:8 hacks/config/polytopes.xml.h:13
-msgid "Orthographic 4d"
-msgstr ""
+#: ../hacks/config/halftone.xml.h:14
+msgid "Maximum speed"
+msgstr "Максимальная скорость"
 
-#: hacks/config/hypertorus.xml.h:9 hacks/config/polytopes.xml.h:14
-msgid "Perspective 3d"
-msgstr ""
+#: ../hacks/config/halftone.xml.h:15
+msgid "Minimum mass"
+msgstr "Минимальная масса"
 
-#: hacks/config/hypertorus.xml.h:10 hacks/config/polytopes.xml.h:15
-msgid "Perspective 4d"
-msgstr ""
+#: ../hacks/config/halftone.xml.h:16
+msgid "Maximum mass"
+msgstr "Максимальная масса"
 
-#: hacks/config/hypertorus.xml.h:11
-msgid "See-Through Bands"
+#: ../hacks/config/halftone.xml.h:18
+msgid ""
+"A halftone dot pattern in motion. Draws the gravity force in each point on "
+"the screen seen through a halftone dot pattern. The gravity force is "
+"calculated from a set of moving mass points. View it from a distance for "
+"best effect. https://en.wikipedia.org/wiki/Halftone Written by Peter Jaric; "
+"2002."
 msgstr ""
 
-#: hacks/config/hypertorus.xml.h:12
-msgid "See-Through Spirals (1 Spiral)"
+#: ../hacks/config/halo.xml.h:1
+msgid "Halo"
 msgstr ""
 
-#: hacks/config/hypertorus.xml.h:13
-msgid "See-Through Spirals (16 Spirals)"
-msgstr ""
+#: ../hacks/config/halo.xml.h:6
+msgid "Number of circles"
+msgstr "Количество кругов"
 
-#: hacks/config/hypertorus.xml.h:14
-msgid "See-Through Spirals (2 Spirals)"
-msgstr ""
+#: ../hacks/config/halo.xml.h:10
+msgid "Random mode"
+msgstr "Случайный режим"
 
-#: hacks/config/hypertorus.xml.h:15
-msgid "See-Through Spirals (4 Spirals)"
-msgstr ""
+#: ../hacks/config/halo.xml.h:11
+msgid "Seuss mode"
+msgstr "Режим Seuss"
 
-#: hacks/config/hypertorus.xml.h:16
-msgid "See-Through Spirals (8 Spirals)"
-msgstr ""
+#: ../hacks/config/halo.xml.h:12
+msgid "Ramp mode"
+msgstr "Режим Ramp"
 
-#: hacks/config/hypertorus.xml.h:19
-msgid "Solid Object"
-msgstr ""
+#: ../hacks/config/halo.xml.h:13
+msgid "Animate circles"
+msgstr "Анимировать круги"
 
-#: hacks/config/hypertorus.xml.h:20 hacks/config/mirrorblob.xml.h:19
-#: hacks/config/polytopes.xml.h:21 hacks/config/pulsar.xml.h:16
-msgid "Solid Surface"
+#: ../hacks/config/halo.xml.h:15
+msgid ""
+"Circular interference patterns. https://en.wikipedia.org/wiki/Moire_pattern "
+"Written by Jamie Zawinski; 1993."
 msgstr ""
 
-#: hacks/config/hypertorus.xml.h:21
-msgid ""
-"This program shows a rotating Clifford Torus: a torus lying on the \"surface"
-"\" of a 4D hypersphere. Written by Carsten Steger, inspired by Thomas "
-"Banchoff's book \"Beyond the Third Dimension: Geometry, Computer Graphics, "
-"and Higher Dimensions\", Scientific American Library, 1990."
+#: ../hacks/config/helix.xml.h:1
+msgid "Helix"
 msgstr ""
 
-#: hacks/config/hypertorus.xml.h:22 hacks/config/polytopes.xml.h:23
-msgid "Transparent Surface"
+#: ../hacks/config/helix.xml.h:9
+msgid "Spirally string-art-ish patterns. Written by Jamie Zawinski; 1992."
 msgstr ""
 
-#: hacks/config/hypertorus.xml.h:23
-msgid "Two-Sided"
+#: ../hacks/config/hexadrop.xml.h:1
+msgid "Hexadrop"
 msgstr ""
 
-#: hacks/config/hypertorus.xml.h:24 hacks/config/polytopes.xml.h:24
-#, fuzzy
-msgid "WX Rotation Speed"
-msgstr "СкоÑ\80оÑ\81Ñ\82Ñ\8c Ð°Ð½Ð¸Ð¼Ð°Ñ\86ии"
+#: ../hacks/config/hexadrop.xml.h:9 ../hacks/config/penrose.xml.h:9
+#: ../hacks/config/twang.xml.h:15
+msgid "Tile size"
+msgstr "РазмеÑ\80 Ð¿Ð»Ð¸Ñ\82ки"
 
-#: hacks/config/hypertorus.xml.h:25 hacks/config/polytopes.xml.h:25
-#, fuzzy
-msgid "WY Rotation Speed"
-msgstr "Скорость анимации"
+#: ../hacks/config/hexadrop.xml.h:11 ../hacks/config/klein.xml.h:2
+msgid "Random shape"
+msgstr "Случайные фигуры"
 
-#: hacks/config/hypertorus.xml.h:26 hacks/config/polytopes.xml.h:26
-#, fuzzy
-msgid "WZ Rotation Speed"
-msgstr "Скорость анимации"
+#: ../hacks/config/hexadrop.xml.h:12
+msgid "Triangles"
+msgstr "Треугольники"
 
-#: hacks/config/hypertorus.xml.h:27 hacks/config/polytopes.xml.h:27
-#, fuzzy
-msgid "Wireframe Mesh"
-msgstr "Каркасное изображение"
+#: ../hacks/config/hexadrop.xml.h:13
+msgid "Squares"
+msgstr "Квадраты"
 
-#: hacks/config/hypertorus.xml.h:28 hacks/config/polytopes.xml.h:28
-#, fuzzy
-msgid "XY Rotation Speed"
-msgstr "Скорость анимации"
+#: ../hacks/config/hexadrop.xml.h:14
+msgid "Hexagons"
+msgstr "Шестиугольники"
 
-#: hacks/config/hypertorus.xml.h:29 hacks/config/polytopes.xml.h:29
-#, fuzzy
-msgid "XZ Rotation Speed"
-msgstr "Скорость анимации"
+#: ../hacks/config/hexadrop.xml.h:15
+msgid "Octagons"
+msgstr "Восьмиугольники"
 
-#: hacks/config/hypertorus.xml.h:30 hacks/config/polytopes.xml.h:30
-#, fuzzy
-msgid "YZ Rotation Speed"
-msgstr "Скорость анимации"
+#: ../hacks/config/hexadrop.xml.h:16
+msgid "Random speed"
+msgstr "Случайная скорость"
 
-#: hacks/config/ifs.xml.h:1
-msgid "2"
-msgstr ""
+#: ../hacks/config/hexadrop.xml.h:17
+msgid "Uniform speed"
+msgstr "Постоянная скорость"
 
-#: hacks/config/ifs.xml.h:2
-msgid "Blend"
-msgstr ""
+#: ../hacks/config/hexadrop.xml.h:18
+msgid "Non-uniform speed"
+msgstr "Непостоянная скорость"
 
-#: hacks/config/ifs.xml.h:3
-#, fuzzy
-msgid "Detail"
-msgstr "По умолчанию"
+#: ../hacks/config/hexadrop.xml.h:19
+msgid "Random sync"
+msgstr "Случайная синхронизация"
 
-#: hacks/config/ifs.xml.h:5
-#, fuzzy
-msgid "Function"
-msgstr "Продолжительность"
+#: ../hacks/config/hexadrop.xml.h:20
+msgid "Synchronized"
+msgstr "Синхронизировано"
 
-#: hacks/config/ifs.xml.h:6
-msgid "Functions"
-msgstr ""
+#: ../hacks/config/hexadrop.xml.h:21
+msgid "Non-synchronized"
+msgstr "Не синхронизировано"
 
-#: hacks/config/ifs.xml.h:7
-msgid "IFS"
+#: ../hacks/config/hexadrop.xml.h:23
+msgid ""
+"A grid of hexagons or other shapes, with tiles dropping out. https://en."
+"wikipedia.org/wiki/Tiling_by_regular_polygons Written by Jamie Zawinski; "
+"2013."
 msgstr ""
 
-#: hacks/config/ifs.xml.h:9
-#, fuzzy
-msgid "Number of Colours"
-msgstr "Количество цветов"
-
-#: hacks/config/ifs.xml.h:11 hacks/config/phosphor.xml.h:6
-msgid "Scale"
+#: ../hacks/config/hexstrut.xml.h:1
+msgid "Hexstrut"
 msgstr ""
 
-#: hacks/config/ifs.xml.h:12
-#, fuzzy
-msgid "Single"
-msgstr "DirectColor"
+#: ../hacks/config/hexstrut.xml.h:9
+msgid "Hexagon Size"
+msgstr "Размер шестиугольников"
 
-#: hacks/config/ifs.xml.h:15
+#: ../hacks/config/hexstrut.xml.h:12
+msgid "Line Thickness"
+msgstr "Толщина линий"
+
+#: ../hacks/config/hexstrut.xml.h:18
 msgid ""
-"This one draws spinning, colliding iterated-function-system images. Note "
-"that the \"quality\" parameter is exponential. Number of points drawn is "
-"functions^detail. The number of colours is only used in Blend mode to "
-"provide a palette to create the base colours. These are then blended "
-"together in a non-colourmap friendly fashion. Written by Chris Le Sueur."
+"A grid of hexagons composed of rotating Y-shaped struts. Waves of rotation "
+"and color changes randomly propagate across the plane. Written by Jamie "
+"Zawinski; 2016."
 msgstr ""
 
-#: hacks/config/ifs.xml.h:16
-msgid "Translate"
+#: ../hacks/config/hilbert.xml.h:1
+msgid "Hilbert"
 msgstr ""
 
-#: hacks/config/imsmap.xml.h:3
-msgid "Brightness Gradients"
-msgstr ""
+#: ../hacks/config/hilbert.xml.h:2
+msgid "2D or 3D"
+msgstr "2D или 3D"
 
-#: hacks/config/imsmap.xml.h:7
-msgid "Hue Gradients"
+#: ../hacks/config/hilbert.xml.h:3
+msgid "2D"
 msgstr ""
 
-#: hacks/config/imsmap.xml.h:8
-msgid "IMSmap"
+#: ../hacks/config/hilbert.xml.h:4
+msgid "3D"
 msgstr ""
 
-#: hacks/config/imsmap.xml.h:12
-msgid "Saturation Gradients"
+#: ../hacks/config/hilbert.xml.h:5
+msgid "Open or closed paths"
+msgstr "Открытые или закрытые пути"
+
+#: ../hacks/config/hilbert.xml.h:6
+msgid "Closed"
+msgstr "Закрытые"
+
+#: ../hacks/config/hilbert.xml.h:7
+msgid "Open"
+msgstr "Открытые"
+
+#.
+#. On a 2.93 gHz iMac i7, I get these rates with -delay 0:
+#.
+#. detail 3:  invisible
+#. detail 4:  barely visible
+#. detail 5:  1000+ fps, looks like noise at -delay 0, ok at -delay 20000
+#. detail 8:  ~700+ fps
+#. detail 9:  ~400 fps
+#. detail 10: ~300 fps
+#. detail 11: ~100 fps
+#. detail 12:  ~50 fps
+#. detail 13:  ~17 fps
+#. detail 14:   ~8 fps
+#. detail 15:   ~2 fps
+#.
+#. With the default -delay, CPU load only starts causing the frame rate
+#. to drop below 30 fps detail 12 or higher.
+#.
+#: ../hacks/config/hilbert.xml.h:12 ../hacks/config/hypnowheel.xml.h:12
+#: ../hacks/config/ifs.xml.h:23
+msgid "2"
 msgstr ""
 
-#: hacks/config/imsmap.xml.h:14
+#: ../hacks/config/hilbert.xml.h:13
+msgid "Recursion levels"
+msgstr "Уровни рекурсии"
+
+#: ../hacks/config/hilbert.xml.h:22
 msgid ""
-"This generates random cloud-like patterns. It looks quite different in "
-"monochrome and color. The basic idea is to take four points on the edge of "
-"the image, and assign each a random ``elevation''. Then find the point "
-"between them, and give it a value which is the average of the other four, "
-"plus some small random offset. Then coloration is done based on elevation. "
-"The color selection is done by binding the elevation to either hue, "
-"saturation, or brightness, and assigning random values to the others. The "
-"``brightness'' mode tends to yield cloudlike patterns, and the others tend "
-"to generate images that look like heat-maps or CAT-scans. Written by Juergen "
-"Nickelsen and Jamie Zawinski."
+"The recursive Hilbert space-filling curve, both 2D and 3D variants. It "
+"incrementally animates the growth and recursion to the maximum depth, then "
+"unwinds it back. The Hilbert path is a single contiguous line that can fill "
+"a volume without crossing itself. As a data structure, Hilbert paths are "
+"useful because ordering along the curve preserves locality: points that are "
+"close together along the curve are also close together in space. The "
+"converse is often, but not always, true. The coloration reflects this. "
+"https://en.wikipedia.org/wiki/Hilbert_curve Written by Jamie Zawinski; 2011."
 msgstr ""
 
-#: hacks/config/interaggregate.xml.h:2
-msgid "Interaggregate"
+#: ../hacks/config/hopalong.xml.h:1
+msgid "Hopalong"
 msgstr ""
 
-#: hacks/config/interaggregate.xml.h:3 hacks/config/intermomentary.xml.h:3
-#, fuzzy
-msgid "Number of Discs"
-msgstr "Ð\9aолиÑ\87еÑ\81Ñ\82во цветов"
+#: ../hacks/config/hopalong.xml.h:8 ../hacks/config/interference.xml.h:17
+#: ../hacks/config/qix.xml.h:11 ../hacks/config/wander.xml.h:10
+msgid "Color contrast"
+msgstr "Ð\9aонÑ\82Ñ\80аÑ\81Ñ\82 цветов"
 
-#: hacks/config/interaggregate.xml.h:6
-msgid ""
-"The Intersection Aggregate is a fun visualization defining the relationships "
-"between objects with Casey Reas, William Ngan, and Robert Hodgin. "
-"Commissioned for display at the Whitney Museum of American Art. A surface "
-"filled with 100 medium to small sized circles. Each circle has a different "
-"size and direction, but moves at the same slow rate. Display: A. The "
-"instantaneous intersections of the circles. B. The aggregate intersections "
-"of the circles. Ported to XScreensaver from the art project \"InterAggregate"
-"\" at http://www.complexification.net"
+#: ../hacks/config/hopalong.xml.h:12
+msgid "Sine"
 msgstr ""
 
-#: hacks/config/interference.xml.h:1 hacks/config/rotzoomer.xml.h:1
-#, fuzzy
-msgid "0"
-msgstr "100%"
-
-#: hacks/config/interference.xml.h:2
-msgid "360"
+#: ../hacks/config/hopalong.xml.h:13
+msgid "Martin"
 msgstr ""
 
-#: hacks/config/interference.xml.h:3
-msgid "Anim Speed"
+#: ../hacks/config/hopalong.xml.h:15
+msgid "Jong"
 msgstr ""
 
-#: hacks/config/interference.xml.h:4
-msgid ""
-"Another color-field hack, this one works by computing decaying sinusoidal "
-"waves, and allowing them to interfere with each other as their origins move. "
-"Written by Hannu Mallat."
+#: ../hacks/config/hopalong.xml.h:16
+msgid "RR"
 msgstr ""
 
-#: hacks/config/interference.xml.h:9
-msgid "Hue"
+#: ../hacks/config/hopalong.xml.h:17
+msgid "EJK1"
 msgstr ""
 
-#: hacks/config/interference.xml.h:10
-msgid "Interference"
+#: ../hacks/config/hopalong.xml.h:18
+msgid "EJK2"
 msgstr ""
 
-#: hacks/config/interference.xml.h:13 hacks/config/t3d.xml.h:9
-#: hacks/config/xearth.xml.h:11 hacks/config/zoom.xml.h:5
-msgid "Magnification"
+#: ../hacks/config/hopalong.xml.h:19
+msgid "EJK3"
 msgstr ""
 
-#: hacks/config/interference.xml.h:16
-msgid "Number of Waves"
+#: ../hacks/config/hopalong.xml.h:20
+msgid "EJK4"
 msgstr ""
 
-#: hacks/config/interference.xml.h:20
-msgid "Wave Size"
+#: ../hacks/config/hopalong.xml.h:21
+msgid "EJK5"
 msgstr ""
 
-#: hacks/config/intermomentary.xml.h:2
-msgid "Intermomentary"
+#: ../hacks/config/hopalong.xml.h:22
+msgid "EJK6"
 msgstr ""
 
-#: hacks/config/intermomentary.xml.h:6
+#: ../hacks/config/hopalong.xml.h:24
 msgid ""
-"The Intersection Momentary is a fun visualization defining the relationships "
-"between objects with Casey Reas, William Ngan, and Robert Hodgin. "
-"Commissioned for display at the Whitney Museum of American Art. A surface "
-"filled with 100 medium to small sized circles. Each circle has a different "
-"size and direction, but moves at the same slow rate. Display: A. The "
-"instantaneous intersections of the circles. B. The aggregate intersections "
-"of the circles. Ported to XScreensaver from the art project \"InterMomentary"
-"\" at http://www.complexification.net"
+"Lacy fractal patterns based on iteration in the imaginary plane, from a 1986 "
+"Scientific American article. See also the \"Discrete\" screen saver. Written "
+"by Patrick Naughton; 1992."
 msgstr ""
 
-#: hacks/config/jigglypuff.xml.h:2
-msgid "Chrome"
+#: ../hacks/config/hydrostat.xml.h:1
+msgid "Hydrostat"
 msgstr ""
 
-#: hacks/config/jigglypuff.xml.h:3
-msgid "Clown barf"
-msgstr ""
+#: ../hacks/config/hydrostat.xml.h:9
+msgid "Number of squid"
+msgstr "Количество кальмаров"
 
-#: hacks/config/jigglypuff.xml.h:5
-#, fuzzy
-msgid "Cycle"
-msgstr "Смена через"
+#: ../hacks/config/hydrostat.xml.h:12
+msgid "Head size"
+msgstr "Размер головы"
 
-#: hacks/config/jigglypuff.xml.h:7
-msgid "Flower box"
-msgstr ""
+#: ../hacks/config/hydrostat.xml.h:15
+msgid "Number of tentacles"
+msgstr "Количество щупалец"
 
-#: hacks/config/jigglypuff.xml.h:9
-msgid "Inertial damping"
-msgstr ""
+#: ../hacks/config/hydrostat.xml.h:20
+msgid "Length of tentacles"
+msgstr "Длина щупалец"
 
-#: hacks/config/jigglypuff.xml.h:10
-msgid "JigglyPuff"
-msgstr ""
+#: ../hacks/config/hydrostat.xml.h:22
+msgid "Weak"
+msgstr "Слабое"
 
-#: hacks/config/jigglypuff.xml.h:14
-#, fuzzy
-msgid "Rotation speed"
-msgstr "Скорость анимации"
+#: ../hacks/config/hydrostat.xml.h:24 ../hacks/config/jigglypuff.xml.h:20
+msgid "Strong"
+msgstr "Сильное"
 
-#: hacks/config/jigglypuff.xml.h:17 hacks/config/sphere.xml.h:7
-msgid "Sphere"
-msgstr ""
+#: ../hacks/config/hydrostat.xml.h:25
+msgid "Current"
+msgstr "Течение"
 
-#: hacks/config/jigglypuff.xml.h:18
-msgid "Sphere strength"
-msgstr ""
+#: ../hacks/config/hydrostat.xml.h:26
+msgid "Viscosity"
+msgstr "Вязкость"
 
-#: hacks/config/jigglypuff.xml.h:19
-#, fuzzy
-msgid "Spookiness"
-msgstr "Сплайны"
+#: ../hacks/config/hydrostat.xml.h:27
+msgid "Pulse"
+msgstr "Пульсация"
 
-#: hacks/config/jigglypuff.xml.h:20
-msgid "Spoooooky"
+#: ../hacks/config/hydrostat.xml.h:30
+msgid ""
+"Wiggly squid or jellyfish with many tentacles. A muscular hydrostat is a "
+"biological structure used to move its host about, consisting of muscles with "
+"no skeletal support. It performs its hydraulic movement without fluid in a "
+"separate compartment, as in a hydrostatic skeleton. https://en.wikipedia.org/"
+"wiki/Muscular_hydrostat Written by Justin Windle and Jamie Zawinski; 2016."
 msgstr ""
 
-#: hacks/config/jigglypuff.xml.h:21 hacks/config/polyhedra.xml.h:148
-#: hacks/config/sballs.xml.h:16
-msgid "Tetrahedron"
+#: ../hacks/config/hyperball.xml.h:1
+msgid "HyperBall"
 msgstr ""
 
-#: hacks/config/jigglypuff.xml.h:22
-msgid ""
-"This little gem does bad things with quasi-spherical objects. The gist of it "
-"is that you have what is, structurally, a tetrahedron with tesselated faces. "
-"the vertices on these faces have forces on them in the form of one "
-"proportional to their distance from the surface of a sphere, and one which "
-"is proportional to how far they differ from some ideal distance from their "
-"neighbors. They also have inertia. The forces and distance are parameters "
-"and there are also a couple of visual parameters. The resulting effect can "
-"range from a shape that does nothing, to a frenetic polygon storm. Somewhere "
-"in between there it usually manifests as a blob that jiggles in a kind of "
-"disturbing manner. woo. It doesn't matter, however. You should just pick "
-"'random'. It overrides all the other options, except for fps, delay and "
-"complexity. By Keith Macleod"
+#: ../hacks/config/hyperball.xml.h:10 ../hacks/config/hypercube.xml.h:10
+msgid "XW rotation"
 msgstr ""
 
-#: hacks/config/jigglypuff.xml.h:23
-msgid "Vertex-vertex behavior"
+#: ../hacks/config/hyperball.xml.h:12 ../hacks/config/hypercube.xml.h:12
+msgid "XY rotation"
 msgstr ""
 
-#: hacks/config/jigglypuff.xml.h:24
-msgid "Vertex-vertex force"
+#: ../hacks/config/hyperball.xml.h:13 ../hacks/config/hypercube.xml.h:13
+msgid "XZ rotation"
 msgstr ""
 
-#: hacks/config/jigglypuff.xml.h:26
-msgid "collapse"
+#: ../hacks/config/hyperball.xml.h:14 ../hacks/config/hypercube.xml.h:14
+msgid "YW rotation"
 msgstr ""
 
-#: hacks/config/jigglypuff.xml.h:27
-msgid "expand"
+#: ../hacks/config/hyperball.xml.h:15 ../hacks/config/hypercube.xml.h:15
+msgid "YZ rotation"
 msgstr ""
 
-#: hacks/config/jigglypuff.xml.h:28
-#, fuzzy
-msgid "none"
-msgstr "Отсутствует"
-
-#: hacks/config/jigglypuff.xml.h:29
-#, fuzzy
-msgid "strong"
-msgstr "Длинный"
-
-#: hacks/config/jigsaw.xml.h:4
-msgid "Jigsaw"
+#: ../hacks/config/hyperball.xml.h:16 ../hacks/config/hypercube.xml.h:16
+msgid "ZW rotation"
 msgstr ""
 
-#: hacks/config/jigsaw.xml.h:6
-msgid "Solved Duration"
+#: ../hacks/config/hyperball.xml.h:17
+msgid ""
+"This screen saver was removed from the XScreenSaver distribution as of "
+"version 5.10. It has been replaced by the more general \"Polytopes\" screen "
+"saver, which can display this object as well as others. The Polytopes \"120-"
+"cell\" object corresponds to this one. Hyperball is to hypercube as "
+"dodecahedron is to cube: this displays a 2D projection of the sequence of 3D "
+"objects which are the projections of the 4D analog to the dodecahedron. "
+"Technically, it is a \"120 cell polytope\". https://en.wikipedia.org/wiki/"
+"Hypercube https://en.wikipedia.org/wiki/Regular_polytope Written by Joe "
+"Keane; 2000."
 msgstr ""
 
-#: hacks/config/jigsaw.xml.h:8
-msgid ""
-"This grabs a screen image, carves it up into a jigsaw puzzle, shuffles it, "
-"and then solves the puzzle. This works especially well when you feed it an "
-"external video signal instead of letting it grab the screen image (actually, "
-"I guess this is generally true...) When it is grabbing a video image, it is "
-"sometimes pretty hard to guess what the image is going to look like once the "
-"puzzle is solved. Written by Jamie Zawinski."
+#: ../hacks/config/hypercube.xml.h:1
+msgid "HyperCube"
 msgstr ""
 
-#: hacks/config/juggle.xml.h:1
-msgid "Draws a juggling stick-man. Written by Tim Auckland."
+#: ../hacks/config/hypercube.xml.h:17
+msgid ""
+"This screen saver was removed from the XScreenSaver distribution as of "
+"version 5.10. It has been replaced by the more general \"Polytopes\" screen "
+"saver, which can display this object as well as others. This displays 2D "
+"projections of the sequence of 3D objects which are the projections of the "
+"4D analog to the cube: as a square is composed of four lines, each touching "
+"two others; and a cube is composed of six squares, each touching four "
+"others; a hypercube is composed of eight cubes, each touching six others. To "
+"make it easier to visualize the rotation, it uses a different color for the "
+"edges of each face. Don't think about it too long, or your brain will melt. "
+"https://en.wikipedia.org/wiki/Hypercube https://en.wikipedia.org/wiki/"
+"Tesseract https://en.wikipedia.org/wiki/Regular_polytope Written by Joe "
+"Keane, Fritz Mueller, and Jamie Zawinski; 1992."
 msgstr ""
 
-#: hacks/config/juggle.xml.h:3
-msgid "Juggle"
+#: ../hacks/config/hypertorus.xml.h:1
+msgid "Hypertorus"
 msgstr ""
 
-#: hacks/config/juggle.xml.h:6
-#, fuzzy
-msgid "Performance Length"
-msgstr "Ð\94линна Ñ\81леда"
+#: ../hacks/config/hypertorus.xml.h:7 ../hacks/config/mismunch.xml.h:12
+#: ../hacks/config/munch.xml.h:15 ../hacks/config/winduprobot.xml.h:16
+msgid "Solid"
+msgstr "СплоÑ\88ной"
 
-#: hacks/config/juggle.xml.h:11
-msgid "Use Pattern "
+#: ../hacks/config/hypertorus.xml.h:9 ../hacks/config/klein.xml.h:16
+#: ../hacks/config/projectiveplane.xml.h:7 ../hacks/config/romanboy.xml.h:19
+msgid "Solid object"
+msgstr "Сплошной объект"
+
+#: ../hacks/config/hypertorus.xml.h:10
+msgid "Transparent bands"
+msgstr "Прозрачные ленты"
+
+#: ../hacks/config/hypertorus.xml.h:11
+msgid "1 transparent spiral"
+msgstr "1 прозрачная спираль"
+
+#: ../hacks/config/hypertorus.xml.h:12
+msgid "2 transparent spirals"
+msgstr "2 прозрачных спирали"
+
+#: ../hacks/config/hypertorus.xml.h:13
+msgid "4 transparent spirals"
+msgstr "4 прозрачных спирали"
+
+#: ../hacks/config/hypertorus.xml.h:14
+msgid "8 transparent spirals"
+msgstr "8 прозрачных спиралей"
+
+#: ../hacks/config/hypertorus.xml.h:15
+msgid "16 Transparent spirals"
+msgstr "16 прозрачных спиралей"
+
+#: ../hacks/config/hypertorus.xml.h:16 ../hacks/config/klein.xml.h:19
+#: ../hacks/config/projectiveplane.xml.h:11 ../hacks/config/romanboy.xml.h:23
+msgid "Two-sided"
+msgstr "Двусторонний"
+
+#: ../hacks/config/hypertorus.xml.h:17
+msgid "Color wheel"
+msgstr "Цветное колесо"
+
+#: ../hacks/config/hypertorus.xml.h:18 ../hacks/config/klein.xml.h:23
+#: ../hacks/config/polytopes.xml.h:14 ../hacks/config/projectiveplane.xml.h:16
+msgid "Perspective 3D"
+msgstr "Перспективное 3D"
+
+#: ../hacks/config/hypertorus.xml.h:19 ../hacks/config/klein.xml.h:24
+#: ../hacks/config/polytopes.xml.h:15 ../hacks/config/projectiveplane.xml.h:17
+msgid "Orthographic 3D"
+msgstr "Ортографическое 3D"
+
+#: ../hacks/config/hypertorus.xml.h:20 ../hacks/config/klein.xml.h:26
+#: ../hacks/config/polytopes.xml.h:16 ../hacks/config/projectiveplane.xml.h:19
+msgid "Perspective 4D"
+msgstr "Перспективное 4D"
+
+#: ../hacks/config/hypertorus.xml.h:21 ../hacks/config/klein.xml.h:27
+#: ../hacks/config/polytopes.xml.h:17 ../hacks/config/projectiveplane.xml.h:20
+msgid "Orthographic 4D"
+msgstr "Ортографическое 4D"
+
+#: ../hacks/config/hypertorus.xml.h:22 ../hacks/config/klein.xml.h:28
+#: ../hacks/config/polytopes.xml.h:19 ../hacks/config/romanboy.xml.h:29
+msgid "-4.0"
 msgstr ""
 
-#: hacks/config/juggle.xml.h:12
-msgid "turn on/off Balls."
-msgstr ""
+#: ../hacks/config/hypertorus.xml.h:23 ../hacks/config/klein.xml.h:29
+#: ../hacks/config/polytopes.xml.h:20
+msgid "WX rotation speed"
+msgstr "Скорость вращения WX"
 
-#: hacks/config/juggle.xml.h:13
-msgid "turn on/off Bowling Balls."
+#: ../hacks/config/hypertorus.xml.h:24 ../hacks/config/klein.xml.h:30
+#: ../hacks/config/polytopes.xml.h:21 ../hacks/config/romanboy.xml.h:31
+msgid "4.0"
 msgstr ""
 
-#: hacks/config/juggle.xml.h:14
-#, fuzzy
-msgid "turn on/off Clubs."
-msgstr "Ð\9aолиÑ\87еÑ\81Ñ\82во Ñ\86веÑ\82ов"
+#: ../hacks/config/hypertorus.xml.h:25 ../hacks/config/klein.xml.h:31
+#: ../hacks/config/polytopes.xml.h:22
+msgid "WY rotation speed"
+msgstr "СкоÑ\80оÑ\81Ñ\82Ñ\8c Ð²Ñ\80аÑ\89ениÑ\8f WY"
 
-#: hacks/config/juggle.xml.h:15
-msgid "turn on/off Flaming Torches."
-msgstr ""
+#: ../hacks/config/hypertorus.xml.h:26 ../hacks/config/klein.xml.h:32
+#: ../hacks/config/polytopes.xml.h:23
+msgid "WZ rotation speed"
+msgstr "Скорость вращения WZ"
 
-#: hacks/config/juggle.xml.h:16
-msgid "turn on/off Knives."
-msgstr ""
+#: ../hacks/config/hypertorus.xml.h:27 ../hacks/config/klein.xml.h:33
+#: ../hacks/config/polytopes.xml.h:27
+msgid "XY rotation speed"
+msgstr "Скорость вращения XY"
 
-#: hacks/config/juggle.xml.h:17
-msgid "turn on/off Rings."
-msgstr ""
+#: ../hacks/config/hypertorus.xml.h:28 ../hacks/config/klein.xml.h:34
+#: ../hacks/config/polytopes.xml.h:28
+msgid "XZ rotation speed"
+msgstr "Скорость вращения XZ"
 
-#: hacks/config/juggle.xml.h:18
-msgid "turn on/off pattern descriptions."
-msgstr ""
+#: ../hacks/config/hypertorus.xml.h:29 ../hacks/config/klein.xml.h:35
+#: ../hacks/config/polytopes.xml.h:29
+msgid "YZ rotation speed"
+msgstr "Скорость вращения YZ"
 
-#: hacks/config/juggler3d.xml.h:1
+#: ../hacks/config/hypertorus.xml.h:30
 msgid ""
-"3D simulation of a juggler performing with balls, clubs and rings. Written "
-"by Brian Apps and partially based on his Win32 Juggle Saver program."
+"A Clifford Torus: a torus lying on the \"surface\" of a 4D hypersphere. "
+"Inspired by Thomas Banchoff's book \"Beyond the Third Dimension: Geometry, "
+"Computer Graphics, and Higher Dimensions\", Scientific American Library, "
+"1990. https://en.wikipedia.org/wiki/N-sphere https://en.wikipedia.org/wiki/"
+"Clifford_torus https://en.wikipedia.org/wiki/Regular_polytope Written by "
+"Carsten Steger; 2003."
 msgstr ""
 
-#: hacks/config/juggler3d.xml.h:3
-msgid "Juggler Horizontal Speed"
+#: ../hacks/config/hypnowheel.xml.h:1
+msgid "Hypnowheel"
 msgstr ""
 
-#: hacks/config/juggler3d.xml.h:4
-msgid "Juggler Spin Speed"
-msgstr ""
+#: ../hacks/config/hypnowheel.xml.h:7
+msgid "Symmetric twisting"
+msgstr "Симметричное вращение"
 
-#: hacks/config/juggler3d.xml.h:5
-msgid "Juggler3D"
+#: ../hacks/config/hypnowheel.xml.h:11 ../hacks/config/intermomentary.xml.h:5
+msgid "50"
 msgstr ""
 
-#: hacks/config/juggler3d.xml.h:6
-#, fuzzy
-msgid "Juggling Speed"
-msgstr "Скорость решения"
+#: ../hacks/config/hypnowheel.xml.h:15
+msgid "Twistiness"
+msgstr "Наклон"
 
-#: hacks/config/juggler3d.xml.h:7
-msgid "Max Height"
+#: ../hacks/config/hypnowheel.xml.h:17
+msgid ""
+"A overlapping, translucent spiral patterns. The tightness of their spirals "
+"fluctuates in and out. https://en.wikipedia.org/wiki/Moire_pattern Written "
+"by Jamie Zawinski; 2008."
 msgstr ""
 
-#: hacks/config/juggler3d.xml.h:8
-msgid "Max Objects"
+#: ../hacks/config/ifs.xml.h:1
+msgid "IFS"
 msgstr ""
 
-#: hacks/config/juggler3d.xml.h:9
-msgid "Min Height"
-msgstr ""
+#: ../hacks/config/ifs.xml.h:24
+msgid "Number of functions"
+msgstr "Количество функций"
 
-#: hacks/config/juggler3d.xml.h:10
-msgid "Min Objects"
+#: ../hacks/config/ifs.xml.h:25
+msgid "6"
 msgstr ""
 
-#: hacks/config/julia.xml.h:3 hacks/config/rorschach.xml.h:4
-msgid "Iterations"
-msgstr ""
+#: ../hacks/config/ifs.xml.h:26
+msgid "Detail"
+msgstr "Деталь"
 
-#: hacks/config/julia.xml.h:4
-msgid "Julia"
-msgstr ""
+#: ../hacks/config/ifs.xml.h:65
+msgid "Translate"
+msgstr "Перевод"
 
-#: hacks/config/julia.xml.h:11
-msgid ""
-"This one draws spinning, animating (are you detecting a pattern here yet?) "
-"explorations of the Julia set. You've probably seen static images of this "
-"fractal form before, but it's a lot of fun to watch in motion as well. One "
-"interesting thing is that there is a small swinging dot passing in front of "
-"the image, which indicates the control point from which the rest of the "
-"image was generated. Written by Sean McCullough."
-msgstr ""
+#: ../hacks/config/ifs.xml.h:66
+msgid "Scale"
+msgstr "Масштаб"
 
-#: hacks/config/kaleidescope.xml.h:1
+#: ../hacks/config/ifs.xml.h:69
 msgid ""
-"Another clone of an ancient meme, consisting largely of frenetic rotational "
-"motion of colored lines. This one is by Ron Tapia. The motion is nice, but I "
-"think it needs more solids, or perhaps just brighter colors. More variations "
-"in the rotational speed might help, too."
+"Clouds of iterated function systems spin and collide. Note that the \"Detail"
+"\" parameter is exponential. Number of points drawn is functions^detail. "
+"https://en.wikipedia.org/wiki/Iterated_function_system Written by Chris Le "
+"Sueur and Robby Griffin; 1997."
 msgstr ""
 
-#: hacks/config/kaleidescope.xml.h:4
-msgid "Kaleidescope"
+#: ../hacks/config/imsmap.xml.h:1
+msgid "IMSMap"
 msgstr ""
 
-#: hacks/config/kaleidescope.xml.h:6 hacks/config/qix.xml.h:18
-msgid "Segments"
-msgstr ""
+#: ../hacks/config/imsmap.xml.h:5
+msgid "1 Second"
+msgstr "1 секунда"
 
-#: hacks/config/kaleidescope.xml.h:9
-msgid "Symmetry"
-msgstr ""
+#: ../hacks/config/imsmap.xml.h:7
+msgid "1 Minute"
+msgstr "1 минута"
 
-#: hacks/config/kaleidescope.xml.h:10
-msgid "Trails"
-msgstr ""
+#: ../hacks/config/imsmap.xml.h:15
+msgid "Hue gradients"
+msgstr "Градиенты оттенков"
 
-#: hacks/config/klein.xml.h:3
-msgid "Klein"
-msgstr ""
+#: ../hacks/config/imsmap.xml.h:16
+msgid "Saturation gradients"
+msgstr "Градиенты насыщенности"
 
-#: hacks/config/klein.xml.h:10
+#: ../hacks/config/imsmap.xml.h:17
+msgid "Brightness gradients"
+msgstr "Градиенты яркости"
+
+#: ../hacks/config/imsmap.xml.h:19
 msgid ""
-"This draws a visualization of a Klein bottle or some other interesting "
-"parametric surfaces. Written by Andrey Mirtchovski."
+"Cloud-like patterns. The idea is to take four points on the edge of the "
+"image, and assign each a random \"elevation\". Then find the point between "
+"them, and give it a value which is the average of the other four, plus some "
+"small random offset. Coloration is done based on elevation. Written by "
+"Juergen Nickelsen and Jamie Zawinski; 1992."
 msgstr ""
 
-#: hacks/config/klein.xml.h:11
-msgid "Use Randomized Surfaces and Primitives"
+#: ../hacks/config/interaggregate.xml.h:1
+msgid "Interaggregate"
 msgstr ""
 
-#: hacks/config/klein.xml.h:12
-msgid "Wander Around the Screen"
-msgstr ""
+#: ../hacks/config/interaggregate.xml.h:6
+#: ../hacks/config/intermomentary.xml.h:6
+msgid "Number of discs"
+msgstr "Количество дисков"
 
-#: hacks/config/kumppa.xml.h:5
-msgid "Kumppa"
+#: ../hacks/config/interaggregate.xml.h:9
+msgid ""
+"Pale pencil-like scribbles slowly fill the screen. A surface is filled with "
+"a hundred medium to small sized circles. Each circle has a different size "
+"and direction, but moves at the same slow rate. Displays the instantaneous "
+"intersections of the circles as well as the aggregate intersections of the "
+"circles. Though actually it doesn't look like circles at all! Written by "
+"Casey Reas, William Ngan, Robert Hodgin, and Jamie Zawinski; 2004."
 msgstr ""
 
-#: hacks/config/kumppa.xml.h:7
-msgid "Randomize"
+#: ../hacks/config/interference.xml.h:1
+msgid "Interference"
 msgstr ""
 
-#: hacks/config/kumppa.xml.h:10
-msgid ""
-"Spiraling, spinning, and very, very fast splashes of color rush toward the "
-"screen. Written by Teemu Suutari."
+#: ../hacks/config/interference.xml.h:9
+msgid "Wave size"
+msgstr "Размер волны"
+
+#: ../hacks/config/interference.xml.h:12
+msgid "Number of waves"
+msgstr "Количество волн"
+
+#: ../hacks/config/interference.xml.h:14 ../hacks/config/t3d.xml.h:11
+msgid "Magnification"
+msgstr "Увеличение"
+
+#: ../hacks/config/interference.xml.h:19
+msgid "Hue"
+msgstr "Оттенок"
+
+#: ../hacks/config/interference.xml.h:20
+msgid "360"
 msgstr ""
 
-#: hacks/config/lament.xml.h:1
+#: ../hacks/config/interference.xml.h:22
 msgid ""
-"Animates a simulation of Lemarchand's Box, repeatedly solving itself. "
-"Requires OpenGL, and a machine with fast hardware support for texture maps. "
-"Warning: occasionally opens doors. Written by Jamie Zawinski."
+"Color field based on computing decaying sinusoidal waves. Written by Hannu "
+"Mallat; 1998."
 msgstr ""
 
-#: hacks/config/lament.xml.h:3
-msgid "Lament"
+#: ../hacks/config/intermomentary.xml.h:1
+msgid "Intermomentary"
 msgstr ""
 
-#: hacks/config/laser.xml.h:4
-msgid "Laser"
+#: ../hacks/config/intermomentary.xml.h:7
+msgid "400"
 msgstr ""
 
-#: hacks/config/laser.xml.h:7
+#: ../hacks/config/intermomentary.xml.h:9
 msgid ""
-"Moving radiating lines, that look vaguely like scanning laser beams. Written "
-"by Pascal Pensa. (Frankie say: relax.)"
+"Blinking dots interact with each other circularly. A surface is filled with "
+"a hundred medium to small sized circles. Each circle has a different size "
+"and direction, but moves at the same slow rate. Displays the instantaneous "
+"intersections of the circles as well as the aggregate intersections of the "
+"circles. The circles begin with a radius of 1 pixel and slowly increase to "
+"some arbitrary size. Circles are drawn with small moving points along the "
+"perimeter. The intersections are rendered as glowing orbs. Glowing orbs are "
+"rendered only when a perimeter point moves past the intersection point. "
+"Written by Casey Reas, William Ngan, Robert Hodgin, and Jamie Zawinski; 2004."
 msgstr ""
 
-#: hacks/config/lavalite.xml.h:2 hacks/config/xmountains.xml.h:2
-#, fuzzy
-msgid "10"
-msgstr "100%"
-
-#: hacks/config/lavalite.xml.h:4
-msgid "Classic Lavalite"
+#: ../hacks/config/jigglypuff.xml.h:1
+msgid "JigglyPuff"
 msgstr ""
 
-#: hacks/config/lavalite.xml.h:5
-msgid "Cone Lavalite"
-msgstr ""
+#: ../hacks/config/jigglypuff.xml.h:2
+msgid "Randomize almost everything"
+msgstr "Выбирать почти все случайно"
+
+#: ../hacks/config/jigglypuff.xml.h:3
+msgid "Cycle"
+msgstr "Цикл"
+
+#: ../hacks/config/jigglypuff.xml.h:4
+msgid "Flower box"
+msgstr "Коробка цветов"
+
+#: ../hacks/config/jigglypuff.xml.h:5
+msgid "Clown barf"
+msgstr "Отрыжка клоуна"
+
+#: ../hacks/config/jigglypuff.xml.h:7 ../hacks/config/sphere.xml.h:1
+msgid "Sphere"
+msgstr "Сфера"
+
+#: ../hacks/config/jigglypuff.xml.h:8 ../hacks/config/morph3d.xml.h:6
+#: ../hacks/config/polyhedra.xml.h:22 ../hacks/config/sballs.xml.h:6
+msgid "Tetrahedron"
+msgstr "Тетраэдр"
+
+#: ../hacks/config/jigglypuff.xml.h:17
+msgid "Inertial damping"
+msgstr "Затухание по инерции"
+
+#: ../hacks/config/jigglypuff.xml.h:19
+msgid "Vertex-vertex force"
+msgstr "Сила вершин"
+
+#: ../hacks/config/jigglypuff.xml.h:22
+msgid "Sphere strength"
+msgstr "Натяжение сферы"
+
+#: ../hacks/config/jigglypuff.xml.h:23
+msgid "Expand"
+msgstr "Расширение"
+
+#: ../hacks/config/jigglypuff.xml.h:24
+msgid "Vertex-vertex behavior"
+msgstr "Поведение вершин"
+
+#: ../hacks/config/jigglypuff.xml.h:25
+msgid "Collapse"
+msgstr "Сжатие"
+
+#: ../hacks/config/jigglypuff.xml.h:26
+msgid "Spookiness"
+msgstr "Ужас"
+
+#: ../hacks/config/jigglypuff.xml.h:27
+msgid "Spoooooky"
+msgstr "У-у-ужас!"
 
-#: hacks/config/lavalite.xml.h:8
+#: ../hacks/config/jigglypuff.xml.h:28
 msgid ""
-"Draws a 3D Simulation a Lava Lite(r): odd-shaped blobs of a mysterious "
-"substance are heated, slowly rise to the top of the bottle, and then drop "
-"back down as they cool. This program requires OpenGL and a fairly fast "
-"machine (both CPU and 3D performance.) Written by Jamie Zawinski. \"LAVA LITE"
-"(r) and the configuration of the LAVA(r) brand motion lamp are registered "
-"trademarks of Haggerty Enterprises, Inc. The configuration of the globe and "
-"base of the motion lamp are registered trademarks of Haggerty Enterprises, "
-"Inc. in the U.S.A. and in other countries around the world.\""
+"Quasi-spherical objects are distorted. You have a tetrahedron with "
+"tesselated faces. The vertices on these faces have forces on them: one "
+"proportional to the distance from the surface of a sphere; and one "
+"proportional to the distance from the neighbors. They also have inertia. The "
+"resulting effect can range from a shape that does nothing, to a frenetic "
+"polygon storm. Somewhere in between there it usually manifests as a blob "
+"that jiggles in a kind of disturbing manner. Written by Keith Macleod; 2003."
 msgstr ""
 
-#: hacks/config/lavalite.xml.h:9
-msgid "Faceted"
+#: ../hacks/config/jigsaw.xml.h:1
+msgid "Jigsaw"
 msgstr ""
 
-#: hacks/config/lavalite.xml.h:11
-msgid "Giant Lavalite"
-msgstr ""
+#: ../hacks/config/jigsaw.xml.h:9
+msgid "Puzzle pieces"
+msgstr "Кусочки пазла"
 
-#: hacks/config/lavalite.xml.h:13
-msgid "LavaLite"
-msgstr ""
+#: ../hacks/config/jigsaw.xml.h:11
+msgid "Chunky"
+msgstr "Жесткий"
 
-#: hacks/config/lavalite.xml.h:15
-msgid "Max Blobs"
-msgstr ""
+#: ../hacks/config/jigsaw.xml.h:14 ../hacks/config/sonar.xml.h:33
+msgid "Tilt"
+msgstr "Наклон"
 
-#: hacks/config/lavalite.xml.h:16
-msgid "Random Lamp Style"
+#: ../hacks/config/jigsaw.xml.h:16
+msgid ""
+"Carves an image up into a jigsaw puzzle, shuffles it, and solves it. https://"
+"en.wikipedia.org/wiki/Jigsaw_puzzle https://en.wikipedia.org/wiki/"
+"Tessellation Written by Jamie Zawinski; 1997."
 msgstr ""
 
-#: hacks/config/lavalite.xml.h:18
-msgid "Rocket Lavalite"
+#: ../hacks/config/juggle.xml.h:1
+msgid "Juggle"
 msgstr ""
 
-#: hacks/config/lightning.xml.h:2
-msgid "Lightning"
-msgstr ""
+#: ../hacks/config/juggle.xml.h:9 ../hacks/config/juggler3d.xml.h:9
+msgid "Performance length"
+msgstr "Длительность исполнения"
+
+#: ../hacks/config/juggle.xml.h:14 ../hacks/config/juggler3d.xml.h:14
+msgid "Clubs"
+msgstr "Клюшки"
+
+#: ../hacks/config/juggle.xml.h:15 ../hacks/config/juggler3d.xml.h:15
+msgid "Rings"
+msgstr "Кольца"
+
+#: ../hacks/config/juggle.xml.h:16 ../hacks/config/juggler3d.xml.h:16
+msgid "Knives"
+msgstr "Ножи"
+
+#: ../hacks/config/juggle.xml.h:17
+msgid "Flaming torches"
+msgstr "Горящие факелы"
 
-#: hacks/config/lightning.xml.h:7
+#. <boolean id="torches" _label="Flaming torches" arg-unset="-no-torches"/>
+#: ../hacks/config/juggle.xml.h:18 ../hacks/config/juggler3d.xml.h:18
+msgid "Bowling balls"
+msgstr "Шары для боулинга"
+
+#: ../hacks/config/juggle.xml.h:19 ../hacks/config/juggler3d.xml.h:19
+msgid "Print Cambridge juggling pattern descriptions"
+msgstr "Выводить кембриджские описания паттернов жонглирования"
+
+#: ../hacks/config/juggle.xml.h:20 ../hacks/config/juggler3d.xml.h:20
+msgid "Juggle this pattern"
+msgstr "Жонглировать этим паттерном"
+
+#: ../hacks/config/juggle.xml.h:22
 msgid ""
-"This one draws crackling fractal lightning bolts. It's simple, direct, and "
-"to the point. If only it had sound... Written by Keith Romberg."
+"This screen saver was removed from the XScreenSaver distribution as of "
+"version 5.09. It has been replaced by the \"Juggler3D\" screen saver. "
+"Written by Tim Auckland; 2002."
 msgstr ""
 
-#: hacks/config/lisa.xml.h:4
-msgid "Lisa"
+#: ../hacks/config/juggler3d.xml.h:1
+msgid "Juggler3D"
 msgstr ""
 
-#: hacks/config/lisa.xml.h:10
-msgid "Steps"
+#: ../hacks/config/juggler3d.xml.h:22
+msgid ""
+"A 3D juggling stick-man, with Cambridge juggling pattern notation used to "
+"describe the patterns he juggles. https://en.wikipedia.org/wiki/Siteswap "
+"Written by Tim Auckland and Jamie Zawinski; 2002."
 msgstr ""
 
-#: hacks/config/lisa.xml.h:11
-msgid ""
-"This draws Lisajous loops, by Caleb Cullen. Remember that device they had "
-"the Phantom Zone prisoners in during their trial in Superman? I think that "
-"was one of these."
+#: ../hacks/config/julia.xml.h:1
+msgid "Julia"
 msgstr ""
 
-#: hacks/config/lissie.xml.h:1
+#: ../hacks/config/julia.xml.h:9 ../hacks/config/rorschach.xml.h:3
+msgid "Iterations"
+msgstr "Итерации"
+
+#: ../hacks/config/julia.xml.h:15
 msgid ""
-"Another Lissajous figure. This one draws the progress of circular shapes "
-"along a path. Written by Alexander Jolk."
+"The Julia set is a close relative of the Mandelbrot set. The small moving "
+"dot indicates the control point from which the rest of the image was "
+"generated. See also the \"Discrete\" screen saver. https://en.wikipedia.org/"
+"wiki/Julia_set Written by Sean McCullough; 1997."
 msgstr ""
 
-#: hacks/config/lissie.xml.h:5
-msgid "Lissie"
+#: ../hacks/config/kaleidescope.xml.h:1
+msgid "Kaleidescope"
 msgstr ""
 
-#: hacks/config/lmorph.xml.h:1
-msgid "Closed Figures"
-msgstr ""
+#: ../hacks/config/kaleidescope.xml.h:6 ../hacks/config/qix.xml.h:6
+msgid "Segments"
+msgstr "Сегменты"
 
-#: hacks/config/lmorph.xml.h:2
-msgid "Control Points"
+#: ../hacks/config/kaleidescope.xml.h:8
+msgid "3"
 msgstr ""
 
-#: hacks/config/lmorph.xml.h:4
-msgid "Interpolation Steps"
-msgstr ""
+#: ../hacks/config/kaleidescope.xml.h:9 ../hacks/config/quasicrystal.xml.h:12
+msgid "Symmetry"
+msgstr "Симметрия"
 
-#: hacks/config/lmorph.xml.h:5
-msgid "LMorph"
+#: ../hacks/config/kaleidescope.xml.h:10
+msgid "32"
 msgstr ""
 
-#: hacks/config/lmorph.xml.h:6
-msgid "Less"
-msgstr ""
+#: ../hacks/config/kaleidescope.xml.h:11
+msgid "Trails"
+msgstr "Следы"
 
-#: hacks/config/lmorph.xml.h:8
-msgid "More"
+#: ../hacks/config/kaleidescope.xml.h:14
+msgid ""
+"A simple kaleidoscope made of line segments. See \"GLeidescope\" for a more "
+"sophisticated take. https://en.wikipedia.org/wiki/Kaleidoscope Written by "
+"Ron Tapia; 1997."
 msgstr ""
 
-#: hacks/config/lmorph.xml.h:9
-msgid "Open Figures"
+#: ../hacks/config/kaleidocycle.xml.h:1
+msgid "Kaleidocycle"
 msgstr ""
 
-#: hacks/config/lmorph.xml.h:10
-msgid "Open and Closed Figures"
+#: ../hacks/config/kaleidocycle.xml.h:7 ../hacks/config/raverhoop.xml.h:7
+msgid "64"
 msgstr ""
 
-#: hacks/config/lmorph.xml.h:15
+#: ../hacks/config/kaleidocycle.xml.h:22
 msgid ""
-"This generates random spline-ish line drawings and morphs between them. "
-"Written by Sverre H. Huseby and Glenn T. Lines."
+"Draw a ring composed of tetrahedra connected at the edges that twists and "
+"rotates toroidally. When a series of tetrahedra are joined at the edges in a "
+"loop, it is possible for them to rotate continously through the center "
+"without deforming. This only works with an even number of tetrahedra, and "
+"there must be eight or more, or they don't fit. Written by Jamie Zawinski; "
+"2013."
 msgstr ""
 
-#: hacks/config/loop.xml.h:3
-msgid "Loop"
+#: ../hacks/config/klein.xml.h:1
+msgid "Klein"
 msgstr ""
 
-#: hacks/config/loop.xml.h:10
-msgid ""
-"This one produces loop-shaped colonies that spawn, age, and eventually die. "
-"Written by David Bagley."
-msgstr ""
+#: ../hacks/config/klein.xml.h:3
+msgid "Figure 8"
+msgstr "Фигура 8"
+
+#: ../hacks/config/klein.xml.h:4
+msgid "Squeezed torus"
+msgstr "Сжатый тор"
 
-#: hacks/config/maze.xml.h:3
-msgid "Backtracking Generator"
+#: ../hacks/config/klein.xml.h:5
+msgid "Lawson"
 msgstr ""
 
-#: hacks/config/maze.xml.h:5 hacks/config/slidescreen.xml.h:3
-msgid "Grid Size"
-msgstr "Размер сетки"
+#: ../hacks/config/klein.xml.h:6 ../hacks/config/projectiveplane.xml.h:38
+#: ../hacks/config/qix.xml.h:15 ../hacks/config/romanboy.xml.h:2
+msgid "Random motion"
+msgstr "Случайное движение"
 
-#: hacks/config/maze.xml.h:6
-msgid "Head Toward Exit"
-msgstr ""
+#: ../hacks/config/klein.xml.h:7 ../hacks/config/projectiveplane.xml.h:39
+#: ../hacks/config/romanboy.xml.h:3
+msgid "Walk"
+msgstr "Движение прямо"
 
-#: hacks/config/maze.xml.h:7
-msgid "Ignorant of Exit Direction"
-msgstr ""
+#: ../hacks/config/klein.xml.h:8 ../hacks/config/projectiveplane.xml.h:40
+#: ../hacks/config/romanboy.xml.h:4
+msgid "Turn"
+msgstr "Поворот"
 
-#: hacks/config/maze.xml.h:8
-msgid "Joining Generator"
-msgstr ""
+#: ../hacks/config/klein.xml.h:9 ../hacks/config/projectiveplane.xml.h:41
+msgid "Walk and turn"
+msgstr "Движение прямо и поворот"
 
-#: hacks/config/maze.xml.h:9
-msgid "Maze"
-msgstr ""
+#: ../hacks/config/klein.xml.h:10 ../hacks/config/projectiveplane.xml.h:42
+#: ../hacks/config/romanboy.xml.h:6
+msgid "Show orientation marks"
+msgstr "Показывать метки ориентирования"
 
-#: hacks/config/maze.xml.h:10
-msgid "Post-Solve Delay"
-msgstr "Задержка после решениия"
+#: ../hacks/config/klein.xml.h:11 ../hacks/config/projectiveplane.xml.h:2
+#: ../hacks/config/romanboy.xml.h:14
+msgid "Random surface"
+msgstr "Случайная поверхность"
 
-#: hacks/config/maze.xml.h:11
-msgid "Pre-Solve Delay"
-msgstr "Задержка перед решением"
+#: ../hacks/config/klein.xml.h:12 ../hacks/config/polytopes.xml.h:2
+#: ../hacks/config/projectiveplane.xml.h:3 ../hacks/config/romanboy.xml.h:15
+msgid "Wireframe mesh"
+msgstr "Ячеистая поверхность"
 
-#: hacks/config/maze.xml.h:12
-msgid "Random Generator"
-msgstr ""
+#: ../hacks/config/klein.xml.h:13 ../hacks/config/mirrorblob.xml.h:27
+#: ../hacks/config/polytopes.xml.h:3 ../hacks/config/projectiveplane.xml.h:4
+#: ../hacks/config/romanboy.xml.h:16
+msgid "Solid surface"
+msgstr "Сплошная поверхность"
 
-#: hacks/config/maze.xml.h:13
-msgid "Seeding Generator"
-msgstr ""
+#: ../hacks/config/klein.xml.h:14 ../hacks/config/polytopes.xml.h:4
+#: ../hacks/config/projectiveplane.xml.h:5 ../hacks/config/romanboy.xml.h:17
+msgid "Transparent surface"
+msgstr "Прозрачная поверхность"
 
-#: hacks/config/maze.xml.h:15
-msgid "Solve Speed"
-msgstr "Скорость решения"
+#: ../hacks/config/klein.xml.h:15 ../hacks/config/projectiveplane.xml.h:6
+#: ../hacks/config/romanboy.xml.h:18
+msgid "Random pattern"
+msgstr "Случайный паттерн"
 
-#: hacks/config/maze.xml.h:16
-msgid ""
-"This is the ancient X maze demo, modified to work with xscreensaver. It "
-"generates a random maze, then solves it with visual feedback. Originally by "
-"Jim Randell; modified by a cast of thousands."
+#: ../hacks/config/klein.xml.h:17
+msgid "See-through bands"
+msgstr "Сквозные ленты"
+
+#: ../hacks/config/klein.xml.h:20
+msgid "Rainbow colors"
+msgstr "Цвета радуги"
+
+#: ../hacks/config/klein.xml.h:21 ../hacks/config/projectiveplane.xml.h:14
+msgid "4d depth colors"
+msgstr "Цвета глубины 4d"
+
+#: ../hacks/config/klein.xml.h:22 ../hacks/config/projectiveplane.xml.h:15
+msgid "Random 3D"
+msgstr "Случайное 3D"
+
+#: ../hacks/config/klein.xml.h:25 ../hacks/config/projectiveplane.xml.h:18
+msgid "Random 4D"
+msgstr "Случайное 4D"
+
+#: ../hacks/config/klein.xml.h:36 ../hacks/config/romanboy.xml.h:34
+msgid "-180.0"
 msgstr ""
 
-#: hacks/config/memscroller.xml.h:1
-msgid "Draw Green"
+#: ../hacks/config/klein.xml.h:37 ../hacks/config/romanboy.xml.h:35
+msgid "Walking direction"
+msgstr "Направление движения"
+
+#: ../hacks/config/klein.xml.h:38 ../hacks/config/romanboy.xml.h:36
+msgid "180.0"
 msgstr ""
 
-#: hacks/config/memscroller.xml.h:2
-msgid "Draw Random Numbers"
+#: ../hacks/config/klein.xml.h:39 ../hacks/config/romanboy.xml.h:8
+msgid "1.0"
 msgstr ""
 
-#: hacks/config/memscroller.xml.h:3
-msgid "Draw in RGB"
+#: ../hacks/config/klein.xml.h:40 ../hacks/config/romanboy.xml.h:37
+msgid "Walking speed"
+msgstr "Скорость движения"
+
+#: ../hacks/config/klein.xml.h:41 ../hacks/config/romanboy.xml.h:10
+msgid "100.0"
 msgstr ""
 
-#: hacks/config/memscroller.xml.h:4
-msgid "Dump Memory"
+#: ../hacks/config/klein.xml.h:46
+msgid ""
+"A Klein bottle is the 4D analog of a moebius strip. You can walk on the "
+"surface of the bottle or rotate it in 4D or walk on it while it rotates in "
+"4D. Inspired by Thomas Banchoff's book \"Beyond the Third Dimension: "
+"Geometry, Computer Graphics, and Higher Dimensions\", Scientific American "
+"Library, 1990. https://en.wikipedia.org/wiki/Klein_bottle Written by Carsten "
+"Steger; 2008."
 msgstr ""
 
-#: hacks/config/memscroller.xml.h:6
-msgid "MemScroller"
+#: ../hacks/config/kumppa.xml.h:1
+msgid "Kumppa"
 msgstr ""
 
-#: hacks/config/memscroller.xml.h:9
+#: ../hacks/config/kumppa.xml.h:6
+msgid "Randomize"
+msgstr "Выбирать все случайно"
+
+#: ../hacks/config/kumppa.xml.h:9
 msgid ""
-"This draws a dump of its own process memory scrolling across the screen in "
-"three windows at three different rates. Written by Jamie Zawinski."
+"Spiraling, spinning, and very, very fast splashes of color rush toward the "
+"screen. Written by Teemu Suutari; 1998."
 msgstr ""
 
-#: hacks/config/menger.xml.h:6
-msgid "Menger"
+#: ../hacks/config/lament.xml.h:1
+msgid "Lament"
 msgstr ""
 
-#: hacks/config/menger.xml.h:19
+#: ../hacks/config/lament.xml.h:9
+#, no-c-format
 msgid ""
-"This draws the three-dimensional variant of the recursive Menger Gasket, a "
-"cube-based fractal object analagous to the Sierpinski Tetrahedron. Written "
-"by Jamie Zawinski."
+"Lemarchand's Box, the Lament Configuration. Warning: occasionally opens "
+"doors. https://en.wikipedia.org/wiki/Lemarchand%27s_box Written by Jamie "
+"Zawinski; 1998."
 msgstr ""
 
-#: hacks/config/metaballs.xml.h:1
-msgid "Big"
+#: ../hacks/config/laser.xml.h:1
+msgid "Laser"
 msgstr ""
 
-#: hacks/config/metaballs.xml.h:2
+#: ../hacks/config/laser.xml.h:13
 msgid ""
-"Draws two dimensional metaballs: overlapping and merging balls with fuzzy "
-"edges. By W.P. van Paassen."
+"This screen saver was removed from the XScreenSaver distribution as of "
+"version 5.08. Moving radiating lines, that look vaguely like scanning laser "
+"beams. (Frankie say relax.) Written by Pascal Pensa; 1997."
 msgstr ""
 
-#: hacks/config/metaballs.xml.h:7
-msgid "MetaBall Movement"
+#: ../hacks/config/lavalite.xml.h:1
+msgid "Lavalite"
 msgstr ""
 
-#: hacks/config/metaballs.xml.h:8
-#, fuzzy
-msgid "MetaBall Radius"
-msgstr "Радиус зерен"
+#: ../hacks/config/lavalite.xml.h:9
+msgid "Max blobs"
+msgstr "Максимум сгустков"
 
-#: hacks/config/metaballs.xml.h:9
-#, fuzzy
-msgid "MetaBalls"
-msgstr "Мячи"
+#: ../hacks/config/lavalite.xml.h:12
+msgid "Impatient"
+msgstr "Нетерпеливый"
 
-#: hacks/config/metaballs.xml.h:11
-#, fuzzy
-msgid "Number of MetaBalls"
-msgstr "Количество цветов"
+#: ../hacks/config/lavalite.xml.h:17
+msgid "Classic Lavalite"
+msgstr "Классическая лавовая лампа"
 
-#: hacks/config/mirrorblob.xml.h:4
-msgid "Blobby"
-msgstr ""
+#: ../hacks/config/lavalite.xml.h:18
+msgid "Giant Lavalite"
+msgstr "Гигантская лавовая лампа"
 
-#: hacks/config/mirrorblob.xml.h:5 hacks/config/nerverot.xml.h:2
-msgid "Calm"
-msgstr ""
+#: ../hacks/config/lavalite.xml.h:19
+msgid "Cone Lavalite"
+msgstr "Конусная лавовая лампа"
 
-#: hacks/config/mirrorblob.xml.h:7
-msgid ""
-"Draws a wobbly blob that distorts the image behind it. Requires OpenGL "
-"hardware acceleration for nice animation. Written by Jon Dowdall."
-msgstr ""
+#: ../hacks/config/lavalite.xml.h:20
+msgid "Rocket Lavalite"
+msgstr "Ракетная лавовая лампа"
 
-#: hacks/config/mirrorblob.xml.h:8
-#, fuzzy
-msgid "Enable Colouring"
-msgstr "Разрешить вспышки"
+#: ../hacks/config/lavalite.xml.h:21
+msgid "Random Lamp Style"
+msgstr "Случайный стиль лампы"
+
+#: ../hacks/config/lavalite.xml.h:22
+msgid "Don't Rotate"
+msgstr "Не вращать"
 
-#: hacks/config/mirrorblob.xml.h:9
-msgid "Enable Reflected Image"
+#: ../hacks/config/lavalite.xml.h:30
+msgid ""
+"A Simulation a Lava Lite(r). Odd-shaped blobs of a mysterious substance are "
+"heated, slowly rise to the top of the bottle, and then drop back down as "
+"they cool. This simulation requires a fairly fast machine (both CPU and 3D "
+"performance.) \"LAVA LITE(r) and the configuration of the LAVA(r) brand "
+"motion lamp are registered trademarks of Haggerty Enterprises, Inc. The "
+"configuration of the globe and base of the motion lamp are registered "
+"trademarks of Haggerty Enterprises, Inc. in the U.S.A. and in other "
+"countries around the world.\" https://en.wikipedia.org/wiki/Lava_lamp "
+"https://en.wikipedia.org/wiki/Metaballs https://en.wikipedia.org/wiki/"
+"Lavarand Written by Jamie Zawinski; 2002."
 msgstr ""
 
-#: hacks/config/mirrorblob.xml.h:10
-msgid "Enable Walls"
+#: ../hacks/config/lcdscrub.xml.h:1
+msgid "LCDscrub"
 msgstr ""
 
-#: hacks/config/mirrorblob.xml.h:12
-#, fuzzy
-msgid "Field Points"
-msgstr "Заполненные сплайны"
+#: ../hacks/config/lcdscrub.xml.h:5
+msgid "Line spread"
+msgstr "Расстояние между линиями"
 
-#: hacks/config/mirrorblob.xml.h:13
-#, fuzzy
-msgid "Freaky"
-msgstr "Gray"
+#: ../hacks/config/lcdscrub.xml.h:8
+msgid "Horizontal white"
+msgstr "Горизонтальные белые"
 
-#: hacks/config/mirrorblob.xml.h:14
-msgid "MirrorBlob"
-msgstr ""
+#: ../hacks/config/lcdscrub.xml.h:9
+msgid "Vertical white"
+msgstr "Вертикальные белые"
 
-#: hacks/config/mirrorblob.xml.h:16
-msgid "Offset Texture Coordinates"
-msgstr ""
+#: ../hacks/config/lcdscrub.xml.h:10
+msgid "Diagonal white"
+msgstr "Диагональные белые"
 
-#: hacks/config/mirrorblob.xml.h:22
-msgid "Very Freaky"
-msgstr ""
+#: ../hacks/config/lcdscrub.xml.h:11
+msgid "Solid white"
+msgstr "Сплошные белые"
 
-#: hacks/config/mirrorblob.xml.h:24
-#, fuzzy
-msgid "X Resolution"
-msgstr "Разрешение"
+#: ../hacks/config/lcdscrub.xml.h:12
+msgid "Primary colors"
+msgstr "Первичные цвета"
+
+#: ../hacks/config/lcdscrub.xml.h:13
+msgid "Horizontal black"
+msgstr "Горизонтальные черные"
+
+#: ../hacks/config/lcdscrub.xml.h:14
+msgid "Vertical black"
+msgstr "Вертикальные черные"
+
+#: ../hacks/config/lcdscrub.xml.h:15
+msgid "Diagonal black"
+msgstr "Диагональные черные"
+
+#: ../hacks/config/lcdscrub.xml.h:16
+msgid "Solid black"
+msgstr "Сплошные черные"
 
-#: hacks/config/mirrorblob.xml.h:25
-#, fuzzy
-msgid "Y Resolution"
-msgstr "Разрешение"
+#: ../hacks/config/lcdscrub.xml.h:17
+msgid ""
+"repairs burn-in on LCD monitors. This saver is functional, rather than "
+"pretty. Believe it or not, screen burn is not a thing of the past. It can "
+"happen to LCD screens pretty easily, even in this modern age. However, "
+"leaving the screen on and displaying high contrast images can often repair "
+"the damage. That's what this screen saver does. See also: http://docs.info."
+"apple.com/article.html?artnum=88343 http://toastycode.com/blog/2008/02/05/"
+"lcd-scrub/ Inspired by the like-named program by Daniel Sandler. Written by "
+"Jamie Zawinski; 2008."
+msgstr ""
 
-#: hacks/config/mismunch.xml.h:5
-msgid "Mismunch"
+#: ../hacks/config/lightning.xml.h:1
+msgid "Lightning"
 msgstr ""
 
-#: hacks/config/mismunch.xml.h:6
+#: ../hacks/config/lightning.xml.h:9
 msgid ""
-"Munching errors! This is a creatively broken misimplementation of the "
-"classic munching squares graphics hack. Written by Steven Hazel."
+"This screen saver was removed from the XScreenSaver distribution as of "
+"version 5.08. Crackling fractal lightning bolts. Written by Keith Romberg; "
+"1997."
 msgstr ""
 
-#: hacks/config/mismunch.xml.h:7
-msgid "One"
+#: ../hacks/config/lisa.xml.h:1
+msgid "Lisa"
+msgstr ""
+
+#: ../hacks/config/lisa.xml.h:6
+msgid "Steps"
 msgstr ""
 
-#: hacks/config/mismunch.xml.h:9
-msgid "Simultaneous Squares"
+#: ../hacks/config/lisa.xml.h:17
+msgid ""
+"This screen saver was removed from the XScreenSaver distribution as of "
+"version 5.08. Lissajous loops. https://en.wikipedia.org/wiki/Lissajous_curve "
+"Written by Caleb Cullen; 1997."
 msgstr ""
 
-#: hacks/config/mismunch.xml.h:13 hacks/config/munch.xml.h:10
-#: hacks/config/qix.xml.h:26
-msgid "XOR"
+#: ../hacks/config/lissie.xml.h:1
+msgid "Lissie"
 msgstr ""
 
-#: hacks/config/moebius.xml.h:1
+#: ../hacks/config/lissie.xml.h:16
 msgid ""
-"Another M. C. Escher hack by Marcelo Vianna, this one draws ``Moebius Strip "
-"II,'' a GL image of ants walking along the surface of a moebius strip."
+"This screen saver was removed from the XScreenSaver distribution as of "
+"version 5.08. Lissajous loops. This one draws the progress of circular "
+"shapes along a path. https://en.wikipedia.org/wiki/Lissajous_curve Written "
+"by Alexander Jolk; 1997."
 msgstr ""
 
-#: hacks/config/moebius.xml.h:2
-msgid "Draw Ants"
+#: ../hacks/config/lmorph.xml.h:1
+msgid "LMorph"
 msgstr ""
 
-#: hacks/config/moebius.xml.h:4
-msgid "Mesh Floor"
+#: ../hacks/config/lmorph.xml.h:6
+msgid "Control points"
 msgstr ""
 
-#: hacks/config/moebius.xml.h:5
-msgid "Moebius"
+#: ../hacks/config/lmorph.xml.h:8
+msgid "Less"
 msgstr ""
 
-#: hacks/config/moebius.xml.h:8
-msgid "Solid Floor"
+#: ../hacks/config/lmorph.xml.h:9
+msgid "Interpolation steps"
 msgstr ""
 
-#: hacks/config/moebius.xml.h:9 hacks/config/qix.xml.h:20
-msgid "Solid Objects"
+#: ../hacks/config/lmorph.xml.h:10
+msgid "More"
 msgstr ""
 
-#: hacks/config/moire.xml.h:6
-msgid "Moire"
+#: ../hacks/config/lmorph.xml.h:14
+msgid "Open and closed figures"
 msgstr ""
 
-#: hacks/config/moire.xml.h:8 hacks/config/rorschach.xml.h:6
-msgid "Offset"
+#: ../hacks/config/lmorph.xml.h:15
+msgid "Open figures"
 msgstr ""
 
-#: hacks/config/moire.xml.h:10
-msgid ""
-"This one draws cool circular interference patterns. Most of the circles you "
-"see aren't explicitly rendered, but show up as a result of interactions "
-"between the other pixels that were drawn. Written by Jamie Zawinski, "
-"inspired by Java code by Michael Bayne. As he pointed out, the beauty of "
-"this one is that the heart of the display algorithm can be expressed with "
-"just a pair of loops and a handful of arithmetic, giving it a high ``display "
-"hack metric''."
+#: ../hacks/config/lmorph.xml.h:16
+msgid "Closed figures"
 msgstr ""
 
-#: hacks/config/moire2.xml.h:1
+#: ../hacks/config/lmorph.xml.h:18
 msgid ""
-"Another example of the fun you can have with moire interference patterns; "
-"this hack generates fields of concentric circles or ovals, and combines the "
-"planes with various operations. The planes are moving independently of one "
-"another, causing the interference lines to ``spray.'' Written by Jamie "
-"Zawinski."
+"This screen saver was removed from the XScreenSaver distribution as of "
+"version 5.08. This generates random spline-ish line drawings and morphs "
+"between them. Written by Sverre H. Huseby and Glenn T. Lines; 1995."
 msgstr ""
 
-#: hacks/config/moire2.xml.h:4
-msgid "Moire2"
+#: ../hacks/config/lockward.xml.h:1
+msgid "Lockward"
 msgstr ""
 
-#: hacks/config/molecule.xml.h:3
-msgid "Describe Molecule"
-msgstr ""
+#: ../hacks/config/lockward.xml.h:5
+msgid "Miniumum rotator idle time"
+msgstr "Минимальное время холостого вращения"
 
-#: hacks/config/molecule.xml.h:5
-msgid "Draw Atomic Bonds"
-msgstr ""
+#: ../hacks/config/lockward.xml.h:6
+msgid "Minimum blink idle time"
+msgstr "Минимальное время холостого мерцания"
 
-#: hacks/config/molecule.xml.h:6
-msgid "Draw Atomic Nuclei"
-msgstr ""
+#: ../hacks/config/lockward.xml.h:7
+msgid "Minimum blink dwell time"
+msgstr "Минимальное время задержки мерцания"
 
-#: hacks/config/molecule.xml.h:7 hacks/config/spheremonics.xml.h:2
-msgid "Draw Bounding Box"
-msgstr ""
+#: ../hacks/config/lockward.xml.h:8
+msgid "Blinking effects"
+msgstr "Эффекты мерцания"
 
-#: hacks/config/molecule.xml.h:8
-msgid "Draw Electron Shells"
-msgstr ""
+#: ../hacks/config/lockward.xml.h:10
+msgid "Maximum rotator idle time"
+msgstr "Максимальное время холостого вращения"
 
-#: hacks/config/molecule.xml.h:9
-msgid ""
-"Draws several different representations of molecules. Some common molecules "
-"are built in, and it can also read PDB (Protein Data Base) files as input. "
-"Written by Jamie Zawinski."
-msgstr ""
+#: ../hacks/config/lockward.xml.h:11
+msgid "Maximum blink idle time"
+msgstr "Максимальное время холостого мерцания"
 
-#: hacks/config/molecule.xml.h:12
-msgid "Label Atoms"
-msgstr ""
+#: ../hacks/config/lockward.xml.h:12
+msgid "Maximum blink dwell time"
+msgstr "Максимальное время задержки мерцания"
 
-#: hacks/config/molecule.xml.h:13
-msgid "Molecule"
+#: ../hacks/config/lockward.xml.h:13
+msgid ""
+"A translucent spinning, blinking thing. Sort of a cross between the wards in "
+"an old combination lock and those old backlit information displays that "
+"animated and changed color via polarized light. Written by Leo L. Schwab; "
+"2007."
 msgstr ""
 
-#: hacks/config/molecule.xml.h:14
-msgid "PDB File or Directory"
+#: ../hacks/config/loop.xml.h:1
+msgid "Loop"
 msgstr ""
 
-#: hacks/config/morph3d.xml.h:1
+#: ../hacks/config/loop.xml.h:14
+#, no-c-format
 msgid ""
-"Another 3d shape-changing GL hack, by Marcelo Vianna. It has the same shiny-"
-"plastic feel as Superquadrics, as many computer-generated objects do..."
+"A cellular automaton that generates loop-shaped colonies that spawn, age, "
+"and eventually die. https://en.wikipedia.org/wiki/Langton%27s_loops Written "
+"by David Bagley; 1999."
 msgstr ""
 
-#: hacks/config/morph3d.xml.h:4
-msgid "Morph3D"
+#: ../hacks/config/m6502.xml.h:1
+msgid "m6502"
 msgstr ""
 
-#: hacks/config/mountain.xml.h:3
+#: ../hacks/config/m6502.xml.h:3
+msgid "Display time for each program"
+msgstr "Время отображения каждой программы"
+
+#: ../hacks/config/m6502.xml.h:5
+msgid "Assembly file"
+msgstr "Файл ассемблера"
+
+#: ../hacks/config/m6502.xml.h:13
 msgid ""
-"Generates random 3d plots that look vaguely mountainous. Written by Pascal "
-"Pensa."
+"Emulates a 6502 microprocessor, and runs some example programs on it. The "
+"family of 6502 chips were used throughout the 70's and 80's in machines such "
+"as the Atari 2600, Commodore PET, VIC20 and C64, Apple ][, and the NES. Some "
+"example programs are included, and it can also read in an assembly file as "
+"input. Original JavaScript Version by Stian Soreng: http://www.6502asm.com/. "
+"Ported to XScreenSaver by Jeremy English. Written by Stian Soreng and Jeremy "
+"English; 2007."
 msgstr ""
 
-#: hacks/config/mountain.xml.h:5
-msgid "Mountain"
+#: ../hacks/config/maze.xml.h:1
+msgid "Maze"
 msgstr ""
 
-#: hacks/config/munch.xml.h:1
+#: ../hacks/config/maze.xml.h:5
+msgid "Random maze generator"
+msgstr "Случайный генератор лабиринта"
+
+#: ../hacks/config/maze.xml.h:6
+msgid "Depth-first backtracking maze generator"
+msgstr "Генератор лабиринта, основанный на возврате обратно"
+
+#: ../hacks/config/maze.xml.h:7
+msgid "Wall-building maze generator (Prim)"
+msgstr "Генератор лабиринта, основанный на построении стен (Prim)"
+
+#: ../hacks/config/maze.xml.h:8
+msgid "Set-joining maze generator (Kruskal)"
+msgstr "Генератор лабиринта, основанный на присоединении (Kruskal)"
+
+#: ../hacks/config/maze.xml.h:9
+msgid "Head toward exit"
+msgstr "Направляться к выходу"
+
+#: ../hacks/config/maze.xml.h:10
+msgid "Ignorant of exit direction"
+msgstr "Не знать направление выхода"
+
+#: ../hacks/config/maze.xml.h:11
+msgid "Grid size"
+msgstr "Размер сетки"
+
+#: ../hacks/config/maze.xml.h:14
+msgid "Linger before solving"
+msgstr "Время до решения"
+
+#: ../hacks/config/maze.xml.h:16
+msgid "Linger after solving"
+msgstr "Время после решения"
+
+#: ../hacks/config/maze.xml.h:17
 msgid ""
-"DATAI 2 ADDB 1,2 ROTC 2,-22 XOR 1,2 JRST .-4 As reported by HAKMEM, in 1962, "
-"Jackson Wright wrote the above PDP-1 code. That code still lives on in this "
-"screenhack, some 35 years later. The number of lines of enclosing code has "
-"increased substantially, however. This version is by Tim Showalter."
+"Generates random mazes, with three different algorithms: Kruskal, Prim, and "
+"a depth-first recursive backtracker. It also solves them. Backtracking and "
+"look-ahead paths are displayed in different colors. https://en.wikipedia.org/"
+"wiki/Maze_generation_algorithm https://en.wikipedia.org/wiki/"
+"Maze_solving_algorithm Written by Martin Weiss, Dave Lemke, Jim Randell, "
+"Jamie Zawinski, Johannes Keukelaar, and Zack Weinberg; 1985."
 msgstr ""
 
-#: hacks/config/munch.xml.h:5
-msgid "Munch"
+#: ../hacks/config/memscroller.xml.h:1
+msgid "MemScroller"
 msgstr ""
 
-#: hacks/config/nerverot.xml.h:1
-msgid "Blot Count"
-msgstr ""
+#: ../hacks/config/memscroller.xml.h:5
+msgid "Dump memory"
+msgstr "Проводить дамп памяти"
 
-#: hacks/config/nerverot.xml.h:3
-msgid "Changes"
-msgstr ""
+#: ../hacks/config/memscroller.xml.h:6
+msgid "Draw random numbers"
+msgstr "Прорисовывать случайные числа"
 
-#: hacks/config/nerverot.xml.h:4
-msgid "Colors"
-msgstr ""
+#: ../hacks/config/memscroller.xml.h:7
+msgid "Draw in RGB"
+msgstr "Прорисовывать в RGB"
 
-#: hacks/config/nerverot.xml.h:5
-msgid "Crunchiness"
-msgstr ""
+#: ../hacks/config/memscroller.xml.h:8
+msgid "Draw green"
+msgstr "Прорисовывать зеленым цветом"
 
-#: hacks/config/nerverot.xml.h:7
+#: ../hacks/config/memscroller.xml.h:10
 msgid ""
-"Draws different shapes composed of nervously vibrating squiggles, as if seen "
-"through a camera operated by a monkey on crack. By Dan Bornstein."
+"Scrolls a dump of its own memory in three windows at three different rates. "
+"Written by Jamie Zawinski; 2004."
 msgstr ""
 
-#: hacks/config/nerverot.xml.h:10
-msgid "Frequent"
+#: ../hacks/config/menger.xml.h:1
+msgid "Menger"
 msgstr ""
 
-#: hacks/config/nerverot.xml.h:16
-msgid "NerveRot"
-msgstr ""
+#: ../hacks/config/menger.xml.h:8 ../hacks/config/sierpinski3d.xml.h:8
+msgid "Max depth"
+msgstr "Максимальная глубина"
 
-#: hacks/config/nerverot.xml.h:17
-msgid "Nervousness"
+#: ../hacks/config/menger.xml.h:21
+msgid ""
+"The Menger Gasket is a cube-based recursive fractal object analagous to the "
+"Sierpinski Tetrahedron. https://en.wikipedia.org/wiki/Menger_sponge https://"
+"en.wikipedia.org/wiki/Sierpinski_carpet Written by Jamie Zawinski; 2001."
 msgstr ""
 
-#: hacks/config/nerverot.xml.h:18 hacks/config/pyro.xml.h:12
-msgid "Seldom"
+#: ../hacks/config/metaballs.xml.h:1
+msgid "MetaBalls"
 msgstr ""
 
-#: hacks/config/nerverot.xml.h:21
-msgid "Spastic"
-msgstr ""
+#: ../hacks/config/metaballs.xml.h:11
+msgid "Metaball count"
+msgstr "Количество метамячей"
 
-#: hacks/config/noof.xml.h:1
-msgid "Draws some rotatey patterns, using OpenGL. Written by Mark Kilgard."
-msgstr ""
+#: ../hacks/config/metaballs.xml.h:13
+msgid "MetaBall Radius"
+msgstr "Радиус метамячей"
 
-#: hacks/config/noof.xml.h:3
-msgid "Noof"
-msgstr ""
+#: ../hacks/config/metaballs.xml.h:15
+msgid "MetaBall Movement"
+msgstr "Темп движения метамячей"
 
-#: hacks/config/noseguy.xml.h:1
+#: ../hacks/config/metaballs.xml.h:17
 msgid ""
-"A little man with a big nose wanders around your screen saying things. The "
-"things which he says are the output of a program or the contents of a file "
-"or URL, as configured on the \"Advanced\" tab of the main Screensaver "
-"Preferences window. By Dan Heller and Jamie Zawinski."
+"2D meta-balls: overlapping and merging balls with fuzzy edges. https://en."
+"wikipedia.org/wiki/Metaballs Written by W.P. van Paassen; 2003."
 msgstr ""
 
-#: hacks/config/noseguy.xml.h:2
-msgid "Get Text from File"
+#: ../hacks/config/mirrorblob.xml.h:1
+msgid "MirrorBlob"
 msgstr ""
 
-#: hacks/config/noseguy.xml.h:3
-msgid "Get Text from Program"
+#: ../hacks/config/mirrorblob.xml.h:5
+msgid "0.1x"
 msgstr ""
 
-#: hacks/config/noseguy.xml.h:4
-msgid "Noseguy"
+#: ../hacks/config/mirrorblob.xml.h:7
+msgid "3.0x"
 msgstr ""
 
-#: hacks/config/noseguy.xml.h:6
-msgid "Text File"
-msgstr ""
+#: ../hacks/config/mirrorblob.xml.h:8
+msgid "5 sec"
+msgstr "5 секунд"
 
-#: hacks/config/noseguy.xml.h:8
-msgid "Use Text Below"
-msgstr ""
+#: ../hacks/config/mirrorblob.xml.h:10
+msgid "5 min"
+msgstr "5 минут"
 
-#: hacks/config/pacman.xml.h:2
-msgid "Pacman"
-msgstr ""
+#: ../hacks/config/mirrorblob.xml.h:12
+msgid "Transition duration"
+msgstr "Направление перехода"
 
-#: hacks/config/pacman.xml.h:3
-#, fuzzy
-msgid "Player Size"
-msgstr "Размер плитки"
+#: ../hacks/config/mirrorblob.xml.h:13 ../hacks/config/timetunnel.xml.h:4
+msgid "30 sec"
+msgstr "30 секунд"
 
-#: hacks/config/pacman.xml.h:4
-msgid ""
-"Simulates a game of Pac-Man on a randomly-created level. Written by Edwin de "
-"Jong."
-msgstr ""
+#: ../hacks/config/mirrorblob.xml.h:16
+msgid "50 bumps"
+msgstr "50 ударов"
 
-#: hacks/config/pedal.xml.h:7
-msgid "Pedal"
-msgstr ""
+#: ../hacks/config/mirrorblob.xml.h:17
+msgid "Clear"
+msgstr "Чистый"
 
-#: hacks/config/pedal.xml.h:8
-msgid ""
-"This is sort of a combination spirograph/string-art. It generates a large, "
-"complex polygon, and lets the X server do the bulk of the work by giving it "
-"an even/odd winding rule. Written by Dale Moore, based on some ancient PDP-"
-"11 code."
-msgstr ""
+#: ../hacks/config/mirrorblob.xml.h:20
+msgid "Enable walls"
+msgstr "Включить стены"
 
-#: hacks/config/penetrate.xml.h:1
-msgid "Always play well"
-msgstr ""
+#: ../hacks/config/mirrorblob.xml.h:21
+msgid "Enable colouring"
+msgstr "Включить окрашивание"
 
-#: hacks/config/penetrate.xml.h:2
-msgid "Explosions"
+#: ../hacks/config/mirrorblob.xml.h:22
+msgid "Enable reflected image"
+msgstr "Включить отражение изображения"
+
+#: ../hacks/config/mirrorblob.xml.h:23
+msgid "Show image on background"
+msgstr "Показывать изображение на фоне"
+
+#: ../hacks/config/mirrorblob.xml.h:24
+msgid "Offset texture coordinates"
+msgstr "Смещение координат текстур"
+
+#: ../hacks/config/mirrorblob.xml.h:28
+msgid "A wobbly blob distorts images behind it. Written by Jon Dowdall; 2003."
 msgstr ""
 
-#: hacks/config/penetrate.xml.h:5
-msgid "Penetrate"
+#: ../hacks/config/mismunch.xml.h:1
+msgid "Mismunch"
 msgstr ""
 
-#: hacks/config/penetrate.xml.h:7
-msgid "Start badly, but learn"
+#: ../hacks/config/mismunch.xml.h:9 ../hacks/config/munch.xml.h:9
+msgid "Simultaneous squares"
+msgstr "Одновременные квадраты"
+
+#: ../hacks/config/mismunch.xml.h:11 ../hacks/config/munch.xml.h:14
+#: ../hacks/config/qix.xml.h:22
+msgid "XOR"
 msgstr ""
 
-#: hacks/config/penetrate.xml.h:8
+#: ../hacks/config/mismunch.xml.h:14
 msgid ""
-"This hack simulates the classic arcade game Missile Command. Written by Adam "
-"Miller."
+"This screen saver was removed from the XScreenSaver distribution as of "
+"version 5.08. It was merged with the \"Munch\" screen saver. Munching "
+"errors! This is a creatively broken misimplementation of the classic "
+"munching squares graphics hack. See the \"Munch\" screen saver for the "
+"original. https://en.wikipedia.org/wiki/HAKMEM https://en.wikipedia.org/wiki/"
+"Munching_square Written by Steven Hazel; 2004."
 msgstr ""
 
-#: hacks/config/penrose.xml.h:1
-msgid "Draw Ammann Lines"
+#: ../hacks/config/moebius.xml.h:1
+msgid "Moebius"
 msgstr ""
 
-#: hacks/config/penrose.xml.h:2
+#: ../hacks/config/moebius.xml.h:5
+msgid "Solid floor"
+msgstr "Сплошная поверхность"
+
+#: ../hacks/config/moebius.xml.h:6
+msgid "Draw ants"
+msgstr "Прорисовывать муравьев"
+
+#: ../hacks/config/moebius.xml.h:8
 msgid ""
-"Draws quasiperiodic tilings; think of the implications on modern formica "
-"technology. Written by Timo Korvola. In April 1997, Sir Roger Penrose, a "
-"British math professor who has worked with Stephen Hawking on such topics as "
-"relativity, black holes, and whether time has a beginning, filed a copyright-"
-"infringement lawsuit against the Kimberly-Clark Corporation, which Penrose "
-"said copied a pattern he created (a pattern demonstrating that ``a "
-"nonrepeating pattern could exist in nature'') for its Kleenex quilted toilet "
-"paper. Penrose said he doesn't like litigation but, ``When it comes to the "
-"population of Great Britain being invited by a multinational to wipe their "
-"bottoms on what appears to be the work of a Knight of the Realm, then a last "
-"stand must be taken.'' As reported by News of the Weird #491, 4-jul-1997."
+"M. C. Escher's \"Moebius Strip II\", an image of ants walking along the "
+"surface of a moebius strip. https://en.wikipedia.org/wiki/Moebius_strip "
+"https://en.wikipedia.org/wiki/Maurits_Cornelis_Escher Written by Marcelo F. "
+"Vianna; 1997."
 msgstr ""
 
-#: hacks/config/penrose.xml.h:6
-msgid "Penrose"
+#: ../hacks/config/moebiusgears.xml.h:1
+msgid "MoebiusGears"
 msgstr ""
 
-#: hacks/config/petri.xml.h:2
-msgid "Colony Shape"
-msgstr ""
+#: ../hacks/config/moebiusgears.xml.h:8
+msgid "Number of gears"
+msgstr "Количество шестеренок"
 
-#: hacks/config/petri.xml.h:3
-msgid "Death Comes"
-msgstr ""
+#: ../hacks/config/moebiusgears.xml.h:9
+msgid "Number of teeth"
+msgstr "Количество зубцов"
 
-#: hacks/config/petri.xml.h:4
-msgid "Diamond"
+#: ../hacks/config/moebiusgears.xml.h:15
+msgid ""
+"An interlinked loop of rotating gears. The layout of the gears follows the "
+"path of a moebius strip. See also the \"Pinion\" and \"Gears\" screen "
+"savers. https://en.wikipedia.org/wiki/Involute_gear https://en.wikipedia.org/"
+"wiki/Moebius_strip Written by Jamie Zawinski; 2007."
 msgstr ""
 
-#: hacks/config/petri.xml.h:6
-msgid "Fertility"
+#: ../hacks/config/moire.xml.h:1
+msgid "Moire"
 msgstr ""
 
-#: hacks/config/petri.xml.h:12
-msgid "Maximum Lifespan"
-msgstr ""
+#: ../hacks/config/moire.xml.h:9 ../hacks/config/rorschach.xml.h:5
+msgid "Offset"
+msgstr "Смещение"
 
-#: hacks/config/petri.xml.h:13
-msgid "Maximum Rate of Death"
+#: ../hacks/config/moire.xml.h:13
+msgid ""
+"When the lines on the screen Make more lines in between, That's a moire'! "
+"https://en.wikipedia.org/wiki/Moire_pattern Written by Jamie Zawinski and "
+"Michael Bayne; 1997."
 msgstr ""
 
-#: hacks/config/petri.xml.h:14
-msgid "Maximum Rate of Growth"
+#: ../hacks/config/moire2.xml.h:1
+msgid "Moire2"
 msgstr ""
 
-#: hacks/config/petri.xml.h:15
-msgid "Minimum Lifespan"
+#: ../hacks/config/moire2.xml.h:10
+msgid ""
+"Generates fields of concentric circles or ovals, and combines the planes "
+"with various operations. The planes are moving independently of one another, "
+"causing the interference lines to spray. https://en.wikipedia.org/wiki/"
+"Moire_pattern Written by Jamie Zawinski; 1998."
 msgstr ""
 
-#: hacks/config/petri.xml.h:16
-msgid "Minimum Rate of Death"
+#: ../hacks/config/molecule.xml.h:1
+msgid "Molecule"
 msgstr ""
 
-#: hacks/config/petri.xml.h:17
-msgid "Minimum Rate of Growth"
-msgstr ""
+#: ../hacks/config/molecule.xml.h:8
+msgid "Label atoms"
+msgstr "Помечать атомы"
 
-#: hacks/config/petri.xml.h:18
-msgid "Mold Varieties"
-msgstr ""
+#: ../hacks/config/molecule.xml.h:9
+msgid "Describe molecule"
+msgstr "Описание молекулы"
 
-#: hacks/config/petri.xml.h:19
-msgid "Offspring"
-msgstr ""
+#: ../hacks/config/molecule.xml.h:12
+msgid "Draw atomic nuclei"
+msgstr "Прорисовывать частицы атомов"
 
-#: hacks/config/petri.xml.h:20
-msgid "Petri"
-msgstr ""
+#: ../hacks/config/molecule.xml.h:13
+msgid "Draw atomic bonds"
+msgstr "Прорисовывать связи между атомами"
 
-#: hacks/config/petri.xml.h:21
-msgid "Quickly"
-msgstr ""
+#: ../hacks/config/molecule.xml.h:14
+msgid "Draw electron shells"
+msgstr "Прорисовывать оболочки электронов"
 
-#: hacks/config/petri.xml.h:24
-msgid "Slowly"
+#: ../hacks/config/molecule.xml.h:25
+msgid "PDB file or directory"
+msgstr "Файл или папка PDB"
+
+#: ../hacks/config/molecule.xml.h:27
+#, no-c-format
+msgid ""
+"Some interesting molecules. Several molecules are built in, and it can also "
+"read PDB (Protein Data Bank) files as input. https://en.wikipedia.org/wiki/"
+"Protein_Data_Bank_%28file_format%29 Written by Jamie Zawinski; 2001."
 msgstr ""
 
-#: hacks/config/petri.xml.h:26
-msgid "Square"
+#: ../hacks/config/morph3d.xml.h:1
+msgid "Morph3D"
 msgstr ""
 
-#: hacks/config/petri.xml.h:27
+#: ../hacks/config/morph3d.xml.h:7 ../hacks/config/polyhedra.xml.h:30
+#: ../hacks/config/sballs.xml.h:7
+msgid "Cube"
+msgstr "Куб"
+
+#: ../hacks/config/morph3d.xml.h:8 ../hacks/config/polyhedra.xml.h:29
+#: ../hacks/config/sballs.xml.h:8
+msgid "Octahedron"
+msgstr "Октаэдр"
+
+#: ../hacks/config/morph3d.xml.h:9 ../hacks/config/polyhedra.xml.h:62
+#: ../hacks/config/sballs.xml.h:9
+msgid "Dodecahedron"
+msgstr "Додекаэдр"
+
+#: ../hacks/config/morph3d.xml.h:10 ../hacks/config/polyhedra.xml.h:61
+#: ../hacks/config/sballs.xml.h:10
+msgid "Icosahedron"
+msgstr "Икосаэдр"
+
+#: ../hacks/config/morph3d.xml.h:12
 msgid ""
-"This simulates colonies of mold growing in a petri dish. Growing colored "
-"circles overlap and leave spiral interference in their wake. Written by Dan "
-"Bornstein."
+"Platonic solids that turn inside out and get spikey. https://en.wikipedia."
+"org/wiki/Platonic_solid Written by Marcelo Vianna; 1997."
 msgstr ""
 
-#: hacks/config/phosphor.xml.h:1
-msgid ""
-"Draws a simulation of an old terminal, with large pixels and long-sustain "
-"phosphor. This program is also a fully-functional VT100 emulator! The text "
-"can be the output of a program or the contents of a file or URL, as "
-"configured on the \"Advanced\" tab of the main Screensaver Preferences "
-"window. Written by Jamie Zawinski."
+#: ../hacks/config/mountain.xml.h:1
+msgid "Mountain"
 msgstr ""
 
-#: hacks/config/phosphor.xml.h:2
-msgid "Dump pipe"
+#: ../hacks/config/mountain.xml.h:6
+msgid "Peaks"
+msgstr "Пики"
+
+#: ../hacks/config/mountain.xml.h:12
+msgid ""
+"Generates random 3D plots that look vaguely mountainous. Written by Pascal "
+"Pensa; 1997."
 msgstr ""
 
-#: hacks/config/phosphor.xml.h:5
-msgid "Phosphor"
+#: ../hacks/config/munch.xml.h:1
+msgid "Munch"
 msgstr ""
 
-#: hacks/config/phosphor.xml.h:10
-#, fuzzy
-msgid "Use PTY"
-msgstr "Использовать"
+#: ../hacks/config/munch.xml.h:11
+msgid "Munch or mismunch"
+msgstr "Соединение или разделение"
 
-#: hacks/config/piecewise.xml.h:1
-msgid "Color shifting speed"
-msgstr ""
+#: ../hacks/config/munch.xml.h:12
+msgid "Munch only"
+msgstr "Только соединение"
 
-#: hacks/config/piecewise.xml.h:6
-msgid "Maximum radius"
-msgstr ""
+#: ../hacks/config/munch.xml.h:13
+msgid "Mismunch only"
+msgstr "Только разделение"
 
-#: hacks/config/piecewise.xml.h:7
-msgid "Minimum radius"
+#: ../hacks/config/munch.xml.h:17
+msgid ""
+"DATAI 2 ADDB 1,2 ROTC 2,-22 XOR 1,2 JRST .-4 As reported by HAKMEM (MIT AI "
+"Memo 239, 1972), Jackson Wright wrote the above PDP-1 code in 1962. That "
+"code still lives on here, some 46 years later. In \"mismunch\" mode, it "
+"displays a creatively broken misimplementation of the classic munching "
+"squares algorithm instead. https://en.wikipedia.org/wiki/HAKMEM https://en."
+"wikipedia.org/wiki/Munching_square Written by Jackson Wright, Tim Showalter, "
+"Jamie Zawinski and Steven Hazel; 1997."
 msgstr ""
 
-#: hacks/config/piecewise.xml.h:8
-msgid "Piecewise"
+#: ../hacks/config/nerverot.xml.h:1
+msgid "NerveRot"
 msgstr ""
 
-#: hacks/config/piecewise.xml.h:12
-msgid ""
-"This draws a bunch of moving circles which switch from visibility to "
-"invisibility at intersection points. Written by Geoffrey Irving."
-msgstr ""
+#: ../hacks/config/nerverot.xml.h:9
+msgid "Blot count"
+msgstr "Количество пятен"
 
-#: hacks/config/pinion.xml.h:1
-#, fuzzy
-msgid "100"
-msgstr "100%"
+#: ../hacks/config/nerverot.xml.h:12 ../hacks/config/raverhoop.xml.h:6
+#: ../hacks/config/topblock.xml.h:14
+msgid "Colors"
+msgstr "Цвета"
 
-#: hacks/config/pinion.xml.h:2
-msgid "2000"
-msgstr ""
+#: ../hacks/config/nerverot.xml.h:13 ../hacks/config/pyro.xml.h:8
+#: ../hacks/config/splodesic.xml.h:5
+msgid "Seldom"
+msgstr "Редкие"
 
-#: hacks/config/pinion.xml.h:4
-msgid ""
-"Draws an interconnected set of gears moving across the screen. Written by "
-"Jamie Zawinski."
-msgstr ""
+#: ../hacks/config/nerverot.xml.h:14
+msgid "Changes"
+msgstr "Изменения"
 
-#: hacks/config/pinion.xml.h:6
-#, fuzzy
-msgid "Gear Size"
-msgstr "Размер сетки"
+#: ../hacks/config/nerverot.xml.h:15
+msgid "Frequent"
+msgstr "Постоянные"
 
-#: hacks/config/pinion.xml.h:8
-msgid "Max RPM"
-msgstr ""
+#: ../hacks/config/nerverot.xml.h:16
+msgid "Calm"
+msgstr "Спокойный"
 
-#: hacks/config/pinion.xml.h:9
-#, fuzzy
-msgid "Pinion"
-msgstr "Длинный"
+#: ../hacks/config/nerverot.xml.h:17
+msgid "Nervousness"
+msgstr "Нервозность"
 
-#: hacks/config/pinion.xml.h:11
-#, fuzzy
-msgid "Scrolling Speed"
-msgstr "Скорость решения"
+#: ../hacks/config/nerverot.xml.h:18
+msgid "Spastic"
+msgstr "Припадочный"
 
-#: hacks/config/pipes.xml.h:1
-msgid "Allow Tight Turns"
-msgstr ""
+#: ../hacks/config/nerverot.xml.h:19
+msgid "Crunchiness"
+msgstr "Разрыв"
 
-#: hacks/config/pipes.xml.h:2
-msgid "Ball Joints"
+#: ../hacks/config/nerverot.xml.h:22
+msgid "Nervously vibrating squiggles. Written by Dan Bornstein; 2000."
 msgstr ""
 
-#: hacks/config/pipes.xml.h:3
-msgid "Curved Pipes"
+#: ../hacks/config/noof.xml.h:1
+msgid "Noof"
 msgstr ""
 
-#: hacks/config/pipes.xml.h:6
-msgid "Fisheye Lens"
+#: ../hacks/config/noof.xml.h:6
+msgid "Flowery, rotatey patterns. Written by Bill Torzewski; 2004."
 msgstr ""
 
-#: hacks/config/pipes.xml.h:7
-msgid "Gadgetry"
+#: ../hacks/config/noseguy.xml.h:1
+msgid "NoseGuy"
 msgstr ""
 
-#: hacks/config/pipes.xml.h:8
+#: ../hacks/config/noseguy.xml.h:3
 msgid ""
-"If you've ever been in the same room with a Windows NT machine, you've "
-"probably seen this GL hack. This version is by Marcelo Vianna."
+"A little man with a big nose wanders around your screen saying things. "
+"Written by Dan Heller and Jamie Zawinski; 1992."
 msgstr ""
 
-#: hacks/config/pipes.xml.h:11
-msgid "Number of Pipe Systems"
+#: ../hacks/config/pacman.xml.h:1
+msgid "Pacman"
 msgstr ""
 
-#: hacks/config/pipes.xml.h:12
-msgid "Pipe Fittings"
-msgstr ""
+#: ../hacks/config/pacman.xml.h:5
+msgid "Player size"
+msgstr "Размер плейера"
 
-#: hacks/config/pipes.xml.h:13
-msgid "Pipes"
+#: ../hacks/config/pacman.xml.h:7
+msgid ""
+"Simulates a game of Pac-Man on a randomly-created level. https://en."
+"wikipedia.org/wiki/Pac-Man Written by Edwin de Jong and Jamie Zawinski; 2004."
 msgstr ""
 
-#: hacks/config/pipes.xml.h:17
-msgid "System Length"
+#: ../hacks/config/pedal.xml.h:1
+msgid "Pedal"
 msgstr ""
 
-#: hacks/config/polyhedra.xml.h:4 hacks/config/sballs.xml.h:1
-msgid "Cube"
+#: ../hacks/config/pedal.xml.h:10
+msgid ""
+"The even-odd winding rule. https://en.wikipedia.org/wiki/Even-odd_rule "
+"https://en.wikipedia.org/wiki/Nonzero-rule Written by Dale Moore; 1995."
 msgstr ""
 
-#: hacks/config/polyhedra.xml.h:5
-msgid "Cubitruncated Cuboctahedron"
+#: ../hacks/config/penetrate.xml.h:1
+msgid "Penetrate"
 msgstr ""
 
-#: hacks/config/polyhedra.xml.h:6
-msgid "Cuboctahedron"
-msgstr ""
+#: ../hacks/config/penetrate.xml.h:3
+msgid "Explosions"
+msgstr "Взрывы"
 
-#: hacks/config/polyhedra.xml.h:7
-msgid "Cubohemioctahedron"
-msgstr ""
+#: ../hacks/config/penetrate.xml.h:6
+msgid "Start badly, but learn"
+msgstr "Начинать плохо, но потом учиться"
 
-#: hacks/config/polyhedra.xml.h:8
-msgid "Deltoidal Hexecontahedron"
-msgstr ""
+#: ../hacks/config/penetrate.xml.h:7
+msgid "Always play well"
+msgstr "Всегда играть хорошо"
 
-#: hacks/config/polyhedra.xml.h:9
-msgid "Deltoidal Icositetrahedron"
+#: ../hacks/config/penetrate.xml.h:9
+msgid ""
+"Simulates (something like) the classic arcade game Missile Command. https://"
+"en.wikipedia.org/wiki/Missile_Command Written by Adam Miller; 1999."
 msgstr ""
 
-#: hacks/config/polyhedra.xml.h:10
-msgid "Disdyakisdodecahedron"
+#: ../hacks/config/penrose.xml.h:1
+msgid "Penrose"
 msgstr ""
 
-#: hacks/config/polyhedra.xml.h:11
-msgid "Disdyakistriacontahedron"
+#: ../hacks/config/penrose.xml.h:11
+msgid "Draw ammann lines"
+msgstr "Прорисовывать промежуточные линии"
+
+#: ../hacks/config/penrose.xml.h:13
+msgid ""
+"Quasiperiodic tilings. In April 1997, Sir Roger Penrose, a British math "
+"professor who has worked with Stephen Hawking on such topics as relativity, "
+"black holes, and whether time has a beginning, filed a copyright-"
+"infringement lawsuit against the Kimberly-Clark Corporation, which Penrose "
+"said copied a pattern he created (a pattern demonstrating that \"a "
+"nonrepeating pattern could exist in nature\") for its Kleenex quilted toilet "
+"paper. Penrose said he doesn't like litigation but, \"When it comes to the "
+"population of Great Britain being invited by a multinational to wipe their "
+"bottoms on what appears to be the work of a Knight of the Realm, then a last "
+"stand must be taken.\" As reported by News of the Weird #491, 4-Jul-1997. "
+"https://en.wikipedia.org/wiki/Penrose_tiling https://en.wikipedia.org/wiki/"
+"Tessellation Written by Timo Korvola; 1997."
 msgstr ""
 
-#: hacks/config/polyhedra.xml.h:12
-msgid "Display Random Polyhedron"
+#: ../hacks/config/petri.xml.h:1
+msgid "Petri"
 msgstr ""
 
-#: hacks/config/polyhedra.xml.h:13
+#: ../hacks/config/petri.xml.h:6
+msgid "Square"
+msgstr "Квадрат"
+
+#: ../hacks/config/petri.xml.h:7
+msgid "Colony shape"
+msgstr "Форма колонии"
+
+#: ../hacks/config/petri.xml.h:8
+msgid "Diamond"
+msgstr "Бриллиант"
+
+#: ../hacks/config/petri.xml.h:9
+msgid "Fertility"
+msgstr "Размножение"
+
+#: ../hacks/config/petri.xml.h:11
+msgid "Offspring"
+msgstr "Потомки"
+
+#: ../hacks/config/petri.xml.h:13
+msgid "Slowly"
+msgstr "Медленно"
+
+#: ../hacks/config/petri.xml.h:14
+msgid "Death comes"
+msgstr "Смерть наступает"
+
+#: ../hacks/config/petri.xml.h:15
+msgid "Quickly"
+msgstr "Быстро"
+
+#: ../hacks/config/petri.xml.h:17
+msgid "Minimum rate of growth"
+msgstr "Минимальный темп роста"
+
+#: ../hacks/config/petri.xml.h:19
+msgid "Maximum rate of growth"
+msgstr "Максимальный темп роста"
+
+#: ../hacks/config/petri.xml.h:20
+msgid "Minimum rate of death"
+msgstr "Минимальный темп смерти"
+
+#: ../hacks/config/petri.xml.h:21
+msgid "Maximum rate of death"
+msgstr "Максимальный темп смерти"
+
+#: ../hacks/config/petri.xml.h:23
+msgid "Minimum lifespan"
+msgstr "Минимальное время жизни"
+
+#: ../hacks/config/petri.xml.h:25
+msgid "Maximum lifespan"
+msgstr "Максимальное время жизни"
+
+#: ../hacks/config/petri.xml.h:27
+msgid "Mold varieties"
+msgstr "Разновидности форм"
+
+#: ../hacks/config/petri.xml.h:28
 msgid ""
-"Displays different 3D solids and some information about each. A new solid is "
-"chosen every few seconds. There are 75 uniform polyhedra, plus 5 infinite "
-"sets of prisms and antiprisms; including their duals brings the total to "
-"160. Written by Dr. Zvi Har'El and Jamie Zawinski."
+"Colonies of mold grow in a petri dish. Growing colored circles overlap and "
+"leave spiral interference in their wake. Written by Dan Bornstein; 1999."
 msgstr ""
 
-#: hacks/config/polyhedra.xml.h:14
-msgid "Ditrigonal Dodecadodecahedron"
+#: ../hacks/config/phosphor.xml.h:1
+msgid "Phosphor"
 msgstr ""
 
-#: hacks/config/polyhedra.xml.h:15 hacks/config/sballs.xml.h:2
-msgid "Dodecahedron"
-msgstr ""
+#: ../hacks/config/phosphor.xml.h:5
+msgid "Font scale"
+msgstr "Размер шрифта"
 
-#: hacks/config/polyhedra.xml.h:18
-msgid "Great Cubicuboctahedron"
+#: ../hacks/config/phosphor.xml.h:14
+msgid ""
+"An old terminal with large pixels and long-sustain phosphor. On MacOS and "
+"Linux, this program is also a fully-functional VT100 emulator! Run it as an "
+"application instead of as a screen saver and you can use it as a terminal. "
+"Written by Jamie Zawinski; 1999."
 msgstr ""
 
-#: hacks/config/polyhedra.xml.h:19
-msgid "Great Deltoidal Hexecontahedron"
+#: ../hacks/config/photopile.xml.h:1
+msgid "Photopile"
 msgstr ""
 
-#: hacks/config/polyhedra.xml.h:20
-msgid "Great Deltoidal Icositetrahedron"
-msgstr ""
+#: ../hacks/config/photopile.xml.h:3
+msgid "Image size"
+msgstr "Размер изображения"
 
-#: hacks/config/polyhedra.xml.h:21
-msgid "Great Dirhombicosidodecacron"
-msgstr ""
+#: ../hacks/config/photopile.xml.h:5 ../hacks/config/t3d.xml.h:5
+msgid "0 deg"
+msgstr "0 градусов"
 
-#: hacks/config/polyhedra.xml.h:22
-msgid "Great Dirhombicosidodecahedron"
-msgstr ""
+#: ../hacks/config/photopile.xml.h:6
+msgid "Maximum angle from vertical"
+msgstr "Максимальный угол по вертикали"
 
-#: hacks/config/polyhedra.xml.h:23
-msgid "Great Disdyakisdodecahedron"
-msgstr ""
+#: ../hacks/config/photopile.xml.h:7 ../hacks/config/t3d.xml.h:7
+msgid "90 deg"
+msgstr "90 градусов"
 
-#: hacks/config/polyhedra.xml.h:24
-msgid "Great Disdyakistriacontahedron"
-msgstr ""
+#: ../hacks/config/photopile.xml.h:9
+msgid "Simulate instant film"
+msgstr "Симулировать моментальную фотографию"
 
-#: hacks/config/polyhedra.xml.h:25
-msgid "Great Ditrigonal Dodecacronic Hexecontahedron"
-msgstr ""
+#: ../hacks/config/photopile.xml.h:10
+msgid "Instant film theme"
+msgstr "Тема быстрой пленки"
 
-#: hacks/config/polyhedra.xml.h:26
-msgid "Great Ditrigonal Dodecicosidodecahedron"
-msgstr ""
+#: ../hacks/config/photopile.xml.h:11
+msgid "Draw drop shadows"
+msgstr "Прорисовывать падающие тени"
 
-#: hacks/config/polyhedra.xml.h:27
-msgid "Great Ditrigonal Icosidodecahedron"
+#: ../hacks/config/photopile.xml.h:23
+msgid ""
+"Loads several random images, and displays them as if lying in a random pile. "
+"The pile is periodically reshuffled, with new images coming in and old ones "
+"being thrown out. Written by Jens Kilian and Jamie Zawinski; 2008."
 msgstr ""
 
-#: hacks/config/polyhedra.xml.h:28
-msgid "Great Dodecacronic Hexecontahedron"
+#: ../hacks/config/piecewise.xml.h:1
+msgid "Piecewise"
 msgstr ""
 
-#: hacks/config/polyhedra.xml.h:29
-msgid "Great Dodecadodecahedron"
-msgstr ""
+#: ../hacks/config/piecewise.xml.h:9
+msgid "Color shift"
+msgstr "Изменение цвета"
 
-#: hacks/config/polyhedra.xml.h:30
-msgid "Great Dodecahedron"
-msgstr ""
+#: ../hacks/config/piecewise.xml.h:12
+msgid "Minimum radius"
+msgstr "Минимальный радиус"
 
-#: hacks/config/polyhedra.xml.h:31
-msgid "Great Dodecahemicosacron"
-msgstr ""
+#: ../hacks/config/piecewise.xml.h:14
+msgid "Maximum radius"
+msgstr "Максимальный радиус"
 
-#: hacks/config/polyhedra.xml.h:32
-msgid "Great Dodecahemicosahedron"
+#: ../hacks/config/piecewise.xml.h:16
+msgid ""
+"Moving circles switch from visibility to invisibility at intersection "
+"points. Written by Geoffrey Irving; 2003."
 msgstr ""
 
-#: hacks/config/polyhedra.xml.h:33
-msgid "Great Dodecahemidodecacron"
+#: ../hacks/config/pinion.xml.h:1
+msgid "Pinion"
 msgstr ""
 
-#: hacks/config/polyhedra.xml.h:34
-msgid "Great Dodecahemidodecahedron"
-msgstr ""
+#: ../hacks/config/pinion.xml.h:8
+msgid "Scrolling speed"
+msgstr "Скорость прокрутки"
 
-#: hacks/config/polyhedra.xml.h:35
-msgid "Great Dodecicosacron"
-msgstr ""
+#: ../hacks/config/pinion.xml.h:10
+msgid "Gear size"
+msgstr "Размер шестеренок"
 
-#: hacks/config/polyhedra.xml.h:36
-msgid "Great Dodecicosahedron"
+#: ../hacks/config/pinion.xml.h:12 ../hacks/config/projectiveplane.xml.h:34
+msgid "100"
 msgstr ""
 
-#: hacks/config/polyhedra.xml.h:37
-msgid "Great Dodecicosidodecahedron"
-msgstr ""
+#: ../hacks/config/pinion.xml.h:13
+msgid "Max RPM"
+msgstr "Максимальное количество оборотов в минуту"
 
-#: hacks/config/polyhedra.xml.h:38
-msgid "Great Hexacronic Icositetrahedron"
+#: ../hacks/config/pinion.xml.h:14
+msgid "2000"
 msgstr ""
 
-#: hacks/config/polyhedra.xml.h:39
-msgid "Great Hexagonal Hexecontahedron"
+#: ../hacks/config/pinion.xml.h:17
+msgid ""
+"A gear system marches across the screen. See also the \"Gears\" and "
+"\"MoebiusGears\" screen savers. https://en.wikipedia.org/wiki/Involute_gear "
+"Written by Jamie Zawinski; 2004."
 msgstr ""
 
-#: hacks/config/polyhedra.xml.h:40
-msgid "Great Icosacronic Hexecontahedron"
+#: ../hacks/config/pipes.xml.h:1
+msgid "Pipes"
 msgstr ""
 
-#: hacks/config/polyhedra.xml.h:41
-msgid "Great Icosahedron"
-msgstr ""
+#: ../hacks/config/pipes.xml.h:6
+msgid "Number of pipes"
+msgstr "Количество труб"
+
+#: ../hacks/config/pipes.xml.h:7
+msgid "A hundred"
+msgstr "Сто"
 
-#: hacks/config/polyhedra.xml.h:42
-msgid "Great Icosicosidodecahedron"
-msgstr ""
+#: ../hacks/config/pipes.xml.h:9
+msgid "Pipe length"
+msgstr "Длина трубы"
 
-#: hacks/config/polyhedra.xml.h:43
-msgid "Great Icosidodecahedron"
-msgstr ""
+#: ../hacks/config/pipes.xml.h:12
+msgid "Gadgetry"
+msgstr "Устройства"
 
-#: hacks/config/polyhedra.xml.h:44
-msgid "Great Icosihemidodecacron"
-msgstr ""
+#: ../hacks/config/pipes.xml.h:14
+msgid "Fisheye lens"
+msgstr "Линза \"Рыбий глаз\""
 
-#: hacks/config/polyhedra.xml.h:45
-msgid "Great Icosihemidodecahedron"
-msgstr ""
+#: ../hacks/config/pipes.xml.h:15
+msgid "Allow tight turns"
+msgstr "Разрешать крутые повороты"
 
-#: hacks/config/polyhedra.xml.h:46
-msgid "Great Inverted Pentagonal Hexecontahedron"
-msgstr ""
+#: ../hacks/config/pipes.xml.h:16
+msgid "Curved pipes"
+msgstr "Искривленные трубы"
 
-#: hacks/config/polyhedra.xml.h:47
-msgid "Great Inverted Snub Icosidodecahedron"
-msgstr ""
+#: ../hacks/config/pipes.xml.h:17
+msgid "Ball joints"
+msgstr "Шаровые шарниры"
 
-#: hacks/config/polyhedra.xml.h:48
-msgid "Great Pentagonal Hexecontahedron"
-msgstr ""
+#: ../hacks/config/pipes.xml.h:18
+msgid "Bolted fittings"
+msgstr "Болтовые фитинги"
 
-#: hacks/config/polyhedra.xml.h:49
-msgid "Great Pentagrammic Hexecontahedron"
-msgstr ""
+#: ../hacks/config/pipes.xml.h:19
+msgid "Random style"
+msgstr "Случайный стиль"
 
-#: hacks/config/polyhedra.xml.h:50
-msgid "Great Pentakisdodekahedron"
+#: ../hacks/config/pipes.xml.h:22
+msgid ""
+"A growing plumbing system, with bolts and valves. Written by Marcelo Vianna "
+"and Jamie Zawinski; 1997."
 msgstr ""
 
-#: hacks/config/polyhedra.xml.h:51
-msgid "Great Retrosnub Icosidodecahedron"
+#: ../hacks/config/polyhedra.xml.h:1
+msgid "Polyhedra"
 msgstr ""
 
-#: hacks/config/polyhedra.xml.h:52
-msgid "Great Rhombic Triacontahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:11
+msgid "Display random polyhedron"
+msgstr "Показывать случайный многогранник"
 
-#: hacks/config/polyhedra.xml.h:53
-msgid "Great Rhombicosidodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:12
+msgid "Pentagonal prism"
+msgstr "Пентагональная призма"
 
-#: hacks/config/polyhedra.xml.h:54
-msgid "Great Rhombicuboctahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:13
+msgid "Pentagonal dipyramid"
+msgstr "Пентагональная бипирамида"
 
-#: hacks/config/polyhedra.xml.h:55
-msgid "Great Rhombidodecacron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:14
+msgid "Pentagonal antiprism"
+msgstr "Пентагональная антипризма"
 
-#: hacks/config/polyhedra.xml.h:56
-msgid "Great Rhombidodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:15
+msgid "Pentagonal deltohedron"
+msgstr "Пентагональный трапецоэдр"
 
-#: hacks/config/polyhedra.xml.h:57
-msgid "Great Rhombihexacron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:16
+msgid "Pentagrammic prism"
+msgstr "Пентаграммическая призма"
 
-#: hacks/config/polyhedra.xml.h:58
-msgid "Great Rhombihexahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:17
+msgid "Pentagrammic dipyramid"
+msgstr "Пентаграммическая бипирамида"
 
-#: hacks/config/polyhedra.xml.h:59
-msgid "Great Snub Dodecicosidodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:18
+msgid "Pentagrammic antiprism"
+msgstr "Пентаграммическая антипризма"
 
-#: hacks/config/polyhedra.xml.h:60
-msgid "Great Snub Icosidodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:19
+msgid "Pentagrammic deltohedron"
+msgstr "Пентаграммический трапецоэдр"
 
-#: hacks/config/polyhedra.xml.h:61
-msgid "Great Stellapentakisdodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:20
+msgid "Pentagrammic crossed antiprism"
+msgstr "Пентаграммическая скрещенная антипризма"
 
-#: hacks/config/polyhedra.xml.h:62
-msgid "Great Stellated Dodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:21
+msgid "Pentagrammic concave deltohedron"
+msgstr "Пентаграммический вогнутый трапецоэдр"
 
-#: hacks/config/polyhedra.xml.h:63
-msgid "Great Stellated Truncated Dodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:23
+msgid "Truncated tetrahedron"
+msgstr "Усеченный тетраэдр"
 
-#: hacks/config/polyhedra.xml.h:64
-msgid "Great Triakisicosahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:24
+msgid "Triakistetrahedron"
+msgstr "Триакистетраэдр"
 
-#: hacks/config/polyhedra.xml.h:65
-msgid "Great Triakisoctahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:25
+msgid "Octahemioctahedron"
+msgstr "Октагемиоктаэдр"
 
-#: hacks/config/polyhedra.xml.h:66
-msgid "Great Triambic Icosahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:26
+msgid "Octahemioctacron"
+msgstr "Октахемиоктакрон"
 
-#: hacks/config/polyhedra.xml.h:67
-msgid "Great Truncated Cuboctahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:27
+msgid "Tetrahemihexahedron"
+msgstr "Тетрагемигексаэдр"
 
-#: hacks/config/polyhedra.xml.h:68
-msgid "Great Truncated Icosahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:28
+msgid "Tetrahemihexacron"
+msgstr "Тетрагемигексакрон"
 
-#: hacks/config/polyhedra.xml.h:69
-msgid "Great Truncated Icosidodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:31
+msgid "Cuboctahedron"
+msgstr "Кубооктаэдр"
 
-#: hacks/config/polyhedra.xml.h:70
-msgid "Hexahemioctacron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:32
+msgid "Rhombic dodecahedron"
+msgstr "Ромбический додекаэдр"
 
-#: hacks/config/polyhedra.xml.h:71 hacks/config/sballs.xml.h:5
-msgid "Icosahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:33
+msgid "Truncated octahedron"
+msgstr "Усеченный октаэдр"
 
-#: hacks/config/polyhedra.xml.h:72
-msgid "Icosidodecadodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:34
+msgid "Tetrakishexahedron"
+msgstr "Тетракисгексаэдр"
 
-#: hacks/config/polyhedra.xml.h:73
-msgid "Icosidodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:35
+msgid "Truncated cube"
+msgstr "Усеченный куб"
 
-#: hacks/config/polyhedra.xml.h:74
-msgid "Icositruncated Dodecadodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:36
+msgid "Triakisoctahedron"
+msgstr "Триакисоктаэдр"
 
-#: hacks/config/polyhedra.xml.h:75
-msgid "Inverted Snub Dodecadodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:37
+msgid "Rhombicuboctahedron"
+msgstr "Ромбокубооктаэдр"
 
-#: hacks/config/polyhedra.xml.h:76
-msgid "Medial Deltoidal Hexecontahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:38
+msgid "Deltoidal icositetrahedron"
+msgstr "Дельтоидальный икоситетраэдр"
 
-#: hacks/config/polyhedra.xml.h:77
-msgid "Medial Disdyakistriacontahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:39
+msgid "Truncated cuboctahedron"
+msgstr "Усеченный кубооктаэдр"
 
-#: hacks/config/polyhedra.xml.h:78
-msgid "Medial Hexagonal Hexecontahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:40
+msgid "Disdyakisdodecahedron"
+msgstr "Гекзакисоктаэдр"
 
-#: hacks/config/polyhedra.xml.h:79
-msgid "Medial Icosacronic Hexecontahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:41
+msgid "Snub cube"
+msgstr "Плосконосый куб"
 
-#: hacks/config/polyhedra.xml.h:80
-msgid "Medial Inverted Pentagonal Hexecontahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:42
+msgid "Pentagonal icositetrahedron"
+msgstr "Пентагональный икоситетраэдр"
 
-#: hacks/config/polyhedra.xml.h:81
-msgid "Medial Pentagonal Hexecontahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:43
+msgid "Small cubicuboctahedron"
+msgstr "Малый кубокубооктаэдр"
 
-#: hacks/config/polyhedra.xml.h:82
-msgid "Medial Rhombic Triacontahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:44
+msgid "Small hexacronic icositetrahedron"
+msgstr "Малый гексакронный икоситетраэдр"
 
-#: hacks/config/polyhedra.xml.h:83
-msgid "Medial Triambic Icosahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:45
+msgid "Great cubicuboctahedron"
+msgstr "Большой кубокубооктаэдр"
 
-#: hacks/config/polyhedra.xml.h:85 hacks/config/sballs.xml.h:7
-msgid "Octahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:46
+msgid "Great hexacronic icositetrahedron"
+msgstr "Большой гексакронный икоситетраэдр"
 
-#: hacks/config/polyhedra.xml.h:86
-msgid "Octahemioctacron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:47
+msgid "Cubohemioctahedron"
+msgstr "Кубогемиоктаэдр"
 
-#: hacks/config/polyhedra.xml.h:87
-msgid "Octahemioctahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:48
+msgid "Hexahemioctacron"
+msgstr "Гексагемиоктакрон"
 
-#: hacks/config/polyhedra.xml.h:88
-msgid "Pentagonal Antiprism"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:49
+msgid "Cubitruncated cuboctahedron"
+msgstr "Кубоусеченный кубооктаэдр"
 
-#: hacks/config/polyhedra.xml.h:89
-msgid "Pentagonal Deltohedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:50
+msgid "Tetradyakishexahedron"
+msgstr "Тетрадиакисгексаэдр"
 
-#: hacks/config/polyhedra.xml.h:90
-msgid "Pentagonal Dipyramid"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:51
+msgid "Great rhombicuboctahedron"
+msgstr "Большой ромбокубооктаэдр"
 
-#: hacks/config/polyhedra.xml.h:91
-msgid "Pentagonal Hexecontahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:52
+msgid "Great deltoidal icositetrahedron"
+msgstr "Большой дельтоидальный икоситетраэдр"
 
-#: hacks/config/polyhedra.xml.h:92
-msgid "Pentagonal Icositetrahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:53
+msgid "Small rhombihexahedron"
+msgstr "Малый ромбогексаэдр"
 
-#: hacks/config/polyhedra.xml.h:93
-msgid "Pentagonal Prism"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:54
+msgid "Small rhombihexacron"
+msgstr "Малый ромбогексакрон"
 
-#: hacks/config/polyhedra.xml.h:94
-msgid "Pentagrammic Antiprism"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:55
+msgid "Stellated truncated hexahedron"
+msgstr "Звездообразный усеченный гексаэдр"
 
-#: hacks/config/polyhedra.xml.h:95
-msgid "Pentagrammic Concave Deltohedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:56
+msgid "Great triakisoctahedron"
+msgstr "Большой триакисоктаэдр"
 
-#: hacks/config/polyhedra.xml.h:96
-msgid "Pentagrammic Crossed Antiprism"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:57
+msgid "Great truncated cuboctahedron"
+msgstr "Большой усеченный кубооктаэдр"
 
-#: hacks/config/polyhedra.xml.h:97
-msgid "Pentagrammic Deltohedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:58
+msgid "Great disdyakisdodecahedron"
+msgstr "Большой гекзакисоктаэдр"
 
-#: hacks/config/polyhedra.xml.h:98
-msgid "Pentagrammic Dipyramid"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:59
+msgid "Great rhombihexahedron"
+msgstr "Большой ромбогексаэдр"
 
-#: hacks/config/polyhedra.xml.h:99
-msgid "Pentagrammic Prism"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:60
+msgid "Great rhombihexacron"
+msgstr "Большой ромбогексакрон"
 
-#: hacks/config/polyhedra.xml.h:100
-msgid "Pentakisdodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:63
+msgid "Icosidodecahedron"
+msgstr "Икосододекаэдр"
 
-#: hacks/config/polyhedra.xml.h:101
-msgid "Polyhedra"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:64
+msgid "Rhombic triacontahedron"
+msgstr "Ромботриаконтаэдр"
 
-#: hacks/config/polyhedra.xml.h:102
-msgid "Rhombic Dodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:65
+msgid "Truncated icosahedron"
+msgstr "Усеченный икосаэдр"
 
-#: hacks/config/polyhedra.xml.h:103
-msgid "Rhombic Triacontahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:66
+msgid "Pentakisdodecahedron"
+msgstr "Пентакисдодекаэдр"
 
-#: hacks/config/polyhedra.xml.h:104
-msgid "Rhombicosacron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:67
+msgid "Truncated dodecahedron"
+msgstr "Усеченный додекаэдр"
 
-#: hacks/config/polyhedra.xml.h:105
-msgid "Rhombicosahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:68
+msgid "Triakisicosahedron"
+msgstr "Триакисикосаэдр"
 
-#: hacks/config/polyhedra.xml.h:106
+#: ../hacks/config/polyhedra.xml.h:69
 msgid "Rhombicosidodecahedron"
-msgstr ""
+msgstr "Ромбоикосододекаэдр"
 
-#: hacks/config/polyhedra.xml.h:107
-msgid "Rhombicuboctahedron"
-msgstr ""
-
-#: hacks/config/polyhedra.xml.h:108
-msgid "Rhombidodecadodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:70
+msgid "Deltoidal hexecontahedron"
+msgstr "Дельтоидальный гексеконтаэдр"
 
-#: hacks/config/polyhedra.xml.h:109
-#, fuzzy
-msgid "Show Description"
-msgstr "Описание"
+#: ../hacks/config/polyhedra.xml.h:71
+msgid "Truncated icosidodecahedron"
+msgstr "Усеченный икосододекаэдр"
 
-#: hacks/config/polyhedra.xml.h:112
-msgid "Small Cubicuboctahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:72
+msgid "Disdyakistriacontahedron"
+msgstr "Дисдиакистриаконтаэдр"
 
-#: hacks/config/polyhedra.xml.h:113
-msgid "Small Ditrigonal Dodecacronic Hexecontahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:73
+msgid "Snub dodecahedron"
+msgstr "Плосконосый додекаэдр"
 
-#: hacks/config/polyhedra.xml.h:114
-msgid "Small Ditrigonal Dodecicosidodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:74
+msgid "Pentagonal hexecontahedron"
+msgstr "Пентагональный гексеконтаэдр"
 
-#: hacks/config/polyhedra.xml.h:115
-msgid "Small Ditrigonal Icosidodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:75
+msgid "Small ditrigonal icosidodecahedron"
+msgstr "Малый дитригональный икосододекаэдр"
 
-#: hacks/config/polyhedra.xml.h:116
-msgid "Small Dodecacronic Hexecontahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:76
+msgid "Small triambic icosahedron"
+msgstr "Малый триамбический икосаэдр"
 
-#: hacks/config/polyhedra.xml.h:117
-msgid "Small Dodecahemicosacron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:77
+msgid "Small icosicosidodecahedron"
+msgstr "Малый икосоикосододекаэдр"
 
-#: hacks/config/polyhedra.xml.h:118
-msgid "Small Dodecahemicosahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:78
+msgid "Small icosacronic hexecontahedron"
+msgstr "Малый икосакронный гексеконтаэдр"
 
-#: hacks/config/polyhedra.xml.h:119
-msgid "Small Dodecahemidodecacron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:79
+msgid "Small snub icosicosidodecahedron"
+msgstr "Малый плосконосый икосоикосододекаэдр"
 
-#: hacks/config/polyhedra.xml.h:120
-msgid "Small Dodecahemidodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:80
+msgid "Small hexagonal hexecontahedron"
+msgstr "Малый гексагональный гексеконтаэдр"
 
-#: hacks/config/polyhedra.xml.h:121
-msgid "Small Dodecicosacron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:81
+msgid "Small dodecicosidodecahedron"
+msgstr "Малый додекоикосододекаэдр"
 
-#: hacks/config/polyhedra.xml.h:122
-msgid "Small Dodecicosahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:82
+msgid "Small dodecacronic hexecontahedron"
+msgstr "Малый додекакронный гексеконтаэдр"
 
-#: hacks/config/polyhedra.xml.h:123
-msgid "Small Dodecicosidodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:83
+msgid "Small stellated dodecahedron"
+msgstr "Малый звездообразный додекаэдр"
 
-#: hacks/config/polyhedra.xml.h:124
-msgid "Small Hexacronic Icositetrahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:84
+msgid "Great dodecahedron"
+msgstr "Большой додекаэдр"
 
-#: hacks/config/polyhedra.xml.h:125
-msgid "Small Hexagonal Hexecontahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:85
+msgid "Great dodecadodecahedron"
+msgstr "Большой додекододекаэдр"
 
-#: hacks/config/polyhedra.xml.h:126
-msgid "Small Hexagrammic Hexecontahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:86
+msgid "Medial rhombic triacontahedron"
+msgstr "Средний ромбический триаконтаэдр"
 
-#: hacks/config/polyhedra.xml.h:127
-msgid "Small Icosacronic Hexecontahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:87
+msgid "Truncated great dodecahedron"
+msgstr "Усеченный большой додекаэдр"
 
-#: hacks/config/polyhedra.xml.h:128
-msgid "Small Icosicosidodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:88
+msgid "Small stellapentakisdodecahedron"
+msgstr "Малый звездчатый пентакисдодекаэдр"
 
-#: hacks/config/polyhedra.xml.h:129
-msgid "Small Icosihemidodecacron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:89
+msgid "Rhombidodecadodecahedron"
+msgstr "Ромбододекододекаэдр"
 
-#: hacks/config/polyhedra.xml.h:130
-msgid "Small Icosihemidodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:90
+msgid "Medial deltoidal hexecontahedron"
+msgstr "Средний дельтоидальный гексеконтаэдр"
 
-#: hacks/config/polyhedra.xml.h:131
-msgid "Small Retrosnub Icosicosidodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:91
+msgid "Small rhombidodecahedron"
+msgstr "Малый ромбододекаэдр"
 
-#: hacks/config/polyhedra.xml.h:132
-msgid "Small Rhombidodecacron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:92
+msgid "Small rhombidodecacron"
+msgstr "Малый ромбододекакрон"
 
-#: hacks/config/polyhedra.xml.h:133
-msgid "Small Rhombidodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:93
+msgid "Snub dodecadodecahedron"
+msgstr "Плосконосый додекододекаэдр"
 
-#: hacks/config/polyhedra.xml.h:134
-msgid "Small Rhombihexacron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:94
+msgid "Medial pentagonal hexecontahedron"
+msgstr "Средний пентагональный гексеконтаэдр"
 
-#: hacks/config/polyhedra.xml.h:135
-msgid "Small Rhombihexahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:95
+msgid "Ditrigonal dodecadodecahedron"
+msgstr "Дитригональный додекододекаэдр"
 
-#: hacks/config/polyhedra.xml.h:136
-msgid "Small Snub Icosicosidodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:96
+msgid "Medial triambic icosahedron"
+msgstr "Средний триамбический икосаэдр"
 
-#: hacks/config/polyhedra.xml.h:137
-msgid "Small Stellapentakisdodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:97
+msgid "Great ditrigonal dodecicosidodecahedron"
+msgstr "Большой дитригональный додекоикосододекаэдр"
 
-#: hacks/config/polyhedra.xml.h:138
-msgid "Small Stellated Dodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:98
+msgid "Great ditrigonal dodecacronic hexecontahedron"
+msgstr "Большой дитригональный додекакронный гексеконтаэдр"
 
-#: hacks/config/polyhedra.xml.h:139
-msgid "Small Stellated Truncated Dodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:99
+msgid "Small ditrigonal dodecicosidodecahedron"
+msgstr "Малый дитригональный додекоикосододекаэдр"
 
-#: hacks/config/polyhedra.xml.h:140
-msgid "Small Triambic Icosahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:100
+msgid "Small ditrigonal dodecacronic hexecontahedron"
+msgstr "Малый дитригональный додекакронный гексеконтаэдр"
 
-#: hacks/config/polyhedra.xml.h:141
-msgid "Snub Cube"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:101
+msgid "Icosidodecadodecahedron"
+msgstr "Икосододекододекаэдр"
 
-#: hacks/config/polyhedra.xml.h:142
-msgid "Snub Dodecadodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:102
+msgid "Medial icosacronic hexecontahedron"
+msgstr "Средний икосакронный гексеконтаэдр"
 
-#: hacks/config/polyhedra.xml.h:143
-msgid "Snub Dodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:103
+msgid "Icositruncated dodecadodecahedron"
+msgstr "Икосоусеченный додекододекаэдр"
 
-#: hacks/config/polyhedra.xml.h:144
-msgid "Snub Icosidodecadodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:104
+msgid "Tridyakisicosahedron"
+msgstr "Тридиакисикосаэдр"
 
-#: hacks/config/polyhedra.xml.h:146
-msgid "Stellated Truncated Hexahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:105
+msgid "Snub icosidodecadodecahedron"
+msgstr "Плосконосый икосододекододекаэдр"
 
-#: hacks/config/polyhedra.xml.h:147
-msgid "Tetradyakishexahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:106
+msgid "Medial hexagonal hexecontahedron"
+msgstr "Средний гексагональный гексеконтаэдр"
 
-#: hacks/config/polyhedra.xml.h:149
-msgid "Tetrahemihexacron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:107
+msgid "Great ditrigonal icosidodecahedron"
+msgstr "Большой дитригональный икосододекаэдр"
 
-#: hacks/config/polyhedra.xml.h:150
-msgid "Tetrahemihexahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:108
+msgid "Great triambic icosahedron"
+msgstr "Большой триамбический икосаэдр"
 
-#: hacks/config/polyhedra.xml.h:151
-msgid "Tetrakishexahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:109
+msgid "Great icosicosidodecahedron"
+msgstr "Большой икосоикосододекаэдр"
 
-#: hacks/config/polyhedra.xml.h:152
-msgid "Triakisicosahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:110
+msgid "Great icosacronic hexecontahedron"
+msgstr "Большой икосакронный гексеконтаэдр"
 
-#: hacks/config/polyhedra.xml.h:153
-msgid "Triakisoctahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:111
+msgid "Small icosihemidodecahedron"
+msgstr "Малый икосогемидодекаэдр"
 
-#: hacks/config/polyhedra.xml.h:154
-msgid "Triakistetrahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:112
+msgid "Small icosihemidodecacron"
+msgstr "Малый икосогемидодекакрон"
 
-#: hacks/config/polyhedra.xml.h:155
-msgid "Tridyakisicosahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:113
+msgid "Small dodecicosahedron"
+msgstr "Малый додекоикосаэдр"
 
-#: hacks/config/polyhedra.xml.h:156
-msgid "Truncated Cube"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:114
+msgid "Small dodecicosacron"
+msgstr "Малый додекоикосакрон"
 
-#: hacks/config/polyhedra.xml.h:157
-msgid "Truncated Cuboctahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:115
+msgid "Small dodecahemidodecahedron"
+msgstr "Малый додекогемидодекаэдр"
 
-#: hacks/config/polyhedra.xml.h:158
-msgid "Truncated Dodecadodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:116
+msgid "Small dodecahemidodecacron"
+msgstr "Малый додекогемидодекакрон"
 
-#: hacks/config/polyhedra.xml.h:159
-msgid "Truncated Dodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:117
+msgid "Great stellated dodecahedron"
+msgstr "Большой звездообразный додекаэдр"
 
-#: hacks/config/polyhedra.xml.h:160
-msgid "Truncated Great Dodecahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:118
+msgid "Great icosahedron"
+msgstr "Большой икосаэдр"
 
-#: hacks/config/polyhedra.xml.h:161
-msgid "Truncated Icosahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:119
+msgid "Great icosidodecahedron"
+msgstr "Большой икосододекаэдр"
 
-#: hacks/config/polyhedra.xml.h:162
-msgid "Truncated Icosidodechedon"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:120
+msgid "Great rhombic triacontahedron"
+msgstr "Большой ромбический триаконтаэдр"
 
-#: hacks/config/polyhedra.xml.h:163
-msgid "Truncated Octahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:121
+msgid "Great truncated icosahedron"
+msgstr "Большой усеченный икосаэдр"
 
-#: hacks/config/polyhedra.xml.h:164
-msgid "Truncated Tetrahedron"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:122
+msgid "Great stellapentakisdodecahedron"
+msgstr "Большой звездчатый пентакисдодекаэдр"
 
-#: hacks/config/polyominoes.xml.h:3
-msgid "Identical Pieces"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:123
+msgid "Rhombicosahedron"
+msgstr "Ромбоикосаэдр"
 
-#: hacks/config/polyominoes.xml.h:7
-msgid "Polyominoes"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:124
+msgid "Rhombicosacron"
+msgstr "Ромбоикосакрон"
 
-#: hacks/config/polyominoes.xml.h:8
-msgid ""
-"Repeatedly attempts to completely fill a rectangle with irregularly-shaped "
-"puzzle pieces. Written by Stephen Montgomery-Smith."
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:125
+msgid "Great snub icosidodecahedron"
+msgstr "Большой плосконосый икосододекаэдр"
 
-#: hacks/config/polytopes.xml.h:2
-msgid "120-Cell"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:126
+msgid "Great pentagonal hexecontahedron"
+msgstr "Большой пентагональный гексеконтаэдр"
 
-#: hacks/config/polytopes.xml.h:3
-msgid "16-Cell (Hyper-Octahedron)"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:127
+msgid "Small stellated truncated dodecahedron"
+msgstr "Малый звездообразный усеченный додекаэдр"
 
-#: hacks/config/polytopes.xml.h:4
-msgid "24-Cell"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:128
+msgid "Great pentakisdodecahedron"
+msgstr "Большой пентакисдодекаэдр"
 
-#: hacks/config/polytopes.xml.h:6
-msgid "5-Cell (Hyper-Tetrahedron)"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:129
+msgid "Truncated dodecadodecahedron"
+msgstr "Усеченный додекододекаэдр"
 
-#: hacks/config/polytopes.xml.h:7
-msgid "600-Cell"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:130
+msgid "Medial disdyakistriacontahedron"
+msgstr "Средний дисдиакистриаконтаэдр"
 
-#: hacks/config/polytopes.xml.h:8
-msgid "8-Cell (Hypercube / Tesseract)"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:131
+msgid "Inverted snub dodecadodecahedron"
+msgstr "Вывернутый плосконосый додекододекаэдр"
 
-#: hacks/config/polytopes.xml.h:9
-msgid "Colors By 4D Depth"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:132
+msgid "Medial inverted pentagonal hexecontahedron"
+msgstr "Средний вывернутый пентагональный гексеконтаэдр"
 
-#: hacks/config/polytopes.xml.h:17
-msgid "Regular 4D Polytopes"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:133
+msgid "Great dodecicosidodecahedron"
+msgstr "Большой додекоикосододекаэдр"
 
-#: hacks/config/polytopes.xml.h:19
-#, fuzzy
-msgid "Single Color"
-msgstr "DirectColor"
+#: ../hacks/config/polyhedra.xml.h:134
+msgid "Great dodecacronic hexecontahedron"
+msgstr "Большой додекакронный гексеконтаэдр"
 
-#: hacks/config/polytopes.xml.h:22
-msgid ""
-"This program shows one of the six regular 4D polytopes rotating in 4D. "
-"Written by Carsten Steger, inspired by H.S.M Coxeter's book \"Regular "
-"Polytopes\", 3rd Edition, Dover Publications, Inc., 1973, and Thomas "
-"Banchoff's book \"Beyond the Third Dimension: Geometry, Computer Graphics, "
-"and Higher Dimensions\", Scientific American Library, 1990."
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:135
+msgid "Small dodecahemicosahedron"
+msgstr "Малый додекогемиикосаэдр"
 
-#: hacks/config/pong.xml.h:2
-#, fuzzy
-msgid "Pong"
-msgstr "Длинный"
+#: ../hacks/config/polyhedra.xml.h:136
+msgid "Small dodecahemicosacron"
+msgstr "Малый додекогемиикосакрон"
 
-#: hacks/config/pong.xml.h:6
-msgid ""
-"The pong program simulates an ancient Pong home video game, as well as "
-"various artifacts from displaying it on a color TV set. Written by Jeremy "
-"English and Trevor Blackwell."
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:137
+msgid "Great dodecicosahedron"
+msgstr "Большой додекоикосаэдр"
 
-#: hacks/config/popsquares.xml.h:2
-msgid "End color"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:138
+msgid "Great dodecicosacron"
+msgstr "Большой додекоикосакрон"
 
-#: hacks/config/popsquares.xml.h:7
-msgid "Start color"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:139
+msgid "Great snub dodecicosidodecahedron"
+msgstr "Большой плосконосый додекоикосододекаэдр"
 
-#: hacks/config/popsquares.xml.h:8
-msgid "Subdivision"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:140
+msgid "Great hexagonal hexecontahedron"
+msgstr "Большой гексагональный гексеконтаэдр"
 
-#: hacks/config/popsquares.xml.h:9
-msgid ""
-"This draws a pop-art-ish looking grid of pulsing colors. By Levi Burton."
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:141
+msgid "Great dodecahemicosahedron"
+msgstr "Большой додекогемиикосаэдр"
 
-#: hacks/config/popsquares.xml.h:10
-msgid "Twitch"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:142
+msgid "Great dodecahemicosacron"
+msgstr "Большой додекогемиикосакрон"
 
-#: hacks/config/popsquares.xml.h:11
-msgid "popsquares"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:143
+msgid "Great stellated truncated dodecahedron"
+msgstr "Большой звездообразный додекаэдр"
 
-#: hacks/config/providence.xml.h:1
-msgid "Draw Eye"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:144
+msgid "Great triakisicosahedron"
+msgstr "Большой триакисикосаэдр"
 
-#: hacks/config/providence.xml.h:3
-msgid "Providence"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:145
+msgid "Great rhombicosidodecahedron"
+msgstr "Большой ромбоикосододекаэдр"
 
-#: hacks/config/providence.xml.h:8
-msgid ""
-"The providence code displays an eye, shrouded in glory, set upon the base of "
-"a pyramid. Written by Blair Tennessy."
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:146
+msgid "Great deltoidal hexecontahedron"
+msgstr "Большой дельтоидальный гексеконтаэдр"
 
-#: hacks/config/pulsar.xml.h:1
-msgid "Anti-alias Lines"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:147
+msgid "Great truncated icosidodecahedron"
+msgstr "Большой усеченный икосододекаэдр"
 
-#: hacks/config/pulsar.xml.h:3
-msgid ""
-"Draws some intersecting planes, making use of alpha blending, fog, textures, "
-"and mipmaps, plus a ``frames per second'' meter so that you can tell how "
-"fast your graphics card is... Requires OpenGL. Written by David Konerding."
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:148
+msgid "Great disdyakistriacontahedron"
+msgstr "Большой дисдиакистриаконтаэдр"
 
-#: hacks/config/pulsar.xml.h:4
-msgid "Enable Blending"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:149
+msgid "Great inverted snub icosidodecahedron"
+msgstr "Большой вывернутый плосконосый икосододекаэдр"
 
-#: hacks/config/pulsar.xml.h:5
-msgid "Enable Depth Buffer"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:150
+msgid "Great inverted pentagonal hexecontahedron"
+msgstr "Большой вывернутый пентагональный гексеконтаэдр"
 
-#: hacks/config/pulsar.xml.h:6
-msgid "Enable Fog"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:151
+msgid "Great dodecahemidodecahedron"
+msgstr "Большой додекогемидодекаэдр"
 
-#: hacks/config/pulsar.xml.h:7
-msgid "Enable Lighting"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:152
+msgid "Great dodecahemidodecacron"
+msgstr "Большой додекогемидодекакрон"
 
-#: hacks/config/pulsar.xml.h:8
-msgid "Enable Texture Filtering"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:153
+msgid "Great icosihemidodecahedron"
+msgstr "Большой икосогемидодекаэдр"
 
-#: hacks/config/pulsar.xml.h:9
-msgid "Enable Texture Mipmaps"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:154
+msgid "Great icosihemidodecacron"
+msgstr "Большой икосогемидодекакрон"
 
-#: hacks/config/pulsar.xml.h:10
-msgid "Enable Texturing"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:155
+msgid "Small retrosnub icosicosidodecahedron"
+msgstr "Малый обратноплосконосый икосоикосододекаэдр"
 
-#: hacks/config/pulsar.xml.h:12
-msgid "Pulsar"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:156
+msgid "Small hexagrammic hexecontahedron"
+msgstr "Малый гексаграммический гексеконтаэдр"
 
-#: hacks/config/pulsar.xml.h:13
-msgid "Quad Count"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:157
+msgid "Great rhombidodecahedron"
+msgstr "Большой ромбододекаэдр"
 
-#: hacks/config/pulsar.xml.h:18
-msgid "Texture PPM File"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:158
+msgid "Great rhombidodecacron"
+msgstr "Большой ромбододекакрон"
 
-#: hacks/config/pyro.xml.h:3
-msgid "Explosive Yield"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:159
+msgid "Great retrosnub icosidodecahedron"
+msgstr "Большой обратноплосконосый икосододекаэдр"
 
-#: hacks/config/pyro.xml.h:6
-msgid "Launch Frequency"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:160
+msgid "Great pentagrammic hexecontahedron"
+msgstr "Большой пентаграммический гексеконтаэдр"
 
-#: hacks/config/pyro.xml.h:9
-msgid "Particle Density"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:161
+msgid "Great dirhombicosidodecahedron"
+msgstr "Большой биромбоикосододекаэдр"
 
-#: hacks/config/pyro.xml.h:10
-msgid "Pyro"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:162
+msgid "Great dirhombicosidodecacron"
+msgstr "Большой биромбоикосододекакрон"
 
-#: hacks/config/pyro.xml.h:11
-msgid ""
-"Pyro draws exploding fireworks. Blah blah blah. Written by Jamie Zawinski."
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:163
+msgid "Utah teapotahedron"
+msgstr "Чайникаэдр Юты"
 
-#: hacks/config/qix.xml.h:1
-msgid "Additive Colors"
-msgstr ""
+#: ../hacks/config/polyhedra.xml.h:167
+msgid "Show description"
+msgstr "Показать описание"
 
-#: hacks/config/qix.xml.h:3
-msgid "Corners"
+#: ../hacks/config/polyhedra.xml.h:169
+msgid ""
+"The 75 uniform polyhedra and their duals, plus 5 prisms and antiprisms, and "
+"some information about each. https://en.wikipedia.org/wiki/Uniform_polyhedra "
+"https://en.wikipedia.org/wiki/Stellation https://en.wikipedia.org/wiki/"
+"Dual_polyhedron https://en.wikipedia.org/wiki/Antiprism Written by Dr. Zvi "
+"Har'El and Jamie Zawinski; 2004."
 msgstr ""
 
-#: hacks/config/qix.xml.h:11
-msgid "Line Segments"
+#: ../hacks/config/polyominoes.xml.h:1
+msgid "Polyominoes"
 msgstr ""
 
-#: hacks/config/qix.xml.h:12
-msgid "Linear Motion"
-msgstr ""
+#: ../hacks/config/polyominoes.xml.h:2
+msgid "Identical pieces"
+msgstr "Одинаковые части"
 
-#: hacks/config/qix.xml.h:15
-msgid "Max Size"
+#: ../hacks/config/polyominoes.xml.h:13
+msgid ""
+"Repeatedly attempts to completely fill a rectangle with irregularly-shaped "
+"puzzle pieces. https://en.wikipedia.org/wiki/Polyomino Written by Stephen "
+"Montgomery-Smith; 2002."
 msgstr ""
 
-#: hacks/config/qix.xml.h:16
-msgid "Qix"
+#: ../hacks/config/polytopes.xml.h:1
+msgid "Polytopes"
 msgstr ""
 
-#: hacks/config/qix.xml.h:17
-msgid "Random Motion"
-msgstr ""
+#: ../hacks/config/polytopes.xml.h:6
+msgid "5-cell (hyper-tetrahedron)"
+msgstr "5 ячеек (гипертетраэдр)"
 
-#: hacks/config/qix.xml.h:23
-msgid "Subtractive Colors"
-msgstr ""
+#: ../hacks/config/polytopes.xml.h:7
+msgid "8-cell (hypercube / tesseract)"
+msgstr "8 ячеек (гиперкуб/тессеракт)"
 
-#: hacks/config/qix.xml.h:24
-msgid ""
-"This is the swiss army chainsaw of qix programs. It bounces a series of line "
-"segments around the screen, and uses variations on this basic motion pattern "
-"to produce all sorts of different presentations: line segments, filled "
-"polygons, overlapping translucent areas... Written by Jamie Zawinski."
-msgstr ""
+#: ../hacks/config/polytopes.xml.h:8
+msgid "16-cell (hyper-octahedron)"
+msgstr "16 ячеек (гипероктаэдр)"
 
-#: hacks/config/qix.xml.h:25
-msgid "Transparent"
-msgstr ""
+#: ../hacks/config/polytopes.xml.h:9
+msgid "24-cell"
+msgstr "24 ячейки"
 
-#: hacks/config/queens.xml.h:2
-msgid "Queens"
-msgstr ""
+#: ../hacks/config/polytopes.xml.h:10
+msgid "120-cell"
+msgstr "120 ячеек"
 
-#: hacks/config/queens.xml.h:5
-msgid ""
-"Solves the N-Queens problem (where, in this program, N is between 5 and 10 "
-"queens.) The problem is: how may one place N queens on an NxN chessboard "
-"such that no queen can attack a sister? Written by Blair Tennessy."
-msgstr ""
+#: ../hacks/config/polytopes.xml.h:11
+msgid "600-cell"
+msgstr "600 ячеек"
 
-#: hacks/config/rd-bomb.xml.h:1
-msgid "/"
-msgstr "/"
+#: ../hacks/config/polytopes.xml.h:12
+msgid "Single color"
+msgstr "Один цвет"
 
-#: hacks/config/rd-bomb.xml.h:3
-#, no-c-format
-msgid "1%"
-msgstr "1%"
+#: ../hacks/config/polytopes.xml.h:13
+msgid "Colors By 4D Depth"
+msgstr "Цвета с глубиной 4D"
 
-#: hacks/config/rd-bomb.xml.h:7
+#: ../hacks/config/polytopes.xml.h:30
 msgid ""
-"Another variation of the `Bomb' program by Scott Draves. This draws a grid "
-"of growing square-like shapes that, once they overtake each other, react in "
-"unpredictable ways. ``RD'' stands for reaction-diffusion."
-msgstr ""
-
-#: hacks/config/rd-bomb.xml.h:8
-msgid "Epoch"
+"The six regular 4D polytopes rotating in 4D. Inspired by H.S.M Coxeter's "
+"book \"Regular Polytopes\", 3rd Edition, Dover Publications, Inc., 1973, and "
+"Thomas Banchoff's book \"Beyond the Third Dimension: Geometry, Computer "
+"Graphics, and Higher Dimensions\", Scientific American Library, 1990. "
+"https://en.wikipedia.org/wiki/Hypercube https://en.wikipedia.org/wiki/"
+"Tesseract https://en.wikipedia.org/wiki/Regular_polytope Written by Carsten "
+"Steger; 2003."
 msgstr ""
 
-#: hacks/config/rd-bomb.xml.h:10
-msgid "Fill Screen"
+#: ../hacks/config/pong.xml.h:1
+msgid "Pong"
 msgstr ""
 
-#: hacks/config/rd-bomb.xml.h:14
-msgid "RD-Bomb"
-msgstr ""
+#: ../hacks/config/pong.xml.h:3
+msgid "Game speed"
+msgstr "Скорость игры"
 
-#: hacks/config/rd-bomb.xml.h:15
-msgid "Reaction/Difusion"
-msgstr "РеакÑ\86иÑ\8f/диÑ\84Ñ\84Ñ\83зиÑ\8f"
+#: ../hacks/config/pong.xml.h:5
+msgid "Crisp"
+msgstr "ТÑ\80еÑ\81к"
 
-#: hacks/config/rd-bomb.xml.h:16
-msgid "Seed Radius"
-msgstr "РадиÑ\83Ñ\81 Ð·ÐµÑ\80ен"
+#: ../hacks/config/pong.xml.h:6
+msgid "Noise"
+msgstr "ШÑ\83м"
 
-#: hacks/config/rd-bomb.xml.h:19 hacks/config/twang.xml.h:12
-msgid "Tile Size"
-msgstr "РазмеÑ\80 Ð¿Ð»Ð¸Ñ\82ки"
+#: ../hacks/config/pong.xml.h:7
+msgid "Noisy"
+msgstr "ШÑ\83мно"
 
-#: hacks/config/rd-bomb.xml.h:22
-msgid "Wander Speed"
-msgstr "СкоÑ\80оÑ\81Ñ\82Ñ\8c Ð±Ð»Ñ\83жданиÑ\8f"
+#: ../hacks/config/pong.xml.h:8
+msgid "Clock mode"
+msgstr "Режим Ð¾Ñ\82обÑ\80ажениÑ\8f Ð²Ñ\80емени"
 
-#: hacks/config/ripples.xml.h:1
-msgid "Big Drops"
+#: ../hacks/config/pong.xml.h:14
+msgid ""
+"The 1971 Pong home video game, including artifacts of an old color TV set. "
+"In clock mode, the score keeps track of the current time. https://en."
+"wikipedia.org/wiki/Pong Written by Jeremy English, Trevor Blackwell and "
+"Jamie Zawinski; 2003."
 msgstr ""
 
-#: hacks/config/ripples.xml.h:2
-msgid "Colors    Two"
+#: ../hacks/config/popsquares.xml.h:1
+msgid "PopSquares"
 msgstr ""
 
-#: hacks/config/ripples.xml.h:3
-msgid "Drizzle"
-msgstr ""
+#: ../hacks/config/popsquares.xml.h:5
+msgid "Subdivision"
+msgstr "Разделение"
 
-#: hacks/config/ripples.xml.h:5
-msgid "Grab Screen Image"
-msgstr ""
+#: ../hacks/config/popsquares.xml.h:8
+msgid "Light red"
+msgstr "Светло-красный"
 
-#: hacks/config/ripples.xml.h:6
-#, fuzzy
-msgid "Grayscale"
-msgstr "GrayScale"
+#: ../hacks/config/popsquares.xml.h:9
+msgid "Light yellow"
+msgstr "Светло-желтый"
+
+#: ../hacks/config/popsquares.xml.h:10
+msgid "Light green"
+msgstr "Светло-зеленый"
+
+#: ../hacks/config/popsquares.xml.h:11
+msgid "Light cyan"
+msgstr "Светло-голубой"
 
-#: hacks/config/ripples.xml.h:7
-msgid "Lighting Effect"
-msgstr ""
+#: ../hacks/config/popsquares.xml.h:12
+msgid "Light blue"
+msgstr "Светло-синий"
 
-#: hacks/config/ripples.xml.h:9
-msgid "Moving Splashes"
-msgstr ""
+#: ../hacks/config/popsquares.xml.h:13
+msgid "Light magenta"
+msgstr "Светло-пурпурный"
 
-#: hacks/config/ripples.xml.h:10
-msgid "Psychedelic Colors"
-msgstr ""
+#: ../hacks/config/popsquares.xml.h:14
+msgid "Dark red"
+msgstr "Темно-красный"
 
-#: hacks/config/ripples.xml.h:11
-msgid "Ripples"
-msgstr ""
+#: ../hacks/config/popsquares.xml.h:15
+msgid "Dark yellow"
+msgstr "Темно-желтый"
 
-#: hacks/config/ripples.xml.h:13
-msgid "Small Drops"
-msgstr ""
+#: ../hacks/config/popsquares.xml.h:16
+msgid "Dark green"
+msgstr "Темно-зеленый"
 
-#: hacks/config/ripples.xml.h:14
-msgid "Storm"
-msgstr ""
+#: ../hacks/config/popsquares.xml.h:17
+msgid "Dark cyan"
+msgstr "Темно-голубой"
 
-#: hacks/config/ripples.xml.h:15
-msgid ""
-"This draws rippling interference patterns like splashing water. With the -"
-"water option, it manipulates your desktop image to look like something is "
-"dripping into it. Written by Tom Hammersley."
-msgstr ""
+#: ../hacks/config/popsquares.xml.h:18
+msgid "Dark blue"
+msgstr "Темно-синий"
 
-#: hacks/config/rocks.xml.h:7
-msgid "Rocks"
-msgstr ""
+#: ../hacks/config/popsquares.xml.h:19
+msgid "Dark magenta"
+msgstr "Темно-пурпурный"
 
-#: hacks/config/rocks.xml.h:10
-msgid "Steering"
-msgstr ""
+#: ../hacks/config/popsquares.xml.h:20
+msgid "Twitch"
+msgstr "Рывок"
 
-#: hacks/config/rocks.xml.h:11
+#: ../hacks/config/popsquares.xml.h:22
 msgid ""
-"This draws an animation of flight through an asteroid field, with changes in "
-"rotation and direction. It can also display 3D separations for red/blue "
-"glasses! Mostly written by Jamie Zawinski."
+"A pop-art-ish looking grid of pulsing colors. Written by Levi Burton; 2003."
 msgstr ""
 
-#: hacks/config/rocks.xml.h:13
-msgid "Velocity"
+#: ../hacks/config/projectiveplane.xml.h:1
+msgid "ProjectivePlane"
 msgstr ""
 
-#: hacks/config/rorschach.xml.h:7
-msgid "Rorschach"
-msgstr ""
+#: ../hacks/config/projectiveplane.xml.h:8 ../hacks/config/romanboy.xml.h:20
+msgid "Distance bands"
+msgstr "Полосы дистанции"
 
-#: hacks/config/rorschach.xml.h:9
-msgid ""
-"This generates random inkblot patterns. The algorithm is deceptively simple "
-"for how well it works; it merely walks a dot around the screen randomly, and "
-"then reflects the image horizontally, vertically, or both. Any deep-seated "
-"neurotic tendencies which this program reveals are your own problem. Written "
-"by Jamie Zawinski."
-msgstr ""
+#: ../hacks/config/projectiveplane.xml.h:9 ../hacks/config/romanboy.xml.h:21
+msgid "Direction bands"
+msgstr "Полосы направления"
 
-#: hacks/config/rorschach.xml.h:10
-msgid "With X Symmetry"
-msgstr ""
+#: ../hacks/config/projectiveplane.xml.h:12 ../hacks/config/romanboy.xml.h:24
+msgid "Distance colors"
+msgstr "Цвета дистанции"
 
-#: hacks/config/rorschach.xml.h:11
-msgid "With Y Symmetry"
-msgstr ""
+#: ../hacks/config/projectiveplane.xml.h:13 ../hacks/config/romanboy.xml.h:25
+msgid "Direction colors"
+msgstr "Цвета направления"
 
-#: hacks/config/rotor.xml.h:1
-msgid ""
-"Another ancient xlock demo, this one by Tom Lawrence. It draws a line "
-"segment moving along a complex spiraling curve."
+#: ../hacks/config/projectiveplane.xml.h:21
+msgid "-4"
 msgstr ""
 
-#: hacks/config/rotor.xml.h:4 hacks/config/wander.xml.h:9
-msgid "Length"
-msgstr ""
+#: ../hacks/config/projectiveplane.xml.h:22
+msgid "WX speed"
+msgstr "Скорость WX"
 
-#: hacks/config/rotor.xml.h:8
-msgid "Rotor"
+#: ../hacks/config/projectiveplane.xml.h:23
+msgid "4"
 msgstr ""
 
-#: hacks/config/rotzoomer.xml.h:2
-#, fuzzy
-msgid "60"
-msgstr "100%"
+#: ../hacks/config/projectiveplane.xml.h:24
+msgid "WY speed"
+msgstr "Скорость WY"
 
-#: hacks/config/rotzoomer.xml.h:3
-msgid "Animate"
-msgstr ""
+#: ../hacks/config/projectiveplane.xml.h:25
+msgid "WZ speed"
+msgstr "Скорость WZ"
 
-#: hacks/config/rotzoomer.xml.h:4
-msgid ""
-"Creates a collage of rotated and scaled portions of the screen. Written by "
-"Claudio Matsuoka."
-msgstr ""
+#: ../hacks/config/projectiveplane.xml.h:26
+msgid "XY speed"
+msgstr "Скорость XY"
 
-#: hacks/config/rotzoomer.xml.h:6
-msgid "Rectangle Count"
-msgstr ""
+#: ../hacks/config/projectiveplane.xml.h:27
+msgid "XZ speed"
+msgstr "Скорость XZ"
 
-#: hacks/config/rotzoomer.xml.h:7
-msgid "RotZoomer"
-msgstr ""
+#: ../hacks/config/projectiveplane.xml.h:28
+msgid "YZ speed"
+msgstr "Скорость YZ"
 
-#: hacks/config/rotzoomer.xml.h:8
-msgid "Stationary Rectangles"
+#: ../hacks/config/projectiveplane.xml.h:29
+msgid "-180"
 msgstr ""
 
-#: hacks/config/rotzoomer.xml.h:9
-msgid "Sweeping Arcs"
-msgstr ""
+#: ../hacks/config/projectiveplane.xml.h:30
+msgid "Walk dir     "
+msgstr "Направление движения"
 
-#: hacks/config/rotzoomer.xml.h:11
-msgid "Wandering Rectangles"
+#: ../hacks/config/projectiveplane.xml.h:31
+msgid "180"
 msgstr ""
 
-#: hacks/config/rubik.xml.h:2
+#: ../hacks/config/projectiveplane.xml.h:33
+msgid "Walk speed"
+msgstr "Скорость движения"
+
+#: ../hacks/config/projectiveplane.xml.h:44
 msgid ""
-"Draws a Rubik's Cube that rotates in three dimensions and repeatedly "
-"shuffles and solves itself. Another fine GL hack by Marcelo Vianna."
+"A 4D embedding of the real projective plane. You can walk on the surface of "
+"the real projective plane or rotate it in 4D or walk on it while it rotates "
+"in 4D. Inspired by Thomas Banchoff's book \"Beyond the Third Dimension: "
+"Geometry, Computer Graphics, and Higher Dimensions\", Scientific American "
+"Library, 1990. https://en.wikipedia.org/wiki/Real_projective_plane https://"
+"en.wikipedia.org/wiki/Roman_surface https://en.wikipedia.org/wiki/Cross_cap "
+"https://en.wikipedia.org/wiki/Moebius_strip http://mathworld.wolfram.com/"
+"RealProjectivePlane.html http://mathworld.wolfram.com/RomanSurface.html "
+"http://mathworld.wolfram.com/Cross-Cap.html http://mathworld.wolfram.com/"
+"MoebiusStrip.html Written by Carsten Steger; 2014."
 msgstr ""
 
-#: hacks/config/rubik.xml.h:5
-msgid "Rubik"
+#: ../hacks/config/providence.xml.h:1
+msgid "Providence"
 msgstr ""
 
-#: hacks/config/rubik.xml.h:7
-msgid "Show Shuffling"
-msgstr ""
+#: ../hacks/config/providence.xml.h:5
+msgid "Draw eye"
+msgstr "Прорисовывать глаз"
 
-#: hacks/config/sballs.xml.h:3
+#: ../hacks/config/providence.xml.h:8
 msgid ""
-"Draws an animation of textured balls spinning like crazy in GL. Requires "
-"OpenGL, and a machine with fast hardware support for texture maps. Written "
-"by Eric Lassauge &lt;lassauge@users.sourceforge.net&gt;."
+"\"A pyramid unfinished. In the zenith an eye in a triangle, surrounded by a "
+"glory, proper.\" https://en.wikipedia.org/wiki/Eye_of_Providence Written by "
+"Blair Tennessy; 2004."
 msgstr ""
 
-#: hacks/config/sballs.xml.h:8
-msgid "Plane"
+#: ../hacks/config/pulsar.xml.h:1
+msgid "Pulsar"
 msgstr ""
 
-#: hacks/config/sballs.xml.h:9
-msgid "Pyramid"
-msgstr ""
+#: ../hacks/config/pulsar.xml.h:5
+msgid "Quad count"
+msgstr "Количество четырехугольников"
 
-#: hacks/config/sballs.xml.h:11
-msgid "Sballs"
-msgstr ""
+#: ../hacks/config/pulsar.xml.h:8
+msgid "Enable texturing"
+msgstr "Включить текстурирование"
 
-#: hacks/config/sballs.xml.h:15
-msgid "Star"
-msgstr ""
+#: ../hacks/config/pulsar.xml.h:9
+msgid "Enable texture mipmaps"
+msgstr "Включить множественное отображение текстур"
 
-#: hacks/config/shadebobs.xml.h:7
-msgid "ShadeBobs"
-msgstr ""
+#: ../hacks/config/pulsar.xml.h:10
+msgid "Enable blending"
+msgstr "Включить перемешивание"
 
-#: hacks/config/shadebobs.xml.h:11
-msgid ""
-"This draws smoothly-shaded oscillating oval patterns, that look something "
-"like vapor trails or neon tubes. Written by Shane Smit."
-msgstr ""
+#: ../hacks/config/pulsar.xml.h:11
+msgid "Anti-alias lines"
+msgstr "Линии сглаживания"
 
-#: hacks/config/sierpinski.xml.h:6
-msgid "Sierpinski"
-msgstr ""
+#: ../hacks/config/pulsar.xml.h:12
+msgid "Enable texture filtering"
+msgstr "Включить фильтрацию текстур"
+
+#: ../hacks/config/pulsar.xml.h:13
+msgid "Enable depth buffer"
+msgstr "Включить буфер глубины"
 
-#: hacks/config/sierpinski.xml.h:10
+#: ../hacks/config/pulsar.xml.h:15
 msgid ""
-"This draws the two-dimensional variant of the recursive Sierpinski triangle "
-"fractal. Written by Desmond Daignault."
+"Intersecting planes, with alpha blending, fog, textures, and mipmaps. "
+"Written by David Konerding; 1999."
 msgstr ""
 
-#: hacks/config/sierpinski3d.xml.h:7
-msgid "Sierpinski3D"
+#: ../hacks/config/pyro.xml.h:1
+msgid "Pyro"
 msgstr ""
 
-#: hacks/config/sierpinski3d.xml.h:11
+#: ../hacks/config/pyro.xml.h:6
+msgid "Particle density"
+msgstr "Плотность частиц"
+
+#: ../hacks/config/pyro.xml.h:9
+msgid "Launch frequency"
+msgstr "Частота запусков"
+
+#: ../hacks/config/pyro.xml.h:12
+msgid "Explosive yield"
+msgstr "Сила взрыва"
+
+#: ../hacks/config/pyro.xml.h:15
 msgid ""
-"This draws the three-dimensional variant of the recursive Sierpinski "
-"triangle fractal, using GL. Written by Tim Robinson and Jamie Zawinski."
+"Exploding fireworks. See also the \"Fireworkx\", \"Eruption\", and \"XFlame"
+"\" screen savers. Written by Jamie Zawinski; 1992."
 msgstr ""
 
-#: hacks/config/slidescreen.xml.h:1 hacks/config/twang.xml.h:1
-#: hacks/config/zoom.xml.h:1
-msgid "Border Width"
+#: ../hacks/config/qix.xml.h:1
+msgid "Qix"
 msgstr ""
 
-#: hacks/config/slidescreen.xml.h:4
-msgid "Slide Speed"
-msgstr ""
+#: ../hacks/config/qix.xml.h:12
+msgid "Line segments"
+msgstr "Сегменты линий"
 
-#: hacks/config/slidescreen.xml.h:5
-msgid "SlideScreen"
-msgstr ""
+#: ../hacks/config/qix.xml.h:13
+msgid "Solid objects"
+msgstr "Сплошные объекты"
 
-#: hacks/config/slidescreen.xml.h:8
-msgid ""
-"This takes an image, divides it into a grid, and then randomly shuffles the "
-"squares around as if it was one of those annoying ``16-puzzle'' games, where "
-"there is a grid of squares, one of which is missing. I hate trying to solve "
-"those puzzles, but watching one permute itself is more amusing. Written by "
-"Jamie Zawinski."
-msgstr ""
+#: ../hacks/config/qix.xml.h:14
+msgid "Linear motion"
+msgstr "Линейное движение"
 
-#: hacks/config/slip.xml.h:6
-msgid "Slip"
-msgstr ""
+#: ../hacks/config/qix.xml.h:16
+msgid "Additive colors"
+msgstr "Добавление цветов"
 
-#: hacks/config/slip.xml.h:10
-msgid ""
-"This program throws some random bits on the screen, then sucks them through "
-"a jet engine and spews them out the other side. To avoid turning the image "
-"completely to mush, every now and then it will and then it interjects some "
-"splashes of color into the scene, or go into a spin cycle, or stretch the "
-"image like taffy, or (this is my addition) grab an image of your current "
-"desktop to chew on. Originally written by Scott Draves; whacked on by Jamie "
-"Zawinski."
-msgstr ""
+#: ../hacks/config/qix.xml.h:17
+msgid "Subtractive colors"
+msgstr "Вычитание цветов"
 
-#: hacks/config/sonar.xml.h:1
-msgid "Ping known hosts"
-msgstr ""
+#: ../hacks/config/qix.xml.h:19
+msgid "Max size"
+msgstr "Максимальный размер"
 
-#: hacks/config/sonar.xml.h:2
-msgid "Ping mode..."
-msgstr ""
+#: ../hacks/config/qix.xml.h:20
+msgid "Poly corners"
+msgstr "Полигоны"
 
-#: hacks/config/sonar.xml.h:3
-msgid "Ping subnet/24 (254 hosts)"
+#: ../hacks/config/qix.xml.h:25
+msgid ""
+"Bounces a series of line segments around the screen, and uses variations on "
+"this basic motion pattern to produce all sorts of different presentations: "
+"line segments, filled polygons, and overlapping translucent areas. https://"
+"en.wikipedia.org/wiki/Qix Written by Jamie Zawinski; 1992."
 msgstr ""
 
-#: hacks/config/sonar.xml.h:4
-msgid "Ping subnet/25 (126 hosts)"
+#: ../hacks/config/quasicrystal.xml.h:1
+msgid "QuasiCrystal"
 msgstr ""
 
-#: hacks/config/sonar.xml.h:5
-msgid "Ping subnet/26 (62 hosts)"
-msgstr ""
+#: ../hacks/config/quasicrystal.xml.h:9
+msgid "Contrast"
+msgstr "Контраст"
 
-#: hacks/config/sonar.xml.h:6
-msgid "Ping subnet/27 (31 hosts)"
+#: ../hacks/config/quasicrystal.xml.h:14
+msgid ""
+"A quasicrystal is a structure that is ordered but aperiodic. Two-dimensional "
+"quasicrystals can be generated by adding a set of planes where x is the sine "
+"of y. Different complex aperiodic plane tilings are produced depending on "
+"the period, position, and rotation of the component planes, and whether the "
+"rotation of the planes is evenly distributed around the circle (the "
+"\"symmetry\" option, above) or random. See also the \"RD-Bomb\", \"CWaves\" "
+"and \"Penrose\" screen savers. https://en.wikipedia.org/wiki/Quasicrystal "
+"Written by Jamie Zawinski; 2013."
 msgstr ""
 
-#: hacks/config/sonar.xml.h:7
-msgid "Ping subnet/28 (14 hosts)"
+#: ../hacks/config/queens.xml.h:1
+msgid "Queens"
 msgstr ""
 
-#: hacks/config/sonar.xml.h:8
-msgid "Ping subnet/29 (6 hosts)"
+#: ../hacks/config/queens.xml.h:7
+msgid ""
+"The N-Queens problem: how to place N queens on an NxN chessboard such that "
+"no queen can attack a sister? See also the \"Endgame\" screen saver. https://"
+"en.wikipedia.org/wiki/Eight_queens_puzzle Written by Blair Tennessy and "
+"Jamie Zawinski; 2002."
 msgstr ""
 
-#: hacks/config/sonar.xml.h:9
-msgid "Ping subnet/30 (2 hosts)"
+#: ../hacks/config/raverhoop.xml.h:1
+msgid "RaverHoop"
 msgstr ""
 
-#: hacks/config/sonar.xml.h:10
-msgid "Resolve Host Names"
-msgstr ""
+#: ../hacks/config/raverhoop.xml.h:9
+msgid "Lights"
+msgstr "Источники света"
 
-#: hacks/config/sonar.xml.h:11
-#, fuzzy
-msgid "Show Ping Times"
-msgstr "Сплошной"
+#: ../hacks/config/raverhoop.xml.h:12
+msgid "Speed, motion"
+msgstr "Скорость, движение"
 
-#: hacks/config/sonar.xml.h:12
-msgid "Simulation Team Members"
-msgstr ""
+#: ../hacks/config/raverhoop.xml.h:14
+msgid "Speed, lights"
+msgstr "Скорость, свет"
 
-#: hacks/config/sonar.xml.h:13
-msgid "Sonar"
-msgstr ""
+#: ../hacks/config/raverhoop.xml.h:16
+msgid "Sustain"
+msgstr "Выдержка"
 
-#: hacks/config/sonar.xml.h:14
-msgid "Team A Name"
+#: ../hacks/config/raverhoop.xml.h:21
+msgid ""
+"Simulates an LED hula hoop in a dark room. Oontz oontz oontz. Written by "
+"Jamie Zawinski; 2016."
 msgstr ""
 
-#: hacks/config/sonar.xml.h:15
-msgid "Team B Name"
+#: ../hacks/config/rd-bomb.xml.h:1 ../hacks/config/rdbomb.xml.h:1
+msgid "RDbomb"
 msgstr ""
 
-#: hacks/config/sonar.xml.h:16
-msgid ""
-"This program draws a simulation of a sonar screen. By default, it displays a "
-"random assortment of ``bogies'' on the screen, but if installed as \"setuid "
-"root\", it can ping (pun intended) your local network, and actually plot the "
-"proximity of the other hosts on your network to you. Written by Stephen "
-"Martin and Jamie Zawinski."
-msgstr ""
+#: ../hacks/config/rd-bomb.xml.h:5 ../hacks/config/rdbomb.xml.h:5
+#: ../hacks/config/voronoi.xml.h:12
+msgid "Wander speed"
+msgstr "Скорость блуждания"
 
-#: hacks/config/sonar.xml.h:17
-msgid "vs."
+#: ../hacks/config/rd-bomb.xml.h:7 ../hacks/config/rdbomb.xml.h:7
+#, no-c-format
+msgid "1%"
 msgstr ""
 
-#: hacks/config/speedmine.xml.h:1
-msgid "Allow Wall Collisions"
-msgstr ""
+#: ../hacks/config/rd-bomb.xml.h:8 ../hacks/config/rdbomb.xml.h:8
+#: ../hacks/config/tessellimage.xml.h:14
+msgid "Fill screen"
+msgstr "Заполнить экран"
 
-#: hacks/config/speedmine.xml.h:2
-msgid "Display Crosshair"
-msgstr ""
+#: ../hacks/config/rd-bomb.xml.h:12 ../hacks/config/rdbomb.xml.h:12
+msgid "Epoch"
+msgstr "Эпоха"
 
-#: hacks/config/speedmine.xml.h:7
-msgid "Max Velocity"
-msgstr ""
+#: ../hacks/config/rd-bomb.xml.h:18 ../hacks/config/rdbomb.xml.h:18
+msgid "X tile size"
+msgstr "Размер плитки X"
 
-#: hacks/config/speedmine.xml.h:8
-msgid "Mine Shaft"
-msgstr ""
+#: ../hacks/config/rd-bomb.xml.h:19 ../hacks/config/rdbomb.xml.h:19
+msgid "Y tile size"
+msgstr "Размер плитки Y"
 
-#: hacks/config/speedmine.xml.h:9
-msgid "Present Bonuses"
-msgstr ""
+#: ../hacks/config/rd-bomb.xml.h:20 ../hacks/config/rdbomb.xml.h:20
+msgid "Reaction"
+msgstr "Реакция"
 
-#: hacks/config/speedmine.xml.h:10
-msgid "Rocky Walls"
-msgstr ""
+#: ../hacks/config/rd-bomb.xml.h:21 ../hacks/config/rdbomb.xml.h:21
+msgid "Diffusion"
+msgstr "Диффузия"
+
+#. #### default is wrong
+#: ../hacks/config/rd-bomb.xml.h:23 ../hacks/config/rdbomb.xml.h:23
+msgid "Seed radius"
+msgstr "Радиус зерен"
 
-#: hacks/config/speedmine.xml.h:12
+#: ../hacks/config/rd-bomb.xml.h:24 ../hacks/config/rdbomb.xml.h:24
 msgid ""
-"Simulates speeding down a rocky mineshaft, or a funky dancing worm. Written "
-"by Conrad Parker."
+"Reaction-diffusion: draws a grid of growing square-like shapes that, once "
+"they overtake each other, react in unpredictable ways. Written by Scott "
+"Draves; 1997."
 msgstr ""
 
-#: hacks/config/speedmine.xml.h:16
-msgid "SpeedMine"
+#: ../hacks/config/ripples.xml.h:1
+msgid "Ripples"
 msgstr ""
 
-#: hacks/config/speedmine.xml.h:17
-msgid "Thrust"
-msgstr ""
+#: ../hacks/config/ripples.xml.h:8
+msgid "Drizzle"
+msgstr "Мелкий дождь"
 
-#: hacks/config/speedmine.xml.h:19 hacks/config/worm.xml.h:10
-msgid "Worm"
-msgstr ""
+#: ../hacks/config/ripples.xml.h:9
+msgid "Drippiness"
+msgstr "Темп"
 
-#: hacks/config/sphere.xml.h:1
-msgid ""
-"Another of the classic screenhacks of the distant past, this one draws "
-"shaded spheres in multiple colors. This hack traces its lineage back to Tom "
-"Duff in 1982."
-msgstr ""
+#: ../hacks/config/ripples.xml.h:10
+msgid "Storm"
+msgstr "Буря"
 
-#: hacks/config/sphereeversion.xml.h:1
-msgid "SphereEversion"
-msgstr ""
+#: ../hacks/config/ripples.xml.h:11
+msgid "Small drops"
+msgstr "Маленькие капли"
 
-#: hacks/config/sphereeversion.xml.h:2
-msgid ""
-"SphereEversion draws an animation of a sphere being turned inside out. A "
-"sphere can be turned inside out, without any tears, sharp creases or "
-"discontinuities, if the surface of the sphere is allowed to intersect "
-"itself. This program animates what is known as the Thurston Eversion. "
-"Written by Nathaniel Thurston and Michael McGuffin. This program is not "
-"included with the XScreenSaver package, but if you don't have it already, "
-"you can find it at &lt;http://www.dgp.utoronto.ca/~mjmcguff/eversion/&gt;."
-msgstr ""
+#: ../hacks/config/ripples.xml.h:12
+msgid "Fluidity"
+msgstr "Степень текучести"
 
-#: hacks/config/spheremonics.xml.h:20
-msgid "Smoothed Lines"
-msgstr ""
+#: ../hacks/config/ripples.xml.h:13
+msgid "Big drops"
+msgstr "Большие капли"
 
-#: hacks/config/spheremonics.xml.h:23
-msgid "Spheremonics"
-msgstr ""
+#: ../hacks/config/ripples.xml.h:14
+msgid "Moving splashes"
+msgstr "Двигающиеся всплески"
 
-#: hacks/config/spheremonics.xml.h:24
-msgid ""
-"These closed objects are commonly called spherical harmonics, although they "
-"are only remotely related to the mathematical definition found in the "
-"solution to certain wave functions, most notable the eigenfunctions of "
-"angular momentum operators. Written by Paul Bourke and Jamie Zawinski."
-msgstr ""
+#: ../hacks/config/ripples.xml.h:15
+msgid "Psychedelic colors"
+msgstr "Психоделические цвета"
 
-#: hacks/config/spiral.xml.h:2 hacks/config/superquadrics.xml.h:2
-msgid "Cycles"
-msgstr ""
+#: ../hacks/config/ripples.xml.h:16
+msgid "Grayscale"
+msgstr "Оттенки серого"
+
+#: ../hacks/config/ripples.xml.h:17
+msgid "Magic lighting effect"
+msgstr "Эффект волшебного освещения"
 
-#: hacks/config/spiral.xml.h:7
+#: ../hacks/config/ripples.xml.h:19
 msgid ""
-"Moving circular patterns, by Peter Schmitzberger. Moving circular patterns "
-"means moire; interference patterns, of course."
+"Rippling interference patterns reminiscent of splashing water distort a "
+"loaded image. Written by Tom Hammersley; 1999."
 msgstr ""
 
-#: hacks/config/spiral.xml.h:11
-msgid "Spiral"
+#: ../hacks/config/rocks.xml.h:1
+msgid "Rocks"
 msgstr ""
 
-#: hacks/config/spotlight.xml.h:1
-msgid ""
-"Draws a spotlight scanning across a black screen, illuminating the "
-"underlying desktop when it passes. Written by Rick Schultz."
-msgstr ""
+#: ../hacks/config/rocks.xml.h:9
+msgid "Velocity"
+msgstr "Скорость"
 
-#: hacks/config/spotlight.xml.h:6
-msgid "Spotlight"
-msgstr ""
+#: ../hacks/config/rocks.xml.h:12
+msgid "Steering"
+msgstr "Управление"
 
-#: hacks/config/sproingies.xml.h:3
-msgid "Q-Bert meets Marble Madness! Written by Ed Mackey."
+#: ../hacks/config/rocks.xml.h:18
+msgid "An asteroid field zooms by. Written by Jamie Zawinski; 1992."
 msgstr ""
 
-#: hacks/config/sproingies.xml.h:9
-msgid "Sproingies"
+#: ../hacks/config/romanboy.xml.h:1
+msgid "RomanBoy"
 msgstr ""
 
-#: hacks/config/squiral.xml.h:3
-msgid ""
-"Draws a set of interacting, square-spiral-producing automata. The spirals "
-"grow outward until they hit something, then they go around it. Written by "
-"Jeff Epler."
-msgstr ""
+#: ../hacks/config/romanboy.xml.h:5
+msgid "Order of the surface"
+msgstr "Порядок поверхности"
 
-#: hacks/config/squiral.xml.h:5
-msgid "Handedness"
-msgstr ""
+#: ../hacks/config/romanboy.xml.h:7
+msgid "Deform the projective plane"
+msgstr "Искажать проективную плоскость"
 
-#: hacks/config/squiral.xml.h:7
-msgid "Left"
-msgstr ""
+#: ../hacks/config/romanboy.xml.h:9
+msgid "Deformation speed"
+msgstr "Скорость искажения"
 
-#: hacks/config/squiral.xml.h:11 hacks/config/twang.xml.h:8
-msgid "Randomness"
+#: ../hacks/config/romanboy.xml.h:11
+msgid "0.0"
 msgstr ""
 
-#: hacks/config/squiral.xml.h:12
-msgid "Right"
-msgstr ""
+#: ../hacks/config/romanboy.xml.h:12
+msgid "Initial deformation"
+msgstr "Начальное искажение"
 
-#: hacks/config/squiral.xml.h:17
-msgid "Squiral"
+#: ../hacks/config/romanboy.xml.h:13
+msgid "1000.0"
 msgstr ""
 
-#: hacks/config/ssystem.xml.h:1
-msgid "SSystem"
-msgstr ""
+#: ../hacks/config/romanboy.xml.h:26
+msgid "Random Projection"
+msgstr "Случайное искажение"
 
-#: hacks/config/ssystem.xml.h:2
-msgid ""
-"SSystem is a GL Solar System simulator. It simulates flybys of Sun, the nine "
-"planets and a few major satellites, with four camera modes. Written by Raul "
-"Alonso. This is not included with the XScreenSaver package, but is packaged "
-"separately. Note: SSystem does not work as a screen saver on all systems, "
-"because it doesn't communicate with xscreensaver properly. It happens to "
-"work with some window managers, but not with others, so your mileage may "
-"vary. SSystem was once available at &lt;http://www1.las.es/~amil/ssystem/"
-"&gt;, but is now gone. You may still be able to find copies elsewhere. "
-"SSystem has since evolved into Celestia, found at &lt;http://www.shatters."
-"net/celestia/&gt;. Sadly, Celestia does not work with xscreensaver at all. "
-"You are encouraged to nag the authors into adding xscreensaver support!"
-msgstr ""
+#: ../hacks/config/romanboy.xml.h:27
+msgid "Perspective"
+msgstr "Перспективное"
 
-#: hacks/config/stairs.xml.h:6
-msgid "Stairs"
-msgstr ""
+#: ../hacks/config/romanboy.xml.h:28
+msgid "Orthographic"
+msgstr "Ортографическое"
+
+#: ../hacks/config/romanboy.xml.h:30
+msgid "X rotation speed"
+msgstr "Скорость вращения X"
+
+#: ../hacks/config/romanboy.xml.h:32
+msgid "Y rotation speed"
+msgstr "Скорость вращения Y"
+
+#: ../hacks/config/romanboy.xml.h:33
+msgid "Z rotation speed"
+msgstr "Скорость вращения Z"
 
-#: hacks/config/stairs.xml.h:8
+#: ../hacks/config/romanboy.xml.h:43
+#, no-c-format
 msgid ""
-"by Marcelo Vianna's third Escher GL hack, this one draws an ``infinite'' "
-"staircase."
+"A 3D immersion of the real projective plane that smoothly deforms between "
+"the Roman surface and the Boy surface. You can walk on the surface of the "
+"real projective plane or rotate it in 3D. Furthermore, it is possible to "
+"smoothly deform the real projective plane between the Roman surface and the "
+"Boy surface while turning it or walking on it. Inspired by François Apéry's "
+"book \"Models of the Real Projective Plane\", Vieweg, 1987. https://en."
+"wikipedia.org/wiki/Boy%27s_surface https://en.wikipedia.org/wiki/"
+"Roman_surface http://mathworld.wolfram.com/BoySurface.html http://mathworld."
+"wolfram.com/RomanSurface.html Written by Carsten Steger; 2014."
 msgstr ""
 
-#: hacks/config/starfish.xml.h:1
-msgid "Color Gradients"
+#: ../hacks/config/rorschach.xml.h:1
+msgid "Rorschach"
 msgstr ""
 
-#: hacks/config/starfish.xml.h:7
-msgid "Pulsating Blob"
-msgstr ""
+#: ../hacks/config/rorschach.xml.h:6
+msgid "With X symmetry"
+msgstr "С симметрией X"
 
-#: hacks/config/starfish.xml.h:10
-msgid "Starfish"
-msgstr ""
+#: ../hacks/config/rorschach.xml.h:7
+msgid "With Y symmetry"
+msgstr "С симметрией Y"
 
-#: hacks/config/starfish.xml.h:13
+#: ../hacks/config/rorschach.xml.h:12
 msgid ""
-"This generates a sequence of undulating, throbbing, star-like patterns which "
-"pulsate, rotate, and turn inside out. Another display mode uses these shapes "
-"to lay down a field of colors, which are then cycled. The motion is very "
-"organic. Written by Jamie Zawinski."
+"Inkblot patterns via a reflected random walk. https://en.wikipedia.org/wiki/"
+"Rorschach_inkblot_test https://en.wikipedia.org/wiki/Random_walk Written by "
+"Jamie Zawinski; 1992."
 msgstr ""
 
-#: hacks/config/starwars.xml.h:2
-msgid "Anti-aliased Lines"
+#: ../hacks/config/rotor.xml.h:1
+msgid "Rotor"
 msgstr ""
 
-#: hacks/config/starwars.xml.h:4
+#: ../hacks/config/rotor.xml.h:6 ../hacks/config/skytentacles.xml.h:6
+#: ../hacks/config/wander.xml.h:9
+msgid "Length"
+msgstr "Длина"
+
+#: ../hacks/config/rotor.xml.h:14
 msgid ""
-"Draws a stream of text slowly scrolling into the distance at an angle, over "
-"a star field, like at the beginning of the movie of the same name. The text "
-"can be the output of a program or the contents of a file or URL, as "
-"configured on the \"Advanced\" tab of the main Screensaver Preferences "
-"window. Written by Jamie Zawinski and Claudio Matauoka."
+"This screen saver was removed from the XScreenSaver distribution as of "
+"version 5.08. Draws a line segment moving along a complex spiraling curve. "
+"Written by Tom Lawrence; 1997."
 msgstr ""
 
-#: hacks/config/starwars.xml.h:5
-msgid "Fade Out"
+#: ../hacks/config/rotzoomer.xml.h:1
+msgid "RotZoomer"
 msgstr ""
 
-#: hacks/config/starwars.xml.h:10
-msgid "Scroll Speed"
-msgstr ""
+#: ../hacks/config/rotzoomer.xml.h:8
+msgid "Rectangle count"
+msgstr "Количество прямоугольников"
 
-#: hacks/config/starwars.xml.h:13
-msgid "Star Rotation Speed"
-msgstr ""
+#: ../hacks/config/rotzoomer.xml.h:10
+msgid "Stationary rectangles"
+msgstr "Стационарные прямоугольники"
 
-#: hacks/config/starwars.xml.h:14
-msgid "StarWars"
-msgstr ""
+#: ../hacks/config/rotzoomer.xml.h:11
+msgid "Wandering rectangles"
+msgstr "Блуждающие прямоугольники"
 
-#: hacks/config/starwars.xml.h:18
-msgid "Texture-Mapped Font"
-msgstr ""
+#: ../hacks/config/rotzoomer.xml.h:12
+msgid "Sweeping arcs"
+msgstr "Широкие дуги"
 
-#: hacks/config/starwars.xml.h:19
-msgid "Thick Lines"
-msgstr ""
+#: ../hacks/config/rotzoomer.xml.h:13
+msgid "Rotating discs"
+msgstr "Вращающиеся диски"
 
-#: hacks/config/starwars.xml.h:20
-msgid "Wrap Long Lines"
-msgstr ""
+#: ../hacks/config/rotzoomer.xml.h:14
+msgid "Animate"
+msgstr "Анимировать"
 
-#: hacks/config/stonerview.xml.h:1
+#: ../hacks/config/rotzoomer.xml.h:16
 msgid ""
-"Chains of colorful squares dance around each other in complex spiral "
-"patterns. Written by Andrew Plotkin, based on SGI's `electropaint' "
-"screensaver."
+"Distorts an image by rotating and scaling random sections of it. Written by "
+"Claudio Matsuoka and Jamie Zawinski; 2001."
 msgstr ""
 
-#: hacks/config/stonerview.xml.h:3
-msgid "StonerView"
+#: ../hacks/config/rubik.xml.h:1
+msgid "Rubik"
 msgstr ""
 
-#: hacks/config/strange.xml.h:6
-msgid "Strange"
-msgstr ""
+#: ../hacks/config/rubik.xml.h:10
+msgid "Hide shuffling"
+msgstr "Скрывать перетасовку"
 
-#: hacks/config/strange.xml.h:7
+#: ../hacks/config/rubik.xml.h:13
+#, no-c-format
 msgid ""
-"This draws strange attractors: it's a colorful, unpredictably-animating "
-"field of dots that swoops and twists around. The motion is very nice. "
-"Written by Massimino Pascal."
+"A Rubik's Cube that repeatedly shuffles and solves itself. See also the "
+"\"GLSnake\" and \"Cube21\" screen savers. https://en.wikipedia.org/wiki/Rubik"
+"%27s_Cube Written by Marcelo Vianna; 1997."
 msgstr ""
 
-#: hacks/config/substrate.xml.h:2 hacks/config/xplanet.xml.h:2
-#, fuzzy, no-c-format
-msgid "0%"
-msgstr "100%"
-
-#: hacks/config/substrate.xml.h:5
-msgid "Circle Percentage"
+#: ../hacks/config/rubikblocks.xml.h:1
+msgid "RubikBlocks"
 msgstr ""
 
-#: hacks/config/substrate.xml.h:9
-#, fuzzy
-msgid "Initial Cracks"
-msgstr "Плотность"
-
-#: hacks/config/substrate.xml.h:10
+#: ../hacks/config/rubikblocks.xml.h:21
 msgid ""
-"Lines like crystals grow on a computational substrate. A simple "
-"perpendicular growth rule creates intricate city-like structures. By J. "
-"Tarbell and Mike Kershaw."
+"The \"Rubik's Mirror Blocks\" puzzle. See also the \"Rubik\", \"Cube21\", "
+"and \"GLSnake\" screen savers. https://en.wikipedia.org/wiki/"
+"Combination_puzzles#Irregular_cuboids Written by Vasek Potocek; 2009."
 msgstr ""
 
-#: hacks/config/substrate.xml.h:13
-#, fuzzy
-msgid "Sandgrains"
-msgstr "Стандартные"
-
-#: hacks/config/substrate.xml.h:17
-msgid "Substrate"
+#: ../hacks/config/sballs.xml.h:1
+msgid "SBalls"
 msgstr ""
 
-#: hacks/config/substrate.xml.h:18
-#, fuzzy
-msgid "Wireframe only"
-msgstr "Каркасное изображение"
+#: ../hacks/config/sballs.xml.h:11
+msgid "Plane"
+msgstr "Плоскость"
 
-#: hacks/config/superquadrics.xml.h:3
-msgid ""
-"Ed Mackey reports that he wrote the first version of this program in BASIC "
-"on a Commodore 64 in 1987, as a 320x200 black and white wireframe. Now it is "
-"GL and has specular reflections."
+#: ../hacks/config/sballs.xml.h:12
+msgid "Pyramid"
+msgstr "Пирамида"
+
+#: ../hacks/config/sballs.xml.h:13
+msgid "Star"
+msgstr "Звезда"
+
+#: ../hacks/config/sballs.xml.h:17
+msgid "Textured balls spinning like crazy. Written by Eric Lassauge; 2002."
 msgstr ""
 
-#: hacks/config/superquadrics.xml.h:11
-msgid "Superquadrics"
+#: ../hacks/config/shadebobs.xml.h:1
+msgid "ShadeBobs"
 msgstr ""
 
-#: hacks/config/swirl.xml.h:4
+#: ../hacks/config/shadebobs.xml.h:17
 msgid ""
-"More flowing, swirly patterns. This version is by M. Dobie and R. Taylor, "
-"but you might have seen a Mac program similar to this called FlowFazer. "
-"There is also a cool Java applet of a similar concept."
+"Oscillating oval patterns that look something like vapor trails or neon "
+"tubes. Written by Shane Smit; 1999."
 msgstr ""
 
-#: hacks/config/swirl.xml.h:8
-msgid "Swirl"
+#: ../hacks/config/sierpinski.xml.h:1
+msgid "Sierpinski"
 msgstr ""
 
-#: hacks/config/t3d.xml.h:1
-msgid "0 deg"
-msgstr ""
+#: ../hacks/config/sierpinski.xml.h:6 ../hacks/config/surfaces.xml.h:22
+#: ../hacks/config/thornbird.xml.h:6 ../hacks/config/voronoi.xml.h:6
+msgid "Points"
+msgstr "Точки"
 
-#: hacks/config/t3d.xml.h:2
-msgid "5 Minute Tick Marks"
+#: ../hacks/config/sierpinski.xml.h:14
+msgid ""
+"The 2D Sierpinski triangle fractal. See also the \"Sierpinski3D\" screen "
+"saver. https://en.wikipedia.org/wiki/Sierpinski_triangle Written by Desmond "
+"Daignault; 1997."
 msgstr ""
 
-#: hacks/config/t3d.xml.h:3
-msgid "90 deg"
+#: ../hacks/config/sierpinski3d.xml.h:1
+msgid "Sierpinski3D"
 msgstr ""
 
-#: hacks/config/t3d.xml.h:4
-msgid "Bigger"
+#: ../hacks/config/sierpinski3d.xml.h:11
+msgid ""
+"The recursive Sierpinski tetrahedron fractal. https://en.wikipedia.org/wiki/"
+"Sierpinski_triangle#Analogs_in_higher_dimension Written by Jamie Zawinski "
+"and Tim Robinson; 1999."
 msgstr ""
 
-#: hacks/config/t3d.xml.h:5
-msgid "Cycle Seconds"
+#: ../hacks/config/skytentacles.xml.h:1
+msgid "SkyTentacles"
 msgstr ""
 
-#: hacks/config/t3d.xml.h:10
-msgid "Minute Tick Marks"
-msgstr ""
+#: ../hacks/config/skytentacles.xml.h:12
+msgid "Flexibility"
+msgstr "Гибкость"
 
-#: hacks/config/t3d.xml.h:12
-msgid "Smaller"
-msgstr ""
+#: ../hacks/config/skytentacles.xml.h:14
+msgid "Wiggliness"
+msgstr "Движения"
 
-#: hacks/config/t3d.xml.h:14
-msgid "T3D"
-msgstr ""
+#: ../hacks/config/skytentacles.xml.h:19
+msgid "X resolution"
+msgstr "Разрешение X"
 
-#: hacks/config/t3d.xml.h:15
-msgid ""
-"This draws a working analog clock composed of floating, throbbing bubbles. "
-"Written by Bernd Paysan."
-msgstr ""
+#: ../hacks/config/skytentacles.xml.h:20
+msgid "Y resolution"
+msgstr "Разрешение Y"
 
-#: hacks/config/t3d.xml.h:16
-msgid "Turn Side-to-Side"
-msgstr ""
+#: ../hacks/config/skytentacles.xml.h:21
+msgid "Draw skin"
+msgstr "Прорисовывать кожу"
 
-#: hacks/config/t3d.xml.h:17
-msgid "Wobbliness"
-msgstr ""
+#: ../hacks/config/skytentacles.xml.h:22
+msgid "Cartoony"
+msgstr "Мультяшный"
 
-#: hacks/config/tangram.xml.h:3
+#: ../hacks/config/skytentacles.xml.h:23
+msgid "Tentacles can intersect"
+msgstr "С щупальцами можно взаимодействовать"
+
+#: ../hacks/config/skytentacles.xml.h:26
 msgid ""
-"Lets you watch the computer solve Tangram puzzles Written by Jeremy English."
+"There is a tentacled abomination in the sky. From above you it devours. "
+"Written by Jamie Zawinski; 2008."
 msgstr ""
 
-#: hacks/config/tangram.xml.h:6
-msgid "Tangram"
+#: ../hacks/config/slidescreen.xml.h:1
+msgid "SlideScreen"
 msgstr ""
 
-#: hacks/config/tangram.xml.h:7
-#, fuzzy
-msgid "Viewing Time"
-msgstr "Сплошной"
+#: ../hacks/config/slidescreen.xml.h:6
+msgid "Pause"
+msgstr "Пауза"
 
-#: hacks/config/tangram.xml.h:9
-msgid "X Camera Rotate"
-msgstr ""
+#: ../hacks/config/slidescreen.xml.h:12
+msgid "Slide speed"
+msgstr "Скорость смены слайдов"
 
-#: hacks/config/tangram.xml.h:10
-msgid "Y Camera Rotate"
-msgstr ""
+#: ../hacks/config/slidescreen.xml.h:17
+msgid "Gutter size"
+msgstr "Размер паза"
 
-#: hacks/config/tangram.xml.h:11
-msgid "Z Camera Rotate"
+#: ../hacks/config/slidescreen.xml.h:19
+msgid ""
+"A variant on a \"fifteen puzzle\", operating on the screen or an image. It "
+"divides the image into a grid and randomly shuffles the squares. https://en."
+"wikipedia.org/wiki/Fifteen_puzzle Written by Jamie Zawinski; 1994."
 msgstr ""
 
-#: hacks/config/thornbird.xml.h:1
-msgid ""
-"Displays a view of the ``Bird in a Thornbush'' fractal. Written by Tim "
-"Auckland."
+#: ../hacks/config/slip.xml.h:1
+msgid "Slip"
 msgstr ""
 
-#: hacks/config/thornbird.xml.h:6
-msgid "Points"
+#: ../hacks/config/slip.xml.h:14
+msgid ""
+"A jet engine consumes the screen, then puts it through a spin cycle. Written "
+"by Scott Draves and Jamie Zawinski; 1997."
 msgstr ""
 
-#: hacks/config/thornbird.xml.h:12
-msgid "Thornbird"
+#: ../hacks/config/sonar.xml.h:1
+msgid "Sonar"
 msgstr ""
 
-#: hacks/config/timetunnel.xml.h:1
-#, fuzzy
-msgid "0 sec"
-msgstr "2 секунды"
+#: ../hacks/config/sonar.xml.h:8
+msgid "Ping local subnet"
+msgstr "Пинговать локальную подсеть"
 
-#: hacks/config/timetunnel.xml.h:2
-#, fuzzy
-msgid "30 sec"
-msgstr "2 секунды"
+#.
+#. <option id="24" _label="Ping subnet/24 (254 hosts)" arg-set="-ping subnet/24"/>
+#. <option id="25" _label="Ping subnet/25 (126 hosts)" arg-set="-ping subnet/25"/>
+#. <option id="26" _label="Ping subnet/26 (62 hosts)"  arg-set="-ping subnet/26"/>
+#. <option id="27" _label="Ping subnet/27 (31 hosts)"  arg-set="-ping subnet/27"/>
+#. <option id="28" _label="Ping subnet/28 (14 hosts)"/>
+#. <option id="29" _label="Ping subnet/29 (6 hosts)"   arg-set="-ping subnet/29"/>
+#. <option id="30" _label="Ping subnet/30 (2 hosts)"   arg-set="-ping subnet/30"/>
+#.
+#: ../hacks/config/sonar.xml.h:18
+msgid "Ping known SSH hosts"
+msgstr "Пинговать известные хосты по SSH"
 
-#: hacks/config/timetunnel.xml.h:4
-msgid "Draw Logo"
-msgstr ""
+#: ../hacks/config/sonar.xml.h:19
+msgid "Ping Google, Facebook, etc."
+msgstr "Пинговать Google, Facebook и т.д."
 
-#: hacks/config/timetunnel.xml.h:5
-msgid ""
-"Draws an animation similar to the opening and closing effects on the Dr. Who "
-"television show. Written by Sean P. Brennan."
-msgstr ""
+#: ../hacks/config/sonar.xml.h:20
+msgid "Simulation (don't ping)"
+msgstr "Симуляция (не пинговать)"
 
-#: hacks/config/timetunnel.xml.h:7
-msgid "Run Backward"
-msgstr ""
+#: ../hacks/config/sonar.xml.h:22
+msgid "Font size"
+msgstr "Размер шрифта"
 
-#: hacks/config/timetunnel.xml.h:10
-msgid "Start sequence time"
-msgstr ""
+#: ../hacks/config/sonar.xml.h:27
+msgid "Simulation team A name"
+msgstr "Имя команды A симуляции"
 
-#: hacks/config/timetunnel.xml.h:11
-msgid "Timetunnel"
-msgstr ""
+#: ../hacks/config/sonar.xml.h:28
+msgid "A count"
+msgstr "Количество A"
 
-#: hacks/config/triangle.xml.h:2
-msgid ""
-"Generates random mountain ranges using iterative subdivision of triangles. "
-"Written by Tobias Gloth."
-msgstr ""
+#: ../hacks/config/sonar.xml.h:29
+msgid "Simulation team B name"
+msgstr "Имя команды B симуляции"
 
-#: hacks/config/triangle.xml.h:7
-msgid "Triangle"
-msgstr ""
+#: ../hacks/config/sonar.xml.h:30
+msgid "B count"
+msgstr "Количество B"
 
-#: hacks/config/truchet.xml.h:4
-msgid ""
-"This draws line- and arc-based Truchet patterns that tile the screen. "
-"Written by Adrian Likins."
-msgstr ""
+#: ../hacks/config/sonar.xml.h:31
+msgid "Resolve host names"
+msgstr "Преобразовывать имена хостов"
 
-#: hacks/config/truchet.xml.h:5
-msgid "Truchet"
-msgstr ""
+#: ../hacks/config/sonar.xml.h:32
+msgid "Show ping times"
+msgstr "Показывать время пинга"
 
-#: hacks/config/twang.xml.h:2
+#: ../hacks/config/sonar.xml.h:35
 msgid ""
-"Divides the screen into a grid, and plucks them. Written by Dan Bornstein."
+"A sonar display pings (get it?) the hosts on your local network, and plots "
+"their distance (response time) from you. The three rings represent ping "
+"times of approximately 2.5, 70 and 2,000 milliseconds respectively. "
+"Alternately, it can run a simulation that doesn't involve hosts. https://en."
+"wikipedia.org/wiki/Ping#History Written by Jamie Zawinski and Stephen "
+"Martin; 1998."
 msgstr ""
 
-#: hacks/config/twang.xml.h:6
-msgid "Jumpy"
+#: ../hacks/config/speedmine.xml.h:1
+msgid "SpeedMine"
 msgstr ""
 
-#: hacks/config/twang.xml.h:11
-msgid "Springiness"
-msgstr ""
+#: ../hacks/config/speedmine.xml.h:6
+msgid "Max velocity"
+msgstr "Максимальная скорость"
 
-#: hacks/config/twang.xml.h:13
-msgid "Transference"
-msgstr ""
+#: ../hacks/config/speedmine.xml.h:8
+msgid "Thrust"
+msgstr "Осевая нагрузка"
 
-#: hacks/config/twang.xml.h:14
-msgid "Twang"
-msgstr ""
+#: ../hacks/config/speedmine.xml.h:10
+msgid "Tunnel"
+msgstr "Туннель"
 
-#: hacks/config/vermiculate.xml.h:1
-msgid "Draws squiggly worm-like paths. Written by Tyler Pierce."
-msgstr ""
+#: ../hacks/config/speedmine.xml.h:11 ../hacks/config/worm.xml.h:1
+msgid "Worm"
+msgstr "Червь"
 
-#: hacks/config/vermiculate.xml.h:2
-msgid "Vermiculate"
-msgstr ""
+#: ../hacks/config/speedmine.xml.h:12
+msgid "Rocky walls"
+msgstr "Каменные стены"
+
+#: ../hacks/config/speedmine.xml.h:13
+msgid "Allow wall collisions"
+msgstr "Разрешать столкновения со стенами"
 
-#: hacks/config/vidwhacker.xml.h:2
-msgid "2 seconds"
-msgstr "2 секунды"
+#: ../hacks/config/speedmine.xml.h:14
+msgid "Present bonuses"
+msgstr "Дарить бонусы"
 
-#: hacks/config/vidwhacker.xml.h:4
-msgid "Image Directory"
-msgstr ""
+#: ../hacks/config/speedmine.xml.h:15
+msgid "Display crosshair"
+msgstr "Показывать перекрестье"
 
-#: hacks/config/vidwhacker.xml.h:5
+#: ../hacks/config/speedmine.xml.h:18
 msgid ""
-"This is actually just a shell script that grabs a frame of video from the "
-"system's video input, and then uses some PBM filters (chosen at random) to "
-"manipulate and recombine the video frame in various ways (edge detection, "
-"subtracting the image from a rotated version of itself, etc.) Then it "
-"displays that image for a few seconds, and does it again. This works really "
-"well if you just feed broadcast television into it."
+"Simulates speeding down a rocky mineshaft, or a funky dancing worm. Written "
+"by Conrad Parker; 2001."
 msgstr ""
 
-#: hacks/config/vidwhacker.xml.h:6
-msgid "VidWhacker"
+#: ../hacks/config/sphere.xml.h:9
+msgid ""
+"This screen saver was removed from the XScreenSaver distribution as of "
+"version 5.08. Draws shaded spheres in multiple colors. Written by Tom Duff "
+"and Jamie Zawinski; 1982, 1997."
 msgstr ""
 
-#: hacks/config/vines.xml.h:6
-msgid ""
-"This one generates a continuous sequence of small, curvy geometric patterns. "
-"It scatters them around your screen until it fills up, then it clears the "
-"screen and starts over. Written by Tracy Camp and David Hansen."
+#: ../hacks/config/spheremonics.xml.h:1
+msgid "Spheremonics"
 msgstr ""
 
-#: hacks/config/vines.xml.h:8
-msgid "Vines"
+#: ../hacks/config/spheremonics.xml.h:18
+msgid "Smoothed lines"
+msgstr "Сглаживание линий"
+
+#: ../hacks/config/spheremonics.xml.h:23
+msgid ""
+"These closed objects are commonly called spherical harmonics, although they "
+"are only remotely related to the mathematical definition found in the "
+"solution to certain wave functions, most notably the eigenfunctions of "
+"angular momentum operators. https://en.wikipedia.org/wiki/"
+"Spherical_harmonics#Visualization_of_the_spherical_harmonics Written by Paul "
+"Bourke and Jamie Zawinski; 2002."
 msgstr ""
 
-#: hacks/config/wander.xml.h:5
-msgid "Draw Spots"
+#: ../hacks/config/spiral.xml.h:1
+msgid "Spiral"
 msgstr ""
 
-#: hacks/config/wander.xml.h:6
+#: ../hacks/config/spiral.xml.h:12
 msgid ""
-"Draws a colorful random-walk, in various forms. Written by Rick Campbell."
+"This screen saver was removed from the XScreenSaver distribution as of "
+"version 5.08. Moving circular moire patterns. Written by Peter "
+"Schmitzberger; 1997."
 msgstr ""
 
-#: hacks/config/wander.xml.h:14
-msgid "Sustain"
+#: ../hacks/config/splitflap.xml.h:1
+msgid "SplitFlap"
 msgstr ""
 
-#: hacks/config/webcollage.xml.h:1
-#, fuzzy
-msgid "2 min"
-msgstr "2 минуты"
+#: ../hacks/config/splitflap.xml.h:8
+msgid "Columns"
+msgstr "Столбцы"
 
-#: hacks/config/webcollage.xml.h:2
-#, fuzzy
-msgid "30 secs"
-msgstr "2 секунды"
+#: ../hacks/config/splitflap.xml.h:9
+msgid "Rows"
+msgstr "Строки"
 
-#: hacks/config/webcollage.xml.h:3
-msgid "Delay:                    None"
-msgstr ""
+#: ../hacks/config/splitflap.xml.h:10
+msgid "Display text"
+msgstr "Показывать текст"
 
-#: hacks/config/webcollage.xml.h:4
-msgid "Dictionary File"
-msgstr ""
+#: ../hacks/config/splitflap.xml.h:11
+msgid "Display 12-hour clock"
+msgstr "Показывать часы в 12-часовом формате"
 
-#: hacks/config/webcollage.xml.h:5
-msgid "Opacity:      Transparent"
-msgstr ""
+#: ../hacks/config/splitflap.xml.h:12
+msgid "Display 24-hour clock"
+msgstr "Показывать часы в 24-часовом формате"
 
-#: hacks/config/webcollage.xml.h:6
-msgid "Overall Filter Program"
+#: ../hacks/config/splitflap.xml.h:26
+msgid ""
+"Simulates a split-flap display, an old style of electromechanical sign as "
+"seen in airports and train stations, and commonly used in alarm clocks in "
+"the 1960s and 1970s. https://en.wikipedia.org/wiki/Split-flap_display "
+"https://en.wikipedia.org/wiki/Flip_clock Written by Jamie Zawinski; 2015."
 msgstr ""
 
-#: hacks/config/webcollage.xml.h:7
-msgid "Per-Image Filter Program"
+#: ../hacks/config/splodesic.xml.h:1
+msgid "Splodesic"
 msgstr ""
 
-#: hacks/config/webcollage.xml.h:9
+#: ../hacks/config/splodesic.xml.h:6
+msgid "Eruption frequency"
+msgstr "Частота извержений"
+
+#: ../hacks/config/splodesic.xml.h:12
 msgid ""
-"This program makes collages out of random images pulled off of the World "
-"Wide Web. It finds these images by doing random web searches, and then "
-"extracting images from the returned pages. It can also be set up to filter "
-"the images through the `VidWhacker' program. WARNING: THE INTERNET SOMETIMES "
-"CONTAINS PORNOGRAPHY. The Internet being what it is, absolutely anything "
-"might show up in the collage including -- quite possibly -- pornography, or "
-"even nudity. Please act accordingly. Written by Jamie Zawinski."
+"A geodesic sphere experiences a series of eruptions. Written by Jamie "
+"Zawinski; 2016."
 msgstr ""
 
-#: hacks/config/webcollage.xml.h:10
-msgid "URL Timeout:     2 secs"
+#: ../hacks/config/spotlight.xml.h:1
+msgid "Spotlight"
 msgstr ""
 
-#: hacks/config/webcollage.xml.h:11
-msgid "WebCollage"
-msgstr ""
+#: ../hacks/config/spotlight.xml.h:9
+msgid "Spotlight size"
+msgstr "Размер прожектора"
 
-#: hacks/config/whirlwindwarp.xml.h:2
+#: ../hacks/config/spotlight.xml.h:12
 msgid ""
-"Floating stars are acted upon by a mixture of simple 2D forcefields. The "
-"strength of each forcefield changes continuously, and it is also switched on "
-"and off at random. By Paul 'Joey' Clark."
+"A spotlight scanning across a black screen, illuminating a loaded image when "
+"it passes. Written by Rick Schultz and Jamie Zawinski; 1999."
 msgstr ""
 
-#: hacks/config/whirlwindwarp.xml.h:7
-msgid "Trail Size"
+#: ../hacks/config/sproingies.xml.h:1
+msgid "Sproingies"
 msgstr ""
 
-#: hacks/config/whirlwindwarp.xml.h:8
-msgid "WhirlwindWarp"
-msgstr ""
+#: ../hacks/config/sproingies.xml.h:7
+msgid "Fall off edge"
+msgstr "Падать с грани"
 
-#: hacks/config/whirlygig.xml.h:1
-msgid "Amplitude"
+#: ../hacks/config/sproingies.xml.h:11
+#, no-c-format
+msgid ""
+"Slinky-like creatures walk down an infinite staircase and occasionally "
+"explode! https://en.wikipedia.org/wiki/Slinky https://en.wikipedia.org/wiki/Q"
+"%2Abert https://en.wikipedia.org/wiki/Marble_Madness Written by Ed Mackey; "
+"1997."
 msgstr ""
 
-#: hacks/config/whirlygig.xml.h:2
-msgid "Circle"
+#: ../hacks/config/squiral.xml.h:1
+msgid "Squiral"
 msgstr ""
 
-#: hacks/config/whirlygig.xml.h:3
-msgid "Draws zooming chains of sinusoidal spots. Written by Ashton Trey Belew."
-msgstr ""
+#: ../hacks/config/squiral.xml.h:5 ../hacks/config/twang.xml.h:9
+msgid "Randomness"
+msgstr "Случайность"
 
-#: hacks/config/whirlygig.xml.h:4
-#, fuzzy
-msgid "Explain modes"
-msgstr "Режимы экрана"
+#: ../hacks/config/squiral.xml.h:7
+msgid "Left"
+msgstr "Влево"
 
-#: hacks/config/whirlygig.xml.h:5
-msgid "Fun"
-msgstr ""
+#: ../hacks/config/squiral.xml.h:8
+msgid "Handedness"
+msgstr "Направление"
 
-#: hacks/config/whirlygig.xml.h:6
-msgid "Funky"
-msgstr ""
+#: ../hacks/config/squiral.xml.h:9
+msgid "Right"
+msgstr "Вправо"
 
-#: hacks/config/whirlygig.xml.h:7
-msgid "Innie"
+#: ../hacks/config/squiral.xml.h:18
+msgid ""
+"Square-spiral-producing automata. The spirals grow outward until they hit "
+"something, then they go around it. Written by Jeff Epler; 1999."
 msgstr ""
 
-#: hacks/config/whirlygig.xml.h:8
-msgid "Leave a trail"
+#: ../hacks/config/stairs.xml.h:1
+msgid "Stairs"
 msgstr ""
 
-#: hacks/config/whirlygig.xml.h:9
-#, fuzzy
-msgid "Linear"
-msgstr "Линии"
+#: ../hacks/config/stairs.xml.h:6
+msgid ""
+"Escher's infinite staircase. https://en.wikipedia.org/wiki/"
+"Maurits_Cornelis_Escher Written by Marcelo Vianna and Jamie Zawinski; 1998."
+msgstr ""
 
-#: hacks/config/whirlygig.xml.h:11
-msgid "Lissajous"
+#: ../hacks/config/starfish.xml.h:1
+msgid "Starfish"
 msgstr ""
 
-#: hacks/config/whirlygig.xml.h:15
-#, fuzzy
-msgid "Test"
-msgstr "Наилучший"
+#: ../hacks/config/starfish.xml.h:3
+msgid "Color gradients"
+msgstr "Градиенты цветов"
 
-#: hacks/config/whirlygig.xml.h:16
-msgid "Use Double Buffering"
-msgstr ""
+#: ../hacks/config/starfish.xml.h:4
+msgid "Pulsating blob"
+msgstr "Пульсирующий сгусток"
 
-#: hacks/config/whirlygig.xml.h:17
-msgid "Whirlies"
+#: ../hacks/config/starfish.xml.h:18
+msgid ""
+"Undulating, throbbing, star-like patterns pulsate, rotate, and turn inside "
+"out. Another display mode uses these shapes to lay down a field of colors, "
+"which are then cycled. The motion is very organic. Written by Jamie "
+"Zawinski; 1997."
 msgstr ""
 
-#: hacks/config/whirlygig.xml.h:18
-msgid "WhirlyGig"
+#: ../hacks/config/starwars.xml.h:1
+msgid "StarWars"
 msgstr ""
 
-#: hacks/config/whirlygig.xml.h:19
-msgid "Wrap the screen"
-msgstr ""
+#: ../hacks/config/starwars.xml.h:2
+msgid "  Frame rate      Low"
+msgstr "Частота кадров       Низкая"
 
-#: hacks/config/worm.xml.h:1
-msgid ""
-"An ancient xlock hack that draws multicolored worms that crawl around the "
-"screen. Written by Brad Taylor, Dave Lemke, Boris Putanec, and Henrik "
-"Theiling."
-msgstr ""
+#: ../hacks/config/starwars.xml.h:4
+msgid "Scroll speed     Slow"
+msgstr "Скорость прокрутки Медленно"
 
-#: hacks/config/wormhole.xml.h:6
-#, fuzzy
-msgid "Star speed"
-msgstr "Скорость акулы"
+#: ../hacks/config/starwars.xml.h:6
+msgid " Stars speed     Slow"
+msgstr "Скорость звезд     Медленно"
 
-#: hacks/config/wormhole.xml.h:7
-msgid "Stars Created"
-msgstr ""
+#: ../hacks/config/starwars.xml.h:10
+msgid "Wrap long lines"
+msgstr "Обрезать длинные строки"
 
-#: hacks/config/wormhole.xml.h:8
-msgid "Wormhole"
-msgstr ""
+#: ../hacks/config/starwars.xml.h:11
+msgid "Texture-mapped font"
+msgstr "Шрифт с текстурой"
 
-#: hacks/config/wormhole.xml.h:9
-msgid ""
-"Wormhole simulates flying through a colored wormhole in space. Written by "
-"Jon Rafkind."
-msgstr ""
+#: ../hacks/config/starwars.xml.h:12
+msgid "Anti-aliased lines"
+msgstr "Линии со сглаживанием"
 
-#: hacks/config/xanalogtv.xml.h:1
-msgid "XAnalogTV"
-msgstr ""
+#: ../hacks/config/starwars.xml.h:13
+msgid "Thick lines"
+msgstr "Толстые линии"
 
-#: hacks/config/xanalogtv.xml.h:2
+#: ../hacks/config/starwars.xml.h:14
+msgid "Fade out"
+msgstr "Затухание"
+
+#: ../hacks/config/starwars.xml.h:18
+msgid "or, Text columns"
+msgstr "или столбцов текста"
+
+#: ../hacks/config/starwars.xml.h:19
 msgid ""
-"XAnalogTV shows a detailed simulation of an old TV set showing various test "
-"patterns, with various picture artifacts like snow, bloom, distortion, "
-"ghosting, and hash noise. It also simulates the TV warming up. It will cycle "
-"through 12 channels, some with images you give it, and some with color bars "
-"or nothing but static. By Trevor Blackwell."
+"A stream of text slowly scrolling into the distance at an angle, over a star "
+"field, like at the beginning of the movie of the same name. https://en."
+"wikipedia.org/wiki/Star_Wars_opening_crawl Written by Jamie Zawinski and "
+"Claudio Matsuoka; 2001."
 msgstr ""
 
-#: hacks/config/xaos.xml.h:1
-msgid "XaoS"
+#: ../hacks/config/stonerview.xml.h:1
+msgid "StonerView"
 msgstr ""
 
-#: hacks/config/xaos.xml.h:2
+#: ../hacks/config/stonerview.xml.h:6
+msgid "Translucent"
+msgstr "Полупрозрачность"
+
+#: ../hacks/config/stonerview.xml.h:8
 msgid ""
-"XaoS generates fast fly-through animations of the Mandelbrot and other "
-"fractal sets. Written by Thomas Marsh and Jan Hubicka. This is not included "
-"with the XScreenSaver package, but if you don't have it already, you can "
-"find it at &lt;http://xaos.theory.org/&gt;."
+"Chains of colorful squares dance around each other in complex spiral "
+"patterns. Inspired by David Tristram's `electropaint' screen saver, "
+"originally written for SGI computers in the late 1980s or early 1990s. "
+"Written by Andrew Plotkin; 2001."
 msgstr ""
 
-#: hacks/config/xdaliclock.xml.h:1
-msgid "12-Hour Time"
+#: ../hacks/config/strange.xml.h:1
+msgid "Strange"
 msgstr ""
 
-#: hacks/config/xdaliclock.xml.h:2
-msgid "24-Hour Time"
-msgstr ""
+#: ../hacks/config/strange.xml.h:5
+msgid "Curviness"
+msgstr "Кривизна"
 
-#: hacks/config/xdaliclock.xml.h:3
-msgid "Cycle Colors"
-msgstr ""
+#: ../hacks/config/strange.xml.h:6
+msgid "1k"
+msgstr "1 000"
 
-#: hacks/config/xdaliclock.xml.h:4
-msgid "Display Seconds"
-msgstr ""
+#: ../hacks/config/strange.xml.h:7
+msgid "Number of points"
+msgstr "Количество точек"
 
-#: hacks/config/xdaliclock.xml.h:5
-msgid "Huge Font"
-msgstr ""
+#: ../hacks/config/strange.xml.h:8
+msgid "500k"
+msgstr "500 000"
 
-#: hacks/config/xdaliclock.xml.h:6 hacks/config/xmatrix.xml.h:10
-msgid "Large Font"
-msgstr ""
+#: ../hacks/config/strange.xml.h:10 ../hacks/config/voronoi.xml.h:9
+msgid "Point size"
+msgstr "Размер точки"
 
-#: hacks/config/xdaliclock.xml.h:7
-msgid "Medium Font"
+#: ../hacks/config/strange.xml.h:13
+#, no-c-format
+msgid "10%"
 msgstr ""
 
-#: hacks/config/xdaliclock.xml.h:8 hacks/config/xmatrix.xml.h:16
-msgid "Small Font"
+#: ../hacks/config/strange.xml.h:16
+#, no-c-format
+msgid "400%"
 msgstr ""
 
-#: hacks/config/xdaliclock.xml.h:9
-msgid "XDaliClock"
-msgstr ""
+#: ../hacks/config/strange.xml.h:17
+msgid "Brightness"
+msgstr "Яркость"
 
-#: hacks/config/xdaliclock.xml.h:10
+#: ../hacks/config/strange.xml.h:24
 msgid ""
-"XDaliClock draws a large digital clock, the numbers of which change by "
-"``melting'' into their new shapes. Written by Jamie Zawinski. This is not "
-"included with the XScreenSaver package, but if you don't have it already, "
-"you can find it at &lt;http://www.jwz.org/xdaliclock/&gt;."
+"Strange attractors: a swarm of dots swoops and twists around. https://en."
+"wikipedia.org/wiki/Attractor#Strange_attractor Written by Massimino Pascal; "
+"1997."
 msgstr ""
 
-#: hacks/config/xearth.xml.h:1
-msgid "Bright"
+#: ../hacks/config/substrate.xml.h:1
+msgid "Substrate"
 msgstr ""
 
-#: hacks/config/xearth.xml.h:2 hacks/config/xplanet.xml.h:7
-msgid "Date/Time Stamp"
-msgstr ""
+#: ../hacks/config/substrate.xml.h:9
+msgid "Sand grains"
+msgstr "Песчинки"
 
-#: hacks/config/xearth.xml.h:3
-msgid "Day  Dim"
+#: ../hacks/config/substrate.xml.h:12
+#, no-c-format
+msgid "0%"
 msgstr ""
 
-#: hacks/config/xearth.xml.h:5
-msgid "Display Stars"
+#: ../hacks/config/substrate.xml.h:13
+msgid "Circle percentage"
 msgstr ""
 
-#: hacks/config/xearth.xml.h:8
-msgid "Label Cities"
-msgstr ""
+#: ../hacks/config/substrate.xml.h:16
+msgid "Initial cracks"
+msgstr "Начальное количество разломов"
 
-#: hacks/config/xearth.xml.h:9 hacks/config/xplanet.xml.h:49
-msgid "Lower Left"
-msgstr ""
+#: ../hacks/config/substrate.xml.h:17
+msgid "Wireframe only"
+msgstr "Только каркас"
 
-#: hacks/config/xearth.xml.h:10 hacks/config/xplanet.xml.h:50
-msgid "Lower Right"
-msgstr ""
+#: ../hacks/config/substrate.xml.h:18
+msgid "Seamless mode"
+msgstr "Бесшовный режим"
 
-#: hacks/config/xearth.xml.h:13 hacks/config/xplanet.xml.h:51
-msgid "Mercator Projection"
+#: ../hacks/config/substrate.xml.h:20
+msgid ""
+"Crystalline lines grow on a computational substrate. A simple perpendicular "
+"growth rule creates intricate city-like structures. Written by J. Tarbell "
+"and Mike Kershaw; 2004."
 msgstr ""
 
-#: hacks/config/xearth.xml.h:14
-msgid "Night   Dim"
+#: ../hacks/config/superquadrics.xml.h:1
+msgid "Superquadrics"
 msgstr ""
 
-#: hacks/config/xearth.xml.h:15
-msgid "No Stars"
-msgstr ""
+#: ../hacks/config/superquadrics.xml.h:6
+msgid "Spin speed"
+msgstr "Скорость вращения"
 
-#: hacks/config/xearth.xml.h:16
-msgid "North/South Rotation"
+#: ../hacks/config/superquadrics.xml.h:14
+msgid "Morphing 3D shapes. Written by Ed Mackey; 1987, 1997."
 msgstr ""
 
-#: hacks/config/xearth.xml.h:18 hacks/config/xplanet.xml.h:53
-msgid "Orthographic Projection"
+#: ../hacks/config/surfaces.xml.h:1
+msgid "Surfaces"
 msgstr ""
 
-#: hacks/config/xearth.xml.h:19 hacks/config/xplanet.xml.h:56
-msgid "Real Time"
-msgstr ""
+#: ../hacks/config/surfaces.xml.h:8
+msgid "Random Surface"
+msgstr "Случайная поверхность"
 
-#: hacks/config/xearth.xml.h:20
-msgid "Shaded Image"
-msgstr ""
+#: ../hacks/config/surfaces.xml.h:9
+msgid "Dini's Surface"
+msgstr "Поверхность Дини"
 
-#: hacks/config/xearth.xml.h:21
-msgid "Sharp"
-msgstr ""
+#: ../hacks/config/surfaces.xml.h:10
+msgid "Enneper's Surface"
+msgstr "Поверхность Эннепера"
 
-#: hacks/config/xearth.xml.h:26
-msgid "Terminator   Blurry"
-msgstr ""
+#: ../hacks/config/surfaces.xml.h:11
+msgid "Kuen Surface"
+msgstr "Поверхность Куэна"
 
-#: hacks/config/xearth.xml.h:27 hacks/config/xplanet.xml.h:61
-msgid "Time Warp"
-msgstr ""
+#: ../hacks/config/surfaces.xml.h:12
+msgid "Moebius Strip"
+msgstr "Петля Мебиуса"
 
-#: hacks/config/xearth.xml.h:29 hacks/config/xplanet.xml.h:62
-msgid "Upper Left"
-msgstr ""
+#: ../hacks/config/surfaces.xml.h:13
+msgid "Seashell"
+msgstr "Ракушка"
 
-#: hacks/config/xearth.xml.h:30 hacks/config/xplanet.xml.h:63
-msgid "Upper Right"
-msgstr ""
+#: ../hacks/config/surfaces.xml.h:14
+msgid "Swallowtail"
+msgstr "Парусник"
 
-#: hacks/config/xearth.xml.h:31
-msgid ""
-"XEarth draws an image of the Earth, as seen from your favorite vantage point "
-"in space, correctly shaded for the current position of the Sun. Written by "
-"Kirk Johnson. This is not included with the XScreenSaver package, but if you "
-"don't have it already, you can find it at &lt;http://www.cs.colorado.edu/"
-"~tuna/xearth/&gt;. There is also a similar (but more recent) program called "
-"xplanet to be found at &lt;http://xplanet.sourceforge.net/&gt;."
-msgstr ""
+#: ../hacks/config/surfaces.xml.h:15
+msgid "Bohemian Dome"
+msgstr "Купол Богемии"
 
-#: hacks/config/xearth.xml.h:32
-msgid "Xearth"
-msgstr ""
+#: ../hacks/config/surfaces.xml.h:16
+msgid "Whitney Umbrella"
+msgstr "Зонтик Уитни"
 
-#: hacks/config/xfishtank.xml.h:5
-msgid "Fish"
-msgstr ""
+#: ../hacks/config/surfaces.xml.h:17
+msgid "Pluecker's Conoid"
+msgstr "Коноид Плюккера"
 
-#: hacks/config/xfishtank.xml.h:6
-msgid "Fish Speed"
-msgstr ""
+#: ../hacks/config/surfaces.xml.h:18
+msgid "Henneberg's Surface"
+msgstr "Поверхность Геннеберга"
 
-#: hacks/config/xfishtank.xml.h:7
-msgid ""
-"Fish! This is not included with the XScreenSaver package, but if you don't "
-"have it already, you can find it at &lt;http://metalab.unc.edu/pub/Linux/X11/"
-"demos/&gt;."
-msgstr ""
+#: ../hacks/config/surfaces.xml.h:19
+msgid "Catalan's Surface"
+msgstr "Поверхность Каталана"
 
-#: hacks/config/xfishtank.xml.h:12
-msgid "XFishTank"
-msgstr ""
+#: ../hacks/config/surfaces.xml.h:20
+msgid "Corkscrew Surface"
+msgstr "Поверхность штопора"
 
-#: hacks/config/xflame.xml.h:1
-msgid "Bitmap File"
-msgstr ""
+#: ../hacks/config/surfaces.xml.h:21
+msgid "Random Display Mode"
+msgstr "Случайный режим отображения"
 
-#: hacks/config/xflame.xml.h:2
+#: ../hacks/config/surfaces.xml.h:24
+msgid "Line Loops"
+msgstr "Замкнутые линии"
+
+#: ../hacks/config/surfaces.xml.h:28
 msgid ""
-"Draws a simulation of pulsing fire. It can also take an arbitrary image and "
-"set it on fire too. Written by Carsten Haitzler, hacked on by many others."
+"Parametric surfaces. http://mathworld.wolfram.com/DinisSurface.html https://"
+"en.wikipedia.org/wiki/Enneper_surface http://mathworld.wolfram.com/"
+"EnnepersMinimalSurface.html http://mathworld.wolfram.com/KuenSurface.html "
+"https://en.wikipedia.org/wiki/Moebius_strip http://mathworld.wolfram.com/"
+"Seashell.html http://mathworld.wolfram.com/SwallowtailCatastrophe.html "
+"http://mathworld.wolfram.com/BohemianDome.html https://en.wikipedia.org/wiki/"
+"Whitney_umbrella http://mathworld.wolfram.com/PlueckersConoid.html http://"
+"mathworld.wolfram.com/HennebergsMinimalSurface.html http://mathworld.wolfram."
+"com/CatalansSurface.html http://mathworld.wolfram.com/CorkscrewSurface.html "
+"Written by Andrey Mirtchovski and Carsten Steger; 2003."
 msgstr ""
 
-#: hacks/config/xflame.xml.h:3
-msgid "Enable Blooming"
-msgstr "Разрешить вспышки"
-
-#: hacks/config/xflame.xml.h:8
-msgid "Xflame"
+#: ../hacks/config/swirl.xml.h:1
+msgid "Swirl"
 msgstr ""
 
-#: hacks/config/xjack.xml.h:4
-msgid ""
-"This program behaves schizophrenically and makes a lot of typos. Written by "
-"Jamie Zawinski. If you haven't seen Stanley Kubrick's masterpiece, ``The "
-"Shining,'' you won't get it. Those who have describe this hack as "
-"``inspired.''"
+#: ../hacks/config/swirl.xml.h:12
+msgid "Flowing, swirly patterns. Written by M. Dobie and R. Taylor; 1997."
 msgstr ""
 
-#: hacks/config/xjack.xml.h:5
-msgid "Xjack"
+#: ../hacks/config/t3d.xml.h:1
+msgid "T3D"
 msgstr ""
 
-#: hacks/config/xlyap.xml.h:1
-msgid ""
-"This generates pretty fractal pictures by doing funky math involving the "
-"``Lyapunov exponent.'' It has a cool interactive mode, too. Written by Ron "
-"Record."
+#: ../hacks/config/t3d.xml.h:6
+msgid "Turn side-to-side"
 msgstr ""
 
-#: hacks/config/xlyap.xml.h:2
-msgid "Xlyap"
+#: ../hacks/config/t3d.xml.h:8
+msgid "Wobbliness"
 msgstr ""
 
-#: hacks/config/xmatrix.xml.h:3
-msgid ""
-"Draws dropping characters similar to what is seen on the computer monitors "
-"in \"The Matrix\". See also \"glmatrix\" for a 3D rendering of the similar "
-"effect that appeared in the title sequence of the movie. Written by Jamie "
-"Zawinski."
+#: ../hacks/config/t3d.xml.h:9
+msgid "Cycle seconds"
 msgstr ""
 
-#: hacks/config/xmatrix.xml.h:4
-msgid "Expansion Algorithm"
+#: ../hacks/config/t3d.xml.h:10
+msgid "Smaller"
 msgstr ""
 
-#: hacks/config/xmatrix.xml.h:6
-msgid "Full"
+#: ../hacks/config/t3d.xml.h:12
+msgid "Bigger"
 msgstr ""
 
-#: hacks/config/xmatrix.xml.h:9
-msgid "Knock Knock"
+#: ../hacks/config/t3d.xml.h:13
+msgid "Minute tick marks"
 msgstr ""
 
-#: hacks/config/xmatrix.xml.h:12
-msgid "Phone Number"
+#: ../hacks/config/t3d.xml.h:14
+msgid "5 minute tick marks"
 msgstr ""
 
-#: hacks/config/xmatrix.xml.h:13
-msgid "Run Trace Program"
+#: ../hacks/config/t3d.xml.h:16
+msgid ""
+"This screen saver was removed from the XScreenSaver distribution as of "
+"version 5.08. Draws a working analog clock composed of floating, throbbing "
+"bubbles. Written by Bernd Paysan; 1999."
 msgstr ""
 
-#: hacks/config/xmatrix.xml.h:14
-msgid "Slider Algorithm"
+#: ../hacks/config/tangram.xml.h:1
+msgid "Tangram"
 msgstr ""
 
-#: hacks/config/xmatrix.xml.h:19
-msgid "Synergistic Algorithm"
-msgstr ""
+#: ../hacks/config/tangram.xml.h:9
+msgid "X rotation"
+msgstr "Поворот X"
 
-#: hacks/config/xmatrix.xml.h:20
-msgid "Xmatrix"
-msgstr ""
+#: ../hacks/config/tangram.xml.h:11
+msgid "Y rotation"
+msgstr "Поворот Y"
 
-#: hacks/config/xmountains.xml.h:1
-#, fuzzy
-msgid "1.0"
-msgstr "100%"
+#: ../hacks/config/tangram.xml.h:12
+msgid "Z rotation"
+msgstr "Поворот Z"
 
-#: hacks/config/xmountains.xml.h:3
-msgid "14"
+#: ../hacks/config/tangram.xml.h:17
+msgid ""
+"Solves tangram puzzles. https://en.wikipedia.org/wiki/Tangram Written by "
+"Jeremy English; 2005."
 msgstr ""
 
-#: hacks/config/xmountains.xml.h:4
-msgid "7"
+#: ../hacks/config/tessellimage.xml.h:1
+msgid "Tessellimage"
 msgstr ""
 
-#: hacks/config/xmountains.xml.h:5
-msgid "Altitude  Low"
-msgstr ""
+#: ../hacks/config/tessellimage.xml.h:5
+msgid "0.1 second"
+msgstr "0.1 секунды"
 
-#: hacks/config/xmountains.xml.h:6
-msgid "Ambient  Low"
-msgstr ""
+#: ../hacks/config/tessellimage.xml.h:7
+msgid "4 seconds"
+msgstr "4 секунды"
 
-#: hacks/config/xmountains.xml.h:7
-msgid "Angle of Light"
-msgstr ""
+#: ../hacks/config/tessellimage.xml.h:15
+msgid "Outline triangles"
+msgstr "Обводить треугольники"
 
-#: hacks/config/xmountains.xml.h:8
-msgid "Contour  Low"
+#: ../hacks/config/tessellimage.xml.h:17
+msgid ""
+"Converts an image to triangles using Delaunay tessellation, and animates the "
+"result at various depths. More triangles are allocated to visually complex "
+"parts of the image. This is accomplished by first computing the first "
+"derivative of the image: the distance between each pixel and its neighbors "
+"(which is essentially edge detection or embossing). Then the Delaunay "
+"control points are chosen by selecting those pixels whose distance value is "
+"above a certain threshold: those are the pixels that have the largest change "
+"in color/brightness. https://en.wikipedia.org/wiki/Delaunay_triangulation "
+"Written by Jamie Zawinski; 2014."
 msgstr ""
 
-#: hacks/config/xmountains.xml.h:9
-msgid "Contrast  Low"
+#: ../hacks/config/testx11.xml.h:1
+msgid "TestX11"
 msgstr ""
 
-#: hacks/config/xmountains.xml.h:10
-#, fuzzy
-msgid "Craggy"
-msgstr "Gray"
-
-#: hacks/config/xmountains.xml.h:11
-msgid "Cross Update"
+#: ../hacks/config/testx11.xml.h:3
+msgid ""
+"Test platform for JWXYZ - the X11 compatibility shim for OS X and iOS. End "
+"users shouldn't normally see this one. Written by Dave Odell; 2015."
 msgstr ""
 
-#: hacks/config/xmountains.xml.h:12
-msgid "Distance  Low"
+#: ../hacks/config/thornbird.xml.h:1
+msgid "Thornbird"
 msgstr ""
 
-#: hacks/config/xmountains.xml.h:14
-msgid "Foreground"
+#: ../hacks/config/thornbird.xml.h:17
+msgid ""
+"Displays a view of the \"Bird in a Thornbush\" fractal. Written by Tim "
+"Auckland; 2002."
 msgstr ""
 
-#: hacks/config/xmountains.xml.h:15
-msgid "Fractal Options"
+#: ../hacks/config/timetunnel.xml.h:1
+msgid "TimeTunnel"
 msgstr ""
 
-#: hacks/config/xmountains.xml.h:16
-msgid "Height  Low"
-msgstr ""
+#: ../hacks/config/timetunnel.xml.h:2
+msgid "0 sec"
+msgstr "0 секунд"
 
-#: hacks/config/xmountains.xml.h:18
-msgid "Horizontal  Low"
-msgstr ""
+#: ../hacks/config/timetunnel.xml.h:3
+msgid "Start sequence time"
+msgstr "Время начальной последовательности"
 
-#: hacks/config/xmountains.xml.h:19
-#, fuzzy
-msgid "Iteration  0"
-msgstr "Продолжительность перехода"
+#: ../hacks/config/timetunnel.xml.h:5
+msgid "End sequence time"
+msgstr "Время конечной последовательности"
 
-#: hacks/config/xmountains.xml.h:20
-msgid "Light Level"
-msgstr ""
+#: ../hacks/config/timetunnel.xml.h:6
+msgid "Draw logo"
+msgstr "Прорисовывать логотип"
 
-#: hacks/config/xmountains.xml.h:21
-msgid "Recursion  0"
-msgstr ""
+#: ../hacks/config/timetunnel.xml.h:7
+msgid "Run backward"
+msgstr "Запускать в обратном порядке"
 
-#: hacks/config/xmountains.xml.h:22
-msgid "Reflections"
+#: ../hacks/config/timetunnel.xml.h:9
+msgid ""
+"An animation similar to the title sequence of Dr. Who in the 70s. Written by "
+"Sean P. Brennan; 2005."
 msgstr ""
 
-#: hacks/config/xmountains.xml.h:23
-msgid "Sea Level  Low"
+#: ../hacks/config/topblock.xml.h:1
+msgid "TopBlock"
 msgstr ""
 
-#: hacks/config/xmountains.xml.h:24
-msgid "Side View"
-msgstr ""
+#: ../hacks/config/topblock.xml.h:6
+msgid "Drop speed"
+msgstr "Скорость падения"
 
-#: hacks/config/xmountains.xml.h:26
-msgid "Smoothing  0"
-msgstr ""
+#: ../hacks/config/topblock.xml.h:9
+msgid "Carpet size"
+msgstr "Размер фундамента"
 
-#: hacks/config/xmountains.xml.h:27
-#, fuzzy
-msgid "Speed  Slow"
-msgstr "Скорость"
+#: ../hacks/config/topblock.xml.h:11
+msgid "Spawn likelyhood"
+msgstr "Вероятность появления"
 
-#: hacks/config/xmountains.xml.h:28
-msgid "Terrain"
-msgstr ""
+#: ../hacks/config/topblock.xml.h:12
+msgid "Polygon count"
+msgstr "Количество полигонов"
 
-#: hacks/config/xmountains.xml.h:29
-msgid "Top View"
-msgstr ""
+#: ../hacks/config/topblock.xml.h:18
+msgid "Follow"
+msgstr "Следовать"
 
-#: hacks/config/xmountains.xml.h:30
-msgid "V. Shift  Low"
-msgstr ""
+#: ../hacks/config/topblock.xml.h:19
+msgid "Blob mode"
+msgstr "Режим сгустков"
 
-#: hacks/config/xmountains.xml.h:31
-msgid "V. Stretch  Low"
-msgstr ""
+#: ../hacks/config/topblock.xml.h:20
+msgid "Tunnel mode"
+msgstr "Режим туннеля"
 
-#: hacks/config/xmountains.xml.h:32
-msgid "Variance  Low"
-msgstr ""
+#: ../hacks/config/topblock.xml.h:21
+msgid "Carpet"
+msgstr "Фундамент"
 
-#: hacks/config/xmountains.xml.h:33
-msgid "Vertical  Low"
+#: ../hacks/config/topblock.xml.h:22
+msgid "Nipples"
+msgstr "Бугорки"
+
+#: ../hacks/config/topblock.xml.h:25
+msgid ""
+"Creates a 3D world with dropping blocks that build up and up. Written by "
+"rednuht; 2006."
 msgstr ""
 
-#: hacks/config/xmountains.xml.h:34
-msgid "Viewpoint"
+#: ../hacks/config/triangle.xml.h:1
+msgid "Triangle"
 msgstr ""
 
-#: hacks/config/xmountains.xml.h:35
+#: ../hacks/config/triangle.xml.h:9
 msgid ""
-"XMountains generates realistic-looking fractal terrains of snow-capped "
-"mountains near water, with either a top view or a side view. Written by "
-"Stephen Booth. This is not included with the XScreenSaver package, but if "
-"you don't have it already, you can find it at &lt;http://www.epcc.ed.ac.uk/"
-"~spb/xmountains/&gt;. (Make sure you have version 2.7 or newer!)"
+"Generates random mountain ranges using iterative subdivision of triangles. "
+"Written by Tobias Gloth; 1997."
 msgstr ""
 
-#: hacks/config/xmountains.xml.h:36
-msgid "Xf  0.0"
+#: ../hacks/config/tronbit.xml.h:1
+msgid "TronBit"
 msgstr ""
 
-#: hacks/config/xmountains.xml.h:37
-msgid "Xmountains"
+#: ../hacks/config/tronbit.xml.h:12
+msgid ""
+"The character \"Bit\" from the film, \"Tron\". The \"yes\" state is a "
+"tetrahedron; the \"no\" state is the second stellation of an icosahedron; "
+"and the idle state oscillates between a small triambic icosahedron and the "
+"compound of an icosahedron and a dodecahedron. https://en.wikipedia.org/wiki/"
+"List_of_Tron_characters#Bit https://en.wikipedia.org/wiki/Uniform_polyhedra "
+"https://en.wikipedia.org/wiki/Stellation Written by Jamie Zawinski; 2011."
 msgstr ""
 
-#: hacks/config/xmountains.xml.h:38
-msgid "Yf  0.0"
+#: ../hacks/config/truchet.xml.h:1
+msgid "Truchet"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:5
-msgid "Ancient Projection"
+#: ../hacks/config/truchet.xml.h:7
+msgid ""
+"Line- and arc-based truchet patterns that tile the screen. https://en."
+"wikipedia.org/wiki/Tessellation Written by Adrian Likins; 1998."
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:6
-msgid "Azimuthal Projection"
+#: ../hacks/config/twang.xml.h:1
+msgid "Twang"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:9
-msgid "From Ariel"
-msgstr ""
+#: ../hacks/config/twang.xml.h:10
+msgid "Jumpy"
+msgstr "Хаотичная"
 
-#: hacks/config/xplanet.xml.h:10
-msgid "From Callisto"
-msgstr ""
+#: ../hacks/config/twang.xml.h:12
+msgid "Springiness"
+msgstr "Эластичность"
 
-#: hacks/config/xplanet.xml.h:11
-msgid "From Charon"
-msgstr ""
+#: ../hacks/config/twang.xml.h:13
+msgid "Transference"
+msgstr "Перемещение"
 
-#: hacks/config/xplanet.xml.h:12
-msgid "From Deimos"
-msgstr ""
+#: ../hacks/config/twang.xml.h:17
+msgid "Border width"
+msgstr "Толщина границы"
 
-#: hacks/config/xplanet.xml.h:13
-msgid "From Dione"
+#: ../hacks/config/twang.xml.h:19
+msgid ""
+"Divides the screen into a grid, and plucks them. Written by Dan Bornstein; "
+"2002."
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:14
-msgid "From Earth"
+#: ../hacks/config/unicrud.xml.h:1
+msgid "Unicrud"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:15
-msgid "From Enceladus"
-msgstr ""
+#: ../hacks/config/unicrud.xml.h:12
+msgid "Display everything"
+msgstr "Показывать все"
 
-#: hacks/config/xplanet.xml.h:16
-msgid "From Europa"
-msgstr ""
+#: ../hacks/config/unicrud.xml.h:13
+msgid "Display Latin1"
+msgstr "Показывать Latin1"
 
-#: hacks/config/xplanet.xml.h:17
-msgid "From Ganymede"
-msgstr ""
+#: ../hacks/config/unicrud.xml.h:14
+msgid "Display simple characters"
+msgstr "Показывать простые символы"
 
-#: hacks/config/xplanet.xml.h:18
-msgid "From Hyperion"
-msgstr ""
+#: ../hacks/config/unicrud.xml.h:15
+msgid "Display mathematical symbols"
+msgstr "Показывать математические символы"
 
-#: hacks/config/xplanet.xml.h:19
-msgid "From Iapetus"
-msgstr ""
+#: ../hacks/config/unicrud.xml.h:16
+msgid "Display emoticons"
+msgstr "Показывать смайлики"
 
-#: hacks/config/xplanet.xml.h:20
-msgid "From Io"
-msgstr ""
+#: ../hacks/config/unicrud.xml.h:17
+msgid "Display hieroglyphs"
+msgstr "Показывать иероглифы"
 
-#: hacks/config/xplanet.xml.h:21
-msgid "From Jupiter"
+#: ../hacks/config/unicrud.xml.h:18
+msgid ""
+"Chooses a random Unicode character and displays it full screen, along with "
+"some information about it. https://en.wikipedia.org/wiki/Unicode Written by "
+"Jamie Zawinski; 2016."
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:22
-msgid "From Major"
+#: ../hacks/config/unknownpleasures.xml.h:1
+msgid "UnknownPleasures"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:23
-msgid "From Mars"
-msgstr ""
+#: ../hacks/config/unknownpleasures.xml.h:12
+msgid "Orthographic Projection"
+msgstr "Ортографическая проекция"
 
-#: hacks/config/xplanet.xml.h:24
-msgid "From Mercury"
+#: ../hacks/config/unknownpleasures.xml.h:16
+#, no-c-format
+msgid ""
+"PSR B1919+21 (AKA CP 1919) was the first pulsar ever discovered: a spinning "
+"neutron star emitting a periodic lighthouse-like beacon. An illustration of "
+"the signal received from it was published in Scientific American in 1971, "
+"and later in The Cambridge Encyclopedia of Astronomy in 1977, where it was "
+"seen by Stephen Morris, the drummer of Joy Division, and was consequently "
+"appropriated by Peter Saville for the cover of the band's album \"Unknown "
+"Pleasures\". https://en.wikipedia.org/wiki/Pulsar https://en.wikipedia.org/"
+"wiki/PSR_B1919%2B21 https://en.wikipedia.org/wiki/Unknown_Pleasures https://"
+"en.wikipedia.org/wiki/Peter_Saville_%28graphic_designer%29 https://en."
+"wikipedia.org/wiki/Joy_Division Written by Jamie Zawinski; 2013."
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:25
-msgid "From Mimas"
+#: ../hacks/config/vermiculate.xml.h:1
+msgid "Vermiculate"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:26
-msgid "From Miranda"
+#: ../hacks/config/vermiculate.xml.h:6
+msgid "Squiggly worm-like paths. Written by Tyler Pierce; 2001."
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:27
-msgid "From Moon"
+#: ../hacks/config/vidwhacker.xml.h:1
+msgid "VidWhacker"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:28
-msgid "From Neptune"
-msgstr ""
+#: ../hacks/config/vidwhacker.xml.h:2
+msgid "2 seconds"
+msgstr "2 секунды"
 
-#: hacks/config/xplanet.xml.h:29
-msgid "From Nereid"
-msgstr ""
+#: ../hacks/config/vidwhacker.xml.h:5
+msgid "Image directory"
+msgstr "Папка с изображениями"
 
-#: hacks/config/xplanet.xml.h:30
-msgid "From Oberon"
+#: ../hacks/config/vidwhacker.xml.h:7
+msgid ""
+"Displays a distorted frame video. This is a shell script that grabs a frame "
+"of video from the system's video input, and then uses some PBM filters "
+"(chosen at random) to manipulate and recombine the video frame in various "
+"ways (edge detection, subtracting the image from a rotated version of "
+"itself, etc.) Then it displays that image for a few seconds, and does it "
+"again. This works really well if you just feed broadcast television into it. "
+"Written by Jamie Zawinski; 1998."
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:31
-msgid "From Phobos"
+#: ../hacks/config/vigilance.xml.h:1
+msgid "Vigilance"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:32
-msgid "From Phoebe"
-msgstr ""
+#: ../hacks/config/vigilance.xml.h:9
+msgid "Number of cameras"
+msgstr "Количество камер"
 
-#: hacks/config/xplanet.xml.h:33
-msgid "From Pluto"
+#: ../hacks/config/vigilance.xml.h:11
+msgid ""
+"Security cameras keep careful track of their surroundings. You can trust "
+"them. Everything is completely under control. Written by Jamie Zawinski; "
+"2017."
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:34
-msgid "From Random"
+#: ../hacks/config/vines.xml.h:1
+msgid "Vines"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:35
-msgid "From Rhea"
+#: ../hacks/config/vines.xml.h:9
+msgid ""
+"This screen saver was removed from the XScreenSaver distribution as of "
+"version 5.08. Generates a continuous sequence of small, curvy geometric "
+"patterns. Written by Tracy Camp and David Hansen; 1997."
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:36
-msgid "From Saturn"
+#: ../hacks/config/voronoi.xml.h:1
+msgid "Voronoi"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:37
-msgid "From Sun"
-msgstr ""
+#: ../hacks/config/voronoi.xml.h:10
+msgid "50 pixels"
+msgstr "50 пикселей"
 
-#: hacks/config/xplanet.xml.h:38
-msgid "From Tethys"
-msgstr ""
+#: ../hacks/config/voronoi.xml.h:13
+msgid "Insertion speed"
+msgstr "Скорость вставки"
 
-#: hacks/config/xplanet.xml.h:39
-msgid "From Titan"
-msgstr ""
+#: ../hacks/config/voronoi.xml.h:14
+msgid "Zoom speed"
+msgstr "Скорость масштабирования"
 
-#: hacks/config/xplanet.xml.h:40
-msgid "From Titania"
-msgstr ""
+#: ../hacks/config/voronoi.xml.h:15
+msgid "Zoom frequency"
+msgstr "Частота масштабирования"
 
-#: hacks/config/xplanet.xml.h:41
-msgid "From Triton"
+#: ../hacks/config/voronoi.xml.h:17
+msgid ""
+"A Voronoi tessellation. Periodically zooms in and adds new points. The "
+"existing points also wander around. There are a set of control points on the "
+"plane, each at the center of a colored cell. Every pixel within that cell is "
+"closer to that cell's control point than to any other control point. That is "
+"what determines the cell's shapes. https://en.wikipedia.org/wiki/"
+"Voronoi_diagram https://en.wikipedia.org/wiki/Tessellation Written by Jamie "
+"Zawinski; 2007."
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:42
-msgid "From Umbriel"
-msgstr ""
+#: ../hacks/config/wander.xml.h:11
+msgid "Draw spots"
+msgstr "Прорисовывать точки"
 
-#: hacks/config/xplanet.xml.h:43
-msgid "From Uranus"
+#: ../hacks/config/wander.xml.h:14
+msgid ""
+"A colorful random-walk. https://en.wikipedia.org/wiki/Random_walk Written by "
+"Rick Campbell; 1999."
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:44
-msgid "From Venus"
+#: ../hacks/config/webcollage.xml.h:1
+msgid "WebCollage"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:45
-msgid "Hemisphere Projection"
-msgstr ""
+#: ../hacks/config/webcollage.xml.h:3
+msgid "Delay between images"
+msgstr "Задержка между изображениями"
 
-#: hacks/config/xplanet.xml.h:46
-msgid "Lambert Projection"
-msgstr ""
+#: ../hacks/config/webcollage.xml.h:4
+msgid "30 secs"
+msgstr "30 секунд"
 
-#: hacks/config/xplanet.xml.h:47
-msgid "Latitude"
-msgstr ""
+#: ../hacks/config/webcollage.xml.h:5
+msgid "2 secs"
+msgstr "2 секунды"
 
-#: hacks/config/xplanet.xml.h:48
-#, fuzzy
-msgid "Longitude"
-msgstr "Длинный"
+#: ../hacks/config/webcollage.xml.h:6
+msgid "Network timeout"
+msgstr "Тайм-аут сети"
 
-#: hacks/config/xplanet.xml.h:52
-msgid "Mollweide Projection"
-msgstr ""
+#: ../hacks/config/webcollage.xml.h:7
+msgid "2 min"
+msgstr "2 минуты"
 
-#: hacks/config/xplanet.xml.h:54
-msgid "Peters Projection"
-msgstr ""
+#: ../hacks/config/webcollage.xml.h:9
+msgid "Image opacity"
+msgstr "Прозрачность изображений"
 
-#: hacks/config/xplanet.xml.h:57
-msgid "Rectangular Projection"
+#: ../hacks/config/webcollage.xml.h:12
+msgid ""
+"This is what the Internet looks like. This creates collages out of random "
+"images from the World Wide Web. It finds the images by feeding random words "
+"into various search engines, and pulling images (or sections of images) out "
+"of the pages returned. WARNING: THE INTERNET SOMETIMES CONTAINS PORNOGRAPHY. "
+"The Internet being what it is, absolutely anything might show up in the "
+"collage including -- quite possibly -- pornography, or even nudity. Please "
+"act accordingly. See also https://www.jwz.org/webcollage/ Written by Jamie "
+"Zawinski; 1999."
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:58
-msgid "Render as a Globe"
+#: ../hacks/config/whirlwindwarp.xml.h:1
+msgid "WhirlWindWarp"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:64
-msgid "View Ariel"
-msgstr ""
+#: ../hacks/config/whirlwindwarp.xml.h:6
+msgid "Trail size"
+msgstr "Длина следа"
 
-#: hacks/config/xplanet.xml.h:65
-msgid "View Callisto"
+#: ../hacks/config/whirlwindwarp.xml.h:9
+msgid ""
+"Floating stars are acted upon by a mixture of simple 2D force fields. The "
+"strength of each force field changes continuously, and it is also switched "
+"on and off at random. Written by Paul 'Joey' Clark; 2001."
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:66
-msgid "View Charon"
+#: ../hacks/config/whirlygig.xml.h:1
+msgid "Whirlygig"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:67
-msgid "View Deimos"
+#: ../hacks/config/whirlygig.xml.h:2
+msgid "Whirlies"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:68
-msgid "View Dione"
+#: ../hacks/config/whirlygig.xml.h:5
+msgid "X speed"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:69
-msgid "View Earth"
+#: ../hacks/config/whirlygig.xml.h:7
+msgid "Y speed"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:70
-msgid "View Enceladus"
+#: ../hacks/config/whirlygig.xml.h:8
+msgid "X amplitude"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:71
-msgid "View Europa"
+#: ../hacks/config/whirlygig.xml.h:9
+msgid "Y amplitude"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:72
-msgid "View Ganymede"
+#: ../hacks/config/whirlygig.xml.h:10
+msgid "X random"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:73
-msgid "View Hyperion"
+#: ../hacks/config/whirlygig.xml.h:11
+msgid "X spin"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:74
-msgid "View Iapetus"
+#: ../hacks/config/whirlygig.xml.h:12
+msgid "X funky"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:75
-msgid "View Io"
+#: ../hacks/config/whirlygig.xml.h:13
+msgid "X circle"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:76
-msgid "View Jupiter"
+#: ../hacks/config/whirlygig.xml.h:14
+msgid "X linear"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:77
-msgid "View Major"
+#: ../hacks/config/whirlygig.xml.h:15
+msgid "X test"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:78
-msgid "View Mars"
+#: ../hacks/config/whirlygig.xml.h:16
+msgid "X fun"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:79
-msgid "View Mercury"
+#: ../hacks/config/whirlygig.xml.h:17
+msgid "X innie"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:80
-msgid "View Mimas"
+#: ../hacks/config/whirlygig.xml.h:18
+msgid "X lissajous"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:81
-msgid "View Miranda"
+#: ../hacks/config/whirlygig.xml.h:19
+msgid "Y random"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:82
-msgid "View Moon"
+#: ../hacks/config/whirlygig.xml.h:20
+msgid "Y spin"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:83
-msgid "View Neptune"
+#: ../hacks/config/whirlygig.xml.h:21
+msgid "Y funky"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:84
-msgid "View Nereid"
+#: ../hacks/config/whirlygig.xml.h:22
+msgid "Y circle"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:85
-msgid "View Oberon"
+#: ../hacks/config/whirlygig.xml.h:23
+msgid "Y linear"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:86
-msgid "View Phobos"
+#: ../hacks/config/whirlygig.xml.h:24
+msgid "Y test"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:87
-msgid "View Phoebe"
+#: ../hacks/config/whirlygig.xml.h:25
+msgid "Y fun"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:88
-msgid "View Pluto"
+#: ../hacks/config/whirlygig.xml.h:26
+msgid "Y innie"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:89
-msgid "View Random"
+#: ../hacks/config/whirlygig.xml.h:27
+msgid "Y lissajous"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:90
-msgid "View Rhea"
+#: ../hacks/config/whirlygig.xml.h:28
+msgid "Leave a trail"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:91
-msgid "View Saturn"
+#: ../hacks/config/whirlygig.xml.h:29
+msgid "Explain modes"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:92
-msgid "View Sun"
+#: ../hacks/config/whirlygig.xml.h:30
+msgid "Wrap the screen"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:93
-msgid "View Tethys"
+#: ../hacks/config/whirlygig.xml.h:32
+msgid ""
+"This screen saver was removed from the XScreenSaver distribution as of "
+"version 5.08. Zooming chains of sinusoidal spots. Written by Ashton Trey "
+"Belew; 2001."
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:94
-msgid "View Titan"
+#: ../hacks/config/winduprobot.xml.h:1
+msgid "WindupRobot"
 msgstr ""
 
-#: hacks/config/xplanet.xml.h:95
-msgid "View Titania"
-msgstr ""
+#: ../hacks/config/winduprobot.xml.h:6
+msgid "Robot speed"
+msgstr "Скорость роботов"
 
-#: hacks/config/xplanet.xml.h:96
-msgid "View Triton"
-msgstr ""
+#: ../hacks/config/winduprobot.xml.h:9
+msgid "Number of robots"
+msgstr "Количество роботов"
 
-#: hacks/config/xplanet.xml.h:97
-msgid "View Umbriel"
-msgstr ""
+#: ../hacks/config/winduprobot.xml.h:12
+msgid "Robot size"
+msgstr "Размер роботов"
 
-#: hacks/config/xplanet.xml.h:98
-msgid "View Uranus"
-msgstr ""
+#: ../hacks/config/winduprobot.xml.h:14
+msgid "Invisible"
+msgstr "Невидимый"
 
-#: hacks/config/xplanet.xml.h:99
-msgid "View Venus"
-msgstr ""
+#: ../hacks/config/winduprobot.xml.h:15
+msgid "Robot skin transparency"
+msgstr "Прозрачность корпуса роботов"
 
-#: hacks/config/xplanet.xml.h:100
-msgid "Xplanet"
-msgstr ""
+#: ../hacks/config/winduprobot.xml.h:17
+msgid "Never"
+msgstr "Никогда"
+
+#: ../hacks/config/winduprobot.xml.h:18
+msgid "Word bubbles"
+msgstr "Пузыри слов"
+
+#: ../hacks/config/winduprobot.xml.h:21
+msgid "Fade opacity"
+msgstr "Исчезающая прозрачность"
 
-#: hacks/config/xplanet.xml.h:101
+#: ../hacks/config/winduprobot.xml.h:23
 msgid ""
-"Xplanet draws an image of the Earth, as seen from your favorite vantage "
-"point in space, correctly shaded for the current position of the Sun. "
-"Written by Hari Nair. This is not included with the XScreenSaver package, "
-"but if you don't have it already, you can find it at &lt;http://xplanet."
-"sourceforge.net/&gt;."
+"A swarm of wind-up toy robots wander around the table-top, bumping into each "
+"other. Each robot contains a mechanically accurate gear system inside, which "
+"you can see when the robot's shell occasionally fades to transparency. Also, "
+"sometimes a cartoony word bubble pops up above a robot, full of random text. "
+"Written by Jamie Zawinski; 2014."
 msgstr ""
 
-#: hacks/config/xrayswarm.xml.h:1
+#: ../hacks/config/worm.xml.h:12
 msgid ""
-"Draws a few swarms of critters flying around the screen, with nicely faded "
-"color trails behind them. Written by Chris Leger."
+"This screen saver was removed from the XScreenSaver distribution as of "
+"version 5.08. Draws multicolored worms that crawl around the screen. Written "
+"by Brad Taylor, Dave Lemke, Boris Putanec, and Henrik Theiling; 1991."
 msgstr ""
 
-#: hacks/config/xrayswarm.xml.h:5
-msgid "XRaySwarm"
+#: ../hacks/config/wormhole.xml.h:1
+msgid "Wormhole"
 msgstr ""
 
-#: hacks/config/xsnow.xml.h:1
+#: ../hacks/config/wormhole.xml.h:6
+msgid "Star speed"
+msgstr "Скорость звезд"
+
+#: ../hacks/config/wormhole.xml.h:9
+msgid "Stars created"
+msgstr "Количество звезд"
+
+#: ../hacks/config/wormhole.xml.h:12
 msgid ""
-"Draws falling snow and the occasional tiny Santa. By Rick Jansen. You can "
-"find it at &lt;http://www.euronet.nl/~rja/Xsnow/&gt;."
+"Flying through a colored wormhole in space. Written by Jon Rafkind; 2004."
 msgstr ""
 
-#: hacks/config/xsnow.xml.h:2
-msgid "Xsnow"
+#: ../hacks/config/xanalogtv.xml.h:1
+msgid "XAnalogTV"
 msgstr ""
 
-#: hacks/config/xspirograph.xml.h:5
+#: ../hacks/config/xanalogtv.xml.h:9
 msgid ""
-"Simulates that pen-in-nested-plastic-gears toy from your childhood. By Rohit "
-"Singh."
+"An old TV set, including artifacts like snow, bloom, distortion, ghosting, "
+"and hash noise. It also simulates the TV warming up. It will cycle through "
+"12 channels, some with images you give it, and some with color bars or "
+"nothing but static. Written by Trevor Blackwell; 2003."
 msgstr ""
 
-#: hacks/config/xspirograph.xml.h:6
-msgid "XSpiroGraph"
+#: ../hacks/config/xflame.xml.h:1
+msgid "XFlame"
 msgstr ""
 
-#: hacks/config/xteevee.xml.h:1
-msgid "Color Bars Enabled"
-msgstr ""
+#. #### -vartrend [20]
+#: ../hacks/config/xflame.xml.h:6
+msgid "Enable blooming"
+msgstr "Разрешить вспышки"
 
-#: hacks/config/xteevee.xml.h:2
-msgid "Cycle Through Modes"
+#: ../hacks/config/xflame.xml.h:8
+msgid ""
+"Pulsing fire. It can also take an arbitrary image and set it on fire too. "
+"Written by Carsten Haitzler and many others; 1999."
 msgstr ""
 
-#: hacks/config/xteevee.xml.h:3
-msgid "Rolling Enabled"
+#: ../hacks/config/xjack.xml.h:1
+msgid "XJack"
 msgstr ""
 
-#: hacks/config/xteevee.xml.h:4
-msgid "Static Enabled"
+#: ../hacks/config/xjack.xml.h:7
+msgid ""
+"This behaves schizophrenically and makes a lot of typos. Written by Jamie "
+"Zawinski; 1997."
 msgstr ""
 
-#: hacks/config/xteevee.xml.h:5
-msgid "XTeeVee"
+#: ../hacks/config/xlyap.xml.h:1
+msgid "XLyap"
 msgstr ""
 
-#: hacks/config/xteevee.xml.h:6
+#: ../hacks/config/xlyap.xml.h:10
 msgid ""
-"XTeeVee simulates various television problems, including static, loss of "
-"vertical hold, and a test pattern. By Greg Knauss."
+"The Lyapunov exponent makes pretty fractal pictures. https://en.wikipedia."
+"org/wiki/Lyapunov_exponent Written by Ron Record; 1997."
 msgstr ""
 
-#: hacks/config/zoom.xml.h:3
-msgid "Lens Offset"
+#: ../hacks/config/xmatrix.xml.h:1
+msgid "XMatrix"
 msgstr ""
 
-#: hacks/config/zoom.xml.h:4
-msgid "Lenses"
-msgstr ""
+#: ../hacks/config/xmatrix.xml.h:2
+msgid "Small font"
+msgstr "Маленький шрифт"
 
-#: hacks/config/zoom.xml.h:9
-msgid ""
-"Zooms in on a part of the screen and then moves around. With the -lenses "
-"option the result is like looking through many overlapping lenses rather "
-"than just a simple zoom. Written by James Macnicol."
-msgstr ""
+#: ../hacks/config/xmatrix.xml.h:3
+msgid "Large font"
+msgstr "Большой шрифт"
+
+#: ../hacks/config/xmatrix.xml.h:8
+msgid "Piped ASCII text"
+msgstr "Линейный ASCII-текст"
+
+#: ../hacks/config/xmatrix.xml.h:9
+msgid "Synergistic algorithm"
+msgstr "Алгоритм синергии"
 
-#~ msgid "/\");"
-#~ msgstr "/\");"
+#: ../hacks/config/xmatrix.xml.h:10
+msgid "Slider algorithm"
+msgstr "Алгоритм скольжения"
 
-#~ msgid "Display Subprocess _Errors"
-#~ msgstr "Показывать ошибки подпроцессов"
+#: ../hacks/config/xmatrix.xml.h:11
+msgid "Expansion algorithm"
+msgstr "Алгоритм расширения"
 
-#~ msgid "Display _Splash Screen at Startup"
-#~ msgstr "Показывать окно-_заставку при запуске"
+#: ../hacks/config/xmatrix.xml.h:12
+msgid "Run trace program"
+msgstr "Запустить программу трассировки"
 
-#, fuzzy
-#~ msgid "_Verbose Diagnostics"
-#~ msgstr "Расширенная диагностика"
+#: ../hacks/config/xmatrix.xml.h:13
+msgid "Knock knock"
+msgstr "Тук-тук"
 
-#, fuzzy
-#~ msgid "Standalone"
-#~ msgstr "Стандартные"
+#: ../hacks/config/xmatrix.xml.h:14
+msgid "Phone number"
+msgstr "Номер телефона"
 
-#, fuzzy
-#~ msgid "Shoot"
-#~ msgstr "Короткий"
+#: ../hacks/config/xmatrix.xml.h:22
+msgid ""
+"The \"digital rain\" effect, as seen on the computer monitors in \"The Matrix"
+"\". See also \"GLMatrix\" for a 3D rendering of the similar effect that "
+"appeared in the movie's title sequence. https://en.wikipedia.org/wiki/"
+"Matrix_digital_rain Written by Jamie Zawinski; 1999."
+msgstr ""
+
+#: ../hacks/config/xrayswarm.xml.h:1
+msgid "XRaySwarm"
+msgstr ""
+
+#: ../hacks/config/xrayswarm.xml.h:6
+msgid ""
+"Worm-like swarms of particles with vapor trails. Written by Chris Leger; "
+"2000."
+msgstr ""
 
-#, fuzzy
-#~ msgid "Enable Background Image"
-#~ msgstr "Плоский фон"
+#: ../hacks/config/xspirograph.xml.h:1
+msgid "XSpirograph"
+msgstr ""
+
+#: ../hacks/config/xspirograph.xml.h:10
+msgid ""
+"Simulates that pen-in-nested-plastic-gears toy from your childhood. https://"
+"en.wikipedia.org/wiki/Spirograph Written by Rohit Singh; 2000."
+msgstr ""
 
-#, fuzzy
-#~ msgid "Linux"
-#~ msgstr "Sparc Linux"
+#: ../hacks/config/zoom.xml.h:8
+msgid "X mag"
+msgstr "Увеличение X"
 
-#~ msgid "Sparc Linux"
-#~ msgstr "Sparc Linux"
+#: ../hacks/config/zoom.xml.h:9
+msgid " X border"
+msgstr "   Граница X"
 
-#~ msgid "Checkered Balls"
-#~ msgstr "Пёстрые мячики"
+#: ../hacks/config/zoom.xml.h:10
+msgid "   X lens"
+msgstr "     Линза X"
 
-#~ msgid "Configure the settings of the screensaver."
-#~ msgstr "Настройка хранителя экрана."
+#: ../hacks/config/zoom.xml.h:11
+msgid "Y mag"
+msgstr "Увеличение Y"
 
-#~ msgid "Preview of screen saver"
-#~ msgstr "Предпросмотр хранителя экрана"
+#: ../hacks/config/zoom.xml.h:12
+msgid " Y border"
+msgstr "   Граница Y"
 
-#~ msgid "_Verbose Dialognostics"
-#~ msgstr "Расширенная диагностика"
+#: ../hacks/config/zoom.xml.h:13
+msgid "    Y lens"
+msgstr "     Линза Y"
 
-#, fuzzy
-#~ msgid "Sandpaper"
-#~ msgstr "Стандартные"
+#: ../hacks/config/zoom.xml.h:14
+msgid "Lenses"
+msgstr "Линзы"
+
+#: ../hacks/config/zoom.xml.h:16
+msgid ""
+"Fatbits! Zooms in on a part of the screen and then moves around. With the "
+"\"Lenses\" option, the result is like looking through many overlapping "
+"lenses rather than just a simple zoom. Written by James Macnicol; 2001."
+msgstr ""
index 05b213e2aec540a4fac553b57f2e4b0367b560a3..ce48db11a434f8ee6d6dba624a4e60327e3799d2 100644 (file)
@@ -731,7 +731,7 @@ eraser_draw (eraser_state *st, Bool first_p)
   return (st->ratio < 1.0);
 }
 
-static void
+void
 eraser_free (eraser_state *st)
 {
   XClearWindow (st->dpy, st->window);
index 0279272865ef4dc093667dec10dfb3d43e54bc46..1e720f91c10e18b31c894073621e4db1af15cd63 100644 (file)
@@ -15,6 +15,7 @@
 
 typedef struct eraser_state eraser_state;
 
+extern void eraser_free (eraser_state *st);
 extern eraser_state *erase_window (Display *, Window, eraser_state *);
 
 #endif /* __XSCREENSAVER_ERASE_H__ */
index 9dbbf2fafced6c0e20d4d469234b0f0e27675520..10fc98ac38b7fb180a19461bb72be7d1a2930fda 100644 (file)
@@ -1,2 +1,2 @@
 static const char screensaver_id[] =
-       "@(#)xscreensaver 5.37 (05-Jul-2017), by Jamie Zawinski (jwz@jwz.org)";
+       "@(#)xscreensaver 5.38 (20-Dec-2017), by Jamie Zawinski (jwz@jwz.org)";
index 0c933b3b4185cc68678ba8aba4ab8be87973e429..bdfbdb43e750d0850e41f8a80b26f72190151939 100644 (file)
@@ -198,12 +198,12 @@ XftColorAllocValue (Display *dpy,
       int green_shift, green_len;
       int blue_shift, blue_len;
 
-      red_shift   = maskbase (visual->red_mask);
-      red_len     = masklen  (visual->red_mask);
-      green_shift = maskbase (visual->green_mask);
-      green_len   = masklen (visual->green_mask);
-      blue_shift  = maskbase (visual->blue_mask);
-      blue_len    = masklen (visual->blue_mask);
+      red_shift   = maskbase (visual->rgba_masks[0]);
+      red_len     = masklen  (visual->rgba_masks[0]);
+      green_shift = maskbase (visual->rgba_masks[1]);
+      green_len   = masklen (visual->rgba_masks[1]);
+      blue_shift  = maskbase (visual->rgba_masks[2]);
+      blue_len    = masklen (visual->rgba_masks[2]);
       result->pixel = (((color->red   >> (16 - red_len))   << red_shift)   |
                        ((color->green >> (16 - green_len)) << green_shift) |
                        ((color->blue  >> (16 - blue_len))  << blue_shift));
index 858e71f4c6380e9de60bc0745d29a1754c7b277b..e01bc8ffb368b51d1b100f07685a157c76146009 100644 (file)
@@ -1,5 +1,5 @@
 %define        name xscreensaver
-%define        version 5.37
+%define        version 5.38
 
 Summary:       X screen saver and locker
 Name:          %{name}