From http://www.jwz.org/xscreensaver/xscreensaver-5.35.tar.gz
authorZygo Blaxell <zblaxell@faye.furryterror.org>
Mon, 17 Oct 2016 02:50:43 +0000 (22:50 -0400)
committerZygo Blaxell <zblaxell@faye.furryterror.org>
Mon, 24 Oct 2016 19:28:35 +0000 (15:28 -0400)
-rw-r--r-- 1 zblaxell zblaxell 10502468 May 24 14:06 xscreensaver-5.35.tar.gz
2918e9db7a6d24189c5bcc401cec2d3adbee644b  xscreensaver-5.35.tar.gz

711 files changed:
Makefile.in
OSX/InvertedSlider.m
OSX/LaunchScreen.xib
OSX/Makefile
OSX/Media-iOS.xcassets/AppIcon.appiconset/Contents.json
OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner100.png [new file with mode: 0644]
OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner167.png [new file with mode: 0644]
OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner180.png [new file with mode: 0644]
OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner40.png [new file with mode: 0644]
OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner58.png [new file with mode: 0644]
OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner80.png [new file with mode: 0644]
OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner87.png [new file with mode: 0644]
OSX/Media-iOS.xcassets/Contents.json [new file with mode: 0644]
OSX/Media-iOS.xcassets/Image.imageset/Contents.json [new file with mode: 0644]
OSX/Media-iOS.xcassets/LaunchImage.launchimage/1242x2208.png [new file with mode: 0644]
OSX/Media-iOS.xcassets/LaunchImage.launchimage/640x1136.png [new file with mode: 0644]
OSX/Media-iOS.xcassets/LaunchImage.launchimage/640x960.png [new file with mode: 0644]
OSX/Media-iOS.xcassets/LaunchImage.launchimage/750x1334.png [new file with mode: 0644]
OSX/Media-iOS.xcassets/LaunchImage.launchimage/Contents.json
OSX/Media-iOS.xcassets/LaunchImage.launchimage/Default-568h@2x.png [deleted file]
OSX/PrefsReader.m
OSX/PxPlus_IBM_VGA8.ttf [new file with mode: 0644]
OSX/README
OSX/SaverListController.m
OSX/SaverRunner.h
OSX/SaverRunner.m
OSX/SaverRunner.plist
OSX/Updater.plist
OSX/XScreenSaver.plist
OSX/XScreenSaverConfigSheet.m
OSX/XScreenSaverGLView.h
OSX/XScreenSaverGLView.m
OSX/XScreenSaverView.h
OSX/XScreenSaverView.m
OSX/bindist.rtf
OSX/build-fntable.pl
OSX/fuzztest.sh [new file with mode: 0755]
OSX/iSaverRunner.plist
OSX/iSaverRunner.xib
OSX/installer.rtf
OSX/ios-function-table.m
OSX/iostextclient.m [deleted file]
OSX/jwxyz-timers.h [deleted file]
OSX/jwxyz-timers.m [deleted file]
OSX/jwxyz.h [deleted file]
OSX/jwxyz.m [deleted file]
OSX/osxgrabscreen.m
OSX/seticon.pl [new file with mode: 0755]
OSX/textclient-iOS.m [new file with mode: 0644]
OSX/update-info-plist.pl
OSX/update-thumbnail.pl [deleted file]
OSX/updates.pl
OSX/updates.xml
OSX/xscreensaver.xcconfig
OSX/xscreensaver.xcodeproj/project.pbxproj
README
aclocal.m4
android/Makefile
android/README
android/XScreenSaverDaydream.java.in [new file with mode: 0644]
android/XScreenSaverGLView.c [deleted file]
android/XScreenSaverSettings.java.in [new file with mode: 0644]
android/XScreenSaverView.c [deleted file]
android/XScreenSaverWallpaper.java.in [new file with mode: 0644]
android/generate_files.pl [deleted file]
android/glue.c [deleted file]
android/grabscreen-android.c [new file with mode: 0644]
android/jwxyz-timers.h [deleted file]
android/jwxyz.c [deleted file]
android/jwxyz.h [deleted file]
android/project/GLWallpaperService/AndroidManifest.xml [deleted file]
android/project/GLWallpaperService/LICENSE [deleted file]
android/project/GLWallpaperService/NOTICE [deleted file]
android/project/GLWallpaperService/build.gradle [deleted file]
android/project/GLWallpaperService/build.xml [deleted file]
android/project/GLWallpaperService/default.properties [deleted file]
android/project/GLWallpaperService/project.properties [deleted file]
android/project/GLWallpaperService/readme-contribute.txt [deleted file]
android/project/GLWallpaperService/readme.txt [deleted file]
android/project/GLWallpaperService/res/drawable-hdpi/icon.png [deleted file]
android/project/GLWallpaperService/res/drawable-ldpi/icon.png [deleted file]
android/project/GLWallpaperService/res/drawable-mdpi/icon.png [deleted file]
android/project/GLWallpaperService/res/layout/main.xml [deleted file]
android/project/GLWallpaperService/res/values/strings.xml [deleted file]
android/project/GLWallpaperService/src/net/rbgrn/android/glwallpaperservice/GLWallpaperService.java [deleted file]
android/project/build.gradle
android/project/settings.gradle
android/project/xscreensaver/AndroidManifest.xml [deleted file]
android/project/xscreensaver/assets/fonts/OCRAStd.otf [new symlink]
android/project/xscreensaver/assets/fonts/PxPlus_IBM_VGA8.ttf [new symlink]
android/project/xscreensaver/assets/fonts/YearlReg.ttf [new symlink]
android/project/xscreensaver/build.gradle
android/project/xscreensaver/jni/Android.mk
android/project/xscreensaver/jni/Application.mk
android/project/xscreensaver/project.properties
android/project/xscreensaver/res/drawable/bouncingcow.png [deleted file]
android/project/xscreensaver/res/drawable/glhanoi.png [deleted file]
android/project/xscreensaver/res/drawable/glmatrix.png [deleted file]
android/project/xscreensaver/res/drawable/hilbert.png [deleted file]
android/project/xscreensaver/res/drawable/hypertorus.png [deleted file]
android/project/xscreensaver/res/drawable/sproingies.png [deleted file]
android/project/xscreensaver/res/drawable/stonerview.png [deleted file]
android/project/xscreensaver/res/drawable/superquadrics.png [deleted file]
android/project/xscreensaver/res/drawable/unknownpleasures.png [deleted file]
android/project/xscreensaver/res/layout/activity_xscreensaver.xml [new file with mode: 0644]
android/project/xscreensaver/res/layout/main.xml
android/project/xscreensaver/res/layout/preference_blurb.xml [new file with mode: 0644]
android/project/xscreensaver/res/layout/slider_preference.xml [new file with mode: 0644]
android/project/xscreensaver/res/layout/slider_preference_dialog.xml [deleted file]
android/project/xscreensaver/res/values/attrs.xml [deleted file]
android/project/xscreensaver/res/values/items.xml [deleted file]
android/project/xscreensaver/res/values/settings.xml [deleted file]
android/project/xscreensaver/res/values/strings.xml [deleted file]
android/project/xscreensaver/res/xml/bouncingcow.xml [deleted file]
android/project/xscreensaver/res/xml/bouncingcow_settings.xml [deleted file]
android/project/xscreensaver/res/xml/glhanoi.xml [deleted file]
android/project/xscreensaver/res/xml/glhanoi_settings.xml [deleted file]
android/project/xscreensaver/res/xml/hypertorus.xml [deleted file]
android/project/xscreensaver/res/xml/hypertorus_settings.xml [deleted file]
android/project/xscreensaver/res/xml/sproingies.xml [deleted file]
android/project/xscreensaver/res/xml/sproingies_settings.xml [deleted file]
android/project/xscreensaver/res/xml/stonerview.xml [deleted file]
android/project/xscreensaver/res/xml/stonerview_settings.xml [deleted file]
android/project/xscreensaver/res/xml/superquadrics.xml [deleted file]
android/project/xscreensaver/res/xml/superquadrics_settings.xml [deleted file]
android/project/xscreensaver/res/xml/unknownpleasures.xml [deleted file]
android/project/xscreensaver/res/xml/unknownpleasures_settings.xml [deleted file]
android/project/xscreensaver/src/org/jwz/xscreensaver/ARenderer.java [deleted file]
android/project/xscreensaver/src/org/jwz/xscreensaver/BufferFactory.java [deleted file]
android/project/xscreensaver/src/org/jwz/xscreensaver/CallNative.java [deleted file]
android/project/xscreensaver/src/org/jwz/xscreensaver/SliderPreference.java
android/project/xscreensaver/src/org/jwz/xscreensaver/TTFAnalyzer.java [new file with mode: 0644]
android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverActivity.java [new file with mode: 0644]
android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverApp.java [new file with mode: 0644]
android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverDaydream.java [new file with mode: 0644]
android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverRenderer.java [new file with mode: 0644]
android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverSettings.java [new file with mode: 0644]
android/project/xscreensaver/src/org/jwz/xscreensaver/XscreensaverApp.java [deleted file]
android/project/xscreensaver/src/org/jwz/xscreensaver/jwxyz.java [new file with mode: 0644]
android/screenhack-android.c [new file with mode: 0644]
config.h.in
configure
configure.in
driver/XScreenSaver.ad.in
driver/XScreenSaver_ad.h
driver/demo-Gtk.c
driver/demo-Xm.c
driver/lock.c
driver/passwd-pam.c
driver/prefs.c
driver/prefs.h
driver/screens.c
driver/splash.c
driver/stderr.c
driver/subprocs.c
driver/test-passwd.c
driver/timers.c
driver/windows.c
driver/xscreensaver-command.c
driver/xscreensaver-command.man
driver/xscreensaver-demo.man
driver/xscreensaver-getimage-file
driver/xscreensaver-text
driver/xscreensaver.c
driver/xscreensaver.h
driver/xscreensaver.man
hacks/Makefile.in
hacks/abstractile.c
hacks/analogtv.c
hacks/analogtv.h
hacks/anemone.c
hacks/anemotaxis.c
hacks/ant.c
hacks/apple2-main.c
hacks/asm6502.c
hacks/attraction.c
hacks/barcode.c
hacks/binaryring.c
hacks/blaster.c
hacks/blitspin.c
hacks/bouboule.c
hacks/boxfit.c
hacks/bsod.c
hacks/bsod.man
hacks/bubbles.h
hacks/bumps.c
hacks/ccurve.c
hacks/celtic.c
hacks/check-configs.pl
hacks/cloudlife.c
hacks/compass.c
hacks/config/README
hacks/config/abstractile.xml
hacks/config/anemone.xml
hacks/config/anemotaxis.xml
hacks/config/ant.xml
hacks/config/antinspect.xml
hacks/config/antmaze.xml
hacks/config/antspotlight.xml
hacks/config/apollonian.xml
hacks/config/apple2.xml
hacks/config/atlantis.xml
hacks/config/attraction.xml
hacks/config/atunnel.xml
hacks/config/barcode.xml
hacks/config/binaryring.xml
hacks/config/blaster.xml
hacks/config/blinkbox.xml
hacks/config/blitspin.xml
hacks/config/blocktube.xml
hacks/config/boing.xml
hacks/config/bouboule.xml
hacks/config/bouncingcow.xml
hacks/config/boxed.xml
hacks/config/boxfit.xml
hacks/config/braid.xml
hacks/config/bsod.xml
hacks/config/bubble3d.xml
hacks/config/bubbles.xml
hacks/config/bumps.xml
hacks/config/cage.xml
hacks/config/carousel.xml
hacks/config/ccurve.xml
hacks/config/celtic.xml
hacks/config/circuit.xml
hacks/config/cityflow.xml
hacks/config/cloudlife.xml
hacks/config/companioncube.xml
hacks/config/compass.xml
hacks/config/coral.xml
hacks/config/crackberg.xml
hacks/config/critical.xml
hacks/config/crystal.xml
hacks/config/cube21.xml
hacks/config/cubenetic.xml
hacks/config/cubestorm.xml
hacks/config/cubicgrid.xml
hacks/config/cwaves.xml
hacks/config/cynosure.xml
hacks/config/dangerball.xml
hacks/config/decayscreen.xml
hacks/config/deco.xml
hacks/config/deluxe.xml
hacks/config/demon.xml
hacks/config/discrete.xml
hacks/config/distort.xml
hacks/config/dnalogo.xml
hacks/config/drift.xml
hacks/config/dymaxionmap.xml [new file with mode: 0644]
hacks/config/endgame.xml
hacks/config/energystream.xml [new file with mode: 0644]
hacks/config/engine.xml
hacks/config/epicycle.xml
hacks/config/eruption.xml
hacks/config/euler2d.xml
hacks/config/extrusion.xml
hacks/config/fadeplot.xml
hacks/config/fiberlamp.xml
hacks/config/fireworkx.xml
hacks/config/flag.xml
hacks/config/flame.xml
hacks/config/flipflop.xml
hacks/config/flipscreen3d.xml
hacks/config/fliptext.xml
hacks/config/flow.xml
hacks/config/fluidballs.xml
hacks/config/flurry.xml
hacks/config/flyingtoasters.xml
hacks/config/fontglide.xml
hacks/config/forest.xml
hacks/config/fuzzyflakes.xml
hacks/config/galaxy.xml
hacks/config/gears.xml
hacks/config/geodesic.xml
hacks/config/geodesicgears.xml
hacks/config/gflux.xml
hacks/config/glblur.xml
hacks/config/glcells.xml
hacks/config/gleidescope.xml
hacks/config/glforestfire.xml
hacks/config/glhanoi.xml
hacks/config/glknots.xml
hacks/config/glmatrix.xml
hacks/config/glplanet.xml
hacks/config/glschool.xml
hacks/config/glslideshow.xml
hacks/config/glsnake.xml
hacks/config/gltext.xml
hacks/config/goop.xml
hacks/config/grav.xml
hacks/config/greynetic.xml
hacks/config/halftone.xml
hacks/config/halo.xml
hacks/config/helix.xml
hacks/config/hexadrop.xml
hacks/config/hilbert.xml
hacks/config/hopalong.xml
hacks/config/hydrostat.xml [new file with mode: 0644]
hacks/config/hyperball.xml
hacks/config/hypercube.xml
hacks/config/hypertorus.xml
hacks/config/hypnowheel.xml
hacks/config/ifs.xml
hacks/config/imsmap.xml
hacks/config/interaggregate.xml
hacks/config/interference.xml
hacks/config/intermomentary.xml
hacks/config/jigglypuff.xml
hacks/config/jigsaw.xml
hacks/config/juggle.xml
hacks/config/juggler3d.xml
hacks/config/julia.xml
hacks/config/kaleidescope.xml
hacks/config/kaleidocycle.xml
hacks/config/klein.xml
hacks/config/kumppa.xml
hacks/config/lament.xml
hacks/config/laser.xml
hacks/config/lavalite.xml
hacks/config/lcdscrub.xml
hacks/config/lightning.xml
hacks/config/lisa.xml
hacks/config/lissie.xml
hacks/config/lmorph.xml
hacks/config/loop.xml
hacks/config/m6502.xml
hacks/config/maze.xml
hacks/config/memscroller.xml
hacks/config/menger.xml
hacks/config/metaballs.xml
hacks/config/mirrorblob.xml
hacks/config/mismunch.xml
hacks/config/moebius.xml
hacks/config/moebiusgears.xml
hacks/config/moire.xml
hacks/config/moire2.xml
hacks/config/molecule.xml
hacks/config/morph3d.xml
hacks/config/mountain.xml
hacks/config/munch.xml
hacks/config/nerverot.xml
hacks/config/noof.xml
hacks/config/noseguy.xml
hacks/config/pacman.xml
hacks/config/pedal.xml
hacks/config/penetrate.xml
hacks/config/penrose.xml
hacks/config/petri.xml
hacks/config/phosphor.xml
hacks/config/photopile.xml
hacks/config/piecewise.xml
hacks/config/pinion.xml
hacks/config/pipes.xml
hacks/config/polyhedra.xml
hacks/config/polyominoes.xml
hacks/config/polytopes.xml
hacks/config/pong.xml
hacks/config/popsquares.xml
hacks/config/projectiveplane.xml
hacks/config/providence.xml
hacks/config/pulsar.xml
hacks/config/pyro.xml
hacks/config/qix.xml
hacks/config/quasicrystal.xml
hacks/config/queens.xml
hacks/config/raverhoop.xml [new file with mode: 0644]
hacks/config/rd-bomb.xml
hacks/config/rdbomb.xml [changed from file to symlink]
hacks/config/ripples.xml
hacks/config/rocks.xml
hacks/config/romanboy.xml
hacks/config/rorschach.xml
hacks/config/rotor.xml
hacks/config/rotzoomer.xml
hacks/config/rubik.xml
hacks/config/rubikblocks.xml
hacks/config/sballs.xml
hacks/config/shadebobs.xml
hacks/config/sierpinski.xml
hacks/config/sierpinski3d.xml
hacks/config/skytentacles.xml
hacks/config/slidescreen.xml
hacks/config/slip.xml
hacks/config/sonar.xml
hacks/config/speedmine.xml
hacks/config/sphere.xml
hacks/config/spheremonics.xml
hacks/config/spiral.xml
hacks/config/splitflap.xml
hacks/config/spotlight.xml
hacks/config/sproingies.xml
hacks/config/squiral.xml
hacks/config/stairs.xml
hacks/config/starfish.xml
hacks/config/starwars.xml
hacks/config/stonerview.xml
hacks/config/strange.xml
hacks/config/substrate.xml
hacks/config/superquadrics.xml
hacks/config/surfaces.xml
hacks/config/swirl.xml
hacks/config/t3d.xml
hacks/config/tangram.xml
hacks/config/tessellimage.xml
hacks/config/thornbird.xml
hacks/config/timetunnel.xml
hacks/config/topblock.xml
hacks/config/triangle.xml
hacks/config/tronbit.xml
hacks/config/truchet.xml
hacks/config/twang.xml
hacks/config/unicrud.xml [new file with mode: 0644]
hacks/config/unknownpleasures.xml
hacks/config/vermiculate.xml
hacks/config/vines.xml
hacks/config/voronoi.xml
hacks/config/wander.xml
hacks/config/webcollage.xml
hacks/config/whirlwindwarp.xml
hacks/config/whirlygig.xml
hacks/config/winduprobot.xml
hacks/config/worm.xml
hacks/config/wormhole.xml
hacks/config/xanalogtv.xml
hacks/config/xflame.xml
hacks/config/xjack.xml
hacks/config/xlyap.xml
hacks/config/xmatrix.xml
hacks/config/xrayswarm.xml
hacks/config/xspirograph.xml
hacks/config/zoom.xml
hacks/coral.c
hacks/critical.c
hacks/crystal.c
hacks/cwaves.c
hacks/cynosure.c
hacks/decayscreen.c
hacks/deco.c
hacks/deluxe.c
hacks/demon.c
hacks/distort.c
hacks/epicycle.c
hacks/euler2d.c
hacks/fiberlamp.c
hacks/flag.c
hacks/flame.c
hacks/flow.c
hacks/fluidballs.c
hacks/fontglide.c
hacks/fps.h
hacks/fuzzyflakes.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/atlantis.h
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/bubble3d.h
hacks/glx/buildlwo.h
hacks/glx/cage.c
hacks/glx/carousel.c
hacks/glx/chessmodels.c
hacks/glx/circuit.c
hacks/glx/companion.c
hacks/glx/crackberg.c
hacks/glx/cube21.c
hacks/glx/cubenetic.c
hacks/glx/cubestorm.c
hacks/glx/cubicgrid.c
hacks/glx/dangerball.c
hacks/glx/dnalogo.c
hacks/glx/dropshadow.h
hacks/glx/dymaxionmap.c [new file with mode: 0644]
hacks/glx/dymaxionmap.man [new file with mode: 0644]
hacks/glx/energystream.c [new file with mode: 0644]
hacks/glx/energystream.man [new file with mode: 0644]
hacks/glx/engine.c
hacks/glx/flipflop.c
hacks/glx/flipscreen3d.c
hacks/glx/flurry.h
hacks/glx/flyingtoasters.c
hacks/glx/fps-gl.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/gllist.c
hacks/glx/glplanet.c
hacks/glx/glschool_gl.h
hacks/glx/glslideshow.c
hacks/glx/glsnake.c
hacks/glx/gltext.c
hacks/glx/gltrackball.c
hacks/glx/glut_stroke.c
hacks/glx/glut_swidth.c
hacks/glx/grab-ximage.c
hacks/glx/hilbert.c
hacks/glx/hydrostat.c [new file with mode: 0644]
hacks/glx/hydrostat.man [new file with mode: 0644]
hacks/glx/hypertorus.c
hacks/glx/hypnowheel.c
hacks/glx/involute.c
hacks/glx/jigglypuff.c
hacks/glx/jigsaw.c
hacks/glx/juggler3d.c
hacks/glx/jwzgles.c [deleted file]
hacks/glx/jwzgles.h [deleted file]
hacks/glx/jwzglesI.h [deleted file]
hacks/glx/kaleidocycle.c
hacks/glx/klein.c
hacks/glx/lament.c
hacks/glx/marching.c
hacks/glx/menger.c
hacks/glx/mirrorblob.c
hacks/glx/moebius.c
hacks/glx/moebiusgears.c
hacks/glx/molecule.c
hacks/glx/molecules.sh
hacks/glx/morph3d.c
hacks/glx/noof.c
hacks/glx/normals.h
hacks/glx/photopile.c
hacks/glx/pipes.c
hacks/glx/polyhedra-gl.c
hacks/glx/polyhedra.c
hacks/glx/polytopes.c
hacks/glx/projectiveplane.c
hacks/glx/providence.c
hacks/glx/quasicrystal.c
hacks/glx/quasicrystal.man
hacks/glx/queens.c
hacks/glx/raverhoop.c [new file with mode: 0644]
hacks/glx/raverhoop.man [new file with mode: 0644]
hacks/glx/romanboy.c
hacks/glx/rotator.c
hacks/glx/rubik.c
hacks/glx/rubikblocks.c
hacks/glx/sballs.c
hacks/glx/sierpinski3d.c
hacks/glx/sonar-icmp.c
hacks/glx/spheremonics.c
hacks/glx/splitflap.c
hacks/glx/sproingies.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/tangram_shapes.c
hacks/glx/teapot.c
hacks/glx/texfont.c
hacks/glx/texfont.h
hacks/glx/topblock.c
hacks/glx/tronbit.c
hacks/glx/tunnel_draw.c
hacks/glx/unicrud.c [new file with mode: 0644]
hacks/glx/unicrud.man [new file with mode: 0644]
hacks/glx/unknownpleasures.c
hacks/glx/voronoi.c
hacks/glx/vrml2gl.pl
hacks/glx/wfront2gl.pl
hacks/glx/winduprobot.c
hacks/glx/xpm-ximage.c
hacks/goop.c
hacks/grav.c
hacks/greynetic.c
hacks/halftone.c
hacks/halo.c
hacks/helix.c
hacks/hexadrop.c
hacks/hyperball.c
hacks/hypercube.c
hacks/ifs.c
hacks/images/dymaxionmap.xpm [new file with mode: 0644]
hacks/imsmap.c
hacks/interaggregate.c
hacks/interference.c
hacks/intermomentary.c
hacks/juggle.c
hacks/julia.c
hacks/kaleidescope.c
hacks/kumppa.c
hacks/laser.c
hacks/lcdscrub.c
hacks/lisa.c
hacks/lissie.c
hacks/loop.c
hacks/m6502.c
hacks/m6502.sh
hacks/maze.c
hacks/memscroller.c
hacks/metaballs.c
hacks/moire.c
hacks/moire2.c
hacks/munch.c
hacks/nerverot.c
hacks/noseguy.c
hacks/pacman.c
hacks/pacman.h
hacks/pedal.c
hacks/penetrate.c
hacks/penrose.c
hacks/petri.c
hacks/phosphor.c
hacks/piecewise.c
hacks/polyominoes.c
hacks/pong.c
hacks/pong.man
hacks/popsquares.c
hacks/qix.c
hacks/rd-bomb.c
hacks/recanim.c
hacks/ripples.c
hacks/rocks.c
hacks/rorschach.c
hacks/rotor.c
hacks/rotzoomer.c
hacks/screenhack.c
hacks/screenhack.h
hacks/screenhackI.h
hacks/shadebobs.c
hacks/slidescreen.c
hacks/speedmine.c
hacks/spiral.c
hacks/spotlight.c
hacks/squiral.c
hacks/starfish.c
hacks/strange.c
hacks/substrate.c
hacks/swirl.c
hacks/t3d.c
hacks/tessellimage.c
hacks/testx11.c
hacks/thornbird.c
hacks/truchet.c
hacks/twang.c
hacks/vermiculate.c
hacks/vidwhacker
hacks/wander.c
hacks/webcollage
hacks/webcollage-cocoa.m
hacks/webcollage-helper.c
hacks/webcollage.man
hacks/whirlwindwarp.c
hacks/whirlygig.c
hacks/wormhole.c
hacks/xanalogtv.c
hacks/xflame.c
hacks/xlockmore.c
hacks/xlockmore.h
hacks/xlyap.c
hacks/xmatrix.c
hacks/xpm-pixmap.c
hacks/xrayswarm.c
hacks/xspirograph.c
hacks/zoom.c
jwxyz/Makefile.in [new file with mode: 0644]
jwxyz/README [new file with mode: 0644]
jwxyz/jwxyz-android.c [new file with mode: 0644]
jwxyz/jwxyz-android.h [new file with mode: 0644]
jwxyz/jwxyz-cocoa.h [new file with mode: 0644]
jwxyz/jwxyz-cocoa.m [new file with mode: 0644]
jwxyz/jwxyz-common.c [new file with mode: 0644]
jwxyz/jwxyz-gl.c [new file with mode: 0644]
jwxyz/jwxyz-timers.c [new file with mode: 0644]
jwxyz/jwxyz-timers.h [new file with mode: 0644]
jwxyz/jwxyz.h [new file with mode: 0644]
jwxyz/jwxyz.m [new file with mode: 0644]
jwxyz/jwxyzI.h [new file with mode: 0644]
jwxyz/jwzgles.c [new file with mode: 0644]
jwxyz/jwzgles.h [new file with mode: 0644]
jwxyz/jwzglesI.h [new file with mode: 0644]
po/POTFILES.in
utils/Makefile.in
utils/aligned_malloc.c
utils/aligned_malloc.h
utils/async_netdb.c
utils/async_netdb.h
utils/compile_axp.com
utils/compile_decc.com
utils/grabclient.c
utils/grabscreen.h
utils/images/logo-180.xpm
utils/images/logo-50.xpm
utils/minixpm.c
utils/textclient-mobile.c [new file with mode: 0644]
utils/textclient.c
utils/textclient.h
utils/thread_util.c
utils/thread_util.h
utils/utf8wc.c
utils/utils.h
utils/version.h
utils/visual.c
utils/xft.c
xscreensaver.spec

index bd6dd28b7892b24658030dfc50cef4beb1172aff..c919051831d5c5f738a4134fd808958100539261 100644 (file)
@@ -6,7 +6,7 @@ srcdir          = @srcdir@
 VPATH          = @srcdir@
 
 SHELL          = /bin/sh
-SUBDIRS        = utils driver hacks hacks/glx po
+SUBDIRS        = utils jwxyz hacks hacks/glx driver po
 SUBDIRS2       = $(SUBDIRS) OSX android
 TARFILES       = README README.hacking README.VMS INSTALL \
                  configure configure.in Makefile.in config.h.in \
@@ -273,6 +273,7 @@ test-tar::
     ../../configure --with-motif=/usr/local/lesstif --without-gnome ;      \
     echo --------------------------------------------------------------- ;  \
     ( cd utils; gmake all ) ;                                              \
+    ( cd jwxyz; gmake all ) ;                                              \
     ( cd driver; gmake all ) ;                                             \
     echo --------------------------------------------------------------- ); \
                                                                            \
@@ -280,6 +281,8 @@ test-tar::
 
 dmg::
        $(MAKE) -C OSX release dmg
+apk::
+       $(MAKE) -C android apk
 
 www::
        @                                                                   \
@@ -293,6 +296,9 @@ www::
   BNAME2="$$HEAD.dmg" ;                                                            \
   NAME2="$$ADIR$$BNAME2" ;                                                 \
   DNAME2="$$DEST/$$HEAD.dmg" ;                                             \
+  BNAME3="$$HEAD.apk" ;                                                            \
+  NAME3="$$ADIR$$BNAME3" ;                                                 \
+  DNAME3="$$DEST/$$HEAD.apk" ;                                             \
                                                                            \
   if ! git diff --quiet ; then                                             \
     echo "uncommitted changes exist!" ;                                            \
@@ -309,6 +315,10 @@ www::
     echo "$$NAME2 does not exist!  Did you forget to \`make dmg'?" ;       \
     exit 1 ;                                                               \
   fi ;                                                                     \
+  if [ ! -f $$NAME3 ]; then                                                \
+    echo "$$NAME3 does not exist!  Did you forget to \`make apk'?" ;       \
+    exit 1 ;                                                               \
+  fi ;                                                                     \
   chmod a-w $$NAME ;                                                       \
   if [ -f $$DNAME ]; then                                                  \
     /bin/echo -n "WARNING: $$DNAME already exists!  Overwrite? ";          \
@@ -323,6 +333,13 @@ www::
     if [ "x$$line" != "xyes" -a "x$$line" != "xy" ]; then                  \
       exit 1 ;                                                                     \
     fi ;                                                                   \
+  fi ;                                                                     \
+  if [ -f $$DNAME3 ]; then                                                 \
+    /bin/echo -n "WARNING: $$DNAME3 already exists!  Overwrite? ";         \
+    read line;                                                             \
+    if [ "x$$line" != "xyes" -a "x$$line" != "xy" ]; then                  \
+      exit 1 ;                                                                     \
+    fi ;                                                                   \
   fi ;                                                                     \
                                                                            \
   git tag -a "v$$VERS" -m "$$VERS" ;                                       \
@@ -332,7 +349,8 @@ www::
                                                                            \
   cp -p $$NAME $$DNAME ;                                                   \
   cp -p $$NAME2 $$DNAME2 ;                                                 \
-  chmod u+w $$DNAME $$DNAME2 ;                                             \
+  cp -p $$NAME3 $$DNAME3 ;                                                 \
+  chmod u+w $$DNAME $$DNAME2 $$DNAME3 ;                                            \
   cp -p OSX/updates.xml $$DEST ;                                           \
   cd $$DEST ;                                                              \
                                                                            \
@@ -359,7 +377,7 @@ www::
   cat $$TMP > download.html ;                                              \
   rm -f $$TMP ;                                                                    \
                                                                            \
-  git add $$BNAME $$BNAME2 ;                                               \
+  git add $$BNAME $$BNAME2 $$BNAME3 ;                                      \
                                                                            \
   $(MAKE) -C ../ xscreensaver/changelog.html xscreensaver/screenshots/index.html; \
   git diff changelog.html ;                                                \
index 642a3e4f73297d08a1fe74acc03ae3c9998db371..6ac0b4196bb31f0d28cb9d1c88c9fc990485a9b1 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2006-2013 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2006-2015 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
@@ -83,8 +83,8 @@
 
 - (NSAttributedString *)attributedStringValue;
 {
-  // #### "Build and Analyze" says this leaks. Unsure whether this is true.
-  return [[NSAttributedString alloc] initWithString:[self stringValue]];
+  return [[[NSAttributedString alloc] initWithString:[self stringValue]]
+           autorelease];
 }
 
 -(void)setFloatValue:(float)v       { [self setDoubleValue: (double) v];      }
index 580d93579bfe0528666b6560fc74be47897e11fe..731d86e2168fd73f70b0ac90d98477ca794cff2e 100644 (file)
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6751" systemVersion="14C1514" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="10116" systemVersion="15D21" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
     <dependencies>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6736"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
     </dependencies>
     <objects>
         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
index 8400adf0b885e4de6a52899ed0f4e70b7c9f08cd..d8664552cbc383e4acc0a6c53de53240bbc6844e 100644 (file)
@@ -1,21 +1,23 @@
-# XScreenSaver for MacOS X, Copyright (c) 2006-2014 by Jamie Zawinski.
+# XScreenSaver for MacOS X, Copyright (c) 2006-2015 by Jamie Zawinski.
 
-# We have to use Xcode 5.0.2 in order to build savers that will run on
-# MacOS 10.6 and 10.7, because that's the latest version of Xcode that
-# ships with a version of clang that implements "-fobjc-gc".
+XCODE_APP = /Applications/Xcode.app
+
+# To build savers that will run on MacOS 10.6 and 10.7, Xcode 5.0.2 must
+# be used (as that's the latest version of Xcode that ships with a version
+# of clang that implements "-fobjc-gc").  However, Xcode 5.0.2 will not
+# launch on MacOS 10.11 or later.
 #
-XCODE_APP = /Applications/Xcode-5.0.2.app
+XCODE_APP = /Applications/Xcode-5.0.2.app
 
 TARGETS    = All Savers
-ARCH       = -arch i386 -arch x86_64
+ARCH       = -arch i386 -arch x86_64 ONLY_ACTIVE_ARCH=NO
 CERT       = 'Jamie Zawinski'
 CERT       = 'iPhone Developer: Jamie Zawinski (Y5M82TL69N)'
 PKGID     = org.jwz.xscreensaver
-THUMBDIR   = $(HOME)/www/xscreensaver/screenshots/
+THUMBDIR   = build/screenshots
 XCODEBUILD = $(XCODE_APP)/Contents/Developer/usr/bin/xcodebuild
 SETFILE    = $(XCODE_APP)/Contents/Developer/Tools/SetFile
-SETICON    = /usr/local/bin/seticon
-# seticon is from osxutils1.7.pkg
+SETICON    = ./seticon.pl
 
 default: release
 all: debug release
@@ -40,12 +42,63 @@ release:: distdepend
        $(XCODEBUILD) $(ARCH) -target "$(TARGETS)" -configuration Release build
 
 release:: check_versions
-release:: update_thumbs
 release:: sign
 
 Sparkle.framework:
        unzip ../archive/Sparkle.framework-2013-12-04.zip
 
+# Download and resize images from jwz.org.
+# This saves us having to include 4MB of images in the tar file
+# that will only be used by a vast minority of people building
+# from source.
+# update-info-plist.pl runs this as needed.
+# Might be better to do this with curl, since that is installed by default.
+
+URL = https://www.jwz.org/xscreensaver/screenshots/
+WGET = wget -q -U xscreensaver-build-osx
+CVT  = -thumbnail '200x150^' -gravity center -extent 200x150 \
+     \( +clone  -alpha extract \
+        -draw 'fill black polygon 0,0 0,6 6,0 fill white circle 6,6 6,0' \
+        \( +clone -flip \) -compose Multiply -composite \
+        \( +clone -flop \) -compose Multiply -composite \
+     \) -alpha off -compose CopyOpacity -composite \
+    -colorspace sRGB \
+    -strip \
+    -quality 95 \
+    +dither -colors 128
+
+$(THUMBDIR)/%.png:
+       @\
+       FILE1=`echo "$@" | sed 's!^.*/\([^/]*\)\.png$$!\1.jpg!'` ;      \
+       FILE2="$@" ;                                                    \
+       TMP="$$FILE2".tmp ;                                             \
+       URL="$(URL)$$FILE1" ;                                           \
+       URL2="$(URL)retired/$$FILE1" ;                                  \
+       if [ ! -d $(THUMBDIR) ]; then mkdir -p $(THUMBDIR) ; fi ;       \
+       rm -f "$$FILE2" "$$TMP" ;                                       \
+       set +e ;                                                        \
+       echo "downloading $$URL..." ;                                   \
+       $(WGET) -O"$$TMP" "$$URL" ;                                     \
+       if [ ! -s "$$TMP" ]; then                                       \
+         echo "downloading $$URL2..." ;                                \
+         $(WGET) -O"$$TMP" "$$URL2" ;                                  \
+       fi ;                                                            \
+       if [ ! -s "$$TMP" ]; then                                       \
+         rm -f "$$TMP" ;                                               \
+         echo "failed: $$URL" ;                                        \
+         exit 1 ;                                                      \
+       fi ;                                                            \
+       rm -f "$$FILE2" ;                                               \
+       convert jpg:- $(CVT) "$$FILE2" < "$$TMP" ;                      \
+       if [ ! -s "$$FILE2" ]; then                                     \
+         echo "$$FILE2 failed" >&2 ;                                   \
+         rm -f "$$FILE2" "$$TMP" ;                                     \
+         exit 1 ;                                                      \
+       else                                                            \
+         rm -f "$$TMP" ;                                               \
+       fi
+
+
 sign:
        @for f in build/Release/*.app/Contents/*/*.saver \
                  build/Release/*.{saver,app} ; do \
@@ -131,10 +184,6 @@ check_coretext:
   exit $$RESULT
 
 
-update_thumbs::
-       ./update-thumbnail.pl $(THUMBDIR) build/Release/*.saver
-
-
 # Arrrrgh
 ios-function-table.m::
        @./build-fntable.pl build/Debug-iphonesimulator/XScreenSaver.app $@
@@ -235,7 +284,8 @@ build/Release/installer.pkg: installer.rtf installer.xml installer.sh installer.
 
 # -format UDBZ saves 4% (~1.2 MB) over UDZO.
 dmg:: distdepend
-dmg:: check_versions check_gc check_coretext
+dmg:: check_versions check_coretext
+#dmg:: check_gc
 dmg:: build/Release/installer.pkg
 dmg::
        @                                                                     \
@@ -291,7 +341,7 @@ dmg::
   cp -p bindist.rtf "$$STAGE/Read Me.rtf" ;                                  \
   cp -p build/Release/installer.pkg "$$PKG" ;                                \
   cp -p bindist-DS_Store "$$STAGE/.DS_Store" ;                               \
-  cp -p bindist.webloc "$$STAGE/Get the iPhone:iPad Version.webloc" ;        \
+  cp -p bindist.webloc "$$STAGE/" ;                                          \
   cp -p XScreenSaverDMG.icns "$$STAGE/.VolumeIcon.icns" ;                    \
   ${SETFILE} -a C "$$STAGE" ;                                                \
   ${SETFILE} -a E "$$STAGE"/*.{rtf,pkg,webloc} ;                             \
@@ -300,6 +350,7 @@ dmg::
   $(SETICON) -d XScreenSaverFolder.icns "$$DST" ;                            \
   $(SETICON) -d XScreenSaverWebloc.icns "$$STAGE"/*.webloc ;                 \
   $(SETICON) -d XScreenSaverPkg.icns "$$STAGE"/*.pkg ;                       \
+  mv "$$STAGE/bindist.webloc" "$$STAGE/Get the iPhone:iPad Version.webloc" ;  \
   hdiutil makehybrid -quiet -ov -hfs -hfs-volume-name "$$VOLNAME"            \
     -hfs-openfolder "$$STAGE" "$$STAGE" -o "$$TMPDMG" ;                              \
   rm -rf "$$STAGE" ;                                                         \
index 43db2a4df27a776da0abcd0c62ff30cc01a01dce..89e33affd486aad4e864c5f84c76a07640123a74 100644 (file)
@@ -7,15 +7,29 @@
       "scale" : "1x"
     },
     {
-      "idiom" : "iphone",
       "size" : "29x29",
+      "idiom" : "iphone",
+      "filename" : "iSaverRunner58.png",
       "scale" : "2x"
     },
     {
+      "size" : "29x29",
       "idiom" : "iphone",
+      "filename" : "iSaverRunner87.png",
+      "scale" : "3x"
+    },
+    {
       "size" : "40x40",
+      "idiom" : "iphone",
+      "filename" : "iSaverRunner80.png",
       "scale" : "2x"
     },
+    {
+      "size" : "40x40",
+      "idiom" : "iphone",
+      "filename" : "iSaverRunner120.png",
+      "scale" : "3x"
+    },
     {
       "size" : "57x57",
       "idiom" : "iphone",
@@ -35,8 +49,9 @@
       "scale" : "2x"
     },
     {
-      "idiom" : "iphone",
       "size" : "60x60",
+      "idiom" : "iphone",
+      "filename" : "iSaverRunner180.png",
       "scale" : "3x"
     },
     {
       "scale" : "1x"
     },
     {
-      "idiom" : "ipad",
       "size" : "29x29",
+      "idiom" : "ipad",
+      "filename" : "iSaverRunner58.png",
       "scale" : "2x"
     },
     {
-      "idiom" : "ipad",
       "size" : "40x40",
+      "idiom" : "ipad",
+      "filename" : "iSaverRunner40.png",
       "scale" : "1x"
     },
     {
-      "idiom" : "ipad",
       "size" : "40x40",
+      "idiom" : "ipad",
+      "filename" : "iSaverRunner80.png",
       "scale" : "2x"
     },
     {
@@ -67,8 +85,9 @@
       "scale" : "1x"
     },
     {
-      "idiom" : "ipad",
       "size" : "50x50",
+      "idiom" : "ipad",
+      "filename" : "iSaverRunner100.png",
       "scale" : "2x"
     },
     {
       "idiom" : "ipad",
       "filename" : "iSaverRunner152.png",
       "scale" : "2x"
+    },
+    {
+      "size" : "83.5x83.5",
+      "idiom" : "ipad",
+      "filename" : "iSaverRunner167.png",
+      "scale" : "2x"
     }
   ],
   "info" : {
diff --git a/OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner100.png b/OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner100.png
new file mode 100644 (file)
index 0000000..4a71d44
Binary files /dev/null and b/OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner100.png differ
diff --git a/OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner167.png b/OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner167.png
new file mode 100644 (file)
index 0000000..85824f0
Binary files /dev/null and b/OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner167.png differ
diff --git a/OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner180.png b/OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner180.png
new file mode 100644 (file)
index 0000000..1e7d0ba
Binary files /dev/null and b/OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner180.png differ
diff --git a/OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner40.png b/OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner40.png
new file mode 100644 (file)
index 0000000..20db74e
Binary files /dev/null and b/OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner40.png differ
diff --git a/OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner58.png b/OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner58.png
new file mode 100644 (file)
index 0000000..e62c324
Binary files /dev/null and b/OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner58.png differ
diff --git a/OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner80.png b/OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner80.png
new file mode 100644 (file)
index 0000000..adc5ad7
Binary files /dev/null and b/OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner80.png differ
diff --git a/OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner87.png b/OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner87.png
new file mode 100644 (file)
index 0000000..0335f60
Binary files /dev/null and b/OSX/Media-iOS.xcassets/AppIcon.appiconset/iSaverRunner87.png differ
diff --git a/OSX/Media-iOS.xcassets/Contents.json b/OSX/Media-iOS.xcassets/Contents.json
new file mode 100644 (file)
index 0000000..da4a164
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/OSX/Media-iOS.xcassets/Image.imageset/Contents.json b/OSX/Media-iOS.xcassets/Image.imageset/Contents.json
new file mode 100644 (file)
index 0000000..f8f827e
--- /dev/null
@@ -0,0 +1,20 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/OSX/Media-iOS.xcassets/LaunchImage.launchimage/1242x2208.png b/OSX/Media-iOS.xcassets/LaunchImage.launchimage/1242x2208.png
new file mode 100644 (file)
index 0000000..2f3cd23
Binary files /dev/null and b/OSX/Media-iOS.xcassets/LaunchImage.launchimage/1242x2208.png differ
diff --git a/OSX/Media-iOS.xcassets/LaunchImage.launchimage/640x1136.png b/OSX/Media-iOS.xcassets/LaunchImage.launchimage/640x1136.png
new file mode 100644 (file)
index 0000000..6763abe
Binary files /dev/null and b/OSX/Media-iOS.xcassets/LaunchImage.launchimage/640x1136.png differ
diff --git a/OSX/Media-iOS.xcassets/LaunchImage.launchimage/640x960.png b/OSX/Media-iOS.xcassets/LaunchImage.launchimage/640x960.png
new file mode 100644 (file)
index 0000000..0bfc1a9
Binary files /dev/null and b/OSX/Media-iOS.xcassets/LaunchImage.launchimage/640x960.png differ
diff --git a/OSX/Media-iOS.xcassets/LaunchImage.launchimage/750x1334.png b/OSX/Media-iOS.xcassets/LaunchImage.launchimage/750x1334.png
new file mode 100644 (file)
index 0000000..4ec452d
Binary files /dev/null and b/OSX/Media-iOS.xcassets/LaunchImage.launchimage/750x1334.png differ
index a6f99a2f556f6f9f18ba97b0e424e5831bb38d16..5dd89e09e1a451460e230a701c95046f0864893a 100644 (file)
@@ -3,6 +3,7 @@
     {
       "orientation" : "portrait",
       "idiom" : "iphone",
+      "filename" : "640x960.png",
       "extent" : "full-screen",
       "minimum-system-version" : "7.0",
       "scale" : "2x"
@@ -11,7 +12,7 @@
       "extent" : "full-screen",
       "idiom" : "iphone",
       "subtype" : "retina4",
-      "filename" : "Default-568h@2x.png",
+      "filename" : "640x1136.png",
       "minimum-system-version" : "7.0",
       "orientation" : "portrait",
       "scale" : "2x"
     {
       "orientation" : "portrait",
       "idiom" : "iphone",
+      "filename" : "640x1136.png",
       "extent" : "full-screen",
-      "scale" : "1x"
+      "subtype" : "retina4",
+      "scale" : "2x"
     },
     {
-      "orientation" : "portrait",
-      "idiom" : "iphone",
       "extent" : "full-screen",
+      "idiom" : "iphone",
+      "subtype" : "667h",
+      "filename" : "750x1334.png",
+      "minimum-system-version" : "8.0",
+      "orientation" : "portrait",
       "scale" : "2x"
     },
     {
-      "orientation" : "portrait",
-      "idiom" : "iphone",
       "extent" : "full-screen",
-      "filename" : "Default-568h@2x.png",
-      "subtype" : "retina4",
-      "scale" : "2x"
-    }
+      "idiom" : "iphone",
+      "subtype" : "736h",
+      "filename" : "1242x2208.png",
+      "minimum-system-version" : "8.0",
+      "orientation" : "portrait",
+      "scale" : "3x"
+    },
   ],
   "info" : {
     "version" : 1,
diff --git a/OSX/Media-iOS.xcassets/LaunchImage.launchimage/Default-568h@2x.png b/OSX/Media-iOS.xcassets/LaunchImage.launchimage/Default-568h@2x.png
deleted file mode 100644 (file)
index 0891b7a..0000000
Binary files a/OSX/Media-iOS.xcassets/LaunchImage.launchimage/Default-568h@2x.png and /dev/null differ
index 4044280294aeb2fb07158b1ff2829aab25fce3f5..a1c4ed48e0625dc1f69aaa0f8cf4fad3a11e407c 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2006-2013 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2006-2015 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
@@ -97,7 +97,9 @@
 {
   NSObject *obj = (NSObject *)
     CFPreferencesCopyAppValue ((CFStringRef) key, (CFStringRef) domain);
-  if (!obj && defaults)
+  if (obj)
+    [obj autorelease];
+  else if (defaults)
     obj = [defaults objectForKey:key];
   return obj;
 }
diff --git a/OSX/PxPlus_IBM_VGA8.ttf b/OSX/PxPlus_IBM_VGA8.ttf
new file mode 100644 (file)
index 0000000..0368d2b
Binary files /dev/null and b/OSX/PxPlus_IBM_VGA8.ttf differ
index 68c2d00377acd3c8575d7c2cfbcf0103442a63e7..555e8e2585186e9206d7fd7725b121029bc5514b 100644 (file)
@@ -15,25 +15,28 @@ ridiculously long list of steps!
 
   1: Duplicate a target (Dangerball for GL, or Attraction for X11).
   2: Rename it, and drag it to the right spot in the list.
-  3: Delete the dangerball.c and dangerball.xml files from the new target.
+  3: Delete the dangerball.c and dangerball.xml files from Build Phases.
   4: Delete the "DangerBall copy-Info.plist" file that got created.
   5: Delete the "DangerBall copy-Info.plist" from the Build Settings too.
-  6: Change PRODUCT_NAME in Build Settings.
+  6: Change PRODUCT_NAME in Build Settings (maybe this automatic now?)
   7: Manage Schemes, rename "DangerBall Copy".
   8: Move to the right place in the list.
   9: Scheme / Run / Info: Executable: SaverTester.app.
  10: Scheme / Run / Arguments: set SELECTED_SAVER environment variable.
  11: File / Add Files / the new .c and .xml.
-     Add to targets: the new target, and also "XScreenSaver-iOS".
- 12: Re-order them in the file list.
- 13: In target "All Savers (OpenGL)" add the new target as a dependency.
- 14: In target "XScreenSaver-iOS", reorder new files in "Copy" and "Compile".
- 15: In target "XScreenSaver-iOS", add "-DUSE_GL" to the new file's options.
- 16: Put a 200x150 screen shot in ~/www/xscreensaver/screenshots/
- 17: ln -s ../../src/xscreensaver/OSX/build/Debug/NEW.saver \
+ 12: Select each file in the left pane; see Target Membership in the right
+     pane and add them to the new target, and to "XScreenSaver-iOS".
+ 13: Re-order them in the file list.
+ 14: In target "All Savers (OpenGL)" add the new target as Build Phases /
+     Target Dependency.
+ 15: In target "XScreenSaver-iOS", reorder new files in Build Phases /
+     "Copy" and "Compile", since they showed up in a random place.
+ 16: In target "XScreenSaver-iOS", add "-DUSE_GL" to the new file's options.
+ 17: Put a 200x150 screen shot in ~/www/xscreensaver/screenshots/
+ 18: ln -s ../../src/xscreensaver/OSX/build/Debug/NEW.saver \
            ~/Library/Screen\ Savers/
- 18: git add xscreensaver.xcodeproj/xcuserdata/*/xcschemes/*.xcscheme
19: Don't forget to create a man page from the XML with xml2man.pl,
+ 19: git add xscreensaver.xcodeproj/xcuserdata/*/xcschemes/*.xcscheme
20: Don't forget to create a man page from the XML with xml2man.pl,
      and update Makefile.in.
- 20: Make a video: -record-animation 3600 -delay 1 -geom 1920x1080+128+64
+ 21: Make a video: -record-animation 3600 -delay 1 -geom 1920x1080+128+64
      ./upload-video.pl NAME
index 05d2c436aaa8b106d6f0ba569d0416815eeaa48e..9377275b7a51b01724d1e9e5f48d7f942dd16d27 100644 (file)
@@ -28,7 +28,7 @@
 - (void) titleTapped:(id) sender
 {
   [[UIApplication sharedApplication]
-    openURL:[NSURL URLWithString:@"http://www.jwz.org/xscreensaver/"]];
+    openURL:[NSURL URLWithString:@"https://www.jwz.org/xscreensaver/"]];
 }
 
 
@@ -65,8 +65,9 @@
   [button addTarget:self
           action:@selector(titleTapped:)
           forControlEvents:UIControlEventTouchUpInside];
-  self.navigationItem.rightBarButtonItem = 
-    [[UIBarButtonItem alloc] initWithCustomView: button];
+  UIBarButtonItem *bi = [[UIBarButtonItem alloc] initWithCustomView: button];
+  self.navigationItem.rightBarButtonItem = bi;
+  [bi release];
   [button release];
 
   // The title bar
index 8e88b86b606e8e6c5fd7f81a0906082850d510e9..bacfd3868a4e9aa53973668e1c12a9f5d09044f7 100644 (file)
      orientation just before the view controller is modal-presented, and
      restore the proper status bar orientation just before the saverView is
      created so it can pick it up in didRotate:. */
-  UIInterfaceOrientation _storedOrientation;
+  // UIInterfaceOrientation _storedOrientation;
+
+  BOOL _showAboutBox;
+  UIView *aboutBox;
+  NSTimer *splashTimer;
 }
 
 @property(nonatomic, retain) NSString *saverName;
   SaverViewController *nonrotating_controller; // Hierarchy 2 (savers)
 
   UIImage *saved_screenshot;
-  UIView *aboutBox;
-  NSTimer *splashTimer;
 
 # endif // USE_IPHONE
 }
 
-- (XScreenSaverView *) makeSaverView: (NSString *) module
-                            withSize: (NSSize) size;
+- (XScreenSaverView *) newSaverView: (NSString *) module
+                           withSize: (NSSize) size;
 - (void) loadSaver: (NSString *)name;
 - (void) selectedSaverDidChange:(NSDictionary *)change;
 
 #else  // USE_IPHONE
 - (void) openPreferences: (NSString *)which;
 - (UIImage *) screenshot;
-- (void)aboutPanel:(UIView *)saverView
-       orientation:(UIInterfaceOrientation)orient;
+- (NSString *) makeDesc:(NSString *)saver
+               yearOnly:(BOOL) yearp;
 #endif // USE_IPHONE
 
 @end
index b3ae2818de0160a9540e0e327a19ee6b139fdaf8..ac010b9fa760d1bbb6e0c6ccea8b6ff96086307e 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2006-2015 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2006-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
@@ -77,7 +77,7 @@
   return allowRotation;
 }
 
-- (NSUInteger)supportedInterfaceOrientations   /* Added in iOS 6 */
+- (UIInterfaceOrientationMask)supportedInterfaceOrientations   /* Added in iOS 6 */
 {
   return UIInterfaceOrientationMaskAll;
 }
 @synthesize saverName;
 
 - (id)initWithSaverRunner:(SaverRunner *)parent
+             showAboutBox:(BOOL)showAboutBox
 {
   self = [super init];
   if (self) {
     _parent = parent;
-    _storedOrientation = UIInterfaceOrientationUnknown;
+    // _storedOrientation = UIInterfaceOrientationUnknown;
+    _showAboutBox = showAboutBox;
 
     self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
     self.wantsFullScreenLayout = YES;
 - (void)dealloc
 {
   [_saverName release];
-  [_saverView dealloc];
+  // iOS: When a UIView deallocs, it doesn't do [UIView removeFromSuperView]
+  // for its subviews, so the subviews end up with a dangling pointer in their
+  // superview properties.
+  [aboutBox removeFromSuperview];
+  [aboutBox release];
+  [_saverView removeFromSuperview];
+  [_saverView release];
   [super dealloc];
 }
 
   UIView *backgroundView = [[UIView alloc] initWithFrame:CGRectNull];
   backgroundView.backgroundColor = [UIColor blackColor];
   self.view = backgroundView;
+  [backgroundView release];
+}
+
+
+- (void)aboutPanel:(UIView *)saverView
+       orientation:(UIInterfaceOrientation)orient
+{
+  if (!_showAboutBox)
+    return;
+
+  NSString *name = _saverName;
+  NSString *year = [_parent makeDesc:_saverName yearOnly:YES];
+
+
+  CGRect frame = [saverView frame];
+  CGFloat rot;
+  CGFloat pt1 = 24;
+  CGFloat pt2 = 14;
+  UIFont *font1 = [UIFont boldSystemFontOfSize:  pt1];
+  UIFont *font2 = [UIFont italicSystemFontOfSize:pt2];
+
+# ifdef __IPHONE_7_0
+  CGSize s = CGSizeMake(frame.size.width, frame.size.height);
+  CGSize tsize1 = [[[NSAttributedString alloc]
+                     initWithString: name
+                     attributes:@{ NSFontAttributeName: font1 }]
+                    boundingRectWithSize: s
+                    options: NSStringDrawingUsesLineFragmentOrigin
+                    context: nil].size;
+  CGSize tsize2 = [[[NSAttributedString alloc]
+                     initWithString: name
+                     attributes:@{ NSFontAttributeName: font2 }]
+                    boundingRectWithSize: s
+                    options: NSStringDrawingUsesLineFragmentOrigin
+                    context: nil].size;
+# else // iOS 6 or Cocoa
+  CGSize tsize1 = [name sizeWithFont:font1
+                   constrainedToSize:CGSizeMake(frame.size.width,
+                                                frame.size.height)];
+  CGSize tsize2 = [year sizeWithFont:font2
+                   constrainedToSize:CGSizeMake(frame.size.width,
+                                                frame.size.height)];
+# endif
+
+  CGSize tsize = CGSizeMake (tsize1.width > tsize2.width ?
+                             tsize1.width : tsize2.width,
+                             tsize1.height + tsize2.height);
+
+  tsize.width  = ceilf(tsize.width);
+  tsize.height = ceilf(tsize.height);
+
+  // Don't know how to find inner margin of UITextView.
+  CGFloat margin = 10;
+  tsize.width  += margin * 4;
+  tsize.height += margin * 2;
+
+  if ([saverView frame].size.width >= 768)
+    tsize.height += pt1 * 3;  // extra bottom margin on iPad
+
+  frame = CGRectMake (0, 0, tsize.width, tsize.height);
+
+  /* Get the text oriented properly, and move it to the bottom of the
+     screen, since many savers have action in the middle.
+   */
+  switch (orient) {
+  case UIInterfaceOrientationLandscapeLeft:
+    rot = -M_PI/2;
+    frame.origin.x = ([saverView frame].size.width
+                      - (tsize.width - tsize.height) / 2
+                      - tsize.height);
+    frame.origin.y = ([saverView frame].size.height - tsize.height) / 2;
+    break;
+  case UIInterfaceOrientationLandscapeRight:
+    rot = M_PI/2;
+    frame.origin.x = -(tsize.width - tsize.height) / 2;
+    frame.origin.y = ([saverView frame].size.height - tsize.height) / 2;
+    break;
+  case UIInterfaceOrientationPortraitUpsideDown:
+    rot = M_PI;
+    frame.origin.x = ([saverView frame].size.width  - tsize.width) / 2;
+    frame.origin.y = 0;
+    break;
+  default:
+    rot = 0;
+    frame.origin.x = ([saverView frame].size.width  - tsize.width) / 2;
+    frame.origin.y =  [saverView frame].size.height - tsize.height;
+    break;
+  }
+
+  if (aboutBox) {
+    [aboutBox removeFromSuperview];
+    [aboutBox release];
+  }
+
+  aboutBox = [[UIView alloc] initWithFrame:frame];
+
+  aboutBox.transform = CGAffineTransformMakeRotation (rot);
+  aboutBox.backgroundColor = [UIColor clearColor];
+
+  /* There seems to be no easy way to stroke the font, so instead draw
+     it 5 times, 4 in black and 1 in yellow, offset by 1 pixel, and add
+     a black shadow to each.  (You'd think the shadow alone would be
+     enough, but there's no way to make it dark enough to be legible.)
+   */
+  for (int i = 0; i < 5; i++) {
+    UITextView *textview;
+    int off = 1;
+    frame.origin.x = frame.origin.y = 0;
+    switch (i) {
+      case 0: frame.origin.x = -off; break;
+      case 1: frame.origin.x =  off; break;
+      case 2: frame.origin.y = -off; break;
+      case 3: frame.origin.y =  off; break;
+    }
+
+    for (int j = 0; j < 2; j++) {
+
+      frame.origin.y = (j == 0 ? 0 : pt1);
+      textview = [[UITextView alloc] initWithFrame:frame];
+      textview.font = (j == 0 ? font1 : font2);
+      textview.text = (j == 0 ? name  : year);
+      textview.textAlignment = NSTextAlignmentCenter;
+      textview.showsHorizontalScrollIndicator = NO;
+      textview.showsVerticalScrollIndicator   = NO;
+      textview.scrollEnabled = NO;
+      textview.editable = NO;
+      textview.userInteractionEnabled = NO;
+      textview.backgroundColor = [UIColor clearColor];
+      textview.textColor = (i == 4 
+                            ? [UIColor yellowColor]
+                            : [UIColor blackColor]);
+
+      CALayer *textLayer = (CALayer *)
+        [textview.layer.sublayers objectAtIndex:0];
+      textLayer.shadowColor   = [UIColor blackColor].CGColor;
+      textLayer.shadowOffset  = CGSizeMake(0, 0);
+      textLayer.shadowOpacity = 1;
+      textLayer.shadowRadius  = 2;
+
+      [aboutBox addSubview:textview];
+    }
+  }
+
+  CABasicAnimation *anim = 
+    [CABasicAnimation animationWithKeyPath:@"opacity"];
+  anim.duration     = 0.3;
+  anim.repeatCount  = 1;
+  anim.autoreverses = NO;
+  anim.fromValue    = [NSNumber numberWithFloat:0.0];
+  anim.toValue      = [NSNumber numberWithFloat:1.0];
+  [aboutBox.layer addAnimation:anim forKey:@"animateOpacity"];
+
+  [saverView addSubview:aboutBox];
+
+  if (splashTimer)
+    [splashTimer invalidate];
+
+  splashTimer =
+    [NSTimer scheduledTimerWithTimeInterval: anim.duration + 2
+             target:self
+             selector:@selector(aboutOff)
+             userInfo:nil
+             repeats:NO];
+}
+
+
+- (void)aboutOff
+{
+  [self aboutOff:FALSE];
+}
+
+- (void)aboutOff:(BOOL)fast
+{
+  if (aboutBox) {
+    if (splashTimer) {
+      [splashTimer invalidate];
+      splashTimer = 0;
+    }
+    if (fast) {
+      aboutBox.layer.opacity = 0;
+      return;
+    }
+
+    CABasicAnimation *anim = 
+      [CABasicAnimation animationWithKeyPath:@"opacity"];
+    anim.duration     = 0.3;
+    anim.repeatCount  = 1;
+    anim.autoreverses = NO;
+    anim.fromValue    = [NSNumber numberWithFloat: 1];
+    anim.toValue      = [NSNumber numberWithFloat: 0];
+    // anim.delegate     = self;
+    aboutBox.layer.opacity = 0;
+    [aboutBox.layer addAnimation:anim forKey:@"animateOpacity"];
+  }
 }
 
 
     [_saverView release];
   }
 
+# if 0
   if (_storedOrientation != UIInterfaceOrientationUnknown) {
     [[UIApplication sharedApplication]
      setStatusBarOrientation:_storedOrientation
      animated:NO];
   }
+# endif
 
-  _saverView = [_parent makeSaverView:_saverName
-                             withSize:parentView.bounds.size];
+  _saverView = [_parent newSaverView:_saverName
+                            withSize:parentView.bounds.size];
 
   if (! _saverView) {
     [[[UIAlertView alloc] initWithTitle: _saverName
   }
 
   _saverView.delegate = _parent;
+  _saverView.autoresizingMask =
+    UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
 
   [self.view addSubview:_saverView];
 
   // heirarchy.
   [_saverView becomeFirstResponder]; // For shakes on iOS 6.
   [_saverView startAnimation];
-  [_parent aboutPanel:_saverView orientation:_storedOrientation];
+  [self aboutPanel:_saverView
+       orientation:/* _storedOrientation */ UIInterfaceOrientationPortrait];
 }
 
 
 - (void)viewDidAppear:(BOOL)animated
 {
+  [super viewDidAppear:animated];
   [self createSaverView];
 }
 
 
 - (BOOL)shouldAutorotate                       /* Added in iOS 6 */
 {
-  return NO;
+  return YES;
 }
 
 
-- (NSUInteger)supportedInterfaceOrientations   /* Added in iOS 6 */
+- (UIInterfaceOrientationMask)supportedInterfaceOrientations   /* Added in iOS 6 */
 {
   // Lies from the iOS docs:
   // "This method is only called if the view controller's shouldAutorotate
   // method returns YES."
-  return UIInterfaceOrientationMaskPortrait;
+  return UIInterfaceOrientationMaskAll;
 }
 
 
+/*
 - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
 {
   return UIInterfaceOrientationPortrait;
 }
+*/
 
 
 - (void)setSaverName:(NSString *)name
   [name retain];
   [_saverName release];
   _saverName = name;
-  _storedOrientation = [UIApplication sharedApplication].statusBarOrientation;
+  // _storedOrientation =
+  //   [UIApplication sharedApplication].statusBarOrientation;
 
   if (_saverView)
     [self createSaverView];
 }
 
+
+- (void)viewWillTransitionToSize: (CGSize)size
+       withTransitionCoordinator: 
+        (id<UIViewControllerTransitionCoordinator>) coordinator
+{
+  [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
+  if (!_saverView)
+    return;
+
+  [CATransaction begin];
+
+  // Completely suppress the rotation animation, since we
+  // will not (visually) be rotating at all.
+  if ([_saverView suppressRotationAnimation])
+    [CATransaction setDisableActions:YES];
+
+  [self aboutOff:TRUE];  // It does goofy things if we rotate while it's up
+
+  [coordinator animateAlongsideTransition:^
+               (id <UIViewControllerTransitionCoordinatorContext> context) {
+    // This executes repeatedly during the rotation.
+  } completion:^(id <UIViewControllerTransitionCoordinatorContext> context) {
+    // This executes once when the rotation has finished.
+    [CATransaction commit];
+    [_saverView orientationChanged];
+  }];
+  // No code goes here, as it would execute before the above completes.
+}
+
 @end
 
 #endif // USE_IPHONE
 @implementation SaverRunner
 
 
-- (XScreenSaverView *) makeSaverView: (NSString *) module
-                            withSize: (NSSize) size
+- (XScreenSaverView *) newSaverView: (NSString *) module
+                           withSize: (NSSize) size
 {
   Class new_class = 0;
 
    */
 # ifndef USE_IPHONE
   if ([saverNames count] == 1) {
-    putenv (strdup ("XSCREENSAVER_STANDALONE=1"));
+    setenv ("XSCREENSAVER_STANDALONE", "1", 1);
   }
 # endif
 
@@ -516,8 +757,8 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str)
 
 - (void) openPreferences: (NSString *) saver
 {
-  XScreenSaverView *saverView = [self makeSaverView:saver
-                                           withSize:CGSizeMake(0, 0)];
+  XScreenSaverView *saverView = [self newSaverView:saver
+                                          withSize:CGSizeMake(0, 0)];
   if (! saverView) return;
 
   NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
@@ -526,8 +767,6 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str)
 
   [rotating_nav pushViewController: [saverView configureView]
                       animated:YES];
-
-  [saverView release];
 }
 
 
@@ -567,15 +806,15 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str)
     }
 
     NSSize size = [cv frame].size;
-    ScreenSaverView *new_view = [self makeSaverView:name withSize: size];
+    ScreenSaverView *new_view = [self newSaverView:name withSize: size];
     NSAssert (new_view, @"unable to make a saver view");
 
     [new_view setFrame: (old_view ? [old_view frame] : [cv frame])];
     [sup addSubview: new_view];
     [win makeFirstResponder:new_view];
     [new_view setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
-    [new_view retain];
     [new_view startAnimation];
+    [new_view release];
   }
 
   NSUserDefaultsController *ctl =
@@ -584,7 +823,7 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str)
 
 # else  // USE_IPHONE
 
-#  if TARGET_IPHONE_SIMULATOR
+#  if !defined __OPTIMIZE__ || TARGET_IPHONE_SIMULATOR
   NSLog (@"selecting saver \"%@\"", name);
 #  endif
 
@@ -608,7 +847,7 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str)
     return;
   }
 
-# if TARGET_IPHONE_SIMULATOR
+# if !defined __OPTIMIZE__ || TARGET_IPHONE_SIMULATOR
   UIScreen *screen = [UIScreen mainScreen];
 
   /* 'nativeScale' is very confusing.
@@ -685,7 +924,9 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str)
   // presentation full screen.
   rotating_nav.modalPresentationStyle = UIModalPresentationFullScreen;
 
-  nonrotating_controller = [[SaverViewController alloc] initWithSaverRunner:self];
+  nonrotating_controller = [[SaverViewController alloc]
+                            initWithSaverRunner:self
+                            showAboutBox:[saverNames count] != 1];
   nonrotating_controller.saverName = name;
 
   /* LAUNCH: */
@@ -712,197 +953,17 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str)
   [d setValue:[bd objectForKey:@"CFBundleShortVersionString"] 
      forKey:@"ApplicationVersion"];
   [d setValue:[bd objectForKey:@"NSHumanReadableCopyright"] forKey:@"Copy"];
-  [d setValue:[[NSAttributedString alloc]
-                initWithString: (NSString *) 
-                  [bd objectForKey:@"CFBundleGetInfoString"]]
-     forKey:@"Credits"];
-
+  NSAttributedString *s = [[NSAttributedString alloc]
+                           initWithString: (NSString *)
+                           [bd objectForKey:@"CFBundleGetInfoString"]];
+  [d setValue:s forKey:@"Credits"];
+  [s release];
+  
   [[NSApplication sharedApplication]
     orderFrontStandardAboutPanelWithOptions:d];
 }
 
-#else  // USE_IPHONE
-
-- (void)aboutPanel:(UIView *)saverView
-       orientation:(UIInterfaceOrientation)orient
-{
-  if ([saverNames count] == 1)
-    return;
-
-  NSString *name = saverName;
-  NSString *year = [self makeDesc:saverName yearOnly:YES];
-
-
-  CGRect frame = [saverView frame];
-  CGFloat rot;
-  CGFloat pt1 = 24;
-  CGFloat pt2 = 14;
-  UIFont *font1 = [UIFont boldSystemFontOfSize:  pt1];
-  UIFont *font2 = [UIFont italicSystemFontOfSize:pt2];
-
-# ifdef __IPHONE_7_0
-  CGSize s = CGSizeMake(frame.size.width, frame.size.height);
-  CGSize tsize1 = [[[NSAttributedString alloc]
-                     initWithString: name
-                     attributes:@{ NSFontAttributeName: font1 }]
-                    boundingRectWithSize: s
-                    options: NSStringDrawingUsesLineFragmentOrigin
-                    context: nil].size;
-  CGSize tsize2 = [[[NSAttributedString alloc]
-                     initWithString: name
-                     attributes:@{ NSFontAttributeName: font2 }]
-                    boundingRectWithSize: s
-                    options: NSStringDrawingUsesLineFragmentOrigin
-                    context: nil].size;
-# else // iOS 6 or Cocoa
-  CGSize tsize1 = [name sizeWithFont:font1
-                   constrainedToSize:CGSizeMake(frame.size.width,
-                                                frame.size.height)];
-  CGSize tsize2 = [year sizeWithFont:font2
-                   constrainedToSize:CGSizeMake(frame.size.width,
-                                                frame.size.height)];
-# endif
-
-  CGSize tsize = CGSizeMake (tsize1.width > tsize2.width ?
-                             tsize1.width : tsize2.width,
-                             tsize1.height + tsize2.height);
-
-  tsize.width  = ceilf(tsize.width);
-  tsize.height = ceilf(tsize.height);
-
-  // Don't know how to find inner margin of UITextView.
-  CGFloat margin = 10;
-  tsize.width  += margin * 4;
-  tsize.height += margin * 2;
-
-  if ([saverView frame].size.width >= 768)
-    tsize.height += pt1 * 3;  // extra bottom margin on iPad
-
-  frame = CGRectMake (0, 0, tsize.width, tsize.height);
-
-  /* Get the text oriented properly, and move it to the bottom of the
-     screen, since many savers have action in the middle.
-   */
-  switch (orient) {
-  case UIInterfaceOrientationLandscapeLeft:
-    rot = -M_PI/2;
-    frame.origin.x = ([saverView frame].size.width
-                      - (tsize.width - tsize.height) / 2
-                      - tsize.height);
-    frame.origin.y = ([saverView frame].size.height - tsize.height) / 2;
-    break;
-  case UIInterfaceOrientationLandscapeRight:
-    rot = M_PI/2;
-    frame.origin.x = -(tsize.width - tsize.height) / 2;
-    frame.origin.y = ([saverView frame].size.height - tsize.height) / 2;
-    break;
-  case UIInterfaceOrientationPortraitUpsideDown:
-    rot = M_PI;
-    frame.origin.x = ([saverView frame].size.width  - tsize.width) / 2;
-    frame.origin.y = 0;
-    break;
-  default:
-    rot = 0;
-    frame.origin.x = ([saverView frame].size.width  - tsize.width) / 2;
-    frame.origin.y =  [saverView frame].size.height - tsize.height;
-    break;
-  }
-
-  if (aboutBox)
-    [aboutBox removeFromSuperview];
-
-  aboutBox = [[UIView alloc] initWithFrame:frame];
-
-  aboutBox.transform = CGAffineTransformMakeRotation (rot);
-  aboutBox.backgroundColor = [UIColor clearColor];
-
-  /* There seems to be no easy way to stroke the font, so instead draw
-     it 5 times, 4 in black and 1 in yellow, offset by 1 pixel, and add
-     a black shadow to each.  (You'd think the shadow alone would be
-     enough, but there's no way to make it dark enough to be legible.)
-   */
-  for (int i = 0; i < 5; i++) {
-    UITextView *textview;
-    int off = 1;
-    frame.origin.x = frame.origin.y = 0;
-    switch (i) {
-      case 0: frame.origin.x = -off; break;
-      case 1: frame.origin.x =  off; break;
-      case 2: frame.origin.y = -off; break;
-      case 3: frame.origin.y =  off; break;
-    }
-
-    for (int j = 0; j < 2; j++) {
-
-      frame.origin.y = (j == 0 ? 0 : pt1);
-      textview = [[UITextView alloc] initWithFrame:frame];
-      textview.font = (j == 0 ? font1 : font2);
-      textview.text = (j == 0 ? name  : year);
-      textview.textAlignment = NSTextAlignmentCenter;
-      textview.showsHorizontalScrollIndicator = NO;
-      textview.showsVerticalScrollIndicator   = NO;
-      textview.scrollEnabled = NO;
-      textview.editable = NO;
-      textview.userInteractionEnabled = NO;
-      textview.backgroundColor = [UIColor clearColor];
-      textview.textColor = (i == 4 
-                            ? [UIColor yellowColor]
-                            : [UIColor blackColor]);
-
-      CALayer *textLayer = (CALayer *)
-        [textview.layer.sublayers objectAtIndex:0];
-      textLayer.shadowColor   = [UIColor blackColor].CGColor;
-      textLayer.shadowOffset  = CGSizeMake(0, 0);
-      textLayer.shadowOpacity = 1;
-      textLayer.shadowRadius  = 2;
-
-      [aboutBox addSubview:textview];
-    }
-  }
-
-  CABasicAnimation *anim = 
-    [CABasicAnimation animationWithKeyPath:@"opacity"];
-  anim.duration     = 0.3;
-  anim.repeatCount  = 1;
-  anim.autoreverses = NO;
-  anim.fromValue    = [NSNumber numberWithFloat:0.0];
-  anim.toValue      = [NSNumber numberWithFloat:1.0];
-  [aboutBox.layer addAnimation:anim forKey:@"animateOpacity"];
-
-  [saverView addSubview:aboutBox];
-
-  if (splashTimer)
-    [splashTimer invalidate];
-
-  splashTimer =
-    [NSTimer scheduledTimerWithTimeInterval: anim.duration + 2
-             target:self
-             selector:@selector(aboutOff)
-             userInfo:nil
-             repeats:NO];
-}
-
-
-- (void)aboutOff
-{
-  if (aboutBox) {
-    if (splashTimer) {
-      [splashTimer invalidate];
-      splashTimer = 0;
-    }
-    CABasicAnimation *anim = 
-      [CABasicAnimation animationWithKeyPath:@"opacity"];
-    anim.duration     = 0.3;
-    anim.repeatCount  = 1;
-    anim.autoreverses = NO;
-    anim.fromValue    = [NSNumber numberWithFloat: 1];
-    anim.toValue      = [NSNumber numberWithFloat: 0];
-    anim.delegate     = self;
-    aboutBox.layer.opacity = 0;
-    [aboutBox.layer addAnimation:anim forKey:@"animateOpacity"];
-  }
-}
-#endif // USE_IPHONE
+#endif // !USE_IPHONE
 
 
 
@@ -942,12 +1003,6 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str)
     NSString *name = [[p lastPathComponent] stringByDeletingPathExtension];
 
 # ifdef USE_IPHONE
-
-#  ifdef __OPTIMIZE__
-    // Do not show TestX11 in release builds.
-    if (! [name caseInsensitiveCompare:@"testx11"])
-      continue;
-#  endif
     // Get the saver name's capitalization right by reading the XML file.
 
     p = [dir stringByAppendingPathComponent: p];
@@ -1068,6 +1123,7 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str)
   NSRect r = [popup frame];
   r.size.width = max_width;
   [popup setFrame:r];
+  [popup autorelease];
   return popup;
 }
 
@@ -1185,9 +1241,23 @@ FAIL:
      and/or 8.2), this confuses the UINavigationController, so put the
      orientation back to portrait before dismissing the SaverViewController.
    */
+# if 0
   [[UIApplication sharedApplication]
    setStatusBarOrientation:UIInterfaceOrientationPortrait
    animated:NO];
+# endif
+
+  /* Make sure the most-recently-run saver is visible.  Sometimes it ends
+     up scrolled half a line off the bottom of the screen.
+   */
+  if (saverName) {
+    for (UIViewController *v in [rotating_nav viewControllers]) {
+      if ([v isKindOfClass:[SaverListController class]]) {
+        [(SaverListController *)v scrollTo: saverName];
+        break;
+      }
+    }
+  }
 
   [rotating_nav dismissViewControllerAnimated:YES completion:^() {
     [nonrotating_controller release];
@@ -1301,8 +1371,10 @@ FAIL:
     [pbox setTitlePosition:NSNoTitle];
     [pbox setBorderType:NSNoBorder];
     [pbox addSubview:gbox];
+    [gbox release];
     if (menu) [pbox addSubview:menu];
     if (pb)   [pbox addSubview:pb];
+    [pb release];
     [pbox sizeToFit];
 
     [pb   setAutoresizingMask:NSViewMinXMargin|NSViewMaxXMargin];
@@ -1334,10 +1406,12 @@ FAIL:
                                    screen:screen];
   [win setMinSize:[win frameRectForContentRect:rect].size];
   [[win contentView] addSubview: (pbox ? (NSView *) pbox : (NSView *) sv)];
+  [pbox release];
 
   [win makeKeyAndOrderFront:win];
   
   [sv startAnimation]; // this is the dummy saver
+  [sv autorelease];
 
   count++;
 
@@ -1386,6 +1460,7 @@ FAIL:
     [a addObject: win];
     // This prevents clicks from being seen by savers.
     // [win setMovableByWindowBackground:YES];
+    [win release];
   }
 # else  // USE_IPHONE
 
@@ -1419,6 +1494,7 @@ FAIL:
                                 descriptions:[self makeDescTable]];
   [rotating_nav pushViewController:menu animated:YES];
   [menu becomeFirstResponder];
+  [menu autorelease];
 
   application.applicationSupportsShakeToEdit = YES;
 
index d28e99aad1023b33921bde5558e43c1d6332c70c..b3b74991c023158f18aadc443923e484cd5995d5 100644 (file)
@@ -7,29 +7,29 @@
        <key>CFBundleExecutable</key>
        <string>${EXECUTABLE_NAME}</string>
        <key>CFBundleGetInfoString</key>
-       <string>5.34</string>
+       <string>5.35</string>
        <key>CFBundleIconFile</key>
        <string>SaverRunner</string>
        <key>CFBundleIdentifier</key>
-       <string>${BUNDLE_IDENTIFIER}</string>
+       <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleLongVersionString</key>
-       <string>5.34</string>
+       <string>5.35</string>
        <key>CFBundleName</key>
        <string>${PRODUCT_NAME}</string>
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleShortVersionString</key>
-       <string>5.34</string>
+       <string>5.35</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.34</string>
+       <string>5.35</string>
        <key>LSMinimumSystemVersion</key>
        <string>${MACOSX_DEPLOYMENT_TARGET}</string>
        <key>NSHumanReadableCopyright</key>
-       <string>5.34</string>
+       <string>5.35</string>
        <key>NSMainNibFile</key>
        <string>SaverRunner</string>
        <key>NSPrincipalClass</key>
index b855083285f8998e08052bdad5d602c40d8ed448..692f7a012ca180f98a876dc9d9e15bb24249fad2 100644 (file)
@@ -4,36 +4,36 @@
 <dict>
        <key>CFBundleDevelopmentRegion</key>
        <string>English</string>
+       <key>CFBundleDisplayName</key>
+       <string>XScreenSaver</string>
        <key>CFBundleExecutable</key>
        <string>${EXECUTABLE_NAME}</string>
        <key>CFBundleGetInfoString</key>
-       <string>5.34</string>
+       <string>5.35</string>
        <key>CFBundleIconFile</key>
        <string>SaverRunner</string>
        <key>CFBundleIdentifier</key>
-       <string>$(BUNDLE_IDENTIFIER)</string>
+       <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleLongVersionString</key>
-       <string>5.34</string>
+       <string>5.35</string>
        <key>CFBundleName</key>
        <string>${PRODUCT_NAME}</string>
-       <key>CFBundleDisplayName</key>
-       <string>XScreenSaver</string>
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleShortVersionString</key>
-       <string>5.34</string>
+       <string>5.35</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.34</string>
+       <string>5.35</string>
        <key>LSMinimumSystemVersion</key>
        <string>${MACOSX_DEPLOYMENT_TARGET}</string>
        <key>LSUIElement</key>
        <true/>
        <key>NSHumanReadableCopyright</key>
-       <string>5.34</string>
+       <string>5.35</string>
        <key>NSMainNibFile</key>
        <string>Updater</string>
        <key>NSPrincipalClass</key>
@@ -41,7 +41,7 @@
        <key>SUEnableSystemProfiling</key>
        <true/>
        <key>SUFeedURL</key>
-       <string>http://www.jwz.org/xscreensaver/updates.xml</string>
+       <string>https://www.jwz.org/xscreensaver/updates.xml</string>
        <key>SUPublicDSAKeyFile</key>
        <string>sparkle_dsa_pub.pem</string>
        <key>SUScheduledCheckInterval</key>
index cf23f9c0b18e91b83fa249202a4e5882ffaa40df..9af74f5fd0cb1bfaa9375e1f381bc967dea6e04e 100644 (file)
@@ -7,7 +7,7 @@
        <key>CFBundleExecutable</key>
        <string>${EXECUTABLE_NAME}</string>
        <key>CFBundleIdentifier</key>
-       <string>${BUNDLE_IDENTIFIER}</string>
+       <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleName</key>
        <key>CFBundlePackageType</key>
        <string>BNDL</string>
        <key>CFBundleShortVersionString</key>
-       <string>5.34</string>
+       <string>5.35</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.34</string>
+       <string>5.35</string>
        <key>LSMinimumSystemVersion</key>
        <string>10.4</string>
        <key>NSMainNibFile</key>
index ec08b90458d4300563b5f6befc76aba4d7f4082f..576c8ab3e805f6efe71131c17a6b8dc88ab9a7e7 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2006-2014 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2006-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
@@ -129,6 +129,7 @@ typedef enum { SimpleXMLCommentKind,
     [n setName:key];
     [n setObjectValue:val];
     [attributes addObject:n];
+    [n release];
   }
 }
 
@@ -543,7 +544,7 @@ static void layout_group (NSView *group, BOOL horiz_p);
                            opts:(const XrmOptionDescRec *)opts_array
                          valRet:(NSString **)val_ret
 {
-  char buf[255];
+  char buf[1280];
   char *tail = 0;
   NSAssert(cmdline_switch, @"cmdline switch is null");
   if (! [cmdline_switch getCString:buf maxLength:sizeof(buf)
@@ -1190,6 +1191,8 @@ hreffify (NSText *nstext)
   [self parseAttrs:dict node:node];
   NSString *name  = [dict objectForKey:@"name"];
   NSString *label = [dict objectForKey:@"_label"];
+  [dict release];
+  dict = 0;
     
   NSAssert1 (label, @"no _label in %@", [node name]);
   NSAssert1 (name, @"no name in \"%@\"", label);
@@ -1223,6 +1226,7 @@ hreffify (NSText *nstext)
   [lab setAutoresizingMask: (UIViewAutoresizingFlexibleWidth |
                              UIViewAutoresizingFlexibleHeight)];
 # endif // USE_IPHONE
+  [lab autorelease];
   return lab;
 }
 
@@ -1240,6 +1244,8 @@ hreffify (NSText *nstext)
   NSString *label     = [dict objectForKey:@"_label"];
   NSString *arg_set   = [dict objectForKey:@"arg-set"];
   NSString *arg_unset = [dict objectForKey:@"arg-unset"];
+  [dict release];
+  dict = 0;
   
   if (!label) {
     NSAssert1 (0, @"no _label in %@", [node name]);
@@ -1283,7 +1289,6 @@ hreffify (NSText *nstext)
   [self placeChild:lab on:parent];
   UISwitch *button = [[UISwitch alloc] initWithFrame:rect];
   [self placeChild:button on:parent right:YES];
-  [lab release];
 
 # endif // USE_IPHONE
   
@@ -1319,6 +1324,8 @@ hreffify (NSText *nstext)
   NSString *high       = [dict objectForKey:@"high"];
   NSString *def        = [dict objectForKey:@"default"];
   NSString *cvt        = [dict objectForKey:@"convert"];
+  [dict release];
+  dict = 0;
   
   NSAssert1 (arg,  @"no arg in %@", label);
   NSAssert1 (type, @"no type in %@", label);
@@ -1372,6 +1379,7 @@ hreffify (NSText *nstext)
     while (range2 > max_ticks)
       range2 /= 10;
 
+# ifndef USE_IPHONE
     // If we have elided ticks, leave it at the max number of ticks.
     if (range != range2 && range2 < max_ticks)
       range2 = max_ticks;
@@ -1380,7 +1388,6 @@ hreffify (NSText *nstext)
     if (float_p && range2 < max_ticks)
       range2 = max_ticks;
 
-# ifndef USE_IPHONE
     [slider setNumberOfTickMarks:range2];
 
     [slider setAllowsTickMarkValuesOnly:
@@ -1403,7 +1410,6 @@ hreffify (NSText *nstext)
         [lab setFont:[NSFont boldSystemFontOfSize:s]];
       }
 # endif
-      [lab release];
     }
     
     if (low_label) {
@@ -1423,8 +1429,6 @@ hreffify (NSText *nstext)
       [lab setLineBreakMode:NSLineBreakByClipping];
       [self placeChild:lab on:parent right:(label ? YES : NO)];
 # endif // USE_IPHONE
-
-      [lab release];
      }
     
 # ifndef USE_IPHONE
@@ -1460,7 +1464,6 @@ hreffify (NSText *nstext)
       [lab setLineBreakMode:NSLineBreakByClipping];
 # endif
       [self placeChild:lab on:parent right:YES];
-      [lab release];
      }
 
     [self bindSwitch:slider cmdline:arg];
@@ -1500,7 +1503,6 @@ hreffify (NSText *nstext)
       rect.size.height = [txt frame].size.height;
       [lab setFrame:rect];
       [self placeChild:lab on:parent];
-      [lab release];
      }
     
     [self placeChild:txt on:parent right:(label ? YES : NO)];
@@ -1601,6 +1603,8 @@ set_menu_item_object (NSMenuItem *item, NSObject *obj)
   //
   NSMutableDictionary *dict = [@{ @"id": @"", } mutableCopy];
   [self parseAttrs:dict node:node];
+  [dict release];
+  dict = 0;
   
   NSRect rect;
   rect.origin.x = rect.origin.y = 0;
@@ -1653,6 +1657,8 @@ set_menu_item_object (NSMenuItem *item, NSObject *obj)
     [self parseAttrs:dict2 node:child];
     NSString *label   = [dict2 objectForKey:@"_label"];
     NSString *arg_set = [dict2 objectForKey:@"arg-set"];
+    [dict2 release];
+    dict2 = 0;
     
     if (!label) {
       NSAssert1 (0, @"no _label in %@", [child name]);
@@ -1792,6 +1798,7 @@ set_menu_item_object (NSMenuItem *item, NSObject *obj)
     [b setLineBreakMode:NSLineBreakByTruncatingHead];
     [b setFont:[NSFont boldSystemFontOfSize: FONT_SIZE]];
     [self placeChild:b on:parent];
+    [b release];
     i++;
   }
 
@@ -1829,6 +1836,7 @@ set_menu_item_object (NSMenuItem *item, NSObject *obj)
   rect.size.height = 50;  // sized later
 # ifndef USE_IPHONE
   NSText *lab = [[NSText alloc] initWithFrame:rect];
+  [lab autorelease];
   [lab setEditable:NO];
   [lab setDrawsBackground:NO];
   [lab setHorizontallyResizable:YES];
@@ -1850,6 +1858,7 @@ set_menu_item_object (NSMenuItem *item, NSObject *obj)
   HTMLLabel *lab = [[HTMLLabel alloc] 
                      initWithText:text
                      font:[NSFont systemFontOfSize: [NSFont systemFontSize]]];
+  [lab autorelease];
   [lab setFrame:rect];
   [lab sizeToFit];
 #  endif // USE_HTML_LABELS
@@ -1859,7 +1868,6 @@ set_menu_item_object (NSMenuItem *item, NSObject *obj)
 # endif // USE_IPHONE
 
   [self placeChild:lab on:parent];
-  [lab release];
 }
 
 
@@ -1877,6 +1885,8 @@ set_menu_item_object (NSMenuItem *item, NSObject *obj)
   [self parseAttrs:dict node:node];
   NSString *label = [dict objectForKey:@"_label"];
   NSString *arg   = [dict objectForKey:@"arg"];
+  [dict release];
+  dict = 0;
 
   if (!label && label_p) {
     NSAssert1 (0, @"no _label in %@", [node name]);
@@ -1927,7 +1937,6 @@ set_menu_item_object (NSMenuItem *item, NSObject *obj)
   if (label) {
     LABEL *lab = [self makeLabel:label];
     [self placeChild:lab on:parent];
-    [lab release];
   }
 
   [self placeChild:txt on:parent right:(label ? YES : NO)];
@@ -1954,6 +1963,8 @@ set_menu_item_object (NSMenuItem *item, NSObject *obj)
   [self parseAttrs:dict node:node];
   NSString *label = [dict objectForKey:@"_label"];
   NSString *arg   = [dict objectForKey:@"arg"];
+  [dict release];
+  dict = 0;
 
   if (!label && label_p) {
     NSAssert1 (0, @"no _label in %@", [node name]);
@@ -1985,7 +1996,6 @@ set_menu_item_object (NSMenuItem *item, NSObject *obj)
   if (label) {
     lab = [self makeLabel:label];
     [self placeChild:lab on:parent];
-    [lab release];
   }
 
   [self placeChild:txt on:parent right:(label ? YES : NO)];
@@ -2043,21 +2053,10 @@ do_file_selector (NSTextField *txt, BOOL dirs_p)
   [panel setCanChooseFiles:!dirs_p];
   [panel setCanChooseDirectories:dirs_p];
 
-  NSString *file = [txt stringValue];
-  if ([file length] <= 0) {
-    file = NSHomeDirectory();
-    if (dirs_p)
-      file = [file stringByAppendingPathComponent:@"Pictures"];
-  }
-
-//  NSString *dir = [file stringByDeletingLastPathComponent];
-
-  int result = [panel runModalForDirectory:file //dir
-                                      file:nil //[file lastPathComponent]
-                                     types:nil];
+  int result = [panel runModal];
   if (result == NSOKButton) {
-    NSArray *files = [panel filenames];
-    file = ([files count] > 0 ? [files objectAtIndex:0] : @"");
+    NSArray *files = [panel URLs];
+    NSString *file = ([files count] > 0 ? [[files objectAtIndex:0] path] : @"");
     file = [file stringByAbbreviatingWithTildeInPath];
     [txt setStringValue:file];
 
@@ -2070,22 +2069,6 @@ do_file_selector (NSTextField *txt, BOOL dirs_p)
     if ([path hasPrefix:@"values."])  // WTF.
       path = [path substringFromIndex:7];
     [[prefs values] setValue:file forKey:path];
-
-#if 0
-    // make sure the end of the string is visible.
-    NSText *fe = [[txt window] fieldEditor:YES forObject:txt];
-    NSRange range;
-    range.location = [file length]-3;
-    range.length = 1;
-    if (! [[txt window] makeFirstResponder:[txt window]])
-      [[txt window] endEditingFor:nil];
-//    [[txt window] makeFirstResponder:nil];
-    [fe setSelectedRange:range];
-//    [tv scrollRangeToVisible:range];
-//    [txt setNeedsDisplay:YES];
-//    [[txt cell] setNeedsDisplay:YES];
-//    [txt selectAll:txt];
-#endif
   }
 }
 
@@ -2189,6 +2172,9 @@ find_text_field_of_button (NSButton *button)
 
   [self placeChild:matrix on:group];
   [self placeChild:rgroup on:group right:YES];
+  [proto release];
+  [matrix release];
+  [rgroup release];
 
   NSXMLNode *node2;
 
@@ -2212,7 +2198,7 @@ find_text_field_of_button (NSButton *button)
               @"arg-set": @"-text-mode date",
               @"_label":  @"Display the date and time" }];
   [node3 setParent: node2];
-  //[node3 release];
+  [node3 autorelease];
 
   node3 = [[NSXMLElement alloc] initWithName:@"option"];
   [node3 setAttributesAsDictionary:
@@ -2220,16 +2206,17 @@ find_text_field_of_button (NSButton *button)
               @"arg-set": @"-text-mode literal",
               @"_label":  @"Display static text" }];
   [node3 setParent: node2];
-  //[node3 release];
+  [node3 autorelease];
 
   node3 = [[NSXMLElement alloc] initWithName:@"option"];
   [node3 setAttributesAsDictionary:
            @{ @"id":     @"url",                           
               @"_label": @"Display the contents of a URL" }];
   [node3 setParent: node2];
-  //[node3 release];
+  [node3 autorelease];
 
   [self makeOptionMenu:node2 on:rgroup];
+  [node2 release];
 
 # endif // USE_IPHONE
 
@@ -2250,6 +2237,7 @@ find_text_field_of_button (NSButton *button)
         withLabel:YES
 # endif
         horizontal:NO];
+  [node2 release];
 
 //  rect = [last_child(rgroup) frame];
 
@@ -2270,6 +2258,7 @@ find_text_field_of_button (NSButton *button)
               @"arg": @"-text-file %" }];
   [self makeFileSelector:node2 on:rgroup
         dirsOnly:NO withLabel:NO editable:NO];
+  [node2 release];
 # endif // !USE_IPHONE
 
 //  rect = [last_child(rgroup) frame];
@@ -2290,6 +2279,7 @@ find_text_field_of_button (NSButton *button)
         withLabel:YES
 # endif
         horizontal:NO];
+  [node2 release];
 
 //  rect = [last_child(rgroup) frame];
 
@@ -2302,6 +2292,7 @@ find_text_field_of_button (NSButton *button)
                  @"arg": @"-text-program %",
               }];
     [self makeTextField:node2 on:rgroup withLabel:NO horizontal:NO];
+    [node2 release];
   }
 
 //  rect = [last_child(rgroup) frame];
@@ -2357,6 +2348,8 @@ find_text_field_of_button (NSButton *button)
   [box sizeToFit];
 
   [self placeChild:box on:parent];
+  [group release];
+  [box release];
 
 # endif // !USE_IPHONE
 }
@@ -2393,6 +2386,7 @@ find_text_field_of_button (NSButton *button)
               @"arg-unset": @"-no-grab-desktop",
             }];
   [self makeCheckbox:node2 on:parent];
+  [node2 release];
 
   node2 = [[NSXMLElement alloc] initWithName:@"boolean"];
   [node2 setAttributesAsDictionary:
@@ -2401,6 +2395,7 @@ find_text_field_of_button (NSButton *button)
               @"arg-set": @"-choose-random-images",
             }];
   [self makeCheckbox:node2 on:parent];
+  [node2 release];
 
   node2 = [[NSXMLElement alloc] initWithName:@"string"];
   [node2 setAttributesAsDictionary:
@@ -2410,6 +2405,7 @@ find_text_field_of_button (NSButton *button)
             }];
   [self makeFileSelector:node2 on:parent
         dirsOnly:YES withLabel:YES editable:YES];
+  [node2 release];
 
 # undef SCREENS
 # undef PHOTOS
@@ -2426,7 +2422,6 @@ find_text_field_of_button (NSButton *button)
   r2.origin.x += 20;
   r2.origin.y += 14;
   [lab2 setFrameOrigin:r2.origin];
-  [lab2 release];
 # endif // USE_IPHONE
 }
 
@@ -2468,6 +2463,7 @@ find_text_field_of_button (NSButton *button)
               @"arg-unset": @"-no-" SUSUEnableAutomaticChecksKey,
             }];
   [self makeCheckbox:node2 on:group];
+  [node2 release];
 
   // <select ...>
 
@@ -2483,7 +2479,7 @@ find_text_field_of_button (NSButton *button)
               @"arg-set": @"-" SUScheduledCheckIntervalKey " 3600",
               @"_label":  @"Hourly" }];
   [node3 setParent: node2];
-  //[node3 release];
+  [node3 autorelease];
 
   node3 = [[NSXMLElement alloc] initWithName:@"option"];
   [node3 setAttributesAsDictionary:
@@ -2491,7 +2487,7 @@ find_text_field_of_button (NSButton *button)
               @"arg-set": @"-" SUScheduledCheckIntervalKey " 86400",
               @"_label":  @"Daily" }];
   [node3 setParent: node2];
-  //[node3 release];
+  [node3 autorelease];
 
   node3 = [[NSXMLElement alloc] initWithName:@"option"];
   [node3 setAttributesAsDictionary:
@@ -2500,7 +2496,7 @@ find_text_field_of_button (NSButton *button)
               @"_label": @"Weekly",
             }];
   [node3 setParent: node2];
-  //[node3 release];
+  [node3 autorelease];
 
   node3 = [[NSXMLElement alloc] initWithName:@"option"];
   [node3 setAttributesAsDictionary:
@@ -2509,10 +2505,11 @@ find_text_field_of_button (NSButton *button)
               @"_label":  @"Monthly",
              }];
   [node3 setParent: node2];
-  //[node3 release];
+  [node3 autorelease];
 
   // </option>
   [self makeOptionMenu:node2 on:group];
+  [node2 release];
 
   // </hgroup>
   layout_group (group, TRUE);
@@ -2681,6 +2678,8 @@ last_child (NSView *parent)
   [box sizeToFit];
 
   [self placeChild:box on:parent];
+  [group release];
+  [box release];
 # endif // !USE_IPHONE
 }
 
@@ -3136,6 +3135,7 @@ wrap_with_buttons (NSWindow *window, NSView *panel)
         attributes:(NSDictionary *)attrs
 {
   NSXMLElement *e = [[NSXMLElement alloc] initWithName:elt];
+  [e autorelease];
   [e setKind:SimpleXMLElementKind];
   [e setAttributesAsDictionary:attrs];
   NSXMLElement *p = xml_parsing;
@@ -3169,6 +3169,7 @@ wrap_with_buttons (NSWindow *window, NSView *panel)
   NSXMLElement *p = xml_parsing;
   [e setParent:p];
   [e setObjectValue: string];
+  [e autorelease];
 }
 
 
@@ -3480,6 +3481,7 @@ wrap_with_buttons (NSWindow *window, NSView *panel)
         [label setFrame:r];
         [label setFont:[NSFont boldSystemFontOfSize: FONT_SIZE]];
         [box addSubview: label];
+        [box autorelease];
 
         ctl = box;
       }
@@ -3566,6 +3568,7 @@ wrap_with_buttons (NSWindow *window, NSView *panel)
         [box addSubview: left];
         [box addSubview: right];
         [box addSubview: mid];
+        [box autorelease];
 
         ctl = box;
       }
@@ -3655,6 +3658,7 @@ wrap_with_buttons (NSWindow *window, NSView *panel)
   TextModeTransformer *t = [[TextModeTransformer alloc] init];
   [NSValueTransformer setValueTransformer:t
                       forName:@"TextModeTransformer"];
+  [t release];
 # endif // USE_IPHONE
 
   [self traverseTree];
index 7f958323ae4b64188f9d22fa4d52d957964ae36b..6e05986f149b41b0c467f043792e364ff0c2dd28 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2006-2012 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2006-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
@@ -30,6 +30,7 @@
 {
 # ifdef USE_IPHONE
   GLuint gl_depthbuffer;
+  BOOL _suppressRotationAnimation;
 # endif /* USE_IPHONE */
 }
 
index 41b99f31b24ebfc7fcd65fc922f52fc3a352dc41..989f8eb9258f36a3a7193bc902f629b4b25e93b2 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2006-2015 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2006-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
@@ -17,6 +17,8 @@
 
 #import "XScreenSaverGLView.h"
 #import "XScreenSaverConfigSheet.h"
+#import "jwxyz-cocoa.h"
+#import "jwxyzI.h"
 #import "screenhackI.h"
 #import "xlockmoreI.h"
 
@@ -39,48 +41,50 @@ extern void check_gl_error (const char *type);
 @implementation XScreenSaverGLView
 
 
-- (NSOpenGLContext *) oglContext
-{
-  return ogl_ctx;
-}
-
-
 #ifdef USE_IPHONE
 /* With GL programs, drawing at full resolution isn't a problem.
  */
 - (CGFloat) hackedContentScaleFactor
 {
-  NSSize ssize = [[[UIScreen mainScreen] currentMode] size];
-  NSSize bsize = [self bounds].size;
+  return [self contentScaleFactor];
+}
 
-  // Ratio of screen size in pixels to view size in points.
-  GLfloat s = ((ssize.width > ssize.height ? ssize.width : ssize.height) /
-               (bsize.width > bsize.height ? bsize.width : bsize.height));
-  return s;
+- (BOOL)ignoreRotation
+{
+  return FALSE;                // Allow xwindow and the glViewport to change shape
+}
+
+- (BOOL) suppressRotationAnimation
+{
+  return _suppressRotationAnimation;  // per-hack setting, default FALSE
+}
+
+- (BOOL) rotateTouches
+{
+  return TRUE;         // We need the XY axes swapped in our events
 }
-#endif // USE_IPHONE
 
 
-#ifdef USE_IPHONE
 - (void) swapBuffers
 {
+#  ifdef JWXYZ_GL
+  GLint gl_renderbuffer = xwindow->gl_renderbuffer;
+#  endif // JWXYZ_GL
   glBindRenderbufferOES (GL_RENDERBUFFER_OES, gl_renderbuffer);
   [ogl_ctx presentRenderbuffer:GL_RENDERBUFFER_OES];
 }
 #endif // USE_IPHONE
 
 
-#ifdef USE_BACKBUFFER
-
 - (void) animateOneFrame
 {
-# ifdef USE_IPHONE
+# if defined USE_IPHONE && defined JWXYZ_QUARTZ
   UIGraphicsPushContext (backbuffer);
 # endif
 
   [self render_x11];
 
-# ifdef USE_IPHONE
+# if defined USE_IPHONE && defined JWXYZ_QUARTZ
   UIGraphicsPopContext();
 # endif
 }
@@ -92,6 +96,42 @@ extern void check_gl_error (const char *type);
 }
 
 
+/* GL screenhacks set their own viewport and matrices. */
+- (void) setViewport
+{
+}
+
+
+#ifdef USE_IPHONE
+
+/* Keep the GL scene oriented into a portrait-mode View, regardless of
+   what the physical device orientation is.
+ */
+- (void) reshape_x11
+{
+  [super reshape_x11];
+
+  glMatrixMode(GL_PROJECTION);
+  glRotatef (-current_device_rotation(), 0, 0, 1);
+  glMatrixMode(GL_MODELVIEW);
+}
+
+- (void) render_x11
+{
+  BOOL was_initted_p = initted_p;
+  [super render_x11];
+
+  if (! was_initted_p)
+    _suppressRotationAnimation =
+      get_boolean_resource (xdpy,
+                            "suppressRotationAnimation",
+                            "SuppressRotationAnimation");
+}
+
+#endif // USE_IPHONE
+
+
+
 /* The backbuffer isn't actually used for GL programs, but it needs to
    be there for X11 calls to not error out.  However, nothing done with
    X11 calls will ever show up!  It all gets written into the backbuffer
@@ -100,11 +140,10 @@ extern void check_gl_error (const char *type);
  */
 - (void) createBackbuffer:(CGSize)new_size
 {
+#ifdef JWXYZ_QUARTZ
   NSAssert (! backbuffer_texture,
                        @"backbuffer_texture shouldn't be used for GL hacks");
 
-  backbuffer_size = new_size;
-
   if (! backbuffer) {
     CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
     int w = 8;
@@ -115,6 +154,7 @@ extern void check_gl_error (const char *type);
                                          kCGImageAlphaNoneSkipLast));
     CGColorSpaceRelease (cs);
   }
+#endif // JWXYZ_QUARTZ
 }
 
 
@@ -125,24 +165,11 @@ extern void check_gl_error (const char *type);
 
 
 /* Likewise. GL screenhacks control display with glXSwapBuffers(). */
-- (void) flushBackbufer
+- (void) flushBackbuffer
 {
 }
 
 
-# endif // USE_BACKBUFFER
-
-
-/* When changing the device orientation, leave the X11 Window and glViewport
-   in portrait configuration.  OpenGL hacks examine current_device_rotation()
-   within the scene as needed.
- */
-- (BOOL)reshapeRotatedWindow
-{
-  return NO;
-}
-
-
 #ifndef USE_IPHONE
 
 - (NSOpenGLPixelFormat *) getGLPixelFormat
@@ -177,18 +204,23 @@ extern void check_gl_error (const char *type);
     // attrs[i++] = NSOpenGLPFANoRecovery;
   }
 
+  attrs[i++] = NSOpenGLPFAWindow;
+# ifdef JWXYZ_GL
+  attrs[i++] = NSOpenGLPFAPixelBuffer;
+# endif
+
   attrs[i] = 0;
 
-  NSOpenGLPixelFormat *pixfmt = [[NSOpenGLPixelFormat alloc]
+  NSOpenGLPixelFormat *result = [[NSOpenGLPixelFormat alloc]
                                  initWithAttributes:attrs];
 
-  if (ms_p && !pixfmt) {   // Retry without multisampling.
+  if (ms_p && !result) {   // Retry without multisampling.
     i -= 2;
     attrs[i] = 0;
-    pixfmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
+    result = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
   }
 
-  return [pixfmt autorelease];
+  return [result autorelease];
 }
 
 #else // !USE_IPHONE
@@ -225,6 +257,11 @@ extern void check_gl_error (const char *type);
                                 GL_RENDERBUFFER_OES, gl_depthbuffer);
 }
 
+- (NSString *)getCAGravity
+{
+  return kCAGravityCenter;
+}
+
 #endif // !USE_IPHONE
 
 
@@ -298,6 +335,11 @@ init_GL (ModeInfo *mi)
 void
 glXSwapBuffers (Display *dpy, Window window)
 {
+  // This all is very much like what's in -[XScreenSaverView flushBackbuffer].
+#ifdef JWXYZ_GL
+  jwxyz_bind_drawable (window, window);
+#endif // JWXYZ_GL
+
   XScreenSaverGLView *view = (XScreenSaverGLView *) jwxyz_window_view (window);
   NSAssert1 ([view isKindOfClass:[XScreenSaverGLView class]],
              @"wrong view class: %@", view);
index cc6867b573340c16cfa0700cc55b3785e309b18d..06f0ebe29a4ffd812b542d2830e4d2cd96e929f8 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2006-2015 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2006-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
@@ -61,7 +61,6 @@
 #endif // USE_IPHONE
 
 
-#define USE_BACKBUFFER  // must be in sync with jwxyz.m
 // Currently only OpenGL backbuffers are supported (OSX and iOS).
 # define BACKBUFFER_OPENGL
 
   fps_state *fpst;
 
 # ifdef USE_IPHONE
-  UIDeviceOrientation orientation, new_orientation;
   BOOL screenLocked;
-
-  CGSize initial_bounds;       // portrait-mode size (pixels, not points).
-       
-  GLfloat rotation_ratio;      // ratio [0-1] thru rotation anim, or -1
-  NSSize rot_current_size;     // intermediate or at-rest orientation.
-  NSSize rot_from, rot_to;     // start/end size rect (pixels, not points)
-  GLfloat rot_current_angle;   // only right angles when rotation complete.
-  GLfloat angle_from, angle_to;        // start angle, end angle (degrees)
-  double rot_start_time;
-
-  BOOL ignore_rotation_p;      // whether hack requested "always portrait".
+  BOOL _ignoreRotation;                // whether hack requested "always portrait".
                                // some want this, some do not.
-
   NSTimer *crash_timer;
 
   NSDictionary *function_tables;
 
   id<XScreenSaverViewDelegate> _delegate;
 
-# endif // USE_IPHONE
+# else // !USE_PHONE
+
+  NSOpenGLPixelFormat *pixfmt;
+
+# endif // !USE_IPHONE
 
-# ifdef USE_BACKBUFFER
+  NSOpenGLContext *ogl_ctx;      // OpenGL rendering context
+
+# ifdef JWXYZ_QUARTZ
   CGContextRef backbuffer;
-  CGSize backbuffer_size;      // pixels, not points.
   CGColorSpaceRef colorspace;
 
 #  ifdef BACKBUFFER_OPENGL
 
   GLsizei gl_texture_w, gl_texture_h;
 
-  NSOpenGLContext *ogl_ctx;      // OpenGL rendering context
   GLuint backbuffer_texture;
   GLenum gl_texture_target;
   GLenum gl_pixel_format, gl_pixel_type;
 #   endif // USE_IPHONE
 #  endif
 
-# endif // USE_BACKBUFFER
+# endif // JWXYZ_QUARTZ
+
+# if defined JWXYZ_GL && defined USE_IPHONE
+  NSOpenGLContext *ogl_ctx_pixmap;
+# endif // JWXYZ_GL && USE_IPHONE
 }
 
 - (id)initWithFrame:(NSRect)frame saverName:(NSString*)n isPreview:(BOOL)p;
 
 - (void) render_x11;
+- (NSOpenGLContext *) oglContext;
 - (void) prepareContext;
 - (NSUserDefaultsController *) userDefaultsController;
 + (NSString *) decompressXML:(NSData *)xml;
 
 #ifdef USE_IPHONE
-- (BOOL)reshapeRotatedWindow;
+- (CGFloat) hackedContentScaleFactor;
 - (void)setScreenLocked:(BOOL)locked;
 - (NSDictionary *)getGLProperties;
 - (void)addExtraRenderbuffers:(CGSize)size;
+- (NSString *)getCAGravity;
+- (void)orientationChanged;
 @property (nonatomic, assign) id<XScreenSaverViewDelegate> delegate;
+@property (nonatomic) BOOL ignoreRotation;
+- (BOOL)suppressRotationAnimation;
+- (BOOL)rotateTouches;
 #else // !USE_IPHONE
 - (NSOpenGLPixelFormat *)getGLPixelFormat;
 #endif // !USE_IPHONE
 
-#ifdef USE_BACKBUFFER
 - (void)enableBackbuffer:(CGSize)new_backbuffer_size;
+- (void)setViewport;
 - (void)createBackbuffer:(CGSize)s;
+- (void)reshape_x11;
+#ifdef JWXYZ_QUARTZ
 - (void)drawBackbuffer;
+#endif // JWXYZ_QUARTZ
 - (void)flushBackbuffer;
-#endif // USE_BACKBUFFER
 
 @end
index 657835b9c9b1e5ebe9eeeb4e045cd616b2c75f6a..bc7f21a3e79221f2f682b23082e84994172c0c5d 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2006-2015 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2006-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
 #import "Updater.h"
 #import "screenhackI.h"
 #import "xlockmoreI.h"
+#import "jwxyzI.h"
+#import "jwxyz-cocoa.h"
 #import "jwxyz-timers.h"
 
-#ifndef USE_IPHONE
+#ifdef USE_IPHONE
+// XScreenSaverView.m speaks OpenGL ES just fine, but enableBackbuffer does
+// need (jwzgles_)gluCheckExtension.
+# import "jwzglesI.h"
+#else
 # import <OpenGL/glu.h>
 #endif
 
@@ -173,17 +179,16 @@ extern NSDictionary *make_function_table_dict(void);  // ios-function-table.m
   const char *dir = [nsdir cStringUsingEncoding:NSUTF8StringEncoding];
   const char *opath = getenv ("PATH");
   if (!opath) opath = "/bin"; // $PATH is unset when running under Shark!
-  char *npath = (char *) malloc (strlen (opath) + strlen (dir) + 30);
-  strcpy (npath, "PATH=");
-  strcat (npath, dir);
+  char *npath = (char *) malloc (strlen (opath) + strlen (dir) + 2);
+  strcpy (npath, dir);
   strcat (npath, ":");
   strcat (npath, opath);
-  if (putenv (npath)) {
-    perror ("putenv");
-    NSAssert1 (0, @"putenv \"%s\" failed", npath);
+  if (setenv ("PATH", npath, 1)) {
+    perror ("setenv");
+    NSAssert1 (0, @"setenv \"PATH=%s\" failed", npath);
   }
 
-  /* Don't free (npath) -- MacOS's putenv() does not copy it. */
+  free (npath);
 }
 
 
@@ -196,14 +201,33 @@ extern NSDictionary *make_function_table_dict(void);  // ios-function-table.m
   NSAssert1 (nsb, @"no bundle for class %@", [self class]);
   
   const char *s = [name cStringUsingEncoding:NSUTF8StringEncoding];
-  char *env = (char *) malloc (strlen (s) + 40);
-  strcpy (env, "XSCREENSAVER_CLASSPATH=");
-  strcat (env, s);
-  if (putenv (env)) {
-    perror ("putenv");
-    NSAssert1 (0, @"putenv \"%s\" failed", env);
+  if (setenv ("XSCREENSAVER_CLASSPATH", s, 1)) {
+    perror ("setenv");
+    NSAssert1 (0, @"setenv \"XSCREENSAVER_CLASSPATH=%s\" failed", s);
   }
-  /* Don't free (env) -- MacOS's putenv() does not copy it. */
+}
+
+
+- (void) loadCustomFonts
+{
+# ifndef USE_IPHONE
+  NSBundle *nsb = [NSBundle bundleForClass:[self class]];
+  NSMutableArray *fonts = [NSMutableArray arrayWithCapacity:20];
+  for (NSString *ext in @[@"ttf", @"otf"]) {
+    [fonts addObjectsFromArray: [nsb pathsForResourcesOfType:ext
+                                     inDirectory:NULL]];
+  }
+  for (NSString *font in fonts) {
+    CFURLRef url = (CFURLRef) [NSURL fileURLWithPath: font];
+    CFErrorRef err = 0;
+    if (! CTFontManagerRegisterFontsForURL (url, kCTFontManagerScopeProcess,
+                                            &err)) {
+      // Just ignore errors:
+      // "The file has already been registered in the specified scope."
+      // NSLog (@"loading font: %@ %@", url, err);
+    }
+  }
+# endif // !USE_IPHONE
 }
 
 
@@ -257,7 +281,12 @@ add_default_options (const XrmOptionDescRec *opts,
     { 0, 0, 0, 0 }
   };
   static const char *default_defaults [] = {
+
+# if defined(USE_IPHONE) && !defined(__OPTIMIZE__)
+    ".doFPS:              True",
+# else
     ".doFPS:              False",
+# endif
     ".doubleBuffer:       True",
     ".multiSample:        False",
 # ifndef USE_IPHONE
@@ -346,42 +375,6 @@ add_default_options (const XrmOptionDescRec *opts,
 }
 
 
-#ifdef USE_IPHONE
-/* 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));
-}
-#endif // USE_IPHONE
-
-#if TARGET_IPHONE_SIMULATOR
-static const char *
-orientname(unsigned long o)
-{
-  switch (o) {
-  case UIDeviceOrientationUnknown:             return "Unknown";
-  case UIDeviceOrientationPortrait:            return "Portrait";
-  case UIDeviceOrientationPortraitUpsideDown:  return "PortraitUpsideDown";
-  case UIDeviceOrientationLandscapeLeft:       return "LandscapeLeft";
-  case UIDeviceOrientationLandscapeRight:      return "LandscapeRight";
-  case UIDeviceOrientationFaceUp:              return "FaceUp";
-  case UIDeviceOrientationFaceDown:            return "FaceDown";
-  default:                                     return "ERROR";
-  }
-}
-#endif // TARGET_IPHONE_SIMULATOR
-
-
 - (id) initWithFrame:(NSRect)frame
            saverName:(NSString *)saverName
            isPreview:(BOOL)isPreview
@@ -409,7 +402,7 @@ orientname(unsigned long o)
                              encoding:NSISOLatin1StringEncoding];
   name = [@"org.jwz.xscreensaver." stringByAppendingString:name];
   [self setResourcesEnv:name];
-
+  [self loadCustomFonts];
   
   XrmOptionDescRec *opts = 0;
   const char **defs = 0;
@@ -424,7 +417,7 @@ orientname(unsigned long o)
 
   next_frame_time = 0;
 
-# ifndef USE_IPHONE
+# if !defined USE_IPHONE && defined JWXYZ_QUARTZ
   // When the view fills the screen and double buffering is enabled, OS X will
   // use page flipping for a minor CPU/FPS boost. In windowed mode, double
   // buffering reduces the frame rate to 1/2 the screen's refresh rate.
@@ -432,32 +425,12 @@ orientname(unsigned long o)
 # endif
 
 # ifdef USE_IPHONE
-  double s = [self hackedContentScaleFactor];
-# else
-  double s = 1;
-# endif
-
-  CGSize bb_size;      // pixels, not points
-  bb_size.width  = s * frame.size.width;
-  bb_size.height = s * frame.size.height;
-
-# ifdef USE_IPHONE
-  initial_bounds = rot_current_size = rot_from = rot_to = bb_size;
-  rotation_ratio = -1;
-
-  orientation = UIDeviceOrientationUnknown;
-  [self didRotate:nil];
   [self initGestures];
 
   // So we can tell when we're docked.
   [UIDevice currentDevice].batteryMonitoringEnabled = YES;
 
   [self setBackgroundColor:[NSColor blackColor]];
-
-  [[NSNotificationCenter defaultCenter]
-   addObserver:self
-   selector:@selector(didRotate:)
-   name:UIDeviceOrientationDidChangeNotification object:nil];
 # endif // USE_IPHONE
 
   return self;
@@ -489,18 +462,23 @@ orientname(unsigned long o)
   [[NSNotificationCenter defaultCenter] removeObserver:self];
 # endif
 
-# ifdef USE_BACKBUFFER
-
 #  ifdef BACKBUFFER_OPENGL
+# ifndef USE_IPHONE
+  [pixfmt release];
+# endif // !USE_IPHONE
   [ogl_ctx release];
   // Releasing the OpenGL context should also free any OpenGL objects,
   // including the backbuffer texture and frame/render/depthbuffers.
 #  endif // BACKBUFFER_OPENGL
 
+# if defined JWXYZ_GL && defined USE_IPHONE
+  [ogl_ctx_pixmap release];
+# endif // JWXYZ_GL
+
+# ifdef JWXYZ_QUARTZ
   if (colorspace)
     CGColorSpaceRelease (colorspace);
-
-# endif // USE_BACKBUFFER
+# endif // JWXYZ_QUARTZ
 
   [prefsReader release];
 
@@ -537,6 +515,45 @@ orientname(unsigned long o)
   [prefs setBool:YES forKey:@"wasRunning"];
   [prefs synchronize];
 }
+
+
+- (void) resizeGL
+{
+  if (!ogl_ctx)
+    return;
+
+  CGSize screen_size = self.bounds.size;
+  double s = self.contentScaleFactor;
+  screen_size.width *= s;
+  screen_size.height *= s;
+
+#if defined JWXYZ_GL
+  GLuint *framebuffer = &xwindow->gl_framebuffer;
+  GLuint *renderbuffer = &xwindow->gl_renderbuffer;
+  xwindow->window.current_drawable = xwindow;
+#elif defined JWXYZ_QUARTZ
+  GLuint *framebuffer = &gl_framebuffer;
+  GLuint *renderbuffer = &gl_renderbuffer;
+#endif // JWXYZ_QUARTZ
+
+  if (*framebuffer)  glDeleteFramebuffersOES  (1, framebuffer);
+  if (*renderbuffer) glDeleteRenderbuffersOES (1, renderbuffer);
+
+  create_framebuffer (framebuffer, renderbuffer);
+
+  //   redundant?
+  //     glRenderbufferStorageOES (GL_RENDERBUFFER_OES, GL_RGBA8_OES,
+  //                               (int)size.width, (int)size.height);
+  [ogl_ctx renderbufferStorage:GL_RENDERBUFFER_OES
+                  fromDrawable:(CAEAGLLayer*)self.layer];
+
+  glFramebufferRenderbufferOES (GL_FRAMEBUFFER_OES,  GL_COLOR_ATTACHMENT0_OES,
+                                GL_RENDERBUFFER_OES, *renderbuffer);
+
+  [self addExtraRenderbuffers:screen_size];
+
+  check_framebuffer_status();
+}
 #endif // USE_IPHONE
 
 
@@ -555,16 +572,6 @@ orientname(unsigned long o)
    */
 
 # ifdef USE_IPHONE
-  {
-    CGSize b = self.bounds.size;
-    double s = [self hackedContentScaleFactor];
-    b.width  *= s;
-    b.height *= s;
-    NSAssert (initial_bounds.width == b.width &&
-              initial_bounds.height == b.height,
-              @"bounds changed unexpectedly");
-  }
-
   if (crash_timer)
     [crash_timer invalidate];
 
@@ -590,6 +597,11 @@ orientname(unsigned long o)
     setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
 # endif
 
+  xwindow = (Window) calloc (1, sizeof(*xwindow));
+  xwindow->type = WINDOW;
+  xwindow->window.view = self;
+  CFRetain (xwindow->window.view);   // needed for garbage collection?
+
 #ifdef BACKBUFFER_OPENGL
   CGSize new_backbuffer_size;
 
@@ -597,16 +609,16 @@ orientname(unsigned long o)
 # ifndef USE_IPHONE
     if (!ogl_ctx) {
 
-      NSOpenGLPixelFormat *pixfmt = [self getGLPixelFormat];
+      pixfmt = [self getGLPixelFormat];
+      [pixfmt retain];
 
       NSAssert (pixfmt, @"unable to create NSOpenGLPixelFormat");
 
-      [pixfmt retain]; // #### ???
-
       // Fun: On OS X 10.7, the second time an OpenGL context is created, after
       // the preferences dialog is launched in SaverTester, the context only
       // lasts until the first full GC. Then it turns black. Solution is to
       // reuse the OpenGL context after this point.
+      // "Analyze" says that both pixfmt and ogl_ctx are leaked.
       ogl_ctx = [[NSOpenGLContext alloc] initWithFormat:pixfmt
                                          shareContext:nil];
 
@@ -623,6 +635,15 @@ orientname(unsigned long o)
     // from initWithFrame.
     [ogl_ctx setView:self];
 
+    // This may not be necessary if there's FBO support.
+#  ifdef JWXYZ_GL
+    xwindow->window.pixfmt = pixfmt;
+    CFRetain (xwindow->window.pixfmt);
+    xwindow->window.virtual_screen = [ogl_ctx currentVirtualScreen];
+    xwindow->window.current_drawable = xwindow;
+    NSAssert (ogl_ctx, @"no CGContext");
+#  endif
+
     // Clear frame buffer ASAP, else there are bits left over from other apps.
     glClearColor (0, 0, 0, 1);
     glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -655,86 +676,37 @@ orientname(unsigned long o)
       eagl_layer.contentsScale = [UIScreen mainScreen].scale;
 
       ogl_ctx = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
-    }
+# ifdef JWXYZ_GL
+      ogl_ctx_pixmap = [[EAGLContext alloc]
+                        initWithAPI:kEAGLRenderingAPIOpenGLES1
+                        sharegroup:ogl_ctx.sharegroup];
+# endif // JWXYZ_GL
 
-    [EAGLContext setCurrentContext: ogl_ctx];
-
-    CGSize screen_size = [[[UIScreen mainScreen] currentMode] size];
-    // iPad, simulator: 768x1024
-    // iPad, physical: 1024x768
-    if (screen_size.width > screen_size.height) {
-      CGFloat w = screen_size.width;
-      screen_size.width = screen_size.height;
-      screen_size.height = w;
+      eagl_layer.contentsGravity = [self getCAGravity];
     }
 
-    if (gl_framebuffer)  glDeleteFramebuffersOES  (1, &gl_framebuffer);
-    if (gl_renderbuffer) glDeleteRenderbuffersOES (1, &gl_renderbuffer);
-
-    glGenFramebuffersOES  (1, &gl_framebuffer);
-    glBindFramebufferOES  (GL_FRAMEBUFFER_OES,  gl_framebuffer);
+# ifdef JWXYZ_GL
+    xwindow->window.ogl_ctx_pixmap = ogl_ctx_pixmap;
+# endif // JWXYZ_GL
 
-    glGenRenderbuffersOES (1, &gl_renderbuffer);
-    glBindRenderbufferOES (GL_RENDERBUFFER_OES, gl_renderbuffer);
-
-//   redundant?
-//     glRenderbufferStorageOES (GL_RENDERBUFFER_OES, GL_RGBA8_OES,
-//                               (int)size.width, (int)size.height);
-    [ogl_ctx renderbufferStorage:GL_RENDERBUFFER_OES
-                    fromDrawable:(CAEAGLLayer*)self.layer];
-
-    glFramebufferRenderbufferOES (GL_FRAMEBUFFER_OES,  GL_COLOR_ATTACHMENT0_OES,
-                                  GL_RENDERBUFFER_OES, gl_renderbuffer);
-
-    [self addExtraRenderbuffers:screen_size];
-
-    int err = glCheckFramebufferStatusOES (GL_FRAMEBUFFER_OES);
-    switch (err) {
-      case GL_FRAMEBUFFER_COMPLETE_OES:
-        break;
-      case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES:
-        NSAssert (0, @"framebuffer incomplete attachment");
-        break;
-      case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES:
-        NSAssert (0, @"framebuffer incomplete missing attachment");
-        break;
-      case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES:
-        NSAssert (0, @"framebuffer incomplete dimensions");
-        break;
-      case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES:
-        NSAssert (0, @"framebuffer incomplete formats");
-        break;
-      case GL_FRAMEBUFFER_UNSUPPORTED_OES:
-        NSAssert (0, @"framebuffer unsupported");
-        break;
-/*
-      case GL_FRAMEBUFFER_UNDEFINED:
-        NSAssert (0, @"framebuffer undefined");
-        break;
-      case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
-        NSAssert (0, @"framebuffer incomplete draw buffer");
-        break;
-      case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
-        NSAssert (0, @"framebuffer incomplete read buffer");
-        break;
-      case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
-        NSAssert (0, @"framebuffer incomplete multisample");
-        break;
-      case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
-        NSAssert (0, @"framebuffer incomplete layer targets");
-        break;
- */
-    default:
-      NSAssert (0, @"framebuffer incomplete, unknown error 0x%04X", err);
-      break;
-    }
+    [EAGLContext setCurrentContext: ogl_ctx];
 
-    glViewport (0, 0, screen_size.width, screen_size.height);
+    [self resizeGL];
 
-    new_backbuffer_size = initial_bounds;
+    double s = [self hackedContentScaleFactor];
+    new_backbuffer_size = self.bounds.size;
+    new_backbuffer_size.width *= s;
+    new_backbuffer_size.height *= s;
 
 # endif // USE_IPHONE
 
+# ifdef JWXYZ_GL
+    xwindow->ogl_ctx = ogl_ctx;
+#  ifndef USE_IPHONE
+    CFRetain (xwindow->ogl_ctx);
+#  endif // USE_IPHONE
+# endif // JWXYZ_GL
+
     check_gl_error ("startAnimation");
 
 //  NSLog (@"%s / %s / %s\n", glGetString (GL_VENDOR),
@@ -744,9 +716,8 @@ orientname(unsigned long o)
   }
 #endif // BACKBUFFER_OPENGL
 
-#ifdef USE_BACKBUFFER
+  [self setViewport];
   [self createBackbuffer:new_backbuffer_size];
-#endif
 }
 
 - (void)stopAnimation
@@ -767,10 +738,13 @@ orientname(unsigned long o)
     xsft->free_cb (xdpy, xwindow, xdata);
     [self unlockFocus];
 
-    // xdpy must be freed before dealloc is called, because xdpy owns a
-    // circular reference to the parent XScreenSaverView.
     jwxyz_free_display (xdpy);
     xdpy = NULL;
+# if defined JWXYZ_GL && !defined USE_IPHONE
+    CFRelease (xwindow->ogl_ctx);
+# endif
+    CFRelease (xwindow->window.view);
+    free (xwindow);
     xwindow = NULL;
 
 //  setup_p = NO; // #### wait, do we need this?
@@ -808,6 +782,7 @@ orientname(unsigned long o)
 
   clear_gl_error();    // This hack is defunct, don't let this linger.
 
+# ifdef JWXYZ_QUARTZ
   CGContextRelease (backbuffer);
   backbuffer = nil;
 
@@ -815,19 +790,30 @@ orientname(unsigned long o)
     munmap (backbuffer_data, backbuffer_len);
   backbuffer_data = NULL;
   backbuffer_len = 0;
+# endif
+}
+
+
+- (NSOpenGLContext *) oglContext
+{
+  return ogl_ctx;
 }
 
 
 // #### maybe this could/should just be on 'lockFocus' instead?
 - (void) prepareContext
 {
-  if (ogl_ctx) {
+  if (xwindow) {
 #ifdef USE_IPHONE
     [EAGLContext setCurrentContext:ogl_ctx];
 #else  // !USE_IPHONE
     [ogl_ctx makeCurrentContext];
 //    check_gl_error ("makeCurrentContext");
 #endif // !USE_IPHONE
+
+#ifdef JWXYZ_GL
+    xwindow->window.current_drawable = xwindow;
+#endif
   }
 }
 
@@ -859,21 +845,20 @@ screenhack_do_fps (Display *dpy, Window w, fps_state *fpst, void *closure)
  */
 - (CGFloat) hackedContentScaleFactor
 {
-  NSSize ssize = [[[UIScreen mainScreen] currentMode] size];
   NSSize bsize = [self bounds].size;
 
   CGFloat
-    max_ssize = ssize.width > ssize.height ? ssize.width : ssize.height,
     max_bsize = bsize.width > bsize.height ? bsize.width : bsize.height;
 
   // Ratio of screen size in pixels to view size in points.
-  CGFloat s = max_ssize / max_bsize;
+  CGFloat s = self.contentScaleFactor;
 
   // Two constraints:
 
   // 1. Don't exceed -- let's say 1280 pixels in either direction.
   //    (Otherwise the frame rate gets bad.)
-  CGFloat mag0 = ceil(max_ssize / 1280);
+  //    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.)
@@ -886,72 +871,39 @@ screenhack_do_fps (Display *dpy, Window w, fps_state *fpst, void *closure)
 }
 
 
-static GLfloat _global_rot_current_angle_kludge;
-
-double current_device_rotation (void)
-{
-  return -_global_rot_current_angle_kludge;
-}
-
-
-- (void) hackRotation
+double
+current_device_rotation (void)
 {
-  if (rotation_ratio >= 0) {   // in the midst of a rotation animation
-
-#   define CLAMP180(N) while (N < 0) N += 360; while (N > 180) N -= 360
-    GLfloat f = angle_from;
-    GLfloat t = angle_to;
-    CLAMP180(f);
-    CLAMP180(t);
-    GLfloat dist = -(t-f);
-    CLAMP180(dist);
-
-    // Intermediate angle.
-    rot_current_angle = f - rotation_ratio * dist;
-
-    // Intermediate frame size.
-    rot_current_size.width = floor(rot_from.width +
-      rotation_ratio * (rot_to.width - rot_from.width));
-    rot_current_size.height = floor(rot_from.height +
-      rotation_ratio * (rot_to.height - rot_from.height));
-
-    // Tick animation.  Complete rotation in 1/6th sec.
-    double now = double_time();
-    double duration = 1/6.0;
-    rotation_ratio = 1 - ((rot_start_time + duration - now) / duration);
+  UIDeviceOrientation o = [[UIDevice currentDevice] orientation];
 
-    if (rotation_ratio > 1 || ignore_rotation_p) {     // Done animating.
-      orientation = new_orientation;
-      rot_current_angle = angle_to;
-      rot_current_size = rot_to;
-      rotation_ratio = -1;
-
-# if TARGET_IPHONE_SIMULATOR
-      NSLog (@"rotation ended: %s %d, %d x %d",
-             orientname(orientation), (int) rot_current_angle,
-             (int) rot_current_size.width, (int) rot_current_size.height);
-# endif
-
-      // Check orientation again in case we rotated again while rotating:
-      // this is a no-op if nothing has changed.
-      [self didRotate:nil];
-    }
-  } else {                     // Not animating a rotation.
-    rot_current_angle = angle_to;
-    rot_current_size = rot_to;
+  /* Sometimes UIDevice doesn't know the proper orientation, or the device is
+     face up/face down, so in those cases fall back to the status bar
+     orientation. The SaverViewController tries to set the status bar to the
+     proper orientation before it creates the XScreenSaverView; see
+     _storedOrientation in SaverViewController.
+   */
+  if (o == UIDeviceOrientationUnknown ||
+      o == UIDeviceOrientationFaceUp  ||
+      o == UIDeviceOrientationFaceDown) {
+    /* Mind the differences between UIInterfaceOrientation and
+       UIDeviceOrientation:
+       1. UIInterfaceOrientation does not include FaceUp and FaceDown.
+       2. LandscapeLeft and LandscapeRight are swapped between the two. But
+          converting between device and interface orientation doesn't need to
+          take this into account, because (from the UIInterfaceOrientation
+          description): "rotating the device requires rotating the content in
+          the opposite direction."
+        */
+    /* statusBarOrientation deprecated in iOS 9 */
+    o = [UIApplication sharedApplication].statusBarOrientation;
   }
 
-  CLAMP180(rot_current_angle);
-  _global_rot_current_angle_kludge = rot_current_angle;
-
-#   undef CLAMP180
-
-  CGSize rotsize = ((ignore_rotation_p || ![self reshapeRotatedWindow])
-                    ? initial_bounds
-                    : rot_current_size);
-  if ((int) backbuffer_size.width  != (int) rotsize.width ||
-      (int) backbuffer_size.height != (int) rotsize.height)
-    [self resize_x11];
+  switch (o) {
+  case UIDeviceOrientationLandscapeLeft:      return -90; break;
+  case UIDeviceOrientationLandscapeRight:     return  90; break;
+  case UIDeviceOrientationPortraitUpsideDown: return 180; break;
+  default:                                    return 0;   break;
+  }
 }
 
 
@@ -984,7 +936,7 @@ double current_device_rotation (void)
 #endif // USE_IPHONE
 
 
-#ifdef USE_BACKBUFFER
+#ifdef JWXYZ_QUARTZ
 
 # ifndef USE_IPHONE
 
@@ -1004,31 +956,6 @@ gl_check_ver (const struct gl_version *caps,
            (caps->major == gl_major && caps->minor >= gl_minor);
 }
 
-# else
-
-static GLboolean
-gluCheckExtension (const GLubyte *ext_name, const GLubyte *ext_string)
-{
-  size_t ext_len = strlen ((const char *)ext_name);
-
-  for (;;) {
-    const GLubyte *found = (const GLubyte *)strstr ((const char *)ext_string,
-                                                    (const char *)ext_name);
-    if (!found)
-      break;
-
-    char last_ch = found[ext_len];
-    if ((found == ext_string || found[-1] == ' ') &&
-        (last_ch == ' ' || !last_ch)) {
-      return GL_TRUE;
-    }
-
-    ext_string = found + ext_len;
-  }
-
-  return GL_FALSE;
-}
-
 # endif
 
 /* Called during startAnimation before the first call to createBackbuffer. */
@@ -1065,9 +992,8 @@ gluCheckExtension (const GLubyte *ext_name, const GLubyte *ext_string)
                        ? GL_TEXTURE_RECTANGLE_EXT : GL_TEXTURE_2D);
 # else
   // OES_texture_npot also provides this, but iOS never provides it.
-  gl_limited_npot_p = gluCheckExtension ((const GLubyte *)
-                                         "GL_APPLE_texture_2D_limited_npot",
-                                         extensions);
+  gl_limited_npot_p = jwzgles_gluCheckExtension
+    ((const GLubyte *) "GL_APPLE_texture_2D_limited_npot", extensions);
   gl_texture_target = GL_TEXTURE_2D;
 # endif
 
@@ -1097,8 +1023,11 @@ gluCheckExtension (const GLubyte *ext_name, const GLubyte *ext_string)
   // you're gonna get for getting a texture onto the screen.
 # ifdef USE_IPHONE
   gl_pixel_format =
-    gluCheckExtension ((const GLubyte *)"GL_APPLE_texture_format_BGRA8888",
-                       extensions) ? GL_BGRA : GL_RGBA;
+    jwzgles_gluCheckExtension
+      ((const GLubyte *)"GL_APPLE_texture_format_BGRA8888", extensions) ?
+      GL_BGRA :
+      GL_RGBA;
+
   gl_pixel_type = GL_UNSIGNED_BYTE;
   // See also OES_read_format.
 # else
@@ -1121,16 +1050,6 @@ gluCheckExtension (const GLubyte *ext_name, const GLubyte *ext_string)
   glEnableClientState (GL_VERTEX_ARRAY);
   glEnableClientState (GL_TEXTURE_COORD_ARRAY);
 
-# ifdef USE_IPHONE
-  glMatrixMode (GL_PROJECTION);
-  glLoadIdentity();
-  NSAssert (new_backbuffer_size.width != 0 && new_backbuffer_size.height != 0,
-            @"initial_bounds never got set");
-  // This is pretty similar to the glOrtho in createBackbuffer for OS X.
-  glOrthof (-new_backbuffer_size.width, new_backbuffer_size.width,
-            -new_backbuffer_size.height, new_backbuffer_size.height, -1, 1);
-# endif // USE_IPHONE
-
   check_gl_error ("enableBackbuffer");
 }
 
@@ -1160,6 +1079,60 @@ to_pow2 (size_t x)
 }
 
 
+#ifdef USE_IPHONE
+- (BOOL) suppressRotationAnimation
+{
+  return [self ignoreRotation];        // Don't animate if we aren't rotating
+}
+
+- (BOOL) rotateTouches
+{
+  return FALSE;                        // Adjust event coordinates only if rotating
+}
+#endif
+
+
+- (void) setViewport
+{
+# ifdef BACKBUFFER_OPENGL
+  NSAssert ([NSOpenGLContext currentContext] ==
+            ogl_ctx, @"invalid GL context");
+
+  NSSize new_size = self.bounds.size;
+
+#  ifdef USE_IPHONE
+  GLfloat s = self.contentScaleFactor;
+  GLfloat hs = self.hackedContentScaleFactor;
+#  else // !USE_IPHONE
+  const GLfloat s = 1;
+  const GLfloat hs = s;
+#  endif
+
+  // On OS X this almost isn't necessary, except for the ugly aliasing
+  // artifacts.
+  glViewport (0, 0, new_size.width * s, new_size.height * s);
+
+  glMatrixMode (GL_PROJECTION);
+  glLoadIdentity();
+#  ifdef USE_IPHONE
+  glOrthof
+#  else
+  glOrtho
+#  endif
+    (-new_size.width * hs, new_size.width * hs,
+     -new_size.height * hs, new_size.height * hs,
+     -1, 1);
+
+#  ifdef USE_IPHONE
+  if ([self ignoreRotation]) {
+    int o = (int) -current_device_rotation();
+    glRotatef (o, 0, 0, 1);
+  }
+#  endif // USE_IPHONE
+# endif // BACKBUFFER_OPENGL
+}
+
+
 /* Create a bitmap context into which we render everything.
    If the desired size has changed, re-created it.
    new_size is in rotated pixels, not points: the same size
@@ -1171,22 +1144,6 @@ to_pow2 (size_t x)
   if (colorspace)
     CGColorSpaceRelease (colorspace);
 
-# ifdef BACKBUFFER_OPENGL
-  NSAssert ([NSOpenGLContext currentContext] ==
-            ogl_ctx, @"invalid GL context");
-
-  // This almost isn't necessary, except for the ugly aliasing artifacts.
-#  ifndef USE_IPHONE
-  glViewport (0, 0, new_size.width, new_size.height);
-
-  glMatrixMode (GL_PROJECTION);
-  glLoadIdentity();
-  // This is pretty similar to the glOrthof in enableBackbuffer for iPhone.
-  glOrtho (-new_size.width, new_size.width, -new_size.height, new_size.height,
-           -1, 1);
-#  endif // !USE_IPHONE
-# endif // BACKBUFFER_OPENGL
-       
   NSWindow *window = [self window];
 
   if (window && xdpy) {
@@ -1202,21 +1159,24 @@ to_pow2 (size_t x)
     colorspace = CGColorSpaceCreateDeviceRGB();
   }
 
+  CGSize osize = CGSizeZero;
+  if (backbuffer) {
+    osize.width = CGBitmapContextGetWidth(backbuffer);
+    osize.height = CGBitmapContextGetHeight(backbuffer);
+  }
+
   if (backbuffer &&
-      (int)backbuffer_size.width  == (int)new_size.width &&
-      (int)backbuffer_size.height == (int)new_size.height)
+      (int)osize.width  == (int)new_size.width &&
+      (int)osize.height == (int)new_size.height)
     return;
 
   CGContextRef ob = backbuffer;
   void *odata = backbuffer_data;
   size_t olen = backbuffer_len;
 
-  CGSize osize = backbuffer_size;      // pixels, not points.
-  backbuffer_size = new_size;          // pixels, not points.
-
-# if TARGET_IPHONE_SIMULATOR
+# if !defined __OPTIMIZE__ || TARGET_IPHONE_SIMULATOR
   NSLog(@"backbuffer %.0fx%.0f",
-        backbuffer_size.width, backbuffer_size.height);
+        new_size.width, new_size.height);
 # endif
 
   /* OS X uses APPLE_client_storage and APPLE_texture_range, as described in
@@ -1245,8 +1205,8 @@ to_pow2 (size_t x)
    */
 
   backbuffer_data = NULL;
-  gl_texture_w = (int)backbuffer_size.width;
-  gl_texture_h = (int)backbuffer_size.height;
+  gl_texture_w = (int)new_size.width;
+  gl_texture_h = (int)new_size.height;
 
   NSAssert (gl_texture_target == GL_TEXTURE_2D
 # ifndef USE_IPHONE
@@ -1319,8 +1279,8 @@ to_pow2 (size_t x)
     (order_little_p ? kCGBitmapByteOrder32Little : kCGBitmapByteOrder32Big);
 
   backbuffer = CGBitmapContextCreate (backbuffer_data,
-                                      (int)backbuffer_size.width,
-                                      (int)backbuffer_size.height,
+                                      (int)new_size.width,
+                                      (int)new_size.height,
                                       8,
                                       bytes_per_row,
                                       colorspace,
@@ -1330,7 +1290,7 @@ to_pow2 (size_t x)
   // Clear it.
   CGRect r;
   r.origin.x = r.origin.y = 0;
-  r.size = backbuffer_size;
+  r.size = new_size;
   CGContextSetGrayFillColor (backbuffer, 0, 1);
   CGContextFillRect (backbuffer, r);
 
@@ -1344,7 +1304,7 @@ to_pow2 (size_t x)
 
     CGRect rect;   // pixels, not points
     rect.origin.x = 0;
-    rect.origin.y = (backbuffer_size.height - osize.height);
+    rect.origin.y = (new_size.height - osize.height);
     rect.size = osize;
 
     CGImageRef img = CGBitmapContextCreateImage (ob);
@@ -1381,51 +1341,28 @@ to_pow2 (size_t x)
                 gl_texture_h, 0, gl_pixel_format, gl_pixel_type,
                 backbuffer_data);
 
-  GLfloat vertices[4][2] =
-  {
-    {-backbuffer_size.width,  backbuffer_size.height},
-    { backbuffer_size.width,  backbuffer_size.height},
-    { backbuffer_size.width, -backbuffer_size.height},
-    {-backbuffer_size.width, -backbuffer_size.height}
-  };
+  GLfloat w = xwindow->frame.width, h = xwindow->frame.height;
+
+  GLfloat vertices[4][2] = {{-w,  h}, {w,  h}, {w, -h}, {-w, -h}};
 
   GLfloat tex_coords[4][2];
 
 #  ifndef USE_IPHONE
-  if (gl_texture_target == GL_TEXTURE_RECTANGLE_EXT) {
-    tex_coords[0][0] = 0;
-    tex_coords[0][1] = 0;
-    tex_coords[1][0] = backbuffer_size.width;
-    tex_coords[1][1] = 0;
-    tex_coords[2][0] = backbuffer_size.width;
-    tex_coords[2][1] = backbuffer_size.height;
-    tex_coords[3][0] = 0;
-    tex_coords[3][1] = backbuffer_size.height;
-  } else
+  if (gl_texture_target != GL_TEXTURE_RECTANGLE_EXT)
 #  endif // USE_IPHONE
   {
-    GLfloat x = backbuffer_size.width / gl_texture_w;
-    GLfloat y = backbuffer_size.height / gl_texture_h;
-    tex_coords[0][0] = 0;
-    tex_coords[0][1] = 0;
-    tex_coords[1][0] = x;
-    tex_coords[1][1] = 0;
-    tex_coords[2][0] = x;
-    tex_coords[2][1] = y;
-    tex_coords[3][0] = 0;
-    tex_coords[3][1] = y;
+    w /= gl_texture_w;
+    h /= gl_texture_h;
   }
 
-#  ifdef USE_IPHONE
-  if (!ignore_rotation_p) {
-    glMatrixMode (GL_MODELVIEW);
-    glLoadIdentity();
-    glRotatef (rot_current_angle, 0, 0, -1);
-
-    if (rotation_ratio >= 0)
-      glClear (GL_COLOR_BUFFER_BIT);
-  }
-#  endif  // USE_IPHONE
+  tex_coords[0][0] = 0;
+  tex_coords[0][1] = 0;
+  tex_coords[1][0] = w;
+  tex_coords[1][1] = 0;
+  tex_coords[2][0] = w;
+  tex_coords[2][1] = h;
+  tex_coords[3][0] = 0;
+  tex_coords[3][1] = h;
 
   glVertexPointer (2, GL_FLOAT, 0, vertices);
   glTexCoordPointer (2, GL_FLOAT, 0, tex_coords);
@@ -1434,29 +1371,81 @@ to_pow2 (size_t x)
 #  if !defined __OPTIMIZE__ || TARGET_IPHONE_SIMULATOR
   check_gl_error ("drawBackbuffer");
 #  endif
+# endif // BACKBUFFER_OPENGL
+}
 
-  // This can also happen near the beginning of render_x11.
-  [self flushBackbuffer];
+#endif // JWXYZ_QUARTZ
 
-# endif // BACKBUFFER_OPENGL
+#ifdef JWXYZ_GL
+
+- (void)enableBackbuffer:(CGSize)new_backbuffer_size;
+{
+  jwxyz_set_matrices (new_backbuffer_size.width, new_backbuffer_size.height);
+  check_gl_error ("enableBackbuffer");
 }
 
+- (void)createBackbuffer:(CGSize)new_size
+{
+  NSAssert ([NSOpenGLContext currentContext] ==
+            ogl_ctx, @"invalid GL context");
+  NSAssert (xwindow->window.current_drawable == xwindow,
+            @"current_drawable not set properly");
+
+# ifndef USE_IPHONE
+  /* On iOS, Retina means glViewport gets called with the screen size instead
+     of the backbuffer/xwindow size. This happens in startAnimation.
+
+     The GL screenhacks call glViewport themselves.
+   */
+  glViewport (0, 0, new_size.width, new_size.height);
+# endif
+
+  // TODO: Preserve contents on resize.
+  glClear (GL_COLOR_BUFFER_BIT);
+  check_gl_error ("createBackbuffer");
+}
+
+#endif // JWXYZ_GL
+
 
 - (void)flushBackbuffer
 {
+# ifdef JWXYZ_GL
+  // Make sure the right context is active: there's two under JWXYZ_GL.
+  jwxyz_bind_drawable (xwindow, xwindow);
+# endif // JWXYZ_GL
+
 # ifndef USE_IPHONE
+
+#  ifdef JWXYZ_QUARTZ
   // The OpenGL pipeline is not automatically synchronized with the contents
   // of the backbuffer, so without glFinish, OpenGL can start rendering from
   // the backbuffer texture at the same time that JWXYZ is clearing and
   // drawing the next frame in the backing store for the backbuffer texture.
+  // This is only a concern under JWXYZ_QUARTZ because of
+  // APPLE_client_storage; JWXYZ_GL doesn't use that.
   glFinish();
+#  endif // JWXYZ_QUARTZ
+
+  // If JWXYZ_GL was single-buffered, there would need to be a glFinish (or
+  // maybe just glFlush?) here, because single-buffered contexts don't always
+  // update what's on the screen after drawing finishes. (i.e., in safe mode)
 
+#  ifdef JWXYZ_QUARTZ
+  // JWXYZ_GL is always double-buffered.
   if (double_buffered_p)
+#  endif // JWXYZ_QUARTZ
     [ogl_ctx flushBuffer]; // despite name, this actually swaps
-# else
+# else // USE_IPHONE
+
+  // jwxyz_bind_drawable() only binds the framebuffer, not the renderbuffer.
+#  ifdef JWXYZ_GL
+  GLint gl_renderbuffer = xwindow->gl_renderbuffer;
+#  endif
+
   glBindRenderbufferOES (GL_RENDERBUFFER_OES, gl_renderbuffer);
   [ogl_ctx presentRenderbuffer:GL_RENDERBUFFER_OES];
-# endif
+# endif // USE_IPHONE
 
 # if !defined __OPTIMIZE__ || TARGET_IPHONE_SIMULATOR
   // glGetError waits for the OpenGL command pipe to flush, so skip it in
@@ -1469,18 +1458,40 @@ to_pow2 (size_t x)
 }
 
 
-#endif // USE_BACKBUFFER
-
-
 /* Inform X11 that the size of our window has changed.
  */
 - (void) resize_x11
 {
-  if (!xwindow) return;  // early
+  if (!xdpy) return;     // early
+
+  NSSize new_size;     // pixels, not points
+
+  new_size = self.bounds.size;
+
+#  ifdef USE_IPHONE
+
+  // If this hack ignores rotation, then that means that it pretends to
+  // always be in portrait mode.  If the View has been resized to a 
+  // landscape shape, swap width and height to keep the backbuffer
+  // in portrait.
+  //
+  if ([self ignoreRotation] && new_size.width > new_size.height) {
+    CGFloat swap    = new_size.width;
+    new_size.width  = new_size.height;
+    new_size.height = swap;
+  }
+
+  double s = self.hackedContentScaleFactor;
+  new_size.width *= s;
+  new_size.height *= s;
+#  endif // USE_IPHONE
 
-  CGSize new_size;     // pixels, not points
+  [self setViewport];
 
-# ifdef USE_BACKBUFFER
+  // On first resize, xwindow->frame is 0x0.
+  if (xwindow->frame.width == new_size.width &&
+      xwindow->frame.height == new_size.height)
+    return;
 
   [self prepareContext];
 
@@ -1488,26 +1499,26 @@ to_pow2 (size_t x)
   [ogl_ctx update];
 #  endif // BACKBUFFER_OPENGL && !USE_IPHONE
 
-#  ifdef USE_IPHONE
-  CGSize rotsize = ((ignore_rotation_p || ![self reshapeRotatedWindow])
-                    ? initial_bounds
-                    : rot_current_size);
-  new_size.width  = rotsize.width;
-  new_size.height = rotsize.height;
-#  else  // !USE_IPHONE
-  new_size = NSSizeToCGSize([self bounds].size);
-#  endif // !USE_IPHONE
-
-  [self createBackbuffer:new_size];
-  jwxyz_window_resized (xdpy, xwindow, 0, 0, new_size.width, new_size.height,
-                        backbuffer);
-# else   // !USE_BACKBUFFER
-  new_size = [self bounds].size;
-  jwxyz_window_resized (xdpy, xwindow, 0, 0, new_size.width, new_size.height,
-                        0);
-# endif  // !USE_BACKBUFFER
+  NSAssert (xwindow && xwindow->type == WINDOW, @"not a window");
+  xwindow->frame.x    = 0;
+  xwindow->frame.y    = 0;
+  xwindow->frame.width  = new_size.width;
+  xwindow->frame.height = new_size.height;
 
-# if TARGET_IPHONE_SIMULATOR
+  [self createBackbuffer:CGSizeMake(xwindow->frame.width,
+                                    xwindow->frame.height)];
+
+# if defined JWXYZ_QUARTZ
+  xwindow->cgc = backbuffer;
+  NSAssert (xwindow->cgc, @"no CGContext");
+# elif defined JWXYZ_GL && !defined USE_IPHONE
+  [ogl_ctx update];
+  [ogl_ctx setView:xwindow->window.view]; // (Is this necessary?)
+# endif // JWXYZ_GL && USE_IPHONE
+
+  jwxyz_window_resized (xdpy);
+
+# if !defined __OPTIMIZE__ || TARGET_IPHONE_SIMULATOR
   NSLog(@"reshape %.0fx%.0f", new_size.width, new_size.height);
 # endif
 
@@ -1516,31 +1527,60 @@ to_pow2 (size_t x)
 }
 
 
+#ifdef USE_IPHONE
+
+/* Called by SaverRunner when the device has changed orientation.
+   That means we need to generate a resize event, even if the size
+   has not changed (e.g., from LandscapeLeft to LandscapeRight).
+ */
+- (void) orientationChanged
+{
+  [self setViewport];
+  resized_p = YES;
+  next_frame_time = 0;  // Get a new frame on screen quickly
+}
+
+/* A hook run after the 'reshape_' method has been called.  Used by
+  XScreenSaverGLView to adjust the in-scene GL viewport.
+ */
+- (void) postReshape
+{
+}
+#endif // USE_IPHONE
+
+
+// Only render_x11 should call this.  XScreenSaverGLView specializes it.
+- (void) reshape_x11
+{
+  xsft->reshape_cb (xdpy, xwindow, xdata,
+                    xwindow->frame.width, xwindow->frame.height);
+}
+
 - (void) render_x11
 {
 # ifdef USE_IPHONE
   @try {
-
-  if (orientation == UIDeviceOrientationUnknown)
-    [self didRotate:nil];
-  [self hackRotation];
 # endif
 
+  // jwxyz_make_display needs this.
+  [self prepareContext]; // resize_x11 also calls this.
+
   if (!initted_p) {
 
     if (! xdpy) {
-# ifdef USE_BACKBUFFER
-      NSAssert (backbuffer, @"no back buffer");
-      xdpy = jwxyz_make_display (self, backbuffer);
-# else
-      xdpy = jwxyz_make_display (self, 0);
-# endif
-      xwindow = XRootWindow (xdpy, 0);
+# ifdef JWXYZ_QUARTZ
+      xwindow->cgc = backbuffer;
+# endif // JWXYZ_QUARTZ
+      xdpy = jwxyz_make_display (xwindow);
 
-# ifdef USE_IPHONE
+# if defined USE_IPHONE
       /* Some X11 hacks (fluidballs) want to ignore all rotation events. */
-      ignore_rotation_p =
+      _ignoreRotation =
+#  ifdef JWXYZ_GL
+        TRUE; // Rotation doesn't work yet. TODO: Make rotation work.
+#  else  // !JWXYZ_GL
         get_boolean_resource (xdpy, "ignoreRotation", "IgnoreRotation");
+#  endif // !JWXYZ_GL
 # endif // USE_IPHONE
 
       [self resize_x11];
@@ -1598,6 +1638,11 @@ to_pow2 (size_t x)
       xsft->fps_cb = 0;
     }
 
+# ifdef USE_IPHONE
+    if (current_device_rotation() != 0)   // launched while rotated
+      resized_p = YES;
+# endif
+
     [self checkForUpdates];
   }
 
@@ -1623,6 +1668,14 @@ to_pow2 (size_t x)
     }
 
 
+  /* Run any XtAppAddInput and XtAppAddTimeOut callbacks now.
+     Do this before delaying for next_frame_time to avoid throttling
+     timers to the hack's frame rate.
+   */
+  XtAppProcessEvent (XtDisplayToApplicationContext (xdpy),
+                     XtIMTimer | XtIMAlternateInput);
+
+
   /* It turns out that on some systems (possibly only 10.5 and older?)
      [ScreenSaverView setAnimationTimeInterval] does nothing.  This means
      that we cannot rely on it.
@@ -1662,7 +1715,6 @@ to_pow2 (size_t x)
   double now = tv.tv_sec + (tv.tv_usec / 1000000.0);
   if (now < next_frame_time) return;
 
-  [self prepareContext]; // resize_x11 also calls this.
   // [self flushBackbuffer];
 
   if (resized_p) {
@@ -1674,26 +1726,10 @@ to_pow2 (size_t x)
       [ogl_ctx setView:self];
 # endif // !USE_IPHONE
 
-    NSRect r;
-# ifndef USE_BACKBUFFER
-    r = [self bounds];
-# else  // USE_BACKBUFFER
-    r.origin.x = 0;
-    r.origin.y = 0;
-    r.size.width  = backbuffer_size.width;
-    r.size.height = backbuffer_size.height;
-# endif // USE_BACKBUFFER
-
-    xsft->reshape_cb (xdpy, xwindow, xdata, r.size.width, r.size.height);
+    [self reshape_x11];
     resized_p = NO;
   }
 
-  // Run any XtAppAddInput callbacks now.
-  // (Note that XtAppAddTimeOut callbacks have already been run by
-  // the Cocoa event loop.)
-  //
-  jwxyz_sources_run (display_sources_data (xdpy));
-
 
   // And finally:
   //
@@ -1707,7 +1743,11 @@ to_pow2 (size_t x)
   now = tv.tv_sec + (tv.tv_usec / 1000000.0);
   next_frame_time = now + (delay / 1000000.0);
 
+# ifdef JWXYZ_QUARTZ
   [self drawBackbuffer];
+# endif
+  // This can also happen near the beginning of render_x11.
+  [self flushBackbuffer];
 
 # ifdef USE_IPHONE     // Allow savers on the iPhone to run full-tilt.
   if (delay < [self animationTimeInterval])
@@ -1753,36 +1793,27 @@ to_pow2 (size_t x)
 }
 
 
-#ifndef USE_BACKBUFFER
-
-- (void) animateOneFrame
-{
-  [self render_x11];
-  jwxyz_flush_context(xdpy);
-}
-
-#else  // USE_BACKBUFFER
-
 - (void) animateOneFrame
 {
   // Render X11 into the backing store bitmap...
 
+# ifdef JWXYZ_QUARTZ
   NSAssert (backbuffer, @"no back buffer");
 
-# ifdef USE_IPHONE
+#  ifdef USE_IPHONE
   UIGraphicsPushContext (backbuffer);
-# endif
+#  endif
+# endif // JWXYZ_QUARTZ
 
   [self render_x11];
 
-# if defined USE_IPHONE && defined USE_BACKBUFFER
+# if defined USE_IPHONE && defined JWXYZ_QUARTZ
   UIGraphicsPopContext();
 # endif
 }
 
-#endif // USE_BACKBUFFER
-
 
+# ifndef USE_IPHONE  // Doesn't exist on iOS
 
 - (void) setFrame:(NSRect) newRect
 {
@@ -1792,15 +1823,24 @@ to_pow2 (size_t x)
     [self resize_x11];
 }
 
-
-# ifndef USE_IPHONE  // Doesn't exist on iOS
 - (void) setFrameSize:(NSSize) newSize
 {
   [super setFrameSize:newSize];
   if (xwindow)
     [self resize_x11];
 }
-# endif // !USE_IPHONE
+
+# else // USE_IPHONE
+
+- (void) layoutSubviews
+{
+  [super layoutSubviews];
+  [self resizeGL];
+  if (xwindow)
+    [self resize_x11];
+}
+
+# endif
 
 
 +(BOOL) performGammaFade
@@ -1843,7 +1883,10 @@ to_pow2 (size_t x)
                  ret, (zs.msg ? zs.msg : "<null>"));
   }
 
-  return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
+  NSString *s = [[NSString alloc]
+                  initWithData:data encoding:NSUTF8StringEncoding];
+  [s autorelease];
+  return s;
 }
 
 
@@ -2139,12 +2182,57 @@ to_pow2 (size_t x)
   int i = 0;
   attrs[i++] = NSOpenGLPFAColorSize; attrs[i++] = 24;
 
+/* OpenGL's core profile removes a lot of the same stuff that was removed in
+   OpenGL ES (e.g. glBegin, glDrawPixels), so it might be a possibility.
+
+  opengl_core_p = True;
+  if (opengl_core_p) {
+    attrs[i++] = NSOpenGLPFAOpenGLProfile;
+    attrs[i++] = NSOpenGLProfileVersion3_2Core;
+  }
+ */
+
+/* Eventually: multisampled pixmaps. May not be supported everywhere.
+   if (multi_sample_p) {
+     attrs[i++] = NSOpenGLPFASampleBuffers; attrs[i++] = 1;
+     attrs[i++] = NSOpenGLPFASamples;       attrs[i++] = 6;
+   }
+ */
+
+# ifdef JWXYZ_QUARTZ
+  // Under Quartz, we're just blitting a texture.
   if (double_buffered_p)
     attrs[i++] = NSOpenGLPFADoubleBuffer;
+# endif
+
+# ifdef JWXYZ_GL
+  /* Under OpenGL, all sorts of drawing commands are being issued, and it might
+     be a performance problem if this activity occurs on the front buffer.
+     Also, some screenhacks expect OS X/iOS to always double-buffer.
+     NSOpenGLPFABackingStore prevents flickering with screenhacks that
+     don't redraw the entire screen every frame.
+   */
+  attrs[i++] = NSOpenGLPFADoubleBuffer;
+  attrs[i++] = NSOpenGLPFABackingStore;
+# endif
+
+  attrs[i++] = NSOpenGLPFAWindow;
+# ifdef JWXYZ_GL
+  attrs[i++] = NSOpenGLPFAPixelBuffer;
+  /* ...But not NSOpenGLPFAFullScreen, because that would be for
+     [NSOpenGLContext setFullScreen].
+   */
+# endif
+
+  /* NSOpenGLPFAFullScreen would go here if initWithFrame's isPreview == NO.
+   */
 
   attrs[i] = 0;
 
-  return [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
+  NSOpenGLPixelFormat *p = [[NSOpenGLPixelFormat alloc]
+                             initWithAttributes:attrs];
+  [p autorelease];
+  return p;
 }
 
 #else  // USE_IPHONE
@@ -2170,7 +2258,7 @@ to_pow2 (size_t x)
   if (relaunch_p) {   // Fake a shake on the SaverListController.
     [_delegate didShake:self];
   } else {     // Not launching another, animate our return to the list.
-# if TARGET_IPHONE_SIMULATOR
+# if !defined __OPTIMIZE__ || TARGET_IPHONE_SIMULATOR
     NSLog (@"fading back to saver list");
 # endif
     [_delegate wantsFadeOut:self];
@@ -2178,149 +2266,6 @@ to_pow2 (size_t x)
 }
 
 
-/* Whether the shape of the X11 Window should be changed to HxW when the
-   device is in a landscape orientation.  X11 hacks want this, but OpenGL
-   hacks do not.
- */
-- (BOOL)reshapeRotatedWindow
-{
-  return YES;
-}
-
-
-/* Called after the device's orientation has changed.
-   
-   Rotation is complicated: the UI, X11 and OpenGL work in 3 different ways.
-
-   The UI (list of savers, preferences panels) is rotated by the system,
-   because its UIWindow is under a UINavigationController that does
-   automatic rotation, using Core Animation.
-
-   The savers are under a different UIWindow and a UINavigationController
-   that does not do automatic rotation.
-
-   We have to do it this way because using Core Animation on an EAGLContext
-   causes the OpenGL pipeline used on both X11 and GL savers to fall back on
-   software rendering and performance goes to hell.
-
-   During and after rotation, the size/shape of the X11 window changes,
-   and ConfigureNotify events are generated.
-
-   X11 code (jwxyz) continues to draw into the (reshaped) backbuffer, which is
-   rendered onto a rotating OpenGL quad.
-
-   GL code always recieves a portrait-oriented X11 Window whose size never
-   changes.  The GL COLOR_BUFFER is displayed on the hardware directly and
-   unrotated, so the GL hacks themselves are responsible for rotating the
-   GL scene to match current_device_rotation().
-
-   Touch events are converted to mouse clicks, and those XEvent coordinates
-   are reported in the coordinate system currently in use by the X11 window.
-   Again, GL must convert those.
- */
-- (void)didRotate:(NSNotification *)notification
-{
-  UIDeviceOrientation current = [[UIDevice currentDevice] orientation];
-
-  /* Sometimes UIDevice doesn't know the proper orientation, or the device is
-     face up/face down, so in those cases fall back to the status bar
-     orientation. The SaverViewController tries to set the status bar to the
-     proper orientation before it creates the XScreenSaverView; see
-     _storedOrientation in SaverViewController.
-   */
-  if (current == UIDeviceOrientationUnknown ||
-    current == UIDeviceOrientationFaceUp ||
-    current == UIDeviceOrientationFaceDown) {
-    /* Mind the differences between UIInterfaceOrientation and
-       UIDeviceOrientaiton:
-       1. UIInterfaceOrientation does not include FaceUp and FaceDown.
-       2. LandscapeLeft and LandscapeRight are swapped between the two. But
-          converting between device and interface orientation doesn't need to
-          take this into account, because (from the UIInterfaceOrientation
-          description): "rotating the device requires rotating the content in
-          the opposite direction."
-        */
-    current = [UIApplication sharedApplication].statusBarOrientation;
-  }
-
-  /* On the iPad (but not iPhone 3GS, or the simulator) sometimes we get
-     an orientation change event with an unknown orientation.  Those seem
-     to always be immediately followed by another orientation change with
-     a *real* orientation change, so let's try just ignoring those bogus
-     ones and hoping that the real one comes in shortly...
-   */
-  if (current == UIDeviceOrientationUnknown)
-    return;
-
-  if (rotation_ratio >= 0) return;     // in the midst of rotation animation
-  if (orientation == current) return;  // no change
-
-  new_orientation = current;           // current animation target
-  rotation_ratio = 0;                  // start animating
-  rot_start_time = double_time();
-
-  switch (orientation) {
-  case UIDeviceOrientationLandscapeLeft:      angle_from = 90;  break;
-  case UIDeviceOrientationLandscapeRight:     angle_from = 270; break;
-  case UIDeviceOrientationPortraitUpsideDown: angle_from = 180; break;
-  default:                                    angle_from = 0;   break;
-  }
-
-  switch (new_orientation) {
-  case UIDeviceOrientationLandscapeLeft:      angle_to = 90;  break;
-  case UIDeviceOrientationLandscapeRight:     angle_to = 270; break;
-  case UIDeviceOrientationPortraitUpsideDown: angle_to = 180; break;
-  default:                                    angle_to = 0;   break;
-  }
-
-  switch (orientation) {
-  case UIDeviceOrientationLandscapeRight:      // from landscape
-  case UIDeviceOrientationLandscapeLeft:
-    rot_from.width  = initial_bounds.height;
-    rot_from.height = initial_bounds.width;
-    break;
-  default:                                     // from portrait
-    rot_from.width  = initial_bounds.width;
-    rot_from.height = initial_bounds.height;
-    break;
-  }
-
-  switch (new_orientation) {
-  case UIDeviceOrientationLandscapeRight:      // to landscape
-  case UIDeviceOrientationLandscapeLeft:
-    rot_to.width  = initial_bounds.height;
-    rot_to.height = initial_bounds.width;
-    break;
-  default:                                     // to portrait
-    rot_to.width  = initial_bounds.width;
-    rot_to.height = initial_bounds.height;
-    break;
-  }
-
-# if TARGET_IPHONE_SIMULATOR
-  NSLog (@"%srotation begun: %s %d -> %s %d; %d x %d",
-         initted_p ? "" : "initial ",
-         orientname(orientation), (int) rot_current_angle,
-         orientname(new_orientation), (int) angle_to,
-         (int) rot_current_size.width, (int) rot_current_size.height);
-# endif
-
-  // Even though the status bar isn't on the screen, this still does two things:
-  // 1. It fixes the orientation of the iOS simulator.
-  // 2. It places the iOS notification center on the expected edge.
-  // 3. It prevents the notification center from causing rotation events.
-  [[UIApplication sharedApplication] setStatusBarOrientation:new_orientation
-                                                    animated:NO];
-
- if (! initted_p) {
-   // If we've done a rotation but the saver hasn't been initialized yet,
-   // don't bother going through an X11 resize, but just do it now.
-   rot_start_time = 0;  // dawn of time
-   [self hackRotation];
- }
-}
-
-
 /* We distinguish between taps and drags.
 
    - Drags/pans (down, motion, up) are sent to the saver to handle.
@@ -2418,66 +2363,85 @@ to_pow2 (size_t x)
    
    Tests:
                      iPad2 iPadAir iPhone4s iPhone5 iPhone6+
-     Attraction        X  yes  Y       Y       Y       Y       Y
-     Fireworkx X  no   Y       Y       Y       Y       Y
-     Carousel  GL yes  Y       Y       Y       Y       Y
-     Voronoi   GL no   Y       Y       Y       Y       Y
+     Attraction        X  yes  -       -       -       -       Y
+     Fireworkx X  no   -       -       -       -       Y
+     Carousel  GL yes  -       -       -       -       Y
+     Voronoi   GL no   -       -       -       -       -
  */
-- (void) convertMouse:(int)rot x:(int*)x y:(int *)y
+- (void) convertMouse:(CGPoint *)p
 {
-  int xx = *x, yy = *y;
+  CGFloat xx = p->x, yy = p->y;
 
 # if TARGET_IPHONE_SIMULATOR
   {
     XWindowAttributes xgwa;
     XGetWindowAttributes (xdpy, xwindow, &xgwa);
-    NSLog (@"TOUCH %4d, %-4d in %4d x %-4d  ig=%d rr=%d cs=%.0f hcs=%.0f\n",
-           *x, *y, 
+    NSLog (@"TOUCH %4g, %-4g in %4d x %-4d  cs=%.0f hcs=%.0f r=%d ig=%d\n",
+           p->x, p->y,
            xgwa.width, xgwa.height,
-           ignore_rotation_p, [self reshapeRotatedWindow],
            [self contentScaleFactor],
-           [self hackedContentScaleFactor]);
+           [self hackedContentScaleFactor],
+           [self rotateTouches], [self ignoreRotation]);
   }
 # endif // TARGET_IPHONE_SIMULATOR
 
-  if (!ignore_rotation_p && [self reshapeRotatedWindow]) {
+  if ([self rotateTouches]) {
+
+    // The XScreenSaverGLView case:
+    // The X11 window is rotated, as is the framebuffer.
+    // The device coordinates match the framebuffer dimensions,
+    // but might have axes swapped... and we need to swap them
+    // by ratios.
     //
-    // For X11 hacks with ignoreRotation == false, we need to rotate the
-    // coordinates to match the unrotated X11 window.  We do not do this
-    // for GL hacks, or for X11 hacks with ignoreRotation == true.
+    int w = [self frame].size.width;
+    int h = [self frame].size.height;
+    GLfloat xr = (GLfloat) xx / w;
+    GLfloat yr = (GLfloat) yy / h;
+    GLfloat swap;
+    int o = (int) current_device_rotation();
+    switch (o) {
+    case -90: case  270: swap = xr; xr = 1-yr; yr = swap;   break;
+    case  90: case -270: swap = xr; xr = yr;   yr = 1-swap; break;
+    case 180: case -180:            xr = 1-xr; yr = 1-yr;   break;
+    default: break;
+    }
+    xx = xr * w;
+    yy = yr * h;
+
+  } else if ([self ignoreRotation]) {
+
+    // The X11 case, where the hack has opted not to rotate:
+    // The X11 window is unrotated, but the framebuffer is rotated.
+    // The device coordinates match the framebuffer, so they need to
+    // be de-rotated to match the X11 window.
     //
     int w = [self frame].size.width;
     int h = [self frame].size.height;
     int swap;
-    switch (orientation) {
-    case UIDeviceOrientationLandscapeRight:
-      swap = xx; xx = h-yy; yy = swap;
-      break;
-    case UIDeviceOrientationLandscapeLeft:
-      swap = xx; xx = yy; yy = w-swap;
-      break;
-    case UIDeviceOrientationPortraitUpsideDown: 
-      xx = w-xx; yy = h-yy;
-    default:
-      break;
+    int o = (int) current_device_rotation();
+    switch (o) {
+    case -90: case  270: swap = xx; xx = h-yy; yy = swap;   break;
+    case  90: case -270: swap = xx; xx = yy;   yy = w-swap; break;
+    case 180: case -180:            xx = w-xx; yy = h-yy;   break;
+    default: break;
     }
   }
 
   double s = [self hackedContentScaleFactor];
-  *x = xx * s;
-  *y = yy * s;
+  p->x = xx * s;
+  p->y = yy * s;
 
 # if TARGET_IPHONE_SIMULATOR || !defined __OPTIMIZE__
   {
     XWindowAttributes xgwa;
     XGetWindowAttributes (xdpy, xwindow, &xgwa);
-    NSLog (@"touch %4d, %-4d in %4d x %-4d  ig=%d rr=%d cs=%.0f hcs=%.0f\n",
-           *x, *y, 
+    NSLog (@"touch %4g, %-4g in %4d x %-4d  cs=%.0f hcs=%.0f r=%d ig=%d\n",
+           p->x, p->y,
            xgwa.width, xgwa.height,
-           ignore_rotation_p, [self reshapeRotatedWindow],
            [self contentScaleFactor],
-           [self hackedContentScaleFactor]);
-    if (*x < 0 || *y < 0 || *x > xgwa.width || *y > xgwa.height)
+           [self hackedContentScaleFactor],
+           [self rotateTouches], [self ignoreRotation]);
+    if (p->x < 0 || p->y < 0 || p->x > xgwa.width || p->y > xgwa.height)
       abort();
   }
 # endif // TARGET_IPHONE_SIMULATOR
@@ -2520,30 +2484,30 @@ to_pow2 (size_t x)
   memset (&xe, 0, sizeof(xe));
 
   CGPoint p = [sender locationInView:self];  // this is in points, not pixels
-  int x = p.x;
-  int y = p.y;
-  [self convertMouse: rot_current_angle x:&x y:&y];
-  jwxyz_mouse_moved (xdpy, xwindow, x, y);
+  [self convertMouse:&p];
+  NSAssert (xwindow && xwindow->type == WINDOW, @"not a window");
+  xwindow->window.last_mouse_x = p.x;
+  xwindow->window.last_mouse_y = p.y;
 
   switch (sender.state) {
   case UIGestureRecognizerStateBegan:
     xe.xany.type = ButtonPress;
     xe.xbutton.button = 1;
-    xe.xbutton.x = x;
-    xe.xbutton.y = y;
+    xe.xbutton.x = p.x;
+    xe.xbutton.y = p.y;
     break;
 
   case UIGestureRecognizerStateEnded:
     xe.xany.type = ButtonRelease;
     xe.xbutton.button = 1;
-    xe.xbutton.x = x;
-    xe.xbutton.y = y;
+    xe.xbutton.x = p.x;
+    xe.xbutton.y = p.y;
     break;
 
   case UIGestureRecognizerStateChanged:
     xe.xany.type = MotionNotify;
-    xe.xmotion.x = x;
-    xe.xmotion.y = y;
+    xe.xmotion.x = p.x;
+    xe.xmotion.y = p.y;
     break;
 
   default:
@@ -2579,14 +2543,12 @@ to_pow2 (size_t x)
   memset (&xe, 0, sizeof(xe));
 
   CGPoint p = [sender locationInView:self];  // this is in points, not pixels
-  int x = p.x;
-  int y = p.y;
-  [self convertMouse: rot_current_angle x:&x y:&y];
+  [self convertMouse:&p];
 
-  if (abs(x) > abs(y))
-    xe.xkey.keycode = (x > 0 ? XK_Right : XK_Left);
+  if (fabs(p.x) > fabs(p.y))
+    xe.xkey.keycode = (p.x > 0 ? XK_Right : XK_Left);
   else
-    xe.xkey.keycode = (y > 0 ? XK_Down : XK_Up);
+    xe.xkey.keycode = (p.y > 0 ? XK_Down : XK_Up);
 
   BOOL ok1 = [self sendEvent: &xe];
   xe.xany.type = KeyRelease;
@@ -2637,6 +2599,12 @@ to_pow2 (size_t x)
 {
   return [NSDictionary dictionaryWithObjectsAndKeys:
           kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat,
+# ifdef JWXYZ_GL
+          /* This could be disabled if we knew the screen would be redrawn
+             entirely for every frame.
+           */
+          [NSNumber numberWithBool:YES], kEAGLDrawablePropertyRetainedBacking,
+# endif // JWXYZ_GL
           nil];
 }
 
@@ -2644,6 +2612,13 @@ to_pow2 (size_t x)
 {
   // No extra renderbuffers are needed for 2D screenhacks.
 }
+
+- (NSString *)getCAGravity
+{
+  return kCAGravityCenter;  // Looks better in e.g. Compass.
+//  return kCAGravityBottomLeft;
+}
 
 #endif // USE_IPHONE
 
@@ -2706,7 +2681,7 @@ to_pow2 (size_t x)
                    options:(NSWorkspaceLaunchWithoutAddingToRecents |
                             NSWorkspaceLaunchWithoutActivation |
                             NSWorkspaceLaunchAndHide)
-                   configuration:nil
+                   configuration:[NSMutableDictionary dictionary]
                    error:&err]) {
     NSLog(@"Unable to launch %@: %@", app_path, err);
   }
index c637fe8ba08386f61908595c4b9857df039aed0e..a5ea639e104c9a41cd3e8c6a3ddc14981dbbc117 100644 (file)
 \b0 by Jamie Zawinski\
 and many others\
 \
-version 5.34\
-24-Oct-2015\
+version 5.35\
+24-May-2016\
 \
-{\field{\*\fldinst{HYPERLINK "http://www.jwz.org/xscreensaver/"}}{\fldrslt \cf2 \ul \ulc2 http://www.jwz.org/xscreensaver/}}\
+{\field{\*\fldinst{HYPERLINK "https://www.jwz.org/xscreensaver/"}}{\fldrslt \cf2 \ul \ulc2 https://www.jwz.org/xscreensaver/}}\
 \pard\pardeftab720
 \cf0 \
 
@@ -57,7 +57,7 @@ unwanted savers to Trash.\
 
 \b0 \cf0 \
 Please visit the 
-{\field{\*\fldinst{HYPERLINK "http://www.jwz.org/xscreensaver/"}}
+{\field{\*\fldinst{HYPERLINK "https://www.jwz.org/xscreensaver/"}}
 {\fldrslt \cf2 \ul \ulc2 XScreenSaver web site}}. 
 The XScreenSaver collection is free software, and all source code is 
 available there.\
@@ -69,6 +69,6 @@ available there.\
 
 \b0 \cf0 \
 XScreenSaver also runs on iOS.  It is available in the 
-{\field{\*\fldinst{HYPERLINK "http://itunes.apple.com/app/xscreensaver/id539014593?mt=8"}}
+{\field{\*\fldinst{HYPERLINK "https://itunes.apple.com/app/xscreensaver/id539014593?mt=8"}}
 {\fldrslt \cf2 \ul \ulc2 iTunes App Store}}, and it's free!
 }
index 7e3a6f5ea3d0571f2044efcad3f4039021a6d77c..dc69dfecc7468f036caf80c7619b057a6b04140c 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/perl -w
-# Copyright © 2012-2014 Jamie Zawinski <jwz@jwz.org>
+# Copyright © 2012-2015 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
@@ -23,7 +23,7 @@ require 5;
 use strict;
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my ($version) = ('$Revision: 1.3 $' =~ m/\s(\d[.\d]+)\s/s);
+my ($version) = ('$Revision: 1.5 $' =~ m/\s(\d[.\d]+)\s/s);
 
 my $verbose = 1;
 
@@ -34,6 +34,7 @@ my %disable = (
    'lcdscrub'          => 1,
    'lockward'          => 1,
    'webcollage'                => 1,
+   'testx11'           => 1,
   );
 
 # Parse the RETIRED_EXES variable from the Makefiles to populate %disable.
@@ -102,8 +103,8 @@ sub build_h($) {
               "\n");
 
   $body .= "extern struct $suf";
-  foreach my $s (@names) {
-    $body .= "\n *${s}_${suf},";
+  foreach my $s (@names, 'testx11') {
+    $body .= "\n ${s}_${suf},";
   }
   $body =~ s/,\s*$/;/s;
 
@@ -120,6 +121,8 @@ sub build_h($) {
             " " . line('apple2', $suf) .
             "#elif defined(PHOSPHOR_ONLY)\n" .
             " " . line('phosphor', $suf) .
+            "#elif defined(TESTX11_ONLY)\n" .
+            " " . line('testx11', $suf) .
             "#else\n");
   foreach my $s (@names) { $body .= line($s, $suf); }
   $body .= ("#endif\n" .
diff --git a/OSX/fuzztest.sh b/OSX/fuzztest.sh
new file mode 100755 (executable)
index 0000000..20d596a
--- /dev/null
@@ -0,0 +1,54 @@
+#!/bin/sh
+# Copyright © 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.
+#
+# Deliver random rotate and shake gestures to the iOS Simulator window.
+#
+# To make this work, you probably need to go to "System Preferences /
+# Security & Privacy / Privacy / Accessibility" and add "Terminal.app"
+# to the list of allowed programs.
+#
+# Created: 18-Apr-2016.
+
+function menu() {
+  which="$1"
+  sim="Simulator"
+ #proc="SystemUIServer"
+  proc="System Events"
+
+  osascript -e "
+   tell application \"$sim\" to activate
+   tell application \"$proc\"
+    tell process \"$sim\"
+     tell menu bar item \"Hardware\" of menu bar 1
+      click menu item \"$which\" of menu \"Hardware\"
+      \"$which\"
+     end tell
+    end tell
+   end tell"
+}
+
+menu 'Shake Gesture'
+
+while true; do
+  i=$[ 2 + $[ RANDOM % 5 ]]
+  echo "sleep $i" ; sleep $i
+  i=$[ RANDOM % 5]
+  if [ $i == 0 ]; then menu 'Shake Gesture'
+  else
+    i=$[ RANDOM % 3]
+    if   [ $i == 0 ]; then menu 'Rotate Left'
+    elif [ $i == 1 ]; then menu 'Rotate Right'
+    else menu 'Rotate Right' ; menu 'Rotate Right'
+    fi
+  fi
+done
+
+exit 0
index 1fa2e2741c74a9cbb43bb74e6894cd98037dc7f8..e62769485a2c96fc5bbfbdaea1413861f1887b5c 100644 (file)
@@ -9,37 +9,38 @@
        <key>CFBundleExecutable</key>
        <string>${EXECUTABLE_NAME}</string>
        <key>CFBundleGetInfoString</key>
-       <string>5.34</string>
+       <string>5.35</string>
        <key>CFBundleIcons</key>
        <dict/>
        <key>CFBundleIcons~ipad</key>
        <dict/>
        <key>CFBundleIdentifier</key>
-       <string>${BUNDLE_IDENTIFIER}</string>
+       <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleLongVersionString</key>
-       <string>5.34</string>
+       <string>5.35</string>
        <key>CFBundleName</key>
        <string>${PRODUCT_NAME}</string>
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleShortVersionString</key>
-       <string>5.34</string>
+       <string>5.35</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.34</string>
+       <string>5.35</string>
        <key>LSRequiresIPhoneOS</key>
        <true/>
        <key>NSHumanReadableCopyright</key>
-       <string>5.34</string>
+       <string>5.35</string>
        <key>NSMainNibFile</key>
        <string>iSaverRunner</string>
        <key>UIAppFonts</key>
        <array>
                <string>OCRAStd.otf</string>
                <string>YearlReg.ttf</string>
+               <string>PxPlus_IBM_VGA8.ttf</string>
        </array>
        <key>UILaunchStoryboardName</key>
        <string>LaunchScreen</string>
index 577cea929d37aa65bc0be119b5007978e1b3b238..ac70579e35345591162a12aabfcb7db181c2da37 100644 (file)
-<?xml version="1.0" encoding="UTF-8"?>
-<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10">
-       <data>
-               <int key="IBDocument.SystemTarget">512</int>
-               <string key="IBDocument.SystemVersion">11E53</string>
-               <string key="IBDocument.InterfaceBuilderVersion">2182</string>
-               <string key="IBDocument.AppKitVersion">1138.47</string>
-               <string key="IBDocument.HIToolboxVersion">569.00</string>
-               <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
-                       <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
-                       <string key="NS.object.0">1181</string>
-               </object>
-               <object class="NSArray" key="IBDocument.IntegratedClassDependencies">
-                       <bool key="EncodedWithXMLCoder">YES</bool>
-                       <string>IBUIWindow</string>
-                       <string>IBProxyObject</string>
-                       <string>IBUICustomObject</string>
-               </object>
-               <object class="NSArray" key="IBDocument.PluginDependencies">
-                       <bool key="EncodedWithXMLCoder">YES</bool>
-                       <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
-               </object>
-               <object class="NSMutableDictionary" key="IBDocument.Metadata">
-                       <string key="NS.key.0">PluginDependencyRecalculationVersion</string>
-                       <integer value="1" key="NS.object.0"/>
-               </object>
-               <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
-                       <bool key="EncodedWithXMLCoder">YES</bool>
-                       <object class="IBProxyObject" id="841351856">
-                               <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
-                               <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
-                       </object>
-                       <object class="IBProxyObject" id="240144534">
-                               <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
-                               <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
-                       </object>
-                       <object class="IBUICustomObject" id="664661524">
-                               <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
-                       </object>
-                       <object class="IBUIWindow" id="380026005">
-                               <reference key="NSNextResponder"/>
-                               <int key="NSvFlags">1298</int>
-                               <object class="NSPSMatrix" key="NSFrameMatrix"/>
-                               <string key="NSFrameSize">{320, 480}</string>
-                               <reference key="NSSuperview"/>
-                               <reference key="NSWindow"/>
-                               <reference key="NSNextKeyView"/>
-                               <object class="NSColor" key="IBUIBackgroundColor">
-                                       <int key="NSColorSpace">1</int>
-                                       <bytes key="NSRGB">MCAwIDAAA</bytes>
-                               </object>
-                               <bool key="IBUIOpaque">NO</bool>
-                               <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
-                               <bool key="IBUIMultipleTouchEnabled">YES</bool>
-                               <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
-                               <bool key="IBUIVisibleAtLaunch">YES</bool>
-                               <bool key="IBUIResizesToFullScreen">YES</bool>
-                       </object>
-               </object>
-               <object class="IBObjectContainer" key="IBDocument.Objects">
-                       <object class="NSMutableArray" key="connectionRecords">
-                               <bool key="EncodedWithXMLCoder">YES</bool>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBCocoaTouchOutletConnection" key="connection">
-                                               <string key="label">delegate</string>
-                                               <reference key="source" ref="841351856"/>
-                                               <reference key="destination" ref="664661524"/>
-                                       </object>
-                                       <int key="connectionID">9</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBCocoaTouchOutletConnection" key="connection">
-                                               <string key="label">window</string>
-                                               <reference key="source" ref="664661524"/>
-                                               <reference key="destination" ref="380026005"/>
-                                       </object>
-                                       <int key="connectionID">5</int>
-                               </object>
-                       </object>
-                       <object class="IBMutableOrderedSet" key="objectRecords">
-                               <object class="NSArray" key="orderedObjects">
-                                       <bool key="EncodedWithXMLCoder">YES</bool>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">0</int>
-                                               <object class="NSArray" key="object" id="0">
-                                                       <bool key="EncodedWithXMLCoder">YES</bool>
-                                               </object>
-                                               <reference key="children" ref="1000"/>
-                                               <nil key="parent"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">2</int>
-                                               <reference key="object" ref="380026005"/>
-                                               <object class="NSMutableArray" key="children">
-                                                       <bool key="EncodedWithXMLCoder">YES</bool>
-                                               </object>
-                                               <reference key="parent" ref="0"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">-1</int>
-                                               <reference key="object" ref="841351856"/>
-                                               <reference key="parent" ref="0"/>
-                                               <string key="objectName">File's Owner</string>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">3</int>
-                                               <reference key="object" ref="664661524"/>
-                                               <reference key="parent" ref="0"/>
-                                               <string key="objectName">SaverRunner</string>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">-2</int>
-                                               <reference key="object" ref="240144534"/>
-                                               <reference key="parent" ref="0"/>
-                                       </object>
-                               </object>
-                       </object>
-                       <object class="NSMutableDictionary" key="flattenedProperties">
-                               <bool key="EncodedWithXMLCoder">YES</bool>
-                               <object class="NSArray" key="dict.sortedKeys">
-                                       <bool key="EncodedWithXMLCoder">YES</bool>
-                                       <string>-1.CustomClassName</string>
-                                       <string>-1.IBPluginDependency</string>
-                                       <string>-2.CustomClassName</string>
-                                       <string>-2.IBPluginDependency</string>
-                                       <string>2.IBAttributePlaceholdersKey</string>
-                                       <string>2.IBPluginDependency</string>
-                                       <string>3.CustomClassName</string>
-                                       <string>3.IBPluginDependency</string>
-                               </object>
-                               <object class="NSArray" key="dict.values">
-                                       <bool key="EncodedWithXMLCoder">YES</bool>
-                                       <string>UIApplication</string>
-                                       <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
-                                       <string>UIResponder</string>
-                                       <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
-                                       <object class="NSMutableDictionary">
-                                               <bool key="EncodedWithXMLCoder">YES</bool>
-                                               <reference key="dict.sortedKeys" ref="0"/>
-                                               <reference key="dict.values" ref="0"/>
-                                       </object>
-                                       <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
-                                       <string>SaverRunner</string>
-                                       <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
-                               </object>
-                       </object>
-                       <object class="NSMutableDictionary" key="unlocalizedProperties">
-                               <bool key="EncodedWithXMLCoder">YES</bool>
-                               <reference key="dict.sortedKeys" ref="0"/>
-                               <reference key="dict.values" ref="0"/>
-                       </object>
-                       <nil key="activeLocalization"/>
-                       <object class="NSMutableDictionary" key="localizations">
-                               <bool key="EncodedWithXMLCoder">YES</bool>
-                               <reference key="dict.sortedKeys" ref="0"/>
-                               <reference key="dict.values" ref="0"/>
-                       </object>
-                       <nil key="sourceID"/>
-                       <int key="maxID">9</int>
-               </object>
-               <object class="IBClassDescriber" key="IBDocument.Classes"/>
-               <int key="IBDocument.localizationMode">0</int>
-               <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
-               <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies">
-                       <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
-                       <integer value="512" key="NS.object.0"/>
-               </object>
-               <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
-                       <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string>
-                       <integer value="3000" key="NS.object.0"/>
-               </object>
-               <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
-               <int key="IBDocument.defaultPropertyAccessControl">3</int>
-               <string key="IBCocoaTouchPluginVersion">1181</string>
-       </data>
-</archive>
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="9531" systemVersion="15C50" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
+    <dependencies>
+        <deployment version="1536" identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9529"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="UIApplication">
+            <connections>
+                <outlet property="delegate" destination="3" id="9"/>
+            </connections>
+        </placeholder>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <customObject id="3" userLabel="SaverRunner" customClass="SaverRunner">
+            <connections>
+                <outlet property="window" destination="2" id="5"/>
+            </connections>
+        </customObject>
+        <window opaque="NO" clearsContextBeforeDrawing="NO" multipleTouchEnabled="YES" contentMode="scaleToFill" visibleAtLaunch="YES" id="2">
+            <rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
+            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+            <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
+            <nil key="simulatedStatusBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+        </window>
+    </objects>
+</document>
index 97524c48e41d676599c08b06fc5983e75f85a253..87eb506e0cca0debd5319774041fa4c0dd4a49b0 100644 (file)
@@ -18,10 +18,10 @@ on only the ones that you want.\
 The full installation will take around 160 MB.\
 \
 Please visit the 
-{\field{\*\fldinst{HYPERLINK "http://www.jwz.org/xscreensaver/"}}{\fldrslt \cf2 \ul \ulc2 XScreenSaver web site}}. 
+{\field{\*\fldinst{HYPERLINK "https://www.jwz.org/xscreensaver/"}}{\fldrslt \cf2 \ul \ulc2 XScreenSaver web site}}. 
 The XScreenSaver collection is free software, and all source code 
 is available there.\
 \
 XScreenSaver also runs on iPhones and iPads. It is available in the 
-{\field{\*\fldinst{HYPERLINK "http://itunes.apple.com/app/xscreensaver/id539014593?mt=8"}}{\fldrslt \cf2 \ul \ulc2 iTunes App Store}}, 
+{\field{\*\fldinst{HYPERLINK "https://itunes.apple.com/app/xscreensaver/id539014593?mt=8"}}{\fldrslt \cf2 \ul \ulc2 iTunes App Store}}, 
 and it's free!}
index ba0e1383662fed14f135602df8794af5a515d9d8..b66570d0ae2af8091c457273454213d93fa9caab 100644 (file)
@@ -1,5 +1,5 @@
 /* Generated file, do not edit.
-   Created: Sat May  2 19:45:40 2015 by build-fntable.pl 1.3.
+   Created: Thu May  5 22:34:31 2016 by build-fntable.pl 1.5.
  */
 
 #import <Foundation/Foundation.h>
 extern NSDictionary *make_function_table_dict(void);
 
 extern struct xscreensaver_function_table
- *abstractile_xscreensaver_function_table,
- *anemone_xscreensaver_function_table,
- *anemotaxis_xscreensaver_function_table,
- *antinspect_xscreensaver_function_table,
- *antmaze_xscreensaver_function_table,
- *antspotlight_xscreensaver_function_table,
- *apollonian_xscreensaver_function_table,
- *apple2_xscreensaver_function_table,
- *atlantis_xscreensaver_function_table,
- *attraction_xscreensaver_function_table,
- *atunnel_xscreensaver_function_table,
- *barcode_xscreensaver_function_table,
- *binaryring_xscreensaver_function_table,
- *blaster_xscreensaver_function_table,
- *blinkbox_xscreensaver_function_table,
- *blitspin_xscreensaver_function_table,
- *blocktube_xscreensaver_function_table,
- *boing_xscreensaver_function_table,
- *bouboule_xscreensaver_function_table,
- *bouncingcow_xscreensaver_function_table,
- *boxed_xscreensaver_function_table,
- *boxfit_xscreensaver_function_table,
- *braid_xscreensaver_function_table,
- *bsod_xscreensaver_function_table,
- *bubble3d_xscreensaver_function_table,
- *bumps_xscreensaver_function_table,
- *cage_xscreensaver_function_table,
- *carousel_xscreensaver_function_table,
- *ccurve_xscreensaver_function_table,
- *celtic_xscreensaver_function_table,
- *circuit_xscreensaver_function_table,
- *cityflow_xscreensaver_function_table,
- *cloudlife_xscreensaver_function_table,
- *companioncube_xscreensaver_function_table,
- *compass_xscreensaver_function_table,
- *coral_xscreensaver_function_table,
- *crackberg_xscreensaver_function_table,
- *crystal_xscreensaver_function_table,
- *cube21_xscreensaver_function_table,
- *cubenetic_xscreensaver_function_table,
- *cubestorm_xscreensaver_function_table,
- *cubicgrid_xscreensaver_function_table,
- *cwaves_xscreensaver_function_table,
- *cynosure_xscreensaver_function_table,
- *dangerball_xscreensaver_function_table,
- *decayscreen_xscreensaver_function_table,
- *deco_xscreensaver_function_table,
- *deluxe_xscreensaver_function_table,
- *demon_xscreensaver_function_table,
- *discrete_xscreensaver_function_table,
- *distort_xscreensaver_function_table,
- *dnalogo_xscreensaver_function_table,
- *drift_xscreensaver_function_table,
- *endgame_xscreensaver_function_table,
- *engine_xscreensaver_function_table,
- *epicycle_xscreensaver_function_table,
- *eruption_xscreensaver_function_table,
- *euler2d_xscreensaver_function_table,
- *fadeplot_xscreensaver_function_table,
- *fiberlamp_xscreensaver_function_table,
- *fireworkx_xscreensaver_function_table,
- *flame_xscreensaver_function_table,
- *flipflop_xscreensaver_function_table,
- *flipscreen3d_xscreensaver_function_table,
- *fliptext_xscreensaver_function_table,
- *flow_xscreensaver_function_table,
- *fluidballs_xscreensaver_function_table,
- *flyingtoasters_xscreensaver_function_table,
- *fontglide_xscreensaver_function_table,
- *fuzzyflakes_xscreensaver_function_table,
- *galaxy_xscreensaver_function_table,
- *gears_xscreensaver_function_table,
- *geodesic_xscreensaver_function_table,
- *geodesicgears_xscreensaver_function_table,
- *gflux_xscreensaver_function_table,
- *glblur_xscreensaver_function_table,
- *glcells_xscreensaver_function_table,
- *gleidescope_xscreensaver_function_table,
- *glhanoi_xscreensaver_function_table,
- *glknots_xscreensaver_function_table,
- *glmatrix_xscreensaver_function_table,
- *glplanet_xscreensaver_function_table,
- *glschool_xscreensaver_function_table,
- *glslideshow_xscreensaver_function_table,
- *glsnake_xscreensaver_function_table,
- *gltext_xscreensaver_function_table,
- *goop_xscreensaver_function_table,
- *grav_xscreensaver_function_table,
- *greynetic_xscreensaver_function_table,
- *halftone_xscreensaver_function_table,
- *halo_xscreensaver_function_table,
- *helix_xscreensaver_function_table,
- *hexadrop_xscreensaver_function_table,
- *hilbert_xscreensaver_function_table,
- *hopalong_xscreensaver_function_table,
- *hypertorus_xscreensaver_function_table,
- *hypnowheel_xscreensaver_function_table,
- *ifs_xscreensaver_function_table,
- *imsmap_xscreensaver_function_table,
- *interaggregate_xscreensaver_function_table,
- *interference_xscreensaver_function_table,
- *intermomentary_xscreensaver_function_table,
- *jigglypuff_xscreensaver_function_table,
- *jigsaw_xscreensaver_function_table,
- *juggler3d_xscreensaver_function_table,
- *julia_xscreensaver_function_table,
- *kaleidescope_xscreensaver_function_table,
- *kaleidocycle_xscreensaver_function_table,
- *klein_xscreensaver_function_table,
- *kumppa_xscreensaver_function_table,
- *lament_xscreensaver_function_table,
- *lavalite_xscreensaver_function_table,
- *loop_xscreensaver_function_table,
- *m6502_xscreensaver_function_table,
- *maze_xscreensaver_function_table,
- *memscroller_xscreensaver_function_table,
- *menger_xscreensaver_function_table,
- *metaballs_xscreensaver_function_table,
- *mirrorblob_xscreensaver_function_table,
- *moebius_xscreensaver_function_table,
- *moebiusgears_xscreensaver_function_table,
- *moire_xscreensaver_function_table,
- *moire2_xscreensaver_function_table,
- *molecule_xscreensaver_function_table,
- *morph3d_xscreensaver_function_table,
- *mountain_xscreensaver_function_table,
- *munch_xscreensaver_function_table,
- *nerverot_xscreensaver_function_table,
- *noof_xscreensaver_function_table,
- *noseguy_xscreensaver_function_table,
- *pacman_xscreensaver_function_table,
- *pedal_xscreensaver_function_table,
- *penetrate_xscreensaver_function_table,
- *penrose_xscreensaver_function_table,
- *petri_xscreensaver_function_table,
- *phosphor_xscreensaver_function_table,
- *photopile_xscreensaver_function_table,
- *piecewise_xscreensaver_function_table,
- *pinion_xscreensaver_function_table,
- *pipes_xscreensaver_function_table,
- *polyhedra_xscreensaver_function_table,
- *polyominoes_xscreensaver_function_table,
- *polytopes_xscreensaver_function_table,
- *pong_xscreensaver_function_table,
- *popsquares_xscreensaver_function_table,
- *projectiveplane_xscreensaver_function_table,
- *providence_xscreensaver_function_table,
- *pulsar_xscreensaver_function_table,
- *pyro_xscreensaver_function_table,
- *qix_xscreensaver_function_table,
- *quasicrystal_xscreensaver_function_table,
- *queens_xscreensaver_function_table,
- *rdbomb_xscreensaver_function_table,
- *ripples_xscreensaver_function_table,
- *rocks_xscreensaver_function_table,
- *romanboy_xscreensaver_function_table,
- *rorschach_xscreensaver_function_table,
- *rotzoomer_xscreensaver_function_table,
- *rubik_xscreensaver_function_table,
- *rubikblocks_xscreensaver_function_table,
- *sballs_xscreensaver_function_table,
- *shadebobs_xscreensaver_function_table,
- *sierpinski_xscreensaver_function_table,
- *sierpinski3d_xscreensaver_function_table,
- *skytentacles_xscreensaver_function_table,
- *slidescreen_xscreensaver_function_table,
- *slip_xscreensaver_function_table,
- *sonar_xscreensaver_function_table,
- *speedmine_xscreensaver_function_table,
- *spheremonics_xscreensaver_function_table,
- *splitflap_xscreensaver_function_table,
- *spotlight_xscreensaver_function_table,
- *sproingies_xscreensaver_function_table,
- *squiral_xscreensaver_function_table,
- *stairs_xscreensaver_function_table,
- *starfish_xscreensaver_function_table,
- *starwars_xscreensaver_function_table,
- *stonerview_xscreensaver_function_table,
- *strange_xscreensaver_function_table,
- *substrate_xscreensaver_function_table,
- *superquadrics_xscreensaver_function_table,
- *surfaces_xscreensaver_function_table,
- *swirl_xscreensaver_function_table,
- *tangram_xscreensaver_function_table,
- *tessellimage_xscreensaver_function_table,
- *thornbird_xscreensaver_function_table,
- *timetunnel_xscreensaver_function_table,
- *topblock_xscreensaver_function_table,
- *triangle_xscreensaver_function_table,
- *tronbit_xscreensaver_function_table,
- *truchet_xscreensaver_function_table,
- *twang_xscreensaver_function_table,
- *unknownpleasures_xscreensaver_function_table,
- *vermiculate_xscreensaver_function_table,
- *voronoi_xscreensaver_function_table,
- *wander_xscreensaver_function_table,
- *whirlwindwarp_xscreensaver_function_table,
- *winduprobot_xscreensaver_function_table,
- *wormhole_xscreensaver_function_table,
- *xanalogtv_xscreensaver_function_table,
- *xflame_xscreensaver_function_table,
- *xjack_xscreensaver_function_table,
- *xlyap_xscreensaver_function_table,
- *xmatrix_xscreensaver_function_table,
- *xrayswarm_xscreensaver_function_table,
- *xspirograph_xscreensaver_function_table,
- *zoom_xscreensaver_function_table;
+ abstractile_xscreensaver_function_table,
+ anemone_xscreensaver_function_table,
+ anemotaxis_xscreensaver_function_table,
+ antinspect_xscreensaver_function_table,
+ antmaze_xscreensaver_function_table,
+ antspotlight_xscreensaver_function_table,
+ apollonian_xscreensaver_function_table,
+ apple2_xscreensaver_function_table,
+ atlantis_xscreensaver_function_table,
+ attraction_xscreensaver_function_table,
+ atunnel_xscreensaver_function_table,
+ barcode_xscreensaver_function_table,
+ binaryring_xscreensaver_function_table,
+ blaster_xscreensaver_function_table,
+ blinkbox_xscreensaver_function_table,
+ blitspin_xscreensaver_function_table,
+ blocktube_xscreensaver_function_table,
+ boing_xscreensaver_function_table,
+ bouboule_xscreensaver_function_table,
+ bouncingcow_xscreensaver_function_table,
+ boxed_xscreensaver_function_table,
+ boxfit_xscreensaver_function_table,
+ braid_xscreensaver_function_table,
+ bsod_xscreensaver_function_table,
+ bubble3d_xscreensaver_function_table,
+ bumps_xscreensaver_function_table,
+ cage_xscreensaver_function_table,
+ carousel_xscreensaver_function_table,
+ ccurve_xscreensaver_function_table,
+ celtic_xscreensaver_function_table,
+ circuit_xscreensaver_function_table,
+ cityflow_xscreensaver_function_table,
+ cloudlife_xscreensaver_function_table,
+ companioncube_xscreensaver_function_table,
+ compass_xscreensaver_function_table,
+ coral_xscreensaver_function_table,
+ crackberg_xscreensaver_function_table,
+ crystal_xscreensaver_function_table,
+ cube21_xscreensaver_function_table,
+ cubenetic_xscreensaver_function_table,
+ cubestorm_xscreensaver_function_table,
+ cubicgrid_xscreensaver_function_table,
+ cwaves_xscreensaver_function_table,
+ cynosure_xscreensaver_function_table,
+ dangerball_xscreensaver_function_table,
+ decayscreen_xscreensaver_function_table,
+ deco_xscreensaver_function_table,
+ deluxe_xscreensaver_function_table,
+ demon_xscreensaver_function_table,
+ discrete_xscreensaver_function_table,
+ distort_xscreensaver_function_table,
+ dnalogo_xscreensaver_function_table,
+ drift_xscreensaver_function_table,
+ dymaxionmap_xscreensaver_function_table,
+ endgame_xscreensaver_function_table,
+ energystream_xscreensaver_function_table,
+ engine_xscreensaver_function_table,
+ epicycle_xscreensaver_function_table,
+ eruption_xscreensaver_function_table,
+ euler2d_xscreensaver_function_table,
+ fadeplot_xscreensaver_function_table,
+ fiberlamp_xscreensaver_function_table,
+ fireworkx_xscreensaver_function_table,
+ flame_xscreensaver_function_table,
+ flipflop_xscreensaver_function_table,
+ flipscreen3d_xscreensaver_function_table,
+ fliptext_xscreensaver_function_table,
+ flow_xscreensaver_function_table,
+ fluidballs_xscreensaver_function_table,
+ flyingtoasters_xscreensaver_function_table,
+ fontglide_xscreensaver_function_table,
+ fuzzyflakes_xscreensaver_function_table,
+ galaxy_xscreensaver_function_table,
+ gears_xscreensaver_function_table,
+ geodesic_xscreensaver_function_table,
+ geodesicgears_xscreensaver_function_table,
+ gflux_xscreensaver_function_table,
+ glblur_xscreensaver_function_table,
+ glcells_xscreensaver_function_table,
+ gleidescope_xscreensaver_function_table,
+ glhanoi_xscreensaver_function_table,
+ glknots_xscreensaver_function_table,
+ glmatrix_xscreensaver_function_table,
+ glplanet_xscreensaver_function_table,
+ glschool_xscreensaver_function_table,
+ glslideshow_xscreensaver_function_table,
+ glsnake_xscreensaver_function_table,
+ gltext_xscreensaver_function_table,
+ goop_xscreensaver_function_table,
+ grav_xscreensaver_function_table,
+ greynetic_xscreensaver_function_table,
+ halftone_xscreensaver_function_table,
+ halo_xscreensaver_function_table,
+ helix_xscreensaver_function_table,
+ hexadrop_xscreensaver_function_table,
+ hilbert_xscreensaver_function_table,
+ hopalong_xscreensaver_function_table,
+ hydrostat_xscreensaver_function_table,
+ hypertorus_xscreensaver_function_table,
+ hypnowheel_xscreensaver_function_table,
+ ifs_xscreensaver_function_table,
+ imsmap_xscreensaver_function_table,
+ interaggregate_xscreensaver_function_table,
+ interference_xscreensaver_function_table,
+ intermomentary_xscreensaver_function_table,
+ jigglypuff_xscreensaver_function_table,
+ jigsaw_xscreensaver_function_table,
+ juggler3d_xscreensaver_function_table,
+ julia_xscreensaver_function_table,
+ kaleidescope_xscreensaver_function_table,
+ kaleidocycle_xscreensaver_function_table,
+ klein_xscreensaver_function_table,
+ kumppa_xscreensaver_function_table,
+ lament_xscreensaver_function_table,
+ lavalite_xscreensaver_function_table,
+ loop_xscreensaver_function_table,
+ m6502_xscreensaver_function_table,
+ maze_xscreensaver_function_table,
+ memscroller_xscreensaver_function_table,
+ menger_xscreensaver_function_table,
+ metaballs_xscreensaver_function_table,
+ mirrorblob_xscreensaver_function_table,
+ moebius_xscreensaver_function_table,
+ moebiusgears_xscreensaver_function_table,
+ moire_xscreensaver_function_table,
+ moire2_xscreensaver_function_table,
+ molecule_xscreensaver_function_table,
+ morph3d_xscreensaver_function_table,
+ mountain_xscreensaver_function_table,
+ munch_xscreensaver_function_table,
+ nerverot_xscreensaver_function_table,
+ noof_xscreensaver_function_table,
+ noseguy_xscreensaver_function_table,
+ pacman_xscreensaver_function_table,
+ pedal_xscreensaver_function_table,
+ penetrate_xscreensaver_function_table,
+ penrose_xscreensaver_function_table,
+ petri_xscreensaver_function_table,
+ phosphor_xscreensaver_function_table,
+ photopile_xscreensaver_function_table,
+ piecewise_xscreensaver_function_table,
+ pinion_xscreensaver_function_table,
+ pipes_xscreensaver_function_table,
+ polyhedra_xscreensaver_function_table,
+ polyominoes_xscreensaver_function_table,
+ polytopes_xscreensaver_function_table,
+ pong_xscreensaver_function_table,
+ popsquares_xscreensaver_function_table,
+ projectiveplane_xscreensaver_function_table,
+ providence_xscreensaver_function_table,
+ pulsar_xscreensaver_function_table,
+ pyro_xscreensaver_function_table,
+ qix_xscreensaver_function_table,
+ quasicrystal_xscreensaver_function_table,
+ queens_xscreensaver_function_table,
+ raverhoop_xscreensaver_function_table,
+ rdbomb_xscreensaver_function_table,
+ ripples_xscreensaver_function_table,
+ rocks_xscreensaver_function_table,
+ romanboy_xscreensaver_function_table,
+ rorschach_xscreensaver_function_table,
+ rotzoomer_xscreensaver_function_table,
+ rubik_xscreensaver_function_table,
+ rubikblocks_xscreensaver_function_table,
+ sballs_xscreensaver_function_table,
+ shadebobs_xscreensaver_function_table,
+ sierpinski_xscreensaver_function_table,
+ sierpinski3d_xscreensaver_function_table,
+ skytentacles_xscreensaver_function_table,
+ slidescreen_xscreensaver_function_table,
+ slip_xscreensaver_function_table,
+ sonar_xscreensaver_function_table,
+ speedmine_xscreensaver_function_table,
+ spheremonics_xscreensaver_function_table,
+ splitflap_xscreensaver_function_table,
+ spotlight_xscreensaver_function_table,
+ sproingies_xscreensaver_function_table,
+ squiral_xscreensaver_function_table,
+ stairs_xscreensaver_function_table,
+ starfish_xscreensaver_function_table,
+ starwars_xscreensaver_function_table,
+ stonerview_xscreensaver_function_table,
+ strange_xscreensaver_function_table,
+ substrate_xscreensaver_function_table,
+ superquadrics_xscreensaver_function_table,
+ surfaces_xscreensaver_function_table,
+ swirl_xscreensaver_function_table,
+ tangram_xscreensaver_function_table,
+ tessellimage_xscreensaver_function_table,
+ thornbird_xscreensaver_function_table,
+ timetunnel_xscreensaver_function_table,
+ topblock_xscreensaver_function_table,
+ triangle_xscreensaver_function_table,
+ tronbit_xscreensaver_function_table,
+ truchet_xscreensaver_function_table,
+ twang_xscreensaver_function_table,
+ unicrud_xscreensaver_function_table,
+ unknownpleasures_xscreensaver_function_table,
+ vermiculate_xscreensaver_function_table,
+ voronoi_xscreensaver_function_table,
+ wander_xscreensaver_function_table,
+ whirlwindwarp_xscreensaver_function_table,
+ winduprobot_xscreensaver_function_table,
+ wormhole_xscreensaver_function_table,
+ xanalogtv_xscreensaver_function_table,
+ xflame_xscreensaver_function_table,
+ xjack_xscreensaver_function_table,
+ xlyap_xscreensaver_function_table,
+ xmatrix_xscreensaver_function_table,
+ xrayswarm_xscreensaver_function_table,
+ xspirograph_xscreensaver_function_table,
+ zoom_xscreensaver_function_table,
+ testx11_xscreensaver_function_table;
 
 NSDictionary *make_function_table_dict(void)
 {
@@ -225,6 +231,8 @@ NSDictionary *make_function_table_dict(void)
        [NSValue valueWithPointer:&apple2_xscreensaver_function_table], @"apple2",
 #elif defined(PHOSPHOR_ONLY)
        [NSValue valueWithPointer:&phosphor_xscreensaver_function_table], @"phosphor",
+#elif defined(TESTX11_ONLY)
+       [NSValue valueWithPointer:&testx11_xscreensaver_function_table], @"testx11",
 #else
        [NSValue valueWithPointer:&abstractile_xscreensaver_function_table], @"abstractile",
        [NSValue valueWithPointer:&anemone_xscreensaver_function_table], @"anemone",
@@ -279,7 +287,9 @@ NSDictionary *make_function_table_dict(void)
        [NSValue valueWithPointer:&distort_xscreensaver_function_table], @"distort",
        [NSValue valueWithPointer:&dnalogo_xscreensaver_function_table], @"dnalogo",
        [NSValue valueWithPointer:&drift_xscreensaver_function_table], @"drift",
+       [NSValue valueWithPointer:&dymaxionmap_xscreensaver_function_table], @"dymaxionmap",
        [NSValue valueWithPointer:&endgame_xscreensaver_function_table], @"endgame",
+       [NSValue valueWithPointer:&energystream_xscreensaver_function_table], @"energystream",
        [NSValue valueWithPointer:&engine_xscreensaver_function_table], @"engine",
        [NSValue valueWithPointer:&epicycle_xscreensaver_function_table], @"epicycle",
        [NSValue valueWithPointer:&eruption_xscreensaver_function_table], @"eruption",
@@ -321,6 +331,7 @@ NSDictionary *make_function_table_dict(void)
        [NSValue valueWithPointer:&hexadrop_xscreensaver_function_table], @"hexadrop",
        [NSValue valueWithPointer:&hilbert_xscreensaver_function_table], @"hilbert",
        [NSValue valueWithPointer:&hopalong_xscreensaver_function_table], @"hopalong",
+       [NSValue valueWithPointer:&hydrostat_xscreensaver_function_table], @"hydrostat",
        [NSValue valueWithPointer:&hypertorus_xscreensaver_function_table], @"hypertorus",
        [NSValue valueWithPointer:&hypnowheel_xscreensaver_function_table], @"hypnowheel",
        [NSValue valueWithPointer:&ifs_xscreensaver_function_table], @"ifs",
@@ -378,6 +389,7 @@ NSDictionary *make_function_table_dict(void)
        [NSValue valueWithPointer:&qix_xscreensaver_function_table], @"qix",
        [NSValue valueWithPointer:&quasicrystal_xscreensaver_function_table], @"quasicrystal",
        [NSValue valueWithPointer:&queens_xscreensaver_function_table], @"queens",
+       [NSValue valueWithPointer:&raverhoop_xscreensaver_function_table], @"raverhoop",
        [NSValue valueWithPointer:&rdbomb_xscreensaver_function_table], @"rdbomb",
        [NSValue valueWithPointer:&ripples_xscreensaver_function_table], @"ripples",
        [NSValue valueWithPointer:&rocks_xscreensaver_function_table], @"rocks",
@@ -418,6 +430,7 @@ NSDictionary *make_function_table_dict(void)
        [NSValue valueWithPointer:&tronbit_xscreensaver_function_table], @"tronbit",
        [NSValue valueWithPointer:&truchet_xscreensaver_function_table], @"truchet",
        [NSValue valueWithPointer:&twang_xscreensaver_function_table], @"twang",
+       [NSValue valueWithPointer:&unicrud_xscreensaver_function_table], @"unicrud",
        [NSValue valueWithPointer:&unknownpleasures_xscreensaver_function_table], @"unknownpleasures",
        [NSValue valueWithPointer:&vermiculate_xscreensaver_function_table], @"vermiculate",
        [NSValue valueWithPointer:&voronoi_xscreensaver_function_table], @"voronoi",
diff --git a/OSX/iostextclient.m b/OSX/iostextclient.m
deleted file mode 100644 (file)
index ea9f3b3..0000000
+++ /dev/null
@@ -1,856 +0,0 @@
-/* xscreensaver, Copyright (c) 2012-2015 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.
- *
- * Loading URLs and returning the underlying text.
- *
- * This is necessary because iOS doesn't have Perl installed, so we can't
- * run "xscreensaver-text" to do this.
- */
-
-#include "utils.h"
-
-#ifdef USE_IPHONE /* whole file -- see utils/textclient.c */
-
-#include "textclient.h"
-#include "resources.h"
-#include "utf8wc.h"
-
-#include <stdio.h>
-
-#undef countof
-#define countof(x) (sizeof((x))/sizeof((*x)))
-
-
-extern const char *progname;
-
-struct text_data {
-
-  enum { DATE, LITERAL, URL } mode;
-  char *literal, *url;
-
-  int columns;
-  int max_lines;
-  char *buf;
-  int buf_size;
-  char *fp;
-
-};
-
-
-text_data *
-textclient_open (Display *dpy)
-{
-  text_data *d = (text_data *) calloc (1, sizeof (*d));
-
-# ifdef DEBUG
-  fprintf (stderr, "%s: textclient: init\n", progname);
-# endif
-
-  char *s = get_string_resource (dpy, "textMode", "TextMode");
-  if (!s || !*s || !strcasecmp (s, "date") || !strcmp (s, "0"))
-    d->mode = DATE;
-  else if (!strcasecmp (s, "literal") || !strcmp (s, "1"))
-    d->mode = LITERAL;
-  else if (!strcasecmp (s, "url") || !strcmp (s, "3"))
-    d->mode = URL;
-  else
-    d->mode = DATE;
-
-  d->literal = get_string_resource (dpy, "textLiteral", "TextLiteral");
-  d->url = get_string_resource (dpy, "textURL", "TextURL");
-
-  return d;
-}
-
-
-void
-textclient_close (text_data *d)
-{
-# ifdef DEBUG
-  fprintf (stderr, "%s: textclient: free\n", progname);
-# endif
-
-  if (d->buf) free (d->buf);
-  if (d->literal) free (d->literal);
-  if (d->url) free (d->url);
-  free (d);
-}
-
-
-static char *
-date_string (void)
-{
-  UIDevice *dd = [UIDevice currentDevice];
-  NSString *name = [dd name];                  // My iPhone
-  NSString *model = [dd model];                        // iPad
-  // NSString *system = [dd systemName];       // iPhone OS
-  NSString *vers = [dd systemVersion];         // 5.0
-  NSString *date =
-    [NSDateFormatter
-      localizedStringFromDate:[NSDate date]
-      dateStyle: NSDateFormatterMediumStyle
-      timeStyle: NSDateFormatterMediumStyle];
-  NSString *nl = @"\n";
-
-  NSString *result = name;
-  result = [result stringByAppendingString: nl];
-  result = [result stringByAppendingString: model];
-  // result = [result stringByAppendingString: nl];
-  // result = [result stringByAppendingString: system];
-  result = [result stringByAppendingString: @" "];
-  result = [result stringByAppendingString: vers];
-  result = [result stringByAppendingString: nl];
-  result = [result stringByAppendingString: nl];
-  result = [result stringByAppendingString: date];
-  result = [result stringByAppendingString: nl];
-  result = [result stringByAppendingString: nl];
-  return strdup ([result cStringUsingEncoding:NSISOLatin1StringEncoding]);
-}
-
-
-/* Returns a copy of the string with some basic HTML entities decoded.
- */
-static char *
-decode_entities (const char *html)
-{
-  char *ret = (char *) malloc ((strlen(html) * 4) + 1);  // room for UTF8
-  const char *in = html;
-  char *out = ret;
-  *out = 0;
-
-  const struct { const char *c; const char *e; } entities[] = {
-
-    { "amp", "&" },
-    { "lt",  "<" },
-    { "gt",  ">" },
-
-    // Convert Latin1 to UTF8
-    { "nbsp", " " },                   //   160
-    { "iexcl", "\302\241" },           // ¡ 161
-    { "cent", "\302\242" },            // ¢ 162
-    { "pound", "\302\243" },           // £ 163
-    { "curren", "\302\244" },          // ¤ 164
-    { "yen", "\302\245" },             // ¥ 165
-    { "brvbar", "\302\246" },          // ¦ 166
-    { "sect", "\302\247" },            // § 167
-    { "uml", "\302\250" },             // ¨ 168
-    { "copy", "\302\251" },            // © 169
-    { "ordf", "\302\252" },            // ª 170
-    { "laquo", "\302\253" },           // « 171
-    { "not", "\302\254" },             // ¬ 172
-    { "shy", "\302\255" },             // ­ 173
-    { "reg", "\302\256" },             // ® 174
-    { "macr", "\302\257" },            // ¯ 175
-    { "deg", "\302\260" },             // ° 176
-    { "plusmn", "\302\261" },          // ± 177
-    { "sup2", "\302\262" },            // ² 178
-    { "sup3", "\302\263" },            // ³ 179
-    { "acute", "\302\264" },           // ´ 180
-    { "micro", "\302\265" },           // µ 181
-    { "para", "\302\266" },            // ¶ 182
-    { "middot", "\302\267" },          // · 183
-    { "cedil", "\302\270" },           // ¸ 184
-    { "sup1", "\302\271" },            // ¹ 185
-    { "ordm", "\302\272" },            // º 186
-    { "raquo", "\302\273" },           // » 187
-    { "frac14", "\302\274" },          // ¼ 188
-    { "frac12", "\302\275" },          // ½ 189
-    { "frac34", "\302\276" },          // ¾ 190
-    { "iquest", "\302\277" },          // ¿ 191
-    { "Agrave", "\303\200" },          // À 192
-    { "Aacute", "\303\201" },          // Á 193
-    { "Acirc", "\303\202" },           // Â 194
-    { "Atilde", "\303\203" },          // Ã 195
-    { "Auml", "\303\204" },            // Ä 196
-    { "Aring", "\303\205" },           // Å 197
-    { "AElig", "\303\206" },           // Æ 198
-    { "Ccedil", "\303\207" },          // Ç 199
-    { "Egrave", "\303\210" },          // È 200
-    { "Eacute", "\303\211" },          // É 201
-    { "Ecirc", "\303\212" },           // Ê 202
-    { "Euml", "\303\213" },            // Ë 203
-    { "Igrave", "\303\214" },          // Ì 204
-    { "Iacute", "\303\215" },          // Í 205
-    { "Icirc", "\303\216" },           // Î 206
-    { "Iuml", "\303\217" },            // Ï 207
-    { "ETH", "\303\220" },             // Ð 208
-    { "Ntilde", "\303\221" },          // Ñ 209
-    { "Ograve", "\303\222" },          // Ò 210
-    { "Oacute", "\303\223" },          // Ó 211
-    { "Ocirc", "\303\224" },           // Ô 212
-    { "Otilde", "\303\225" },          // Õ 213
-    { "Ouml", "\303\226" },            // Ö 214
-    { "times", "\303\227" },           // × 215
-    { "Oslash", "\303\230" },          // Ø 216
-    { "Ugrave", "\303\231" },          // Ù 217
-    { "Uacute", "\303\232" },          // Ú 218
-    { "Ucirc", "\303\233" },           // Û 219
-    { "Uuml", "\303\234" },            // Ü 220
-    { "Yacute", "\303\235" },          // Ý 221
-    { "THORN", "\303\236" },           // Þ 222
-    { "szlig", "\303\237" },           // ß 223
-    { "agrave", "\303\240" },          // à 224
-    { "aacute", "\303\241" },          // á 225
-    { "acirc", "\303\242" },           // â 226
-    { "atilde", "\303\243" },          // ã 227
-    { "auml", "\303\244" },            // ä 228
-    { "aring", "\303\245" },           // å 229
-    { "aelig", "\303\246" },           // æ 230
-    { "ccedil", "\303\247" },          // ç 231
-    { "egrave", "\303\250" },          // è 232
-    { "eacute", "\303\251" },          // é 233
-    { "ecirc", "\303\252" },           // ê 234
-    { "euml", "\303\253" },            // ë 235
-    { "igrave", "\303\254" },          // ì 236
-    { "iacute", "\303\255" },          // í 237
-    { "icirc", "\303\256" },           // î 238
-    { "iuml", "\303\257" },            // ï 239
-    { "eth", "\303\260" },             // ð 240
-    { "ntilde", "\303\261" },          // ñ 241
-    { "ograve", "\303\262" },          // ò 242
-    { "oacute", "\303\263" },          // ó 243
-    { "ocirc", "\303\264" },           // ô 244
-    { "otilde", "\303\265" },          // õ 245
-    { "ouml", "\303\266" },            // ö 246
-    { "divide", "\303\267" },          // ÷ 247
-    { "oslash", "\303\270" },          // ø 248
-    { "ugrave", "\303\271" },          // ù 249
-    { "uacute", "\303\272" },          // ú 250
-    { "ucirc", "\303\273" },           // û 251
-    { "uuml", "\303\274" },            // ü 252
-    { "yacute", "\303\275" },          // ý 253
-    { "thorn", "\303\276" },           // þ 254
-    { "yuml", "\303\277" },            // ÿ 255
-
-      // And some random others
-    { "bdquo", "\342\200\236" },       // „
-    { "bull", "\342\200\242" },                // •
-    { "circ", "\313\206" },            // ˆ
-    { "cong", "\342\211\205" },                // ≅
-    { "empty", "\342\210\205" },       // ∅
-    { "emsp", "\342\200\203" },                //  
-    { "ensp", "\342\200\202" },                //  
-    { "equiv", "\342\211\241" },       // ≡
-    { "frasl", "\342\201\204" },       // ⁄
-    { "ge", "\342\211\245" },          // ≥
-    { "hArr", "\342\207\224" },                // ⇔
-    { "harr", "\342\206\224" },                // ↔
-    { "hellip", "\342\200\246" },      // …
-    { "lArr", "\342\207\220" },                // ⇐
-    { "lang", "\342\237\250" },                // ⟨
-    { "larr", "\342\206\220" },                // ←
-    { "ldquo", "\342\200\234" },       // “
-    { "le", "\342\211\244" },          // ≤
-    { "lowast", "\342\210\227" },      // ∗
-    { "loz", "\342\227\212" },         // ◊
-    { "lsaquo", "\342\200\271" },      // ‹
-    { "lsquo", "\342\200\230" },       // ‘
-    { "mdash", "\342\200\224" },       // —
-    { "minus", "\342\210\222" },       // −
-    { "ndash", "\342\200\223" },       // –
-    { "ne", "\342\211\240" },          // ≠
-    { "OElig", "\305\222" },           // Œ
-    { "oelig", "\305\223" },           // œ
-    { "prime", "\342\200\262" },       // ′
-    { "quot", "\342\200\235" },                // ”
-    { "rArr", "\342\207\222" },                // ⇒
-    { "rang", "\342\237\251" },                // ⟩
-    { "rarr", "\342\206\222" },                // →
-    { "rdquo", "\342\200\235" },       // ”
-    { "rsaquo", "\342\200\272" },      // ›
-    { "rsquo", "\342\200\231" },       // ’
-    { "sbquo", "\342\200\232" },       // ‚
-    { "sim", "\342\210\274" },         // ∼
-    { "thinsp", "\342\200\211" },      //  
-    { "tilde", "\313\234" },           // ˜
-    { "trade", "\342\204\242" },       // ™
-  };
-
-  while (*in) {
-    if (*in == '&') {
-      int done = 0;
-      if (in[1] == '#' && in[2] == 'x') {                      // &#x41;
-        unsigned long i = 0;
-        in += 2;
-        while ((*in >= '0' && *in <= '9') ||
-               (*in >= 'A' && *in <= 'F') ||
-               (*in >= 'a' && *in <= 'f')) {
-          i = (i * 16) + (*in >= 'a' ? *in - 'a' + 16 :
-                          *in >= 'A' ? *in - 'A' + 16 :
-                          *in - '0');
-          in++;
-        }
-        *out += utf8_encode (i, out, strlen(out));
-        done = 1;
-      } else if (in[1] == '#') {                               // &#65;
-        unsigned long i = 0;
-        in++;
-        while (*in >= '0' && *in <= '9') {
-          i = (i * 10) + (*in - '0');
-          in++;
-        }
-        *out += utf8_encode (i, out, strlen(out));
-        done = 1;
-      } else {
-        int i;
-        for (i = 0; !done && i < countof(entities); i++) {
-          if (!strncmp (in+1, entities[i].c, strlen(entities[i].c))) {
-            strcpy (out, entities[i].e);
-            in  += strlen(entities[i].c) + 1;
-            out += strlen(entities[i].e);
-            done = 1;
-          }
-        }
-      }
-
-      if (done) {
-        if (*in == ';')
-          in++;
-      } else {
-        *out++ = *in++;
-      }
-    } else {
-      *out++ = *in++;
-    }
-  }
-  *out = 0;
-
-  /* Shrink */
-  ret = realloc (ret, out - ret + 1);
-
-  return ret;
-}
-
-
-/* Returns a copy of the HTML string that has been converted to plain text,
-   in UTF8 encoding.  HTML tags are stripped, <BR> and <P> are converted
-   to newlines, and some basic HTML entities are decoded.
- */
-static char *
-strip_html (const char *html)
-{
-  int tag = 0;
-  int comment = 0;
-  int white = 0;
-  int nl = 0;
-  char *ret = (char *) malloc ((strlen(html) * 4) + 1);  // room for UTF8
-  char *out = ret;
-  *out = 0;
-
-  for (const char *in = html; *in; in++) {
-    if (comment) {
-      if (!strncmp (in, "-->", 3)) {
-        comment = 0;
-      }
-    } else if (tag) {
-      if (*in == '>') {
-        tag = 0;
-      }
-    } else if (*in == '<') {
-      tag = 1;
-      if (!strncmp (in, "<!--", 4)) {
-        comment = 1;
-        tag = 0;
-      } else if (!strncasecmp (in, "<BR", 3)) {
-        *out++ = '\n';
-        white = 1;
-        nl++;
-      } else if (!strncasecmp (in, "<P", 2)) {
-        if (nl < 2) { *out++ = '\n'; nl++; }
-        if (nl < 2) { *out++ = '\n'; nl++; }
-        white = 1;
-      }
-    } else if (*in == ' ' || *in == '\t' || *in == '\r' || *in == '\n') {
-      if (!white && out != html)
-        *out++ = ' ';
-      white = 1;
-    } else {
-      *out++ = *in;
-      white = 0;
-      nl = 0;
-    }
-  }
-  *out = 0;
-
-  {
-    char *ret2 = decode_entities (ret);
-    free (ret);
-    ret = ret2;
-  }
-
-  return ret;
-}
-
-
-static char *
-copy_rss_field (const char *s)
-{
-  if (!s) return 0;
-  while (*s && *s != '>')                      // Skip forward to >
-    s++;
-  if (! *s) return 0;
-  s++;
-
-  if (!strncmp (s, "<![CDATA[", 9)) {          // CDATA quoting
-    s += 9;
-    char *e = strstr (s, "]]");
-    if (e) *e = 0;
-    unsigned long L = strlen (s);
-    char *s2 = (char *) malloc (L+1);
-    memcpy (s2, s, L+1);
-    return s2;
-
-  } else {                                     // Entity-encoded.
-    const char *s2;
-    for (s2 = s; *s2 && *s2 != '<'; s2++)      // Terminate at <
-      ;
-    char *s3 = (char *) malloc (s2 - s + 1);
-    if (! s3) return 0;
-    memcpy (s3, s, s2-s);
-    s3[s2-s] = 0;
-    char *s4 = strip_html (s3);
-    free (s3);
-    return s4;
-  }
-}
-
-
-static char *
-pick_rss_field (const char *a, const char *b, const char *c, const char *d)
-{
-  // Pick the longest of the fields.
-  char *a2 = copy_rss_field (a);
-  char *b2 = copy_rss_field (b);
-  char *c2 = copy_rss_field (c);
-  char *d2 = copy_rss_field (d);
-  unsigned long al = a2 ? strlen(a2) : 0;
-  unsigned long bl = b2 ? strlen(b2) : 0;
-  unsigned long cl = c2 ? strlen(c2) : 0;
-  unsigned long dl = d2 ? strlen(d2) : 0;
-  char *ret = 0;
-
-  if      (al > bl && al > cl && al > dl) ret = a2;
-  else if (bl > al && bl > cl && bl > dl) ret = b2;
-  else if (cl > al && cl > bl && cl > dl) ret = c2;
-  else ret = d2;
-  if (a2 && a2 != ret) free (a2);
-  if (b2 && b2 != ret) free (b2);
-  if (c2 && c2 != ret) free (c2);
-  if (d2 && d2 != ret) free (d2);
-  return ret;
-}
-
-
-/* Strip some Wikipedia formatting from the string to make it more readable.
- */
-static void
-strip_wiki (char *text)
-{
-  char *in = text;
-  char *out = text;
-  while (*in) 
-    {
-      if (!strncmp (in, "<!--", 4))            /* <!-- ... --> */
-        {
-          char *e = strstr (in+4, "-->");
-          if (e) in = e + 3;
-        }
-      else if (!strncmp (in, "/*", 2))         /* ... */
-        {
-          char *e = strstr (in+2, "*/");
-          if (e) in = e + 2;
-        }
-      else if (!strncmp (in, "{{Infobox", 9))  /* {{Infobox ... \n}}\n */
-        {
-          char *e = strstr (in+2, "\n}}");
-          if (e) in = e + 3;
-          else *out++ = *in++;
-        }
-      else if (!strncmp (in, "{{", 2))         /* {{ ...table... }} */
-        {
-          char *e = strstr (in+2, "}}");
-          if (e) in = e + 2;
-          else *out++ = *in++;
-        }
-      else if (!strncmp (in, "{|", 2))         /* {| ...table... |} */
-        {
-          char *e = strstr (in+2, "|}");
-          if (e) in = e + 2;
-          else *out++ = *in++;
-        }
-      else if (!strncmp (in, "|-", 2))         /* |- ...table cell... | */
-        {
-          char *e = strstr (in+2, "|");
-          if (e) in = e + 1;
-          else *out++ = *in++;
-        }
-      else if (!strncmp (in, "<ref", 4))       /* <ref>...</ref> -> "*" */
-        {
-          char *e1 = strstr (in+4, "/>");
-          char *e2 = strstr (in+4, "</ref>");
-          if (e1 && e1 < e2) in = e1 + 2;
-          else if (e2) in = e2 + 6;
-          else *out++ = *in++;
-
-          *out++ = '*';
-        }
-      else if (!strncmp (in, "<", 1))          /* <...> */
-        {
-          char *e = strstr (in+1, ">");
-          if (e) in = e + 1;
-        }
-      else if (!strncmp (in, "[[", 2))         /* [[ ... ]] */
-        {
-          char *e1 = strstr (in+2, "|");
-          char *e2 = strstr (in+2, "]]");
-          if (e1 && e2 && e1 < e2)             /* [[link|anchor]] */
-            {
-              long L = e2 - e1 - 1;
-              memmove (out, e1+1, L);
-              out += L;
-              in = e2+2;
-            }
-          else if (e2)                         /* [[link]] */
-            {
-              long L = e2 - in - 2;
-              memmove (out, in+2, L);
-              out += L;
-              in = e2+2;
-            }
-          else
-            *out++ = *in++;
-        }
-      else if (!strncmp (in, "[", 1))          /* [ ... ] */
-        {
-          char *e1 = strstr (in+2, " ");
-          char *e2 = strstr (in+2, "]");
-          if (e1 && e2 && e1 < e2)             /* [url anchor] */
-            {
-              long L = e2 - e1 - 1;
-              memmove (out, e1+1, L);
-              out += L;
-              in = e2+2;
-            }
-          else
-            *out++ = *in++;
-        }
-      else if (!strncmp (in, "''''", 4))       /* omit '''' */
-        in += 4;
-      else if (!strncmp (in, "'''", 3))        /* omit ''' */
-        in += 3;
-      else if (!strncmp (in, "''", 2) ||       /* '' or `` or "" -> " */
-               !strncmp (in, "``", 2) ||
-               !strncmp (in, "\"\"", 2))
-        {
-          *out++ = '"';
-          in += 2;
-        }
-      else
-        {
-          *out++ = *in++;
-        }
-    }
-  *out = 0;
-
-  /* Collapse newlines */
-  in = text;
-  out = text;
-  while (*in) 
-    {
-      while (!strncmp(in, "\n\n\n", 3))
-        in++;
-      *out++ = *in++;
-    }
-  *out = 0;
-}
-
-
-/* Returns a copy of the RSS document that has been converted to plain text,
-   in UTF8 encoding.  Rougly, it uses the contents of the <description> field
-   of each <item>, and decodes HTML within it.
- */
-static char *
-strip_rss (const char *rss)
-{
-  char *ret = malloc (strlen(rss) * 4 + 1);  // room for UTF8
-  char *out = ret;
-  const char *a = 0, *b = 0, *c = 0, *d = 0, *t = 0;
-  int head = 1;
-  int done = 0;
-  int wiki_p = !!strcasestr (rss, "<generator>MediaWiki");
-
-  *out = 0;
-  for (const char *in = rss; *in; in++) {
-    if (*in == '<') {
-      if (!strncasecmp (in, "<item", 5) ||     // New item, dump.
-          !strncasecmp (in, "<entry", 6)) {
-      DONE:
-        head = 0;
-        char *title = copy_rss_field (t);
-        char *body  = pick_rss_field (a, b, c, d);
-
-        a = b = c = d = t = 0;
-
-        if (title && body && !strcmp (title, body)) {
-          free (title);
-          title = 0;
-        }
-
-        if (title) {
-          strcpy (out, title);
-          free (title);
-          out += strlen (out);
-          strcpy (out, "\n\n");
-          out += strlen (out);
-        }
-
-        if (body) {
-          strcpy (out, body);
-          free (body);
-          out += strlen (out);
-          strcpy (out, "<P>");
-          out += strlen (out);
-        }
-
-      } else if (head) {   // still before first <item>
-        ;
-      } else if (!strncasecmp (in, "<title", 6)) {
-        t = in+6;
-      } else if (!strncasecmp (in, "<summary", 8)) {
-        d = in+8;
-      } else if (!strncasecmp (in, "<description", 12)) {
-        a = in+12;
-      } else if (!strncasecmp (in, "<content:encoded", 16)) {
-        c = in+16;
-      } else if (!strncasecmp (in, "<content", 8)) {
-        b = in+8;
-      }
-    }
-  }
-
-  if (! done) {                // Finish off the final item.
-    done = 1;
-    goto DONE;
-  }
-
-  ret = strip_html (ret);
-
-  if (wiki_p) {
-    char *ret2;
-    strip_wiki (ret);
-    ret2 = decode_entities (ret);
-    free (ret);
-    ret = ret2;
-  }
-
-  return ret;
-}
-
-
-static void
-wrap_text (char *body, int columns, int max_lines)
-{
-  int col = 0, last_col = 0;
-  char *last_space = 0;
-  int lines = 0;
-  if (! body) return;
-  for (char *p = body; *p; p++) {
-    if (*p == '\r' || *p == '\n' || *p == ' ' || *p == '\t') {
-      if (col > columns && last_space) {
-        *last_space = '\n';
-        col = col - last_col;
-      }
-      last_space = p;
-      last_col = col;
-    }
-    if (*p == '\r' || *p == '\n') {
-      col = 0;
-      last_col = 0;
-      last_space = 0;
-      lines++;
-      if (max_lines && lines >= max_lines)
-        {
-          *p = 0;
-          break;
-        }
-    } else {
-      col++;
-    }
-  }
-}
-
-
-static void
-rewrap_text (char *body, int columns)
-{
-  if (! body) return;
-  for (char *p = body; *p; p++) {
-    if (*p == '\n') {
-      if (p[1] == '\n')
-        p++;
-      else
-        *p = ' ';
-    }
-  }
-  wrap_text (body, columns, 0);
-}
-
-
-
-static void
-strip_backslashes (char *s)
-{
-  char *out = s;
-  for (char *in = s; *in; in++) {
-    if (*in == '\\') {
-      in++;
-      if      (*in == 'n') *out++ = '\n';
-      else if (*in == 'r') *out++ = '\r';
-      else if (*in == 't') *out++ = '\t';
-      else *out++ = *in;
-    } else {
-      *out++ = *in;
-    }
-  }
-  *out = 0;
-}
-
-
-/* Returns the contents of the URL as plain text.
-   HTML and RSS are decoded.
- */
-static char *
-url_string (const char *url)
-{
-  NSURL *nsurl =
-    [NSURL URLWithString:
-             [NSString stringWithCString: url
-                       encoding:NSISOLatin1StringEncoding]];
-  NSString *body =
-    [NSString stringWithContentsOfURL: nsurl
-              encoding: NSUTF8StringEncoding
-              error: nil];
-  if (! body)
-    return 0;
-
-  enum { RSS, HTML, TEXT } type;
-
-  // Only search the first 1/2 K of the document while determining type.
-
-  unsigned long L = [body length];
-  if (L > 512) L = 512;
-  NSString *head = [[[body substringToIndex: L]
-                      stringByTrimmingCharactersInSet:
-                        [NSCharacterSet whitespaceAndNewlineCharacterSet]]
-                     lowercaseString];
-  if ([head hasPrefix:@"<?xml"] ||
-      [head hasPrefix:@"<!doctype rss"])
-    type = RSS;
-  else if ([head hasPrefix:@"<!doctype html"] ||
-           [head hasPrefix:@"<html"] ||
-           [head hasPrefix:@"<head"])
-    type = HTML;
-  else if ([head rangeOfString:@"<base"].length ||
-           [head rangeOfString:@"<body"].length ||
-           [head rangeOfString:@"<script"].length ||
-           [head rangeOfString:@"<style"].length ||
-           [head rangeOfString:@"<a href"].length)
-    type = HTML;
-  else if ([head rangeOfString:@"<channel"].length ||
-           [head rangeOfString:@"<generator"].length ||
-           [head rangeOfString:@"<description"].length ||
-           [head rangeOfString:@"<content"].length ||
-           [head rangeOfString:@"<feed"].length ||
-           [head rangeOfString:@"<entry"].length)
-    type = RSS;
-  else
-    type = TEXT;
-
-  char *body2 = strdup ([body cStringUsingEncoding:NSUTF8StringEncoding]);
-  char *body3 = 0;
-
-  switch (type) {
-  case HTML: body3 = strip_html (body2); break;
-  case RSS:  body3 = strip_rss (body2);  break;
-  case TEXT: break;
-  default: abort(); break;
-  }
-
-  if (body3) {
-    free (body2);
-    return body3;
-  } else {
-    return body2;
-  }
-}
-
-
-int
-textclient_getc (text_data *d)
-{
-  if (!d->fp || !*d->fp) {
-    if (d->buf) {
-      free (d->buf);
-      d->buf = 0;
-      d->fp = 0;
-    }
-    switch (d->mode) {
-    case DATE: DATE:
-      d->buf = date_string();
-      break;
-    case LITERAL:
-      if (!d->literal || !*d->literal)
-        goto DATE;
-      d->buf = (char *) malloc (strlen (d->literal) + 3);
-      strcpy (d->buf, d->literal);
-      strcat (d->buf, "\n");
-      strip_backslashes (d->buf);
-      d->fp = d->buf;
-      break;
-    case URL:
-      if (!d->url || !*d->url)
-        goto DATE;
-      d->buf = url_string (d->url);
-      break;
-    default:
-      abort();
-    }
-    if (d->columns > 10)
-      wrap_text (d->buf, d->columns, d->max_lines);
-    d->fp = d->buf;
-  }
-
-  if (!d->fp || !*d->fp)
-    return -1;
-
-  unsigned char c = (unsigned char) *d->fp++;
-  return (int) c;
-}
-
-
-Bool
-textclient_putc (text_data *d, XKeyEvent *k)
-{
-  return False;
-}
-
-
-void
-textclient_reshape (text_data *d,
-                    int pix_w, int pix_h,
-                    int char_w, int char_h,
-                    int max_lines)
-{
-  d->columns = char_w;
-  d->max_lines = max_lines;
-  rewrap_text (d->buf, d->columns);
-}
-
-#endif /* USE_IPHONE -- whole file */
diff --git a/OSX/jwxyz-timers.h b/OSX/jwxyz-timers.h
deleted file mode 100644 (file)
index e9fa648..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/* xscreensaver, Copyright (c) 2006-2014 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 is the OSX implementation of Xt timers, for libjwxyz.
- */
-
-#ifndef __JWXYZ_TIMERS_H__
-#define __JWXYZ_TIMERS_H__
-
-#include "jwxyz.h"
-
-typedef struct jwxyz_sources_data jwxyz_sources_data;
-
-extern jwxyz_sources_data *jwxyz_sources_init (XtAppContext);
-extern void jwxyz_sources_free (jwxyz_sources_data *);
-extern void jwxyz_sources_run (jwxyz_sources_data *);
-
-#endif /* __JWXYZ_TIMERS_H__ */
diff --git a/OSX/jwxyz-timers.m b/OSX/jwxyz-timers.m
deleted file mode 100644 (file)
index 3956569..0000000
+++ /dev/null
@@ -1,361 +0,0 @@
-/* xscreensaver, Copyright (c) 2006-2014 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 is the OSX implementation of Xt timers, for libjwxyz.
- */
-
-//#define DEBUG_TIMERS
-//#define DEBUG_SOURCES
-
-#import <stdlib.h>
-
-#import "jwxyz.h"
-#import "jwxyz-timers.h"
-
-
-
-#ifdef DEBUG_TIMERS
-# define LOGT( str,arg1)      NSLog(str,arg1)
-# define LOGT2(str,arg1,arg2) NSLog(str,arg1,arg2)
-#else
-# define LOGT( str,arg1)
-# define LOGT2(str,arg1,arg2)
-#endif
-
-#ifdef DEBUG_SOURCES
-# define LOGI( str,arg1,arg2)      NSLog(str,arg1,arg2)
-# define LOGI2(str,arg1,arg2,arg3) NSLog(str,arg1,arg2,arg3)
-#else
-# define LOGI( str,arg1,arg2)
-# define LOGI2(str,arg1,arg2,arg3)
-#endif
-
-#define ASSERT_RET(C,S) do {                    \
-    if (!(C)) {                                 \
-      jwxyz_abort ("jwxyz-timers: %s",(S));     \
-      return;                                   \
- }} while(0)
-
-
-XtAppContext
-XtDisplayToApplicationContext (Display *dpy)
-{
-  return (XtAppContext) dpy;
-}
-
-#define app_to_display(APP) ((Display *) (APP))
-
-
-struct jwxyz_sources_data {
-  int fd_count;
-  XtInputId ids[FD_SETSIZE];
-  struct jwxyz_XtIntervalId *all_timers;
-};
-
-struct jwxyz_XtIntervalId {
-  XtAppContext app;
-  CFRunLoopTimerRef cftimer;
-  int refcount;
-
-  XtTimerCallbackProc cb;
-  XtPointer closure;
-
-  struct jwxyz_XtIntervalId *next;
-};
-
-struct jwxyz_XtInputId {
-  XtAppContext app;
-  int refcount;
-
-  XtInputCallbackProc cb;
-  XtPointer closure;
-  int fd;
-};
-
-
-static const void *
-jwxyz_timer_retain (const void *arg)
-{
-  struct jwxyz_XtIntervalId *data = (struct jwxyz_XtIntervalId *) arg;
-  data->refcount++;
-  LOGT2(@"timer  0x%08X: retain %d", (unsigned int) data, data->refcount);
-  return arg;
-}
-
-/* This is called both by the user to manually kill a timer (XtRemoveTimeOut)
-   and by the run loop after a timer has fired (CFRunLoopTimerInvalidate).
- */
-static void
-jwxyz_timer_release (const void *arg)
-{
-  struct jwxyz_XtIntervalId *data = (struct jwxyz_XtIntervalId *) arg;
-  jwxyz_sources_data *td = display_sources_data (app_to_display (data->app));
-
-  data->refcount--;
-  LOGT2(@"timer  0x%08X: release %d", (unsigned int) data, data->refcount);
-  ASSERT_RET (data->refcount >= 0, "double free");
-
-  if (data->refcount == 0) {
-
-    // Remove it from the list of live timers.
-    XtIntervalId prev, timer;
-    int hit = 0;
-    for (timer = td->all_timers, prev = 0;
-         timer;
-         prev = timer, timer = timer->next) {
-      if (timer == data) {
-        ASSERT_RET (!hit, "circular timer list");
-        if (prev)
-          prev->next = timer->next;
-        else
-          td->all_timers = timer->next;
-        timer->next = 0;
-        hit = 1;
-      } else {
-        ASSERT_RET (timer->refcount > 0, "timer list corrupted");
-      }
-    }
-
-    free (data);
-  }
-}
-
-static const void *
-jwxyz_source_retain (const void *arg)
-{
-  struct jwxyz_XtInputId *data = (struct jwxyz_XtInputId *) arg;
-  data->refcount++;
-  LOGI2(@"source 0x%08X %2d: retain %d", (unsigned int) data, data->fd, 
-        data->refcount);
-  return arg;
-}
-
-static void
-jwxyz_source_release (const void *arg)
-{
-  struct jwxyz_XtInputId *data = (struct jwxyz_XtInputId *) arg;
-  data->refcount--;
-  LOGI2(@"source 0x%08X %2d: release %d", (unsigned int) data, data->fd,
-        data->refcount);
-  ASSERT_RET (data->refcount >= 0, "double free");
-  if (data->refcount == 0) {
-    memset (data, 0xA1, sizeof(*data));
-    data->fd = -666;
-    free (data);
-  }
-}
-
-
-static void
-jwxyz_timer_cb (CFRunLoopTimerRef timer, void *arg)
-{
-  struct jwxyz_XtIntervalId *data = (struct jwxyz_XtIntervalId *) arg;
-  LOGT(@"timer  0x%08X: fire", (unsigned int) data);
-  data->cb (data->closure, &data);
-
-  // Our caller (__CFRunLoopDoTimer) will now call CFRunLoopTimerInvalidate,
-  // which will call jwxyz_timer_release.
-}
-
-
-XtIntervalId
-XtAppAddTimeOut (XtAppContext app, unsigned long msecs,
-                 XtTimerCallbackProc cb, XtPointer closure)
-{
-  jwxyz_sources_data *td = display_sources_data (app_to_display (app));
-  struct jwxyz_XtIntervalId *data = (struct jwxyz_XtIntervalId *)
-    calloc (1, sizeof(*data));
-  data->app = app;
-  data->cb = cb;
-  data->closure = closure;
-
-  LOGT2(@"timer  0x%08X: alloc %lu", (unsigned int) data, msecs);
-  
-  CFRunLoopTimerContext ctx = { 0, };
-  ctx.info    = data;
-  ctx.retain  = jwxyz_timer_retain;
-  ctx.release = jwxyz_timer_release;
-
-  CFAbsoluteTime time = CFAbsoluteTimeGetCurrent() + (msecs / 1000.0);
-
-  data->cftimer =
-    CFRunLoopTimerCreate (NULL, // allocator
-                          time, 0, 0, 0, // interval, flags, order
-                          jwxyz_timer_cb, &ctx);
-  // CFRunLoopTimerCreate called jwxyz_timer_retain.
-
-  data->next = td->all_timers;
-  td->all_timers = data;
-
-  CFRunLoopAddTimer (CFRunLoopGetCurrent(), data->cftimer,
-                     kCFRunLoopCommonModes);
-  return data;
-}
-
-
-void
-XtRemoveTimeOut (XtIntervalId id)
-{
-  LOGT(@"timer  0x%08X: remove", (unsigned int) id);
-  ASSERT_RET (id->refcount > 0, "already freed");
-  ASSERT_RET (id->cftimer, "timers corrupted");
-
-  CFRunLoopRemoveTimer (CFRunLoopGetCurrent(), id->cftimer,
-                        kCFRunLoopCommonModes);
-  CFRunLoopTimerInvalidate (id->cftimer);
-  // CFRunLoopTimerInvalidate called jwxyz_timer_release.
-}
-
-
-jwxyz_sources_data *
-jwxyz_sources_init (XtAppContext app)
-{
-  jwxyz_sources_data *td = (jwxyz_sources_data *) calloc (1, sizeof (*td));
-  return td;
-}
-
-static void
-jwxyz_source_select (XtInputId id)
-{
-  jwxyz_sources_data *td = display_sources_data (app_to_display (id->app));
-  ASSERT_RET (id->fd > 0 && id->fd < FD_SETSIZE, "fd out of range");
-  ASSERT_RET (td->ids[id->fd] == 0, "sources corrupted");
-  td->ids[id->fd] = id;
-  td->fd_count++;
-}
-
-static void
-jwxyz_source_deselect (XtInputId id)
-{
-  jwxyz_sources_data *td = display_sources_data (app_to_display (id->app));
-  ASSERT_RET (td->fd_count > 0, "sources corrupted");
-  ASSERT_RET (id->fd > 0 && id->fd < FD_SETSIZE, "fd out of range");
-  ASSERT_RET (td->ids[id->fd] == id, "sources corrupted");
-  td->ids[id->fd] = 0;
-  td->fd_count--;
-}
-
-void
-jwxyz_sources_run (jwxyz_sources_data *td)
-{
-  if (td->fd_count == 0) return;
-
-  struct timeval tv = { 0, };
-  fd_set fds;
-  int i;
-  int max = 0;
-
-  FD_ZERO (&fds);
-  for (i = 0; i < FD_SETSIZE; i++) {
-    if (td->ids[i]) {
-      FD_SET (i, &fds);
-      max = i;
-    }
-  }
-
-  ASSERT_RET (max > 0, "no fds");
-
-  if (0 < select (max+1, &fds, NULL, NULL, &tv)) {
-    for (i = 0; i < FD_SETSIZE; i++) {
-      if (FD_ISSET (i, &fds)) {
-        XtInputId id = td->ids[i];
-        ASSERT_RET (id && id->cb, "sources corrupted");
-        ASSERT_RET (id->fd == i, "sources corrupted");
-        id->cb (id->closure, &id->fd, &id);
-      }
-    }
-  }
-}
-
-
-XtInputId
-XtAppAddInput (XtAppContext app, int fd, XtPointer flags,
-               XtInputCallbackProc cb, XtPointer closure)
-{
-  struct jwxyz_XtInputId *data = (struct jwxyz_XtInputId *)
-    calloc (1, sizeof(*data));
-  data->cb = cb;
-  data->fd = fd;
-  data->closure = closure;
-
-  LOGI(@"source 0x%08X %2d: alloc", (unsigned int) data, data->fd);
-
-  data->app = app;
-  jwxyz_source_retain (data);
-  jwxyz_source_select (data);
-
-  return data;
-}
-
-void
-XtRemoveInput (XtInputId id)
-{
-  LOGI(@"source 0x%08X %2d: remove", (unsigned int) id, id->fd);
-  ASSERT_RET (id->refcount > 0, "sources corrupted");
-
-  jwxyz_source_deselect (id);
-  jwxyz_source_release (id);
-}
-
-static void
-jwxyz_XtRemoveInput_all (jwxyz_sources_data *td)
-{
-  int i;
-  for (i = 0; i < FD_SETSIZE; i++) {
-    XtInputId id = td->ids[i];
-    if (id) XtRemoveInput (id);
-  }
-}
-
-
-static void
-jwxyz_XtRemoveTimeOut_all (jwxyz_sources_data *td)
-{
-  struct jwxyz_XtIntervalId *timer, *next;
-  int count = 0;
-
-  // Iterate the timer list, being careful that XtRemoveTimeOut removes
-  // things from that list.
-  if (td->all_timers) {
-    for (timer = td->all_timers, next = timer->next;
-         timer;
-         timer = next, next = (timer ? timer->next : 0)) {
-      XtRemoveTimeOut (timer);
-      count++;
-      ASSERT_RET (count < 10000, "way too many timers to free");
-    }
-    ASSERT_RET (!td->all_timers, "timer list didn't empty");
-  }
-}
-
-
-void
-jwxyz_sources_free (jwxyz_sources_data *td)
-{
-  jwxyz_XtRemoveInput_all (td);
-  jwxyz_XtRemoveTimeOut_all (td);
-  memset (td, 0xA1, sizeof(*td));
-  free (td);
-}
-
-
-XtInputMask
-XtAppPending (XtAppContext app)
-{
-  return XtIMAlternateInput;  /* just always say yes */
-}
-
-void
-XtAppProcessEvent (XtAppContext app, XtInputMask mask)
-{
-  jwxyz_sources_data *td = display_sources_data (app_to_display (app));
-  jwxyz_sources_run (td);
-}
diff --git a/OSX/jwxyz.h b/OSX/jwxyz.h
deleted file mode 100644 (file)
index 69b716b..0000000
+++ /dev/null
@@ -1,799 +0,0 @@
-/* xscreensaver, Copyright (c) 1991-2015 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.
- */
-
-/* JWXYZ Is Not Xlib.
-
-   But it's a bunch of function definitions that bear some resemblance to
-   Xlib and that do Cocoa-ish things that bear some resemblance to the
-   things that Xlib might have done.
- */
-
-#ifndef __JWXYZ_H__
-#define __JWXYZ_H__
-
-extern void jwxyz_abort(const char *fmt, ...) __dead2;
-#define abort() jwxyz_abort("abort in %s:%d", __FUNCTION__, __LINE__)
-
-typedef int Bool;
-typedef int Status;
-typedef void * XPointer;
-typedef unsigned long Time;
-typedef unsigned int KeySym;
-typedef unsigned int KeyCode;
-typedef unsigned int VisualID;
-typedef unsigned long Atom; /* Must be as large as a char *. */
-
-typedef struct jwxyz_Display           Display;
-typedef struct jwxyz_Screen            Screen;
-typedef struct jwxyz_Visual            Visual;
-typedef struct jwxyz_Drawable *                Drawable;
-typedef struct jwxyz_Colormap *                Colormap;
-typedef struct jwxyz_GC        *               GC;
-typedef struct jwxyz_XColor            XColor;
-typedef struct jwxyz_XGCValues         XGCValues;
-typedef struct jwxyz_XPoint            XPoint;
-typedef struct jwxyz_XSegment          XSegment;
-typedef struct jwxyz_XRectangle                XRectangle;
-typedef struct jwxyz_XArc              XArc;
-typedef struct jwxyz_XWindowAttributes XWindowAttributes;
-typedef struct jwxyz_XrmOptionDescRec  XrmOptionDescRec;
-typedef struct jwxyz_XrmDatabase *      XrmDatabase;
-typedef struct jwxyz_XImage            XImage;
-typedef struct jwxyz_XFontProp          XFontProp;
-typedef struct jwxyz_XFontStruct       XFontStruct;
-typedef struct jwxyz_Font *            Font;
-typedef struct jwxyz_XFontSet *                XFontSet;
-typedef struct jwxyz_XCharStruct       XCharStruct;
-typedef struct jwxyz_XComposeStatus    XComposeStatus;
-typedef struct jwxyz_XPixmapFormatValues XPixmapFormatValues;
-typedef struct jwxyz_XChar2b            XChar2b;
-
-typedef union  jwxyz_XEvent            XEvent;
-typedef struct jwxyz_XAnyEvent         XAnyEvent;
-typedef struct jwxyz_XKeyEvent         XKeyEvent;
-typedef struct jwxyz_XMotionEvent      XMotionEvent;
-typedef struct jwxyz_XButtonEvent      XButtonEvent;
-typedef XKeyEvent                      XKeyPressedEvent;
-typedef XKeyEvent                      XKeyReleasedEvent;
-typedef XMotionEvent                   XPointerMovedEvent;
-typedef XButtonEvent                   XButtonPressedEvent;
-typedef XButtonEvent                   XButtonReleasedEvent;
-
-
-/* Not technically Xlib... */
-typedef struct jwxyz_GLXContext *      GLXContext;
-typedef struct jwxyz_XtAppContext *    XtAppContext;
-typedef struct jwxyz_XtIntervalId *    XtIntervalId;
-typedef struct jwxyz_XtInputId *       XtInputId;
-typedef void *                         XtPointer;
-typedef unsigned long                  XtInputMask;
-#define XtInputReadMask                        (1L<<0)
-#define XtInputWriteMask               (1L<<1)
-#define XtInputExceptMask              (1L<<2)
-#define XtIMXEvent                     1
-#define XtIMTimer                      2
-#define XtIMAlternateInput             4
-#define XtIMSignal                     8
-#define XtIMAll (XtIMXEvent | XtIMTimer | XtIMAlternateInput | XtIMSignal)
-
-#define True 1
-#define TRUE 1
-#define False 0
-#define FALSE 0
-#define None 0
-
-#define Window Drawable
-#define Pixmap Drawable
-
-#define XrmoptionNoArg  0
-#define XrmoptionSepArg 1
-
-#define CoordModeOrigin                0
-#define CoordModePrevious       1
-
-#define LineSolid              0
-#define LineOnOffDash          1
-#define LineDoubleDash         2
-
-#define CapNotLast             0
-#define CapButt                        1
-#define CapRound               2
-#define CapProjecting          3
-
-#define JoinMiter              0
-#define JoinRound              1
-#define JoinBevel              2
-
-#define FillSolid              0
-#define FillTiled              1
-#define FillStippled           2
-#define FillOpaqueStippled     3
-
-#define EvenOddRule            0
-#define WindingRule            1
-
-#define Complex                        0
-#define Nonconvex              1
-#define Convex                 2
-
-#define XYBitmap               0
-#define XYPixmap               1
-#define ZPixmap                        2
-
-#define AllocNone              0
-#define AllocAll               1
-
-#define StaticGray             0
-#define GrayScale              1
-#define StaticColor            2
-#define PseudoColor            3
-#define TrueColor              4
-#define DirectColor            5
-
-#define LSBFirst               0
-#define MSBFirst               1
-
-#define DoRed                  (1<<0)
-#define DoGreen                        (1<<1)
-#define DoBlue                 (1<<2)
-
-#define GCFunction              (1L<<0)
-#define GCPlaneMask             (1L<<1)
-#define GCForeground            (1L<<2)
-#define GCBackground            (1L<<3)
-#define GCLineWidth             (1L<<4)
-#define GCLineStyle             (1L<<5)
-#define GCCapStyle              (1L<<6)
-#define GCJoinStyle            (1L<<7)
-#define GCFillStyle            (1L<<8)
-#define GCFillRule             (1L<<9) 
-#define GCTile                 (1L<<10)
-#define GCStipple              (1L<<11)
-#define GCTileStipXOrigin      (1L<<12)
-#define GCTileStipYOrigin      (1L<<13)
-#define GCFont                         (1L<<14)
-#define GCSubwindowMode                (1L<<15)
-#define GCGraphicsExposures     (1L<<16)
-#define GCClipXOrigin          (1L<<17)
-#define GCClipYOrigin          (1L<<18)
-#define GCClipMask             (1L<<19)
-#define GCDashOffset           (1L<<20)
-#define GCDashList             (1L<<21)
-#define GCArcMode              (1L<<22)
-
-#define KeyPress               2
-#define KeyRelease             3
-#define ButtonPress            4
-#define ButtonRelease          5
-#define MotionNotify           6
-#define Expose                 12
-#define GraphicsExpose         13
-#define NoExpose               14
-#define VisibilityNotify       15
-
-#define ClipByChildren         0
-#define IncludeInferiors       1
-
-#define KeyPressMask           (1L<<0)
-#define KeyReleaseMask         (1L<<1)
-#define ButtonPressMask                (1L<<2)
-#define ButtonReleaseMask      (1L<<3)
-#define PointerMotionMask      (1L<<6)
-
-#define Button1                        1
-#define Button2                        2
-#define Button3                        3
-#define Button4                        4
-#define Button5                        5
-
-#define ShiftMask              (1<<0)
-#define LockMask               (1<<1)
-#define ControlMask            (1<<2)
-#define Mod1Mask               (1<<3)
-#define Mod2Mask               (1<<4)
-#define Mod3Mask               (1<<5)
-#define Mod4Mask               (1<<6)
-#define Mod5Mask               (1<<7)
-#define Button1Mask            (1<<8)
-#define Button2Mask            (1<<9)
-#define Button3Mask            (1<<10)
-#define Button4Mask            (1<<11)
-#define Button5Mask            (1<<12)
-
-#define XK_Shift_L             0xFFE1
-#define XK_Shift_R             0xFFE2
-#define XK_Control_L           0xFFE3
-#define XK_Control_R           0xFFE4
-#define XK_Caps_Lock           0xFFE5
-#define XK_Shift_Lock          0xFFE6
-#define XK_Meta_L              0xFFE7
-#define XK_Meta_R              0xFFE8
-#define XK_Alt_L               0xFFE9
-#define XK_Alt_R               0xFFEA
-#define XK_Super_L             0xFFEB
-#define XK_Super_R             0xFFEC
-#define XK_Hyper_L             0xFFED
-#define XK_Hyper_R             0xFFEE
-
-#define XK_Home                        0xFF50
-#define XK_Left                        0xFF51
-#define XK_Up                  0xFF52
-#define XK_Right               0xFF53
-#define XK_Down                        0xFF54
-#define XK_Prior               0xFF55
-#define XK_Page_Up             0xFF55
-#define XK_Next                        0xFF56
-#define XK_Page_Down           0xFF56
-#define XK_End                 0xFF57
-#define XK_Begin               0xFF58
-
-#define XK_F1                  0xFFBE
-#define XK_F2                  0xFFBF
-#define XK_F3                  0xFFC0
-#define XK_F4                  0xFFC1
-#define XK_F5                  0xFFC2
-#define XK_F6                  0xFFC3
-#define XK_F7                  0xFFC4
-#define XK_F8                  0xFFC5
-#define XK_F9                  0xFFC6
-#define XK_F10                 0xFFC7
-#define XK_F11                 0xFFC8
-#define XK_F12                 0xFFC9
-
-
-#define GXclear                        0x0             /* 0 */
-#define GXand                  0x1             /* src AND dst */
-// #define GXandReverse                0x2             /* src AND NOT dst */
-#define GXcopy                 0x3             /* src */
-// #define GXandInverted       0x4             /* NOT src AND dst */
-// #define GXnoop              0x5             /* dst */
-#define GXxor                  0x6             /* src XOR dst */
-#define GXor                   0x7             /* src OR dst */
-// #define GXnor               0x8             /* NOT src AND NOT dst */
-// #define GXequiv             0x9             /* NOT src XOR dst */
-// #define GXinvert            0xa             /* NOT dst */
-// #define GXorReverse         0xb             /* src OR NOT dst */
-// #define GXcopyInverted      0xc             /* NOT src */
-// #define GXorInverted                0xd             /* NOT src OR dst */
-// #define GXnand              0xe             /* NOT src OR NOT dst */
-#define GXset                  0xf             /* 1 */
-
-#define XA_FONT                 18
-
-#define DefaultScreen(dpy) (0)
-#define BlackPixelOfScreen XBlackPixelOfScreen
-#define WhitePixelOfScreen XWhitePixelOfScreen
-#define BlackPixel(dpy,n) BlackPixelOfScreen(ScreenOfDisplay(dpy,n))
-#define WhitePixel(dpy,n) WhitePixelOfScreen(ScreenOfDisplay(dpy,n))
-#define CellsOfScreen XCellsOfScreen
-#define XFree(x) free(x)
-#define BitmapPad(dpy) (8)
-#define BitmapBitOrder(dpy) (MSBFirst)
-#define ImageByteOrder(dpy) (MSBFirst)
-#define DisplayOfScreen XDisplayOfScreen
-#define DefaultScreenOfDisplay XDefaultScreenOfDisplay
-#define ScreenOfDisplay(dpy,n) DefaultScreenOfDisplay(dpy)
-#define DefaultVisualOfScreen XDefaultVisualOfScreen
-#define DefaultColormapOfScreen(s) (0)
-#define RootWindow XRootWindow
-#define RootWindowOfScreen(s) RootWindow(DisplayOfScreen(s),0)
-#define DisplayWidth XDisplayWidth
-#define DisplayHeight XDisplayHeight
-#define XMaxRequestSize(dpy) (65535)
-
-#define ScreenCount(dpy) jwxyz_ScreenCount(dpy)
-extern int jwxyz_ScreenCount(Display *);
-
-extern Display *jwxyz_make_display (void *nsview, void *cgc);
-extern void jwxyz_free_display (Display *);
-extern void *jwxyz_window_view (Window);
-extern void jwxyz_window_resized (Display *, Window,
-                                  int, int, int, int,
-                                  void *cgc);
-extern void jwxyz_mouse_moved (Display *, Window, int x, int y);
-extern void jwxyz_flush_context (Display *);
-
-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);
-
-unsigned long XBlackPixelOfScreen(Screen *);
-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 *);
-extern Status XGetGeometry (Display *, Drawable, Window *root_ret,
-                            int *x_ret, int *y_ret, 
-                            unsigned int *w_ret, unsigned int *h_ret,
-                            unsigned int *bw_ret, unsigned int *depth_ret);
-extern Status XAllocColor (Display *, Colormap, XColor *);
-extern Status XAllocColorCells (Display *, Colormap, Bool contig,
-                                unsigned long *pmret, unsigned int npl,
-                                unsigned long *pxret, unsigned int npx);
-extern int XStoreColors (Display *, Colormap, XColor *, int n);
-extern int XStoreColor (Display *, Colormap, XColor *);
-extern Status XParseColor(Display *, Colormap, const char *spec, XColor *ret);
-extern Status XAllocNamedColor (Display *, Colormap, char *name,
-                                XColor *screen_ret, XColor *exact_ret);
-extern int XQueryColor (Display *, Colormap, XColor *);
-extern int XQueryColors(Display *, Colormap colormap, XColor *, int ncolors);
-
-extern int XSetForeground (Display *, GC, unsigned long);
-extern int XSetBackground (Display *, GC, unsigned long);
-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);
-
-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, 
-                      int dest_x, int dest_y);
-extern int XCopyPlane (Display *, Drawable, Drawable, GC,
-                       int src_x, int src_y,
-                       unsigned width, int height,
-                       int dest_x, int dest_y,
-                       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);
-extern int XFillArc (Display *, Drawable, GC, int x, int y, 
-                     unsigned int width, unsigned int height,
-                     int angle1, int angle2);
-extern int XDrawArcs (Display *, Drawable, GC, XArc *arcs, int narcs);
-extern int XFillArcs (Display *, Drawable, GC, XArc *arcs, int narcs);
-extern int XDrawRectangle (Display *, Drawable, GC, int x, int y, 
-                           unsigned int width, unsigned int height);
-extern int XFillRectangle (Display *, Drawable, GC, int x, int y, 
-                           unsigned int width, unsigned int height);
-extern int XFillRectangles (Display *, Drawable, GC, XRectangle *, int n);
-
-extern int XDrawString (Display *, Drawable, GC, int x, int y, const char *,
-                        int len);
-extern int XDrawImageString (Display *, Drawable, GC, int x, int y, 
-                             const char *, int len);
-extern int XDrawString16 (Display *, Drawable, GC, int x, int y,
-                          const XChar2b *, int len);
-
-extern Bool XQueryPointer (Display *, Window, Window *root_ret,
-                           Window *child_ret,
-                           int *root_x_ret, int *root_y_ret,
-                           int *win_x_ret, int *win_y_ret,
-                           unsigned int *mask_ret);
-extern int XLookupString (XKeyEvent *, char *ret, int size, KeySym *ks_ret,
-                          XComposeStatus *);
-extern KeySym XKeycodeToKeysym (Display *, KeyCode, int index);
-
-extern Status XInitImage (XImage *);
-extern XImage *XCreateImage (Display *, Visual *, unsigned int depth,
-                             int format, int offset, char *data,
-                             unsigned int width, unsigned int height,
-                             int bitmap_pad, int bytes_per_line);
-extern XImage *XSubImage (XImage *, int x, int y, 
-                          unsigned int w, unsigned int h);
-
-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 *XGetImage (Display *, Drawable, int x, int y,
-                          unsigned int w, unsigned int h,
-                          unsigned long pm, int fmt);
-extern Pixmap XCreatePixmapFromBitmapData (Display *, Drawable,
-                                           const char *data,
-                                           unsigned int w, unsigned int h,
-                                           unsigned long fg,
-                                           unsigned int bg,
-                                           unsigned int depth);
-extern XPixmapFormatValues *XListPixmapFormats (Display *, int *count_ret);
-
-extern void jwxyz_draw_NSImage_or_CGImage (Display *, Drawable, 
-                                           Bool nsimg_p, void *NSImage_arg,
-                                           XRectangle *geom_ret, 
-                                           int exif_rotation);
-
-extern int XSetGraphicsExposures (Display *, GC, Bool);
-extern Bool XTranslateCoordinates (Display *, Window src_w, Window dest_w,
-                                   int src_x, int src_y,
-                                   int *dest_x_ret, int *dest_y_ret,
-                                   Window *child_ret);
-
-extern Font XLoadFont (Display *, const char *);
-extern XFontStruct * XQueryFont (Display *, Font);
-extern XFontStruct * XLoadQueryFont (Display *, const char *);
-extern int XFreeFontInfo (char **names, XFontStruct *info, int n);
-extern int XFreeFont (Display *, XFontStruct *);
-extern int XUnloadFont (Display *, Font);
-extern int XTextExtents (XFontStruct *, const char *, int length,
-                         int *dir_ret, int *ascent_ret, int *descent_ret,
-                         XCharStruct *overall_ret);
-extern char * jwxyz_unicode_character_name (Font, unsigned long uc);
-extern int XTextExtents16 (XFontStruct *, const XChar2b *, int length,
-                           int *dir_ret, int *ascent_ret, int *descent_ret,
-                           XCharStruct *overall_ret);
-extern int XTextWidth (XFontStruct *, const char *, int length);
-extern int XSetFont (Display *, GC, Font);
-
-extern XFontSet XCreateFontSet (Display *, char *name, 
-                                char ***missing_charset_list_return,
-                                int *missing_charset_count_return,
-                                char **def_string_return);
-extern void XFreeFontSet (Display *, XFontSet);
-extern void XFreeStringList (char **);
-extern int Xutf8TextExtents (XFontSet, const char *, int num_bytes,
-                             XRectangle *overall_ink_return,
-                             XRectangle *overall_logical_return);
-extern void Xutf8DrawString (Display *, Drawable, XFontSet, GC,
-                             int x, int y, const char *, int num_bytes);
-extern const char *jwxyz_nativeFontName (Font, float *size);
-
-extern Pixmap XCreatePixmap (Display *, Drawable,
-                             unsigned int width, unsigned int height,
-                             unsigned int depth);
-extern int XFreePixmap (Display *, Pixmap);
-
-extern char *XGetAtomName (Display *, Atom);
-
-// Xt timers and fds
-extern XtAppContext XtDisplayToApplicationContext (Display *);
-typedef void (*XtTimerCallbackProc) (XtPointer closure, XtIntervalId *);
-typedef void (*XtInputCallbackProc) (XtPointer closure, int *fd, XtInputId *);
-extern XtIntervalId XtAppAddTimeOut (XtAppContext, unsigned long usecs,
-                                     XtTimerCallbackProc, XtPointer closure);
-extern void XtRemoveTimeOut (XtIntervalId);
-extern XtInputId XtAppAddInput (XtAppContext, int fd, XtPointer flags,
-                               XtInputCallbackProc, XtPointer closure);
-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
-extern void glXSwapBuffers (Display *, Window);
-extern void glXMakeCurrent (Display *, Window, GLXContext);
-
-// also declared in utils/visual.h
-extern int has_writable_cells (Screen *, Visual *);
-extern int visual_depth (Screen *, Visual *);
-extern int visual_cells (Screen *, Visual *);
-extern int visual_class (Screen *, Visual *);
-extern int get_bits_per_pixel (Display *, int);
-extern int screen_number (Screen *);
-
-// also declared in utils/grabclient.h
-extern Bool use_subwindow_mode_p (Screen *, Window);
-
-
-struct jwxyz_Visual {
-  VisualID visualid;   /* visual id of this visual */
-  int class;           /* class of screen (monochrome, etc.) */
-  unsigned long red_mask, green_mask, blue_mask;       /* mask values */
-  int bits_per_rgb;    /* log base 2 of distinct color values */
-//  int map_entries;   /* color map entries */
-};
-
-struct jwxyz_XGCValues {
-  int function;                /* logical operation */
-#if 0
-  unsigned long plane_mask;/* plane mask */
-#endif
-  unsigned long foreground;/* foreground pixel */
-  unsigned long background;/* background pixel */
-  int line_width;      /* line width */
-#if 0
-  int line_style;      /* LineSolid, LineOnOffDash, LineDoubleDash */
-#endif
-  int cap_style;       /* CapNotLast, CapButt, CapRound, CapProjecting */
-  int join_style;      /* JoinMiter, JoinRound, JoinBevel */
-#if 0
-  int fill_style;      /* FillSolid, FillTiled, 
-                          FillStippled, FillOpaeueStippled */
-#endif
-  int fill_rule;       /* EvenOddRule, WindingRule */
-#if 0
-  int arc_mode;                /* ArcChord, ArcPieSlice */
-  Pixmap tile;         /* tile pixmap for tiling operations */
-  Pixmap stipple;      /* stipple 1 plane pixmap for stipping */
-  int ts_x_origin;     /* offset for tile or stipple operations */
-  int ts_y_origin;
-#endif
-  Font font;           /* default text font for text operations */
-  int subwindow_mode;     /* ClipByChildren, IncludeInferiors */
-#if 0
-  Bool graphics_exposures;/* boolean, should exposures be generated */
-#endif
-  int clip_x_origin;   /* origin for clipping */
-  int clip_y_origin;
-  Pixmap clip_mask;    /* bitmap clipping; other calls for rects */
-#if 0
-  int dash_offset;     /* patterned/dashed line information */
-  char dashes;
-#endif
-
-  Bool alpha_allowed_p;        /* jwxyz extension: whether pixel values may have
-                           a non-opaque alpha component. */
-  Bool antialias_p;    /* jwxyz extension: whether Quartz should draw
-                           with antialiasing. */
-};
-
-struct jwxyz_XWindowAttributes {
-    int x, y;                  /* location of window */
-    int width, height;         /* width and height of window */
-    int border_width;          /* border width of window */
-    int depth;                 /* depth of window */
-    Visual *visual;            /* the associated visual structure */
-#if 0
-    Window root;               /* root of screen containing window */
-    int class;                 /* InputOutput, InputOnly*/
-    int bit_gravity;           /* one of bit gravity values */
-    int win_gravity;           /* one of the window gravity values */
-    int backing_store;         /* NotUseful, WhenMapped, Always */
-    unsigned long backing_planes;/* planes to be preserved if possible */
-    unsigned long backing_pixel;/* value to be used when restoring planes */
-    Bool save_under;           /* boolean, should bits under be saved? */
-#endif
-    Colormap colormap;         /* color map to be associated with window */
-#if 0
-    Bool map_installed;                /* boolean, is color map currently installed*/
-    int map_state;             /* IsUnmapped, IsUnviewable, IsViewable */
-    long all_event_masks;      /* set of events all people have interest in*/
-    long your_event_mask;      /* my event mask */
-    long do_not_propagate_mask; /* set of events that should not propagate */
-    Bool override_redirect;    /* boolean value for override-redirect */
-#endif
-    Screen *screen;            /* back pointer to correct screen */
-};
-
-struct jwxyz_XColor {
-  unsigned long pixel;
-  unsigned short red, green, blue;
-  char flags;  /* do_red, do_green, do_blue */
-  char pad;
-};
-
-struct jwxyz_XPoint {
-  short x, y;
-};
-
-struct jwxyz_XSegment {
-  short x1, y1, x2, y2;
-};
-
-struct jwxyz_XRectangle {
-  short x, y;
-  unsigned short width, height;
-};
-
-struct jwxyz_XArc {
-  short x, y;
-  unsigned short width, height;
-  short angle1, angle2;
-};
-
-
-struct jwxyz_XrmOptionDescRec {
-  char *option;
-  char *specifier;
-  int argKind;
-  void *value;
-};
-
-struct jwxyz_XAnyEvent {
-  int type;
-#if 0
-  unsigned long serial;
-  Bool send_event;
-  Display *display;
-  Window window;
-#endif
-};
-
-struct jwxyz_XKeyEvent {
-  int type;
-#if 0
-  unsigned long serial;
-  Bool send_event;
-  Display *display;
-  Window window;
-  Window root;
-  Window subwindow;
-  Time time;
-  int x, y;
-  int x_root, y_root;
-#endif
-  unsigned int state;
-  unsigned int keycode;
-#if 0
-  Bool same_screen;
-#endif
-};
-
-struct jwxyz_XButtonEvent {
-  int type;
-#if 0
-  unsigned long serial;
-  Bool send_event;
-  Display *display;
-  Window window;
-  Window root;
-  Window subwindow;
-  Time time;
-#endif
-  int x, y;
-#if 0
-  int x_root, y_root;
-#endif
-  unsigned int state;
-  unsigned int button;
-#if 0
-  Bool same_screen;
-#endif
-};
-
-struct jwxyz_XMotionEvent {
-  int type;
-#if 0
-  unsigned long serial;
-  Bool send_event;
-  Display *display;
-  Window window;
-  Window root;
-  Window subwindow;
-  Time time;
-#endif
-  int x, y;
-#if 0
-  int x_root, y_root;
-#endif
-  unsigned int state;
-#if 0
-  char is_hint;
-  Bool same_screen;
-#endif
-};
-
-union jwxyz_XEvent {
-  int type;
-  XAnyEvent xany;
-  XKeyEvent xkey;
-  XButtonEvent xbutton;
-  XMotionEvent xmotion;
-};
-
-struct jwxyz_XImage {
-    int width, height;         /* size of image */
-    int xoffset;               /* number of pixels offset in X direction */
-    int format;                        /* XYBitmap, XYPixmap, ZPixmap */
-    char *data;                        /* pointer to image data */
-    int byte_order;            /* data byte order, LSBFirst, MSBFirst */
-    int bitmap_unit;           /* quant. of scanline 8, 16, 32 */
-    int bitmap_bit_order;      /* LSBFirst, MSBFirst */
-    int bitmap_pad;            /* 8, 16, 32 either XY or ZPixmap */
-    int depth;                 /* depth of image */
-    int bytes_per_line;                /* accelarator to next line */
-    int bits_per_pixel;                /* bits per pixel (ZPixmap) */
-    unsigned long red_mask;    /* bits in z arrangment */
-    unsigned long green_mask;
-    unsigned long blue_mask;
-//  XPointer obdata;           /* hook for the object routines to hang on */
-    struct funcs {             /* image manipulation routines */
-#if 0
-      XImage *(*create_image)(
-               Display*        /* display */,
-               Visual*         /* visual */,
-               unsigned int    /* depth */,
-               int             /* format */,
-               int             /* offset */,
-               char*           /* data */,
-               unsigned int    /* width */,
-               unsigned int    /* height */,
-               int             /* bitmap_pad */,
-               int             /* bytes_per_line */);
-       int (*destroy_image)        (XImage *);
-#endif
-       unsigned long (*get_pixel)  (XImage *, int, int);
-       int (*put_pixel)            (XImage *, int, int, unsigned long);
-#if 0
-       XImage *(*sub_image)        (XImage *, int, int, unsigned int, unsigned int);
-       int (*add_pixel)            (XImage *, long);
-#endif
-    } f;
-};
-
-struct jwxyz_XCharStruct {
-  short        lbearing;       /* origin to left edge of ink */
-  short        rbearing;       /* origin to right edge of ink */
-  short        width;          /* advance to next char's origin */
-  short        ascent;         /* baseline to top edge of ink */
-  short        descent;        /* baseline to bottom edge of ink */
-#if 0
-  unsigned short attributes;   /* per char flags (not predefined) */
-#endif
-};
-
-struct jwxyz_XFontProp {
-  Atom          name;
-  unsigned long card32; /* Careful: This holds (32- or 64-bit) pointers. */
-};
-
-struct jwxyz_XFontStruct {
-#if 0
-  XExtData     *ext_data;      /* hook for extension to hang data */
-#endif
-  Font          fid;            /* Font id for this font */
-#if 0
-  unsigned     direction;      /* hint about direction the font is painted */
-#endif
-  unsigned     min_char_or_byte2;      /* first character */
-  unsigned     max_char_or_byte2;      /* last character */
-#if 0
-  unsigned     min_byte1;      /* first row that exists */
-  unsigned     max_byte1;      /* last row that exists */
-  Bool all_chars_exist;        /* flag if all characters have non-zero size*/
-#endif
-  unsigned     default_char;   /* char to print for undefined character */
-  int         n_properties;   /* how many properties there are */
-  XFontProp    *properties;    /* pointer to array of additional properties*/
-  XCharStruct  min_bounds;     /* minimum bounds over all existing char*/
-  XCharStruct  max_bounds;     /* maximum bounds over all existing char*/
-  XCharStruct  *per_char;      /* first_char to last_char information */
-  int          ascent;         /* log. extent above baseline for spacing */
-  int          descent;        /* log. descent below baseline for spacing */
-};
-
-struct jwxyz_XComposeStatus {
-  char dummy;
-};
-
-struct  jwxyz_XPixmapFormatValues {
-  int depth;
-  int bits_per_pixel;
-  int scanline_pad;
-};
-
-struct jwxyz_XChar2b {
-  unsigned char byte1;
-  unsigned char byte2;
-};
-
-#endif /* __JWXYZ_H__ */
diff --git a/OSX/jwxyz.m b/OSX/jwxyz.m
deleted file mode 100644 (file)
index 8d18127..0000000
+++ /dev/null
@@ -1,4203 +0,0 @@
-/* xscreensaver, Copyright (c) 1991-2015 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.
- */
-
-/* JWXYZ Is Not Xlib.
-
-   But it's a bunch of function definitions that bear some resemblance to
-   Xlib and that do Cocoa-ish things that bear some resemblance to the
-   things that Xlib might have done.
- */
-
-#import <stdlib.h>
-#import <stdint.h>
-#import <wchar.h>
-
-#ifdef USE_IPHONE
-# import <UIKit/UIKit.h>
-# import <UIKit/UIScreen.h>
-# import <QuartzCore/QuartzCore.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
-#else
-# import <Cocoa/Cocoa.h>
-#endif
-
-#import <CoreText/CTFont.h>
-#import <CoreText/CTLine.h>
-#import <CoreText/CTRun.h>
-
-#import "jwxyz.h"
-#import "jwxyz-timers.h"
-#import "yarandom.h"
-#import "utf8wc.h"
-#import "xft.h"
-
-# define USE_BACKBUFFER  /* must be in sync with XScreenSaverView.h */
-
-#undef  Assert
-#define Assert(C,S) do { if (!(C)) jwxyz_abort ("%s",(S)); } while(0)
-
-# undef MAX
-# undef MIN
-# define MAX(a,b) ((a)>(b)?(a):(b))
-# define MIN(a,b) ((a)<(b)?(a):(b))
-
-
-struct jwxyz_Drawable {
-  enum { WINDOW, PIXMAP } type;
-  CGContextRef cgc;
-  CGImageRef cgi;
-  CGRect frame;
-  union {
-    struct {
-      NSView *view;
-      unsigned long background;
-      int last_mouse_x, last_mouse_y;
-    } window;
-    struct {
-      int depth;
-      void *cgc_buffer;                // the bits to which CGContextRef renders
-    } pixmap;
-  };
-};
-
-struct jwxyz_Display {
-  Window main_window;
-  Screen *screen;
-  int screen_count;
-  struct jwxyz_sources_data *timers_data;
-
-# ifndef USE_IPHONE
-  CGDirectDisplayID cgdpy;  /* ...of the one and only Window, main_window.
-                               This can change if the window is dragged to
-                               a different screen. */
-# endif
-
-  CGColorSpaceRef colorspace;  /* Color space of this screen.  We tag all of
-                                  our images with this to avoid translation
-                                  when rendering. */
-};
-
-struct jwxyz_Screen {
-  Display *dpy;
-  CGBitmapInfo bitmap_info;
-  unsigned long black, white;
-  Visual *visual;
-  int screen_number;
-};
-
-struct jwxyz_GC {
-  XGCValues gcv;
-  unsigned int depth;
-  CGImageRef clip_mask;  // CGImage copy of the Pixmap in gcv.clip_mask
-};
-
-struct jwxyz_Font {
-  Display *dpy;
-  char *ps_name;
-  NSFont *nsfont;
-  float size;   // points
-  char *xa_font;
-
-  // In X11, "Font" is just an ID, and "XFontStruct" contains the metrics.
-  // But we need the metrics on both of them, so they go here.
-  XFontStruct metrics;
-};
-
-struct jwxyz_XFontSet {
-  XFontStruct *font;
-};
-
-
-/* Instead of calling abort(), throw a real exception, so that
-   XScreenSaverView can catch it and display a dialog.
- */
-void
-jwxyz_abort (const char *fmt, ...)
-{
-  char s[10240];
-  if (!fmt || !*fmt)
-    strcpy (s, "abort");
-  else
-    {
-      va_list args;
-      va_start (args, fmt);
-      vsprintf (s, fmt, args);
-      va_end (args);
-    }
-  [[NSException exceptionWithName: NSInternalInconsistencyException
-                reason: [NSString stringWithCString: s
-                                  encoding:NSUTF8StringEncoding]
-                userInfo: nil]
-    raise];
-  abort();  // not reached
-}
-
-// 24/32bpp -> 32bpp image conversion.
-// Any of RGBA, BGRA, ABGR, or ARGB can be represented by a rotate of 0/8/16/24
-// bits and an optional byte order swap.
-
-// This type encodes such a conversion.
-typedef unsigned convert_mode_t;
-
-// It's rotate, then swap.
-// A rotation here shifts bytes forward in memory. On x86/ARM, that's a left
-// rotate, and on PowerPC, a rightward rotation.
-static const convert_mode_t CONVERT_MODE_ROTATE_MASK = 0x3;
-static const convert_mode_t CONVERT_MODE_SWAP = 0x4;
-
-
-// Converts an array of pixels ('src') from one format to another, placing the
-// result in 'dest', according to the pixel conversion mode 'mode'.
-static void
-convert_row (uint32_t *dest, const void *src, size_t count,
-             convert_mode_t mode, size_t src_bpp)
-{
-  Assert (src_bpp == 24 || src_bpp == 32, "weird bpp");
-
-  // This works OK iff src == dest or src and dest do not overlap.
-
-  if (!mode) {
-    if (src != dest)
-      memcpy (dest, src, count * 4);
-    return;
-  }
-
-  // This is correct, but not fast.
-  convert_mode_t rot = (mode & CONVERT_MODE_ROTATE_MASK) * 8;
-  convert_mode_t flip = mode & CONVERT_MODE_SWAP;
-
-  src_bpp /= 8;
-
-  uint32_t *dest_end = dest + count;
-  while (dest != dest_end) {
-    uint32_t x;
-
-    if (src_bpp == 4)
-      x = *(const uint32_t *)src;
-    else { // src_bpp == 3
-      const uint8_t *src8 = (const uint8_t *)src;
-      // __LITTLE/BIG_ENDIAN__ are defined by the compiler.
-# if defined __LITTLE_ENDIAN__
-      x = src8[0] | (src8[1] << 8) | (src8[2] << 16) | 0xff000000;
-# elif defined __BIG_ENDIAN__
-      x = (src8[0] << 24) | (src8[1] << 16) | (src8[2] << 8) | 0xff;
-# else
-#  error "Can't determine system endianness."
-# endif
-    }
-
-    src = (const uint8_t *)src + src_bpp;
-
-    /* The naive (i.e. ubiquitous) portable implementation of bitwise rotation,
-       for 32-bit integers, is:
-
-       (x << rot) | (x >> (32 - rot))
-
-       This works nearly everywhere. Compilers on x86 wil generally recognize
-       the idiom and convert it to a ROL instruction. But there's a problem
-       here: according to the C specification, bit shifts greater than or equal
-       to the length of the integer are undefined. And if rot = 0:
-       1. (x << 0) | (x >> (32 - 0))
-       2. (x << 0) | (x >> 32)
-       3. (x << 0) | (Undefined!)
-
-       Still, when the compiler converts this to a ROL on x86, everything works
-       as intended. But, there are two additional problems when Clang does
-       compile-time constant expression evaluation with the (x >> 32)
-       expression:
-       1. Instead of evaluating it to something reasonable (either 0, like a
-          human would intuitively expect, or x, like x86 would with SHR), Clang
-          seems to pull a value out of nowhere, like -1, or some other random
-          number.
-       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.
-
-       http://blog.regehr.org/archives/1063
-       http://llvm.org/bugs/show_bug.cgi?id=17332
-       As described in those links, there is a solution here: Masking the
-       undefined shift with '& 31' as below makes the experesion well-defined
-       again. And LLVM is set to pick up on this safe version of the idiom and
-       use a rotation instruction on architectures (like x86) that support it,
-       just like it does with the unsafe version.
-
-       Too bad LLVM doesn't want to pick up on that particular optimization
-       here. Oh well. At least this code usually isn't critical w.r.t.
-       performance.
-     */
-
-# if defined __LITTLE_ENDIAN__
-    x = (x << rot) | (x >> ((32 - rot) & 31));
-# elif defined __BIG_ENDIAN__
-    x = (x >> rot) | (x << ((32 - rot) & 31));
-# endif
-
-    if (flip)
-      x = __builtin_bswap32(x); // LLVM/GCC built-in function.
-
-    *dest = x;
-    ++dest;
-  }
-}
-
-
-// Converts a single pixel.
-static uint32_t
-convert_px (uint32_t px, convert_mode_t mode)
-{
-  convert_row (&px, &px, 1, mode, 32);
-  return px;
-}
-
-
-// This returns the inverse conversion mode, such that:
-// pixel
-//   == convert_px(convert_px(pixel, mode), convert_mode_invert(mode))
-//   == convert_px(convert_px(pixel, convert_mode_invert(mode)), mode)
-static convert_mode_t
-convert_mode_invert (convert_mode_t mode)
-{
-  // swap(0); rot(n) == rot(n); swap(0)
-  // swap(1); rot(n) == rot(-n); swap(1)
-  return mode & CONVERT_MODE_SWAP ? mode : CONVERT_MODE_ROTATE_MASK & -mode;
-}
-
-
-// This combines two conversions into one, such that:
-// convert_px(convert_px(pixel, mode0), mode1)
-//   == convert_px(pixel, convert_mode_merge(mode0, mode1))
-static convert_mode_t
-convert_mode_merge (convert_mode_t m0, convert_mode_t m1)
-{
-  // rot(r0); swap(s0); rot(r1); swap(s1)
-  // rot(r0); rot(s0 ? -r1 : r1); swap(s0); swap(s1)
-  // rot(r0 + (s0 ? -r1 : r1)); swap(s0 + s1)
-  return
-    ((m0 + (m0 & CONVERT_MODE_SWAP ? -m1 : m1)) & CONVERT_MODE_ROTATE_MASK) |
-    ((m0 ^ m1) & CONVERT_MODE_SWAP);
-}
-
-
-// This returns a conversion mode that converts an arbitrary 32-bit format
-// specified by bitmap_info to RGBA.
-static convert_mode_t
-convert_mode_to_rgba (CGBitmapInfo bitmap_info)
-{
-  // Former default: kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little
-  // i.e. BGRA
-  // red   = 0x00FF0000;
-  // green = 0x0000FF00;
-  // blue  = 0x000000FF;
-
-  // RGBA: kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder32Big
-
-  CGImageAlphaInfo alpha_info =
-    (CGImageAlphaInfo)(bitmap_info & kCGBitmapAlphaInfoMask);
-
-  Assert (! (bitmap_info & kCGBitmapFloatComponents),
-          "kCGBitmapFloatComponents unsupported");
-  Assert (alpha_info != kCGImageAlphaOnly, "kCGImageAlphaOnly not supported");
-
-  convert_mode_t rot = alpha_info == kCGImageAlphaFirst ||
-                       alpha_info == kCGImageAlphaPremultipliedFirst ||
-                       alpha_info == kCGImageAlphaNoneSkipFirst ?
-                       3 : 0;
-
-  CGBitmapInfo byte_order = bitmap_info & kCGBitmapByteOrderMask;
-
-  Assert (byte_order == kCGBitmapByteOrder32Little ||
-          byte_order == kCGBitmapByteOrder32Big,
-          "byte order not supported");
-
-  convert_mode_t swap = byte_order == kCGBitmapByteOrder32Little ?
-                        CONVERT_MODE_SWAP : 0;
-  if (swap)
-    rot = CONVERT_MODE_ROTATE_MASK & -rot;
-  return swap | rot;
-}
-
-
-union color_bytes
-{
-  uint32_t pixel;
-  uint8_t bytes[4];
-};
-
-
-static uint32_t
-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)));
-}
-
-
-static void
-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)
-{
-  uint8_t rgba8[4];
-  query_color (dpy, pixel, rgba8);
-  for (unsigned i = 0; i != 4; ++i)
-    rgba[i] = rgba8[i] * (1.0f / 255.0f);
-}
-
-
-/* We keep a list of all of the Displays that have been created and not
-   yet freed so that they can have sensible display numbers.  If three
-   displays are created (0, 1, 2) and then #1 is closed, then the fourth
-   display will be given the now-unused display number 1. (Everything in
-   here assumes a 1:1 Display/Screen mapping.)
-
-   The size of this array is the most number of live displays at one time.
-   So if it's 20, then we'll blow up if the system has 19 monitors and also
-   has System Preferences open (the small preview window).
-
-   Note that xlockmore-style savers tend to allocate big structures, so
-   setting this to 1000 will waste a few megabytes.  Also some of them assume
-   that the number of screens never changes, so dynamically expanding this
-   array won't work.
- */
-# ifndef USE_IPHONE
-static Display *jwxyz_live_displays[20] = { 0, };
-# endif
-
-
-Display *
-jwxyz_make_display (void *nsview_arg, void *cgc_arg)
-{
-  CGContextRef cgc = (CGContextRef) cgc_arg;
-  NSView *view = (NSView *) nsview_arg;
-  Assert (view, "no view");
-  if (!view) return 0;
-
-  Display *d = (Display *) calloc (1, sizeof(*d));
-  d->screen = (Screen *) calloc (1, sizeof(Screen));
-  d->screen->dpy = d;
-  
-  d->screen_count = 1;
-  d->screen->screen_number = 0;
-# ifndef USE_IPHONE
-  {
-    // Find the first empty slot in live_displays and plug us in.
-    int size = sizeof(jwxyz_live_displays) / sizeof(*jwxyz_live_displays);
-    int i;
-    for (i = 0; i < size; i++) {
-      if (! jwxyz_live_displays[i])
-        break;
-    }
-    if (i >= size) abort();
-    jwxyz_live_displays[i] = d;
-    d->screen_count = size;
-    d->screen->screen_number = i;
-  }
-# endif // !USE_IPHONE
-
-# ifdef USE_BACKBUFFER
-  d->screen->bitmap_info = CGBitmapContextGetBitmapInfo (cgc);
-# else
-  d->screen->bitmap_info = (kCGImageAlphaNoneSkipFirst |
-                            kCGBitmapByteOrder32Little);
-# endif
-  d->screen->black = alloc_color (d, 0x0000, 0x0000, 0x0000, 0xFFFF);
-  d->screen->white = alloc_color (d, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF);
-
-# if 0
-  // Tests for the image conversion modes.
-  {
-    const uint32_t key = 0x04030201;
-#  ifdef __LITTLE_ENDIAN__
-    assert (convert_px (key, 0) == key);
-    assert (convert_px (key, 1) == 0x03020104);
-    assert (convert_px (key, 3) == 0x01040302);
-    assert (convert_px (key, 4) == 0x01020304);
-    assert (convert_px (key, 5) == 0x04010203);
-#  endif
-    for (unsigned i = 0; i != 8; ++i) {
-      assert (convert_px(convert_px(key, i), convert_mode_invert(i)) == key);
-      assert (convert_mode_invert(convert_mode_invert(i)) == i);
-    }
-
-    for (unsigned i = 0; i != 8; ++i) {
-      for (unsigned j = 0; j != 8; ++j)
-        assert (convert_px(convert_px(key, i), j) ==
-                convert_px(key, convert_mode_merge(i, j)));
-    }
-  }
-# endif
-
-  Visual *v = (Visual *) calloc (1, sizeof(Visual));
-  v->class      = TrueColor;
-  v->red_mask   = alloc_color (d, 0xFFFF, 0x0000, 0x0000, 0x0000);
-  v->green_mask = alloc_color (d, 0x0000, 0xFFFF, 0x0000, 0x0000);
-  v->blue_mask  = alloc_color (d, 0x0000, 0x0000, 0xFFFF, 0x0000);
-  CGBitmapInfo byte_order = d->screen->bitmap_info & kCGBitmapByteOrderMask;
-  Assert ( ! (d->screen->bitmap_info & kCGBitmapFloatComponents) &&
-          (byte_order == kCGBitmapByteOrder32Little ||
-           byte_order == kCGBitmapByteOrder32Big),
-          "invalid bits per channel");
-  v->bits_per_rgb = 8;
-  d->screen->visual = v;
-  
-  d->timers_data = jwxyz_sources_init (XtDisplayToApplicationContext (d));
-
-
-  Window w = (Window) calloc (1, sizeof(*w));
-  w->type = WINDOW;
-  w->window.view = view;
-  CFRetain (w->window.view);   // needed for garbage collection?
-  w->window.background = BlackPixel(d,0);
-
-  d->main_window = w;
-
-# ifndef USE_IPHONE
-  if (! cgc) {
-    [view lockFocus];
-    cgc = [[[view window] graphicsContext] graphicsPort];
-    [view unlockFocus];
-    w->cgc = cgc;
-  }
-# endif
-
-  Assert (cgc, "no CGContext");
-  return d;
-}
-
-void
-jwxyz_free_display (Display *dpy)
-{
-  jwxyz_sources_free (dpy->timers_data);
-  
-# ifndef USE_IPHONE
-  {
-    // Find us in live_displays and clear that slot.
-    int size = ScreenCount(dpy);
-    int i;
-    for (i = 0; i < size; i++) {
-      if (dpy == jwxyz_live_displays[i]) {
-        jwxyz_live_displays[i] = 0;
-        break;
-      }
-    }
-    if (i >= size) abort();
-  }
-# endif // !USE_IPHONE
-
-  free (dpy->screen->visual);
-  free (dpy->screen);
-  CFRelease (dpy->main_window->window.view);
-  free (dpy->main_window);
-  free (dpy);
-}
-
-
-void *
-jwxyz_window_view (Window w)
-{
-  Assert (w && w->type == WINDOW, "not a window");
-  return w->window.view;
-}
-
-
-/* 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)
-{
-  if (d && d->cgi) {
-    CGImageRelease (d->cgi);
-    d->cgi = 0;
-  }
-}
-
-
-/* Call this when the View changes size or position.
- */
-void
-jwxyz_window_resized (Display *dpy, Window w, 
-                      int new_x, int new_y, int new_width, int new_height,
-                      void *cgc_arg)
-{
-  CGContextRef cgc = (CGContextRef) cgc_arg;
-  Assert (w && w->type == WINDOW, "not a window");
-  w->frame.origin.x    = new_x;
-  w->frame.origin.y    = new_y;
-  w->frame.size.width  = new_width;
-  w->frame.size.height = new_height;
-
-  if (cgc) w->cgc = cgc;
-  Assert (w->cgc, "no CGContext");
-
-# ifndef USE_IPHONE
-  // Figure out which screen the window is currently on.
-  {
-    int wx, wy;
-    XTranslateCoordinates (dpy, w, NULL, 0, 0, &wx, &wy, NULL);
-    CGPoint p;
-    p.x = wx;
-    p.y = wy;
-    CGDisplayCount n;
-    dpy->cgdpy = 0;
-    CGGetDisplaysWithPoint (p, 1, &dpy->cgdpy, &n);
-    // Auuugh!
-    if (! dpy->cgdpy) {
-      p.x = p.y = 0;
-      CGGetDisplaysWithPoint (p, 1, &dpy->cgdpy, &n);
-    }
-    Assert (dpy->cgdpy, "unable to find CGDisplay");
-  }
-# endif // USE_IPHONE
-
-# ifndef USE_BACKBUFFER
-  // Funny thing: As of OS X 10.9, if USE_BACKBUFFER is turned off,
-  // then this one's faster.
-
-  {
-    // Figure out this screen's colorspace, and use that for every CGImage.
-    //
-    CMProfileRef profile = 0;
-    CMGetProfileByAVID ((CMDisplayIDType) dpy->cgdpy, &profile);
-    Assert (profile, "unable to find colorspace profile");
-    dpy->colorspace = CGColorSpaceCreateWithPlatformColorSpace (profile);
-    Assert (dpy->colorspace, "unable to find colorspace");
-  }
-# else  // USE_BACKBUFFER
-
-  // WTF?  It's faster if we *do not* use the screen's colorspace!
-  //
-  dpy->colorspace = CGColorSpaceCreateDeviceRGB();
-# endif // USE_BACKBUFFER
-
-  invalidate_drawable_cache (w);
-}
-
-
-#ifdef USE_IPHONE
-void
-jwxyz_mouse_moved (Display *dpy, Window w, int x, int y)
-{
-  Assert (w && w->type == WINDOW, "not a window");
-  w->window.last_mouse_x = x;
-  w->window.last_mouse_y = y;
-}
-#endif // USE_IPHONE
-
-
-void
-jwxyz_flush_context (Display *dpy)
-{
-  // This is only used when USE_BACKBUFFER is off.
-  // CGContextSynchronize is another possibility.
-  CGContextFlush(dpy->main_window->cgc);
-}
-
-jwxyz_sources_data *
-display_sources_data (Display *dpy)
-{
-  return dpy->timers_data;
-}
-
-
-Window
-XRootWindow (Display *dpy, int screen)
-{
-  return dpy->main_window;
-}
-
-Screen *
-XDefaultScreenOfDisplay (Display *dpy)
-{
-  return dpy->screen;
-}
-
-Visual *
-XDefaultVisualOfScreen (Screen *screen)
-{
-  return screen->visual;
-}
-
-Display *
-XDisplayOfScreen (Screen *s)
-{
-  return s->dpy;
-}
-
-int
-XDisplayNumberOfScreen (Screen *s)
-{
-  return 0;
-}
-
-int
-XScreenNumberOfScreen (Screen *s)
-{
-  return s->screen_number;
-}
-
-int
-jwxyz_ScreenCount (Display *dpy)
-{
-  return dpy->screen_count;
-}
-
-int
-XDisplayWidth (Display *dpy, int screen)
-{
-  return (int) dpy->main_window->frame.size.width;
-}
-
-int
-XDisplayHeight (Display *dpy, int screen)
-{
-  return (int) dpy->main_window->frame.size.height;
-}
-
-unsigned long
-XBlackPixelOfScreen(Screen *screen)
-{
-  return screen->black;
-}
-
-unsigned long
-XWhitePixelOfScreen(Screen *screen)
-{
-  return screen->white;
-}
-
-unsigned long
-XCellsOfScreen(Screen *screen)
-{
-  Visual *v = screen->visual;
-  return v->red_mask | v->green_mask | v->blue_mask;
-}
-
-static void
-validate_pixel (Display *dpy, unsigned long pixel, unsigned int depth,
-                BOOL alpha_allowed_p)
-{
-  if (depth == 1)
-    Assert ((pixel == 0 || pixel == 1), "bogus mono pixel");
-  else if (!alpha_allowed_p)
-    Assert (((pixel & BlackPixel(dpy,0)) == BlackPixel(dpy,0)),
-            "bogus color pixel");
-}
-
-
-static void
-set_color (Display *dpy, CGContextRef cgc, unsigned long argb,
-           unsigned int depth, BOOL alpha_allowed_p, BOOL fill_p)
-{
-  validate_pixel (dpy, argb, depth, alpha_allowed_p);
-  if (depth == 1) {
-    if (fill_p)
-      CGContextSetGrayFillColor   (cgc, (argb ? 1.0 : 0.0), 1.0);
-    else
-      CGContextSetGrayStrokeColor (cgc, (argb ? 1.0 : 0.0), 1.0);
-  } else {
-    float rgba[4];
-    query_color_float (dpy, argb, rgba);
-    if (fill_p)
-      CGContextSetRGBFillColor   (cgc, rgba[0], rgba[1], rgba[2], rgba[3]);
-    else
-      CGContextSetRGBStrokeColor (cgc, rgba[0], rgba[1], rgba[2], rgba[3]);
-  }
-}
-
-static void
-set_line_mode (CGContextRef cgc, XGCValues *gcv)
-{
-  CGContextSetLineWidth (cgc, gcv->line_width ? gcv->line_width : 1);
-  CGContextSetLineJoin  (cgc,
-                         gcv->join_style == JoinMiter ? kCGLineJoinMiter :
-                         gcv->join_style == JoinRound ? kCGLineJoinRound :
-                         kCGLineJoinBevel);
-  CGContextSetLineCap   (cgc, 
-                         gcv->cap_style == CapNotLast ? kCGLineCapButt  :
-                         gcv->cap_style == CapButt    ? kCGLineCapButt  :
-                         gcv->cap_style == CapRound   ? kCGLineCapRound :
-                         kCGLineCapSquare);
-}
-
-static void
-set_clip_mask (Drawable d, GC gc)
-{
-  Assert (!!gc->gcv.clip_mask == !!gc->clip_mask, "GC clip mask mixup");
-
-  Pixmap p = gc->gcv.clip_mask;
-  if (!p) return;
-  Assert (p->type == PIXMAP, "not a pixmap");
-
-  CGRect wr = d->frame;
-  CGRect to;
-  to.origin.x    = wr.origin.x + gc->gcv.clip_x_origin;
-  to.origin.y    = wr.origin.y + wr.size.height - gc->gcv.clip_y_origin
-                    - p->frame.size.height;
-  to.size.width  = p->frame.size.width;
-  to.size.height = p->frame.size.height;
-
-  CGContextClipToMask (d->cgc, to, gc->clip_mask);
-}
-
-
-/* Pushes a GC context; sets BlendMode and ClipMask.
- */
-static void
-push_gc (Drawable d, GC gc)
-{
-  CGContextRef cgc = d->cgc;
-  CGContextSaveGState (cgc);
-
-  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;
-  }
-
-  if (gc->gcv.clip_mask)
-    set_clip_mask (d, gc);
-}
-
-#define pop_gc(d,gc) CGContextRestoreGState (d->cgc)
-
-
-/* Pushes a GC context; sets BlendMode, ClipMask, Fill, and Stroke colors.
- */
-static void
-push_color_gc (Display *dpy, Drawable d, GC gc, unsigned long color,
-               BOOL antialias_p, Bool fill_p)
-{
-  push_gc (d, gc);
-
-  int 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;
-  }
-
-  CGContextRef cgc = d->cgc;
-  set_color (dpy, cgc, color, depth, gc->gcv.alpha_allowed_p, fill_p);
-  CGContextSetShouldAntialias (cgc, antialias_p);
-}
-
-
-/* Pushes a GC context; sets Fill and Stroke colors to the foreground color.
- */
-static void
-push_fg_gc (Display *dpy, Drawable d, GC gc, Bool fill_p)
-{
-  push_color_gc (dpy, d, gc, gc->gcv.foreground, gc->gcv.antialias_p, fill_p);
-}
-
-/* Pushes a GC context; sets Fill and Stroke colors to the background color.
- */
-static void
-push_bg_gc (Display *dpy, Drawable d, GC gc, Bool fill_p)
-{
-  push_color_gc (dpy, d, gc, gc->gcv.background, gc->gcv.antialias_p, fill_p);
-}
-
-static Bool
-bitmap_context_p (Drawable d)
-{
-# ifdef USE_BACKBUFFER
-  return True;
-# else
-  // Because of the backbuffer, all iPhone Windows work like Pixmaps.
-  return d->type == PIXMAP;
-# endif
-}
-
-
-
-/* You've got to be fucking kidding me!
-
-   It is *way* faster to draw points by creating and drawing a 1x1 CGImage
-   with repeated calls to CGContextDrawImage than it is to make a single
-   call to CGContextFillRects() with a list of 1x1 rectangles!
-
-   I still wouldn't call it *fast*, however...
- */
-#define XDRAWPOINTS_IMAGES
-
-/* Update, 2012: Kurt Revis <krevis@snoize.com> points out that diddling
-   the bitmap data directly is faster.  This only works on Pixmaps, though,
-   not Windows.  (Fortunately, on iOS, the Window is really a Pixmap.)
- */
-#define XDRAWPOINTS_CGDATA
-
-int
-XDrawPoints (Display *dpy, Drawable d, GC gc, 
-             XPoint *points, int count, int mode)
-{
-  int i;
-  CGRect wr = d->frame;
-
-# ifdef XDRAWPOINTS_CGDATA
-
-  if (bitmap_context_p (d))
-  {
-    CGContextRef cgc = d->cgc;
-    void *data = CGBitmapContextGetData (cgc);
-    size_t bpr = CGBitmapContextGetBytesPerRow (cgc);
-    size_t w = CGBitmapContextGetWidth (cgc);
-    size_t h = CGBitmapContextGetHeight (cgc);
-
-    Assert (data, "no bitmap data in Drawable");
-
-    unsigned long argb = gc->gcv.foreground;
-    validate_pixel (dpy, argb, gc->depth, gc->gcv.alpha_allowed_p);
-    if (gc->depth == 1)
-      argb = (gc->gcv.foreground ? WhitePixel(dpy,0) : BlackPixel(dpy,0));
-
-    CGFloat x0 = wr.origin.x;
-    CGFloat y0 = wr.origin.y; // Y axis is refreshingly not flipped.
-
-    // It's uglier, but faster, to hoist the conditional out of the loop.
-    if (mode == CoordModePrevious) {
-      CGFloat x = x0, y = y0;
-      for (i = 0; i < count; i++, points++) {
-        x += points->x;
-        y += points->y;
-
-        if (x >= 0 && x < w && y >= 0 && y < h) {
-          unsigned int *p = (unsigned int *)
-            ((char *) data + (size_t) y * bpr + (size_t) x * 4);
-          *p = (unsigned int) argb;
-        }
-      }
-    } else {
-      for (i = 0; i < count; i++, points++) {
-        CGFloat x = x0 + points->x;
-        CGFloat y = y0 + points->y;
-
-        if (x >= 0 && x < w && y >= 0 && y < h) {
-          unsigned int *p = (unsigned int *)
-            ((char *) data + (size_t) y * bpr + (size_t) x * 4);
-          *p = (unsigned int) argb;
-        }
-      }
-    }
-
-  } else       /* d->type == WINDOW */
-
-# endif /* XDRAWPOINTS_CGDATA */
-  {
-    push_fg_gc (dpy, d, gc, YES);
-
-# ifdef XDRAWPOINTS_IMAGES
-
-    unsigned int argb = gc->gcv.foreground;
-    validate_pixel (dpy, argb, gc->depth, gc->gcv.alpha_allowed_p);
-    if (gc->depth == 1)
-      argb = (gc->gcv.foreground ? WhitePixel(dpy,0) : BlackPixel(dpy,0));
-
-    CGDataProviderRef prov = CGDataProviderCreateWithData (NULL, &argb, 4,
-                                                           NULL);
-    CGImageRef cgi = CGImageCreate (1, 1,
-                                    8, 32, 4,
-                                    dpy->colorspace, 
-                                    /* Host-ordered, since we're using the
-                                       address of an int as the color data. */
-                                    dpy->screen->bitmap_info,
-                                    prov, 
-                                    NULL,  /* decode[] */
-                                    NO, /* interpolate */
-                                    kCGRenderingIntentDefault);
-    CGDataProviderRelease (prov);
-
-    CGContextRef cgc = d->cgc;
-    CGRect rect;
-    rect.size.width = rect.size.height = 1;
-    for (i = 0; i < count; i++) {
-      if (i > 0 && mode == CoordModePrevious) {
-        rect.origin.x += points->x;
-        rect.origin.x -= points->y;
-      } else {
-        rect.origin.x = wr.origin.x + points->x;
-        rect.origin.y = wr.origin.y + wr.size.height - points->y - 1;
-      }
-
-      //Assert(CGImageGetColorSpace (cgi) == dpy->colorspace,"bad colorspace");
-      CGContextDrawImage (cgc, rect, cgi);
-      points++;
-    }
-
-    CGImageRelease (cgi);
-
-# else /* ! XDRAWPOINTS_IMAGES */
-
-    CGRect *rects = (CGRect *) malloc (count * sizeof(CGRect));
-    CGRect *r = rects;
-  
-    for (i = 0; i < count; i++) {
-      r->size.width = r->size.height = 1;
-      if (i > 0 && mode == CoordModePrevious) {
-        r->origin.x = r[-1].origin.x + points->x;
-        r->origin.y = r[-1].origin.x - points->y;
-      } else {
-        r->origin.x = wr.origin.x + points->x;
-        r->origin.y = wr.origin.y + wr.size.height - points->y;
-      }
-      points++;
-      r++;
-    }
-
-    CGContextFillRects (d->cgc, rects, count);
-    free (rects);
-
-# endif /* ! XDRAWPOINTS_IMAGES */
-
-    pop_gc (d, gc);
-  }
-
-  invalidate_drawable_cache (d);
-
-  return 0;
-}
-
-
-int
-XDrawPoint (Display *dpy, Drawable d, GC gc, int x, int y)
-{
-  XPoint p;
-  p.x = x;
-  p.y = y;
-  return XDrawPoints (dpy, d, gc, &p, 1, CoordModeOrigin);
-}
-
-
-static void draw_rects (Display *dpy, Drawable d, GC gc,
-                        const XRectangle *rectangles, unsigned nrectangles,
-                        unsigned long pixel, BOOL fill_p);
-
-static void draw_rect (Display *, Drawable, GC, 
-                       int x, int y, unsigned int width, unsigned int height, 
-                       unsigned long pixel, BOOL fill_p);
-
-static void *
-seek_xy (void *dst, size_t dst_pitch, unsigned x, unsigned y)
-{
-  return (char *)dst + dst_pitch * y + x * 4;
-}
-
-static unsigned int
-drawable_depth (Drawable d)
-{
-  return (d->type == WINDOW
-          ? visual_depth (NULL, NULL)
-          : d->pixmap.depth);
-}
-
-
-int
-XCopyArea (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)
-{
-  Assert (gc, "no GC");
-  Assert ((width  < 65535), "improbably large width");
-  Assert ((height < 65535), "improbably large height");
-  Assert ((src_x  < 65535 && src_x  > -65535), "improbably large src_x");
-  Assert ((src_y  < 65535 && src_y  > -65535), "improbably large src_y");
-  Assert ((dst_x  < 65535 && dst_x  > -65535), "improbably large dst_x");
-  Assert ((dst_y  < 65535 && dst_y  > -65535), "improbably large dst_y");
-
-  if (width == 0 || height == 0)
-    return 0;
-
-  if (gc->gcv.function == GXset ||
-      gc->gcv.function == GXclear) {
-    // "set" and "clear" are dumb drawing modes that ignore the source
-    // bits and just draw solid rectangles.
-    draw_rect (dpy, dst, 0, dst_x, dst_y, width, height,
-               (gc->gcv.function == GXset
-                ? (gc->depth == 1 ? 1 : WhitePixel(dpy,0))
-                : (gc->depth == 1 ? 0 : BlackPixel(dpy,0))), YES);
-    return 0;
-  }
-
-  CGRect src_frame, dst_frame;   // Sizes and origins of the two drawables
-  CGRect src_rect,  dst_rect;    // The two rects to draw, clipped to the
-                                 //  bounds of their drawables.
-  BOOL clipped = NO;             // Whether we did any clipping of the rects.
-
-  src_frame = src->frame;
-  dst_frame = dst->frame;
-  
-  // Initialize src_rect...
-  //
-  src_rect.origin.x    = src_frame.origin.x + src_x;
-  src_rect.origin.y    = src_frame.origin.y + src_frame.size.height
-                          - height - src_y;
-  if (src_rect.origin.y < -65535) Assert(0, "src.origin.y went nuts");
-  src_rect.size.width  = width;
-  src_rect.size.height = height;
-  
-  // Initialize dst_rect...
-  //
-  dst_rect.origin.x    = dst_frame.origin.x + dst_x;
-  dst_rect.origin.y    = dst_frame.origin.y + dst_frame.size.height
-                          - height - dst_y;
-  if (dst_rect.origin.y < -65535) Assert(0, "dst.origin.y went nuts");
-  dst_rect.size.width  = width;
-  dst_rect.size.height = height;
-  
-  // Clip rects to frames...
-  //
-
-# define CLIP(THIS,THAT,VAL,SIZE) do { \
-  float off = THIS##_rect.origin.VAL; \
-  if (off < 0) { \
-    clipped = YES; \
-    THIS##_rect.size.SIZE  += off; \
-    THAT##_rect.size.SIZE  += off; \
-    THIS##_rect.origin.VAL -= off; \
-    THAT##_rect.origin.VAL -= off; \
-  } \
-  off = (( THIS##_rect.origin.VAL +  THIS##_rect.size.SIZE) - \
-         (THIS##_frame.origin.VAL + THIS##_frame.size.SIZE)); \
-  if (off > 0) { \
-    clipped = YES; \
-    THIS##_rect.size.SIZE  -= off; \
-    THAT##_rect.size.SIZE  -= off; \
-  }} while(0)
-
-  CLIP (dst, src, x, width);
-  CLIP (dst, src, y, height);
-
-  // Not actually the original dst_rect, just the one before it's clipped to
-  // the src_frame.
-  CGRect orig_dst_rect = dst_rect;
-
-  CLIP (src, dst, x, width);
-  CLIP (src, dst, y, height);
-# undef CLIP
-
-  if (orig_dst_rect.size.width <= 0 || orig_dst_rect.size.height <= 0)
-    return 0;
-
-  // Sort-of-special case where no pixels can be grabbed from the source,
-  // and the whole destination is filled with the background color.
-  if (src_rect.size.width < 0 || src_rect.size.height < 0) {
-    
-    Assert((int)src_rect.size.width  == (int)dst_rect.size.width ||
-           (int)src_rect.size.height == (int)dst_rect.size.height,
-           "size mismatch");
-    
-    src_rect.size.width  = 0;
-    src_rect.size.height = 0;
-    dst_rect.size.width  = 0;
-    dst_rect.size.height = 0;
-  }
-  
-  BOOL mask_p = src->type == PIXMAP && src->pixmap.depth == 1;
-
-
-  /* If we're copying from a bitmap to a bitmap, and there's nothing funny
-     going on with clipping masks or depths or anything, optimize it by
-     just doing a memcpy instead of going through a CGI.
-   */
-  if (bitmap_context_p (src) &&
-      bitmap_context_p (dst) &&
-      gc->gcv.function == GXcopy &&
-      !gc->gcv.clip_mask &&
-      drawable_depth (src) == drawable_depth (dst)) {
-
-    Assert(!(int)src_frame.origin.x &&
-           !(int)src_frame.origin.y &&
-           !(int)dst_frame.origin.x &&
-           !(int)dst_frame.origin.y,
-           "unexpected non-zero origin");
-
-    char *src_data = CGBitmapContextGetData(src->cgc);
-    char *dst_data = CGBitmapContextGetData(dst->cgc);
-    size_t src_pitch = CGBitmapContextGetBytesPerRow(src->cgc);
-    size_t dst_pitch = CGBitmapContextGetBytesPerRow(dst->cgc);
-
-    // Int to float and back again. It's not very safe, but it seems to work.
-    int src_x0 = src_rect.origin.x;
-    int dst_x0 = dst_rect.origin.x;
-
-    // Flip the Y-axis a second time.
-    int src_y0 = (src_frame.origin.y + src_frame.size.height -
-                  src_rect.size.height - src_rect.origin.y);
-    int dst_y0 = (dst_frame.origin.y + dst_frame.size.height -
-                  dst_rect.size.height - dst_rect.origin.y);
-
-    unsigned width0  = (int) src_rect.size.width;
-    unsigned height0 = (int) src_rect.size.height;
-
-    Assert((int)src_rect.size.width  == (int)dst_rect.size.width ||
-           (int)src_rect.size.height == (int)dst_rect.size.height,
-           "size mismatch");
-    {
-      char *src_data0 = seek_xy(src_data, src_pitch, src_x0, src_y0);
-      char *dst_data0 = seek_xy(dst_data, dst_pitch, dst_x0, dst_y0);
-      size_t src_pitch0 = src_pitch;
-      size_t dst_pitch0 = dst_pitch;
-      size_t bytes = width0 * 4;
-
-      if (src == dst && dst_y0 > src_y0) {
-        // Copy upwards if the areas might overlap.
-        src_data0 += src_pitch0 * (height0 - 1);
-        dst_data0 += dst_pitch0 * (height0 - 1);
-        src_pitch0 = -src_pitch0;
-        dst_pitch0 = -dst_pitch0;
-      }
-
-      size_t lines0 = height0;
-      while (lines0) {
-        // memcpy is an alias for memmove on OS X.
-        memmove(dst_data0, src_data0, bytes);
-        src_data0 += src_pitch0;
-        dst_data0 += dst_pitch0;
-        --lines0;
-      }
-    }
-# ifndef USE_BACKBUFFER
-  } else if (src->type == WINDOW && src == dst && !mask_p) {
-
-    // If we are copying from a window to itself, we can use NSCopyBits()
-    // without first copying the rectangle to an intermediary CGImage.
-    // This is ~28% faster (but I *expected* it to be twice as fast...)
-    // (kumppa, bsod, decayscreen, memscroller, slidescreen, slip, xjack)
-    //
-
-    push_gc (dst, gc);
-
-    NSRect nsfrom;
-    nsfrom.origin.x    = src_rect.origin.x;    // NSRect != CGRect on 10.4
-    nsfrom.origin.y    = src_rect.origin.y;
-    nsfrom.size.width  = src_rect.size.width;
-    nsfrom.size.height = src_rect.size.height;
-    NSPoint nsto;
-    nsto.x             = dst_rect.origin.x;
-    nsto.y             = dst_rect.origin.y;
-    NSCopyBits (0, nsfrom, nsto);
-
-    pop_gc (dst, gc);
-
-# endif
-  } else {
-
-    NSObject *releaseme = 0;
-    CGImageRef cgi;
-    BOOL free_cgi_p = NO;
-
-    if (bitmap_context_p (src)) {
-
-      // If we are copying from a Pixmap to a Pixmap or Window, we must first
-      // copy the bits to an intermediary CGImage object, then copy that to the
-      // destination drawable's CGContext.
-      //
-      // (It doesn't seem to be possible to use NSCopyBits() to optimize the
-      // case of copying from a Pixmap back to itself, but I don't think that
-      // happens very often anyway.)
-      //
-      // First we get a CGImage out of the pixmap CGContext -- it's the whole
-      // pixmap, but it presumably shares the data pointer instead of copying
-      // it.  We then cache that CGImage it inside the Pixmap object.  Note:
-      // invalidate_drawable_cache() must be called to discard this any time a
-      // modification is made to the pixmap, or we'll end up re-using old bits.
-      //
-      if (!src->cgi)
-        src->cgi = CGBitmapContextCreateImage (src->cgc);
-      cgi = src->cgi;
-
-      // if doing a sub-rect, trim it down.
-      if (src_rect.origin.x    != src_frame.origin.x   ||
-          src_rect.origin.y    != src_frame.origin.y   ||
-          src_rect.size.width  != src_frame.size.width ||
-          src_rect.size.height != src_frame.size.height) {
-        // #### I don't understand why this is needed...
-        src_rect.origin.y = (src_frame.size.height -
-                             src_rect.size.height - src_rect.origin.y);
-        // This does not copy image data, so it should be fast.
-        cgi = CGImageCreateWithImageInRect (cgi, src_rect);
-        free_cgi_p = YES;
-      }
-
-# ifndef USE_BACKBUFFER
-    } else { /* (src->type == WINDOW) */
-
-      NSRect nsfrom;    // NSRect != CGRect on 10.4
-      nsfrom.origin.x    = src_rect.origin.x;
-      nsfrom.origin.y    = src_rect.origin.y;
-      nsfrom.size.width  = src_rect.size.width;
-      nsfrom.size.height = src_rect.size.height;
-
-      // If we are copying from a Window to a Pixmap, we must first copy
-      // the bits to an intermediary CGImage object, then copy that to the
-      // Pixmap's CGContext.
-      //
-      NSBitmapImageRep *bm = [[NSBitmapImageRep alloc]
-                               initWithFocusedViewRect:nsfrom];
-      unsigned char *data = [bm bitmapData];
-      int bps = [bm bitsPerSample];
-      int bpp = [bm bitsPerPixel];
-      int bpl = [bm bytesPerRow];
-      releaseme = bm;
-
-      // create a CGImage from those bits.
-      // (As of 10.5, we could just do cgi = [bm CGImage] (it is autoreleased)
-      // but that method didn't exist in 10.4.)
-
-      CGDataProviderRef prov =
-        CGDataProviderCreateWithData (NULL, data, bpl * nsfrom.size.height,
-                                      NULL);
-      cgi = CGImageCreate (src_rect.size.width, src_rect.size.height,
-                           bps, bpp, bpl,
-                           dpy->colorspace,
-                           /* Use whatever default bit ordering we got from
-                              initWithFocusedViewRect.  I would have assumed
-                              that it was (kCGImageAlphaNoneSkipFirst |
-                              kCGBitmapByteOrder32Host), but on Intel,
-                              it's not!
-                           */
-                           0,
-                           prov,
-                           NULL,  /* decode[] */
-                           NO, /* interpolate */
-                           kCGRenderingIntentDefault);
-      free_cgi_p = YES;
-      //Assert(CGImageGetColorSpace(cgi) == dpy->colorspace,"bad colorspace");
-      CGDataProviderRelease (prov);
-
-# endif // !USE_BACKBUFFER
-    }
-
-    CGContextRef cgc = dst->cgc;
-
-    if (mask_p) {              // src depth == 1
-
-      push_bg_gc (dpy, dst, gc, YES);
-
-      // fill the destination rectangle with solid background...
-      CGContextFillRect (cgc, dst_rect);
-
-      Assert (cgc, "no CGC with 1-bit XCopyArea");
-
-      // 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, gc->gcv.foreground, gc->depth,
-                 gc->gcv.alpha_allowed_p, YES);
-      CGContextClipToMask (cgc, dst_rect, cgi);
-      CGContextFillRect (cgc, dst_rect);
-
-      pop_gc (dst, gc);
-
-    } else {           // src depth > 1
-
-      push_gc (dst, gc);
-
-      // copy the CGImage onto the destination CGContext
-      //Assert(CGImageGetColorSpace(cgi) == dpy->colorspace, "bad colorspace");
-      CGContextDrawImage (cgc, dst_rect, cgi);
-
-      pop_gc (dst, gc);
-    }
-
-    if (free_cgi_p) CGImageRelease (cgi);
-
-    if (releaseme) [releaseme release];
-  }
-
-  // If either the src or dst rects did not lie within their drawables, then
-  // we have adjusted both the src and dst rects to account for the clipping;
-  // that means we need to clear to the background, so that clipped bits end
-  // up in the bg color instead of simply not being copied.
-  //
-  // This has to happen after the copy, because if it happens before, the
-  // cleared area will get grabbed if it overlaps with the source rectangle.
-  //
-  if (clipped && dst->type == WINDOW) {
-    // Int to float and back again. It's not very safe, but it seems to work.
-    int dst_x0 = dst_rect.origin.x;
-
-    // Flip the Y-axis a second time.
-    int dst_y0 = (dst_frame.origin.y + dst_frame.size.height -
-                  dst_rect.size.height - dst_rect.origin.y);
-
-    unsigned width0  = (int) src_rect.size.width;
-    unsigned height0 = (int) src_rect.size.height;
-
-    int orig_dst_x = orig_dst_rect.origin.x;
-    int orig_dst_y = (dst_frame.origin.y + dst_frame.size.height -
-                      orig_dst_rect.origin.y - orig_dst_rect.size.height);
-    int orig_width  = orig_dst_rect.size.width;
-    int orig_height = orig_dst_rect.size.height;
-
-    Assert (orig_dst_x >= 0 &&
-            orig_dst_x + orig_width  <= (int) dst_frame.size.width &&
-            orig_dst_y >= 0 &&
-            orig_dst_y + orig_height <= (int) dst_frame.size.height,
-            "wrong dimensions");
-
-    XRectangle rects[4];
-    XRectangle *rects_end = rects;
-
-    if (orig_dst_y < dst_y0) {
-      rects_end->x = orig_dst_x;
-      rects_end->y = orig_dst_y;
-      rects_end->width = orig_width;
-      rects_end->height = dst_y0 - orig_dst_y;
-      ++rects_end;
-    }
-
-    if (orig_dst_y + orig_height > dst_y0 + height0) {
-      rects_end->x = orig_dst_x;
-      rects_end->y = dst_y0 + height0;
-      rects_end->width = orig_width;
-      rects_end->height = orig_dst_y + orig_height - dst_y0 - height0;
-      ++rects_end;
-    }
-
-    if (orig_dst_x < dst_x0) {
-      rects_end->x = orig_dst_x;
-      rects_end->y = dst_y0;
-      rects_end->width = dst_x0 - orig_dst_x;
-      rects_end->height = height0;
-      ++rects_end;
-    }
-
-    if (dst_x0 + width0 < orig_dst_x + orig_width) {
-      rects_end->x = dst_x0 + width0;
-      rects_end->y = dst_y0;
-      rects_end->width = orig_dst_x + orig_width - dst_x0 - width0;
-      rects_end->height = height0;
-      ++rects_end;
-    }
-
-    unsigned long old_function = gc->gcv.function;
-    gc->gcv.function = GXcopy;
-    draw_rects (dpy, dst, gc, rects, rects_end - rects,
-                dst->window.background,
-                YES);
-    gc->gcv.function = old_function;
-  }
-
-  invalidate_drawable_cache (dst);
-  return 0;
-}
-
-
-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 ((gc->depth == 1 || plane == 1), "hairy plane mask!");
-  
-  // This isn't right: XCopyPlane() is supposed to map 1/0 to fg/bg,
-  // not to white/black.
-  return XCopyArea (dpy, src, dest, gc,
-                    src_x, src_y, width, height, dest_x, dest_y);
-}
-
-
-static CGPoint
-map_point (Drawable d, int x, int y)
-{
-  const CGRect *wr = &d->frame;
-  CGPoint p;
-  p.x = wr->origin.x + x;
-  p.y = wr->origin.y + wr->size.height - y;
-  return p;
-}
-
-
-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;
-  }
-}
-
-
-static CGPoint
-point_for_line (Drawable d, GC gc, int x, int y)
-{
-  CGPoint result = map_point (d, x, y);
-  adjust_point_for_line (gc, &result);
-  return result;
-}
-
-
-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,
-            int mode)
-{
-  int i;
-  CGPoint p;
-  push_fg_gc (dpy, d, gc, NO);
-
-  CGContextRef cgc = d->cgc;
-
-  set_line_mode (cgc, &gc->gcv);
-  
-  // if the first and last points coincide, use closepath to get
-  // the proper line-joining.
-  BOOL closed_p = (points[0].x == points[count-1].x &&
-                   points[0].y == points[count-1].y);
-  if (closed_p) count--;
-  
-  p = point_for_line(d, gc, points->x, points->y);
-  points++;
-  CGContextBeginPath (cgc);
-  CGContextMoveToPoint (cgc, p.x, p.y);
-  for (i = 1; i < count; i++) {
-    if (mode == CoordModePrevious) {
-      p.x += points->x;
-      p.y -= points->y;
-    } else {
-      p = point_for_line(d, gc, points->x, points->y);
-    }
-    CGContextAddLineToPoint (cgc, p.x, p.y);
-    points++;
-  }
-  if (closed_p) CGContextClosePath (cgc);
-  CGContextStrokePath (cgc);
-  pop_gc (d, gc);
-  invalidate_drawable_cache (d);
-  return 0;
-}
-
-
-int
-XDrawSegments (Display *dpy, Drawable d, GC gc, XSegment *segments, int count)
-{
-  int i;
-
-  CGContextRef cgc = d->cgc;
-
-  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++;
-  }
-  CGContextStrokePath (cgc);
-  pop_gc (d, gc);
-  invalidate_drawable_cache (d);
-  return 0;
-}
-
-
-int
-XClearWindow (Display *dpy, Window win)
-{
-  Assert (win && win->type == WINDOW, "not a window");
-  CGRect wr = win->frame;
-  return XClearArea (dpy, win, 0, 0, wr.size.width, wr.size.height, 0);
-}
-
-int
-XSetWindowBackground (Display *dpy, Window w, unsigned long pixel)
-{
-  Assert (w && w->type == WINDOW, "not a window");
-  validate_pixel (dpy, pixel, 32, NO);
-  w->window.background = pixel;
-  return 0;
-}
-
-static void
-draw_rects (Display *dpy, Drawable d, GC gc,
-           const XRectangle *rectangles, unsigned nrectangles,
-           unsigned long pixel, BOOL fill_p)
-{
-  Assert (!gc || gc->depth == drawable_depth (d), "depth mismatch");
-
-  CGContextRef cgc = d->cgc;
-
-  Bool fast_fill_p =
-    fill_p &&
-    bitmap_context_p (d) &&
-    (!gc || (gc->gcv.function == GXcopy &&
-             !gc->gcv.alpha_allowed_p &&
-             !gc->gcv.clip_mask));
-
-  if (!fast_fill_p) {
-    if (gc) {
-      push_color_gc (dpy, d, gc, pixel, gc->gcv.antialias_p, fill_p);
-      if (!fill_p)
-        set_line_mode (cgc, &gc->gcv);
-    } else {
-      set_color (dpy, d->cgc, pixel, drawable_depth (d), NO, fill_p);
-    }
-  }
-
-  for (unsigned i = 0; i != nrectangles; ++i) {
-
-    int x = rectangles[i].x;
-    int y = rectangles[i].y;
-    int width = rectangles[i].width;
-    int height = rectangles[i].height;
-
-    if (fast_fill_p) {
-      int
-        dw = CGBitmapContextGetWidth (cgc),
-        dh = CGBitmapContextGetHeight (cgc);
-
-      if (x >= dw || y >= dh)
-        continue;
-
-      if (x < 0) {
-        width += x;
-        x = 0;
-      }
-
-      if (y < 0) {
-        height += y;
-        y = 0;
-      }
-
-      if (width <= 0 || height <= 0)
-        continue;
-
-      int max_width = dw - x;
-      if (width > max_width)
-        width = max_width;
-      int max_height = dh - y;
-      if (height > max_height)
-        height = max_height;
-
-      if (drawable_depth (d) == 1)
-        pixel = pixel ? WhitePixel(dpy, 0) : BlackPixel(dpy, 0);
-
-      size_t dst_bytes_per_row = CGBitmapContextGetBytesPerRow (d->cgc);
-      void *dst = seek_xy (CGBitmapContextGetData (d->cgc),
-                           dst_bytes_per_row, x, y);
-
-      Assert(sizeof(wchar_t) == 4, "somebody changed the ABI");
-      while (height) {
-        // Would be nice if Apple used SSE/NEON in wmemset. Maybe someday.
-        wmemset (dst, pixel, width);
-        --height;
-        dst = (char *) dst + dst_bytes_per_row;
-      }
-
-    } else {
-      CGRect r;
-      r.origin = map_point (d, x, y);
-      r.origin.y -= height;
-      r.size.width = width;
-      r.size.height = height;
-      if (fill_p)
-        CGContextFillRect (cgc, r);
-      else {
-        adjust_point_for_line (gc, &r.origin);
-        CGContextStrokeRect (cgc, r);
-      }
-    }
-  }
-
-  if (!fast_fill_p && gc)
-    pop_gc (d, gc);
-  invalidate_drawable_cache (d);
-}
-
-static void
-draw_rect (Display *dpy, Drawable d, GC gc,
-           int x, int y, unsigned int width, unsigned int height,
-           unsigned long pixel, BOOL fill_p)
-{
-  XRectangle r = {x, y, width, height};
-  draw_rects (dpy, d, gc, &r, 1, pixel, fill_p);
-}
-
-int
-XFillRectangle (Display *dpy, Drawable d, GC gc, int x, int y, 
-                unsigned int width, unsigned int height)
-{
-  draw_rect (dpy, d, gc, x, y, width, height, gc->gcv.foreground, YES);
-  return 0;
-}
-
-int
-XDrawRectangle (Display *dpy, Drawable d, GC gc, int x, int y, 
-                unsigned int width, unsigned int height)
-{
-  draw_rect (dpy, d, gc, x, y, width, height, gc->gcv.foreground, NO);
-  return 0;
-}
-
-int
-XFillRectangles (Display *dpy, Drawable d, GC gc, XRectangle *rects, int n)
-{
-  draw_rects (dpy, d, gc, rects, n, gc->gcv.foreground, YES);
-  return 0;
-}
-
-
-int
-XClearArea (Display *dpy, Window win, int x, int y, int w, int h, Bool exp)
-{
-  Assert (win && win->type == WINDOW, "not a window");
-  draw_rect (dpy, win, 0, x, y, w, h, win->window.background, YES);
-  return 0;
-}
-
-
-int
-XFillPolygon (Display *dpy, Drawable d, GC gc, 
-              XPoint *points, int npoints, int shape, int mode)
-{
-  CGRect wr = d->frame;
-  int i;
-  push_fg_gc (dpy, d, gc, YES);
-  CGContextRef cgc = d->cgc;
-  CGContextBeginPath (cgc);
-  float x = 0, y = 0;
-  for (i = 0; i < npoints; i++) {
-    if (i > 0 && mode == CoordModePrevious) {
-      x += points[i].x;
-      y -= points[i].y;
-    } else {
-      x = wr.origin.x + points[i].x;
-      y = wr.origin.y + wr.size.height - points[i].y;
-    }
-        
-    if (i == 0)
-      CGContextMoveToPoint (cgc, x, y);
-    else
-      CGContextAddLineToPoint (cgc, x, y);
-  }
-  CGContextClosePath (cgc);
-  if (gc->gcv.fill_rule == EvenOddRule)
-    CGContextEOFillPath (cgc);
-  else
-    CGContextFillPath (cgc);
-  pop_gc (d, gc);
-  invalidate_drawable_cache (d);
-  return 0;
-}
-
-#define radians(DEG) ((DEG) * M_PI / 180.0)
-#define degrees(RAD) ((RAD) * 180.0 / M_PI)
-
-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)
-{
-  CGRect wr = d->frame;
-  CGRect bound;
-  bound.origin.x = wr.origin.x + x;
-  bound.origin.y = wr.origin.y + wr.size.height - y - height;
-  bound.size.width = width;
-  bound.size.height = height;
-  
-  CGPoint ctr;
-  ctr.x = bound.origin.x + bound.size.width /2;
-  ctr.y = bound.origin.y + bound.size.height/2;
-  
-  float r1 = radians (angle1/64.0);
-  float r2 = radians (angle2/64.0) + r1;
-  BOOL clockwise = angle2 < 0;
-  BOOL closed_p = (angle2 >= 360*64 || angle2 <= -360*64);
-  
-  push_fg_gc (dpy, d, gc, fill_p);
-
-  CGContextRef cgc = d->cgc;
-  CGContextBeginPath (cgc);
-  
-  CGContextSaveGState(cgc);
-  CGContextTranslateCTM (cgc, ctr.x, ctr.y);
-  CGContextScaleCTM (cgc, width/2.0, height/2.0);
-  if (fill_p)
-    CGContextMoveToPoint (cgc, 0, 0);
-
-  CGContextAddArc (cgc, 0.0, 0.0, 1, r1, r2, clockwise);
-  CGContextRestoreGState (cgc);  // restore before stroke, for line width
-
-  if (closed_p)
-    CGContextClosePath (cgc); // for proper line joining
-  
-  if (fill_p) {
-    CGContextFillPath (cgc);
-  } else {
-    set_line_mode (cgc, &gc->gcv);
-    CGContextStrokePath (cgc);
-  }
-
-  pop_gc (d, gc);
-  invalidate_drawable_cache (d);
-  return 0;
-}
-
-int
-XDrawArc (Display *dpy, Drawable d, GC gc, int x, int y, 
-          unsigned int width, unsigned int height, int angle1, int angle2)
-{
-  return draw_arc (dpy, d, gc, x, y, width, height, angle1, angle2, NO);
-}
-
-int
-XFillArc (Display *dpy, Drawable d, GC gc, int x, int y, 
-          unsigned int width, unsigned int height, int angle1, int angle2)
-{
-  return draw_arc (dpy, d, gc, x, y, width, height, angle1, angle2, YES);
-}
-
-int
-XDrawArcs (Display *dpy, Drawable d, GC gc, XArc *arcs, int narcs)
-{
-  int i;
-  for (i = 0; i < narcs; i++)
-    draw_arc (dpy, d, gc, 
-              arcs[i].x, arcs[i].y, 
-              arcs[i].width, arcs[i].height, 
-              arcs[i].angle1, arcs[i].angle2,
-              NO);
-  return 0;
-}
-
-int
-XFillArcs (Display *dpy, Drawable d, GC gc, XArc *arcs, int narcs)
-{
-  int i;
-  for (i = 0; i < narcs; i++)
-    draw_arc (dpy, d, gc, 
-              arcs[i].x, arcs[i].y, 
-              arcs[i].width, arcs[i].height, 
-              arcs[i].angle1, arcs[i].angle2,
-              YES);
-  return 0;
-}
-
-
-static void
-gcv_defaults (Display *dpy, XGCValues *gcv, int depth)
-{
-  memset (gcv, 0, sizeof(*gcv));
-  gcv->function   = GXcopy;
-  gcv->foreground = (depth == 1 ? 1 : WhitePixel(dpy,0));
-  gcv->background = (depth == 1 ? 0 : BlackPixel(dpy,0));
-  gcv->line_width = 1;
-  gcv->cap_style  = CapNotLast;
-  gcv->join_style = JoinMiter;
-  gcv->fill_rule  = EvenOddRule;
-
-  gcv->alpha_allowed_p = NO;
-  gcv->antialias_p     = YES;
-}
-
-static void
-set_gcv (Display *dpy, GC gc, XGCValues *from, unsigned long mask)
-{
-  if (! mask) return;
-  Assert (gc && from, "no gc");
-  if (!gc || !from) return;
-
-  if (mask & GCFunction)       gc->gcv.function        = from->function;
-  if (mask & GCForeground)     gc->gcv.foreground      = from->foreground;
-  if (mask & GCBackground)     gc->gcv.background      = from->background;
-  if (mask & GCLineWidth)      gc->gcv.line_width      = from->line_width;
-  if (mask & GCCapStyle)       gc->gcv.cap_style       = from->cap_style;
-  if (mask & GCJoinStyle)      gc->gcv.join_style      = from->join_style;
-  if (mask & GCFillRule)       gc->gcv.fill_rule       = from->fill_rule;
-  if (mask & GCClipXOrigin)    gc->gcv.clip_x_origin   = from->clip_x_origin;
-  if (mask & GCClipYOrigin)    gc->gcv.clip_y_origin   = from->clip_y_origin;
-  if (mask & GCSubwindowMode)  gc->gcv.subwindow_mode  = from->subwindow_mode;
-  
-  if (mask & GCClipMask)       XSetClipMask (0, gc, from->clip_mask);
-  if (mask & GCFont)           XSetFont (0, gc, from->font);
-
-  if (mask & GCForeground) validate_pixel (dpy, from->foreground, gc->depth,
-                                           gc->gcv.alpha_allowed_p);
-  if (mask & GCBackground) validate_pixel (dpy, from->background, gc->depth,
-                                           gc->gcv.alpha_allowed_p);
-    
-  Assert ((! (mask & (GCLineStyle |
-                      GCPlaneMask |
-                      GCFillStyle |
-                      GCTile |
-                      GCStipple |
-                      GCTileStipXOrigin |
-                      GCTileStipYOrigin |
-                      GCGraphicsExposures |
-                      GCDashOffset |
-                      GCDashList |
-                      GCArcMode))),
-          "unimplemented gcvalues mask");
-}
-
-
-GC
-XCreateGC (Display *dpy, Drawable d, unsigned long mask, XGCValues *xgcv)
-{
-  struct jwxyz_GC *gc = (struct jwxyz_GC *) calloc (1, sizeof(*gc));
-  gc->depth = drawable_depth (d);
-
-  gcv_defaults (dpy, &gc->gcv, gc->depth);
-  set_gcv (dpy, gc, xgcv, mask);
-  return gc;
-}
-
-int
-XChangeGC (Display *dpy, GC gc, unsigned long mask, XGCValues *gcv)
-{
-  set_gcv (dpy, gc, gcv, mask);
-  return 0;
-}
-
-
-int
-XFreeGC (Display *dpy, GC gc)
-{
-  if (gc->gcv.font)
-    XUnloadFont (dpy, gc->gcv.font);
-
-  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);
-  }
-  free (gc);
-  return 0;
-}
-
-
-Status
-XGetWindowAttributes (Display *dpy, Window w, XWindowAttributes *xgwa)
-{
-  Assert (w && w->type == WINDOW, "not a window");
-  memset (xgwa, 0, sizeof(*xgwa));
-  xgwa->x      = w->frame.origin.x;
-  xgwa->y      = w->frame.origin.y;
-  xgwa->width  = w->frame.size.width;
-  xgwa->height = w->frame.size.height;
-  xgwa->depth  = 32;
-  xgwa->screen = dpy->screen;
-  xgwa->visual = dpy->screen->visual;
-  return 0;
-}
-
-Status
-XGetGeometry (Display *dpy, Drawable d, Window *root_ret,
-              int *x_ret, int *y_ret, 
-              unsigned int *w_ret, unsigned int *h_ret,
-              unsigned int *bw_ret, unsigned int *d_ret)
-{
-  *x_ret    = d->frame.origin.x;
-  *y_ret    = d->frame.origin.y;
-  *w_ret    = d->frame.size.width;
-  *h_ret    = d->frame.size.height;
-  *d_ret    = drawable_depth (d);
-  *root_ret = RootWindow (dpy, 0);
-  *bw_ret   = 0;
-  return True;
-}
-
-
-Status
-XAllocColor (Display *dpy, Colormap cmap, XColor *color)
-{
-  color->pixel = alloc_color (dpy,
-                              color->red, color->green, color->blue, 0xFFFF);
-  return 1;
-}
-
-Status
-XAllocColorCells (Display *dpy, Colormap cmap, Bool contig,
-                  unsigned long *pmret, unsigned int npl,
-                  unsigned long *pxret, unsigned int npx)
-{
-  return 0;
-}
-
-int
-XStoreColors (Display *dpy, Colormap cmap, XColor *colors, int n)
-{
-  Assert(0, "XStoreColors called");
-  return 0;
-}
-
-int
-XStoreColor (Display *dpy, Colormap cmap, XColor *c)
-{
-  Assert(0, "XStoreColor called");
-  return 0;
-}
-
-int
-XFreeColors (Display *dpy, Colormap cmap, unsigned long *px, int npixels,
-             unsigned long planes)
-{
-  return 0;
-}
-
-Status
-XParseColor (Display *dpy, Colormap cmap, const char *spec, XColor *ret)
-{
-  unsigned char r=0, g=0, b=0;
-  if (*spec == '#' && strlen(spec) == 7) {
-    static unsigned const char hex[] = {   // yeah yeah, shoot me.
-      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,
-      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,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,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};
-    r = (hex[spec[1]] << 4) | hex[spec[2]];
-    g = (hex[spec[3]] << 4) | hex[spec[4]];
-    b = (hex[spec[5]] << 4) | hex[spec[6]];
-  } else if (!strcasecmp(spec,"black")) {
-//  r = g = b = 0;
-  } else if (!strcasecmp(spec,"white")) {
-    r = g = b = 255;
-  } else if (!strcasecmp(spec,"red")) {
-    r = 255;
-  } else if (!strcasecmp(spec,"green")) {
-    g = 255;
-  } else if (!strcasecmp(spec,"blue")) {
-    b = 255;
-  } else if (!strcasecmp(spec,"cyan")) {
-    g = b = 255;
-  } else if (!strcasecmp(spec,"magenta")) {
-    r = b = 255;
-  } else if (!strcasecmp(spec,"yellow")) {
-    r = g = 255;
-  } else {
-    return 0;
-  }
-  
-  ret->red   = (r << 8) | r;
-  ret->green = (g << 8) | g;
-  ret->blue  = (b << 8) | b;
-  ret->flags = DoRed|DoGreen|DoBlue;
-  return 1;
-}
-
-Status
-XAllocNamedColor (Display *dpy, Colormap cmap, char *name,
-                  XColor *screen_ret, XColor *exact_ret)
-{
-  if (! XParseColor (dpy, cmap, name, screen_ret))
-    return False;
-  *exact_ret = *screen_ret;
-  return XAllocColor (dpy, cmap, screen_ret);
-}
-
-int
-XQueryColor (Display *dpy, Colormap cmap, XColor *color)
-{
-  validate_pixel (dpy, color->pixel, 32, NO);
-  uint8_t rgba[4];
-  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];
-  color->flags = DoRed|DoGreen|DoBlue;
-  return 0;
-}
-
-int
-XQueryColors (Display *dpy, Colormap cmap, XColor *c, int n)
-{
-  int i;
-  for (i = 0; i < n; i++)
-    XQueryColor (dpy, cmap, &c[i]);
-  return 0;
-}
-
-
-static unsigned long
-ximage_getpixel_1 (XImage *ximage, int x, int y)
-{
-  return ((ximage->data [y * ximage->bytes_per_line + (x>>3)] >> (x & 7)) & 1);
-}
-
-static int
-ximage_putpixel_1 (XImage *ximage, int x, int y, unsigned long pixel)
-{
-  if (pixel)
-    ximage->data [y * ximage->bytes_per_line + (x>>3)] |=  (1 << (x & 7));
-  else
-    ximage->data [y * ximage->bytes_per_line + (x>>3)] &= ~(1 << (x & 7));
-
-  return 0;
-}
-
-static unsigned long
-ximage_getpixel_32 (XImage *ximage, int x, int y)
-{
-  return ((unsigned long)
-          *((uint32_t *) ximage->data +
-            (y * (ximage->bytes_per_line >> 2)) +
-            x));
-}
-
-static int
-ximage_putpixel_32 (XImage *ximage, int x, int y, unsigned long pixel)
-{
-  *((uint32_t *) ximage->data +
-    (y * (ximage->bytes_per_line >> 2)) +
-    x) = (uint32_t) pixel;
-  return 0;
-}
-
-
-Status
-XInitImage (XImage *ximage)
-{
-  if (!ximage->bytes_per_line)
-    ximage->bytes_per_line = (ximage->depth == 1
-                              ? (ximage->width + 7) / 8
-                              : ximage->width * 4);
-
-  if (ximage->depth == 1) {
-    ximage->f.put_pixel = ximage_putpixel_1;
-    ximage->f.get_pixel = ximage_getpixel_1;
-  } else if (ximage->depth == 32 || ximage->depth == 24) {
-    ximage->f.put_pixel = ximage_putpixel_32;
-    ximage->f.get_pixel = ximage_getpixel_32;
-  } else {
-    Assert (0, "unknown depth");
-  }
-  return 1;
-}
-
-
-XImage *
-XCreateImage (Display *dpy, Visual *visual, unsigned int depth,
-              int format, int offset, char *data,
-              unsigned int width, unsigned int height,
-              int bitmap_pad, int bytes_per_line)
-{
-  XImage *ximage = (XImage *) calloc (1, sizeof(*ximage));
-  ximage->width = width;
-  ximage->height = height;
-  ximage->format = format;
-  ximage->data = data;
-  ximage->bitmap_unit = 8;
-  ximage->byte_order = LSBFirst;
-  ximage->bitmap_bit_order = ximage->byte_order;
-  ximage->bitmap_pad = bitmap_pad;
-  ximage->depth = depth;
-  ximage->red_mask   = (depth == 1 ? 0 : dpy->screen->visual->red_mask);
-  ximage->green_mask = (depth == 1 ? 0 : dpy->screen->visual->green_mask);
-  ximage->blue_mask  = (depth == 1 ? 0 : dpy->screen->visual->blue_mask);
-  ximage->bits_per_pixel = (depth == 1 ? 1 : 32);
-  ximage->bytes_per_line = bytes_per_line;
-
-  XInitImage (ximage);
-  return ximage;
-}
-
-XImage *
-XSubImage (XImage *from, int x, int y, unsigned int w, unsigned int h)
-{
-  XImage *to = (XImage *) malloc (sizeof(*to));
-  memcpy (to, from, sizeof(*from));
-  to->width = w;
-  to->height = h;
-  to->bytes_per_line = 0;
-  XInitImage (to);
-
-  to->data = (char *) malloc (h * to->bytes_per_line);
-
-  if (x >= from->width)
-    w = 0;
-  else if (x+w > from->width)
-    w = from->width - x;
-
-  if (y >= from->height)
-    h = 0;
-  else if (y+h > from->height)
-    h = from->height - y;
-
-  int tx, ty;
-  for (ty = 0; ty < h; ty++)
-    for (tx = 0; tx < w; tx++)
-      XPutPixel (to, tx, ty, XGetPixel (from, x+tx, y+ty));
-  return to;
-}
-
-
-XPixmapFormatValues *
-XListPixmapFormats (Display *dpy, int *n_ret)
-{
-  XPixmapFormatValues *ret = calloc (2, sizeof(*ret));
-  ret[0].depth = 32;
-  ret[0].bits_per_pixel = 32;
-  ret[0].scanline_pad = 8;
-  ret[1].depth = 1;
-  ret[1].bits_per_pixel = 1;
-  ret[1].scanline_pad = 8;
-  *n_ret = 2;
-  return ret;
-}
-
-
-unsigned long
-XGetPixel (XImage *ximage, int x, int y)
-{
-  return ximage->f.get_pixel (ximage, x, y);
-}
-
-
-int
-XPutPixel (XImage *ximage, int x, int y, unsigned long pixel)
-{
-  return ximage->f.put_pixel (ximage, x, y, pixel);
-}
-
-int
-XDestroyImage (XImage *ximage)
-{
-  if (ximage->data) free (ximage->data);
-  free (ximage);
-  return 0;
-}
-
-
-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)
-{
-  CGRect wr = d->frame;
-
-  Assert (gc, "no GC");
-  Assert ((w < 65535), "improbably large width");
-  Assert ((h < 65535), "improbably large height");
-  Assert ((src_x  < 65535 && src_x  > -65535), "improbably large src_x");
-  Assert ((src_y  < 65535 && src_y  > -65535), "improbably large src_y");
-  Assert ((dest_x < 65535 && dest_x > -65535), "improbably large dest_x");
-  Assert ((dest_y < 65535 && dest_y > -65535), "improbably large dest_y");
-
-  // Clip width and height to the bounds of the Drawable
-  //
-  if (dest_x + w > wr.size.width) {
-    if (dest_x > wr.size.width)
-      return 0;
-    w = wr.size.width - dest_x;
-  }
-  if (dest_y + h > wr.size.height) {
-    if (dest_y > wr.size.height)
-      return 0;
-    h = wr.size.height - dest_y;
-  }
-  if (w <= 0 || h <= 0)
-    return 0;
-
-  // Clip width and height to the bounds of the XImage
-  //
-  if (src_x + w > ximage->width) {
-    if (src_x > ximage->width)
-      return 0;
-    w = ximage->width - src_x;
-  }
-  if (src_y + h > ximage->height) {
-    if (src_y > ximage->height)
-      return 0;
-    h = ximage->height - src_y;
-  }
-  if (w <= 0 || h <= 0)
-    return 0;
-
-  CGContextRef cgc = d->cgc;
-
-  if (gc->gcv.function == GXset ||
-      gc->gcv.function == GXclear) {
-    // "set" and "clear" are dumb drawing modes that ignore the source
-    // bits and just draw solid rectangles.
-    draw_rect (dpy, d, 0, dest_x, dest_y, w, h,
-               (gc->gcv.function == GXset
-                ? (gc->depth == 1 ? 1 : WhitePixel(dpy,0))
-                : (gc->depth == 1 ? 0 : BlackPixel(dpy,0))), YES);
-    return 0;
-  }
-
-  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.origin.x + dest_x;
-  r.origin.y = wr.origin.y + wr.size.height - dest_y - h;
-  r.size.width = w;
-  r.size.height = h;
-
-  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);
-    CGDataProviderRef prov = 
-      CGDataProviderCreateWithData (NULL, data, bsize, NULL);
-
-    CGImageRef cgi = CGImageCreate (w, h,
-                                    bpp/4, bpp, bpl,
-                                    dpy->colorspace, 
-                                    dpy->screen->bitmap_info,
-                                    prov, 
-                                    NULL,  /* decode[] */
-                                    NO, /* interpolate */
-                                    kCGRenderingIntentDefault);
-    CGDataProviderRelease (prov);
-    //Assert (CGImageGetColorSpace (cgi) == dpy->colorspace, "bad colorspace");
-    CGContextDrawImage (cgc, r, cgi);
-    CGImageRelease (cgi);
-
-  } else {   // (bpp == 1)
-
-    /* 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[] */
-                                         NO); /* interpolate */
-    push_fg_gc (dpy, d, gc, YES);
-
-    CGContextFillRect (cgc, r);                                // foreground color
-    CGContextClipToMask (cgc, r, mask);
-    set_color (dpy, cgc, gc->gcv.background, gc->depth, NO, YES);
-    CGContextFillRect (cgc, r);                                // background color
-    pop_gc (d, gc);
-
-    free (flipped);
-    CGDataProviderRelease (prov);
-    CGImageRelease (mask);
-  }
-
-  invalidate_drawable_cache (d);
-
-  return 0;
-}
-
-
-XImage *
-XGetImage (Display *dpy, Drawable d, int x, int y,
-           unsigned int width, unsigned int height,
-           unsigned long plane_mask, int format)
-{
-  const unsigned char *data = 0;
-  size_t depth, ibpp, ibpl;
-  convert_mode_t mode;
-# ifndef USE_BACKBUFFER
-  NSBitmapImageRep *bm = 0;
-# endif
-  
-  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");
-
-  CGContextRef cgc = d->cgc;
-
-#ifndef USE_BACKBUFFER
-  // Because of the backbuffer, all iPhone Windows work like Pixmaps.
-  if (d->type == PIXMAP)
-# endif
-  {
-    depth = drawable_depth (d);
-    mode = convert_mode_to_rgba (dpy->screen->bitmap_info);
-    ibpp = CGBitmapContextGetBitsPerPixel (cgc);
-    ibpl = CGBitmapContextGetBytesPerRow (cgc);
-    data = CGBitmapContextGetData (cgc);
-    Assert (data, "CGBitmapContextGetData failed");
-
-# ifndef USE_BACKBUFFER
-  } else { /* (d->type == WINDOW) */
-
-    // get the bits (desired sub-rectangle) out of the NSView
-    NSRect nsfrom;
-    nsfrom.origin.x = x;
-//  nsfrom.origin.y = y;
-    nsfrom.origin.y = d->frame.size.height - height - y;
-    nsfrom.size.width = width;
-    nsfrom.size.height = height;
-    bm = [[NSBitmapImageRep alloc] initWithFocusedViewRect:nsfrom];
-    depth = 32;
-    mode = ([bm bitmapFormat] & NSAlphaFirstBitmapFormat) ? 3 : 0;
-    ibpp = [bm bitsPerPixel];
-    ibpl = [bm bytesPerRow];
-    data = [bm bitmapData];
-    Assert (data, "NSBitmapImageRep initWithFocusedViewRect failed");
-# endif // !USE_BACKBUFFER
-  }
-  
-  // data points at (x,y) with ibpl rowstride.  ignore x,y from now on.
-  data += (y * ibpl) + (x * (ibpp/8));
-  
-  format = (depth == 1 ? XYPixmap : ZPixmap);
-  XImage *image = XCreateImage (dpy, 0, (unsigned int) depth,
-                                format, 0, 0, width, height, 0, 0);
-  image->data = (char *) malloc (height * image->bytes_per_line);
-  
-  int obpl = image->bytes_per_line;
-  
-  /* both PPC and Intel use word-ordered ARGB frame buffers, which
-     means that on Intel it is BGRA when viewed by bytes (And BGR
-     when using 24bpp packing).
-
-     BUT! Intel-64 stores alpha at the other end! 32bit=RGBA, 64bit=ARGB.
-     The NSAlphaFirstBitmapFormat bit in bitmapFormat seems to be the
-     indicator of this latest kink.
-   */
-  int xx, yy;
-  if (depth == 1) {
-    const unsigned char *iline = data;
-    for (yy = 0; yy < height; yy++) {
-
-      const unsigned char *iline2 = iline;
-      for (xx = 0; xx < width; xx++) {
-
-        iline2++;                     // ignore R  or  A  or  A  or  B
-        iline2++;                     // ignore G  or  B  or  R  or  G
-        unsigned char r = *iline2++;  // use    B  or  G  or  G  or  R
-        if (ibpp == 32) iline2++;     // ignore A  or  R  or  B  or  A
-
-        XPutPixel (image, xx, yy, (r ? 1 : 0));
-      }
-      iline += ibpl;
-    }
-  } else {
-    const unsigned char *iline = data;
-    unsigned char *oline = (unsigned char *) image->data;
-
-    mode = convert_mode_merge (mode,
-             convert_mode_invert (
-               convert_mode_to_rgba (dpy->screen->bitmap_info)));
-
-    for (yy = 0; yy < height; yy++) {
-
-      convert_row ((uint32_t *)oline, iline, width, mode, ibpp);
-
-      oline += obpl;
-      iline += ibpl;
-    }
-  }
-
-# ifndef USE_BACKBUFFER
-  if (bm) [bm release];
-# endif
-
-  return image;
-}
-
-
-
-/* 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)
-{
-  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 {
-    draw_rect (dpy, d, 0, 0, 0, winr.size.width, winr.size.height,
-               drawable_depth (d) == 1 ? 0 : BlackPixel(dpy,0), YES);
-  }
-
-  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);
-}
-
-
-
-Pixmap
-XCreatePixmapFromBitmapData (Display *dpy, Drawable drawable,
-                             const char *data,
-                             unsigned int w, unsigned int h,
-                             unsigned long fg, unsigned int bg,
-                             unsigned int depth)
-{
-  Pixmap p = XCreatePixmap (dpy, drawable, w, h, depth);
-  XImage *image = XCreateImage (dpy, 0, 1, XYPixmap, 0, 
-                                (char *) data, w, h, 0, 0);
-  XGCValues gcv;
-  gcv.foreground = fg;
-  gcv.background = bg;
-  GC gc = XCreateGC (dpy, p, GCForeground|GCBackground, &gcv);
-  XPutImage (dpy, p, gc, image, 0, 0, 0, 0, w, h);
-  XFreeGC (dpy, gc);
-  image->data = 0;
-  XDestroyImage (image);
-  return p;
-}
-
-Pixmap
-XCreatePixmap (Display *dpy, Drawable d,
-               unsigned int width, unsigned int height, unsigned int depth)
-{
-  char *data = (char *) malloc (width * height * 4);
-  if (! data) return 0;
-
-  Pixmap p = (Pixmap) calloc (1, sizeof(*p));
-  p->type = PIXMAP;
-  p->frame.size.width  = width;
-  p->frame.size.height = height;
-  p->pixmap.depth      = depth;
-  p->pixmap.cgc_buffer = data;
-  
-  /* Quartz doesn't have a 1bpp image type.
-     Used to use 8bpp gray images instead of 1bpp, but some Mac video cards
-     don't support that!  So we always use 32bpp, regardless of depth. */
-
-  p->cgc = CGBitmapContextCreate (data, width, height,
-                                  8, /* bits per component */
-                                  width * 4, /* bpl */
-                                  dpy->colorspace,
-                                  dpy->screen->bitmap_info);
-  Assert (p->cgc, "could not create CGBitmapContext");
-  return p;
-}
-
-
-int
-XFreePixmap (Display *d, Pixmap p)
-{
-  Assert (p && p->type == PIXMAP, "not a pixmap");
-  invalidate_drawable_cache (p);
-  CGContextRelease (p->cgc);
-  if (p->pixmap.cgc_buffer)
-    free (p->pixmap.cgc_buffer);
-  free (p);
-  return 0;
-}
-
-
-static Pixmap
-copy_pixmap (Display *dpy, Pixmap p)
-{
-  if (!p) return 0;
-  Assert (p->type == PIXMAP, "not a pixmap");
-
-  Pixmap p2 = 0;
-
-  Window root;
-  int x, y;
-  unsigned int width, height, border_width, depth;
-  if (XGetGeometry (dpy, p, &root,
-                    &x, &y, &width, &height, &border_width, &depth)) {
-    XGCValues gcv;
-    gcv.function = GXcopy;
-    GC gc = XCreateGC (dpy, p, GCFunction, &gcv);
-    if (gc) {
-      p2 = XCreatePixmap (dpy, p, width, height, depth);
-      if (p2)
-        XCopyArea (dpy, p, p2, gc, 0, 0, width, height, 0, 0);
-      XFreeGC (dpy, gc);
-    }
-  }
-
-  Assert (p2, "could not copy pixmap");
-
-  return p2;
-}
-
-
-char *
-XGetAtomName (Display *dpy, Atom atom)
-{
-  if (atom == XA_FONT)
-    return strdup ("FONT");
-
-  // Note that atoms (that aren't predefined) are just char *.
-  return strdup ((char *) atom);
-}
-
-
-/* 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.
- */
-static void
-utf8_metrics (Font fid, NSString *nsstr, XCharStruct *cs)
-{
-  // Returns the metrics of the multi-character, single-line UTF8 string.
-
-  NSFont *nsfont = fid->nsfont;
-  Drawable d = XRootWindow (fid->dpy, 0);
-
-  CGContextRef cgc = d->cgc;
-  NSDictionary *attr =
-    [NSDictionary dictionaryWithObjectsAndKeys:
-                    nsfont, NSFontAttributeName,
-                  nil];
-  NSAttributedString *astr = [[NSAttributedString alloc]
-                               initWithString:nsstr
-                                   attributes:attr];
-  CTLineRef ctline = CTLineCreateWithAttributedString (
-                       (__bridge CFAttributedStringRef) astr);
-  CGContextSetTextPosition (cgc, 0, 0);
-  CGContextSetShouldAntialias (cgc, True);  // #### Guess?
-
-  memset (cs, 0, sizeof(*cs));
-
-  // "CTRun represents set of consecutive glyphs sharing the same
-  // attributes and direction".
-  //
-  // We also get multiple runs any time font subsitution happens:
-  // E.g., if the current font is Verdana-Bold, a &larr; character
-  // in the NSString will actually be rendered in LucidaGrande-Bold.
-  //
-  int count = 0;
-  for (id runid in (NSArray *)CTLineGetGlyphRuns(ctline)) {
-    CTRunRef run = (CTRunRef) runid;
-    CFRange r = { 0, };
-    CGRect bbox = CTRunGetImageBounds (run, cgc, r);
-    CGFloat ascent, descent, leading;
-    CGFloat advancement =
-      CTRunGetTypographicBounds (run, r, &ascent, &descent, &leading);
-
-# ifndef USE_IPHONE
-    // Only necessary for when LCD smoothing is enabled, which iOS doesn't do.
-    bbox.origin.x    -= 2.0/3.0;
-    bbox.size.width  += 4.0/3.0;
-    bbox.size.height += 1.0/2.0;
-# endif
-
-    // Create the metrics for this run:
-    XCharStruct cc;
-    cc.ascent   = ceil  (bbox.origin.y + bbox.size.height);
-    cc.descent  = ceil (-bbox.origin.y);
-    cc.lbearing = floor (bbox.origin.x);
-    cc.rbearing = ceil  (bbox.origin.x + bbox.size.width);
-    cc.width    = floor (advancement + 0.5);
-
-    // Add those metrics into the cumulative metrics:
-    if (count == 0)
-      *cs = cc;
-    else
-      {
-        cs->ascent   = MAX (cs->ascent,     cc.ascent);
-        cs->descent  = MAX (cs->descent,    cc.descent);
-        cs->lbearing = MIN (cs->lbearing,   cs->width + cc.lbearing);
-        cs->rbearing = MAX (cs->rbearing,   cs->width + cc.rbearing);
-        cs->width    = MAX (cs->width,      cs->width + cc.width);
-      }
-
-    // Why no y? What about vertical text?
-    // XCharStruct doesn't encapsulate that but XGlyphInfo does.
-
-    count++;
-  }
-
-  CFRelease (ctline);
-}
-
-
-
-// This is XQueryFont, but for the XFontStruct embedded in 'Font'
-//
-static void
-query_font (Font fid)
-{
-  if (!fid || !fid->nsfont) {
-    Assert (0, "no NSFont in fid");
-    return;
-  }
-  if (![fid->nsfont fontName]) {
-    Assert(0, @"broken NSFont in fid");
-    return;
-  }
-
-  int first = 32;
-  int last = 255;
-
-  XFontStruct *f = &fid->metrics;
-  XCharStruct *min = &f->min_bounds;
-  XCharStruct *max = &f->max_bounds;
-
-  f->fid               = fid;
-  f->min_char_or_byte2 = first;
-  f->max_char_or_byte2 = last;
-  f->default_char      = 'M';
-  f->ascent            =  ceil ([fid->nsfont ascender]);
-  f->descent           = -floor ([fid->nsfont descender]);
-
-  min->width    = 32767;  // set to smaller values in the loop
-  min->ascent   = 32767;
-  min->descent  = 32767;
-  min->lbearing = 32767;
-  min->rbearing = 32767;
-
-  f->per_char = (XCharStruct *) calloc (last-first+2, sizeof (XCharStruct));
-
-  for (int i = first; i <= last; i++) {
-    XCharStruct *cs = &f->per_char[i-first];
-
-    char s2[2];
-    s2[0] = i;
-    s2[1] = 0;
-    NSString *nsstr = [NSString stringWithCString:s2
-                               encoding:NSISOLatin1StringEncoding];
-    utf8_metrics (fid, nsstr, cs);
-
-    max->width    = MAX (max->width,    cs->width);
-    max->ascent   = MAX (max->ascent,   cs->ascent);
-    max->descent  = MAX (max->descent,  cs->descent);
-    max->lbearing = MAX (max->lbearing, cs->lbearing);
-    max->rbearing = MAX (max->rbearing, cs->rbearing);
-
-    min->width    = MIN (min->width,    cs->width);
-    min->ascent   = MIN (min->ascent,   cs->ascent);
-    min->descent  = MIN (min->descent,  cs->descent);
-    min->lbearing = MIN (min->lbearing, cs->lbearing);
-    min->rbearing = MIN (min->rbearing, cs->rbearing);
-
-# if 0
-    fprintf(stderr, " %3d %c: w=%3d lb=%3d rb=%3d as=%3d ds=%3d "
-                    " bb=%5.1f x %5.1f @ %5.1f %5.1f  adv=%5.1f %5.1f\n",
-            i, i, cs->width, cs->lbearing, cs->rbearing, 
-            cs->ascent, cs->descent,
-            bbox.size.width, bbox.size.height,
-            bbox.origin.x, bbox.origin.y,
-            advancement.width, advancement.height);
-# endif // 0
-  }
-}
-
-
-// Since 'Font' includes the metrics, this just makes a copy of that.
-//
-XFontStruct *
-XQueryFont (Display *dpy, Font fid)
-{
-  // copy XFontStruct
-  XFontStruct *f = (XFontStruct *) calloc (1, sizeof(*f));
-  *f = fid->metrics;
-
-  // build XFontProps
-  f->n_properties = 1;
-  f->properties = malloc (sizeof(*f->properties) * f->n_properties);
-  f->properties[0].name = XA_FONT;
-  Assert (sizeof (f->properties[0].card32) >= sizeof (char *),
-          "atoms probably needs a real implementation");
-  // If XInternAtom is ever implemented, use it here.
-  f->properties[0].card32 = (char *)fid->xa_font;
-
-  // copy XCharStruct array
-  int size = (f->max_char_or_byte2 - f->min_char_or_byte2) + 1;
-  f->per_char = (XCharStruct *) calloc (size + 2, sizeof (XCharStruct));
-  memcpy (f->per_char, fid->metrics.per_char,
-          size * sizeof (XCharStruct));
-
-  return f;
-}
-
-
-static Font
-copy_font (Font fid)
-{
-  // copy 'Font' struct
-  Font fid2 = (Font) malloc (sizeof(*fid2));
-  *fid2 = *fid;
-
-  // copy XCharStruct array
-  int size = fid->metrics.max_char_or_byte2 - fid->metrics.min_char_or_byte2;
-  fid2->metrics.per_char = (XCharStruct *) 
-    malloc ((size + 2) * sizeof (XCharStruct));
-  memcpy (fid2->metrics.per_char, fid->metrics.per_char, 
-          size * sizeof (XCharStruct));
-
-  // copy the other pointers
-  fid2->ps_name = strdup (fid->ps_name);
-  fid2->xa_font = strdup (fid->xa_font);
-//  [fid2->nsfont retain];
-  fid2->metrics.fid = fid2;
-
-  return fid2;
-}
-
-
-static NSArray *
-font_family_members (NSString *family_name)
-{
-# ifndef USE_IPHONE
-  return [[NSFontManager sharedFontManager]
-          availableMembersOfFontFamily:family_name];
-# else
-  return [UIFont fontNamesForFamilyName:family_name];
-# endif
-}
-
-
-static NSString *
-default_font_family (NSFontTraitMask require)
-{
-  return require & NSFixedPitchFontMask ? @"Courier" : @"Verdana";
-}
-
-
-static NSFont *
-try_font (NSFontTraitMask traits, NSFontTraitMask mask,
-          NSString *family_name, float size,
-          char **name_ret)
-{
-  Assert (size > 0, "zero font size");
-
-  NSArray *family_members = font_family_members (family_name);
-  if (!family_members.count)
-    family_members = font_family_members (default_font_family (traits));
-
-# ifndef USE_IPHONE
-  for (unsigned k = 0; k != family_members.count; ++k) {
-
-    NSArray *member = [family_members objectAtIndex:k];
-    NSFontTraitMask font_mask =
-    [(NSNumber *)[member objectAtIndex:3] unsignedIntValue];
-
-    if ((font_mask & mask) == traits) {
-
-      NSString *name = [member objectAtIndex:0];
-      NSFont *f = [NSFont fontWithName:name size:size];
-      if (!f)
-        break;
-
-      /* Don't use this font if it (probably) doesn't include ASCII characters.
-       */
-      NSStringEncoding enc = [f mostCompatibleStringEncoding];
-      if (! (enc == NSUTF8StringEncoding ||
-             enc == NSISOLatin1StringEncoding ||
-             enc == NSNonLossyASCIIStringEncoding ||
-             enc == NSISOLatin2StringEncoding ||
-             enc == NSUnicodeStringEncoding ||
-             enc == NSWindowsCP1250StringEncoding ||
-             enc == NSWindowsCP1252StringEncoding ||
-             enc == NSMacOSRomanStringEncoding)) {
-        // NSLog(@"skipping \"%@\": encoding = %d", name, enc);
-        break;
-      }
-      // NSLog(@"using \"%@\": %d", name, enc);
-
-      // *name_ret = strdup ([name cStringUsingEncoding:NSUTF8StringEncoding]);
-      *name_ret = strdup (name.UTF8String);
-      return f;
-    }
-  }
-# else // USE_IPHONE
-
-  for (NSString *fn in family_members) {
-# define MATCH(X) \
-         ([fn rangeOfString:X options:NSCaseInsensitiveSearch].location \
-         != NSNotFound)
-
-    // The magic invocation for getting font names is
-    // [[UIFontDescriptor
-    //   fontDescriptorWithFontAttributes:@{UIFontDescriptorNameAttribute: name}]
-    //  symbolicTraits]
-    // ...but this only works on iOS 7 and later.
-    NSFontTraitMask font_mask = 0;
-    if (MATCH(@"Bold"))
-      font_mask |= NSBoldFontMask;
-    if (MATCH(@"Italic") || MATCH(@"Oblique"))
-      font_mask |= NSItalicFontMask;
-
-    if ((font_mask & mask) == traits) {
-
-      /* Check if it can do ASCII.  No good way to accomplish this!
-         These are fonts present in iPhone Simulator as of June 2012
-         that don't include ASCII.
-       */
-      if (MATCH(@"AppleGothic") ||     // Korean
-          MATCH(@"Dingbats") ||                // Dingbats
-          MATCH(@"Emoji") ||           // Emoticons
-          MATCH(@"Geeza") ||           // Arabic
-          MATCH(@"Hebrew") ||          // Hebrew
-          MATCH(@"HiraKaku") ||                // Japanese
-          MATCH(@"HiraMin") ||         // Japanese
-          MATCH(@"Kailasa") ||         // Tibetan
-          MATCH(@"Ornaments") ||       // Dingbats
-          MATCH(@"STHeiti")            // Chinese
-       )
-         break;
-
-      *name_ret = strdup (fn.UTF8String);
-      return [UIFont fontWithName:fn size:size];
-    }
-# undef MATCH
-  }
-
-# endif
-
-  return NULL;
-}
-
-
-/* On Cocoa and iOS, fonts may be specified as "Georgia Bold 24" instead
-   of XLFD strings; also they can be comma-separated strings with multiple
-   font names.  First one that exists wins.
- */
-static NSFont *
-try_native_font (const char *name, float scale,
-                 char **name_ret, float *size_ret, char **xa_font)
-{
-  if (!name) return 0;
-  const char *spc = strrchr (name, ' ');
-  if (!spc) return 0;
-
-  NSFont *f = 0;
-  char *token = strdup (name);
-  char *name2;
-
-  while ((name2 = strtok (token, ","))) {
-    token = 0;
-
-    while (*name2 == ' ' || *name2 == '\t' || *name2 == '\n')
-      name2++;
-
-    spc = strrchr (name2, ' ');
-    if (!spc) continue;
-
-    int dsize = 0;
-    if (1 != sscanf (spc, " %d ", &dsize))
-      continue;
-    float size = dsize;
-
-    if (size <= 4) continue;
-
-    size *= scale;
-
-    name2[strlen(name2) - strlen(spc)] = 0;
-
-    NSString *nsname = [NSString stringWithCString:name2
-                                          encoding:NSUTF8StringEncoding];
-    f = [NSFont fontWithName:nsname size:size];
-    if (f) {
-      *name_ret = name2;
-      *size_ret = size;
-      *xa_font = strdup (name); // Maybe this should be an XLFD?
-      break;
-    } else {
-      NSLog(@"No native font: \"%@\" %.0f", nsname, size);
-    }
-  }
-
-  free (token);
-  return f;
-}
-
-
-/* Returns a random font in the given size and face.
- */
-static NSFont *
-random_font (NSFontTraitMask traits, NSFontTraitMask mask,
-             float size, NSString **family_ret, char **name_ret)
-{
-
-# ifndef USE_IPHONE
-  // Providing Unbold or Unitalic in the mask for availableFontNamesWithTraits
-  // returns an empty list, at least on a system with default fonts only.
-  NSArray *families = [[NSFontManager sharedFontManager]
-                       availableFontFamilies];
-  if (!families) return 0;
-# else
-  NSArray *families = [UIFont familyNames];
-
-  // There are many dups in the families array -- uniquify it.
-  {
-    NSArray *sorted_families =
-    [families sortedArrayUsingSelector:@selector(compare:)];
-    NSMutableArray *new_families =
-    [NSMutableArray arrayWithCapacity:sorted_families.count];
-
-    NSString *prev_family = nil;
-    for (NSString *family in sorted_families) {
-      if ([family compare:prev_family])
-        [new_families addObject:family];
-    }
-
-    families = new_families;
-  }
-# endif // USE_IPHONE
-
-  long n = [families count];
-  if (n <= 0) return 0;
-
-  int j;
-  for (j = 0; j < n; j++) {
-    int i = random() % n;
-    NSString *family_name = [families objectAtIndex:i];
-
-    NSFont *result = try_font (traits, mask, family_name, size, name_ret);
-    if (result) {
-      [*family_ret release];
-      *family_ret = family_name;
-      [*family_ret retain];
-      return result;
-    }
-  }
-
-  // None of the fonts support ASCII?
-  return 0;
-}
-
-
-// Fonts need this. XDisplayHeightMM and friends should probably be consistent
-// with this as well if they're ever implemented.
-static const unsigned dpi = 75;
-
-
-static const char *
-xlfd_field_end (const char *s)
-{
-  const char *s2 = strchr(s, '-');
-  if (!s2)
-    s2 = s + strlen(s);
-  return s2;
-}
-
-
-static size_t
-xlfd_next (const char **s, const char **s2)
-{
-  if (!**s2) {
-    *s = *s2;
-  } else {
-    Assert (**s2 == '-', "xlfd parse error");
-    *s = *s2 + 1;
-    *s2 = xlfd_field_end (*s);
-  }
-
-  return *s2 - *s;
-}
-
-
-static NSFont *
-try_xlfd_font (const char *name, float scale,
-               char **name_ret, float *size_ret, char **xa_font)
-{
-  NSFont *nsfont = 0;
-  NSString *family_name = nil;
-  NSFontTraitMask require = 0, forbid = 0;
-  BOOL rand  = NO;
-  float size = 0;
-  char *ps_name = 0;
-
-  const char *s = (name ? name : "");
-
-  size_t L = strlen (s);
-# define CMP(STR) (L == strlen(STR) && !strncasecmp (s, (STR), L))
-# define UNSPEC   (L == 0 || L == 1 && *s == '*')
-  if      (CMP ("6x10"))     size = 8,  require |= NSFixedPitchFontMask;
-  else if (CMP ("6x10bold")) size = 8,  require |= NSFixedPitchFontMask | NSBoldFontMask;
-  else if (CMP ("fixed"))    size = 12, require |= NSFixedPitchFontMask;
-  else if (CMP ("9x15"))     size = 12, require |= NSFixedPitchFontMask;
-  else if (CMP ("9x15bold")) size = 12, require |= NSFixedPitchFontMask | NSBoldFontMask;
-  else if (CMP ("vga"))      size = 12, require |= NSFixedPitchFontMask;
-  else if (CMP ("console"))  size = 12, require |= NSFixedPitchFontMask;
-  else if (CMP ("gallant"))  size = 12, require |= NSFixedPitchFontMask;
-  else {
-
-    // Incorrect fields are ignored.
-
-    if (*s == '-')
-      ++s;
-    const char *s2 = xlfd_field_end(s);
-
-    // Foundry (ignore)
-
-    L = xlfd_next (&s, &s2); // Family name
-    // This used to substitute Georgia for Times. Now it doesn't.
-    if (CMP ("random")) {
-      rand = YES;
-    } else if (CMP ("fixed")) {
-      require |= NSFixedPitchFontMask;
-      family_name = @"Courier";
-    } else if (!UNSPEC) {
-      family_name = [[[NSString alloc] initWithBytes:s
-                                              length:L
-                                            encoding:NSUTF8StringEncoding]
-                     autorelease];
-    }
-
-    L = xlfd_next (&s, &s2); // Weight name
-    if (CMP ("bold") || CMP ("demibold"))
-      require |= NSBoldFontMask;
-    else if (CMP ("medium") || CMP ("regular"))
-      forbid |= NSBoldFontMask;
-
-    L = xlfd_next (&s, &s2); // Slant
-    if (CMP ("i") || CMP ("o"))
-      require |= NSItalicFontMask;
-    else if (CMP ("r"))
-      forbid |= NSItalicFontMask;
-
-    xlfd_next (&s, &s2); // Set width name (ignore)
-    xlfd_next (&s, &s2); // Add style name (ignore)
-
-    xlfd_next (&s, &s2); // Pixel size (ignore)
-
-    xlfd_next (&s, &s2); // Point size
-    char *s3;
-    uintmax_t n = strtoumax(s, &s3, 10);
-    if (s2 == s3)
-      size = n / 10.0;
-
-    xlfd_next (&s, &s2); // Resolution X (ignore)
-    xlfd_next (&s, &s2); // Resolution Y (ignore)
-
-    xlfd_next (&s, &s2); // Spacing
-    if (CMP ("p"))
-      forbid |= NSFixedPitchFontMask;
-    else if (CMP ("m") || CMP ("c"))
-      require |= NSFixedPitchFontMask;
-
-    // Don't care about average_width or charset registry.
-  }
-# undef CMP
-# undef UNSPEC
-
-  if (!family_name && !rand)
-    family_name = default_font_family (require);
-
-  if (size < 6 || size > 1000)
-    size = 12;
-
-  size *= scale;
-
-  NSFontTraitMask mask = require | forbid;
-
-  if (rand) {
-    nsfont   = random_font (require, mask, size, &family_name, &ps_name);
-    [family_name autorelease];
-  }
-
-  if (!nsfont)
-    nsfont   = try_font (require, mask, family_name, size, &ps_name);
-
-  // if that didn't work, turn off attibutes until it does
-  // (e.g., there is no "Monaco-Bold".)
-  //
-  if (!nsfont && (mask & NSItalicFontMask)) {
-    require &= ~NSItalicFontMask;
-    mask &= ~NSItalicFontMask;
-    nsfont = try_font (require, mask, family_name, size, &ps_name);
-  }
-  if (!nsfont && (mask & NSBoldFontMask)) {
-    require &= ~NSBoldFontMask;
-    mask &= ~NSBoldFontMask;
-    nsfont = try_font (require, mask, family_name, size, &ps_name);
-  }
-  if (!nsfont && (mask & NSFixedPitchFontMask)) {
-    require &= ~NSFixedPitchFontMask;
-    mask &= ~NSFixedPitchFontMask;
-    nsfont = try_font (require, mask, family_name, size, &ps_name);
-  }
-
-  if (nsfont) {
-    *name_ret = ps_name;
-    *size_ret = size;
-    float actual_size = size / scale;
-    asprintf(xa_font, "-*-%s-%s-%c-*-*-%u-%u-%u-%u-%c-0-iso10646-1",
-             family_name.UTF8String,
-             (require & NSBoldFontMask) ? "bold" : "medium",
-             (require & NSItalicFontMask) ? 'o' : 'r',
-             (unsigned)(dpi * actual_size / 72.27 + 0.5),
-             (unsigned)(actual_size * 10 + 0.5), dpi, dpi,
-             (require & NSFixedPitchFontMask) ? 'm' : 'p');
-    return nsfont;
-  } else {
-    return 0;
-  }
-}
-
-
-Font
-XLoadFont (Display *dpy, const char *name)
-{
-  Font fid = (Font) calloc (1, sizeof(*fid));
-
-  float scale = 1;
-
-# ifdef USE_IPHONE
-  /* Since iOS screens are physically smaller than desktop screens, scale up
-     the fonts to make them more readable.
-
-     Note that X11 apps on iOS also have the backbuffer sized in points
-     instead of pixels, resulting in an effective X11 screen size of 768x1024
-     or so, even if the display has significantly higher resolution.  That is
-     unrelated to this hack, which is really about DPI.
-   */
-  scale = 2;
-# endif
-
-  fid->dpy = dpy;
-  fid->nsfont = try_native_font (name, scale, &fid->ps_name, &fid->size,
-                                 &fid->xa_font);
-
-  if (!fid->nsfont && name &&
-      strchr (name, ' ') &&
-      !strchr (name, '*')) {
-    // If name contains a space but no stars, it is a native font spec --
-    // return NULL so that we know it really didn't exist.  Else, it is an
-    //  XLFD font, so keep trying.
-    XUnloadFont (dpy, fid);
-    return 0;
-  }
-
-  if (! fid->nsfont)
-    fid->nsfont = try_xlfd_font (name, scale, &fid->ps_name, &fid->size,
-                                 &fid->xa_font);
-
-  // We should never return NULL for XLFD fonts.
-  if (!fid->nsfont) {
-    Assert (0, "no font");
-    return 0;
-  }
-  CFRetain (fid->nsfont);   // needed for garbage collection?
-
-  //NSLog(@"parsed \"%s\" to %s %.1f", name, fid->ps_name, fid->size);
-
-  query_font (fid);
-
-  return fid;
-}
-
-
-XFontStruct *
-XLoadQueryFont (Display *dpy, const char *name)
-{
-  Font fid = XLoadFont (dpy, name);
-  if (!fid) return 0;
-  return XQueryFont (dpy, fid);
-}
-
-int
-XUnloadFont (Display *dpy, Font fid)
-{
-  if (fid->ps_name)
-    free (fid->ps_name);
-  if (fid->metrics.per_char)
-    free (fid->metrics.per_char);
-
-  // #### DAMMIT!  I can't tell what's going wrong here, but I keep getting
-  //      crashes in [NSFont ascender] <- query_font, and it seems to go away
-  //      if I never release the nsfont.  So, fuck it, we'll just leak fonts.
-  //      They're probably not very big...
-  //
-  //  [fid->nsfont release];
-  //  CFRelease (fid->nsfont);
-
-  free (fid);
-  return 0;
-}
-
-int
-XFreeFontInfo (char **names, XFontStruct *info, int n)
-{
-  int i;
-  if (names) {
-    for (i = 0; i < n; i++)
-      if (names[i]) free (names[i]);
-    free (names);
-  }
-  if (info) {
-    for (i = 0; i < n; i++)
-      if (info[i].per_char) {
-        free (info[i].per_char);
-        free (info[i].properties);
-      }
-    free (info);
-  }
-  return 0;
-}
-
-int
-XFreeFont (Display *dpy, XFontStruct *f)
-{
-  Font fid = f->fid;
-  XFreeFontInfo (0, f, 1);
-  XUnloadFont (dpy, fid);
-  return 0;
-}
-
-
-int
-XSetFont (Display *dpy, GC gc, Font fid)
-{
-  if (gc->gcv.font)
-    XUnloadFont (dpy, gc->gcv.font);
-  gc->gcv.font = copy_font (fid);
-  [gc->gcv.font->nsfont retain];
-  CFRetain (gc->gcv.font->nsfont);   // needed for garbage collection?
-  return 0;
-}
-
-
-XFontSet
-XCreateFontSet (Display *dpy, char *name, 
-                char ***missing_charset_list_return,
-                int *missing_charset_count_return,
-                char **def_string_return)
-{
-  char *name2 = strdup (name);
-  char *s = strchr (name, ",");
-  if (s) *s = 0;
-  XFontSet set = 0;
-  XFontStruct *f = XLoadQueryFont (dpy, name2);
-  if (f)
-    {
-      set = (XFontSet) calloc (1, sizeof(*set));
-      set->font = f;
-    }
-  free (name2);
-  if (missing_charset_list_return)  *missing_charset_list_return = 0;
-  if (missing_charset_count_return) *missing_charset_count_return = 0;
-  if (def_string_return) *def_string_return = 0;
-  return set;
-}
-
-
-void
-XFreeFontSet (Display *dpy, XFontSet set)
-{
-  XFreeFont (dpy, set->font);
-  free (set);
-}
-
-
-const char *
-jwxyz_nativeFontName (Font f, float *size)
-{
-  if (size) *size = f->size;
-  return f->ps_name;
-}
-
-
-void
-XFreeStringList (char **list)
-{
-  int i;
-  if (!list) return;
-  for (i = 0; list[i]; i++)
-    XFree (list[i]);
-  XFree (list);
-}
-
-
-// Returns the verbose Unicode name of this character, like "agrave" or
-// "daggerdouble".  Used by fontglide debugMetrics.
-//
-char *
-jwxyz_unicode_character_name (Font fid, unsigned long uc)
-{
-  char *ret = 0;
-  CTFontRef ctfont =
-    CTFontCreateWithName ((CFStringRef) [fid->nsfont fontName],
-                          [fid->nsfont pointSize],
-                          NULL);
-  Assert (ctfont, @"no CTFontRef for UIFont");
-
-  CGGlyph cgglyph;
-  if (CTFontGetGlyphsForCharacters (ctfont, (UniChar *) &uc, &cgglyph, 1)) {
-    NSString *name = (NSString *)
-      CGFontCopyGlyphNameForGlyph (CTFontCopyGraphicsFont (ctfont, 0),
-                                   cgglyph);
-    ret = (name ? strdup ([name UTF8String]) : 0);
-  }
-
-  CFRelease (ctfont);
-  return ret;
-}
-
-
-// Given a UTF8 string, return an NSString.  Bogus UTF8 characters are ignored.
-// We have to do this because stringWithCString returns NULL if there are
-// any invalid characters at all.
-//
-static NSString *
-sanitize_utf8 (const char *in, int in_len, Bool *latin1_pP)
-{
-  int out_len = in_len * 4;   // length of string might increase
-  char *s2 = (char *) malloc (out_len);
-  char *out = s2;
-  const char *in_end  = in  + in_len;
-  const char *out_end = out + out_len;
-  Bool latin1_p = True;
-
-  while (in < in_end)
-    {
-      unsigned long uc;
-      long L1 = utf8_decode ((const unsigned char *) in, in_end - in, &uc);
-      long L2 = utf8_encode (uc, out, out_end - out);
-      in  += L1;
-      out += L2;
-      if (uc > 255) latin1_p = False;
-    }
-  *out = 0;
-  NSString *nsstr =
-    [NSString stringWithCString:s2 encoding:NSUTF8StringEncoding];
-  free (s2);
-  if (latin1_pP) *latin1_pP = latin1_p;
-  return (nsstr ? nsstr : @"");
-}
-
-
-int
-XTextExtents (XFontStruct *f, const char *s, int length,
-              int *dir_ret, int *ascent_ret, int *descent_ret,
-              XCharStruct *cs)
-{
-  // Unfortunately, adding XCharStructs together to get the extents for a
-  // string doesn't work: Cocoa uses non-integral character advancements, but
-  // XCharStruct.width is an integer. Plus that doesn't take into account
-  // kerning pairs, alternate glyphs, and fun stuff like the word "Zapfino" in
-  // Zapfino.
-
-  NSString *nsstr = [[[NSString alloc] initWithBytes:s
-                                              length:length
-                                            encoding:NSISOLatin1StringEncoding]
-                     autorelease];
-  utf8_metrics (f->fid, nsstr, cs);
-  *dir_ret = 0;
-  *ascent_ret  = f->ascent;
-  *descent_ret = f->descent;
-  return 0;
-}
-
-int
-XTextWidth (XFontStruct *f, const char *s, int length)
-{
-  int ascent, descent, dir;
-  XCharStruct cs;
-  XTextExtents (f, s, length, &dir, &ascent, &descent, &cs);
-  return cs.width;
-}
-
-
-int
-XTextExtents16 (XFontStruct *f, const XChar2b *s, int length,
-                int *dir_ret, int *ascent_ret, int *descent_ret,
-                XCharStruct *cs)
-{
-  Bool latin1_p = True;
-  int i, utf8_len = 0;
-  char *utf8 = XChar2b_to_utf8 (s, &utf8_len);   // already sanitized
-
-  for (i = 0; i < length; i++)
-    if (s[i].byte1 > 0) {
-      latin1_p = False;
-      break;
-    }
-
-  {
-    NSString *nsstr = [NSString stringWithCString:utf8
-                                encoding:NSUTF8StringEncoding];
-    utf8_metrics (f->fid, nsstr, cs);
-  }
-
-  *dir_ret = 0;
-  *ascent_ret  = f->ascent;
-  *descent_ret = f->descent;
-  free (utf8);
-  return 0;
-}
-
-
-/* "Returns the distance in pixels in the primary draw direction from
-   the drawing origin to the origin of the next character to be drawn."
-
-   "overall_ink_return is set to the bbox of the string's character ink."
-
-   "The overall_ink_return for a nondescending, horizontally drawn Latin
-   character is conventionally entirely above the baseline; that is,
-   overall_ink_return.height <= -overall_ink_return.y."
-
-     [So this means that y is the top of the ink, and height grows down:
-      For above-the-baseline characters, y is negative.]
-
-   "The overall_ink_return for a nonkerned character is entirely at, and to
-   the right of, the origin; that is, overall_ink_return.x >= 0."
-
-     [So this means that x is the left of the ink, and width grows right.
-      For left-of-the-origin characters, x is negative.]
-
-   "A character consisting of a single pixel at the origin would set
-   overall_ink_return fields y = 0, x = 0, width = 1, and height = 1."
- */
-int
-Xutf8TextExtents (XFontSet set, const char *str, int len,
-                  XRectangle *overall_ink_return,
-                  XRectangle *overall_logical_return)
-{
-  Bool latin1_p;
-  NSString *nsstr = sanitize_utf8 (str, len, &latin1_p);
-  XCharStruct cs;
-
-  utf8_metrics (set->font->fid, nsstr, &cs);
-
-  /* "The overall_logical_return is the bounding box that provides minimum
-     spacing to other graphical features for the string. Other graphical
-     features, for example, a border surrounding the text, should not
-     intersect this rectangle."
-
-     So I think that means they're the same?  Or maybe "ink" is the bounding
-     box, and "logical" is the advancement?  But then why is the return value
-     the advancement?
-   */
-  if (overall_ink_return)
-    XCharStruct_to_XmbRectangle (cs, *overall_ink_return);
-  if (overall_logical_return)
-    XCharStruct_to_XmbRectangle (cs, *overall_logical_return);
-
-  return cs.width;
-}
-
-
-static int
-draw_string (Display *dpy, Drawable d, GC gc, int x, int y,
-             NSString *nsstr)
-{
-  if (! nsstr) return 1;
-
-  CGRect wr = d->frame;
-  CGContextRef cgc = d->cgc;
-
-  unsigned long argb = gc->gcv.foreground;
-  if (gc->depth == 1) argb = (argb ? WhitePixel(dpy,0) : BlackPixel(dpy,0));
-  float rgba[4];
-  query_color_float (dpy, argb, rgba);
-  NSColor *fg = [NSColor colorWithDeviceRed:rgba[0]
-                                      green:rgba[1]
-                                       blue:rgba[2]
-                                      alpha:rgba[3]];
-
-  if (!gc->gcv.font) {
-    Assert (0, "no font");
-    return 1;
-  }
-
-  /* This crashes on iOS 5.1 because NSForegroundColorAttributeName,
-      NSFontAttributeName, and NSAttributedString are only present on iOS 6
-      and later.  We could resurrect the Quartz code from v5.29 and do a
-      runtime conditional on that, but that would be a pain in the ass.
-      Probably time to just make iOS 6 a requirement.
-   */
-
-  NSDictionary *attr =
-    [NSDictionary dictionaryWithObjectsAndKeys:
-                    gc->gcv.font->nsfont, NSFontAttributeName,
-                    fg, NSForegroundColorAttributeName,
-                  nil];
-
-  // Don't understand why we have to do both set_color and
-  // NSForegroundColorAttributeName, but we do.
-  //
-  set_color (dpy, cgc, argb, 32, NO, YES);
-
-  NSAttributedString *astr = [[NSAttributedString alloc]
-                               initWithString:nsstr
-                                   attributes:attr];
-  CTLineRef dl = CTLineCreateWithAttributedString (
-                   (__bridge CFAttributedStringRef) astr);
-
-  // Not sure why this is necessary, but xoff is positive when the first
-  // character on the line has a negative lbearing.  Without this, the
-  // string is rendered with the first ink at 0 instead of at lbearing.
-  // I have not seen xoff be negative, so I'm not sure if that can happen.
-  //
-  // Test case: "Combining Double Tilde" U+0360 (\315\240) followed by
-  // a letter.
-  //
-  CGFloat xoff = CTLineGetOffsetForStringIndex (dl, 0, NULL);
-  Assert (xoff >= 0, "unexpected CTLineOffset");
-  x -= xoff;
-
-  CGContextSetTextPosition (cgc,
-                            wr.origin.x + x,
-                            wr.origin.y + wr.size.height - y);
-  CGContextSetShouldAntialias (cgc, gc->gcv.antialias_p);
-
-  CTLineDraw (dl, cgc);
-  CFRelease (dl);
-
-  invalidate_drawable_cache (d);
-  return 0;
-}
-
-
-int
-XDrawString (Display *dpy, Drawable d, GC gc, int x, int y,
-             const char  *str, int len)
-{
-  char *s2 = (char *) malloc (len + 1);
-  strncpy (s2, str, len);
-  s2[len] = 0;
-  NSString *nsstr = [NSString stringWithCString:s2
-                                       encoding:NSISOLatin1StringEncoding];
-  int ret = draw_string (dpy, d, gc, x, y, nsstr);
-  free (s2);
-  return ret;
-}
-
-
-int
-XDrawString16 (Display *dpy, Drawable d, GC gc, int x, int y,
-             const XChar2b *str, int len)
-{
-  char *s2 = XChar2b_to_utf8 (str, 0);   // already sanitized
-  NSString *nsstr =
-    [NSString stringWithCString:s2 encoding:NSUTF8StringEncoding];
-  int ret = draw_string (dpy, d, gc, x, y, nsstr);
-  free (s2);
-  return ret;
-}
-
-
-void
-Xutf8DrawString (Display *dpy, Drawable d, XFontSet set, GC gc,
-                 int x, int y, const char *str, int len)
-{
-  char *s2 = (char *) malloc (len + 1);
-  strncpy (s2, str, len);
-  s2[len] = 0;
-  NSString *nsstr = sanitize_utf8 (str, len, 0);
-  draw_string (dpy, d, gc, x, y, nsstr);
-  free (s2);
-}
-
-
-int
-XDrawImageString (Display *dpy, Drawable d, GC gc, int x, int y,
-                  const char *str, int len)
-{
-  int ascent, descent, dir;
-  XCharStruct cs;
-  XTextExtents (&gc->gcv.font->metrics, str, len,
-                &dir, &ascent, &descent, &cs);
-  draw_rect (dpy, d, gc,
-             x + MIN (0, cs.lbearing),
-             y - MAX (0, ascent),
-             MAX (MAX (0, cs.rbearing) -
-                  MIN (0, cs.lbearing),
-                  cs.width),
-             MAX (0, ascent) + MAX (0, descent),
-             gc->gcv.background, YES);
-  return XDrawString (dpy, d, gc, x, y, str, len);
-}
-
-
-int
-XSetForeground (Display *dpy, GC gc, unsigned long fg)
-{
-  validate_pixel (dpy, fg, gc->depth, gc->gcv.alpha_allowed_p);
-  gc->gcv.foreground = fg;
-  return 0;
-}
-
-
-int
-XSetBackground (Display *dpy, GC gc, unsigned long bg)
-{
-  validate_pixel (dpy, bg, gc->depth, gc->gcv.alpha_allowed_p);
-  gc->gcv.background = bg;
-  return 0;
-}
-
-int
-jwxyz_XSetAlphaAllowed (Display *dpy, GC gc, Bool allowed)
-{
-  gc->gcv.alpha_allowed_p = allowed;
-  return 0;
-}
-
-int
-jwxyz_XSetAntiAliasing (Display *dpy, GC gc, Bool antialias_p)
-{
-  gc->gcv.antialias_p = antialias_p;
-  return 0;
-}
-
-
-int
-XSetLineAttributes (Display *dpy, GC gc, unsigned int line_width,
-                    int line_style, int cap_style, int join_style)
-{
-  gc->gcv.line_width = line_width;
-  Assert (line_style == LineSolid, "only LineSolid implemented");
-//  gc->gcv.line_style = line_style;
-  gc->gcv.cap_style = cap_style;
-  gc->gcv.join_style = join_style;
-  return 0;
-}
-
-int
-XSetGraphicsExposures (Display *dpy, GC gc, Bool which)
-{
-  return 0;
-}
-
-int
-XSetFunction (Display *dpy, GC gc, int which)
-{
-  gc->gcv.function = which;
-  return 0;
-}
-
-int
-XSetSubwindowMode (Display *dpy, GC gc, int which)
-{
-  gc->gcv.subwindow_mode = which;
-  return 0;
-}
-
-int
-XSetClipMask (Display *dpy, GC gc, Pixmap m)
-{
-  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)
-{
-  gc->gcv.clip_x_origin = x;
-  gc->gcv.clip_y_origin = y;
-  return 0;
-}
-
-
-static void
-get_pos (Window w, NSPoint *vpos, NSPoint *p)
-{
-# ifdef USE_IPHONE
-
-  vpos->x = 0;
-  vpos->y = 0;
-
-  if (p) {
-    p->x = w->window.last_mouse_x;
-    p->y = w->window.last_mouse_y;
-  }
-
-# else  // !USE_IPHONE
-
-  NSWindow *nsw = [w->window.view window];
-  NSPoint wpos;
-  // get bottom left of window on screen, from bottom left
-  wpos.x = wpos.y = 0;
-  wpos = [nsw convertBaseToScreen:wpos];
-  
-  // get bottom left of view on window, from bottom left
-  vpos->x = vpos->y = 0;
-  *vpos = [w->window.view convertPoint:*vpos toView:[nsw contentView]];
-
-  // get bottom left of view on screen, from bottom left
-  vpos->x += wpos.x;
-  vpos->y += wpos.y;
-  
-  // get top left of view on screen, from bottom left
-  vpos->y += w->frame.size.height;
-  
-  // get top left of view on screen, from top left
-  NSArray *screens = [NSScreen screens];
-  NSScreen *screen = (screens && [screens count] > 0
-                      ? [screens objectAtIndex:0]
-                      : [NSScreen mainScreen]);
-  NSRect srect = [screen frame];
-  vpos->y = srect.size.height - vpos->y;
-
-  if (p) {
-    // get the mouse position on window, from bottom left
-    NSEvent *e = [NSApp currentEvent];
-    *p = [e locationInWindow];
-
-    // get mouse position on screen, from bottom left
-    p->x += wpos.x;
-    p->y += wpos.y;
-
-    // get mouse position on screen, from top left
-    p->y = srect.size.height - p->y;
-  }
-
-# endif // !USE_IPHONE
-}
-
-Bool
-XQueryPointer (Display *dpy, Window w, Window *root_ret, Window *child_ret,
-               int *root_x_ret, int *root_y_ret,
-               int *win_x_ret, int *win_y_ret, unsigned int *mask_ret)
-{
-  Assert (w && w->type == WINDOW, "not a window");
-
-  NSPoint vpos, p;
-  get_pos (w, &vpos, &p);
-
-  if (root_x_ret) *root_x_ret = (int) p.x;
-  if (root_y_ret) *root_y_ret = (int) p.y;
-  if (win_x_ret)  *win_x_ret  = (int) (p.x - vpos.x);
-  if (win_y_ret)  *win_y_ret  = (int) (p.y - vpos.y);
-  if (mask_ret)   *mask_ret   = 0;  // #### poll the keyboard modifiers?
-  if (root_ret)   *root_ret   = 0;
-  if (child_ret)  *child_ret  = 0;
-  return True;
-}
-
-Bool
-XTranslateCoordinates (Display *dpy, Window w, Window dest_w,
-                       int src_x, int src_y,
-                       int *dest_x_ret, int *dest_y_ret,
-                       Window *child_ret)
-{
-  Assert (w && w->type == WINDOW, "not a window");
-
-  NSPoint vpos, p;
-  get_pos (w, &vpos, NULL);
-
-  // point starts out relative to top left of view
-  p.x = src_x;
-  p.y = src_y;
-
-  // get point relative to top left of screen
-  p.x += vpos.x;
-  p.y += vpos.y;
-
-  *dest_x_ret = p.x;
-  *dest_y_ret = p.y;
-  if (child_ret)
-    *child_ret = w;
-  return True;
-}
-
-
-KeySym
-XKeycodeToKeysym (Display *dpy, KeyCode code, int index)
-{
-  return code;
-}
-
-int
-XLookupString (XKeyEvent *e, char *buf, int size, KeySym *k_ret,
-               XComposeStatus *xc)
-{
-  KeySym ks = XKeycodeToKeysym (0, e->keycode, 0);
-  char c = 0;
-  // Do not put non-ASCII KeySyms like XK_Shift_L and XK_Page_Up in the string.
-  if ((unsigned int) ks <= 255)
-    c = (char) ks;
-
-  // Put control characters in the string.  Not meta.
-  if (e->state & ControlMask) {
-    if (c >= 'a' && c <= 'z')    // Upcase control.
-      c -= 'a'-'A';
-    if (c >= '@' && c <= '_')    // Shift to control page.
-      c -= '@';
-    if (c == ' ')               // C-SPC is NULL.
-      c = 0;
-  }
-
-  if (k_ret) *k_ret = ks;
-  if (size > 0) buf[0] = c;
-  if (size > 1) buf[1] = 0;
-  return (size > 0 ? 1 : 0);
-}
-
-
-int
-XFlush (Display *dpy)
-{
-  // Just let the event loop take care of this on its own schedule.
-  return 0;
-}
-
-int
-XSync (Display *dpy, Bool flush)
-{
-  return XFlush (dpy);
-}
-
-
-// declared in utils/visual.h
-int
-has_writable_cells (Screen *s, Visual *v)
-{
-  return 0;
-}
-
-int
-visual_depth (Screen *s, Visual *v)
-{
-  return 32;
-}
-
-int
-visual_cells (Screen *s, Visual *v)
-{
-  return (int)(v->red_mask | v->green_mask | v->blue_mask);
-}
-
-int
-visual_class (Screen *s, Visual *v)
-{
-  return TrueColor;
-}
-
-int
-get_bits_per_pixel (Display *dpy, int depth)
-{
-  Assert (depth == 32 || depth == 1, "unexpected depth");
-  return depth;
-}
-
-int
-screen_number (Screen *screen)
-{
-  Display *dpy = DisplayOfScreen (screen);
-  int i;
-  for (i = 0; i < ScreenCount (dpy); i++)
-    if (ScreenOfDisplay (dpy, i) == screen)
-      return i;
-  abort ();
-  return 0;
-}
-
-// declared in utils/grabclient.h
-Bool
-use_subwindow_mode_p (Screen *screen, Window window)
-{
-  return False;
-}
index 29b257acb405bd303e7cdb768bccc6b01f5af31b..c7f4f15b686902b3185744abf1f3f06eef74c001 100644 (file)
@@ -24,7 +24,7 @@
 #else
 # import "SaverRunner.h"
 #endif
-#import "jwxyz.h"
+#import "jwxyz-cocoa.h"
 #import "grabscreen.h"
 #import "colorbars.h"
 #import "resources.h"
diff --git a/OSX/seticon.pl b/OSX/seticon.pl
new file mode 100755 (executable)
index 0000000..69faf68
--- /dev/null
@@ -0,0 +1,102 @@
+#!/usr/bin/perl -w
+# Copyright © 2015 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.
+
+# This is a replacement for seticon from http://osxutils.sourceforge.net/.
+
+require 5;
+use diagnostics;
+use strict;
+#use IPC::Open2;
+use File::Temp;
+
+my $progname = $0; $progname =~ s@.*/@@g;
+my ($version) = ('$Revision: 1.4 $' =~ m/\s(\d[.\d]+)\s/s);
+
+my $verbose = 0;
+
+sub set_icon ($$) {
+  my ($icon, $target) = @_;
+  my $target_res = $target;
+
+  if (-d $target) {
+    $target_res = $target_res . "/Icon\r";
+  }
+
+  # Rez hates absolute paths, apparently.
+  if ($icon =~ m@^/@s) {
+    my $cwd = `pwd`;
+    chomp $cwd;
+    $icon =~ s@^\Q$cwd/@@s;
+  }
+
+  # The Rez language is documented in "Building and Managing Programs in MPW,
+  # Second Edition". No longer available on Apple's servers, it can now be
+  # found at:
+  # http://www.powerpc.hu/manila/static/home/Apple/developer/Tool_Chest/Core_Mac_OS_Tools/MPW_etc./Documentation/MPW_Reference/Building_Progs_In_MPW.sit.hqx
+
+  my $pgm = "Read 'icns' (kCustomIconResource) \"$icon\";\n";
+
+  # Rez can read from stdin, but only if it is a file handle, not if it
+  # is a pipe (OS X 10.9, Xcode 5; OSX 10.11, Xcode 6).
+
+  my ($rez_fh, $rez_filename) = File::Temp::tempfile(DIR => '.', UNLINK => 1);
+  print $rez_fh $pgm;
+  close $rez_fh;
+
+  my @cmd = ('Rez',
+             'CoreServices.r',
+             $rez_filename,
+             '-o', $target_res);
+
+  print STDERR "$progname: exec: " . join(' ', @cmd) . "\n$pgm\n"
+    if ($verbose);
+
+#  my ($in, $out);
+#  my $pid = open2 ($out, $in, @cmd);
+#  print $in $pgm;
+#  close ($in);
+#  waitpid ($pid, 0);
+
+  system (@cmd);
+
+  my $exit  = $? >> 8;
+  exit ($exit) if $exit;
+
+  # Have to also inform Finder that the icon is there, with the
+  # com.apple.FinderInfo xattr (a FolderInfo struct).
+  @cmd = ('SetFile', '-a', 'C', $target);
+  system (@cmd);
+  $exit  = $? >> 8;
+  exit ($exit) if $exit;
+}
+
+sub usage() {
+  print "Usage: $progname -d source [file...]\n";
+  exit 1;
+}
+
+sub main() {
+  my ($d, $src, $dst);
+  while ($#ARGV >= 0) {
+    $_ = shift @ARGV;
+    if (m/^--?verbose$/s)      { $verbose++; }
+    elsif (m/^-v+$/s)          { $verbose += length($_)-1; }
+    elsif (m/^-d$/s)           { $d = 1; }
+    elsif (!defined($src))     { $src = $_; }
+    elsif (!defined($dst))     { $dst = $_; }
+    else { usage; }
+  }
+  usage() unless ($d && $src);
+  set_icon ($src, $dst);
+}
+
+main();
+exit 0;
diff --git a/OSX/textclient-iOS.m b/OSX/textclient-iOS.m
new file mode 100644 (file)
index 0000000..7e57291
--- /dev/null
@@ -0,0 +1,71 @@
+/* xscreensaver, Copyright (c) 2012-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.
+ *
+ * Loading URLs and returning the underlying text.
+ *
+ * This is necessary because iOS doesn't have Perl installed, so we can't
+ * run "xscreensaver-text" to do this.
+ */
+
+#include "utils.h"
+
+#ifdef USE_IPHONE // whole file
+
+#include "textclient.h"
+
+char *
+textclient_mobile_date_string (void)
+{
+  UIDevice *dd = [UIDevice currentDevice];
+  NSString *name = [dd name];                  // My iPhone
+  NSString *model = [dd model];                        // iPad
+  // NSString *system = [dd systemName];       // iPhone OS
+  NSString *vers = [dd systemVersion];         // 5.0
+  NSString *date =
+    [NSDateFormatter
+      localizedStringFromDate:[NSDate date]
+      dateStyle: NSDateFormatterMediumStyle
+      timeStyle: NSDateFormatterMediumStyle];
+  NSString *nl = @"\n";
+
+  NSString *result = name;
+  result = [result stringByAppendingString: nl];
+  result = [result stringByAppendingString: model];
+  // result = [result stringByAppendingString: nl];
+  // result = [result stringByAppendingString: system];
+  result = [result stringByAppendingString: @" "];
+  result = [result stringByAppendingString: vers];
+  result = [result stringByAppendingString: nl];
+  result = [result stringByAppendingString: nl];
+  result = [result stringByAppendingString: date];
+  result = [result stringByAppendingString: nl];
+  result = [result stringByAppendingString: nl];
+  return strdup ([result cStringUsingEncoding:NSISOLatin1StringEncoding]);
+}
+
+
+/* Returns the contents of the URL. */
+char *
+textclient_mobile_url_string (Display *dpy, const char *url)
+{
+  NSURL *nsurl =
+    [NSURL URLWithString:
+             [NSString stringWithCString: url
+                       encoding:NSISOLatin1StringEncoding]];
+  NSString *body =
+    [NSString stringWithContentsOfURL: nsurl
+              encoding: NSUTF8StringEncoding
+              error: nil];
+  return (body
+          ? strdup ([body cStringUsingEncoding:NSUTF8StringEncoding])
+          : 0);
+}
+
+#endif // USE_IPHONE -- whole file
index 172996bd96d855f533a8000c3e251b174c863076..2b7968c320cb3b7691e1e5c464f70ee11a349cd6 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/perl -w
-# Copyright © 2006-2014 Jamie Zawinski <jwz@jwz.org>
+# Copyright © 2006-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
@@ -27,11 +27,12 @@ use IO::Compress::Gzip qw(gzip $GzipError);
 
 my ($exec_dir, $progname) = ($0 =~ m@^(.*?)/([^/]+)$@);
 
-my ($version) = ('$Revision: 1.38 $' =~ m/\s(\d[.\d]+)\s/s);
+my ($version) = ('$Revision: 1.45 $' =~ m/\s(\d[.\d]+)\s/s);
 
 $ENV{PATH} = "/usr/local/bin:$ENV{PATH}";   # for seticon
+$ENV{PATH} = "/opt/local/bin:$ENV{PATH}";   # for macports wget
 
-my $thumbdir = $ENV{HOME} . '/www/xscreensaver/screenshots/';
+my $thumbdir = 'build/screenshots';
 
 
 
@@ -123,20 +124,11 @@ sub read_saver_xml($) {
 }
 
 
-sub update_saver_xml($$) {
-  my ($app_dir, $vers) = @_;
-  my ($filename, $body, $was_compressed_p) = read_saver_xml ($app_dir);
-  my $obody = $body;
-
-  return () unless defined ($filename);
-
-  $body =~ m@<screensaver[^<>]*?[ \t]_label=\"([^\"]+)\"@m ||
-    error ("$filename: no name label");
-  my $name = $1;
+# This is duplicated in hacks/check-configs.pl for Android
+#
+sub munge_blurb($$$$) {
+  my ($filename, $name, $vers, $desc) = @_;
 
-  $body =~ m@<_description>(.*?)</_description>@s ||
-    error ("$filename: no description tag");
-  my $desc = $1;
   $desc =~ s/^([ \t]*\n)+//s;
   $desc =~ s/\s*$//s;
 
@@ -144,7 +136,7 @@ sub update_saver_xml($$) {
   $desc =~ s@<!--.*?-->@@gs;
   $desc =~ s/^.* version \d[^\n]*\n//s;
   $desc =~ s/^From the XScreenSaver.*\n//m;
-  $desc =~ s@^http://www\.jwz\.org/xscreensaver.*\n@@m;
+  $desc =~ s@^https://www\.jwz\.org/xscreensaver.*\n@@m;
   $desc =~
        s/\nCopyright [^ \r\n\t]+ (\d{4})(-\d{4})? (.*)\.$/\nWritten $3; $1./s;
   $desc =~ s/^\n+//s;
@@ -153,9 +145,6 @@ sub update_saver_xml($$) {
     if ($desc =~ m/([<>&][^<>&\s]*)/s);
   error ("$filename: description contains ctl chars: $1")
     if ($desc =~ m/([\000-\010\013-\037])/s);
-  error ("$filename: description contains non-ASCII and is not UTF-8: $1")
-    if ($body !~ m/\Q<?xml version="1.0" encoding="UTF-8"/s &&
-        $desc =~ m/([^\000-\176])/s);
 
   error ("$filename: can't extract authors")
     unless ($desc =~ m@^(.*)\nWritten by[ \t]+(.+)$@s);
@@ -194,13 +183,13 @@ sub update_saver_xml($$) {
                $desc . "\n" .
                "\n" . 
                "From the XScreenSaver collection: " .
-               "http://www.jwz.org/xscreensaver/\n" .
+               "https://www.jwz.org/xscreensaver/\n" .
                "Copyright \302\251 $year by $authors.\n");
 
   my $desc2 = ("$name $vers,\n" .                      # Info.plist
                "\302\251 $year $authors.\n" .
                "From the XScreenSaver collection:\n" .
-               "http://www.jwz.org/xscreensaver/\n" .
+               "https://www.jwz.org/xscreensaver/\n" .
                "\n" .
                $desc .
                "\n");
@@ -208,9 +197,34 @@ sub update_saver_xml($$) {
   # unwrap lines, but only when it's obviously ok: leave blank lines,
   # and don't unwrap if that would compress leading whitespace on a line.
   #
-  $desc2 =~ s/^(From |http:)/\n$1/gm;
+  $desc2 =~ s/^(From |https?:)/\n$1/gm;
   1 while ($desc2 =~ s/([^\s])[ \t]*\n([^\s])/$1 $2/gs);
-  $desc2 =~ s/\n\n(From |http:)/\n$1/gs;
+  $desc2 =~ s/\n\n(From |https?:)/\n$1/gs;
+
+  return ($desc1, $desc2);
+}
+
+
+sub update_saver_xml($$) {
+  my ($app_dir, $vers) = @_;
+  my ($filename, $body, $was_compressed_p) = read_saver_xml ($app_dir);
+  my $obody = $body;
+
+  return () unless defined ($filename);
+
+  $body =~ m@<screensaver[^<>]*?[ \t]_label=\"([^\"]+)\"@m ||
+    error ("$filename: no name label");
+  my $name = $1;
+
+  $body =~ m@<_description>(.*?)</_description>@s ||
+    error ("$filename: no description tag");
+  my $desc = $1;
+
+  error ("$filename: description contains non-ASCII and is not UTF-8: $1")
+    if ($body !~ m/\Q<?xml version="1.0" encoding="UTF-8"/s &&
+        $desc =~ m/([^\000-\176])/s);
+
+  my ($desc1, $desc2) = munge_blurb ($filename, $name, $vers, $desc);
 
   $body =~ s@(<_description>)(.*?)(</_description>)@$1$desc1$3@s;
 
@@ -304,11 +318,9 @@ sub set_icon($) {
   my ($app_dir) = @_;
   $app_dir =~ s@/+$@@s;
 
-  # "seticon" is from osxutils, http://osxutils.sourceforge.net/
-
   my $icon = ($app_dir =~ m/\.saver$/ ? 'XScreenSaver' : 'SaverRunner');
   $icon = "$app_dir/../../../$icon.icns";
-  my @cmd = ("seticon", "-d", $icon, $app_dir);
+  my @cmd = ("$app_dir/../../../seticon.pl", "-d", $icon, $app_dir);
   print STDERR "$progname: exec: " . join(' ', @cmd) . "\n"
     if ($verbose > 1);
   system (@cmd);
@@ -320,11 +332,26 @@ sub set_thumb($) {
 
   return unless ($app_dir =~ m@\.saver/?$@s);
 
-  my @cmd = ("$exec_dir/update-thumbnail.pl", $thumbdir, $app_dir);
-  push @cmd, "-" . ("v" x $verbose) if ($verbose);
-  print STDERR "$progname: exec: " . join(' ', @cmd) . "\n"
-    if ($verbose > 1);
-  system (@cmd);
+  my $name = $app_dir;
+  $name =~ s@^.*/@@s;
+  $name =~ s@\..*?$@@s;
+  $name = lc($name);
+
+  $name = 'rd-bomb' if ($name eq 'rdbomb');  # sigh
+
+  if (! -f "$thumbdir/$name.png") {
+    system ("make", "$thumbdir/$name.png");
+    my $exit  = $? >> 8;
+    exit ($exit) if $exit;
+    error ("unable to download $name.png")
+      unless (-f "$thumbdir/$name.png");
+  }
+
+  $app_dir =~ s@/+$@@s;
+  $app_dir .= "/Contents/Resources";
+  error ("$app_dir does not exist") unless (-d $app_dir);
+
+  system ("cp", "-p", "$thumbdir/$name.png", "$app_dir/thumbnail.png");
   my $exit  = $? >> 8;
   exit ($exit) if $exit;
 }
@@ -408,7 +435,7 @@ sub update($) {
     $copyright =~ s/\b\d{4}-(\d{4})\b/$1/;
 
     # Lose the Wikipedia URLs.
-    $info_str =~ s@http:.*?\b(wikipedia|mathworld)\b[^\s]+[ \t]*\n?@@gm;
+    $info_str =~ s@https?:.*?\b(wikipedia|mathworld)\b[^\s]+[ \t]*\n?@@gm;
 
     $info_str =~ s/(\n\n)\n+/$1/gs;
     $info_str =~ s/(^\s+|\s+$)//gs;
diff --git a/OSX/update-thumbnail.pl b/OSX/update-thumbnail.pl
deleted file mode 100755 (executable)
index da95f4a..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-#!/usr/bin/perl -w
-# Copyright © 2006-2014 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.
-#
-# Converts and installs a thumbnail image inside a .saver bundle.
-#
-# Created:  26-Jul-2012.
-
-require 5;
-#use diagnostics;      # Fails on some MacOS 10.5 systems
-use strict;
-
-my $progname = $0; $progname =~ s@.*/@@g;
-my ($version) = ('$Revision: 1.4 $' =~ m/\s(\d[.\d]+)\s/s);
-
-my $verbose = 1;
-
-$ENV{PATH} = "/opt/local/bin:$ENV{PATH}";   # MacPorts, for ImageMagick
-
-
-sub safe_system(@) {
-  my @cmd = @_;
-  system (@cmd);
-  my $exit_value  = $? >> 8;
-  my $signal_num  = $? & 127;
-  my $dumped_core = $? & 128;
-  error ("$cmd[0]: core dumped!") if ($dumped_core);
-  error ("$cmd[0]: signal $signal_num!") if ($signal_num);
-  error ("$cmd[0]: exited with $exit_value!") if ($exit_value);
-}
-
-
-# Returns true if the two files differ (by running "cmp")
-#
-sub cmp_files($$) {
-  my ($file1, $file2) = @_;
-
-  my @cmd = ("cmp", "-s", "$file1", "$file2");
-  print STDERR "$progname: executing \"" . join(" ", @cmd) . "\"\n"
-    if ($verbose > 3);
-
-  system (@cmd);
-  my $exit_value  = $? >> 8;
-  my $signal_num  = $? & 127;
-  my $dumped_core = $? & 128;
-
-  error ("$cmd[0]: core dumped!") if ($dumped_core);
-  error ("$cmd[0]: signal $signal_num!") if ($signal_num);
-  return $exit_value;
-}
-
-
-sub update($$) {
-  my ($src_dir, $app_dir) = @_;
-
-  # Apparently Apple wants Resources/{thumbnail.png to be 90x58,
-  # and Resources/thumbnail@2x.png to be 180x116.  Let's just 
-  # make the former, but make it be the latter's size.
-  #
-  my $size = '180x116';
-
-  error ("$app_dir does not exist") unless (-d $app_dir);
-  error ("$app_dir: no name")
-    unless ($app_dir =~ m@/([^/.]+).(saver|app)/?$@x);
-  my $app_name = $1;
-
-  $app_dir =~ s@/+$@@s;
-  $app_dir .= "/Contents/Resources";
-
-  error ("$app_dir does not exist") unless (-d $app_dir);
-  my $target = "$app_dir/thumbnail.png";
-
-  $src_dir .= "/" unless ($src_dir =~ m@/$@s);
-  my $src_dir2 = "${src_dir}retired/";
-
-  $app_name =~ s/rdbomb/rd-bomb/si;   # sigh
-
-  my $img  = $src_dir  . lc($app_name) . ".jpg";
-  my $img2 = $src_dir2 . lc($app_name) . ".jpg";
-  $img = $img2 if (! -f $img && -f $img2);
-  error ("$img does not exist") unless (-f $img);
-
-  my $tmp = sprintf ("%s/thumb-%08x.png",
-                     ($ENV{TMPDIR} ? $ENV{TMPDIR} : "/tmp"),
-                     rand(0xFFFFFFFF));
-  my @cmd = ("convert",
-             $img, 
-             "-strip",
-             "-resize", $size . "^",
-             "-gravity", "center",
-             "-extent", $size,
-             "-quality", "95",                 # saves 8%
-             "+dither", "-colors", "128",      # Saves an additional 61%
-             $tmp);
-
-  print STDERR "$progname: exec: " . join(' ', @cmd) . "\n" 
-    if ($verbose > 2);
-  safe_system (@cmd);
-
-  if (! -s $tmp) {
-    unlink $tmp;
-    error ("failed: " . join(" ", @cmd));
-  }
-
-  # This only saves 0.4% on top of the above.
-  #  @cmd = ("optipng", "-quiet", "-o7", $tmp);
-  #  print STDERR "$progname: exec: " . join(' ', @cmd) . "\n" 
-  #    if ($verbose > 2);
-  #  safe_system (@cmd);
-
-  if (! -s $tmp) {
-    unlink $tmp;
-    error ("failed: " . join(" ", @cmd));
-  }
-
-  if (! cmp_files ($tmp, $target)) {
-    unlink $tmp;
-    print STDERR "$progname: $target: unchanged\n" if ($verbose > 1);
-  } elsif (! rename ($tmp, $target)) {
-    unlink $tmp;
-    error ("mv $tmp $target: $!");
-  } else {
-    print STDERR "$progname: wrote $target\n" if ($verbose);
-  }
-}
-
-
-sub error($) {
-  my ($err) = @_;
-  print STDERR "$progname: $err\n";
-  exit 1;
-}
-
-sub usage() {
-  print STDERR "usage: $progname [--verbose] image-dir program.app ...\n";
-  exit 1;
-}
-
-sub main() {
-
-  my $src_dir;
-  my @files = ();
-  while ($_ = $ARGV[0]) {
-    shift @ARGV;
-    if    (m/^--?verbose$/s)  { $verbose++; }
-    elsif (m/^-v+$/)          { $verbose += length($_)-1; }
-    elsif (m/^--?q(uiet)?$/s) { $verbose = 0; }
-    elsif (m/^-/s)            { usage(); }
-    elsif (! $src_dir)        { $src_dir = $_; }
-    else                      { push @files, $_; }
-  }
-  usage() unless ($src_dir && $#files >= 0);
-  foreach (@files) {
-    update ($src_dir, $_);
-  }
-}
-
-main();
-exit 0;
index 20d082f4bff1c5ee2a763a0a14ab23481d3cf954..5938a4aee55b95bb03e1d1304a0f2c6959d4b864 100755 (executable)
@@ -21,12 +21,12 @@ use open ":encoding(utf8)";
 use POSIX;
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my $version = q{ $Revision: 1.1 $ }; $version =~ s/^[^\d]+([\d.]+).*/$1/;
+my ($version) = ('$Revision: 1.2 $' =~ m/\s(\d[.\d]+)\s/s);
 
 my $verbose = 0;
 my $debug_p = 0;
 
-my $base_url = "http://www.jwz.org/";
+my $base_url = "https://www.jwz.org/";
 my $priv_key_file = "$ENV{HOME}/.ssh/sparkle_dsa_priv.pem";
 my $sign_update = "./sign_update.rb";
 
index e6f7bbca15c7435e61457ec2b5af1c0d44c0bf50..1ad71d50178fed5e7717e9f093ef74125571c927 100644 (file)
@@ -4,48 +4,48 @@
      xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
   <title>xscreensaver updater</title>
-  <link>http://www.jwz.org/xscreensaver/updates.xml</link>
+  <link>https://www.jwz.org/xscreensaver/updates.xml</link>
   <description>Updates to xscreensaver.</description>
   <language>en</language>
   <item>
-   <title>Version 5.33</title>
-   <link>http://www.jwz.org/xscreensaver/xscreensaver-5.33.dmg</link>
-   <description><![CDATA[&bull; New hacks, `splitflap' and `romanboy'. <BR>&bull; Better detection of user activity on modern GNOME systems. <BR>&bull; Sonar now does asynchronous host name resolution. <BR>&bull; Improved Unicode support. <BR>&bull; Updated `webcollage' for recent changes. <BR>&bull; Various minor fixes.]]></description>
-   <pubDate>Thu, 25 Jun 2015 12:45:10 -0700</pubDate>
-   <enclosure url="http://www.jwz.org/xscreensaver/xscreensaver-5.33.dmg"
-    sparkle:version="5.33"
-    sparkle:dsaSignature="MCwCFEd0Zr8mliQgeG30xb2yfmitxc3yAhQs6xnD7v8ho9wmyCv1yJFjexcfgA=="
-    length="58437761"
+   <title>Version 5.35</title>
+   <link>https://www.jwz.org/xscreensaver/xscreensaver-5.35.dmg</link>
+   <description><![CDATA[&bull; New hacks, `dymaxionmap', `unicrud', `energystream', `raverhoop' and `hydrostat'. <BR>&bull; Added Windows 10 to `bsod'. <BR>&bull; X11: ignore WM_USER_TIME property changes with days-old timestamps. Thanks, KDE. <BR>&bull; MacOS, iOS: Better fonts in 'BSOD' and 'memscroller'. <BR>&bull; MacOS 10.7 or later and iOS 6.0 or later are now required, since Xcode 6 can no longer build executables that work on older OSes. <BR>&bull; Many, many Android improvements. <BR>&bull; iOS: Fixed rotation to work with the new iOS 8+ API. <BR>&bull; X11: `pong' is now playable.]]></description>
+   <pubDate>Mon, 23 May 2016 21:08:11 -0700</pubDate>
+   <enclosure url="https://www.jwz.org/xscreensaver/xscreensaver-5.35.dmg"
+    sparkle:version="5.35"
+    sparkle:dsaSignature="MC4CFQC4E0tIMWvdSbiycSktRBSLdA18aQIVAJknRfXSqcFu6Dd5Lem7+fnsevDi"
+    length="50566210"
     type="application/octet-stream" />
   </item>
   <item>
-   <title>Version 5.32</title>
-   <link>http://www.jwz.org/xscreensaver/xscreensaver-5.32.dmg</link>
-   <description><![CDATA[&bull; Fixed some X11 compilation problems. <BR>&bull; Fixed display size and shake gestures on iOS. <BR>&bull; OSX/iOS Performance improvements.]]></description>
-   <pubDate>Tue, 18 Nov 2014 23:25:45 -0800</pubDate>
-   <enclosure url="http://www.jwz.org/xscreensaver/xscreensaver-5.32.dmg"
-    sparkle:version="5.32"
-    sparkle:dsaSignature="MC0CFC8zpKjqvEY7GD1ePcf6P5leMJEhAhUAmNXVKRrAFBXwvyfJBw79iN3zobQ="
-    length="55175283"
+   <title>Version 5.34</title>
+   <link>https://www.jwz.org/xscreensaver/xscreensaver-5.34.dmg</link>
+   <description><![CDATA[&bull; Fixed a crash when hot-swapping monitors while locked. <BR>&bull; Fixed some incorrect output from `xscreensaver-command -watch'. <BR>&bull; Various OSX and iOS performance improvements.]]></description>
+   <pubDate>Sat, 24 Oct 2015 12:16:41 -0700</pubDate>
+   <enclosure url="https://www.jwz.org/xscreensaver/xscreensaver-5.34.dmg"
+    sparkle:version="5.34"
+    sparkle:dsaSignature="MCwCFAoZpMknlOVF0zFXlzFruzFvRXufAhQVKY0qlzelKcArrlC6k7EbHLTcyg=="
+    length="58850776"
     type="application/octet-stream" />
   </item>
   <item>
-   <title>Version 5.30</title>
-   <link>http://www.jwz.org/xscreensaver/xscreensaver-5.30.dmg</link>
-   <description><![CDATA[&bull; New hack, `winduprobot'. <BR>&bull; Many improvements to `lament', including Leviathan. <BR>&bull; Fixed the normals in `flyingtoasters': shading is correct now. <BR>&bull; Implemented TEXTURE_GEN in GLES: flying toast is now toasted on iOS. <BR>&bull; Make cel-shading sort-of work in `skytentacles' on iOS. <BR>&bull; Fixed dragging-to-rotate on rotated iOS devices, I think. <BR>&bull; Dragging has inertia now. <BR>&bull; Most hacks respond to mouse-clicks, double-taps and swipes as meaning "do something different now". <BR>&bull; Reworked OpenGL fonts. <BR>&bull; The OSX auto-update installer wasn't working. This time for sure? <BR>&bull; Various minor fixes.]]></description>
-   <pubDate>Wed, 10 Sep 2014 22:04:30 -0700</pubDate>
-   <enclosure url="http://www.jwz.org/xscreensaver/xscreensaver-5.30.dmg"
-    sparkle:version="5.30"
-    sparkle:dsaSignature="MC0CFDPqS6izb2TmEZpWMTqOwsOs3XiTAhUAoqdy8mZ0FdDHvO519aXvZR3WZIo="
-    length="53012325"
+   <title>Version 5.33</title>
+   <link>https://www.jwz.org/xscreensaver/xscreensaver-5.33.dmg</link>
+   <description><![CDATA[&bull; New hacks, `splitflap' and `romanboy'. <BR>&bull; Better detection of user activity on modern GNOME systems. <BR>&bull; Sonar now does asynchronous host name resolution. <BR>&bull; Improved Unicode support. <BR>&bull; Updated `webcollage' for recent changes. <BR>&bull; Various minor fixes.]]></description>
+   <pubDate>Thu, 25 Jun 2015 12:45:10 -0700</pubDate>
+   <enclosure url="https://www.jwz.org/xscreensaver/xscreensaver-5.33.dmg"
+    sparkle:version="5.33"
+    sparkle:dsaSignature="MCwCFEd0Zr8mliQgeG30xb2yfmitxc3yAhQs6xnD7v8ho9wmyCv1yJFjexcfgA=="
+    length="58437761"
     type="application/octet-stream" />
   </item>
   <item>
    <title>Version 5.14</title>
-   <link>http://www.jwz.org/xscreensaver/xscreensaver-5.14.dmg</link>
+   <link>https://www.jwz.org/xscreensaver/xscreensaver-5.14.dmg</link>
    <description><![CDATA[&bull; Fixed crash in Blank Only Mode when DPMS disabled. <BR>&bull; Added "Quick Power-off in Blank Only Mode" option. <BR>&bull; BSOD GLaDOS.]]></description>
    <pubDate>Fri, 20 May 2011 11:42:36 -0700</pubDate>
-   <enclosure url="http://www.jwz.org/xscreensaver/xscreensaver-5.14.dmg"
+   <enclosure url="https://www.jwz.org/xscreensaver/xscreensaver-5.14.dmg"
     sparkle:version="5.14"
     sparkle:dsaSignature="MCwCFHrKuttf1gN27mVG3YL8+ueMJmNaAhR6aSkKQefuNFNp6MinLq2o1nocaA=="
     length="54485615"
index 10313ccf4edeffef6edbf1ac483b8654b23a71b4..c1a9cc246dd689db7d6ee86da6c1c45b99d9611d 100644 (file)
@@ -1,7 +1,11 @@
 // To create builds that work properly on MacOS 10.6, Xcode 5.0.2 must
 // be used, since that is the latest version that supports garbage collection.
-// If the Xcode version is 5.02 or earlier, this must be set to "-fobjc-gc".
-// If the Xcode version is newer than that, this must be blank (and the
-// builds created will not work on 10.6.)
+// If the Xcode version is 5.02 or earlier, use these settings:
+//   "10.4", "-fobjc-gc", "-no-fobjc-gc"
+// If the Xcode version is later than that, use these settings:
+//   "10.6", "", ""
+// and the generate builds will only work on 10.6 or later.
 //
-OBJC_GC_CFLAGS=-fobjc-gc
+MACOSX_DEPLOYMENT_TARGET=10.7
+OBJC_GC_CFLAGS=
+OBJC_NO_GC_CFLAGS=
index f07ba7b7104df24429d24ef20075edbd83a2a52b..ae75ecf71a0aad6a1bbba7ab8b01376ace3cfbaa 100644 (file)
                                AF4FF4D70D52CD0D00666F98 /* PBXTargetDependency */,
                                AF777A4109B660B500EA3033 /* PBXTargetDependency */,
                                AF777A3F09B660B500EA3033 /* PBXTargetDependency */,
+                               AFEC23EB1CB6ED0800DE138F /* PBXTargetDependency */,
                                AF777A3D09B660B500EA3033 /* PBXTargetDependency */,
+                               AFACE8911CC8365F008B24CD /* PBXTargetDependency */,
                                AF777A3B09B660B500EA3033 /* PBXTargetDependency */,
                                AF777A3909B660B400EA3033 /* PBXTargetDependency */,
                                AF777A3709B660B400EA3033 /* PBXTargetDependency */,
                                AF777A1B09B660B300EA3033 /* PBXTargetDependency */,
                                AF777A1909B660B300EA3033 /* PBXTargetDependency */,
                                AF4F10F0143450C300E34F3F /* PBXTargetDependency */,
+                               AFC0E8C91CDC6125008CAFAC /* PBXTargetDependency */,
                                AF777A1709B660B300EA3033 /* PBXTargetDependency */,
                                AF42C5160D624E9200B27FF6 /* PBXTargetDependency */,
                                AF777A1509B660B300EA3033 /* PBXTargetDependency */,
                                AF7779F509B660B100EA3033 /* PBXTargetDependency */,
                                AFBFE7401786405E00432B21 /* PBXTargetDependency */,
                                AF7779F309B660B000EA3033 /* PBXTargetDependency */,
+                               AFA211AA1CD5A08000C0D2A1 /* PBXTargetDependency */,
                                AF63A80F1AB4EFD300593C75 /* PBXTargetDependency */,
                                AF7779F109B660B000EA3033 /* PBXTargetDependency */,
                                AF32D9F90F3AD0D90080F535 /* PBXTargetDependency */,
                                AF7779DD09B660AF00EA3033 /* PBXTargetDependency */,
                                AF998EF70A083E1D0051049D /* PBXTargetDependency */,
                                AF4F10F2143450C300E34F3F /* PBXTargetDependency */,
+                               AF46E9ED1CBBA49A00240FBC /* PBXTargetDependency */,
                                AFDA65AA178A54690070D24B /* PBXTargetDependency */,
                                AF0DCA5C0C4CBB4300D76972 /* PBXTargetDependency */,
                                AF39E2BA198A16920064A58D /* PBXTargetDependency */,
 /* End PBXAggregateTarget section */
 
 /* Begin PBXBuildFile section */
-               550FB5FE1AD64424001A4FA5 /* Media-iOS.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 550FB5FD1AD64424001A4FA5 /* Media-iOS.xcassets */; };
-               550FB5FF1AD64424001A4FA5 /* Media-iOS.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 550FB5FD1AD64424001A4FA5 /* Media-iOS.xcassets */; };
                550FB6001AD64424001A4FA5 /* Media-iOS.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 550FB5FD1AD64424001A4FA5 /* Media-iOS.xcassets */; };
                55EDCB3D1AD498A800251909 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 55EDCB3C1AD498A800251909 /* LaunchScreen.xib */; };
-               55EDCB3E1AD49DFA00251909 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 55EDCB3C1AD498A800251909 /* LaunchScreen.xib */; };
-               55EDCB3F1AD49DFE00251909 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 55EDCB3C1AD498A800251909 /* LaunchScreen.xib */; };
                AF012918157C1E4C00C396E1 /* chessmodels.c in Sources */ = {isa = PBXBuildFile; fileRef = AFA55E2309935F2B00F3E977 /* chessmodels.c */; };
                AF0839A609930BAC00277BE9 /* atlantis.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFC258700988A468000655EE /* atlantis.xml */; };
                AF0839B009930C4900277BE9 /* atlantis.c in Sources */ = {isa = PBXBuildFile; fileRef = AF0839A909930C4900277BE9 /* atlantis.c */; };
                AF1FD720158FF96500C40F17 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
                AF1FD721158FF96500C40F17 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
                AF1FD722158FF96500C40F17 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
-               AF1FD723158FF96500C40F17 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
                AF1FD727158FF96500C40F17 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
                AF1FD728158FF96500C40F17 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
                AF1FD729158FF96500C40F17 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
                AF1FD7F0158FF96500C40F17 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
                AF1FD7F1158FF96500C40F17 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
                AF1FD7F2158FF96500C40F17 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
-               AF1FD7F3158FF96500C40F17 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
                AF1FD7F7158FF96500C40F17 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
                AF1FD7F8158FF96500C40F17 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
                AF1FD7F9158FF96500C40F17 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
                AF2C32C615C0FC9D007A6896 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
                AF2C32C715C0FC9D007A6896 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
                AF2C32C815C0FC9D007A6896 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
-               AF2D4D8613E902F5002AA818 /* SaverRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = AFE1FD400981E32E00F7970E /* SaverRunner.m */; };
-               AF2D4D8713E902F5002AA818 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; };
-               AF2D4F7513E91093002AA818 /* SaverRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = AFE1FD400981E32E00F7970E /* SaverRunner.m */; };
-               AF2D4F7613E91093002AA818 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; };
+               AF2D8F321CEBA10300198014 /* jwxyz-timers.c in Sources */ = {isa = PBXBuildFile; fileRef = AF2D8F301CEBA10300198014 /* jwxyz-timers.c */; };
+               AF2D8F331CEBA10300198014 /* jwxyz-timers.h in Headers */ = {isa = PBXBuildFile; fileRef = AF2D8F311CEBA10300198014 /* jwxyz-timers.h */; };
                AF32D9E70F3AD0B40080F535 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
                AF32D9FB0F3AD1200080F535 /* rubikblocks.c in Sources */ = {isa = PBXBuildFile; fileRef = AF32D9FA0F3AD1200080F535 /* rubikblocks.c */; };
                AF32D9FD0F3AD1330080F535 /* rubikblocks.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF32D9FC0F3AD1330080F535 /* rubikblocks.xml */; };
                AF3581C31431D47B00E09C51 /* voronoi.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF0DCA610C4CBB8E00D76972 /* voronoi.xml */; };
                AF3581C61431D47B00E09C51 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
-               AF3581C71431D47B00E09C51 /* voronoi.c in Sources */ = {isa = PBXBuildFile; fileRef = AF0DCA5F0C4CBB7300D76972 /* voronoi.c */; };
-               AF3581C81431D47B00E09C51 /* hilbert.c in Sources */ = {isa = PBXBuildFile; fileRef = AF78D18A142DD96E002AAF77 /* hilbert.c */; };
                AF3581DC1431D5FC00E09C51 /* companion_disc.c in Sources */ = {isa = PBXBuildFile; fileRef = AF3581D61431D5FC00E09C51 /* companion_disc.c */; };
                AF3581DF1431D5FC00E09C51 /* companion_heart.c in Sources */ = {isa = PBXBuildFile; fileRef = AF3581D71431D5FC00E09C51 /* companion_heart.c */; };
                AF3581E21431D5FC00E09C51 /* companion_quad.c in Sources */ = {isa = PBXBuildFile; fileRef = AF3581D81431D5FC00E09C51 /* companion_quad.c */; };
                AF3581E81431D61D00E09C51 /* companioncube.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF3581E61431D61D00E09C51 /* companioncube.xml */; };
                AF3581FF143330F900E09C51 /* voronoi.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF0DCA610C4CBB8E00D76972 /* voronoi.xml */; };
                AF358203143330F900E09C51 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
-               AF358204143330F900E09C51 /* voronoi.c in Sources */ = {isa = PBXBuildFile; fileRef = AF0DCA5F0C4CBB7300D76972 /* voronoi.c */; };
-               AF358205143330F900E09C51 /* hilbert.c in Sources */ = {isa = PBXBuildFile; fileRef = AF78D18A142DD96E002AAF77 /* hilbert.c */; };
-               AF358206143330F900E09C51 /* companion_disc.c in Sources */ = {isa = PBXBuildFile; fileRef = AF3581D61431D5FC00E09C51 /* companion_disc.c */; };
-               AF358207143330F900E09C51 /* companion_heart.c in Sources */ = {isa = PBXBuildFile; fileRef = AF3581D71431D5FC00E09C51 /* companion_heart.c */; };
-               AF358208143330F900E09C51 /* companion_quad.c in Sources */ = {isa = PBXBuildFile; fileRef = AF3581D81431D5FC00E09C51 /* companion_quad.c */; };
-               AF358209143330F900E09C51 /* companion.c in Sources */ = {isa = PBXBuildFile; fileRef = AF3581D91431D5FC00E09C51 /* companion.c */; };
                AF35821C1433314C00E09C51 /* tronbit_idle1.c in Sources */ = {isa = PBXBuildFile; fileRef = AF3582171433314C00E09C51 /* tronbit_idle1.c */; };
                AF35821D1433314C00E09C51 /* tronbit_idle2.c in Sources */ = {isa = PBXBuildFile; fileRef = AF3582181433314C00E09C51 /* tronbit_idle2.c */; };
                AF35821E1433314C00E09C51 /* tronbit_no.c in Sources */ = {isa = PBXBuildFile; fileRef = AF3582191433314C00E09C51 /* tronbit_no.c */; };
                AF3C714B0D624BF50030CC0D /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
                AF3C715E0D624C600030CC0D /* hypnowheel.c in Sources */ = {isa = PBXBuildFile; fileRef = AF3C715D0D624C600030CC0D /* hypnowheel.c */; };
                AF3C71600D624C7C0030CC0D /* hypnowheel.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF3C715F0D624C7C0030CC0D /* hypnowheel.xml */; };
+               AF46E9D61CBBA2B300240FBC /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AF46E9D81CBBA2B300240FBC /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AF46E9D91CBBA2B300240FBC /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AF46E9DA1CBBA2B300240FBC /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AF46E9DB1CBBA2B300240FBC /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AF46E9DC1CBBA2B300240FBC /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AF46E9DD1CBBA2B300240FBC /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AF46E9DE1CBBA2B300240FBC /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AF46E9E81CBBA41600240FBC /* unicrud.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF46E9E61CBBA3F900240FBC /* unicrud.xml */; };
+               AF46E9E91CBBA41B00240FBC /* unicrud.c in Sources */ = {isa = PBXBuildFile; fileRef = AF46E9E71CBBA3F900240FBC /* unicrud.c */; };
+               AF46E9EA1CBBA42F00240FBC /* unicrud.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF46E9E61CBBA3F900240FBC /* unicrud.xml */; };
+               AF46E9EB1CBBA43B00240FBC /* unicrud.c in Sources */ = {isa = PBXBuildFile; fileRef = AF46E9E71CBBA3F900240FBC /* unicrud.c */; settings = {COMPILER_FLAGS = "-DUSE_GL"; }; };
                AF476FBC099D154F001F091E /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
                AF476FCF099D1587001F091E /* interference.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFC258CC0988A468000655EE /* interference.xml */; };
                AF476FD1099D15AA001F091E /* interference.c in Sources */ = {isa = PBXBuildFile; fileRef = AF476FD0099D15AA001F091E /* interference.c */; };
                AF4FF4C10D52CBDE00666F98 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
                AF4FF4D10D52CC8400666F98 /* cubicgrid.c in Sources */ = {isa = PBXBuildFile; fileRef = AF4FF4D00D52CC8400666F98 /* cubicgrid.c */; };
                AF4FF4D40D52CCAA00666F98 /* cubicgrid.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF4FF4D30D52CCAA00666F98 /* cubicgrid.xml */; };
-               AF51FD3415845CD500E5741F /* phosphor.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFC258F30988A469000655EE /* phosphor.xml */; };
-               AF51FD3515845D1400E5741F /* SaverListController.m in Sources */ = {isa = PBXBuildFile; fileRef = AF84AF1E15829AF000607E4C /* SaverListController.m */; };
-               AF51FD3615845F9900E5741F /* iSaverRunner.xib in Resources */ = {isa = PBXBuildFile; fileRef = AF56019B157DAA3D00DB2055 /* iSaverRunner.xib */; };
-               AF51FD3715845F9F00E5741F /* iSaverRunner.xib in Resources */ = {isa = PBXBuildFile; fileRef = AF56019B157DAA3D00DB2055 /* iSaverRunner.xib */; };
                AF51FD3915845FCB00E5741F /* SaverRunner.icns in Resources */ = {isa = PBXBuildFile; fileRef = AF2D522513E954A0002AA818 /* SaverRunner.icns */; };
                AF561DF615969BC3007CA5ED /* iosgrabimage.m in Sources */ = {isa = PBXBuildFile; fileRef = AF561DF515969BC3007CA5ED /* iosgrabimage.m */; };
                AF561DF815969C5B007CA5ED /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF561DF715969C5B007CA5ED /* AssetsLibrary.framework */; };
                AF5C9AFD1A0CCE6E00B0147A /* dangerball.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFC258920988A468000655EE /* dangerball.xml */; };
-               AF5C9AFF1A0CCE6E00B0147A /* dangerball.c in Sources */ = {isa = PBXBuildFile; fileRef = AF480DD1098F4F6200FB32B8 /* dangerball.c */; };
                AF5C9B001A0CCE6E00B0147A /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
                AF5C9B021A0CCE6E00B0147A /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
                AF5C9B031A0CCE6E00B0147A /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
                AF63A80B1AB4EF5D00593C75 /* romanboy.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF63A8081AB4EF5D00593C75 /* romanboy.xml */; };
                AF63A80C1AB4EF5D00593C75 /* romanboy.c in Sources */ = {isa = PBXBuildFile; fileRef = AF63A8091AB4EF5D00593C75 /* romanboy.c */; };
                AF63A80D1AB4EF5D00593C75 /* romanboy.c in Sources */ = {isa = PBXBuildFile; fileRef = AF63A8091AB4EF5D00593C75 /* romanboy.c */; settings = {COMPILER_FLAGS = "-DUSE_GL"; }; };
+               AF63F2511C3465BE0033E133 /* iSaverRunner.xib in Resources */ = {isa = PBXBuildFile; fileRef = AF56019B157DAA3D00DB2055 /* iSaverRunner.xib */; };
+               AF63F2521C3465BE0033E133 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 55EDCB3C1AD498A800251909 /* LaunchScreen.xib */; };
+               AF63F2531C3465BE0033E133 /* iSaverRunner57t.png in Resources */ = {isa = PBXBuildFile; fileRef = AF73FF201A08AB9400E485E9 /* iSaverRunner57t.png */; };
+               AF63F25D1C3465BE0033E133 /* apple2.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFC2586F0988A468000655EE /* apple2.xml */; };
+               AF63F2B71C3465BE0033E133 /* Media-iOS.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 550FB5FD1AD64424001A4FA5 /* Media-iOS.xcassets */; };
+               AF63F3281C3465BE0033E133 /* SaverRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = AFE1FD400981E32E00F7970E /* SaverRunner.m */; };
+               AF63F3291C3465BE0033E133 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; };
+               AF63F32A1C3465BE0033E133 /* SaverListController.m in Sources */ = {isa = PBXBuildFile; fileRef = AF84AF1E15829AF000607E4C /* SaverListController.m */; };
+               AF63F32D1C3465BE0033E133 /* analogtv.c in Sources */ = {isa = PBXBuildFile; fileRef = AF9D4CFA09B5AC94006E59CF /* analogtv.c */; };
+               AF63F32F1C3465BE0033E133 /* apple2-main.c in Sources */ = {isa = PBXBuildFile; fileRef = AF9D4E0509B5BC9D006E59CF /* apple2-main.c */; };
+               AF63F3301C3465BE0033E133 /* apple2.c in Sources */ = {isa = PBXBuildFile; fileRef = AF9D4DD309B5B990006E59CF /* apple2.c */; };
+               AF63F43F1C3465BE0033E133 /* ios-function-table.m in Sources */ = {isa = PBXBuildFile; fileRef = AFAA6B441773F07700DE720C /* ios-function-table.m */; };
+               AF63F4411C3465BE0033E133 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AF63F4421C3465BE0033E133 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3A1590054B003974F3 /* OpenGLES.framework */; };
+               AF63F4431C3465BE0033E133 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3815900514003974F3 /* UIKit.framework */; };
+               AF63F4441C3465BE0033E133 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF561DF715969C5B007CA5ED /* AssetsLibrary.framework */; };
+               AF63F4451C3465BE0033E133 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3C15900558003974F3 /* Foundation.framework */; };
+               AF63F4461C3465BE0033E133 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3E1590056A003974F3 /* CoreGraphics.framework */; };
+               AF63F4471C3465BE0033E133 /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF0FAF3B159BAC7B00BCE2F7 /* CoreText.framework */; };
+               AF63F4481C3465BE0033E133 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3F1590056A003974F3 /* QuartzCore.framework */; };
+               AF63F4491C3465BE0033E133 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78377C17DBA85D003B9FC0 /* libz.dylib */; };
+               AF63F4591C34682A0033E133 /* iSaverRunner.xib in Resources */ = {isa = PBXBuildFile; fileRef = AF56019B157DAA3D00DB2055 /* iSaverRunner.xib */; };
+               AF63F45A1C34682A0033E133 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 55EDCB3C1AD498A800251909 /* LaunchScreen.xib */; };
+               AF63F45B1C34682A0033E133 /* iSaverRunner57t.png in Resources */ = {isa = PBXBuildFile; fileRef = AF73FF201A08AB9400E485E9 /* iSaverRunner57t.png */; };
+               AF63F45D1C34682A0033E133 /* Media-iOS.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 550FB5FD1AD64424001A4FA5 /* Media-iOS.xcassets */; };
+               AF63F45F1C34682A0033E133 /* SaverRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = AFE1FD400981E32E00F7970E /* SaverRunner.m */; };
+               AF63F4601C34682A0033E133 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; };
+               AF63F4611C34682A0033E133 /* SaverListController.m in Sources */ = {isa = PBXBuildFile; fileRef = AF84AF1E15829AF000607E4C /* SaverListController.m */; };
+               AF63F4651C34682A0033E133 /* ios-function-table.m in Sources */ = {isa = PBXBuildFile; fileRef = AFAA6B441773F07700DE720C /* ios-function-table.m */; };
+               AF63F4671C34682A0033E133 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AF63F4681C34682A0033E133 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3A1590054B003974F3 /* OpenGLES.framework */; };
+               AF63F4691C34682A0033E133 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3815900514003974F3 /* UIKit.framework */; };
+               AF63F46A1C34682A0033E133 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF561DF715969C5B007CA5ED /* AssetsLibrary.framework */; };
+               AF63F46B1C34682A0033E133 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3C15900558003974F3 /* Foundation.framework */; };
+               AF63F46C1C34682A0033E133 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3E1590056A003974F3 /* CoreGraphics.framework */; };
+               AF63F46D1C34682A0033E133 /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF0FAF3B159BAC7B00BCE2F7 /* CoreText.framework */; };
+               AF63F46E1C34682A0033E133 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3F1590056A003974F3 /* QuartzCore.framework */; };
+               AF63F46F1C34682A0033E133 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78377C17DBA85D003B9FC0 /* libz.dylib */; };
+               AF63F4761C3469410033E133 /* phosphor.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFC258F30988A469000655EE /* phosphor.xml */; };
+               AF63F4771C3469570033E133 /* phosphor.c in Sources */ = {isa = PBXBuildFile; fileRef = AF77770309B63B5F00EA3033 /* phosphor.c */; };
+               AF63F4811C3469FC0033E133 /* iSaverRunner.xib in Resources */ = {isa = PBXBuildFile; fileRef = AF56019B157DAA3D00DB2055 /* iSaverRunner.xib */; };
+               AF63F4821C3469FC0033E133 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 55EDCB3C1AD498A800251909 /* LaunchScreen.xib */; };
+               AF63F4831C3469FC0033E133 /* iSaverRunner57t.png in Resources */ = {isa = PBXBuildFile; fileRef = AF73FF201A08AB9400E485E9 /* iSaverRunner57t.png */; };
+               AF63F4851C3469FC0033E133 /* Media-iOS.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 550FB5FD1AD64424001A4FA5 /* Media-iOS.xcassets */; };
+               AF63F4871C3469FC0033E133 /* SaverRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = AFE1FD400981E32E00F7970E /* SaverRunner.m */; };
+               AF63F4881C3469FC0033E133 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; };
+               AF63F4891C3469FC0033E133 /* SaverListController.m in Sources */ = {isa = PBXBuildFile; fileRef = AF84AF1E15829AF000607E4C /* SaverListController.m */; };
+               AF63F48B1C3469FC0033E133 /* ios-function-table.m in Sources */ = {isa = PBXBuildFile; fileRef = AFAA6B441773F07700DE720C /* ios-function-table.m */; };
+               AF63F48D1C3469FC0033E133 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AF63F48E1C3469FC0033E133 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3A1590054B003974F3 /* OpenGLES.framework */; };
+               AF63F48F1C3469FC0033E133 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3815900514003974F3 /* UIKit.framework */; };
+               AF63F4901C3469FC0033E133 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF561DF715969C5B007CA5ED /* AssetsLibrary.framework */; };
+               AF63F4911C3469FC0033E133 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3C15900558003974F3 /* Foundation.framework */; };
+               AF63F4921C3469FC0033E133 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3E1590056A003974F3 /* CoreGraphics.framework */; };
+               AF63F4931C3469FC0033E133 /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF0FAF3B159BAC7B00BCE2F7 /* CoreText.framework */; };
+               AF63F4941C3469FC0033E133 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3F1590056A003974F3 /* QuartzCore.framework */; };
+               AF63F4951C3469FC0033E133 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78377C17DBA85D003B9FC0 /* libz.dylib */; };
+               AF63F49C1C346B0A0033E133 /* testx11.xml in Resources */ = {isa = PBXBuildFile; fileRef = CE3D01681B76F83E00993C75 /* testx11.xml */; };
+               AF63F49D1C346B1A0033E133 /* testx11.c in Sources */ = {isa = PBXBuildFile; fileRef = CE3D016A1B76F8E200993C75 /* testx11.c */; };
                AF64232F099F45C3000F4CD4 /* braid.c in Sources */ = {isa = PBXBuildFile; fileRef = AFD56EC10996A76F00BA26F7 /* braid.c */; };
                AF642330099F45CA000F4CD4 /* braid.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFC2587D0988A468000655EE /* braid.xml */; };
                AF6423F9099FF9C2000F4CD4 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
                AF78377B17DBA581003B9FC0 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
                AF78D179142DD8F3002AAF77 /* voronoi.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF0DCA610C4CBB8E00D76972 /* voronoi.xml */; };
                AF78D17B142DD8F3002AAF77 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
-               AF78D17C142DD8F3002AAF77 /* voronoi.c in Sources */ = {isa = PBXBuildFile; fileRef = AF0DCA5F0C4CBB7300D76972 /* voronoi.c */; };
                AF78D18D142DD96E002AAF77 /* hilbert.c in Sources */ = {isa = PBXBuildFile; fileRef = AF78D18A142DD96E002AAF77 /* hilbert.c */; };
                AF78D191142DD99B002AAF77 /* hilbert.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF78D18E142DD99A002AAF77 /* hilbert.xml */; };
                AF794F6A099748450059A8B0 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
                AF7ACFD919FF0BA600BD752B /* geodesicgears.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF7ACFD819FF0BA600BD752B /* geodesicgears.xml */; };
                AF7ACFDA19FF0BA600BD752B /* geodesicgears.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF7ACFD819FF0BA600BD752B /* geodesicgears.xml */; };
                AF7F54A417DC249500CE1158 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78377C17DBA85D003B9FC0 /* libz.dylib */; };
-               AF7F54A517DC24A300CE1158 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78377C17DBA85D003B9FC0 /* libz.dylib */; };
-               AF7F54A617DC24B500CE1158 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78377C17DBA85D003B9FC0 /* libz.dylib */; };
-               AF84AF1F15829AF000607E4C /* SaverListController.m in Sources */ = {isa = PBXBuildFile; fileRef = AF84AF1E15829AF000607E4C /* SaverListController.m */; };
                AF84AF2015829AF000607E4C /* SaverListController.m in Sources */ = {isa = PBXBuildFile; fileRef = AF84AF1E15829AF000607E4C /* SaverListController.m */; };
                AF84FD4209B1209E00F3AB06 /* GLUT.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF84FD4109B1209E00F3AB06 /* GLUT.framework */; };
                AF918983158FC00A002B5D1E /* iSaverRunner.xib in Resources */ = {isa = PBXBuildFile; fileRef = AF56019B157DAA3D00DB2055 /* iSaverRunner.xib */; };
                AF9D4DF509B5BB19006E59CF /* apple2.c in Sources */ = {isa = PBXBuildFile; fileRef = AF9D4DD309B5B990006E59CF /* apple2.c */; };
                AF9D4E0409B5BC85006E59CF /* apple2.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFC2586F0988A468000655EE /* apple2.xml */; };
                AF9D4E0609B5BC9D006E59CF /* apple2-main.c in Sources */ = {isa = PBXBuildFile; fileRef = AF9D4E0509B5BC9D006E59CF /* apple2-main.c */; };
-               AF9D4E2209B63413006E59CF /* jwxyz-timers.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9D4E2109B63413006E59CF /* jwxyz-timers.m */; };
                AF9E7EC9190F4C4000A8B01F /* enable_gc.c in Sources */ = {isa = PBXBuildFile; fileRef = AF9E7EC8190F4C4000A8B01F /* enable_gc.c */; };
+               AFA211891CD1AA2E00C0D2A1 /* textclient-mobile.c in Sources */ = {isa = PBXBuildFile; fileRef = AFA211881CD1AA1800C0D2A1 /* textclient-mobile.c */; };
+               AFA2118A1CD1AA3A00C0D2A1 /* textclient-mobile.c in Sources */ = {isa = PBXBuildFile; fileRef = AFA211881CD1AA1800C0D2A1 /* textclient-mobile.c */; };
+               AFA2118B1CD1AA3F00C0D2A1 /* textclient-mobile.c in Sources */ = {isa = PBXBuildFile; fileRef = AFA211881CD1AA1800C0D2A1 /* textclient-mobile.c */; };
+               AFA211931CD59DAF00C0D2A1 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AFA211951CD59DAF00C0D2A1 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AFA211961CD59DAF00C0D2A1 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AFA211971CD59DAF00C0D2A1 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AFA211981CD59DAF00C0D2A1 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AFA211991CD59DAF00C0D2A1 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AFA2119A1CD59DAF00C0D2A1 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AFA2119B1CD59DAF00C0D2A1 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AFA211A51CD5A00F00C0D2A1 /* raverhoop.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFA211A41CD59FD800C0D2A1 /* raverhoop.xml */; };
+               AFA211A61CD5A02600C0D2A1 /* raverhoop.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFA211A41CD59FD800C0D2A1 /* raverhoop.xml */; };
+               AFA211A71CD5A03F00C0D2A1 /* raverhoop.c in Sources */ = {isa = PBXBuildFile; fileRef = AFA211A31CD59FD800C0D2A1 /* raverhoop.c */; };
+               AFA211A81CD5A04300C0D2A1 /* raverhoop.c in Sources */ = {isa = PBXBuildFile; fileRef = AFA211A31CD59FD800C0D2A1 /* raverhoop.c */; settings = {COMPILER_FLAGS = "-DUSE_GL"; }; };
                AFA339350B058505002B0E7D /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
                AFA33BAF0B0585F7002B0E7D /* webcollage-cocoa.m in Sources */ = {isa = PBXBuildFile; fileRef = AFA33BAE0B0585F7002B0E7D /* webcollage-cocoa.m */; };
                AFA33BB00B05860F002B0E7D /* webcollage.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFC2592C0988A469000655EE /* webcollage.xml */; };
                AFA5638F0993980D00F3E977 /* timetunnel.c in Sources */ = {isa = PBXBuildFile; fileRef = AFA5638E0993980D00F3E977 /* timetunnel.c */; };
                AFA563B8099398F700F3E977 /* juggler3d.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFC258D10988A468000655EE /* juggler3d.xml */; };
                AFA563BA0993991300F3E977 /* juggler3d.c in Sources */ = {isa = PBXBuildFile; fileRef = AFA563B90993991300F3E977 /* juggler3d.c */; };
-               AFAA6B2D1773870700DE720C /* apple2-main.c in Sources */ = {isa = PBXBuildFile; fileRef = AF9D4E0509B5BC9D006E59CF /* apple2-main.c */; };
-               AFAA6B2E1773870700DE720C /* apple2.c in Sources */ = {isa = PBXBuildFile; fileRef = AF9D4DD309B5B990006E59CF /* apple2.c */; };
-               AFAA6B2F1773871900DE720C /* analogtv.c in Sources */ = {isa = PBXBuildFile; fileRef = AF9D4CFA09B5AC94006E59CF /* analogtv.c */; };
-               AFAA6B301773876900DE720C /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3A1590054B003974F3 /* OpenGLES.framework */; };
-               AFAA6B311773876E00DE720C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3815900514003974F3 /* UIKit.framework */; };
-               AFAA6B321773877300DE720C /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF561DF715969C5B007CA5ED /* AssetsLibrary.framework */; };
-               AFAA6B331773877800DE720C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3C15900558003974F3 /* Foundation.framework */; };
-               AFAA6B341773877C00DE720C /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3E1590056A003974F3 /* CoreGraphics.framework */; };
-               AFAA6B351773878000DE720C /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF0FAF3B159BAC7B00BCE2F7 /* CoreText.framework */; };
-               AFAA6B361773878400DE720C /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3F1590056A003974F3 /* QuartzCore.framework */; };
-               AFAA6B3B1773926C00DE720C /* phosphor.c in Sources */ = {isa = PBXBuildFile; fileRef = AF77770309B63B5F00EA3033 /* phosphor.c */; };
-               AFAA6B3D177392DD00DE720C /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3A1590054B003974F3 /* OpenGLES.framework */; };
-               AFAA6B3E177392E000DE720C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3815900514003974F3 /* UIKit.framework */; };
-               AFAA6B3F177392E400DE720C /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF561DF715969C5B007CA5ED /* AssetsLibrary.framework */; };
-               AFAA6B40177392E800DE720C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3C15900558003974F3 /* Foundation.framework */; };
-               AFAA6B41177392EC00DE720C /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3E1590056A003974F3 /* CoreGraphics.framework */; };
-               AFAA6B42177392F000DE720C /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF0FAF3B159BAC7B00BCE2F7 /* CoreText.framework */; };
-               AFAA6B43177392F600DE720C /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3F1590056A003974F3 /* QuartzCore.framework */; };
                AFAA6B451773F07800DE720C /* ios-function-table.m in Sources */ = {isa = PBXBuildFile; fileRef = AFAA6B441773F07700DE720C /* ios-function-table.m */; };
-               AFAA6B461773F30500DE720C /* ios-function-table.m in Sources */ = {isa = PBXBuildFile; fileRef = AFAA6B441773F07700DE720C /* ios-function-table.m */; };
-               AFAA6B471773F35600DE720C /* ios-function-table.m in Sources */ = {isa = PBXBuildFile; fileRef = AFAA6B441773F07700DE720C /* ios-function-table.m */; };
+               AFACE87A1CC83458008B24CD /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AFACE87C1CC83458008B24CD /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AFACE87D1CC83458008B24CD /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AFACE87E1CC83458008B24CD /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AFACE87F1CC83458008B24CD /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AFACE8801CC83458008B24CD /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AFACE8811CC83458008B24CD /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AFACE8821CC83458008B24CD /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AFACE88C1CC835F7008B24CD /* energystream.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFACE88B1CC83578008B24CD /* energystream.xml */; };
+               AFACE88D1CC83608008B24CD /* energystream.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFACE88B1CC83578008B24CD /* energystream.xml */; };
+               AFACE88E1CC83613008B24CD /* energystream.c in Sources */ = {isa = PBXBuildFile; fileRef = AFACE88A1CC83578008B24CD /* energystream.c */; };
+               AFACE88F1CC83617008B24CD /* energystream.c in Sources */ = {isa = PBXBuildFile; fileRef = AFACE88A1CC83578008B24CD /* energystream.c */; settings = {COMPILER_FLAGS = "-DUSE_GL"; }; };
                AFAD462309D5F4DA00AB5F95 /* grabclient.c in Sources */ = {isa = PBXBuildFile; fileRef = AFAD462209D5F4DA00AB5F95 /* grabclient.c */; };
                AFB591AE178B812C00EA4005 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
                AFB591B0178B812C00EA4005 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
                AFBFE778178647FE00432B21 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
                AFBFE779178647FE00432B21 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
                AFBFE7831786483B00432B21 /* Phosphor.saver in Resources */ = {isa = PBXBuildFile; fileRef = AF7776F609B63ABF00EA3033 /* Phosphor.saver */; };
-               AFBFE78B17895CD000432B21 /* apple2.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFC2586F0988A468000655EE /* apple2.xml */; };
+               AFC0E8B21CDC601A008CAFAC /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AFC0E8B41CDC601A008CAFAC /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AFC0E8B51CDC601A008CAFAC /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AFC0E8B61CDC601A008CAFAC /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AFC0E8B71CDC601A008CAFAC /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AFC0E8B81CDC601A008CAFAC /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AFC0E8B91CDC601A008CAFAC /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AFC0E8BA1CDC601A008CAFAC /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AFC0E8C41CDC60B0008CAFAC /* hydrostat.c in Sources */ = {isa = PBXBuildFile; fileRef = AFC0E8C21CDC60A9008CAFAC /* hydrostat.c */; settings = {COMPILER_FLAGS = "-DUSE_GL"; }; };
+               AFC0E8C51CDC60D6008CAFAC /* hydrostat.c in Sources */ = {isa = PBXBuildFile; fileRef = AFC0E8C21CDC60A9008CAFAC /* hydrostat.c */; };
+               AFC0E8C61CDC60DB008CAFAC /* hydrostat.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFC0E8C31CDC60A9008CAFAC /* hydrostat.xml */; };
+               AFC0E8C71CDC60DE008CAFAC /* hydrostat.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFC0E8C31CDC60A9008CAFAC /* hydrostat.xml */; };
                AFC211950E4E30C800D87B6E /* teapot.c in Sources */ = {isa = PBXBuildFile; fileRef = AFC211930E4E30C800D87B6E /* teapot.c */; };
+               AFC43E741C68364B00C89999 /* PxPlus_IBM_VGA8.ttf in Resources */ = {isa = PBXBuildFile; fileRef = AFC43E731C68364B00C89999 /* PxPlus_IBM_VGA8.ttf */; };
+               AFC43E771C684BE400C89999 /* PxPlus_IBM_VGA8.ttf in Resources */ = {isa = PBXBuildFile; fileRef = AFC43E731C68364B00C89999 /* PxPlus_IBM_VGA8.ttf */; };
+               AFC43E7B1C6AA77900C89999 /* YearlReg.ttf in Resources */ = {isa = PBXBuildFile; fileRef = AFEC68381BD6CDF9004C1B64 /* YearlReg.ttf */; };
+               AFC43E7C1C6AA78800C89999 /* OCRAStd.otf in Resources */ = {isa = PBXBuildFile; fileRef = AFEC68361BD6CA85004C1B64 /* OCRAStd.otf */; };
                AFC7592D158D8E8B00C5458E /* textclient.c in Sources */ = {isa = PBXBuildFile; fileRef = AFC7592B158D8E8B00C5458E /* textclient.c */; };
                AFC7592E158D8E8B00C5458E /* textclient.h in Headers */ = {isa = PBXBuildFile; fileRef = AFC7592C158D8E8B00C5458E /* textclient.h */; };
-               AFC75930158D9A7A00C5458E /* iostextclient.m in Sources */ = {isa = PBXBuildFile; fileRef = AFC7592F158D9A7A00C5458E /* iostextclient.m */; };
+               AFC75930158D9A7A00C5458E /* textclient-iOS.m in Sources */ = {isa = PBXBuildFile; fileRef = AFC7592F158D9A7A00C5458E /* textclient-iOS.m */; };
                AFCCCBB009BFE4B000353F4D /* rdbomb.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFCCCBAD09BFE4B000353F4D /* rdbomb.xml */; };
                AFCCCBB309BFE51900353F4D /* thornbird.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFC259230988A469000655EE /* thornbird.xml */; };
                AFCF453715986A2100E6E8CC /* dnalogo.c in Sources */ = {isa = PBXBuildFile; fileRef = AF77787609B653DC00EA3033 /* dnalogo.c */; settings = {COMPILER_FLAGS = "-DUSE_GL"; }; };
                AFEB9C3D15900558003974F3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3C15900558003974F3 /* Foundation.framework */; };
                AFEB9C401590056A003974F3 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3E1590056A003974F3 /* CoreGraphics.framework */; };
                AFEB9C411590056A003974F3 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFEB9C3F1590056A003974F3 /* QuartzCore.framework */; };
+               AFEC23D41CB6EAE100DE138F /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AFEC23D61CB6EAE100DE138F /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AFEC23D71CB6EAE100DE138F /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AFEC23D81CB6EAE100DE138F /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AFEC23D91CB6EAE100DE138F /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AFEC23DA1CB6EAE100DE138F /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AFEC23DB1CB6EAE100DE138F /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AFEC23DC1CB6EAE100DE138F /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AFEC23E61CB6EC0400DE138F /* dymaxionmap.c in Sources */ = {isa = PBXBuildFile; fileRef = AFEC23E41CB6EBC400DE138F /* dymaxionmap.c */; };
+               AFEC23E71CB6EC0B00DE138F /* dymaxionmap.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFEC23E51CB6EBDA00DE138F /* dymaxionmap.xml */; };
+               AFEC23E81CB6EC6800DE138F /* dymaxionmap.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFEC23E51CB6EBDA00DE138F /* dymaxionmap.xml */; };
+               AFEC23E91CB6EC7F00DE138F /* dymaxionmap.c in Sources */ = {isa = PBXBuildFile; fileRef = AFEC23E41CB6EBC400DE138F /* dymaxionmap.c */; settings = {COMPILER_FLAGS = "-DUSE_GL"; }; };
                AFEC68371BD6CA85004C1B64 /* OCRAStd.otf in Resources */ = {isa = PBXBuildFile; fileRef = AFEC68361BD6CA85004C1B64 /* OCRAStd.otf */; };
                AFEC68391BD6CDF9004C1B64 /* YearlReg.ttf in Resources */ = {isa = PBXBuildFile; fileRef = AFEC68381BD6CDF9004C1B64 /* YearlReg.ttf */; };
                AFF1BA0F19A96D8B0016A88D /* lament_model.c in Sources */ = {isa = PBXBuildFile; fileRef = AFF1BA0E19A96D8B0016A88D /* lament_model.c */; };
                CE3D01601B76F4C100993C75 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
                CE3D01691B76F88A00993C75 /* testx11.xml in Resources */ = {isa = PBXBuildFile; fileRef = CE3D01681B76F83E00993C75 /* testx11.xml */; };
                CE3D016B1B76F93700993C75 /* testx11.c in Sources */ = {isa = PBXBuildFile; fileRef = CE3D016A1B76F8E200993C75 /* testx11.c */; };
-               CE3D016C1B76FEB100993C75 /* testx11.xml in Resources */ = {isa = PBXBuildFile; fileRef = CE3D01681B76F83E00993C75 /* testx11.xml */; };
-               CE3D016D1B76FF1600993C75 /* testx11.c in Sources */ = {isa = PBXBuildFile; fileRef = CE3D016A1B76F8E200993C75 /* testx11.c */; };
+               CE43C2BF1C055157004C2BC6 /* jwxyz-cocoa.m in Sources */ = {isa = PBXBuildFile; fileRef = CE43C2BE1C055157004C2BC6 /* jwxyz-cocoa.m */; };
+               CE55645A1C25141000645458 /* jwxyz-gl.c in Sources */ = {isa = PBXBuildFile; fileRef = CE5564591C25141000645458 /* jwxyz-gl.c */; };
+               CE8EA1C21C35CF10002D1020 /* jwxyz-common.c in Sources */ = {isa = PBXBuildFile; fileRef = CE8EA1C11C35CF10002D1020 /* jwxyz-common.c */; };
                CE9289D319BD00E300961F22 /* async_netdb.c in Sources */ = {isa = PBXBuildFile; fileRef = CE9289D119BD00E200961F22 /* async_netdb.c */; };
                CE9289D419BD00E300961F22 /* async_netdb.h in Headers */ = {isa = PBXBuildFile; fileRef = CE9289D219BD00E300961F22 /* async_netdb.h */; };
                CEE0BC621A6B0D6200C098BF /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
                        remoteGlobalIDString = AF1A17610D6D6EE3008AF328;
                        remoteInfo = LCDscrub;
                };
-               AF2D4D8113E902F5002AA818 /* PBXContainerItemProxy */ = {
-                       isa = PBXContainerItemProxy;
-                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
-                       proxyType = 1;
-                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
-                       remoteInfo = jwxyz;
-               };
-               AF2D4D9D13E90347002AA818 /* PBXContainerItemProxy */ = {
-                       isa = PBXContainerItemProxy;
-                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
-                       proxyType = 1;
-                       remoteGlobalIDString = AF7776E409B63ABF00EA3033;
-                       remoteInfo = Phosphor;
-               };
-               AF2D4F6C13E91093002AA818 /* PBXContainerItemProxy */ = {
-                       isa = PBXContainerItemProxy;
-                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
-                       proxyType = 1;
-                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
-                       remoteInfo = jwxyz;
-               };
-               AF2D4F8E13E91127002AA818 /* PBXContainerItemProxy */ = {
-                       isa = PBXContainerItemProxy;
-                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
-                       proxyType = 1;
-                       remoteGlobalIDString = AF9D4DEC09B5BB19006E59CF;
-                       remoteInfo = Apple2;
-               };
                AF32D9E20F3AD0B40080F535 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        remoteGlobalIDString = AFE30BE80E52B14700CCF4A5;
                        remoteInfo = Sonar;
                };
+               AF46E9D11CBBA2B300240FBC /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AF46E9EC1CBBA49A00240FBC /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF46E9CF1CBBA2B300240FBC;
+                       remoteInfo = Unicrud;
+               };
                AF476FB7099D154F001F091E /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        remoteGlobalIDString = AF63A7F11AB4EDDB00593C75;
                        remoteInfo = RomanBoy;
                };
+               AF63F2491C3465BE0033E133 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AF63F24B1C3465BE0033E133 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4FF4930D52CA0800666F98;
+                       remoteInfo = m6502.h;
+               };
+               AF63F24D1C3465BE0033E133 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AFA56119099378CB00F3E977;
+                       remoteInfo = molecules.h;
+               };
+               AF63F4521C34682A0033E133 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AF63F4541C34682A0033E133 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4FF4930D52CA0800666F98;
+                       remoteInfo = m6502.h;
+               };
+               AF63F4561C34682A0033E133 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AFA56119099378CB00F3E977;
+                       remoteInfo = molecules.h;
+               };
+               AF63F47A1C3469FC0033E133 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AF63F47C1C3469FC0033E133 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4FF4930D52CA0800666F98;
+                       remoteInfo = m6502.h;
+               };
+               AF63F47E1C3469FC0033E133 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AFA56119099378CB00F3E977;
+                       remoteInfo = molecules.h;
+               };
                AF6423F4099FF9C2000F4CD4 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        remoteGlobalIDString = AF64260F09A18D6C000F4CD4;
                        remoteInfo = HyperBall;
                };
+               AFA2118E1CD59DAF00C0D2A1 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AFA211A91CD5A08000C0D2A1 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AFA2118C1CD59DAF00C0D2A1;
+                       remoteInfo = RaverHoop;
+               };
                AFA339300B058505002B0E7D /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
                        remoteInfo = jwxyz;
                };
+               AFACE8751CC83458008B24CD /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AFACE8901CC8365F008B24CD /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AFACE8731CC83458008B24CD;
+                       remoteInfo = EnergyStream;
+               };
                AFB581AF102F363300342B11 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        remoteGlobalIDString = AFBFE767178647FE00432B21;
                        remoteInfo = "Phosphor-OSX";
                };
+               AFC0E8AD1CDC601A008CAFAC /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AFC0E8C81CDC6125008CAFAC /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AFC0E8AB1CDC601A008CAFAC;
+                       remoteInfo = Hydrostat;
+               };
                AFCAD5F80992DFE00009617A /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        remoteGlobalIDString = AFE6A41B0CDD7FAA002805BF;
                        remoteInfo = Abstractile;
                };
+               AFEC23CF1CB6EAE100DE138F /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AFEC23EA1CB6ED0800DE138F /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AFEC23CD1CB6EAE100DE138F;
+                       remoteInfo = DymaxionMap;
+               };
                AFF2868117860E830050A578 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                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; };
-               AF2D4D8F13E902F5002AA818 /* Phosphor.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Phosphor.app; sourceTree = BUILT_PRODUCTS_DIR; };
-               AF2D4F7E13E91093002AA818 /* Apple2.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Apple2.app; sourceTree = BUILT_PRODUCTS_DIR; };
                AF2D522513E954A0002AA818 /* SaverRunner.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = SaverRunner.icns; sourceTree = "<group>"; };
+               AF2D8F301CEBA10300198014 /* jwxyz-timers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "jwxyz-timers.c"; path = "../jwxyz/jwxyz-timers.c"; sourceTree = "<group>"; };
+               AF2D8F311CEBA10300198014 /* jwxyz-timers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "jwxyz-timers.h"; path = "../jwxyz/jwxyz-timers.h"; sourceTree = "<group>"; };
                AF32D9F40F3AD0B40080F535 /* RubikBlocks.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RubikBlocks.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AF32D9FA0F3AD1200080F535 /* rubikblocks.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = rubikblocks.c; path = hacks/glx/rubikblocks.c; sourceTree = "<group>"; };
                AF32D9FC0F3AD1330080F535 /* rubikblocks.xml */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.xml; path = rubikblocks.xml; sourceTree = "<group>"; };
                AF3C71590D624BF50030CC0D /* Hypnowheel.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Hypnowheel.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AF3C715D0D624C600030CC0D /* hypnowheel.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = hypnowheel.c; path = hacks/glx/hypnowheel.c; sourceTree = "<group>"; };
                AF3C715F0D624C7C0030CC0D /* hypnowheel.xml */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.xml; path = hypnowheel.xml; sourceTree = "<group>"; };
+               AF46E9E41CBBA2B300240FBC /* Unicrud.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Unicrud.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AF46E9E61CBBA3F900240FBC /* unicrud.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = unicrud.xml; sourceTree = "<group>"; };
+               AF46E9E71CBBA3F900240FBC /* unicrud.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = unicrud.c; path = hacks/glx/unicrud.c; sourceTree = "<group>"; };
                AF476FC6099D154F001F091E /* Interference.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Interference.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AF476FD0099D15AA001F091E /* interference.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = interference.c; path = hacks/interference.c; sourceTree = "<group>"; };
                AF476FEB099D1686001F091E /* Truchet.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Truchet.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AF5C9B0D1A0CCE6E00B0147A /* Cityflow.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Cityflow.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AF5C9B0F1A0CCF4E00B0147A /* cityflow.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = cityflow.xml; sourceTree = "<group>"; };
                AF5C9B101A0CCF4E00B0147A /* cityflow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cityflow.c; path = hacks/glx/cityflow.c; sourceTree = "<group>"; };
-               AF6048F8157C07C600CA21E4 /* jwzgles.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = jwzgles.c; path = ../hacks/glx/jwzgles.c; sourceTree = "<group>"; };
-               AF6048F9157C07C600CA21E4 /* jwzgles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = jwzgles.h; path = ../hacks/glx/jwzgles.h; sourceTree = "<group>"; };
-               AF6048FA157C07C600CA21E4 /* jwzglesI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = jwzglesI.h; path = ../hacks/glx/jwzglesI.h; sourceTree = "<group>"; };
+               AF6048F8157C07C600CA21E4 /* jwzgles.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = jwzgles.c; path = ../jwxyz/jwzgles.c; sourceTree = "<group>"; };
+               AF6048F9157C07C600CA21E4 /* jwzgles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = jwzgles.h; path = ../jwxyz/jwzgles.h; sourceTree = "<group>"; };
+               AF6048FA157C07C600CA21E4 /* jwzglesI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = jwzglesI.h; path = ../jwxyz/jwzglesI.h; sourceTree = "<group>"; };
                AF63A8061AB4EDDB00593C75 /* RomanBoy.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RomanBoy.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AF63A8081AB4EF5D00593C75 /* romanboy.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = romanboy.xml; sourceTree = "<group>"; };
                AF63A8091AB4EF5D00593C75 /* romanboy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = romanboy.c; path = hacks/glx/romanboy.c; sourceTree = "<group>"; };
+               AF63F44E1C3465BE0033E133 /* Apple2.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Apple2.app; sourceTree = BUILT_PRODUCTS_DIR; };
+               AF63F4741C34682A0033E133 /* Phosphor.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Phosphor.app; sourceTree = BUILT_PRODUCTS_DIR; };
+               AF63F49A1C3469FC0033E133 /* TestX11.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TestX11.app; sourceTree = BUILT_PRODUCTS_DIR; };
                AF642405099FF9C2000F4CD4 /* Extrusion.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Extrusion.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AF642409099FFAF0000F4CD4 /* extrusion-helix2.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = "extrusion-helix2.c"; path = "hacks/glx/extrusion-helix2.c"; sourceTree = "<group>"; };
                AF64240A099FFAF0000F4CD4 /* extrusion-helix3.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = "extrusion-helix3.c"; path = "hacks/glx/extrusion-helix3.c"; sourceTree = "<group>"; };
                AF9D4DD309B5B990006E59CF /* apple2.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = apple2.c; path = hacks/apple2.c; sourceTree = "<group>"; };
                AF9D4DFE09B5BB19006E59CF /* Apple2.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Apple2.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AF9D4E0509B5BC9D006E59CF /* apple2-main.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = "apple2-main.c"; path = "hacks/apple2-main.c"; sourceTree = "<group>"; };
-               AF9D4E2109B63413006E59CF /* jwxyz-timers.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = "jwxyz-timers.m"; sourceTree = "<group>"; };
                AF9E7EBF190F4C1B00A8B01F /* enable_gc */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = enable_gc; sourceTree = BUILT_PRODUCTS_DIR; };
                AF9E7EC8190F4C4000A8B01F /* enable_gc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = enable_gc.c; sourceTree = "<group>"; };
+               AFA211881CD1AA1800C0D2A1 /* textclient-mobile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "textclient-mobile.c"; path = "utils/textclient-mobile.c"; sourceTree = "<group>"; };
+               AFA211A11CD59DAF00C0D2A1 /* RaverHoop.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RaverHoop.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AFA211A31CD59FD800C0D2A1 /* raverhoop.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = raverhoop.c; path = hacks/glx/raverhoop.c; sourceTree = "<group>"; };
+               AFA211A41CD59FD800C0D2A1 /* raverhoop.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = raverhoop.xml; sourceTree = "<group>"; };
                AFA339400B058505002B0E7D /* WebCollage.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = WebCollage.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AFA33BAE0B0585F7002B0E7D /* webcollage-cocoa.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; name = "webcollage-cocoa.m"; path = "hacks/webcollage-cocoa.m"; sourceTree = "<group>"; };
                AFA33BC70B058740002B0E7D /* webcollage-helper */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "webcollage-helper"; sourceTree = BUILT_PRODUCTS_DIR; };
                AFA563B6099398BB00F3E977 /* Juggler3D.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Juggler3D.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AFA563B90993991300F3E977 /* juggler3d.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = juggler3d.c; path = hacks/glx/juggler3d.c; sourceTree = "<group>"; };
                AFAA6B441773F07700DE720C /* ios-function-table.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "ios-function-table.m"; sourceTree = "<group>"; };
+               AFACE8881CC83458008B24CD /* EnergyStream.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = EnergyStream.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AFACE88A1CC83578008B24CD /* energystream.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = energystream.c; path = hacks/glx/energystream.c; sourceTree = "<group>"; };
+               AFACE88B1CC83578008B24CD /* energystream.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = energystream.xml; sourceTree = "<group>"; };
                AFAD462209D5F4DA00AB5F95 /* grabclient.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = grabclient.c; path = utils/grabclient.c; sourceTree = "<group>"; };
                AFB591BA178B812C00EA4005 /* Hexadrop.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Hexadrop.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AFB591BC178B81E600EA4005 /* hexadrop.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = hexadrop.xml; sourceTree = "<group>"; };
                AFBF89B10E424036006A2D66 /* fpsI.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; name = fpsI.h; path = hacks/fpsI.h; sourceTree = "<group>"; };
                AFBFE75E178642DC00432B21 /* Apple2.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Apple2.app; sourceTree = BUILT_PRODUCTS_DIR; };
                AFBFE77E178647FE00432B21 /* Phosphor.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Phosphor.app; sourceTree = BUILT_PRODUCTS_DIR; };
+               AFC0E8C01CDC601A008CAFAC /* Hydrostat.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Hydrostat.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AFC0E8C21CDC60A9008CAFAC /* hydrostat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = hydrostat.c; path = hacks/glx/hydrostat.c; sourceTree = "<group>"; };
+               AFC0E8C31CDC60A9008CAFAC /* hydrostat.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = hydrostat.xml; sourceTree = "<group>"; };
                AFC211930E4E30C800D87B6E /* teapot.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = teapot.c; path = hacks/glx/teapot.c; sourceTree = "<group>"; };
                AFC211940E4E30C800D87B6E /* teapot.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; name = teapot.h; path = hacks/glx/teapot.h; sourceTree = "<group>"; };
                AFC254B909873AF9000655EE /* screenhackI.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; name = screenhackI.h; path = hacks/screenhackI.h; sourceTree = "<group>"; };
                AFC25B5E0988BA63000655EE /* deco.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = deco.c; path = hacks/deco.c; sourceTree = "<group>"; };
                AFC25B990988BC08000655EE /* colors.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = colors.c; path = utils/colors.c; sourceTree = "<group>"; };
                AFC25B9A0988BC08000655EE /* colors.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; name = colors.h; path = utils/colors.h; sourceTree = "<group>"; };
+               AFC43E731C68364B00C89999 /* PxPlus_IBM_VGA8.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = PxPlus_IBM_VGA8.ttf; sourceTree = "<group>"; };
                AFC7592B158D8E8B00C5458E /* textclient.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = textclient.c; path = utils/textclient.c; sourceTree = "<group>"; };
                AFC7592C158D8E8B00C5458E /* textclient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = textclient.h; path = utils/textclient.h; sourceTree = "<group>"; };
-               AFC7592F158D9A7A00C5458E /* iostextclient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = iostextclient.m; sourceTree = "<group>"; };
+               AFC7592F158D9A7A00C5458E /* textclient-iOS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "textclient-iOS.m"; path = "OSX/textclient-iOS.m"; sourceTree = "<group>"; };
                AFCCCBAD09BFE4B000353F4D /* rdbomb.xml */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.xml; path = rdbomb.xml; sourceTree = "<group>"; };
                AFCF83501AF5B515008BB7E1 /* SplitFlap.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SplitFlap.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AFCF83521AF5B5FD008BB7E1 /* splitflap.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = splitflap.xml; sourceTree = "<group>"; };
                AFE1FD400981E32E00F7970E /* SaverRunner.m */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.objc; path = SaverRunner.m; sourceTree = "<group>"; };
                AFE1FD410981E32E00F7970E /* InvertedSlider.h */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.h; path = InvertedSlider.h; sourceTree = "<group>"; };
                AFE1FD420981E32E00F7970E /* InvertedSlider.m */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.objc; path = InvertedSlider.m; sourceTree = "<group>"; };
-               AFE1FD430981E32E00F7970E /* jwxyz.h */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.h; path = jwxyz.h; sourceTree = "<group>"; };
-               AFE1FD440981E32E00F7970E /* jwxyz.m */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.objc; path = jwxyz.m; sourceTree = "<group>"; };
+               AFE1FD430981E32E00F7970E /* jwxyz.h */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.h; name = jwxyz.h; path = ../jwxyz/jwxyz.h; sourceTree = "<group>"; };
+               AFE1FD440981E32E00F7970E /* jwxyz.m */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.objc; path = ../jwxyz/jwxyz.m; sourceTree = "<group>"; };
                AFE1FD470981E32E00F7970E /* PrefsReader.h */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.h; path = PrefsReader.h; sourceTree = "<group>"; };
                AFE1FD480981E32E00F7970E /* PrefsReader.m */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.objc; path = PrefsReader.m; sourceTree = "<group>"; };
                AFE1FD530981E3CB00F7970E /* erase.c */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.c; name = erase.c; path = utils/erase.c; sourceTree = "<group>"; };
                AFEB9C3C15900558003974F3 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
                AFEB9C3E1590056A003974F3 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; };
                AFEB9C3F1590056A003974F3 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; };
+               AFEC23E21CB6EAE100DE138F /* DymaxionMap.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DymaxionMap.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AFEC23E41CB6EBC400DE138F /* dymaxionmap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dymaxionmap.c; path = hacks/glx/dymaxionmap.c; sourceTree = "<group>"; };
+               AFEC23E51CB6EBDA00DE138F /* dymaxionmap.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = dymaxionmap.xml; sourceTree = "<group>"; };
                AFEC68361BD6CA85004C1B64 /* OCRAStd.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = OCRAStd.otf; sourceTree = "<group>"; };
                AFEC68381BD6CDF9004C1B64 /* YearlReg.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = YearlReg.ttf; sourceTree = "<group>"; };
                AFF1BA0E19A96D8B0016A88D /* lament_model.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = lament_model.c; path = hacks/glx/lament_model.c; sourceTree = "<group>"; };
                CE3D01661B76F4C100993C75 /* TestX11.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TestX11.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                CE3D01681B76F83E00993C75 /* testx11.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = testx11.xml; sourceTree = "<group>"; };
                CE3D016A1B76F8E200993C75 /* testx11.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = testx11.c; path = hacks/testx11.c; sourceTree = "<group>"; };
+               CE43C2BE1C055157004C2BC6 /* jwxyz-cocoa.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "../jwxyz/jwxyz-cocoa.m"; sourceTree = "<group>"; };
+               CE5564591C25141000645458 /* jwxyz-gl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "jwxyz-gl.c"; path = "../jwxyz/jwxyz-gl.c"; sourceTree = "<group>"; };
+               CE8206741B89048800E35532 /* jwxyz-cocoa.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "../jwxyz/jwxyz-cocoa.h"; sourceTree = "<group>"; };
+               CE8C49CC1C011CC400BA2DCF /* jwxyzI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jwxyzI.h; path = ../jwxyz/jwxyzI.h; sourceTree = "<group>"; };
+               CE8EA1C11C35CF10002D1020 /* jwxyz-common.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "jwxyz-common.c"; path = "../jwxyz/jwxyz-common.c"; sourceTree = "<group>"; };
                CE9289D119BD00E200961F22 /* async_netdb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = async_netdb.c; path = utils/async_netdb.c; sourceTree = "<group>"; };
                CE9289D219BD00E300961F22 /* async_netdb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = async_netdb.h; path = utils/async_netdb.h; sourceTree = "<group>"; };
                CEAF85661ABE4A70008F104C /* SaverListController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SaverListController.h; sourceTree = "<group>"; };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
-               AF2D4D8813E902F5002AA818 /* Frameworks */ = {
-                       isa = PBXFrameworksBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               AF1FD7F3158FF96500C40F17 /* libjwxyz.a in Frameworks */,
-                               AFAA6B3D177392DD00DE720C /* OpenGLES.framework in Frameworks */,
-                               AFAA6B3E177392E000DE720C /* UIKit.framework in Frameworks */,
-                               AFAA6B3F177392E400DE720C /* AssetsLibrary.framework in Frameworks */,
-                               AFAA6B40177392E800DE720C /* Foundation.framework in Frameworks */,
-                               AFAA6B41177392EC00DE720C /* CoreGraphics.framework in Frameworks */,
-                               AFAA6B42177392F000DE720C /* CoreText.framework in Frameworks */,
-                               AFAA6B43177392F600DE720C /* QuartzCore.framework in Frameworks */,
-                               AF7F54A617DC24B500CE1158 /* libz.dylib in Frameworks */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               AF2D4F7713E91093002AA818 /* Frameworks */ = {
-                       isa = PBXFrameworksBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               AF1FD723158FF96500C40F17 /* libjwxyz.a in Frameworks */,
-                               AFAA6B301773876900DE720C /* OpenGLES.framework in Frameworks */,
-                               AFAA6B311773876E00DE720C /* UIKit.framework in Frameworks */,
-                               AFAA6B321773877300DE720C /* AssetsLibrary.framework in Frameworks */,
-                               AFAA6B331773877800DE720C /* Foundation.framework in Frameworks */,
-                               AFAA6B341773877C00DE720C /* CoreGraphics.framework in Frameworks */,
-                               AFAA6B351773878000DE720C /* CoreText.framework in Frameworks */,
-                               AFAA6B361773878400DE720C /* QuartzCore.framework in Frameworks */,
-                               AF7F54A517DC24A300CE1158 /* libz.dylib in Frameworks */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
                AF32D9E80F3AD0B40080F535 /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF46E9D71CBBA2B300240FBC /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF46E9D81CBBA2B300240FBC /* libjwxyz.a in Frameworks */,
+                               AF46E9D91CBBA2B300240FBC /* ScreenSaver.framework in Frameworks */,
+                               AF46E9DA1CBBA2B300240FBC /* QuartzCore.framework in Frameworks */,
+                               AF46E9DB1CBBA2B300240FBC /* Cocoa.framework in Frameworks */,
+                               AF46E9DC1CBBA2B300240FBC /* Carbon.framework in Frameworks */,
+                               AF46E9DD1CBBA2B300240FBC /* OpenGL.framework in Frameworks */,
+                               AF46E9DE1CBBA2B300240FBC /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF476FBE099D154F001F091E /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF63F4401C3465BE0033E133 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF63F4411C3465BE0033E133 /* libjwxyz.a in Frameworks */,
+                               AF63F4421C3465BE0033E133 /* OpenGLES.framework in Frameworks */,
+                               AF63F4431C3465BE0033E133 /* UIKit.framework in Frameworks */,
+                               AF63F4441C3465BE0033E133 /* AssetsLibrary.framework in Frameworks */,
+                               AF63F4451C3465BE0033E133 /* Foundation.framework in Frameworks */,
+                               AF63F4461C3465BE0033E133 /* CoreGraphics.framework in Frameworks */,
+                               AF63F4471C3465BE0033E133 /* CoreText.framework in Frameworks */,
+                               AF63F4481C3465BE0033E133 /* QuartzCore.framework in Frameworks */,
+                               AF63F4491C3465BE0033E133 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF63F4661C34682A0033E133 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF63F4671C34682A0033E133 /* libjwxyz.a in Frameworks */,
+                               AF63F4681C34682A0033E133 /* OpenGLES.framework in Frameworks */,
+                               AF63F4691C34682A0033E133 /* UIKit.framework in Frameworks */,
+                               AF63F46A1C34682A0033E133 /* AssetsLibrary.framework in Frameworks */,
+                               AF63F46B1C34682A0033E133 /* Foundation.framework in Frameworks */,
+                               AF63F46C1C34682A0033E133 /* CoreGraphics.framework in Frameworks */,
+                               AF63F46D1C34682A0033E133 /* CoreText.framework in Frameworks */,
+                               AF63F46E1C34682A0033E133 /* QuartzCore.framework in Frameworks */,
+                               AF63F46F1C34682A0033E133 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF63F48C1C3469FC0033E133 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF63F48D1C3469FC0033E133 /* libjwxyz.a in Frameworks */,
+                               AF63F48E1C3469FC0033E133 /* OpenGLES.framework in Frameworks */,
+                               AF63F48F1C3469FC0033E133 /* UIKit.framework in Frameworks */,
+                               AF63F4901C3469FC0033E133 /* AssetsLibrary.framework in Frameworks */,
+                               AF63F4911C3469FC0033E133 /* Foundation.framework in Frameworks */,
+                               AF63F4921C3469FC0033E133 /* CoreGraphics.framework in Frameworks */,
+                               AF63F4931C3469FC0033E133 /* CoreText.framework in Frameworks */,
+                               AF63F4941C3469FC0033E133 /* QuartzCore.framework in Frameworks */,
+                               AF63F4951C3469FC0033E133 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF6423FA099FF9C2000F4CD4 /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFA211941CD59DAF00C0D2A1 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFA211951CD59DAF00C0D2A1 /* libjwxyz.a in Frameworks */,
+                               AFA211961CD59DAF00C0D2A1 /* ScreenSaver.framework in Frameworks */,
+                               AFA211971CD59DAF00C0D2A1 /* QuartzCore.framework in Frameworks */,
+                               AFA211981CD59DAF00C0D2A1 /* Cocoa.framework in Frameworks */,
+                               AFA211991CD59DAF00C0D2A1 /* Carbon.framework in Frameworks */,
+                               AFA2119A1CD59DAF00C0D2A1 /* OpenGL.framework in Frameworks */,
+                               AFA2119B1CD59DAF00C0D2A1 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFA339370B058505002B0E7D /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFACE87B1CC83458008B24CD /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFACE87C1CC83458008B24CD /* libjwxyz.a in Frameworks */,
+                               AFACE87D1CC83458008B24CD /* ScreenSaver.framework in Frameworks */,
+                               AFACE87E1CC83458008B24CD /* QuartzCore.framework in Frameworks */,
+                               AFACE87F1CC83458008B24CD /* Cocoa.framework in Frameworks */,
+                               AFACE8801CC83458008B24CD /* Carbon.framework in Frameworks */,
+                               AFACE8811CC83458008B24CD /* OpenGL.framework in Frameworks */,
+                               AFACE8821CC83458008B24CD /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFB591AF178B812C00EA4005 /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFC0E8B31CDC601A008CAFAC /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFC0E8B41CDC601A008CAFAC /* libjwxyz.a in Frameworks */,
+                               AFC0E8B51CDC601A008CAFAC /* ScreenSaver.framework in Frameworks */,
+                               AFC0E8B61CDC601A008CAFAC /* QuartzCore.framework in Frameworks */,
+                               AFC0E8B71CDC601A008CAFAC /* Cocoa.framework in Frameworks */,
+                               AFC0E8B81CDC601A008CAFAC /* Carbon.framework in Frameworks */,
+                               AFC0E8B91CDC601A008CAFAC /* OpenGL.framework in Frameworks */,
+                               AFC0E8BA1CDC601A008CAFAC /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFCF83431AF5B515008BB7E1 /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFEC23D51CB6EAE100DE138F /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFEC23D61CB6EAE100DE138F /* libjwxyz.a in Frameworks */,
+                               AFEC23D71CB6EAE100DE138F /* ScreenSaver.framework in Frameworks */,
+                               AFEC23D81CB6EAE100DE138F /* QuartzCore.framework in Frameworks */,
+                               AFEC23D91CB6EAE100DE138F /* Cocoa.framework in Frameworks */,
+                               AFEC23DA1CB6EAE100DE138F /* Carbon.framework in Frameworks */,
+                               AFEC23DB1CB6EAE100DE138F /* OpenGL.framework in Frameworks */,
+                               AFEC23DC1CB6EAE100DE138F /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFF2868717860E830050A578 /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        isa = PBXGroup;
                        children = (
                                AF561DF515969BC3007CA5ED /* iosgrabimage.m */,
-                               AFC7592F158D9A7A00C5458E /* iostextclient.m */,
                                AFE1FD410981E32E00F7970E /* InvertedSlider.h */,
                                AFE1FD420981E32E00F7970E /* InvertedSlider.m */,
-                               AF9D4E2109B63413006E59CF /* jwxyz-timers.m */,
+                               AF2D8F301CEBA10300198014 /* jwxyz-timers.c */,
+                               AF2D8F311CEBA10300198014 /* jwxyz-timers.h */,
                                AFE1FD430981E32E00F7970E /* jwxyz.h */,
                                AFE1FD440981E32E00F7970E /* jwxyz.m */,
+                               CE8C49CC1C011CC400BA2DCF /* jwxyzI.h */,
+                               CE8206741B89048800E35532 /* jwxyz-cocoa.h */,
+                               CE43C2BE1C055157004C2BC6 /* jwxyz-cocoa.m */,
+                               CE8EA1C11C35CF10002D1020 /* jwxyz-common.c */,
+                               CE5564591C25141000645458 /* jwxyz-gl.c */,
                                AF6048F8157C07C600CA21E4 /* jwzgles.c */,
                                AF6048F9157C07C600CA21E4 /* jwzgles.h */,
                                AF6048FA157C07C600CA21E4 /* jwzglesI.h */,
                                AFD51B300F063B4A00471C02 /* Photopile.saver */,
                                AF32D9F40F3AD0B40080F535 /* RubikBlocks.saver */,
                                AF4A345D102A593600A81B2A /* Surfaces.saver */,
-                               AF2D4D8F13E902F5002AA818 /* Phosphor.app */,
-                               AF2D4F7E13E91093002AA818 /* Apple2.app */,
                                AF78D189142DD8F3002AAF77 /* Hilbert.saver */,
                                AF3581D51431D47B00E09C51 /* CompanionCube.saver */,
                                AF358216143330F900E09C51 /* TronBit.saver */,
                                AF63A8061AB4EDDB00593C75 /* RomanBoy.saver */,
                                AFCF83501AF5B515008BB7E1 /* SplitFlap.saver */,
                                CE3D01661B76F4C100993C75 /* TestX11.saver */,
+                               AF63F44E1C3465BE0033E133 /* Apple2.app */,
+                               AF63F4741C34682A0033E133 /* Phosphor.app */,
+                               AF63F49A1C3469FC0033E133 /* TestX11.app */,
+                               AFEC23E21CB6EAE100DE138F /* DymaxionMap.saver */,
+                               AF46E9E41CBBA2B300240FBC /* Unicrud.saver */,
+                               AFACE8881CC83458008B24CD /* EnergyStream.saver */,
+                               AFA211A11CD59DAF00C0D2A1 /* RaverHoop.saver */,
+                               AFC0E8C01CDC601A008CAFAC /* Hydrostat.saver */,
                        );
                        name = Products;
                        path = ..;
                                AF0FAF0B09CA6FF900EE1051 /* xscreensaver-text */,
                                AFEC68361BD6CA85004C1B64 /* OCRAStd.otf */,
                                AFEC68381BD6CDF9004C1B64 /* YearlReg.ttf */,
+                               AFC43E731C68364B00C89999 /* PxPlus_IBM_VGA8.ttf */,
                        );
                        name = Resources;
                        sourceTree = "<group>";
                                AF0839AA09930C4900277BE9 /* dolphin.c */,
                                AF241F81107C38DF00046A84 /* dropshadow.c */,
                                AF241F82107C38DF00046A84 /* dropshadow.h */,
+                               AFEC23E41CB6EBC400DE138F /* dymaxionmap.c */,
                                AF7778C109B65C6A00EA3033 /* e_textures.h */,
                                AFA55E2509935F2B00F3E977 /* endgame.c */,
+                               AFACE88A1CC83578008B24CD /* energystream.c */,
                                AFA55C230993435300F3E977 /* engine.c */,
                                AF642409099FFAF0000F4CD4 /* extrusion-helix2.c */,
                                AF64240A099FFAF0000F4CD4 /* extrusion-helix3.c */,
                                AFA55C8C099349EE00F3E977 /* glsnake.c */,
                                AFD56E080996A07A00BA26F7 /* gltext.c */,
                                AF78D18A142DD96E002AAF77 /* hilbert.c */,
+                               AFC0E8C21CDC60A9008CAFAC /* hydrostat.c */,
                                AFA55F59099362DF00F3E977 /* hypertorus.c */,
                                AF3C715D0D624C600030CC0D /* hypnowheel.c */,
                                AFE6A16A0CDD78EA002805BF /* involute.c */,
                                AFA55B3F09933EC600F3E977 /* pulsar.c */,
                                AFF28695178611720050A578 /* quasicrystal.c */,
                                AFA55E0609935EB800F3E977 /* queens.c */,
+                               AFA211A31CD59FD800C0D2A1 /* raverhoop.c */,
                                AFBE743F19A7C6930018AA35 /* robot.c */,
                                AF39E2A0198A13F50064A58D /* robot-wireframe.c */,
                                AF63A8091AB4EF5D00593C75 /* romanboy.c */,
                                AF998EF80A083E750051049D /* topblock.c */,
                                AF083A58099312B000277BE9 /* tunnel_draw.c */,
                                AF083A5D099312DB00277BE9 /* tunnel_draw.h */,
+                               AF46E9E71CBBA3F900240FBC /* unicrud.c */,
                                AFDA65A4178A541A0070D24B /* unknownpleasures.c */,
                                AF0DCA5F0C4CBB7300D76972 /* voronoi.c */,
                                AF0839AD09930C4900277BE9 /* whale.c */,
                                AFC258980988A468000655EE /* distort.xml */,
                                AF77787909B6545E00EA3033 /* dnalogo.xml */,
                                AFC258990988A468000655EE /* drift.xml */,
+                               AFEC23E51CB6EBDA00DE138F /* dymaxionmap.xml */,
                                AFC2589B0988A468000655EE /* endgame.xml */,
+                               AFACE88B1CC83578008B24CD /* energystream.xml */,
                                AFC2589C0988A468000655EE /* engine.xml */,
                                AFC2589D0988A468000655EE /* epicycle.xml */,
                                AFC2589E0988A468000655EE /* eruption.xml */,
                                AF78D18E142DD99A002AAF77 /* hilbert.xml */,
                                AFC258C50988A468000655EE /* hopalong.xml */,
                                AFC258C60988A468000655EE /* hyperball.xml */,
+                               AFC0E8C31CDC60A9008CAFAC /* hydrostat.xml */,
                                AFC258C70988A468000655EE /* hypercube.xml */,
                                AFC258C80988A468000655EE /* hypertorus.xml */,
                                AF3C715F0D624C7C0030CC0D /* hypnowheel.xml */,
                                AFC258FF0988A469000655EE /* qix.xml */,
                                AFF28694178611720050A578 /* quasicrystal.xml */,
                                AFC259000988A469000655EE /* queens.xml */,
+                               AFA211A41CD59FD800C0D2A1 /* raverhoop.xml */,
                                AFCCCBAD09BFE4B000353F4D /* rdbomb.xml */,
                                AFC259030988A469000655EE /* ripples.xml */,
                                AFC259040988A469000655EE /* rocks.xml */,
                                AFC259280988A469000655EE /* vermiculate.xml */,
                                AFC259290988A469000655EE /* vidwhacker.xml */,
                                AFC2592A0988A469000655EE /* vines.xml */,
+                               AF46E9E61CBBA3F900240FBC /* unicrud.xml */,
                                AFDA65A3178A541A0070D24B /* unknownpleasures.xml */,
                                AF0DCA610C4CBB8E00D76972 /* voronoi.xml */,
                                AFC2592B0988A469000655EE /* wander.xml */,
                                AF77780909B64F4900EA3033 /* texfont.h */,
                                AFC7592B158D8E8B00C5458E /* textclient.c */,
                                AFC7592C158D8E8B00C5458E /* textclient.h */,
+                               AFC7592F158D9A7A00C5458E /* textclient-iOS.m */,
+                               AFA211881CD1AA1800C0D2A1 /* textclient-mobile.c */,
                                AFDA11231934424D003D397F /* thread_util.c */,
                                AFDA11241934424D003D397F /* thread_util.h */,
                                AF480EAD098F63BE00FB32B8 /* trackball.c */,
                                AF975C94099C929800B05160 /* xpm-pixmap.h in Headers */,
                                AF4775C1099D9E79001F091E /* resources.h in Headers */,
                                AF9D473909B52EE0006E59CF /* colorbars.h in Headers */,
+                               AF2D8F331CEBA10300198014 /* jwxyz-timers.h in Headers */,
                                AFDA11261934424D003D397F /* aligned_malloc.h in Headers */,
                                AFDA11281934424D003D397F /* thread_util.h in Headers */,
                                AFBF893F0E41D930006A2D66 /* fps.h in Headers */,
                        productReference = AF1AD9E218500F9F00932759 /* XScreenSaverUpdater.app */;
                        productType = "com.apple.product-type.application";
                };
-               AF2D4D7F13E902F5002AA818 /* Phosphor-iOS */ = {
-                       isa = PBXNativeTarget;
-                       buildConfigurationList = AF2D4D8C13E902F5002AA818 /* Build configuration list for PBXNativeTarget "Phosphor-iOS" */;
-                       buildPhases = (
-                               AF2D4D8213E902F5002AA818 /* Resources */,
-                               AF2D4D8513E902F5002AA818 /* Sources */,
-                               AF2D4D8813E902F5002AA818 /* Frameworks */,
-                               AF2D51F413E94AC4002AA818 /* Run Update Info Plist */,
-                       );
-                       buildRules = (
-                       );
-                       dependencies = (
-                               AF2D4D8013E902F5002AA818 /* PBXTargetDependency */,
-                               AF2D4D9E13E90347002AA818 /* PBXTargetDependency */,
-                       );
-                       name = "Phosphor-iOS";
-                       productName = PhosphorApp;
-                       productReference = AF2D4D8F13E902F5002AA818 /* Phosphor.app */;
-                       productType = "com.apple.product-type.application";
-               };
-               AF2D4F6A13E91093002AA818 /* Apple2-iOS */ = {
-                       isa = PBXNativeTarget;
-                       buildConfigurationList = AF2D4F7B13E91093002AA818 /* Build configuration list for PBXNativeTarget "Apple2-iOS" */;
-                       buildPhases = (
-                               AF2D4F6F13E91093002AA818 /* Resources */,
-                               AF2D4F7413E91093002AA818 /* Sources */,
-                               AF2D4F7713E91093002AA818 /* Frameworks */,
-                               AF2D51FD13E94B2D002AA818 /* Run Update Info Plist */,
-                       );
-                       buildRules = (
-                       );
-                       dependencies = (
-                               AF2D4F6B13E91093002AA818 /* PBXTargetDependency */,
-                               AF2D4F8F13E91127002AA818 /* PBXTargetDependency */,
-                       );
-                       name = "Apple2-iOS";
-                       productName = Apple2App;
-                       productReference = AF2D4F7E13E91093002AA818 /* Apple2.app */;
-                       productType = "com.apple.product-type.application";
-               };
                AF32D9E00F3AD0B40080F535 /* RubikBlocks */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = AF32D9F10F3AD0B40080F535 /* Build configuration list for PBXNativeTarget "RubikBlocks" */;
                        productReference = AF3C71590D624BF50030CC0D /* Hypnowheel.saver */;
                        productType = "com.apple.product-type.bundle";
                };
+               AF46E9CF1CBBA2B300240FBC /* Unicrud */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AF46E9E11CBBA2B300240FBC /* Build configuration list for PBXNativeTarget "Unicrud" */;
+                       buildPhases = (
+                               AF46E9D21CBBA2B300240FBC /* Resources */,
+                               AF46E9D41CBBA2B300240FBC /* Sources */,
+                               AF46E9D71CBBA2B300240FBC /* Frameworks */,
+                               AF46E9DF1CBBA2B300240FBC /* Rez */,
+                               AF46E9E01CBBA2B300240FBC /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AF46E9D01CBBA2B300240FBC /* PBXTargetDependency */,
+                       );
+                       name = Unicrud;
+                       productName = DangerBall;
+                       productReference = AF46E9E41CBBA2B300240FBC /* Unicrud.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
                AF476FB5099D154F001F091E /* Interference */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = AF476FC3099D154F001F091E /* Build configuration list for PBXNativeTarget "Interference" */;
                        productReference = AF63A8061AB4EDDB00593C75 /* RomanBoy.saver */;
                        productType = "com.apple.product-type.bundle";
                };
+               AF63F2471C3465BE0033E133 /* Apple2-iOS */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AF63F44B1C3465BE0033E133 /* Build configuration list for PBXNativeTarget "Apple2-iOS" */;
+                       buildPhases = (
+                               AF63F24F1C3465BE0033E133 /* Update Function Table */,
+                               AF63F2501C3465BE0033E133 /* Resources */,
+                               AF63F3271C3465BE0033E133 /* Sources */,
+                               AF63F4401C3465BE0033E133 /* Frameworks */,
+                               AF63F44A1C3465BE0033E133 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AF63F2481C3465BE0033E133 /* PBXTargetDependency */,
+                               AF63F24A1C3465BE0033E133 /* PBXTargetDependency */,
+                               AF63F24C1C3465BE0033E133 /* PBXTargetDependency */,
+                       );
+                       name = "Apple2-iOS";
+                       productName = SaverTester;
+                       productReference = AF63F44E1C3465BE0033E133 /* Apple2.app */;
+                       productType = "com.apple.product-type.application";
+               };
+               AF63F4501C34682A0033E133 /* Phosphor-iOS */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AF63F4711C34682A0033E133 /* Build configuration list for PBXNativeTarget "Phosphor-iOS" */;
+                       buildPhases = (
+                               AF63F4571C34682A0033E133 /* Update Function Table */,
+                               AF63F4581C34682A0033E133 /* Resources */,
+                               AF63F45E1C34682A0033E133 /* Sources */,
+                               AF63F4661C34682A0033E133 /* Frameworks */,
+                               AF63F4701C34682A0033E133 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AF63F4511C34682A0033E133 /* PBXTargetDependency */,
+                               AF63F4531C34682A0033E133 /* PBXTargetDependency */,
+                               AF63F4551C34682A0033E133 /* PBXTargetDependency */,
+                       );
+                       name = "Phosphor-iOS";
+                       productName = SaverTester;
+                       productReference = AF63F4741C34682A0033E133 /* Phosphor.app */;
+                       productType = "com.apple.product-type.application";
+               };
+               AF63F4781C3469FC0033E133 /* TestX11-iOS */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AF63F4971C3469FC0033E133 /* Build configuration list for PBXNativeTarget "TestX11-iOS" */;
+                       buildPhases = (
+                               AF63F47F1C3469FC0033E133 /* Update Function Table */,
+                               AF63F4801C3469FC0033E133 /* Resources */,
+                               AF63F4861C3469FC0033E133 /* Sources */,
+                               AF63F48C1C3469FC0033E133 /* Frameworks */,
+                               AF63F4961C3469FC0033E133 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AF63F4791C3469FC0033E133 /* PBXTargetDependency */,
+                               AF63F47B1C3469FC0033E133 /* PBXTargetDependency */,
+                               AF63F47D1C3469FC0033E133 /* PBXTargetDependency */,
+                       );
+                       name = "TestX11-iOS";
+                       productName = SaverTester;
+                       productReference = AF63F49A1C3469FC0033E133 /* TestX11.app */;
+                       productType = "com.apple.product-type.application";
+               };
                AF6423F2099FF9C2000F4CD4 /* Extrusion */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = AF642402099FF9C2000F4CD4 /* Build configuration list for PBXNativeTarget "Extrusion" */;
                        productReference = AF9E7EBF190F4C1B00A8B01F /* enable_gc */;
                        productType = "com.apple.product-type.tool";
                };
+               AFA2118C1CD59DAF00C0D2A1 /* RaverHoop */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AFA2119E1CD59DAF00C0D2A1 /* Build configuration list for PBXNativeTarget "RaverHoop" */;
+                       buildPhases = (
+                               AFA2118F1CD59DAF00C0D2A1 /* Resources */,
+                               AFA211911CD59DAF00C0D2A1 /* Sources */,
+                               AFA211941CD59DAF00C0D2A1 /* Frameworks */,
+                               AFA2119C1CD59DAF00C0D2A1 /* Rez */,
+                               AFA2119D1CD59DAF00C0D2A1 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AFA2118D1CD59DAF00C0D2A1 /* PBXTargetDependency */,
+                       );
+                       name = RaverHoop;
+                       productName = DangerBall;
+                       productReference = AFA211A11CD59DAF00C0D2A1 /* RaverHoop.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
                AFA3392E0B058505002B0E7D /* WebCollage */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = AFA3393D0B058505002B0E7D /* Build configuration list for PBXNativeTarget "WebCollage" */;
                        productReference = AFA563B6099398BB00F3E977 /* Juggler3D.saver */;
                        productType = "com.apple.product-type.bundle";
                };
+               AFACE8731CC83458008B24CD /* EnergyStream */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AFACE8851CC83458008B24CD /* Build configuration list for PBXNativeTarget "EnergyStream" */;
+                       buildPhases = (
+                               AFACE8761CC83458008B24CD /* Resources */,
+                               AFACE8781CC83458008B24CD /* Sources */,
+                               AFACE87B1CC83458008B24CD /* Frameworks */,
+                               AFACE8831CC83458008B24CD /* Rez */,
+                               AFACE8841CC83458008B24CD /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AFACE8741CC83458008B24CD /* PBXTargetDependency */,
+                       );
+                       name = EnergyStream;
+                       productName = DangerBall;
+                       productReference = AFACE8881CC83458008B24CD /* EnergyStream.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
                AFB591A7178B812C00EA4005 /* Hexadrop */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = AFB591B7178B812C00EA4005 /* Build configuration list for PBXNativeTarget "Hexadrop" */;
                        productReference = AFBFE77E178647FE00432B21 /* Phosphor.app */;
                        productType = "com.apple.product-type.application";
                };
+               AFC0E8AB1CDC601A008CAFAC /* Hydrostat */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AFC0E8BD1CDC601A008CAFAC /* Build configuration list for PBXNativeTarget "Hydrostat" */;
+                       buildPhases = (
+                               AFC0E8AE1CDC601A008CAFAC /* Resources */,
+                               AFC0E8B01CDC601A008CAFAC /* Sources */,
+                               AFC0E8B31CDC601A008CAFAC /* Frameworks */,
+                               AFC0E8BB1CDC601A008CAFAC /* Rez */,
+                               AFC0E8BC1CDC601A008CAFAC /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AFC0E8AC1CDC601A008CAFAC /* PBXTargetDependency */,
+                       );
+                       name = Hydrostat;
+                       productName = DangerBall;
+                       productReference = AFC0E8C01CDC601A008CAFAC /* Hydrostat.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
                AFCF833B1AF5B515008BB7E1 /* SplitFlap */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = AFCF834D1AF5B515008BB7E1 /* Build configuration list for PBXNativeTarget "SplitFlap" */;
                        productReference = AFE6A42D0CDD7FAA002805BF /* Abstractile.saver */;
                        productType = "com.apple.product-type.bundle";
                };
+               AFEC23CD1CB6EAE100DE138F /* DymaxionMap */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AFEC23DF1CB6EAE100DE138F /* Build configuration list for PBXNativeTarget "DymaxionMap" */;
+                       buildPhases = (
+                               AFEC23D01CB6EAE100DE138F /* Resources */,
+                               AFEC23D21CB6EAE100DE138F /* Sources */,
+                               AFEC23D51CB6EAE100DE138F /* Frameworks */,
+                               AFEC23DD1CB6EAE100DE138F /* Rez */,
+                               AFEC23DE1CB6EAE100DE138F /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AFEC23CE1CB6EAE100DE138F /* PBXTargetDependency */,
+                       );
+                       name = DymaxionMap;
+                       productName = DangerBall;
+                       productReference = AFEC23E21CB6EAE100DE138F /* DymaxionMap.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
                AFF2867F17860E830050A578 /* QuasiCrystal */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = AFF2868F17860E830050A578 /* Build configuration list for PBXNativeTarget "QuasiCrystal" */;
                29B97313FDCFA39411CA2CEA /* Project object */ = {
                        isa = PBXProject;
                        attributes = {
-                               LastUpgradeCheck = 0620;
+                               LastUpgradeCheck = 0730;
                                TargetAttributes = {
                                        AF918977158FC00A002B5D1E = {
                                                DevelopmentTeam = 4627ATJELP;
                                AF47721E099D4F67001F091E /* Anemone */,
                                AF4773C1099D67B9001F091E /* Anemotaxis */,
                                AF9D4DEC09B5BB19006E59CF /* Apple2 */,
-                               AF2D4F6A13E91093002AA818 /* Apple2-iOS */,
+                               AF63F2471C3465BE0033E133 /* Apple2-iOS */,
                                AFBFE74B178642DC00432B21 /* Apple2-OSX */,
                                AF9770660989D2F6001F8B92 /* Attraction */,
                                AF975A86099C6BC300B05160 /* Barcode */,
                                AF4778AB099DDB79001F091E /* Penetrate */,
                                AF477670099DA849001F091E /* Petri */,
                                AF7776E409B63ABF00EA3033 /* Phosphor */,
-                               AF2D4D7F13E902F5002AA818 /* Phosphor-iOS */,
+                               AF63F4501C34682A0033E133 /* Phosphor-iOS */,
                                AFBFE767178647FE00432B21 /* Phosphor-OSX */,
                                AF477283099D5926001F091E /* Piecewise */,
                                AF9D4CE709B5AA8E006E59CF /* Pong */,
                                AF47759F099D9CF7001F091E /* Starfish */,
                                AF477723099DB044001F091E /* Substrate */,
                                AF68A47E19196CF800D41CD1 /* Tessellimage */,
-                               CE3D01511B76F4C100993C75 /* TestX11 */,
                                AF476FDA099D1686001F091E /* Truchet */,
                                AF9D496C09B5411D006E59CF /* Twang */,
                                AF4776F1099DAE7A001F091E /* Vermiculate */,
                                AF4FF4BA0D52CBDE00666F98 /* CubicGrid */,
                                AF4810EB09909FBA00FB32B8 /* DangerBall */,
                                AF77786109B6536000EA3033 /* DNAlogo */,
+                               AFEC23CD1CB6EAE100DE138F /* DymaxionMap */,
+                               AFACE8731CC83458008B24CD /* EnergyStream */,
                                AFA55E0D09935EDC00F3E977 /* Endgame */,
                                AFA55C0E0993431300F3E977 /* Engine */,
                                AF6423F2099FF9C2000F4CD4 /* Extrusion */,
                                AFA55C77099349A600F3E977 /* GLSnake */,
                                AFD56DF10996A03800BA26F7 /* GLText */,
                                AF78D175142DD8F3002AAF77 /* Hilbert */,
+                               AFC0E8AB1CDC601A008CAFAC /* Hydrostat */,
                                AFA55F420993629000F3E977 /* Hypertorus */,
                                AF3C71450D624BF50030CC0D /* Hypnowheel */,
                                AFA55F06099361B700F3E977 /* JigglyPuff */,
                                AFA55B2509933E8D00F3E977 /* Pulsar */,
                                AFF2867F17860E830050A578 /* QuasiCrystal */,
                                AFA55DF009935E4900F3E977 /* Queens */,
+                               AFA2118C1CD59DAF00C0D2A1 /* RaverHoop */,
                                AF63A7F11AB4EDDB00593C75 /* RomanBoy */,
                                AFA559CF0993330600F3E977 /* Rubik */,
                                AF32D9E00F3AD0B40080F535 /* RubikBlocks */,
                                AFA56379099397B300F3E977 /* TimeTunnel */,
                                AF998EDA0A083DB30051049D /* TopBlock */,
                                AF3581FB143330F900E09C51 /* TronBit */,
+                               AF46E9CF1CBBA2B300240FBC /* Unicrud */,
                                AFDA658E178A52B70070D24B /* Unknown Pleasures */,
                                AF0DCA420C4CBB0D00D76972 /* Voronoi */,
                                AF39E282198A11F60064A58D /* WindupRobot */,
                                AFD570260996B56D00BA26F7 /* Sphere */,
                                AFD570430996B61600BA26F7 /* Spiral */,
                                AF4771A7099D4949001F091E /* T3D */,
+                               CE3D01511B76F4C100993C75 /* TestX11 */,
+                               AF63F4781C3469FC0033E133 /* TestX11-iOS */,
                                AFD56F0B0996AAFA00BA26F7 /* Vines */,
                                AF477208099D4EE8001F091E /* Whirlygig */,
                                AFD5709B0996B88E00BA26F7 /* Worm */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
-               AF2D4D8213E902F5002AA818 /* Resources */ = {
-                       isa = PBXResourcesBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               AF51FD3715845F9F00E5741F /* iSaverRunner.xib in Resources */,
-                               55EDCB3F1AD49DFE00251909 /* LaunchScreen.xib in Resources */,
-                               550FB5FF1AD64424001A4FA5 /* Media-iOS.xcassets in Resources */,
-                               AF51FD3415845CD500E5741F /* phosphor.xml in Resources */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               AF2D4F6F13E91093002AA818 /* Resources */ = {
-                       isa = PBXResourcesBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               AF51FD3615845F9900E5741F /* iSaverRunner.xib in Resources */,
-                               55EDCB3E1AD49DFA00251909 /* LaunchScreen.xib in Resources */,
-                               550FB5FE1AD64424001A4FA5 /* Media-iOS.xcassets in Resources */,
-                               AFBFE78B17895CD000432B21 /* apple2.xml in Resources */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
                AF32D9E30F3AD0B40080F535 /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF46E9D21CBBA2B300240FBC /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF46E9E81CBBA41600240FBC /* unicrud.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF476FB8099D154F001F091E /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF63F2501C3465BE0033E133 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF63F2511C3465BE0033E133 /* iSaverRunner.xib in Resources */,
+                               AF63F2521C3465BE0033E133 /* LaunchScreen.xib in Resources */,
+                               AF63F2531C3465BE0033E133 /* iSaverRunner57t.png in Resources */,
+                               AF63F25D1C3465BE0033E133 /* apple2.xml in Resources */,
+                               AF63F2B71C3465BE0033E133 /* Media-iOS.xcassets in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF63F4581C34682A0033E133 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF63F4591C34682A0033E133 /* iSaverRunner.xib in Resources */,
+                               AF63F45A1C34682A0033E133 /* LaunchScreen.xib in Resources */,
+                               AF63F45B1C34682A0033E133 /* iSaverRunner57t.png in Resources */,
+                               AF63F4761C3469410033E133 /* phosphor.xml in Resources */,
+                               AF63F45D1C34682A0033E133 /* Media-iOS.xcassets in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF63F4801C3469FC0033E133 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF63F4811C3469FC0033E133 /* iSaverRunner.xib in Resources */,
+                               AF63F4821C3469FC0033E133 /* LaunchScreen.xib in Resources */,
+                               AF63F4831C3469FC0033E133 /* iSaverRunner57t.png in Resources */,
+                               AF63F49C1C346B0A0033E133 /* testx11.xml in Resources */,
+                               AF63F4851C3469FC0033E133 /* Media-iOS.xcassets in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF6423F5099FF9C2000F4CD4 /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        buildActionMask = 2147483647;
                        files = (
                                AF77787A09B6545E00EA3033 /* dnalogo.xml in Resources */,
+                               AFC43E7B1C6AA77900C89999 /* YearlReg.ttf in Resources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        buildActionMask = 2147483647;
                        files = (
                                AF918983158FC00A002B5D1E /* iSaverRunner.xib in Resources */,
-                               55EDCB3D1AD498A800251909 /* LaunchScreen.xib in Resources */,
                                AF73FF211A08AB9400E485E9 /* iSaverRunner57t.png in Resources */,
+                               55EDCB3D1AD498A800251909 /* LaunchScreen.xib in Resources */,
+                               550FB6001AD64424001A4FA5 /* Media-iOS.xcassets in Resources */,
                                AFEC68371BD6CA85004C1B64 /* OCRAStd.otf in Resources */,
+                               AFC43E741C68364B00C89999 /* PxPlus_IBM_VGA8.ttf in Resources */,
                                AFEC68391BD6CDF9004C1B64 /* YearlReg.ttf in Resources */,
                                AF918AB4158FC53D002B5D1E /* abstractile.xml in Resources */,
                                AF918AB5158FC53D002B5D1E /* anemone.xml in Resources */,
                                AF918AE6158FC53D002B5D1E /* discrete.xml in Resources */,
                                AF918AE7158FC53D002B5D1E /* distort.xml in Resources */,
                                AFCF453815986A3000E6E8CC /* dnalogo.xml in Resources */,
+                               AFEC23E81CB6EC6800DE138F /* dymaxionmap.xml in Resources */,
                                AF918AE9158FC53D002B5D1E /* drift.xml in Resources */,
                                AF918AEA158FC53D002B5D1E /* endgame.xml in Resources */,
+                               AFACE88C1CC835F7008B24CD /* energystream.xml in Resources */,
                                AF918AEB158FC53D002B5D1E /* engine.xml in Resources */,
                                AF918AEC158FC53D002B5D1E /* epicycle.xml in Resources */,
                                AF918AED158FC53D002B5D1E /* eruption.xml in Resources */,
                                AF918AFF158FC53D002B5D1E /* galaxy.xml in Resources */,
                                AF918B00158FC53D002B5D1E /* gears.xml in Resources */,
                                AFF3C9FF17CCAD9A0028F240 /* geodesic.xml in Resources */,
+                               AF7ACFDA19FF0BA600BD752B /* geodesicgears.xml in Resources */,
                                AF918B01158FC53D002B5D1E /* gflux.xml in Resources */,
                                AF918B02158FC53D002B5D1E /* glblur.xml in Resources */,
                                AF918B03158FC53D002B5D1E /* glcells.xml in Resources */,
                                AFB591BF178B81E600EA4005 /* hexadrop.xml in Resources */,
                                AF918B14158FC53D002B5D1E /* hilbert.xml in Resources */,
                                AF918B15158FC53D002B5D1E /* hopalong.xml in Resources */,
+                               AFC0E8C71CDC60DE008CAFAC /* hydrostat.xml in Resources */,
                                AF918B18158FC53D002B5D1E /* hypertorus.xml in Resources */,
                                AF918B19158FC53D002B5D1E /* hypnowheel.xml in Resources */,
                                AF918B1A158FC53D002B5D1E /* ifs.xml in Resources */,
-                               550FB6001AD64424001A4FA5 /* Media-iOS.xcassets in Resources */,
                                AF918B1B158FC53D002B5D1E /* imsmap.xml in Resources */,
                                AF918B1C158FC53D002B5D1E /* interaggregate.xml in Resources */,
                                AF918B1D158FC53D002B5D1E /* interference.xml in Resources */,
                                AF918B34158FC53D002B5D1E /* menger.xml in Resources */,
                                AF918B35158FC53D002B5D1E /* metaballs.xml in Resources */,
                                AF918B36158FC53D002B5D1E /* mirrorblob.xml in Resources */,
-                               AF7ACFDA19FF0BA600BD752B /* geodesicgears.xml in Resources */,
                                AF918B38158FC53D002B5D1E /* moebius.xml in Resources */,
                                AF918B39158FC53D002B5D1E /* moebiusgears.xml in Resources */,
                                AF918B3A158FC53D002B5D1E /* moire.xml in Resources */,
                                AF918B55158FC53E002B5D1E /* qix.xml in Resources */,
                                AFF28697178611720050A578 /* quasicrystal.xml in Resources */,
                                AF918B56158FC53E002B5D1E /* queens.xml in Resources */,
+                               AFA211A51CD5A00F00C0D2A1 /* raverhoop.xml in Resources */,
                                AF918B57158FC53E002B5D1E /* rdbomb.xml in Resources */,
                                AF918B58158FC53E002B5D1E /* ripples.xml in Resources */,
                                AF918B59158FC53E002B5D1E /* rocks.xml in Resources */,
                                AF918B76158FC53E002B5D1E /* swirl.xml in Resources */,
                                AF918B78158FC53E002B5D1E /* tangram.xml in Resources */,
                                AF68A49819196E3E00D41CD1 /* tessellimage.xml in Resources */,
-                               CE3D016C1B76FEB100993C75 /* testx11.xml in Resources */,
                                AF918B79158FC53E002B5D1E /* thornbird.xml in Resources */,
                                AF918B7A158FC53E002B5D1E /* timetunnel.xml in Resources */,
                                AF918B7B158FC53E002B5D1E /* topblock.xml in Resources */,
                                AF918B7E158FC53E002B5D1E /* truchet.xml in Resources */,
                                AF918B7F158FC53E002B5D1E /* twang.xml in Resources */,
                                AF918B80158FC53E002B5D1E /* vermiculate.xml in Resources */,
+                               AF46E9EA1CBBA42F00240FBC /* unicrud.xml in Resources */,
                                AFDA65A6178A541A0070D24B /* unknownpleasures.xml in Resources */,
                                AF918B83158FC53E002B5D1E /* voronoi.xml in Resources */,
                                AF918B84158FC53E002B5D1E /* wander.xml in Resources */,
                        buildActionMask = 2147483647;
                        files = (
                                AF975B16099C70B200B05160 /* memscroller.xml in Resources */,
+                               AFC43E7C1C6AA78800C89999 /* OCRAStd.otf in Resources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        files = (
                                AF9D4DC209B5B862006E59CF /* bsod.xml in Resources */,
                                AF0FAF1709CA712600EE1051 /* xscreensaver-getimage-file in Resources */,
+                               AFC43E771C684BE400C89999 /* PxPlus_IBM_VGA8.ttf in Resources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFA2118F1CD59DAF00C0D2A1 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFA211A61CD5A02600C0D2A1 /* raverhoop.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFA339310B058505002B0E7D /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFACE8761CC83458008B24CD /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFACE88D1CC83608008B24CD /* energystream.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFB591AA178B812C00EA4005 /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFC0E8AE1CDC601A008CAFAC /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFC0E8C61CDC60DB008CAFAC /* hydrostat.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFCF833E1AF5B515008BB7E1 /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFEC23D01CB6EAE100DE138F /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFEC23E71CB6EC0B00DE138F /* dymaxionmap.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFF2868217860E830050A578 /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF46E9DF1CBBA2B300240FBC /* Rez */ = {
+                       isa = PBXRezBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF476FC2099D154F001F091E /* Rez */ = {
                        isa = PBXRezBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFA2119C1CD59DAF00C0D2A1 /* Rez */ = {
+                       isa = PBXRezBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFA3393B0B058505002B0E7D /* Rez */ = {
                        isa = PBXRezBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFACE8831CC83458008B24CD /* Rez */ = {
+                       isa = PBXRezBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFB591B5178B812C00EA4005 /* Rez */ = {
                        isa = PBXRezBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFC0E8BB1CDC601A008CAFAC /* Rez */ = {
+                       isa = PBXRezBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFCF834B1AF5B515008BB7E1 /* Rez */ = {
                        isa = PBXRezBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFEC23DD1CB6EAE100DE138F /* Rez */ = {
+                       isa = PBXRezBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFF2868D17860E830050A578 /* Rez */ = {
                        isa = PBXRezBuildPhase;
                        buildActionMask = 2147483647;
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
-               AF2D51F413E94AC4002AA818 /* Run Update Info Plist */ = {
+               AF32D9F00F3AD0B40080F535 /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
-               AF2D51FD13E94B2D002AA818 /* Run Update Info Plist */ = {
+               AF3581D11431D47B00E09C51 /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
-               AF32D9F00F3AD0B40080F535 /* Run Update Info Plist */ = {
+               AF358212143330F900E09C51 /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
-               AF3581D11431D47B00E09C51 /* Run Update Info Plist */ = {
+               AF35E89C0E63823600691F2F /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
-               AF358212143330F900E09C51 /* Run Update Info Plist */ = {
+               AF39E292198A11F60064A58D /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
-               AF35E89C0E63823600691F2F /* Run Update Info Plist */ = {
+               AF3C71550D624BF50030CC0D /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
-               AF39E292198A11F60064A58D /* Run Update Info Plist */ = {
+               AF46E9E01CBBA2B300240FBC /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
-               AF3C71550D624BF50030CC0D /* Run Update Info Plist */ = {
+               AF48DEFF0A0C25E000F94CF9 /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
-               AF48DEFF0A0C25E000F94CF9 /* Run Update Info Plist */ = {
+               AF4A3459102A593600A81B2A /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
-               AF4A3459102A593600A81B2A /* Run Update Info Plist */ = {
+               AF4E1D1819CE7013002B6190 /* Update GC build settings */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                       );
+                       name = "Update GC build settings";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "#!/bin/sh\n\n# Edit the contents of \"xscreensaver.xcconfig\" based on the running\n# Xcode version.  If we are running Xcode 5.0.2, we *must* turn on GC.\n# If we are running a newer version of Xcode than that, we *cannot*\n# turn on GC.\n\nTMP=`mktemp -t xcode`\nSRC=\"$SRCROOT/xscreensaver.xcconfig\"\nMACOSX_DEPLOYMENT_TARGET=10.7\nOBJC_GC_CFLAGS=\nOBJC_NO_GC_CFLAGS=\nif [ \"$XCODE_VERSION_MAJOR\" -lt \"0600\" ]; then\n  MACOSX_DEPLOYMENT_TARGET=10.4\n  OBJC_GC_CFLAGS=\"-fobjc-gc\"\n  OBJC_NO_GC_CFLAGS=\"-fno-objc-gc\"\nfi\n\nrm -f \"$TMP\"\nsed -e \"s/^\\(MACOSX_DEPLOYMENT_TARGET=\\).*/\\1${MACOSX_DEPLOYMENT_TARGET}/\" \\\n    -e \"s/^\\(OBJC_GC_CFLAGS=\\).*/\\1${OBJC_GC_CFLAGS}/\" \\\n    -e \"s/^\\(OBJC_NO_GC_CFLAGS=\\).*/\\1${OBJC_NO_GC_CFLAGS}/\" \\\n  < $SRC > $TMP\nif ! ( cmp -s \"$SRC\" \"$TMP\" ); then\necho \"$SRC updated:\"\n  diff -U0 \"$SRC\" \"$TMP\"\n  cat \"$TMP\" > \"$SRC\"\nelse\n  echo \"$SRC unchanged\"\nfi\n\nrm -f \"$TMP\"\nexit 0\n";
+                       showEnvVarsInLog = 0;
+               };
+               AF4FD6F60CE7A486005EE58E /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
-               AF4E1D1819CE7013002B6190 /* Update GC build settings */ = {
+               AF4FF4CA0D52CBDE00666F98 /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
                        );
                        inputPaths = (
                        );
-                       name = "Update GC build settings";
+                       name = "Run Update Info Plist";
                        outputPaths = (
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                        shellPath = /bin/sh;
-                       shellScript = "#!/bin/sh\n\n# Edit the contents of \"xscreensaver.xcconfig\" based on the running\n# Xcode version.  If we are running Xcode 5.0.2, we *must* turn on GC.\n# If we are running a newer version of Xcode than that, we *cannot*\n# turn on GC.\n\nTMP=`mktemp -t xcode`\nSRC=\"$SRCROOT/xscreensaver.xcconfig\"\nOBJC_GC_CFLAGS=\nif [ \"$XCODE_VERSION_MAJOR\" -lt \"0600\" ]; then\n  OBJC_GC_CFLAGS=\"-fobjc-gc\"\nfi\n\nrm -f \"$TMP\"\nsed -e \"s/^\\(OBJC_GC_CFLAGS=\\).*/\\1${OBJC_GC_CFLAGS}/\" < $SRC > $TMP\nif ! ( cmp -s \"$SRC\" \"$TMP\" ); then\necho \"$SRC updated:\"\n  diff -U0 \"$SRC\" \"$TMP\"\n  cat \"$TMP\" > \"$SRC\"\nelse\n  echo \"$SRC unchanged\"\nfi\n\nrm -f \"$TMP\"\nexit 0\n";
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
-               AF4FD6F60CE7A486005EE58E /* Run Update Info Plist */ = {
+               AF578FA11434E918002455DD /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
-               AF4FF4CA0D52CBDE00666F98 /* Run Update Info Plist */ = {
+               AF5C9B091A0CCE6E00B0147A /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
-               AF578FA11434E918002455DD /* Run Update Info Plist */ = {
+               AF63A8021AB4EDDB00593C75 /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
-               AF5C9B091A0CCE6E00B0147A /* Run Update Info Plist */ = {
+               AF63F24F1C3465BE0033E133 /* Update Function Table */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                       );
+                       name = "Update Function Table";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/build-fntable.pl $SOURCE_ROOT/ios-function-table.m";
+               };
+               AF63F44A1C3465BE0033E133 /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
-               AF63A8021AB4EDDB00593C75 /* Run Update Info Plist */ = {
+               AF63F4571C34682A0033E133 /* Update Function Table */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                       );
+                       name = "Update Function Table";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/build-fntable.pl $SOURCE_ROOT/ios-function-table.m";
+               };
+               AF63F4701C34682A0033E133 /* 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;
+               };
+               AF63F47F1C3469FC0033E133 /* Update Function Table */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                       );
+                       name = "Update Function Table";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/build-fntable.pl $SOURCE_ROOT/ios-function-table.m";
+               };
+               AF63F4961C3469FC0033E133 /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
+               AFA2119D1CD59DAF00C0D2A1 /* 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;
+               };
                AFA3393C0B058505002B0E7D /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
+               AFACE8841CC83458008B24CD /* 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;
+               };
                AFB591B6178B812C00EA4005 /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        shellPath = /bin/sh;
                        shellScript = "SRC=$SRCROOT/$PRODUCT_NAME-app.xml\nDST=$BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX/Contents/Resources\nNAME=`echo $PRODUCT_NAME.xml | tr A-Z a-z`\ncp -p $SRC $DST/$NAME\nln -sf ../../../$NAME $DST/$PRODUCT_NAME.saver/Contents/Resources/";
                };
+               AFC0E8BC1CDC601A008CAFAC /* 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;
+               };
                AFCCCBB509C033DF00353F4D /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
+               AFEC23DE1CB6EAE100DE138F /* 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;
+               };
                AFF2868E17860E830050A578 /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
-               AF2D4D8513E902F5002AA818 /* Sources */ = {
-                       isa = PBXSourcesBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               AF2D4D8613E902F5002AA818 /* SaverRunner.m in Sources */,
-                               AF2D4D8713E902F5002AA818 /* main.m in Sources */,
-                               AF84AF1F15829AF000607E4C /* SaverListController.m in Sources */,
-                               AFAA6B461773F30500DE720C /* ios-function-table.m in Sources */,
-                               AFAA6B3B1773926C00DE720C /* phosphor.c in Sources */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
-               AF2D4F7413E91093002AA818 /* Sources */ = {
-                       isa = PBXSourcesBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               AF2D4F7513E91093002AA818 /* SaverRunner.m in Sources */,
-                               AF2D4F7613E91093002AA818 /* main.m in Sources */,
-                               AF51FD3515845D1400E5741F /* SaverListController.m in Sources */,
-                               AFAA6B471773F35600DE720C /* ios-function-table.m in Sources */,
-                               AFAA6B2F1773871900DE720C /* analogtv.c in Sources */,
-                               AFAA6B2D1773870700DE720C /* apple2-main.c in Sources */,
-                               AFAA6B2E1773870700DE720C /* apple2.c in Sources */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
                AF32D9E50F3AD0B40080F535 /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        buildActionMask = 2147483647;
                        files = (
                                AF3581C61431D47B00E09C51 /* XScreenSaverSubclass.m in Sources */,
-                               AF3581C71431D47B00E09C51 /* voronoi.c in Sources */,
-                               AF3581C81431D47B00E09C51 /* hilbert.c in Sources */,
                                AF3581DC1431D5FC00E09C51 /* companion_disc.c in Sources */,
                                AF3581DF1431D5FC00E09C51 /* companion_heart.c in Sources */,
                                AF3581E21431D5FC00E09C51 /* companion_quad.c in Sources */,
                        buildActionMask = 2147483647;
                        files = (
                                AF358203143330F900E09C51 /* XScreenSaverSubclass.m in Sources */,
-                               AF358204143330F900E09C51 /* voronoi.c in Sources */,
-                               AF358205143330F900E09C51 /* hilbert.c in Sources */,
-                               AF358206143330F900E09C51 /* companion_disc.c in Sources */,
-                               AF358207143330F900E09C51 /* companion_heart.c in Sources */,
-                               AF358208143330F900E09C51 /* companion_quad.c in Sources */,
-                               AF358209143330F900E09C51 /* companion.c in Sources */,
                                AF35821C1433314C00E09C51 /* tronbit_idle1.c in Sources */,
                                AF35821D1433314C00E09C51 /* tronbit_idle2.c in Sources */,
                                AF35821E1433314C00E09C51 /* tronbit_no.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF46E9D41CBBA2B300240FBC /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF46E9E91CBBA41B00240FBC /* unicrud.c in Sources */,
+                               AF46E9D61CBBA2B300240FBC /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF476FBB099D154F001F091E /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                                AF4808CA098C3BEE00FB32B8 /* PrefsReader.m in Sources */,
                                AFDA11251934424D003D397F /* aligned_malloc.c in Sources */,
                                AF4808CC098C3BF200FB32B8 /* spline.c in Sources */,
+                               AF2D8F321CEBA10300198014 /* jwxyz-timers.c in Sources */,
                                AF4808CD098C3BF400FB32B8 /* usleep.c in Sources */,
+                               CE55645A1C25141000645458 /* jwxyz-gl.c in Sources */,
                                AF4808CE098C3BF800FB32B8 /* XScreenSaverConfigSheet.m in Sources */,
                                AF4808CF098C3BFB00FB32B8 /* XScreenSaverView.m in Sources */,
                                AF4808D0098C3BFD00FB32B8 /* yarandom.c in Sources */,
                                AFA55A95099336D800F3E977 /* normals.c in Sources */,
                                AFDA11271934424D003D397F /* thread_util.c in Sources */,
                                AF975C93099C929800B05160 /* xpm-pixmap.c in Sources */,
+                               CE8EA1C21C35CF10002D1020 /* jwxyz-common.c in Sources */,
                                AF4774E8099D8D8C001F091E /* logo.c in Sources */,
                                AF4775C0099D9E79001F091E /* resources.c in Sources */,
                                AF9D468F09B51567006E59CF /* osxgrabscreen.m in Sources */,
                                AF9D473809B52EE0006E59CF /* colorbars.c in Sources */,
-                               AF9D4E2209B63413006E59CF /* jwxyz-timers.m in Sources */,
                                AF77783409B6516900EA3033 /* grab-ximage.c in Sources */,
                                AF77783709B6518400EA3033 /* texfont.c in Sources */,
+                               CE43C2BF1C055157004C2BC6 /* jwxyz-cocoa.m in Sources */,
                                AF77783A09B651AF00EA3033 /* glut_stroke.c in Sources */,
                                AF77783D09B651C700EA3033 /* glut_swidth.c in Sources */,
                                AFAD462309D5F4DA00AB5F95 /* grabclient.c in Sources */,
                                AF6048FB157C07C600CA21E4 /* jwzgles.c in Sources */,
                                AFC7592D158D8E8B00C5458E /* textclient.c in Sources */,
-                               AFC75930158D9A7A00C5458E /* iostextclient.m in Sources */,
+                               AFC75930158D9A7A00C5458E /* textclient-iOS.m in Sources */,
                                AF561DF615969BC3007CA5ED /* iosgrabimage.m in Sources */,
                                CE9289D319BD00E300961F22 /* async_netdb.c in Sources */,
                        );
                        buildActionMask = 2147483647;
                        files = (
                                AF5C9B131A0CCF4E00B0147A /* cityflow.c in Sources */,
-                               AF5C9AFF1A0CCE6E00B0147A /* dangerball.c in Sources */,
                                AF5C9B001A0CCE6E00B0147A /* XScreenSaverSubclass.m in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF63F3271C3465BE0033E133 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF63F3281C3465BE0033E133 /* SaverRunner.m in Sources */,
+                               AF63F3291C3465BE0033E133 /* main.m in Sources */,
+                               AF63F32A1C3465BE0033E133 /* SaverListController.m in Sources */,
+                               AF63F32D1C3465BE0033E133 /* analogtv.c in Sources */,
+                               AF63F32F1C3465BE0033E133 /* apple2-main.c in Sources */,
+                               AFA2118B1CD1AA3F00C0D2A1 /* textclient-mobile.c in Sources */,
+                               AF63F3301C3465BE0033E133 /* apple2.c in Sources */,
+                               AF63F43F1C3465BE0033E133 /* ios-function-table.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF63F45E1C34682A0033E133 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF63F45F1C34682A0033E133 /* SaverRunner.m in Sources */,
+                               AF63F4601C34682A0033E133 /* main.m in Sources */,
+                               AF63F4611C34682A0033E133 /* SaverListController.m in Sources */,
+                               AF63F4771C3469570033E133 /* phosphor.c in Sources */,
+                               AF63F4651C34682A0033E133 /* ios-function-table.m in Sources */,
+                               AFA2118A1CD1AA3A00C0D2A1 /* textclient-mobile.c in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF63F4861C3469FC0033E133 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF63F4871C3469FC0033E133 /* SaverRunner.m in Sources */,
+                               AF63F4881C3469FC0033E133 /* main.m in Sources */,
+                               AF63F4891C3469FC0033E133 /* SaverListController.m in Sources */,
+                               AF63F49D1C346B1A0033E133 /* testx11.c in Sources */,
+                               AF63F48B1C3469FC0033E133 /* ios-function-table.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF6423F7099FF9C2000F4CD4 /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        buildActionMask = 2147483647;
                        files = (
                                AF78D17B142DD8F3002AAF77 /* XScreenSaverSubclass.m in Sources */,
-                               AF78D17C142DD8F3002AAF77 /* voronoi.c in Sources */,
                                AF78D18D142DD96E002AAF77 /* hilbert.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
-                               AF918986158FC00A002B5D1E /* SaverRunner.m in Sources */,
+                               AFAA6B451773F07800DE720C /* ios-function-table.m in Sources */,
                                AF918987158FC00A002B5D1E /* main.m in Sources */,
+                               AF918986158FC00A002B5D1E /* SaverRunner.m in Sources */,
                                AF918988158FC00A002B5D1E /* SaverListController.m in Sources */,
                                AF918993158FC2BE002B5D1E /* abstractile.c in Sources */,
                                AF918994158FC2BE002B5D1E /* anemone.c in Sources */,
                                AF918995158FC2E0002B5D1E /* analogtv.c in Sources */,
                                AF918996158FC310002B5D1E /* anemotaxis.c in Sources */,
+                               AF9189FF158FC38A002B5D1E /* apollonian.c in Sources */,
                                AF918997158FC310002B5D1E /* apple2-main.c in Sources */,
                                AF918998158FC310002B5D1E /* apple2.c in Sources */,
                                AF918999158FC310002B5D1E /* asm6502.c in Sources */,
                                AF73FF3A1A09889700E485E9 /* binaryring.c in Sources */,
                                AF91899C158FC310002B5D1E /* blaster.c in Sources */,
                                AF91899D158FC310002B5D1E /* blitspin.c in Sources */,
+                               AF918A00158FC38A002B5D1E /* bouboule.c in Sources */,
                                AF91899E158FC310002B5D1E /* boxfit.c in Sources */,
+                               AF918A01158FC38A002B5D1E /* braid.c in Sources */,
                                AF91899F158FC310002B5D1E /* bsod.c in Sources */,
                                AF9189A0158FC310002B5D1E /* bubbles-default.c in Sources */,
                                AF9189A2158FC310002B5D1E /* bumps.c in Sources */,
                                AF9189A5158FC310002B5D1E /* cloudlife.c in Sources */,
                                AF9189AA158FC311002B5D1E /* compass.c in Sources */,
                                AF9189AB158FC311002B5D1E /* coral.c in Sources */,
+                               AF918A02158FC38A002B5D1E /* crystal.c in Sources */,
                                AF9189AD158FC311002B5D1E /* cwaves.c in Sources */,
                                AF9189AE158FC311002B5D1E /* cynosure.c in Sources */,
                                AF9189AF158FC311002B5D1E /* decayscreen.c in Sources */,
                                AF9189B0158FC311002B5D1E /* deco.c in Sources */,
+                               AF68A49C19196E3E00D41CD1 /* delaunay.c in Sources */,
                                AF9189B1158FC311002B5D1E /* deluxe.c in Sources */,
+                               AF918A03158FC38A002B5D1E /* demon.c in Sources */,
+                               AF918A04158FC38A002B5D1E /* discrete.c in Sources */,
                                AF9189B2158FC311002B5D1E /* distort.c in Sources */,
+                               AF918A05158FC38A002B5D1E /* drift.c in Sources */,
                                AF9189B3158FC311002B5D1E /* epicycle.c in Sources */,
                                AF9189B4158FC311002B5D1E /* eruption.c in Sources */,
+                               AF918A06158FC38A002B5D1E /* euler2d.c in Sources */,
+                               AF918A07158FC38A002B5D1E /* fadeplot.c in Sources */,
+                               AF918A08158FC38A002B5D1E /* fiberlamp.c in Sources */,
                                AF9189B5158FC311002B5D1E /* fireworkx.c in Sources */,
                                AF9189B6158FC334002B5D1E /* flame.c in Sources */,
+                               AF918A0A158FC38A002B5D1E /* flow.c in Sources */,
                                AF9189B7158FC334002B5D1E /* fluidballs.c in Sources */,
                                AF9189B8158FC334002B5D1E /* fontglide.c in Sources */,
                                AF9189B9158FC334002B5D1E /* fps.c in Sources */,
                                AF9189BA158FC334002B5D1E /* fuzzyflakes.c in Sources */,
+                               AF918A0C158FC38A002B5D1E /* galaxy.c in Sources */,
                                AF9189BB158FC334002B5D1E /* goop.c in Sources */,
+                               AF918A0D158FC38A002B5D1E /* grav.c in Sources */,
                                AF9189BC158FC334002B5D1E /* greynetic.c in Sources */,
                                AF9189BD158FC334002B5D1E /* halftone.c in Sources */,
                                AF9189BE158FC334002B5D1E /* halo.c in Sources */,
                                AF9189BF158FC334002B5D1E /* helix.c in Sources */,
+                               AFB591C1178B81E600EA4005 /* hexadrop.c in Sources */,
+                               AF918A0E158FC38A002B5D1E /* hopalong.c in Sources */,
                                AF9189C2158FC334002B5D1E /* ifs.c in Sources */,
                                AF9189C3158FC334002B5D1E /* imsmap.c in Sources */,
                                AF9189C4158FC334002B5D1E /* interaggregate.c in Sources */,
                                AF9189C5158FC334002B5D1E /* interference.c in Sources */,
                                AF9189C6158FC334002B5D1E /* intermomentary.c in Sources */,
+                               AF918A11158FC38A002B5D1E /* julia.c in Sources */,
                                AF9189C7158FC334002B5D1E /* kaleidescope.c in Sources */,
                                AF9189C8158FC334002B5D1E /* kumppa.c in Sources */,
+                               AF918A16158FC38A002B5D1E /* loop.c in Sources */,
                                AF9189CB158FC334002B5D1E /* m6502.c in Sources */,
                                AF9189CC158FC334002B5D1E /* maze.c in Sources */,
                                AF9189CD158FC334002B5D1E /* memscroller.c in Sources */,
                                AF9189CE158FC334002B5D1E /* metaballs.c in Sources */,
                                AF9189CF158FC334002B5D1E /* moire.c in Sources */,
                                AF9189D0158FC334002B5D1E /* moire2.c in Sources */,
+                               AF918A17158FC38A002B5D1E /* mountain.c in Sources */,
                                AF9189D1158FC334002B5D1E /* munch.c in Sources */,
                                AF9189D2158FC334002B5D1E /* nerverot.c in Sources */,
                                AF9189D3158FC334002B5D1E /* noseguy.c in Sources */,
+                               AF918A18158FC38A002B5D1E /* pacman.c in Sources */,
+                               AF918A19158FC38A002B5D1E /* pacman_ai.c in Sources */,
+                               AF918A1A158FC38A002B5D1E /* pacman_level.c in Sources */,
                                AF9189D4158FC334002B5D1E /* pedal.c in Sources */,
                                AF9189D5158FC334002B5D1E /* penetrate.c in Sources */,
                                AF9189D6158FC334002B5D1E /* petri.c in Sources */,
                                AF9189DA158FC334002B5D1E /* popsquares.c in Sources */,
                                AF9189DB158FC334002B5D1E /* pyro.c in Sources */,
                                AF9189DC158FC334002B5D1E /* qix.c in Sources */,
+                               AF918A1B158FC38A002B5D1E /* penrose.c in Sources */,
+                               AF918A1C158FC38A002B5D1E /* polyominoes.c in Sources */,
                                AF9189DD158FC334002B5D1E /* rd-bomb.c in Sources */,
                                AF9189DE158FC334002B5D1E /* ripples.c in Sources */,
                                AF9189DF158FC35D002B5D1E /* rocks.c in Sources */,
                                AF9189E6158FC35D002B5D1E /* squiral.c in Sources */,
                                AF9189E7158FC35D002B5D1E /* starfish.c in Sources */,
                                AF9189E8158FC35D002B5D1E /* substrate.c in Sources */,
-                               CE3D016D1B76FF1600993C75 /* testx11.c in Sources */,
+                               AF918A1E158FC38A002B5D1E /* sierpinski.c in Sources */,
+                               AF918A1F158FC38A002B5D1E /* slip.c in Sources */,
+                               AF918A22158FC38A002B5D1E /* strange.c in Sources */,
+                               AF918A23158FC38A002B5D1E /* swirl.c in Sources */,
+                               AFA211891CD1AA2E00C0D2A1 /* textclient-mobile.c in Sources */,
+                               AF68A49A19196E3E00D41CD1 /* tessellimage.c in Sources */,
+                               AF918A25158FC38A002B5D1E /* triangle.c in Sources */,
+                               AF918A24158FC38A002B5D1E /* thornbird.c in Sources */,
                                AF9189EF158FC35D002B5D1E /* truchet.c in Sources */,
                                AF9189F0158FC35D002B5D1E /* twang.c in Sources */,
                                AF9189F1158FC35D002B5D1E /* vermiculate.c in Sources */,
                                AF9189FB158FC35E002B5D1E /* xrayswarm.c in Sources */,
                                AF9189FC158FC35E002B5D1E /* xspirograph.c in Sources */,
                                AF9189FD158FC35E002B5D1E /* zoom.c in Sources */,
-                               AF9189FF158FC38A002B5D1E /* apollonian.c in Sources */,
-                               AF918A00158FC38A002B5D1E /* bouboule.c in Sources */,
-                               AF918A01158FC38A002B5D1E /* braid.c in Sources */,
-                               AF918A02158FC38A002B5D1E /* crystal.c in Sources */,
-                               AF918A03158FC38A002B5D1E /* demon.c in Sources */,
-                               AF918A04158FC38A002B5D1E /* discrete.c in Sources */,
-                               AF918A05158FC38A002B5D1E /* drift.c in Sources */,
-                               AF918A06158FC38A002B5D1E /* euler2d.c in Sources */,
-                               AF918A07158FC38A002B5D1E /* fadeplot.c in Sources */,
-                               AF918A08158FC38A002B5D1E /* fiberlamp.c in Sources */,
-                               AF918A0A158FC38A002B5D1E /* flow.c in Sources */,
-                               AF918A0C158FC38A002B5D1E /* galaxy.c in Sources */,
-                               AF918A0D158FC38A002B5D1E /* grav.c in Sources */,
-                               AFB591C1178B81E600EA4005 /* hexadrop.c in Sources */,
-                               AF918A0E158FC38A002B5D1E /* hopalong.c in Sources */,
-                               AF918A11158FC38A002B5D1E /* julia.c in Sources */,
-                               AF918A16158FC38A002B5D1E /* loop.c in Sources */,
-                               AF918A17158FC38A002B5D1E /* mountain.c in Sources */,
-                               AF918A18158FC38A002B5D1E /* pacman.c in Sources */,
-                               AF918A19158FC38A002B5D1E /* pacman_ai.c in Sources */,
-                               AF918A1A158FC38A002B5D1E /* pacman_level.c in Sources */,
-                               AF918A1B158FC38A002B5D1E /* penrose.c in Sources */,
-                               AF918A1C158FC38A002B5D1E /* polyominoes.c in Sources */,
-                               AF918A1E158FC38A002B5D1E /* sierpinski.c in Sources */,
-                               AF918A1F158FC38A002B5D1E /* slip.c in Sources */,
-                               AF918A22158FC38A002B5D1E /* strange.c in Sources */,
-                               AF918A23158FC38A002B5D1E /* swirl.c in Sources */,
-                               AF68A49A19196E3E00D41CD1 /* tessellimage.c in Sources */,
-                               AF918A24158FC38A002B5D1E /* thornbird.c in Sources */,
-                               AF68A49C19196E3E00D41CD1 /* delaunay.c in Sources */,
-                               AF918A25158FC38A002B5D1E /* triangle.c in Sources */,
                                AF918A28158FC3BB002B5D1E /* antinspect.c in Sources */,
                                AF918A29158FC3BB002B5D1E /* antmaze.c in Sources */,
                                AF918A2A158FC3BB002B5D1E /* antspotlight.c in Sources */,
                                AF918A46158FC3BB002B5D1E /* dangerball.c in Sources */,
                                AFCF453715986A2100E6E8CC /* dnalogo.c in Sources */,
                                AF918A48158FC3BB002B5D1E /* dolphin.c in Sources */,
+                               AFEC23E91CB6EC7F00DE138F /* dymaxionmap.c in Sources */,
                                AF918A49158FC3BB002B5D1E /* dropshadow.c in Sources */,
                                AF918A4A158FC3E5002B5D1E /* endgame.c in Sources */,
+                               AFACE88F1CC83617008B24CD /* energystream.c in Sources */,
                                AF918A4B158FC3E5002B5D1E /* engine.c in Sources */,
                                AF918A54158FC3E5002B5D1E /* flipflop.c in Sources */,
                                AF918A55158FC3E5002B5D1E /* flipscreen3d.c in Sources */,
                                AF918A68158FC3E5002B5D1E /* glsnake.c in Sources */,
                                AF918A69158FC3E5002B5D1E /* gltext.c in Sources */,
                                AF918A6A158FC3E5002B5D1E /* hilbert.c in Sources */,
+                               AFC0E8C41CDC60B0008CAFAC /* hydrostat.c in Sources */,
                                AF918A6B158FC3E5002B5D1E /* hypertorus.c in Sources */,
                                AF918A6C158FC3E5002B5D1E /* hypnowheel.c in Sources */,
                                AF918A6D158FC3E5002B5D1E /* involute.c in Sources */,
                                AF918A84158FC417002B5D1E /* pulsar.c in Sources */,
                                AFF28699178611720050A578 /* quasicrystal.c in Sources */,
                                AF918A85158FC417002B5D1E /* queens.c in Sources */,
+                               AFA211A81CD5A04300C0D2A1 /* raverhoop.c in Sources */,
                                AFBE744119A7C6EF0018AA35 /* robot.c in Sources */,
                                AF39E2B7198A15EE0064A58D /* robot-wireframe.c in Sources */,
                                AF63A80D1AB4EF5D00593C75 /* romanboy.c in Sources */,
                                AF9189ED158FC35D002B5D1E /* tronbit_no.c in Sources */,
                                AF9189EE158FC35D002B5D1E /* tronbit_yes.c in Sources */,
                                AF918AB1158FC47B002B5D1E /* tunnel_draw.c in Sources */,
+                               AF46E9EB1CBBA43B00240FBC /* unicrud.c in Sources */,
                                AFDA65A8178A541A0070D24B /* unknownpleasures.c in Sources */,
                                AF918AB2158FC47B002B5D1E /* voronoi.c in Sources */,
                                AF918AB3158FC47B002B5D1E /* whale.c in Sources */,
                                AF39E2B8198A15EE0064A58D /* winduprobot.c in Sources */,
-                               AFAA6B451773F07800DE720C /* ios-function-table.m in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFA211911CD59DAF00C0D2A1 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFA211A71CD5A03F00C0D2A1 /* raverhoop.c in Sources */,
+                               AFA211931CD59DAF00C0D2A1 /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFA339340B058505002B0E7D /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFACE8781CC83458008B24CD /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFACE87A1CC83458008B24CD /* XScreenSaverSubclass.m in Sources */,
+                               AFACE88E1CC83613008B24CD /* energystream.c in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFB591AC178B812C00EA4005 /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFC0E8B01CDC601A008CAFAC /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFC0E8C51CDC60D6008CAFAC /* hydrostat.c in Sources */,
+                               AFC0E8B21CDC601A008CAFAC /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFCF83401AF5B515008BB7E1 /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFEC23D21CB6EAE100DE138F /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFEC23E61CB6EC0400DE138F /* dymaxionmap.c in Sources */,
+                               AFEC23D41CB6EAE100DE138F /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFF2868417860E830050A578 /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        target = AF1A17610D6D6EE3008AF328 /* LCDscrub */;
                        targetProxy = AF1A17830D6D6FA7008AF328 /* PBXContainerItemProxy */;
                };
-               AF2D4D8013E902F5002AA818 /* PBXTargetDependency */ = {
-                       isa = PBXTargetDependency;
-                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
-                       targetProxy = AF2D4D8113E902F5002AA818 /* PBXContainerItemProxy */;
-               };
-               AF2D4D9E13E90347002AA818 /* PBXTargetDependency */ = {
-                       isa = PBXTargetDependency;
-                       target = AF7776E409B63ABF00EA3033 /* Phosphor */;
-                       targetProxy = AF2D4D9D13E90347002AA818 /* PBXContainerItemProxy */;
-               };
-               AF2D4F6B13E91093002AA818 /* PBXTargetDependency */ = {
-                       isa = PBXTargetDependency;
-                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
-                       targetProxy = AF2D4F6C13E91093002AA818 /* PBXContainerItemProxy */;
-               };
-               AF2D4F8F13E91127002AA818 /* PBXTargetDependency */ = {
-                       isa = PBXTargetDependency;
-                       target = AF9D4DEC09B5BB19006E59CF /* Apple2 */;
-                       targetProxy = AF2D4F8E13E91127002AA818 /* PBXContainerItemProxy */;
-               };
                AF32D9E10F3AD0B40080F535 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
                        target = AFE30BE80E52B14700CCF4A5 /* Sonar */;
                        targetProxy = AF4540D10E52BE8800AE87B5 /* PBXContainerItemProxy */;
                };
+               AF46E9D01CBBA2B300240FBC /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AF46E9D11CBBA2B300240FBC /* PBXContainerItemProxy */;
+               };
+               AF46E9ED1CBBA49A00240FBC /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF46E9CF1CBBA2B300240FBC /* Unicrud */;
+                       targetProxy = AF46E9EC1CBBA49A00240FBC /* PBXContainerItemProxy */;
+               };
                AF476FB6099D154F001F091E /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
                        target = AF63A7F11AB4EDDB00593C75 /* RomanBoy */;
                        targetProxy = AF63A80E1AB4EFD300593C75 /* PBXContainerItemProxy */;
                };
+               AF63F2481C3465BE0033E133 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AF63F2491C3465BE0033E133 /* PBXContainerItemProxy */;
+               };
+               AF63F24A1C3465BE0033E133 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4FF4930D52CA0800666F98 /* m6502.h */;
+                       targetProxy = AF63F24B1C3465BE0033E133 /* PBXContainerItemProxy */;
+               };
+               AF63F24C1C3465BE0033E133 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AFA56119099378CB00F3E977 /* molecules.h */;
+                       targetProxy = AF63F24D1C3465BE0033E133 /* PBXContainerItemProxy */;
+               };
+               AF63F4511C34682A0033E133 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AF63F4521C34682A0033E133 /* PBXContainerItemProxy */;
+               };
+               AF63F4531C34682A0033E133 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4FF4930D52CA0800666F98 /* m6502.h */;
+                       targetProxy = AF63F4541C34682A0033E133 /* PBXContainerItemProxy */;
+               };
+               AF63F4551C34682A0033E133 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AFA56119099378CB00F3E977 /* molecules.h */;
+                       targetProxy = AF63F4561C34682A0033E133 /* PBXContainerItemProxy */;
+               };
+               AF63F4791C3469FC0033E133 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AF63F47A1C3469FC0033E133 /* PBXContainerItemProxy */;
+               };
+               AF63F47B1C3469FC0033E133 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4FF4930D52CA0800666F98 /* m6502.h */;
+                       targetProxy = AF63F47C1C3469FC0033E133 /* PBXContainerItemProxy */;
+               };
+               AF63F47D1C3469FC0033E133 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AFA56119099378CB00F3E977 /* molecules.h */;
+                       targetProxy = AF63F47E1C3469FC0033E133 /* PBXContainerItemProxy */;
+               };
                AF6423F3099FF9C2000F4CD4 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
                        target = AF64260F09A18D6C000F4CD4 /* HyperBall */;
                        targetProxy = AFA160931052FF87009B93AA /* PBXContainerItemProxy */;
                };
+               AFA2118D1CD59DAF00C0D2A1 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AFA2118E1CD59DAF00C0D2A1 /* PBXContainerItemProxy */;
+               };
+               AFA211AA1CD5A08000C0D2A1 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AFA2118C1CD59DAF00C0D2A1 /* RaverHoop */;
+                       targetProxy = AFA211A91CD5A08000C0D2A1 /* PBXContainerItemProxy */;
+               };
                AFA3392F0B058505002B0E7D /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
                        target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
                        targetProxy = AFA563A6099398BB00F3E977 /* PBXContainerItemProxy */;
                };
+               AFACE8741CC83458008B24CD /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AFACE8751CC83458008B24CD /* PBXContainerItemProxy */;
+               };
+               AFACE8911CC8365F008B24CD /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AFACE8731CC83458008B24CD /* EnergyStream */;
+                       targetProxy = AFACE8901CC8365F008B24CD /* PBXContainerItemProxy */;
+               };
                AFB581B0102F363300342B11 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AFD571B50996D9DC00BA26F7 /* Juggle */;
                        target = AFBFE767178647FE00432B21 /* Phosphor-OSX */;
                        targetProxy = AFBFE786178648F500432B21 /* PBXContainerItemProxy */;
                };
+               AFC0E8AC1CDC601A008CAFAC /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AFC0E8AD1CDC601A008CAFAC /* PBXContainerItemProxy */;
+               };
+               AFC0E8C91CDC6125008CAFAC /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AFC0E8AB1CDC601A008CAFAC /* Hydrostat */;
+                       targetProxy = AFC0E8C81CDC6125008CAFAC /* PBXContainerItemProxy */;
+               };
                AFCAD5F90992DFE00009617A /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AF9771D60989DC4A001F8B92 /* SaverTester */;
                        target = AFE6A41B0CDD7FAA002805BF /* Abstractile */;
                        targetProxy = AFE6A42F0CDD7FEE002805BF /* PBXContainerItemProxy */;
                };
+               AFEC23CE1CB6EAE100DE138F /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AFEC23CF1CB6EAE100DE138F /* PBXContainerItemProxy */;
+               };
+               AFEC23EB1CB6ED0800DE138F /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AFEC23CD1CB6EAE100DE138F /* DymaxionMap */;
+                       targetProxy = AFEC23EA1CB6ED0800DE138F /* PBXContainerItemProxy */;
+               };
                AFF2868017860E830050A578 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
                                        "$(SRCROOT)",
                                );
                                INFOPLIST_FILE = "$(SRCROOT)/Updater.plist";
-                               "OTHER_CFLAGS[sdk=macosx*]" = "-fno-objc-gc";
+                               "OTHER_CFLAGS[sdk=macosx*]" = "${OBJC_NO_GC_CFLAGS}";
+                               PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_IDENTIFIER)";
                                PRODUCT_NAME = "$(TARGET_NAME)";
                                WRAPPER_EXTENSION = app;
                        };
                                        "$(SRCROOT)",
                                );
                                INFOPLIST_FILE = "$(SRCROOT)/Updater.plist";
-                               "OTHER_CFLAGS[sdk=macosx*]" = "-fno-objc-gc";
+                               "OTHER_CFLAGS[sdk=macosx*]" = "${OBJC_NO_GC_CFLAGS}";
+                               PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_IDENTIFIER)";
                                PRODUCT_NAME = "$(TARGET_NAME)";
                                WRAPPER_EXTENSION = app;
                        };
                        name = Release;
                };
-               AF2D4D8D13E902F5002AA818 /* Debug */ = {
-                       isa = XCBuildConfiguration;
-                       buildSettings = {
-                               ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-                               ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
-                               GCC_PREPROCESSOR_DEFINITIONS = (
-                                       "USE_IPHONE=1",
-                                       "PHOSPHOR_ONLY=1",
-                                       "$(inherited)",
-                               );
-                               INFOPLIST_FILE = iSaverRunner.plist;
-                               INSTALL_PATH = "$(HOME)/Applications";
-                               PRODUCT_NAME = Phosphor;
-                               SDKROOT = iphoneos;
-                               WRAPPER_EXTENSION = app;
-                       };
-                       name = Debug;
-               };
-               AF2D4D8E13E902F5002AA818 /* Release */ = {
-                       isa = XCBuildConfiguration;
-                       buildSettings = {
-                               ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-                               ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
-                               GCC_PREPROCESSOR_DEFINITIONS = (
-                                       "USE_IPHONE=1",
-                                       "PHOSPHOR_ONLY=1",
-                                       "$(inherited)",
-                               );
-                               INFOPLIST_FILE = iSaverRunner.plist;
-                               INSTALL_PATH = "$(HOME)/Applications";
-                               PRODUCT_NAME = Phosphor;
-                               SDKROOT = iphoneos;
-                               WRAPPER_EXTENSION = app;
-                       };
-                       name = Release;
-               };
-               AF2D4F7C13E91093002AA818 /* Debug */ = {
-                       isa = XCBuildConfiguration;
-                       buildSettings = {
-                               ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-                               ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
-                               GCC_PREPROCESSOR_DEFINITIONS = (
-                                       "USE_IPHONE=1",
-                                       "APPLE2_ONLY=1",
-                                       "$(inherited)",
-                               );
-                               INFOPLIST_FILE = iSaverRunner.plist;
-                               INSTALL_PATH = "$(HOME)/Applications";
-                               PRODUCT_NAME = Apple2;
-                               SDKROOT = iphoneos;
-                               WRAPPER_EXTENSION = app;
-                       };
-                       name = Debug;
-               };
-               AF2D4F7D13E91093002AA818 /* Release */ = {
-                       isa = XCBuildConfiguration;
-                       buildSettings = {
-                               ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-                               ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
-                               GCC_PREPROCESSOR_DEFINITIONS = (
-                                       "USE_IPHONE=1",
-                                       "APPLE2_ONLY=1",
-                                       "$(inherited)",
-                               );
-                               INFOPLIST_FILE = iSaverRunner.plist;
-                               INSTALL_PATH = "$(HOME)/Applications";
-                               PRODUCT_NAME = Apple2;
-                               SDKROOT = iphoneos;
-                               WRAPPER_EXTENSION = app;
-                       };
-                       name = Release;
-               };
                AF32D9F20F3AD0B40080F535 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                        };
                        name = Release;
                };
+               AF46E9E21CBBA2B300240FBC /* 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;
+               };
+               AF46E9E31CBBA2B300240FBC /* 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;
+               };
                AF476FC4099D154F001F091E /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                INSTALL_PATH = /usr/local/lib;
+                               PRODUCT_BUNDLE_IDENTIFIER = "${BUNDLE_IDENTIFIER}";
                                SKIP_INSTALL = YES;
                                SUPPORTED_PLATFORMS = "macosx iphonesimulator iphoneos";
                                VALID_ARCHS = "i386 x86_64 armv6 armv7 armv7s arm64";
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                INSTALL_PATH = /usr/local/lib;
+                               PRODUCT_BUNDLE_IDENTIFIER = "${BUNDLE_IDENTIFIER}";
                                SKIP_INSTALL = YES;
                                SUPPORTED_PLATFORMS = "macosx iphonesimulator iphoneos";
                                VALID_ARCHS = "i386 x86_64 armv6 armv7 armv7s arm64";
                        };
                        name = Release;
                };
+               AF63F44C1C3465BE0033E133 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+                               ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+                               BUNDLE_IDENTIFIER = "org.jwz.${PROJECT_NAME:rfc1034identifier}.apple2";
+                               CODE_SIGN_IDENTITY = "iPhone Developer";
+                               "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+                               GCC_PREPROCESSOR_DEFINITIONS = (
+                                       "USE_IPHONE=1",
+                                       "APPLE2_ONLY=1",
+                                       "$(inherited)",
+                               );
+                               "GCC_WARN_64_TO_32_BIT_CONVERSION[arch=*64]" = NO;
+                               INFOPLIST_FILE = iSaverRunner.plist;
+                               INSTALL_PATH = "$(HOME)/Applications";
+                               PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_IDENTIFIER)";
+                               PRODUCT_NAME = Apple2;
+                               PROVISIONING_PROFILE = "";
+                               SDKROOT = iphoneos;
+                               WRAPPER_EXTENSION = app;
+                       };
+                       name = Debug;
+               };
+               AF63F44D1C3465BE0033E133 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+                               ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+                               BUNDLE_IDENTIFIER = "org.jwz.${PROJECT_NAME:rfc1034identifier}.apple2";
+                               CODE_SIGN_IDENTITY = "iPhone Developer";
+                               "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+                               GCC_PREPROCESSOR_DEFINITIONS = (
+                                       "USE_IPHONE=1",
+                                       "APPLE2_ONLY=1",
+                                       "$(inherited)",
+                               );
+                               "GCC_WARN_64_TO_32_BIT_CONVERSION[arch=*64]" = NO;
+                               INFOPLIST_FILE = iSaverRunner.plist;
+                               INSTALL_PATH = "$(HOME)/Applications";
+                               PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_IDENTIFIER)";
+                               PRODUCT_NAME = Apple2;
+                               PROVISIONING_PROFILE = "";
+                               SDKROOT = iphoneos;
+                               WRAPPER_EXTENSION = app;
+                       };
+                       name = Release;
+               };
+               AF63F4721C34682A0033E133 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+                               ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+                               BUNDLE_IDENTIFIER = "org.jwz.${PROJECT_NAME:rfc1034identifier}.phosphor";
+                               CODE_SIGN_IDENTITY = "iPhone Developer";
+                               "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+                               GCC_PREPROCESSOR_DEFINITIONS = (
+                                       "USE_IPHONE=1",
+                                       "PHOSPHOR_ONLY=1",
+                                       "$(inherited)",
+                               );
+                               "GCC_WARN_64_TO_32_BIT_CONVERSION[arch=*64]" = NO;
+                               INFOPLIST_FILE = iSaverRunner.plist;
+                               INSTALL_PATH = "$(HOME)/Applications";
+                               PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_IDENTIFIER)";
+                               PRODUCT_NAME = Phosphor;
+                               PROVISIONING_PROFILE = "";
+                               SDKROOT = iphoneos;
+                               WRAPPER_EXTENSION = app;
+                       };
+                       name = Debug;
+               };
+               AF63F4731C34682A0033E133 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+                               ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+                               BUNDLE_IDENTIFIER = "org.jwz.${PROJECT_NAME:rfc1034identifier}.phosphor";
+                               CODE_SIGN_IDENTITY = "iPhone Developer";
+                               "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+                               GCC_PREPROCESSOR_DEFINITIONS = (
+                                       "USE_IPHONE=1",
+                                       "PHOSPHOR_ONLY=1",
+                                       "$(inherited)",
+                               );
+                               "GCC_WARN_64_TO_32_BIT_CONVERSION[arch=*64]" = NO;
+                               INFOPLIST_FILE = iSaverRunner.plist;
+                               INSTALL_PATH = "$(HOME)/Applications";
+                               PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_IDENTIFIER)";
+                               PRODUCT_NAME = Phosphor;
+                               PROVISIONING_PROFILE = "";
+                               SDKROOT = iphoneos;
+                               WRAPPER_EXTENSION = app;
+                       };
+                       name = Release;
+               };
+               AF63F4981C3469FC0033E133 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+                               ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+                               BUNDLE_IDENTIFIER = "org.jwz.${PROJECT_NAME:rfc1034identifier}.testX11";
+                               CODE_SIGN_IDENTITY = "iPhone Developer";
+                               "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+                               GCC_PREPROCESSOR_DEFINITIONS = (
+                                       "USE_IPHONE=1",
+                                       "TESTX11_ONLY=1",
+                                       "$(inherited)",
+                               );
+                               "GCC_WARN_64_TO_32_BIT_CONVERSION[arch=*64]" = NO;
+                               INFOPLIST_FILE = iSaverRunner.plist;
+                               INSTALL_PATH = "$(HOME)/Applications";
+                               PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_IDENTIFIER)";
+                               PRODUCT_NAME = TestX11;
+                               PROVISIONING_PROFILE = "";
+                               SDKROOT = iphoneos;
+                               WRAPPER_EXTENSION = app;
+                       };
+                       name = Debug;
+               };
+               AF63F4991C3469FC0033E133 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+                               ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+                               BUNDLE_IDENTIFIER = "org.jwz.${PROJECT_NAME:rfc1034identifier}.testX11";
+                               CODE_SIGN_IDENTITY = "iPhone Developer";
+                               "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+                               GCC_PREPROCESSOR_DEFINITIONS = (
+                                       "USE_IPHONE=1",
+                                       "TESTX11_ONLY=1",
+                                       "$(inherited)",
+                               );
+                               "GCC_WARN_64_TO_32_BIT_CONVERSION[arch=*64]" = NO;
+                               INFOPLIST_FILE = iSaverRunner.plist;
+                               INSTALL_PATH = "$(HOME)/Applications";
+                               PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_IDENTIFIER)";
+                               PRODUCT_NAME = TestX11;
+                               PROVISIONING_PROFILE = "";
+                               SDKROOT = iphoneos;
+                               WRAPPER_EXTENSION = app;
+                       };
+                       name = Release;
+               };
                AF642403099FF9C2000F4CD4 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                "GCC_WARN_64_TO_32_BIT_CONVERSION[arch=*64]" = NO;
                                INFOPLIST_FILE = iSaverRunner.plist;
                                INSTALL_PATH = "$(HOME)/Applications";
+                               PRODUCT_BUNDLE_IDENTIFIER = "${BUNDLE_IDENTIFIER}";
                                PRODUCT_NAME = XScreenSaver;
                                PROVISIONING_PROFILE = "";
                                SDKROOT = iphoneos;
                                "GCC_WARN_64_TO_32_BIT_CONVERSION[arch=*64]" = NO;
                                INFOPLIST_FILE = iSaverRunner.plist;
                                INSTALL_PATH = "$(HOME)/Applications";
+                               PRODUCT_BUNDLE_IDENTIFIER = "${BUNDLE_IDENTIFIER}";
                                PRODUCT_NAME = XScreenSaver;
                                PROVISIONING_PROFILE = "";
                                SDKROOT = iphoneos;
                        buildSettings = {
                                INFOPLIST_FILE = SaverRunner.plist;
                                INSTALL_PATH = "$(HOME)/Applications";
+                               PRODUCT_BUNDLE_IDENTIFIER = "${BUNDLE_IDENTIFIER}";
                                WRAPPER_EXTENSION = app;
                        };
                        name = Debug;
                        buildSettings = {
                                INFOPLIST_FILE = SaverRunner.plist;
                                INSTALL_PATH = "$(HOME)/Applications";
+                               PRODUCT_BUNDLE_IDENTIFIER = "${BUNDLE_IDENTIFIER}";
                                WRAPPER_EXTENSION = app;
                        };
                        name = Release;
                AF9E7EC6190F4C1C00A8B01F /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
+                               PRODUCT_BUNDLE_IDENTIFIER = "${BUNDLE_IDENTIFIER}";
                                PRODUCT_NAME = "$(TARGET_NAME)";
                                SKIP_INSTALL = YES;
                        };
                AF9E7EC7190F4C1C00A8B01F /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
+                               PRODUCT_BUNDLE_IDENTIFIER = "${BUNDLE_IDENTIFIER}";
                                PRODUCT_NAME = "$(TARGET_NAME)";
                                SKIP_INSTALL = YES;
                        };
                        name = Release;
                };
+               AFA2119F1CD59DAF00C0D2A1 /* 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;
+               };
+               AFA211A01CD59DAF00C0D2A1 /* 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;
+               };
                AFA3393E0B058505002B0E7D /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                        buildSettings = {
                                GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
                                INSTALL_PATH = "$(HOME)/bin";
-                               "OTHER_CFLAGS[sdk=macosx*]" = "-fno-objc-gc";
+                               "OTHER_CFLAGS[sdk=macosx*]" = "${OBJC_NO_GC_CFLAGS}";
                                OTHER_LDFLAGS = (
                                        "-framework",
                                        Cocoa,
                        buildSettings = {
                                GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
                                INSTALL_PATH = "$(HOME)/bin";
-                               "OTHER_CFLAGS[sdk=macosx*]" = "-fno-objc-gc";
+                               "OTHER_CFLAGS[sdk=macosx*]" = "${OBJC_NO_GC_CFLAGS}";
                                OTHER_LDFLAGS = (
                                        "-framework",
                                        Cocoa,
                        };
                        name = Release;
                };
+               AFACE8861CC83458008B24CD /* 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;
+               };
+               AFACE8871CC83458008B24CD /* 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;
+               };
                AFB591B8178B812C00EA4005 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                        };
                        name = Release;
                };
+               AFC0E8BE1CDC601A008CAFAC /* 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;
+               };
+               AFC0E8BF1CDC601A008CAFAC /* 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;
+               };
                AFCF834E1AF5B515008BB7E1 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                        };
                        name = Release;
                };
+               AFEC23E01CB6EAE100DE138F /* 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;
+               };
+               AFEC23E11CB6EAE100DE138F /* 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;
+               };
                AFF2869017860E830050A578 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
                                "CODE_SIGN_IDENTITY[sdk=iphonesimulator*]" = "iPhone Developer";
                                COMBINE_HIDPI_IMAGES = YES;
+                               ENABLE_TESTABILITY = YES;
                                GCC_OPTIMIZATION_LEVEL = 0;
                                GCC_PRECOMPILE_PREFIX_HEADER = YES;
                                GCC_PREFIX_HEADER = xscreensaver_Prefix.pch;
                                        "HAVE_STRUCT_SOCKADDR_SA_LEN=1",
                                        "HAVE_XUTF8DRAWSTRING=1",
                                        "HAVE_INTTYPES_H=1",
+                                       "JWXYZ_QUARTZ=1",
+                                       "HAVE_JWXYZ=1",
                                        "$(GCC_PREPROCESSOR_DEFINITIONS)",
                                );
                                GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
                                        "$(HEADER_SEARCH_PATHS)",
                                        "$(SRCROOT)/..",
                                        "$(SRCROOT)/../utils",
+                                       "$(SRCROOT)/../jwxyz",
                                        "$(SRCROOT)/../hacks",
                                );
                                INFOPLIST_FILE = XScreenSaver.plist;
                                INSTALL_PATH = "$(HOME)/Library/Screen Savers";
-                               IPHONEOS_DEPLOYMENT_TARGET = 5.1.1;
+                               IPHONEOS_DEPLOYMENT_TARGET = 6.0;
                                LIBRARY_SEARCH_PATHS = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
-                               MACOSX_DEPLOYMENT_TARGET = 10.4;
                                ONLY_ACTIVE_ARCH = YES;
                                OTHER_CFLAGS = "";
                                "OTHER_CFLAGS[sdk=macosx*]" = "$(OBJC_GC_CFLAGS)";
                                "OTHER_LDFLAGS[sdk=macosx*]" = "-headerpad_max_install_names";
                                PRODUCT_NAME = "$(TARGET_NAME)";
-                               PROVISIONING_PROFILE = "A33D2D59-2A1E-4D45-8AA1-CB2EC74F9DCC";
+                               PROVISIONING_PROFILE = "";
                                SDKROOT = macosx;
                                "SDKROOT[arch=arm*]" = iphoneos;
                                SYMROOT = "$(SRCROOT)/build";
                                        "HAVE_STRUCT_SOCKADDR_SA_LEN=1",
                                        "HAVE_XUTF8DRAWSTRING=1",
                                        "HAVE_INTTYPES_H=1",
+                                       "JWXYZ_QUARTZ=1",
+                                       "HAVE_JWXYZ=1",
                                        "$(GCC_PREPROCESSOR_DEFINITIONS)",
                                );
                                GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
                                        "$(HEADER_SEARCH_PATHS)",
                                        "$(SRCROOT)/..",
                                        "$(SRCROOT)/../utils",
+                                       "$(SRCROOT)/../jwxyz",
                                        "$(SRCROOT)/../hacks",
                                );
                                INFOPLIST_FILE = XScreenSaver.plist;
                                INSTALL_PATH = "$(HOME)/Library/Screen Savers";
-                               IPHONEOS_DEPLOYMENT_TARGET = 5.1.1;
+                               IPHONEOS_DEPLOYMENT_TARGET = 6.0;
                                LIBRARY_SEARCH_PATHS = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
                                LLVM_LTO = NO;
-                               "LLVM_LTO[sdk=macosx*]" = YES;
-                               MACOSX_DEPLOYMENT_TARGET = 10.4;
+                               "LLVM_LTO[sdk=macosx*]" = NO;
                                OTHER_CFLAGS = "";
                                "OTHER_CFLAGS[sdk=macosx*]" = "$(OBJC_GC_CFLAGS)";
                                "OTHER_LDFLAGS[sdk=macosx*]" = "-headerpad_max_install_names";
                                PRODUCT_NAME = "$(TARGET_NAME)";
-                               PROVISIONING_PROFILE = "A33D2D59-2A1E-4D45-8AA1-CB2EC74F9DCC";
+                               PROVISIONING_PROFILE = "";
                                SDKROOT = macosx;
                                "SDKROOT[arch=arm*]" = iphoneos;
                                SYMROOT = "$(SRCROOT)/build";
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
-               AF2D4D8C13E902F5002AA818 /* Build configuration list for PBXNativeTarget "Phosphor-iOS" */ = {
-                       isa = XCConfigurationList;
-                       buildConfigurations = (
-                               AF2D4D8D13E902F5002AA818 /* Debug */,
-                               AF2D4D8E13E902F5002AA818 /* Release */,
-                       );
-                       defaultConfigurationIsVisible = 0;
-                       defaultConfigurationName = Release;
-               };
-               AF2D4F7B13E91093002AA818 /* Build configuration list for PBXNativeTarget "Apple2-iOS" */ = {
-                       isa = XCConfigurationList;
-                       buildConfigurations = (
-                               AF2D4F7C13E91093002AA818 /* Debug */,
-                               AF2D4F7D13E91093002AA818 /* Release */,
-                       );
-                       defaultConfigurationIsVisible = 0;
-                       defaultConfigurationName = Release;
-               };
                AF32D9F10F3AD0B40080F535 /* Build configuration list for PBXNativeTarget "RubikBlocks" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
+               AF46E9E11CBBA2B300240FBC /* Build configuration list for PBXNativeTarget "Unicrud" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AF46E9E21CBBA2B300240FBC /* Debug */,
+                               AF46E9E31CBBA2B300240FBC /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                AF476FC3099D154F001F091E /* Build configuration list for PBXNativeTarget "Interference" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
+               AF63F44B1C3465BE0033E133 /* Build configuration list for PBXNativeTarget "Apple2-iOS" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AF63F44C1C3465BE0033E133 /* Debug */,
+                               AF63F44D1C3465BE0033E133 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               AF63F4711C34682A0033E133 /* Build configuration list for PBXNativeTarget "Phosphor-iOS" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AF63F4721C34682A0033E133 /* Debug */,
+                               AF63F4731C34682A0033E133 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               AF63F4971C3469FC0033E133 /* Build configuration list for PBXNativeTarget "TestX11-iOS" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AF63F4981C3469FC0033E133 /* Debug */,
+                               AF63F4991C3469FC0033E133 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                AF642402099FF9C2000F4CD4 /* Build configuration list for PBXNativeTarget "Extrusion" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
+               AFA2119E1CD59DAF00C0D2A1 /* Build configuration list for PBXNativeTarget "RaverHoop" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AFA2119F1CD59DAF00C0D2A1 /* Debug */,
+                               AFA211A01CD59DAF00C0D2A1 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                AFA3393D0B058505002B0E7D /* Build configuration list for PBXNativeTarget "WebCollage" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
+               AFACE8851CC83458008B24CD /* Build configuration list for PBXNativeTarget "EnergyStream" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AFACE8861CC83458008B24CD /* Debug */,
+                               AFACE8871CC83458008B24CD /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                AFB591B7178B812C00EA4005 /* Build configuration list for PBXNativeTarget "Hexadrop" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
+               AFC0E8BD1CDC601A008CAFAC /* Build configuration list for PBXNativeTarget "Hydrostat" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AFC0E8BE1CDC601A008CAFAC /* Debug */,
+                               AFC0E8BF1CDC601A008CAFAC /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                AFCF834D1AF5B515008BB7E1 /* Build configuration list for PBXNativeTarget "SplitFlap" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
+               AFEC23DF1CB6EAE100DE138F /* Build configuration list for PBXNativeTarget "DymaxionMap" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AFEC23E01CB6EAE100DE138F /* Debug */,
+                               AFEC23E11CB6EAE100DE138F /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                AFF2868F17860E830050A578 /* Build configuration list for PBXNativeTarget "QuasiCrystal" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
diff --git a/README b/README
index 8f14a203d3647e343fee22fd96a672d64fe2197e..209e9688e78dc75526744c959a7a895cd58826fa 100644 (file)
--- a/README
+++ b/README
@@ -8,7 +8,7 @@
                             By Jamie Zawinski
                              and many others
 
-                     http://www.jwz.org/xscreensaver/
+                     https://www.jwz.org/xscreensaver/
 
 ===============================================================================
 
@@ -17,17 +17,21 @@ 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.
 
-To compile on a Unix system with X11:
+To compile for a Unix system with X11:
 
     ./configure
     make
     make install
 
-To compile on MacOS X:
+To compile for MacOS X or iOS:
 
     Use the included XCode project.  Requires XCode 4 and MacOS X 10.5
     or newer.
 
+To compile for Android:
+
+    See android/README.
+
 Interested in writing a new screen saver?
 
     See the README.hacking file.
@@ -38,6 +42,18 @@ XScreenSaver has an extensive manual -- please read it!
 
 ===============================================================================
 
+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.7 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.
+       * X11: `pong' is now playable.
+
 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.
index 4b9a5174b317546da17b028a627f095988d1eb4e..e9201d78ac72e08201a56dcea1555774e69a5627 100644 (file)
@@ -1,6 +1,6 @@
-# generated automatically by aclocal 1.14.1 -*- Autoconf -*-
+# generated automatically by aclocal 1.15 -*- Autoconf -*-
 
-# Copyright (C) 1996-2013 Free Software Foundation, Inc.
+# Copyright (C) 1996-2014 Free Software Foundation, Inc.
 
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -561,31 +561,6 @@ fi
 # Substitute ALL_LINGUAS so we can use it in po/Makefile
 AC_SUBST(ALL_LINGUAS)
 
-# Set DATADIRNAME correctly if it is not set yet
-# (copied from glib-gettext.m4)
-if test -z "$DATADIRNAME"; then
-  AC_LINK_IFELSE(
-    [AC_LANG_PROGRAM([[]],
-                     [[extern int _nl_msg_cat_cntr;
-                       return _nl_msg_cat_cntr]])],
-    [DATADIRNAME=share],
-    [case $host in
-    *-*-solaris*)
-    dnl On Solaris, if bind_textdomain_codeset is in libc,
-    dnl GNU format message catalog is always supported,
-    dnl since both are added to the libc all together.
-    dnl Hence, we'd like to go with DATADIRNAME=share
-    dnl in this case.
-    AC_CHECK_FUNC(bind_textdomain_codeset,
-      [DATADIRNAME=share], [DATADIRNAME=lib])
-    ;;
-    *)
-    [DATADIRNAME=lib]
-    ;;
-    esac])
-fi
-AC_SUBST(DATADIRNAME)
-
 IT_PO_SUBDIR([po])
 
 ])
@@ -649,13 +624,13 @@ dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
 dnl
-dnl This file can can be used in projects which are not available under
+dnl This file can be used in projects which are not available under
 dnl the GNU General Public License or the GNU Library General Public
 dnl License but which still want to provide support for the GNU gettext
 dnl functionality.
 dnl Please note that the actual code of the GNU gettext library is covered
 dnl by the GNU Library General Public License, and the rest of the GNU
-dnl gettext package package is covered by the GNU General Public License.
+dnl gettext package is covered by the GNU General Public License.
 dnl They are *not* in the public domain.
 
 dnl Authors:
@@ -675,7 +650,7 @@ AC_DEFUN([AM_NLS],
   AC_SUBST([USE_NLS])
 ])
 
-# Copyright (C) 2006-2013 Free Software Foundation, Inc.
+# Copyright (C) 2006-2014 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
index a5ddb40625126c173009ce1ad91f875d29f6a8ed..f296352011d29d9f3263e8a2ef0ad8e83de90659 100644 (file)
 # XScreenSaver for Android
 
+export TERM=dumb
+GRADLE = cd project ; ./gradlew
 
-TARGET         = project
+default:: debug
+all:: release
 
-default: apk
-
-clean:: gradle_clean
-
-distclean::
+clean::
+       $(GRADLE) clean
 
 distdepend::
 
-all:
-       cd project ; ./gradlew assembleDebug
+# Set this to the set of platforms you want to compile for in debug mode.
+# E.g., if you are running an x86 emulator, there's no point in compiling
+# for a dozen other platforms.  Release builds override this to "all".
+#
+export APP_ABI = all
+
 
 # TODO:
 # check_versions:
-# update_thumbs:
+
+
+# These hacks have interdependencies with others, so we can't build without
+# including them or there are link errors:
+#
+ANDROID_BASE_HACKS=            \
+       apple2                  \
+       bubble3d                \
+       pacman                  \
+       polyhedra               \
+       sonar                   \
+       sproingies              \
+
+# These are the ones that currently work, at least to some degree:
+#
+export ANDROID_HACKS=          \
+       $(ANDROID_BASE_HACKS)   \
+       abstractile             \
+       anemone                 \
+       anemotaxis              \
+       apollonian              \
+       attraction              \
+       atunnel                 \
+       blaster                 \
+       blinkbox                \
+       blocktube               \
+       boing                   \
+       bouncingcow             \
+       boxed                   \
+       boxfit                  \
+       braid                   \
+       bsod                    \
+       cage                    \
+       ccurve                  \
+       cloudlife               \
+       companioncube           \
+       compass                 \
+       coral                   \
+       crystal                 \
+       cubestorm               \
+       cwaves                  \
+       cynosure                \
+       dangerball              \
+       decayscreen             \
+       deco                    \
+       demon                   \
+       discrete                \
+       distort                 \
+       dnalogo                 \
+       drift                   \
+       energystream            \
+       engine                  \
+       epicycle                \
+       eruption                \
+       euler2d                 \
+       fadeplot                \
+       fiberlamp               \
+       fireworkx               \
+       flame                   \
+       flipflop                \
+       flow                    \
+       fluidballs              \
+       flyingtoasters          \
+       fuzzyflakes             \
+       galaxy                  \
+       gears                   \
+       geodesic                \
+       geodesicgears           \
+       glcells                 \
+       glknots                 \
+       glmatrix                \
+       glschool                \
+       glsnake                 \
+       gltext                  \
+       grav                    \
+       greynetic               \
+       helix                   \
+       hexadrop                \
+       hilbert                 \
+       hopalong                \
+       hypnowheel              \
+       ifs                     \
+       imsmap                  \
+       interference            \
+       intermomentary          \
+       julia                   \
+       kaleidescope            \
+       kaleidocycle            \
+       klein                   \
+       kumppa                  \
+       lament                  \
+       lavalite                \
+       loop                    \
+       m6502                   \
+       maze                    \
+       memscroller             \
+       menger                  \
+       metaballs               \
+       moebiusgears            \
+       moire                   \
+       morph3d                 \
+       nerverot                \
+       noof                    \
+       penetrate               \
+       penrose                 \
+       petri                   \
+       piecewise               \
+       pinion                  \
+       polytopes               \
+       pong                    \
+       popsquares              \
+       providence              \
+       pyro                    \
+       quasicrystal            \
+       raverhoop               \
+       rd-bomb                 \
+       ripples                 \
+       romanboy                \
+       rorschach               \
+       rotzoomer               \
+       rubik                   \
+       rubikblocks             \
+       sballs                  \
+       shadebobs               \
+       sierpinski              \
+       sierpinski3d            \
+       slidescreen             \
+       squiral                 \
+       stairs                  \
+       starfish                \
+       stonerview              \
+       strange                 \
+       substrate               \
+       superquadrics           \
+       swirl                   \
+       tangram                 \
+       thornbird               \
+       timetunnel              \
+       topblock                \
+       triangle                \
+       tronbit                 \
+       twang                   \
+       unknownpleasures        \
+       vermiculate             \
+       voronoi                 \
+       wander                  \
+       whirlwindwarp           \
+       winduprobot             \
+       wormhole                \
+       xflame                  \
+       xlyap                   \
+       xspirograph             \
+
+
+# These don't work well enough to turn on by default:
+#
+ANDROID_TODO=                  \
+       antinspect              \
+       antmaze                 \
+       antspotlight            \
+       atlantis                \
+       barcode                 \
+       binaryring              \
+       blitspin                \
+       bouboule                \
+       bumps                   \
+       carousel                \
+       celtic                  \
+       circuit                 \
+       cityflow                \
+       crackberg               \
+       cube21                  \
+       cubenetic               \
+       cubicgrid               \
+       deluxe                  \
+       dymaxionmap             \
+       endgame                 \
+       flipscreen3d            \
+       fliptext                \
+       fontglide               \
+       gflux                   \
+       glblur                  \
+       gleidescope             \
+       glhanoi                 \
+       glplanet                \
+       glslideshow             \
+       goop                    \
+       halftone                \
+       halo                    \
+       hypertorus              \
+       interaggregate          \
+       jigglypuff              \
+       jigsaw                  \
+       juggler3d               \
+       mirrorblob              \
+       moebius                 \
+       moire2                  \
+       molecule                \
+       mountain                \
+       munch                   \
+       noseguy                 \
+       pedal                   \
+       phosphor                \
+       photopile               \
+       pipes                   \
+       polyominoes             \
+       projectiveplane         \
+       pulsar                  \
+       qix                     \
+       queens                  \
+       rocks                   \
+       skytentacles            \
+       slip                    \
+       speedmine               \
+       spheremonics            \
+       splitflap               \
+       spotlight               \
+       starwars                \
+       surfaces                \
+       tessellimage            \
+       testx11                 \
+       truchet                 \
+       unicrud                 \
+       xanalogtv               \
+       xjack                   \
+       xmatrix                 \
+       xrayswarm               \
+       zoom                    \
+
+
+# Download and resize images from jwz.org.
+# This saves us having to include 4MB of images in the tar file
+# that will only be used by a vast minority of people building
+# from source.
+# Android actually wants these to be 160x160 but our source is 200x150.
+
+URL = https://www.jwz.org/xscreensaver/screenshots/
+WGET = wget -q -U xscreensaver-build-android
+CVT  = -thumbnail '150x150^' -gravity center -extent 150x150 \
+     \( +clone  -alpha extract \
+        -draw 'fill black polygon 0,0 0,15 15,0 fill white circle 15,15 15,0' \
+        \( +clone -flip \) -compose Multiply -composite \
+        \( +clone -flop \) -compose Multiply -composite \
+     \) -alpha off -compose CopyOpacity -composite \
+    -colorspace sRGB \
+    -strip \
+    -quality 95 \
+    +dither -colors 128
+
+
+project/xscreensaver/res/drawable/%.png:
+       @\
+       FILE1=`echo "$@" | sed 's!^.*/\([^/]*\)\.png$$!\1.jpg!'` ;      \
+       FILE2="$@" ;                                                    \
+       FILE1=`echo "$$FILE1" | sed s/rdbomb/rd-bomb/` ;                \
+       FILE2=`echo "$$FILE2" | sed s/rd-bomb/rdbomb/` ;                \
+       URL="$(URL)$$FILE1" ;                                           \
+       echo "converting $$URL..." ;                                    \
+       rm -f "$$FILE2" ;                                               \
+       $(WGET) -O- "$$URL" |                                           \
+       convert jpg:- $(CVT) "$$FILE2" ;                                \
+       if [ ! -s "$$FILE2" ]; then                                     \
+         echo "$$FILE2 failed" >&2 ;                                   \
+         exit 1 ;                                                      \
+       fi
+
+thumbs::
+       @for f in $(ANDROID_HACKS) $(ANDROID_TODO) ; do                 \
+         $(MAKE) project/xscreensaver/res/drawable/$$f.png ;           \
+       done
+
+clean_thumbs::
+       @\
+       for f in $(ANDROID_HACKS) $(ANDROID_TODO) ; do                  \
+         rm -f project/xscreensaver/res/drawable/$$f.png ;             \
+       done
+distclean:: clean_thumbs
+
+
+EXTRA_TARFILES = project/xscreensaver/res/drawable/thumbnail.png \
 
 echo_tarfiles:
-       @echo `find \
-               Makefile \
-               README \
-               *.[ch] *.pl \
-               project \
-               project/xscreensaver/res/drawable/*.png \
-               project/xscreensaver/res/values/settings.xml \
-               project/xscreensaver/res/values/strings.xml \
-         \( \( -name '.??*' -o -name build -o -name gen \
-                -o -name libs -o -name obj -o -name '*~*' \) \
-            -prune \) \
-         -o \( -type f -o -type l \) -print \
-       | sed 's@^\./@@' \
-       | sort`
-
-apk: apk_raw_debug
-
-apk_raw_debug:
-               cd $(TARGET); ./gradlew assembleDebug
-
-gradle_clean:
-               -cd $(TARGET); ./gradlew clean
+       @FILES=`find . $(EXTRA_TARFILES) \( \(  \
+                  -name .DS_Store              \
+               -o -name '*~'                   \
+               -o -name '*.keystore'           \
+               -o -name '*_dream.xml'          \
+               -o -name '*_settings.xml'       \
+               -o -name AndroidManifest.xml    \
+               -o -name strings.xml            \
+               -o -name settings.xml           \
+               -o -name attrs.xml              \
+               -o -name .gitignore             \
+               -o -name .gradle                \
+               -o -name drawable               \
+               -o -name build                  \
+               -o -name gen                    \
+               -o -name libs                   \
+               -o -name obj                    \
+               \) -prune \)                    \
+               -o \( \( -type f -o -type l \)  \
+                     -print \)                 \
+               | sed 's@^\./@@'                \
+               | sort` ;                       \
+       echo $$FILES
+
+debug::
+       $(GRADLE) assembleDebug
+release::
+       export APP_ABI=all ; \
+       $(GRADLE) assembleRelease
+
+
+KEYSTORE = xscreensaver.keystore
+$(KEYSTORE):
+       keytool -genkey -v -keystore $@ \
+       -alias xscreensaver -keyalg RSA -keysize 2048 -validity 10000
+
+APK_DIR       = project/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
+
+  TOOLDIR = $(shell echo $$HOME/Library/Android/sdk/build-tools/* | tail -1)
+ ZIPALIGN = $(TOOLDIR)/zipalign
+JARSIGNER = jarsigner
+
+sign_release::
+       cp -p $(APK_UNSIGNED) $(APK_UNALIGNED)
+       $(JARSIGNER) -verbose -sigalg SHA1withRSA -digestalg SHA1 \
+                    -keystore $(KEYSTORE) $(APK_UNALIGNED) xscreensaver
+       rm -f $(APK_SIGNED)
+       $(ZIPALIGN) -v 4 $(APK_UNALIGNED) $(APK_SIGNED)
+       rm -f $(APK_UNALIGNED)
+       $(JARSIGNER) -verify -verbose -certs $(APK_SIGNED)
+       @ls -lF $(APK_SIGNED)
+
+apk:: release
+       @\
+  VERS=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ]*\).*/\1/p' ../utils/version.h` ; \
+  HEAD="xscreensaver-$$VERS" ;                                               \
+  if [ ! -s $(APK_SIGNED) -o $(APK_UNSIGNED) -nt $(APK_SIGNED) ]; then \
+    $(MAKE) sign_release ;                                             \
+  fi ;                                                                 \
+  set -x ;                                                             \
+  cp -p $(APK_SIGNED) ../archive/$$HEAD.apk
+
 
+## #### Pare it down for faster debugging...
+#export APP_ABI = armeabi-v7a
+#export APP_ABI = x86
+#
+#export ANDROID_HACKS=         \
+#      $(ANDROID_BASE_HACKS)   \
+#  bsod                                \
+#  apollonian                  \
+#  engine                      \
+#  dnalogo                     \
+#  twang                       \
+#  memscroller                 \
index 35b7b426d48d058fb55c1884df0210cceb55070d..74b8097ccfcece2d5151f72bd992a9eca251b4d8 100644 (file)
@@ -9,7 +9,7 @@ If you're messing with this, please let us know!
         jwz@jwz.org
 
 
-To build:
+To set up your Android development environment:
 
     Install JDK 7 (http://www.oracle.com/technetwork/java/javase/downloads/)
     Install Android Studio (http://developer.android.com/sdk/)
@@ -23,64 +23,215 @@ To build:
     On MacOS, the value you want is probably ~/Library/Android/sdk/
     Also set "ndk.dir" in project/local.properties.
 
+To build:
+
+    ./configure
     cd android
     make
 
-    If it fails, try a "make clean" and then try make again.
-    Make sure you have the needed Android SDK platform versions installed.
-
     Hopefully an "xscreensaver-debug.apk" file will appear in
     android/project/xscreensaver/build/outputs/apk/.
 
     Load that onto your device and go to:
-      Settings / Display / Wallpaper / Live Wallpapers.
+      Settings / Display / Daydream
+    or just click on the XScreenSaver icon, which is a shortcut to that.
+
+    To create and configure an emulator image, use the GUI tool and and
+    give the emulator a name (say, "Nexus_5").
+
+      $ANDROID_HOME/sdk/tools/android avd
+
+    Configuration options are in $HOME/.android/avd/*.avd/config.ini
 
-    To launch the emulator:
-      $ANDROID_HOME/sdk/tools/emulator -avd Nexus_5_API_21_x86
+    To launch it:
 
-    To load it into the currently-running emulator:
+      $ANDROID_HOME/sdk/tools/emulator -avd Nexus_5
+
+    Warning!  On my system at least, the emulator runs out of memory
+    when trying to display the Daydream page if all of the savers are
+    loaded.  This is troubling.  You can work around this by editing
+    your *.avd/config.ini and setting vm.heapSize=128; or by editing
+    android/Makefile and paring down the $ANDROID_HACKS list to a
+    smaller subset (60 or so with the default heapSize).
+
+
+    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
 
+    Extremely verbose log output, including stack traces:
+        $ANDROID_HOME/platform-tools/adb logcat
 
-The files in these subdirectories are source code, more or less:
+    Non-fatal log output for only this app:
+        $ANDROID_HOME/platform-tools/adb logcat \
+          -s xscreensaver:d AndroidRuntime:d libEGL:d
 
-        project/xscreensaver/*.xml
-        project/xscreensaver/src/org/jwz/xscreensaver/
-        project/GLWallpaperService/ (a third-party library, unchanged)
+    Note that sometimes "logcat" will just sit there forever saying
+    "waiting for device".  This is because the emulator is a piece of
+    shit and sometimes decides to just randomly not service connections.
+    If you restart the emulator, and wait minutes for the whole damned
+    thing to boot up again, it will probably work next time.  Probably.
 
-These directories are boilerplate for Android apps:
 
-        project/xscreensaver/res/layout/
-        project/xscreensaver/res/values/
-        project/xscreensaver/res/xml/
+Directory structure:
+
+    Boilerplate for the Java version of "make":
+        project/*gradle*
+        project/*.properties
+        project/xscreensaver/*gradle*
+        project/xscreensaver/build.*
+        project/xscreensaver/*.properties
+
+    The other half of the Makefile:
+        project/xscreensaver/jni/*.mk
+
+    Source code:
+        project/xscreensaver/src/org/jwz/xscreensaver/*.java
+        project/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-hdpi/
-        project/xscreensaver/res/drawable/thumbnail.png
+        project/xscreensaver/res/drawable/
 
-These are files that we generate:
+    Files that we generate:
 
-        project/xscreensaver/src/org/jwz/xscreensaver/gen/
+        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
 
-These too (intermediate build files):
+    Other files generated as a part of the build process:
 
-        .gradle/
         gen/
-        project/GLWallpaperService/build/
-        project/build/
+        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/
 
-These are files that we *will* generate but don't yet:
-
-        project/xscreensaver/res/drawable/*.png
-        XScreenSaverView.c
-
-When adding a new hack, edit:
-
-        project/xscreensaver/jni/Android.mk
-        project/xscreensaver/build.gradle
-        generate_files.pl
+When adding a new hack, edit android/Makefile, then "make clean" and "make".
+
+
+TODO list, and known bugs:
+
+  - See the top of ../jwxyz/jwxyz-gl.c for a low level TODO list,
+    but here's what's wrong with the savers from a high level view:
+
+  - Rotation is wonky (on some devices?)
+
+  - The Android emulator is a piece of shit and crashes all the time,
+    so it's possible that some of these work fine on real devices.
+    I don't actually have an Android device, so I have no idea.
+
+  - As mentioned above, the Android emulator runs out of memory if
+    more than about 60 of the Daydreams are installed with the default
+    heapSize.  Again, I don't know if this is an issue on real devices.
+    I sure hope not.
+
+  - The code that attempts to grab a screen shot before the Daydream begins
+    doesn't work.
+
+  - When a saver exits abnormally, we catch the exception and attempt to 
+    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
+  apple2       text, images into pixmaps doesn't work
+  atlantis     crashes emulator, sometimes
+  barcode       pixmaps
+  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
+  flipflop      images
+  flipscreen3d  images
+  fliptext      text
+  fontglide     text
+  fuzzyflakes   thick lines
+  gflux         images
+  glblur        crashes emulator, sometimes
+  gleidescope   images
+  glhanoi       crashes emulator, but a few seconds in
+  glplanet      crashes emulator
+  glslideshow   images
+  goop          polygons
+  halftone      XFillArc crash
+  halo          XOR
+  hypertorus    crashes emulator
+  interaggregate        window background should be white
+  jigglypuff    incredibly slow
+  jigsaw        crashes emulator
+  juggler3d    crashes emulator
+  maze          no logo, lines look weird
+  mirrorblob    images
+  moebius       crashes emulator
+  moire2        pixmaps
+  molecule     crashes emulator
+  mountain      polygons
+  munch         XOR
+  noseguy       pixmaps
+  pacman       launches really slowly; fails at loading XPMs
+  pedal         polygons
+  phosphor      pixmaps
+  photopile     pixmaps
+  pipes         blank
+  polyhedra    crashes emulator
+  polyominoes   pixmaps
+  projectiveplane       crashes emulator
+  pulsar        crashes emulator
+  qix           polygons
+  queens       crashes emulator
+  rocks         polygons
+  skytentacles  crashes emulator
+  slip          pixmaps
+  sonar                crashes emulator
+  speedmine     polygons
+  spheremonics  crashes emulator
+  splitflap     text
+  spotlight     pixmaps
+  starfish      polygons
+  starwars     crashes emulator
+  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/XScreenSaverDaydream.java.in b/android/XScreenSaverDaydream.java.in
new file mode 100644 (file)
index 0000000..46c3dc7
--- /dev/null
@@ -0,0 +1,26 @@
+/* -*- 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 template for the generated per-saver classes.
+ */
+
+package org.jwz.xscreensaver.gen;
+
+import org.jwz.xscreensaver.XScreenSaverDaydream;
+import org.jwz.xscreensaver.jwxyz;
+
+public class @CLASS@ extends XScreenSaverDaydream {
+  public @CLASS@() {
+    super(jwxyz.API_@API@);
+  }
+}
diff --git a/android/XScreenSaverGLView.c b/android/XScreenSaverGLView.c
deleted file mode 100644 (file)
index 346b292..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-#include <android/log.h>
-#include "screenhackI.h"
-#include "xlockmoreI.h"
-
-#if defined(USE_IPHONE) || (HAVE_ANDROID)
-# include "jwzgles.h"
-#else
-# include <OpenGL/OpenGL.h>
-#endif
-
-/* used by the OpenGL screen savers
- */
-extern GLXContext *init_GL (ModeInfo *);
-extern void glXSwapBuffers (Display *, Window);
-extern void glXMakeCurrent (Display *, Window, GLXContext);
-extern void clear_gl_error (void);
-extern void check_gl_error (const char *type);
-
-/* Does nothing - prepareContext already did the work.
- */
-void
-glXMakeCurrent (Display *dpy, Window window, GLXContext context)
-{
-}
-
-
-/* clear away any lingering error codes */
-void
-clear_gl_error (void)
-{
-  while (glGetError() != GL_NO_ERROR)
-    ;
-}
-
-
-// needs to be implemented in Android...
-/* Copy the back buffer to the front buffer.
- */
-void
-glXSwapBuffers (Display *dpy, Window window)
-{
-}
-
-
-/* Called by OpenGL savers using the XLockmore API.
- */
-GLXContext *
-init_GL (ModeInfo *mi)
-{
-  Window win = mi->window;
-
-  // Caller expects a pointer to an opaque struct...  which it dereferences.
-  // Don't ask me, it's historical...
-  static int blort = -1;
-  return (void *) &blort;
-}
-
-/* report a GL error. */
-void
-check_gl_error (const char *type)
-{
-  char buf[100];
-  GLenum i;
-  const char *e;
-  switch ((i = glGetError())) {
-    case GL_NO_ERROR: return;
-    case GL_INVALID_ENUM:          e = "invalid enum";      break;
-    case GL_INVALID_VALUE:         e = "invalid value";     break;
-    case GL_INVALID_OPERATION:     e = "invalid operation"; break;
-    case GL_STACK_OVERFLOW:        e = "stack overflow";    break;
-    case GL_STACK_UNDERFLOW:       e = "stack underflow";   break;
-    case GL_OUT_OF_MEMORY:         e = "out of memory";     break;
-#ifdef GL_TABLE_TOO_LARGE_EXT
-    case GL_TABLE_TOO_LARGE_EXT:   e = "table too large";   break;
-#endif
-#ifdef GL_TEXTURE_TOO_LARGE_EXT
-    case GL_TEXTURE_TOO_LARGE_EXT: e = "texture too large"; break;
-#endif
-    default:
-      e = buf; sprintf (buf, "unknown GL error %d", (int) i); break;
-  }
-  __android_log_write(ANDROID_LOG_ERROR, "xscreensaver", e);
-}
-
diff --git a/android/XScreenSaverSettings.java.in b/android/XScreenSaverSettings.java.in
new file mode 100644 (file)
index 0000000..914c653
--- /dev/null
@@ -0,0 +1,24 @@
+/* -*- 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 template for the generated per-saver "Settings" classes.
+ */
+
+package org.jwz.xscreensaver.gen;
+
+import android.content.SharedPreferences;
+import org.jwz.xscreensaver.XScreenSaverSettings;
+
+public class @CLASS@ extends XScreenSaverSettings
+  implements SharedPreferences.OnSharedPreferenceChangeListener {
+}
diff --git a/android/XScreenSaverView.c b/android/XScreenSaverView.c
deleted file mode 100644 (file)
index c89ec1b..0000000
+++ /dev/null
@@ -1,425 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <zlib.h>
-//#include <android/log.h>
-#include "screenhackI.h"
-#include "xlockmoreI.h"
-
-#ifndef isupper
-# define isupper(c)  ((c) >= 'A' && (c) <= 'Z')
-#endif
-#ifndef _tolower
-# define _tolower(c)  ((c) - 'A' + 'a')
-#endif
-
-extern struct xscreensaver_function_table *xscreensaver_function_table;
-
-extern const char *progname;
-extern const char *progclass;
-int mono_p = 0;
-
-static char *hilbert_mode;
-static char *sproingies_count;
-static char *sproingies_wireframe;
-static char *bouncingcow_count;
-static char *bouncingcow_speed;
-static char *superquadrics_spinspeed;
-static char *stonerview_delay;
-static char *stonerview_transparent;
-static char *unknownpleasures_wireframe;
-static char *unknownpleasures_speed;
-static char *hypertorus_displayMode;
-static char *hypertorus_appearance;
-static char *hypertorus_colors;
-static char *hypertorus_projection3d;
-static char *hypertorus_projection4d;
-static char *hypertorus_speedwx;
-static char *hypertorus_speedwy;
-static char *hypertorus_speedwz;
-static char *hypertorus_speedxy;
-static char *hypertorus_speedxz;
-static char *hypertorus_speedyz;
-static char *glhanoi_light;
-static char *glhanoi_fog;
-static char *glhanoi_trails;
-static char *glhanoi_poles;
-static char *glhanoi_speed;
-
-
-Bool 
-get_boolean_resource (Display *dpy, char *res_name, char *res_class)
-{
-  char *tmp, buf [100];
-  char *s = get_string_resource (dpy, res_name, res_class);
-  char *os = s;
-  if (! s) return 0;
-  for (tmp = buf; *s; s++)
-    *tmp++ = isupper (*s) ? _tolower (*s) : *s;
-  *tmp = 0;
-  //free (os);
-
-  while (*buf &&
-         (buf[strlen(buf)-1] == ' ' ||
-          buf[strlen(buf)-1] == '\t'))
-    buf[strlen(buf)-1] = 0;
-
-  if (!strcmp (buf, "on") || !strcmp (buf, "true") || !strcmp (buf, "yes"))
-    return 1;
-  if (!strcmp (buf,"off") || !strcmp (buf, "false") || !strcmp (buf,"no"))
-    return 0;
-  fprintf (stderr, "%s: %s must be boolean, not %s.\n",
-           progname, res_name, buf);
-  return 0;
-}
-
-int 
-get_integer_resource (Display *dpy, char *res_name, char *res_class)
-{
-  int val;
-  char c, *s = get_string_resource (dpy, res_name, res_class);
-  char *ss = s;
-  if (!s) return 0;
-
-  while (*ss && *ss <= ' ') ss++;                       /* skip whitespace */
-
-  if (ss[0] == '0' && (ss[1] == 'x' || ss[1] == 'X'))   /* 0x: parse as hex */
-    {
-      if (1 == sscanf (ss+2, "%x %c", (unsigned int *) &val, &c))
-        {
-          //free (s);
-          return val;
-        }
-    }
-  else                                                  /* else parse as dec */
-    {
-      if (1 == sscanf (ss, "%d %c", &val, &c))
-        {
-          //free (s);
-          return val;
-        }
-    }
-
-  fprintf (stderr, "%s: %s must be an integer, not %s.\n",
-           progname, res_name, s);
-  //free (s);
-  return 0;
-}
-
-double
-get_float_resource (Display *dpy, char *res_name, char *res_class)
-{
-  double val;
-  char c, *s = get_string_resource (dpy, res_name, res_class);
-  if (! s) return 0.0;
-  if (1 == sscanf (s, " %lf %c", &val, &c))
-    {
-      //free (s);
-      return val;
-    }
-  fprintf (stderr, "%s: %s must be a float, not %s.\n",
-           progname, res_name, s);
-  //free (s);
-  return 0.0;
-}
-
-
-// TODO: fill in what is not here
-char *get_string_resource(Display * dpy, char *name, char *class)
-{
-    char *implement;
-    //__android_log_print (ANDROID_LOG_INFO, "xscreensaver", "s %s %s %s", progname, name, class); 
-
-    if (strcmp(progname, "hilbert") == 0) {
-       if (strcmp(name, "mode") == 0 && strcmp(class, "Mode") == 0) {
-           implement = malloc(8 * sizeof(char));
-           strcpy(implement, hilbert_mode);
-       } else if (strcmp(name, "ends") == 0 && strcmp(class, "Ends") == 0) {
-           implement = malloc(5 * sizeof(char));
-           strcpy(implement, "open");
-       } else if (strcmp(name, "speed") == 0 && strcmp(class, "Speed") == 0) {
-           return "1.0";
-       } else if (strcmp(name, "thickness") == 0
-                  && strcmp(class, "Thickness") == 0) {
-           return "0.25";
-       } else if (strcmp(name, "delay") == 0 && strcmp(class, "Usecs") == 0) {
-           return "30000";
-       } else if (strcmp(name, "maxDepth") == 0
-           && strcmp(class, "MaxDepth") == 0) {
-           // too deep is too much for less powerful Android phones
-           return "3";
-           //return 5;
-       } else if (strcmp(name, "spin") == 0 && strcmp(class, "Spin") == 0) {
-            return "True";
-       } else if (strcmp(name, "wireframe") == 0
-                  && strcmp(class, "Boolean") == 0) {
-            return "False";
-       } else if (strcmp(name, "wander") == 0
-                  && strcmp(class, "Wander") == 0) {
-            return "False";
-       } else {
-            return 0;
-        }
-    }
-    else if (strcmp(progname, "sproingies") == 0) {
-       if (strcmp(name, "count") == 0 && strcmp(class, "Int") == 0) {
-           return sproingies_count;
-       } else if (strcmp(name, "wireframe") == 0
-           && strcmp(class, "Boolean") == 0) {
-           return sproingies_wireframe;
-       } else {
-            return 0;
-        }
-    }
-    else if (strcmp(progname, "superquadrics") == 0) {
-       if (strcmp(name, "spinspeed") == 0
-           && strcmp(class, "Spinspeed") == 0) {
-           return superquadrics_spinspeed;
-       } else if (strcmp(name, "count") == 0 && strcmp(class, "Int") == 0) {
-           return "25";
-       } else if (strcmp(name, "cycles") == 0
-                  && strcmp(class, "Int") == 0) {
-           return "40";
-       } else if (strcmp(name, "delay") == 0
-                  && strcmp(class, "Usecs") == 0) {
-           return "40000";
-       } else if (strcmp(name, "wireframe") == 0
-           && strcmp(class, "Boolean") == 0) {
-            return "False";
-       } else {
-            return 0;
-        }
-    }
-    else if (strcmp(progname, "stonerview") == 0) {
-       if (strcmp(name, "use3d") == 0 && strcmp(class, "Boolean") == 0) {
-           return "True";
-       } else if (strcmp(name, "transparent") == 0
-                  && strcmp(class, "Transparent") == 0) {
-           return stonerview_transparent;
-       } else if (strcmp(name, "wireframe") == 0
-                  && strcmp(class, "Boolean") == 0) {
-           return "False";
-       } else if (strcmp(name, "doFPS") == 0
-                  && strcmp(class, "DoFPS") == 0) {
-           return "False";
-        } else {
-            return 0;
-        }
-    }
-    else if (strcmp(progname, "bouncingcow") == 0) {
-       if (strcmp(name, "count") == 0
-           && strcmp(class, "Int") == 0) {
-           return bouncingcow_count;
-        } else if (strcmp(name, "speed") == 0
-           && strcmp(class, "Speed") == 0) {
-           return bouncingcow_speed;
-        } else {
-            return 0;
-        }
-    }
-    else if (strcmp(progname, "unknownpleasures") == 0) {
-
-        if (strcmp(name, "wireframe") == 0) {
-          return unknownpleasures_wireframe;
-        } else if (strcmp(name, "speed") == 0) {
-          return unknownpleasures_speed;
-        } else if (strcmp(name, "count") == 0) {
-          return "80";
-        } else if (strcmp(name, "resolution") == 0) {
-          return "100";
-          //return "200";
-        } else if (strcmp(name, "ortho") == 0) {
-          return "True";
-          //return "False";
-        } else {
-          return 0;
-        }
-
-    }
-    else if (strcmp(progname, "hypertorus") == 0) {
-       if (strcmp(name, "displayMode") == 0) {
-           return hypertorus_displayMode;
-       } else if (strcmp(name, "appearance") == 0) {
-           return hypertorus_appearance;
-       } else if (strcmp(name, "colors") == 0) {
-           return hypertorus_colors;
-       } else if (strcmp(name, "projection3d") == 0) {
-           return hypertorus_projection3d;
-       } else if (strcmp(name, "projection4d") == 0) {
-           return hypertorus_projection4d;
-       } else if (strcmp(name, "speedwx") == 0) {
-           return hypertorus_speedwz;
-       } else if (strcmp(name, "speedwy") == 0) {
-           return hypertorus_speedwy;
-       } else if (strcmp(name, "speedwz") == 0) {
-           return hypertorus_speedwz;
-       } else if (strcmp(name, "speedxy") == 0) {
-           return hypertorus_speedxy;
-       } else if (strcmp(name, "speedxz") == 0) {
-           return hypertorus_speedxz;
-       } else if (strcmp(name, "speedyz") == 0) {
-           return hypertorus_speedyz;
-       } else {
-            return 0;
-        }
-    }
-    else if (strcmp(progname, "glhanoi") == 0) {
-        if (strcmp(name, "light") == 0) {
-            return glhanoi_light;
-        } else if (strcmp(name, "fog") == 0) {
-            return glhanoi_fog;
-        } else if (strcmp(name, "trails") == 0) {
-            return glhanoi_trails;
-        } else if (strcmp(name, "poles") == 0) {
-            return glhanoi_poles;
-        } else if (strcmp(name, "speed") == 0) {
-            return glhanoi_speed;
-        } else {
-            return 0;
-        }
-    }
-    else {
-       implement = 0;
-    }
-
-    return implement;
-}
-
-
-void setSuperquadricsSettings(char *hck, char *khck)
-{
-    if (strcmp(khck, "superquadrics_spinspeed") == 0) {
-        superquadrics_spinspeed = malloc(4 * sizeof(char));
-        strcpy(superquadrics_spinspeed, hck);
-    }
-}
-
-void setHilbertSettings(char *hck, char *khck)
-{
-    if (strcmp(khck, "hilbert_mode") == 0) {
-        if (!hilbert_mode) {
-            hilbert_mode = malloc(8 * sizeof(char));
-        }
-        if (strcmp(hck, "3D") == 0) {
-            strcpy(hilbert_mode, "3D");
-        }
-        else if (strcmp(hck, "2D") == 0) {
-            strcpy(hilbert_mode, "2D");
-        }
-    }
-}
-
-void setSproingiesSettings(char *hck, char *khck)
-{
-    if (strcmp(khck, "sproingies_count") == 0) {
-        sproingies_count = malloc(3 * sizeof(char));
-        strcpy(sproingies_count, hck);
-    }
-    else if (strcmp(khck, "sproingies_wireframe") == 0) {
-        sproingies_wireframe = malloc(6 * sizeof(char));
-        strcpy(sproingies_wireframe, hck);
-    }
-}
-
-void setStonerviewSettings(char *hck, char *khck)
-{
-    if (strcmp(khck, "stonerview_transparent") == 0) {
-        stonerview_transparent = malloc(6 * sizeof(char));
-        strcpy(stonerview_transparent, hck);
-    }
-}
-
-void setBouncingcowSettings(char *hck, char *khck)
-{
-    if (strcmp(khck, "bouncingcow_count") == 0) {
-        bouncingcow_count = malloc(3 * sizeof(char));
-        strcpy(bouncingcow_count, hck);
-    }
-    else if (strcmp(khck, "bouncingcow_speed") == 0) {
-        bouncingcow_speed = malloc(4 * sizeof(char));
-        strcpy(bouncingcow_speed, hck);
-    }
-}
-
-void setUnknownpleasuresSettings(char *hck, char *khck)
-{
-    if (strcmp(khck, "unknownpleasures_speed") == 0) {
-        unknownpleasures_speed = malloc(3 * sizeof(char));
-        strcpy(unknownpleasures_speed, hck);
-    }
-    else if (strcmp(khck, "unknownpleasures_wireframe") == 0) {
-        unknownpleasures_wireframe = malloc(6 * sizeof(char));
-        strcpy(unknownpleasures_wireframe, hck);
-    }
-}
-
-void setHypertorusSettings(char *hck, char *khck)
-{
-    if (strcmp(khck, "hypertorus_displayMode") == 0) {
-        hypertorus_displayMode = malloc(13 * sizeof(char));
-        strcpy(hypertorus_displayMode, hck);
-    }
-    else if (strcmp(khck, "hypertorus_appearance") == 0) {
-        hypertorus_appearance = malloc(12 * sizeof(char));
-        strcpy(hypertorus_appearance, hck);
-    }
-    else if (strcmp(khck, "hypertorus_colors") == 0) {
-        hypertorus_colors = malloc(5 * sizeof(char));
-        strcpy(hypertorus_colors, hck);
-    }
-    else if (strcmp(khck, "hypertorus_projection3d") == 0) {
-        hypertorus_projection3d = malloc(17 * sizeof(char));
-        strcpy(hypertorus_projection3d, hck);
-    }
-    else if (strcmp(khck, "hypertorus_projection4d") == 0) {
-        hypertorus_projection4d = malloc(17 * sizeof(char));
-        strcpy(hypertorus_projection4d, hck);
-    }
-    else if (strcmp(khck, "hypertorus_speedwx") == 0) {
-        hypertorus_speedwx = malloc(5 * sizeof(char));
-        strcpy(hypertorus_speedwx, hck);
-    }
-    else if (strcmp(khck, "hypertorus_speedwy") == 0) {
-        hypertorus_speedwy = malloc(5 * sizeof(char));
-        strcpy(hypertorus_speedwy, hck);
-    }
-    else if (strcmp(khck, "hypertorus_speedwz") == 0) {
-        hypertorus_speedwz = malloc(5 * sizeof(char));
-        strcpy(hypertorus_speedwz, hck);
-    }
-    else if (strcmp(khck, "hypertorus_speedxy") == 0) {
-        hypertorus_speedxy = malloc(5 * sizeof(char));
-        strcpy(hypertorus_speedxy, hck);
-    }
-    else if (strcmp(khck, "hypertorus_speedxz") == 0) {
-        hypertorus_speedxz = malloc(5 * sizeof(char));
-        strcpy(hypertorus_speedxz, hck);
-    }
-    else if (strcmp(khck, "hypertorus_speedyz") == 0) {
-        hypertorus_speedyz = malloc(5 * sizeof(char));
-        strcpy(hypertorus_speedyz, hck);
-    }
-}
-
-void setGlhanoiSettings(char *hck, char *khck) {
-
-    if (strcmp(khck, "glhanoi_light") == 0) {
-        glhanoi_light = malloc(6 * sizeof(char));
-        strcpy(glhanoi_light , hck);
-    }
-    else if (strcmp(khck, "glhanoi_fog") == 0) {
-        glhanoi_fog = malloc(6 * sizeof(char));
-        strcpy(glhanoi_fog , hck);
-    }
-    else if (strcmp(khck, "glhanoi_trails") == 0) {
-        glhanoi_trails = malloc(3 * sizeof(char));
-        strcpy(glhanoi_trails , hck);
-    }
-    else if (strcmp(khck, "glhanoi_poles") == 0) {
-        glhanoi_poles = malloc(3 * sizeof(char));
-        strcpy(glhanoi_poles , hck);
-    }
-    else if (strcmp(khck, "glhanoi_speed") == 0) {
-        glhanoi_speed = malloc(3 * sizeof(char));
-        strcpy(glhanoi_speed , hck);
-    }
-}
diff --git a/android/XScreenSaverWallpaper.java.in b/android/XScreenSaverWallpaper.java.in
new file mode 100644 (file)
index 0000000..b9f7084
--- /dev/null
@@ -0,0 +1,26 @@
+/* -*- 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 template for the generated per-saver classes.
+ */
+
+package org.jwz.xscreensaver.gen;
+
+import org.jwz.xscreensaver.XScreenSaverWallpaper;
+import org.jwz.xscreensaver.jwxyz;
+
+public class @CLASS@ extends XScreenSaverWallpaper {
+  public @CLASS@() {
+    super("@NAME@", jwxyz.API_@API@);
+  }
+}
diff --git a/android/generate_files.pl b/android/generate_files.pl
deleted file mode 100755 (executable)
index cdc7b54..0000000
+++ /dev/null
@@ -1,1723 +0,0 @@
-#!/usr/bin/perl -w
-# Copyright © 2008-2015 Jamie Zawinski <jwz@jwz.org>
-# Copyright © 2015 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 parses the .c and .xml files and makes sure they are in sync: that
-# options are spelled the same, and that all the numbers are in sync.
-# Some of that functionality may be removed in the future.
-#
-# This also generates necessary Android files based on the information in
-# those source and XML files.
-#
-# For the moment, the get_keys_and_values() subroutine is where support for
-# previously unsupported Android live wallpapers is added.
-#
-# Created:  13-May-2015.
-
-require 5;
-use diagnostics;
-use strict;
-
-my $progname = $0; $progname =~ s@.*/@@g;
-my ($version) = ('$Revision: 1.1 $' =~ m/\s(\d[.\d]+)\s/s);
-
-my $verbose = 0;
-
-
-my $xlockmore_default_opts = '';
-foreach (qw(count cycles delay ncolors size font)) {
-  $xlockmore_default_opts .= "{\"-$_\", \".$_\", XrmoptionSepArg, 0},\n";
-}
-$xlockmore_default_opts .= 
- "{\"-wireframe\", \".wireframe\", XrmoptionNoArg, \"true\"},\n" .
- "{\"-3d\", \".use3d\", XrmoptionNoArg, \"true\"},\n" .
- "{\"-no-3d\", \".use3d\", XrmoptionNoArg, \"false\"},\n";
-
-my $thread_default_opts = 
-  "{\"-threads\",    \".useThreads\", XrmoptionNoArg, \"True\"},\n" .
-  "{\"-no-threads\", \".useThreads\", XrmoptionNoArg, \"False\"},\n";
-
-my $analogtv_default_opts = '';
-foreach (qw(color tint brightness contrast)) {
-  $analogtv_default_opts .= "{\"-tv-$_\", \".TV$_\", XrmoptionSepArg, 0},\n";
-}
-
-$analogtv_default_opts .= $thread_default_opts;
-
-
-sub parse_settings_xml($) {
-
-  my ($saver) = @_;
-
-  my $file = "project/xscreensaver/res/values/settings.xml";
-  my $body = '';
-
-  local *IN;
-
-  if (-e $file) {
-      open (IN, '<', $file) || error ("$file: $!");
-  }
-  else {
-      my @short;
-      return @short;
-  }
-
-  while (<IN>) { $body .= $_; }
-  close IN;
-  $file =~ s@^.*/@@;
-  $body =~ s/<!--.*?-->/ /gsi;
-  $body =~ s/\s+/ /gs;
-  $body =~ s/</\001</gs;
-
-  my (@all);
-  my $loop;
-
-  foreach (split (m/\001/, $body)) {
-    next if (m/^\s*$/s);
-    my ($type, $args) = m@^<([?/]?[-_a-z]+)\b\s*(.*)$@si;
-    error ("$progname: $file: unparsable: $_") unless $type;
-    next if ($type =~ m@^/@);
-
-    if ($type =~ m/^(\?xml|resources)/s) {
-
-    } elsif ($type eq 'string-array') {
-      my ($name) = ($args =~ m/\bname\s*=\s*\"([^\"]+)\"/);
-      my ($value) = ($args =~ m/>([^\"]+)/);
-      $loop = $name;
-
-      if ($name =~ /^$saver/) {
-        error ("$saver: $saver already in $file");
-      }
-
-    } elsif ($type eq 'item') {
-
-      my ($item_value) = ($args =~ m/>(.+)/);
-      my $item = $loop . " = " . $item_value;
-      push @all, $item;
-
-    } else {
-      error ("$file: unknown type \"$type\" for no arg");
-    }
-  }
-
-  return @all;
-
-}
-
-
-sub parse_items_xml($) {
-
-  my ($saver) = @_;
-
-  my $file = "project/xscreensaver/res/values/items.xml";
-  my $body = '';
-  my (%pixkeys) ;
-
-  local *IN;
-
-  if (-e $file) {
-      open (IN, '<', $file) || error ("$file: $!");
-  }
-  else {
-      my %short;
-      return %short;
-  }
-
-  while (<IN>) { $body .= $_; }
-  close IN;
-  $file =~ s@^.*/@@;
-  $body =~ s/<!--.*?-->/ /gsi;
-
-  $body =~ s/\s+/ /gs;
-  $body =~ s/</\001</gs;
-
-  foreach (split (m/\001/, $body)) {
-    next if (m/^\s*$/s);
-    my ($type, $args) = m@^<([?/]?[-_a-z]+)\b\s*(.*)$@si;
-    error ("$progname: $file: unparsable: $_") unless $type;
-    next if ($type =~ m@^/@);
-
-    if ($type =~ m/^(\?xml|resources)/s) {
-
-    } elsif ($type eq 'item') {
-      my ($name) = ($args =~ m/\bname\s*=\s*\"([^\"]+)\"/);
-      my ($value) = ($args =~ m/>([^\"]+)/);
-
-      if ($name =~ /^$saver/) {
-        error ("$saver: $saver already in $file");
-      }
-
-      $pixkeys{$name} = $value;
-
-    } else {
-      error ("$file: unknown type \"$type\" for no arg");
-    }
-  }
-
-  return (%pixkeys);
-}
-
-
-sub parse_glue($) {
-  my ($saver) = @_;
-  my $file = "gen/glue.c";
-  my $in;
-
-  if (-e $file) {
-      open ($in, '<', $file) || error ("$file: $!");
-  }
-  else {
-      my @short;
-      return @short;
-  }
-
-  my $body = '';
-  while (<$in>) { $body .= $_; }
-  close $in;
-  $file =~ s@^.*/@@;
-  $body =~ s@^#\s*(if|ifdef|ifndef|elif|else|endif).*$@@gm;
-
-  my (@hacks);
-  if ($body =~ m/table\s*\*([a-z,\s\*_]+)xscreensaver_function_table;/s) {
-    foreach (split (/,\s*\n/, $1)) {
-      s/^\s*//s;
-      s/\*//s;
-      my @ftables = split (/_/, $_);
-      my $ftable = $ftables[0];
-      if ($ftable eq $saver) {
-         error("$saver is already in glue");
-      }
-      push @hacks, $ftable;
-    }
-  }
-  return @hacks;
-}
-
-# Returns two tables:
-# - A table of the default resource values.
-# - A table of "-switch" => "resource: value", or "-switch" => "resource: %"
-#
-sub parse_src($) {
-  my ($saver) = @_;
-  my $ffile = lc($saver) . ".c";
-
-  # kludge...
-  $ffile = 'apple2-main.c' if ($ffile eq 'apple2.c');
-  $ffile = 'sproingiewrap.c' if ($ffile eq 'sproingies.c');
-  $ffile = 'b_lockglue.c' if ($ffile eq 'bubble3d.c');
-  $ffile = 'polyhedra-gl.c' if ($ffile eq 'polyhedra.c');
-  $ffile = 'companion.c' if ($ffile eq 'companioncube.c');
-
-  my $file = "../hacks/" . $ffile;
-
-  $file = "../hacks/glx/$ffile" unless (-f $file);
-  my $body = '';
-  open (my $in, '<', $file) || error ("$file: $!");
-  while (<$in>) { $body .= $_; }
-  close $in;
-  $file =~ s@^.*/@@;
-
-  my $xlockmore_p = 0;
-  my $thread_p = ($body =~ m/THREAD_DEFAULTS/);
-  my $analogtv_p = ($body =~ m/ANALOGTV_DEFAULTS/);
-
-  $body =~ s@/\*.*?\*/@@gs;
-  $body =~ s@^#\s*(if|ifdef|ifndef|elif|else|endif).*$@@gm;
-  $body =~ s/(THREAD|ANALOGTV)_(DEFAULTS|OPTIONS)(_XLOCK)?//gs;
-
-  print STDERR "$progname: $file: defaults:\n" if ($verbose > 2);
-  my %res_to_val;
-  if ($body =~ m/_defaults\s*\[\]\s*=\s*{(.*?)}\s*;/s) {
-    foreach (split (/,\s*\n/, $1)) {
-      s/^\s*//s;
-      s/\s*$//s;
-      next if m/^0?$/s;
-      my ($key, $val) = m@^\"([^:\s]+)\s*:\s*(.*?)\s*\"$@;
-      print STDERR "$progname: $file: unparsable: $_\n" unless $key;
-      $key =~ s/^[.*]//s;
-      $res_to_val{$key} = $val;
-      print STDERR "$progname: $file:   $key = $val\n" if ($verbose > 2);
-    }
-  } elsif ($body =~ m/\#\s*define\s*DEFAULTS\s*\\?\s*(.*?)\n[\n#]/s) {
-    $xlockmore_p = 1;
-    my $str = $1;
-    $str =~ s/\"\s*\\\n\s*\"//gs;
-    $str =~ m/^\s*\"(.*?)\"\s*\\?\s*$/ || 
-      error ("$file: unparsable defaults: $str");
-    $str = $1;
-    $str =~ s/\s*\\n\s*/\n/gs;
-    foreach (split (/\n/, $str)) {
-      my ($key, $val) = m@^([^:\s]+)\s*:\s*(.*?)\s*$@;
-      print STDERR "$progname: $file: unparsable: $_\n" unless $key;
-      $key =~ s/^[.*]//s;
-      $res_to_val{$key} = $val;
-      print STDERR "$progname: $file:   $key = $val\n" if ($verbose > 2);
-    }
-
-    while ($body =~ s/^#\s*define\s+(DEF_([A-Z\d_]+))\s+\"([^\"]+)\"//m) {
-      my ($key1, $key2, $val) = ($1, lc($2), $3);
-      $key2 =~ s/_(.)/\U$1/gs;  # "foo_bar" -> "fooBar"
-      $key2 =~ s/Rpm/RPM/;      # kludge
-      $res_to_val{$key2} = $val;
-      print STDERR "$progname: $file:   $key1 ($key2) = $val\n" 
-        if ($verbose > 2);
-    }
-
-  } else {
-    error ("$file: no defaults");
-  }
-
-  $body =~ m/XSCREENSAVER_MODULE(_2)?\s*\(\s*\"([^\"]+)\"/ ||
-    error ("$file: no module name");
-  $res_to_val{progclass} = $2;
-  $res_to_val{doFPS} = 'false';
-  print STDERR "$progname: $file:   progclass = $2\n" if ($verbose > 2);
-
-  print STDERR "$progname: $file: switches to resources:\n"
-    if ($verbose > 2);
-  my %switch_to_res;
-  $switch_to_res{-fps} = 'doFPS: true';
-  $switch_to_res{-fg}  = 'foreground: %';
-  $switch_to_res{-bg}  = 'background: %';
-
-  my ($ign, $opts) = ($body =~ m/(_options|\bopts)\s*\[\]\s*=\s*{(.*?)}\s*;/s);
-  if  ($xlockmore_p || $thread_p || $analogtv_p || $opts) {
-    $opts = '' unless $opts;
-    $opts .= ",\n$xlockmore_default_opts" if ($xlockmore_p);
-    $opts .= ",\n$thread_default_opts" if ($thread_p);
-    $opts .= ",\n$analogtv_default_opts" if ($analogtv_p);
-
-    foreach (split (/,\s*\n/, $opts)) {
-      s/^\s*//s;
-      s/\s*$//s;
-      next if m/^$/s;
-      next if m/^{\s*0\s*,/s;
-      my ($switch, $res, $type, $v0, $v1, $v2) =
-        m@^ \s* { \s * \"([^\"]+)\" \s* ,
-                  \s * \"([^\"]+)\" \s* ,
-                  \s * ([^\s]+)     \s* ,
-                  \s * (\"([^\"]*)\"|([a-zA-Z\d_]+)) \s* }@xi;
-      print STDERR "$progname: $file: unparsable: $_\n" unless $switch;
-      my $val = defined($v1) ? $v1 : $v2;
-      $val = '%' if ($type eq 'XrmoptionSepArg');
-      $res =~ s/^[.*]//s;
-      $res =~ s/^[a-z\d]+\.//si;
-      $switch =~ s/^\+/-no-/s;
-
-      $val = "$res: $val";
-      if (defined ($switch_to_res{$switch})) {
-        print STDERR "$progname: $file:   DUP! $switch = \"$val\"\n" 
-          if ($verbose > 2);
-      } else {
-        $switch_to_res{$switch} = $val;
-        print STDERR "$progname: $file:   $switch = \"$val\"\n" 
-          if ($verbose > 2);
-      }
-    }
-  } else {
-    error ("$file: no options");
-  }
-
-  return (\%res_to_val, \%switch_to_res);
-}
-
-# Returns a list of:
-#    "resource = default value"
-# or "resource != non-default value"
-#
-sub parse_manifest_xml($$) {
-  my @result = ();
-  my ($saver, $switch_to_res) = @_;
-  my $file = "project/xscreensaver/AndroidManifest.xml";
-  my $body = '';
-  local *IN;
-
-  if (-e $file) {
-      open (IN, "<$file") || error ("$file: $!");
-  }
-  else {
-      return @result;
-  }
-
-  while (<IN>) { $body .= $_; }
-  close IN;
-  $file =~ s@^.*/@@;
-
-  $body =~ s/<!--.*?-->/ /gsi;
-
-  $body =~ s/\s+/ /gs;
-  $body =~ s/</\001</gs;
-  $body =~ s/\001(<option)/$1/gs;
-
-  print STDERR "$progname: $file: options:\n" if ($verbose > 2);
-
-  foreach (split (m/\001/, $body)) {
-    next if (m/^\s*$/s);
-    my ($type, $args) = m@^<([?/]?[-_a-z]+)\b\s*(.*)$@si;
-    error ("$progname: $file: unparsable: $_") unless $type;
-    next if ($type =~ m@^/@);
-    if ($type eq 'meta-data') {
-        my ($value) = ($args =~ m/\@xml\/([^\"]+)\"/);
-        push @result, $value;
-    }
-  }
-  return @result;
-}
-
-# Returns a list of:
-#    "resource = default value"
-# or "resource != non-default value"
-#
-sub parse_strings_xml($$) {
-  my @result = ();
-  my ($saver, $switch_to_res) = @_;
-  my $file = "project/xscreensaver/res/values/strings.xml";
-  my $body = '';
-  local *IN;
-
-  if (-e $file) {
-      open (IN, "<$file") || error ("$file: $!");
-  }
-  else {
-      return @result;
-  }
-
-  while (<IN>) { $body .= $_; }
-  close IN;
-  $file =~ s@^.*/@@;
-
-  $body =~ s/<!--.*?-->/ /gsi;
-
-  $body =~ s/\s+/ /gs;
-  $body =~ s/</\001</gs;
-  $body =~ s/\001(<option)/$1/gs;
-
-  print STDERR "$progname: $file: options:\n" if ($verbose > 2);
-
-  my $saver_name = $saver . "_name";
-
-  foreach (split (m/\001/, $body)) {
-    next if (m/^\s*$/s);
-    my ($type, $args) = m@^<([?/]?[-_a-z]+)\b\s*(.*)$@si;
-    error ("$progname: $file: unparsable: $_") unless $type;
-    next if ($type =~ m@^/@);
-
-    if ($type =~ m/^([hv]group|\?xml|resources|xscreensaver-(image|text|updater))/s) {
-
-    } elsif ($type eq 'string') {
-      my ($name) = ($args =~ m/\bname\s*=\s*\"([^\"]+)\"/);
-      my ($value) = ($args =~ m/>([^\"]+)/);
-      my ($val) = "$name = $value";
-      if ($saver_name eq $name) {
-        error ("$saver: $saver already in $file");
-      }
-      push @result, $val;
-    } elsif ($type eq 'item')  {
-      # ignore
-    } else {
-      error ("$file: unknown type \"$type\" for no arg");
-    }
-  }
-
-  return @result;
-}
-
-
-
-# Returns a list of:
-#    "resource = default value"
-# or "resource != non-default value"
-#
-sub parse_xml($$) {
-  my ($saver, $switch_to_res) = @_;
-  my $file = "../hacks/config/" . lc($saver) . ".xml";
-  my $body = '';
-  local *IN;
-  open (IN, "<$file") || error ("$file: $!");
-  while (<IN>) { $body .= $_; }
-  close IN;
-  $file =~ s@^.*/@@;
-
-  my @result = ();
-
-  $body =~ s/<!--.*?-->/ /gsi;
-
-  $body =~ s/\s+/ /gs;
-  $body =~ s/</\001</gs;
-  $body =~ s/\001(<option)/$1/gs;
-
-  my $video = undef;
-
-  print STDERR "$progname: $file: options:\n" if ($verbose > 2);
-  foreach (split (m/\001/, $body)) {
-    next if (m/^\s*$/s);
-    my ($type, $args) = m@^<([?/]?[-_a-z]+)\b\s*(.*)$@si;
-
-    my $type_val;
-    error ("$progname: $file: unparsable: $_") unless $type;
-    next if ($type =~ m@^/@);
-
-    if ($type =~ m/^([hv]group|\?xml|command|string|file|_description|xscreensaver-(image|text|updater))/s) {
-
-    } elsif ($type eq 'screensaver') {
-      my ($name) = ($args =~ m/\b_label\s*=\s*\"([^\"]+)\"/);
-      my $val = "progclass = $name";
-      push @result, $val;
-      print STDERR "$progname: $file:   name:    $name\n" if ($verbose > 2);
-
-    } elsif ($type eq 'video') {
-      error ("$file: multiple videos") if $video;
-      ($video) = ($args =~ m/\bhref="(.*?)"/);
-      error ("$file: unparsable video") unless $video;
-      error ("$file: unparsable video URL")
-        unless ($video =~ m@^https?://www\.youtube\.com/watch\?v=[^?&]+$@s);
-
-    } elsif ($type eq 'number') {
-      my ($arg) = ($args =~ m/\barg\s*=\s*\"([^\"]+)\"/);
-      my ($val) = ($args =~ m/\bdefault\s*=\s*\"([^\"]+)\"/);
-      $val = '' unless defined($val);
-
-      my ($low) = ($args =~ m/\blow\s*=\s*\"([^\"]+)\"/);
-      my ($high) = ($args =~ m/\bhigh\s*=\s*\"([^\"]+)\"/);
-
-      my ($ll) = ($args =~ m/\b_low-label\s*=\s*\"([^\"]+)\"/);
-      my ($hl) = ($args =~ m/\b_high-label\s*=\s*\"([^\"]+)\"/);
-
-      my $switch = $arg;
-      $switch =~ s/\s+.*$//;
-      my ($res) = $switch_to_res->{$switch};
-      error ("$file: no resource for $type switch \"$arg\"") unless $res;
-      $res =~ s/: \%$//;
-      error ("$file: unparsable value: $res") if ($res =~ m/:/);
-
-      $type_val = "$res" . "_type = $type";
-      push @result, $type_val;
-      $val = "$res = $val";
-      push @result, $val;
-      $val = "$res" . "_low = $low";
-      push @result, $val;
-      $val = "$res" . "_high = $high";
-      push @result, $val;
-      $val = "$res" . "_low-label = $ll";
-      push @result, $val;
-      $val = "$res" . "_high-label = $hl";
-      push @result, $val;
-
-      print STDERR "$progname: $file:   number:  $val\n" if ($verbose > 2);
-
-    } elsif ($type eq 'boolean') {
-      my ($set)   = ($args =~ m/\barg-set\s*=\s*\"([^\"]+)\"/);
-      my ($unset) = ($args =~ m/\barg-unset\s*=\s*\"([^\"]+)\"/);
-      my ($arg) = $set || $unset || error ("$file: unparsable: $args");
-      my ($res) = $switch_to_res->{$arg};
-        error ("$file: no resource for boolean switch \"$arg\"") unless $res;
-      my ($res2, $val) = ($res =~ m/^(.*?): (.*)$/s);
-      error ("$file: unparsable boolean resource: $res") unless $res2;
-      $res = $res2;
-      $type_val = "$res" . "_type = $type";
-      push @result, $type_val;
-#      $val = ($set ? "$res != $val" : "$res = $val");
-      $val = "$res != $val";
-      push @result, $val;
-
-      print STDERR "$progname: $file:   boolean: $val\n" if ($verbose > 2);
-
-    } elsif ($type eq 'select') {
-      $args =~ s/</\001</gs;
-      my @opts = split (/\001/, $args);
-      shift @opts;
-      my $unset_p = 0;
-      my $this_res = undef;
-      foreach (@opts) {
-        error ("$file: unparsable: $_") unless (m/^<option\s/);
-        my ($set) = m/\barg-set\s*=\s*\"([^\"]+)\"/;
-        if ($set) {
-          my ($set2, $val) = ($set =~ m/^(.*?) (.*)$/s);
-          $set = $set2 if ($set2);
-          my ($res) = $switch_to_res->{$set};
-          error ("$file: no resource for select switch \"$set\"") unless $res;
-
-          my ($res2, $val2) = ($res =~ m/^(.*?): (.*)$/s);
-          error ("$file: unparsable select resource: $res") unless $res2;
-          $res = $res2;
-          $type_val = "$res" . "_type = $type";
-          push @result, $type_val;
-          $val = $val2 unless ($val2 eq '%');
-
-          error ("$file: mismatched resources: $res vs $this_res")
-            if (defined($this_res) && $this_res ne $res);
-          $this_res = $res;
-
-          $val = "$res != $val";
-          push @result, $val;
-          $val = "$res" . "_type = $type";
-          push @result, $val;
-
-          print STDERR "$progname: $file:   select:  $val\n" if ($verbose > 2);
-
-        } else {
-          error ("$file: multiple default options: $set") if ($unset_p);
-          $unset_p++;
-        }
-      }
-
-    } else {
-      error ("$file: unknown type \"$type\" for no arg");
-    }
-  }
-
-#  error ("$file: no video") unless $video;
-  print STDERR "\n$file: WARNING: no video\n\n" unless $video;
-
-  return @result;
-}
-
-
-sub parse_then_make($) {
-  my ($saver) = @_;
-
-  # kludge
-  return 0 if ($saver =~ m/(-helper)$/);
-
-  my ($src_opts, $switchmap) = parse_src ($saver);
-  my (@xml_opts) = parse_xml ($saver, $switchmap);
-
-  # tests if hack is supported yet
-  my (@test) = get_keys_and_values($saver, @xml_opts);
-  my (@strings_xml_opts) = parse_strings_xml ($saver, $switchmap);
-  my (%pixkeys) =  parse_items_xml($saver);
-  my (@manifest_xml_opts) = parse_manifest_xml ($saver, $switchmap);
-  my (@glue_hacks) = parse_glue($saver);
-  my (@settings_xml_opts) = parse_settings_xml($saver);
-
-  my (@all_settings) = get_settings($saver, $switchmap, \@xml_opts);
-
-  make_settings($saver);
-  make_service($saver);
-  make_wallpaper($saver, @xml_opts);
-
-  make_manifest($saver, @manifest_xml_opts);
-
-  make_hack_xml($saver);
-  make_hack_settings_xml($saver, @xml_opts);
-  make_strings_xml($saver, \@xml_opts, \@strings_xml_opts);
-  make_items_xml($saver, \@xml_opts, \%pixkeys);
-  make_settings_xml($saver, \@all_settings, \@settings_xml_opts);
-
-  make_glue($saver, @glue_hacks);
-
-  return 0;
-}
-
-
-sub make_manifest($$) {
-  my ($saver, @manifest_opts) = @_;
-  push @manifest_opts, $saver unless grep{$_ eq $saver} @manifest_opts;
-  my $hack = ucfirst($saver);
-  my $file = "project/xscreensaver/AndroidManifest.xml";
-  open (my $in, '>', $file) || error ("$file: $!");
-
-  my $body = ("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" .
-              "<manifest " .
-              "xmlns:android=\"http://schemas.android.com/apk/res/android\" " .
-              "package=\"org.jwz.xscreensaver\"\n" .
-              "android:versionCode=\"1\"\n" .
-              "android:versionName=\"1.0\">\n" .
-              "<uses-sdk android:minSdkVersion=\"14\" " .
-              "android:targetSdkVersion=\"19\" />\n" .
-              "<application android:icon=\"\@drawable/thumbnail\" " .
-              "android:label=\"\@string/app_name\" " .
-              "android:name=\".XscreensaverApp\">\n\n");
-
-  foreach my $save (@manifest_opts) {
-      my $hac = ucfirst($save);
-      $body = $body . ("<service android:label=\"\@string/" . $save . 
-              "_name\" android:name=\".gen." . $hac . "Service\" " .
-              "android:permission=\"android.permission.BIND_WALLPAPER\">\n" .
-              " <intent-filter>\n" .
-              "   <action " .
-              "android:name=\"android.service.wallpaper.WallpaperService\" " .
-              "/>\n" .
-              " </intent-filter>\n" .
-              " <meta-data android:name=\"android.service.wallpaper\" " .
-              "android:resource=\"\@xml/" . $save . "\" />\n" .
-              "</service>\n" .
-              "<activity " .
-              "android:label=\"\@string/" . $save . "_settings\" " .
-              "android:name=\"org.jwz.xscreensaver.gen." . $hac . 
-              "Settings\" " .
-              "android:theme=\"\@android:style/Theme.Light.WallpaperSettings\" " .
-              "android:exported=\"true\">\n" .
-              "</activity>\n\n");
-
-  }
-
-  $body = $body . ("</application>\n\n" .
-              "<uses-sdk android:minSdkVersion=\"14\" />\n" .
-              "<uses-feature " .
-              "android:name=\"android.software.live_wallpaper\" " .
-              "android:required=\"true\" />\n" .
-              "</manifest>\n");
-
-  print $in $body;
-  close $in;
-}
-
-
-sub make_hack_settings_xml($$) {
-
-  my ($saver, @xml_opts) = @_;
-  my $hack = ucfirst($saver);
-  my $file = "project/xscreensaver/res/xml/" . $saver . "_settings.xml";
-  my (%saver_keys) = get_keys_and_values($saver, @xml_opts);
-
-  open (my $in, '>', $file) || error ("$file: $!");
-
-  my $body = ("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" .
-              "<PreferenceScreen xmlns:android=" .
-              "\"http://schemas.android.com/apk/res/android\">\n" .
-              "    <PreferenceCategory\n" .
-              "        android:title=\"\@string/" . $saver .
-              "_settings\"\n" .
-              "        android:key=\"" . $saver .
-              "wallpaper_settings\">\n");
-
-  my @keyarray = keys %saver_keys;
-
-
-  foreach my $sgkey (@keyarray) {
-
-    my $type = get_type($sgkey, @xml_opts);
-
-
-    if ($type eq "number") {
-        $body = $body . "    <org.jwz.xscreensaver.SliderPreference\n" .
-              "        android:defaultValue=\"\@string/" . $saver .
-              "_" . $sgkey .
-              "_float\"\n" .
-              "        android:dialogMessage=\"\@string/" . $saver .
-              "_" . $sgkey .
-              "_settings_summary\"\n" .
-              "        android:key=\"" . $saver . "_" . $sgkey .
-              "\"\n" .
-              "        android:summary=\"\@array/" . $saver . "_" . $sgkey .
-              "_prefix\"\n" .
-              "        android:title=\"\@string/" . $saver . "_" . $sgkey .
-              "_settings_title\" />\n";
-     } else {
-         $body = $body .  "    <ListPreference\n" .
-              "            android:key=\"" . $saver . "_" . $sgkey .
-              "\"\n" .
-              "            android:title=\"\@string/" . $saver . "_" . $sgkey .
-              "_settings_title\"\n" .
-              "            android:summary=\"\@string/$saver" . "_" . $sgkey .
-              "_settings_summary\"\n" .
-              "            android:entries=\"\@array/$saver" . "_$sgkey" .
-              "_names\"\n" .
-              "            android:defaultValue=\"\@string/" . $saver . 
-              "_" . $sgkey . "_default" . "\"\n" .
-              "            android:entryValues=\"\@array/$saver" .
-              "_$sgkey" .
-              "_prefix\" />\n";
-     }
-  }
-
-  $body = $body .   "    </PreferenceCategory>\n" .
-              "</PreferenceScreen>\n";
-
-  print $in $body;
-  close $in;
-}
-
-
-sub make_items_xml($\@\%) {
-  my $saver = $_[0];
-  my @xml_opts = @{$_[1]};
-  my %pixkeys = %{$_[2]};
-
-  my $file = "project/xscreensaver/res/values/items.xml";
-
-  my $body = ("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" .
-              "<resources>\n");
-
-  while(my($key, $value) = each %pixkeys) {
-      $body = $body . "    <item name=\"" . $key .
-             "\" format=\"float\" type=\"string\">". $value . "</item>\n";
-
-  }
-
-  my (%saver_keys) = get_keys_and_values($saver, @xml_opts);
-  my @keyarray = keys %saver_keys;
-
-  foreach my $item_key (@keyarray) {
-
-    my $type = get_type($item_key, @xml_opts);
-
-    if ($type eq "number") {
-
-      my ($low, $high, $default) = get_low_high_def($item_key, @xml_opts);
-      my $float = ($default - $low) / ($high - $low);
-
-      $body = ($body .
-              "    <item name=\"" . $saver . "_" . $item_key .
-              "_float\" format=\"float\" type=\"string\">$float</item>\n");
-    }
-  }
-
-  $body =    ($body .
-              "</resources>\n");
-  open (my $in, '>', $file) || error ("$file: $!");
-  print $in $body;
-  close $in;
-}
-
-
-sub get_type($@) {
-
-    my($type_key, @xml_opts) = @_;
-    my $type='';
-
-    foreach my $claim (@xml_opts) {
-
-        my ($res, $compare, $xval) = ($claim =~ m/^(.*) (=|!=) (.*)$/s);
-        if ($res eq $type_key . "_type") {
-            $type = $xval;
-        }
-
-    }
-    return $type;
-
-}
-
-
-sub get_low_high_def($@) {
-
-    my($sgkey, @xml_opts) = @_;
-
-    my $low;
-    my $high;
-    my $default;
-
-    foreach my $claim (@xml_opts) {
-        my ($res, $compare, $xval) = ($claim =~ m/^(.*) (=|!=) (.*)$/s);
-        if ($res eq $sgkey . "_low") {
-            $low = $xval;
-        }
-        elsif ($res eq $sgkey . "_high") {
-            $high = $xval;
-        }
-        elsif ($res eq $sgkey) {
-            $default = $xval;
-        }
-    }
-
-    return ($low, $high, $default);
-
-}
-
-
-sub make_settings_xml($\@\@) {
-
-  my $saver = $_[0];
-  my @xml_opts = @{$_[1]};
-  my @old_settings_xml = @{$_[2]};
-  my $file = "project/xscreensaver/res/values/settings.xml";
-
-  my $body = ("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" .
-              "<resources " .
-              "xmlns:xliff=\"urn:oasis:names:tc:xliff:document:1.2\">\n");
-
-  my $arrays_from_old_settings = old_settings_string_arrays(@old_settings_xml);
-
-  $body = $body . $arrays_from_old_settings;
-
-  my (%saver_keys) = get_keys_and_values($saver, @xml_opts);
-  my @key_array = keys %saver_keys;
-
-  my ($low, $high, $low_label, $high_label, $type);
-  my @selects;
-
-  # for each setting of the hack which we chose to add
-  foreach my $selected_setting_key (@key_array) {
-      # see what values were in the relevant xml in hacks/config for this hack
-      foreach my $claim (@xml_opts) {
-           my ($xres, $xcompare, $xval) = ($claim =~ m/^(.*) (=|!=) (.*)$/s);
-           if ($xres =~ /^$selected_setting_key/) {
-               my $one, my $two;
-               if ($xres =~ /_/ ) {
-                   ($one, $two) = ($xres =~ m/^(.*)_(.*)$/s);
-                    if ($two eq "type") {
-                        $type = $xval;
-                    } elsif ($two eq "low-label") {
-                        $low_label = $xval;
-                    } elsif ($two eq "high-label") {
-                        $high_label = $xval;
-                    } elsif ($two eq "low") {
-                        $low = $xval;
-                    } elsif ($two eq "high") {
-                        $high = $xval;
-                    }
-               } else {
-                   $one = $xres;
-                    if ($type eq "select") {
-                        push @selects, $xval;
-                    }
-               }
-            }
-       }
-
-       # add setting values based on the setting type (boolean, number, select)
-       if ($type eq "boolean") {
-           $body = $body . "    <string-array name=\"" . $saver .
-           "_" . $selected_setting_key . "_names" . "\">\n" .
-           "        <item>\"True\"</item>\n" .
-           "        <item>\"False\"</item>\n" .
-           "    </string-array>\n" .
-           "    <string-array name=\"" . $saver . "_" . $selected_setting_key .
-           "_prefix" . "\">\n" .
-           "        <item>\@string/t</item>\n" .
-           "        <item>\@string/f</item>\n" .
-           "    </string-array>\n";
-       } elsif ($type eq "number") {
-           $body = $body . "    <string-array name=\"" . $saver .
-           "_" . $selected_setting_key . "_names" . "\">\n" .
-           "        <item>\"" . $low_label . "\"</item>\n" .
-           "        <item>\"" . $high_label . "\"</item>\n" .
-           "    </string-array>\n" .
-           "    <string-array name=\"" . $saver . "_" . $selected_setting_key .
-           "_prefix" . "\">\n" .
-           "        <item>\"" . $low . "\"</item>\n" .
-           "        <item>\"" . $high . "\"</item>\n" .
-           "    </string-array>\n";
-       } elsif ($type eq "select") {
-           $body = $body . "    <string-array name=\"" . $saver .
-           "_" . $selected_setting_key . "_names" . "\">\n";
-
-           foreach my $item (@selects) {
-               $body = $body . "        <item>\"" . $item . "\"</item>\n" ;
-           }
-
-           $body = $body . "    </string-array>\n" .
-           "    <string-array name=\"" . $saver .
-           "_" . $selected_setting_key . "_prefix" . "\">\n";
-
-           foreach my $item (@selects) {
-               $body = $body . "        <item>\"" . $item . "\"</item>\n" ;
-           }
-
-           $body = $body . "    </string-array>\n";
-       }
-
-       @selects=();
-  }
-
-  $body =    ($body .
-              "</resources>\n");
-
-  open (my $in, '>', $file) || error ("$file: $!");
-  print $in $body;
-  close $in;
-
-}
-
-
-sub old_settings_string_arrays(@) {
-
-  my (@old_settings_file) = @_;
-
-  my $body = '';
-  my $current_string_array='';
-
-
-  foreach my $claim (@old_settings_file) {
-    my ($res, $compare, $xval) = ($claim =~ m/^(.*) (=) (.*)$/s);
-    error ("unparsable xml claim: $_") unless $compare;
-
-    if ($current_string_array ne $res) {
-        if (length($current_string_array) > 0) {
-           $body = $body . "    </string-array>\n";
-        }
-
-        $current_string_array = $res;
-        $body = $body .  "    <string-array name=\"" . $current_string_array .
-                         "\">\n";
-    }
-
-    $body = $body . "        <item>" . $xval . "</item>\n";
-  }
-
-  if ($#old_settings_file > -1) {
-      $body = $body . "    </string-array>\n";
-  }
-
-
-  return $body;
-
-}
-
-
-# TODO: This adds the proper parameters to settings such as hilbert's, but it
-# does not remove the improper parameters from hacks such as Hilbert yet.
-#
-sub get_settings($$\@) {
-  my $saver = $_[0];
-  my $switchmap = $_[1];
-  my @xml_opts = @{$_[2]};
-
-  my @keys = keys % { $switchmap};
-
-  my $res_seen = 0;
-  my $val_seen = 0;
-  my @also;
-  foreach my $sgkey (@keys) {
-      my ($k, $v) = ($switchmap->{$sgkey} =~ m/^(.*): (.*)$/);
-
-      if ($v ne '%') {
-          foreach my $claim (@xml_opts) {
-               my ($res, $compare, $val) = ($claim =~ m/^(.*) (=|!=) (.*)$/s);
-               if ($res eq $k && $val eq $v) {
-                   $val_seen = $val_seen + 1;
-               }
-               elsif ($res eq $k) {
-                   $res_seen = $res_seen + 1;
-               }
-          }
-
-          if ($val_seen eq 0 && $res_seen > 0) {
-              my $so = "$k != $v";
-              push @also, $so;
-          }
-
-          $val_seen = 0;
-          $res_seen = 0;
-      }
-  }
-
-  my @all = (@xml_opts, @also);
-  return @all;
-
-}
-
-
-sub make_strings_xml($\@\@) {
-
-  my $saver = $_[0];
-  my @xml_opts = @{$_[1]};
-  my @strings_xml_opts = @{$_[2]};
-
-  my $saver_name = $saver . "_name";
-  my $hack = ucfirst($saver);
-  my $file = "project/xscreensaver/res/values/strings.xml";
-  my (%saver_keys) = get_keys_and_values($saver, @xml_opts);
-
-  my $body = ("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" .
-              "<resources>\n" .
-              "    <string name=\"hello\">Hello World!</string>\n" .
-              "    <string name=\"service_label\">Xscreensaver</string>\n" .
-              "    <string name=\"description\">A live wallpaper</string>\n\n" .
-              "    <string name=\"app_name\">Xscreensaver</string>\n" .
-              "    <string name=\"author\">jwz and helpers</string>\n" .
-              "    <string name=\"t\">True</string>\n" .
-              "    <string name=\"f\">False</string>\n");
-
-  foreach my $claim (@strings_xml_opts) {
-    my ($res, $compare, $xval) = ($claim =~ m/^(.*) (=|!=) (.*)$/s);
-    error ("$saver: unparsable xml claim: $_") unless $compare;
-    if ($res eq 'hello' ||
-        $res eq 'service_label' ||
-        $res eq 'description' ||
-        $res eq 'app_name' ||
-        $res eq 'author' ||
-        $res eq 't' ||
-        $res eq 'f') {
-    }
-    elsif ($res eq $saver_name) {
-        error ("$saver: $saver already in $file");
-    }
-    else {
-        $body = ($body .
-                 "    <string name=\"" . $res . "\">" . $xval . "</string>\n");
-    }
-  }
-
-  $body =    ($body .
-              "    <string name=\"" . $saver . "_name\">" . $hack .  
-              "</string>\n" .
-              "    <string name=\"" . $saver . 
-              "_settings\">Settings</string>\n" .
-              "    <string name=\"" . $saver . "_description\">" . $hack .  
-
-              "</string>\n");
-
-  my @keyarray = keys %saver_keys;
-
-  foreach my $sgkey (@keyarray) {
-
-    my $type = get_type($sgkey, @xml_opts);
-
-    if ($type eq "number") {
-
-         my ($low, $high, $default) = get_low_high_def($sgkey, @xml_opts);
-          my $float = ($default - $low) / ($high - $low);
-
-          $body = ($body . "    <string name=\"" . $saver . "_" . $sgkey .
-              "_settings_title\">" . "Set " . $sgkey . "</string>\n" .
-              "    <string name=\"" . $saver . "_" . $sgkey .
-              "_settings_summary\">" . "Choose " . $sgkey . "</string>\n" .
-              "    <string name=\"" . $saver . "_" . $sgkey .
-              "_low\">" . $low . "</string>\n" .
-              "    <string name=\"" . $saver . "_" . $sgkey .
-              "_high\">" . $high . "</string>\n" .
-              "    <string name=\"" . $saver . "_" . $sgkey .
-              "_default\">" . $saver_keys{$sgkey} . "</string>\n");
-    }
-      else {
-
-              $body = ($body . "    <string name=\"" . $saver . "_" . $sgkey .
-              "_settings_title\">" . "Set " . $sgkey . "</string>\n" .
-              "    <string name=\"" . $saver . "_" . $sgkey .  
-
-              "_settings_summary\">" . "Choose " . $sgkey . "</string>\n" .
-              "    <string name=\"" . $saver . "_" . $sgkey .  
-              "_default\">" . $saver_keys{$sgkey} . "</string>\n");
-      }
-  }
-
-  $body =    ($body .
-              "</resources>\n");
-
-  open (my $in, '>', $file) || error ("$file: $!");
-  print $in $body;
-  close $in;
-}
-
-
-sub make_hack_xml($) {
-  my ($saver) = @_;
-  my $hack = ucfirst($saver);
-
-  my $dir = "project/xscreensaver/res/xml/";
-  my $file = $dir . $saver . ".xml";
-  my $in;
-
-  if (-d $dir) {
-      open ($in, '>', $file) || error ("$file: $!");
-  }
-  else {
-      mkdir $dir;
-      open ($in, '>', $file) || error ("$file: $!");
-  }
-
-  my $body = ("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" .
-              "<wallpaper xmlns:android=" .
-              "\"http://schemas.android.com/apk/res/android\"\n" .
-              "   android:description=\"\@string/" . $saver .
-              "_description\"\n" .
-              "   android:settingsActivity=\"org.jwz.xscreensaver.gen.$hack" .
-              "Settings\"\n" .
-              "   android:thumbnail=\"\@drawable/" . $saver .
-              "\" />\n");
-
-  print $in $body;
-  close $in;
-}
-
-
-sub make_glue($$) {
-  my ($saver, @glue_hacks) = @_;
-  my (@hacks) = @glue_hacks;
-
-  push @hacks, $saver;
-
-  my $dir = "gen/";
-  my $file = $dir . "glue.c";
-  my $in;
-
-  if (-d $dir) {
-      open ($in, '>', $file) || error ("$file: $!");
-  }
-  else {
-      mkdir $dir;
-      open ($in, '>', $file) || error ("$file: $!");
-  }
-
-
-  my $body = ("#include <jni.h>\n" .
-              "#include <math.h>\n" .
-              "#include <stdlib.h>\n" .
-              "#include <stdio.h>\n" .
-              "#include <time.h>\n" .
-              "#include <pthread.h>\n" .
-              "#include <GLES/gl.h>\n\n" .
-              "#include \"screenhackI.h\"\n" .
-              "#include \"jwzglesI.h\"\n" .
-              "#include \"version.h\"\n\n" .
-              "void drawXscreensaver();\n\n" .
-              "int sWindowWidth = 0;\n" .
-              "int sWindowHeight = 0;\n" .
-              "int initTried = 0;\n" .
-              "int renderTried = 0;\n" .
-              "int resetTried = 0;\n" .
-              "int currentFlip = 0;\n\n" .
-              "pthread_mutex_t mutg = PTHREAD_MUTEX_INITIALIZER;\n\n" .
-              "extern struct xscreensaver_function_table " .
-              "*xscreensaver_function_table;\n\n" .
-              "// if adding a table here, increase the magic number\n" .
-              "struct xscreensaver_function_table\n");
-
-              for my $i (0 .. $#hacks) {
-                $body = $body . "    *" . $hacks[$i] ;
-                $body = $body . "_xscreensaver_function_table";
-                if ($i eq $#hacks  ) {
-                  $body = $body . ";\n\n";
-                }
-                else {
-                  $body = $body . ",\n";
-                }
-              }
-
-  $body = $body . "struct running_hack {\n" .
-              "    struct xscreensaver_function_table *xsft;\n" .
-              "    Display *dpy;\n" .
-              "    Window window;\n" .
-              "    void *closure;\n" .
-              "};\n\n" .
-              "const char *progname;\n" .
-              "const char *progclass;\n\n" .
-              "struct running_hack rh[";
-  $body = $body . scalar(@hacks);
-  $body = $body . "];\n" .
-              "// ^ magic number of hacks - TODO: remove magic number\n\n\n" .
-              "int chosen;\n" .
-              "JNIEXPORT void JNICALL\n" .
-              "    Java_org_jwz_xscreensaver_CallNative_nativeInit\n" .
-              "    (JNIEnv * env);\n" .
-              "JNIEXPORT void JNICALL\n" .
-              "    Java_org_jwz_xscreensaver_CallNative_nativeResize\n" .
-              "    (JNIEnv * env, jobject thiz, jint w, jint h);\n" .
-              "JNIEXPORT void JNICALL\n" .
-              "    Java_org_jwz_xscreensaver_CallNative_nativeRender\n" .
-              "    (JNIEnv * env);\n" .
-              "JNIEXPORT void JNICALL\n" .
-              "    Java_org_jwz_xscreensaver_CallNative_nativeDone\n" .
-              "    (JNIEnv * env);\n";
-
-  foreach my $bighack (@hacks) {
-      my $bh = ucfirst($bighack);
-      $body = $body . "JNIEXPORT void JNICALL\n" .
-              "    Java_org_jwz_xscreensaver_gen_" . $bh . 
-              "Wallpaper_allnativeSettings\n" .
-              "    (JNIEnv * env, jobject thiz, jstring jhack," .
-              " jstring hackPref,\n" .
-              "     jint draw, jstring key);\n";
-
-  }
-
-  $body = $body . "\n\n\nvoid doinit()\n{\n\n" ;
-
-  for my $j (0 .. $#hacks) {
-    if ($j == 0) {
-      $body = $body . "    if (chosen == " . $j . ") {\n" ;
-    } elsif ($j == $#hacks) {
-      $body = $body .         "    } else {\n" ;
-    } else {
-      $body = $body . "    } else if (chosen == " . $j . ") {\n";
-    }
-      $body = $body .  "       progname = \"" . $hacks[$j] . "\";\n" .
-              "        rh[chosen].xsft = &" . $hacks[$j] . 
-              "_xscreensaver_function_table;\n" ;
-    }
-
-  $body = $body . "    }\n\n" ;
-  $body = $body . "    rh[chosen].dpy = jwxyz_make_display(0, 0);\n" .
-              "    rh[chosen].window = XRootWindow(rh[chosen].dpy, 0);\n" .
-              "// TODO: Zero looks right, " .
-              "but double-check that is the right number\n\n" .
-              "    progclass = rh[chosen].xsft->progclass;\n\n" .
-              "    if (rh[chosen].xsft->setup_cb)\n" .
-              "        rh[chosen].xsft->setup_cb(rh[chosen].xsft,\n" .
-              "                                  rh[chosen].xsft->setup_arg);\n\n" .
-              "    if (resetTried < 1) {\n" .
-              "        resetTried++;\n" .
-              "        jwzgles_reset();\n" .
-              "    }\n\n" .
-              "    void *(*init_cb) (Display *, Window, void *) =\n" .
-              "        (void *(*)(Display *, Window, void *)) " .
-              "rh[chosen].xsft->init_cb;\n\n" .
-              "    rh[chosen].closure =\n" .
-              "        init_cb(rh[chosen].dpy, rh[chosen].window,\n" .
-              "                rh[chosen].xsft->setup_arg);\n\n}\n\n\n" .
-              "void drawXscreensaver()\n{\n" .
-              "    pthread_mutex_lock(&mutg);\n" .
-              "    rh[chosen].xsft->draw_cb(rh[chosen].dpy, " .
-              "rh[chosen].window,\n" .
-              "                             rh[chosen].closure);\n" .
-              "    pthread_mutex_unlock(&mutg);\n\n}\n\n\n" .
-              "JNIEXPORT void JNICALL\n" .
-              "    Java_org_jwz_xscreensaver_CallNative_nativeInit\n" .
-              "    (JNIEnv * env) {\n\n" .
-              "    if (initTried < 1) {\n" .
-              "        initTried++;\n" .
-              "    } else {\n" .
-              "        if (!rh[chosen].dpy) {\n" .
-              "            doinit();\n" .
-              "        } else {\n" .
-              "            rh[chosen].xsft->free_cb(rh[chosen].dpy, " .
-              "rh[chosen].window,\n" .
-              "                                     rh[chosen].closure);\n" .
-              "            jwxyz_free_display(rh[chosen].dpy);\n" .
-              "            rh[chosen].dpy = NULL;\n" .
-              "            rh[chosen].window = NULL;\n" .
-              "            if (!rh[chosen].dpy) {\n" .
-              "                doinit();\n" .
-              "            }\n\n        }\n" .
-              "    }\n\n}\n\n\n" .
-              "JNIEXPORT void JNICALL\n" .
-              "    Java_org_jwz_xscreensaver_CallNative_nativeResize\n" .
-              "    (JNIEnv * env, jobject thiz, jint w, jint h) {\n\n" .
-              "    sWindowWidth = w;\n" .
-              "    sWindowHeight = h;\n\n" .
-              "    if (!rh[chosen].dpy) {\n" .
-              "        doinit();\n" .
-              "    }\n\n" .
-              "    jwxyz_window_resized(rh[chosen].dpy, " .
-              "rh[chosen].window, 0, 0, w, h, 0);\n\n" .
-              "    rh[chosen].xsft->reshape_cb(rh[chosen].dpy, " .
-              "rh[chosen].window,\n" .
-              "                                rh[chosen].closure, w, h);\n}\n\n" .
-              "JNIEXPORT void JNICALL\n" .
-              "    Java_org_jwz_xscreensaver_CallNative_nativeRender\n" .
-              "    (JNIEnv * env) {\n" .
-              "    if (renderTried < 1) {\n" .
-              "        renderTried++;\n" .
-              "    } else {\n" .
-              "        drawXscreensaver();\n" .
-              "    }\n}\n\n" .
-              "// TODO: Check Java side is calling this properly\n" .
-              "JNIEXPORT void JNICALL\n" .
-              "    Java_org_jwz_xscreensaver_CallNative_nativeDone\n" .
-              "    (JNIEnv * env) {\n\n" .
-              "    rh[chosen].xsft->free_cb(rh[chosen].dpy, " .
-              "rh[chosen].window,\n" .
-              "                             rh[chosen].closure);\n" .
-              "    jwxyz_free_display(rh[chosen].dpy);\n" .
-              "    rh[chosen].dpy = NULL;\n" .
-              "    rh[chosen].window = NULL;\n\n}\n\n" ;
-
-  for my $j (0 .. $#hacks) {
-    my $jhack =  ucfirst($hacks[$j]);
-
-    $body = $body . "JNIEXPORT void JNICALL\n" .
-              "    Java_org_jwz_xscreensaver_gen_" . $jhack . 
-              "Wallpaper_allnativeSettings\n" .
-              "    (JNIEnv * env, jobject thiz, jstring jhack," .
-              " jstring hackPref,\n" .
-              "     jint draw, jstring key) {\n\n" .
-              "    const char *chack = " .
-              "(*env)->GetStringUTFChars(env, hackPref, NULL);\n" .
-              "    char *hck = (char *) chack;\n" .
-              "    const char *kchack = " .
-              "(*env)->GetStringUTFChars(env, key, NULL);\n" .
-              "    char *khck = (char *) kchack;\n\n" .
-              "    if (draw == 2) {\n" .
-              "        set" . $jhack . "Settings(hck, khck);\n" .
-              "    }\n\n" .
-              "    chosen = " . $j . ";\n}\n\n";
-
-  }
-
-
-  print $in $body;
-  close $in;
-}
-
-sub make_wallpaper($$) {
-  my ($saver, @xml_opts) = @_;
-  my $hack = ucfirst($saver);
-  my $file = "project/xscreensaver/src/org/jwz/xscreensaver/gen/";
-  $file = $file . $hack . "Wallpaper.java";
-  my (%saver_keys) = get_keys_and_values($saver, @xml_opts);
-
-  open (my $in, '>', $file) || error ("$file: $!");
-
-  my $body = ("package org.jwz.xscreensaver.gen;\n" .
-              "import javax.microedition.khronos.egl.EGLConfig;\n" .
-              "import javax.microedition.khronos.opengles.GL10;\n" .
-              "import net.rbgrn.android.glwallpaperservice.*;\n" .
-              "import android.opengl.GLU;\n" .
-              "import android.content.Context;\n" .
-              "import android.content.SharedPreferences;\n" .
-              "import org.jwz.xscreensaver.*;\n" .
-              "public class " . $hack .
-              "Wallpaper extends ARenderer {\n" .
-              "    private static native void allnativeSettings(" .
-              "String hack, String hackPref, int draw, String key);\n" .
-              "    public static final String SHARED_PREFS_NAME=\"" . $saver .
-              "settings\";\n" .
-              "    CallNative cn;\n" .
-              "    public void onSurfaceCreated(" .
-              "GL10 gl, EGLConfig config) {\n" .
-              "        super.onSurfaceCreated(gl, config);\n" .
-              "        cn = new CallNative();\n" .
-              "        NonSurfaceCreated();\n" .
-              "    }\n" .
-              "    public void onDrawFrame(GL10 gl) {\n" .
-              "        super.onDrawFrame(gl);\n" .
-              "        allnativeSettings(\"bogus\", \"bogus\", 1, \"bogus\");\n" .
-              "        NonDrawFrame();\n" .
-              "    }\n" .
-              "    void NonDrawFrame() {\n" .
-              "        cn.nativeRender();\n" .
-              "    }\n" .
-              "    void doSP(SharedPreferences sspp) {\n" .
-
-
-              "        String hack = \"" . $saver . "\";\n");
-
-  my @keyarray = keys %saver_keys;
-  foreach my $sgkey (@keyarray) {          
-
-    my $type = get_type($sgkey, @xml_opts);
-
-    if ($type eq "number") {
-
-              my ($low, $high, $default) = get_low_high_def($sgkey, @xml_opts);
-              my $float = ($default - $low) / ($high - $low);
-
-              $body = $body .
-              "        String " . $sgkey .
-              "_low = sspp.getString(\"" . $saver .
-              "_" . $sgkey . "_low\", \"". $low . "\");\n" .
-              "        String " . $sgkey .
-              "_high = sspp.getString(\"" . $saver .
-              "_" . $sgkey . "_high\", \"" . $high . "\");\n" .
-              "        Float " . $sgkey . "PrefF = sspp.getFloat(\"" . $saver .
-              "_" . $sgkey . "\", " . $float . "f);\n" .
-              "        String " . $sgkey . "Pref = getNumber(" . $sgkey .
-              "_low, " . $sgkey . "_high, " . $sgkey . "PrefF);\n" .
-              "        allnativeSettings(hack, " . $sgkey .
-              "Pref, 2, \"" . $saver .  "_" . $sgkey . "\");\n";
-    }
-      elsif ($type eq "boolean") {
-
-              $body = $body . "        String " . $sgkey .
-              "Pref = sspp.getString(\"" . $saver .  "_" . $sgkey . 
-              "\", \"" . $saver_keys{$sgkey} . "\");\n" .
-              "        allnativeSettings(hack, " . $sgkey .
-              "Pref, 2, \"" . $saver .  "_" . $sgkey . "\");\n";
-
-      }
-      elsif ($type eq "select") {
-
-              $body = $body . "        String " . $sgkey .
-              "Pref = sspp.getString(\"" . $saver .  "_" . $sgkey .
-              "\", \"" . $saver_keys{$sgkey} . "\");\n" .
-              "        allnativeSettings(hack, " . $sgkey .
-              "Pref, 2, \"" . $saver .  "_" . $sgkey . "\");\n";
-
-      }
-      else {
-          print STDERR "$progname: type $type not yet implemented \n";
-      }
-
-  }
-
-  $body = $body . "    }\n" .
-              "    String getNumber(String low, String high, Float pref) {\n" .
-              "        Float lowF = Float.parseFloat(low);\n" .
-              "        Float lowH = Float.parseFloat(high);\n" .
-              "        Float diff = lowH - lowF;\n" .
-              "        Float mult = pref * diff;\n" .
-              "        Float add = mult + lowF;\n" .
-              "        int i;\n" .
-              "        String s;\n" .
-              "        if (diff > 2.0) {\n" .
-              "            i = (Integer) Math.round(add);\n" .
-              "            s = Integer.toString(i);\n}\n" .
-              "        else {\n" .
-              "            s = Float.toString(add);\n}\n" .
-              "        return s;\n" .
-              "    }\n\n" .
-              "    static\n" .
-              "    {\n" .
-              "        System.loadLibrary (\"xscreensaver\");\n" .
-              "    }\n" .
-              "}\n";
-
-  print $in $body;
-  close $in;
-
-}
-
-sub get_keys_and_values($$) {
-
-  my ($saver, @xml_opts) = @_;
-  my (%saver_keys) ;
-
-  foreach my $claim (@xml_opts) {
-    my ($res, $compare, $xval) = ($claim =~ m/^(.*) (=|!=) (.*)$/s);
-    error ("$saver: unparsable xml claim: $_") unless $compare;
-
-    if ($saver eq "sproingies") {
-        if ($res eq "count") {
-            $saver_keys{$res} = $xval;
-        }
-        elsif ($res eq "wireframe") {
-            #$saver_keys{$res} = $xval;
-            $saver_keys{$res} = "False";
-        }
-
-    }
-    elsif ($saver eq "hilbert") {
-        if ($res eq "mode") {
-            $saver_keys{$res} = $xval;
-        }
-    }
-    elsif ($saver eq "stonerview") {
-        if ($res eq "transparent") {
-            #$saver_keys{$res} = $xval;
-            $saver_keys{$res} = "False";
-        }
-    }
-    elsif ($saver eq "superquadrics") {
-        # spinspeed/speed.  float/int
-        if ($res eq "spinspeed") {
-            $saver_keys{$res} = $xval;
-        }
-    }
-    elsif ($saver eq "bouncingcow") {
-        if ($res eq "count") {
-            $saver_keys{$res} = "3";
-        }
-        elsif ($res eq "speed") {
-            $saver_keys{$res} = "0.1";
-        }
-    }
-    elsif ($saver eq "unknownpleasures") {
-        if ($res eq "wireframe") {
-            $saver_keys{$res} = "True";
-        }
-        elsif ($res eq "speed") {
-            $saver_keys{$res} = "3.0";
-        }
-        #elsif ($res eq "count") {
-        #    $saver_keys{$res} = $xval;
-        #}
-        #elsif ($res eq "resolution") {
-        #    $saver_keys{$res} = $xval;
-        #}
-        #elsif ($res eq "ortho") {
-        #    $saver_keys{$res} = $xval;
-        #}
-
-    }
-    elsif ($saver eq "hypertorus") {
-        if ($res =~ /^(displayMode|appearance|colors|projection3d|projection4d|speedwx|speedwy|speedwz|speedxy|speedxz|speedyz)$/) {
-            $saver_keys{$res} = $xval;
-        }
-    }
-    elsif ($saver eq "glhanoi") {
-        if ($res =~ /^(light|fog|trails|poles|speed)$/) {
-            # TODO: check in xval for true/false should be higher up in logic
-            if ($xval =~ /^(true|false)$/) {
-                $saver_keys{$res} = ucfirst($xval);
-            }
-            else {
-                $saver_keys{$res} = $xval;
-            }
-        }
-    }
-    else {
-        error ("$saver: not yet supported for Android");
-    }
-
-  }
-
-  return (%saver_keys);
-}
-
-
-sub make_service($) {
-  my ($saver) = @_;
-  my $hack = ucfirst($saver);
-  my $file = "project/xscreensaver/src/org/jwz/xscreensaver/gen/";
-  $file = $file . $hack . "Service.java";
-  open (my $in, '>', $file) || error ("$file: $!");
-
-  my $body = ("package org.jwz.xscreensaver.gen;\n\n" .
-              "import net.rbgrn.android.glwallpaperservice.*;\n" .
-              "import android.content.SharedPreferences;\n" .
-              "import org.jwz.xscreensaver.*;\n\n" .
-              "// Original code provided by Robert Green\n" .
-              "// http://www.rbgrn.net/content/354-glsurfaceview-adapted-3d-live-wallpapers\n" .
-              "public class " . $hack .
-              "Service extends GLWallpaperService {\n\n" .
-              "    SharedPreferences sp;\n\n" .
-              "    public " . $hack .
-              "Service() {\n" .
-              "        super();\n" .
-              "    }\n\n" .
-              "    \@Override\n" .
-              "    public void onCreate() {\n" .
-              "        sp = ((XscreensaverApp)getApplication())." .
-              "getThePrefs($hack" . "Wallpaper.SHARED_PREFS_NAME);\n" .
-              "    }\n\n" .
-              "    public Engine onCreateEngine() {\n" .
-              "        MyEngine engine = new MyEngine();\n" .
-              "        return engine;\n" .
-              "    }\n\n" .
-              "    class MyEngine extends GLEngine {\n" .
-              "        " . $hack .
-              "Wallpaper renderer;\n" .
-              "        public MyEngine() {\n" .
-              "            super();\n" .
-              "            // handle prefs, other initialization\n" .
-              "            renderer = new " . $hack .
-              "Wallpaper();\n" .
-              "            setEGLConfigChooser(8, 8, 8, 8, 16, 0);\n" .
-              "            setRenderer(renderer);\n" .
-              "            setRenderMode(RENDERMODE_CONTINUOUSLY);\n" .
-              "        }\n\n" .
-              "        public void onDestroy() {\n" .
-              "            super.onDestroy();\n" .
-              "            if (renderer != null) {\n" .
-              "                renderer.release(); " .
-              "// assuming yours has this method - it should!\n" .
-              "            }\n" .
-              "            renderer = null;\n" .
-              "        }\n\n" .
-              "        \@Override\n" .
-              "        public void onVisibilityChanged(boolean visible) {\n" .
-              "            super.onVisibilityChanged(visible);\n" .
-              "            if (visible) {\n" .
-              "                renderer.doSP(sp);\n" .
-              "            }\n" .
-              "        }\n\n" .
-              "    }\n" .
-              "    static\n" .
-              "    {\n" .
-              "        System.loadLibrary (\"xscreensaver\");\n" .
-              "    }\n\n\n" .
-              "}\n");
-
-  print $in $body;
-  close $in;
-
-}
-
-sub make_settings($) {
-  my ($saver) = @_;
-  my $hack = ucfirst($saver);
-  my $dir = "project/xscreensaver/src/org/jwz/xscreensaver/gen/";
-  my $file = $dir . $hack . "Settings.java";
-  my $in;
-
-  if (-d $dir) {
-      open ($in, '>', $file) || error ("$file: $!");
-  }
-  else {
-      mkdir $dir;
-      open ($in, '>', $file) || error ("$file: $!");
-  }
-
-  my $body = ("/*\n" .
-              " * Copyright (C) 2009 Google Inc.\n" .
-              " *\n" .
-              " * Licensed under the Apache License, Version 2.0 " .
-              "(the \"License\"); you may not\n" .
-              " * use this file except in compliance with the License. " .
-              "You may obtain a copy of\n" .
-              " * the License at\n" .
-              " *\n" .
-              " * http://www.apache.org/licenses/LICENSE-2.0\n" .
-              " *\n" .
-              " * Unless required by applicable law or agreed to in writing," .
-              " software\n" .
-              " * distributed under the License is distributed" .
-              " on an \"AS IS\" BASIS, WITHOUT\n" .
-              " * WARRANTIES OR CONDITIONS OF ANY KIND," .
-              " either express or implied. See the\n" .
-              " * License for the specific language governing" .
-              "permissions and limitations under\n" .
-              " * the License.\n" .
-              " */\n\n" .
-              "package org.jwz.xscreensaver.gen;\n\n" .
-              "import org.jwz.xscreensaver.R;\n\n" .
-              "import android.content.SharedPreferences;\n" .
-              "import android.os.Bundle;\n" .
-              "import android.preference.PreferenceActivity;\n\n" .
-              "public class " . $hack .
-              "Settings extends PreferenceActivity\n" .
-              "    implements " .
-              "SharedPreferences.OnSharedPreferenceChangeListener {\n\n" .
-              "    \@Override\n" .
-              "    protected void onCreate(Bundle icicle) {\n" .
-              "        super.onCreate(icicle);\n" .
-              "        getPreferenceManager().setSharedPreferencesName(\n" .
-              "            " . $hack .
-              "Wallpaper.SHARED_PREFS_NAME);\n" .
-              "        addPreferencesFromResource(R.xml." . $saver .
-              "_settings);\n" .
-              "        getPreferenceManager().getSharedPreferences()." .
-              "registerOnSharedPreferenceChangeListener(\n" .
-              "            this);\n" .
-              "    }\n\n" .
-              "    \@Override\n" .
-              "    protected void onResume() {\n" .
-              "        super.onResume();\n" .
-              "    }\n\n" .
-              "    \@Override\n" .
-              "    protected void onDestroy() {\n" .
-              "        getPreferenceManager().getSharedPreferences()." .
-              "unregisterOnSharedPreferenceChangeListener(\n" .
-              "            this);\n" .
-              "        super.onDestroy();\n" .
-              "    }\n\n" .
-              "    public void onSharedPreferenceChanged(" .
-              "SharedPreferences sharedPreferences,\n" .
-              "                                          String key) {\n" .
-              "    }\n" .
-              "}\n");
-
-  print $in $body;
-  close $in;
-}
-
-
-sub error($) {
-  my ($err) = @_;
-  print STDERR "$progname: $err\n";
-  exit 1;
-}
-
-sub usage() {
-  print STDERR "usage: $progname [--verbose] files ...\n";
-  exit 1;
-}
-
-sub main() {
-  my @files = ();
-  while ($#ARGV >= 0) {
-    $_ = shift @ARGV;
-    if (m/^--?verbose$/) { $verbose++; }
-    elsif (m/^-v+$/) { $verbose += length($_)-1; }
-    elsif (m/^-./) { usage; }
-    else { push @files, $_; }
-#    else { usage; }
-  }
-
-  usage unless ($#files >= 0);
-  my $failures = 0;
-  foreach (@files) { $failures += parse_then_make($_); }
-  exit ($failures);
-}
-
-main();
diff --git a/android/glue.c b/android/glue.c
deleted file mode 100644 (file)
index d794c35..0000000
+++ /dev/null
@@ -1,306 +0,0 @@
-#include <jni.h>
-#include <math.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-#include <pthread.h>
-#include <GLES/gl.h>
-
-#include "screenhackI.h"
-#include "jwzglesI.h"
-#include "version.h"
-
-void drawXscreensaver();
-
-int sWindowWidth = 0;
-int sWindowHeight = 0;
-int initTried = 0;
-int renderTried = 0;
-int resetTried = 0;
-int currentFlip = 0;
-
-pthread_mutex_t mutg = PTHREAD_MUTEX_INITIALIZER;
-
-extern struct xscreensaver_function_table *xscreensaver_function_table;
-
-// if adding a table here, increase the magic number
-struct xscreensaver_function_table
-*hypertorus_xscreensaver_function_table,
-    *hilbert_xscreensaver_function_table,
-    *endgame_xscreensaver_function_table,
-    *stonerview_xscreensaver_function_table,
-    *sproingies_xscreensaver_function_table,
-    *blinkbox_xscreensaver_function_table,
-    *bouncingcow_xscreensaver_function_table,
-    *superquadrics_xscreensaver_function_table;
-
-struct running_hack {
-    struct xscreensaver_function_table *xsft;
-    Display *dpy;
-    Window window;
-    void *closure;
-};
-
-const char *progname;
-const char *progclass;
-
-struct running_hack rh[8];
-// ^ magic number of hacks - TODO: remove magic number
-
-
-int chosen;
-// 0 superquadrics
-// 1 stonerview
-// 2 sproingies
-// 3 hilbert
-
-JNIEXPORT void JNICALL
-    Java_org_jwz_xscreensaver_CallNative_nativeInit
-    (JNIEnv * env);
-JNIEXPORT void JNICALL
-    Java_org_jwz_xscreensaver_CallNative_nativeResize
-    (JNIEnv * env, jobject thiz, jint w, jint h);
-JNIEXPORT void JNICALL
-    Java_org_jwz_xscreensaver_CallNative_nativeRender
-    (JNIEnv * env);
-JNIEXPORT void JNICALL
-    Java_org_jwz_xscreensaver_CallNative_nativeDone
-    (JNIEnv * env);
-JNIEXPORT void JNICALL
-    Java_org_jwz_xscreensaver_gen_SproingiesWallpaper_allnativeSettings
-    (JNIEnv * env, jobject thiz, jstring jhack, jstring hackPref,
-     jint draw, jstring key);
-JNIEXPORT void JNICALL
-    Java_org_jwz_xscreensaver_gen_SuperquadricsWallpaper_allnativeSettings
-    (JNIEnv * env, jobject thiz, jstring jhack, jstring hackPref,
-     jint draw, jstring key);
-JNIEXPORT void JNICALL
-    Java_org_jwz_xscreensaver_gen_HilbertWallpaper_allnativeSettings
-    (JNIEnv * env, jobject thiz, jstring jhack, jstring hackPref,
-     jint draw, jstring key);
-JNIEXPORT void JNICALL
-    Java_org_jwz_xscreensaver_gen_StonerviewWallpaper_allnativeSettings
-    (JNIEnv * env, jobject thiz, jstring jhack, jstring hackPref,
-     jint draw, jstring key);
-JNIEXPORT void JNICALL
-    Java_org_jwz_xscreensaver_gen_BouncingcowWallpaper_allnativeSettings
-    (JNIEnv * env, jobject thiz, jstring jhack, jstring hackPref,
-     jint draw, jstring key);
-
-
-
-void doinit()
-{
-
-    if (chosen == 0) {
-       progname = "superquadrics";
-       rh[chosen].xsft = &superquadrics_xscreensaver_function_table;
-    } else if (chosen == 1) {
-       progname = "stonerview";
-       rh[chosen].xsft = &stonerview_xscreensaver_function_table;
-
-    } else if (chosen == 2) {
-       progname = "sproingies";
-       rh[chosen].xsft = &sproingies_xscreensaver_function_table;
-
-    } else if (chosen == 3) {
-       progname = "hilbert";
-       rh[chosen].xsft = &hilbert_xscreensaver_function_table;
-    } else if (chosen == 4) {
-       progname = "bouncingcow";
-       rh[chosen].xsft = &bouncingcow_xscreensaver_function_table;
-    } else {
-       progname = "sproingies";
-       rh[chosen].xsft = &sproingies_xscreensaver_function_table;
-    }
-
-    rh[chosen].dpy = jwxyz_make_display(0, 0);
-    rh[chosen].window = XRootWindow(rh[chosen].dpy, 0);
-// TODO: Zero looks right, but double-check that is the right number
-
-    progclass = rh[chosen].xsft->progclass;
-
-    if (rh[chosen].xsft->setup_cb)
-       rh[chosen].xsft->setup_cb(rh[chosen].xsft,
-                                 rh[chosen].xsft->setup_arg);
-
-    if (resetTried < 1) {
-       resetTried++;
-        jwzgles_reset();
-    }
-
-    void *(*init_cb) (Display *, Window, void *) =
-       (void *(*)(Display *, Window, void *)) rh[chosen].xsft->init_cb;
-
-    rh[chosen].closure =
-       init_cb(rh[chosen].dpy, rh[chosen].window,
-               rh[chosen].xsft->setup_arg);
-
-}
-
-
-
-void drawXscreensaver()
-{
-    pthread_mutex_lock(&mutg);
-    rh[chosen].xsft->draw_cb(rh[chosen].dpy, rh[chosen].window,
-                            rh[chosen].closure);
-    pthread_mutex_unlock(&mutg);
-
-}
-
-
-JNIEXPORT void JNICALL
-    Java_org_jwz_xscreensaver_CallNative_nativeInit
-    (JNIEnv * env) {
-
-    if (initTried < 1) {
-       initTried++;
-    } else {
-       if (!rh[chosen].dpy) {
-           doinit();
-       } else {
-           rh[chosen].xsft->free_cb(rh[chosen].dpy, rh[chosen].window,
-                                    rh[chosen].closure);
-           jwxyz_free_display(rh[chosen].dpy);
-           rh[chosen].dpy = NULL;
-           rh[chosen].window = NULL;
-           if (!rh[chosen].dpy) {
-               doinit();
-           }
-
-       }
-    }
-
-}
-
-
-JNIEXPORT void JNICALL
-    Java_org_jwz_xscreensaver_CallNative_nativeResize
-    (JNIEnv * env, jobject thiz, jint w, jint h) {
-
-    sWindowWidth = w;
-    sWindowHeight = h;
-
-    if (!rh[chosen].dpy) {
-       doinit();
-    }
-
-    jwxyz_window_resized(rh[chosen].dpy, rh[chosen].window, 0, 0, w, h, 0);
-
-    rh[chosen].xsft->reshape_cb(rh[chosen].dpy, rh[chosen].window,
-                               rh[chosen].closure, w, h);
-}
-
-JNIEXPORT void JNICALL
-    Java_org_jwz_xscreensaver_CallNative_nativeRender
-    (JNIEnv * env) {
-    if (renderTried < 1) {
-       renderTried++;
-    } else {
-       drawXscreensaver();
-    }
-}
-
-// TODO: Check Java side is calling this properly
-JNIEXPORT void JNICALL
-    Java_org_jwz_xscreensaver_CallNative_nativeDone
-    (JNIEnv * env) {
-
-    rh[chosen].xsft->free_cb(rh[chosen].dpy, rh[chosen].window,
-                            rh[chosen].closure);
-    jwxyz_free_display(rh[chosen].dpy);
-    rh[chosen].dpy = NULL;
-    rh[chosen].window = NULL;
-
-}
-
-JNIEXPORT void JNICALL
-    Java_org_jwz_xscreensaver_gen_HilbertWallpaper_allnativeSettings
-    (JNIEnv * env, jobject thiz, jstring jhack, jstring hackPref,
-     jint draw, jstring key) {
-
-
-    const char *chack = (*env)->GetStringUTFChars(env, hackPref, NULL);
-    char *hck = (char *) chack;
-    const char *kchack = (*env)->GetStringUTFChars(env, key, NULL);
-    char *khck = (char *) kchack;
-
-    if (draw == 2) {
-        setHilbertSettings(hck, khck);
-    }
-
-    chosen = 3;
-}
-
-JNIEXPORT void JNICALL
-    Java_org_jwz_xscreensaver_gen_SuperquadricsWallpaper_allnativeSettings
-    (JNIEnv * env, jobject thiz, jstring jhack, jstring hackPref,
-     jint draw, jstring key) {
-
-    const char *chack = (*env)->GetStringUTFChars(env, hackPref, NULL);
-    char *hck = (char *) chack;
-
-    const char *kchack = (*env)->GetStringUTFChars(env, key, NULL);
-    char *khck = (char *) kchack;
-
-    if (draw == 2) {
-        setSuperquadricsSettings(hck, khck);
-    }
-
-    chosen = 0;
-}
-
-
-JNIEXPORT void JNICALL
-    Java_org_jwz_xscreensaver_gen_SproingiesWallpaper_allnativeSettings
-    (JNIEnv * env, jobject thiz, jstring jhack, jstring hackPref,
-     jint draw, jstring key) {
-
-    const char *chack = (*env)->GetStringUTFChars(env, hackPref, NULL);
-    char *hck = (char *) chack;
-
-    const char *kchack = (*env)->GetStringUTFChars(env, key, NULL);
-    char *khck = (char *) kchack;
-
-    if (draw == 2) {
-        setSproingiesSettings(hck, khck);
-    }
-
-    chosen = 2;
-}
-
-JNIEXPORT void JNICALL
-    Java_org_jwz_xscreensaver_gen_StonerviewWallpaper_allnativeSettings
-    (JNIEnv * env, jobject thiz, jstring jhack, jstring hackPref,
-     jint draw, jstring key) {
-
-    const char *chack = (*env)->GetStringUTFChars(env, hackPref, NULL);
-    char *hck = (char *) chack;
-    const char *kchack = (*env)->GetStringUTFChars(env, key, NULL);
-    char *khck = (char *) kchack;
-
-    if (draw == 2) {
-        setStonerviewSettings(hck, khck);
-    }
-
-    chosen = 1;
-}
-
-JNIEXPORT void JNICALL
-    Java_org_jwz_xscreensaver_gen_BouncingcowWallpaper_allnativeSettings
-    (JNIEnv * env, jobject thiz, jstring jhack, jstring hackPref,
-     jint draw, jstring key) {
-
-    const char *chack = (*env)->GetStringUTFChars(env, hackPref, NULL);
-    char *hck = (char *) chack;
-    const char *kchack = (*env)->GetStringUTFChars(env, key, NULL);
-    char *khck = (char *) kchack;
-
-    if (draw == 2) {
-        setBouncingcowSettings(hck, khck);
-    }
-
-    chosen = 4;
-}
-
diff --git a/android/grabscreen-android.c b/android/grabscreen-android.c
new file mode 100644 (file)
index 0000000..3871075
--- /dev/null
@@ -0,0 +1,24 @@
+#include <stdlib.h>
+#include <stdint.h>
+//
+//#import "SaverRunner.h"
+//
+#include "jwxyz.h"
+#include "grabscreen.h"
+#include "colorbars.h"
+#include "resources.h"
+#include "usleep.h"
+
+Bool
+osx_grab_desktop_image (Screen *screen, Window xwindow, Drawable drawable,
+                        XRectangle *geom_ret)
+{
+abort();
+}
+
+Bool
+osx_load_image_file (Screen *screen, Window xwindow, Drawable drawable,
+                     const char *filename, XRectangle *geom_ret)
+{
+abort();
+}
diff --git a/android/jwxyz-timers.h b/android/jwxyz-timers.h
deleted file mode 100644 (file)
index 472cdf9..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/* xscreensaver, Copyright (c) 2006-2012 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 is an implementation of Xt timers, for libjwxyz.
- */
-
-#ifndef __JWXYZ_TIMERS_H__
-#define __JWXYZ_TIMERS_H__
-
-#include "jwxyz.h"
-
-typedef struct jwxyz_sources_data jwxyz_sources_data;
-
-extern jwxyz_sources_data *jwxyz_sources_init (XtAppContext);
-extern void jwxyz_sources_free (jwxyz_sources_data *);
-extern void jwxyz_sources_run (jwxyz_sources_data *);
-
-extern void jwxyz_XtRemoveInput_all (Display *);
-
-#endif /* __JWXYZ_TIMERS_H__ */
diff --git a/android/jwxyz.c b/android/jwxyz.c
deleted file mode 100644 (file)
index d2ed46c..0000000
+++ /dev/null
@@ -1,467 +0,0 @@
-/* xscreensaver, Copyright (c) 1991-2015 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.
- */
-
-/* JWXYZ Is Not Xlib.
-
-   But it's a bunch of function definitions that bear some resemblance to
-   Xlib and that do things that bear some resemblance to the
-   things that Xlib might have done.
- */
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <wchar.h>
-#include <android/log.h>
-
-#include "jwxyz.h"
-#include "jwxyz-timers.h"
-#include "yarandom.h"
-#include "screenhackI.h"
-
-typedef signed char BOOL;
-#define YES             (BOOL)1
-#define NO              (BOOL)0
-
-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;
-
-struct jwxyz_Drawable {
-    enum { WINDOW, PIXMAP } type;
-    CGRect frame;
-    union {
-       struct {
-           unsigned long background;
-           int last_mouse_x, last_mouse_y;
-       } window;
-       struct {
-           int depth;
-           void *cgc_buffer;   
-       } pixmap;
-    };
-};
-
-struct jwxyz_Display {
-    Window main_window;
-    Screen *screen;
-    int screen_count;
-    struct jwxyz_sources_data *timers_data;
-};
-
-struct jwxyz_Screen {
-    Display *dpy;
-    Visual *visual;
-    unsigned long black, white;
-    int screen_number;
-};
-
-
-Screen *
-XDefaultScreenOfDisplay (Display *dpy)
-{
-  return dpy->screen;
-}
-
-unsigned long
-XBlackPixelOfScreen(Screen *screen)
-{
-  return screen->black;
-}
-
-unsigned long
-XWhitePixelOfScreen(Screen *screen)
-{
-  return screen->white;
-}
-
-
-static void draw_rect(Display *, Drawable, GC,
-                     int x, int y, unsigned int width,
-                     unsigned int height, BOOL foreground_p, BOOL fill_p);
-
-Status
-XParseColor(Display * dpy, Colormap cmap, const char *spec, XColor * ret)
-{
-    unsigned char r = 0, g = 0, b = 0;
-    if (*spec == '#' && strlen(spec) == 7) {
-       static unsigned const char hex[] = {    // yeah yeah, shoot me.
-           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,
-           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, 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, 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
-       };
-       r = (hex[spec[1]] << 4) | hex[spec[2]];
-       g = (hex[spec[3]] << 4) | hex[spec[4]];
-       b = (hex[spec[5]] << 4) | hex[spec[6]];
-    } else if (!strcasecmp(spec, "black")) {
-//  r = g = b = 0;
-    } else if (!strcasecmp(spec, "white")) {
-       r = g = b = 255;
-    } else if (!strcasecmp(spec, "red")) {
-       r = 255;
-    } else if (!strcasecmp(spec, "green")) {
-       g = 255;
-    } else if (!strcasecmp(spec, "blue")) {
-       b = 255;
-    } else if (!strcasecmp(spec, "cyan")) {
-       g = b = 255;
-    } else if (!strcasecmp(spec, "magenta")) {
-       r = b = 255;
-    } else if (!strcasecmp(spec, "yellow")) {
-       r = g = 255;
-    } else {
-       return 0;
-    }
-
-    ret->red = (r << 8) | r;
-    ret->green = (g << 8) | g;
-    ret->blue = (b << 8) | b;
-    ret->flags = DoRed | DoGreen | DoBlue;
-    return 1;
-}
-
-Status XAllocColor(Display * dpy, Colormap cmap, XColor * color)
-{
-    // store 32 bit ARGB in the pixel field.
-    // (The uint32_t is so that 0xFF000000 doesn't become 0xFFFFFFFFFF000000)
-    color->pixel = (uint32_t)
-       ((0xFF << 24) |
-        (((color->red >> 8) & 0xFF) << 16) |
-        (((color->green >> 8) & 0xFF) << 8) |
-        (((color->blue >> 8) & 0xFF)));
-    return 1;
-}
-
-//  needs to be implemented in Android...
-int
-XFillRectangle(Display * dpy, Drawable d, GC gc, int x, int y,
-              unsigned int width, unsigned int height)
-{
-    return 0;
-}
-
-//  needs to be implemented in Android...
-int
-XDrawString(Display * dpy, Drawable d, GC gc, int x, int y,
-           const char *str, int len)
-{
-    return 0;                  // try this for now...
-}
-
-
-//  needs to be implemented in Android...
-int XFreeGC(Display * dpy, GC gc)
-{
-    return 0;
-}
-
-
-
-int XFreeFont(Display * dpy, XFontStruct * f)
-{
-    return 0;
-}
-
-int XFreeFontInfo(char **names, XFontStruct * info, int n)
-{
-    int i;
-    if (names) {
-       for (i = 0; i < n; i++)
-           if (names[i])
-               free(names[i]);
-       free(names);
-    }
-    if (info) {
-       for (i = 0; i < n; i++)
-           if (info[i].per_char)
-               free(info[i].per_char);
-       free(info);
-    }
-    return 0;
-}
-
-
-//  needs to be implemented in Android...
-int XUnloadFont(Display * dpy, Font fid)
-{
-    return 0;
-}
-
-
-//  needs to be implemented in Android...
-GC
-XCreateGC(Display * dpy, Drawable d, unsigned long mask, XGCValues * xgcv)
-{
-}
-
-
-//  needs to be implemented in Android...
-XFontStruct *XLoadQueryFont(Display * dpy, const char *name)
-{
-}
-
-
-Status
-XGetWindowAttributes(Display * dpy, Window w, XWindowAttributes * xgwa)
-{
-
-//  Assert (w && w->type == WINDOW, "not a window");
-
-    memset(xgwa, 0, sizeof(*xgwa));
-    xgwa->x = w->frame.origin.x;
-    xgwa->y = w->frame.origin.y;
-    xgwa->width = w->frame.size.width;
-    xgwa->height = w->frame.size.height;
-    xgwa->depth = 32;
-    xgwa->screen = dpy->screen;
-    xgwa->visual = dpy->screen->visual;
-
-    return 0;
-}
-
-//  needs to be implemented in Android...
-int XSetFont(Display * dpy, GC gc, Font fid)
-{
-    return 0;
-}
-
-
-//  needs to be implemented in Android...
-int XClearWindow(Display * dpy, Window win)
-{
-}
-
-// declared in utils/visual.h
-int has_writable_cells(Screen * s, Visual * v)
-{
-    return 0;
-}
-
-Status
-XAllocColorCells(Display * dpy, Colormap cmap, Bool contig,
-                unsigned long *pmret, unsigned int npl,
-                unsigned long *pxret, unsigned int npx)
-{
-    return 0;
-}
-
-int XStoreColors(Display * dpy, Colormap cmap, XColor * colors, int n)
-{
-    //Assert(0, "XStoreColors called");
-    return 0;
-}
-
-int
-XFreeColors(Display * dpy, Colormap cmap, unsigned long *px, int npixels,
-           unsigned long planes)
-{
-    return 0;
-}
-
-int XFlush(Display * dpy)
-{
-    return 0;
-}
-
-Display *XDisplayOfScreen(Screen * s)
-{
-    return s->dpy;
-}
-
-//  needs to be implemented in Android...
-int
-XLookupString(XKeyEvent * e, char *buf, int size, KeySym * k_ret,
-             XComposeStatus * xc)
-{
-    return 0;
-}
-
-int XScreenNumberOfScreen(Screen * s)
-{
-    return s->screen_number;
-}
-
-int jwxyz_ScreenCount(Display * dpy)
-{
-    return dpy->screen_count;
-}
-
-
-/*
-// should this be defined?
-static Display *jwxyz_live_displays[20] = { 0, };
-*/
-
-Display * jwxyz_make_display (void *nsview_arg, void *cgc_arg)
-{
-    Display *d = (Display *) calloc(1, sizeof(*d));
-    d->screen = (Screen *) calloc(1, sizeof(Screen));
-    d->screen->dpy = d;
-
-    d->screen_count = 1;
-    d->screen->screen_number = 0;
-    d->screen->black = 0xFF000000;
-    d->screen->white = 0xFFFFFFFF;
-
-    Visual *v = (Visual *) calloc(1, sizeof(Visual));
-    v->class = TrueColor;
-    v->red_mask = 0x00FF0000;
-    v->green_mask = 0x0000FF00;
-    v->blue_mask = 0x000000FF;
-    v->bits_per_rgb = 8;
-    d->screen->visual = v;
-
-    Window w = (Window) calloc(1, sizeof(*w));
-    w->type = WINDOW;
-    w->window.background = BlackPixelOfScreen(d->screen);
-
-    d->main_window = w;
-
-    return d;
-}
-
-void
-jwxyz_free_display (Display *dpy)
-{
-  free (dpy->screen->visual);
-  free (dpy->screen);
-  free (dpy->main_window);
-  free (dpy);
-}
-
-
-/* Call this when the Renderer calls onSurfaceChanged
- */
-void
-jwxyz_window_resized (Display *dpy, Window w, 
-                      int new_x, int new_y, int new_width, int new_height,
-                      void *cgc_arg)
-{
-    w->frame.origin.x = new_x;
-    w->frame.origin.y = new_y;
-    w->frame.size.width = new_width;
-    w->frame.size.height = new_height;
-}
-
-Window XRootWindow(Display * dpy, int screen)
-{
-    return dpy->main_window;
-}
-
-/* Handle an abort on Android
-   TODO: Test that Android handles aborts properly
- */
-void
-jwxyz_abort (const char *fmt, ...)
-{
-  char s[10240];
-  if (!fmt || !*fmt)
-    strcpy (s, "abort");
-  else
-    {
-      va_list args;
-      va_start (args, fmt);
-      vsprintf (s, fmt, args);
-      va_end (args);
-    }
-  /* Send error to Android device log */
-  __android_log_write(ANDROID_LOG_ERROR, "xscreensaver", s);
-
-  abort();  
-}
-
-Pixmap
-XCreatePixmap (Display *dpy, Drawable d,
-               unsigned int width, unsigned int height, unsigned int depth)
-{
-}
-
-int
-XDestroyImage (XImage *ximage)
-{
-  if (ximage->data) free (ximage->data);
-  free (ximage);
-  return 0;
-}
-
-int
-XDrawString16 (Display *dpy, Drawable d, GC gc, int x, int y,
-             const XChar2b *str, int len)
-{
-}
-
-int
-XFreePixmap (Display *d, Pixmap p)
-{
-}
-
-XImage *
-XGetImage (Display *dpy, Drawable d, int x, int y,
-           unsigned int width, unsigned int height,
-           unsigned long plane_mask, int format)
-{
-}
-
-unsigned long
-XGetPixel (XImage *ximage, int x, int y)
-{
-}
-
-int
-XSetForeground (Display *dpy, GC gc, unsigned long fg)
-{
-}
-
-int
-XTextExtents16 (XFontStruct *f, const XChar2b *s, int length,
-                int *dir_ret, int *ascent_ret, int *descent_ret,
-                XCharStruct *cs)
-{
-}
-
-int
-XPutPixel (XImage *ximage, int x, int y, unsigned long pixel)
-{
-}
-
-XImage *
-XCreateImage (Display *dpy, Visual *visual, unsigned int depth,
-              int format, int offset, char *data,
-              unsigned int width, unsigned int height,
-              int bitmap_pad, int bytes_per_line)
-{
-}
diff --git a/android/jwxyz.h b/android/jwxyz.h
deleted file mode 100644 (file)
index 2f4d59d..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-/* Android does not have __dead2 defined
-   TODO: Test Android ability to abort properly */
-#define __dead2
-#include "../OSX/jwxyz.h"
diff --git a/android/project/GLWallpaperService/AndroidManifest.xml b/android/project/GLWallpaperService/AndroidManifest.xml
deleted file mode 100644 (file)
index 23eb68f..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-      package="net.rbgrn.android.glwallpaperservice"
-      android:versionCode="1"
-      android:versionName="1.0">
-    <application android:label="@string/app_name">
-
-
-    </application>
-    <uses-sdk android:minSdkVersion="7" />
-
-</manifest> 
diff --git a/android/project/GLWallpaperService/LICENSE b/android/project/GLWallpaperService/LICENSE
deleted file mode 100644 (file)
index d645695..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
diff --git a/android/project/GLWallpaperService/NOTICE b/android/project/GLWallpaperService/NOTICE
deleted file mode 100644 (file)
index 117f024..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-Copyright 2008 The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-
-Portions of this software were developed by Robert Green. The original
-software is available from
-     http://www.rbgrn.net/content/354-glsurfaceview-adapted-3d-live-wallpapers
-
-Other contributors include
-     Mark Guerra - http://www.markguerra.net
-     TaDaa - https://github.com/TaDaa
diff --git a/android/project/GLWallpaperService/build.gradle b/android/project/GLWallpaperService/build.gradle
deleted file mode 100644 (file)
index 1081dae..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-apply plugin: 'android-library'
-
-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']
-        }
-
-        // 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')
-    }
-    defaultConfig {
-        minSdkVersion 15
-        targetSdkVersion 21
-    }
-    productFlavors {
-    }
-}
diff --git a/android/project/GLWallpaperService/build.xml b/android/project/GLWallpaperService/build.xml
deleted file mode 100644 (file)
index b75ecc9..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project name="GLWallpaperService" 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/GLWallpaperService/default.properties b/android/project/GLWallpaperService/default.properties
deleted file mode 100644 (file)
index 4eaf136..0000000
+++ /dev/null
@@ -1,12 +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 use,
-# "build.properties", and override values to adapt the script to your
-# project structure.
-
-# Project target.
-target=android-7
-android.library=true
diff --git a/android/project/GLWallpaperService/project.properties b/android/project/GLWallpaperService/project.properties
deleted file mode 100644 (file)
index 0eb624c..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=true
-# Project target.
-target=android-7
diff --git a/android/project/GLWallpaperService/readme-contribute.txt b/android/project/GLWallpaperService/readme-contribute.txt
deleted file mode 100644 (file)
index d04a0ab..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-Project Setup - GLWallpaperService
-==================================
-
-Discussion Group:
-http://groups.google.com/group/glwallpaperservice
-
-Repository:
-https://github.com/markfguerra/GLWallpaperService/
-
-Intended Audience
------------------
-This document is for developers who want to improve GLWallpaperService. It shows you how to download the source code to to improve it (or break it) as you please using Eclipse.
-If you're only interested in using the software to make an OpenGL Wallpaper, this isn't for you. Instead, look at readme.txt for info on how to get and install the Jar.
-
-
-Install required software
--------------------------
-To start, make sure install Eclipse the latest Android SDK are installed. Optionally, install git. Follow the instructions provided by those software projects to do so.
-    Eclipse:     http://wiki.eclipse.org/FAQ_Where_do_I_get_and_install_Eclipse%3F
-    Android SDK: http://developer.android.com/sdk/installing.html
-       Git:         http://git-scm.com/
-
-Also, if you plan on using git, we recommend you make an account on github.
-       http://github.com/
-
-
-Folder Setup
-------------
-We are going to make two folders in this document. One will contain the code itself, and another will contain the Eclipse workspace. If you prefer that they both be in the same folder, do so. As if I could stop you ;)
-
-Go to where you're putting all this stuff.
-    cd /path/to/your/folder
-
-Make a folder for your workspace.
-    mkdir workspace
-
-
-Get the code
-------------
-Download the source code. You can do so using git or just a regular old download.
-
-For a direct download, go here. Extract the zip into a sub folder:
-    https://github.com/markfguerra/GLWallpaperService/zipball/master
-
-If you use github, please fork this code from their web interface:
-    https://github.com/markfguerra/GLWallpaperService
-
-Then you want to make a local clone of your github fork. Github will provide you with your own Url. My clone command looks like this:
-    git clone git@github.com:markfguerra/GLWallpaperService.git
-
-A new folder will be created automatically, called GLWallpaperService/ containing your source code.
-
-Visit this link if you need help using github:
-    http://help.github.com/
-
-
-Start Eclipse
--------------
-Open Eclipse and choose the folder you just created for your workspace. When it finishes loading, click the Arrow to go to the workbench.
-
-
-Set up the Android SDK
-----------------------
-To set up the Android SDK for this project:
-In the menu, go to Eclipse->Preferences. Go to the Android section.
-Give it the location of your Android SDK folder. Give it a minute to figure things out.
-Select Android 2.1 (Api level 7) then click Ok.
-
-
-Import the code into the workspace
-----------------------------------
-In the Eclipse menu, choose File->New->"Android Project"
-Choose "Create new project from existing source"
-For the location click browse and select the "GLWallpaperService" folder. To be clear, this is a sub-folder of the folder that contains the LICENSE file.
-Select "Android 2.1-update1" as your build target. This is API Level 7.
-For the Project Name, type "GLWallpaperService"
-Repeat these steps for the "GLWallpaperTest" folder. Use the project name "GLWallpaperTest"
-
-The code will now be in your workspace.
-
-
-Resolving build errors
-----------------------
-Most people should have a working project at this point. However, some folks encounter build errors when they first import the code into their workspace. There are a couple of tricks to help you fix them.
-First and foremost, make sure you have the latest versions of the Android SDK and Eclipse plugin. This is important, because older versions of the developer tools handle Library Projects differently, so if you have an old version this may cause problems.
-You may have to fix the Project Properties. Right-click on the "GLWallpaperService" project in the Package Explorer. Select "Android Tools"->"Fix Project Properties".
-Also fix the project properties for "GLWallpaperTest" the same way.
-In the menu, click on Project->Clean to clean all projects.
-In Package Explorer, right-click on the GLWallpaperService project and click on "Refresh". Do the same for GLWallpaperTest.
-You may need to click on Project->Clean to clean all projects again after the refresh.
-Your errors should go away at this point. If not, try using a programming Q&A site such as stackoverflow.com and also search Google.
-
-
-To Run
-------
-Save your work. By default, saving will also compile your code in Eclipse.
-
-Plug in your Android Device to your computer, if you have one. If you don't plug in an Android device, the emulator will launch when you run the code. You may need create an Android Emulator if you havn't done so already.
-
-In the Menu, choose Run->"Run Configurations".
-Choose "Android Application"
-Click on the "New" button. This is the button with the plus sign on it.
-The name of the run configuration is New_configuration. Change it if you like.
-Click "Browse..." to choose a project. Select GLWallpaperTest. This is a sample wallpaper that comes with the code.
-Click Apply. Click Run.
-The wallpaper will now install on your device or emulator. Use the regular Android live wallpaper picker to select "GL Wallpaper Test Project". You should see a 3D rotating cube.
-
-Now that your run configuration is set up, you can run New_configuration any time by using the Toolbar icon.
-
-
-Creating GLWallpaperService.jar
--------------------------------
-Do the following to create the JAR file, which is convenient for use in projects.
-In the Eclipse menu, click File -> Export
-Choose "JAR File"
-On the "JAR Export" screen, choose only GLWallpaperService.java. You do not need to include other files.
-Make note of where the JAR will be saved and click Finish
-
-
-Contribute your code
---------------------
-If you do something cool with this software, we would love it if you would share your changes with us. Even if your changes still need some polishing. Don't worry, we're friendly :)
-
-If you are using git and github, push your changes to your fork and send us a pull request. If you're not using those fancy things, we want to hear from you anyway. Send us a message and we'll work something out.
-
-Thanks for your interest in this project. Good luck coding!
-
diff --git a/android/project/GLWallpaperService/readme.txt b/android/project/GLWallpaperService/readme.txt
deleted file mode 100644 (file)
index 3b6380d..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-Truly Excellent Live Wallpaper - Version 0.1
-
-
-Upstream codebases
-------------------
-
-This is a port of Xscreensaver 5.29 to Android.
-
-On the Android side, it uses Ben Gruver's version of Mark Guerra's GL 
-WallpaperService for Android.
-
-Xscreensaver's GLX hacks are OpenGL, and Android is OpenGL ES, 
-so we use the OpenGL to OpenGL ES translation shim that is in Xscreensaver.
-
-
-Compiling
----------
-
-We are compiling our APK with ant.  If you have a problem getting this 
-to work with Eclipse, Android Studio, or some other IDE, let us know.  
-TrulyCreative is the Service, and GLWallpaperService is the library 
-which TrulyCreative uses.  Also don't forget this uses C/C++ code via 
-the NDK, so you have to build both the C/C++ and Java/Dalvik code.
-
-
-
-Licenses
---------
-
-Some code in gl1.c is based off code from
-Jetro Lauha's San Angeles Observation project
-which is under a BSD-style license.
-
-GLWallpaperService is under an Apache License, Version 2.0.
-
-Look in the TrulyExcellent/jni/xscreensaver to see what licenses are used.
-MIT/X11 seems to be the primary license.
-
-The rest of the code is released under Apache License, Version 2.0.  
-Some of that code is from the Android Open Source Project, some is from 
-Dennis Sheil.  Dennis Sheil dual-licenses his code as MIT/X11 license also.
diff --git a/android/project/GLWallpaperService/res/drawable-hdpi/icon.png b/android/project/GLWallpaperService/res/drawable-hdpi/icon.png
deleted file mode 100644 (file)
index 079e7a4..0000000
Binary files a/android/project/GLWallpaperService/res/drawable-hdpi/icon.png and /dev/null differ
diff --git a/android/project/GLWallpaperService/res/drawable-ldpi/icon.png b/android/project/GLWallpaperService/res/drawable-ldpi/icon.png
deleted file mode 100644 (file)
index c4d1934..0000000
Binary files a/android/project/GLWallpaperService/res/drawable-ldpi/icon.png and /dev/null differ
diff --git a/android/project/GLWallpaperService/res/drawable-mdpi/icon.png b/android/project/GLWallpaperService/res/drawable-mdpi/icon.png
deleted file mode 100644 (file)
index 1e14e4b..0000000
Binary files a/android/project/GLWallpaperService/res/drawable-mdpi/icon.png and /dev/null differ
diff --git a/android/project/GLWallpaperService/res/layout/main.xml b/android/project/GLWallpaperService/res/layout/main.xml
deleted file mode 100644 (file)
index 3a5f117..0000000
+++ /dev/null
@@ -1,12 +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"
-    >
-<TextView  
-    android:layout_width="fill_parent" 
-    android:layout_height="wrap_content" 
-    android:text="@string/hello"
-    />
-</LinearLayout>
diff --git a/android/project/GLWallpaperService/res/values/strings.xml b/android/project/GLWallpaperService/res/values/strings.xml
deleted file mode 100644 (file)
index c67ae51..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string name="hello">Hello World!</string>
-    <string name="app_name">GL Wallpaper Service</string>
-</resources>
diff --git a/android/project/GLWallpaperService/src/net/rbgrn/android/glwallpaperservice/GLWallpaperService.java b/android/project/GLWallpaperService/src/net/rbgrn/android/glwallpaperservice/GLWallpaperService.java
deleted file mode 100644 (file)
index 63a5be5..0000000
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * Copyright (c) 2011 Ben Gruver
- * All rights reserved.
- *
- * You may use this code at your option under the following BSD license
- * or Apache 2.0 license terms
- *
- * [The "BSD license"]
- * 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.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
- *
- * [The "Apache 2.0 license"]
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.rbgrn.android.glwallpaperservice;
-
-import android.opengl.GLSurfaceView;
-import android.service.wallpaper.WallpaperService;
-import android.view.SurfaceHolder;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
-
-public abstract class GLWallpaperService extends WallpaperService {
-    public interface Renderer extends GLSurfaceView.Renderer {
-    }
-
-    public class GLEngine extends WallpaperService.Engine {
-       public final static int RENDERMODE_WHEN_DIRTY = 0;
-       public final static int RENDERMODE_CONTINUOUSLY = 1;
-
-        private Object lock = new Object();
-        private GLSurfaceView mGLSurfaceView = null;
-
-        private int debugFlags;
-        private int renderMode;
-
-        /**
-         * If we don't have a GLSurfaceView yet, then we queue up any operations that are requested, until the
-         * GLSurfaceView is created.
-         *
-         * Initially, we created the glSurfaceView in the GLEngine constructor, and things seemed to work. However,
-         * it turns out a few devices aren't set up to handle the surface related events at this point, and crash.
-         *
-         * This is a work around so that we can delay the creation of the GLSurfaceView until the surface is actually
-         * created, so that the underlying code should be in a state to be able to handle the surface related events
-         * that get fired when GLSurfaceView is created.
-         */
-        private List<Runnable> pendingOperations = new ArrayList<Runnable>();
-
-        public GLEngine() {
-        }
-
-        public void setGLWrapper(final GLSurfaceView.GLWrapper glWrapper) {
-            synchronized (lock) {
-                if (mGLSurfaceView != null) {
-                    mGLSurfaceView.setGLWrapper(glWrapper);
-                } else {
-                    pendingOperations.add(new Runnable() {
-                        public void run() {
-                            setGLWrapper(glWrapper);
-                        }
-                    });
-                }
-            }
-        }
-
-        public void setDebugFlags(final int debugFlags) {
-            synchronized (lock) {
-                if (mGLSurfaceView != null) {
-                    mGLSurfaceView.setDebugFlags(debugFlags);
-                } else {
-                    this.debugFlags = debugFlags;
-                    pendingOperations.add(new Runnable() {
-                        public void run() {
-                            setDebugFlags(debugFlags);
-                        }
-                    });
-                }
-            }
-        }
-
-        public int getDebugFlags() {
-            synchronized (lock) {
-                if (mGLSurfaceView != null) {
-                    return mGLSurfaceView.getDebugFlags();
-                } else {
-                    return debugFlags;
-                }
-            }
-        }
-
-        public void setRenderer(final GLSurfaceView.Renderer renderer) {
-            synchronized (lock) {
-                if (mGLSurfaceView != null) {
-                    mGLSurfaceView.setRenderer(renderer);
-                    if (!isVisible()) {
-                        mGLSurfaceView.onPause();
-                    }
-                } else {
-                    pendingOperations.add(new Runnable() {
-                        public void run() {
-                            setRenderer(renderer);
-                        }
-                    });
-                }
-            }
-        }
-
-        public void queueEvent(final Runnable r) {
-            synchronized (lock) {
-                if (mGLSurfaceView != null) {
-                    mGLSurfaceView.queueEvent(r);
-                } else {
-                    pendingOperations.add(new Runnable() {
-                        public void run() {
-                            queueEvent(r);
-                        }
-                    });
-                }
-            }
-        }
-
-        public void setEGLContextFactory(final GLSurfaceView.EGLContextFactory factory) {
-            synchronized (lock) {
-                if (mGLSurfaceView != null) {
-                    mGLSurfaceView.setEGLContextFactory(factory);
-                } else {
-                    pendingOperations.add(new Runnable() {
-                        public void run() {
-                            setEGLContextFactory(factory);
-                        }
-                    });
-                }
-            }
-        }
-
-        public void setEGLWindowSurfaceFactory(final GLSurfaceView.EGLWindowSurfaceFactory factory) {
-            synchronized (lock) {
-                if (mGLSurfaceView != null) {
-                    mGLSurfaceView.setEGLWindowSurfaceFactory(factory);
-                } else {
-                    pendingOperations.add(new Runnable() {
-                        public void run() {
-                            setEGLWindowSurfaceFactory(factory);
-                        }
-                    });
-                }
-            }
-        }
-
-        public void setEGLConfigChooser(final GLSurfaceView.EGLConfigChooser configChooser) {
-            synchronized (lock) {
-                if (mGLSurfaceView != null) {
-                    mGLSurfaceView.setEGLConfigChooser(configChooser);
-                } else {
-                    pendingOperations.add(new Runnable() {
-                        public void run() {
-                            setEGLConfigChooser(configChooser);
-                        }
-                    });
-                }
-            }
-        }
-
-        public void setEGLConfigChooser(final boolean needDepth) {
-            synchronized (lock) {
-                if (mGLSurfaceView != null) {
-                    mGLSurfaceView.setEGLConfigChooser(needDepth);
-                } else {
-                    pendingOperations.add(new Runnable() {
-                        public void run() {
-                            setEGLConfigChooser(needDepth);
-                        }
-                    });
-                }
-            }
-        }
-
-        public void setEGLConfigChooser(final int redSize, final int greenSize, final int blueSize,
-            final int alphaSize, final int depthSize, final int stencilSize) {
-            synchronized (lock) {
-                if (mGLSurfaceView != null) {
-                    mGLSurfaceView.setEGLConfigChooser(redSize, greenSize, blueSize,
-                        alphaSize, depthSize, stencilSize);
-                } else {
-                    pendingOperations.add(new Runnable() {
-                        public void run() {
-                            setEGLConfigChooser(redSize, greenSize, blueSize, alphaSize, depthSize, stencilSize);
-                        }
-                    });
-                }
-            }
-        }
-
-        public void setEGLContextClientVersion(final int version) {
-            synchronized (lock) {
-                Method method = null;
-
-                try {
-                    //the setEGLContextClientVersion method is first available in api level 8, but we would
-                    //like to support compiling against api level 7
-                    method = GLSurfaceView.class.getMethod("setEGLContextClientVersion", int.class);
-                } catch (NoSuchMethodException ex) {
-                    return;
-                }
-
-                if (mGLSurfaceView != null) {
-                    try {
-                        method.invoke(mGLSurfaceView, version);
-                    } catch (IllegalAccessException ex) {
-                        return;
-                    } catch (InvocationTargetException ex) {
-                        return;
-                    }
-                } else {
-                    pendingOperations.add(new Runnable() {
-                        public void run() {
-                            setEGLContextClientVersion(version);
-                        }
-                    });
-                }
-            }
-        }
-
-        public void setRenderMode(final int renderMode) {
-            synchronized (lock) {
-                if (mGLSurfaceView != null) {
-                    mGLSurfaceView.setRenderMode(renderMode);
-                } else {
-                    this.renderMode = renderMode;
-                    pendingOperations.add(new Runnable() {
-                        public void run() {
-                            setRenderMode(renderMode);
-                        }
-                    });
-                }
-            }
-        }
-
-        public int getRenderMode() {
-            synchronized (lock) {
-                if (mGLSurfaceView != null) {
-                    return mGLSurfaceView.getRenderMode();
-                } else {
-                    return renderMode;
-                }
-            }
-        }
-
-        public void requestRender() {
-            if (mGLSurfaceView != null) {
-                mGLSurfaceView.requestRender();
-            }
-        }
-
-        @Override
-        public void onVisibilityChanged(final boolean visible) {
-            super.onVisibilityChanged(visible);
-
-            synchronized (lock) {
-                if (mGLSurfaceView != null) {
-                    if (visible) {
-                        mGLSurfaceView.onResume();
-                    } else {
-                        mGLSurfaceView.onPause();
-                    }
-                } else {
-                    pendingOperations.add(new Runnable() {
-                        public void run() {
-                            if (visible) {
-                                mGLSurfaceView.onResume();
-                            } else {
-                                mGLSurfaceView.onPause();
-                            }
-                        }
-                    });
-                }
-            }
-        }
-
-        @Override
-        public void onSurfaceChanged(final SurfaceHolder holder, final int format, final int width, final int height) {
-            synchronized (lock) {
-                if (mGLSurfaceView != null) {
-                    mGLSurfaceView.surfaceChanged(holder, format, width, height);
-                } else {
-                    pendingOperations.add(new Runnable() {
-                        public void run() {
-                            onSurfaceChanged(holder, format, width, height);
-                        }
-                    });
-                }
-            }
-        }
-
-        @Override
-        public void onSurfaceCreated(SurfaceHolder holder) {
-            synchronized (lock) {
-                if (mGLSurfaceView == null) {
-                    mGLSurfaceView = new GLSurfaceView(GLWallpaperService.this) {
-                        @Override
-                        public SurfaceHolder getHolder() {
-                            return GLEngine.this.getSurfaceHolder();
-                        }
-                    };
-                    for (Runnable pendingOperation: pendingOperations) {
-                        pendingOperation.run();
-                    }
-                    pendingOperations.clear();
-                }
-                mGLSurfaceView.surfaceCreated(holder);
-            }
-        }
-
-        @Override
-        public void onSurfaceDestroyed(SurfaceHolder holder) {
-            synchronized (lock) {
-                if (mGLSurfaceView != null) {
-                    mGLSurfaceView.surfaceDestroyed(holder);
-                }
-            }
-        }
-    }
-}
index f2533c79546de89d46a50c9b2f7fe9e1f0593aab..41cd0d1573e42f35248d8fb620613e099de4bfc8 100644 (file)
@@ -7,3 +7,13 @@ buildscript {
         classpath 'com.android.tools.build:gradle:1.1.0'
     }
 }
+
+task clean(type: Delete) {
+    delete('./build')
+}
+
+task distClean(type: Delete) {
+    delete('./.gradle')
+}
+
+distClean.dependsOn clean
index 42a7906743b75bd6aafc50c1ebd252ec89e228ef..5fc665bd0607bcc573b92a0837a9ed3619801345 100644 (file)
@@ -1,2 +1 @@
 include ':xscreensaver'
-include ':GLWallpaperService'
diff --git a/android/project/xscreensaver/AndroidManifest.xml b/android/project/xscreensaver/AndroidManifest.xml
deleted file mode 100644 (file)
index d7d548b..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.jwz.xscreensaver"
-android:versionCode="1"
-android:versionName="1.0">
-<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" />
-<application android:icon="@drawable/thumbnail" android:label="@string/app_name" android:name=".XscreensaverApp">
-
-<service android:label="@string/sproingies_name" android:name=".gen.SproingiesService" android:permission="android.permission.BIND_WALLPAPER">
- <intent-filter>
-   <action android:name="android.service.wallpaper.WallpaperService" />
- </intent-filter>
- <meta-data android:name="android.service.wallpaper" android:resource="@xml/sproingies" />
-</service>
-<activity android:label="@string/sproingies_settings" android:name="org.jwz.xscreensaver.gen.SproingiesSettings" android:theme="@android:style/Theme.Light.WallpaperSettings" android:exported="true">
-</activity>
-
-<service android:label="@string/superquadrics_name" android:name=".gen.SuperquadricsService" android:permission="android.permission.BIND_WALLPAPER">
- <intent-filter>
-   <action android:name="android.service.wallpaper.WallpaperService" />
- </intent-filter>
- <meta-data android:name="android.service.wallpaper" android:resource="@xml/superquadrics" />
-</service>
-<activity android:label="@string/superquadrics_settings" android:name="org.jwz.xscreensaver.gen.SuperquadricsSettings" android:theme="@android:style/Theme.Light.WallpaperSettings" android:exported="true">
-</activity>
-
-<service android:label="@string/stonerview_name" android:name=".gen.StonerviewService" android:permission="android.permission.BIND_WALLPAPER">
- <intent-filter>
-   <action android:name="android.service.wallpaper.WallpaperService" />
- </intent-filter>
- <meta-data android:name="android.service.wallpaper" android:resource="@xml/stonerview" />
-</service>
-<activity android:label="@string/stonerview_settings" android:name="org.jwz.xscreensaver.gen.StonerviewSettings" android:theme="@android:style/Theme.Light.WallpaperSettings" android:exported="true">
-</activity>
-
-<service android:label="@string/unknownpleasures_name" android:name=".gen.UnknownpleasuresService" android:permission="android.permission.BIND_WALLPAPER">
- <intent-filter>
-   <action android:name="android.service.wallpaper.WallpaperService" />
- </intent-filter>
- <meta-data android:name="android.service.wallpaper" android:resource="@xml/unknownpleasures" />
-</service>
-<activity android:label="@string/unknownpleasures_settings" android:name="org.jwz.xscreensaver.gen.UnknownpleasuresSettings" android:theme="@android:style/Theme.Light.WallpaperSettings" android:exported="true">
-</activity>
-
-<service android:label="@string/bouncingcow_name" android:name=".gen.BouncingcowService" android:permission="android.permission.BIND_WALLPAPER">
- <intent-filter>
-   <action android:name="android.service.wallpaper.WallpaperService" />
- </intent-filter>
- <meta-data android:name="android.service.wallpaper" android:resource="@xml/bouncingcow" />
-</service>
-<activity android:label="@string/bouncingcow_settings" android:name="org.jwz.xscreensaver.gen.BouncingcowSettings" android:theme="@android:style/Theme.Light.WallpaperSettings" android:exported="true">
-</activity>
-
-<service android:label="@string/hypertorus_name" android:name=".gen.HypertorusService" android:permission="android.permission.BIND_WALLPAPER">
- <intent-filter>
-   <action android:name="android.service.wallpaper.WallpaperService" />
- </intent-filter>
- <meta-data android:name="android.service.wallpaper" android:resource="@xml/hypertorus" />
-</service>
-<activity android:label="@string/hypertorus_settings" android:name="org.jwz.xscreensaver.gen.HypertorusSettings" android:theme="@android:style/Theme.Light.WallpaperSettings" android:exported="true">
-</activity>
-
-<service android:label="@string/glhanoi_name" android:name=".gen.GlhanoiService" android:permission="android.permission.BIND_WALLPAPER">
- <intent-filter>
-   <action android:name="android.service.wallpaper.WallpaperService" />
- </intent-filter>
- <meta-data android:name="android.service.wallpaper" android:resource="@xml/glhanoi" />
-</service>
-<activity android:label="@string/glhanoi_settings" android:name="org.jwz.xscreensaver.gen.GlhanoiSettings" android:theme="@android:style/Theme.Light.WallpaperSettings" android:exported="true">
-</activity>
-
-</application>
-
-<uses-sdk android:minSdkVersion="14" />
-<uses-feature android:name="android.software.live_wallpaper" android:required="true" />
-</manifest>
diff --git a/android/project/xscreensaver/assets/fonts/OCRAStd.otf b/android/project/xscreensaver/assets/fonts/OCRAStd.otf
new file mode 120000 (symlink)
index 0000000..6a6cb46
--- /dev/null
@@ -0,0 +1 @@
+../../../../../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
new file mode 120000 (symlink)
index 0000000..7be8e8e
--- /dev/null
@@ -0,0 +1 @@
+../../../../../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
new file mode 120000 (symlink)
index 0000000..d67181b
--- /dev/null
@@ -0,0 +1 @@
+../../../../../OSX/YearlReg.ttf
\ No newline at end of file
index 13373ec5fc44b7efc3f7310f21afa2fc4f5ca5c6..0700c946e45c6943bce3c6e0bce710cdb5386038 100644 (file)
@@ -2,7 +2,6 @@ apply plugin: 'android'
 
 dependencies {
     compile fileTree(include: '*.jar', dir: 'libs')
-    compile project(':GLWallpaperService')
 }
 
 android {
@@ -52,33 +51,54 @@ android {
 
     // generate files early in the process
     task perlBuild(type: Exec) {
-        commandLine 'perl', '-x../..', '../../generate_files.pl', 'sproingies', 'superquadrics', 'stonerview', 'unknownpleasures', 'bouncingcow', 'hypertorus', 'glhanoi'
+        commandLine 'sh', '-c',
+          'cd ../..; ../hacks/check-configs.pl --build-android $ANDROID_HACKS'
     }
-
   
-    task perlClean(type: Exec) {
-        commandLine 'rm', '-f', '../../gen/glue.c', './res/values/items.xml', './res/values/strings.xml', './res/values/settings.xml'
+    task perlClean(type: Delete) {
+        delete('../../gen')
+        delete('res/values')
+        delete('res/xml')
+        delete('src/org/jwz/xscreensaver/gen')
+        delete('AndroidManifest.xml')
     }
 
-    task perlCleaner(type: Exec) {
-        commandLine 'rm', '-rf', './res/xml', './src/org/jwz/xscreensaver/gen'
+    task objlibClean(type: Delete) {
+        delete('./build')
+        delete('./libs')
+        delete('./obj')
     }
 
-    task objlibClean(type: Exec) {
-        commandLine 'rm', '-rf', './obj/local', './libs/armeabi', './libs/armeabi-v7a', './libs/mips', './libs/x86'
+    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
 
-    // if perlBuild already generated file, do not run perlBuild again
-    if (! file("../../gen/glue.c").exists()) {
-        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 perlCleaner
     clean.dependsOn objlibClean
 
-    // 
+    tasks.withType(JavaCompile) {
+        options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
+    }
+
     tasks.withType(JavaCompile) {
         compileTask -> compileTask.dependsOn ndkBuild
     }
index fccfccac7183b361c590838402c18b10aba8153c..b29a57816c69ade46f223ec81e1f8a711ac19408 100644 (file)
@@ -4,17 +4,96 @@ include $(CLEAR_VARS)
 
 LOCAL_MODULE := xscreensaver
 
+# The base framework files:
 LOCAL_SRC_FILES := \
-    xscreensaver/hacks/xlockmore.c \
+    xscreensaver/android/screenhack-android.c \
+    xscreensaver/android/grabscreen-android.c \
+    xscreensaver/jwxyz/jwxyz-android.c \
+    xscreensaver/jwxyz/jwxyz-common.c \
+    xscreensaver/jwxyz/jwxyz-gl.c \
+    xscreensaver/jwxyz/jwxyz-timers.c \
+    xscreensaver/jwxyz/jwzgles.c \
+
+# Utilities used by the hacks:
+LOCAL_SRC_FILES += \
+    xscreensaver/hacks/analogtv.c \
+    xscreensaver/hacks/delaunay.c \
     xscreensaver/hacks/fps.c \
+    xscreensaver/hacks/glx/dropshadow.c \
+    xscreensaver/hacks/glx/chessmodels.c \
     xscreensaver/hacks/glx/fps-gl.c \
-    xscreensaver/hacks/glx/jwzgles.c \
+    xscreensaver/hacks/glx/gltrackball.c \
+    xscreensaver/hacks/glx/glut_stroke.c \
+    xscreensaver/hacks/glx/glut_swidth.c \
+    xscreensaver/hacks/glx/grab-ximage.c \
+    xscreensaver/hacks/glx/marching.c \
+    xscreensaver/hacks/glx/normals.c \
     xscreensaver/hacks/glx/rotator.c \
-    xscreensaver/hacks/glx/tube.c \
     xscreensaver/hacks/glx/sphere.c \
-    xscreensaver/hacks/glx/sproingies.c \
-    xscreensaver/hacks/glx/sproingiewrap.c \
+    xscreensaver/hacks/glx/texfont.c \
+    xscreensaver/hacks/glx/trackball.c \
+    xscreensaver/hacks/glx/tube.c \
+    xscreensaver/hacks/glx/xpm-ximage.c \
+    xscreensaver/hacks/xlockmore.c \
+    xscreensaver/hacks/xpm-pixmap.c \
+    xscreensaver/utils/async_netdb.c \
+    xscreensaver/utils/aligned_malloc.c \
+    xscreensaver/utils/colorbars.c \
+    xscreensaver/utils/colors.c \
+    xscreensaver/utils/erase.c \
+    xscreensaver/utils/grabclient.c \
+    xscreensaver/utils/hsv.c \
+    xscreensaver/utils/logo.c \
+    xscreensaver/utils/minixpm.c \
+    xscreensaver/utils/resources.c \
+    xscreensaver/utils/spline.c \
+    xscreensaver/utils/textclient-mobile.c \
+    xscreensaver/utils/thread_util.c \
+    xscreensaver/utils/usleep.c \
+    xscreensaver/utils/utf8wc.c \
+    xscreensaver/utils/xft.c \
+    xscreensaver/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 "xscreensaver/hacks/$$f.c" ; \
+    else \
+      echo "xscreensaver/hacks/glx/$$f.c" ; \
+    fi ; \
+  done )
+
+# Some savers occupy more than one source file:
+LOCAL_SRC_FILES += \
+    xscreensaver/hacks/apple2-main.c \
+    xscreensaver/hacks/asm6502.c \
+    xscreensaver/hacks/pacman_ai.c \
+    xscreensaver/hacks/pacman_level.c \
+    xscreensaver/hacks/glx/b_draw.c \
+    xscreensaver/hacks/glx/b_lockglue.c \
+    xscreensaver/hacks/glx/b_sphere.c \
+    xscreensaver/hacks/glx/buildlwo.c \
+    xscreensaver/hacks/glx/companion_quad.c \
+    xscreensaver/hacks/glx/companion_disc.c \
+    xscreensaver/hacks/glx/companion_heart.c \
+    xscreensaver/hacks/glx/cow_face.c \
+    xscreensaver/hacks/glx/cow_hide.c \
+    xscreensaver/hacks/glx/cow_hoofs.c \
+    xscreensaver/hacks/glx/cow_horns.c \
+    xscreensaver/hacks/glx/cow_tail.c \
+    xscreensaver/hacks/glx/cow_udder.c \
+    xscreensaver/hacks/glx/dolphin.c \
     xscreensaver/hacks/glx/gllist.c \
+    xscreensaver/hacks/glx/glschool_alg.c \
+    xscreensaver/hacks/glx/glschool_gl.c \
+    xscreensaver/hacks/glx/involute.c \
+    xscreensaver/hacks/glx/lament_model.c \
+    xscreensaver/hacks/glx/pipeobjs.c \
+    xscreensaver/hacks/glx/robot.c \
+    xscreensaver/hacks/glx/robot-wireframe.c \
+    xscreensaver/hacks/glx/polyhedra-gl.c \
     xscreensaver/hacks/glx/s1_1.c \
     xscreensaver/hacks/glx/s1_2.c \
     xscreensaver/hacks/glx/s1_3.c \
@@ -22,41 +101,65 @@ LOCAL_SRC_FILES := \
     xscreensaver/hacks/glx/s1_5.c \
     xscreensaver/hacks/glx/s1_6.c \
     xscreensaver/hacks/glx/s1_b.c \
-    xscreensaver/hacks/glx/superquadrics.c \
-    xscreensaver/hacks/glx/trackball.c \
-    xscreensaver/hacks/glx/gltrackball.c \
-    xscreensaver/hacks/glx/texfont.c \
-    xscreensaver/hacks/glx/stonerview.c \
+    xscreensaver/hacks/glx/shark.c \
+    xscreensaver/hacks/glx/sonar-sim.c \
+    xscreensaver/hacks/glx/sonar-icmp.c \
+    xscreensaver/hacks/glx/splitflap_obj.c \
+    xscreensaver/hacks/glx/sproingiewrap.c \
     xscreensaver/hacks/glx/stonerview-move.c \
     xscreensaver/hacks/glx/stonerview-osc.c \
     xscreensaver/hacks/glx/stonerview-view.c \
-    xscreensaver/hacks/glx/hilbert.c \
-    xscreensaver/hacks/glx/xpm-ximage.c \
-    xscreensaver/hacks/glx/cow_face.c \
-    xscreensaver/hacks/glx/cow_hide.c \
-    xscreensaver/hacks/glx/cow_hoofs.c \
-    xscreensaver/hacks/glx/cow_horns.c \
-    xscreensaver/hacks/glx/cow_tail.c \
-    xscreensaver/hacks/glx/cow_udder.c \
-    xscreensaver/hacks/glx/bouncingcow.c \
-    xscreensaver/hacks/glx/unknownpleasures.c \
-    xscreensaver/hacks/glx/glhanoi.c \
-    xscreensaver/utils/minixpm.c \
-    xscreensaver/utils/hsv.c \
-    xscreensaver/utils/colors.c \
-    xscreensaver/utils/resources.c \
-    xscreensaver/utils/xft.c \
-    xscreensaver/utils/utf8wc.c \
-    xscreensaver/utils/yarandom.c \
-    xscreensaver/android/XScreenSaverView.c \
-    xscreensaver/android/XScreenSaverGLView.c \
-    xscreensaver/android/jwxyz.c \
-    xscreensaver/android/gen/glue.c
+    xscreensaver/hacks/glx/swim.c \
+    xscreensaver/hacks/glx/tangram_shapes.c \
+    xscreensaver/hacks/glx/teapot.c \
+    xscreensaver/hacks/glx/toast.c \
+    xscreensaver/hacks/glx/toast2.c \
+    xscreensaver/hacks/glx/toaster.c \
+    xscreensaver/hacks/glx/toaster_base.c \
+    xscreensaver/hacks/glx/toaster_handle.c \
+    xscreensaver/hacks/glx/toaster_handle2.c \
+    xscreensaver/hacks/glx/toaster_jet.c \
+    xscreensaver/hacks/glx/toaster_knob.c \
+    xscreensaver/hacks/glx/toaster_slots.c \
+    xscreensaver/hacks/glx/toaster_wing.c \
+    xscreensaver/hacks/glx/tronbit_idle1.c \
+    xscreensaver/hacks/glx/tronbit_idle2.c \
+    xscreensaver/hacks/glx/tronbit_no.c \
+    xscreensaver/hacks/glx/tronbit_yes.c \
+    xscreensaver/hacks/glx/tunnel_draw.c \
+    xscreensaver/hacks/glx/whale.c \
 
-LOCAL_LDLIBS := -lGLESv1_CM -ldl -llog
+LOCAL_LDLIBS := -lGLESv1_CM -ldl -llog -lEGL
 
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/xscreensaver $(LOCAL_PATH)/xscreensaver/android $(LOCAL_PATH)/xscreensaver/utils $(LOCAL_PATH)/xscreensaver/hacks $(LOCAL_PATH)/xscreensaver/hacks/glx
+LOCAL_C_INCLUDES := \
+       $(LOCAL_PATH)/xscreensaver \
+       $(LOCAL_PATH)/xscreensaver/android \
+       $(LOCAL_PATH)/xscreensaver/utils \
+       $(LOCAL_PATH)/xscreensaver/jwxyz \
+       $(LOCAL_PATH)/xscreensaver/hacks \
+       $(LOCAL_PATH)/xscreensaver/hacks/glx \
 
-LOCAL_CFLAGS += -std=c99 -DSTANDALONE=1 -DUSE_GL=1 -DGETTIMEOFDAY_TWO_ARGS=1 -DHAVE_JWZGLES=1 -DHAVE_ANDROID=1 -DGL_VERSION_ES_CM_1_0
+# -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)
index 7fe6f2bf81c7576bd14500d7a460effe6494b117..a7aa11b6cae19fc6d8e7b00c0ad9bdedf6aa1aad 100644 (file)
@@ -1,8 +1,6 @@
-#APP_ABI := armeabi-v7a
-#APP_ABI := armeabi armeabi-v7a
-APP_ABI := all
+# Get this value from android/Makefile
+APP_ABI := $(shell echo $$APP_ABI)
 APP_STL := stlport_static
-#APP_PLATFORM := android-10
 APP_PLATFORM := android-14
 # ^^ this can be increased
 
index 572ed00861311e1f071c9faa58aa923a3d1e5dba..1e1e7a3c5d67ac49e3afccd050c46aa237ba70c2 100644 (file)
@@ -10,6 +10,6 @@
 # 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=../GLWallpaperService
+android.library.reference.1=
 # Project target.
 target=android-19
diff --git a/android/project/xscreensaver/res/drawable/bouncingcow.png b/android/project/xscreensaver/res/drawable/bouncingcow.png
deleted file mode 100644 (file)
index 25cc4e6..0000000
Binary files a/android/project/xscreensaver/res/drawable/bouncingcow.png and /dev/null differ
diff --git a/android/project/xscreensaver/res/drawable/glhanoi.png b/android/project/xscreensaver/res/drawable/glhanoi.png
deleted file mode 100644 (file)
index 4a68dcb..0000000
Binary files a/android/project/xscreensaver/res/drawable/glhanoi.png and /dev/null differ
diff --git a/android/project/xscreensaver/res/drawable/glmatrix.png b/android/project/xscreensaver/res/drawable/glmatrix.png
deleted file mode 100644 (file)
index d3e527d..0000000
Binary files a/android/project/xscreensaver/res/drawable/glmatrix.png and /dev/null differ
diff --git a/android/project/xscreensaver/res/drawable/hilbert.png b/android/project/xscreensaver/res/drawable/hilbert.png
deleted file mode 100644 (file)
index 18f5efe..0000000
Binary files a/android/project/xscreensaver/res/drawable/hilbert.png and /dev/null differ
diff --git a/android/project/xscreensaver/res/drawable/hypertorus.png b/android/project/xscreensaver/res/drawable/hypertorus.png
deleted file mode 100644 (file)
index e2afc4c..0000000
Binary files a/android/project/xscreensaver/res/drawable/hypertorus.png and /dev/null differ
diff --git a/android/project/xscreensaver/res/drawable/sproingies.png b/android/project/xscreensaver/res/drawable/sproingies.png
deleted file mode 100644 (file)
index 0db567e..0000000
Binary files a/android/project/xscreensaver/res/drawable/sproingies.png and /dev/null differ
diff --git a/android/project/xscreensaver/res/drawable/stonerview.png b/android/project/xscreensaver/res/drawable/stonerview.png
deleted file mode 100644 (file)
index 90cd263..0000000
Binary files a/android/project/xscreensaver/res/drawable/stonerview.png and /dev/null differ
diff --git a/android/project/xscreensaver/res/drawable/superquadrics.png b/android/project/xscreensaver/res/drawable/superquadrics.png
deleted file mode 100644 (file)
index 53e6be7..0000000
Binary files a/android/project/xscreensaver/res/drawable/superquadrics.png and /dev/null differ
diff --git a/android/project/xscreensaver/res/drawable/unknownpleasures.png b/android/project/xscreensaver/res/drawable/unknownpleasures.png
deleted file mode 100644 (file)
index 41df9c1..0000000
Binary files a/android/project/xscreensaver/res/drawable/unknownpleasures.png and /dev/null differ
diff --git a/android/project/xscreensaver/res/layout/activity_xscreensaver.xml b/android/project/xscreensaver/res/layout/activity_xscreensaver.xml
new file mode 100644 (file)
index 0000000..824be40
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:padding="15dp"
+    tools:context="org.jwz.xscreensaver.XScreenSaverActivity">
+    <Button
+        android:id="@+id/apply_wallpaper"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:padding="15dp"
+        android:text="Open Daydream list"
+        android:layout_centerVertical="true"
+        android:layout_centerHorizontal="true" />
+</RelativeLayout>
index 3a5f117d3cb175d0566107e1e731d079600d9337..4361cfe8aa28395efd1cfbf9d17e48d96d614a62 100644 (file)
@@ -4,9 +4,4 @@
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     >
-<TextView  
-    android:layout_width="fill_parent" 
-    android:layout_height="wrap_content" 
-    android:text="@string/hello"
-    />
 </LinearLayout>
diff --git a/android/project/xscreensaver/res/layout/preference_blurb.xml b/android/project/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/project/xscreensaver/res/layout/slider_preference.xml b/android/project/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/project/xscreensaver/res/layout/slider_preference_dialog.xml b/android/project/xscreensaver/res/layout/slider_preference_dialog.xml
deleted file mode 100644 (file)
index 7e2eafc..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright 2012 Jay Weisskopf
-
-Licensed under the MIT License (see LICENSE.txt)
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/slider_preference_layout"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:orientation="vertical"
-    android:paddingBottom="8dip"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip"
-    android:paddingTop="8dip" >
-
-    <TextView
-        android:id="@+android:id/message"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content" />
-
-    <SeekBar
-        android:id="@+id/slider_preference_seekbar"
-        android:layout_width="fill_parent"
-        android:layout_height="wrap_content"
-        android:paddingBottom="12dip"
-        android:paddingTop="12dip" />
-
-</LinearLayout>
\ No newline at end of file
diff --git a/android/project/xscreensaver/res/values/attrs.xml b/android/project/xscreensaver/res/values/attrs.xml
deleted file mode 100644 (file)
index 9cb85bd..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright 2012 Jay Weisskopf
-
-Licensed under the MIT License (see LICENSE.txt)
--->
-<resources>
-
-    <declare-styleable name="SliderPreference">
-        <attr name="android:summary" />
-    </declare-styleable>
-
-</resources>
\ No newline at end of file
diff --git a/android/project/xscreensaver/res/values/items.xml b/android/project/xscreensaver/res/values/items.xml
deleted file mode 100644 (file)
index a4ddc4b..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <item name="bouncingcow_count_float" format="float" type="string">0</item>
-    <item name="bouncingcow_speed_float" format="float" type="string">0.487179487179487</item>
-    <item name="hypertorus_speedxy_float" format="float" type="string">0.7125</item>
-    <item name="hypertorus_speedwy_float" format="float" type="string">0.6625</item>
-    <item name="superquadrics_spinspeed_float" format="float" type="string">0.328859060402685</item>
-    <item name="hypertorus_speedxz_float" format="float" type="string">0.7375</item>
-    <item name="hypertorus_speedwz_float" format="float" type="string">0.6875</item>
-    <item name="unknownpleasures_speed_float" format="float" type="string">0.310344827586207</item>
-    <item name="hypertorus_speedwx_float" format="float" type="string">0.6375</item>
-    <item name="hypertorus_speedyz_float" format="float" type="string">0.7625</item>
-    <item name="sproingies_count_float" format="float" type="string">0.241379310344828</item>
-    <item name="glhanoi_trails_float" format="float" type="string">0.2</item>
-    <item name="glhanoi_poles_float" format="float" type="string">-0.107142857142857</item>
-    <item name="glhanoi_speed_float" format="float" type="string">0</item>
-</resources>
diff --git a/android/project/xscreensaver/res/values/settings.xml b/android/project/xscreensaver/res/values/settings.xml
deleted file mode 100644 (file)
index 2a5b276..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string-array name="sproingies_count_names">
-        <item>"One"</item>
-        <item>"Lots"</item>
-    </string-array>
-    <string-array name="sproingies_count_prefix">
-        <item>"1"</item>
-        <item>"30"</item>
-    </string-array>
-    <string-array name="sproingies_wireframe_names">
-        <item>"True"</item>
-        <item>"False"</item>
-    </string-array>
-    <string-array name="sproingies_wireframe_prefix">
-        <item>@string/t</item>
-        <item>@string/f</item>
-    </string-array>
-    <string-array name="superquadrics_spinspeed_names">
-        <item>"Slow"</item>
-        <item>"Fast"</item>
-    </string-array>
-    <string-array name="superquadrics_spinspeed_prefix">
-        <item>"0.1"</item>
-        <item>"15.0"</item>
-    </string-array>
-    <string-array name="stonerview_transparent_names">
-        <item>"True"</item>
-        <item>"False"</item>
-    </string-array>
-    <string-array name="stonerview_transparent_prefix">
-        <item>@string/t</item>
-        <item>@string/f</item>
-    </string-array>
-    <string-array name="unknownpleasures_speed_names">
-        <item>"Slow"</item>
-        <item>"Fast"</item>
-    </string-array>
-    <string-array name="unknownpleasures_speed_prefix">
-        <item>"0.1"</item>
-        <item>"3.0"</item>
-    </string-array>
-    <string-array name="unknownpleasures_wireframe_names">
-        <item>"True"</item>
-        <item>"False"</item>
-    </string-array>
-    <string-array name="unknownpleasures_wireframe_prefix">
-        <item>@string/t</item>
-        <item>@string/f</item>
-    </string-array>
-    <string-array name="bouncingcow_count_names">
-        <item>"Moo"</item>
-        <item>"Herd"</item>
-    </string-array>
-    <string-array name="bouncingcow_count_prefix">
-        <item>"1"</item>
-        <item>"9"</item>
-    </string-array>
-    <string-array name="bouncingcow_speed_names">
-        <item>"Slow"</item>
-        <item>"Fast"</item>
-    </string-array>
-    <string-array name="bouncingcow_speed_prefix">
-        <item>"0.05"</item>
-        <item>"2.0"</item>
-    </string-array>
-    <string-array name="hypertorus_speedwz_names">
-        <item>"-4.0"</item>
-        <item>"4.0"</item>
-    </string-array>
-    <string-array name="hypertorus_speedwz_prefix">
-        <item>"-4.0"</item>
-        <item>"4.0"</item>
-    </string-array>
-    <string-array name="hypertorus_displayMode_names">
-        <item>"wireframe"</item>
-        <item>"transparent"</item>
-        <item>"surface"</item>
-    </string-array>
-    <string-array name="hypertorus_displayMode_prefix">
-        <item>"wireframe"</item>
-        <item>"transparent"</item>
-        <item>"surface"</item>
-    </string-array>
-    <string-array name="hypertorus_projection4d_names">
-        <item>"orthographic"</item>
-        <item>"perspective"</item>
-    </string-array>
-    <string-array name="hypertorus_projection4d_prefix">
-        <item>"orthographic"</item>
-        <item>"perspective"</item>
-    </string-array>
-    <string-array name="hypertorus_speedwy_names">
-        <item>"-4.0"</item>
-        <item>"4.0"</item>
-    </string-array>
-    <string-array name="hypertorus_speedwy_prefix">
-        <item>"-4.0"</item>
-        <item>"4.0"</item>
-    </string-array>
-    <string-array name="hypertorus_appearance_names">
-        <item>"solid"</item>
-        <item>"spirals-1"</item>
-        <item>"spirals-2"</item>
-        <item>"spirals-4"</item>
-        <item>"spirals-8"</item>
-        <item>"spirals-16"</item>
-        <item>"bands"</item>
-    </string-array>
-    <string-array name="hypertorus_appearance_prefix">
-        <item>"solid"</item>
-        <item>"spirals-1"</item>
-        <item>"spirals-2"</item>
-        <item>"spirals-4"</item>
-        <item>"spirals-8"</item>
-        <item>"spirals-16"</item>
-        <item>"bands"</item>
-    </string-array>
-    <string-array name="hypertorus_colors_names">
-        <item>"twosided"</item>
-        <item>"colorwheel"</item>
-    </string-array>
-    <string-array name="hypertorus_colors_prefix">
-        <item>"twosided"</item>
-        <item>"colorwheel"</item>
-    </string-array>
-    <string-array name="hypertorus_speedxz_names">
-        <item>"-4.0"</item>
-        <item>"4.0"</item>
-    </string-array>
-    <string-array name="hypertorus_speedxz_prefix">
-        <item>"-4.0"</item>
-        <item>"4.0"</item>
-    </string-array>
-    <string-array name="hypertorus_speedxy_names">
-        <item>"-4.0"</item>
-        <item>"4.0"</item>
-    </string-array>
-    <string-array name="hypertorus_speedxy_prefix">
-        <item>"-4.0"</item>
-        <item>"4.0"</item>
-    </string-array>
-    <string-array name="hypertorus_projection3d_names">
-        <item>"orthographic"</item>
-        <item>"perspective"</item>
-    </string-array>
-    <string-array name="hypertorus_projection3d_prefix">
-        <item>"orthographic"</item>
-        <item>"perspective"</item>
-    </string-array>
-    <string-array name="hypertorus_speedyz_names">
-        <item>"-4.0"</item>
-        <item>"4.0"</item>
-    </string-array>
-    <string-array name="hypertorus_speedyz_prefix">
-        <item>"-4.0"</item>
-        <item>"4.0"</item>
-    </string-array>
-    <string-array name="hypertorus_speedwx_names">
-        <item>"-4.0"</item>
-        <item>"4.0"</item>
-    </string-array>
-    <string-array name="hypertorus_speedwx_prefix">
-        <item>"-4.0"</item>
-        <item>"4.0"</item>
-    </string-array>
-    <string-array name="glhanoi_fog_names">
-        <item>"True"</item>
-        <item>"False"</item>
-    </string-array>
-    <string-array name="glhanoi_fog_prefix">
-        <item>@string/t</item>
-        <item>@string/f</item>
-    </string-array>
-    <string-array name="glhanoi_trails_names">
-        <item>"0"</item>
-        <item>"10"</item>
-    </string-array>
-    <string-array name="glhanoi_trails_prefix">
-        <item>"0"</item>
-        <item>"10"</item>
-    </string-array>
-    <string-array name="glhanoi_light_names">
-        <item>"True"</item>
-        <item>"False"</item>
-    </string-array>
-    <string-array name="glhanoi_light_prefix">
-        <item>@string/t</item>
-        <item>@string/f</item>
-    </string-array>
-    <string-array name="glhanoi_poles_names">
-        <item>"0"</item>
-        <item>"31"</item>
-    </string-array>
-    <string-array name="glhanoi_poles_prefix">
-        <item>"3"</item>
-        <item>"31"</item>
-    </string-array>
-    <string-array name="glhanoi_speed_names">
-        <item>"1"</item>
-        <item>"20"</item>
-    </string-array>
-    <string-array name="glhanoi_speed_prefix">
-        <item>"1"</item>
-        <item>"20"</item>
-    </string-array>
-</resources>
diff --git a/android/project/xscreensaver/res/values/strings.xml b/android/project/xscreensaver/res/values/strings.xml
deleted file mode 100644 (file)
index b93c6d5..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string name="hello">Hello World!</string>
-    <string name="service_label">Xscreensaver</string>
-    <string name="description">A live wallpaper</string>
-
-    <string name="app_name">Xscreensaver</string>
-    <string name="author">jwz and helpers</string>
-    <string name="t">True</string>
-    <string name="f">False</string>
-    <string name="sproingies_name">Sproingies</string>
-    <string name="sproingies_settings">Settings</string>
-    <string name="sproingies_description">Sproingies</string>
-    <string name="sproingies_count_settings_title">Set count</string>
-    <string name="sproingies_count_settings_summary">Choose count</string>
-    <string name="sproingies_count_low">1</string>
-    <string name="sproingies_count_high">30</string>
-    <string name="sproingies_count_default">8</string>
-    <string name="sproingies_wireframe_settings_title">Set wireframe</string>
-    <string name="sproingies_wireframe_settings_summary">Choose wireframe</string>
-    <string name="sproingies_wireframe_default">False</string>
-    <string name="superquadrics_name">Superquadrics</string>
-    <string name="superquadrics_settings">Settings</string>
-    <string name="superquadrics_description">Superquadrics</string>
-    <string name="superquadrics_spinspeed_settings_title">Set spinspeed</string>
-    <string name="superquadrics_spinspeed_settings_summary">Choose spinspeed</string>
-    <string name="superquadrics_spinspeed_low">0.1</string>
-    <string name="superquadrics_spinspeed_high">15.0</string>
-    <string name="superquadrics_spinspeed_default">5.0</string>
-    <string name="stonerview_name">Stonerview</string>
-    <string name="stonerview_settings">Settings</string>
-    <string name="stonerview_description">Stonerview</string>
-    <string name="stonerview_transparent_settings_title">Set transparent</string>
-    <string name="stonerview_transparent_settings_summary">Choose transparent</string>
-    <string name="stonerview_transparent_default">False</string>
-    <string name="unknownpleasures_name">Unknownpleasures</string>
-    <string name="unknownpleasures_settings">Settings</string>
-    <string name="unknownpleasures_description">Unknownpleasures</string>
-    <string name="unknownpleasures_speed_settings_title">Set speed</string>
-    <string name="unknownpleasures_speed_settings_summary">Choose speed</string>
-    <string name="unknownpleasures_speed_low">0.1</string>
-    <string name="unknownpleasures_speed_high">3.0</string>
-    <string name="unknownpleasures_speed_default">3.0</string>
-    <string name="unknownpleasures_wireframe_settings_title">Set wireframe</string>
-    <string name="unknownpleasures_wireframe_settings_summary">Choose wireframe</string>
-    <string name="unknownpleasures_wireframe_default">True</string>
-    <string name="bouncingcow_name">Bouncingcow</string>
-    <string name="bouncingcow_settings">Settings</string>
-    <string name="bouncingcow_description">Bouncingcow</string>
-    <string name="bouncingcow_count_settings_title">Set count</string>
-    <string name="bouncingcow_count_settings_summary">Choose count</string>
-    <string name="bouncingcow_count_low">1</string>
-    <string name="bouncingcow_count_high">9</string>
-    <string name="bouncingcow_count_default">3</string>
-    <string name="bouncingcow_speed_settings_title">Set speed</string>
-    <string name="bouncingcow_speed_settings_summary">Choose speed</string>
-    <string name="bouncingcow_speed_low">0.05</string>
-    <string name="bouncingcow_speed_high">2.0</string>
-    <string name="bouncingcow_speed_default">0.1</string>
-    <string name="hypertorus_name">Hypertorus</string>
-    <string name="hypertorus_settings">Settings</string>
-    <string name="hypertorus_description">Hypertorus</string>
-    <string name="hypertorus_speedwz_settings_title">Set speedwz</string>
-    <string name="hypertorus_speedwz_settings_summary">Choose speedwz</string>
-    <string name="hypertorus_speedwz_low">-4.0</string>
-    <string name="hypertorus_speedwz_high">4.0</string>
-    <string name="hypertorus_speedwz_default">1.5</string>
-    <string name="hypertorus_displayMode_settings_title">Set displayMode</string>
-    <string name="hypertorus_displayMode_settings_summary">Choose displayMode</string>
-    <string name="hypertorus_displayMode_default">transparent</string>
-    <string name="hypertorus_projection4d_settings_title">Set projection4d</string>
-    <string name="hypertorus_projection4d_settings_summary">Choose projection4d</string>
-    <string name="hypertorus_projection4d_default">orthographic</string>
-    <string name="hypertorus_speedwy_settings_title">Set speedwy</string>
-    <string name="hypertorus_speedwy_settings_summary">Choose speedwy</string>
-    <string name="hypertorus_speedwy_low">-4.0</string>
-    <string name="hypertorus_speedwy_high">4.0</string>
-    <string name="hypertorus_speedwy_default">1.3</string>
-    <string name="hypertorus_appearance_settings_title">Set appearance</string>
-    <string name="hypertorus_appearance_settings_summary">Choose appearance</string>
-    <string name="hypertorus_appearance_default">spirals-16</string>
-    <string name="hypertorus_colors_settings_title">Set colors</string>
-    <string name="hypertorus_colors_settings_summary">Choose colors</string>
-    <string name="hypertorus_colors_default">twosided</string>
-    <string name="hypertorus_speedxz_settings_title">Set speedxz</string>
-    <string name="hypertorus_speedxz_settings_summary">Choose speedxz</string>
-    <string name="hypertorus_speedxz_low">-4.0</string>
-    <string name="hypertorus_speedxz_high">4.0</string>
-    <string name="hypertorus_speedxz_default">1.9</string>
-    <string name="hypertorus_speedxy_settings_title">Set speedxy</string>
-    <string name="hypertorus_speedxy_settings_summary">Choose speedxy</string>
-    <string name="hypertorus_speedxy_low">-4.0</string>
-    <string name="hypertorus_speedxy_high">4.0</string>
-    <string name="hypertorus_speedxy_default">1.7</string>
-    <string name="hypertorus_projection3d_settings_title">Set projection3d</string>
-    <string name="hypertorus_projection3d_settings_summary">Choose projection3d</string>
-    <string name="hypertorus_projection3d_default">orthographic</string>
-    <string name="hypertorus_speedyz_settings_title">Set speedyz</string>
-    <string name="hypertorus_speedyz_settings_summary">Choose speedyz</string>
-    <string name="hypertorus_speedyz_low">-4.0</string>
-    <string name="hypertorus_speedyz_high">4.0</string>
-    <string name="hypertorus_speedyz_default">2.1</string>
-    <string name="hypertorus_speedwx_settings_title">Set speedwx</string>
-    <string name="hypertorus_speedwx_settings_summary">Choose speedwx</string>
-    <string name="hypertorus_speedwx_low">-4.0</string>
-    <string name="hypertorus_speedwx_high">4.0</string>
-    <string name="hypertorus_speedwx_default">1.1</string>
-    <string name="glhanoi_name">Glhanoi</string>
-    <string name="glhanoi_settings">Settings</string>
-    <string name="glhanoi_description">Glhanoi</string>
-    <string name="glhanoi_fog_settings_title">Set fog</string>
-    <string name="glhanoi_fog_settings_summary">Choose fog</string>
-    <string name="glhanoi_fog_default">True</string>
-    <string name="glhanoi_trails_settings_title">Set trails</string>
-    <string name="glhanoi_trails_settings_summary">Choose trails</string>
-    <string name="glhanoi_trails_low">0</string>
-    <string name="glhanoi_trails_high">10</string>
-    <string name="glhanoi_trails_default">2</string>
-    <string name="glhanoi_light_settings_title">Set light</string>
-    <string name="glhanoi_light_settings_summary">Choose light</string>
-    <string name="glhanoi_light_default">False</string>
-    <string name="glhanoi_poles_settings_title">Set poles</string>
-    <string name="glhanoi_poles_settings_summary">Choose poles</string>
-    <string name="glhanoi_poles_low">3</string>
-    <string name="glhanoi_poles_high">31</string>
-    <string name="glhanoi_poles_default">0</string>
-    <string name="glhanoi_speed_settings_title">Set speed</string>
-    <string name="glhanoi_speed_settings_summary">Choose speed</string>
-    <string name="glhanoi_speed_low">1</string>
-    <string name="glhanoi_speed_high">20</string>
-    <string name="glhanoi_speed_default">1</string>
-</resources>
diff --git a/android/project/xscreensaver/res/xml/bouncingcow.xml b/android/project/xscreensaver/res/xml/bouncingcow.xml
deleted file mode 100644 (file)
index e531543..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
-   android:description="@string/bouncingcow_description"
-   android:settingsActivity="org.jwz.xscreensaver.gen.BouncingcowSettings"
-   android:thumbnail="@drawable/bouncingcow" />
diff --git a/android/project/xscreensaver/res/xml/bouncingcow_settings.xml b/android/project/xscreensaver/res/xml/bouncingcow_settings.xml
deleted file mode 100644 (file)
index eb2cdb5..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
-    <PreferenceCategory
-        android:title="@string/bouncingcow_settings"
-        android:key="bouncingcowwallpaper_settings">
-    <org.jwz.xscreensaver.SliderPreference
-        android:defaultValue="@string/bouncingcow_count_float"
-        android:dialogMessage="@string/bouncingcow_count_settings_summary"
-        android:key="bouncingcow_count"
-        android:summary="@array/bouncingcow_count_prefix"
-        android:title="@string/bouncingcow_count_settings_title" />
-    <org.jwz.xscreensaver.SliderPreference
-        android:defaultValue="@string/bouncingcow_speed_float"
-        android:dialogMessage="@string/bouncingcow_speed_settings_summary"
-        android:key="bouncingcow_speed"
-        android:summary="@array/bouncingcow_speed_prefix"
-        android:title="@string/bouncingcow_speed_settings_title" />
-    </PreferenceCategory>
-</PreferenceScreen>
diff --git a/android/project/xscreensaver/res/xml/glhanoi.xml b/android/project/xscreensaver/res/xml/glhanoi.xml
deleted file mode 100644 (file)
index 0c3ac16..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
-   android:description="@string/glhanoi_description"
-   android:settingsActivity="org.jwz.xscreensaver.gen.GlhanoiSettings"
-   android:thumbnail="@drawable/glhanoi" />
diff --git a/android/project/xscreensaver/res/xml/glhanoi_settings.xml b/android/project/xscreensaver/res/xml/glhanoi_settings.xml
deleted file mode 100644 (file)
index 2c103f4..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
-    <PreferenceCategory
-        android:title="@string/glhanoi_settings"
-        android:key="glhanoiwallpaper_settings">
-    <ListPreference
-            android:key="glhanoi_fog"
-            android:title="@string/glhanoi_fog_settings_title"
-            android:summary="@string/glhanoi_fog_settings_summary"
-            android:entries="@array/glhanoi_fog_names"
-            android:defaultValue="@string/glhanoi_fog_default"
-            android:entryValues="@array/glhanoi_fog_prefix" />
-    <org.jwz.xscreensaver.SliderPreference
-        android:defaultValue="@string/glhanoi_trails_float"
-        android:dialogMessage="@string/glhanoi_trails_settings_summary"
-        android:key="glhanoi_trails"
-        android:summary="@array/glhanoi_trails_prefix"
-        android:title="@string/glhanoi_trails_settings_title" />
-    <ListPreference
-            android:key="glhanoi_light"
-            android:title="@string/glhanoi_light_settings_title"
-            android:summary="@string/glhanoi_light_settings_summary"
-            android:entries="@array/glhanoi_light_names"
-            android:defaultValue="@string/glhanoi_light_default"
-            android:entryValues="@array/glhanoi_light_prefix" />
-    <org.jwz.xscreensaver.SliderPreference
-        android:defaultValue="@string/glhanoi_poles_float"
-        android:dialogMessage="@string/glhanoi_poles_settings_summary"
-        android:key="glhanoi_poles"
-        android:summary="@array/glhanoi_poles_prefix"
-        android:title="@string/glhanoi_poles_settings_title" />
-    <org.jwz.xscreensaver.SliderPreference
-        android:defaultValue="@string/glhanoi_speed_float"
-        android:dialogMessage="@string/glhanoi_speed_settings_summary"
-        android:key="glhanoi_speed"
-        android:summary="@array/glhanoi_speed_prefix"
-        android:title="@string/glhanoi_speed_settings_title" />
-    </PreferenceCategory>
-</PreferenceScreen>
diff --git a/android/project/xscreensaver/res/xml/hypertorus.xml b/android/project/xscreensaver/res/xml/hypertorus.xml
deleted file mode 100644 (file)
index d3b8b8e..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
-   android:description="@string/hypertorus_description"
-   android:settingsActivity="org.jwz.xscreensaver.gen.HypertorusSettings"
-   android:thumbnail="@drawable/hypertorus" />
diff --git a/android/project/xscreensaver/res/xml/hypertorus_settings.xml b/android/project/xscreensaver/res/xml/hypertorus_settings.xml
deleted file mode 100644 (file)
index c1e98c5..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
-    <PreferenceCategory
-        android:title="@string/hypertorus_settings"
-        android:key="hypertoruswallpaper_settings">
-    <org.jwz.xscreensaver.SliderPreference
-        android:defaultValue="@string/hypertorus_speedwz_float"
-        android:dialogMessage="@string/hypertorus_speedwz_settings_summary"
-        android:key="hypertorus_speedwz"
-        android:summary="@array/hypertorus_speedwz_prefix"
-        android:title="@string/hypertorus_speedwz_settings_title" />
-    <ListPreference
-            android:key="hypertorus_displayMode"
-            android:title="@string/hypertorus_displayMode_settings_title"
-            android:summary="@string/hypertorus_displayMode_settings_summary"
-            android:entries="@array/hypertorus_displayMode_names"
-            android:defaultValue="@string/hypertorus_displayMode_default"
-            android:entryValues="@array/hypertorus_displayMode_prefix" />
-    <ListPreference
-            android:key="hypertorus_projection4d"
-            android:title="@string/hypertorus_projection4d_settings_title"
-            android:summary="@string/hypertorus_projection4d_settings_summary"
-            android:entries="@array/hypertorus_projection4d_names"
-            android:defaultValue="@string/hypertorus_projection4d_default"
-            android:entryValues="@array/hypertorus_projection4d_prefix" />
-    <org.jwz.xscreensaver.SliderPreference
-        android:defaultValue="@string/hypertorus_speedwy_float"
-        android:dialogMessage="@string/hypertorus_speedwy_settings_summary"
-        android:key="hypertorus_speedwy"
-        android:summary="@array/hypertorus_speedwy_prefix"
-        android:title="@string/hypertorus_speedwy_settings_title" />
-    <ListPreference
-            android:key="hypertorus_appearance"
-            android:title="@string/hypertorus_appearance_settings_title"
-            android:summary="@string/hypertorus_appearance_settings_summary"
-            android:entries="@array/hypertorus_appearance_names"
-            android:defaultValue="@string/hypertorus_appearance_default"
-            android:entryValues="@array/hypertorus_appearance_prefix" />
-    <ListPreference
-            android:key="hypertorus_colors"
-            android:title="@string/hypertorus_colors_settings_title"
-            android:summary="@string/hypertorus_colors_settings_summary"
-            android:entries="@array/hypertorus_colors_names"
-            android:defaultValue="@string/hypertorus_colors_default"
-            android:entryValues="@array/hypertorus_colors_prefix" />
-    <org.jwz.xscreensaver.SliderPreference
-        android:defaultValue="@string/hypertorus_speedxz_float"
-        android:dialogMessage="@string/hypertorus_speedxz_settings_summary"
-        android:key="hypertorus_speedxz"
-        android:summary="@array/hypertorus_speedxz_prefix"
-        android:title="@string/hypertorus_speedxz_settings_title" />
-    <org.jwz.xscreensaver.SliderPreference
-        android:defaultValue="@string/hypertorus_speedxy_float"
-        android:dialogMessage="@string/hypertorus_speedxy_settings_summary"
-        android:key="hypertorus_speedxy"
-        android:summary="@array/hypertorus_speedxy_prefix"
-        android:title="@string/hypertorus_speedxy_settings_title" />
-    <ListPreference
-            android:key="hypertorus_projection3d"
-            android:title="@string/hypertorus_projection3d_settings_title"
-            android:summary="@string/hypertorus_projection3d_settings_summary"
-            android:entries="@array/hypertorus_projection3d_names"
-            android:defaultValue="@string/hypertorus_projection3d_default"
-            android:entryValues="@array/hypertorus_projection3d_prefix" />
-    <org.jwz.xscreensaver.SliderPreference
-        android:defaultValue="@string/hypertorus_speedyz_float"
-        android:dialogMessage="@string/hypertorus_speedyz_settings_summary"
-        android:key="hypertorus_speedyz"
-        android:summary="@array/hypertorus_speedyz_prefix"
-        android:title="@string/hypertorus_speedyz_settings_title" />
-    <org.jwz.xscreensaver.SliderPreference
-        android:defaultValue="@string/hypertorus_speedwx_float"
-        android:dialogMessage="@string/hypertorus_speedwx_settings_summary"
-        android:key="hypertorus_speedwx"
-        android:summary="@array/hypertorus_speedwx_prefix"
-        android:title="@string/hypertorus_speedwx_settings_title" />
-    </PreferenceCategory>
-</PreferenceScreen>
diff --git a/android/project/xscreensaver/res/xml/sproingies.xml b/android/project/xscreensaver/res/xml/sproingies.xml
deleted file mode 100644 (file)
index 35bfc8e..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
-   android:description="@string/sproingies_description"
-   android:settingsActivity="org.jwz.xscreensaver.gen.SproingiesSettings"
-   android:thumbnail="@drawable/sproingies" />
diff --git a/android/project/xscreensaver/res/xml/sproingies_settings.xml b/android/project/xscreensaver/res/xml/sproingies_settings.xml
deleted file mode 100644 (file)
index 9181949..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
-    <PreferenceCategory
-        android:title="@string/sproingies_settings"
-        android:key="sproingieswallpaper_settings">
-    <org.jwz.xscreensaver.SliderPreference
-        android:defaultValue="@string/sproingies_count_float"
-        android:dialogMessage="@string/sproingies_count_settings_summary"
-        android:key="sproingies_count"
-        android:summary="@array/sproingies_count_prefix"
-        android:title="@string/sproingies_count_settings_title" />
-    <ListPreference
-            android:key="sproingies_wireframe"
-            android:title="@string/sproingies_wireframe_settings_title"
-            android:summary="@string/sproingies_wireframe_settings_summary"
-            android:entries="@array/sproingies_wireframe_names"
-            android:defaultValue="@string/sproingies_wireframe_default"
-            android:entryValues="@array/sproingies_wireframe_prefix" />
-    </PreferenceCategory>
-</PreferenceScreen>
diff --git a/android/project/xscreensaver/res/xml/stonerview.xml b/android/project/xscreensaver/res/xml/stonerview.xml
deleted file mode 100644 (file)
index 693cab8..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
-   android:description="@string/stonerview_description"
-   android:settingsActivity="org.jwz.xscreensaver.gen.StonerviewSettings"
-   android:thumbnail="@drawable/stonerview" />
diff --git a/android/project/xscreensaver/res/xml/stonerview_settings.xml b/android/project/xscreensaver/res/xml/stonerview_settings.xml
deleted file mode 100644 (file)
index e7d25ee..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
-    <PreferenceCategory
-        android:title="@string/stonerview_settings"
-        android:key="stonerviewwallpaper_settings">
-    <ListPreference
-            android:key="stonerview_transparent"
-            android:title="@string/stonerview_transparent_settings_title"
-            android:summary="@string/stonerview_transparent_settings_summary"
-            android:entries="@array/stonerview_transparent_names"
-            android:defaultValue="@string/stonerview_transparent_default"
-            android:entryValues="@array/stonerview_transparent_prefix" />
-    </PreferenceCategory>
-</PreferenceScreen>
diff --git a/android/project/xscreensaver/res/xml/superquadrics.xml b/android/project/xscreensaver/res/xml/superquadrics.xml
deleted file mode 100644 (file)
index 59c891b..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
-   android:description="@string/superquadrics_description"
-   android:settingsActivity="org.jwz.xscreensaver.gen.SuperquadricsSettings"
-   android:thumbnail="@drawable/superquadrics" />
diff --git a/android/project/xscreensaver/res/xml/superquadrics_settings.xml b/android/project/xscreensaver/res/xml/superquadrics_settings.xml
deleted file mode 100644 (file)
index b2da332..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
-    <PreferenceCategory
-        android:title="@string/superquadrics_settings"
-        android:key="superquadricswallpaper_settings">
-    <org.jwz.xscreensaver.SliderPreference
-        android:defaultValue="@string/superquadrics_spinspeed_float"
-        android:dialogMessage="@string/superquadrics_spinspeed_settings_summary"
-        android:key="superquadrics_spinspeed"
-        android:summary="@array/superquadrics_spinspeed_prefix"
-        android:title="@string/superquadrics_spinspeed_settings_title" />
-    </PreferenceCategory>
-</PreferenceScreen>
diff --git a/android/project/xscreensaver/res/xml/unknownpleasures.xml b/android/project/xscreensaver/res/xml/unknownpleasures.xml
deleted file mode 100644 (file)
index b3f091c..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
-   android:description="@string/unknownpleasures_description"
-   android:settingsActivity="org.jwz.xscreensaver.gen.UnknownpleasuresSettings"
-   android:thumbnail="@drawable/unknownpleasures" />
diff --git a/android/project/xscreensaver/res/xml/unknownpleasures_settings.xml b/android/project/xscreensaver/res/xml/unknownpleasures_settings.xml
deleted file mode 100644 (file)
index 72e8bb8..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
-    <PreferenceCategory
-        android:title="@string/unknownpleasures_settings"
-        android:key="unknownpleasureswallpaper_settings">
-    <org.jwz.xscreensaver.SliderPreference
-        android:defaultValue="@string/unknownpleasures_speed_float"
-        android:dialogMessage="@string/unknownpleasures_speed_settings_summary"
-        android:key="unknownpleasures_speed"
-        android:summary="@array/unknownpleasures_speed_prefix"
-        android:title="@string/unknownpleasures_speed_settings_title" />
-    <ListPreference
-            android:key="unknownpleasures_wireframe"
-            android:title="@string/unknownpleasures_wireframe_settings_title"
-            android:summary="@string/unknownpleasures_wireframe_settings_summary"
-            android:entries="@array/unknownpleasures_wireframe_names"
-            android:defaultValue="@string/unknownpleasures_wireframe_default"
-            android:entryValues="@array/unknownpleasures_wireframe_prefix" />
-    </PreferenceCategory>
-</PreferenceScreen>
diff --git a/android/project/xscreensaver/src/org/jwz/xscreensaver/ARenderer.java b/android/project/xscreensaver/src/org/jwz/xscreensaver/ARenderer.java
deleted file mode 100644 (file)
index fd65be1..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-package org.jwz.xscreensaver;
-
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.opengles.GL10;
-
-import net.rbgrn.android.glwallpaperservice.*;
-import android.opengl.GLU;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-
-
-// Original code provided by Robert Green
-// http://www.rbgrn.net/content/354-glsurfaceview-adapted-3d-live-wallpapers
-public class ARenderer implements GLWallpaperService.Renderer {
-
-    CallNative cn;
-    boolean secondRun = false;
-
-    // Used for Lighting
-    //private static float[] ambientComponent0 = {0.3f, 0.3f, 1.0f, 1.0f};
-    //private static float[] ambientComponent0 = {0.3f, 0.3f, 0.3f, 1.0f};
-    private static float[] ambientComponent0 = {0.5f, 0.5f, 0.5f, 1.0f};
-    private static float[] diffuseComponent0 = {1.0f, 1.0f, 1.0f, 1.0f};
-    private static float[] lightPosition0 =    {1f, 1f, -1f, 0f};
-
-    public void onDrawFrame(GL10 gl) {
-        if (!secondRun) {
-            secondRun = true;
-            return;
-        }
-        //gl.glClearColor(0.2f, 0.6f, 0.2f, 1f);
-        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
-    }
-
-    public void onSurfaceChanged(GL10 gl, int width, int height) {
-
-        gl.glMatrixMode(GL10.GL_PROJECTION);
-        gl.glLoadIdentity();
-        GLU.gluPerspective(gl, 60f, (float)width/(float)height, 1f, 100f);
-
-        gl.glMatrixMode(GL10.GL_MODELVIEW);
-        gl.glLoadIdentity();
-
-        gl.glMatrixMode(GL10.GL_MODELVIEW);
-        gl.glTranslatef(0, 0, -5);
-        gl.glRotatef(30f, 1, 0, 0);
-
-        gl.glEnable(GL10.GL_LIGHTING);
-        gl.glEnable(GL10.GL_RESCALE_NORMAL);
-        gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
-//Set the color of light bouncing off of surfaces to respect the surface color
-        gl.glEnable(GL10.GL_COLOR_MATERIAL);
-
-        setupLightSources(gl);
-
-// Turn on a global ambient light. The "Cosmic Background Radiation", if you will.
-        //float[] ambientLightRGB = {0.3f, 0.3f, 0.3f, 1.0f};
-        float[] ambientLightRGB = {0.5f, 0.5f, 0.5f, 1.0f};
-        gl.glLightModelfv(GL10.GL_LIGHT_MODEL_AMBIENT, ambientLightRGB, 0);
-        NonSurfaceChanged(width, height);
-    }
-
-    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
-
-        if (!secondRun) {
-            return;
-        }
-        cn = new CallNative();
-
-        gl.glClearDepthf(1f);
-        gl.glEnable(GL10.GL_DEPTH_TEST);
-        gl.glDepthFunc(GL10.GL_LEQUAL);
-
-//Turn on culling, so OpenGL only draws one side of the primitives
-        gl.glEnable(GL10.GL_CULL_FACE);
-//Define the front of a primitive to be the side where the listed vertexes are counterclockwise
-        gl.glFrontFace(GL10.GL_CCW);
-//Do not draw the backs of primitives
-        gl.glCullFace(GL10.GL_BACK);
-
-    }
-
-    private void setupLightSources(GL10 gl) {
-        if (!secondRun) {
-            return;
-        }
-        //Enable Light source 0
-        gl.glEnable(GL10.GL_LIGHT0);
-
-        //Useful part of the Arrays start a 0
-        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, ambientComponent0, 0);
-        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, diffuseComponent0, 0);
-
-        //Position the light in the scene
-        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPosition0, 0);
-    }
-
-    /**
-     * Called when the engine is destroyed. Do any necessary clean up because
-     * at this point your renderer instance is now done for.
-     */
-    public void release() {
-        NonDone();
-
-    }
-
-    public void NonSurfaceCreated() {
-        cn.nativeInit();
-    }
-
-    void NonSurfaceChanged(int w, int h) {
-        if (!secondRun) {
-            return;
-        }
-        cn.nativeResize(w, h);
-    }
-
-    void NonDrawFrame() {
-        cn.nativeRender();
-    }
-
-    void NonDone() {
-        cn.nativeDone();
-    }
-
-    static
-    {
-        System.loadLibrary ("xscreensaver");
-    }
-
-}
diff --git a/android/project/xscreensaver/src/org/jwz/xscreensaver/BufferFactory.java b/android/project/xscreensaver/src/org/jwz/xscreensaver/BufferFactory.java
deleted file mode 100644 (file)
index 228928f..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-package org.jwz.xscreensaver;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.FloatBuffer;
-import java.nio.ShortBuffer;
-
-/**
- * A utility class to create buffers.
- *
- * All public methods are static. The Singleton pattern was avoided to avoid concerns about
- * threading and the Android life cycle. If needed, It can be implemented later given some research.
- */
-public class BufferFactory {
-    // This class cannot and should not be instantiated
-    private BufferFactory() {}
-
-    // We use Buffer.allocateDirect() to get memory outside of
-    // the normal, garbage collected heap. I think this is done
-    // because the buffer is subject to native I/O.
-    // See http://download.oracle.com/javase/1.4.2/docs/api/java/nio/ByteBuffer.html#direct
-
-    /**
-     * Creates a buffer of floats using memory outside the normal, garbage collected heap
-     *
-     * @param capacity         The number of primitives to create in the buffer.
-     */
-    public static FloatBuffer createFloatBuffer(int capacity) {
-        // 4 is the number of bytes in a float
-        ByteBuffer vbb = ByteBuffer.allocateDirect(capacity * 4);
-        vbb.order(ByteOrder.nativeOrder());
-        return vbb.asFloatBuffer();
-    }
-
-    /**
-     * Creates a buffer of shorts using memory outside the normal, garbage collected heap
-     *
-     * @param capacity         The number of primitives to create in the buffer.
-     */
-    public static ShortBuffer createShortBuffer(int capacity) {
-        // 2 is the number of bytes in a short
-        ByteBuffer vbb = ByteBuffer.allocateDirect(capacity * 2);
-        vbb.order(ByteOrder.nativeOrder());
-        return vbb.asShortBuffer();
-    }
-}
diff --git a/android/project/xscreensaver/src/org/jwz/xscreensaver/CallNative.java b/android/project/xscreensaver/src/org/jwz/xscreensaver/CallNative.java
deleted file mode 100644 (file)
index be8c66d..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.jwz.xscreensaver;
-
-public class CallNative {
-
-    void onSurfaceCreated() {
-        nativeInit();
-    }
-
-    void onSurfaceChanged(int w, int h) {
-        nativeResize(w, h);
-    }
-
-    void onDrawFrame() {
-        nativeRender();
-    }
-
-    void onDone() {
-        nativeDone();
-    }
-
-    public static native void nativeInit();
-    public static native void nativeResize(int w, int h);
-    public static native void nativeRender();
-    public static native void nativeDone();
-}
index 8a772637a24ebbcf224ba11038a92680e461ab08..c1a1a1de15a59eb00b0a1c96081420a8d658b170 100644 (file)
-/*
- * Copyright 2012 Jay Weisskopf
+/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * xscreensaver, Copyright (c) 2016 Jamie Zawinski <jwz@jwz.org>
  *
- * Licensed under the MIT License (see LICENSE.txt)
+ * 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 net.jayschwa.android.preference;
 package org.jwz.xscreensaver;
 
-
 import android.content.Context;
 import android.content.res.TypedArray;
-import android.preference.DialogPreference;
+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;
 
-/**
- * @author Jay Weisskopf
- */
-public class SliderPreference extends DialogPreference {
-
-       protected final static int SEEKBAR_RESOLUTION = 10000;
-
-       protected float mValue;
-       protected int mSeekBarValue;
-       protected CharSequence[] mSummaries;
-
-       /**
-        * @param context
-        * @param attrs
-        */
-       public SliderPreference(Context context, AttributeSet attrs) {
-               super(context, attrs);
-               setup(context, attrs);
-       }
-
-       /**
-        * @param context
-        * @param attrs
-        * @param defStyle
-        */
-       public SliderPreference(Context context, AttributeSet attrs, int defStyle) {
-               super(context, attrs, defStyle);
-               setup(context, attrs);
-       }
-
-       private void setup(Context context, AttributeSet attrs) {
-               setDialogLayoutResource(R.layout.slider_preference_dialog);
-               TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SliderPreference);
-               try {
-                       setSummary(a.getTextArray(R.styleable.SliderPreference_android_summary));
-               } catch (Exception e) {
-                       // Do nothing
-               }
-               a.recycle();
-       }
-
-       @Override
-       protected Object onGetDefaultValue(TypedArray a, int index) {
-               return a.getFloat(index, 0);
-       }
-
-       @Override
-       protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
-               setValue(restoreValue ? getPersistedFloat(mValue) : (Float) defaultValue);
-       }
-
-       @Override
-       public CharSequence getSummary() {
-               if (mSummaries != null && mSummaries.length > 0) {
-                       int index = (int) (mValue * mSummaries.length);
-                       index = Math.min(index, mSummaries.length - 1);
-                       return mSummaries[index];
-               } else {
-                       return super.getSummary();
-               }
-       }
-
-       public void setSummary(CharSequence[] summaries) {
-               mSummaries = summaries;
-       }
-
-       @Override
-       public void setSummary(CharSequence summary) {
-               super.setSummary(summary);
-               mSummaries = null;
-       }
-
-       @Override
-       public void setSummary(int summaryResId) {
-               try {
-                       setSummary(getContext().getResources().getStringArray(summaryResId));
-               } catch (Exception e) {
-                       super.setSummary(summaryResId);
-               }
-       }
-
-       public float getValue() {
-               return mValue;
-       }
-
-       public void setValue(float value) {
-               value = Math.max(0, Math.min(value, 1)); // clamp to [0, 1]
-               if (shouldPersist()) {
-                       persistFloat(value);
-               }
-               if (value != mValue) {
-                       mValue = value;
-                       notifyChanged();
-               }
-       }
-
-       @Override
-       protected View onCreateDialogView() {
-               mSeekBarValue = (int) (mValue * SEEKBAR_RESOLUTION);
-               View view = super.onCreateDialogView();
-               SeekBar seekbar = (SeekBar) view.findViewById(R.id.slider_preference_seekbar);
-               seekbar.setMax(SEEKBAR_RESOLUTION);
-               seekbar.setProgress(mSeekBarValue);
-               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) {
-                                       SliderPreference.this.mSeekBarValue = progress;
-                               }
-                       }
-               });
-               return view;
-       }
-
-       @Override
-       protected void onDialogClosed(boolean positiveResult) {
-               final float newValue = (float) mSeekBarValue / SEEKBAR_RESOLUTION;
-               if (positiveResult && callChangeListener(newValue)) {
-                       setValue(newValue);
-               }
-               super.onDialogClosed(positiveResult);
-       }
-
-       // TODO: Save and restore preference state.
+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
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/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverActivity.java b/android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverActivity.java
new file mode 100644 (file)
index 0000000..a82727c
--- /dev/null
@@ -0,0 +1,57 @@
+/* -*- 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 {
+
+  @Override
+  protected void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    openList();
+    setContentView(R.layout.activity_xscreensaver);
+
+    findViewById(R.id.apply_wallpaper)
+      .setOnClickListener(new View.OnClickListener() {
+          @Override
+          public void onClick(View v) {
+              openList();
+          }
+      });
+
+  }
+
+  private void openList() {
+    Intent intent;
+    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+        intent = new Intent(Settings.ACTION_DREAM_SETTINGS);
+    } else {
+        intent = new Intent(Settings.ACTION_DISPLAY_SETTINGS);
+    }
+    startActivity(intent);
+  }
+
+}
diff --git a/android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverApp.java b/android/project/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/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverDaydream.java b/android/project/xscreensaver/src/org/jwz/xscreensaver/XScreenSaverDaydream.java
new file mode 100644 (file)
index 0000000..ea04df0
--- /dev/null
@@ -0,0 +1,289 @@
+/* -*- 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;
+  private int api;
+  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 (int api) {
+    super();
+    this.api = api;
+  }
+
+  // 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();
+
+    // Extract the saver name from e.g. "BouncingCowDaydream"
+    String name = this.getClass().getSimpleName();
+    String tail = "Daydream";
+    if (name.endsWith(tail))
+      name = name.substring (0, name.length() - tail.length());
+    name = name.toLowerCase();
+
+    WindowManager wm = (WindowManager) getSystemService (WINDOW_SERVICE);
+    renderer =
+      new XScreenSaverRenderer (name, api, getApplicationContext(), wm,
+                                screenshot, this);
+
+    glview = new GLSurfaceView (this);
+    glview.setRenderer (renderer);
+    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
new file mode 100644 (file)
index 0000000..9889ea8
--- /dev/null
@@ -0,0 +1,166 @@
+/* -*- 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 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;
+  int api;
+  Handler.Callback abort_callback;
+
+  Iterable<Map.Entry<String, String>> prefs;
+  Context app;
+  WindowManager wm;
+  Bitmap screenshot;
+
+  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, int api,
+                               Context app, WindowManager wm,
+                               Bitmap screenshot,
+                               Handler.Callback abort_callback) {
+    super();
+    this.hack   = hack;
+    this.api    = api;
+    this.app    = app;
+    this.wm     = wm;
+    this.prefs  = prefs;
+    this.screenshot = screenshot;
+    this.abort_callback = abort_callback;
+    LOG ("init %s %d", hack, api);
+  }
+
+  public void onDrawFrame (GL10 gl) {
+    try {
+      if (jwxyz_obj != null)
+        jwxyz_obj.nativeRender();
+    } catch (RuntimeException e) {
+      except (e);
+    }
+  }
+
+  public void onSurfaceChanged(GL10 gl, int w, int h) {
+    try {
+      if (jwxyz_obj == null)
+        jwxyz_obj = new jwxyz (hack, api, app, screenshot, w, h);
+
+      double r;
+
+      Display d = wm.getDefaultDisplay();
+
+      switch (d.getRotation()) {
+      case Surface.ROTATION_90:  r = 90;  break;
+      case Surface.ROTATION_180: r = 180; break;
+      case Surface.ROTATION_270: r = 270; break;
+      default: r = 0; break;
+      }
+
+      jwxyz_obj.nativeResize (w, h, r);
+
+    } 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
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/project/xscreensaver/src/org/jwz/xscreensaver/XscreensaverApp.java b/android/project/xscreensaver/src/org/jwz/xscreensaver/XscreensaverApp.java
deleted file mode 100644 (file)
index 609ef32..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.jwz.xscreensaver;
-
-import android.app.Application;
-import android.content.SharedPreferences;
-
-public class XscreensaverApp extends Application {
-
-    public XscreensaverApp() {
-        super();
-    }
-
-
-    public SharedPreferences getThePrefs(String p) {
-        SharedPreferences prefs = getApplicationContext().getSharedPreferences(p, 0);
-        return prefs;
-    }
-
-}
diff --git a/android/project/xscreensaver/src/org/jwz/xscreensaver/jwxyz.java b/android/project/xscreensaver/src/org/jwz/xscreensaver/jwxyz.java
new file mode 100644 (file)
index 0000000..a83e8cf
--- /dev/null
@@ -0,0 +1,824 @@
+/* -*- 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 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;
+  public final static int API_XLIB = 0;
+  public final static int API_GL   = 1;
+  Bitmap screenshot;
+
+  SharedPreferences prefs;
+  Hashtable<String, String> defaults = new Hashtable<String, String>();
+
+  // Maps numeric IDs to Java objects, so that C code can reference them
+  // even if GC relocates them.
+  private Hashtable<Long, Object> rootset = new Hashtable<Long, Object>();
+  private long rootset_id = 1000;
+
+
+  // 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, int api,
+                                  Hashtable<String,String> defaults,
+                                  int w, int h);
+  public native void nativeResize (int w, int h, double rot);
+  public native void 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, int api, 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, api, 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 X Logical Font Descriptions, and a few standard X font names.
+  // Returns [ String name, Float size, Typeface ]
+  private Object[] parseXLFD (String name) {
+    float   size   = 12;
+    boolean bold   = false;
+    boolean italic = false;
+    boolean fixed  = false;
+    boolean serif  = false;
+
+    if      (name.equals("6x10"))     { size = 8;  fixed = true; }
+    else if (name.equals("6x10bold")) { size = 8;  fixed = true; bold = true; }
+    else if (name.equals("fixed"))    { size = 12; fixed = true; }
+    else if (name.equals("9x15"))     { size = 12; fixed = true; }
+    else if (name.equals("9x15bold")) { size = 12; fixed = true; bold = true; }
+    else if (name.equals("vga"))      { size = 12; fixed = true; }
+    else if (name.equals("console"))  { size = 12; fixed = true; }
+    else if (name.equals("gallant"))  { size = 12; fixed = true; }
+    else {
+      String[] tokens = name.split("-");       // XLFD
+      int L = tokens.length;
+      int i = 1;
+      String foundry  = (i < L ? tokens[i++] : "");
+      String family   = (i < L ? tokens[i++] : "");
+      String weight   = (i < L ? tokens[i++] : "");
+      String slant    = (i < L ? tokens[i++] : "");
+      String setwidth = (i < L ? tokens[i++] : "");
+      String adstyle  = (i < L ? tokens[i++] : "");
+      String pxsize   = (i < L ? tokens[i++] : "");
+      String ptsize   = (i < L ? tokens[i++] : "");
+      String resx     = (i < L ? tokens[i++] : "");
+      String resy     = (i < L ? tokens[i++] : "");
+      String spacing  = (i < L ? tokens[i++] : "");
+      String avgw     = (i < L ? tokens[i++] : "");
+      String charset  = (i < L ? tokens[i++] : "");
+      String registry = (i < L ? tokens[i++] : "");
+
+      if (spacing.equals("m") ||
+          family.equals("fixed") ||
+          family.equals("courier") ||
+          family.equals("console") ||
+          family.equals("lucidatypewriter")) {
+        fixed = true;
+      } else if (family.equals("times") ||
+                 family.equals("georgia")) {
+        serif = true;
+      }
+
+      if (weight.equals("bold") || weight.equals("demibold")) {
+        bold = true; 
+      }
+
+      if (slant.equals("i") || slant.equals("o")) {
+        italic = true;
+      }
+
+      // -*-courier-bold-r-*-*-14-*-*-*-*-*-*-*                14 px
+      // -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*       14 pt
+      // -*-courier-bold-r-*-*-140-*                   14 pt, via wildcard
+      // -*-courier-bold-r-*-140-*                     14 pt, not handled
+      // -*-courier-bold-r-*-*-14-180-*-*-*-*-*-*      error
+
+      if (!ptsize.equals("") && !ptsize.equals("*")) {
+        // It was in the ptsize field, so that's definitely what it is.
+        size = Float.valueOf(ptsize) / 10.0f;
+      } else if (!pxsize.equals("") && !pxsize.equals("*")) {
+        size = Float.valueOf(pxsize);
+        // If it's a fully qualified XLFD, then this really is the pxsize.
+        // Otherwise, this is probably point size with a multi-field wildcard.
+        if (registry.equals(""))   // not a fully qualified XLFD
+          size /= 10.0f;
+      }
+    }
+
+    if (name.equals("random")) {
+      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"));
+
+    Typeface font = Typeface.create (name,
+                                     (bold && italic ? Typeface.BOLD_ITALIC :
+                                      bold   ? Typeface.BOLD :
+                                      italic ? Typeface.ITALIC :
+                                      Typeface.NORMAL));
+
+    Object ret[] = { name, new Float(size), font };
+    return ret;
+  }
+
+
+  // Parses "Native Font Name One 12, Native Font Name Two 14".
+  // Returns [ String name, Float size, Typeface ]
+  private Object[] parseNativeFont (String names) {
+    for (String name : names.split(",")) {
+      float size = 0;
+      name = name.trim();
+      if (name.equals("")) continue;
+      int spc = name.lastIndexOf(" ");
+      if (spc > 0) {
+        size = Float.valueOf (name.substring (spc + 1));
+        name = name.substring (0, spc);
+      }
+      if (size <= 0)
+        size = 12;
+
+      Object font = all_fonts.get (name);
+      if (font instanceof String)
+        font = Typeface.create (name, Typeface.NORMAL);
+
+      if (font != null) {
+        Object ret[] = { name, size, (Typeface) font };
+        return ret;
+      }
+    }
+
+    return null;
+  }
+
+
+  // Returns [ Long font_id, String name, Float size, ascent, descent ]
+  public Object[] loadFont(String name) {
+    Object pair[];
+
+    if (name.equals("")) return null;
+
+    if (name.contains(" ")) {
+      pair = parseNativeFont (name);
+    } else {
+      pair = parseXLFD (name);
+    }
+
+    if (pair == null) return null;
+
+    String name2  = (String)   pair[0];
+    float size    = (Float)    pair[1];
+    Typeface font = (Typeface) pair[2];
+
+    size *= 2;
+
+    name2 += (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));
+
+    Long font_key = new Long(rootset_id++);
+    rootset.put (font_key, paint);
+
+    LOG ("load font %s, \"%s\" = \"%s %.1f\"",
+         font_key.toString(), name, name2, size);
+
+    FontMetrics fm = paint.getFontMetrics();
+    Object ret[] = { font_key, name2, new Float(size),
+                     new Float(-fm.ascent), new Float(fm.descent) };
+    return ret;
+  }
+
+
+  public void releaseFont(long font_id) {
+    rootset.remove (new Long(font_id));
+  }
+
+  /* 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 (long font_id, String text, boolean render_p) {
+
+    Paint paint = (Paint) rootset.get(new Long(font_id));
+
+    if (paint == null) {
+      LOG ("no font %d", font_id);
+      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.  Blocking load.
+  public ByteBuffer loadURL (String url) {
+
+    int size0 = 10240;
+    int size = size0;
+    int count = 0;
+    ByteBuffer body = ByteBuffer.allocateDirect (size);
+
+    try {
+      LOG ("load URL: %s", url);
+      URL u = new URL(url);
+      InputStream s = u.openStream();
+      byte buf[] = new byte[10240];
+      while (true) {
+        int n = s.read (buf);
+        if (n == -1) break;
+        // LOG ("read %d", n);
+        if (count + n + 1 >= size) {
+          int size2 = (int) (size * 1.2 + size0);
+          // LOG ("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);
+    }
+
+    return body;
+  }
+
+
+  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/screenhack-android.c b/android/screenhack-android.c
new file mode 100644 (file)
index 0000000..d5067ab
--- /dev/null
@@ -0,0 +1,209 @@
+/* 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.
+ *
+ * Utility functions related to the hacks/ APIs.
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/utsname.h>
+#include <android/log.h>
+#include "screenhackI.h"
+#include "xlockmoreI.h"
+#include "textclient.h"
+
+#if defined(USE_IPHONE) || (HAVE_ANDROID)
+# include "jwzgles.h"
+#else
+# include <OpenGL/OpenGL.h>
+#endif
+
+#ifndef isupper
+# define isupper(c)  ((c) >= 'A' && (c) <= 'Z')
+#endif
+#ifndef _tolower
+# define _tolower(c)  ((c) - 'A' + 'a')
+#endif
+
+Bool 
+get_boolean_resource (Display *dpy, char *res_name, char *res_class)
+{
+  char *tmp, buf [100];
+  char *s = get_string_resource (dpy, res_name, res_class);
+  char *os = s;
+  if (! s) return 0;
+  for (tmp = buf; *s; s++)
+    *tmp++ = isupper (*s) ? _tolower (*s) : *s;
+  *tmp = 0;
+  free (os);
+
+  while (*buf &&
+         (buf[strlen(buf)-1] == ' ' ||
+          buf[strlen(buf)-1] == '\t'))
+    buf[strlen(buf)-1] = 0;
+
+  if (!strcmp (buf, "on") || !strcmp (buf, "true") || !strcmp (buf, "yes"))
+    return 1;
+  if (!strcmp (buf,"off") || !strcmp (buf, "false") || !strcmp (buf,"no"))
+    return 0;
+  fprintf (stderr, "%s: %s must be boolean, not %s.\n",
+           progname, res_name, buf);
+  return 0;
+}
+
+int 
+get_integer_resource (Display *dpy, char *res_name, char *res_class)
+{
+  int val;
+  char c, *s = get_string_resource (dpy, res_name, res_class);
+  char *ss = s;
+  if (!s) return 0;
+
+  while (*ss && *ss <= ' ') ss++;                       /* skip whitespace */
+
+  if (ss[0] == '0' && (ss[1] == 'x' || ss[1] == 'X'))   /* 0x: parse as hex */
+    {
+      if (1 == sscanf (ss+2, "%x %c", (unsigned int *) &val, &c))
+        {
+          free (s);
+          return val;
+        }
+    }
+  else                                                  /* else parse as dec */
+    {
+      /* Allow integer values to end in ".0". */
+      int L = strlen(ss);
+      if (L > 2 && ss[L-2] == '.' && ss[L-1] == '0')
+        ss[L-2] = 0;
+
+      if (1 == sscanf (ss, "%d %c", &val, &c))
+        {
+          free (s);
+          return val;
+        }
+    }
+
+  fprintf (stderr, "%s: %s must be an integer, not %s.\n",
+           progname, res_name, s);
+  free (s);
+  return 0;
+}
+
+double
+get_float_resource (Display *dpy, char *res_name, char *res_class)
+{
+  double val;
+  char c, *s = get_string_resource (dpy, res_name, res_class);
+  if (! s) return 0.0;
+  if (1 == sscanf (s, " %lf %c", &val, &c))
+    {
+      free (s);
+      return val;
+    }
+  fprintf (stderr, "%s: %s must be a float, not %s.\n",
+           progname, res_name, s);
+  free (s);
+  return 0.0;
+}
+
+
+char *
+textclient_mobile_date_string (void)
+{
+  struct utsname uts;
+  if (uname (&uts) < 0)
+    return strdup("uname() failed");
+  else
+    {
+      time_t now = time ((time_t *) 0);
+      char *ts = ctime (&now);
+      char *buf, *s;
+      if ((s = strchr(uts.nodename, '.')))
+        *s = 0;
+      buf = (char *) malloc(strlen(uts.machine) +
+                            strlen(uts.sysname) +
+                            strlen(uts.release) +
+                            strlen(ts) + 10);
+      sprintf (buf, "%s %s %s\n%s", uts.machine, uts.sysname, uts.release, ts);
+      return buf;
+    }
+}
+
+
+/* used by the OpenGL screen savers
+ */
+
+/* Does nothing - prepareContext already did the work.
+ */
+void
+glXMakeCurrent (Display *dpy, Window window, GLXContext context)
+{
+}
+
+
+/* clear away any lingering error codes */
+void
+clear_gl_error (void)
+{
+  while (glGetError() != GL_NO_ERROR)
+    ;
+}
+
+
+// needs to be implemented in Android...
+/* Copy the back buffer to the front buffer.
+ */
+void
+glXSwapBuffers (Display *dpy, Window window)
+{
+}
+
+
+/* Called by OpenGL savers using the XLockmore API.
+ */
+GLXContext *
+init_GL (ModeInfo *mi)
+{
+  // Window win = mi->window;
+
+  // Caller expects a pointer to an opaque struct...  which it dereferences.
+  // Don't ask me, it's historical...
+  static int blort = -1;
+  return (void *) &blort;
+}
+
+/* report a GL error. */
+void
+check_gl_error (const char *type)
+{
+  char buf[100];
+  GLenum i;
+  const char *e;
+  switch ((i = glGetError())) {
+    case GL_NO_ERROR: return;
+    case GL_INVALID_ENUM:          e = "invalid enum";      break;
+    case GL_INVALID_VALUE:         e = "invalid value";     break;
+    case GL_INVALID_OPERATION:     e = "invalid operation"; break;
+    case GL_STACK_OVERFLOW:        e = "stack overflow";    break;
+    case GL_STACK_UNDERFLOW:       e = "stack underflow";   break;
+    case GL_OUT_OF_MEMORY:         e = "out of memory";     break;
+#ifdef GL_TABLE_TOO_LARGE_EXT
+    case GL_TABLE_TOO_LARGE_EXT:   e = "table too large";   break;
+#endif
+#ifdef GL_TEXTURE_TOO_LARGE_EXT
+    case GL_TEXTURE_TOO_LARGE_EXT: e = "texture too large"; break;
+#endif
+    default:
+      e = buf; sprintf (buf, "unknown GL error %d", (int) i); break;
+  }
+  __android_log_write(ANDROID_LOG_ERROR, "xscreensaver", e);
+}
index 3524ec4fc9a172a263eed360ed7dfbad41f6306a..4f3251cd490bce33bc7a204ae3fd4f73768cc39d 100644 (file)
 /* Define to 1 if you have the <sys/stat.h> header file. */
 #undef HAVE_SYS_STAT_H
 
+/* Define to 1 if you have the <sys/termios.h> header file. */
+#undef HAVE_SYS_TERMIOS_H
+
 /* Define to 1 if you have the <sys/types.h> header file. */
 #undef HAVE_SYS_TYPES_H
 
index 79b41332a194ffcf8a9f670e39a0dbed4862b984..75c16008e62509d01ea1dfcb39dcd4baabb71c32 100755 (executable)
--- a/configure
+++ b/configure
@@ -706,11 +706,11 @@ PO_IN_DATADIR_TRUE
 INTLLIBS
 INSTOBJEXT
 GMOFILES
+DATADIRNAME
 CATOBJEXT
 CATALOGS
 MSGFMT_OPTS
 GETTEXT_PACKAGE
-DATADIRNAME
 ALL_LINGUAS
 GMSGFMT
 MSGFMT
@@ -2630,7 +2630,7 @@ echo "command line was: $0 $@"
 # check for some random other files that come later in the tar file,
 # to make sure everything is here.
 #
-for d in driver utils hacks hacks/glx ; do
+for d in utils jwxyz hacks hacks/glx driver ; do
   f=$srcdir/$d/Makefile.in
   if test \! -r $f ; then
     echo ""
@@ -7600,44 +7600,6 @@ fi
 # Substitute ALL_LINGUAS so we can use it in po/Makefile
 
 
-# Set DATADIRNAME correctly if it is not set yet
-# (copied from glib-gettext.m4)
-if test -z "$DATADIRNAME"; then
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-extern int _nl_msg_cat_cntr;
-                       return _nl_msg_cat_cntr
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  DATADIRNAME=share
-else
-  case $host in
-    *-*-solaris*)
-                        ac_fn_c_check_func "$LINENO" "bind_textdomain_codeset" "ac_cv_func_bind_textdomain_codeset"
-if test "x$ac_cv_func_bind_textdomain_codeset" = xyes; then :
-  DATADIRNAME=share
-else
-  DATADIRNAME=lib
-fi
-
-    ;;
-    *)
-    DATADIRNAME=lib
-    ;;
-    esac
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-fi
-
-
 
 
 
@@ -13310,7 +13272,7 @@ if ${ac_cv_mesagl_version_string+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 13317 "configure"
+#line 13279 "configure"
 #include "confdefs.h"
 #include <GL/gl.h>
 #ifndef MESA_MAJOR_VERSION
@@ -13890,7 +13852,7 @@ if test "$with_gles" = yes; then
   have_gles=yes
   $as_echo "#define HAVE_JWZGLES 1" >>confdefs.h
 
-  JWZGLES_OBJS="jwzgles.o"
+  JWZGLES_OBJS='$(JWXYZ_BIN)/jwzgles.o'
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: using OpenGL ES compatiblity shim" >&5
 $as_echo "using OpenGL ES compatiblity shim" >&6; }
 elif test "$with_gles" != no; then
@@ -14863,7 +14825,7 @@ fi
 ###############################################################################
 
 PTY_LIBS=
-for ac_header in pty.h util.h
+for ac_header in pty.h util.h sys/termios.h
 do :
   as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
 ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
@@ -16011,7 +15973,7 @@ APPDEFAULTS=$ac_x_app_defaults
 
 
 
-ac_config_files="$ac_config_files Makefile utils/Makefile driver/Makefile driver/xscreensaver.pam driver/xscreensaver-demo.glade2 hacks/Makefile hacks/glx/Makefile po/Makefile.in driver/XScreenSaver.ad"
+ac_config_files="$ac_config_files Makefile utils/Makefile jwxyz/Makefile hacks/Makefile hacks/glx/Makefile po/Makefile.in driver/Makefile driver/xscreensaver.pam driver/xscreensaver-demo.glade2 driver/XScreenSaver.ad"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
     "default-1") CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;;
     "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
     "utils/Makefile") CONFIG_FILES="$CONFIG_FILES utils/Makefile" ;;
-    "driver/Makefile") CONFIG_FILES="$CONFIG_FILES driver/Makefile" ;;
-    "driver/xscreensaver.pam") CONFIG_FILES="$CONFIG_FILES driver/xscreensaver.pam" ;;
-    "driver/xscreensaver-demo.glade2") CONFIG_FILES="$CONFIG_FILES driver/xscreensaver-demo.glade2" ;;
+    "jwxyz/Makefile") CONFIG_FILES="$CONFIG_FILES jwxyz/Makefile" ;;
     "hacks/Makefile") CONFIG_FILES="$CONFIG_FILES hacks/Makefile" ;;
     "hacks/glx/Makefile") CONFIG_FILES="$CONFIG_FILES hacks/glx/Makefile" ;;
     "po/Makefile.in") CONFIG_FILES="$CONFIG_FILES po/Makefile.in" ;;
+    "driver/Makefile") CONFIG_FILES="$CONFIG_FILES driver/Makefile" ;;
+    "driver/xscreensaver.pam") CONFIG_FILES="$CONFIG_FILES driver/xscreensaver.pam" ;;
+    "driver/xscreensaver-demo.glade2") CONFIG_FILES="$CONFIG_FILES driver/xscreensaver-demo.glade2" ;;
     "driver/XScreenSaver.ad") CONFIG_FILES="$CONFIG_FILES driver/XScreenSaver.ad" ;;
     "po/stamp-it") CONFIG_COMMANDS="$CONFIG_COMMANDS po/stamp-it" ;;
 
index 4c4dee50460d4f9bb3e6c5b5256f05c3b7b4da73..0098d909a83d6e72d9b8240bb487e1800ebacaa3 100644 (file)
@@ -330,7 +330,7 @@ AH_TEMPLATE([HAVE_RECORD_ANIM],
 # check for some random other files that come later in the tar file,
 # to make sure everything is here.
 #
-for d in driver utils hacks hacks/glx ; do
+for d in utils jwxyz hacks hacks/glx driver ; do
   f=$srcdir/$d/Makefile.in
   if test \! -r $f ; then
     echo ""
@@ -3230,7 +3230,7 @@ HANDLE_X_PATH_ARG(with_gles, --with-gles, JWZGLES)
 if test "$with_gles" = yes; then
   have_gles=yes
   AC_DEFINE(HAVE_JWZGLES)
-  JWZGLES_OBJS="jwzgles.o"
+  JWZGLES_OBJS='$(JWXYZ_BIN)/jwzgles.o'
   AC_MSG_RESULT(using OpenGL ES compatiblity shim)
 elif test "$with_gles" != no; then
   echo "error: must be yes or no: --with-gles=$with_xpm"
@@ -3538,7 +3538,7 @@ fi
 ###############################################################################
 
 PTY_LIBS=
-AC_CHECK_HEADERS(pty.h util.h)
+AC_CHECK_HEADERS(pty.h util.h sys/termios.h)
 AC_CHECK_X_LIB(util, forkpty,
                [PTY_LIBS="-lutil"
                 ac_have_forkpty=yes
@@ -4157,12 +4157,13 @@ AC_SUBST(PERL)
 
 AC_OUTPUT(Makefile
           utils/Makefile
-          driver/Makefile
-          driver/xscreensaver.pam
-          driver/xscreensaver-demo.glade2
+          jwxyz/Makefile
           hacks/Makefile
           hacks/glx/Makefile
           po/Makefile.in
+          driver/Makefile
+          driver/xscreensaver.pam
+          driver/xscreensaver-demo.glade2
           driver/XScreenSaver.ad)
 
 ###############################################################################
index 1c1850fb4ac394d8f3af25bfa5a0c1d91292196f..2b48a030e442c46e12a594fa42cf36c83ce13e4a 100644 (file)
@@ -4,11 +4,11 @@
 !            a screen saver and locker for the X window system
 !                            by Jamie Zawinski
 !
-!                              version 5.34
-!                              24-Oct-2015
+!                              version 5.35
+!                              24-May-2016
 !
 ! See "man xscreensaver" for more info.  The latest version is always
-! available at http://www.jwz.org/xscreensaver/
+! available at https://www.jwz.org/xscreensaver/
 
 
 ! These resources, when placed in the system-wide app-defaults directory
@@ -90,7 +90,7 @@ GetViewPortIsFullOfLies: False
 
 ! This is the URL loaded by the "Help" button on the splash screen,
 ! and by the "Documentation" menu item in xscreensaver-demo.
-*helpURL: http://www.jwz.org/xscreensaver/man.html
+*helpURL: https://www.jwz.org/xscreensaver/man.html
 
 ! loadURL       -- how the "Help" buttons load the helpURL (/bin/sh syntax.)
 ! manualCommand -- how the "Documentation" buttons display man pages.
@@ -371,7 +371,11 @@ GetViewPortIsFullOfLies: False
                                tessellimage -root                          \n\
 @GL_KLUDGE@ GL:                                winduprobot -root                           \n\
 @GL_KLUDGE@ GL:                                splitflap -root                             \n\
-                               testx11 -root                               \n
+@GL_KLUDGE@ GL:                                dymaxionmap -root                           \n\
+@GL_KLUDGE@ GL:                                energystream -root                          \n\
+@GL_KLUDGE@ GL:                                hydrostat -root                             \n\
+@GL_KLUDGE@ GL:                                raverhoop -root                             \n\
+@GL_KLUDGE@ GL:                                unicrud -root                               \n
 
 
 
@@ -430,7 +434,7 @@ XScreenSaver.bourneShell:           /bin/sh
 *passwd.uname:                  True
 
 *splash.heading.label:         XScreenSaver %s
-*splash.body.label:            Copyright \251 1991-2015 by
+*splash.body.label:            Copyright \251 1991-2016 by
 *splash.body2.label:           Jamie Zawinski <jwz@jwz.org>
 *splash.demo.label:            Settings
 *splash.help.label:            Help
@@ -462,6 +466,8 @@ XScreenSaver.bourneShell:           /bin/sh
 *hacks.dangerball.name:     DangerBall
 *hacks.decayscreen.name:    DecayScreen
 *hacks.dnalogo.name:        DNA Logo
+*hacks.dymaxionmap.name:    DymaxionMap
+*hacks.energystream.name:   EnergyStream
 *hacks.euler2d.name:        Euler2D
 *hacks.fadeplot.name:       FadePlot
 *hacks.flipflop.name:       FlipFlop
@@ -494,6 +500,7 @@ XScreenSaver.bourneShell:           /bin/sh
 *hacks.popsquares.name:     PopSquares
 *hacks.projectiveplane.name:ProjectivePlane
 *hacks.quasicrystal.name:   QuasiCrystal
+*hacks.raverhoop.name:      RaverHoop
 *hacks.rd-bomb.name:        RDbomb
 *hacks.rdbomb.name:         RDbomb
 *hacks.romanboy.name:       RomanBoy
index 3060b56bf1764af935adab3f5f89679152db83c8..5ca109b47463f9585f52d5bbb22f76121afdd178 100644 (file)
@@ -46,7 +46,7 @@
 "GetViewPortIsFullOfLies: False",
 "*demoCommand: xscreensaver-demo",
 "*prefsCommand: xscreensaver-demo -prefs",
-"*helpURL: http://www.jwz.org/xscreensaver/man.html",
+"*helpURL: https://www.jwz.org/xscreensaver/man.html",
 "*loadURL: firefox '%s' || mozilla '%s' || netscape '%s'",
 "*manualCommand: xterm -sb -fg black -bg gray75 -T '%s manual' \
                    -e /bin/sh -c 'man \"%s\" ; read foo'",
                                tessellimage -root                          \\n\
   GL:                          winduprobot -root                           \\n\
   GL:                          splitflap -root                             \\n\
-                               testx11 -root                               \\n",
+  GL:                          dymaxionmap -root                           \\n\
+  GL:                          energystream -root                          \\n\
+  GL:                          hydrostat -root                             \\n\
+  GL:                          raverhoop -root                             \\n\
+  GL:                          unicrud -root                               \\n",
 "XScreenSaver.pointerPollTime:         0:00:05",
 "XScreenSaver.pointerHysteresis:               10",
 "XScreenSaver.initialDelay:            0:00:00",
 "*passwd.asterisks:              True",
 "*passwd.uname:                  True",
 "*splash.heading.label:                XScreenSaver %s",
-"*splash.body.label:           Copyright \\251 1991-2015 by",
+"*splash.body.label:           Copyright \\251 1991-2016 by",
 "*splash.body2.label:          Jamie Zawinski <jwz@jwz.org>",
 "*splash.demo.label:           Settings",
 "*splash.help.label:           Help",
 "*hacks.dangerball.name:     DangerBall",
 "*hacks.decayscreen.name:    DecayScreen",
 "*hacks.dnalogo.name:        DNA Logo",
+"*hacks.dymaxionmap.name:    DymaxionMap",
+"*hacks.energystream.name:   EnergyStream",
 "*hacks.euler2d.name:        Euler2D",
 "*hacks.fadeplot.name:       FadePlot",
 "*hacks.flipflop.name:       FlipFlop",
 "*hacks.popsquares.name:     PopSquares",
 "*hacks.projectiveplane.name:ProjectivePlane",
 "*hacks.quasicrystal.name:   QuasiCrystal",
+"*hacks.raverhoop.name:      RaverHoop",
 "*hacks.rd-bomb.name:        RDbomb",
 "*hacks.rdbomb.name:         RDbomb",
 "*hacks.romanboy.name:       RomanBoy",
index 27d2316d2c494e68d2eaa65e253364ab3af846af..f5c483965a3a8ead6947abc473d9ea4a823f1c29 100644 (file)
@@ -1,5 +1,5 @@
 /* demo-Gtk.c --- implements the interactive demo-mode and options dialogs.
- * xscreensaver, Copyright (c) 1993-2013 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1993-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
@@ -801,7 +801,7 @@ about_menu_cb (GtkMenuItem *menuitem, gpointer user_data)
   char *s, *s2;
   char copy[1024];
   char year[5];
-  char *desc = _("For updates, check http://www.jwz.org/xscreensaver/");
+  char *desc = _("For updates, check https://www.jwz.org/xscreensaver/");
 
   s = strchr (vers, ',');
   *s = 0;
@@ -5292,13 +5292,13 @@ main (int argc, char **argv)
     the_network_is_not_the_computer (s);
 
 
-  if (senescent_p())
+  if (decrepit_p())
     warning_dialog (s->toplevel_widget,
       _("Warning:\n\n"
         "This version of xscreensaver is VERY OLD!\n"
         "Please upgrade!\n"
         "\n"
-        "http://www.jwz.org/xscreensaver/\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"
index 56d1aac5fece36a14b71d84d70fabbb5dec4d6d7..149e7c5154169ea73669f36d15c5354fc7bd1a33 100644 (file)
@@ -360,7 +360,7 @@ about_menu_cb (Widget button, XtPointer client_data, XtPointer ignored)
            "version is no longer maintained.  Please use the GTK version\n"
            "instead, which has many more features.\n"
            "\n"
-           "For xscreensaver updates, check http://www.jwz.org/xscreensaver/",
+           "For xscreensaver updates, check https://www.jwz.org/xscreensaver/",
            s, s2);
   free (s);
 
index 7c92be60d6375bda6dbb69c47191d1ab833919ef..ec413aee1a933779522f6b0d9a599bec355382eb 100644 (file)
@@ -1,5 +1,5 @@
 /* lock.c --- handling the password dialog for locking-mode.
- * xscreensaver, Copyright (c) 1993-2014 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1993-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
@@ -487,7 +487,7 @@ make_passwd_window (saver_info *si,
    * room for the dialog to grow without going off the edge of the screen. */
   max_string_width_px *= 0.75;
 
-  if (!info_msg && senescent_p())
+  if (!info_msg && decrepit_p())
     info_msg = ("\n"
                 "This version of XScreenSaver\n"
                 "is very old! Please upgrade!\n");
@@ -534,7 +534,7 @@ make_passwd_window (saver_info *si,
       /* Measure the info_label. */
       if (pw->info_label->overall_width > pw->width)
         pw->width = pw->info_label->overall_width;
-       h2 += pw->info_label->overall_height;
+      h2 += pw->info_label->overall_height;
 
       /* Measure the user string. */
       XTextExtents (pw->passwd_font,
index 0c60d50869de4bc54254ee7787c30644b6867fb2..930c6ca2801ea349ff5e67a6ee22e7b49ab7c112 100644 (file)
@@ -1,7 +1,7 @@
 /* passwd-pam.c --- verifying typed passwords with PAM
  * (Pluggable Authentication Modules.)
  * written by Bill Nottingham <notting@redhat.com> (and jwz) for
- * xscreensaver, Copyright (c) 1993-2012 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1993-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
@@ -77,9 +77,12 @@ extern void unblock_sigchld (void);
 /* Some time between Red Hat 4.2 and 7.0, the words were transposed 
    in the various PAM_x_CRED macro names.  Yay!
  */
-#ifndef  PAM_REFRESH_CRED
+#if !defined(PAM_REFRESH_CRED) && defined(PAM_CRED_REFRESH)
 # define PAM_REFRESH_CRED PAM_CRED_REFRESH
 #endif
+#if !defined(PAM_REINITIALIZE_CRED) && defined(PAM_CRED_REINITIALIZE)
+# define PAM_REINITIALIZE_CRED PAM_CRED_REINITIALIZE
+#endif
 
 static int pam_conversation (int nmsgs,
                              const struct pam_message **msg,
@@ -306,13 +309,17 @@ pam_try_unlock(saver_info *si, Bool verbose_p,
       /* Each time we successfully authenticate, refresh credentials,
          for Kerberos/AFS/DCE/etc.  If this fails, just ignore that
          failure and blunder along; it shouldn't matter.
-
-         Note: this used to be PAM_REFRESH_CRED instead of
-         PAM_REINITIALIZE_CRED, but Jason Heiss <jheiss@ee.washington.edu>
-         says that the Linux PAM library ignores that one, and only refreshes
-         credentials when using PAM_REINITIALIZE_CRED.
        */
+
+#if defined(__linux__)
+      /* Apparently the Linux PAM library ignores PAM_REFRESH_CRED and only
+         refreshes credentials when using PAM_REINITIALIZE_CRED. */
       status2 = pam_setcred (pamh, PAM_REINITIALIZE_CRED);
+#else
+      /* But Solaris requires PAM_REFRESH_CRED or extra prompts appear. */
+      status2 = pam_setcred (pamh, PAM_REFRESH_CRED);
+#endif
+
       if (verbose_p)
         fprintf (stderr, "%s:   pam_setcred (...) ==> %d (%s)\n",
                  blurb(), status2, PAM_STRERROR(pamh, status2));
index 55bac7ba8fffb22a09f7b245f8fdbd45fef93b05..ee3a196e0a0fd0cb08652165cf233d9a9e063c78 100644 (file)
@@ -1,5 +1,5 @@
 /* dotfile.c --- management of the ~/.xscreensaver file.
- * xscreensaver, Copyright (c) 1998-2014 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1998-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
@@ -755,7 +755,7 @@ write_init_file (Display *dpy,
     fprintf (out,
             "# %s Preferences File\n"
             "# Written by %s %s for %s on %s.\n"
-            "# http://www.jwz.org/xscreensaver/\n"
+            "# https://www.jwz.org/xscreensaver/\n"
             "\n",
             progclass, progname, version_string, whoami, timestr);
   }
@@ -1661,7 +1661,7 @@ stop_the_insanity (saver_preferences *p)
 
 
 Bool
-senescent_p (void)
+decrepit_p (void)
 {
   /* If you are in here because you're planning on disabling this warning
      before redistributing my software, please don't.
@@ -1690,8 +1690,14 @@ senescent_p (void)
      sucks", and they say "but I don't know how to compile from source,
      herp derp I eat paste", and *everybody* goes away unhappy.
 
-     It wastes an enormous amount of my time, and kind of makes me regret
-     ever having released this software in the first place.
+     It wastes an enormous amount of my time, but worse than that, it
+     does a grave disservice to the users, who are stuck experiencing
+     bugs that are already fixed!  These users think they are running the
+     latest release, and they are not.  They would like to be running the
+     actual latest release, but they don't know how, because their distro
+     makes that very difficult for them.  It's terrible for everyone, and
+     kind of makes me regret ever having released this software in the
+     first place.
 
      So seriously. I ask that if you're planning on disabling this
      obsolescence warning, that you instead just remove xscreensaver from
@@ -1704,37 +1710,61 @@ senescent_p (void)
 
      Thank you!
 
-     jwz, 2014
+     jwz, 2014, 2016.
+
+     PS: In particular, since Debian refuses to upgrade software on any
+     kind of rational timeline, I have asked that they stop shipping
+     xscreensaver at all.  They have refused.  Instead of upgrading the
+     software, they simply patched out this warning.
+
+     If you want to witness the sad state of the open source peanut
+     gallery, look no farther than the comments on my blog:
+     http://jwz.org/b/yiYo
+
+     Many of these people fall back on their go-to argument of, "If it is
+     legal, it must be right."  If you believe in that rhetorical device
+     then you are a terrible person, and possibly a sociopath.
+
+     There are also the armchair lawyers who say "Well, instead of
+     *asking* people to do the right thing out of common courtesy, you
+     should just change your license to prohibit them from acting
+     amorally."  Again, this is the answer of a sociopath, but that aside,
+     if you devote even a second's thought to this you will realize that
+     the end result of this would be for distros like Debian to just keep
+     shipping the last version with the old license and then never
+     upgrading it again -- which would be the worst possible outcome for
+     everyone involved, most especially the users.
   */
-  time_t now = time ((time_t *) 0);                            /*   N   */
-  struct tm *tm = localtime (&now);                            /*   o   */
-  const char *s = screensaver_id;                              /*       */
-  char mon[4], year[5];                                                /*   d   */
-  int m, y, months;                                            /*   o   */
-  s = strchr (s, ' '); if (!s) abort(); s++;                   /*   n   */
-  s = strchr (s, '('); if (!s) abort(); s++;                   /*   '   */
-  s = strchr (s, '-'); if (!s) abort(); s++;                   /*   t   */
-  strncpy (mon, s, 3);                                         /*       */
-  mon[3] = 0;                                                  /*   d   */
-  s = strchr (s, '-'); if (!s) abort(); s++;                   /*   o   */
-  strncpy (year, s, 4);                                                /*       */
-  year[4] = 0;                                                 /*   i   */
-  y = atoi (year);                                             /*   t   */
-  if      (!strcmp(mon, "Jan")) m = 0;                         /*   ,   */
-  else if (!strcmp(mon, "Feb")) m = 1;                         /*       */
-  else if (!strcmp(mon, "Mar")) m = 2;                         /*   s   */
-  else if (!strcmp(mon, "Apr")) m = 3;                         /*   t   */
-  else if (!strcmp(mon, "May")) m = 4;                         /*   o   */
-  else if (!strcmp(mon, "Jun")) m = 5;                         /*   p   */
-  else if (!strcmp(mon, "Jul")) m = 6;                         /*   ,   */
-  else if (!strcmp(mon, "Aug")) m = 7;                         /*       */
-  else if (!strcmp(mon, "Sep")) m = 8;                         /*   s   */
-  else if (!strcmp(mon, "Oct")) m = 9;                         /*   t   */
+
+  time_t now = time ((time_t *) 0);                            /*       */
+  struct tm *tm = localtime (&now);                            /*   d   */
+  const char *s = screensaver_id;                              /*   o   */
+  char mon[4], year[5];                                                /*   n   */
+  int m, y, months;                                            /*   '   */
+  s = strchr (s, ' '); if (!s) abort(); s++;                   /*   t   */
+  s = strchr (s, '('); if (!s) abort(); s++;                   /*       */
+  s = strchr (s, '-'); if (!s) abort(); s++;                   /*   d   */
+  strncpy (mon, s, 3);                                         /*   o   */
+  mon[3] = 0;                                                  /*       */
+  s = strchr (s, '-'); if (!s) abort(); s++;                   /*   i   */
+  strncpy (year, s, 4);                                                /*   t   */
+  year[4] = 0;                                                 /*   ,   */
+  y = atoi (year);                                             /*       */
+  if      (!strcmp(mon, "Jan")) m = 0;                         /*   s   */
+  else if (!strcmp(mon, "Feb")) m = 1;                         /*   t   */
+  else if (!strcmp(mon, "Mar")) m = 2;                         /*   o   */
+  else if (!strcmp(mon, "Apr")) m = 3;                         /*   p   */
+  else if (!strcmp(mon, "May")) m = 4;                         /*   ,   */
+  else if (!strcmp(mon, "Jun")) m = 5;                         /*       */
+  else if (!strcmp(mon, "Jul")) m = 6;                         /*   s   */
+  else if (!strcmp(mon, "Aug")) m = 7;                         /*   t   */
+  else if (!strcmp(mon, "Sep")) m = 8;                         /*   a   */
+  else if (!strcmp(mon, "Oct")) m = 9;                         /*   a   */
   else if (!strcmp(mon, "Nov")) m = 10;                                /*   a   */
-  else if (!strcmp(mon, "Dec")) m = 11;                                /*   a   */
-  else abort();                                                        /*   a   */
+  else if (!strcmp(mon, "Dec")) m = 11;                                /*   h   */
+  else abort();                                                        /*   h   */
   months = ((((tm->tm_year + 1900) * 12) + tm->tm_mon) -       /*   h   */
-            (y * 12 + m));                                     /*   h   */
-                                                               /*   h   */
-  return (months > 18);                                                /*   p   */
+            (y * 12 + m));                                     /*   p   */
+                                                               /*   .   */
+  return (months >= 17);                                       /*       */
 }
index d9711d79636f8ee76b96d78cfdfbb78486334fc1..cf186d39b4d88e4cc53d16e3dca4a4cb9502274b 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1993-2015 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1993-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
@@ -20,7 +20,7 @@ extern int write_init_file (Display *,
                             saver_preferences *, const char *version_string,
                             Bool verbose_p);
 const char *init_file_name (void);
-extern Bool senescent_p (void);
+extern Bool decrepit_p (void);
 
 extern screenhack *parse_screenhack (const char *line);
 extern void free_screenhack (screenhack *);
index 52320d65c359f110cde58a38be32e23d79ac25be..1a2f41d19b91f91d84ac3e2a25a95eeac6055459 100644 (file)
@@ -284,6 +284,23 @@ vidmode_scan_monitors (Display *dpy, char **errP)
           m->height = ml.vdisplay;
         }
 
+      /* On a system that has VidMode but does not have RANDR, and that has
+         "Option Rotate" set, WidthOfScreen/HeightOfScreen are the rotated
+         size, but XF86VidModeModeLine contains the unrotated size.
+         Maybe there's something in 'flags' that indicates this?
+         Or, we can just notice that the aspect ratios are inverted:
+       */
+      if (m->width > 0 &&
+          m->height > 0 &&
+          ((m->width > m->height) != 
+           (WidthOfScreen(screen) > HeightOfScreen(screen))))
+        {
+          int swap = m->width;
+          m->width = m->height;
+          m->height = swap;
+        }
+
+
       /* Apparently, though the server stores the X position in increments of
          1 pixel, it will only make changes to the *display* in some other
          increment.  With XF86_SVGA on a Thinkpad, the display only updates
@@ -294,7 +311,7 @@ vidmode_scan_monitors (Display *dpy, char **errP)
          I consider it a bug that XF86VidModeGetViewPort() is telling me the
          server's *target* scroll position rather than the server's *actual*
          scroll position.  David Dawes agrees, and says they may fix this in
-         XFree86 4.0, but it's notrivial.
+         XFree86 4.0, but it's nontrivial.
 
          He also confirms that this behavior is server-dependent, so the
          actual scroll position cannot be reliably determined by the client.
index 55d386a3b3c4cc82f73295d981412b8207fb527e..18c669ddd184ca6c1a9ed4de75c61aa98c353fc1 100644 (file)
@@ -1,4 +1,5 @@
-/* xscreensaver, Copyright (c) 1991-2014 Jamie Zawinski <jwz@netscape.com>
+/* xscreensaver, Copyright (c) 1991-2014, 2016
+ * -Jamie Zawinski <jwz@netscape.com>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -167,7 +168,7 @@ make_splash_dialog (saver_info *si)
   Colormap cmap;
   char *f;
 
-  Bool whine = senescent_p ();
+  Bool whine = decrepit_p ();
 
   if (whine)
     {
index 7def5d929dc16b7690e9edf3e1ec2fd358c47545..84fa697290d6268c34846fb36fb548ea56b8503a 100644 (file)
@@ -1,5 +1,5 @@
 /* stderr.c --- capturing stdout/stderr output onto the screensaver window.
- * xscreensaver, Copyright (c) 1991-2012 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1991-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
@@ -510,7 +510,7 @@ stderr_log_file (saver_info *si)
            "%s: logging to \"%s\" at %s\n"
  "##########################################################################\n"
            "\n",
-           blurb(), filename, timestring());
+           blurb(), filename, timestring(0));
 }
 
 
index ecbaeb24a31080ca669cdd698581c6ad0aa7d860..29ad60092daf40880afdae6d1acb064b122ec48f 100644 (file)
@@ -1,5 +1,5 @@
 /* subprocs.c --- choosing, spawning, and killing screenhacks.
- * xscreensaver, Copyright (c) 1991-2015 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1991-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
@@ -213,6 +213,7 @@ struct screenhack_job {
   pid_t pid;
   int screen;
   enum job_status status;
+  time_t launched, killed;
   struct screenhack_job *next;
 };
 
@@ -228,14 +229,21 @@ show_job_list (void)
   struct screenhack_job *job;
   fprintf(stderr, "%s: job list:\n", blurb());
   for (job = jobs; job; job = job->next)
-    fprintf (stderr, "  %5ld: %2d: (%s) %s\n",
-            (long) job->pid,
-             job->screen,
-            (job->status == job_running ? "running" :
-             job->status == job_stopped ? "stopped" :
-             job->status == job_killed  ? " killed" :
-             job->status == job_dead    ? "   dead" : "    ???"),
-            job->name);
+    {
+      char b[] = "           ??:??:??     ";
+      char *t = (job->killed   ? timestring (job->killed) :
+                 job->launched ? timestring (job->launched) : b);
+      t += 11;
+      t[8] = 0;
+        fprintf (stderr, "  %5ld: %2d: (%s) %s %s\n",
+                 (long) job->pid,
+                 job->screen,
+                 (job->status == job_running ? "running" :
+                  job->status == job_stopped ? "stopped" :
+                  job->status == job_killed  ? " killed" :
+                  job->status == job_dead    ? "   dead" : "    ???"),
+                 t, job->name);
+    }
   fprintf (stderr, "\n");
 }
 
@@ -277,6 +285,8 @@ make_job (pid_t pid, int screen, const char *cmd)
   job->pid = pid;
   job->screen = screen;
   job->status = job_running;
+  job->launched = time ((time_t *) 0);
+  job->killed = 0;
   job->next = jobs;
   jobs = job;
 
@@ -315,6 +325,10 @@ static void
 clean_job_list (void)
 {
   struct screenhack_job *job, *prev, *next;
+  time_t now = time ((time_t *) 0);
+  static time_t last_warn = 0;
+  Bool warnedp = False;
+
   for (prev = 0, job = jobs, next = (job ? job->next : 0);
        job;
        prev = job, job = next, next = (job ? job->next : 0))
@@ -326,7 +340,21 @@ clean_job_list (void)
          free_job (job);
          job = prev;
        }
+      else if (job->status == job_killed &&
+               now - job->killed > 10 &&
+               now - last_warn   > 10)
+        {
+          fprintf (stderr,
+                   "%s: WARNING: pid %ld (%s) sent SIGTERM %ld seconds ago"
+                   " and did not die!\n",
+                   blurb(),
+                   (long) job->pid,
+                   job->name,
+                   (long) (now - job->killed));
+          warnedp = True;
+        }
     }
+  if (warnedp) last_warn = now;
 }
 
 
@@ -439,7 +467,10 @@ kill_job (saver_info *si, pid_t pid, int signal)
     }
 
   switch (signal) {
-  case SIGTERM: job->status = job_killed;  break;
+  case SIGTERM:
+    job->status = job_killed;
+    job->killed = time ((time_t *) 0);
+    break;
 #ifdef SIGSTOP
     /* #### there must be a way to do this on VMS... */
   case SIGSTOP: job->status = job_stopped; break;
index b9b6c328a7594244c30ebcc754c28dffa20064b5..2bd62199084b96fe3b00e2b28e6b686a2127d2bf 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1998-2014 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1998-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
@@ -66,6 +66,7 @@ void resize_screensaver_window (saver_info *si) { }
 void describe_monitor_layout (saver_info *si) { }
 Bool update_screen_layout (saver_info *si) { return 0; }
 Bool in_signal_handler_p = 0;
+char *timestring (time_t when) { return ""; }
 
 const char *blurb(void) { return progname; }
 Atom XA_SCREENSAVER, XA_DEMO, XA_PREFS;
index 81c8adb6fe9958bd816627e2de2cc1bced866cd0..318a61f47e467ee91e3d45b09177b08ff3f162a9 100644 (file)
@@ -18,6 +18,7 @@
 #include <X11/Xlib.h>
 #include <X11/Intrinsic.h>
 #include <X11/Xos.h>
+#include <X11/Xatom.h>
 #include <time.h>
 #include <sys/time.h>
 #ifdef HAVE_XMU
@@ -989,29 +990,90 @@ sleep_until_idle (saver_info *si, Bool until_idle_p)
 
       case PropertyNotify:
 
+        /* Starting in late 2014, GNOME programs don't actually select for
+           or receive KeyPress events: they do it behind the scenes through
+           some kind of Input Method magic, even when running in an en_US
+           locale.  However, those applications *do* update the WM_USER_TIME
+           property on their own windows every time they recieve a secret
+           KeyPress, so we must *also* monitor that property on every
+           window, and treat changes to it as identical to KeyPress.
+
+           _NET_WM_USER_TIME is documented (such as it is) here:
+
+             http://standards.freedesktop.org/wm-spec/latest/ar01s05.html
+             #idm139870829932528
+
+           Specifically:
+
+             "Contains the XServer time at which last user activity in this
+             window took place. [...]  A client [...] might, for example,
+             use the timestamp of the last KeyPress or ButtonPress event."
+
+           As of early 2016, KDE4 does something really stupid, though: some
+           hidden power management thing reduces the display brightness 150
+           seconds after the screen is blanked -- and sets a WM_USER_TIME
+           property on a hidden "kded4" window whose time is in the distant
+           past (the time at which the X server launched).
+
+           So we ignore any WM_USER_TIME whose timestamp is more than a
+           couple seconds old.
+         */
         if (event.x_event.xproperty.state == PropertyNewValue &&
             event.x_event.xproperty.atom == XA_NET_WM_USER_TIME)
           {
-            /* Let's just assume that they only ever set USER_TIME to the
-               current time, and don't do something stupid like repeatedly
-               setting it to 20 minutes ago. */
+            int threshold = 2; /* seconds */
+            Bool bogus_p = True;
+            Window w = event.x_event.xproperty.window;
+
+            Atom type;
+            int format;
+            unsigned long nitems, bytesafter;
+            unsigned char *data = 0;
+            Cardinal user_time = 0;
+            XErrorHandler old_handler = XSetErrorHandler (BadWindow_ehandler);
+
+            if (XGetWindowProperty (si->dpy, w, 
+                                    XA_NET_WM_USER_TIME, 0L, 1L, False,
+                                    XA_CARDINAL, &type, &format, &nitems,
+                                    &bytesafter, &data)
+                == Success &&
+                data &&
+                type == XA_CARDINAL &&
+                format == 32 &&
+                nitems == 1)
+              {
+                long diff;
+                user_time = ((Cardinal *) data)[0];
+                diff = event.x_event.xproperty.time - user_time;
+                if (diff >= 0 && diff < threshold)
+                  bogus_p = False;
+              }
+
+            if (data) XFree (data);
 
             why = "WM_USER_TIME";
 
             if (p->debug_p)
               {
-                Window w = event.x_event.xproperty.window;
                 XWindowAttributes xgwa;
                 int i;
+
                 XGetWindowAttributes (si->dpy, w, &xgwa);
                 for (i = 0; i < si->nscreens; i++)
                   if (xgwa.root == RootWindowOfScreen (si->screens[i].screen))
                     break;
-                fprintf (stderr,"%s: %d: %s on 0x%lx\n",
-                         blurb(), i, why, (unsigned long) w);
+                fprintf (stderr,"%s: %d: %s = %ld%s on 0x%lx\n",
+                         blurb(), i, why, (unsigned long) user_time,
+                         (bogus_p ? " (bad)" : ""),
+                         (unsigned long) w);
               }
 
-            if (until_idle_p)
+            XSync (si->dpy, False);
+            XSetErrorHandler (old_handler);
+
+            if (bogus_p)
+              break;
+            else if (until_idle_p)
               reset_timers (si);
             else
               goto DONE;
index d33f251ad9efcd0de2cdc7b171a7a08f2ab359cb..1a9701aa52121f23ebc9a7269830d5472572fb54 100644 (file)
@@ -897,7 +897,7 @@ saver_exit (saver_info *si, int status, const char *dump_core_reason)
 
       if (bugp)
        fprintf(real_stderr,
-               "%s: see http://www.jwz.org/xscreensaver/bugs.html\n"
+               "%s: see https://www.jwz.org/xscreensaver/bugs.html\n"
                "\t\t\tfor bug reporting information.\n\n",
                blurb());
 
index 0057438a37ede9125fabb77fde0b5b53b1aa2fc7..6adf1fdd5e852ca6a9b9987842b88593b34ac987 100644 (file)
@@ -134,7 +134,7 @@ usage: %s -<option>\n\
                 some way.\n\
 \n\
   See the man page for more details.\n\
-  For updates, check http://www.jwz.org/xscreensaver/\n\
+  For updates, check https://www.jwz.org/xscreensaver/\n\
 \n";
 
 /* Note: The "-throttle" command is deprecated -- it predates the XDPMS
index 0dee348fbdfdad605831f59c578a1d7139de6404..040a183373538c769e37dd685d315baa831b3c47 100644 (file)
@@ -242,7 +242,7 @@ the \fIxscreensaver\fP process, not the \fIxscreensaver-command\fP process.
 .SH UPGRADES
 The latest version of
 .BR xscreensaver (1)
-and related tools can always be found at http://www.jwz.org/xscreensaver/
+and related tools can always be found at https://www.jwz.org/xscreensaver/
 .SH "SEE ALSO"
 .BR X (1),
 .BR xscreensaver (1),
index d686d27f97ddd1ef85713492ef6e8295ab9f47a8..7da5fea5ee5ed8c420f21f3baa59aa7d1c01cc03 100644 (file)
@@ -380,7 +380,7 @@ stored in the RESOURCE_MANAGER property.
 to get the default HTTP proxy host and port.
 .SH UPGRADES
 The latest version of xscreensaver, an online version of this manual,
-and a FAQ can always be found at http://www.jwz.org/xscreensaver/
+and a FAQ can always be found at https://www.jwz.org/xscreensaver/
 .SH SEE ALSO
 .BR X (1),
 .BR xscreensaver (1),
index bbb1a250e1456e87fb6d641cd03335c5d9fc3896..981ddb753d6510edce449841f2db11eb8185b5bb 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/perl -w
-# Copyright © 2001-2013 Jamie Zawinski <jwz@jwz.org>.
+# Copyright © 2001-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
@@ -57,7 +57,7 @@ BEGIN { eval 'use LWP::Simple;' }
 
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my $version = q{ $Revision: 1.38 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/;
+my ($version) = ('$Revision: 1.40 $' =~ m/\s(\d[.\d]+)\s/s);
 
 my $verbose = 0;
 
@@ -360,19 +360,28 @@ sub html_unquote($) {
 
 
 
+# Figure out what the proxy server should be, either from environment
+# variables or by parsing the output of the (MacOS) program "scutil",
+# which tells us what the system-wide proxy settings are.
+#
 sub set_proxy($) {
   my ($ua) = @_;
 
-  if (!defined($ENV{http_proxy}) && !defined($ENV{HTTP_PROXY})) {
-    my $proxy_data = `scutil --proxy 2>/dev/null`;
-    my ($server) = ($proxy_data =~ m/\bHTTPProxy\s*:\s*([^\s]+)/s);
-    my ($port)   = ($proxy_data =~ m/\bHTTPPort\s*:\s*([^\s]+)/s);
-    if ($server) {
+  my $proxy_data = `scutil --proxy 2>/dev/null`;
+  foreach my $proto ('http', 'https') {
+    my ($server) = ($proxy_data =~ m/\b${proto}Proxy\s*:\s*([^\s]+)/si);
+    my ($port)   = ($proxy_data =~ m/\b${proto}Port\s*:\s*([^\s]+)/si);
+    my ($enable) = ($proxy_data =~ m/\b${proto}Enable\s*:\s*([^\s]+)/si);
+
+    if ($server && $enable) {
       # Note: this ignores the "ExceptionsList".
-      $ENV{http_proxy} = "http://" . $server . ($port ? ":$port" : "") . "/";
-      print STDERR "$progname: MacOS proxy: $ENV{http_proxy}\n"
-        if ($verbose > 2)
-      }
+      my $proto2 = 'http';
+      $ENV{"${proto}_proxy"} = ("${proto2}://" . $server .
+                                ($port ? ":$port" : "") . "/");
+      print STDERR "$progname: MacOS $proto proxy: " .
+                   $ENV{"${proto}_proxy"} . "\n"
+        if ($verbose > 2);
+    }
   }
 
   $ua->env_proxy();
@@ -408,6 +417,9 @@ sub parse_feed($) {
     # only for "Photostreams", and only the first 20 images of those.
     # Thanks, assholes.)
 
+    error ("null response: $url")
+      if ($body =~ m/^\s*$/s);
+
     error ("not an RSS or Atom feed, or HTML: $url")
       unless ($body =~ m@<(HEAD|BODY|A|IMG)\b@si);
 
index 81998297d765c325de6a0a89dca029dedb184215..1b55832d92c49422ba6675da8179d7388719f1a1 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/perl -w
-# Copyright © 2005-2015 Jamie Zawinski <jwz@jwz.org>
+# Copyright © 2005-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
@@ -37,7 +37,7 @@ use Text::Wrap qw(wrap);
 use bytes;
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my ($version) = ('$Revision: 1.39 $' =~ m/\s(\d[.\d]+)\s/s);
+my ($version) = ('$Revision: 1.41 $' =~ m/\s(\d[.\d]+)\s/s);
 
 my $verbose = 0;
 my $http_proxy = undef;
@@ -277,6 +277,8 @@ sub which($) {
 
 sub output() {
 
+  binmode (STDOUT, ($latin1_p ? ':raw' : ':utf8'));
+
   # Do some basic sanity checking (null text, null file names, etc.)
   #
   if (($text_mode eq 'literal' && $text_literal =~ m/^\s*$/i) ||
@@ -659,16 +661,21 @@ sub reformat_text($) {
 sub set_proxy($) {
   my ($ua) = @_;
 
-  if (!defined($ENV{http_proxy}) && !defined($ENV{HTTP_PROXY})) {
-    my $proxy_data = `scutil --proxy 2>/dev/null`;
-    my ($server) = ($proxy_data =~ m/\bHTTPProxy\s*:\s*([^\s]+)/s);
-    my ($port)   = ($proxy_data =~ m/\bHTTPPort\s*:\s*([^\s]+)/s);
-    if ($server) {
+  my $proxy_data = `scutil --proxy 2>/dev/null`;
+  foreach my $proto ('http', 'https') {
+    my ($server) = ($proxy_data =~ m/\b${proto}Proxy\s*:\s*([^\s]+)/si);
+    my ($port)   = ($proxy_data =~ m/\b${proto}Port\s*:\s*([^\s]+)/si);
+    my ($enable) = ($proxy_data =~ m/\b${proto}Enable\s*:\s*([^\s]+)/si);
+
+    if ($server && $enable) {
       # Note: this ignores the "ExceptionsList".
-      $ENV{http_proxy} = "http://" . $server . ($port ? ":$port" : "") . "/";
-      print STDERR "$progname: MacOS proxy: $ENV{http_proxy}\n"
-        if ($verbose > 2)
-      }
+      my $proto2 = 'http';
+      $ENV{"${proto}_proxy"} = ("${proto2}://" . $server .
+                                ($port ? ":$port" : "") . "/");
+      print STDERR "$progname: MacOS $proto proxy: " .
+                   $ENV{"${proto}_proxy"} . "\n"
+        if ($verbose > 2);
+    }
   }
 
   $ua->env_proxy();
index 45f0f0c48330afda7192a3b02fc6aee26100f965..76969f23d2454bc0e01628af46abbb8e5018ff67 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1991-2015 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1991-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
@@ -305,7 +305,7 @@ xscreensaver %s, copyright (c) 1991-%s by Jamie Zawinski <jwz@jwz.org>\n\
 \n\
   For updates, online manual, and FAQ, please see the web page:\n\
 \n\
-       http://www.jwz.org/xscreensaver/\n\
+       https://www.jwz.org/xscreensaver/\n\
 \n");
 
   fflush (stdout);
@@ -317,7 +317,7 @@ xscreensaver %s, copyright (c) 1991-%s by Jamie Zawinski <jwz@jwz.org>\n\
 Bool in_signal_handler_p = 0;  /* I hate C so much... */
 
 char *
-timestring (void)
+timestring (time_t when)
 {
   if (in_signal_handler_p)
     {
@@ -330,9 +330,10 @@ timestring (void)
     }
   else
     {
-      time_t now = time ((time_t *) 0);
-      char *str = (char *) ctime (&now);
-      char *nl = (char *) strchr (str, '\n');
+      char *str, *nl;
+      if (! when) when = time ((time_t *) 0);
+      str = (char *) ctime (&when);
+      nl = (char *) strchr (str, '\n');
       if (nl) *nl = 0; /* take off that dang newline */
       return str;
     }
@@ -348,7 +349,7 @@ blurb (void)
   else
     {
       static char buf[255];
-      char *ct = timestring();
+      char *ct = timestring(0);
       int n = strlen(progname);
       if (n > 100) n = 99;
       strncpy(buf, progname, n);
@@ -424,7 +425,7 @@ saver_ehandler (Display *dpy, XErrorEvent *error)
    "    won't work.  A \"log.txt\" file will also be written.  Please *do*\n"
    "    include the complete \"log.txt\" file with your bug report.\n"
    "\n"
-   "    http://www.jwz.org/xscreensaver/bugs.html explains how to create\n"
+   "    https://www.jwz.org/xscreensaver/bugs.html explains how to create\n"
    "    the most useful bug reports, and how to examine core files.\n"
    "\n"
    "    The more information you can provide, the better.  But please\n"
@@ -494,8 +495,8 @@ startup_ehandler (String name, String type, String class,
     }
 
   fprintf (stderr, "\n"
-          "              http://www.jwz.org/xscreensaver/faq.html\n"
-          "              http://www.jwz.org/xscreensaver/man.html\n"
+          "              https://www.jwz.org/xscreensaver/faq.html\n"
+          "              https://www.jwz.org/xscreensaver/man.html\n"
           "\n");
 
   fflush (stderr);
@@ -749,7 +750,7 @@ process_command_line (saver_info *si, int *argc, char **argv)
     You control a running xscreensaver process by sending it messages\n\
     with `xscreensaver-demo' or `xscreensaver-command'.\n\
 .   See the man pages for details, or check the web page:\n\
-    http://www.jwz.org/xscreensaver/\n\n");
+    https://www.jwz.org/xscreensaver/\n\n");
            }
 
          exit (1);
@@ -803,12 +804,12 @@ print_banner (saver_info *si)
             "\n",
             blurb());
 
-  if (p->verbose_p && senescent_p ())
+  if (p->verbose_p && decrepit_p ())
     fprintf (stderr, "\n"
              "*************************************"
              "**************************************\n"
             "%s: Warning: this version of xscreensaver is VERY OLD!\n"
-            "%s: Please upgrade!  http://www.jwz.org/xscreensaver/\n"
+            "%s: Please upgrade!  https://www.jwz.org/xscreensaver/\n"
              "*************************************"
              "**************************************\n"
             "\n",
@@ -1197,10 +1198,10 @@ main_loop (saver_info *si)
        {
          if (si->demoing_p)
            fprintf (stderr, "%s: demoing %d at %s.\n", blurb(),
-                    si->selection_mode, timestring());
+                    si->selection_mode, timestring(0));
          else
             fprintf (stderr, "%s: blanking screen at %s.\n", blurb(),
-                     timestring());
+                     timestring(0));
        }
 
       maybe_reload_init_file (si);
@@ -1209,7 +1210,7 @@ main_loop (saver_info *si)
         {
           if (p->verbose_p)
             fprintf (stderr, "%s: idle with blanking disabled at %s.\n",
-                     blurb(), timestring());
+                     blurb(), timestring(0));
 
           /* Go around the loop and wait for the next bout of idleness,
              or for the init file to change, or for a remote command to
@@ -1411,7 +1412,7 @@ main_loop (saver_info *si)
 
       if (p->verbose_p)
        fprintf (stderr, "%s: unblanking screen at %s.\n",
-                blurb(), timestring ());
+                blurb(), timestring (0));
 
       /* Kill before unblanking, to stop drawing as soon as possible. */
       for (i = 0; i < si->nscreens; i++)
index d67966efdfed30ebbe937a9ac587fcf65219357a..877d119857f639f3b2394402ec5497f3dc734faa 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1993-2014 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1993-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
@@ -190,7 +190,7 @@ extern int saver_ehandler (Display *dpy, XErrorEvent *error);
 extern int BadWindow_ehandler (Display *dpy, XErrorEvent *error);
 extern Bool window_exists_p (Display *dpy, Window window);
 extern Bool in_signal_handler_p;
-extern char *timestring (void);
+extern char *timestring (time_t);
 extern Bool display_is_on_console_p (saver_info *si);
 extern Visual *get_best_gl_visual (saver_info *si, Screen *screen);
 extern void check_for_leaks (const char *where);
index 11f5b02927e3c1b3c8928b3bbc67a218456ac65d..42f0c3d9c89f8e642dfe738500afc451ec952c08 100644 (file)
@@ -283,7 +283,7 @@ containing:
 [Unit]
 Description=XScreenSaver
 [Service]
-ExecStart=xscreensaver
+ExecStart=/usr/bin/xscreensaver
 [Install]
 WantedBy=default.target
 .EE
@@ -349,7 +349,7 @@ and
 .BR xhost (1).
 .SH BUGS
 Bugs?  There are no bugs.  Ok, well, maybe.  If you find one, please let
-me know.  http://www.jwz.org/xscreensaver/bugs.html explains how to
+me know.  https://www.jwz.org/xscreensaver/bugs.html explains how to
 construct the most useful bug reports.
 .PP
 .TP 4
@@ -928,7 +928,7 @@ to get the name of a resource file that overrides the global resources
 stored in the RESOURCE_MANAGER property.
 .SH UPGRADES
 The latest version of xscreensaver, an online version of this manual,
-and a FAQ can always be found at http://www.jwz.org/xscreensaver/
+and a FAQ can always be found at https://www.jwz.org/xscreensaver/
 .SH SEE ALSO
 .BR X (1),
 .BR Xsecurity (1),
index e15a71406255a33c6d4935c56369262e27bbfbee..ccc0b6169b97e04ab749c3b321afb2ccee4bafd1 100644 (file)
@@ -1,4 +1,4 @@
-# hacks/Makefile.in --- xscreensaver, Copyright (c) 1997-2014 Jamie Zawinski.
+# hacks/Makefile.in --- xscreensaver, Copyright (c) 1997-2015 Jamie Zawinski.
 # the `../configure' script generates `hacks/Makefile' from this file.
 
 @SET_MAKE@
@@ -84,13 +84,13 @@ UTIL_OBJS   = $(UTILS_BIN)/alpha.o $(UTILS_BIN)/colors.o \
                  $(UTILS_BIN)/hsv.o $(UTILS_BIN)/resources.o \
                  $(UTILS_BIN)/spline.o $(UTILS_BIN)/usleep.o \
                  $(UTILS_BIN)/visual.o $(UTILS_BIN)/logo.o \
-                 $(UTILS_SRC)/minixpm.o \
+                 $(UTILS_BIN)/minixpm.o \
                  $(UTILS_BIN)/yarandom.o $(UTILS_BIN)/erase.o \
                  $(UTILS_BIN)/xshm.o $(UTILS_BIN)/xdbe.o \
                  $(UTILS_BIN)/colorbars.o \
-                 $(UTILS_SRC)/textclient.o $(UTILS_SRC)/aligned_malloc.o \
-                 $(UTILS_SRC)/thread_util.o \
-                 $(UTILS_SRC)/xft.o $(UTILS_SRC)/utf8wc.o
+                 $(UTILS_BIN)/textclient.o $(UTILS_BIN)/aligned_malloc.o \
+                 $(UTILS_BIN)/thread_util.o \
+                 $(UTILS_BIN)/xft.o $(UTILS_BIN)/utf8wc.o
 
 SRCS           = attraction.c blitspin.c bouboule.c braid.c bubbles.c \
                  bubbles-default.c decayscreen.c deco.c drift.c flag.c \
@@ -190,7 +190,7 @@ JPEG_EXES   = webcollage-helper
 
 RETIRED_EXES   = ant bubbles critical flag forest hyperball hypercube laser \
                  lightning lisa lissie lmorph rotor sphere spiral t3d vines \
-                 whirlygig worm xsublim juggle
+                 whirlygig worm xsublim juggle testx11
 
 HACK_OBJS_1    = fps.o $(UTILS_BIN)/resources.o $(UTILS_BIN)/visual.o \
                  $(UTILS_BIN)/usleep.o $(UTILS_BIN)/yarandom.o \
@@ -273,7 +273,7 @@ TARFILES    = $(SRCS) $(HDRS) $(SCRIPTS) $(MEN) $(RETIRED_MEN) \
 
 
 default: all
-all: $(EXES) $(RETIRED_EXES) testx11
+all: $(EXES) $(RETIRED_EXES)
 
 install:   install-program   install-scripts install-xml install-man
 uninstall: uninstall-program uninstall-xml uninstall-man
@@ -389,7 +389,7 @@ uninstall-xml:
        done
 
 clean:
-       -rm -f *.o a.out core $(EXES) $(RETIRED_EXES) testx11 m6502.h
+       -rm -f *.o a.out core $(EXES) $(RETIRED_EXES) m6502.h
 
 distclean: clean
        -rm -f Makefile TAGS *~ "#"*
@@ -873,8 +873,10 @@ 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       $(HACK_OBJS)
-       $(CC_HACK) -o $@ $@.o   $(HACK_OBJS) $(COL) $(HACK_LIBS)
+testx11:       testx11.o       glx/rotator.o $(HACK_OBJS)
+       $(CC_HACK) -o $@ $@.o   glx/rotator.o $(HACK_OBJS) $(COL) $(HACK_LIBS)
+glx/rotator.o: glx/rotator.c
+       $(MAKE) -C glx $(@F) CC="$(CC)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)"
 
 # The rules for those hacks which follow the `xlockmore' API.
 #
@@ -1042,6 +1044,7 @@ anemone.o: $(UTILS_SRC)/hsv.h
 anemone.o: $(UTILS_SRC)/resources.h
 anemone.o: $(UTILS_SRC)/usleep.h
 anemone.o: $(UTILS_SRC)/visual.h
+anemone.o: $(UTILS_SRC)/xdbe.h
 anemone.o: $(UTILS_SRC)/yarandom.h
 anemotaxis.o: ../config.h
 anemotaxis.o: $(srcdir)/fps.h
@@ -1053,6 +1056,7 @@ anemotaxis.o: $(UTILS_SRC)/hsv.h
 anemotaxis.o: $(UTILS_SRC)/resources.h
 anemotaxis.o: $(UTILS_SRC)/usleep.h
 anemotaxis.o: $(UTILS_SRC)/visual.h
+anemotaxis.o: $(UTILS_SRC)/xdbe.h
 anemotaxis.o: $(UTILS_SRC)/yarandom.h
 ant.o: $(srcdir)/automata.h
 ant.o: ../config.h
@@ -1359,6 +1363,7 @@ compass.o: $(UTILS_SRC)/hsv.h
 compass.o: $(UTILS_SRC)/resources.h
 compass.o: $(UTILS_SRC)/usleep.h
 compass.o: $(UTILS_SRC)/visual.h
+compass.o: $(UTILS_SRC)/xdbe.h
 compass.o: $(UTILS_SRC)/yarandom.h
 coral.o: ../config.h
 coral.o: $(srcdir)/fps.h
@@ -1455,6 +1460,7 @@ deluxe.o: $(UTILS_SRC)/hsv.h
 deluxe.o: $(UTILS_SRC)/resources.h
 deluxe.o: $(UTILS_SRC)/usleep.h
 deluxe.o: $(UTILS_SRC)/visual.h
+deluxe.o: $(UTILS_SRC)/xdbe.h
 deluxe.o: $(UTILS_SRC)/yarandom.h
 demon.o: $(srcdir)/automata.h
 demon.o: ../config.h
@@ -1631,6 +1637,7 @@ fluidballs.o: $(UTILS_SRC)/hsv.h
 fluidballs.o: $(UTILS_SRC)/resources.h
 fluidballs.o: $(UTILS_SRC)/usleep.h
 fluidballs.o: $(UTILS_SRC)/visual.h
+fluidballs.o: $(UTILS_SRC)/xdbe.h
 fluidballs.o: $(UTILS_SRC)/yarandom.h
 fontglide.o: ../config.h
 fontglide.o: $(srcdir)/fps.h
@@ -1644,6 +1651,7 @@ fontglide.o: $(UTILS_SRC)/textclient.h
 fontglide.o: $(UTILS_SRC)/usleep.h
 fontglide.o: $(UTILS_SRC)/utf8wc.h
 fontglide.o: $(UTILS_SRC)/visual.h
+fontglide.o: $(UTILS_SRC)/xdbe.h
 fontglide.o: $(UTILS_SRC)/xft.h
 fontglide.o: $(UTILS_SRC)/yarandom.h
 forest.o: ../config.h
@@ -1857,6 +1865,7 @@ interference.o: $(UTILS_SRC)/resources.h
 interference.o: $(UTILS_SRC)/thread_util.h
 interference.o: $(UTILS_SRC)/usleep.h
 interference.o: $(UTILS_SRC)/visual.h
+interference.o: $(UTILS_SRC)/xdbe.h
 interference.o: $(UTILS_SRC)/xshm.h
 interference.o: $(UTILS_SRC)/yarandom.h
 intermomentary.o: ../config.h
@@ -1918,6 +1927,7 @@ kumppa.o: $(UTILS_SRC)/hsv.h
 kumppa.o: $(UTILS_SRC)/resources.h
 kumppa.o: $(UTILS_SRC)/usleep.h
 kumppa.o: $(UTILS_SRC)/visual.h
+kumppa.o: $(UTILS_SRC)/xdbe.h
 kumppa.o: $(UTILS_SRC)/yarandom.h
 laser.o: ../config.h
 laser.o: $(srcdir)/fps.h
@@ -2068,6 +2078,7 @@ moire2.o: $(UTILS_SRC)/hsv.h
 moire2.o: $(UTILS_SRC)/resources.h
 moire2.o: $(UTILS_SRC)/usleep.h
 moire2.o: $(UTILS_SRC)/visual.h
+moire2.o: $(UTILS_SRC)/xdbe.h
 moire2.o: $(UTILS_SRC)/yarandom.h
 moire.o: ../config.h
 moire.o: $(srcdir)/fps.h
@@ -2291,6 +2302,7 @@ piecewise.o: $(UTILS_SRC)/hsv.h
 piecewise.o: $(UTILS_SRC)/resources.h
 piecewise.o: $(UTILS_SRC)/usleep.h
 piecewise.o: $(UTILS_SRC)/visual.h
+piecewise.o: $(UTILS_SRC)/xdbe.h
 piecewise.o: $(UTILS_SRC)/yarandom.h
 polyominoes.o: ../config.h
 polyominoes.o: $(srcdir)/fps.h
@@ -2331,6 +2343,7 @@ popsquares.o: $(UTILS_SRC)/hsv.h
 popsquares.o: $(UTILS_SRC)/resources.h
 popsquares.o: $(UTILS_SRC)/usleep.h
 popsquares.o: $(UTILS_SRC)/visual.h
+popsquares.o: $(UTILS_SRC)/xdbe.h
 popsquares.o: $(UTILS_SRC)/yarandom.h
 pyro.o: ../config.h
 pyro.o: $(srcdir)/fps.h
@@ -2632,6 +2645,7 @@ tessellimage.o: $(UTILS_SRC)/visual.h
 tessellimage.o: $(UTILS_SRC)/yarandom.h
 testx11.o: ../config.h
 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)/colors.h
@@ -2760,6 +2774,7 @@ whirlygig.o: $(UTILS_SRC)/hsv.h
 whirlygig.o: $(UTILS_SRC)/resources.h
 whirlygig.o: $(UTILS_SRC)/usleep.h
 whirlygig.o: $(UTILS_SRC)/visual.h
+whirlygig.o: $(UTILS_SRC)/xdbe.h
 whirlygig.o: $(UTILS_SRC)/yarandom.h
 wormhole.o: ../config.h
 wormhole.o: $(srcdir)/fps.h
index f1abbb60d20ad4cd588be049026cf205f1510e35..b4394f14ec257f1c965a72466ad4bec1eccb4128 100644 (file)
@@ -916,6 +916,7 @@ _getcolor(struct state *st, int x, int y)
 {
   int n, cv[LAYERS];
 
+  cv[0] = 0;
   for (n=0; n<st->layers; n++) {
     cv[n]=_pattern(st,x,y,n);
                   /* first wave/shape */
@@ -1588,7 +1589,7 @@ static const char *abstractile_defaults [] = {
   "*sleep:             3",
   "*speed:             3",
   "*tile:         random",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
   0
index c26c315c3aab7a8ce746d759438119b62153d848..28930c5ef91c791359b8c993662c61bc00bc8b2e 100644 (file)
@@ -64,9 +64,9 @@
    - removed unusable hashnoise code
  */
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
 # include "jwxyz.h"
-#else /* !HAVE_COCOA */
+#else /* !HAVE_JWXYZ */
 # include <X11/Xlib.h>
 # include <X11/Xutil.h>
 #endif
@@ -344,7 +344,7 @@ analogtv_configure(analogtv *it)
   wlim = it->xgwa.width;
   ratio = wlim / (float) hlim;
 
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   /* Fill the whole iPhone screen, even though that distorts the image. */
   min_ratio = 0;
   max_ratio = 10;
@@ -392,7 +392,7 @@ analogtv_configure(analogtv *it)
 
 
   height_diff = ((hlim + ANALOGTV_VISLINES/2) % ANALOGTV_VISLINES) - ANALOGTV_VISLINES/2;
-  if (height_diff != 0 && fabs(height_diff) < hlim * height_snap)
+  if (height_diff != 0 && abs(height_diff) < hlim * height_snap)
     {
       hlim -= height_diff;
     }
index 92d9b8e69605909d3b359b44e30a87d917c1e2e1..99c7909d5b6098a1fec5bf911d224fe743bd4de3 100644 (file)
 #include "thread_util.h"
 #include "xshm.h"
 
+#if defined(USE_IPHONE) || defined(HAVE_ANDROID)
+# define HAVE_MOBILE
+#endif
+
 /*
   You'll need these to generate standard NTSC TV signals
  */
@@ -294,7 +298,7 @@ int analogtv_handle_events (analogtv *it);
 #define ANALOGTV_DEFAULTS_SHM
 #endif
 
-#ifndef USE_IPHONE
+#ifndef HAVE_MOBILE
 # define ANALOGTV_DEF_BRIGHTNESS "2"
 # define ANALOGTV_DEF_CONTRAST "150"
 #else
index 9f65145aff3985916964a63c3816630b4e76bdd0..deedb270b659da0c929e426e94c9a6a0ebadc429 100644 (file)
@@ -193,7 +193,7 @@ anemone_init (Display *disp, Window window)
 
   st->dbuf = TRUE;
 
-# ifdef HAVE_COCOA     /* Don't second-guess Quartz's double-buffering */
+# ifdef HAVE_JWXYZ     /* Don't second-guess Quartz's double-buffering */
   st->dbuf = False;
 # endif
 
@@ -426,7 +426,7 @@ static const char *anemone_defaults [] = {
 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
   "*useDBE:            True",
 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
   0
index 50f35348566189649de37857af8a438fd25ddfda..4f9c9d8ea7d72677b31d4f076289dcafc91904fe 100644 (file)
@@ -403,7 +403,7 @@ anemotaxis_init (Display *disp, Window win)
 
   st->dbuf = True;
 
-# ifdef HAVE_COCOA     /* Don't second-guess Quartz's double-buffering */
+# ifdef HAVE_JWXYZ     /* Don't second-guess Quartz's double-buffering */
     st->dbuf = False;
 # endif
 
index f9abb270546ff0a5d0fbfcf2d585b54ef37652a7..ac7555a66d0049bd7dd5831e4f416ad9ff42b31a 100644 (file)
@@ -52,7 +52,7 @@ static const char sccsid[] = "@(#)ant.c       5.00 2000/11/01 xlockmore";
   Neighbors 6 and neighbors 3 produce the same Turk ants.
 */
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 /*# define DO_STIPPLE*/
 #endif
 
index 46053eda1566fc948409d55daf08b8ec0a8e3858..642efe0b9d3931d368ab2f5b85b462e096656aea 100644 (file)
@@ -1313,7 +1313,7 @@ a2_vt100_printc (apple2_sim_t *sim, struct terminal_controller_data *state,
             free (s);
             goto PRINT;
           } else {
-            c = 0;
+            /* c = 0; */
           }
         }
       }
@@ -1868,7 +1868,7 @@ apple2_draw (Display *dpy, Window window, void *closure)
     st->sim = 0;
   }
 
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   return 0;
 #else
   return 5000;
index bceb4fb499a4d2e2611bc9bafd5b83deaf9a2952..2228a38e4052b93e31d28a7f3077b2a0c7bed65e 100644 (file)
@@ -20,8 +20,6 @@
       I changed the structure of the assembler in this version.
 */
 
-#define NDEBUG  /* Uncomment when done with debugging */
-
 #include <stdlib.h>
 #include <stdio.h>
 /*#include <malloc.h>*/
@@ -41,7 +39,7 @@
 #  define random rand
 #endif*/
 
-#ifndef USE_IPHONE
+#ifndef HAVE_MOBILE
 # define READ_FILES
 #endif
 
@@ -1876,7 +1874,7 @@ static BOOL translate(m6502_Opcodes *op,Param *param, machine_6502 *machine){
        if (op->BRA) {
          pushByte(machine, op->BRA);
           {
-            int diff = abs(param->lbladdr - machine->defaultCodePC);
+            int diff = (param->lbladdr - machine->defaultCodePC);
             int backward = (param->lbladdr < machine->defaultCodePC);
             pushByte(machine, (backward) ? 0xff - diff : diff - 1);
           }
index c841b001bc28e4db4c8064aeac25d7ccd736bb73..331cbcf8e5b8f73a34d053900864e4faa8ce9a3b 100644 (file)
@@ -337,7 +337,7 @@ attraction_init (Display *dpy, Window window)
   st->erase_gc = XCreateGC (dpy, window, GCForeground|GCLineWidth|GCCapStyle,&gcv);
 
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
   jwxyz_XSetAntiAliasing (dpy, st->draw_gc,  False);
   jwxyz_XSetAntiAliasing (dpy, st->erase_gc, False);
 #endif
@@ -1067,7 +1067,7 @@ static const char *attraction_defaults [] = {
   "*vx:                0",
   "*vy:                0",
   "*mouseForeground: white",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
   0
index d6592163f496492db7f104570cbcf0b2bf47bcbf..cd3038ce534b1bf4fc109b621232a387bb3bf6db 100644 (file)
@@ -14,6 +14,7 @@
  */
 
 #include <math.h>
+#include <time.h>
 #include "screenhack.h"
 
 /* non-user-modifiable immutable definitions */
@@ -824,7 +825,7 @@ static void drawDigitChar (struct state *st, Bitmap *b, int x, int y, char c)
     if ((c < '0') || (c > '9'))
       c = '0';
 
-    bitmapDrawChar5x8 (b, x, y, c);
+  bitmapDrawChar5x8 (b, x, y, c);
 }
 
 /* draw a upc/ean digit at the given coordinates */
index f337537d75894e3d0248b3203cddf12ef1913793..3cbaec27ffac7959ccbe0d27a9c6999a78122b90 100644 (file)
 #include "colors.h"
 #include "hsv.h"
 
-#if HAVE_INTTYPES_H
-# include <inttypes.h>
-#else
-typedef unsigned long uint32_t;
-#endif
-
 #define ANTIALIAS   1
 #define BLACK       0
 #define WHITE       1
@@ -43,7 +37,7 @@ typedef unsigned long uint32_t;
 #define max(a,b) ((a)>(b)?(a):(b))
 
 /* better if signed */
-typedef uint32_t pixel_t;
+typedef unsigned long pixel_t;
 
 
 typedef struct {
@@ -90,7 +84,7 @@ static void point2rgb(int depth, pixel_t c, int *r, int *g, int *b)
     switch(depth) {
     case 32:
     case 24:
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
         /* This program idiotically does not go through a color map, so
                we have to hardcode in knowledge of how jwxyz.a packs pixels!
                Fix it to go through st->colors[st->ncolors] instead!
@@ -124,7 +118,7 @@ static pixel_t rgb2point(int depth, int r, int g, int b)
     switch(depth) {
     case 32:
     case 24:
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
         /* This program idiotically does not go through a color map, so
                we have to hardcode in knowledge of how jwxyz.a packs pixels!
                Fix it to go through st->colors[st->ncolors] instead!
@@ -184,7 +178,7 @@ void draw_point ( struct state* st,
 
 
 void print_color ( struct state* st, pixel_t color ) {
-    int r, g, b;
+    int r=0, g=0, b=0;
     point2rgb(st->depth, color, &r, &g, &b);
     printf( "%d %d %d\n", r, g, b);
 }
@@ -389,7 +383,7 @@ static void clamp ( int* value, int l, int h ) {
 }
 
 static pixel_t next_color ( struct state* st, pixel_t current ) {
-    int r, g, b;
+    int r=0, g=0, b=0;
 
     point2rgb(st->depth, current, &r, &g, &b);
     r += random() % 5 - 2;
index 080a277b77933cbd1178f353302eb26c868f84a1..3944146fffa048dad91a15388456691cd93ab6e8 100644 (file)
@@ -739,7 +739,7 @@ blaster_draw (Display *dpy, Window window, void *closure)
 {
   struct state *st = (struct state *) closure;
 
-#ifdef HAVE_COCOA      /* Don't second-guess Quartz's double-buffering */
+#ifdef HAVE_JWXYZ      /* Don't second-guess Quartz's double-buffering */
   XClearWindow (dpy, window);
 #endif
 
@@ -1041,7 +1041,7 @@ blaster_init (Display *d, Window w)
       make_gc (st->r_color5,"r_color5");
       make_gc (st->l_color0,"l_color0");
       make_gc (st->l_color1,"l_color1");
-#ifdef HAVE_COCOA      /* Don't second-guess Quartz's double-buffering */
+#ifdef HAVE_JWXYZ      /* Don't second-guess Quartz's double-buffering */
     st->black = 0;
 #else
                make_gc (st->black,"background");
@@ -1129,7 +1129,7 @@ static const char *blaster_defaults [] = {
   "*move_stars_x: 2",
   "*move_stars_y: 1",
   "*move_stars_random: 0",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
   0
index b0feffead4d7a136b9d2a61dfe5f6a26de9df97a..2be03cd1fb6076d7b4512728fdd39c08cc1e36a6 100644 (file)
@@ -27,6 +27,7 @@
 #include "screenhack.h"
 #include "xpm-pixmap.h"
 #include <stdio.h>
+#include <time.h>
 
 #include "images/som.xbm"
 
@@ -40,7 +41,7 @@
    So, on OSX, we implement the blitter by hand.  It is correct, but
    orders of magnitude slower.
  */
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # define USE_XCOPYAREA
 #endif
 
@@ -422,7 +423,7 @@ static const char *blitspin_defaults [] = {
   "*duration:  120",
   "*bitmap:    (default)",
   "*geometry:  1080x1080",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
   0
index 7fb026040b916a1291aac002f14168bf58d46511..82218fb45c61903c90e7c8ae255ff92c6efa4e85 100644 (file)
@@ -543,7 +543,7 @@ draw_bouboule(ModeInfo * mi)
        Star       *star;
        XArc       *arc = NULL, *arcleft = NULL;
 
-#ifdef HAVE_COCOA      /* Don't second-guess Quartz's double-buffering */
+#ifdef HAVE_JWXYZ      /* Don't second-guess Quartz's double-buffering */
     XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi));
 #endif
 
index c78d11a04439ca9da8e176054abf85cee8641c3c..28be76784d55af9f097fae24cc8407ac7280493b 100644 (file)
@@ -530,9 +530,9 @@ static const char *boxfit_defaults [] = {
   "*borderSize:                   1",
   "*grab:                 False",
   "*peek:                 False",
-  "*grabDesktopImages:     False",   /* HAVE_COCOA */
-  "*chooseRandomImages:    True",    /* HAVE_COCOA */
-#ifdef USE_IPHONE
+  "*grabDesktopImages:     False",   /* HAVE_JWXYZ */
+  "*chooseRandomImages:    True",    /* HAVE_JWXYZ */
+#ifdef HAVE_MOBILE
   "*ignoreRotation:       True",
   "*rotateImages:          True",
 #endif
index 8539b204cc5777c1d50369818b46b6d8266b2ed2..3926f64d1da362865739ddda3aa2982162c49798 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1998-2014 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1998-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
@@ -40,6 +40,7 @@
 #include "apple2.h"
 
 #include <ctype.h>
+#include <time.h>
 
 #ifdef HAVE_XSHM_EXTENSION
 #include "xshm.h"
@@ -49,7 +50,7 @@
 # include <sys/utsname.h>
 #endif /* HAVE_UNAME */
 
-#if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM) || defined(HAVE_COCOA)
+#if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM) || defined(HAVE_JWXYZ)
 # define DO_XPM
 #endif
 
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
 
+# undef MIN
+# undef MAX
+# define MIN(A,B) ((A)<(B)?(A):(B))
+# define MAX(A,B) ((A)>(B)?(A):(B))
+
 #undef EOF
 typedef enum { EOF=0, 
                LEFT, CENTER, RIGHT, 
                LEFT_FULL, CENTER_FULL, RIGHT_FULL, 
                COLOR, INVERT, MOVETO, MARGINS,
-               CURSOR_BLOCK, CURSOR_LINE, RECT, COPY, PIXMAP, IMG,
+               CURSOR_BLOCK, CURSOR_LINE, RECT, COPY, PIXMAP, IMG, FONT,
                PAUSE, CHAR_DELAY, LINE_DELAY,
                LOOP, RESET
 } bsod_event_type;
@@ -87,7 +93,7 @@ struct bsod_state {
   Display *dpy;
   Window window;
   XWindowAttributes xgwa;
-  XFontStruct *font;
+  XFontStruct *font, *fontA, *fontB, *fontC;
   unsigned long fg, bg;
   GC gc;
   int left_margin, right_margin;       /* for text wrapping */
@@ -257,6 +263,15 @@ struct bsod_state {
   (bst)->pos++; \
   } while (0)
 
+/* Switch between fonts A, B and C.
+ */
+#define BSOD_FONT(bst,n) do { \
+  ensure_queue (bst); \
+  (bst)->queue[(bst)->pos].type = FONT; \
+  (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (n)); \
+  (bst)->pos++; \
+  } while (0)
+
 /* 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.
  */
@@ -542,6 +557,18 @@ bsod_pop (struct bsod_state *bst)
       bst->pos++;
       return 0;
     }
+  case FONT:
+    {
+      switch ((long) bst->queue[bst->pos].arg1) {
+      case 0: bst->font = bst->fontA; break;
+      case 1: bst->font = bst->fontB; break;
+      case 2: bst->font = bst->fontC; break;
+      default: abort(); break;
+      }
+      XSetFont (bst->dpy, bst->gc, bst->font->fid);
+      bst->pos++;
+      return 0;
+    }
   case PAUSE:
     {
       long delay = (long) bst->queue[bst->pos].arg1;
@@ -643,7 +670,9 @@ make_bsod_state (Display *dpy, Window window,
   struct bsod_state *bst;
   char buf1[1024], buf2[1024];
   char buf3[1024], buf4[1024];
-  const char *font1, *font2;
+  char buf5[1024], buf6[1024];
+  char buf7[1024], buf8[1024];
+  const char *font1, *font2, *font3, *font4;
 
   bst = (struct bsod_state *) calloc (1, sizeof (*bst));
   bst->queue_size = 10;
@@ -660,7 +689,7 @@ make_bsod_state (Display *dpy, Window window,
        use ".bigFont" if it is loadable, else use ".bigFont2".
    */
   if (
-# ifdef USE_IPHONE
+# ifdef HAVE_MOBILE
       1
 # else
       bst->xgwa.height < 640
@@ -679,9 +708,31 @@ make_bsod_state (Display *dpy, Window window,
       sprintf (buf3, "%.100s.bigFont2", name);
       sprintf (buf4, "%.100s.bigFont2", class);
     }
+  sprintf (buf5, "%.100s.fontB", name);
+  sprintf (buf6, "%.100s.fontB", class);
+  sprintf (buf7, "%.100s.fontC", name);
+  sprintf (buf8, "%.100s.fontC", class);
 
   font1 = get_string_resource (dpy, buf1, buf2);
   font2 = get_string_resource (dpy, buf3, buf4);
+  font3 = get_string_resource (dpy, buf5, buf6);
+  font4 = get_string_resource (dpy, buf7, buf8);
+
+  /* If there was no ".mode.font2" resource also look for ".font2".
+     Under real X11, the wildcard does this, so this is redundant,
+     but jwxyz needs it because it doesn't implement wildcards.
+   */
+# define RES2(VAR, BUF1, BUF2) do {                          \
+    if (! VAR) {                                             \
+      VAR = get_string_resource (dpy,                        \
+                                strchr (BUF1, '.') + 1,     \
+                                strchr (BUF2, '.') + 1);    \
+    }} while(0)
+  RES2 (font1, buf1, buf2);
+  RES2 (font2, buf3, buf4);
+  RES2 (font3, buf5, buf6);
+  RES2 (font4, buf7, buf8);
+#undef RES2
 
   if (font1)
     bst->font = XLoadQueryFont (dpy, font1);
@@ -697,6 +748,17 @@ make_bsod_state (Display *dpy, Window window,
   if (! bst->font)
     abort();
 
+  if (font3)
+    bst->fontB = XLoadQueryFont (dpy, font3);
+  if (font4)
+    bst->fontC = XLoadQueryFont (dpy, font4);
+
+  if (! bst->fontB) bst->fontB = bst->font;
+  if (! bst->fontC) bst->fontC = bst->font;
+
+  bst->fontA = bst->font;
+
+
   gcv.font = bst->font->fid;
 
   sprintf (buf1, "%.100s.foreground", name);
@@ -709,8 +771,8 @@ make_bsod_state (Display *dpy, Window window,
                                                  buf1, buf2);
   bst->gc = XCreateGC (dpy, window, GCFont|GCForeground|GCBackground, &gcv);
 
-#ifdef HAVE_COCOA
-  jwxyz_XSetAntiAliasing (dpy, bst->gc, False);
+#ifdef HAVE_JWXYZ
+  jwxyz_XSetAntiAliasing (dpy, bst->gc, True);
 #endif
 
   bst->left_margin = bst->right_margin = 10;
@@ -813,7 +875,7 @@ windows_31 (Display *dpy, Window window)
 static struct bsod_state *
 windows_nt (Display *dpy, Window window)
 {
-  struct bsod_state *bst = make_bsod_state (dpy, window, "windows", "Windows");
+  struct bsod_state *bst = make_bsod_state (dpy, window, "nt", "NT");
 
   BSOD_TEXT (bst, LEFT,
    "*** STOP: 0x0000001E (0x80000003,0x80106fc0,0x8025ea21,0xfd6829e8)\n"
@@ -1010,6 +1072,135 @@ windows_lh (Display *dpy, Window window)
 }
 
 
+static struct bsod_state *
+windows_10 (Display *dpy, Window window)
+{
+  struct bsod_state *bst = 
+    make_bsod_state (dpy, window, "win10", "Win10");
+
+  int qr_width  = 41;
+  int qr_height = 41;
+  static const unsigned char qr_bits[] = {
+    0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,
+    0x03,0x9A,0x70,0xEE,0x80,0x01,0xFB,0x22,0xAA,0xA6,0xBE,0x01,
+    0x8B,0x8E,0x74,0xE7,0xA2,0x01,0x8B,0xEE,0x42,0xC4,0xA2,0x01,
+    0x8B,0x42,0x6E,0xED,0xA2,0x01,0xFB,0xDA,0x63,0xA6,0xBE,0x01,
+    0x03,0xAA,0xAA,0xAA,0x80,0x01,0xFF,0x8B,0xD8,0x9D,0xFF,0x01,
+    0x63,0x62,0xDA,0x1B,0x98,0x01,0x6F,0x67,0x98,0x9F,0xBC,0x01,
+    0x4F,0xCC,0x55,0x81,0x83,0x01,0xB7,0x6D,0xFF,0x68,0xB2,0x01,
+    0xC3,0x10,0x87,0x8B,0x96,0x01,0x6F,0xB1,0x91,0x58,0x94,0x01,
+    0xE3,0x36,0x88,0x84,0xB8,0x01,0x83,0x9B,0xFE,0x59,0xD7,0x01,
+    0x3B,0x74,0x98,0x5C,0xB4,0x01,0x37,0x75,0xDC,0x91,0xA6,0x01,
+    0x77,0xDE,0x01,0x54,0xBA,0x01,0xBB,0x6D,0x8B,0xB9,0xB5,0x01,
+    0x1F,0x06,0xBD,0x9B,0xB4,0x01,0xD3,0xBD,0x91,0x19,0x84,0x01,
+    0x0B,0x20,0xD8,0x91,0xB4,0x01,0x33,0x95,0xBC,0x0A,0xD5,0x01,
+    0xB3,0x60,0xDC,0xD9,0xB6,0x01,0xEF,0x77,0x18,0x09,0xA4,0x01,
+    0xA3,0xC2,0x95,0x51,0xB2,0x01,0xDF,0x63,0xDB,0xBE,0xB3,0x01,
+    0x03,0x08,0xC9,0x09,0xF0,0x01,0xFF,0xA3,0x19,0xBD,0xFB,0x01,
+    0x03,0x2E,0x84,0xA5,0xAA,0x01,0xFB,0x9A,0xFC,0x9B,0xBB,0x01,
+    0x8B,0x7E,0x9C,0x1D,0xB0,0x01,0x8B,0x6E,0x58,0xA1,0xDB,0x01,
+    0x8B,0xDA,0xD5,0x65,0xA2,0x01,0xFB,0x72,0xFB,0xE9,0xF0,0x01,
+    0x03,0x02,0x99,0x3B,0xB3,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0x01};
+  Pixmap pixmap;
+
+  const char *lines[] = {
+    ":(\n",
+    "\n",
+    "Your PC ran into a problem and needs to restart. We're just\n",
+    "collecting some error info, and then we'll restart for you.\n",
+    "\n",
+    "\n",
+    "\n",
+    "For more information about this issue and\n",
+    "possible fixes, visit\n",
+/*  "https://www.jwz.org/xscreensaver\n",*/
+    "http://youtu.be/-RjmN9RZyr4\n", 
+    "\n",
+    "If you call a support person, give them this info:\n",
+    "Stop code CRITICAL_PROCESS_DIED", 
+ };
+  int i, y = 0, y0 = 0;
+  int line_height0 = bst->fontB->ascent;
+  int line_height1 = bst->fontA->ascent + bst->fontA->descent;
+  int line_height2 = bst->fontC->ascent + bst->fontC->descent;
+  int line_height = line_height0;
+  int top, left0, left;
+  int stop = 60 + (random() % 39);
+
+  line_height1 *= 1.3;
+  line_height2 *= 1.5;
+
+  top = ((bst->xgwa.height - (line_height0 * 1 +
+                              line_height1 * 6 +
+                              line_height2 * 6))
+         / 2);
+
+  {
+    int dir, ascent, descent;
+    XCharStruct ov;
+    const char *s = lines[2];
+    XTextExtents (bst->fontA, s, strlen(s),
+                  &dir, &ascent, &descent, &ov);
+    left = left0 = (bst->xgwa.width - ov.width) / 2;
+  }
+
+  pixmap = XCreatePixmapFromBitmapData (dpy, window, (char *) qr_bits,
+                                        qr_width, qr_height,
+                                        bst->fg, bst->bg, bst->xgwa.depth);
+  for (i = 0; i < 2; i++)
+    {
+      pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual, bst->xgwa.depth,
+                              pixmap, qr_width, qr_height);
+      qr_width *= 2;
+      qr_height *= 2;
+    }
+  bst->pixmap = pixmap;
+
+  y = top;
+  line_height = line_height0;
+  BSOD_FONT (bst, 1);
+  for (i = 0; i < countof(lines); i++)
+    {
+      BSOD_MOVETO (bst, left, y);
+      BSOD_TEXT (bst, LEFT, lines[i]);
+      y += line_height;
+      if (i == 0)
+        {
+          BSOD_FONT (bst, 0);
+          line_height = line_height1;
+        }
+      else if (i == 4)
+        {
+          y0 = y;
+          y += line_height / 2;
+          BSOD_PIXMAP (bst, 0, 0, qr_width, qr_height, left, y + line_height1);
+          BSOD_FONT (bst, 2);
+          line_height = line_height2;
+          left += qr_width + line_height2 / 2;
+# ifdef HAVE_MOBILE
+          y -= 14;
+# endif
+        }
+    }
+
+  left = left0;
+  BSOD_FONT (bst, 0);
+  for (i = 0; i <= stop; i++)
+    {
+      char buf[100];
+      sprintf (buf, "%d%% complete", i);
+      BSOD_MOVETO (bst, left, y0);
+      BSOD_TEXT (bst, LEFT, buf);
+      BSOD_PAUSE (bst, 85000);
+    }
+  BSOD_PAUSE (bst, 3000000);
+
+  XClearWindow (dpy, window);
+  return bst;
+}
+
+
 static struct bsod_state *
 windows_other (Display *dpy, Window window)
 {
@@ -1123,7 +1314,8 @@ sco (Display *dpy, Window window)
 static struct bsod_state *
 sparc_linux (Display *dpy, Window window)
 {
-  struct bsod_state *bst = make_bsod_state (dpy, window, "sco", "SCO");
+  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;
 
@@ -1234,7 +1426,8 @@ amiga (Display *dpy, Window window)
                                &pix_w, &pix_h, 0);
 # endif /* DO_XPM */
 
-  if (pixmap && bst->xgwa.height > 600)        /* scale up the bitmap */
+  if (pixmap &&
+      MIN (bst->xgwa.width, bst->xgwa.height) > 600) /* scale up the bitmap */
     {
       pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual, bst->xgwa.depth,
                               pixmap, pix_w, pix_h);
@@ -1605,7 +1798,7 @@ macx_10_0 (Display *dpy, Window window)
     pixmap = xpm_data_to_pixmap (dpy, window, (char **) happy_mac,
                                  &pix_w, &pix_h, &mask);
 
-# ifdef USE_IPHONE
+# ifdef HAVE_MOBILE
     if (pixmap)
       {
         pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual,
@@ -1897,7 +2090,7 @@ macx (Display *dpy, Window window)
 }
 
 
-#ifndef HAVE_COCOA /* #### I have no idea how to implement this without
+#ifndef HAVE_JWXYZ /* #### I have no idea how to implement this without
                            real plane-masks.  I don't think it would look
                            right if done with alpha-transparency... */
 /* blit damage
@@ -1919,15 +2112,12 @@ blitdamage (Display *dpy, Window window)
   int w, h;
   int chunk_h, chunk_w;
   int steps;
-  long gc_mask = 0;
   int src_x, src_y;
   int x, y;
   
   w = bst->xgwa.width;
   h = bst->xgwa.height;
 
-  gc_mask = GCForeground;
-  
   XSetPlaneMask (dpy, bst->gc, random());
 
   steps = 50;
@@ -1960,7 +2150,7 @@ blitdamage (Display *dpy, Window window)
 
   return bst;
 }
-#endif /* !HAVE_COCOA */
+#endif /* !HAVE_JWXYZ */
 
 
 /*
@@ -2628,7 +2818,7 @@ hppa_linux (Display *dpy, Window window)
      { -1, "Soft power switch enabled, polling @ 0xf0400804.\n" },
      { -1, "pty: 256 Unix98 ptys configured\n" },
      { -1, "Generic RTC Driver v1.07\n" },
-     { -1, "Serial: 8250/16550 driver $Revision: 1.101 $ 13 ports, "
+     { -1, "Serial: 8250/16550 driver $" "Revision: 1.100 $ 13 ports, "
            "IRQ sharing disabled\n" },
      { -1, "ttyS0 at I/O 0x3f8 (irq = 0) is a 16550A\n" },
      { -1, "ttyS1 at I/O 0x2f8 (irq = 0) is a 16550A\n" },
@@ -2987,7 +3177,7 @@ hvx (Display *dpy, Window window)
 static struct bsod_state *
 hpux (Display *dpy, Window window)
 {
-  struct bsod_state *bst = make_bsod_state (dpy, window, "hvx", "HVX");
+  struct bsod_state *bst = make_bsod_state (dpy, window, "hpux", "HPUX");
   const char *sysname;
   char buf[2048];
 
@@ -4071,6 +4261,7 @@ static const struct {
   { "Windows",         windows_31 },
   { "NT",              windows_nt },
   { "Win2K",           windows_other },
+  { "Win10",           windows_10 },
   { "Amiga",           amiga },
   { "Mac",             mac },
   { "MacsBug",         macsbug },
@@ -4082,7 +4273,7 @@ static const struct {
   { "SparcLinux",      sparc_linux },
   { "BSD",             bsd },
   { "Atari",           atari },
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
   { "BlitDamage",      blitdamage },
 #endif
   { "Solaris",         sparc_solaris },
@@ -4103,8 +4294,9 @@ static const struct {
 
 struct driver_state {
   const char *name;
-  int only, which;
-  int delay;
+  int only, which, next_one;
+  int mode_duration;
+  int delay_remaining;
   time_t start;
   Bool debug_p, cycle_p;
   struct bsod_state *bst;
@@ -4114,7 +4306,7 @@ struct driver_state {
 static void
 hack_title (struct driver_state *dst)
 {
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
   char *oname = 0;
   XFetchName (dst->bst->dpy, dst->bst->window, &oname);
   if (oname && !strncmp (oname, "BSOD: ", 6)) {
@@ -4127,7 +4319,7 @@ hack_title (struct driver_state *dst)
     XStoreName (dst->bst->dpy, dst->bst->window, nname);
     free (nname);
   }
-# endif /* !HAVE_COCOA */
+# endif /* !HAVE_JWXYZ */
 }
 
 static void *
@@ -4136,12 +4328,13 @@ bsod_init (Display *dpy, Window window)
   struct driver_state *dst = (struct driver_state *) calloc (1, sizeof(*dst));
   char *s;
 
-  dst->delay = get_integer_resource (dpy, "delay", "Integer");
-  if (dst->delay < 3) dst->delay = 3;
+  dst->mode_duration = get_integer_resource (dpy, "delay", "Integer");
+  if (dst->mode_duration < 3) dst->mode_duration = 3;
 
   dst->debug_p = get_boolean_resource (dpy, "debug", "Boolean");
 
   dst->only = -1;
+  dst->next_one = -1;
   s = get_string_resource(dpy, "doOnly", "DoOnly");
   if (s && !strcasecmp (s, "cycle"))
     {
@@ -4177,7 +4370,7 @@ bsod_draw (Display *dpy, Window window, void *closure)
 
  AGAIN:
   now = time ((time_t *) 0);
-  time_left = dst->start + dst->delay - now;
+  time_left = dst->start + dst->mode_duration - now;
 
   if (dst->bst && dst->bst->img_loader)   /* still loading */
     {
@@ -4186,11 +4379,27 @@ bsod_draw (Display *dpy, Window window, void *closure)
       return 100000;
     }
 
+ DELAY_NOW:
+  /* Rather than returning a multi-second delay from the draw() routine,
+     meaning "don't call us again for N seconds", we quantize that down
+     to 1/10th second intervals so that it's more responsive to
+     rotate/reshape events.
+   */
+  if (dst->delay_remaining)
+    {
+      int inc = 10000;
+      int this_delay = MIN (dst->delay_remaining, inc);
+      dst->delay_remaining = MAX (0, dst->delay_remaining - inc);
+      return this_delay;
+    }
+
   if (! dst->bst && time_left > 0)     /* run completed; wait out the delay */
     {
       if (dst->debug_p)
         fprintf (stderr, "%s: %s: %d left\n", progname, dst->name, time_left);
-      return 500000;
+      dst->start = 0;
+      if (time_left > 5) time_left = 5;  /* Boooored now */
+      dst->delay_remaining = 1000000 * time_left;
     }
 
   else if (dst->bst)                   /* sub-mode currently running */
@@ -4200,12 +4409,15 @@ bsod_draw (Display *dpy, Window window, void *closure)
       if (time_left > 0)
         this_delay = bsod_pop (dst->bst);
 
-      /* XSync (dpy, False);  slows down char drawing too much on HAVE_COCOA */
+      /* XSync (dpy, False);  slows down char drawing too much on HAVE_JWXYZ */
 
       if (this_delay == 0)
         goto AGAIN;                    /* no delay, not expired: stay here */
       else if (this_delay >= 0)
-        return this_delay;             /* return; time to sleep */
+        {
+          dst->delay_remaining = this_delay;   /* return; time to sleep */
+          goto DELAY_NOW;
+        }
       else
         {                              /* sub-mode run completed or expired */
           if (dst->debug_p)
@@ -4217,7 +4429,9 @@ bsod_draw (Display *dpy, Window window, void *closure)
     }
   else                                 /* launch a new sub-mode */
     {
-      if (dst->cycle_p)
+      if (dst->next_one >= 0)
+        dst->which = dst->next_one, dst->next_one = -1;
+      else if (dst->cycle_p)
         dst->which = (dst->which + 1) % countof(all_modes);
       else if (dst->only >= 0)
         dst->which = dst->only;
@@ -4300,11 +4514,13 @@ bsod_reshape (Display *dpy, Window window, void *closure,
   if (dst->debug_p)
     fprintf (stderr, "%s: %s: reshape reset\n", progname, dst->name);
 
-  /* just pick a new mode and restart when the window is resized. */
+  /* just restart this mode and restart when the window is resized. */
   if (dst->bst)
     free_bsod_state (dst->bst);
   dst->bst = 0;
   dst->start = 0;
+  dst->delay_remaining = 0;
+  dst->next_one = dst->which;
   dst->name = "none";
   XClearWindow (dpy, window);
 }
@@ -4329,6 +4545,7 @@ bsod_event (Display *dpy, Window window, void *closure, XEvent *event)
         free_bsod_state (dst->bst);
       dst->bst = 0;
       dst->start = 0;
+      dst->delay_remaining = 0;
       dst->name = "none";
       XClearWindow (dpy, window);
       return True;
@@ -4356,6 +4573,7 @@ static const char *bsod_defaults [] = {
   "*doWindows:            True",
   "*doNT:                 True",
   "*doWin2K:              True",
+  "*doWin10:              True",
   "*doAmiga:              True",
   "*doMac:                True",
   "*doMacsBug:            True",
@@ -4382,21 +4600,22 @@ static const char *bsod_defaults [] = {
   "*doGLaDOS:             True",
   "*doAndroid:            True",
 
-  "*font:                 9x15bold",
-  "*font2:                -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
-  "*bigFont:              -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
-  "*bigFont2:             -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
-
   ".foreground:                   White",
   ".background:                   Black",
 
   ".windows.foreground:           White",
   ".windows.background:           #0000AA",    /* EGA color 0x01. */
 
+  ".nt.foreground:        White",
+  ".nt.background:        #0000AA",    /* EGA color 0x01. */
+
   ".windowslh.foreground:  White",
   ".windowslh.background:  #AA0000",    /* EGA color 0x04. */
   ".windowslh.background2: #AAAAAA",    /* EGA color 0x07. */
 
+  ".win10.foreground:      White",
+  ".win10.background:      #1070AA",
+
   ".glaDOS.foreground:    White",
   ".glaDOS.background:    #0000AA",    /* EGA color 0x01. */
 
@@ -4410,8 +4629,6 @@ static const char *bsod_defaults [] = {
   ".atari.foreground:     Black",
   ".atari.background:     White",
 
-  ".macsbug.font:         -*-courier-medium-r-*-*-*-80-*-*-m-*-*-*",
-  ".macsbug.bigFont:      -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
   ".macsbug.foreground:           Black",
   ".macsbug.background:           White",
   ".macsbug.borderColor:   #AAAAAA",
@@ -4424,55 +4641,39 @@ static const char *bsod_defaults [] = {
   ".macx.textBackground:   Black",
   ".macx.background:      #888888",
 
-  ".macdisk.font:         -*-courier-bold-r-*-*-*-80-*-*-m-*-*-*",
-  ".macdisk.bigFont:      -*-courier-bold-r-*-*-*-100-*-*-m-*-*-*",
-
-  ".sco.font:             -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
   ".sco.foreground:       White",
   ".sco.background:       Black",
 
-  ".hvx.font:             -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
   ".hvx.foreground:       White",
   ".hvx.background:       Black",
 
   ".linux.foreground:      White",
   ".linux.background:      Black",
 
-  ".hppalinux.bigFont:    -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
   ".hppalinux.foreground:  White",
   ".hppalinux.background:  Black",
 
-  ".sparclinux.bigFont:           -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
   ".sparclinux.foreground: White",
   ".sparclinux.background: Black",
 
-  ".bsd.font:             vga",
-  ".bsd.bigFont:          -sun-console-medium-r-*-*-22-*-*-*-m-*-*-*",
-  ".bsd.bigFont2:         -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
   ".bsd.foreground:       #c0c0c0",
   ".bsd.background:       Black",
 
-  ".solaris.font:          -sun-gallant-*-*-*-*-19-*-*-*-*-120-*-*",
   ".solaris.foreground:    Black",
   ".solaris.background:    White",
 
-  ".hpux.bigFont:         -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
   ".hpux.foreground:      White",
   ".hpux.background:      Black",
 
-  ".os390.bigFont:        -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
   ".os390.background:     Black",
   ".os390.foreground:     Red",
 
-  ".tru64.bigFont:        -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
   ".tru64.foreground:     White",
   ".tru64.background:     #0000AA",    /* EGA color 0x01. */
 
-  ".vms.bigFont:          -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
   ".vms.foreground:       White",
   ".vms.background:       Black",
 
-  ".msdos.bigFont:        -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
   ".msdos.foreground:     White",
   ".msdos.background:     Black",
 
@@ -4500,16 +4701,116 @@ static const char *bsod_defaults [] = {
   "*useSHM:                True",
 #endif
 
-# ifdef USE_IPHONE
-  "*font:                 Courier-Bold 9",
-  ".amiga.font:                   Courier-Bold 12",
-  ".macsbug.font:         Courier-Bold 5",
-  ".sco.font:             Courier-Bold 9",
-  ".hvx.font:             Courier-Bold 9",
-  ".bsd.font:             Courier-Bold 9",
-  ".solaris.font:          Courier-Bold 6",
-  ".macdisk.font:          Courier-Bold 6",
-# endif
+  "*fontB:                ",
+  "*fontC:                ",
+
+# if defined(USE_IPHONE)
+
+  "*font:                 PxPlus IBM VGA8 16, Courier-Bold 14",
+  "*bigFont:              ",
+  "*font2:                ",
+  "*bigFont2:             ",
+
+  ".mac.font:             Courier-Bold 18",
+  ".macsbug.font:         Courier-Bold 8",
+  ".macx.font:            Courier-Bold 14",
+  ".macdisk.font:         Courier-Bold 14",
+  ".msdos.font:                   PxPlus IBM VGA8 32, Courier-Bold 28",
+  ".nt.font:              PxPlus IBM VGA8 12, Courier-Bold 10",
+  ".win10.font:                   Arial 12, Helvetica 12",
+  ".win10.bigFont:        Arial 12, Helvetica 12",
+  ".win10.fontB:          Arial 50, Helvetica 50",
+  ".win10.fontC:          Arial 9, Helvetica 9",
+  ".win10.bigFont2:       ",
+
+# elif defined(HAVE_ANDROID)
+
+  "*font:                 PxPlus IBM VGA8 16",
+  "*bigFont:              ",
+  "*font2:                ",
+  "*bigFont2:             ",
+
+  ".mac.font:             -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
+  ".macsbug.font:         -*-courier-bold-r-*-*-*-80-*-*-m-*-*-*",
+  ".macx.font:            -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
+  ".macdisk.font:         -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
+  ".msdos.font:                   PxPlus IBM VGA8 32",
+  ".nt.font:              PxPlus IBM VGA8 12",
+
+  ".win10.font:                   -*-helvetica-medium-r-*-*-*-120-*-*-*-*-*-*",
+  ".win10.bigFont:        -*-helvetica-medium-r-*-*-*-120-*-*-*-*-*-*",
+  ".win10.fontB:          -*-helvetica-medium-r-*-*-*-500-*-*-*-*-*-*",
+  ".win10.fontC:          -*-helvetica-medium-r-*-*-*-90-*-*-*-*-*-*",
+  ".win10.bigFont2:       ",
+
+# elif defined(HAVE_COCOA)
+
+  "*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",
+
+  ".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",
+
+  ".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",
+  ".win10.fontB:          Arial 100, Helvetica 100",
+  ".win10.fontC:          Arial 16, Helvetica 16",
+  ".win10.bigFont2:       ",
+
+# else   /* X11 */
+
+  "*font:                 9x15bold",
+  "*font2:                -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
+  "*bigFont:              -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
+  "*bigFont2:             -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
+
+  ".macsbug.font:         -*-courier-medium-r-*-*-*-80-*-*-m-*-*-*",
+  ".macsbug.bigFont:      -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
+
+  ".macdisk.font:         -*-courier-bold-r-*-*-*-80-*-*-m-*-*-*",
+  ".macdisk.bigFont:      -*-courier-bold-r-*-*-*-100-*-*-m-*-*-*",
+
+  ".sco.font:             -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
+  ".hvx.font:             -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
+  ".hppalinux.bigFont:    -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
+  ".sparclinux.bigFont:           -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
+
+  ".bsd.font:             vga",
+  ".bsd.bigFont:          -sun-console-medium-r-*-*-22-*-*-*-m-*-*-*",
+  ".bsd.bigFont2:         -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
+
+  ".solaris.font:          -sun-gallant-*-*-*-*-19-*-*-*-*-120-*-*",
+  ".hpux.bigFont:         -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
+  ".os390.bigFont:        -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
+  ".tru64.bigFont:        -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
+  ".vms.bigFont:          -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
+  ".msdos.bigFont:        -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
+
+  ".win10.font:                   -*-helvetica-medium-r-*-*-*-180-*-*-*-*-*-*",
+  ".win10.bigFont:        -*-helvetica-medium-r-*-*-*-180-*-*-*-*-*-*",
+  ".win10.fontB:          -*-helvetica-medium-r-*-*-*-240-*-*-*-*-*-*",
+  ".win10.fontC:          -*-helvetica-medium-r-*-*-*-140-*-*-*-*-*-*",
+  ".win10.font2:          ",
+  ".win10.bigFont2:       ",
+
+# endif  /* X11 */
 
   0
 };
@@ -4524,6 +4825,8 @@ static const XrmOptionDescRec bsod_options [] = {
   { "-no-nt",          ".doNT",                XrmoptionNoArg,  "False" },
   { "-2k",             ".doWin2K",             XrmoptionNoArg,  "True"  },
   { "-no-2k",          ".doWin2K",             XrmoptionNoArg,  "False" },
+  { "-win10",          ".doWin10",             XrmoptionNoArg,  "True"  },
+  { "-no-win10",       ".doWin10",             XrmoptionNoArg,  "False" },
   { "-amiga",          ".doAmiga",             XrmoptionNoArg,  "True"  },
   { "-no-amiga",       ".doAmiga",             XrmoptionNoArg,  "False" },
   { "-mac",            ".doMac",               XrmoptionNoArg,  "True"  },
index 1741a5d9ccd0722618e1e1ac059df8137ac6c62e..874e25d4e89b84873b0aaa169900523cca1f5523 100644 (file)
@@ -76,6 +76,7 @@ hacks are displayed and which aren't.
 .BR doWindows ,
 .BR doNT ,
 .BR doWin2K ,
+.BR doWin10 ,
 .BR doAmiga ,
 .BR doMac ,
 .BR doMac1 ,
index 11ce3e6279fbc31f6a648cf1364c2a2e4080d35e..4d6b239b9e182a42f9f280a993b320d93693ef50 100644 (file)
@@ -5,7 +5,7 @@
 #ifndef _BUBBLES_H_
 #define _BUBBLES_H_
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
 # include "jwxyz.h"
 # define HAVE_XPM
 #else
index a0b7345cfd4207607f3a8de854218af9decc580a..60de04a3c9ebb87957e3b782a4f1ed942cf2a284 100644 (file)
@@ -30,6 +30,7 @@
 
 
 #include <math.h>
+#include <time.h>
 #include <inttypes.h>
 #include "screenhack.h"
 
@@ -63,7 +64,7 @@ static const char *bumps_defaults [] = {
 #ifdef HAVE_XSHM_EXTENSION
   "*useSHM:            True",
 #endif /* HAVE_XSHM_EXTENSION */
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
   "*rotateImages:   True",
 #endif
index 057fed0b256a4aca37c03664da60e9f975a46c7a..23b53e84da9f2bfdb92344fa646cba5239c8ea19 100644 (file)
@@ -849,7 +849,7 @@ static const char *ccurve_defaults [] =
     ".delay:      3",
     ".pause:      0.4",
     ".limit: 200000",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
     "*ignoreRotation: True",
 #endif
     0
index 6ce4e7074dadb899a8a2e9e749d11c1c33d1bd72..890b3982a96d6a2b98c5c0d6bf3665e64b425802 100644 (file)
  */
 
 #include <math.h>
-#include <assert.h>
 #include "screenhack.h"
 #include "erase.h"
 
 #define SQRT_3 1.73205080756887729352
+#undef assert
+#define assert(EXP) do { if (!((EXP))) abort(); } while(0)
 
 /*-----------------------------------------*/
 
@@ -838,7 +839,7 @@ static const char *celtic_defaults[] = {
     "*delay: 10000",
     "*delay2: 5",
     "*showGraph: False",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
     "*ignoreRotation: True",
 #endif
     0
index 789a45e084d17db10eda6a33b9712c373f0c7498..d4ec71990875cf965b69944cc773b60208411a95 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/perl -w
-# Copyright © 2008-2014 Jamie Zawinski <jwz@jwz.org>
+# Copyright © 2008-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
@@ -12,6 +12,8 @@
 # This parses the .c and .xml files and makes sure they are in sync: that
 # options are spelled the same, and that all the numbers are in sync.
 #
+# It also converts the hacks/config/ XML files into the Android XML files.
+#
 # Created:  1-Aug-2008.
 
 require 5;
@@ -19,11 +21,22 @@ use diagnostics;
 use strict;
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my ($version) = ('$Revision: 1.12 $' =~ m/\s(\d[.\d]+)\s/s);
+my ($version) = ('$Revision: 1.21 $' =~ m/\s(\d[.\d]+)\s/s);
 
 my $verbose = 0;
+my $debug_p = 0;
 
 
+my $text_default_opts = '';
+foreach (qw(text-mode text-literal text-file text-url text-program)) {
+  my $s = $_; $s =~ s/-(.)/\U$1/g; $s =~ s/url/URL/si;
+  $text_default_opts .= "{\"-$_\", \".$s\", XrmoptionSepArg, 0},\n";
+}
+my $image_default_opts = '';
+foreach (qw(choose-random-images grab-desktop-images)) {
+  my $s = $_; $s =~ s/-(.)/\U$1/g;
+  $image_default_opts .= "{\"-$_\", \".$s\", XrmoptionSepArg, 0},\n";
+}
 my $xlockmore_default_opts = '';
 foreach (qw(count cycles delay ncolors size font)) {
   $xlockmore_default_opts .= "{\"-$_\", \".$_\", XrmoptionSepArg, 0},\n";
@@ -60,10 +73,14 @@ sub parse_src($) {
   $file = 'b_lockglue.c' if ($file eq 'bubble3d.c');
   $file = 'polyhedra-gl.c' if ($file eq 'polyhedra.c');
   $file = 'companion.c' if ($file eq 'companioncube.c');
+  $file = 'rd-bomb.c' if ($file eq 'rdbomb.c');
 
-  $file = "glx/$file" unless (-f $file);
+  my $ofile = $file;
+  $file = "glx/$ofile"          unless (-f $file);
+  $file = "../hacks/$ofile"     unless (-f $file);
+  $file = "../hacks/glx/$ofile" unless (-f $file);
   my $body = '';
-  open (my $in, '<', $file) || error ("$file: $!");
+  open (my $in, '<', $file) || error ("$ofile: $!");
   while (<$in>) { $body .= $_; }
   close $in;
   $file =~ s@^.*/@@;
@@ -71,10 +88,13 @@ sub parse_src($) {
   my $xlockmore_p = 0;
   my $thread_p = ($body =~ m/THREAD_DEFAULTS/);
   my $analogtv_p = ($body =~ m/ANALOGTV_DEFAULTS/);
+  my $text_p = ($body =~ m/"textclient\.h"/);
+  my $grab_p = ($body =~ m/load_image_async/);
 
   $body =~ s@/\*.*?\*/@@gs;
   $body =~ s@^#\s*(if|ifdef|ifndef|elif|else|endif).*$@@gm;
   $body =~ s/(THREAD|ANALOGTV)_(DEFAULTS|OPTIONS)(_XLOCK)?//gs;
+  $body =~ s/__extension__//gs;
 
   print STDERR "$progname: $file: defaults:\n" if ($verbose > 2);
   my %res_to_val;
@@ -101,6 +121,7 @@ sub parse_src($) {
       my ($key, $val) = m@^([^:\s]+)\s*:\s*(.*?)\s*$@;
       print STDERR "$progname: $file: unparsable: $_\n" unless $key;
       $key =~ s/^[.*]//s;
+      $val =~ s/"\s*"\s*$//s;
       $res_to_val{$key} = $val;
       print STDERR "$progname: $file:   $key = $val\n" if ($verbose > 2);
     }
@@ -122,18 +143,29 @@ sub parse_src($) {
     error ("$file: no module name");
   $res_to_val{progclass} = $2;
   $res_to_val{doFPS} = 'false';
+  $res_to_val{textMode} = 'date';
+  $res_to_val{textLiteral} = '';
+  $res_to_val{textURL} =
+    'https://en.wikipedia.org/w/index.php?title=Special:NewPages&feed=rss';
+  $res_to_val{grabDesktopImages} = 'true';
+  $res_to_val{chooseRandomImages} = 'true';
+
   print STDERR "$progname: $file:   progclass = $2\n" if ($verbose > 2);
 
   print STDERR "$progname: $file: switches to resources:\n"
     if ($verbose > 2);
   my %switch_to_res;
-  $switch_to_res{-fps} = 'doFPS: true';
-  $switch_to_res{-fg}  = 'foreground: %';
-  $switch_to_res{-bg}  = 'background: %';
+  $switch_to_res{'-fps'} = 'doFPS: true';
+  $switch_to_res{'-fg'}  = 'foreground: %';
+  $switch_to_res{'-bg'}  = 'background: %';
+  $switch_to_res{'-no-grab-desktop-images'}  = 'grabDesktopImages: false';
+  $switch_to_res{'-no-choose-random-images'}  = 'chooseRandomImages: false';
 
   my ($ign, $opts) = ($body =~ m/(_options|\bopts)\s*\[\]\s*=\s*{(.*?)}\s*;/s);
   if  ($xlockmore_p || $thread_p || $analogtv_p || $opts) {
     $opts = '' unless $opts;
+    $opts .= ",\n$text_default_opts" if ($text_p);
+    $opts .= ",\n$image_default_opts" if ($grab_p);
     $opts .= ",\n$xlockmore_default_opts" if ($xlockmore_p);
     $opts .= ",\n$thread_default_opts" if ($thread_p);
     $opts .= ",\n$analogtv_default_opts" if ($analogtv_p);
@@ -142,7 +174,7 @@ sub parse_src($) {
       s/^\s*//s;
       s/\s*$//s;
       next if m/^$/s;
-      next if m/^{\s*0\s*,/s;
+      next if m/^\{\s*0\s*,/s;
       my ($switch, $res, $type, $v0, $v1, $v2) =
         m@^ \s* { \s * \"([^\"]+)\" \s* ,
                   \s * \"([^\"]+)\" \s* ,
@@ -176,26 +208,55 @@ sub parse_src($) {
 #    "resource = default value"
 # or "resource != non-default value"
 #
-sub parse_xml($$) {
-  my ($saver, $switch_to_res) = @_;
+# Also a hash of the simplified XML contents.
+#
+sub parse_xml($$$) {
+  my ($saver, $switch_to_res, $src_opts) = @_;
+
+  my $saver_title = undef;
+  my $gl_p = 0;
   my $file = "config/" . lc($saver) . ".xml";
+  my $ofile = $file;
+  $file = "../hacks/$ofile" unless (-f $file);
   my $body = '';
-  local *IN;
-  open (IN, "<$file") || error ("$file: $!");
-  while (<IN>) { $body .= $_; }
-  close IN;
+  open (my $in, '<', $file) || error ("$ofile: $!");
+  while (<$in>) { $body .= $_; }
+  close $in;
   $file =~ s@^.*/@@;
 
   my @result = ();
 
+  $body =~ s@<xscreensaver-text\s*/?>@
+    <select id="textMode">
+      <option id="date"  _label="Display the date and time"/>
+      <option id="text"  _label="Display static text"
+        arg-set="-text-mode literal"/>
+      <option id="url"   _label="Display the contents of a URL"
+        arg-set="-text-mode url"/>
+    </select>
+    <string id="textLiteral" _label="Text to display" arg="-text-literal %"/>
+    <string id="textURL" _label="URL to display" arg="-text-url %"/>
+    @gs;
+
+  $body =~ s@<xscreensaver-image\s*/?>@
+    <boolean id="grabDesktopImages" _label="Grab screenshots"
+       arg-unset="-no-grab-desktop-images"/>
+    <boolean id="chooseRandomImages" _label="Use photo library"
+       arg-unset="-no-choose-random-images"/>
+    @gs;
+
   $body =~ s/<!--.*?-->/ /gsi;
 
+  $body =~ s@(<(_description)>.*?</\2>)@{ $_ = $1; s/\n/\002/gs; $_; }@gsexi;
+
   $body =~ s/\s+/ /gs;
   $body =~ s/</\001</gs;
   $body =~ s/\001(<option)/$1/gs;
 
   my $video = undef;
 
+  my @widgets = ();
+
   print STDERR "$progname: $file: options:\n" if ($verbose > 2);
   foreach (split (m/\001/, $body)) {
     next if (m/^\s*$/s);
@@ -203,13 +264,33 @@ sub parse_xml($$) {
     error ("$progname: $file: unparsable: $_") unless $type;
     next if ($type =~ m@^/@);
 
-    if ($type =~ m/^([hv]group|\?xml|command|string|file|_description|xscreensaver-(image|text|updater))/s) {
+    my $ctrl = { type => $type };
+
+    if ($type =~ m/^( [hv]group |
+                      \?xml |
+                      command |
+                      file |
+                      xscreensaver-image |
+                      xscreensaver-updater
+                    )/sx) {
+      $ctrl = undef;
+
+    } elsif ($type eq '_description') {
+      $args =~ s/\002/\n/gs;
+      $args =~ s@^>\s*@@s;
+      $args =~ s/^\n*|\s*$//gs;
+      $ctrl->{text} = $args;
 
     } elsif ($type eq 'screensaver') {
-      my ($name) = ($args =~ m/\b_label\s*=\s*\"([^\"]+)\"/);
-      my $val = "progclass = $name";
+      ($saver_title) = ($args =~ m/\b_label\s*=\s*\"([^\"]+)\"/s);
+      ($gl_p) = ($args =~ m/\bgl="?yes/s);
+      my $s = $saver_title;
+      $s =~ s/\s+//gs;
+      my $val = "progclass = $s";
       push @result, $val;
-      print STDERR "$progname: $file:   name:    $name\n" if ($verbose > 2);
+      print STDERR "$progname: $file:   name:    $saver_title\n"
+        if ($verbose > 2);
+      $ctrl = undef;
 
     } elsif ($type eq 'video') {
       error ("$file: multiple videos") if $video;
@@ -217,35 +298,7 @@ sub parse_xml($$) {
       error ("$file: unparsable video") unless $video;
       error ("$file: unparsable video URL")
         unless ($video =~ m@^https?://www\.youtube\.com/watch\?v=[^?&]+$@s);
-
-    } elsif ($type eq 'number') {
-      my ($arg) = ($args =~ m/\barg\s*=\s*\"([^\"]+)\"/);
-      my ($val) = ($args =~ m/\bdefault\s*=\s*\"([^\"]+)\"/);
-      $val = '' unless defined($val);
-
-      my $switch = $arg;
-      $switch =~ s/\s+.*$//;
-      my ($res) = $switch_to_res->{$switch};
-      error ("$file: no resource for $type switch \"$arg\"") unless $res;
-      $res =~ s/: \%$//;
-      error ("$file: unparsable value: $res") if ($res =~ m/:/);
-      $val = "$res = $val";
-      push @result, $val;
-      print STDERR "$progname: $file:   number:  $val\n" if ($verbose > 2);
-
-    } elsif ($type eq 'boolean') {
-      my ($set)   = ($args =~ m/\barg-set\s*=\s*\"([^\"]+)\"/);
-      my ($unset) = ($args =~ m/\barg-unset\s*=\s*\"([^\"]+)\"/);
-      my ($arg) = $set || $unset || error ("$file: unparsable: $args");
-      my ($res) = $switch_to_res->{$arg};
-        error ("$file: no resource for boolean switch \"$arg\"") unless $res;
-      my ($res2, $val) = ($res =~ m/^(.*?): (.*)$/s);
-      error ("$file: unparsable boolean resource: $res") unless $res2;
-      $res = $res2;
-#      $val = ($set ? "$res != $val" : "$res = $val");
-      $val = "$res != $val";
-      push @result, $val;
-      print STDERR "$progname: $file:   boolean: $val\n" if ($verbose > 2);
+      $ctrl = undef;
 
     } elsif ($type eq 'select') {
       $args =~ s/</\001</gs;
@@ -253,9 +306,23 @@ sub parse_xml($$) {
       shift @opts;
       my $unset_p = 0;
       my $this_res = undef;
+      my @menu = ();
       foreach (@opts) {
-        error ("$file: unparsable: $_") unless (m/^<option\s/);
-        my ($set) = m/\barg-set\s*=\s*\"([^\"]+)\"/;
+        error ("$file: unparsable option: $_") unless (m/^<option\s/);
+
+        my %item;
+        my $opt = $_;
+        $opt =~ s@^<option\s+@@s;
+        $opt =~ s@[?/]>\s*$@@s;
+        while ($opt =~ s/^\s*([^\s]+)\s*=\s*"(.*?)"\s*(.*)/$3/s) {
+          my ($k, $v) = ($1, $2);
+          $item{$k} = $v;
+        }
+
+        error ("unparsable XML option line: $_ [$opt]") if ($opt);
+        push @menu, \%item;
+
+        my ($set) = $item{'arg-set'};
         if ($set) {
           my ($set2, $val) = ($set =~ m/^(.*?) (.*)$/s);
           $set = $set2 if ($set2);
@@ -266,6 +333,7 @@ sub parse_xml($$) {
           error ("$file: unparsable select resource: $res") unless $res2;
           $res = $res2;
           $val = $val2 unless ($val2 eq '%');
+          $item{value} = $val;
 
           error ("$file: mismatched resources: $res vs $this_res")
             if (defined($this_res) && $this_res ne $res);
@@ -280,16 +348,86 @@ sub parse_xml($$) {
           $unset_p++;
         }
       }
+      $ctrl->{resource} = $this_res;
+      $ctrl->{default} = $src_opts->{$this_res};
+      $ctrl->{menu} = \@menu;
 
     } else {
-      error ("$file: unknown type \"$type\" for no arg");
+
+      my $rest = $args;
+      $rest =~ s@[/?]*>\s*$@@s;
+      while ($rest =~ s/^\s*([^\s]+)\s*=\s*"(.*?)"\s*(.*)/$3/s) {
+        my ($k, $v) = ($1, $2);
+        $ctrl->{$k} = $v;
+      }
+      error ("unparsable XML line: $args [$rest]") if ($rest);
+
+      if ($type eq 'number') {
+        my ($arg) = $ctrl->{arg};
+        my ($val) = $ctrl->{default};
+        $val = '' unless defined($val);
+
+        my $switch = $arg;
+        $switch =~ s/\s+.*$//;
+        my ($res) = $switch_to_res->{$switch};
+        error ("$file: no resource for $type switch \"$arg\"") unless $res;
+
+        $res =~ s/: \%$//;
+        error ("$file: unparsable value: $res") if ($res =~ m/:/);
+        $ctrl->{resource} = $res;
+
+        $val = "$res = $val";
+        push @result, $val;
+        print STDERR "$progname: $file:   number:  $val\n" if ($verbose > 2);
+
+      } elsif ($type eq 'boolean') {
+        my ($set)   = $ctrl->{'arg-set'};
+        my ($unset) = $ctrl->{'arg-unset'};
+        my ($arg) = $set || $unset || error ("$file: unparsable: $args");
+        my ($res) = $switch_to_res->{$arg};
+          error ("$file: no resource for boolean switch \"$arg\"") unless $res;
+
+        my ($res2, $val) = ($res =~ m/^(.*?): (.*)$/s);
+        error ("$file: unparsable boolean resource: $res") unless $res2;
+        $res = $res2;
+
+        $ctrl->{resource} = $res;
+        $ctrl->{convert} = 'invert' if ($val =~ m/false/i);
+        $ctrl->{default} = ($ctrl->{convert} ? 'true' : 'false');
+
+#       $val = ($set ? "$res != $val" : "$res = $val");
+        $val = "$res != $val";
+        push @result, $val;
+        print STDERR "$progname: $file:   boolean: $val\n" if ($verbose > 2);
+
+      } elsif ($type eq 'string') {
+        my ($arg) = $ctrl->{arg};
+
+        my $switch = $arg;
+        $switch =~ s/\s+.*$//;
+        my ($res) = $switch_to_res->{$switch};
+        error ("$file: no resource for $type switch \"$arg\"") unless $res;
+
+        $res =~ s/: \%$//;
+        error ("$file: unparsable value: $res") if ($res =~ m/:/);
+        $ctrl->{resource} = $res;
+        $ctrl->{default} = $src_opts->{$res};
+        my $val = "$res = %";
+        push @result, $val;
+        print STDERR "$progname: $file:   string:  $val\n" if ($verbose > 2);
+
+      } else {
+        error ("$file: unknown type \"$type\" for no arg");
+      }
     }
+
+    push @widgets, $ctrl if $ctrl;
   }
 
 #  error ("$file: no video") unless $video;
   print STDERR "\n$file: WARNING: no video\n\n" unless $video;
 
-  return @result;
+  return ($saver_title, $gl_p, \@result, \@widgets);
 }
 
 
@@ -300,22 +438,24 @@ sub check_config($) {
   return 0 if ($saver =~ m/(-helper)$/);
 
   my ($src_opts, $switchmap) = parse_src ($saver);
-  my (@xml_opts) = parse_xml ($saver, $switchmap);
+  my ($saver_title, $gl_p, $xml_opts, $widgets) =
+    parse_xml ($saver, $switchmap, $src_opts);
 
   my $failures = 0;
-  foreach my $claim (@xml_opts) {
+  foreach my $claim (@$xml_opts) {
     my ($res, $compare, $xval) = ($claim =~ m/^(.*) (=|!=) (.*)$/s);
-    error ("$saver: unparsable xml claim: $_") unless $compare;
+    error ("$saver: unparsable xml claim: $claim") unless $compare;
 
     my $sval = $src_opts->{$res};
-    if ($res =~ m/^TV/) {
+    if ($res =~ m/^TV|^text-mode/) {
       print STDERR "$progname: $saver: OK: skipping \"$res\"\n"
         if ($verbose > 1);
     } elsif (!defined($sval)) {
       print STDERR "$progname: $saver: $res: not in source\n";
-    } elsif ($compare eq '!='
-             ? $sval eq $xval
-             : $sval ne $xval) {
+    } elsif ($claim !~ m/ = %$/s &&
+             ($compare eq '!='
+              ? $sval eq $xval
+              : $sval ne $xval)) {
       print STDERR "$progname: $saver: " .
         "src has \"$res = $sval\", xml has \"$claim\"\n";
       $failures++;
@@ -330,6 +470,7 @@ sub check_config($) {
   my $obd = "../OSX/build/Debug";
   if (-d $obd) {
     my $progclass = $src_opts->{progclass};
+    $progclass = 'DNAlogo' if ($progclass eq 'DNALogo');
     my $f = (glob("$obd/$progclass.saver*"))[0];
     if (!$f && $progclass ne 'Flurry') {
       print STDERR "$progname: $progclass.saver does not exist\n";
@@ -344,6 +485,618 @@ sub check_config($) {
 }
 
 
+# Returns true if the two files differ (by running "cmp")
+#
+sub cmp_files($$) {
+  my ($file1, $file2) = @_;
+
+  my @cmd = ("cmp", "-s", "$file1", "$file2");
+  print STDERR "$progname: executing \"" . join(" ", @cmd) . "\"\n"
+    if ($verbose > 3);
+
+  system (@cmd);
+  my $exit_value  = $? >> 8;
+  my $signal_num  = $? & 127;
+  my $dumped_core = $? & 128;
+
+  error ("$cmd[0]: core dumped!") if ($dumped_core);
+  error ("$cmd[0]: signal $signal_num!") if ($signal_num);
+  return $exit_value;
+}
+
+
+sub diff_files($$) {
+  my ($file1, $file2) = @_;
+
+  my @cmd = ("diff", 
+             "-U1",
+#            "-w",
+             "--unidirectional-new-file", "$file1", "$file2");
+  print STDERR "$progname: executing \"" . join(" ", @cmd) . "\"\n"
+    if ($verbose > 3);
+
+  system (@cmd);
+  my $exit_value  = $? >> 8;
+  my $signal_num  = $? & 127;
+  my $dumped_core = $? & 128;
+
+  error ("$cmd[0]: core dumped!") if ($dumped_core);
+  error ("$cmd[0]: signal $signal_num!") if ($signal_num);
+  return $exit_value;
+}
+
+
+# If the two files differ:
+#   mv file2 file1
+# else
+#   rm file2
+#
+sub rename_or_delete($$;$) {
+  my ($file, $file_tmp, $suffix_msg) = @_;
+
+  my $changed_p = cmp_files ($file, $file_tmp);
+
+  if ($changed_p && $debug_p) {
+    print STDOUT "\n" . ('#' x 79) . "\n";
+    diff_files ("$file", "$file_tmp");
+    $changed_p = 0;
+  }
+
+  if ($changed_p) {
+
+    if (!rename ("$file_tmp", "$file")) {
+      unlink "$file_tmp";
+      error ("mv $file_tmp $file: $!");
+    }
+    print STDERR "$progname: wrote $file" .
+      ($suffix_msg ? " $suffix_msg" : "") . "\n";
+
+  } else {
+    unlink "$file_tmp" || error ("rm $file_tmp: $!\n");
+    print STDERR "$file unchanged" .
+                 ($suffix_msg ? " $suffix_msg" : "") . "\n"
+        if ($verbose);
+    print STDERR "$progname: rm $file_tmp\n" if ($verbose > 2);
+  }
+}
+
+
+# Write the given body to the file, but don't alter the file's
+# date if the new content is the same as the existing content.
+#
+sub write_file_if_changed($$;$) {
+  my ($outfile, $body, $suffix_msg) = @_;
+
+  my $file_tmp = "$outfile.tmp";
+  open (my $out, '>', $file_tmp) || error ("$file_tmp: $!");
+  (print $out $body) || error ("$file_tmp: $!");
+  close $out || error ("$file_tmp: $!");
+  rename_or_delete ($outfile, $file_tmp, $suffix_msg);
+}
+
+
+# Read the template file and splice in the @KEYWORDS@ in the hash.
+#
+sub read_template($$) {
+  my ($file, $subs) = @_;
+  my $body = '';
+  open (my $in, '<', $file) || error ("$file: $!");
+  while (<$in>) { $body .= $_; }
+  close $in;
+
+  $body =~ s@/\*.*?\*/@@gs;  # omit comments
+  $body =~ s@//.*$@@gm;
+
+  foreach my $key (keys %$subs) {
+    my $val = $subs->{$key};
+    $body =~ s/@\Q$key\E@/$val/gs;
+  }
+
+  if ($body =~ m/(@[-_A-Z\d]+@)/s) {
+    error ("$file: unmatched: $1 [$body]");
+  }
+
+  $body =~ s/[ \t]+$//gm;
+  $body =~ s/(\n\n)\n+/$1/gs;
+  return $body;
+}
+
+
+# This is duplicated in OSX/update-info-plist.pl
+#
+sub munge_blurb($$$$) {
+  my ($filename, $name, $vers, $desc) = @_;
+
+  $desc =~ s/^([ \t]*\n)+//s;
+  $desc =~ s/\s*$//s;
+
+  # in case it's done already...
+  $desc =~ s@<!--.*?-->@@gs;
+  $desc =~ s/^.* version \d[^\n]*\n//s;
+  $desc =~ s/^From the XScreenSaver.*\n//m;
+  $desc =~ s@^https://www\.jwz\.org/xscreensaver.*\n@@m;
+  $desc =~
+       s/\nCopyright [^ \r\n\t]+ (\d{4})(-\d{4})? (.*)\.$/\nWritten $3; $1./s;
+  $desc =~ s/^\n+//s;
+
+  error ("$filename: description contains markup: $1")
+    if ($desc =~ m/([<>&][^<>&\s]*)/s);
+  error ("$filename: description contains ctl chars: $1")
+    if ($desc =~ m/([\000-\010\013-\037])/s);
+
+  error ("$filename: can't extract authors")
+    unless ($desc =~ m@^(.*)\nWritten by[ \t]+(.+)$@s);
+  $desc = $1;
+  my $authors = $2;
+  $desc =~ s/\s*$//s;
+
+  my $year = undef;
+  if ($authors =~ m@^(.*?)\s*[,;]\s+(\d\d\d\d)([-\s,;]+\d\d\d\d)*[.]?$@s) {
+    $authors = $1;
+    $year = $2;
+  }
+
+  error ("$filename: can't extract year") unless $year;
+  my $cyear = 1900 + ((localtime())[5]);
+  $year = "$cyear" unless $year;
+  if ($year && ! ($year =~ m/$cyear/)) {
+    $year = "$year-$cyear";
+  }
+
+  $authors =~ s/[.,;\s]+$//s;
+
+  # List me as a co-author on all of them, since I'm the one who
+  # did the OSX port, packaged it up, and built the executables.
+  #
+  my $curator = "Jamie Zawinski";
+  if (! ($authors =~ m/$curator/si)) {
+    if ($authors =~ m@^(.*?),? and (.*)$@s) {
+      $authors = "$1, $2, and $curator";
+    } else {
+      $authors .= " and $curator";
+    }
+  }
+
+  my $desc1 = ("$name, version $vers.\n\n" .           # savername.xml
+               $desc . "\n" .
+               "\n" . 
+               "From the XScreenSaver collection: " .
+               "https://www.jwz.org/xscreensaver/\n" .
+               "Copyright \302\251 $year by $authors.\n");
+
+  my $desc2 = ("$name $vers,\n" .                      # Info.plist
+               "\302\251 $year $authors.\n" .
+               #"From the XScreenSaver collection:\n" .
+               #"https://www.jwz.org/xscreensaver/\n" .
+               "\n" .
+               $desc .
+               "\n");
+
+  # unwrap lines, but only when it's obviously ok: leave blank lines,
+  # and don't unwrap if that would compress leading whitespace on a line.
+  #
+  $desc2 =~ s/^(From |https?:)/\n$1/gm;
+  1 while ($desc2 =~ s/([^\s])[ \t]*\n([^\s])/$1 $2/gs);
+  $desc2 =~ s/\n\n(From |https?:)/\n$1/gs;
+
+  return ($desc1, $desc2);
+}
+
+
+sub build_android(@) {
+  my (@savers) = @_;
+
+  my $package     = "org.jwz.xscreensaver";
+  my $project_dir = "project/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";
+  my $gen_dir     = "gen";
+
+  my $xml_header = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
+
+  my $manifest = '';
+  my $arrays   = '';
+  my $strings  = '';
+  my %write_files;
+  my %string_dups;
+
+  my $vers;
+  {
+    my $file = "../utils/version.h";
+    my $body = '';
+    open (my $in, '<', $file) || error ("$file: $!");
+    while (<$in>) { $body .= $_; }
+    close $in;
+    ($vers) = ($body =~ m@ (\d+\.\d+) @s);
+    error ("$file: no version number") unless $vers;
+  }
+
+
+  foreach my $saver (@savers) {
+    next if ($saver =~ m/(-helper)$/);
+    $saver = 'rdbomb' if ($saver eq 'rd-bomb');
+
+    my ($src_opts, $switchmap) = parse_src ($saver);
+    my ($saver_title, $gl_p, $xml_opts, $widgets) =
+      parse_xml ($saver, $switchmap, $src_opts);
+
+    my $daydream_class = "${saver_title}Daydream";
+    my $settings_class = "${saver_title}Settings";
+    foreach ($settings_class, $daydream_class) {
+      s/\s+//gs;
+      s/^([a-z])/\U$1/gs;  # upcase first letter
+    }
+
+    $saver_title =~ s/(.[a-z])([A-Z\d])/$1 $2/gs;      # Spaces in InterCaps
+    $saver_title =~ s/^(GL|RD)[- ]?(.)/$1 \U$2/gs;     # Space after "GL"
+    $saver_title =~ s/^Apple ?2$/Apple &#x5D;&#x5B;/gs;        # "Apple ]["
+    $saver_title =~ s/(m)oe(bius)/$1&#xF6;$2/gsi;      # &ouml;
+    $saver_title =~ s/(moir)e/$1&#xE9;/gsi;            # &eacute;
+    $saver_title =~ s/^([a-z])/\U$1/s;                 # "M6502" for sorting
+
+    my $settings = '';
+
+    my $localize0 = sub($$) {
+      my ($key, $string) = @_;
+      $string =~ s@([\\\"\'])@\\$1@gs;         # backslashify
+      $string =~ s@\n@\\n@gs;                  # quote newlines
+      $key =~ s@[^a-z\d_]+@_@gsi;              # illegal characters
+
+      my $old = $string_dups{$key};
+      error ("dup string: $key: \"$old\" != \"$string\"")
+        if (defined($old) && $old ne $string);
+      $string_dups{$key} = $string;
+
+      my $fmt = ($string =~ m/%/ ? ' formatted="false"' : '');
+      $strings .= "<string name=\"${key}\"$fmt>$string</string>\n"
+        unless defined($old);
+      return "\@string/$key";
+    };
+
+    $localize0->('app_name', 'XScreenSaver');
+
+    $settings .= ("<Preference\n" .
+                  "  android:key=\"${saver}_reset\"\n" .
+                  "  android:title=\"" .
+                      $localize0->('reset_to_defaults', 'Reset to defaults') .
+                     "\"\n" .
+                  " />\n");
+
+    my $daydream_desc = '';
+    foreach my $widget (@$widgets) {
+      my $type  = $widget->{type};
+      my $rsrc  = $widget->{resource};
+      my $label = $widget->{_label};
+      my $def   = $widget->{default};
+      my $invert_p = (($widget->{convert} || '') eq 'invert');
+
+      my $key   = "${saver}_$rsrc" if $rsrc;
+
+      #### The menus don't actually have titles on X11 or Cocoa...
+      $label = $widget->{resource} unless $label;
+
+      my $localize = sub($;$) {
+        my ($string, $suf) = @_;
+        $suf = 'title' unless $suf;
+        return $localize0->("${saver}_${rsrc}_${suf}", $string);
+      };
+
+      if ($type eq 'slider' || $type eq 'spinbutton') {
+
+        my $low        = $widget->{low};
+        my $high       = $widget->{high};
+        my $float_p    = $low =~ m/[.]/;
+        my $low_label  = $widget->{'_low-label'};
+        my $high_label = $widget->{'_high-label'};
+
+        $low_label  = $low  unless defined($low_label);
+        $high_label = $high unless defined($high_label);
+
+        ($low, $high) = ($high, $low)
+          if (($widget->{convert} || '') eq 'invert');
+
+        $settings .=
+          ("<$package.SliderPreference\n" .
+           "  android:layout=\"\@layout/slider_preference\"\n" .
+           "  android:key=\"${key}\"\n" .
+           "  android:title=\"" . $localize->($label) . "\"\n" .
+           "  android:defaultValue=\"$def\"\n" .
+           "  low=\"$low\"\n" .
+           "  high=\"$high\"\n" .
+           "  lowLabel=\""  . $localize->($low_label,  'low_label')  . "\"\n" .
+           "  highLabel=\"" . $localize->($high_label, 'high_label') . "\"\n" .
+           "  integral=\"" .($float_p ? 'false' : 'true'). "\" />\n");
+
+      } elsif ($type eq 'boolean') {
+
+        my $def = ($invert_p ? 'true' : 'false');
+        $settings .=
+          ("<CheckBoxPreference\n" .
+           "  android:key=\"${key}\"\n" .
+           "  android:title=\"" . $localize->($label) . "\"\n" .
+           "  android:defaultValue=\"$def\" />\n");
+
+      } elsif ($type eq 'select') {
+
+        $label =~ s/^(.)/\U$1/s;  # upcase first letter of menu title
+        $label =~ s/[-_]/ /gs;
+        $label =~ s/([a-z])([A-Z])/$1 $2/gs;
+        $def = '' unless defined ($def);
+        $settings .=
+          ("<ListPreference\n" .
+           "  android:key=\"${key}\"\n" .
+           "  android:title=\"" . $localize->($label, 'menu') . "\"\n" .
+           "  android:entries=\"\@array/${key}_entries\"\n" .
+           "  android:defaultValue=\"$def\"\n" .
+           "  android:entryValues=\"\@array/${key}_values\" />\n");
+
+        my $a1 = '';
+        foreach my $item (@{$widget->{menu}}) {
+          my $val = $item->{value};
+          if (! defined($val)) {
+            $val = $src_opts->{$widget->{resource}};
+            error ("$saver: no default resource in option menu " .
+                   $item->{_label})
+              unless defined($val);
+          }
+          $val =~ s@([\\\"\'])@\\$1@gs;                # backslashify
+          $a1 .= "  <item>$val</item>\n";
+        }
+
+        my $a2 = '';
+        foreach my $item (@{$widget->{menu}}) {
+          my $val = $item->{value};
+          $val = $src_opts->{$widget->{resource}} unless defined($val);
+          $a2 .= ("  <item>" . $localize->($item->{_label}, $val) .
+                  "</item>\n");
+        }
+
+        my $fmt1 = ($a1 =~ m/%/ ? ' formatted="false"' : '');
+        my $fmt2 = ($a2 =~ m/%/ ? ' formatted="false"' : '');
+        $arrays .= ("<string-array name=\"${key}_values\"$fmt1>\n" .
+                    $a1 .
+                    "</string-array>\n" .
+                    "<string-array name=\"${key}_entries\"$fmt2>\n" .
+                    $a2 .
+                    "</string-array>\n");
+
+      } elsif ($type eq 'string') {
+
+        $def =~ s/&/&amp;/gs;
+        $settings .=
+          ("<EditTextPreference\n" .
+           "  android:key=\"${key}\"\n" .
+           "  android:title=\"" . $localize->($label) . "\"\n" .
+           "  android:defaultValue=\"$def\" />\n");
+
+      } elsif ($type eq 'file') {
+
+      } elsif ($type eq '_description') {
+
+        $type = 'description';
+        $rsrc = $type;
+        my $desc = $widget->{text};
+        (undef, $desc) = munge_blurb ($saver, $saver_title, $vers, $desc);
+
+        # Lose the Wikipedia URLs.
+        $desc =~ s@https?:.*?\b(wikipedia|mathworld)\b[^\s]+[ \t]*\n?@@gm;
+        $desc =~ s/(\n\n)\n+/$1/s;
+        $desc =~ s/\s*$/\n\n\n/s;
+
+        $daydream_desc = $desc;
+
+        my ($year) = ($daydream_desc =~ m/\b((19|20)\d\d)\b/s);
+        error ("$saver: no year") unless $year;
+        $daydream_desc =~ s/^.*?\n\n//gs;
+        $daydream_desc =~ s/\n.*$//gs;
+        $daydream_desc = "$year: $daydream_desc";
+        $daydream_desc =~ s/^(.{72}).+$/$1.../s;
+
+        $settings .=
+          ("<Preference\n" .
+           "  android:icon=\"\@drawable/thumbnail\"\n" .
+           "  android:key=\"${saver}_${type}\"\n" .
+#           "  android:selectable=\"false\"\n" .
+           "  android:persistent=\"false\"\n" .
+           "  android:layout=\"\@layout/preference_blurb\"\n" .
+           "  android:summary=\"" . $localize->($desc) . "\">\n" .
+           "  <intent android:action=\"android.intent.action.VIEW\"\n" .
+           "    android:data=\"https://www.jwz.org/xscreensaver/\" />\n" .
+           "</Preference>\n");
+
+      } else {
+        error ("unhandled type: $type");
+      }
+    }
+
+    my $heading = "XScreenSaver: $saver_title";
+
+    $settings =~ s/^/  /gm;
+    $settings = ($xml_header .
+                 "<PreferenceScreen xmlns:android=\"" .
+                 "http://schemas.android.com/apk/res/android\"\n" .
+                 "  android:title=\"" .
+                 $localize0->("${saver}_settings_title", $heading) . "\">\n" .
+                 $settings .
+                 "</PreferenceScreen>\n");
+
+    my $saver_underscore = $saver;
+    $saver_underscore =~ s/-/_/g;
+    $write_files{"$xml_dir/${saver_underscore}_settings.xml"} = $settings;
+
+    $manifest .= ("<service android:label=\"" .
+                     $localize0->("${saver_underscore}_saver_title",
+                                  $saver_title) .
+                     "\"\n" .
+                  "  android:summary=\"" .
+                       $localize0->("${saver_underscore}_saver_desc",
+                                    $daydream_desc) . "\"\n" .
+                  "  android:name=\".gen.$daydream_class\"\n" .
+                  "  android:permission=\"android.permission" .
+                       ".BIND_DREAM_SERVICE\"\n" .
+                  "  android:exported=\"true\"\n" .
+                  "  android:icon=\"\@drawable/${saver_underscore}\">\n" .
+                  "  <intent-filter>\n" .
+                  "    <action android:name=\"android.service.dreams" .
+                        ".DreamService\" />\n" .
+                  "    <category android:name=\"android.intent.category" .
+                        ".DEFAULT\" />\n" .
+                  "  </intent-filter>\n" .
+                  "  <meta-data android:name=\"android.service.dream\"\n" .
+                  "    android:resource=\"\@xml/${saver}_dream\" />\n" .
+                  "</service>\n" .
+                  "<activity android:name=\"" .
+                    "$package.gen.$settings_class\" />\n"
+                 );
+
+    my $dream = ("<dream xmlns:android=\"" .
+                   "http://schemas.android.com/apk/res/android\"\n" .
+                 "  android:settingsActivity=\"" .
+                     "$package.gen.$settings_class\" />\n");
+    $write_files{"$xml_dir/${saver_underscore}_dream.xml"} = $dream;
+
+    $write_files{"$java_dir/$daydream_class.java"} =
+      read_template ("XScreenSaverDaydream.java.in",
+                     { CLASS => $daydream_class,
+                       API  => ($gl_p ? 'GL' : 'XLIB') });
+
+    $write_files{"$java_dir/$settings_class.java"} =
+      read_template ("XScreenSaverSettings.java.in",
+                     { CLASS => $settings_class });
+  }
+
+  $arrays =~ s/^/  /gm;
+  $arrays = ($xml_header .
+             "<resources xmlns:xliff=\"" .
+             "urn:oasis:names:tc:xliff:document:1.2\">\n" .
+             $arrays .
+             "</resources>\n");
+
+  $strings =~ s/^/  /gm;
+  $strings = ($xml_header .
+              "<resources>\n" .
+              $strings .
+              "</resources>\n");
+
+  $manifest .= "<activity android:name=\"$package.XScreenSaverSettings\" />\n";
+
+  $manifest .= ("<activity android:name=\"" .
+                "org.jwz.xscreensaver.XScreenSaverActivity\"\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" .
+                ".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;
+  $versb++ if ($versb == 53500); # Herp derp
+
+  $manifest =~ s/^/   /gm;
+  $manifest = ($xml_header .
+               "<manifest xmlns:android=\"" .
+               "http://schemas.android.com/apk/res/android\"\n" .
+               "  package=\"$package\"\n" .
+               "  android:versionCode=\"$versb\"\n" .
+               "  android:versionName=\"$vers\">\n" .
+
+               "  <uses-sdk android:minSdkVersion=\"14\"" .
+               " android:targetSdkVersion=\"19\" />\n" .
+
+               "  <uses-feature android:glEsVersion=\"0x00010001\"\n" .
+               "    android:required=\"true\" />\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:label=\"\@string/app_name\"\n" .
+               "    android:name=\".XScreenSaverApp\">\n" .
+               $manifest .
+               "  </application>\n" .
+               "</manifest>\n");
+
+  $write_files{"$project_dir/AndroidManifest.xml"}     = $manifest;
+  $write_files{"$values_dir/settings.xml"} = $arrays;
+  $write_files{"$values_dir/strings.xml"}  = $strings;
+
+  my @s2 = ();
+  foreach my $saver (sort @savers) {
+    push @s2, $saver unless ($saver =~ m/(-helper)$/);
+  }
+  my @s3 = @s2;
+
+  foreach (@s2) { s/^(.*)$/${1}_xscreensaver_function_table/s; }
+  foreach (@s3) { s/^(.*)$/{"$1", &${1}_xscreensaver_function_table}/s; }
+
+  my $fntable_h = ("extern struct xscreensaver_function_table\n" .
+                   "  " . join(",\n  ", @s2) . ";\n" .
+                   "\n" .
+                   "static const struct function_table_entry" .
+                   " function_table[] = {\n" .
+                   "  " . join(",\n  ", @s3) . "\n" .
+                   "};\n");
+  $write_files{"$gen_dir/function-table.h"} = $fntable_h;
+
+
+  $write_files{"$values_dir/attrs.xml"} =
+    # This file doesn't actually have any substitutions in it, so it could
+    # just be static, somewhere...
+    # SliderPreference.java refers to this via "R.styleable.SliderPreference".
+    ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" .
+     "<resources>\n" .
+     "  <declare-styleable name=\"SliderPreference\">\n" .
+     "    <attr name=\"android:summary\" />\n" .
+     "  </declare-styleable>\n" .
+     "</resources>\n");
+
+
+  foreach my $file (sort keys %write_files) {
+    my ($dir) = ($file =~ m@^(.*)/[^/]*$@s);
+    system ("mkdir", "-p", $dir) if (! -d $dir && !$debug_p);
+    my $body = $write_files{$file};
+    $body = "// Generated by $progname\n$body"
+      if ($file =~ m/\.(java|[chm])$/s);
+    write_file_if_changed ($file, $body);
+  }
+
+  # Unlink any .xml files from a previous run that shouldn't be there:
+  # if a hack is removed from $ANDROID_HACKS in android/Makefile but
+  # the old XML files remain behind, the build blows up.
+  #
+  opendir (my $dirp, $xml_dir) || error ("$xml_dir: $!");
+  my @files = readdir ($dirp);
+  closedir $dirp;
+  foreach my $f (sort @files) {
+    next if ($f eq '.' || $f eq '..');
+    $f = "$xml_dir/$f";
+    next if (defined ($write_files{$f}));
+    if ($f =~ m/_(settings|dream)\.xml$/s) {
+      print STDERR "$progname: rm $f\n";
+      unlink ($f) unless ($debug_p);
+    } else {
+      print STDERR "$progname: warning: unrecognised file: $f\n";
+    }
+  }
+}
+
+
 sub error($) {
   my ($err) = @_;
   print STDERR "$progname: $err\n";
@@ -351,16 +1104,20 @@ sub error($) {
 }
 
 sub usage() {
-  print STDERR "usage: $progname [--verbose] files ...\n";
+  print STDERR "usage: $progname [--verbose] [--debug]" .
+    " [--build-android] files ...\n";
   exit 1;
 }
 
 sub main() {
+  my $android_p = 0;
   my @files = ();
   while ($#ARGV >= 0) {
     $_ = shift @ARGV;
     if (m/^--?verbose$/) { $verbose++; }
     elsif (m/^-v+$/) { $verbose += length($_)-1; }
+    elsif (m/^--?debug$/s) { $debug_p++; }
+    elsif (m/^--?build-android$/s) { $android_p++; }
     elsif (m/^-./) { usage; }
     else { push @files, $_; }
 #    else { usage; }
@@ -368,7 +1125,12 @@ sub main() {
 
   usage unless ($#files >= 0);
   my $failures = 0;
-  foreach (@files) { $failures += check_config($_); }
+  foreach my $file (@files) {
+    $failures += check_config ($file);
+  }
+
+  build_android (@files) if ($android_p);
+
   exit ($failures);
 }
 
index 34f47807317663d07fa143fa354e91098bddae53..4b65f9e3fa3250543f60d47c95cdac3ab2fcb858 100644 (file)
@@ -406,7 +406,7 @@ static const char *cloudlife_defaults[] = {
     "*maxAge:          64",
     "*initialDensity:  30",
     "*cellSize:                3",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
     "*ignoreRotation:   True",
 #endif
     0
index 415e7c0a499d2e69a6075386d9651d3ecc4a94d9..38d890e5120e878848b38ee2eabf1c30b4933543 100644 (file)
@@ -822,7 +822,7 @@ compass_init (Display *dpy, Window window)
   st->delay = get_integer_resource (st->dpy, "delay", "Integer");
   st->dbuf = get_boolean_resource (st->dpy, "doubleBuffer", "Boolean");
 
-# ifdef HAVE_COCOA     /* Don't second-guess Quartz's double-buffering */
+# ifdef HAVE_JWXYZ     /* Don't second-guess Quartz's double-buffering */
   st->dbuf = False;
 # endif
 
index 8b01fa51daef37d4943afa8374ca7d7666ab32fc..fa35d9420f7c0039ac74d1cc98139ce710b45ac7 100644 (file)
@@ -4,10 +4,10 @@
             a screen saver and locker for the X window system
                             by Jamie Zawinski
 
-                              version 5.34
-                               24-Oct-2015
+                              version 5.35
+                               24-May-2016
 
-                     http://www.jwz.org/xscreensaver/
+                     https://www.jwz.org/xscreensaver/
 
 -----------------------------------------------------------------------
 
index 0ff0c6c762cb0fdbda922053c42022357645c9a9..c7063300835533102c24132596b4c2ef12b13bdb 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=NgSetBY6VP4"/>
+  <video href="https://www.youtube.com/watch?v=NgSetBY6VP4"/>
 
   <number id="speed" type="slider" arg="-speed %"
           _label="Speed" _low-label="Slow" _high-label="Fast"
index d420c166bfa08e970a42e7406e30be93fa5f9cb2..90dff7a38b9535473c9fc739c9ce591fa22a33f7 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=usITxM2YJZs"/>
+  <video href="https://www.youtube.com/watch?v=usITxM2YJZs"/>
 
 <!--
  -withdraw 1200
index a91c25075ea1474597dc09db1013163df4c74312..6c3785f71ecc4110d62b046d7be8486bbff6135d 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=hIqmIQbQkW8"/>
+  <video href="https://www.youtube.com/watch?v=hIqmIQbQkW8"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 1619c6787bcdd7804ccb5f11cd87df5f587df9ab..8bb74235342631219af6611f1042bbc9ae6a742d 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=PaG7RCO4ezs"/>
+  <video href="https://www.youtube.com/watch?v=PaG7RCO4ezs"/>
 
   <hgroup>
    <vgroup>
index 9a6b9ed80fa12ec1067c6cb2259c43f166eee927..ee4ce7b3415e243fff58b0662b86957e018f626f 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=Ecw9dDc0db0"/>
+  <video href="https://www.youtube.com/watch?v=Ecw9dDc0db0"/>
 
   <number id="speed" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index aa4e05894808c542cc8b3d050cdbc3b71de05d5b..15802053558ba32c265a70b61aa7fc2af462a85e 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=Bwa5-n6UUj8"/>
+  <video href="https://www.youtube.com/watch?v=Bwa5-n6UUj8"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 7a9db2df37e25d2ffc3215a436ee9edaf5c93d1d..fe78174c0f7e34129c1b67cdc9a7f021266d3378 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=NYisFYtODTA"/>
+  <video href="https://www.youtube.com/watch?v=NYisFYtODTA"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 61c088c7614fc481e073c17a1d7e58bf8d727fb6..72d0e415d23ff9a6d5ec88e4097c7422ef4bb3f4 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=aeWnjSROR8U"/>
+  <video href="https://www.youtube.com/watch?v=aeWnjSROR8U"/>
 
   <boolean id="label" _label="Draw labels" arg-unset="-no-label"/>
 
index 2761f82de51b470d46376ca2ab90cd675ab332b1..e48fc2ce8875b8a6ee2ef434aa41ebbbe0793349 100644 (file)
@@ -4,7 +4,7 @@
 
  <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=p3QZqhp67l8"/>
+  <video href="https://www.youtube.com/watch?v=p3QZqhp67l8"/>
 
  <hgroup>
   <vgroup>
index c114d77abb788cd2fddc0f3fde753ccf702c1efa..2e06b8540f74eeade9b3f7c89e3f5776f10f80fc 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=U78xPez5UGg"/>
+  <video href="https://www.youtube.com/watch?v=U78xPez5UGg"/>
 
   <number id="sharkspeed" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index a528a46887361c5e6851e7f1f10229876b828f24..b0ca4aed0e4a2d984f972896eba5abda4cc51786 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=KAT9nkXCdms"/>
+  <video href="https://www.youtube.com/watch?v=KAT9nkXCdms"/>
 
   <hgroup>
   <select id="mode">
index a55d850215b1ce2f65d5273e004ffb0e816bb5a1..eea3b96928d35fe17aa073049312a9f76832c492 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=mpCRbi3jkuc"/>
+  <video href="https://www.youtube.com/watch?v=mpCRbi3jkuc"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 7642ad6437741a4595d3e2e33d8130bef3b85b3c..76fca2840bce41f7169696cefbd095f6e58cc691 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=gmtAySJdsfg"/>
+  <video href="https://www.youtube.com/watch?v=gmtAySJdsfg"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 138917345bfca9addc37bc1e045e14f0c9e32eb3..a96026c5e67f91c39fbc4ff43856c7b8cbe23287 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=KPiJb0Qm1SE"/>
+  <video href="https://www.youtube.com/watch?v=KPiJb0Qm1SE"/>
 
   <number id="growth-delay" type="slider" arg="-growth-delay %"
           _label="Growth delay" _low-label="Low" _high-label="High"
index a3d96df4900b734cf87107019237447d20f23326..d7cb42db44f93ceb519be36ef60004b30d3fa7b1 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=bp3J3si2Hr0"/>
+  <video href="https://www.youtube.com/watch?v=bp3J3si2Hr0"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index dfaf3ae90fe4e58b70f49d30808f379d01edc43d..d457df209c8cb906626f8fa53366c4d4a8b346f2 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=lgjbHMcSd8U"/>
+  <video href="https://www.youtube.com/watch?v=lgjbHMcSd8U"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 81d484e647e98b606b59e067aa8a5017ef06c35a..df53aa7b5efcaa8ff33eaac49fd437b70d95d283 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=UTtcwb-UWW8"/>
+  <video href="https://www.youtube.com/watch?v=UTtcwb-UWW8"/>
 
   <hgroup>
    <vgroup>
index e290d631f2dd244f6de811fc3c28269e7990da15..85f88f998af1f01f9c7d731aab2831aae84e54b6 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=L0JUBhpZlMw"/>
+  <video href="https://www.youtube.com/watch?v=L0JUBhpZlMw"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index de23fb4d5d7daaf2bff384cf0db4a24a726e26ef..a36d1e24252ffbd5e8fb8e3039934ceff7045ed4 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=J3KAsV31d6M"/>
+  <video href="https://www.youtube.com/watch?v=J3KAsV31d6M"/>
 
   <number id="size" type="slider" arg="-size %"
           _label="Size" _low-label="Tiny" _high-label="Huge"
index 2112f6375e3b3f334b639cc3cc3a5100ad5e2212..b28912eece23680c3d1b17a0e74aa66517c8ad30 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=MdmIBmlkyFw"/>
+  <video href="https://www.youtube.com/watch?v=MdmIBmlkyFw"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index aa7fc4594548a62cdcaf6bad6ebe19a2002674ad..0e3dfe5807291490d9fcf3354a31e4fd7e9ccee7 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=O_b5UWhv49w"/>
+  <video href="https://www.youtube.com/watch?v=O_b5UWhv49w"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 2a5299589aef614d444f1d338046822b64bb173e..b2926f0b9a74dc025f85fdbc1f1c8b5716698648 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=CU4QFtZm9So"/>
+  <video href="https://www.youtube.com/watch?v=CU4QFtZm9So"/>
 
   <hgroup>
    <vgroup>
index cc4b5ec4672b3614fbf826f6040e1288ba7646a1..a297e13c95908db8bae67dc02ccbce0a89840ca8 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=8GkcbBbcwBk"/>
+  <video href="https://www.youtube.com/watch?v=8GkcbBbcwBk"/>
 
   <hgroup>
    <vgroup>
index fe09fced46f3834c443bec39f143007bfc99abf3..b49fa2237d184f8518d9f6a9d023772fce805f55 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=PUhJq56ViGM"/>
+  <video href="https://www.youtube.com/watch?v=PUhJq56ViGM"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index f092db9aef44da2c7c1598dc6a8df39202d647ad..8162f7f7369e87bc5df926344cf54017a54eb12c 100644 (file)
@@ -4,7 +4,7 @@
 
  <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=YIqbMCfR3r0"/>
+  <video href="https://www.youtube.com/watch?v=YIqbMCfR3r0"/>
 
  <hgroup>
   <number id="delay" type="slider" arg="-delay %"
@@ -18,6 +18,7 @@
    <boolean id="windows"    _label="Windows 3.1"    arg-unset="-no-windows"/>
    <boolean id="nt"         _label="Windows NT"     arg-unset="-no-nt"/>
    <boolean id="2k"         _label="Windows 2000  " arg-unset="-no-2k"/>
+   <boolean id="win10"      _label="Windows 10    " arg-unset="-no-win10"/>
    <boolean id="msdos"      _label="MS-DOS"         arg-unset="-no-msdos"/>
   </vgroup>
   <vgroup>
index baee55dd7d18ca9ae2f620fa9b0fdd5f61fb2acd..985c394a9dc6d1bdf1d679ae0379ab4c9650763b 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=4vcj8sq9FO8"/>
+  <video href="https://www.youtube.com/watch?v=4vcj8sq9FO8"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
           convert="invert"/>
 
   <boolean id="transp" _label="Transparent bubbles" arg-unset="-no-transparent"/>
-  <string id="color"    _label="Bubble color"      arg="-color %"/>
+   <select id="bubblecolor">
+    <option id="random" _label="Random" />
+    <option id="Red"    _label="Amber" arg-set="-color #FF0000" />
+    <option id="Green"  _label="Green" arg-set="-color #00FF00" />
+    <option id="Blue"   _label="Blue"  arg-set="-color #0000FF" />
+    <option id="white"  _label="White" arg-set="-color #FFFFFF" />
+   </select>
   <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
   <xscreensaver-updater />
 
index 399006a47773e9238e60697fd9641f4438f0d4dd..86cb132312fad697e58398e896821b8d24b33cee 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=Mli1TjZY1YA"/>
+  <video href="https://www.youtube.com/watch?v=Mli1TjZY1YA"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index e52c2d82c8e99a959a2ef4697876b7ae137c7d55..78ee9698fd057b13592f078411a530a93142933a 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=IV7D-NYRCiU"/>
+  <video href="https://www.youtube.com/watch?v=IV7D-NYRCiU"/>
 
   <!-- #### -degrees [360] -->
   <!-- #### -color [random] -->
index 42179a9efdd8725be3930b14bc6d380189ea4541..6ede6188d75c45111528d7a38ef5959ace24e139 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=BxGHUFvI2Zo"/>
+  <video href="https://www.youtube.com/watch?v=BxGHUFvI2Zo"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index ded64e48c5e437759660d39850b0977626cbdaf9..6f9a79f34f1408be3e8f80e238ab0c650be76b22 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=IyqWkGVrFIY"/>
+  <video href="https://www.youtube.com/watch?v=IyqWkGVrFIY"/>
 
   <hgroup>
    <vgroup>
index 64e8fe3a4d3e95897735141fb5a0f4887f76e489..e15138f754bb8b03137df122162b97a742c17178 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=zqIlWzUHOz8"/>
+  <video href="https://www.youtube.com/watch?v=zqIlWzUHOz8"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Change image every" _low-label="0 seconds" _high-label="30 seconds"
index 52759fd1a0f0d25cccfd65b3717b7d7f985a283e..f84d12bf07ddfc171ffe29eafe5c1fd400fe1c97 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=PnX60AAoTdw"/>
+  <video href="https://www.youtube.com/watch?v=PnX60AAoTdw"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index f45122f5f41c2ee36ee592eb73bb26b19d25d988..0605002c9b812786a31534631d77b0678614acc6 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=tfqR1j1OQs8"/>
+  <video href="https://www.youtube.com/watch?v=tfqR1j1OQs8"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 58c0efc0a054c3d35d92c0adf74c15a3d84c2b7a..61f67d9d447e8298c51dd4c5d15fb7ffc503f5f2 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=LJMtu-9T3U0"/>
+  <video href="https://www.youtube.com/watch?v=LJMtu-9T3U0"/>
 
   <hgroup>
    <vgroup>
index 565ed6fc66f1680176818c91ab85bc267fae13fc..767a8ea24d61a712064503fb6520694304c1320b 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=TkVDO3nTTsE"/>
+  <video href="https://www.youtube.com/watch?v=TkVDO3nTTsE"/>
 
   <number id="delay" type="slider" arg="-cycle-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 91413495f9eac5d4dac26362a9a25a03a24d824d..128edc5178ec4800b90e5904ad2cd7a3bfed10ca 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=Q54NVuxhGso"/>
+  <video href="https://www.youtube.com/watch?v=Q54NVuxhGso"/>
 
   <hgroup>
    <vgroup>
index 6344e3ce6732d8149855fa63120261a5708b7283..83e0c83bc30ac8d51420323b9e191d546b3958cb 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=IssDEcgB550"/>
+  <video href="https://www.youtube.com/watch?v=IssDEcgB550"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 2c0f5c28ad2eeca21855818ae1acc75720614277..c722ea558c1c455db0adfb495a1928f8e5793c9e 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=3WTSvzJcQhw"/>
+  <video href="https://www.youtube.com/watch?v=3WTSvzJcQhw"/>
 
   <number id="delay2" type="slider" arg="-delay2 %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 8f21543ec1b935fa93657dd1e0b2233d5cba9a01..dacf2798d6418cb0c948ef42526b4c53cda0ec41 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=ej1No4EK8Rc"/>
+  <video href="https://www.youtube.com/watch?v=ej1No4EK8Rc"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index dede344952985c6320591b6c20b7333863cac872..399c569165cb313c0ee8ec8f519afea01f32ce77 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=HN2ykbM2cTk"/>
+  <video href="https://www.youtube.com/watch?v=HN2ykbM2cTk"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index fa16cafa8415200eb1e9b40d657aeb376baf364f..ab1f1dd7585283ac064351999ab09dc95b9457f3 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=M27wWKGXIvw"/>
+  <video href="https://www.youtube.com/watch?v=M27wWKGXIvw"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 86848f25097d95c05e22acff4da7dfd4e51bb262..f16d7fdcf338bc7f765b57d4f41b0d1a7f0c7e08 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=AFtxL6--lTQ"/>
+  <video href="https://www.youtube.com/watch?v=AFtxL6--lTQ"/>
 
   <hgroup>
    <vgroup>
index db466aa24839bbc55f6338a266d6c52cf6080f1d..3907214fa141d7036de25f7a8cadd5e8f6b910a8 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=aElbM0rZZNg"/>
+  <video href="https://www.youtube.com/watch?v=aElbM0rZZNg"/>
 
   <hgroup>
    <vgroup>
index a1d0ecab0a15b881d247fde527abfa6540790a79..daad604b2e195444fc2b41e06e3c696485eeb581 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=enuZbkMiqCE"/>
+  <video href="https://www.youtube.com/watch?v=enuZbkMiqCE"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 67b2f099c24ff9d601dd0cf9c2f9127445533c56..b8a90a898118c3ea043c2ee1ddf03168f7844b6f 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=nOTi7gy9l-I"/>
+  <video href="https://www.youtube.com/watch?v=nOTi7gy9l-I"/>
 
   <number id="delay" type="slider" arg="-delay %"
     _label="Frame rate" _low-label="Low" _high-label="High"
index 9fd01cab034a77ded869615c26613928c18763cf..b18f36588f20bb1a6f598a9273d0af4897f16961 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=yOuJqiDUrpY"/>
+  <video href="https://www.youtube.com/watch?v=yOuJqiDUrpY"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index ebbb994a45cfc24f9e832abc4ed5086cccd8c5b0..c81130d8f0c241abaa7d7d9ae21fef91836daf14 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=If7FOc8UnYs"/>
+  <video href="https://www.youtube.com/watch?v=If7FOc8UnYs"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 4f385f4e49a86e5c226d9ee7ca8a05a079224ea9..12bbac5522dc06234e1420d605d0a8f3c53e6356 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=QU0aPwWwHbg"/>
+  <video href="https://www.youtube.com/watch?v=QU0aPwWwHbg"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index c0d98f6c7072f13a9863d286c45eedd6c9e3cf91..93d85b3df23f4f483483d68abb075fda5c5ae854 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=dFlyRTObuDo"/>
+  <video href="https://www.youtube.com/watch?v=dFlyRTObuDo"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 9dd9c0021aff54747b04d3733b8c398a61181690..b5347cf1699328f8322c308c1ae0253939156bd2 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=kfdDTv07Nhw"/>
+  <video href="https://www.youtube.com/watch?v=kfdDTv07Nhw"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Duration" _low-label="1 second" _high-label="1 minute"
index 0ad477c85295f598225e8664782c30ffd2ea08b6..0cd4746476a77a28f8f4e242aebbcb8df7da7685 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=2CsKEVR3ecs"/>
+  <video href="https://www.youtube.com/watch?v=2CsKEVR3ecs"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 24358ae8222f0c0e70bb99a532330e12dd7a9da9..bd78bf10dc58f72f933fbb6339d309050f575953 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=OhHI-pIHddA"/>
+  <video href="https://www.youtube.com/watch?v=OhHI-pIHddA"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 7cee8033f3e372efd768ab6bd288db7c528c8e65..01c7d4f4aed6796e17e6803a15f4df0568e6ce32 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=l-yIY8vRlHA"/>
+  <video href="https://www.youtube.com/watch?v=l-yIY8vRlHA"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index c31e5ad6d692bdf6ba8aa97c0bc6ae520c1e8fb9..ab06ae1b64cb826ba3f59bde3365045651e502e1 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=ENaG3gwtukM"/>
+  <video href="https://www.youtube.com/watch?v=ENaG3gwtukM"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 03be4a0c0f935102999bc57f39f4869308996d50..9d37d53e3a51c7e3a9ef58c2c17a1d7127c91ec6 100644 (file)
@@ -1,10 +1,10 @@
 <?xml version="1.0" encoding="ISO-8859-1"?>
 
-<screensaver name="DNAlogo" _label="DNA Logo" gl="yes">
+<screensaver name="dnalogo" _label="DNA Logo" gl="yes">
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=B7I5A7E3SP0"/>
+  <video href="https://www.youtube.com/watch?v=B7I5A7E3SP0"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame Rate" _low-label="Low" _high-label="High"
@@ -41,9 +41,9 @@ Codeword
         San Francisco, CA
         94107
 
-        http://www.dnalounge.com/
+        https://www.dnalounge.com/
         http://www.dnapizza.com/
-        http://www.codeword-sf.com/
+        https://www.codeword-sf.com/
 
 Written by Jamie Zawinski; 2001.
   </_description>
index 21f21fe9cba1326fa4f3d078508972012c00c503..9eda2b457496d71a841976d85be738f055d047e1 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=cppZgCh6U7I"/>
+  <video href="https://www.youtube.com/watch?v=cppZgCh6U7I"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
diff --git a/hacks/config/dymaxionmap.xml b/hacks/config/dymaxionmap.xml
new file mode 100644 (file)
index 0000000..c5dbb82
--- /dev/null
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="dymaxionmap" _label="DymaxionMap" gl="yes">
+
+  <command arg="-root"/>
+
+  <video href="https://www.youtube.com/watch?v=I-LwEg8-340"/>
+
+  <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="Animation speed" _low-label="Slow" _high-label="Fast"
+          low="0.05" high="10.0" default="1.0"/>
+
+  <!-- #### -no-texture -->
+
+  <file id="bitmap" _label="Image file" arg="-image %"/>
+
+  <hgroup>
+   <boolean id="wander" _label="Wander"    arg-unset="-no-wander"/>
+   <boolean id="roll"   _label="Roll"      arg-unset="-no-roll"/>
+   <boolean id="stars"  _label="Stars"     arg-unset="-no-stars"/>
+  </hgroup>
+
+  <hgroup>
+   <boolean id="wire"    _label="Wireframe"       arg-set="-wireframe"/>
+   <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
+  </hgroup>
+
+  <xscreensaver-updater />
+
+  <_description>
+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.
+  </_description>
+</screensaver>
index 5831cfdfd104c79bdf878477892cb00ab6a40132..88eac221d637c0050f83c01dfaa82b9808b57327 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=QfglC_lvUTA"/>
+  <video href="https://www.youtube.com/watch?v=QfglC_lvUTA"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
diff --git a/hacks/config/energystream.xml b/hacks/config/energystream.xml
new file mode 100644 (file)
index 0000000..554e3bb
--- /dev/null
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="energystream" _label="EnergyStream" gl="yes">
+
+  <command arg="-root"/>
+
+  <video href="http://www.youtube.com/watch?v=TbWZ6v5Zzk8"/>
+
+  <number id="speed" type="slider" arg="-speed %"
+          _label="Speed" _low-label="Slow" _high-label="Fast"
+          low="0.01" high="5.0" default="1.0"/>
+
+  <hgroup>
+   <boolean id="wander" _label="Wander"    arg-unset="-wander" />
+   <boolean id="spin"   _label="Spin"      arg-unset="-spin" />
+   <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
+  </hgroup>
+
+  <xscreensaver-updater />
+
+  <_description>
+A flow of particles which form an energy stream.
+
+Written by Eugene Sandulenko and Konrad "Yoghurt" Zagorowicz; 2016.
+  </_description>
+</screensaver>
index 8b59c93e51cb69ef812ad88a12b893deb1a2b22f..5c91d28314d2e3a2f0912a5d26778263d0a4f499 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=8BL2o8QJmiA"/>
+  <video href="https://www.youtube.com/watch?v=8BL2o8QJmiA"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index c73a700af2d793db43f51428377efd4a018df798..0b56922417a4a8d0ce38ca667a2bd272529a7957 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=rpk3zxQxaR8"/>
+  <video href="https://www.youtube.com/watch?v=rpk3zxQxaR8"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index c87ca58834fcdfa6ed2ffe87dcbddef1a3fe9611..da778fe85cfce09e5633379c3a9b59db7779a9c6 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=CQ6jDBnumT8"/>
+  <video href="https://www.youtube.com/watch?v=CQ6jDBnumT8"/>
 
   <hgroup>
    <vgroup>
index d7ecf503b95c709870429113ce3d35d67af4c888..31222e661533fec19f373b94aec7a50892cc8753 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=ZH1ZtfId0iA"/>
+  <video href="https://www.youtube.com/watch?v=ZH1ZtfId0iA"/>
 
   <hgroup>
    <vgroup>
index 7260e3e3e73e8c64a2bbc2c1fecd3b2ab6bf3e8f..97c26a8e4b452f8fdf786cdc77b5aa546ea5c61f 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=eKYmqL7ndGs"/>
+  <video href="https://www.youtube.com/watch?v=eKYmqL7ndGs"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index c8e7a018d263b8f7d35b818636ac971f25dd3e43..a977c2b80cfda1998fb7182cc03174b7047cf60c 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=Cev034v37JM"/>
+  <video href="https://www.youtube.com/watch?v=Cev034v37JM"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index ed5c54ada6166e9bd504d87dbed859c69f48c64b..b07e863a18ba940fb0e4e808bbd45a910f01f573 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=PvYKJ-vkxE0"/>
+  <video href="https://www.youtube.com/watch?v=PvYKJ-vkxE0"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 8dc15150394c9c0ec828c7d352707a03657f387c..2c8d096e40d541350f923bd3bdbf2db277304385 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=-l9BfvnFIPM"/>
+  <video href="https://www.youtube.com/watch?v=-l9BfvnFIPM"/>
 
   <number id="Delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 00f7eb527c86d1c2ddd0d68c4b522abf1be0f2c0..1e6cfb3f09c06a7c435479a69242adb6d04f48e3 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=LuEC3EONzjc"/>
+  <video href="https://www.youtube.com/watch?v=LuEC3EONzjc"/>
 
   <string id="text" _label="Text for flag" arg="-text %"/>
 
index 1fa6dcf9000693be6981ad3d80c760310653006c..8e341c6edbfc9aa9ffd4aea2c6e2d6356de4ed3d 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=6Pu8JKNT_Jk"/>
+  <video href="https://www.youtube.com/watch?v=6Pu8JKNT_Jk"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index bf2e942623de878102c5981e1e7ba5f6388d2880..7f843a3ba7f2e0297ba48bd315a072ebcacaf7ea 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=RzWRoAMFtnw"/>
+  <video href="https://www.youtube.com/watch?v=RzWRoAMFtnw"/>
 
   <hgroup>
    <vgroup>
index 04d95fe5b5a3d0b6b4b84f928e27ebd432fc3d39..5ed1cfb7dba4732ec55a64b8061e57c99932ecea 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=mu3iN_BSpt4"/>
+  <video href="https://www.youtube.com/watch?v=mu3iN_BSpt4"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index d9dcba2c47eb133919a3d104bc7a1c873d3946d0..48c7e64186d8e08e2502032dc3c4bc837bc1f099 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=vcB-6S7Hfuk"/>
+  <video href="https://www.youtube.com/watch?v=vcB-6S7Hfuk"/>
 
   <hgroup>
    <vgroup>
index 2b9cac399750da310d45b7c27ac0ab1b0eed82f2..804080a53829dc7e5ce6c92daa58c570cbc4b7fc 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=RJjbRV0FC_A"/>
+  <video href="https://www.youtube.com/watch?v=RJjbRV0FC_A"/>
 
   <hgroup>
    <vgroup>
index 40333a99c5821bdd83bd9acc61b2e52c89a2366c..2acd92cd77e318af2b05f36d79eab9655cd60f52 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=5Iz9V-vOrxA"/>
+  <video href="https://www.youtube.com/watch?v=5Iz9V-vOrxA"/>
 
   <hgroup>
    <vgroup>
index e6776dc9a778a91e44eb5152d34948f2c559ef25..93bd7535e1ecfdd326c9e601967f982269587856 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=0beqUyN5ZsI"/>
+  <video href="https://www.youtube.com/watch?v=0beqUyN5ZsI"/>
 
   <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
 
index 9dddf283cd44183c73ad855334651527ff202669..7df645911369092f11116a4a5edd3e6beda57c4d 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=mLGDvtbFvfg"/>
+  <video href="https://www.youtube.com/watch?v=mLGDvtbFvfg"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 809ea006d221faacc4dbf7541d20645fbf16b388..db437d39fc133eeaf1df671268b16104529bc8fd 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=2KCXD19FHk0"/>
+  <video href="https://www.youtube.com/watch?v=2KCXD19FHk0"/>
 
   <hgroup>
    <vgroup>
index b64d413388f4df6b1c88914273e86bf1e1f3f637..2e0bd41591d80f669ab1c7959a130c1a1d76bd77 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=EEK2qbAmKWs"/>
+  <video href="https://www.youtube.com/watch?v=EEK2qbAmKWs"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index d6822330c092634c1a2ce07bed794556f519a1fd..b59517dcd5caf3286b4163d44ef281bfb91bab13 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=NrGe3xcqAns"/>
+  <video href="https://www.youtube.com/watch?v=NrGe3xcqAns"/>
 
   <hgroup>
    <vgroup>
index 8fa3c44d024d390257dadc026fa573a66ab8b5e3..b12d62f0b1ab0857bb79ea008fe841061c124c0c 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=xBprAm9w-Fo"/>
+  <video href="https://www.youtube.com/watch?v=xBprAm9w-Fo"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 460198ae213f418854999f7defa5468dd78dde7f..957fbdb0d93eeb766cea0ccb1869b4b699cf8c00 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=OHamiC1tcdg"/>
+  <video href="https://www.youtube.com/watch?v=OHamiC1tcdg"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 22fd8f3195ce1eae3cab0050873494ed29662127..0bc52ffcc9c45f3aad3926438a342bb17e8339c3 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=qulzooBLIcU"/>
+  <video href="https://www.youtube.com/watch?v=qulzooBLIcU"/>
 
   <hgroup>
    <vgroup>
index b54e2ce57e7eec20a4a482cc8bbd8ef52915042a..813268a23d625f6c1f2eaa999673ae2ef72e8000 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=gd_nTnJQ4Ps"/>
+  <video href="https://www.youtube.com/watch?v=gd_nTnJQ4Ps"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
@@ -34,6 +34,7 @@ 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.
   </_description>
index 8e0d9ed1614ccca6be2618e537c22f11b5ea221f..baced1361b496d5192faabbc70fd78b030c875f1 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=vbRFlKH-LpA"/>
+  <video href="https://www.youtube.com/watch?v=vbRFlKH-LpA"/>
 
   <hgroup>
    <vgroup>
index a440df4d14d3bc8b3506827e6a14a1efb87b9bb0..ffa953d9a580212dd2ccc98cc57f19b45b301730 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=wUWwQXRp8lE"/>
+  <video href="https://www.youtube.com/watch?v=wUWwQXRp8lE"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index f04c7c2f4b48fdba34745e4ba75875c24e1c2fad..da86fe6340f140d9c8a81ce4a3f4c07f142e2f37 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=94ac7nEQyBI"/>
+  <video href="https://www.youtube.com/watch?v=94ac7nEQyBI"/>
 
   <hgroup>
    <vgroup>
index 427ccc041f57a79442682410d33efa5d10be358a..b75bc11f3388faf588fdd74a5381f7e9df583b76 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=q6F-CDX6-tU"/>
+  <video href="https://www.youtube.com/watch?v=q6F-CDX6-tU"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 78a475adec089f32348f57a5d1c6f0433c923a00..08f882c74fed3e7a74c26b7e9ef6437b9e742ce3 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=_0Ff3qHUfsA"/>
+  <video href="https://www.youtube.com/watch?v=_0Ff3qHUfsA"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 2ae57881cdb2a60e2bb8183141c2cd18214b9bb6..6d9aec2e2a8b33d0c8be78864ef3068d3cf369a2 100644 (file)
@@ -4,7 +4,7 @@
 
  <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=1qRCviRmsTY"/>
+  <video href="https://www.youtube.com/watch?v=1qRCviRmsTY"/>
 
   <hgroup>
    <vgroup>
index e4fc4c079b9a720b7999812f5bce53fd8996f536..afdd2964a2e8af9e918fb5631129cf85fb0522a5 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=ILiYNkeEb_k"/>
+  <video href="https://www.youtube.com/watch?v=ILiYNkeEb_k"/>
 
   <hgroup>
    <vgroup>
index 6d6c3f43458d05527333529c621d1b620c53a69d..18293dacb789b5b0ea166b6a11a3b65115fdc4f5 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=_dktSpsaCPg"/>
+  <video href="https://www.youtube.com/watch?v=_dktSpsaCPg"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index bc6f792509c87649800b4af8fdc8d856383f67b0..dc93c8b8bf69d0371cad87d060998c4fee2223b0 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=hXZquXPG4pg"/>
+  <video href="https://www.youtube.com/watch?v=hXZquXPG4pg"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
@@ -12,7 +12,6 @@
           convert="invert"/>
 
   <!-- #### -no-texture -->
-  <!-- #### -no-stars -->
 
   <file id="bitmap" _label="Image file" arg="-image %"/>
 
index 4550e340ff3f0918bffaa1910e23f228c69c9d96..a79ce12263642f63d4a3ca1f81ba444b9a5b27b5 100644 (file)
@@ -4,7 +4,7 @@
 
  <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=SuMIatcSPdU"/>
+  <video href="https://www.youtube.com/watch?v=SuMIatcSPdU"/>
 
   <hgroup>
    <vgroup>
index ae0022cd50a3b68d05bb32f1f98424493b8fd2a1..c92a6de053a6988aacbec38556fd9aff094c270a 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=Hi0xUWnqBhQ"/>
+  <video href="https://www.youtube.com/watch?v=Hi0xUWnqBhQ"/>
 
   <hgroup>
    <vgroup>
index 6a2a162038228ac6964ba01495bba1105052a412..d73663d62c6448319e945cf502640b831cab9632 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=AIqz-G0n1JU"/>
+  <video href="https://www.youtube.com/watch?v=AIqz-G0n1JU"/>
 
   <hgroup>
    <vgroup>
index d3a10a01d58d2d3c0060f428e5c5d608a8e5dab9..99ec92fb10e525ee4f0be1f8737fd3168994462b 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=jrXa-QtY6MU"/>
+  <video href="https://www.youtube.com/watch?v=jrXa-QtY6MU"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 8957cc82931f8f5bab677af79071eb3363b33615..53222f86cd95ce5c94fe485b19412f05dc4b93d4 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=bLMAF4Q-mGA"/>
+  <video href="https://www.youtube.com/watch?v=bLMAF4Q-mGA"/>
 
   <hgroup>
    <vgroup>
index 2ae6efd207c9f387388e3e0858b647b677a4644b..807f37d2a9c0ac167424c2a05786a2ba399b8ac1 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=spQRFDmDMeg"/>
+  <video href="https://www.youtube.com/watch?v=spQRFDmDMeg"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index f92033e2dcf12b0f85d7a34cd1e77c2a52e09ac6..cbc11a934aa4de9327b575d1926cafe387c2e4cf 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=lVEi089s1_c"/>
+  <video href="https://www.youtube.com/watch?v=lVEi089s1_c"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 14739d9c8f10606feb562cfbf80ab427aa2320b5..be656608dc8c5505113c5f300ac4f50ca17120e2 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=K2lqgBPde4o"/>
+  <video href="https://www.youtube.com/watch?v=K2lqgBPde4o"/>
 
   <hgroup>
    <vgroup>
index 4be07c30375d1df575af8b1f94b54a01316df5e9..ef947e2defde143b98d5227a03cfcab49a8418da 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=K7LbfXh3LTc"/>
+  <video href="https://www.youtube.com/watch?v=K7LbfXh3LTc"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index e1dfa0a846e71c8f155b9c8ed87276510c4d4a14..00d452551b3477b0fc7b3b5cd7e59b867148f68a 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=H-mMnadnPSs"/>
+  <video href="https://www.youtube.com/watch?v=H-mMnadnPSs"/>
 
   <number id="delay" type="slider" arg="-subdelay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index b3dde5c3a4f4049f9c0a771dd5751d12d0d51b81..8f8baef7cc6622751ba4e09ca6b7362481d3438c 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=HMPVzQUGW-Q"/>
+  <video href="https://www.youtube.com/watch?v=HMPVzQUGW-Q"/>
 
   <hgroup>
    <vgroup>
index 3ad638e69f3fd108eb78986091a79035ab139ea2..7f44aed0b146bb3d199d90fdfad982af64c2915c 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=NhKmipo_Ek4"/>
+  <video href="https://www.youtube.com/watch?v=NhKmipo_Ek4"/>
 
   <hgroup>
    <vgroup>
index 7372b7de1db0233f199a1630560077b5e44b31ed..c3c5aadb9aa8cb5814a6f8b363e0e007a78dec65 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=Ck0pKMflau0"/>
+  <video href="https://www.youtube.com/watch?v=Ck0pKMflau0"/>
 
   <hgroup>
    <vgroup>
diff --git a/hacks/config/hydrostat.xml b/hacks/config/hydrostat.xml
new file mode 100644 (file)
index 0000000..b8b8bbe
--- /dev/null
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="hydrostat" _label="Hydrostat" gl="yes">
+
+  <command arg="-root"/>
+
+  <video href="https://www.youtube.com/watch?v=nn-nA18hFt0"/>
+
+  <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="Animation speed" _low-label="Slow" _high-label="Fast"
+            low="0.01" high="4.0" default="1.0"/>
+
+    <number id="count" type="slider" arg="-count %"
+            _label="Number of squid" _low-label="One" _high-label="Many"
+            low="1" high="100" default="3" />
+
+    <number id="head_radius" type="slider" arg="-head-radius %"
+            _label="Head size" _low-label="Small" _high-label="Large"
+            low="10" high="100" default="60" />
+
+    <number id="tentacles" type="slider" arg="-tentacles %"
+            _label="Number of tentacles" _low-label="Few" _high-label="Many"
+            low="3" high="100" default="35" />
+
+   </vgroup>
+   <vgroup>
+
+    <number id="thickness" type="slider" arg="-thickness %"
+            _label="Thickness" _low-label="Thin" _high-label="Thick"
+            low="3" high="40" default="18" />
+
+    <number id="length" type="slider" arg="-length %"
+            _label="Length of tentacles" _low-label="Short" _high-label="Long"
+            low="10" high="150" default="55" />
+
+    <number id="gravity" type="slider" arg="-gravity %"
+            _label="Gravity" _low-label="Weak" _high-label="Strong"
+            low="0" high="10.0" default="0.5" />
+
+    <number id="current" type="slider" arg="-current %"
+            _label="Current" _low-label="Weak" _high-label="Strong"
+            low="0.0" high="10.0" default="0.25" />
+
+    <number id="friction" type="slider" arg="-friction %"
+            _label="Viscosity" _low-label="Low" _high-label="High"
+            low="0.0" high="0.1" default="0.02" />
+   </vgroup>
+  </hgroup>
+
+  <hgroup>
+   <boolean id="pulse" _label="Pulse"    arg-unset="-no-pulse" />
+   <boolean id="wire"   _label="Wireframe" arg-set="-wireframe"/>
+   <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
+   <xscreensaver-updater />
+  </hgroup>
+
+  <_description>
+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.
+  </_description>
+</screensaver>
index fddf92e760dc9a7a6ba898635071184bc679031b..8f674d2f63e39f7dbbc975064e865f50ca6579b5 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=BqOHgn0BQOc"/>
+  <video href="https://www.youtube.com/watch?v=BqOHgn0BQOc"/>
 
   <hgroup>
     <vgroup>
index e5d50090d6140708a5c9d16e73afcb1b110c82c0..f47123048294a1d6e14c0f9c74862075f19d7de0 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=tOLzz_D4-0E"/>
+  <video href="https://www.youtube.com/watch?v=tOLzz_D4-0E"/>
 
   <hgroup>
     <vgroup>
index 1f9b1e4480cac7bb865e112805c23ff74fd25640..a82e090afd7e057aa9797372e15689a7e78f4cf7 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=KJWe4G4Qa1Q"/>
+  <video href="https://www.youtube.com/watch?v=KJWe4G4Qa1Q"/>
 
   <hgroup>
   <number id="delay" type="slider" arg="-delay %"
index 6f5ef08a4c0892fc42955d059fc869028a36c44f..ae8975cfae3b6babd5f047199b1d999a1b83fb2e 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=QcJnc9EKJrI"/>
+  <video href="https://www.youtube.com/watch?v=QcJnc9EKJrI"/>
 
   <hgroup>
    <vgroup>
index 1bd807a51dcac666a51c5c67ffab3774be675615..14999f42dd2a4610e531ece4697ebca992e3dc26 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=0uOIrVFsECM"/>
+  <video href="https://www.youtube.com/watch?v=0uOIrVFsECM"/>
 
   <number id="delay" type="slider" arg="-delay %"
     _label="Frame rate" _low-label="Low" _high-label="High"
index 9809cc53ff5f075ef70578da88f69e8501b66a5c..f3d3cb24b176469eafd90953ffb7cab462cdef58 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=FP8YJzFkdoQ"/>
+  <video href="https://www.youtube.com/watch?v=FP8YJzFkdoQ"/>
 
   <number id="delay2" type="slider" arg="-delay2 %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index a474e95a277c116e520d6a7b78454baee8c7ef5d..c1ce7f328ae9b2e5e0970f59c97d8902981d92fc 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=wqPOZiuj4RI"/>
+  <video href="https://www.youtube.com/watch?v=wqPOZiuj4RI"/>
 
   <number id="speed" type="slider" arg="-growth-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 3d6b8baf338d9f62a3346d431283fc98e9a9d108..969d10cb350c0e07a71f8fb307682cee3913f0a3 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=nEmvx4l1sHI"/>
+  <video href="https://www.youtube.com/watch?v=nEmvx4l1sHI"/>
 
   <hgroup>
    <vgroup>
index 26b5835526f528771fb44e91d68380b0089b175d..6db1424a8bc8b25e51b2c0ccafd67d96403c0937 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=pH-ykepPopw"/>
+  <video href="https://www.youtube.com/watch?v=pH-ykepPopw"/>
 
   <number id="speed" type="slider" arg="-draw-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 97fe6dcafb6e35e49aa1b099e07540960309db5e..832bbefbdd46b92b5e4d108cc66bc1d444cdb5bc 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=60vfs2WcDtE"/>
+  <video href="https://www.youtube.com/watch?v=60vfs2WcDtE"/>
 
   <hgroup>
    <boolean id="random" _label="Randomize almost everything" arg-unset="-no-random"/>
index 0769ca8b74264dff500b75ffc4d22a57033dac96..219a5348eb88b723da462e974f7ba7a34cabc5b9 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=T5_hiY2eEeo"/>
+  <video href="https://www.youtube.com/watch?v=T5_hiY2eEeo"/>
 
   <hgroup>
    <vgroup>
index b7a702d6f48d25c7fe5068bd312411e789966fbd..8c8c05a75a1d91304ea01752e4038e74c823352f 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=E3Ae7uQtWP0"/>
+  <video href="https://www.youtube.com/watch?v=E3Ae7uQtWP0"/>
 
   <hgroup>
    <vgroup>
index 42d53addca3586621da88b6d82d0720f7c9421d1..0e136f22126193c84cfeaac890050255b560c685 100644 (file)
@@ -3,7 +3,7 @@
 <screensaver name="juggler3d" _label="Juggler3D" gl="yes">
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=TJkKaXBOvCA"/>
+  <video href="https://www.youtube.com/watch?v=TJkKaXBOvCA"/>
 
   <hgroup>
    <vgroup>
index ac9d4516d28e70d6c19c9ff79b333813242ec7dd..f648197bc8149bc86da91c2000c41d0869d160c4 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=cA4Rgq-rmy8"/>
+  <video href="https://www.youtube.com/watch?v=cA4Rgq-rmy8"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index ac16a2665592bfeba67520d67f445dfe8e7f6ce8..ccfc18f3e8eaf243502b086c0cc40ae5215dea76 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=mGplFlx1y3M"/>
+  <video href="https://www.youtube.com/watch?v=mGplFlx1y3M"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 7ec9931cef06652fdb2194a1b8112c92e241d848..06228d246b20bc269d8b591c1a9378d9edf07932 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=SJqRaCCy_vo"/>
+  <video href="https://www.youtube.com/watch?v=SJqRaCCy_vo"/>
 
   <hgroup>
    <vgroup>
@@ -31,7 +31,7 @@
       <option id="xy"  _label="Rotate around X and Y axes" arg-set="-spin XY"/>
       <option id="xz"  _label="Rotate around X and Z axes" arg-set="-spin XZ"/>
       <option id="yz"  _label="Rotate around Y and Z axes" arg-set="-spin YZ"/>
-      <option id="xyz" _label="Rotate around all three axes" arg-set="-spin YZ"/>
+      <option id="xyz" _label="Rotate around all three axes" arg-set="-spin XYZ"/>
     </select>
 
     <boolean id="wander" _label="Wander" arg-set="-wander"/>
index cb943c0eaf365fd7604af5796f21e77b7541e09a..8a93c9e0e3ba9b81bfea54cad8ab46886a7d28d6 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=c2gvyGVNG80"/>
+  <video href="https://www.youtube.com/watch?v=c2gvyGVNG80"/>
 
   <hgroup>
     <select id="kleinbottle">
index e64e8f7a034408e07dd90a8b627ab849c70f2eed..85f7ee2fff12d8f274126cf70659d10bfeb2ade4 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=64ULSfxhkDY"/>
+  <video href="https://www.youtube.com/watch?v=64ULSfxhkDY"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index f4726485c15ef56384967cb76ccd85e8c81b10a1..7f0de9d0eeeac5f343c0475a103a8273854930ac 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=-TBqI4YKOKI"/>
+  <video href="https://www.youtube.com/watch?v=-TBqI4YKOKI"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 4ee42adc414dd5c5b7b2e8892a865379c393c699..4694cca1e2caa1a46550efd28669e46cd2ee4841 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=QjPEa3KDlsw"/>
+  <video href="https://www.youtube.com/watch?v=QjPEa3KDlsw"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index e7667c41c207b805c8c0c1fb839508a4911c1834..5e7d4f7f5289c3ff4be2d674ff5a9aca36e468d4 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=XKbtdHL35u0"/>
+  <video href="https://www.youtube.com/watch?v=XKbtdHL35u0"/>
 
   <hgroup>
    <vgroup>
index f255f11602b49f7bcff5f7045c000dcd6aafa0ef..c92b1255286b1a833a5f0326053c27bc752f7122 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=aWtHHBOkO4w"/>
+  <video href="https://www.youtube.com/watch?v=aWtHHBOkO4w"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
@@ -14,7 +14,7 @@
   <hgroup>
    <vgroup>
     <number id="spread" type="spinbutton" arg="-spread %"
-            _label="Line spread" low="2" high="64" default="8"/>
+            _label="Line spread" low="2" high="8192" default="8"/>
     <number id="cycles" type="spinbutton" arg="-cycles %"
             _label="Cycles" low="1" high="600" default="60"/>
     <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
index f6f664b4d48bdc96df9b038cf06861156b1fbff5..8e602fe7213e511d5d9c20b3656ba9d86b99635e 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=lUUdHtPvp5Y"/>
+  <video href="https://www.youtube.com/watch?v=lUUdHtPvp5Y"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 07010a85ab44a4c567ad39581cdf9b6111943ad2..d142fad631e10322d6d256edac10efa166092189 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=AUbAuARmlnE"/>
+  <video href="https://www.youtube.com/watch?v=AUbAuARmlnE"/>
 
   <hgroup>
    <vgroup>
index 13fa3560a184171b7c14715d0dc9d05cd6769de2..ca165a4ac4c0e5cfb0e6358ec6efeb686bde0e55 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=6EBNCXcD9f0"/>
+  <video href="https://www.youtube.com/watch?v=6EBNCXcD9f0"/>
 
   <hgroup>
    <vgroup>
index f33fa07f48c616bfd96e199666e7104647fb38f4..f0920b3237ea6ecf95e069311b1e4460f2c03044 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=yMbMB7xQMkA"/>
+  <video href="https://www.youtube.com/watch?v=yMbMB7xQMkA"/>
 
   <hgroup>
    <vgroup>
index 42415d338f9c147625c083470bc5ef56c60f6029..65571c0c8def7a546802a90ef33b14e47cd04d7d 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=_kTMO7oEN8U"/>
+  <video href="https://www.youtube.com/watch?v=_kTMO7oEN8U"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index c8010a61a1ff3d3505b5abcb0c8d43896285de22..4eec9aba6b16a18510763ad70affcfa865b1c3bc 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root" />
 
-  <video href="http://www.youtube.com/watch?v=KlDw0nYwUe4"/>
+  <video href="https://www.youtube.com/watch?v=KlDw0nYwUe4"/>
 
   <number id="displaytime" type="slider" arg="-displaytime %"
           _label="Display time for each program"
index f405e9cc4d3b5b40c3f7e9e0d88e50d4c2cdceca..83b5b926cd74f04ff1259d9cb0a3069fa9ab3a8e 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=-u4neMXIRA8"/>
+  <video href="https://www.youtube.com/watch?v=-u4neMXIRA8"/>
 
   <hgroup>
    <vgroup>
index ec8dc84429b87fd3f7a07a8619e59b1e3ad08fdd..ccb6c0a043d4290b3c9ec5ab12d5b056fecf797c 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=DQJRNlTKCdA"/>
+  <video href="https://www.youtube.com/watch?v=DQJRNlTKCdA"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 5d247a99aa90cb2cd7e3ba2288418d304875fdac..760167e00aee8f54cfbdccd7900b3fc3e1c5ebba 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=qpnuNJH9cLw"/>
+  <video href="https://www.youtube.com/watch?v=qpnuNJH9cLw"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 72d0d35e0dab93813e0d3b57cf84bc399ded55f5..0d1a2181948cbd7da6746788df7b1ea3c3d7f18c 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=wcdKHCp9foY"/>
+  <video href="https://www.youtube.com/watch?v=wcdKHCp9foY"/>
 
  <!-- #### -color [random] -->
 
index dc6e7d2fadcf0f59645537d2b68093d4181e5a94..657ca102e4e7927d197e180cb06db18017056756 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=o4GTO18KHe8"/>
+  <video href="https://www.youtube.com/watch?v=o4GTO18KHe8"/>
 
   <hgroup>
    <vgroup>
index 807028cb458df6332370a101a14decc1cfbbc10c..02a258f4694a04fc9ad2608bd859b0afba03c31b 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=aXNIYpdh8Ug"/>
+  <video href="https://www.youtube.com/watch?v=aXNIYpdh8Ug"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index c75e3ec0e8f1d07e82c137bc645382c5b335b009..324c5278627b3c3c5ec5f7107bb6cbe252a72fc6 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=77Nib6jQrXc"/>
+  <video href="https://www.youtube.com/watch?v=77Nib6jQrXc"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 592128e3f20835e21832ec3e5bcdf2847f758a0d..9233f915a4ff898752d949624b83fa1dc7d5123d 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=kpT6j2-9b40"/>
+  <video href="https://www.youtube.com/watch?v=kpT6j2-9b40"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 29c5f6cc109137fb9100c941386173705270fd40..9c3f55816fd708c5a22628c3444a0aba0aa858b1 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=S50zFVcUe4s"/>
+  <video href="https://www.youtube.com/watch?v=S50zFVcUe4s"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Duration" _low-label="1 second" _high-label="1 minute"
index 1b9d02f4ddb01a51ea757e39551d4f640609c26f..1785df3be2ab8e7e040b4c655f9b6d218225ba25 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=7iBNbYCo8so"/>
+  <video href="https://www.youtube.com/watch?v=7iBNbYCo8so"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 6f83c24f13f3456bde306cd3f504f499563fafa4..fe1129bedd992f694e2379cdcb4f714c8243ce08 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=D1A0tNcPL4M"/>
+  <video href="https://www.youtube.com/watch?v=D1A0tNcPL4M"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 7c67e374278f0fef4edff5c5cf3d1bfe07de3ab6..0122fb759f7d2a696f1ee8b4ef99ceeabcbe9d2a 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=lNtDppjOli4"/>
+  <video href="https://www.youtube.com/watch?v=lNtDppjOli4"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 4a1835ea4a36da6c74bdd7445b38f385cd323fe1..de0eb4d7b0cdc21c2352430faacf91cc3bd194a8 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=knqnPcZGqkA"/>
+  <video href="https://www.youtube.com/watch?v=knqnPcZGqkA"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 744a18f3f3956b6bb637a27b8e9e9e5ab267bc7b..9875838976e1e05f95b19e1e263256c46d35a958 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=aXNIYpdh8Ug"/>
+  <video href="https://www.youtube.com/watch?v=aXNIYpdh8Ug"/>
 
   <hgroup>
    <vgroup>
index 8eb8a5dfa2942fc74f1f5c3c5277bb5674d6ace1..ef6db856d76f138032cd8cf7c7003140b6344dde 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=oUfgDnyGqHM"/>
+  <video href="https://www.youtube.com/watch?v=oUfgDnyGqHM"/>
 
   <hgroup>
    <vgroup>
index be59c7374e1ecea792759953909a93e3488024aa..3e2b0fc768a43509e1584a3c68efc727968b4f60 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=x5DQjgYqmn0"/>
+  <video href="https://www.youtube.com/watch?v=x5DQjgYqmn0"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index e3654f4703c033544a096d13e1b7b5a6ee8d2bcc..bfc1674d15ad31058cb91ba8a95c27e9d0d8dc3e 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=ONJlg9Y_TLI"/>
+  <video href="https://www.youtube.com/watch?v=ONJlg9Y_TLI"/>
 
   <xscreensaver-text />
   <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
index d93e9e73aae0fd1d69778b7b600c444eb34b1e8f..5ef77d59c5bdc04552cb28ce996744a81d7a1d4a 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=G-pdjis0ECw"/>
+  <video href="https://www.youtube.com/watch?v=G-pdjis0ECw"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index dddb94e05b15acc40312d95fadd95038759cf251..5ddb6e13c91a5d064f9b11b732e786947d3ae758 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=VFibXcP1JH0"/>
+  <video href="https://www.youtube.com/watch?v=VFibXcP1JH0"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Duration" _low-label="1 second" _high-label="1 minute"
index c85b7ab7a6f310d50ec6a84173f1060facac7447..a7f6de945f2591167c690aff9a6a337e6cb1eacb 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=iuutzMOVYgI"/>
+  <video href="https://www.youtube.com/watch?v=iuutzMOVYgI"/>
 
   <number id="bgrowth" type="slider" arg="-bgrowth %"
           _label="Explosions" _low-label="Slow" _high-label="Fast"
index aebbfcdd4aa157d49540378777b7b3801ce918b0..aa70323b9c22f61d30833b2680995a8622b57a11 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=atlkrWkbYHk"/>
+  <video href="https://www.youtube.com/watch?v=atlkrWkbYHk"/>
 
    <hgroup>
     <vgroup>
index dab2468a1f37b3a9fbbd015faf7a177eb1967f26..eff93738f7bfeb7ad4ee778c70369ebe90ef7aba 100644 (file)
@@ -4,7 +4,7 @@
 
  <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=QkJ9cN0QQd8"/>
+  <video href="https://www.youtube.com/watch?v=QkJ9cN0QQd8"/>
 
  <hgroup>
   <number id="delay" type="slider" arg="-delay %"
index f291d37d6bce56af68f97d8d830f42e9cb4147c3..484cf886dfa90826bcabff98d8d44eb8573f59fa 100644 (file)
@@ -4,7 +4,7 @@
 
  <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=G6ZWTrl7pV0"/>
+  <video href="https://www.youtube.com/watch?v=G6ZWTrl7pV0"/>
 
  <hgroup>
   <vgroup>
index afceb0004bfaf97899515102e3418db34b4da73b..6337dbd8ecdc114844d214149d635fdbcb9be175 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=snm7o95AR8E"/>
+  <video href="https://www.youtube.com/watch?v=snm7o95AR8E"/>
 
   <hgroup>
    <vgroup>
index 6b60fbdfe89a2892e955032477596fda0ab7eb4c..fb6990a99289a95b43916e33b9a81d81736a24c5 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=3gQr1FxFSe0"/>
+  <video href="https://www.youtube.com/watch?v=3gQr1FxFSe0"/>
 
   <hgroup>
    <vgroup>
index eb0b31104e24258403cac906bbb8d4a4ce1c7301..edb4f0e8baf1e64a68ae77f4272d72d185e27193 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=rHY8dR1urQk"/>
+  <video href="https://www.youtube.com/watch?v=rHY8dR1urQk"/>
 
   <hgroup>
    <vgroup>
index 22be2528fc2954da27cf216ca211bb488304fdde..ba2deff690f853024baad075f67120dad9025371 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=UsUGENa7jvE"/>
+  <video href="https://www.youtube.com/watch?v=UsUGENa7jvE"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 2909cd42101a12abbe6333962912ded38ee776b1..078099909701cd20c89c7ea272975d9032983b88 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=gYb-3EErLJE"/>
+  <video href="https://www.youtube.com/watch?v=gYb-3EErLJE"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
 <option _label="Great snub icosidodecahedron" arg-set="-which great_snub_icosidodecahedron"/>
 <option _label="Great pentagonal hexecontahedron" arg-set="-which great_pentagonal_hexecontahedron"/>
 <option _label="Small stellated truncated dodecahedron" arg-set="-which small_stellated_truncated_dodecahedron"/>
-<option _label="Great pentakisdodekahedron" arg-set="-which great_pentakisdodekahedron"/>
+<option _label="Great pentakisdodecahedron" arg-set="-which great_pentakisdodecahedron"/>
 <option _label="Truncated dodecadodecahedron" arg-set="-which truncated_dodecadodecahedron"/>
 <option _label="Medial disdyakistriacontahedron" arg-set="-which medial_disdyakistriacontahedron"/>
 <option _label="Inverted snub dodecadodecahedron" arg-set="-which inverted_snub_dodecadodecahedron"/>
index adbd824b8648af92bfca26315a39cb6f1b1f14cf..74b05f23e19818738a3a820a92749b628034ed93 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=6j2H2gL8cws"/>
+  <video href="https://www.youtube.com/watch?v=6j2H2gL8cws"/>
 
   <boolean id="identical" _label="Identical pieces" arg-set="-identical"/>
 
index 157a5b6b4b840a37d9683cc0ef0f63fbaa8d7d51..1e6f1f36150db719127dd430adf1a1ac0bc2f23c 100644 (file)
@@ -4,7 +4,7 @@
 
  <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=MKZQ5Q7QINM"/>
+  <video href="https://www.youtube.com/watch?v=MKZQ5Q7QINM"/>
 
  <hgroup>
   <vgroup>
index 6fdf1c1f28496ad53e68b8ed9f5d5c81e86d722f..3db1ff5c798d4fe36bb6fc706b952028799d0ec0 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=2jPmisDwwi0"/>
+  <video href="https://www.youtube.com/watch?v=2jPmisDwwi0"/>
 
   <hgroup>
    <vgroup>
index ce036b1236964f309dcb95bddfa42ea94685c244..8bc519ae13d0cd26c92fd2454e96838a7eaa50a3 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=99Aweq7Nypc"/>
+  <video href="https://www.youtube.com/watch?v=99Aweq7Nypc"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index fc625a9ed850ac0997a7d127699b3fe158769b40..fa9dfb86c7093a6b013156e85702e9a43d0639cc 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=Zg6ONPUTwUQ"/>
+  <video href="https://www.youtube.com/watch?v=Zg6ONPUTwUQ"/>
 
   <hgroup>
     <select id="display-mode">
index a51be31ecbf03a8b927f181208dbf957b8604a5e..0156dc06596ab534add18055af158e57d188f2eb 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=bnwRPPMopWc"/>
+  <video href="https://www.youtube.com/watch?v=bnwRPPMopWc"/>
 
   <number id="speed" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 7a21430923b71c79cbfbc172b04e192de988ea81..64be3bf73c3acc96e95a3197b161e4ef56351b3f 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=pR0lpvOAbUo"/>
+  <video href="https://www.youtube.com/watch?v=pR0lpvOAbUo"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 1a18855b0aa6783cf388794cf43d3b5259b0a266..ca81c3d019da337030b2afd1f1d5133fd7dc831d 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=JJqVfnMstuw"/>
+  <video href="https://www.youtube.com/watch?v=JJqVfnMstuw"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Slow" _high-label="Fast"
index 755d42ee503865adc3e69636984daf074015eb0e..a2a4ea239ff2c369d2138d67460a29456bb7a1e8 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=GPqDtJ0vF8U"/>
+  <video href="https://www.youtube.com/watch?v=GPqDtJ0vF8U"/>
 
   <hgroup>
    <vgroup>
index a5db06699f0912713fde247215f82a9d1d419ac6..0823c892945725e315555b153fb0b2ddadd45e92 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=JsGf65d5TfM"/>
+  <video href="https://www.youtube.com/watch?v=JsGf65d5TfM"/>
 
   <hgroup>
    <vgroup>
@@ -20,7 +20,8 @@
    <vgroup>
     <number id="count" type="slider" arg="-count %"
             _label="Density" _low-label="Low" _high-label="High"
-            low="7" high="37" default="17"/>
+            low="7" high="37" default="17"
+            convert="invert"/>
 
     <number id="contrast" type="slider" arg="-contrast %"
             _label="Contrast" _low-label="Low" _high-label="High"
index 112ada6ad4040d9dc8cd066ccd60f8c49181ce81..aa949fd4617d39ab8aff36d2bb067a79b88b917d 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=Ssy0ldFDeAs"/>
+  <video href="https://www.youtube.com/watch?v=Ssy0ldFDeAs"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
diff --git a/hacks/config/raverhoop.xml b/hacks/config/raverhoop.xml
new file mode 100644 (file)
index 0000000..4932255
--- /dev/null
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="raverhoop" _label="RaverHoop" gl="yes">
+
+  <command arg="-root"/>
+
+  <video href="https://www.youtube.com/watch?v=0k2sP_Imb80" />
+
+  <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="ncolors" type="slider" arg="-ncolors %"
+            _label="Colors" _low-label="1" _high-label="64"
+            low="1" high="64" default="12"/>
+
+    <number id="lights" type="slider" arg="-lights %"
+            _label="Lights" _low-label="Sparse" _high-label="Dense"
+            low="3" high="512" default="200"/>
+
+   </vgroup>
+   <vgroup>
+
+    <number id="speed" type="slider" arg="-speed %"
+            _label="Speed, motion" _low-label="Slow" _high-label="Fast"
+            low="0.1" high="5.0" default="1.0"/>
+
+    <number id="light-speed" type="slider" arg="-light-speed %"
+            _label="Speed, lights" _low-label="Slow" _high-label="Fast"
+            low="0.1" high="5.0" default="1.0"/>
+
+    <number id="sustain" type="slider" arg="-sustain %"
+            _label="Sustain" _low-label="Brief" _high-label="Long"
+            low="0.1" high="5.0" default="1.0"/>
+   </vgroup>
+  </hgroup>
+
+  <hgroup>
+   <boolean id="wander" _label="Wander"    arg-set="-wander"/>
+   <boolean id="spin"   _label="Spin"      arg-set="-spin"/>
+   <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
+  </hgroup>
+
+  <xscreensaver-updater />
+
+  <_description>
+Simulates an LED hula hoop in a dark room. Oontz oontz oontz.
+
+Written by Jamie Zawinski; 2016.
+  </_description>
+</screensaver>
index bfb153b0d3c063eb5ce6e313d55c7caa366ea37a..c8a656d5a09ecfd5c4ebdfa44c2da34743583822 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=xiooDyrZSsY"/>
+  <video href="https://www.youtube.com/watch?v=xiooDyrZSsY"/>
 
   <hgroup>
    <vgroup>
deleted file mode 100644 (file)
index 67de92797e7532a109db4630315d297cdda74c07..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1,66 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-
-<screensaver name="rd-bomb" _label="RDbomb">
-
-  <command arg="-root"/>
-
-  <hgroup>
-   <vgroup>
-    <number id="delay" type="slider" arg="-delay %"
-            _label="Frame rate" _low-label="Slow" _high-label="Fast"
-            low="0" high="250000" default="30000"
-            convert="invert"/>
-
-    <number id="speed" type="slider" arg="-speed %"
-             _label="Wander speed" _low-label="Slow" _high-label="Fast"
-             low="0.0" high="10.0" default="0.0"/>
-
-    <number id="size" type="slider" arg="-size %"
-             _label="Fill screen" _low-label="1%" _high-label="100%"
-             low="0.01" high="1.0" default="1.0"/>
-   </vgroup>
-   <vgroup>
-    <number id="epoch" type="slider" arg="-epoch %"
-             _label="Epoch" _low-label="Small" _high-label="Large"
-             low="1000" high="300000" default="40000"/>
-
-    <number id="ncolors" type="slider" arg="-ncolors %"
-              _label="Number of colors" _low-label="Two" _high-label="Many"
-              low="1" high="255" default="255"/>
-
-    <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
-
-    <xscreensaver-updater />
-
-   </vgroup>
-  </hgroup>
-
-  <hgroup>
-   <vgroup>
-    <number id="width" type="spinbutton" arg="-width %"
-            _label="X tile size" low="0" high="500" default="0"/>
-    <number id="pixheight" type="spinbutton" arg="-height %"
-            _label="Y tile size" low="0" high="500" default="0"/>
-   </vgroup>
-   <vgroup>
-    <number id="reaction" type="spinbutton" arg="-reaction %"
-            _label="Reaction" low="-1" high="2" default="-1"/>
-    <number id="diffusion" type="spinbutton" arg="-diffusion %"
-            _label="Diffusion" low="-1" high="2" default="-1"/>
-   </vgroup>
-   <vgroup>
-    <!-- #### default is wrong -->
-    <number id="radius" type="spinbutton" arg="-radius %"
-           _label="Seed radius" low="-1" high="60" default="-1"/>
-
-   </vgroup>
-
-  </hgroup>
-
-  <_description>
-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.
-  </_description>
-</screensaver>
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..b70f7a7709c046f5b72f0cd46b0ed0be3fdcaccc
--- /dev/null
@@ -0,0 +1 @@
+rd-bomb.xml
\ No newline at end of file
index 48b80b1917969c59bb461708ae66dc297d91721e..191e0419c9c5b662ceec9f0c26a798afc0ea3b74 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=w8YXAalnRzc"/>
+  <video href="https://www.youtube.com/watch?v=w8YXAalnRzc"/>
 
   <hgroup>
    <vgroup>
index 767db6c3b5b5c0dcdff4305915ac4ee32cca0759..964de8219f70aacb049739cef9b4ef3996a583b6 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=7x7PMI7LFK0"/>
+  <video href="https://www.youtube.com/watch?v=7x7PMI7LFK0"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 35d7c7e0b13e4644d2b57986a63b6829791e2693..b2f6cb4596686c6f8500b425db20693ad2f1546e 100644 (file)
@@ -2,7 +2,7 @@
 
 <screensaver name="romanboy" _label="RomanBoy" gl="yes">
 
-  <video href="http://www.youtube.com/watch?v=KEW5TuPbWyg"/>
+  <video href="https://www.youtube.com/watch?v=KEW5TuPbWyg"/>
 
   <command arg="-root"/>
 
index 1541e0e30c4a18b7ebe224ba418e475b1a260028..e4f0207f964480f04c52f28605ef0203d5a26b14 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=G1OLn4Mdk5Y"/>
+  <video href="https://www.youtube.com/watch?v=G1OLn4Mdk5Y"/>
 
   <number id="iterations" type="slider" arg="-iterations %"
           _label="Iterations" _low-label="Small" _high-label="Large"
index 9583e0fa276519f681333a2581adce8f1566a88e..2ffddf1ae0d295f7c01406e532edf5497ec7fbdb 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=HWcEvT1keDA"/>
+  <video href="https://www.youtube.com/watch?v=HWcEvT1keDA"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 18aa533e811500ea0e94fefacc09ed400503613a..bd4ce740e2a7a222c0c06c08629b3b402351c997 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=JVKDhd8gc7c"/>
+  <video href="https://www.youtube.com/watch?v=JVKDhd8gc7c"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index d7debd3c464677566f80191ef1ad88aa8de79150..f48668b4a0691f814164d0c1f6b28654a4a83c0f 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=AQdJgvyVkXU"/>
+  <video href="https://www.youtube.com/watch?v=AQdJgvyVkXU"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 213ba1f042b6295513442a01c16d656cfbb4c125..de96caf8d6342b34d242cef2018e560f3786f11f 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=B2sGaRLWz-A"/>
+  <video href="https://www.youtube.com/watch?v=B2sGaRLWz-A"/>
 
   <hgroup>
    <vgroup>
index 8de0c84658fba356168996a8be8a96824b788cf1..6a72def0e798f5bdb429fde8bf2c3810cd0eefbf 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=pcfqdvvPG8k"/>
+  <video href="https://www.youtube.com/watch?v=pcfqdvvPG8k"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index d906796dd00362b1ae2622a487ea558635ffe524..f34c5b9a73d477bdef55e6fb16d030e85760c03a 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=gJtxnQ5_8Zk"/>
+  <video href="https://www.youtube.com/watch?v=gJtxnQ5_8Zk"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index ee065393ef4950eb495da804e32213d780b30e88..3aec43ddc10455f8647b5350cd06e7f090da907b 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=m0zdPWuFhjA"/>
+  <video href="https://www.youtube.com/watch?v=m0zdPWuFhjA"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index c5bca419ecd010ef4a19cb2d7a84df9f9c4466e6..782fe9d8b440e0db896141bf5413574a3a9f8a08 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=TGQRLAhDLv0"/>
+  <video href="https://www.youtube.com/watch?v=TGQRLAhDLv0"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index bbbd1f0c2c55ba52e7aee121788cd5d148ca233a..e6d1b5b264270e448d45ef0ffcca6b57e3620d4d 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=iCjtXUSQv1A"/>
+  <video href="https://www.youtube.com/watch?v=iCjtXUSQv1A"/>
 
  <hgroup>
   <vgroup>
index 204d63092c2e9f4be0253455019b9758f51e8b5c..30189983c85d79892fb0071803db00ca42988f2d 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=uKNE4xCdlno"/>
+  <video href="https://www.youtube.com/watch?v=uKNE4xCdlno"/>
 
   <hgroup>
    <vgroup>
index 9be06dc93ef824edfbf7808ed1450e437821e460..5a656f37e923d536cdcf68a0d415ebf2d20ed153 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=BgzNvBm4MuE"/>
+  <video href="https://www.youtube.com/watch?v=BgzNvBm4MuE"/>
 
   <hgroup>
    <vgroup>
index 0f92dd330bca2dd5b9d2d8709ba7f0cc4cefd0cb..e459c51b3ac885bc79a27af3c0e9255f783c58e5 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=XEL8g3qbthE"/>
+  <video href="https://www.youtube.com/watch?v=XEL8g3qbthE"/>
 
   <hgroup>
    <vgroup>
index 0754a7094e07f574202875eb160c74cfad1b948a..cf7b88a482a774aed339cbd84cbdb551046e5c04 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=awOnhCxRD_c"/>
+  <video href="https://www.youtube.com/watch?v=awOnhCxRD_c"/>
 
   <hgroup>
    <vgroup>
index 2f5666dbe00e37fb139196f42836c4dd97eaa028..55a5d791e2cb1e5de5a06fd951445171fa0fcfe8 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=FswhxIVXdt8"/>
+  <video href="https://www.youtube.com/watch?v=FswhxIVXdt8"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 27d201a66ed8d67568a9324da431a67c1f7c079b..fc4fa92b905858937defcd280e4e5118fdd73804 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=KrNVwyWi0io"/>
+  <video href="https://www.youtube.com/watch?v=KrNVwyWi0io"/>
 
   <hgroup>
    <vgroup>
index 21bba9408c7e8f0c50b5e4638075b22778a534d6..71e78c717f60fafa77f364f72504ae3b3863b170 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=8Ov2SxnO_Kg"/>
+  <video href="https://www.youtube.com/watch?v=8Ov2SxnO_Kg"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 40c2cad2c37110e2e2b8765b32083e58bb04b982..265c9b6c32af3d2cb5bf99e31f50dae9ab565768 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=rZOL2jyDey0"/>
+  <video href="https://www.youtube.com/watch?v=rZOL2jyDey0"/>
 
   <hgroup>
    <vgroup>
index 7fa8c0fea8689cc5e948ac226913e7143c89ac25..24bfb9a050ffa752ef1de62febffd022de85a330 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=av29CVh2UeM"/>
+  <video href="https://www.youtube.com/watch?v=av29CVh2UeM"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 8a90229202e557f853b339fdcf9b05987a259bd6..1d16ff07428e6a44dbebf366861ca80c0e8d72bd 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=fmHl17ppgc0"/>
+  <video href="https://www.youtube.com/watch?v=fmHl17ppgc0"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 6ff728eb9339b70d3376c0d887cd0f7f57703b5c..1cc7e44ee3cc4bcafa1762a7b5251e57e9144915 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=WPhqyM9Bb4o"/>
+  <video href="https://www.youtube.com/watch?v=WPhqyM9Bb4o"/>
 
   <hgroup>
    <vgroup>
index 5f2c6940488566be8ac605657e7b641c2af82f52..099f963723afe763f2ec888b47b13593bbceea34 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=Y1ceRT30qr0"/>
+  <video href="https://www.youtube.com/watch?v=Y1ceRT30qr0"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 3e2a5e819de8e7d0b17a5307832d2339465c3ad5..006bc009710796e31e459483e6a1f5b836d1908d 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=atwc7IJHuLo"/>
+  <video href="https://www.youtube.com/watch?v=atwc7IJHuLo"/>
 
   <select id="mode">
     <option id="random" _label="Random"/>
index 1ce1f906aa5c1c8bb9d3b30536ffc32db80f7b6f..b70eedaf69468601ffce3eb8b38eb774d42b7a06 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=UUjC-6e7y_U"/>
+  <video href="https://www.youtube.com/watch?v=UUjC-6e7y_U"/>
 
   <hgroup>
    <vgroup>
index d52841c78f910b4d01dc4b53a66c322586eb9220..5db55f58e59330f2ac2289097915aed3e8c362a0 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=xvDK_wwnXWs"/>
+  <video href="https://www.youtube.com/watch?v=xvDK_wwnXWs"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index d8f3a2a7bf8e7b037ae698816787ce23ae2545b5..e4d530545a74e70c1d7239ee6997c90dd8e00d15 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=F1qna7UAxC0"/>
+  <video href="https://www.youtube.com/watch?v=F1qna7UAxC0"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 97158f8bf3fcd47ac48f353a355319c43dbde440..11e8ccc93ebda2a5ebda43f6d0c0ffda092c3b34 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=dCCVgBOVD0E"/>
+  <video href="https://www.youtube.com/watch?v=dCCVgBOVD0E"/>
 
   <hgroup>
    <vgroup>
index efb4811e9612d443398b438894ddd2b83a4bff82..642125cf0b1af9c53f165bdb473b9665716d1618 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=Mjlc7iPA1N4"/>
+  <video href="https://www.youtube.com/watch?v=Mjlc7iPA1N4"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index f4b4cab3676f08444a5470fbc3c1f4e406b87fa5..92a184aecf1dbf386eb69d704be9b4318ea8082a 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=Q412lxz3fTg"/>
+  <video href="https://www.youtube.com/watch?v=Q412lxz3fTg"/>
 
   <hgroup>
    <vgroup>
index a8cbed1617f0b0d6a593bb6707307810905502c5..199bdb75877c0fcabb1d9d8d31e0bb185234fd84 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=o_VRQxPCB7w"/>
+  <video href="https://www.youtube.com/watch?v=o_VRQxPCB7w"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 3de15550340ab062e12be65b09efe98d6fff7694..d1fd19b12812d41b2c8096963b728c54e86944c2 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=5UohH7U2CAI"/>
+  <video href="https://www.youtube.com/watch?v=5UohH7U2CAI"/>
 
   <hgroup>
    <vgroup>
index 8f58caa63852a1c75268d6c30b39758dfa1c3879..11b8f714b4fcc67940cbaede3a193ea806ecab01 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=JgJ-OsgCCJ4"/>
+  <video href="https://www.youtube.com/watch?v=JgJ-OsgCCJ4"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index acdd58655d0d559e261a28e87a5b492b711561f7..78b44e98f78167634e552a1dedf94dd1a438eebc 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=JNgybysnYU8"/>
+  <video href="https://www.youtube.com/watch?v=JNgybysnYU8"/>
 
   <hgroup>
    <vgroup>
index 0c940cca6ade765d23a7ba2eb1b32255c3fc23c2..8bbd1ab52e1ca019239b0fe8e828aba2d77725d8 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=rfGfPezVnac"/>
+  <video href="https://www.youtube.com/watch?v=rfGfPezVnac"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 0f7e22df29794d798a2e0442b964e9613d458dd3..3f14c03e9cad75702169a72ad7460b6d17edc0de 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=GZe5rk_7TnA"/>
+  <video href="https://www.youtube.com/watch?v=GZe5rk_7TnA"/>
 
   <number id="start" type="slider" arg="-start %"
           _label="Start sequence time" _low-label="0 sec" _high-label="30 sec"
index 590af18fee13c018c8a74ad9e5bd850e768a8fae..df498bcfb0415f32a77d3847af0120bd172e0ce0 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=zj0FHFJgQJ8"/>
+  <video href="https://www.youtube.com/watch?v=zj0FHFJgQJ8"/>
 
   <hgroup>
    <vgroup>
index 2eaf7f797a14bec43b63b162a626fc2b2bb4e383..70d9949b03ceb98c158db985c451e609fea21292 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=GXrzjY-Flro"/>
+  <video href="https://www.youtube.com/watch?v=GXrzjY-Flro"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 499536b9246b06f5a547f520fd5a18d4699782ed..965d3338673f13e58c2836816e9f73b6eaf58243 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=dIF4fodt-L8"/>
+  <video href="https://www.youtube.com/watch?v=dIF4fodt-L8"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 4440347af53504a340e6a9c4ab4f3707fd497f6d..c20a3f8825ed987bf675f44c02d68a894b82bdcc 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=hoJ23JSsUD8"/>
+  <video href="https://www.youtube.com/watch?v=hoJ23JSsUD8"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 824f420ff3175c26830bcb1dd162f86c93ea8785..3eefdeda4106f9988660ac0b3f012a4e135d9d86 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=7pxDMSduQoU"/>
+  <video href="https://www.youtube.com/watch?v=7pxDMSduQoU"/>
 
   <hgroup>
    <vgroup>
diff --git a/hacks/config/unicrud.xml b/hacks/config/unicrud.xml
new file mode 100644 (file)
index 0000000..bf56fb1
--- /dev/null
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="unicrud" _label="Unicrud" gl="yes">
+
+  <command arg="-root"/>
+
+  <video href="https://www.youtube.com/watch?v=prEzdYMZ7xA"/>
+
+  <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="Animation speed" _low-label="Slow" _high-label="Fast"
+          low="0.05" high="10.0" default="1.0"/>
+
+  <hgroup>
+   <boolean id="wander" _label="Wander"    arg-unset="-no-wander"/>
+   <boolean id="spin"   _label="Spin"      arg-unset="-no-spin"/>
+   <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
+  </hgroup>
+
+  <select id="block">
+    <option _label="Display everything"/>
+    <option _label="Display Latin1" arg-set="-block Latin1,Latin_Extended-A,Latin_Extended-B,Spacing_Modifier_Letters"/>
+    <option _label="Display simple characters" arg-set="-block Latin1,Latin_Extended-A,Latin_Extended-B,Spacing_Modifier_Letters,Phonetic_Extensions,Latin_Extended_Additional,Greek_Extended,General_Punctuation,Superscripts_and_Subscripts,Currency_Symbols,Letterlike_Symbols,Number_Forms"/>
+    <option _label="Display mathematical symbols" arg-set="-block Greek_and_Coptic,Mathematical_Operators,Miscellaneous_Mathematical_Symbols-A,Supplemental_Arrows-A,Supplemental_Arrows-B,Miscellaneous_Mathematical_Symbols-B,Supplemental_Mathematical_Operators,Miscellaneous_Symbols_and_Arrows"/>
+    <option _label="Display emoticons" arg-set="-block Currency_Symbols,Miscellaneous_Technical,Box_Drawing,Geometric_Shapes,Miscellaneous_Symbols,Dingbats,Mahjong_Tiles,Domino_Tiles,Playing_Cards,Miscellaneous_Symbols_and_Pictographs,Emoticons,Ornamental_Dingbats,Transport_and_Map_Symbols,Alchemical_Symbols,Geometric_Shapes_Extended,Supplemental_Symbols_and_Pictographs,Egyptian_Hieroglyphs"/>
+    <option _label="Display hieroglyphs" arg-set="-block Egyptian_Hieroglyphs"/>
+  </select>
+
+  <xscreensaver-updater />
+
+  <_description>
+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.
+  </_description>
+</screensaver>
index 92a441f040e19b816dd25c9675f6db38ae5ecabf..7ef79ac6ecd2f6491101b69954affe69c6f8fbdf 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=vuWhUxBq99E"/>
+  <video href="https://www.youtube.com/watch?v=vuWhUxBq99E"/>
 
   <hgroup>
    <vgroup>
index d144e9565e7573f1147703a7ab58e7aa1e1f8e5c..55a8b755e18be359348ccbc3a287b6771211b234 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=YSg9KY-qw5o"/>
+  <video href="https://www.youtube.com/watch?v=YSg9KY-qw5o"/>
 
   <number id="speed" type="slider" arg="-speed %"
           _label="Duration" _low-label="Short" _high-label="Long"
index e34ce3b71fe4d032f53f4d7c9bd0b4d53ea8a8e6..0299d77da2a2191fa821a3a53580d8d14f8e3588 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=IaVfFCIAUn8"/>
+  <video href="https://www.youtube.com/watch?v=IaVfFCIAUn8"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 9239be2825dc15ab43948634fe36d3ffdd5e8280..9e0ef2e13b89f0ce59821228dc033037a96b5b75 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=hD_8cBvknUM"/>
+  <video href="https://www.youtube.com/watch?v=hD_8cBvknUM"/>
 
   <hgroup>
    <vgroup>
index b2fec25b1debe3200cf519c7166c82b3e5a4e857..ad72fe883cd9cadb42ec33d10fb6fdc2e8f38de5 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=2ZZC46Z9wJE"/>
+  <video href="https://www.youtube.com/watch?v=2ZZC46Z9wJE"/>
 
   <hgroup>
    <vgroup>
index d645290638328d9dd2bd23b5f4bf238522e86900..c26ea984f60241054da740f6429e5d99407bb6c4 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=u8esWjcR4eI"/>
+  <video href="https://www.youtube.com/watch?v=u8esWjcR4eI"/>
 
   <hgroup>
    <vgroup>
@@ -49,7 +49,7 @@ 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 http://www.jwz.org/webcollage/
+See also https://www.jwz.org/webcollage/
 
 Written by Jamie Zawinski; 1999.
   </_description>
index 823e372f47d64fd0d3c9f9a3257edbe349c5aa66..7cd774e2a9f58aa6ee7ba3ebe92c5f9d9b541112 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=eWrRhSYzimY"/>
+  <video href="https://www.youtube.com/watch?v=eWrRhSYzimY"/>
 
   <number id="points" type="slider" arg="-points %"
           _label="Particles" _low-label="Few" _high-label="Many"
index e5c05b311b5ded962dd9663ed00b590031720b63..d7842dbad1506cdf2665f8508b1525b72330e926 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=Y2JTY7bssPM"/>
+  <video href="https://www.youtube.com/watch?v=Y2JTY7bssPM"/>
 
   <hgroup>
    <number id="whirlies" type="spinbutton" arg="-whirlies %"
index a642b5bcf18e1729627374a0a0dbf6e5e17f2b9d..0aaf78a99b2c1c9513d4de47a8c566ad140728c2 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=RmpsDx9MuUM"/>
+  <video href="https://www.youtube.com/watch?v=RmpsDx9MuUM"/>
 
   <hgroup>
    <vgroup>
index a1ab72c20d261c5f69ce1b42bc421ef83859daf9..9678f2900d798c3ac2134ddd379c8c581c26b8f4 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=-S26J2Ja11g"/>
+  <video href="https://www.youtube.com/watch?v=-S26J2Ja11g"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 1314456bb77334df8ae4a13ba410eaf9177f788b..387afa156f9b675f0d24ecb80ab806b9c11cd461 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=jGuJU8JKxlI"/>
+  <video href="https://www.youtube.com/watch?v=jGuJU8JKxlI"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 66f2c204080400cb045cf82615757b75c693669b..3de067f47c4f804a2022f7d08cc37e93787ebc8f 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=VmM1KkFsry0"/>
+  <video href="https://www.youtube.com/watch?v=VmM1KkFsry0"/>
 
   <xscreensaver-image />
 
index 8c3a3568aeabd70b06877a432a811fe6b95b8a63..783dcab52428117ff99cca2f9db56fee160369c3 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=jUJiULU4i0k"/>
+  <video href="https://www.youtube.com/watch?v=jUJiULU4i0k"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 959ca57aff02cb6b9924c0edbcecb4f4f0310cda..542d19f61309fc12a90b333d5aeca99f38568998 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=wSOiSrEbxu4"/>
+  <video href="https://www.youtube.com/watch?v=wSOiSrEbxu4"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Speed" _low-label="Slow" _high-label="Fast"
index 27233ac24d946bdc76e33f5b3b69dddc56f0055d..1d2e17642196e9bf523d4dbeb0660972f86b2ac4 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=5MrEaXnhEPg"/>
+  <video href="https://www.youtube.com/watch?v=5MrEaXnhEPg"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 19c97a9614677aab5e5c5fbc3635c8b184498463..b1afe9c6e4062e05ef3efc2b9472e60a3749d357 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=dSJQHm-YoWc"/>
+  <video href="https://www.youtube.com/watch?v=dSJQHm-YoWc"/>
 
   <hgroup>
    <select id="size">
index 0f2efc446684a80debf86638f2bcbf4df8f219ab..5aaf815aa2234d550af4c0064644c41c4b455aa3 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=e_E-k37b4Vc"/>
+  <video href="https://www.youtube.com/watch?v=e_E-k37b4Vc"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index d63bd6bd3b8a0e1e4f3b972a0b35f8e3b34b954e..6be28f044ac4f6b4479cd9b1572afc43c8daf6ae 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=XWCeQqzNavY"/>
+  <video href="https://www.youtube.com/watch?v=XWCeQqzNavY"/>
 
   <number id="delay" type="slider" arg="-subdelay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
index 6593f66ddcfdcbc313ecf648dd5d653f96c403c5..c538bb89a9477293deade86daa90004fd2a70f70 100644 (file)
@@ -4,7 +4,7 @@
 
   <command arg="-root"/>
 
-  <video href="http://www.youtube.com/watch?v=LeQa9inGEKc"/>
+  <video href="https://www.youtube.com/watch?v=LeQa9inGEKc"/>
 
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
   <hgroup>
    <vgroup>
     <number id="pixwidth" type="spinbutton" arg="-pixwidth %"
-            _label="X magnification" low="2" high="100" default="10"/>
+            _label="X mag" low="2" high="100" default="40" />
     <number id="pixspacex" type="spinbutton" arg="-pixspacex %"
-            _label=" X border width" low="0" high="10" default="2"/>
+            _label=" X border" low="0" high="10" default="2" />
     <number id="lensoffsetx" type="spinbutton" arg="-lensoffsetx %"
-            _label="   X lens offset" low="1" high="100" default="5"/>
+            _label="   X lens" low="1" high="100" default="5" />
    </vgroup>
    <vgroup>
     <number id="pixheight" type="spinbutton" arg="-pixheight %"
-            _label="Y magnification" low="2" high="100" default="10"/>
+            _label="Y mag" low="2" high="100" default="40" />
     <number id="pixspacey" type="spinbutton" arg="-pixspacey %"
-            _label=" Y border width" low="0" high="10" default="2"/>
+            _label=" Y border" low="0" high="10" default="2" />
     <number id="lensoffsety" type="spinbutton" arg="-lensoffsety %"
-            _label="    Y lens offset" low="1" high="100" default="5"/>
+            _label="    Y lens" low="1" high="100" default="5" />
    </vgroup>
 
    <vgroup>
index 7a4e4a97b517bd657aa771c1fb1ac9ae5eb854de..0f7f255a544a3a88e968f5a6ec0edfdd4e7b1398 100644 (file)
@@ -296,7 +296,7 @@ static const char *coral_defaults[] = {
   "*seeds:     20", /* too many for 640x480, too few for 1280x1024 */
   "*delay:     5",
   "*delay2:    20000",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
   0
index ab3a6f7366e3ca853b6b2031f950dd212e105ef0..81fd0c1a1056547e789302e5082bb4f03541f596 100644 (file)
@@ -100,8 +100,10 @@ model_allocate (int model_w, int model_h)
   mm->height = model_h;
 
   mm->cells = malloc (sizeof (unsigned short) * model_w * model_h);
-  if (!mm->cells)
+  if (!mm->cells) {
+    free (mm);
     return 0;
+  }
 
   return mm;
 }
@@ -290,7 +292,7 @@ critical_init (Display *dpy, Window window)
   model_w = 80;
   st->settings.cell_size = st->wattr.width / model_w;
   model_h = st->settings.cell_size ?
-    st->wattr.height / st->settings.cell_size : 0;
+    st->wattr.height / st->settings.cell_size : 1;
 
   /* Construct the initial model state. */
 
@@ -319,7 +321,7 @@ critical_init (Display *dpy, Window window)
 
   st->fgc = XCreateGC (st->dpy, st->window, 0, &st->gcv);
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
   jwxyz_XSetAntiAliasing (dpy, st->fgc, False);
   jwxyz_XSetAntiAliasing (dpy, st->bgc, False);
 #endif
index 8b077c88fa29725db65cb11d5c23280f184f4bc3..9dfa5ea266873d9e953c57d41732aeaf993d6724 100644 (file)
@@ -567,7 +567,7 @@ draw_crystal(ModeInfo * mi)
        crystalstruct *cryst = &crystals[MI_SCREEN(mi)];
        int         i;
 
-#ifdef HAVE_COCOA      /* Don't second-guess Quartz's double-buffering */
+#ifdef HAVE_JWXYZ      /* Don't second-guess Quartz's double-buffering */
     XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi));
 #endif
 
index f14a498603bea1513ed75dcc9c247ac8924b11a9..2caea50da34a42960548dbedf6ee632ae61b5f11 100644 (file)
@@ -193,7 +193,7 @@ static const char *cwaves_defaults [] = {
   "*scale:                2",
   "*debug:                False",
   "*delay:                20000",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation:        True",
 #endif
   0
index 5420d14d4fbfdf99503019cc82c9b1efda8c078a..9a4318b7cdce04b3e120891c3b51d5ac7ef8be43 100644 (file)
@@ -155,7 +155,7 @@ cynosure_init (Display *d, Window w)
 #else /* !DO_STIPPLE */
   st->shadow_gc = XCreateGC(st->dpy, st->window, GCForeground, &gcv);
 
-#  ifdef HAVE_COCOA /* allow non-opaque alpha components in pixel values */
+#  ifdef HAVE_JWXYZ /* allow non-opaque alpha components in pixel values */
   jwxyz_XSetAlphaAllowed (st->dpy, st->shadow_gc, True);
 #  endif
 
@@ -167,14 +167,14 @@ cynosure_init (Display *d, Window w)
 
       for (i = 0; i < st->ncolors2; i++)
         {
-#  ifdef HAVE_COCOA
+#  ifdef HAVE_JWXYZ
           /* give a non-opaque alpha to the shadow colors */
           unsigned long pixel = st->colors[i].pixel;
           unsigned long amask = BlackPixelOfScreen (st->xgwa.screen);
           unsigned long a = (0x77777777 & amask);
           pixel = (pixel & (~amask)) | a;
           st->colors2[i].pixel = pixel;
-#  else /* !HAVE_COCOA */
+#  else /* !HAVE_JWXYZ */
           int h;
           double s, v;
           rgb_to_hsv (st->colors[i].red,
@@ -188,7 +188,7 @@ cynosure_init (Display *d, Window w)
                       &st->colors2[i].blue);
           st->colors2[i].pixel = st->colors[i].pixel;
           XAllocColor (st->dpy, st->xgwa.colormap, &st->colors2[i]);
-#  endif /* !HAVE_COCOA */
+#  endif /* !HAVE_JWXYZ */
         }
     }
 # endif /* !DO_STIPPLE */
@@ -425,7 +425,7 @@ static const char *cynosure_defaults [] = {
   "*sway:              30",
   "*tweak:             20",
   "*gridSize:          12",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation:     True",
 #endif
   0
index e2ce9a0963d347c00ea0a7851d47b185599d8403..f0d4e95c6b2b4da8ca000f46f115b36628b47c2c 100644 (file)
@@ -36,6 +36,7 @@
  */
 
 #include "screenhack.h"
+#include <time.h>
 
 struct state {
   Display *dpy;
@@ -372,7 +373,7 @@ static const char *decayscreen_defaults [] = {
   "*delay:                     10000",
   "*mode:                      random",
   "*duration:                  120",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation:             True",
   "*rotateImages:               True",
 #endif
index 27ada0502553f698aecf30e05c8b1e268e91dde1..1839056c4e274859cfe00fe390557b4da23365a1 100644 (file)
@@ -313,7 +313,7 @@ static const char *deco_defaults [] = {
   "*goldenRatio:        False",
   "*smoothColors:       False",
   "*mondrian:           False",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation:     True",
 #endif
   0
index 06cfe1b9dc7373b3c4d1b15e4331930f8f6fcc04..3db698c9ddbdf3ea98dca8380111c1b48488f183 100644 (file)
@@ -173,7 +173,7 @@ make_throbber (struct state *st, Drawable d, int w, int h, unsigned long pixel)
   if (t->speed > 0) t->speed = -t->speed;
 
   flags = GCForeground;
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
   if (st->transparent_p)
     {
       gcv.foreground = ~0L;
@@ -181,7 +181,7 @@ make_throbber (struct state *st, Drawable d, int w, int h, unsigned long pixel)
       flags |= GCPlaneMask;
     }
   else
-# endif /* !HAVE_COCOA */
+# endif /* !HAVE_JWXYZ */
     {
       gcv.foreground = pixel;
     }
@@ -193,7 +193,7 @@ make_throbber (struct state *st, Drawable d, int w, int h, unsigned long pixel)
   flags |= (GCLineWidth | GCCapStyle | GCJoinStyle);
   t->gc = XCreateGC (st->dpy, d, flags, &gcv);
 
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
   if (st->transparent_p)
     {
       /* give a non-opaque alpha to the color */
@@ -205,7 +205,7 @@ make_throbber (struct state *st, Drawable d, int w, int h, unsigned long pixel)
       jwxyz_XSetAlphaAllowed (st->dpy, t->gc, True);
       XSetForeground (st->dpy, t->gc, pixel);
     }
-# endif /* HAVE_COCOA */
+# endif /* HAVE_JWXYZ */
 
   switch (random() % 11) {
   case 0: case 1: case 2: case 3: t->draw = draw_star; break;
@@ -275,7 +275,7 @@ deluxe_init (Display *dpy, Window window)
   st->dbeclear_p = get_boolean_resource (st->dpy, "useDBEClear", "Boolean");
 #endif
 
-# ifdef HAVE_COCOA     /* Don't second-guess Quartz's double-buffering */
+# ifdef HAVE_JWXYZ     /* Don't second-guess Quartz's double-buffering */
   st->dbuf = False;
 # endif
 
@@ -292,7 +292,7 @@ deluxe_init (Display *dpy, Window window)
       st->colors[0].pixel = get_pixel_resource(st->dpy, st->xgwa.colormap,
                                            "foreground", "Foreground");
     }
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
   else if (st->transparent_p)
     {
       st->nplanes = get_integer_resource (st->dpy, "planes", "Planes");
@@ -313,10 +313,10 @@ deluxe_init (Display *dpy, Window window)
          goto COLOR;
        }
     }
-#endif /* !HAVE_COCOA */
+#endif /* !HAVE_JWXYZ */
   else
     {
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
     COLOR:
 #endif
       make_random_colormap (st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap,
@@ -438,7 +438,7 @@ static const char *deluxe_defaults [] = {
   "*useDBE:            True",
   "*useDBEClear:       True",
 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation:     True",
 #endif
   0
index 47c545abe41c32d6895cbcca5888d9abe835d88d..03ddf1f76087341b741709816c59a8c595442d0c 100644 (file)
@@ -46,7 +46,7 @@ static const char sccsid[] = "@(#)demon.c     5.00 2000/11/01 xlockmore";
   Triangle 3, 9, or 12
 */
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # define DO_STIPPLE
 #endif
 
@@ -446,7 +446,7 @@ init_demon (ModeInfo * mi)
 #endif /* DO_STIPPLE */
        free_struct(dp);
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
     jwxyz_XSetAntiAliasing (MI_DISPLAY(mi), MI_GC(mi), False);
 #endif
 
index 28593f06f3aa8793c56001ab6543f62fff09cd9d..477ee63b77844dbdaae1a07bf68f628558a7627d 100644 (file)
@@ -35,6 +35,7 @@
  */
 
 #include <math.h>
+#include <time.h>
 #include "screenhack.h"
 /*#include <X11/Xmd.h>*/
 
@@ -847,7 +848,7 @@ static const char *distort_defaults [] = {
 #ifdef HAVE_XSHM_EXTENSION
        "*useSHM:                       False",         /* xshm turns out not to help. */
 #endif /* HAVE_XSHM_EXTENSION */
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation:     True",
   "*rotateImages:       True",
 #endif
index 4f94a907e4abc6aaa0c0513e8499d43f179b406e..91a47a28ee93489cca060e3f2dce3795595cf5e3 100644 (file)
@@ -65,7 +65,7 @@ static const char *epicycle_defaults [] = {
   "*divisorPoisson: 0.4",
   "*sizeFactorMin: 1.05",
   "*sizeFactorMax: 2.05",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
   0
@@ -723,7 +723,7 @@ epicycle_draw (Display *dpy, Window window, void *closure)
 
       st->L = compute_divisor_lcm(st->pb0->epicycles);
       
-      st->colour_cycle_rate = fabs(st->L);
+      st->colour_cycle_rate = labs(st->L);
       
       st->xtime = fabs(st->L * st->circle / st->wdot_max);
 
index c8bd46f725a3f7571ac5042aa75b29d7368dc76a..e50d8194b2c6ef3d00df79676f8d16a6a305c18c 100644 (file)
@@ -527,7 +527,7 @@ init_euler2d (ModeInfo * mi)
        }
        sp = &euler2ds[MI_SCREEN(mi)];
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
   jwxyz_XSetAntiAliasing (MI_DISPLAY(mi), MI_GC(mi),  False);
 #endif
 
index 4c594fbb99f7b36d31663953653864338e9241f7..43157751415f3b7c128f88b4bec3ff9b2c793d8f 100644 (file)
@@ -165,7 +165,7 @@ init_fiberlamp(ModeInfo * mi)
   fl = &fiberlamps[MI_SCREEN(mi)];
 
   /* Create or Resize double buffer */
-#ifdef HAVE_COCOA      /* Don't second-guess Quartz's double-buffering */
+#ifdef HAVE_JWXYZ      /* Don't second-guess Quartz's double-buffering */
   fl->dbufp = False;
 #else
   fl->dbufp = True;
index 351ca0002fca3df1a015a5e148e9eb72ecb3a5c1..92e6f1765c7bb6d57ee49f9eac99c33157c38392 100644 (file)
@@ -194,7 +194,7 @@ make_flag_bits(ModeInfo *mi)
   char *bitmap_name = get_string_resource (dpy, "bitmap", "Bitmap");
   char *text = get_string_resource (dpy, "text", "Text");
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
   bitmap_name = 0;  /* #### always use default */
 #endif
 
@@ -460,7 +460,7 @@ init_flag(ModeInfo * mi)
 
        if (!fp->initialized) {
       fp->dbufp = True;
-# ifdef HAVE_COCOA             /* Don't second-guess Quartz's double-buffering */
+# ifdef HAVE_JWXYZ             /* Don't second-guess Quartz's double-buffering */
       fp->dbufp = False;
 #endif
                fp->initialized = True;
index 9f13c87bafe93beac020afcec0876306688d88bc..7b590563f20c4eb249a2630ced15fd2a2f322612 100644 (file)
@@ -419,7 +419,7 @@ static const char *flame_defaults [] = {
   "*delay:     50000",
   "*delay2:    2000000",
   "*points:    10000",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
   0
index fc69e3a5d5ffae5be17ce4688cf5b9b87d1c4e62..cfbc2b1e501d6d371332e57bc18887bfa216be9f 100644 (file)
@@ -778,7 +778,7 @@ init_flow (ModeInfo * mi)
                sp->beecount = NRAND(-sp->beecount) + 1; /* Minimum 1 */
        }
 
-# ifdef HAVE_COCOA     /* Don't second-guess Quartz's double-buffering */
+# ifdef HAVE_JWXYZ     /* Don't second-guess Quartz's double-buffering */
   dbufp = False;
 # endif
 
@@ -834,7 +834,7 @@ draw_flow (ModeInfo * mi)
        if (sp->csegs == NULL)
                return;
 
-#ifdef HAVE_COCOA      /* Don't second-guess Quartz's double-buffering */
+#ifdef HAVE_JWXYZ      /* Don't second-guess Quartz's double-buffering */
     XClearWindow (MI_DISPLAY(mi), MI_WINDOW(mi));
 #endif
 
index 6bab228740d4c38266dfa2fec6fe9b2691c60fbd..7fc43bd2c9d5ae8afb63c668b7de7dbfe8f28a97 100644 (file)
@@ -228,7 +228,7 @@ fluidballs_init (Display *dpy, Window window)
 
   state->dbuf = get_boolean_resource (dpy, "doubleBuffer", "Boolean");
 
-# ifdef HAVE_COCOA     /* Don't second-guess Quartz's double-buffering */
+# ifdef HAVE_JWXYZ     /* Don't second-guess Quartz's double-buffering */
   state->dbuf = False;
 # endif
 
@@ -330,7 +330,7 @@ fluidballs_init (Display *dpy, Window window)
                                                "ShakeThreshold");
   state->time_tick = 999999;
 
-# ifdef USE_IPHONE     /* Always obey real-world gravity */
+# ifdef HAVE_MOBILE    /* Always obey real-world gravity */
   state->shake_p = False;
 # endif
 
@@ -449,11 +449,12 @@ check_wall_clock (b_state *state, float max_d)
 
       state->time_since_shake += (now.tv_sec - state->last_time.tv_sec);
 
-# ifdef USE_IPHONE     /* Always obey real-world gravity */
+# ifdef HAVE_MOBILE    /* Always obey real-world gravity */
       {
         float a = fabs (fabs(state->accx) > fabs(state->accy)
                         ? state->accx : state->accy);
-        switch ((int) current_device_rotation ()) {
+        int rot = current_device_rotation();
+        switch (rot) {
         case    0: case  360: state->accx =  0; state->accy =  a; break;
         case  -90:            state->accx = -a; state->accy =  0; break;
         case   90:            state->accx =  a; state->accy =  0; break;
@@ -461,7 +462,7 @@ check_wall_clock (b_state *state, float max_d)
         default: break;
         }
       }
-# endif /* USE_IPHONE */
+# endif /* HAVE_MOBILE */
 
       if (state->fps_p) 
        {
@@ -488,28 +489,32 @@ static void
 repaint_balls (b_state *state)
 {
   int a;
+# ifndef HAVE_JWXYZ
   int x1a, x2a, y1a, y2a;
+# endif
   int x1b, x2b, y1b, y2b;
   float max_d = 0;
 
-#ifdef HAVE_COCOA      /* Don't second-guess Quartz's double-buffering */
+#ifdef HAVE_JWXYZ      /* Don't second-guess Quartz's double-buffering */
   XClearWindow (state->dpy, state->b);
 #endif
 
   for (a=1; a <= state->count; a++)
     {
       GC gc;
+# ifndef HAVE_JWXYZ
       x1a = (state->opx[a] - state->r[a] - state->xmin);
       y1a = (state->opy[a] - state->r[a] - state->ymin);
       x2a = (state->opx[a] + state->r[a] - state->xmin);
       y2a = (state->opy[a] + state->r[a] - state->ymin);
+# endif
 
       x1b = (state->px[a] - state->r[a] - state->xmin);
       y1b = (state->py[a] - state->r[a] - state->ymin);
       x2b = (state->px[a] + state->r[a] - state->xmin);
       y2b = (state->py[a] + state->r[a] - state->ymin);
 
-#ifndef HAVE_COCOA     /* Don't second-guess Quartz's double-buffering */
+#ifndef HAVE_JWXYZ     /* Don't second-guess Quartz's double-buffering */
 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
       if (!state->dbeclear_p || !state->backb)
 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
@@ -522,7 +527,7 @@ repaint_balls (b_state *state)
                        0, 360*64);
            }
        }
-#endif /* !HAVE_COCOA */
+#endif /* !HAVE_JWXYZ */
 
       if (state->mouse_ball == a)
         gc = state->draw_gc2;
@@ -795,7 +800,7 @@ fluidballs_free (Display *dpy, Window window, void *closure)
 static const char *fluidballs_defaults [] = {
   ".background:                black",
   ".foreground:                yellow",
-  ".textColor:         white",
+  ".textColor:         yellow",
   "*mouseForeground:   white",
   "*delay:             10000",
   "*count:             300",
@@ -812,7 +817,7 @@ static const char *fluidballs_defaults [] = {
   "*useDBE:            True",
   "*useDBEClear:       True",
 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation:    True",
 #endif
   0
index e45591fca8b3934379ae1527d790eb55502d7928..6a304171fa88e8ba142518e91d352e5c47efbd73 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2003-2015 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2003-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
@@ -25,8 +25,9 @@
 /* #define DEBUG */
 
 #include <math.h>
+#include <time.h>
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # include <X11/Intrinsic.h>
 #endif
 
@@ -174,7 +175,7 @@ pick_font_1 (state *s, sentence *se)
   char pattern[1024];
   char pattern2[1024];
 
-# ifndef HAVE_COCOA /* real Xlib */
+#ifndef HAVE_JWXYZ /* real Xlib */
   char **names = 0;
   char **names2 = 0;
   XFontStruct *info = 0;
@@ -333,7 +334,7 @@ pick_font_1 (state *s, sentence *se)
   XFreeFontInfo (names2, info, count2);
   XFreeFontNames (names);
 
-# else  /* HAVE_COCOA */
+# else  /* HAVE_JWXYZ */
 
   if (s->font_override)
     sprintf (pattern, "%.200s", s->font_override);
@@ -346,7 +347,7 @@ pick_font_1 (state *s, sentence *se)
       sprintf (pattern, "*-%s-%s-%s-*-*-*-%d-*", family, weight, slant, size);
     }
   ok = True;
-# endif /* HAVE_COCOA */
+# endif /* HAVE_JWXYZ */
 
   if (! ok) return False;
 
@@ -364,7 +365,7 @@ pick_font_1 (state *s, sentence *se)
     }
 
   strcpy (pattern2, pattern);
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
   {
     float s;
     const char *n = jwxyz_nativeFontName (se->xftfont->xfont->fid, &s);
@@ -493,7 +494,7 @@ static char *unread_word_text = 0;
 /* Returns a newly-allocated string with one word in it, or NULL if there
    is no complete word available.
  */
-static const char *
+static char *
 get_word_text (state *s)
 {
   const char *start = s->buf;
@@ -520,9 +521,9 @@ get_word_text (state *s)
 
   if (unread_word_text)
     {
-      start = unread_word_text;
+      result = unread_word_text;
       unread_word_text = 0;
-      return start;
+      return strdup (result);
     }
 
   /* Skip over whitespace at the beginning of the buffer,
@@ -1121,7 +1122,7 @@ populate_sentence (state *s, sentence *se)
 
   while (!done)
     {
-      const char *txt = get_word_text (s);
+      char *txt = get_word_text (s);
       word *w;
       if (!txt)
         {
@@ -1146,6 +1147,8 @@ populate_sentence (state *s, sentence *se)
         }
 
       w = new_word (s, se, txt, !se->move_chars_p);
+      free (txt);
+      txt = 0;
 
       /* If we have a few words, let punctuation terminate the sentence:
          stop gathering more words if the last word ends in a period, etc. */
@@ -1185,6 +1188,7 @@ populate_sentence (state *s, sentence *se)
               y + se->xftfont->ascent + se->xftfont->descent > s->xgwa.height)
             {
               unread_word (s, w);
+              free (w);
               /* done = True; */
               break;
             }
@@ -1592,7 +1596,7 @@ fontglide_draw_metrics (state *s)
   gc  = XCreateGC (s->dpy, dest, 0, 0);
   XSetFont (s->dpy, gc,  s->metrics_font1->fid);
 
-# ifdef HAVE_COCOA
+# if defined(HAVE_JWXYZ)
   jwxyz_XSetAntiAliasing (s->dpy, gc, False);
 # endif
 
@@ -1617,7 +1621,7 @@ fontglide_draw_metrics (state *s)
     }
 
   strcpy (fn2, fn);
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
   {
     float ss;
     const char *n = jwxyz_nativeFontName (s->metrics_xftfont->xfont->fid, &ss);
@@ -1652,7 +1656,7 @@ fontglide_draw_metrics (state *s)
                s->xgwa.height - 5,
                fn2, strlen(fn2));
 
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
   {
     char *name =
       jwxyz_unicode_character_name (s->metrics_font1->fid, s->debug_metrics_p);
@@ -1741,7 +1745,7 @@ fontglide_draw_metrics (state *s)
         {
           Pixmap p2;
           GC gc2 = XCreateGC (s->dpy, p, 0, 0);
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
           jwxyz_XSetAntiAliasing (s->dpy, gc2, False);
 # endif
           XSetFont (s->dpy, gc2, s->metrics_font1->fid);
@@ -1749,7 +1753,7 @@ fontglide_draw_metrics (state *s)
           XFillRectangle (s->dpy, p, gc2, 0, 0, pixw, pixh);
           XSetForeground (s->dpy, gc,  WhitePixelOfScreen (s->xgwa.screen));
           XSetForeground (s->dpy, gc2, WhitePixelOfScreen (s->xgwa.screen));
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
           jwxyz_XSetAntiAliasing (s->dpy, gc2,
                                   s->debug_metrics_antialiasing_p);
 # endif
@@ -1890,7 +1894,7 @@ fontglide_draw_metrics (state *s)
         {
           XSetFont (s->dpy, gc, s->metrics_font1->fid);
           XSetForeground (s->dpy, gc,  WhitePixelOfScreen (s->xgwa.screen));
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
           jwxyz_XSetAntiAliasing (s->dpy, gc, s->debug_metrics_antialiasing_p);
 # endif
           sprintf (txt2, "%s        [XX%sXX]    [%s%s%s%s]",
@@ -1913,7 +1917,7 @@ fontglide_draw_metrics (state *s)
                          xoff + x/2 + (sc*cc.rbearing/2) - cc.rbearing/2,
                          ascent + 10,
                          txt2, strlen(txt2));
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
           jwxyz_XSetAntiAliasing (s->dpy, gc, False);
 # endif
           XSetFont (s->dpy, gc, s->metrics_font2->fid);
@@ -1949,7 +1953,7 @@ fontglide_draw_metrics (state *s)
                        txt2, strlen(txt2));
         }
 
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
       jwxyz_XSetAntiAliasing (s->dpy, gc, True);
 # endif
 
@@ -2056,7 +2060,7 @@ fontglide_draw_metrics (state *s)
                  xoff + x + sc*cc.rbearing, y - sc*ascent,
                  xoff + x + sc*cc.rbearing, y + sc*descent + 40);
 
-      y += sc * (ascent + descent) * 2;
+      /* y += sc * (ascent + descent) * 2; */
     }
   }
 
@@ -2196,7 +2200,7 @@ fontglide_init (Display *dpy, Window window)
                         ? 199 : 0);
   s->debug_scale = 6;
 
-#  ifdef HAVE_COCOA
+#  ifdef HAVE_JWXYZ
   if (s->debug_metrics_p && !s->font_override)
     s->font_override = "Helvetica Bold 16";
 #  endif
@@ -2205,7 +2209,7 @@ fontglide_init (Display *dpy, Window window)
 
   s->dbuf = get_boolean_resource (dpy, "doubleBuffer", "Boolean");
 
-# ifdef HAVE_COCOA     /* Don't second-guess Quartz's double-buffering */
+# ifdef HAVE_JWXYZ     /* Don't second-guess Quartz's double-buffering */
   s->dbuf = False;
 # endif
 
index d99ab84bf049267250cb64c331cf9cc6da9ee493..d3832c1f68014db0bb05951f1a38ad10729e5e35 100644 (file)
@@ -26,7 +26,7 @@ extern double fps_compute (fps_state *, unsigned long polys, double depth);
 extern void fps_draw (fps_state *);
 
 /* Doesn't really belong here, but close enough. */
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   extern double current_device_rotation (void);
 #else
 # define current_device_rotation() (0)
index 91762eac7ff55682a79c6d289251d7d77a600a88..072bce49345e32bc63c55906a1a84d4625d95735 100644 (file)
@@ -320,7 +320,7 @@ FuzzyFlakesInit(Flake *flake)
    flake->DB.b = flake->DB.ba = flake->DB.bb = 0;
    flake->DB.dbuf = get_boolean_resource(flake->dpy, "doubleBuffer", "Boolean");
 
-# ifdef HAVE_COCOA     /* Don't second-guess Quartz's double-buffering */
+# ifdef HAVE_JWXYZ     /* Don't second-guess Quartz's double-buffering */
    flake->DB.dbuf = False;
 # endif
 
index 2aeeb6f30f0cc11640d7088d1eb6acb1f83c9af1..b8fbd0c4ce8db57ba5a251fa46b4b8be2ee40706 100644 (file)
@@ -313,7 +313,7 @@ init_galaxy(ModeInfo * mi)
  }
  gp = &universes[MI_SCREEN(mi)];
 
-# ifdef HAVE_COCOA     /* Don't second-guess Quartz's double-buffering */
+# ifdef HAVE_JWXYZ     /* Don't second-guess Quartz's double-buffering */
   dbufp = False;
 # endif
 
index 211d35681547c9884124478a666cb1c702608275..678a510c3697608b02776c69f0b7b45be51b411a 100644 (file)
@@ -64,9 +64,11 @@ MINIXPM              = $(UTILS_BIN)/minixpm.o
 HACK_SRC       = $(srcdir)/..
 HACK_BIN       = ..
 UTILS_SRC      = $(HACK_SRC)/../utils
+JWXYZ_SRC      = $(HACK_SRC)/../jwxyz
 UTILS_BIN      = $(HACK_BIN)/../utils
+JWXYZ_BIN      = $(HACK_BIN)/../jwxyz
 
-INCLUDES_1     = -I. -I$(srcdir) -I$(UTILS_SRC) -I$(HACK_SRC) -I../..
+INCLUDES_1     = -I. -I$(srcdir) -I$(UTILS_SRC) -I$(JWXYZ_SRC) -I$(HACK_SRC) -I../..
 INCLUDES       = $(INCLUDES_1) @INCLUDES@
 
 UTILDIR_OBJS   = $(UTILS_BIN)/colors.o $(UTILS_BIN)/grabclient.o \
@@ -79,6 +81,7 @@ UTILDIR_OBJS  = $(UTILS_BIN)/colors.o $(UTILS_BIN)/grabclient.o \
                  $(UTILS_BIN)/textclient.o $(UTILS_BIN)/async_netdb.o \
                  $(UTILS_BIN)/aligned_malloc.o $(UTILS_BIN)/thread_util.o \
                  $(UTILS_BIN)/spline.o
+JWXYZ_OBJS     = $(JWXYZ_BIN)/jwzgles.o
 HACKDIR_OBJS   = $(HACK_SRC)/screenhack.o $(UTILS_SRC)/xlockmore.o \
                  $(HACK_SRC)/fps.o
 
@@ -119,10 +122,12 @@ SRCS              = xscreensaver-gl-helper.c normals.c fps-gl.c \
                  jigsaw.c photopile.c dropshadow.c rubikblocks.c surfaces.c \
                  hilbert.c companion.c companion_quad.c companion_disc.c \
                  companion_heart.c tronbit.c tronbit_idle1.c tronbit_idle2.c \
-                 tronbit_no.c tronbit_yes.c jwzgles.c kaleidocycle.c \
+                 tronbit_no.c tronbit_yes.c kaleidocycle.c \
                  quasicrystal.c unknownpleasures.c geodesic.c geodesicgears.c \
                  projectiveplane.c winduprobot.c robot.c robot-wireframe.c \
-                 cityflow.c romanboy.c splitflap.c splitflap_obj.c
+                 cityflow.c romanboy.c splitflap.c splitflap_obj.c \
+                 dymaxionmap.c unicrud.c energystream.c raverhoop.c \
+                 hydrostat.c
 
 OBJS           = xscreensaver-gl-helper.o normals.o fps-gl.o \
                  atlantis.o b_draw.o b_lockglue.o b_sphere.o bubble3d.o \
@@ -161,10 +166,12 @@ OBJS              = xscreensaver-gl-helper.o normals.o fps-gl.o \
                  jigsaw.o photopile.o dropshadow.o rubikblocks.o surfaces.o \
                  hilbert.o companion.o companion_quad.o companion_disc.o \
                  companion_heart.o tronbit.o tronbit_idle1.o tronbit_idle2.o \
-                 tronbit_no.o tronbit_yes.o jwzgles.o kaleidocycle.o \
+                 tronbit_no.o tronbit_yes.o kaleidocycle.o \
                  quasicrystal.o unknownpleasures.o geodesic.o geodesicgears.o \
                  projectiveplane.o winduprobot.o robot.o robot-wireframe.o \
-                 cityflow.o romanboy.o splitflap.o splitflap_obj.o
+                 cityflow.o romanboy.o splitflap.o splitflap_obj.o \
+                 dymaxionmap.o unicrud.o energystream.o raverhoop.o \
+                 hydrostat.o
 
 GL_EXES                = cage gears moebius pipes sproingies stairs superquadrics \
                  morph3d rubik atlantis lament bubble3d glplanet pulsar \
@@ -182,7 +189,8 @@ GL_EXES             = cage gears moebius pipes sproingies stairs superquadrics \
                  rubikblocks surfaces hilbert companioncube tronbit \
                  kaleidocycle quasicrystal unknownpleasures geodesic \
                  geodesicgears projectiveplane winduprobot cityflow romanboy \
-                 splitflap
+                 splitflap dymaxionmap unicrud energystream raverhoop \
+                 hydrostat
 GLE_EXES       = extrusion
 SUID_EXES      = sonar
 GL_UTIL_EXES   = xscreensaver-gl-helper
@@ -217,7 +225,7 @@ HDRS                = atlantis.h bubble3d.h buildlwo.h e_textures.h xpm-ximage.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 \
-                 jwzgles.h jwzglesI.h teapot2.h dnapizza.h curlicue.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 \
@@ -242,7 +250,8 @@ GL_MEN              = atlantis.man boxed.man bubble3d.man cage.man circuit.man \
                  companioncube.man tronbit.man kaleidocycle.man \
                  quasicrystal.man unknownpleasures.man geodesic.man \
                  geodesicgears.man projectiveplane.man winduprobot.man \
-                 cityflow.man romanboy.man splitflap.man
+                 cityflow.man romanboy.man splitflap.man dymaxionmap.man \
+                 unicrud.man energystream.man raverhoop.man hydrostat.man
 MEN            = @GL_MEN@
 RETIRED_MEN    = glforestfire.man
 EXTRAS         = README Makefile.in dxf2gl.pl vrml2gl.pl wfront2gl.pl \
@@ -422,6 +431,7 @@ distdepend:: molecules.h
          sed -e '/^#.*/d'                                                  \
              -e 's@ \./@ @g;s@ /[^ ]*@@g;/^.*:$$/d'                        \
              -e 's@\.\./\.\./utils@$$(UTILS_SRC)@g'                        \
+             -e 's@\.\./\.\./jwxyz@$$(JWXYZ_SRC)@g'                        \
              -e 's@\.\./glx/@@g'                                           \
              -e 's@ \.\./@ $$(HACK_SRC)/@g'                                \
              -e 's@ \([^$$]\)@ $$(srcdir)/\1@g'                            \
@@ -494,6 +504,8 @@ $(HACK_BIN)/fps.o:          $(HACK_SRC)/fps.c
 
 $(UTILDIR_OBJS):
        $(MAKE) -C $(UTILS_BIN) $(@F) CC="$(CC)" CFLAGS="$(CFLAGS)"
+$(JWXYZ_OBJS):
+       $(MAKE) -C $(JWXYZ_BIN) $(@F) CC="$(CC)" CFLAGS="$(CFLAGS)"
 $(HACKDIR_OBJS):
        $(MAKE) -C $(HACK_BIN) $(@F) CC="$(CC)" CFLAGS="$(CFLAGS)"
 
@@ -593,6 +605,9 @@ PLANET_OBJS=sphere.o xpm-ximage.o $(HACK_TRACK_OBJS)
 glplanet:      glplanet.o      $(PLANET_OBJS)
        $(CC_HACK) -o $@ $@.o   $(PLANET_OBJS) $(XPM_LIBS)
 
+dymaxionmap:   dymaxionmap.o   normals.o $(PLANET_OBJS)
+       $(CC_HACK) -o $@ $@.o   normals.o $(PLANET_OBJS) $(XPM_LIBS)
+
 pulsar:                pulsar.o        $(HACK_OBJS) xpm-ximage.o
        $(CC_HACK) -o $@ $@.o   $(HACK_OBJS) xpm-ximage.o $(XPM_LIBS)
 
@@ -753,7 +768,6 @@ STONER_OBJS=stonerview-move.o stonerview-osc.o stonerview-view.o
 stonerview:    stonerview.o    $(STONER_OBJS) $(HACK_TRACK_OBJS)
        $(CC_HACK) -o $@ $@.o   $(STONER_OBJS) $(HACK_TRACK_OBJS) $(HACK_LIBS)
 
-
 molecules.h:
        @echo "building molecules.h from $(HACK_SRC)/images/molecules/*.pdb"; \
        UTILS_SRC="$(UTILS_SRC)" \
@@ -910,6 +924,19 @@ FLAP_OBJS=splitflap_obj.o gllist.o splitflap.o $(TEXT) $(HACK_TRACK_OBJS)
 splitflap:                     $(FLAP_OBJS)
        $(CC_HACK) -o $@        $(FLAP_OBJS) $(XPM_LIBS) $(TEXT_LIBS)
 
+unicrud:       unicrud.o       $(HACK_TRACK_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(HACK_TRACK_OBJS) $(HACK_LIBS)
+
+ES_OBJS=xpm-ximage.o $(HACK_TRACK_OBJS)
+energystream:  energystream.o  $(ES_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(ES_OBJS) $(XPM_LIBS) $(HACK_LIBS)
+
+raverhoop:     raverhoop.o     $(HACK_TRACK_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(HACK_TRACK_OBJS) $(HACK_LIBS)
+
+HSTAT_OBJS=sphere.o normals.o $(HACK_TRACK_OBJS)
+hydrostat:     hydrostat.o     $(HSTAT_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(HSTAT_OBJS) $(HACK_LIBS)
 
 ##############################################################################
 #
@@ -918,8 +945,6 @@ splitflap:                  $(FLAP_OBJS)
 antinspect.o: ../../config.h
 antinspect.o: $(HACK_SRC)/fps.h
 antinspect.o: $(srcdir)/gltrackball.h
-antinspect.o: $(srcdir)/jwzglesI.h
-antinspect.o: $(srcdir)/jwzgles.h
 antinspect.o: $(HACK_SRC)/screenhackI.h
 antinspect.o: $(srcdir)/sphere.h
 antinspect.o: $(UTILS_SRC)/colors.h
@@ -936,8 +961,6 @@ antmaze.o: $(srcdir)/ants.h
 antmaze.o: ../../config.h
 antmaze.o: $(HACK_SRC)/fps.h
 antmaze.o: $(srcdir)/gltrackball.h
-antmaze.o: $(srcdir)/jwzglesI.h
-antmaze.o: $(srcdir)/jwzgles.h
 antmaze.o: $(srcdir)/rotator.h
 antmaze.o: $(HACK_SRC)/screenhackI.h
 antmaze.o: $(srcdir)/sphere.h
@@ -957,8 +980,6 @@ antspotlight.o: ../../config.h
 antspotlight.o: $(HACK_SRC)/fps.h
 antspotlight.o: $(srcdir)/gltrackball.h
 antspotlight.o: $(srcdir)/grab-ximage.h
-antspotlight.o: $(srcdir)/jwzglesI.h
-antspotlight.o: $(srcdir)/jwzgles.h
 antspotlight.o: $(srcdir)/rotator.h
 antspotlight.o: $(HACK_SRC)/screenhackI.h
 antspotlight.o: $(srcdir)/sphere.h
@@ -977,8 +998,6 @@ atlantis.o: $(srcdir)/atlantis.h
 atlantis.o: ../../config.h
 atlantis.o: $(HACK_SRC)/fps.h
 atlantis.o: $(HACK_SRC)/images/sea-texture.xpm
-atlantis.o: $(srcdir)/jwzglesI.h
-atlantis.o: $(srcdir)/jwzgles.h
 atlantis.o: $(HACK_SRC)/screenhackI.h
 atlantis.o: $(UTILS_SRC)/colors.h
 atlantis.o: $(UTILS_SRC)/grabscreen.h
@@ -999,8 +1018,6 @@ atunnel.o: $(HACK_SRC)/images/tunnel2.xpm
 atunnel.o: $(HACK_SRC)/images/tunnel3.xpm
 atunnel.o: $(HACK_SRC)/images/tunnel4.xpm
 atunnel.o: $(HACK_SRC)/images/tunnel5.xpm
-atunnel.o: $(srcdir)/jwzglesI.h
-atunnel.o: $(srcdir)/jwzgles.h
 atunnel.o: $(HACK_SRC)/screenhackI.h
 atunnel.o: $(srcdir)/tunnel_draw.h
 atunnel.o: $(UTILS_SRC)/colors.h
@@ -1017,8 +1034,6 @@ atunnel.o: $(srcdir)/xpm-ximage.h
 b_draw.o: $(srcdir)/bubble3d.h
 b_draw.o: ../../config.h
 b_draw.o: $(HACK_SRC)/fps.h
-b_draw.o: $(srcdir)/jwzglesI.h
-b_draw.o: $(srcdir)/jwzgles.h
 b_draw.o: $(HACK_SRC)/screenhackI.h
 b_draw.o: $(UTILS_SRC)/colors.h
 b_draw.o: $(UTILS_SRC)/grabscreen.h
@@ -1031,8 +1046,6 @@ b_draw.o: $(UTILS_SRC)/yarandom.h
 b_draw.o: $(HACK_SRC)/xlockmoreI.h
 blinkbox.o: ../../config.h
 blinkbox.o: $(HACK_SRC)/fps.h
-blinkbox.o: $(srcdir)/jwzglesI.h
-blinkbox.o: $(srcdir)/jwzgles.h
 blinkbox.o: $(HACK_SRC)/screenhackI.h
 blinkbox.o: $(srcdir)/sphere.h
 blinkbox.o: $(UTILS_SRC)/colors.h
@@ -1048,8 +1061,6 @@ blinkbox.o: $(HACK_SRC)/xlockmore.h
 b_lockglue.o: $(srcdir)/bubble3d.h
 b_lockglue.o: ../../config.h
 b_lockglue.o: $(HACK_SRC)/fps.h
-b_lockglue.o: $(srcdir)/jwzglesI.h
-b_lockglue.o: $(srcdir)/jwzgles.h
 b_lockglue.o: $(HACK_SRC)/screenhackI.h
 b_lockglue.o: $(UTILS_SRC)/colors.h
 b_lockglue.o: $(UTILS_SRC)/grabscreen.h
@@ -1064,8 +1075,6 @@ b_lockglue.o: $(HACK_SRC)/xlockmore.h
 blocktube.o: ../../config.h
 blocktube.o: $(HACK_SRC)/fps.h
 blocktube.o: $(HACK_SRC)/images/blocktube.xpm
-blocktube.o: $(srcdir)/jwzglesI.h
-blocktube.o: $(srcdir)/jwzgles.h
 blocktube.o: $(HACK_SRC)/screenhackI.h
 blocktube.o: $(UTILS_SRC)/colors.h
 blocktube.o: $(UTILS_SRC)/grabscreen.h
@@ -1081,8 +1090,6 @@ blocktube.o: $(srcdir)/xpm-ximage.h
 boing.o: ../../config.h
 boing.o: $(HACK_SRC)/fps.h
 boing.o: $(srcdir)/gltrackball.h
-boing.o: $(srcdir)/jwzglesI.h
-boing.o: $(srcdir)/jwzgles.h
 boing.o: $(HACK_SRC)/screenhackI.h
 boing.o: $(UTILS_SRC)/colors.h
 boing.o: $(UTILS_SRC)/grabscreen.h
@@ -1098,8 +1105,6 @@ bouncingcow.o: ../../config.h
 bouncingcow.o: $(HACK_SRC)/fps.h
 bouncingcow.o: $(srcdir)/gllist.h
 bouncingcow.o: $(srcdir)/gltrackball.h
-bouncingcow.o: $(srcdir)/jwzglesI.h
-bouncingcow.o: $(srcdir)/jwzgles.h
 bouncingcow.o: $(srcdir)/rotator.h
 bouncingcow.o: $(HACK_SRC)/screenhackI.h
 bouncingcow.o: $(UTILS_SRC)/colors.h
@@ -1116,8 +1121,6 @@ bouncingcow.o: $(srcdir)/xpm-ximage.h
 boxed.o: $(srcdir)/boxed.h
 boxed.o: ../../config.h
 boxed.o: $(HACK_SRC)/fps.h
-boxed.o: $(srcdir)/jwzglesI.h
-boxed.o: $(srcdir)/jwzgles.h
 boxed.o: $(HACK_SRC)/screenhackI.h
 boxed.o: $(UTILS_SRC)/colors.h
 boxed.o: $(UTILS_SRC)/grabscreen.h
@@ -1132,8 +1135,6 @@ boxed.o: $(HACK_SRC)/xlockmore.h
 b_sphere.o: $(srcdir)/bubble3d.h
 b_sphere.o: ../../config.h
 b_sphere.o: $(HACK_SRC)/fps.h
-b_sphere.o: $(srcdir)/jwzglesI.h
-b_sphere.o: $(srcdir)/jwzgles.h
 b_sphere.o: $(HACK_SRC)/screenhackI.h
 b_sphere.o: $(UTILS_SRC)/colors.h
 b_sphere.o: $(UTILS_SRC)/grabscreen.h
@@ -1147,8 +1148,6 @@ b_sphere.o: $(HACK_SRC)/xlockmoreI.h
 bubble3d.o: $(srcdir)/bubble3d.h
 bubble3d.o: ../../config.h
 bubble3d.o: $(HACK_SRC)/fps.h
-bubble3d.o: $(srcdir)/jwzglesI.h
-bubble3d.o: $(srcdir)/jwzgles.h
 bubble3d.o: $(HACK_SRC)/screenhackI.h
 bubble3d.o: $(UTILS_SRC)/colors.h
 bubble3d.o: $(UTILS_SRC)/grabscreen.h
@@ -1161,13 +1160,9 @@ bubble3d.o: $(UTILS_SRC)/yarandom.h
 bubble3d.o: $(HACK_SRC)/xlockmoreI.h
 buildlwo.o: $(srcdir)/buildlwo.h
 buildlwo.o: ../../config.h
-buildlwo.o: $(srcdir)/jwzglesI.h
-buildlwo.o: $(srcdir)/jwzgles.h
 cage.o: ../../config.h
 cage.o: $(HACK_SRC)/fps.h
 cage.o: $(HACK_SRC)/images/wood.xpm
-cage.o: $(srcdir)/jwzglesI.h
-cage.o: $(srcdir)/jwzgles.h
 cage.o: $(HACK_SRC)/screenhackI.h
 cage.o: $(UTILS_SRC)/colors.h
 cage.o: $(UTILS_SRC)/grabscreen.h
@@ -1184,8 +1179,6 @@ carousel.o: ../../config.h
 carousel.o: $(HACK_SRC)/fps.h
 carousel.o: $(srcdir)/gltrackball.h
 carousel.o: $(srcdir)/grab-ximage.h
-carousel.o: $(srcdir)/jwzglesI.h
-carousel.o: $(srcdir)/jwzgles.h
 carousel.o: $(srcdir)/rotator.h
 carousel.o: $(HACK_SRC)/screenhackI.h
 carousel.o: $(srcdir)/texfont.h
@@ -1201,12 +1194,8 @@ carousel.o: $(HACK_SRC)/xlockmoreI.h
 carousel.o: $(HACK_SRC)/xlockmore.h
 chessmodels.o: $(srcdir)/chessmodels.h
 chessmodels.o: ../../config.h
-chessmodels.o: $(srcdir)/jwzglesI.h
-chessmodels.o: $(srcdir)/jwzgles.h
 circuit.o: ../../config.h
 circuit.o: $(HACK_SRC)/fps.h
-circuit.o: $(srcdir)/jwzglesI.h
-circuit.o: $(srcdir)/jwzgles.h
 circuit.o: $(HACK_SRC)/screenhackI.h
 circuit.o: $(srcdir)/texfont.h
 circuit.o: $(UTILS_SRC)/colors.h
@@ -1222,8 +1211,6 @@ circuit.o: $(HACK_SRC)/xlockmore.h
 cityflow.o: ../../config.h
 cityflow.o: $(HACK_SRC)/fps.h
 cityflow.o: $(srcdir)/gltrackball.h
-cityflow.o: $(srcdir)/jwzglesI.h
-cityflow.o: $(srcdir)/jwzgles.h
 cityflow.o: $(HACK_SRC)/screenhackI.h
 cityflow.o: $(UTILS_SRC)/colors.h
 cityflow.o: $(UTILS_SRC)/grabscreen.h
@@ -1237,18 +1224,12 @@ cityflow.o: $(HACK_SRC)/xlockmoreI.h
 cityflow.o: $(HACK_SRC)/xlockmore.h
 companion_disc.o: ../../config.h
 companion_disc.o: $(srcdir)/gllist.h
-companion_disc.o: $(srcdir)/jwzglesI.h
-companion_disc.o: $(srcdir)/jwzgles.h
 companion_heart.o: ../../config.h
 companion_heart.o: $(srcdir)/gllist.h
-companion_heart.o: $(srcdir)/jwzglesI.h
-companion_heart.o: $(srcdir)/jwzgles.h
 companion.o: ../../config.h
 companion.o: $(HACK_SRC)/fps.h
 companion.o: $(srcdir)/gllist.h
 companion.o: $(srcdir)/gltrackball.h
-companion.o: $(srcdir)/jwzglesI.h
-companion.o: $(srcdir)/jwzgles.h
 companion.o: $(srcdir)/rotator.h
 companion.o: $(HACK_SRC)/screenhackI.h
 companion.o: $(UTILS_SRC)/colors.h
@@ -1264,36 +1245,20 @@ companion.o: $(HACK_SRC)/xlockmore.h
 companion.o: $(srcdir)/xpm-ximage.h
 companion_quad.o: ../../config.h
 companion_quad.o: $(srcdir)/gllist.h
-companion_quad.o: $(srcdir)/jwzglesI.h
-companion_quad.o: $(srcdir)/jwzgles.h
 cow_face.o: ../../config.h
 cow_face.o: $(srcdir)/gllist.h
-cow_face.o: $(srcdir)/jwzglesI.h
-cow_face.o: $(srcdir)/jwzgles.h
 cow_hide.o: ../../config.h
 cow_hide.o: $(srcdir)/gllist.h
-cow_hide.o: $(srcdir)/jwzglesI.h
-cow_hide.o: $(srcdir)/jwzgles.h
 cow_hoofs.o: ../../config.h
 cow_hoofs.o: $(srcdir)/gllist.h
-cow_hoofs.o: $(srcdir)/jwzglesI.h
-cow_hoofs.o: $(srcdir)/jwzgles.h
 cow_horns.o: ../../config.h
 cow_horns.o: $(srcdir)/gllist.h
-cow_horns.o: $(srcdir)/jwzglesI.h
-cow_horns.o: $(srcdir)/jwzgles.h
 cow_tail.o: ../../config.h
 cow_tail.o: $(srcdir)/gllist.h
-cow_tail.o: $(srcdir)/jwzglesI.h
-cow_tail.o: $(srcdir)/jwzgles.h
 cow_udder.o: ../../config.h
 cow_udder.o: $(srcdir)/gllist.h
-cow_udder.o: $(srcdir)/jwzglesI.h
-cow_udder.o: $(srcdir)/jwzgles.h
 crackberg.o: ../../config.h
 crackberg.o: $(HACK_SRC)/fps.h
-crackberg.o: $(srcdir)/jwzglesI.h
-crackberg.o: $(srcdir)/jwzgles.h
 crackberg.o: $(HACK_SRC)/screenhackI.h
 crackberg.o: $(UTILS_SRC)/colors.h
 crackberg.o: $(UTILS_SRC)/grabscreen.h
@@ -1308,8 +1273,6 @@ crackberg.o: $(HACK_SRC)/xlockmore.h
 cube21.o: ../../config.h
 cube21.o: $(HACK_SRC)/fps.h
 cube21.o: $(srcdir)/gltrackball.h
-cube21.o: $(srcdir)/jwzglesI.h
-cube21.o: $(srcdir)/jwzgles.h
 cube21.o: $(HACK_SRC)/screenhackI.h
 cube21.o: $(UTILS_SRC)/colors.h
 cube21.o: $(UTILS_SRC)/grabscreen.h
@@ -1324,8 +1287,6 @@ cube21.o: $(HACK_SRC)/xlockmore.h
 cubenetic.o: ../../config.h
 cubenetic.o: $(HACK_SRC)/fps.h
 cubenetic.o: $(srcdir)/gltrackball.h
-cubenetic.o: $(srcdir)/jwzglesI.h
-cubenetic.o: $(srcdir)/jwzgles.h
 cubenetic.o: $(srcdir)/rotator.h
 cubenetic.o: $(HACK_SRC)/screenhackI.h
 cubenetic.o: $(UTILS_SRC)/colors.h
@@ -1341,8 +1302,6 @@ cubenetic.o: $(HACK_SRC)/xlockmore.h
 cubestorm.o: ../../config.h
 cubestorm.o: $(HACK_SRC)/fps.h
 cubestorm.o: $(srcdir)/gltrackball.h
-cubestorm.o: $(srcdir)/jwzglesI.h
-cubestorm.o: $(srcdir)/jwzgles.h
 cubestorm.o: $(srcdir)/rotator.h
 cubestorm.o: $(HACK_SRC)/screenhackI.h
 cubestorm.o: $(UTILS_SRC)/colors.h
@@ -1358,8 +1317,6 @@ cubestorm.o: $(HACK_SRC)/xlockmore.h
 cubicgrid.o: ../../config.h
 cubicgrid.o: $(HACK_SRC)/fps.h
 cubicgrid.o: $(srcdir)/gltrackball.h
-cubicgrid.o: $(srcdir)/jwzglesI.h
-cubicgrid.o: $(srcdir)/jwzgles.h
 cubicgrid.o: $(srcdir)/rotator.h
 cubicgrid.o: $(HACK_SRC)/screenhackI.h
 cubicgrid.o: $(UTILS_SRC)/colors.h
@@ -1375,8 +1332,6 @@ cubicgrid.o: $(HACK_SRC)/xlockmore.h
 dangerball.o: ../../config.h
 dangerball.o: $(HACK_SRC)/fps.h
 dangerball.o: $(srcdir)/gltrackball.h
-dangerball.o: $(srcdir)/jwzglesI.h
-dangerball.o: $(srcdir)/jwzgles.h
 dangerball.o: $(srcdir)/rotator.h
 dangerball.o: $(HACK_SRC)/screenhackI.h
 dangerball.o: $(srcdir)/sphere.h
@@ -1392,11 +1347,8 @@ dangerball.o: $(UTILS_SRC)/yarandom.h
 dangerball.o: $(HACK_SRC)/xlockmoreI.h
 dangerball.o: $(HACK_SRC)/xlockmore.h
 dnalogo.o: ../../config.h
-dnalogo.o: $(srcdir)/dnapizza.h
 dnalogo.o: $(HACK_SRC)/fps.h
 dnalogo.o: $(srcdir)/gltrackball.h
-dnalogo.o: $(srcdir)/jwzglesI.h
-dnalogo.o: $(srcdir)/jwzgles.h
 dnalogo.o: $(srcdir)/normals.h
 dnalogo.o: $(srcdir)/rotator.h
 dnalogo.o: $(HACK_SRC)/screenhackI.h
@@ -1417,8 +1369,6 @@ dnalogo.o: $(HACK_SRC)/xlockmore.h
 dolphin.o: $(srcdir)/atlantis.h
 dolphin.o: ../../config.h
 dolphin.o: $(HACK_SRC)/fps.h
-dolphin.o: $(srcdir)/jwzglesI.h
-dolphin.o: $(srcdir)/jwzgles.h
 dolphin.o: $(HACK_SRC)/screenhackI.h
 dolphin.o: $(UTILS_SRC)/colors.h
 dolphin.o: $(UTILS_SRC)/grabscreen.h
@@ -1429,15 +1379,43 @@ dolphin.o: $(UTILS_SRC)/visual.h
 dolphin.o: $(UTILS_SRC)/yarandom.h
 dropshadow.o: ../../config.h
 dropshadow.o: $(srcdir)/dropshadow.h
-dropshadow.o: $(srcdir)/jwzglesI.h
-dropshadow.o: $(srcdir)/jwzgles.h
+dropshadow.o: $(HACK_SRC)/fps.h
+dropshadow.o: $(HACK_SRC)/screenhackI.h
+dropshadow.o: $(UTILS_SRC)/colors.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
+dymaxionmap.o: $(HACK_SRC)/fps.h
+dymaxionmap.o: $(srcdir)/gltrackball.h
+dymaxionmap.o: $(HACK_SRC)/images/dymaxionmap.xpm
+dymaxionmap.o: $(HACK_SRC)/images/ground.xpm
+dymaxionmap.o: $(srcdir)/normals.h
+dymaxionmap.o: $(srcdir)/rotator.h
+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)/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
+dymaxionmap.o: $(srcdir)/xpm-ximage.h
 endgame.o: $(srcdir)/chessgames.h
 endgame.o: $(srcdir)/chessmodels.h
 endgame.o: ../../config.h
 endgame.o: $(HACK_SRC)/fps.h
 endgame.o: $(srcdir)/gltrackball.h
-endgame.o: $(srcdir)/jwzglesI.h
-endgame.o: $(srcdir)/jwzgles.h
 endgame.o: $(HACK_SRC)/screenhackI.h
 endgame.o: $(UTILS_SRC)/colors.h
 endgame.o: $(UTILS_SRC)/grabscreen.h
@@ -1449,11 +1427,24 @@ endgame.o: $(UTILS_SRC)/xshm.h
 endgame.o: $(UTILS_SRC)/yarandom.h
 endgame.o: $(HACK_SRC)/xlockmoreI.h
 endgame.o: $(HACK_SRC)/xlockmore.h
+energystream.o: ../../config.h
+energystream.o: $(HACK_SRC)/fps.h
+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)/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
 engine.o: ../../config.h
 engine.o: $(HACK_SRC)/fps.h
 engine.o: $(srcdir)/gltrackball.h
-engine.o: $(srcdir)/jwzglesI.h
-engine.o: $(srcdir)/jwzgles.h
 engine.o: $(srcdir)/rotator.h
 engine.o: $(HACK_SRC)/screenhackI.h
 engine.o: $(srcdir)/texfont.h
@@ -1469,26 +1460,16 @@ engine.o: $(HACK_SRC)/xlockmoreI.h
 engine.o: $(HACK_SRC)/xlockmore.h
 extrusion-helix2.o: ../../config.h
 extrusion-helix2.o: $(srcdir)/extrusion.h
-extrusion-helix2.o: $(srcdir)/jwzglesI.h
-extrusion-helix2.o: $(srcdir)/jwzgles.h
 extrusion-helix3.o: ../../config.h
 extrusion-helix3.o: $(srcdir)/extrusion.h
-extrusion-helix3.o: $(srcdir)/jwzglesI.h
-extrusion-helix3.o: $(srcdir)/jwzgles.h
 extrusion-helix4.o: ../../config.h
 extrusion-helix4.o: $(srcdir)/extrusion.h
-extrusion-helix4.o: $(srcdir)/jwzglesI.h
-extrusion-helix4.o: $(srcdir)/jwzgles.h
 extrusion-joinoffset.o: ../../config.h
 extrusion-joinoffset.o: $(srcdir)/extrusion.h
-extrusion-joinoffset.o: $(srcdir)/jwzglesI.h
-extrusion-joinoffset.o: $(srcdir)/jwzgles.h
 extrusion.o: ../../config.h
 extrusion.o: $(srcdir)/extrusion.h
 extrusion.o: $(HACK_SRC)/fps.h
 extrusion.o: $(srcdir)/gltrackball.h
-extrusion.o: $(srcdir)/jwzglesI.h
-extrusion.o: $(srcdir)/jwzgles.h
 extrusion.o: $(srcdir)/rotator.h
 extrusion.o: $(HACK_SRC)/screenhackI.h
 extrusion.o: $(UTILS_SRC)/colors.h
@@ -1504,22 +1485,14 @@ extrusion.o: $(HACK_SRC)/xlockmore.h
 extrusion.o: $(srcdir)/xpm-ximage.h
 extrusion-screw.o: ../../config.h
 extrusion-screw.o: $(srcdir)/extrusion.h
-extrusion-screw.o: $(srcdir)/jwzglesI.h
-extrusion-screw.o: $(srcdir)/jwzgles.h
 extrusion-taper.o: ../../config.h
 extrusion-taper.o: $(srcdir)/extrusion.h
-extrusion-taper.o: $(srcdir)/jwzglesI.h
-extrusion-taper.o: $(srcdir)/jwzgles.h
 extrusion-twistoid.o: ../../config.h
 extrusion-twistoid.o: $(srcdir)/extrusion.h
-extrusion-twistoid.o: $(srcdir)/jwzglesI.h
-extrusion-twistoid.o: $(srcdir)/jwzgles.h
 flipflop.o: ../../config.h
 flipflop.o: $(HACK_SRC)/fps.h
 flipflop.o: $(srcdir)/gltrackball.h
 flipflop.o: $(srcdir)/grab-ximage.h
-flipflop.o: $(srcdir)/jwzglesI.h
-flipflop.o: $(srcdir)/jwzgles.h
 flipflop.o: $(HACK_SRC)/screenhackI.h
 flipflop.o: $(UTILS_SRC)/colors.h
 flipflop.o: $(UTILS_SRC)/grabscreen.h
@@ -1535,8 +1508,6 @@ flipscreen3d.o: ../../config.h
 flipscreen3d.o: $(HACK_SRC)/fps.h
 flipscreen3d.o: $(srcdir)/gltrackball.h
 flipscreen3d.o: $(srcdir)/grab-ximage.h
-flipscreen3d.o: $(srcdir)/jwzglesI.h
-flipscreen3d.o: $(srcdir)/jwzgles.h
 flipscreen3d.o: $(HACK_SRC)/screenhackI.h
 flipscreen3d.o: $(UTILS_SRC)/colors.h
 flipscreen3d.o: $(UTILS_SRC)/grabscreen.h
@@ -1550,8 +1521,6 @@ flipscreen3d.o: $(HACK_SRC)/xlockmoreI.h
 flipscreen3d.o: $(HACK_SRC)/xlockmore.h
 fliptext.o: ../../config.h
 fliptext.o: $(HACK_SRC)/fps.h
-fliptext.o: $(srcdir)/jwzglesI.h
-fliptext.o: $(srcdir)/jwzgles.h
 fliptext.o: $(HACK_SRC)/screenhackI.h
 fliptext.o: $(srcdir)/texfont.h
 fliptext.o: $(UTILS_SRC)/colors.h
@@ -1569,8 +1538,6 @@ flurry.o: ../../config.h
 flurry.o: $(srcdir)/flurry.h
 flurry.o: $(HACK_SRC)/fps.h
 flurry.o: $(srcdir)/gltrackball.h
-flurry.o: $(srcdir)/jwzglesI.h
-flurry.o: $(srcdir)/jwzgles.h
 flurry.o: $(srcdir)/rotator.h
 flurry.o: $(HACK_SRC)/screenhackI.h
 flurry.o: $(UTILS_SRC)/colors.h
@@ -1586,29 +1553,21 @@ flurry.o: $(HACK_SRC)/xlockmore.h
 flurry-smoke.o: ../../config.h
 flurry-smoke.o: $(srcdir)/flurry.h
 flurry-smoke.o: $(srcdir)/gltrackball.h
-flurry-smoke.o: $(srcdir)/jwzglesI.h
-flurry-smoke.o: $(srcdir)/jwzgles.h
 flurry-smoke.o: $(srcdir)/rotator.h
 flurry-smoke.o: $(UTILS_SRC)/yarandom.h
 flurry-spark.o: ../../config.h
 flurry-spark.o: $(srcdir)/flurry.h
 flurry-spark.o: $(srcdir)/gltrackball.h
-flurry-spark.o: $(srcdir)/jwzglesI.h
-flurry-spark.o: $(srcdir)/jwzgles.h
 flurry-spark.o: $(srcdir)/rotator.h
 flurry-spark.o: $(UTILS_SRC)/yarandom.h
 flurry-star.o: ../../config.h
 flurry-star.o: $(srcdir)/flurry.h
 flurry-star.o: $(srcdir)/gltrackball.h
-flurry-star.o: $(srcdir)/jwzglesI.h
-flurry-star.o: $(srcdir)/jwzgles.h
 flurry-star.o: $(srcdir)/rotator.h
 flurry-star.o: $(UTILS_SRC)/yarandom.h
 flurry-texture.o: ../../config.h
 flurry-texture.o: $(srcdir)/flurry.h
 flurry-texture.o: $(srcdir)/gltrackball.h
-flurry-texture.o: $(srcdir)/jwzglesI.h
-flurry-texture.o: $(srcdir)/jwzgles.h
 flurry-texture.o: $(srcdir)/rotator.h
 flurry-texture.o: $(UTILS_SRC)/yarandom.h
 flyingtoasters.o: ../../config.h
@@ -1617,8 +1576,6 @@ flyingtoasters.o: $(srcdir)/gllist.h
 flyingtoasters.o: $(srcdir)/gltrackball.h
 flyingtoasters.o: $(HACK_SRC)/images/chromesphere.xpm
 flyingtoasters.o: $(HACK_SRC)/images/toast.xpm
-flyingtoasters.o: $(srcdir)/jwzglesI.h
-flyingtoasters.o: $(srcdir)/jwzgles.h
 flyingtoasters.o: $(HACK_SRC)/screenhackI.h
 flyingtoasters.o: $(UTILS_SRC)/colors.h
 flyingtoasters.o: $(UTILS_SRC)/grabscreen.h
@@ -1634,8 +1591,6 @@ flyingtoasters.o: $(srcdir)/xpm-ximage.h
 fps-gl.o: ../../config.h
 fps-gl.o: $(HACK_SRC)/fpsI.h
 fps-gl.o: $(HACK_SRC)/fps.h
-fps-gl.o: $(srcdir)/jwzglesI.h
-fps-gl.o: $(srcdir)/jwzgles.h
 fps-gl.o: $(HACK_SRC)/screenhackI.h
 fps-gl.o: $(srcdir)/texfont.h
 fps-gl.o: $(UTILS_SRC)/colors.h
@@ -1651,8 +1606,6 @@ gears.o: ../../config.h
 gears.o: $(HACK_SRC)/fps.h
 gears.o: $(srcdir)/gltrackball.h
 gears.o: $(srcdir)/involute.h
-gears.o: $(srcdir)/jwzglesI.h
-gears.o: $(srcdir)/jwzgles.h
 gears.o: $(srcdir)/normals.h
 gears.o: $(srcdir)/rotator.h
 gears.o: $(HACK_SRC)/screenhackI.h
@@ -1672,8 +1625,6 @@ geodesicgears.o: $(HACK_SRC)/fps.h
 geodesicgears.o: $(srcdir)/gllist.h
 geodesicgears.o: $(srcdir)/gltrackball.h
 geodesicgears.o: $(srcdir)/involute.h
-geodesicgears.o: $(srcdir)/jwzglesI.h
-geodesicgears.o: $(srcdir)/jwzgles.h
 geodesicgears.o: $(srcdir)/normals.h
 geodesicgears.o: $(srcdir)/rotator.h
 geodesicgears.o: $(HACK_SRC)/screenhackI.h
@@ -1692,8 +1643,6 @@ geodesic.o: ../../config.h
 geodesic.o: $(HACK_SRC)/fps.h
 geodesic.o: $(srcdir)/gllist.h
 geodesic.o: $(srcdir)/gltrackball.h
-geodesic.o: $(srcdir)/jwzglesI.h
-geodesic.o: $(srcdir)/jwzgles.h
 geodesic.o: $(srcdir)/normals.h
 geodesic.o: $(srcdir)/rotator.h
 geodesic.o: $(HACK_SRC)/screenhackI.h
@@ -1711,8 +1660,6 @@ gflux.o: ../../config.h
 gflux.o: $(HACK_SRC)/fps.h
 gflux.o: $(srcdir)/gltrackball.h
 gflux.o: $(srcdir)/grab-ximage.h
-gflux.o: $(srcdir)/jwzglesI.h
-gflux.o: $(srcdir)/jwzgles.h
 gflux.o: $(HACK_SRC)/screenhackI.h
 gflux.o: $(UTILS_SRC)/colors.h
 gflux.o: $(UTILS_SRC)/grabscreen.h
@@ -1727,8 +1674,6 @@ gflux.o: $(HACK_SRC)/xlockmore.h
 glblur.o: ../../config.h
 glblur.o: $(HACK_SRC)/fps.h
 glblur.o: $(srcdir)/gltrackball.h
-glblur.o: $(srcdir)/jwzglesI.h
-glblur.o: $(srcdir)/jwzgles.h
 glblur.o: $(srcdir)/rotator.h
 glblur.o: $(HACK_SRC)/screenhackI.h
 glblur.o: $(UTILS_SRC)/colors.h
@@ -1743,8 +1688,6 @@ glblur.o: $(HACK_SRC)/xlockmoreI.h
 glblur.o: $(HACK_SRC)/xlockmore.h
 glcells.o: ../../config.h
 glcells.o: $(HACK_SRC)/fps.h
-glcells.o: $(srcdir)/jwzglesI.h
-glcells.o: $(srcdir)/jwzgles.h
 glcells.o: $(HACK_SRC)/screenhackI.h
 glcells.o: $(UTILS_SRC)/colors.h
 glcells.o: $(UTILS_SRC)/grabscreen.h
@@ -1759,8 +1702,6 @@ glcells.o: $(HACK_SRC)/xlockmore.h
 gleidescope.o: ../../config.h
 gleidescope.o: $(HACK_SRC)/fps.h
 gleidescope.o: $(srcdir)/grab-ximage.h
-gleidescope.o: $(srcdir)/jwzglesI.h
-gleidescope.o: $(srcdir)/jwzgles.h
 gleidescope.o: $(HACK_SRC)/screenhackI.h
 gleidescope.o: $(UTILS_SRC)/colors.h
 gleidescope.o: $(UTILS_SRC)/grabscreen.h
@@ -1778,8 +1719,6 @@ glforestfire.o: $(HACK_SRC)/fps.h
 glforestfire.o: $(srcdir)/gltrackball.h
 glforestfire.o: $(HACK_SRC)/images/ground.xpm
 glforestfire.o: $(HACK_SRC)/images/tree.xpm
-glforestfire.o: $(srcdir)/jwzglesI.h
-glforestfire.o: $(srcdir)/jwzgles.h
 glforestfire.o: $(HACK_SRC)/screenhackI.h
 glforestfire.o: $(UTILS_SRC)/colors.h
 glforestfire.o: $(UTILS_SRC)/grabscreen.h
@@ -1794,8 +1733,6 @@ glforestfire.o: $(HACK_SRC)/xlockmore.h
 glforestfire.o: $(srcdir)/xpm-ximage.h
 glhanoi.o: ../../config.h
 glhanoi.o: $(HACK_SRC)/fps.h
-glhanoi.o: $(srcdir)/jwzglesI.h
-glhanoi.o: $(srcdir)/jwzgles.h
 glhanoi.o: $(srcdir)/rotator.h
 glhanoi.o: $(HACK_SRC)/screenhackI.h
 glhanoi.o: $(UTILS_SRC)/colors.h
@@ -1811,8 +1748,6 @@ glhanoi.o: $(HACK_SRC)/xlockmore.h
 glknots.o: ../../config.h
 glknots.o: $(HACK_SRC)/fps.h
 glknots.o: $(srcdir)/gltrackball.h
-glknots.o: $(srcdir)/jwzglesI.h
-glknots.o: $(srcdir)/jwzgles.h
 glknots.o: $(srcdir)/rotator.h
 glknots.o: $(HACK_SRC)/screenhackI.h
 glknots.o: $(srcdir)/tube.h
@@ -1828,13 +1763,9 @@ glknots.o: $(HACK_SRC)/xlockmoreI.h
 glknots.o: $(HACK_SRC)/xlockmore.h
 gllist.o: ../../config.h
 gllist.o: $(srcdir)/gllist.h
-gllist.o: $(srcdir)/jwzglesI.h
-gllist.o: $(srcdir)/jwzgles.h
 glmatrix.o: ../../config.h
 glmatrix.o: $(HACK_SRC)/fps.h
 glmatrix.o: $(HACK_SRC)/images/matrix3.xpm
-glmatrix.o: $(srcdir)/jwzglesI.h
-glmatrix.o: $(srcdir)/jwzgles.h
 glmatrix.o: $(HACK_SRC)/screenhackI.h
 glmatrix.o: $(UTILS_SRC)/colors.h
 glmatrix.o: $(UTILS_SRC)/grabscreen.h
@@ -1852,8 +1783,6 @@ glplanet.o: $(HACK_SRC)/fps.h
 glplanet.o: $(srcdir)/gltrackball.h
 glplanet.o: $(HACK_SRC)/images/earth_night.xpm
 glplanet.o: $(HACK_SRC)/images/earth.xpm
-glplanet.o: $(srcdir)/jwzglesI.h
-glplanet.o: $(srcdir)/jwzgles.h
 glplanet.o: $(srcdir)/rotator.h
 glplanet.o: $(HACK_SRC)/screenhackI.h
 glplanet.o: $(srcdir)/sphere.h
@@ -1874,8 +1803,6 @@ glschool_alg.o: $(UTILS_SRC)/yarandom.h
 glschool_gl.o: ../../config.h
 glschool_gl.o: $(srcdir)/glschool_alg.h
 glschool_gl.o: $(srcdir)/glschool_gl.h
-glschool_gl.o: $(srcdir)/jwzglesI.h
-glschool_gl.o: $(srcdir)/jwzgles.h
 glschool_gl.o: $(srcdir)/sphere.h
 glschool_gl.o: $(srcdir)/tube.h
 glschool.o: ../../config.h
@@ -1883,8 +1810,6 @@ glschool.o: $(HACK_SRC)/fps.h
 glschool.o: $(srcdir)/glschool_alg.h
 glschool.o: $(srcdir)/glschool_gl.h
 glschool.o: $(srcdir)/glschool.h
-glschool.o: $(srcdir)/jwzglesI.h
-glschool.o: $(srcdir)/jwzgles.h
 glschool.o: $(HACK_SRC)/screenhackI.h
 glschool.o: $(UTILS_SRC)/colors.h
 glschool.o: $(UTILS_SRC)/grabscreen.h
@@ -1899,8 +1824,6 @@ glschool.o: $(HACK_SRC)/xlockmore.h
 glslideshow.o: ../../config.h
 glslideshow.o: $(HACK_SRC)/fps.h
 glslideshow.o: $(srcdir)/grab-ximage.h
-glslideshow.o: $(srcdir)/jwzglesI.h
-glslideshow.o: $(srcdir)/jwzgles.h
 glslideshow.o: $(HACK_SRC)/screenhackI.h
 glslideshow.o: $(srcdir)/texfont.h
 glslideshow.o: $(UTILS_SRC)/colors.h
@@ -1915,8 +1838,6 @@ glslideshow.o: $(HACK_SRC)/xlockmoreI.h
 glslideshow.o: $(HACK_SRC)/xlockmore.h
 glsnake.o: ../../config.h
 glsnake.o: $(HACK_SRC)/fps.h
-glsnake.o: $(srcdir)/jwzglesI.h
-glsnake.o: $(srcdir)/jwzgles.h
 glsnake.o: $(HACK_SRC)/screenhackI.h
 glsnake.o: $(srcdir)/texfont.h
 glsnake.o: $(UTILS_SRC)/colors.h
@@ -1934,8 +1855,6 @@ gltext.o: $(HACK_SRC)/fps.h
 gltext.o: $(srcdir)/gltrackball.h
 gltext.o: $(srcdir)/glut_roman.h
 gltext.o: $(srcdir)/glutstroke.h
-gltext.o: $(srcdir)/jwzglesI.h
-gltext.o: $(srcdir)/jwzgles.h
 gltext.o: $(srcdir)/rotator.h
 gltext.o: $(HACK_SRC)/screenhackI.h
 gltext.o: $(srcdir)/sphere.h
@@ -1954,21 +1873,13 @@ gltext.o: $(HACK_SRC)/xlockmoreI.h
 gltext.o: $(HACK_SRC)/xlockmore.h
 gltrackball.o: ../../config.h
 gltrackball.o: $(srcdir)/gltrackball.h
-gltrackball.o: $(srcdir)/jwzglesI.h
-gltrackball.o: $(srcdir)/jwzgles.h
 gltrackball.o: $(srcdir)/trackball.h
 glut_stroke.o: ../../config.h
 glut_stroke.o: $(srcdir)/glutstroke.h
-glut_stroke.o: $(srcdir)/jwzglesI.h
-glut_stroke.o: $(srcdir)/jwzgles.h
 glut_swidth.o: ../../config.h
 glut_swidth.o: $(srcdir)/glutstroke.h
-glut_swidth.o: $(srcdir)/jwzglesI.h
-glut_swidth.o: $(srcdir)/jwzgles.h
 grab-ximage.o: ../../config.h
 grab-ximage.o: $(srcdir)/grab-ximage.h
-grab-ximage.o: $(srcdir)/jwzglesI.h
-grab-ximage.o: $(srcdir)/jwzgles.h
 grab-ximage.o: $(UTILS_SRC)/grabscreen.h
 grab-ximage.o: $(UTILS_SRC)/resources.h
 grab-ximage.o: $(UTILS_SRC)/visual.h
@@ -1976,8 +1887,6 @@ grab-ximage.o: $(UTILS_SRC)/xshm.h
 hilbert.o: ../../config.h
 hilbert.o: $(HACK_SRC)/fps.h
 hilbert.o: $(srcdir)/gltrackball.h
-hilbert.o: $(srcdir)/jwzglesI.h
-hilbert.o: $(srcdir)/jwzgles.h
 hilbert.o: $(srcdir)/rotator.h
 hilbert.o: $(HACK_SRC)/screenhackI.h
 hilbert.o: $(srcdir)/sphere.h
@@ -1992,11 +1901,25 @@ hilbert.o: $(UTILS_SRC)/xshm.h
 hilbert.o: $(UTILS_SRC)/yarandom.h
 hilbert.o: $(HACK_SRC)/xlockmoreI.h
 hilbert.o: $(HACK_SRC)/xlockmore.h
+hydrostat.o: ../../config.h
+hydrostat.o: $(HACK_SRC)/fps.h
+hydrostat.o: $(srcdir)/gltrackball.h
+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)/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
 hypertorus.o: ../../config.h
 hypertorus.o: $(HACK_SRC)/fps.h
 hypertorus.o: $(srcdir)/gltrackball.h
-hypertorus.o: $(srcdir)/jwzglesI.h
-hypertorus.o: $(srcdir)/jwzgles.h
 hypertorus.o: $(HACK_SRC)/screenhackI.h
 hypertorus.o: $(UTILS_SRC)/colors.h
 hypertorus.o: $(UTILS_SRC)/grabscreen.h
@@ -2010,8 +1933,6 @@ hypertorus.o: $(HACK_SRC)/xlockmoreI.h
 hypertorus.o: $(HACK_SRC)/xlockmore.h
 hypnowheel.o: ../../config.h
 hypnowheel.o: $(HACK_SRC)/fps.h
-hypnowheel.o: $(srcdir)/jwzglesI.h
-hypnowheel.o: $(srcdir)/jwzgles.h
 hypnowheel.o: $(srcdir)/rotator.h
 hypnowheel.o: $(HACK_SRC)/screenhackI.h
 hypnowheel.o: $(UTILS_SRC)/colors.h
@@ -2027,8 +1948,6 @@ hypnowheel.o: $(HACK_SRC)/xlockmore.h
 involute.o: ../../config.h
 involute.o: $(HACK_SRC)/fps.h
 involute.o: $(srcdir)/involute.h
-involute.o: $(srcdir)/jwzglesI.h
-involute.o: $(srcdir)/jwzgles.h
 involute.o: $(srcdir)/normals.h
 involute.o: $(HACK_SRC)/screenhackI.h
 involute.o: $(UTILS_SRC)/colors.h
@@ -2042,8 +1961,6 @@ jigglypuff.o: ../../config.h
 jigglypuff.o: $(HACK_SRC)/fps.h
 jigglypuff.o: $(srcdir)/gltrackball.h
 jigglypuff.o: $(HACK_SRC)/images/jigglymap.xpm
-jigglypuff.o: $(srcdir)/jwzglesI.h
-jigglypuff.o: $(srcdir)/jwzgles.h
 jigglypuff.o: $(HACK_SRC)/screenhackI.h
 jigglypuff.o: $(UTILS_SRC)/colors.h
 jigglypuff.o: $(UTILS_SRC)/grabscreen.h
@@ -2060,8 +1977,6 @@ jigsaw.o: ../../config.h
 jigsaw.o: $(HACK_SRC)/fps.h
 jigsaw.o: $(srcdir)/gltrackball.h
 jigsaw.o: $(srcdir)/grab-ximage.h
-jigsaw.o: $(srcdir)/jwzglesI.h
-jigsaw.o: $(srcdir)/jwzgles.h
 jigsaw.o: $(srcdir)/normals.h
 jigsaw.o: $(srcdir)/rotator.h
 jigsaw.o: $(HACK_SRC)/screenhackI.h
@@ -2080,8 +1995,6 @@ jigsaw.o: $(HACK_SRC)/xlockmore.h
 juggler3d.o: ../../config.h
 juggler3d.o: $(HACK_SRC)/fps.h
 juggler3d.o: $(srcdir)/gltrackball.h
-juggler3d.o: $(srcdir)/jwzglesI.h
-juggler3d.o: $(srcdir)/jwzgles.h
 juggler3d.o: $(srcdir)/rotator.h
 juggler3d.o: $(HACK_SRC)/screenhackI.h
 juggler3d.o: $(srcdir)/sphere.h
@@ -2097,13 +2010,9 @@ juggler3d.o: $(UTILS_SRC)/xshm.h
 juggler3d.o: $(UTILS_SRC)/yarandom.h
 juggler3d.o: $(HACK_SRC)/xlockmoreI.h
 juggler3d.o: $(HACK_SRC)/xlockmore.h
-jwzgles.o: ../../config.h
-jwzgles.o: $(srcdir)/jwzglesI.h
 kaleidocycle.o: ../../config.h
 kaleidocycle.o: $(HACK_SRC)/fps.h
 kaleidocycle.o: $(srcdir)/gltrackball.h
-kaleidocycle.o: $(srcdir)/jwzglesI.h
-kaleidocycle.o: $(srcdir)/jwzgles.h
 kaleidocycle.o: $(srcdir)/normals.h
 kaleidocycle.o: $(srcdir)/rotator.h
 kaleidocycle.o: $(HACK_SRC)/screenhackI.h
@@ -2121,8 +2030,6 @@ klein.o: ../../config.h
 klein.o: $(srcdir)/curlicue.h
 klein.o: $(HACK_SRC)/fps.h
 klein.o: $(srcdir)/gltrackball.h
-klein.o: $(srcdir)/jwzglesI.h
-klein.o: $(srcdir)/jwzgles.h
 klein.o: $(HACK_SRC)/screenhackI.h
 klein.o: $(UTILS_SRC)/colors.h
 klein.o: $(UTILS_SRC)/grabscreen.h
@@ -2136,15 +2043,11 @@ klein.o: $(HACK_SRC)/xlockmoreI.h
 klein.o: $(HACK_SRC)/xlockmore.h
 lament_model.o: ../../config.h
 lament_model.o: $(srcdir)/gllist.h
-lament_model.o: $(srcdir)/jwzglesI.h
-lament_model.o: $(srcdir)/jwzgles.h
 lament.o: ../../config.h
 lament.o: $(HACK_SRC)/fps.h
 lament.o: $(srcdir)/gllist.h
 lament.o: $(srcdir)/gltrackball.h
 lament.o: $(HACK_SRC)/images/lament512.xpm
-lament.o: $(srcdir)/jwzglesI.h
-lament.o: $(srcdir)/jwzgles.h
 lament.o: $(srcdir)/normals.h
 lament.o: $(srcdir)/rotator.h
 lament.o: $(HACK_SRC)/screenhackI.h
@@ -2162,8 +2065,6 @@ lament.o: $(srcdir)/xpm-ximage.h
 lavalite.o: ../../config.h
 lavalite.o: $(HACK_SRC)/fps.h
 lavalite.o: $(srcdir)/gltrackball.h
-lavalite.o: $(srcdir)/jwzglesI.h
-lavalite.o: $(srcdir)/jwzgles.h
 lavalite.o: $(srcdir)/marching.h
 lavalite.o: $(srcdir)/rotator.h
 lavalite.o: $(HACK_SRC)/screenhackI.h
@@ -2180,8 +2081,6 @@ lavalite.o: $(HACK_SRC)/xlockmore.h
 lavalite.o: $(srcdir)/xpm-ximage.h
 lockward.o: ../../config.h
 lockward.o: $(HACK_SRC)/fps.h
-lockward.o: $(srcdir)/jwzglesI.h
-lockward.o: $(srcdir)/jwzgles.h
 lockward.o: $(HACK_SRC)/screenhackI.h
 lockward.o: $(UTILS_SRC)/colors.h
 lockward.o: $(UTILS_SRC)/grabscreen.h
@@ -2194,15 +2093,11 @@ lockward.o: $(UTILS_SRC)/yarandom.h
 lockward.o: $(HACK_SRC)/xlockmoreI.h
 lockward.o: $(HACK_SRC)/xlockmore.h
 marching.o: ../../config.h
-marching.o: $(srcdir)/jwzglesI.h
-marching.o: $(srcdir)/jwzgles.h
 marching.o: $(srcdir)/marching.h
 marching.o: $(srcdir)/normals.h
 menger.o: ../../config.h
 menger.o: $(HACK_SRC)/fps.h
 menger.o: $(srcdir)/gltrackball.h
-menger.o: $(srcdir)/jwzglesI.h
-menger.o: $(srcdir)/jwzgles.h
 menger.o: $(srcdir)/rotator.h
 menger.o: $(HACK_SRC)/screenhackI.h
 menger.o: $(UTILS_SRC)/colors.h
@@ -2219,8 +2114,6 @@ mirrorblob.o: ../../config.h
 mirrorblob.o: $(HACK_SRC)/fps.h
 mirrorblob.o: $(srcdir)/gltrackball.h
 mirrorblob.o: $(srcdir)/grab-ximage.h
-mirrorblob.o: $(srcdir)/jwzglesI.h
-mirrorblob.o: $(srcdir)/jwzgles.h
 mirrorblob.o: $(HACK_SRC)/screenhackI.h
 mirrorblob.o: $(UTILS_SRC)/colors.h
 mirrorblob.o: $(UTILS_SRC)/grabscreen.h
@@ -2236,8 +2129,6 @@ moebiusgears.o: ../../config.h
 moebiusgears.o: $(HACK_SRC)/fps.h
 moebiusgears.o: $(srcdir)/gltrackball.h
 moebiusgears.o: $(srcdir)/involute.h
-moebiusgears.o: $(srcdir)/jwzglesI.h
-moebiusgears.o: $(srcdir)/jwzgles.h
 moebiusgears.o: $(srcdir)/normals.h
 moebiusgears.o: $(srcdir)/rotator.h
 moebiusgears.o: $(HACK_SRC)/screenhackI.h
@@ -2254,8 +2145,6 @@ moebiusgears.o: $(HACK_SRC)/xlockmore.h
 moebius.o: ../../config.h
 moebius.o: $(HACK_SRC)/fps.h
 moebius.o: $(srcdir)/gltrackball.h
-moebius.o: $(srcdir)/jwzglesI.h
-moebius.o: $(srcdir)/jwzgles.h
 moebius.o: $(srcdir)/rotator.h
 moebius.o: $(HACK_SRC)/screenhackI.h
 moebius.o: $(srcdir)/sphere.h
@@ -2273,8 +2162,6 @@ moebius.o: $(HACK_SRC)/xlockmore.h
 molecule.o: ../../config.h
 molecule.o: $(HACK_SRC)/fps.h
 molecule.o: $(srcdir)/gltrackball.h
-molecule.o: $(srcdir)/jwzglesI.h
-molecule.o: $(srcdir)/jwzgles.h
 molecule.o: molecules.h
 molecule.o: $(srcdir)/rotator.h
 molecule.o: $(HACK_SRC)/screenhackI.h
@@ -2293,8 +2180,6 @@ molecule.o: $(HACK_SRC)/xlockmoreI.h
 molecule.o: $(HACK_SRC)/xlockmore.h
 morph3d.o: ../../config.h
 morph3d.o: $(HACK_SRC)/fps.h
-morph3d.o: $(srcdir)/jwzglesI.h
-morph3d.o: $(srcdir)/jwzgles.h
 morph3d.o: $(HACK_SRC)/screenhackI.h
 morph3d.o: $(UTILS_SRC)/colors.h
 morph3d.o: $(UTILS_SRC)/grabscreen.h
@@ -2308,8 +2193,6 @@ morph3d.o: $(HACK_SRC)/xlockmoreI.h
 morph3d.o: $(HACK_SRC)/xlockmore.h
 noof.o: ../../config.h
 noof.o: $(HACK_SRC)/fps.h
-noof.o: $(srcdir)/jwzglesI.h
-noof.o: $(srcdir)/jwzgles.h
 noof.o: $(HACK_SRC)/screenhackI.h
 noof.o: $(UTILS_SRC)/colors.h
 noof.o: $(UTILS_SRC)/grabscreen.h
@@ -2322,15 +2205,11 @@ noof.o: $(UTILS_SRC)/yarandom.h
 noof.o: $(HACK_SRC)/xlockmoreI.h
 noof.o: $(HACK_SRC)/xlockmore.h
 normals.o: ../../config.h
-normals.o: $(srcdir)/jwzglesI.h
-normals.o: $(srcdir)/jwzgles.h
 normals.o: $(srcdir)/normals.h
 photopile.o: ../../config.h
 photopile.o: $(srcdir)/dropshadow.h
 photopile.o: $(HACK_SRC)/fps.h
 photopile.o: $(srcdir)/grab-ximage.h
-photopile.o: $(srcdir)/jwzglesI.h
-photopile.o: $(srcdir)/jwzgles.h
 photopile.o: $(HACK_SRC)/screenhackI.h
 photopile.o: $(srcdir)/texfont.h
 photopile.o: $(UTILS_SRC)/colors.h
@@ -2347,8 +2226,6 @@ pinion.o: ../../config.h
 pinion.o: $(HACK_SRC)/fps.h
 pinion.o: $(srcdir)/gltrackball.h
 pinion.o: $(srcdir)/involute.h
-pinion.o: $(srcdir)/jwzglesI.h
-pinion.o: $(srcdir)/jwzgles.h
 pinion.o: $(srcdir)/normals.h
 pinion.o: $(HACK_SRC)/screenhackI.h
 pinion.o: $(srcdir)/texfont.h
@@ -2364,14 +2241,10 @@ pinion.o: $(HACK_SRC)/xlockmoreI.h
 pinion.o: $(HACK_SRC)/xlockmore.h
 pipeobjs.o: $(srcdir)/buildlwo.h
 pipeobjs.o: ../../config.h
-pipeobjs.o: $(srcdir)/jwzglesI.h
-pipeobjs.o: $(srcdir)/jwzgles.h
 pipes.o: $(srcdir)/buildlwo.h
 pipes.o: ../../config.h
 pipes.o: $(HACK_SRC)/fps.h
 pipes.o: $(srcdir)/gltrackball.h
-pipes.o: $(srcdir)/jwzglesI.h
-pipes.o: $(srcdir)/jwzgles.h
 pipes.o: $(HACK_SRC)/screenhackI.h
 pipes.o: $(srcdir)/sphere.h
 pipes.o: $(srcdir)/teapot.h
@@ -2388,8 +2261,6 @@ pipes.o: $(HACK_SRC)/xlockmore.h
 polyhedra-gl.o: ../../config.h
 polyhedra-gl.o: $(HACK_SRC)/fps.h
 polyhedra-gl.o: $(srcdir)/gltrackball.h
-polyhedra-gl.o: $(srcdir)/jwzglesI.h
-polyhedra-gl.o: $(srcdir)/jwzgles.h
 polyhedra-gl.o: $(srcdir)/normals.h
 polyhedra-gl.o: $(srcdir)/polyhedra.h
 polyhedra-gl.o: $(srcdir)/rotator.h
@@ -2411,8 +2282,6 @@ polyhedra.o: $(srcdir)/polyhedra.h
 polytopes.o: ../../config.h
 polytopes.o: $(HACK_SRC)/fps.h
 polytopes.o: $(srcdir)/gltrackball.h
-polytopes.o: $(srcdir)/jwzglesI.h
-polytopes.o: $(srcdir)/jwzgles.h
 polytopes.o: $(HACK_SRC)/screenhackI.h
 polytopes.o: $(UTILS_SRC)/colors.h
 polytopes.o: $(UTILS_SRC)/grabscreen.h
@@ -2428,8 +2297,6 @@ projectiveplane.o: ../../config.h
 projectiveplane.o: $(srcdir)/curlicue.h
 projectiveplane.o: $(HACK_SRC)/fps.h
 projectiveplane.o: $(srcdir)/gltrackball.h
-projectiveplane.o: $(srcdir)/jwzglesI.h
-projectiveplane.o: $(srcdir)/jwzgles.h
 projectiveplane.o: $(HACK_SRC)/screenhackI.h
 projectiveplane.o: $(UTILS_SRC)/colors.h
 projectiveplane.o: $(UTILS_SRC)/grabscreen.h
@@ -2444,8 +2311,6 @@ projectiveplane.o: $(HACK_SRC)/xlockmore.h
 providence.o: ../../config.h
 providence.o: $(HACK_SRC)/fps.h
 providence.o: $(srcdir)/gltrackball.h
-providence.o: $(srcdir)/jwzglesI.h
-providence.o: $(srcdir)/jwzgles.h
 providence.o: $(HACK_SRC)/screenhackI.h
 providence.o: $(UTILS_SRC)/colors.h
 providence.o: $(UTILS_SRC)/grabscreen.h
@@ -2459,8 +2324,6 @@ providence.o: $(HACK_SRC)/xlockmoreI.h
 providence.o: $(HACK_SRC)/xlockmore.h
 pulsar.o: ../../config.h
 pulsar.o: $(HACK_SRC)/fps.h
-pulsar.o: $(srcdir)/jwzglesI.h
-pulsar.o: $(srcdir)/jwzgles.h
 pulsar.o: $(HACK_SRC)/screenhackI.h
 pulsar.o: $(UTILS_SRC)/colors.h
 pulsar.o: $(UTILS_SRC)/grabscreen.h
@@ -2475,8 +2338,6 @@ pulsar.o: $(HACK_SRC)/xlockmore.h
 pulsar.o: $(srcdir)/xpm-ximage.h
 quasicrystal.o: ../../config.h
 quasicrystal.o: $(HACK_SRC)/fps.h
-quasicrystal.o: $(srcdir)/jwzglesI.h
-quasicrystal.o: $(srcdir)/jwzgles.h
 quasicrystal.o: $(srcdir)/rotator.h
 quasicrystal.o: $(HACK_SRC)/screenhackI.h
 quasicrystal.o: $(UTILS_SRC)/colors.h
@@ -2493,8 +2354,6 @@ queens.o: $(srcdir)/chessmodels.h
 queens.o: ../../config.h
 queens.o: $(HACK_SRC)/fps.h
 queens.o: $(srcdir)/gltrackball.h
-queens.o: $(srcdir)/jwzglesI.h
-queens.o: $(srcdir)/jwzgles.h
 queens.o: $(HACK_SRC)/screenhackI.h
 queens.o: $(UTILS_SRC)/colors.h
 queens.o: $(UTILS_SRC)/grabscreen.h
@@ -2506,20 +2365,29 @@ queens.o: $(UTILS_SRC)/xshm.h
 queens.o: $(UTILS_SRC)/yarandom.h
 queens.o: $(HACK_SRC)/xlockmoreI.h
 queens.o: $(HACK_SRC)/xlockmore.h
+raverhoop.o: ../../config.h
+raverhoop.o: $(HACK_SRC)/fps.h
+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)/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
 robot.o: ../../config.h
 robot.o: $(srcdir)/gllist.h
-robot.o: $(srcdir)/jwzglesI.h
-robot.o: $(srcdir)/jwzgles.h
 robot-wireframe.o: ../../config.h
 robot-wireframe.o: $(srcdir)/gllist.h
-robot-wireframe.o: $(srcdir)/jwzglesI.h
-robot-wireframe.o: $(srcdir)/jwzgles.h
 romanboy.o: ../../config.h
 romanboy.o: $(srcdir)/curlicue.h
 romanboy.o: $(HACK_SRC)/fps.h
 romanboy.o: $(srcdir)/gltrackball.h
-romanboy.o: $(srcdir)/jwzglesI.h
-romanboy.o: $(srcdir)/jwzgles.h
 romanboy.o: $(HACK_SRC)/screenhackI.h
 romanboy.o: $(UTILS_SRC)/colors.h
 romanboy.o: $(UTILS_SRC)/grabscreen.h
@@ -2537,8 +2405,6 @@ rotator.o: $(UTILS_SRC)/yarandom.h
 rubikblocks.o: ../../config.h
 rubikblocks.o: $(HACK_SRC)/fps.h
 rubikblocks.o: $(srcdir)/gltrackball.h
-rubikblocks.o: $(srcdir)/jwzglesI.h
-rubikblocks.o: $(srcdir)/jwzgles.h
 rubikblocks.o: $(srcdir)/rotator.h
 rubikblocks.o: $(HACK_SRC)/screenhackI.h
 rubikblocks.o: $(UTILS_SRC)/colors.h
@@ -2554,8 +2420,6 @@ rubikblocks.o: $(HACK_SRC)/xlockmore.h
 rubik.o: ../../config.h
 rubik.o: $(HACK_SRC)/fps.h
 rubik.o: $(srcdir)/gltrackball.h
-rubik.o: $(srcdir)/jwzglesI.h
-rubik.o: $(srcdir)/jwzgles.h
 rubik.o: $(HACK_SRC)/screenhackI.h
 rubik.o: $(UTILS_SRC)/colors.h
 rubik.o: $(UTILS_SRC)/grabscreen.h
@@ -2569,39 +2433,23 @@ rubik.o: $(HACK_SRC)/xlockmoreI.h
 rubik.o: $(HACK_SRC)/xlockmore.h
 s1_1.o: ../../config.h
 s1_1.o: $(srcdir)/gllist.h
-s1_1.o: $(srcdir)/jwzglesI.h
-s1_1.o: $(srcdir)/jwzgles.h
 s1_2.o: ../../config.h
 s1_2.o: $(srcdir)/gllist.h
-s1_2.o: $(srcdir)/jwzglesI.h
-s1_2.o: $(srcdir)/jwzgles.h
 s1_3.o: ../../config.h
 s1_3.o: $(srcdir)/gllist.h
-s1_3.o: $(srcdir)/jwzglesI.h
-s1_3.o: $(srcdir)/jwzgles.h
 s1_4.o: ../../config.h
 s1_4.o: $(srcdir)/gllist.h
-s1_4.o: $(srcdir)/jwzglesI.h
-s1_4.o: $(srcdir)/jwzgles.h
 s1_5.o: ../../config.h
 s1_5.o: $(srcdir)/gllist.h
-s1_5.o: $(srcdir)/jwzglesI.h
-s1_5.o: $(srcdir)/jwzgles.h
 s1_6.o: ../../config.h
 s1_6.o: $(srcdir)/gllist.h
-s1_6.o: $(srcdir)/jwzglesI.h
-s1_6.o: $(srcdir)/jwzgles.h
 s1_b.o: ../../config.h
 s1_b.o: $(srcdir)/gllist.h
-s1_b.o: $(srcdir)/jwzglesI.h
-s1_b.o: $(srcdir)/jwzgles.h
 sballs.o: ../../config.h
 sballs.o: $(HACK_SRC)/fps.h
 sballs.o: $(srcdir)/gltrackball.h
 sballs.o: $(HACK_SRC)/images/sball-bg.xpm
 sballs.o: $(HACK_SRC)/images/sball.xpm
-sballs.o: $(srcdir)/jwzglesI.h
-sballs.o: $(srcdir)/jwzgles.h
 sballs.o: $(HACK_SRC)/screenhackI.h
 sballs.o: $(UTILS_SRC)/colors.h
 sballs.o: $(UTILS_SRC)/grabscreen.h
@@ -2617,8 +2465,6 @@ sballs.o: $(srcdir)/xpm-ximage.h
 shark.o: $(srcdir)/atlantis.h
 shark.o: ../../config.h
 shark.o: $(HACK_SRC)/fps.h
-shark.o: $(srcdir)/jwzglesI.h
-shark.o: $(srcdir)/jwzgles.h
 shark.o: $(HACK_SRC)/screenhackI.h
 shark.o: $(UTILS_SRC)/colors.h
 shark.o: $(UTILS_SRC)/grabscreen.h
@@ -2630,8 +2476,6 @@ shark.o: $(UTILS_SRC)/yarandom.h
 sierpinski3d.o: ../../config.h
 sierpinski3d.o: $(HACK_SRC)/fps.h
 sierpinski3d.o: $(srcdir)/gltrackball.h
-sierpinski3d.o: $(srcdir)/jwzglesI.h
-sierpinski3d.o: $(srcdir)/jwzgles.h
 sierpinski3d.o: $(srcdir)/rotator.h
 sierpinski3d.o: $(HACK_SRC)/screenhackI.h
 sierpinski3d.o: $(UTILS_SRC)/colors.h
@@ -2648,8 +2492,6 @@ skytentacles.o: ../../config.h
 skytentacles.o: $(HACK_SRC)/fps.h
 skytentacles.o: $(srcdir)/gltrackball.h
 skytentacles.o: $(HACK_SRC)/images/scales.xpm
-skytentacles.o: $(srcdir)/jwzglesI.h
-skytentacles.o: $(srcdir)/jwzgles.h
 skytentacles.o: $(srcdir)/normals.h
 skytentacles.o: $(srcdir)/rotator.h
 skytentacles.o: $(HACK_SRC)/screenhackI.h
@@ -2682,8 +2524,6 @@ sonar-icmp.o: $(UTILS_SRC)/yarandom.h
 sonar.o: ../../config.h
 sonar.o: $(HACK_SRC)/fps.h
 sonar.o: $(srcdir)/gltrackball.h
-sonar.o: $(srcdir)/jwzglesI.h
-sonar.o: $(srcdir)/jwzgles.h
 sonar.o: $(srcdir)/rotator.h
 sonar.o: $(HACK_SRC)/screenhackI.h
 sonar.o: $(srcdir)/sonar.h
@@ -2714,8 +2554,6 @@ sonar-sim.o: $(UTILS_SRC)/yarandom.h
 spheremonics.o: ../../config.h
 spheremonics.o: $(HACK_SRC)/fps.h
 spheremonics.o: $(srcdir)/gltrackball.h
-spheremonics.o: $(srcdir)/jwzglesI.h
-spheremonics.o: $(srcdir)/jwzgles.h
 spheremonics.o: $(srcdir)/normals.h
 spheremonics.o: $(srcdir)/rotator.h
 spheremonics.o: $(HACK_SRC)/screenhackI.h
@@ -2731,15 +2569,11 @@ spheremonics.o: $(UTILS_SRC)/yarandom.h
 spheremonics.o: $(HACK_SRC)/xlockmoreI.h
 spheremonics.o: $(HACK_SRC)/xlockmore.h
 sphere.o: ../../config.h
-sphere.o: $(srcdir)/jwzglesI.h
-sphere.o: $(srcdir)/jwzgles.h
 sphere.o: $(srcdir)/sphere.h
 splitflap.o: ../../config.h
 splitflap.o: $(HACK_SRC)/fps.h
 splitflap.o: $(srcdir)/gllist.h
 splitflap.o: $(srcdir)/gltrackball.h
-splitflap.o: $(srcdir)/jwzglesI.h
-splitflap.o: $(srcdir)/jwzgles.h
 splitflap.o: $(srcdir)/rotator.h
 splitflap.o: $(HACK_SRC)/screenhackI.h
 splitflap.o: $(srcdir)/texfont.h
@@ -2758,13 +2592,9 @@ splitflap.o: $(HACK_SRC)/xlockmore.h
 splitflap.o: $(srcdir)/xpm-ximage.h
 splitflap_obj.o: ../../config.h
 splitflap_obj.o: $(srcdir)/gllist.h
-splitflap_obj.o: $(srcdir)/jwzglesI.h
-splitflap_obj.o: $(srcdir)/jwzgles.h
 sproingies.o: ../../config.h
 sproingies.o: $(HACK_SRC)/fps.h
 sproingies.o: $(srcdir)/gllist.h
-sproingies.o: $(srcdir)/jwzglesI.h
-sproingies.o: $(srcdir)/jwzgles.h
 sproingies.o: $(HACK_SRC)/screenhackI.h
 sproingies.o: $(srcdir)/sproingies.h
 sproingies.o: $(UTILS_SRC)/colors.h
@@ -2778,8 +2608,6 @@ sproingies.o: $(UTILS_SRC)/yarandom.h
 sproingies.o: $(HACK_SRC)/xlockmoreI.h
 sproingiewrap.o: ../../config.h
 sproingiewrap.o: $(HACK_SRC)/fps.h
-sproingiewrap.o: $(srcdir)/jwzglesI.h
-sproingiewrap.o: $(srcdir)/jwzgles.h
 sproingiewrap.o: $(HACK_SRC)/screenhackI.h
 sproingiewrap.o: $(srcdir)/sproingies.h
 sproingiewrap.o: $(UTILS_SRC)/colors.h
@@ -2796,8 +2624,6 @@ stairs.o: ../../config.h
 stairs.o: $(HACK_SRC)/fps.h
 stairs.o: $(srcdir)/gltrackball.h
 stairs.o: $(HACK_SRC)/images/wood.xpm
-stairs.o: $(srcdir)/jwzglesI.h
-stairs.o: $(srcdir)/jwzgles.h
 stairs.o: $(HACK_SRC)/screenhackI.h
 stairs.o: $(srcdir)/sphere.h
 stairs.o: $(UTILS_SRC)/colors.h
@@ -2815,8 +2641,6 @@ starwars.o: ../../config.h
 starwars.o: $(HACK_SRC)/fps.h
 starwars.o: $(srcdir)/glut_roman.h
 starwars.o: $(srcdir)/glutstroke.h
-starwars.o: $(srcdir)/jwzglesI.h
-starwars.o: $(srcdir)/jwzgles.h
 starwars.o: $(HACK_SRC)/screenhackI.h
 starwars.o: $(srcdir)/starwars.h
 starwars.o: $(srcdir)/texfont.h
@@ -2840,8 +2664,6 @@ stonerview-move.o: $(UTILS_SRC)/yarandom.h
 stonerview.o: ../../config.h
 stonerview.o: $(HACK_SRC)/fps.h
 stonerview.o: $(srcdir)/gltrackball.h
-stonerview.o: $(srcdir)/jwzglesI.h
-stonerview.o: $(srcdir)/jwzgles.h
 stonerview.o: $(HACK_SRC)/screenhackI.h
 stonerview.o: $(srcdir)/stonerview.h
 stonerview.o: $(srcdir)/stonerview-move.h
@@ -2862,15 +2684,11 @@ stonerview-osc.o: $(srcdir)/stonerview-move.h
 stonerview-osc.o: $(srcdir)/stonerview-osc.h
 stonerview-osc.o: $(UTILS_SRC)/yarandom.h
 stonerview-view.o: ../../config.h
-stonerview-view.o: $(srcdir)/jwzglesI.h
-stonerview-view.o: $(srcdir)/jwzgles.h
 stonerview-view.o: $(srcdir)/stonerview.h
 stonerview-view.o: $(srcdir)/stonerview-move.h
 stonerview-view.o: $(srcdir)/stonerview-osc.h
 superquadrics.o: ../../config.h
 superquadrics.o: $(HACK_SRC)/fps.h
-superquadrics.o: $(srcdir)/jwzglesI.h
-superquadrics.o: $(srcdir)/jwzgles.h
 superquadrics.o: $(HACK_SRC)/screenhackI.h
 superquadrics.o: $(UTILS_SRC)/colors.h
 superquadrics.o: $(UTILS_SRC)/grabscreen.h
@@ -2885,8 +2703,6 @@ superquadrics.o: $(HACK_SRC)/xlockmore.h
 surfaces.o: ../../config.h
 surfaces.o: $(HACK_SRC)/fps.h
 surfaces.o: $(srcdir)/gltrackball.h
-surfaces.o: $(srcdir)/jwzglesI.h
-surfaces.o: $(srcdir)/jwzgles.h
 surfaces.o: $(srcdir)/rotator.h
 surfaces.o: $(HACK_SRC)/screenhackI.h
 surfaces.o: $(UTILS_SRC)/colors.h
@@ -2902,8 +2718,6 @@ surfaces.o: $(HACK_SRC)/xlockmore.h
 swim.o: $(srcdir)/atlantis.h
 swim.o: ../../config.h
 swim.o: $(HACK_SRC)/fps.h
-swim.o: $(srcdir)/jwzglesI.h
-swim.o: $(srcdir)/jwzgles.h
 swim.o: $(HACK_SRC)/screenhackI.h
 swim.o: $(UTILS_SRC)/colors.h
 swim.o: $(UTILS_SRC)/grabscreen.h
@@ -2916,8 +2730,6 @@ swim.o: $(UTILS_SRC)/yarandom.h
 swim.o: $(HACK_SRC)/xlockmoreI.h
 tangram.o: ../../config.h
 tangram.o: $(HACK_SRC)/fps.h
-tangram.o: $(srcdir)/jwzglesI.h
-tangram.o: $(srcdir)/jwzgles.h
 tangram.o: $(HACK_SRC)/screenhackI.h
 tangram.o: $(srcdir)/tangram_shapes.h
 tangram.o: $(srcdir)/texfont.h
@@ -2932,19 +2744,11 @@ tangram.o: $(UTILS_SRC)/yarandom.h
 tangram.o: $(HACK_SRC)/xlockmoreI.h
 tangram.o: $(HACK_SRC)/xlockmore.h
 tangram_shapes.o: ../../config.h
-tangram_shapes.o: $(srcdir)/jwzglesI.h
-tangram_shapes.o: $(srcdir)/jwzgles.h
 tangram_shapes.o: $(srcdir)/tangram_shapes.h
 teapot.o: ../../config.h
-teapot.o: $(srcdir)/jwzglesI.h
-teapot.o: $(srcdir)/jwzgles.h
-teapot.o: $(srcdir)/normals.h
-teapot.o: $(srcdir)/teapot2.h
 teapot.o: $(srcdir)/teapot.h
 texfont.o: ../../config.h
 texfont.o: $(HACK_SRC)/fps.h
-texfont.o: $(srcdir)/jwzglesI.h
-texfont.o: $(srcdir)/jwzgles.h
 texfont.o: $(srcdir)/texfont.h
 texfont.o: $(UTILS_SRC)/resources.h
 texfont.o: $(UTILS_SRC)/xft.h
@@ -2956,8 +2760,6 @@ timetunnel.o: $(HACK_SRC)/images/timetunnel0.xpm
 timetunnel.o: $(HACK_SRC)/images/timetunnel1.xpm
 timetunnel.o: $(HACK_SRC)/images/timetunnel2.xpm
 timetunnel.o: $(HACK_SRC)/images/tunnelstar.xpm
-timetunnel.o: $(srcdir)/jwzglesI.h
-timetunnel.o: $(srcdir)/jwzgles.h
 timetunnel.o: $(srcdir)/rotator.h
 timetunnel.o: $(HACK_SRC)/screenhackI.h
 timetunnel.o: $(UTILS_SRC)/colors.h
@@ -2974,49 +2776,27 @@ timetunnel.o: $(HACK_SRC)/xlockmore.h
 timetunnel.o: $(srcdir)/xpm-ximage.h
 toast2.o: ../../config.h
 toast2.o: $(srcdir)/gllist.h
-toast2.o: $(srcdir)/jwzglesI.h
-toast2.o: $(srcdir)/jwzgles.h
 toaster_base.o: ../../config.h
 toaster_base.o: $(srcdir)/gllist.h
-toaster_base.o: $(srcdir)/jwzglesI.h
-toaster_base.o: $(srcdir)/jwzgles.h
 toaster_handle2.o: ../../config.h
 toaster_handle2.o: $(srcdir)/gllist.h
-toaster_handle2.o: $(srcdir)/jwzglesI.h
-toaster_handle2.o: $(srcdir)/jwzgles.h
 toaster_handle.o: ../../config.h
 toaster_handle.o: $(srcdir)/gllist.h
-toaster_handle.o: $(srcdir)/jwzglesI.h
-toaster_handle.o: $(srcdir)/jwzgles.h
 toaster_jet.o: ../../config.h
 toaster_jet.o: $(srcdir)/gllist.h
-toaster_jet.o: $(srcdir)/jwzglesI.h
-toaster_jet.o: $(srcdir)/jwzgles.h
 toaster_knob.o: ../../config.h
 toaster_knob.o: $(srcdir)/gllist.h
-toaster_knob.o: $(srcdir)/jwzglesI.h
-toaster_knob.o: $(srcdir)/jwzgles.h
 toaster.o: ../../config.h
 toaster.o: $(srcdir)/gllist.h
-toaster.o: $(srcdir)/jwzglesI.h
-toaster.o: $(srcdir)/jwzgles.h
 toaster_slots.o: ../../config.h
 toaster_slots.o: $(srcdir)/gllist.h
-toaster_slots.o: $(srcdir)/jwzglesI.h
-toaster_slots.o: $(srcdir)/jwzgles.h
 toaster_wing.o: ../../config.h
 toaster_wing.o: $(srcdir)/gllist.h
-toaster_wing.o: $(srcdir)/jwzglesI.h
-toaster_wing.o: $(srcdir)/jwzgles.h
 toast.o: ../../config.h
 toast.o: $(srcdir)/gllist.h
-toast.o: $(srcdir)/jwzglesI.h
-toast.o: $(srcdir)/jwzgles.h
 topblock.o: ../../config.h
 topblock.o: $(HACK_SRC)/fps.h
 topblock.o: $(srcdir)/gltrackball.h
-topblock.o: $(srcdir)/jwzglesI.h
-topblock.o: $(srcdir)/jwzgles.h
 topblock.o: $(HACK_SRC)/screenhackI.h
 topblock.o: $(srcdir)/sphere.h
 topblock.o: $(srcdir)/topblock.h
@@ -3035,22 +2815,14 @@ trackball.o: ../../config.h
 trackball.o: $(srcdir)/trackball.h
 tronbit_idle1.o: ../../config.h
 tronbit_idle1.o: $(srcdir)/gllist.h
-tronbit_idle1.o: $(srcdir)/jwzglesI.h
-tronbit_idle1.o: $(srcdir)/jwzgles.h
 tronbit_idle2.o: ../../config.h
 tronbit_idle2.o: $(srcdir)/gllist.h
-tronbit_idle2.o: $(srcdir)/jwzglesI.h
-tronbit_idle2.o: $(srcdir)/jwzgles.h
 tronbit_no.o: ../../config.h
 tronbit_no.o: $(srcdir)/gllist.h
-tronbit_no.o: $(srcdir)/jwzglesI.h
-tronbit_no.o: $(srcdir)/jwzgles.h
 tronbit.o: ../../config.h
 tronbit.o: $(HACK_SRC)/fps.h
 tronbit.o: $(srcdir)/gllist.h
 tronbit.o: $(srcdir)/gltrackball.h
-tronbit.o: $(srcdir)/jwzglesI.h
-tronbit.o: $(srcdir)/jwzgles.h
 tronbit.o: $(srcdir)/rotator.h
 tronbit.o: $(HACK_SRC)/screenhackI.h
 tronbit.o: $(srcdir)/sphere.h
@@ -3066,16 +2838,10 @@ tronbit.o: $(HACK_SRC)/xlockmoreI.h
 tronbit.o: $(HACK_SRC)/xlockmore.h
 tronbit_yes.o: ../../config.h
 tronbit_yes.o: $(srcdir)/gllist.h
-tronbit_yes.o: $(srcdir)/jwzglesI.h
-tronbit_yes.o: $(srcdir)/jwzgles.h
 tube.o: ../../config.h
-tube.o: $(srcdir)/jwzglesI.h
-tube.o: $(srcdir)/jwzgles.h
 tube.o: $(srcdir)/tube.h
 tunnel_draw.o: ../../config.h
 tunnel_draw.o: $(HACK_SRC)/fps.h
-tunnel_draw.o: $(srcdir)/jwzglesI.h
-tunnel_draw.o: $(srcdir)/jwzgles.h
 tunnel_draw.o: $(HACK_SRC)/screenhackI.h
 tunnel_draw.o: $(srcdir)/tunnel_draw.h
 tunnel_draw.o: $(UTILS_SRC)/colors.h
@@ -3087,11 +2853,26 @@ 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
+unicrud.o: $(HACK_SRC)/fps.h
+unicrud.o: $(srcdir)/gltrackball.h
+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)/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
 unknownpleasures.o: ../../config.h
 unknownpleasures.o: $(HACK_SRC)/fps.h
 unknownpleasures.o: $(srcdir)/gltrackball.h
-unknownpleasures.o: $(srcdir)/jwzglesI.h
-unknownpleasures.o: $(srcdir)/jwzgles.h
 unknownpleasures.o: $(HACK_SRC)/screenhackI.h
 unknownpleasures.o: $(UTILS_SRC)/colors.h
 unknownpleasures.o: $(UTILS_SRC)/grabscreen.h
@@ -3105,8 +2886,6 @@ unknownpleasures.o: $(HACK_SRC)/xlockmoreI.h
 unknownpleasures.o: $(HACK_SRC)/xlockmore.h
 voronoi.o: ../../config.h
 voronoi.o: $(HACK_SRC)/fps.h
-voronoi.o: $(srcdir)/jwzglesI.h
-voronoi.o: $(srcdir)/jwzgles.h
 voronoi.o: $(HACK_SRC)/screenhackI.h
 voronoi.o: $(UTILS_SRC)/colors.h
 voronoi.o: $(UTILS_SRC)/grabscreen.h
@@ -3121,8 +2900,6 @@ voronoi.o: $(HACK_SRC)/xlockmore.h
 whale.o: $(srcdir)/atlantis.h
 whale.o: ../../config.h
 whale.o: $(HACK_SRC)/fps.h
-whale.o: $(srcdir)/jwzglesI.h
-whale.o: $(srcdir)/jwzgles.h
 whale.o: $(HACK_SRC)/screenhackI.h
 whale.o: $(UTILS_SRC)/colors.h
 whale.o: $(UTILS_SRC)/grabscreen.h
@@ -3135,9 +2912,8 @@ winduprobot.o: ../../config.h
 winduprobot.o: $(HACK_SRC)/fps.h
 winduprobot.o: $(srcdir)/gllist.h
 winduprobot.o: $(srcdir)/gltrackball.h
+winduprobot.o: $(HACK_SRC)/images/chromesphere.xpm
 winduprobot.o: $(srcdir)/involute.h
-winduprobot.o: $(srcdir)/jwzglesI.h
-winduprobot.o: $(srcdir)/jwzgles.h
 winduprobot.o: $(HACK_SRC)/screenhackI.h
 winduprobot.o: $(srcdir)/sphere.h
 winduprobot.o: $(srcdir)/texfont.h
@@ -3155,8 +2931,6 @@ winduprobot.o: $(HACK_SRC)/xlockmore.h
 winduprobot.o: $(srcdir)/xpm-ximage.h
 xlock-gl-utils.o: ../../config.h
 xlock-gl-utils.o: $(HACK_SRC)/fps.h
-xlock-gl-utils.o: $(srcdir)/jwzglesI.h
-xlock-gl-utils.o: $(srcdir)/jwzgles.h
 xlock-gl-utils.o: $(HACK_SRC)/screenhackI.h
 xlock-gl-utils.o: $(srcdir)/texfont.h
 xlock-gl-utils.o: $(UTILS_SRC)/colors.h
index b4581e5695cfc5ea49a2f5bbd668b27fddec544f..a1ffadd569e3ec760deb17f0b855af657039b65b 100644 (file)
@@ -25,7 +25,7 @@
 #include "xlock.h"
 #endif
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
 # include "jwxyz.h"
 #else
 # include <X11/Xlib.h>
@@ -655,13 +655,23 @@ ENTRYPOINT void draw_antinspect(ModeInfo * mi)
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
   glPushMatrix();
-  glRotatef(current_device_rotation(), 0, 0, 1);
 
   mi->polygon_count = 0;
 
   /* position camera --- this works well, we can peer inside 
      the antbubble */
   glTranslatef(0.0, 0.0, -10.0);
+
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+    glRotatef(o, 0, 0, 1);
+  }
+# endif
+
   gltrackball_rotate(mp->trackball);
   glRotatef((15.0/2.0 + 15.0*sin(mp->ant_step/100.0)), 1.0, 0.0, 0.0);
   glRotatef(30.0, 1.0, 0.0, 0.0);
index 6258fb9e6603663a7e5ae54ac9f9be1622530589..a66c4b5c0b6b3a1741a606beabc5d1d42394566a 100644 (file)
@@ -31,7 +31,7 @@ static const char sccsid[] = "@(#)antmaze.c   5.01 2001/03/01 xlockmore";
 # include "xlock.h"            /* from the xlockmore distribution */
 #endif /* !STANDALONE */
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
 # include "jwxyz.h"
 #else
 # include <X11/Xlib.h>
@@ -1422,6 +1422,7 @@ ENTRYPOINT void init_antmaze(ModeInfo * mi)
 static void
 device_rotate(ModeInfo *mi)
 {
+#if 0
   GLfloat rot = current_device_rotation();
   glRotatef(rot, 0, 0, 1);
   if ((rot >  45 && rot <  135) ||
@@ -1430,6 +1431,7 @@ device_rotate(ModeInfo *mi)
       GLfloat s = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
       glScalef (1/s, s, 1);
     }
+#endif
 }
 
 
index 36c81241aab3c5238334b328f74b172e1d3fbbba..a049976de0d4683cd1798fac13aa14d338570395 100644 (file)
@@ -25,7 +25,7 @@
 #include "xlock.h"
 #endif
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
 # include "jwxyz.h"
 #else
 # include <X11/Xlib.h>
index 98ebf3235f9800c37feb4cde205876e44d40cc68..1d9deab8e92a28253df122c8eeb5f4496d49ddf4 100644 (file)
@@ -354,7 +354,7 @@ clear_tank (atlantisstruct * ap)
         glPushMatrix();
         {
           glLoadIdentity();
-          glRotatef(current_device_rotation(), 0, 0, 1);
+          /* glRotatef(current_device_rotation(), 0, 0, 1); */
 
 # ifndef HAVE_JWZGLES
           glShadeModel (GL_SMOOTH);
index 4177eeffafacfaf01a9c3ea5d1cf3b65ecad3492..3b24bfab32526b702a8dc01b0ff54f4a4f910447 100644 (file)
 #ifdef STANDALONE
 # include <math.h>
 # include "screenhackI.h"
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
 #  include <GL/gl.h>
 #  include <GL/glx.h>
 # endif
 #else
 # include "xlock.h"
 #endif
+#ifdef HAVE_ANDROID
+#include <GLES/gl.h>
+#endif
+
 
 #ifdef HAVE_JWZGLES
 # include "jwzgles.h"
index 13b8399b6674684812aabc0ae5b4f17d5a027dcd..ea43b9bf87151ded310f282935d40bcb96fe0149 100644 (file)
@@ -41,6 +41,7 @@ static const char sccsid[] = "@(#)atunnel.c   5.13 2004/05/25 xlockmore";
 #ifdef STANDALONE              /* xscreensaver mode */
 #define        DEFAULTS                "*delay:        10000   \n" \
                                 "*showFPS:  False   \n" \
+                                                               "*suppressRotationAnimation: True\n" \
 
 # define refresh_atunnel 0
 # define atunnel_handle_event 0
index f322be2caf9b54d2cd9c285a8e4c01450bb03ae0..90880d17fa9fe06ae52b5489342989c5df848fda 100644 (file)
@@ -53,7 +53,7 @@ struct glb_config glb_config =
 
 
 #define DEF_TRANSPARENT "True"
-#define DEF_COLOR "random"
+#define DEF_BUBBLECOLOR "random"
 
 static Bool transparent_p;
 static char *bubble_color_str;
@@ -64,12 +64,12 @@ static char *bubble_color_str;
 static XrmOptionDescRec opts[] = {
   { "-transparent",  ".transparent",   XrmoptionNoArg, "True" },
   { "+transparent",  ".transparent",   XrmoptionNoArg, "False" },
-  { "-color",    ".bubble3d.bubblecolor", XrmoptionSepArg, 0 },
+  { "-color",        ".bubblecolor",   XrmoptionSepArg, 0 },
 };
 
 static argtype vars[] = {
   {&transparent_p,   "transparent", "Transparent", DEF_TRANSPARENT, t_Bool},
-  {&bubble_color_str,        "bubblecolor", "BubbleColor", DEF_COLOR, t_String},
+  {&bubble_color_str,        "bubblecolor", "BubbleColor", DEF_BUBBLECOLOR, t_String},
 };
 
 ENTRYPOINT ModeSpecOpt bubble3d_opts = {countof(opts), opts, countof(vars), vars, NULL};
@@ -198,7 +198,17 @@ draw_bubble3d(ModeInfo * mi)
 
         glb_config.polygon_count = 0;
         glPushMatrix();
-        glRotatef(current_device_rotation(), 0, 0, 1);
+
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+        {
+          GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+          int o = (int) current_device_rotation();
+          if (o != 0 && o != 180 && o != -180)
+            glScalef (1/h, 1/h, 1/h);
+          glRotatef(o, 0, 0, 1);
+        }
+# endif
+
        do_display(c);
         glPopMatrix();
         mi->polygon_count = glb_config.polygon_count;
index 2b3802c8856ccc753d2729d375a7ddec6f2dd8d2..ba4693815f6d474d64d0eb54881267fae92eb4ac 100644 (file)
@@ -14,6 +14,7 @@
 
 #define DEFAULTS       "*delay:        30000            \n" \
                        "*wireframe:    False            \n" \
+                       "*suppressRotationAnimation: True\n" \
 
 # define refresh_ball 0
 # define release_ball 0
@@ -243,6 +244,13 @@ reshape_ball (ModeInfo *mi, int width, int height)
              0.0, 0.0, 0.0,
              0.0, 2.0,  10.0);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
 }
 
 static void
index 69605e7e3c48fc3c843103340e155f38a02d2c20..51f2f3db758fd2fdc3472cfb5cb089eca43c76cd 100644 (file)
@@ -16,6 +16,7 @@
 #define DEFAULTS        "*delay:       40000           \n" \
                         "*wireframe:    False           \n" \
                        "*showFPS:      False           \n" \
+                       "*suppressRotationAnimation: True\n" \
 
 # define refresh_blocktube 0
 # define blocktube_handle_event 0
@@ -321,6 +322,14 @@ ENTRYPOINT void reshape_blocktube (ModeInfo *mi, int width, int height)
     glLoadIdentity();
     gluPerspective(45.0, 1/h, 1.0, 100.0);
     glMatrixMode(GL_MODELVIEW);
+
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+    {
+      int o = (int) current_device_rotation();
+      if (o != 0 && o != 180 && o != -180)
+        glScalef (1/h, 1/h, 1/h);
+    }
+# endif
 }
 
 static int cube_vertices(float x, float y, float z, int wire)
index 91fd6383fbcdf0694a2c5f362e3f5c1d6c43ceeb..0ba3d913199c0d93a516ff940c5305ffb02c23e4 100644 (file)
@@ -611,12 +611,14 @@ draw_boing (ModeInfo *mi)
   {
     double rot = current_device_rotation();
     glRotatef(rot, 0, 0, 1);
+/*
     if ((rot >  45 && rot <  135) ||
         (rot < -45 && rot > -135))
       {
         GLfloat s = MI_WIDTH(mi) / (GLfloat) MI_HEIGHT(mi);
         glScalef (1/s, s, 1);
       }
+*/
   }
 
   gltrackball_rotate (bp->trackball);
index 968002c4f4d7c18c789a20af23ddb8ae529e8597..a2faf1f8190549e002987f681d8c53b082fdf8db 100644 (file)
@@ -471,7 +471,16 @@ draw_cow (ModeInfo *mi)
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
   glPushMatrix ();
-  glRotatef(current_device_rotation(), 0, 0, 1);
+
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+    glRotatef(o, 0, 0, 1);
+  }
+# endif
 
   glScalef (0.5, 0.5, 0.5);
 
index 4e16f09e2ec5b6477ef551cea8523ef7fd0a8092..a7f07d4c313473f489d7bf3cebcde02f6cf99ae1 100644 (file)
@@ -1029,7 +1029,15 @@ static void draw(ModeInfo * mi)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    
-   glRotatef(current_device_rotation(), 0, 0, 1);
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+    glRotatef(o, 0, 0, 1);
+  }
+# endif
 
    gp->tic += 0.01f;
    gp->camtic += 0.01f + 0.01f * sin(gp->tic * speed);
index 70919c347a04503c6838ef8580dc699331fa9051..92ccbbde064f8f797d39cb0f8935b855bf0af9b9 100644 (file)
@@ -14,7 +14,7 @@
 # include "xlock.h"            /* from the xlockmore distribution */
 #endif /* !STANDALONE */
 
-#ifndef HAVE_COCOA
+#if !defined(HAVE_JWXYZ) && !defined(HAVE_JWZGLES)
 # include <GL/gl.h>
 # include <GL/glu.h>
 #endif
index 4b9008186f0b8d3a276a9e8b1adb5c78befebeea..b7fbbd9471051c2417d64b50b222f012fafbf822 100644 (file)
 #endif /* HAVE_CONFIG_H */
 
 #ifdef STANDALONE
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
 #  include <GL/gl.h>
 # endif
 #endif
 
+#ifdef HAVE_ANDROID
+# include <GLES/gl.h>
+#endif
+
+
 #ifdef HAVE_JWZGLES
 # include "jwzgles.h"
 #endif /* HAVE_JWZGLES */
index bcd382b64449197f9fc2651198b2a4f9056a6644..268d0830c604255b979221fc5d699c54fb3d1ed4 100644 (file)
@@ -79,10 +79,10 @@ static const char sccsid[] = "@(#)cage.c    5.01 2001/03/01 xlockmore";
 # define MODE_cage
 # define DEFAULTS                      "*delay:                25000   \n"                     \
                                                        "*showFPS:      False   \n"                     \
-                                                       "*wireframe:    False   \n"
+                                                       "*wireframe:    False   \n"                     \
+                                                       "*suppressRotationAnimation: True\n" \
 
 # define refresh_cage 0
-# define reshape_cage 0
 # define cage_handle_event 0
 # include "xlockmore.h"                /* from the xscreensaver distribution */
 #else /* !STANDALONE */
@@ -291,7 +291,7 @@ draw_impossiblecage(ModeInfo *mi, cagestruct * cp, int wire)
 }
 
 static void
-reshape(ModeInfo * mi, int width, int height)
+reshape_cage(ModeInfo * mi, int width, int height)
 {
        cagestruct *cp = &cage[MI_SCREEN(mi)];
        int i;
@@ -415,7 +415,7 @@ init_cage (ModeInfo * mi)
        cp->step = NRAND(90);
        if ((cp->glx_context = init_GL(mi)) != NULL) {
 
-               reshape(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+               reshape_cage(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
                glDrawBuffer(GL_BACK);
                pinit(mi);
        } else {
@@ -452,6 +452,18 @@ draw_cage (ModeInfo * mi)
                glScalef(Scale4Iconic * cp->WindH / cp->WindW, Scale4Iconic, Scale4Iconic);
        }
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+    if (o != 0 && o != 180 && o != -180) {
+      glScalef (1/h, h, 1/h);  /* #### not quite right */
+      h = 1.7;
+      glScalef (h, h, h);
+    }
+  }
+# endif
+
        /* cage */
        glRotatef(cp->step * 100, 0, 0, 1);
        glRotatef(25 + cos(cp->step * 5) * 6, 1, 0, 0);
index 23e0ef3a7a423fe462cb7fe450efbb3b74360fc0..f81bcf540bb7ca56aaefa0381f38091a418910b8 100644 (file)
@@ -46,7 +46,7 @@
 #include "grab-ximage.h"
 #include "texfont.h"
 
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
 #  include <X11/Intrinsic.h>     /* for XrmDatabase in -debug mode */
 # endif
 
@@ -463,7 +463,7 @@ carousel_handle_event (ModeInfo *mi, XEvent *event)
 static void
 hack_resources (Display *dpy)
 {
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
   char *res = "desktopGrabber";
   char *val = get_string_resource (dpy, res, "DesktopGrabber");
   char buf1[255];
@@ -475,7 +475,7 @@ hack_resources (Display *dpy)
   value.addr = buf2;
   value.size = strlen(buf2);
   XrmPutResource (&db, buf1, "String", &value);
-# endif /* !HAVE_COCOA */
+# endif /* !HAVE_JWXYZ */
 }
 
 
@@ -513,6 +513,7 @@ loading_msg (ModeInfo *mi, int n)
   glPushMatrix();
   glLoadIdentity();
 
+/*
   {
     double rot = current_device_rotation();
     glRotatef(rot, 0, 0, 1);
@@ -523,13 +524,16 @@ loading_msg (ModeInfo *mi, int n)
         glScalef (s, 1/s, 1);
       }
   }
+*/
 
-  if (MI_WIDTH(mi) < MI_HEIGHT(mi))  /* USE_IPHONE portrait orientation */
+# ifdef HAVE_MOBILE
+  if (MI_WIDTH(mi) < MI_HEIGHT(mi))  /* portrait orientation */
     {
       GLfloat s = (MI_WIDTH(mi) / (GLfloat) MI_HEIGHT(mi));
       glScalef (s, s, s);
       glTranslatef(-s/2, 0, 0);
     }
+# endif
 
   glOrtho(0, MI_WIDTH(mi), 0, MI_HEIGHT(mi), -1, 1);
   glTranslatef ((MI_WIDTH(mi)  - ss->loading_sw) / 2,
index eac7b25273d631f177c828e7406dbe853e3b187c..7dd7ecaf6f6825ed3f444a832ed45970f7dfec07 100644 (file)
 #include <math.h>
 #include <stdlib.h>
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # include <GL/glx.h>
 # include <GL/gl.h>
 #endif
 
+#ifdef HAVE_ANDROID
+#include <GLES/gl.h>
+#define Bool int
+#endif
+
 #ifdef HAVE_JWZGLES
 # include "jwzgles.h"
 #endif /* HAVE_JWZGLES */
index 3a848d195e7178925979925875daa64f416801a7..a0b9c161bf41746e99bd2012d9ee62e906c50967 100644 (file)
@@ -32,6 +32,7 @@
 #ifdef STANDALONE
 #define DEFAULTS        "*delay:   20000 \n" \
                         "*showFPS: False \n" \
+                       "*suppressRotationAnimation: True\n" \
                "*componentFont: -*-courier-bold-r-normal-*-*-140-*-*-*-*-*-*"
 
 # define refresh_circuit 0
@@ -1037,7 +1038,6 @@ static int DrawIC(Circuit *ci, IC *c)
   GLfloat lspec[] = {0.6, 0.6, 0.6, 0};
   GLfloat lcol[] = {0.4, 0.4, 0.4, 0};
   GLfloat lshine = 40;
-  float th, size;
 
   glPushMatrix();
   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col);
@@ -1103,20 +1103,12 @@ static int DrawIC(Circuit *ci, IC *c)
     glDisable(GL_POLYGON_OFFSET_FILL);
     glEnable(GL_TEXTURE_2D);
     glEnable(GL_BLEND);
-    if (c->pins == 8)
-      size = 0.4;
-    else
-      size = 0.6;
-    th = size*2/3;
 
     {
       GLfloat texfg[] = {0.7, 0.7, 0.7, 1.0};
       GLfloat s = 0.015;
       XCharStruct e;
-      int w, h;
       texture_string_metrics (ci->font, c->text, &e, 0, 0);
-      w = e.width;
-      h = e.ascent + e.descent;
 
       glPushMatrix();
       glTranslatef (0, 0, 0.1);
@@ -1356,10 +1348,9 @@ static int DrawTransistor(Circuit *ci, Transistor *t)
       GLfloat texfg[] = {0.7, 0.7, 0.7, 1.0};
       GLfloat s = 0.015;
       XCharStruct e;
-      int w, h;
+      int w;
       texture_string_metrics (ci->font, t->text, &e, 0, 0);
       w = e.width;
-      h = e.ascent + e.descent;
       glPushMatrix();
       glRotatef (90, 1, 0, 0);
       glTranslatef (0.5, -0.05, 0.21);
@@ -1385,10 +1376,9 @@ static int DrawTransistor(Circuit *ci, Transistor *t)
       GLfloat texfg[] = {0.7, 0.7, 0.7, 1.0};
       GLfloat s = 0.015;
       XCharStruct e;
-      int w, h;
+      int w;
       texture_string_metrics (ci->font, t->text, &e, 0, 0);
       w = e.width;
-      h = e.ascent + e.descent;
       glPushMatrix();
       glTranslatef (0.75, 0.75, 0.01);
       glScalef (s, s, s);
@@ -1918,7 +1908,6 @@ static void display(ModeInfo *mi)
   glEnable(GL_LIGHTING);
   glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
   glLoadIdentity();
-  /* glRotatef(current_device_rotation(), 0, 0, 1); */
   gluLookAt(ci->viewer[0], ci->viewer[1], ci->viewer[2], 
             0.0, 0.0, 0.0, 
             0.0, 1.0, 0.0);
@@ -1933,6 +1922,18 @@ static void display(ModeInfo *mi)
   glLighti(GL_LIGHT0, GL_CONSTANT_ATTENUATION, (GLfloat)1); 
   glLighti(GL_LIGHT0, GL_LINEAR_ATTENUATION, (GLfloat)0.5); 
   glLighti(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, (GLfloat)0); 
+
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (h, h, h);
+    h = 2;
+    glScalef (h, h, h);
+  }
+# endif
+
   mi->polygon_count += drawgrid(ci);
   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, light_sp);
   if (f_rand() < 0.05) {
index 441028e7fbbe3a6e7524cfb05a0eb2a295cc4f94..57f5277554ae88f725e49d819335ffef8278a9b0 100644 (file)
@@ -361,6 +361,14 @@ reshape_cube (ModeInfo *mi, int width, int height)
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
   glClear(GL_COLOR_BUFFER_BIT);
 }
 
index 85c6294090da6a632c0748da872cba5d48084a65..30af9633440d6e6f27c2c4cfa885583a6db5ad26 100644 (file)
@@ -1,7 +1,7 @@
 /***************************
  ** crackberg; Matus Telgarsky [ catachresis@cmu.edu ] 2005 
  ** */
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # define XK_MISCELLANY
 # include <X11/keysymdef.h>
 #endif
index 542c93699e3953bde0e1b36708b3edd435e8c651..31a3c6afe2d35dba4f13a26041d4a3e2169f5bfe 100644 (file)
@@ -515,10 +515,20 @@ static Bool draw_main(ModeInfo *mi, cube21_conf *cp)
     glTranslatef(0, 0, zpos);
   glScalef(size, size, size);
 
-  gltrackball_rotate (cp->trackball);
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
 
   glRotatef(cp->xrot, 1.0, 0.0, 0.0);
   glRotatef(cp->yrot, 0.0, 1.0, 0.0);
+
+  gltrackball_rotate (cp->trackball);
+
   if(cp->wire) glColor3f(0.7, 0.7, 0.7);
   switch(cp->state) {
     case CUBE21_PAUSE1:
@@ -891,6 +901,10 @@ ENTRYPOINT void init_cube21(ModeInfo *mi)
     make_texture(cp);
   }
 
+#ifdef HAVE_MOBILE
+  size *= 2;
+#endif
+
   if ((cp->glx_context = init_GL(mi)) != NULL) {
     init_gl(mi);
     init_cp(cp);
index 9d91268aedda64563ed12ed8aafda4ea851785e6..d611ac391df2387f54e5cb6ec990d2379458b0f5 100644 (file)
@@ -13,6 +13,7 @@
                        "*count:        5           \n" \
                        "*showFPS:      False       \n" \
                        "*wireframe:    False       \n" \
+                       "*suppressRotationAnimation: True\n" \
 
 # define refresh_cube 0
 # define release_cube 0
@@ -199,6 +200,14 @@ reshape_cube (ModeInfo *mi, int width, int height)
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
   glClear(GL_COLOR_BUFFER_BIT);
 }
 
index f3fd88bbb262f6eed0889857185963b81e7723f8..9c278b135e38c97524cce08f645eae43bebcbf3b 100644 (file)
@@ -14,6 +14,7 @@
                        "*showFPS:      False       \n" \
                        "*fpsSolid:     True        \n" \
                        "*wireframe:    False       \n" \
+                       "*suppressRotationAnimation: True\n" \
 
 
 # define refresh_cube 0
@@ -174,6 +175,14 @@ reshape_cube (ModeInfo *mi, int width, int height)
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 }
 
index 3f72162c6e6d87caf087fd1ab83562fc4680ead1..82a1862b258db5734a445fa4c8b8f793e22a5194 100644 (file)
@@ -21,7 +21,8 @@
 
 #define DEFAULTS   "*delay:         20000         \n" \
                    "*showFPS:       False         \n" \
-                   "*wireframe:     False         \n"
+                   "*wireframe:     False         \n" \
+                  "*suppressRotationAnimation: True\n" \
 
 # define refresh_cubicgrid 0
 #include "xlockmore.h"
@@ -103,8 +104,9 @@ cubicgrid_handle_event (ModeInfo *mi, XEvent *event)
 }
 
 
-static Bool draw_main(cubicgrid_conf *cp) 
+static Bool draw_main(ModeInfo *mi)
 {
+  cubicgrid_conf *cp = &cubicgrid[MI_SCREEN(mi)];
   double x, y, z;
 
   glClear(GL_COLOR_BUFFER_BIT);
@@ -117,6 +119,16 @@ static Bool draw_main(cubicgrid_conf *cp)
 
   glScalef(size/ticks, size/ticks, size/ticks);
 
+
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1);
+  }
+# endif
+
   gltrackball_rotate (cp->trackball);
 
   get_rotation (cp->rot, &x, &y, &z, !cp->button_down_p);
@@ -241,7 +253,7 @@ ENTRYPOINT void draw_cubicgrid(ModeInfo * mi)
   MI_IS_DRAWN(mi) = True;
   if (!cp->glx_context) return;
   glXMakeCurrent(display, window, *(cp->glx_context));
-  if (!draw_main(cp)) {
+  if (!draw_main(mi)) {
     release_cubicgrid(mi);
     return;
   }
index a44a55d703ac7beb86b58d589865fcd9abab198c..030546483f86e48c84f63dca26755225849732a0 100644 (file)
@@ -13,6 +13,7 @@
                        "*count:        30          \n" \
                        "*showFPS:      False       \n" \
                        "*wireframe:    False       \n" \
+                       "*suppressRotationAnimation: True\n" \
 
 # define refresh_ball 0
 # define release_ball 0
@@ -101,6 +102,14 @@ reshape_ball (ModeInfo *mi, int width, int height)
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
   glClear(GL_COLOR_BUFFER_BIT);
 }
 
index 2d3bbb2c8df383e8ffc3370d6901cff20c82afb7..1cf6929c046f1049a33484eb6cb1201daf7c65b2 100644 (file)
@@ -1,4 +1,4 @@
-/* DNA Logo, Copyright (c) 2001-2015 Jamie Zawinski <jwz@jwz.org>
+/* DNA Logo, Copyright (c) 2001-2016 Jamie Zawinski <jwz@jwz.org>
  *
  *      DNA Lounge
  *
@@ -8,7 +8,7 @@
  *      San Francisco, CA
  *      94103
  *
- *      http://www.dnalounge.com/
+ *      https://www.dnalounge.com/
  *      http://www.dnapizza.com/
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -61,7 +61,7 @@
                        "*cwFont:           " CWFONT "\n" \
                        "*geometry:         =640x640\n" \
 
-# if defined(HAVE_COCOA)
+# if defined(HAVE_COCOA) || defined(HAVE_ANDROID)
 #  define CWFONT "Yearling 28, OCR A Std 24"
 # else
 #  define CWFONT "-*-helvetica-medium-r-normal-*-*-240-*-*-*-*-*-*"
@@ -72,7 +72,6 @@
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
 
-#undef LINEAR
 #undef DXF_OUTPUT_HACK
 
 #ifdef DXF_OUTPUT_HACK   /* When this is defined, instead of rendering
@@ -113,9 +112,11 @@ typedef enum {
 
 typedef struct {
   Bool spinning_p;
-  GLfloat position;     /* 0.0 - 1.0 */
-  GLfloat speed;        /* how far along the path (may be negative) */
-  GLfloat probability;  /* relative likelyhood to start spinning */
+  GLfloat position;            /* 0.0 - 1.0 */
+  GLfloat position_eased;      /* 0.0 - 1.0, eased in and out */
+  GLfloat easement;            /* portion of path that is eased. <= 0.5 */
+  GLfloat speed;               /* how far along the path (may be negative) */
+  GLfloat probability;         /* relative likelyhood to start spinning */
 } spinner;
 
 typedef struct {
@@ -1519,7 +1520,6 @@ make_pizza (logo_configuration *dc, int facetted, int wire)
   GLfloat th, x, y, s;
   int i, j, k;
   int endpoints;
-  int endedge1;
 
 # ifdef HAVE_TESS
   tess_out TO, *to = &TO;
@@ -1571,7 +1571,6 @@ make_pizza (logo_configuration *dc, int facetted, int wire)
         points[j++] = edge[i*2];
         points[j++] = 0;
       }
-    endedge1 = i;
   }
 
   s = 0.798;  /* radius of end of slice, before crust gap */
@@ -1759,21 +1758,39 @@ make_pizza (logo_configuration *dc, int facetted, int wire)
 # else  /* !HAVE_TESS */
   if (! wire)
     {
+      glTranslatef(0, 0, thick2);
+      glNormal3f (0, 0, 1);
+      glFrontFace (GL_CW);
+
+      /* Sadly, jwzgl's glVertexPointer seems not to be recordable inside
+         display lists. */
+#  if 0
       glDisableClientState (GL_COLOR_ARRAY);
       glDisableClientState (GL_NORMAL_ARRAY);
       glDisableClientState (GL_TEXTURE_COORD_ARRAY);
       glEnableClientState (GL_VERTEX_ARRAY);
       glVertexPointer (3, GL_FLOAT, 0, dnapizza_triangles);
-
-      glTranslatef(0, 0, thick2);
-      glNormal3f (0, 0, 1);
-      glFrontFace (GL_CW);
       glDrawArrays (GL_TRIANGLES, 0, countof (dnapizza_triangles) / 3);
+#  else
+      glBegin (GL_TRIANGLES);
+      for (i = 0; i < countof (dnapizza_triangles); i += 3)
+        glVertex3fv (dnapizza_triangles + i);
+      glEnd();
+#  endif
 
       glTranslatef(0, 0, -thick2*2);
       glNormal3f (0, 0, -1);
       glFrontFace (GL_CCW);
+
+#  if 0
       glDrawArrays (GL_TRIANGLES, 0, countof (dnapizza_triangles) / 3);
+#  else
+      int i;
+      glBegin (GL_TRIANGLES);
+      for (i = 0; i < countof (dnapizza_triangles); i += 3)
+        glVertex3fv (dnapizza_triangles + i);
+      glEnd();
+#  endif
 
       glTranslatef(0, 0, thick2);
     }
@@ -1935,7 +1952,7 @@ make_codeword_path (ModeInfo *mi)
 
   int dial = 0;
   int letter;
-  GLfloat last_r;
+  GLfloat last_r = 0;
 
   GLfloat inner_circum = M_PI * 2 * (iradius + rtick * 2);
   GLfloat outer_circum = M_PI * 2 * (iradius + rtick * (letters + 1));
@@ -2328,7 +2345,7 @@ codeword_text_output (ModeInfo *mi, GLfloat anim_ratio)
           buf[1] = 0;
           texture_string_metrics (dc->font, buf, &e, &ascent, &descent);
 
-# ifdef USE_IPHONE
+# ifdef HAVE_MOBILE
           /* #### Magic magic magic WTF... */
           glScalef (0.5, 0.5, 0.5);
 # endif
@@ -2497,7 +2514,7 @@ draw_codeword_path (ModeInfo *mi)
   glColor4fv (dc->codeword_color);
   glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, dc->codeword_color);
 
-# ifdef USE_IPHONE  /* Make the whole thing fit on the phone screen */
+# ifdef HAVE_MOBILE  /* Make the whole thing fit on the phone screen */
   {
     GLfloat size = MI_WIDTH(mi) < MI_HEIGHT(mi) ? MI_WIDTH(mi) : MI_HEIGHT(mi);
     glScalef (0.9, 0.9, 0.9);
@@ -2643,7 +2660,7 @@ draw_codeword_path (ModeInfo *mi)
   /* Draw the start and end caps */
   {
     int i;
-    GLfloat x, y, z, x2, y2, z2, X, Y, Z, L;
+    GLfloat x, y, z, x2, y2, z2, X, Y, Z;
     GLfloat r = dc->codeword_spread * dc->codeword_cap_size;
 
     i = 0;
@@ -2676,7 +2693,6 @@ draw_codeword_path (ModeInfo *mi)
     X = (x2 - x);
     Y = (y2 - y);
     Z = (z2 - z);
-    L = sqrt (X*X + Y*Y + Z*Z);
 
     glPushMatrix();
     glTranslatef (x, y, z);
@@ -2718,6 +2734,14 @@ reshape_logo (ModeInfo *mi, int width, int height)
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);  /* #### Why does this change the lighting? */
+  }
+# endif
+
   glClear(GL_COLOR_BUFFER_BIT);
 }
 
@@ -2912,16 +2936,25 @@ init_logo (ModeInfo *mi)
   dc->gasket_spinnerx.probability = 0.1;
   dc->gasket_spinnery.probability = 0.1;
   dc->gasket_spinnerz.probability = 1.0;
+  dc->gasket_spinnerx.easement    = 0.08;
+  dc->gasket_spinnery.easement    = 0.08;
+  dc->gasket_spinnerz.easement    = 0.08;
 
   dc->helix_spinnerz.probability  = 0.6;
+  dc->helix_spinnerz.easement     = 0.2;
 
   dc->pizza_spinnerz.probability  = 0.6;
   dc->pizza_spinnery.probability  = 0.6;
+  dc->pizza_spinnerz.easement     = 0.2;
+  dc->pizza_spinnery.easement     = 0.2;
 
   dc->frame_spinner.probability   = 5.0;
+  dc->frame_spinner.easement      = 0.2;
 
   dc->scene_spinnerx.probability  = 0.1;
   dc->scene_spinnery.probability  = 0.0;
+  dc->scene_spinnerx.easement     = 0.1;
+  dc->scene_spinnery.easement     = 0.1;
 
   if (dc->mode == CODEWORD_IN)
     {
@@ -3099,6 +3132,14 @@ logo_handle_event (ModeInfo *mi, XEvent *event)
 }
 
 
+static GLfloat
+spinner_ease (GLfloat x)
+{
+  /* Smooth curve up, ending at slope = 1. */
+  return cos ((x/2 + 1) * M_PI) + 1;
+}
+
+
 static void
 tick_spinner (ModeInfo *mi, spinner *s)
 {
@@ -3110,12 +3151,20 @@ tick_spinner (ModeInfo *mi, spinner *s)
   if (s->spinning_p)
     {
       s->position += s->speed;
-      if (s->position >=  1.0 || s->position <= -1.0)
-          
+      if (s->position >=  1.0 || s->position <= 0.0)
         {
           s->position = 0;
+          s->position_eased = 0;
           s->spinning_p = False;
         }
+      else if (s->easement > 0 && s->position <= s->easement)
+        s->position_eased = (s->easement *
+                             spinner_ease (s->position / s->easement));
+      else if (s->easement > 0 && s->position >= 1-s->easement)
+        s->position_eased = (1 - s->easement *
+                             spinner_ease ((1 - s->position) / s->easement));
+      else
+        s->position_eased = s->position;
     }
   else if (s->probability &&
            (random() % (int) (PROBABILITY_SCALE / s->probability)) == 0)
@@ -3127,7 +3176,10 @@ tick_spinner (ModeInfo *mi, spinner *s)
         s->speed = dc->speed * (frand(ss/3) + frand(ss/3) + frand(ss/3));
       } while (s->speed <= 0);
       if (random() & 1)
-        s->speed = -s->speed;
+        {
+          s->speed = -s->speed;
+          s->position = 1.0;
+        }
     }
 }
 
@@ -3182,28 +3234,6 @@ draw_logo (ModeInfo *mi)
   tick_spinner (mi, &dc->frame_spinner);
   link_spinners (mi, &dc->scene_spinnerx, &dc->scene_spinnery);
 
-# ifdef LINEAR
-  {
-    static double i = 0.0;
-    dc->anim_state = HELIX;
-    dc->wire_overlay = 0;
-    dc->gasket_spinnerx.spinning_p = 0;
-    dc->gasket_spinnery.spinning_p = 0;
-    dc->gasket_spinnerz.spinning_p = 0;
-    dc->helix_spinnerz.spinning_p = 0;
-    dc->pizza_spinnery.spinning_p = 0;
-    dc->pizza_spinnerz.spinning_p = 0;
-    dc->scene_spinnerx.spinning_p = 0;
-    dc->scene_spinnery.spinning_p = 0;
-    dc->frame_spinner.spinning_p = 0;
-    dc->frame_spinner.position = 0.3;
-    dc->gasket_spinnerz.position = i;
-    dc->helix_spinnerz.position = i;
-    i += 0.005;
-    if (i > 1) i = 0;
-  }
-# endif /* LINEAR */
-
   switch (dc->anim_state)
     {
     case HELIX:
@@ -3268,7 +3298,7 @@ draw_logo (ModeInfo *mi)
       break;
 
     case CODEWORD:
-      dc->scene_spinnerx.probability = 2.5;
+      dc->scene_spinnerx.probability = 0.5;
       dc->scene_spinnery.probability = 0.2;
       if (! dc->button_down_p)
         dc->anim_ratio += (0.0005 + frand(0.002)) * dc->speed;
@@ -3323,9 +3353,6 @@ draw_logo (ModeInfo *mi)
   glRotatef(current_device_rotation(), 0, 0, 1);
   {
     GLfloat scale = 1.8;
-# ifdef LINEAR
-    scale = 3.85;
-# endif
     glScalef(scale, scale, scale);
 
     glColor3f(dc->color[0], dc->color[1], dc->color[2]);
@@ -3334,9 +3361,9 @@ draw_logo (ModeInfo *mi)
     /* Draw frame before trackball rotation */
     if (! codeword_p)
       {
-        GLfloat p = (dc->frame_spinner.position >= 0
-                     ? dc->frame_spinner.position
-                     : -dc->frame_spinner.position);
+        GLfloat p = (dc->frame_spinner.position_eased >= 0
+                     ? dc->frame_spinner.position_eased
+                     : -dc->frame_spinner.position_eased);
         GLfloat size = (p > 0.5 ? 1-p : p);
         scale = 1 + (size * 10);
         glPushMatrix();
@@ -3373,22 +3400,16 @@ draw_logo (ModeInfo *mi)
     glRotatef(90, 1, 0, 0);
     glRotatef(90, 0, 0, 1);
 
-# ifdef LINEAR
-#  define SINIFY(I) (I)
-# else
-#  define SINIFY(I) sin (M_PI/2 * (I))
-# endif
-
     if (! codeword_p)
       {
-        glRotatef (360 * SINIFY (dc->scene_spinnerx.position), 0, 1, 0);
-        glRotatef (360 * SINIFY (dc->scene_spinnery.position), 0, 0, 1);
+        glRotatef (360 * dc->scene_spinnerx.position_eased, 0, 1, 0);
+        glRotatef (360 * dc->scene_spinnery.position_eased, 0, 0, 1);
 
         glPushMatrix();
 
-        glRotatef (360 * SINIFY (dc->gasket_spinnerx.position), 0, 1, 0);
-        glRotatef (360 * SINIFY (dc->gasket_spinnery.position), 0, 0, 1);
-        glRotatef (360 * SINIFY (dc->gasket_spinnerz.position), 1, 0, 0);
+        glRotatef (360 * dc->gasket_spinnerx.position_eased, 0, 1, 0);
+        glRotatef (360 * dc->gasket_spinnery.position_eased, 0, 0, 1);
+        glRotatef (360 * dc->gasket_spinnerz.position_eased, 1, 0, 0);
 
         memcpy (gcolor, dc->color, sizeof (dc->color));
         if (dc->wire_overlay != 0)
@@ -3426,12 +3447,12 @@ draw_logo (ModeInfo *mi)
 
         if (pizza_p)
           {
-            glRotatef (360 * SINIFY (dc->pizza_spinnery.position), 1, 0, 0);
-            glRotatef (360 * SINIFY (dc->pizza_spinnerz.position), 0, 0, 1);
+            glRotatef (360 * dc->pizza_spinnery.position_eased, 1, 0, 0);
+            glRotatef (360 * dc->pizza_spinnerz.position_eased, 0, 0, 1);
           }
         else
           {
-            glRotatef (360 * SINIFY (dc->helix_spinnerz.position), 0, 0, 1);
+            glRotatef (360 * dc->helix_spinnerz.position_eased, 0, 0, 1);
           }
 
         scale = ((dc->anim_state == PIZZA_IN || dc->anim_state == HELIX_IN)
@@ -3488,8 +3509,8 @@ draw_logo (ModeInfo *mi)
         glRotatef (max/2 - y*max, 0, 1, 0);
         /* glRotatef (max/2 - z*max, 1, 0, 0); */
 # else
-        glRotatef (360 * SINIFY (dc->scene_spinnerx.position), 0, 1, 0);
-        glRotatef (360 * SINIFY (dc->scene_spinnery.position), 0, 0, 1);
+        glRotatef (360 * dc->scene_spinnerx.position_eased, 0, 1, 0);
+        glRotatef (360 * dc->scene_spinnery.position_eased, 0, 0, 1);
 # endif
 
         glClearColor (dc->codeword_bg[0],
index 212a0c6567ef4bb1b32c0ce9a550dab5bceab2b4..09af0c8f45b586880fd3f0685bf04380d10e2037 100644 (file)
 # include "config.h"
 #endif /* HAVE_CONFIG_H */
 
-#ifdef HAVE_COCOA
-# ifndef HAVE_JWZGLES
-#  include <OpenGL/glu.h>
-# endif
-#else /* !HAVE_COCOA */
-# include <GL/gl.h>
-# include <GL/glu.h>
-#endif /* !HAVE_COCOA */
-
-#ifdef HAVE_JWZGLES
-# include "jwzgles.h"
-#endif /* HAVE_JWZGLES */
+#include "xlockmoreI.h"
 
 /* Initialize drop shadow texture, return a texture ID.
  */
diff --git a/hacks/glx/dymaxionmap.c b/hacks/glx/dymaxionmap.c
new file mode 100644 (file)
index 0000000..f82a98d
--- /dev/null
@@ -0,0 +1,1028 @@
+/* dymaxionmap --- Buckminster Fuller's unwrapped icosahedral globe.
+ * Copyright (c) 2016 Jamie Zawinski.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appear in all copies and that
+ * both that copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * This file is provided AS IS with no warranties of any kind. The author
+ * shall have no liability with respect to the infringement of copyrights,
+ * trade secrets or any patents by this file or any part thereof.  In no
+ * event will the author be liable for any lost revenue or profits or
+ * other special, indirect and consequential damages.
+ */
+
+#define LABEL_FONT "-*-helvetica-bold-r-normal-*-*-240-*-*-*-*-*-*"
+
+#ifdef STANDALONE
+#define DEFAULTS    "*delay:           20000   \n" \
+                   "*showFPS:          False   \n" \
+                   "*wireframe:        False   \n" \
+                   "*labelFont:  " LABEL_FONT "\n"
+# define refresh_planet 0
+# include "xlockmore.h"                    /* from the xscreensaver distribution */
+#else  /* !STANDALONE */
+# include "xlock.h"                /* from the xlockmore distribution */
+#endif /* !STANDALONE */
+
+#ifdef USE_GL /* whole file */
+
+#include "sphere.h"
+#include "normals.h"
+#include "texfont.h"
+
+#ifdef HAVE_XMU
+# ifndef VMS
+#  include <X11/Xmu/Drawing.h>
+#else  /* VMS */
+#  include <Xmu/Drawing.h>
+# endif /* VMS */
+#endif
+
+#define DEF_ROTATE  "True"
+#define DEF_ROLL    "True"
+#define DEF_WANDER  "True"
+#define DEF_TEXTURE "True"
+#define DEF_STARS   "True"
+#define DEF_SPEED   "1.0"
+#define DEF_IMAGE   "BUILTIN"
+
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+#undef BELLRAND
+#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3)
+
+static int do_roll;
+static int do_wander;
+static int do_texture;
+static int do_stars;
+static GLfloat speed;
+static char *which_image;
+
+static XrmOptionDescRec opts[] = {
+  {"-speed",   ".dymaxionmap.speed",   XrmoptionSepArg, 0 },
+  {"-roll",    ".dymaxionmap.roll",    XrmoptionNoArg, "true" },
+  {"+roll",    ".dymaxionmap.roll",    XrmoptionNoArg, "false" },
+  {"-wander",  ".dymaxionmap.wander",  XrmoptionNoArg, "true" },
+  {"+wander",  ".dymaxionmap.wander",  XrmoptionNoArg, "false" },
+  {"-texture", ".dymaxionmap.texture", XrmoptionNoArg, "true" },
+  {"+texture", ".dymaxionmap.texture", XrmoptionNoArg, "false" },
+  {"-stars",   ".dymaxionmap.stars",   XrmoptionNoArg, "true" },
+  {"+stars",   ".dymaxionmap.stars",   XrmoptionNoArg, "false" },
+  {"-image",   ".dymaxionmap.image",  XrmoptionSepArg, 0 },
+};
+
+static argtype vars[] = {
+  {&speed,       "speed",   "Speed",   DEF_SPEED,   t_Float},
+  {&do_roll,    "roll",    "Roll",    DEF_ROLL,    t_Bool},
+  {&do_wander,  "wander",  "Wander",  DEF_WANDER,  t_Bool},
+  {&do_texture,         "texture", "Texture", DEF_TEXTURE, t_Bool},
+  {&do_stars,   "stars",   "Stars",   DEF_STARS,   t_Bool},
+  {&which_image, "image",   "Image",   DEF_IMAGE,   t_String},
+};
+
+ENTRYPOINT ModeSpecOpt planet_opts = {countof(opts), opts, countof(vars), vars, NULL};
+
+#ifdef USE_MODULES
+ModStruct   planet_description =
+{"planet", "init_planet", "draw_planet", "release_planet",
+ "draw_planet", "init_planet", NULL, &planet_opts,
+ 1000, 1, 2, 1, 4, 1.0, "",
+ "Buckminster Fuller's unwrapped icosahedral globe", 0, NULL};
+#endif
+
+# ifdef __GNUC__
+  __extension__         /* don't warn about "string length is greater than the length
+                   ISO C89 compilers are required to support" when including
+                   the following XPM file... */
+# endif
+#include "../images/dymaxionmap.xpm"
+#include "../images/ground.xpm"
+
+#include "xpm-ximage.h"
+#include "rotator.h"
+#include "gltrackball.h"
+
+
+typedef struct {
+  GLXContext *glx_context;
+  GLuint starlist;
+  int starcount;
+  rotator *rot;
+  trackball_state *trackball;
+  Bool button_down_p;
+  enum { STARTUP, FLAT, FOLD, 
+         ICO, STEL_IN, AXIS, SPIN, STEL, STEL_OUT,
+         ICO2, UNFOLD } state;
+  GLfloat ratio;
+  GLuint tex1, tex2;
+  texture_font_data *font_data;
+} planetstruct;
+
+
+static planetstruct *planets = NULL;
+
+
+/* Set up and enable texturing on our object */
+static void
+setup_xpm_texture (ModeInfo *mi, char **xpm_data)
+{
+  XImage *image = xpm_to_ximage (MI_DISPLAY (mi), MI_VISUAL (mi),
+                                 MI_COLORMAP (mi), xpm_data);
+  char buf[1024];
+  clear_gl_error();
+  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
+              image->width, image->height, 0,
+              GL_RGBA,
+              /* GL_UNSIGNED_BYTE, */
+              GL_UNSIGNED_INT_8_8_8_8_REV,
+              image->data);
+  sprintf (buf, "builtin texture (%dx%d)", image->width, image->height);
+  check_gl_error(buf);
+
+  /* setup parameters for texturing */
+  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+}
+
+
+static void
+setup_file_texture (ModeInfo *mi, char *filename)
+{
+  Display *dpy = mi->dpy;
+  Visual *visual = mi->xgwa.visual;
+  char buf[1024];
+
+  Colormap cmap = mi->xgwa.colormap;
+  XImage *image = xpm_file_to_ximage (dpy, visual, cmap, filename);
+  clear_gl_error();
+  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
+              image->width, image->height, 0,
+              GL_RGBA,
+              /* GL_UNSIGNED_BYTE, */
+              GL_UNSIGNED_INT_8_8_8_8_REV,
+              image->data);
+  sprintf (buf, "texture: %.100s (%dx%d)",
+          filename, image->width, image->height);
+  check_gl_error(buf);
+
+  /* setup parameters for texturing */
+  glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+  glPixelStorei(GL_UNPACK_ROW_LENGTH, image->width);
+
+  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+}
+
+
+static void
+setup_texture(ModeInfo * mi)
+{
+  planetstruct *gp = &planets[MI_SCREEN(mi)];
+
+  if (!which_image ||
+      !*which_image ||
+      !strcmp(which_image, "BUILTIN"))
+    {
+      glGenTextures (1, &gp->tex1);
+      glBindTexture (GL_TEXTURE_2D, gp->tex1);
+      setup_xpm_texture (mi, dymaxionmap_xpm);
+    }
+  else
+    {
+      glGenTextures (1, &gp->tex1);
+      glBindTexture (GL_TEXTURE_2D, gp->tex1);
+      setup_file_texture (mi, which_image);
+    }
+
+  glGenTextures (1, &gp->tex2);
+  glBindTexture (GL_TEXTURE_2D, gp->tex2);
+  setup_xpm_texture (mi, ground);
+
+  check_gl_error("texture initialization");
+
+  /* Need to flip the texture top for bottom for some reason. */
+  glMatrixMode (GL_TEXTURE);
+  glScalef (1, -1, 1);
+  glMatrixMode (GL_MODELVIEW);
+}
+
+
+static void
+init_stars (ModeInfo *mi)
+{
+  planetstruct *gp = &planets[MI_SCREEN(mi)];
+  int i, j;
+  int width  = MI_WIDTH(mi);
+  int height = MI_HEIGHT(mi);
+  int size = (width > height ? width : height);
+  int nstars = size * size / 80;
+  int max_size = 3;
+  GLfloat inc = 0.5;
+  int steps = max_size / inc;
+
+  gp->starlist = glGenLists(1);
+  glNewList(gp->starlist, GL_COMPILE);
+  for (j = 1; j <= steps; j++)
+    {
+      glPointSize(inc * j);
+      glBegin (GL_POINTS);
+      for (i = 0; i < nstars / steps; i++)
+       {
+         GLfloat d = 0.1;
+         GLfloat r = 0.15 + frand(0.3);
+         GLfloat g = r + frand(d) - d;
+         GLfloat b = r + frand(d) - d;
+
+         GLfloat x = frand(1)-0.5;
+         GLfloat y = frand(1)-0.5;
+         GLfloat z = ((random() & 1)
+                      ? frand(1)-0.5
+                      : (BELLRAND(1)-0.5)/12);   /* milky way */
+         d = sqrt (x*x + y*y + z*z);
+         x /= d;
+         y /= d;
+         z /= d;
+         glColor3f (r, g, b);
+         glVertex3f (x, y, z);
+         gp->starcount++;
+       }
+      glEnd ();
+    }
+  glEndList ();
+
+  check_gl_error("stars initialization");
+}
+
+
+ENTRYPOINT void
+reshape_planet (ModeInfo *mi, int width, int height)
+{
+  GLfloat h = (GLfloat) height / (GLfloat) width;
+
+  glViewport(0, 0, (GLint) width, (GLint) height);
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  glFrustum(-1.0, 1.0, -h, h, 5.0, 100.0);
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+  glTranslatef(0.0, 0.0, -40);
+
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (h, h, h);
+  }
+# endif
+
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+}
+
+
+static void
+do_normal2 (Bool frontp, XYZ a, XYZ b, XYZ c)
+{
+  if (frontp)
+    do_normal (a.x, a.y, a.z,
+               b.x, b.y, b.z,
+               c.x, c.y, c.z);
+  else
+    do_normal (b.x, b.y, b.z,
+               a.x, a.y, a.z,
+               c.x, c.y, c.z);
+}
+
+
+static void
+triangle0 (ModeInfo *mi, Bool frontp, GLfloat stel_ratio, int bitmask)
+{
+  /* Render a triangle as six sub-triangles:
+
+                A
+               / \
+              / | \
+             /  |  \
+            / 0 | 1 \
+        E  /_   |   _\  F
+          /  \_ | _/  \
+         / 5   \D/   2 \
+        /    /  |  \    \
+       /   / 4  | 3  \   \
+      /  /      |       \ \
+   B ----------------------- C
+                G
+   */
+
+  Bool wire = MI_IS_WIREFRAME(mi);
+  GLfloat h = sqrt(3) / 2;
+  GLfloat h2 = sqrt(h*h - (h/2)*(h/2)) - 0.5;
+  XYZ  A,  B,  C,  D,  E,  F,  G;
+  XYZ tA, tB, tC, tD, tE, tF, tG;
+  XYZ  a,  b,  c;
+  XYZ ta, tb, tc;
+  A.x =  0;   A.y = h;   A.z = 0;
+  B.x = -0.5, B.y = 0;   B.z = 0;
+  C.x =  0.5, C.y = 0;   C.z = 0;
+  D.x =  0;   D.y = h/3; D.z = 0;
+  E.x = -h2;  E.y = h/2; E.z = 0;
+  F.x =  h2;  F.y = h/2; F.z = 0;
+  G.x =  0;   G.y = 0;   G.z = 0;
+
+  /* When tweaking object XY to stellate, don't change texture coordinates. */
+  tA = A; tB = B; tC = C; tD = D; tE = E; tF = F; tG = G;
+
+  /* Eyeballed this to find the depth of stellation that seems to most
+     approximate a sphere.
+   */
+  D.z = 0.193 * stel_ratio;
+
+  /* We want to raise E, F and G as well but we can't just shift Z:
+     we need to keep them on the same vector from the center of the sphere,
+     which means also changing F and G's X and Y.
+  */
+  E.z = F.z = G.z = 0.132 * stel_ratio;
+  {
+    double magic_x = 0.044;
+    double magic_y = 0.028;
+    /* G.x stays 0 */
+    G.y -= sqrt (magic_x*magic_x + magic_y*magic_y) * stel_ratio;
+    E.x -= magic_x * stel_ratio;
+    E.y += magic_y * stel_ratio;
+    F.x += magic_x * stel_ratio;
+    F.y += magic_y * stel_ratio;
+  }
+
+
+  if (bitmask & 1<<0)
+    {
+      glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLES);
+      a  =  E;  b =  D;  c =  A;
+      ta = tE; tb = tD; tc = tA;
+      do_normal2 (frontp, a, b, c);
+      glTexCoord2f (ta.x, ta.y); glVertex3f (a.x, a.y, a.z);
+      glTexCoord2f (tb.x, tb.y); glVertex3f (b.x, b.y, b.z);
+      glTexCoord2f (tc.x, tc.y); glVertex3f (c.x, c.y, c.z);
+      glEnd();
+      mi->polygon_count++;
+    }
+  if (bitmask & 1<<1)
+    {
+      glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLES);
+      a  =  D;  b =  F;  c =  A;
+      ta = tD; tb = tF; tc = tA;
+      do_normal2 (frontp, a, b, c);
+      glTexCoord2f (ta.x, ta.y); glVertex3f (a.x, a.y, a.z);
+      glTexCoord2f (tb.x, tb.y); glVertex3f (b.x, b.y, b.z);
+      glTexCoord2f (tc.x, tc.y); glVertex3f (c.x, c.y, c.z);
+      glEnd();
+      mi->polygon_count++;
+    }
+  if (bitmask & 1<<2)
+    {
+      glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLES);
+      a  =  D;  b =  C;  c =  F;
+      ta = tD; tb = tC; tc = tF;
+      do_normal2 (frontp, a, b, c);
+      glTexCoord2f (ta.x, ta.y); glVertex3f (a.x, a.y, a.z);
+      glTexCoord2f (tb.x, tb.y); glVertex3f (b.x, b.y, b.z);
+      glTexCoord2f (tc.x, tc.y); glVertex3f (c.x, c.y, c.z);
+      glEnd();
+      mi->polygon_count++;
+    }
+  if (bitmask & 1<<3)
+    {
+      glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLES);
+      a  =  G;  b =  C;  c =  D;
+      ta = tG; tb = tC; tc = tD;
+      do_normal2 (frontp, a, b, c);
+      glTexCoord2f (ta.x, ta.y); glVertex3f (a.x, a.y, a.z);
+      glTexCoord2f (tb.x, tb.y); glVertex3f (b.x, b.y, b.z);
+      glTexCoord2f (tc.x, tc.y); glVertex3f (c.x, c.y, c.z);
+      glEnd();
+      mi->polygon_count++;
+    }
+  if (bitmask & 1<<4)
+    {
+      glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLES);
+      a  =  B;  b =  G;  c =  D;
+      ta = tB; tb = tG; tc = tD;
+      do_normal2 (frontp, a, b, c);
+      glTexCoord2f (ta.x, ta.y); glVertex3f (a.x, a.y, a.z);
+      glTexCoord2f (tb.x, tb.y); glVertex3f (b.x, b.y, b.z);
+      glTexCoord2f (tc.x, tc.y); glVertex3f (c.x, c.y, c.z);
+      glEnd();
+      mi->polygon_count++;
+    }
+  if (bitmask & 1<<5)
+    {
+      glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLES);
+      a  =  B;  b =  D;  c =  E;
+      ta = tB; tb = tD; tc = tE;
+      do_normal2 (frontp, a, b, c);
+      glTexCoord2f (ta.x, ta.y); glVertex3f (a.x, a.y, a.z);
+      glTexCoord2f (tb.x, tb.y); glVertex3f (b.x, b.y, b.z);
+      glTexCoord2f (tc.x, tc.y); glVertex3f (c.x, c.y, c.z);
+      glEnd();
+      mi->polygon_count++;
+    }
+  if (bitmask & 1<<6)
+    {
+      glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLES);
+      a  =  E;  b =  D;  c =  A;
+      ta = tE; tb = tD; tc = tA;
+      do_normal2 (frontp, a, b, c);
+      glTexCoord2f (ta.x, ta.y); glVertex3f (a.x, a.y, a.z);
+      glTexCoord2f (tb.x, tb.y); glVertex3f (b.x, b.y, b.z);
+      glTexCoord2f (tc.x, tc.y); glVertex3f (c.x, c.y, c.z);
+      glEnd();
+      mi->polygon_count++;
+    }
+}
+
+
+/* The segments, numbered arbitrarily from the top left:
+             ________         _      ________
+             \      /\      /\ \    |\      /
+              \ 0  /  \    /  \3>   | \ 5  /
+               \  / 1  \  / 2  \| ..|4 \  /-6-..
+     ___________\/______\/______\/______\/______\
+    |   /\      /\      /\      /\      /\   
+    |7 /  \ 9  /  \ 11 /  \ 13 /  \ 15 /  \  
+    | / 8  \  / 10 \  / 12 \  / 14 \  / 16 \ 
+    |/______\/______\/______\/______\/______\
+     \      /\      /       /\      /\
+      \ 17 /  \ 18 /       /  \ 20 /  \
+       \  /    \  /       / 19 \  / 21 \
+        \/      \/       /______\/______\
+
+   Each triangle can be connected to at most two other triangles.
+   We start from the middle, #12, and work our way to the edges.
+   Its centroid is 0,0.
+ */
+static void
+triangle (ModeInfo *mi, int which, Bool frontp, 
+          GLfloat fold_ratio, GLfloat stel_ratio)
+{
+  planetstruct *gp = &planets[MI_SCREEN(mi)];
+  const GLfloat fg[3] = { 1, 1, 1 };
+  const GLfloat bg[3] = { 0.3, 0.3, 0.3 };
+  int a = -1, b = -1;
+  GLfloat max = acos (sqrt(5)/3);
+  GLfloat rot = -max * fold_ratio / (M_PI/180);
+  Bool wire = MI_IS_WIREFRAME(mi);
+
+  if (wire)
+    glColor3fv (fg);
+
+  switch (which) {
+  case 3:                              /* One third of the face. */
+    triangle0 (mi, frontp, stel_ratio, 1<<3 | 1<<4);
+    break;
+  case 4:                              /* Two thirds of the face: convex. */
+    triangle0 (mi, frontp, stel_ratio, 1<<1 | 1<<2 | 1<<3 | 1<<4);
+    break;
+  case 6:                              /* One half of the face. */
+    triangle0 (mi, frontp, stel_ratio, 1<<1 | 1<<2 | 1<<3);
+    break;
+  case 7:                              /* One half of the face. */
+    triangle0 (mi, frontp, stel_ratio, 1<<2 | 1<<3 | 1<<4);
+    break;
+  default:                             /* Full face. */
+    triangle0 (mi, frontp, stel_ratio, 0x3F);
+    break;
+  }
+
+  if (wire)
+    {
+      char tag[20];
+      glColor3fv (bg);
+      sprintf (tag, "%d", which);
+      glPushMatrix();
+      glTranslatef (-0.1, 0.2, 0);
+      glScalef (0.005, 0.005, 0.005);
+      print_texture_string (gp->font_data, tag);
+      glPopMatrix();
+      mi->polygon_count++;
+    }
+
+
+  /* The connection hierarchy of the faces starting at the middle, #12. */
+  switch (which) {
+  case  0: break;
+  case  1: a =  0; b = -1; break;
+  case  2: a = -1; b =  3; break;
+  case  3: break;
+  case  4: a = -1; b =  5; break;
+  case  5: a = -1; b =  6; break;
+  case  7: break;
+  case  6: break;
+  case  8: a = 17; b =  7; break;
+  case  9: a =  8; b = -1; break;
+  case 10: a = 18; b =  9; break;
+  case 11: a = 10; b =  1; break;
+  case 12: a = 11; b = 13; break;
+  case 13: a =  2; b = 14; break;
+  case 14: a = 15; b = 20; break;
+  case 15: a =  4; b = 16; break;
+  case 16: break;
+  case 17: break;
+  case 18: break;
+  case 19: break;
+  case 20: a = 21; b = 19; break;
+  case 21: break;
+  default: abort(); break;
+  }
+
+  if (a != -1)
+    {
+      glPushMatrix();
+      glTranslatef (-0.5, 0, 0);       /* Move model matrix to upper left */
+      glRotatef (60, 0, 0, 1);
+      glTranslatef ( 0.5, 0, 0);
+
+      glMatrixMode(GL_TEXTURE);
+      /* glPushMatrix(); */
+      glTranslatef (-0.5, 0, 0);       /* Move texture matrix the same way */
+      glRotatef (60, 0, 0, 1);
+      glTranslatef ( 0.5, 0, 0);
+
+      glMatrixMode(GL_MODELVIEW);
+
+      glRotatef (rot, 1, 0, 0);
+      triangle (mi, a, frontp, fold_ratio, stel_ratio);
+
+      /* This should just be a PopMatrix on the TEXTURE stack, but
+         fucking iOS has GL_MAX_TEXTURE_STACK_DEPTH == 4!  WTF!
+         So we have to undo our rotations and translations manually.
+       */
+      glMatrixMode(GL_TEXTURE);
+      /* glPopMatrix(); */
+      glTranslatef (-0.5, 0, 0);
+      glRotatef (-60, 0, 0, 1);
+      glTranslatef (0.5, 0, 0);
+
+      glMatrixMode(GL_MODELVIEW);
+      glPopMatrix();
+    }
+
+  if (b != -1)
+    {
+      glPushMatrix();
+      glTranslatef (0.5, 0, 0);                /* Move model matrix to upper right */
+      glRotatef (-60, 0, 0, 1);
+      glTranslatef (-0.5, 0, 0);
+
+      glMatrixMode(GL_TEXTURE);
+      /* glPushMatrix(); */
+      glTranslatef (0.5, 0, 0);                /* Move texture matrix the same way */
+      glRotatef (-60, 0, 0, 1);
+      glTranslatef (-0.5, 0, 0);
+
+      glMatrixMode(GL_MODELVIEW);
+
+      glRotatef (rot, 1, 0, 0);
+      triangle (mi, b, frontp, fold_ratio, stel_ratio);
+
+      /* See above. Grr. */
+      glMatrixMode(GL_TEXTURE);
+      /* glPopMatrix(); */
+      glTranslatef (0.5, 0, 0);
+      glRotatef (60, 0, 0, 1);
+      glTranslatef (-0.5, 0, 0);
+
+      glMatrixMode(GL_MODELVIEW);
+      glPopMatrix();
+    }
+}
+
+
+static void
+draw_triangles (ModeInfo *mi, GLfloat fold_ratio, GLfloat stel_ratio)
+{
+  planetstruct *gp = &planets[MI_SCREEN(mi)];
+  Bool wire = MI_IS_WIREFRAME(mi);
+  GLfloat h = sqrt(3) / 2;
+  GLfloat c = h / 3;
+
+  glTranslatef (0, -h/3, 0);  /* Center on face 12 */
+
+  /* When closed, center on midpoint of icosahedron. Eyeballed this. */
+  glTranslatef (0, 0, fold_ratio * 0.754);
+
+  glFrontFace (GL_CCW);
+
+  /* Adjust the texture matrix so that it has the same coordinate space
+     as the model. */
+
+  glMatrixMode(GL_TEXTURE);
+  glPushMatrix();
+  {
+    GLfloat texw = 5.5;
+    GLfloat texh = 3 * h;
+    GLfloat midx = 2.5;
+    GLfloat midy = 3 * c;
+    glScalef (1/texw, -1/texh, 1);
+    glTranslatef (midx, midy, 0);
+  }
+  glMatrixMode(GL_MODELVIEW);
+
+
+
+  /* Front faces */
+
+  if (wire)
+    glDisable (GL_TEXTURE_2D);
+  else if (do_texture)
+    {
+      glEnable (GL_TEXTURE_2D);
+      glBindTexture (GL_TEXTURE_2D, gp->tex1);
+    }
+  else
+    glDisable (GL_TEXTURE_2D);
+
+  triangle (mi, 12, True, fold_ratio, stel_ratio);
+
+  /* Back faces */
+
+  if (wire)
+    glDisable (GL_TEXTURE_2D);
+  else if (do_texture)
+    {
+      glEnable (GL_TEXTURE_2D);
+      glBindTexture (GL_TEXTURE_2D, gp->tex2);
+    }
+  else
+    glDisable (GL_TEXTURE_2D);
+
+  glFrontFace (GL_CW);
+
+  triangle (mi, 12, False, fold_ratio, 0);
+
+  glMatrixMode(GL_TEXTURE);
+  glPopMatrix();
+  glMatrixMode(GL_MODELVIEW);
+}
+
+
+static void
+align_axis (ModeInfo *mi, int undo)
+{
+  /* Rotate so that an axis is lined up with the north and south poles
+     on the map, which are not in the center of their faces, or any
+     other easily computable spot. */
+
+  GLfloat r1 = 20.5;
+  GLfloat r2 = 28.5;
+
+  if (undo)
+    {
+      glRotatef (-r2, 0, 1, 0);
+      glRotatef ( r2, 1, 0, 0);
+      glRotatef (-r1, 1, 0, 0);
+    }
+  else
+    {
+      glRotatef (r1, 1, 0, 0);
+      glRotatef (-r2, 1, 0, 0);
+      glRotatef ( r2, 0, 1, 0);
+    }
+}
+
+
+static void
+draw_axis (ModeInfo *mi)
+{
+  GLfloat s;
+  glDisable (GL_TEXTURE_2D);
+  glDisable (GL_LIGHTING);
+  glPushMatrix();
+
+  align_axis (mi, 0);
+  glTranslatef (0.34, 0.39, -0.61);
+
+  s = 0.96;
+  glScalef (s, s, s);   /* tighten up the enclosing sphere */
+
+  glColor3f (0.5, 0.5, 0);
+
+  glRotatef (90,  1, 0, 0);    /* unit_sphere is off by 90 */
+  glRotatef (9.5, 0, 1, 0);    /* line up the time zones */
+  glFrontFace (GL_CCW);
+  unit_sphere (12, 24, True);
+  glBegin(GL_LINES);
+  glVertex3f(0, -2, 0);
+  glVertex3f(0,  2, 0);
+  glEnd();
+
+  glPopMatrix();
+}
+
+
+
+
+ENTRYPOINT Bool
+planet_handle_event (ModeInfo *mi, XEvent *event)
+{
+  planetstruct *gp = &planets[MI_SCREEN(mi)];
+
+  if (gltrackball_event_handler (event, gp->trackball,
+                                MI_WIDTH (mi), MI_HEIGHT (mi),
+                                &gp->button_down_p))
+    return True;
+  else if (event->xany.type == KeyPress)
+    {
+      KeySym keysym;
+      char c = 0;
+      XLookupString (&event->xkey, &c, 1, &keysym, 0);
+      if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
+        {
+          switch (gp->state) {
+          case FLAT: case ICO: case STEL: case AXIS: case ICO2:
+            gp->ratio = 1;
+            break;
+          default:
+            break;
+          }
+          return True;
+        }
+    }
+
+  return False;
+}
+
+
+ENTRYPOINT void
+init_planet (ModeInfo * mi)
+{
+  planetstruct *gp;
+  int screen = MI_SCREEN(mi);
+  Bool wire = MI_IS_WIREFRAME(mi);
+
+  if (planets == NULL) {
+    if ((planets = (planetstruct *) calloc(MI_NUM_SCREENS(mi),
+                                         sizeof (planetstruct))) == NULL)
+      return;
+  }
+  gp = &planets[screen];
+
+  if ((gp->glx_context = init_GL(mi)) != NULL) {
+    reshape_planet(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+  }
+
+  gp->state = STARTUP;
+  gp->ratio = 0;
+  gp->font_data = load_texture_font (mi->dpy, "labelFont");
+
+  {
+    double spin_speed  = 0.1;
+    double wander_speed = 0.002;
+    gp->rot = make_rotator (do_roll ? spin_speed : 0,
+                           do_roll ? spin_speed : 0,
+                           0, 1,
+                           do_wander ? wander_speed : 0,
+                           False);
+    gp->trackball = gltrackball_init (True);
+  }
+
+  if (wire)
+    do_texture = False;
+
+  if (do_texture)
+    setup_texture (mi);
+
+  if (do_stars)
+    init_stars (mi);
+
+  glEnable (GL_DEPTH_TEST);
+  glEnable (GL_NORMALIZE);
+  glEnable (GL_CULL_FACE);
+
+  if (!wire)
+    {
+      GLfloat pos[4] = {0.4, 0.2, 0.4, 0.0};
+      GLfloat amb[4] = {0.4, 0.4, 0.4, 1.0};
+      GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0};
+      GLfloat spc[4] = {1.0, 1.0, 1.0, 1.0};
+
+      glEnable(GL_LIGHTING);
+      glEnable(GL_LIGHT0);
+      glLightfv(GL_LIGHT0, GL_POSITION, pos);
+      glLightfv(GL_LIGHT0, GL_AMBIENT, amb);
+      glLightfv(GL_LIGHT0, GL_DIFFUSE, dif);
+      glLightfv(GL_LIGHT0, GL_SPECULAR, spc);
+    }
+}
+
+
+static GLfloat
+ease_fn (GLfloat r)
+{
+  return cos ((r/2 + 1) * M_PI) + 1; /* Smooth curve up, end at slope 1. */
+}
+
+
+static GLfloat
+ease_ratio (GLfloat r)
+{
+  GLfloat ease = 0.35;
+  if      (r <= 0)     return 0;
+  else if (r >= 1)     return 1;
+  else if (r <= ease)  return     ease * ease_fn (r / ease);
+  else if (r > 1-ease) return 1 - ease * ease_fn ((1 - r) / ease);
+  else                 return r;
+}
+
+
+ENTRYPOINT void
+draw_planet (ModeInfo * mi)
+{
+  planetstruct *gp = &planets[MI_SCREEN(mi)];
+  int wire = MI_IS_WIREFRAME(mi);
+  Display *dpy = MI_DISPLAY(mi);
+  Window window = MI_WINDOW(mi);
+  double x, y, z;
+
+  if (!gp->glx_context)
+    return;
+
+  glDrawBuffer(GL_BACK);
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  glXMakeCurrent (dpy, window, *(gp->glx_context));
+
+  mi->polygon_count = 0;
+
+  if (! gp->button_down_p)
+    switch (gp->state) {
+    case STARTUP:  gp->ratio += speed * 0.01;  break;
+    case FLAT:     gp->ratio += speed * 0.005; break;
+    case FOLD:     gp->ratio += speed * 0.01;  break;
+    case ICO:      gp->ratio += speed * 0.01;  break;
+    case STEL_IN:  gp->ratio += speed * 0.05;  break;
+    case STEL:     gp->ratio += speed * 0.01;  break;
+    case STEL_OUT: gp->ratio += speed * 0.07;  break;
+    case ICO2:     gp->ratio += speed * 0.07;  break;
+    case AXIS:     gp->ratio += speed * 0.02;  break;
+    case SPIN:     gp->ratio += speed * 0.005; break;
+    case UNFOLD:   gp->ratio += speed * 0.01;  break;
+    default:       abort();
+    }
+
+  if (gp->ratio > 1.0)
+    {
+      gp->ratio = 0;
+      switch (gp->state) {
+      case STARTUP:  gp->state = FLAT;     break;
+      case FLAT:     gp->state = FOLD;     break;
+      case FOLD:     gp->state = ICO;      break;
+      case ICO:      gp->state = STEL_IN;  break;
+      case STEL_IN:  gp->state = STEL;     break;
+      case STEL:
+        {
+          int i = (random() << 9) % 7;
+          gp->state = (i < 3 ? STEL_OUT :
+                       i < 6 ? SPIN : AXIS);
+        }
+        break;
+      case AXIS:     gp->state = STEL_OUT; break;
+      case SPIN:     gp->state = STEL_OUT; break;
+      case STEL_OUT: gp->state = ICO2;     break;
+      case ICO2:     gp->state = UNFOLD;   break;
+      case UNFOLD:   gp->state = FLAT;     break;
+      default:       abort();
+      }
+    }
+
+  glEnable(GL_LINE_SMOOTH);
+  glEnable(GL_POINT_SMOOTH);
+  glEnable(GL_DEPTH_TEST);
+  glEnable(GL_CULL_FACE);
+  glCullFace(GL_BACK); 
+
+  glPushMatrix();
+
+  gltrackball_rotate (gp->trackball);
+  glRotatef (current_device_rotation(), 0, 0, 1);
+
+  if (gp->state != STARTUP)
+    {
+      get_position (gp->rot, &x, &y, &z, !gp->button_down_p);
+      x = (x - 0.5) * 3;
+      y = (y - 0.5) * 3;
+      z = 0;
+      glTranslatef(x, y, z);
+    }
+
+  if (do_roll && gp->state != STARTUP)
+    {
+      get_rotation (gp->rot, &x, &y, 0, !gp->button_down_p);
+      glRotatef (x * 360, 1.0, 0.0, 0.0);
+      glRotatef (y * 360, 0.0, 1.0, 0.0);
+    }
+
+  if (do_stars)
+    {
+      glDisable(GL_TEXTURE_2D);
+      glDisable(GL_LIGHTING);
+      glPushMatrix();
+      glScalef (60, 60, 60);
+      glRotatef (90, 1, 0, 0);
+      glRotatef (35, 1, 0, 0);
+      glCallList (gp->starlist);
+      mi->polygon_count += gp->starcount;
+      glPopMatrix();
+      glClear(GL_DEPTH_BUFFER_BIT);
+    }
+
+  if (! wire)
+    glEnable (GL_LIGHTING);
+
+  if (do_texture)
+    glEnable(GL_TEXTURE_2D);
+
+  glScalef (2.6, 2.6, 2.6);
+
+  {
+    GLfloat fold_ratio = 0;
+    GLfloat stel_ratio = 0;
+    switch (gp->state) {
+    case FOLD:     fold_ratio =     gp->ratio; break;
+    case UNFOLD:   fold_ratio = 1 - gp->ratio; break;
+    case ICO: case ICO2: fold_ratio = 1; break;
+    case STEL: case AXIS: case SPIN: fold_ratio = 1; stel_ratio = 1; break;
+    case STEL_IN:  fold_ratio = 1; stel_ratio = gp->ratio; break;
+    case STEL_OUT: fold_ratio = 1; stel_ratio = 1 - gp->ratio; break;
+    case STARTUP:      /* Tilt in from flat */
+      glRotatef (-90 * ease_ratio (1 - gp->ratio), 1, 0, 0);
+      break;
+
+    default: break;
+    }
+
+# ifdef HAVE_MOBILE  /* Enlarge the icosahedron a bit to make it more visible */
+    {
+      GLfloat s = 1 + 1.3 * ease_ratio (fold_ratio);
+      glScalef (s, s, s);
+    }
+# endif
+
+    if (gp->state == SPIN)
+      {
+        align_axis (mi, 0);
+        glRotatef (ease_ratio (gp->ratio) * 360 * 3, 0, 0, 1);
+        align_axis (mi, 1);
+      }
+
+    draw_triangles (mi, ease_ratio (fold_ratio), ease_ratio (stel_ratio));
+
+    if (gp->state == AXIS)
+      draw_axis(mi);
+  }
+
+  glPopMatrix();
+
+  if (mi->fps_p) do_fps (mi);
+  glFinish();
+  glXSwapBuffers(dpy, window);
+}
+
+
+ENTRYPOINT void
+release_planet (ModeInfo * mi)
+{
+  if (planets != NULL) {
+    int screen;
+
+    for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
+      planetstruct *gp = &planets[screen];
+
+      if (gp->glx_context) {
+       /* Display lists MUST be freed while their glXContext is current. */
+       /* but this gets a BadMatch error. -jwz */
+       /*glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(gp->glx_context));*/
+
+       if (glIsList(gp->starlist))
+         glDeleteLists(gp->starlist, 1);
+      }
+    }
+    (void) free((void *) planets);
+    planets = NULL;
+  }
+  FreeAllGL(mi);
+}
+
+
+XSCREENSAVER_MODULE_2 ("DymaxionMap", dymaxionmap, planet)
+
+#endif
diff --git a/hacks/glx/dymaxionmap.man b/hacks/glx/dymaxionmap.man
new file mode 100644 (file)
index 0000000..e08b23f
--- /dev/null
@@ -0,0 +1,70 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+dymaxionmap - An animation of Buckminster Fuller's unwrapped icosahedral globe.
+.SH SYNOPSIS
+.B dymaxionmap
+[\-display \fIhost:display.screen\fP]
+[\-visual \fIvisual\fP]
+[\-window]
+[\-root]
+[\-delay \fInumber\fP]
+[\-no-wander]
+[\-no-roll]
+[\-no-stars]
+[\-wireframe]
+[\-fps]
+.SH DESCRIPTION
+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.
+.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 \-wander | \-no-wander
+Whether the object should wander around the screen.
+.TP 8
+.B \-roll | \-no-roll
+Whether the object should roll randomly.
+.TP 8
+.B \-stars | \-no-stars
+Whether to display a star field.
+.TP 8
+.B \-wireframe | \-no-wireframe
+Render in wireframe instead of solid.
+.TP 8
+.B \-fps | \-no-fps
+Whether to show a frames-per-second display at the bottom 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 2016 by Jamie Zawinski.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski.
diff --git a/hacks/glx/energystream.c b/hacks/glx/energystream.c
new file mode 100644 (file)
index 0000000..642a1a1
--- /dev/null
@@ -0,0 +1,546 @@
+/* energystream, Copyright (c) 2016 Eugene Sandulenko <sev@scummvm.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.
+ *
+ * Based on Public Domain code by konrad "yoghurt" zagorowicz
+ * for Tesla demo by Sunflower (http://www.pouet.net/prod.php?which=33)
+ */
+
+#define DEFAULTS  "*delay:  30000       \n" \
+      "*count:        30          \n" \
+      "*showFPS:      False       \n" \
+      "*wireframe:    False       \n" \
+
+# define refresh_stream 0
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+#include "xlockmore.h"
+#include "gltrackball.h"
+#include "rotator.h"
+#include <ctype.h>
+
+#ifdef USE_GL /* whole file */
+
+static float change_time = 0;
+static float change_time1 = 25;
+static float change_time2 = 40;
+static float change_time3 = 60;
+
+#define DEF_STREAMS     "16"
+
+#include <sys/time.h>
+#include <time.h>
+
+typedef struct timeval streamtime;
+
+#define GETSECS(t) ((t).tv_sec)
+#define GETMSECS(t) ((t).tv_usec/1000)
+
+#define DEF_SPIN        "False"
+#define DEF_WANDER      "False"
+#define DEF_SPEED       "1.0"
+
+
+typedef struct {
+  float x, y, z;
+} Vector;
+
+typedef struct {
+  Vector *flares;
+  int num_flares;
+  GLuint flare_tex;
+  float speed;
+} flare_stream;
+
+typedef struct {
+  GLXContext *glx_context;
+  rotator *rot;
+  trackball_state *trackball;
+  Bool button_down_p;
+
+  time_t start_time;
+
+  int num_streams;
+  flare_stream *streams;
+
+} stream_configuration;
+
+static stream_configuration *ess = NULL;
+
+static int num_streams;
+static Bool do_spin;
+static GLfloat global_speed;
+static Bool do_wander;
+
+static XrmOptionDescRec opts[] = {
+  { "-streams",  ".streams",  XrmoptionSepArg, 0 },
+  { "-spin",   ".spin",   XrmoptionNoArg, "True" },
+  { "+spin",   ".spin",   XrmoptionNoArg, "False" },
+  { "-speed",  ".speed",  XrmoptionSepArg, 0 },
+  { "-wander", ".wander", XrmoptionNoArg, "True" },
+  { "+wander", ".wander", XrmoptionNoArg, "False" }
+};
+
+static argtype vars[] = {
+  {&num_streams, "streams",  "Streams",  DEF_STREAMS,  t_Int},
+  {&do_spin,   "spin",   "Spin",   DEF_SPIN,   t_Bool},
+  {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool},
+  {&global_speed, "speed",  "Speed",  DEF_SPEED,  t_Float},
+};
+
+ENTRYPOINT ModeSpecOpt stream_opts = {countof(opts), opts, countof(vars), vars, NULL};
+
+static void gettime(streamtime *t)
+{
+#ifdef GETTIMEOFDAY_TWO_ARGS
+        struct timezone tzp;
+        gettimeofday(t, &tzp);
+#else /* !GETTIMEOFDAY_TWO_ARGS */
+        gettimeofday(t);
+#endif /* !GETTIMEOFDAY_TWO_ARGS */
+}
+
+
+/* Window management, etc
+ */
+ENTRYPOINT void
+reshape_stream (ModeInfo *mi, int width, int height)
+{
+  GLfloat h = (GLfloat) height / (GLfloat) width;
+
+  glViewport (0, 0, (GLint) width, (GLint) height);
+
+  glMatrixMode (GL_PROJECTION);
+  glLoadIdentity ();
+  gluPerspective (30.0, 1/h, 1.0, 100.0);
+
+  glMatrixMode (GL_MODELVIEW);
+  glLoadIdentity ();
+  gluLookAt (0.0, 0.0, 30.0,
+             0.0, 0.0, 0.0,
+             0.0, 1.0, 0.0);
+
+  glClear (GL_COLOR_BUFFER_BIT);
+}
+
+
+ENTRYPOINT Bool
+stream_handle_event (ModeInfo *mi, XEvent *event)
+{
+  stream_configuration *es = &ess[MI_SCREEN(mi)];
+
+  if (gltrackball_event_handler (event, es->trackball,
+                                 MI_WIDTH (mi), MI_HEIGHT (mi),
+                                 &es->button_down_p))
+    return True;
+
+  return False;
+}
+
+#define TEX_WIDTH 256
+#define TEX_HEIGHT 256
+#define COEFF 0.2
+
+static GLuint gen_texture (void)
+{
+    int x, y, i;
+    float color;
+    GLuint tex;
+
+    unsigned char *texture = (unsigned char *)calloc (TEX_WIDTH * TEX_HEIGHT, 4);
+    unsigned char *ptr = texture;
+
+    float tint[3];
+    for (i = 0; i < 3; i++)
+      tint[i] = 1.0 * random() / RAND_MAX;
+
+    for (y = 0; y < TEX_HEIGHT; y++) {
+        for (x = 0; x < TEX_WIDTH; x++) {
+            color = 255 - sqrt((x - TEX_WIDTH / 2) * (x - TEX_WIDTH / 2) / COEFF
+                        + (y - TEX_HEIGHT / 2) * (y - TEX_HEIGHT / 2) / COEFF);
+
+            if (color < 0)
+                color = 0;
+
+            for (i = 0; i < 3; i++)
+                ptr[i] = (unsigned char)(color * tint[i]);
+            ptr[3] = color ? 255 : 0;
+
+            ptr += 4;
+        }
+    }
+
+  glGenTextures (1, &tex);
+#ifdef HAVE_GLBINDTEXTURE
+  glBindTexture (GL_TEXTURE_2D, tex);
+#endif /* HAVE_GLBINDTEXTURE */
+  glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
+  clear_gl_error ();
+  glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, TEX_WIDTH, TEX_HEIGHT,
+      0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, texture);
+  check_gl_error ("texture");
+
+  /* Texture parameters, LINEAR scaling for better texture quality */
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  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_MIN_FILTER, GL_LINEAR);
+
+  free (texture);
+
+  return tex;
+}
+
+static inline void vector_copy (Vector *a, Vector *b)
+{
+  a->x = b->x;
+  a->y = b->y;
+  a->z = b->z;
+}
+
+/* a += b */
+static inline void vector_add (Vector *a, Vector *b)
+{
+  a->x += b->x;
+  a->y += b->y;
+  a->z += b->z;
+}
+
+/* a -= b */
+static inline void vector_sub (Vector *a, Vector *b)
+{
+  a->x -= b->x;
+  a->y -= b->y;
+  a->z -= b->z;
+}
+
+static void init_flare_stream (flare_stream *s, int num_flares, float bx, float by, float bz, float speed)
+{
+  int i;
+
+  s->flares = (Vector *) calloc (num_flares, sizeof (Vector));
+  s->num_flares = num_flares;
+  s->flare_tex = gen_texture();
+  s->speed = speed;
+
+  for (i = 0; i != s->num_flares; i++)
+  {
+    s->flares[i].x = -800.0f * random() / RAND_MAX - 1150 + bx;
+    s->flares[i].y =   10.0f * random() / RAND_MAX -   20 + by;
+    s->flares[i].z =   10.0f * random() / RAND_MAX -   20 + bz;
+  }
+}
+
+static void render_flare_stream (flare_stream *s, float cur_time, Vector *vx, Vector *vy, float alpha)
+{
+  float fMultipler = 1;
+  int i;
+
+  if (s->flare_tex == -1)
+    return;
+  if (!s->num_flares)
+    return;
+
+  if (cur_time < change_time)
+    return;
+
+  cur_time -= change_time;
+
+  glColor4f (1.0, 1, 1, alpha);
+#ifdef HAVE_GLBINDTEXTURE
+  glBindTexture (GL_TEXTURE_2D, s->flare_tex);
+#endif
+
+  glBegin (GL_QUADS);
+
+  if (cur_time + change_time > change_time1)
+  {
+    if (cur_time + change_time > change_time2)
+    {
+      fMultipler = 2.5;
+    }
+    else
+      fMultipler = 2;
+  }
+
+  for (i = 0; i != s->num_flares; i++)
+  {
+    Vector flare_pos;
+    Vector cc;
+
+    flare_pos.x = fmod (s->flares[i].x + cur_time * s->speed * fMultipler, 800) - 400;
+    flare_pos.y = s->flares[i].y + 2 * sin (cur_time * 7 + s->flares[i].x);
+    flare_pos.z = s->flares[i].z + 2 * cos (cur_time * 7 + i * 3.14);
+
+    glTexCoord2f (0, 0);
+    vector_copy  (&cc, &flare_pos);
+    vector_sub   (&cc, vx);
+    vector_add   (&cc, vy);
+    glVertex3fv  ((float *)&cc);
+
+    glTexCoord2f ( 1, 0 );
+    vector_copy  (&cc, &flare_pos);
+    vector_add   (&cc, vx);
+    vector_add   (&cc, vy);
+    glVertex3fv  ((float *)&cc);
+
+    glTexCoord2f ( 1, 1 );
+    vector_copy  (&cc, &flare_pos);
+    vector_add   (&cc, vx);
+    vector_sub   (&cc, vy);
+    glVertex3fv  ((float *)&cc);
+
+    glTexCoord2f ( 0, 1 );
+    vector_copy  (&cc, &flare_pos);
+    vector_sub   (&cc, vx);
+    vector_sub   (&cc, vy);
+    glVertex3fv  ((float *)&cc);
+  }
+
+  glEnd ();
+}
+
+ENTRYPOINT void
+init_stream (ModeInfo *mi)
+{
+  stream_configuration *es;
+  streamtime current_time;
+
+  if (!ess)
+  {
+    ess = (stream_configuration *)
+      calloc (MI_NUM_SCREENS(mi), sizeof (stream_configuration));
+    if (!ess)
+    {
+      fprintf (stderr, "%s: out of memory\n", progname);
+      exit (1);
+    }
+  }
+
+  es = &ess[MI_SCREEN(mi)];
+
+  es->glx_context = init_GL (mi);
+
+  reshape_stream (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+
+  gettime (&current_time);
+  es->start_time = GETSECS(current_time) * 1000 + GETMSECS(current_time);
+
+  es->num_streams = num_streams;
+
+  es->streams = (flare_stream *) calloc (es->num_streams, sizeof(flare_stream));
+
+  init_flare_stream (&es->streams[0], 150, 0, 50, 0, 300);
+  init_flare_stream (&es->streams[1], 150, 0, 0, 0, 150);
+  init_flare_stream (&es->streams[2], 150, 0, 90, 60, 250);
+  init_flare_stream (&es->streams[3], 150, 0, -100, 30, 160);
+  init_flare_stream (&es->streams[4], 150, 0, 50, -100, 340);
+  init_flare_stream (&es->streams[5], 150, 0, -50, 50, 270 );
+  init_flare_stream (&es->streams[6], 150, 0, 100, 50, 180);
+  init_flare_stream (&es->streams[7], 150, 0, -30, 90, 130);
+
+  init_flare_stream (&es->streams[8], 150, 0, 150, 10, 200);
+  init_flare_stream (&es->streams[9], 150, 0, 100, -100, 210);
+  init_flare_stream (&es->streams[10], 150, 0, 190, 160, 220);
+  init_flare_stream (&es->streams[11], 150, 0, -200, 130, 230);
+  init_flare_stream (&es->streams[12], 150, 0, 150, -200, 240);
+  init_flare_stream (&es->streams[13], 150, 0, -150, 250, 160);
+  init_flare_stream (&es->streams[14], 150, 0, 200, 150, 230);
+  init_flare_stream (&es->streams[15], 150, 0, -130, 190, 250);
+
+  {
+    double spin_speed   = 0.5  * global_speed;
+    double wander_speed = 0.02 * global_speed;
+    double spin_accel   = 1.1;
+
+    es->rot = make_rotator (do_spin ? spin_speed : 0,
+                            do_spin ? spin_speed : 0,
+                            do_spin ? spin_speed : 0,
+                            spin_accel,
+                            do_wander ? wander_speed : 0,
+                            True);
+    es->trackball = gltrackball_init (True);
+  }
+}
+
+ENTRYPOINT void
+release_stream (ModeInfo * mi)
+{
+  int screen;
+
+  for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
+  {
+    stream_configuration *es = &ess[screen];
+    int i;
+
+    for (i = 0; i < es->num_streams; i++) {
+      free (es->streams[i].flares);
+      glDeleteTextures (1, &es->streams[i].flare_tex);
+    }
+
+    free (es->streams);
+  }
+
+  FreeAllGL (mi);
+}
+
+
+static void inverse_matrix (float m[16]) {
+  double a,b,c,d,e,f,g,h,i,j,k,l;
+  register double dW;
+
+  a = m[ 0]; b = m[ 1]; c = m[ 2];
+  d = m[ 4]; e = m[ 5]; f = m[ 6];
+  g = m[ 8]; h = m[ 9]; i = m[10];
+  j = m[12]; k = m[13]; l = m[14];
+
+  dW = 1.0 / (a * (e * i - f * h)
+           - (b * (d * i - f * g)
+           +  c * (e * g - d * h)));
+
+  m[ 0]= (float)((e * i - f * h) * dW);
+  m[ 1]= (float)((c * h - b * i) * dW);
+  m[ 2]= (float)((b * f - c * e) * dW);
+
+  m[ 4]= (float)((f * g - d * i) * dW);
+  m[ 5]= (float)((a * i - c * g) * dW);
+  m[ 6]= (float)((c * d - a * f) * dW);
+
+  m[ 8]= (float)((d * h - e * g) * dW);
+  m[ 9]= (float)((b * g - a * h) * dW);
+  m[10]= (float)((a * e - b * d) * dW);
+
+  m[12]= (float)((e * (g * l - i * j)
+                + f * (h * j - g * k)
+                - d * (h * l - i * k)) * dW);
+  m[13]= (float)((a * (h * l - i * k)
+                + b * (i * j - g * l)
+                + c * (g * k - h * j)) * dW);
+  m[14]= (float)((b * (d * l - f * j)
+                + c * (e * j - d * k)
+                - a * (e * l - f * k)) * dW);
+}
+
+ENTRYPOINT void
+draw_stream (ModeInfo *mi)
+{
+  stream_configuration *es = &ess[MI_SCREEN(mi)];
+  Display *dpy = MI_DISPLAY(mi);
+  Window window = MI_WINDOW(mi);
+  streamtime current_time;
+  float cur_time;
+  int i;
+  float alpha = 1.0;
+  Vector vx;
+  Vector vy;
+  GLfloat m[4*4];
+
+  if (!es->glx_context)
+    return;
+
+  gettime (&current_time);
+
+  cur_time = (float)(GETSECS(current_time) * 1000 + GETMSECS(current_time) - es->start_time) / 1000.0;
+  cur_time *= global_speed;
+
+  glXMakeCurrent (MI_DISPLAY(mi), MI_WINDOW(mi), *(es->glx_context));
+
+  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  glMatrixMode (GL_PROJECTION);
+  glLoadIdentity ();
+  glFrustum (-.6f, .6f, -.45f, .45f, 1, 1000);
+
+  glMatrixMode (GL_MODELVIEW);
+  glLoadIdentity ();
+
+  glEnable (GL_LIGHTING);
+  glEnable (GL_TEXTURE_2D);
+  glEnable (GL_BLEND);
+  glBlendFunc (GL_SRC_ALPHA, GL_ONE);
+  glDisable (GL_CULL_FACE);
+  glDisable (GL_DEPTH_TEST);
+  glDepthMask (0);
+
+  glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
+
+  glTranslatef (0, 0, -300);
+  glRotatef (cur_time * 30, 1, 0, 0);
+  glRotatef (30 * sin(cur_time / 3) + 10, 0, 0, 1);
+
+  {
+    double x, y, z;
+    get_position (es->rot, &x, &y, &z, !es->button_down_p);
+    glTranslatef((x - 0.5) * 8,
+                 (y - 0.5) * 8,
+                 (z - 0.5) * 15);
+
+    gltrackball_rotate (es->trackball);
+
+    get_rotation (es->rot, &x, &y, &z, !es->button_down_p);
+    glRotatef (x * 360, 1.0, 0.0, 0.0);
+    glRotatef (y * 360, 0.0, 1.0, 0.0);
+    glRotatef (z * 360, 0.0, 0.0, 1.0);
+  }
+
+  if (cur_time > change_time1)
+  {
+    if (cur_time > change_time2)
+    {
+      glRotatef (90, 0, 1, 0);
+
+      if (cur_time > change_time3)
+        es->start_time = GETSECS(current_time) * 1000 + GETMSECS(current_time) - 5000;
+    }
+    else
+    {
+      glRotatef (180, 0, 1, 0);
+    }
+  }
+
+  glEnable ( GL_FOG);
+  glFogf (GL_FOG_START, 200);
+  glFogf (GL_FOG_END, 500);
+  glFogf (GL_FOG_MODE, GL_LINEAR);
+
+  glGetFloatv (GL_MODELVIEW_MATRIX, m);
+
+  inverse_matrix (m);
+
+  vx.x = m[0] * 10;
+  vx.y = m[1] * 10;
+  vx.z = m[2] * 10;
+
+  vy.x = m[4] * 10;
+  vy.y = m[5] * 10;
+  vy.z = m[6] * 10;
+
+  mi->polygon_count = 0;
+
+  for (i = 0; i != es->num_streams; i++)
+  {
+    mi->polygon_count += es->streams[i].num_flares;
+    render_flare_stream (&es->streams[i], cur_time, &vx, &vy, alpha);
+  }
+
+  glDisable (GL_TEXTURE_2D);
+  glDisable (GL_LIGHTING);
+  glDisable (GL_FOG);
+  glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+  if (mi->fps_p) do_fps (mi);
+  glFinish();
+
+  glXSwapBuffers (dpy, window);
+}
+
+XSCREENSAVER_MODULE_2("EnergyStream", energystream, stream)
+
+#endif /* USE_GL */
diff --git a/hacks/glx/energystream.man b/hacks/glx/energystream.man
new file mode 100644 (file)
index 0000000..c2591f3
--- /dev/null
@@ -0,0 +1,56 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+energystream - a flow of particles which form an energy stream
+.SH SYNOPSIS
+.B energystream
+[\-display \fIhost:display.screen\fP]
+[\-visual \fIvisual\fP]
+[\-window]
+[\-root]
+[\-no-wander]
+[\-no-spin]
+[\-fps]
+.SH DESCRIPTION
+Draws a set of flowing particles with camera flying around and through it.
+.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 \-wander | \-no-wander
+Whether the camera should wander around the screen.
+.TP 8
+.B \-spin | \-no-spin
+Whether the camera should spin.
+.TP 8
+.B \-fps
+Display the current frame rate, CPU load, and polygon count.
+.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 2016 by Eugene Sandulenko.  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
+Eugene Sandulenko.
index b31cf0d9d91cedde4bd8d180f43629f6f6722c00..753eff6679dd53b196c53fd15bf31d937288ed46 100644 (file)
@@ -24,6 +24,7 @@
 #ifdef STANDALONE
 #define DEFAULTS        "*delay:           30000        \n" \
                         "*showFPS:         False        \n" \
+                       "*suppressRotationAnimation: True\n" \
        "*titleFont:  -*-helvetica-medium-r-normal-*-*-180-*-*-*-*-*-*\n" \
 
 # define refresh_engine 0
@@ -326,8 +327,10 @@ static int cylinder (Engine *e, GLfloat x, GLfloat y, GLfloat z,
   for (a = sangle ; a <= angle || b <= angle ; a+= step) {
     y2=outer*(float)e->sin_table[a]+y;
     z2=outer*(float)e->cos_table[a]+z;
-    if (endcaps)
-       y2c[a] = y2; z2c[a] = z2; /* cache for later */
+    if (endcaps) {
+       y2c[a] = y2;
+       z2c[a] = z2; /* cache for later */
+    }
     if (tube) {
       Y2=inner*(float)e->sin_table[a]+y;
       Z2=inner*(float)e->cos_table[a]+z;
@@ -598,8 +601,9 @@ static int boom(Engine *e, GLfloat x, GLfloat y, int s)
   return polys;
 }
 
-static int display(Engine *e)
+static int display(ModeInfo *mi)
 {
+ Engine *e = &engine[MI_SCREEN(mi)];
   int polys = 0;
   GLfloat zb, yb;
   float rightSide;
@@ -615,6 +619,15 @@ static int display(Engine *e)
             0.0, 1.0, 0.0);
   glPushMatrix();
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
   glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
   glLightfv(GL_LIGHT0, GL_SPECULAR, light_sp);
   glLightfv(GL_LIGHT0, GL_DIFFUSE, light_sp);
@@ -970,7 +983,7 @@ ENTRYPOINT void draw_engine(ModeInfo *mi)
   glXMakeCurrent(disp, w, *(e->glx_context));
 
 
-  mi->polygon_count = display(e);
+  mi->polygon_count = display(mi);
 
   glColor3f (1, 1, 0);
   if (do_titles)
index d780348c8c7bdba88417aa1e20984b612f815478..3d35c1e1c277821f26299a3ef66eed4d2bff4b57 100644 (file)
@@ -169,7 +169,7 @@ static void randsheet_move( randsheet *rs, float rot );
 static int randsheet_draw( randsheet *rs );
 static void setup_lights(void);
 static int drawBoard(Flipflopcreen *);
-static int display(Flipflopcreen *c);
+static int display(ModeInfo *mi);
 static int draw_sheet(float *tex);
 
 
@@ -233,8 +233,9 @@ drawBoard(Flipflopcreen *c)
 
 
 static int
-display(Flipflopcreen *c)
+display(ModeInfo *mi)
 {
+    Flipflopcreen *c = &qs[MI_SCREEN(mi)];
     GLfloat amb[] = { 0.8, 0.8, 0.8, 1.0 };
     int polys = 0;
 
@@ -242,7 +243,6 @@ display(Flipflopcreen *c)
     glClear(clearbits);
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
-
     glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.2);
     glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.15/board_avg_size );
     glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.15/board_avg_size );
@@ -262,6 +262,15 @@ display(Flipflopcreen *c)
     if(textured)
       glBindTexture(GL_TEXTURE_2D, c->texid);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+    {
+      GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+      int o = (int) current_device_rotation();
+      if (o != 0 && o != 180 && o != -180)
+        glScalef (1/h, 1/h, 1/h);
+    }
+# endif
+
     polys = drawBoard(c);
 
     if (!c->button_down_p) {
@@ -443,7 +452,7 @@ draw_flipflop(ModeInfo *mi)
 
     glXMakeCurrent(disp, w, *(c->glx_context));
 
-    mi->polygon_count = display(c);
+    mi->polygon_count = display(mi);
 
     if(mi->fps_p){
         do_fps(mi);
index 4d6ff301d7292ca380afcebc4f18ef6495b5e367..8ae26becc842eb7c688f646c84aa3e4bca0f7c73 100644 (file)
@@ -18,7 +18,8 @@
 #define DEFAULTS "*delay:     20000 \n" \
                  "*showFPS:   False \n" \
                  "*wireframe: False \n" \
-                 "*useSHM:    True  \n"
+                 "*useSHM:    True  \n" \
+                "*suppressRotationAnimation: True\n" \
 
 # define refresh_screenflip 0
 # include "xlockmore.h"                         /* from the xscreensaver distribution */
@@ -304,13 +305,14 @@ 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();
   gluLookAt(viewer[0], viewer[1], viewer[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
   glPushMatrix();
 
+/*
   glRotatef(rot, 0, 0, 1);
   if ((rot >  45 && rot <  135) ||
       (rot < -45 && rot > -135))
@@ -318,6 +320,7 @@ static void display(Screenflip *c, int wire)
       GLfloat s = c->winw / (GLfloat) c->winh;
       glScalef (s, 1/s, 1);
     }
+*/
 
   if (inposition(c)) {
     frozen = 0;
@@ -331,9 +334,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) {
index a304ac6d834ca607407b6eee7de96b43026f8f4d..14718b64f8265f8929f2b9018c8a6d68f746b93d 100644 (file)
@@ -39,7 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 # include "config.h"
 #endif /* HAVE_CONFIG_H */
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # include <GL/gl.h>
 # include <GL/glu.h>
 # include <GL/glx.h>
index 1d89cbb8005c3a23201406154f221ab37761b21b..edf1dd64bb4285b86210d0b4a6d0449963df55f5 100644 (file)
@@ -304,6 +304,14 @@ reshape_toasters (ModeInfo *mi, int width, int height)
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
   glClear(GL_COLOR_BUFFER_BIT);
 }
 
index 6020b257ea59e3ca3cec8c2e02264a27fdc6da75..eb6b6de5fbe4fdfb92ea7c623c7474338cbc3dfd 100644 (file)
@@ -84,16 +84,11 @@ xlockmore_gl_draw_fps (ModeInfo *mi)
       XWindowAttributes xgwa;
       int lines = 1;
       const char *s;
-      int y = st->y;
 
       XGetWindowAttributes (st->dpy, st->window, &xgwa);
       for (s = st->string; *s; s++) 
         if (*s == '\n') lines++;
 
-      if (y < 0)
-        y = xgwa.height + y - (lines * data->line_height);
-      y += lines * data->line_height;
-
       glColor3f (1, 1, 1);
       print_texture_label (st->dpy, data->texfont,
                            xgwa.width, xgwa.height,
index 61599f9ae5e372ed490379bea978101acf41f69c..1f26cea286f6288da0bcd6d67f1dfd3149337c4d 100644 (file)
@@ -16,6 +16,7 @@
                        "*count:        0           \n" \
                        "*showFPS:      False       \n" \
                        "*wireframe:    False       \n" \
+                       "*suppressRotationAnimation: True\n" \
 
 # define refresh_gears 0
 # define release_gears 0
@@ -98,6 +99,14 @@ reshape_gears (ModeInfo *mi, int width, int height)
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
   glClear(GL_COLOR_BUFFER_BIT);
 }
 
@@ -759,7 +768,7 @@ init_gears (ModeInfo *mi)
       bp->planetary_p = False;
 
       if (total_gears <= 0)
-        total_gears = 3 + abs (BELLRAND (8) - 4);  /* 3 - 7, mostly 3. */
+        total_gears = 3 + fabs (BELLRAND (8) - 4);  /* 3 - 7, mostly 3. */
       bp->gears = (gear **) calloc (total_gears+2, sizeof(**bp->gears));
       bp->ngears = 0;
 
index 383e3045d0b6a7be2cf8eb4da00b671c59e4a623..b22b065eee8d730eb58d6acc58c977e0b12e32ae 100644 (file)
@@ -11,7 +11,8 @@
 
 #define DEFAULTS       "*delay:        30000       \n" \
                        "*count:        4           \n" \
-                       "*showFPS:      False       \n"
+                       "*showFPS:      False       \n" \
+                       "*suppressRotationAnimation: True\n" \
 
 # define refresh_geodesic 0
 # define release_geodesic 0
@@ -468,6 +469,14 @@ reshape_geodesic (ModeInfo *mi, int width, int height)
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
   glClear(GL_COLOR_BUFFER_BIT);
 }
 
index 6002e3477460f7d9ba93d0422c30e308ded316c8..dc234809fbda035ad9b5d4b657373b7dec32e844 100644 (file)
@@ -17,6 +17,7 @@
                        "*wireframe:    False       \n" \
                        "*showFPS:      False       \n" \
                        "*texFontCacheSize: 100     \n" \
+                       "*suppressRotationAnimation: True\n" \
                "*font:  -*-helvetica-medium-r-normal-*-*-160-*-*-*-*-*-*\n" \
 
 # define refresh_geodesic 0
@@ -1328,6 +1329,14 @@ reshape_geodesic (ModeInfo *mi, int width, int height)
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
   glClear(GL_COLOR_BUFFER_BIT);
 }
 
index d38e46e82c17ec13640c1c6c51d20f2c67b7713e..1e6daed2578b16b090439049423b2659e0710ab3 100644 (file)
@@ -43,8 +43,8 @@
 #define DEFAULTS                        "*delay:               20000\n" \
                                                                                "*showFPS:      False\n" \
                                         "*mode:         grab\n"  \
-                                        "*useSHM:       True \n" 
-
+                                        "*useSHM:       True \n" \
+                                                                               "*suppressRotationAnimation: True\n" \
 
 # define refresh_gflux 0
 # include "xlockmore.h"                                /* from the xscreensaver distribution */
@@ -283,23 +283,26 @@ ENTRYPOINT void draw_gflux(ModeInfo * mi)
 }
 
 
-/* reset the projection matrix */
-static void resetProjection(void) 
+/* Standard reshape function */
+ENTRYPOINT void
+reshape_gflux(ModeInfo *mi, int width, int height)
 {
+    glViewport( 0, 0, width, height );
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
     glFrustum(-_zoom,_zoom,-0.8*_zoom,0.8*_zoom,2,6);
     glTranslatef(0.0,0.0,-4.0);
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
-}
 
-/* Standard reshape function */
-ENTRYPOINT void
-reshape_gflux(ModeInfo *mi, int width, int height)
-{
-    glViewport( 0, 0, width, height );
-    resetProjection();
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+    {
+      GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+      int o = (int) current_device_rotation();
+      if (o != 0 && o != 180 && o != -180)
+        glScalef (1/h, 1/h, 1/h);
+    }
+# endif
 }
 
 
index 95c4110a3408111d54c19b2d6dcbef4db7465330..ab3f6501f0b804e21473886d6c7bbee3e2a5ec6f 100644 (file)
@@ -24,7 +24,8 @@
 
 #define DEFAULTS       "*delay:    10000 \n" \
                        "*showFPS:  False \n" \
-                       "*fpsSolid: True  \n"
+                       "*fpsSolid: True  \n" \
+                       "*suppressRotationAnimation: True\n" \
 
 # define refresh_glblur 0
 # define release_glblur 0
@@ -124,6 +125,14 @@ reshape_glblur (ModeInfo *mi, int width, int height)
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
   glClear(GL_COLOR_BUFFER_BIT);
 }
 
index c312f0c2d6083405036065366610ad5ba860725e..4c651763321d551135236d84b590b7703e99f7f5 100644 (file)
@@ -54,6 +54,7 @@
 #define DEFAULTS       "*delay:        30000            \n" \
                        "*showFPS:      False            \n" \
                        "*wireframe:    False            \n" \
+                       "*suppressRotationAnimation: True\n" \
 
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
@@ -718,9 +719,24 @@ static int render( State *st )
     glEnable( GL_NORMALIZE );
     glPolygonMode( GL_FRONT, GL_FILL );
   } else {
+# ifndef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */
     glPolygonMode( GL_FRONT, GL_LINE );
+# endif
   }
   
+# if 0
+  if (st->wire) {
+    glDisable(GL_DEPTH_TEST);
+    glColor3f (1, 1, 1);
+    glBegin(GL_LINE_LOOP);
+    glVertex3f(0, 0, 0); glVertex3f(st->width, 0, 0);
+    glVertex3f(st->width, st->height, 0); glVertex3f(0, st->height, 0);
+    glVertex3f(0, 0, 0); glVertex3f(st->width/4, 0, 0);
+    glVertex3f(st->width/4, st->height/4, 0); glVertex3f(0, st->height/4, 0);
+    glEnd();
+  }
+# endif
+
   /* draw the dead cells if choosen */
   if (st->keep_old_cells) {
     for (b=0; b<st->num_cells; ++b) {
@@ -748,6 +764,15 @@ static int render( State *st )
       num_paint++;
       /*glColor3f( fac, fac, fac );*/
       
+# if 0
+      if (st->wire) {
+        glBegin(GL_LINES);
+        glVertex3f(0, 0, 0);
+        glVertex3f(st->cell[b].x, st->cell[b].y, 0);
+        glEnd();
+      }
+# endif
+
       glPushMatrix();
       glTranslatef( st->cell[b].x, st->cell[b].y, 0.0 );
       glRotatef( st->cell[b].rotation, 0.0, 0.0, 1.0 );
@@ -906,6 +931,27 @@ static int create_list( State *st, double fac )
 
 static void draw_cell( State *st, int shape )
 {
+# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */
+  if (st->wire) {
+    glDisable(GL_DEPTH_TEST);
+    glColor3f (1, 1, 1);
+    glPushMatrix();
+    glScalef (0.33, 0.33, 1);
+    glBegin (GL_LINE_LOOP);
+    glVertex3f (-1, -1, 0); glVertex3f (-1,  1, 0);
+    glVertex3f ( 1,  1, 0); glVertex3f ( 1, -1, 0);
+    glEnd();
+    if (shape == 9) {
+      glBegin (GL_LINES);
+      glVertex3f (-1, -1, 0); glVertex3f (1,  1, 0);
+      glVertex3f (-1,  1, 0); glVertex3f (1, -1, 0);
+      glEnd();
+    }
+    glPopMatrix();
+    return;
+  }
+# endif
+
   if (-1 == st->cell_list[shape]) {
     st->cell_list[shape] = create_list( st, (double)shape/10.0 );
   }
@@ -1147,9 +1193,11 @@ static void tick( State *st )
       
       /* have a snack */
       x = ((int)st->cell[b].x)/4;
-      if (x<0) x=0; if (x>=w4) x = w4-1;
+      if (x<0) x=0;
+      if (x>=w4) x = w4-1;
       y = ((int)st->cell[b].y)/4;
-      if (y<0) y=0; if (y>=h4) y = h4-1;
+      if (y<0) y=0;
+      if (y>=h4) y = h4-1;
     
       offset = x+y*w4;
     
@@ -1173,10 +1221,17 @@ ENTRYPOINT void
 reshape_glcells( ModeInfo *mi, int width, int height )
 {
   State *st  = &sstate[MI_SCREEN(mi)];
+# ifdef HAVE_MOBILE
+  int rot = current_device_rotation();
+# endif
   st->height = height;
   st->width  = width;
+# ifdef HAVE_MOBILE
+  st->screen_scale = (double)(width < height ? width : height) / 1600.0;
+# else
   st->screen_scale = (double)width / 1600.0;
-  
+# endif
+
   st->radius = s_radius;
   if (st->radius < 5) st->radius = 5;
   if (st->radius > 200) st->radius = 200;
@@ -1192,12 +1247,23 @@ reshape_glcells( ModeInfo *mi, int width, int height )
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glOrtho( 0, width, height, 0, 200, 0 );
+# ifdef HAVE_MOBILE
+  glRotatef (rot, 0, 0, 1);
+# endif
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
-  
   if (st->food) free( st->food );
   st->food = (int *)malloc( ((width*height)/16)*sizeof(int) );
   /* create_cells( st );*/
+
+# ifdef HAVE_MOBILE
+  glTranslatef (st->width/2, st->height/2, 0);
+  if (rot == 90 || rot == -90 || rot == 270 || rot == -270)
+    st->width = height, st->height = width;
+  glRotatef (rot, 0, 0, 1);
+  if (st->wire) glScalef(0.8, 0.8, 1);
+  glTranslatef (-st->width/2, -st->height/2, 0);
+# endif
 }
 
 ENTRYPOINT void 
@@ -1221,10 +1287,6 @@ init_glcells( ModeInfo *mi )
   st->num_cells = 0;
   st->wire = MI_IS_WIREFRAME(mi);
   
-# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */
-  st->wire = 0;
-# endif
-
   /* get settings */
   st->max_cells = s_maxcells;;
   if (st->max_cells < 50) st->max_cells = 50;
@@ -1298,7 +1360,7 @@ draw_glcells( ModeInfo *mi )
                   *(st->glx_context) );
   
   mi->polygon_count = render( st );
-  
+
   if (mi->fps_p) do_fps (mi);
   
   glFinish();
index 9ea8035306a76519803cd30377599252127d9380..9a49b20af138759a19c87a1e1291c43813174d5b 100644 (file)
@@ -74,7 +74,8 @@
                "*delay:                20000           \n"     \
                "*showFPS:              False           \n"     \
                "*size:                 0                       \n"     \
-               "*useSHM:               True            \n"
+               "*useSHM:               True            \n" \
+               "*suppressRotationAnimation: True\n" \
 
 # define refresh_gleidescope 0
 # include "xlockmore.h"                                /* from the xscreensaver distribution */
@@ -1117,15 +1118,9 @@ draw_hexagons(ModeInfo *mi, int translucency, texture *texture)
 {
     int polys = 0;
        int             i;
-       GLfloat col[4];
        vector2f t[3];
        gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
 
-       col[0] = 1.0;
-       col[1] = 1.0;
-       col[2] = 1.0;
-       col[3] = (float)translucency / MAX_FADE;
-
        calculate_texture_coords(mi, texture, t);
 
        glColor4f(1.0, 1.0, 1.0, (float)translucency / MAX_FADE);
@@ -1246,7 +1241,6 @@ draw(ModeInfo * mi)
        GLfloat x_angle, y_angle, z_angle;
        gleidestruct *gp = &gleidescope[MI_SCREEN(mi)];
        vectorf v1;
-       GLfloat pos[4];
 
     mi->polygon_count = 0;
 
@@ -1328,11 +1322,14 @@ draw(ModeInfo * mi)
                        0.0);
 #endif
 
-       /* light position same as camera */
-       pos[0] = v1.x;
-       pos[1] = v1.y;
-       pos[2] = v1.z;
-       pos[3] = 0;
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+    {
+      GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+      int o = (int) current_device_rotation();
+      if (o != 0 && o != 180 && o != -180)
+        glScalef (1/h, 1/h, 1/h);
+    }
+# endif
 
        if (gp->fade == 0)
        {
@@ -1401,7 +1398,6 @@ ENTRYPOINT void reshape_gleidescope(ModeInfo *mi, int width, int height)
        glLoadIdentity();
        gluPerspective(50.0, 1/h, 0.1, 2000.0);
        glMatrixMode (GL_MODELVIEW);
-
        glLineWidth(1);
        glPointSize(1);   
 }
index 3697b2e4b0b7148269ac32ba6a7e1625d0f74af6..e880cfa19b9cced70ae8ef939d88d2197db51250 100644 (file)
@@ -621,13 +621,15 @@ static Bool inittree(ModeInfo * mi)
                return False;
     }
     /* initialise positions */
-    for(i=0;i<fs->num_trees;i++)
-       do {
-           fs->treepos[i].x =vrnd()*TREEOUTR*2.0-TREEOUTR;
-           fs->treepos[i].y =0.0;
-           fs->treepos[i].z =vrnd()*TREEOUTR*2.0-TREEOUTR;
-           dist=sqrt(fs->treepos[i].x *fs->treepos[i].x +fs->treepos[i].z *fs->treepos[i].z );
-        } while((dist<TREEINR) || (dist>TREEOUTR));
+    for(i=0;i<fs->num_trees;i++) {
+      do {
+        fs->treepos[i].x =vrnd()*TREEOUTR*2.0-TREEOUTR;
+        fs->treepos[i].y =0.0;
+        fs->treepos[i].z =vrnd()*TREEOUTR*2.0-TREEOUTR;
+        dist = sqrt(fs->treepos[i].x * fs->treepos[i].x +
+                    fs->treepos[i].z * fs->treepos[i].z);
+      } while((dist<TREEINR) || (dist>TREEOUTR));
+    }
        return True;
 }
 
index f9bc6fe0d2aef93a6194938d7dfdf0f681eb003c..6f52b3a1014e9f768dfb3cfaed5a24c4610e0c84 100644 (file)
@@ -345,7 +345,7 @@ static void moveSetup(glhcfg *glhanoi, Disk * disk)
        int dst = glhanoi->dst;
        GLfloat theta;
        GLfloat sintheta, costheta;
-       double absx, dh;
+       double dh;
        double dx, dz; /* total x and z distances from src to dst */
        Pole *poleSrc, *poleDst;
 
@@ -385,7 +385,7 @@ static void moveSetup(glhcfg *glhanoi, Disk * disk)
        /* horizontal distance to travel? */
        /* was: absx = sqrt(disk->xmax - disk->xmin); */
        dh = distance(poleSrc->position, poleDst->position);
-       absx = sqrt(dh);
+       /* absx = sqrt(dh); */
        ymax = glhanoi->poleHeight + dh;
        if(glhanoi->state == FINISHED) {
                ymax += dh * (double)(glhanoi->numberOfDisks - disk->id);
@@ -888,7 +888,6 @@ static int drawTube(GLdouble bottomRadius, GLdouble topRadius,
        GLint lastSlice = nSlice - 1;
        GLfloat radius;
        GLfloat innerRadius;
-       GLfloat maxRadius;
 
        if(bottomThickness > bottomRadius) {
                bottomThickness = bottomRadius;
@@ -902,11 +901,11 @@ static int drawTube(GLdouble bottomRadius, GLdouble topRadius,
        if(topThickness < 0.0) {
                topThickness = 0.0;
        }
-       if(topRadius >= bottomRadius) {
+/*     if(topRadius >= bottomRadius) {
                maxRadius = topRadius;
        } else {
                maxRadius = bottomRadius;
-       }
+       } */
 
        /* bottom */
        y = 0.0;
@@ -1968,6 +1967,15 @@ ENTRYPOINT void draw_glhanoi(ModeInfo * mi)
        update_glhanoi(glhanoi);
        updateView(glhanoi);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+    {
+      GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+      int o = (int) current_device_rotation();
+      if (o != 0 && o != 180 && o != -180)
+        glScalef (1/h, 1/h, 1/h);
+    }
+# endif
+
        if(!glhanoi->wire && glhanoi->texture) {
                glEnable(GL_TEXTURE_2D);
        }
@@ -1994,6 +2002,8 @@ ENTRYPOINT Bool glhanoi_handle_event(ModeInfo * mi, XEvent * event)
 {
        glhcfg *glhanoi = &glhanoi_cfg[MI_SCREEN(mi)];
 
+    /* #### this is all wrong on iOS -- should be using gltrackball. */
+
        if(event->xany.type == ButtonPress && event->xbutton.button == Button1) {
                glhanoi->button_down_p = True;
                glhanoi->drag_x = event->xbutton.x;
index 36ff1983daca7773483822ebe53ff5fda1293bd6..8dd63728e8ee8650fb568ddef501e76b4a302314 100644 (file)
@@ -16,6 +16,7 @@
 #define DEFAULTS       "*delay:        30000       \n" \
                        "*showFPS:      False       \n" \
                        "*wireframe:    False       \n" \
+                       "*suppressRotationAnimation: True\n" \
 
 # define refresh_knot 0
 # define release_knot 0
@@ -190,6 +191,14 @@ reshape_knot (ModeInfo *mi, int width, int height)
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
   glClear(GL_COLOR_BUFFER_BIT);
 }
 
index 778143d55b09b6adcdddb4eb481a02ce8a18fa3a..342e38134d8a26f7cb1c99a8a241658227ff37af 100644 (file)
@@ -16,7 +16,8 @@ renderList (const struct gllist *list, int wire_p)
 {
   while (list)
     {
-      if (!wire_p || list->primitive == GL_LINES)
+      if (!wire_p || list->primitive == GL_LINES ||
+          list->primitive == GL_POINTS)
         {
           glInterleavedArrays (list->format, 0, list->data);
           glDrawArrays (list->primitive, 0, list->points);
index 8c9dec8fff6ce1342d333d7d5182ceb112dbd567..3657e4c4f9c67e67ae0113652ff65fe68ab2fab8 100644 (file)
@@ -35,7 +35,9 @@
                                        "*showFPS:                      False   \n" \
                                        "*wireframe:            False   \n"     \
                                        "*imageForeground:      Green   \n" \
-                                       "*imageBackground:      Blue    \n"
+                                       "*imageBackground:      Blue    \n" \
+                                       "*suppressRotationAnimation: True\n" \
+
 # define refresh_planet 0
 # include "xlockmore.h"                                /* from the xscreensaver distribution */
 #else  /* !STANDALONE */
@@ -309,6 +311,14 @@ reshape_planet (ModeInfo *mi, int width, int height)
   glLoadIdentity();
   glTranslatef(0.0, 0.0, -40);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (h, h, h);
+  }
+# endif
+
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 }
 
@@ -418,7 +428,9 @@ init_planet (ModeInfo * mi)
   gp->latlonglist = glGenLists(1);
   glNewList (gp->latlonglist, GL_COMPILE);
   glPushMatrix ();
-  glRotatef (90, 1, 0, 0);
+  glRotatef (90, 1, 0, 0);  /* unit_sphere is off by 90 */
+  glRotatef (8,  0, 1, 0);  /* line up the time zones */
+  unit_sphere (12, 24, 1);
   unit_sphere (12, 24, 1);
   glBegin(GL_LINES);
   glVertex3f(0, -2, 0);
@@ -488,8 +500,7 @@ draw_planet (ModeInfo * mi)
     {
       glDisable(GL_TEXTURE_2D);
       glPushMatrix();
-      glTranslatef(-x, -y, -z);
-      glScalef (40, 40, 40);
+      glScalef (60, 60, 60);
       glRotatef (90, 1, 0, 0);
       glRotatef (35, 1, 0, 0);
       glCallList (gp->starlist);
@@ -505,7 +516,7 @@ draw_planet (ModeInfo * mi)
 
   glScalef (3, 3, 3);
 
-# ifdef USE_IPHONE
+# ifdef HAVE_MOBILE
   glScalef (2, 2, 2);
 # endif
 
index ac311f7db7e80d20b50419f61e4ba522403d04e5..c5e2d384ee77eb59cbe3233e949eed10cee58f0a 100644 (file)
@@ -15,7 +15,7 @@
 # include "config.h"
 #endif /* HAVE_CONFIG_H */
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
 # include "jwxyz.h"
 # ifndef HAVE_JWZGLES
 #  include <OpenGL/glu.h>
 # include <GL/glu.h>
 #endif
 
+#ifdef HAVE_ANDROID
+#include <GLES/gl.h>
+#endif
+
 #ifdef HAVE_JWZGLES
 # include "jwzgles.h"
 #endif /* HAVE_JWZGLES */
index 992d75cbbea974029b05b8ec1ba7c9e6dff40338..3e3548d8e08f6df20ded6b18d5c73c3b81fd11ab 100644 (file)
@@ -226,7 +226,7 @@ ENTRYPOINT ModeSpecOpt slideshow_opts = {countof(opts), opts, countof(vars), var
 static const char *
 blurb (void)
 {
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
   return "GLSlideshow";
 # else
   static char buf[255];
@@ -867,6 +867,7 @@ draw_sprites (ModeInfo *mi)
 
   glPushMatrix();
 
+/*
   {
     GLfloat rot = current_device_rotation();
     glTranslatef (0.5, 0.5, 0);
@@ -879,6 +880,7 @@ draw_sprites (ModeInfo *mi)
       }
     glTranslatef (-0.5, -0.5, 0);
   }
+*/
 
   for (i = 0; i < ss->nsprites; i++)
     draw_sprite (mi, ss->sprites[i]);
@@ -911,6 +913,7 @@ reshape_slideshow (ModeInfo *mi, int width, int height)
   glViewport (0, 0, width, height);
   glMatrixMode (GL_PROJECTION);
   glLoadIdentity();
+  glRotatef (current_device_rotation(), 0, 0, 1);
   glMatrixMode (GL_MODELVIEW);
   glLoadIdentity();
 
@@ -993,7 +996,7 @@ sanity_check (ModeInfo *mi)
 static void
 check_fps (ModeInfo *mi)
 {
-#ifndef HAVE_COCOA  /* always assume Cocoa is fast enough */
+#ifndef HAVE_JWXYZ  /* always assume Cocoa and mobile are fast enough */
 
   slideshow_state *ss = &sss[MI_SCREEN(mi)];
 
@@ -1045,7 +1048,7 @@ check_fps (ModeInfo *mi)
 
   /* Need this in case zoom changed. */
   reshape_slideshow (mi, mi->xgwa.width, mi->xgwa.height);
-#endif /* HAVE_COCOA */
+#endif /* HAVE_JWXYZ */
 }
 
 
index 094b12a0c4fd0459d1417c26529d7986c98b54b5..2616ad273be4ad16d73e885739f19aa33f687ea2 100644 (file)
 #ifdef HAVE_GLUT
 # include <GL/glut.h>
 #else
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
 #  define HAVE_GETTIMEOFDAY
 # else
 #  include <GL/gl.h>
 #  include <GL/glu.h>
 # endif
 #endif
+# ifdef HAVE_ANDROID
+# include <GLES/gl.h>
+#endif
 
 #ifdef HAVE_JWZGLES
 # include "jwzgles.h"
@@ -149,6 +152,7 @@ static GLfloat angvel;
 #define DEFAULTS "*delay:          30000                      \n" \
                  "*count:          30                         \n" \
                  "*showFPS:        False                      \n" \
+               "*suppressRotationAnimation: True\n" \
          "*labelfont:   -*-helvetica-medium-r-normal-*-*-180-*-*-*-*-*-*\n" \
 
 
@@ -2263,6 +2267,15 @@ ENTRYPOINT void glsnake_display(
     glRotatef(yspin, 0.0, 1.0, 0.0); 
     glRotatef(zspin, 0.0, 0.0, 1.0); 
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+    {
+      GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+      int o = (int) current_device_rotation();
+      if (o != 0 && o != 180 && o != -180)
+        glScalef (1/h, 1/h, 1/h);
+    }
+# endif
+
     /* now draw each node along the snake -- this is quite ugly :p */
     mi->polygon_count = 0;
     for (i = 0; i < NODE_COUNT; i++) {
index bc7e81bf6c27aedfb25d2f6c450b38e911713393..a4d80b050edc1d93c392eba38163ecf14812a12a 100644 (file)
@@ -125,6 +125,14 @@ reshape_text (ModeInfo *mi, int width, int height)
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
   glClear(GL_COLOR_BUFFER_BIT);
 }
 
index f07cb7cddb94cbd3b1a414143c55d635be017fd3..71775f15a3bca931e3107ed97eca8ce49585b82f 100644 (file)
@@ -42,7 +42,7 @@
 #include "gltrackball.h"
 
 /* Bah, copied from ../fps.h */
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   extern double current_device_rotation (void);
 #else
 # define current_device_rotation() (0)
@@ -241,7 +241,7 @@ gltrackball_mousewheel (trackball_state *ts,
   int horizontal_p;
   int mx, my, move, scale;
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
   flip_p = 0;      /* MacOS has already handled this. */
 #endif
 
index 455e3db0dd4da49a4957f646fd3fc34b67d66149..59850ea76c43c010d7aede3435716f1749799417 100644 (file)
@@ -8,15 +8,24 @@
 #if 0   /* for Mesa */
 # include "glutint.h"
 #else   /* for xscreensaver */
+
 # ifdef HAVE_CONFIG_H
 #  include "config.h"
 # endif
-# ifndef HAVE_COCOA
+
+# ifdef HAVE_COCOA
+#  include "jwxyz.h"
+# elif defined(HAVE_ANDROID)
+#  include "jwxyz.h"
+#  include <GLES/gl.h>
+# else  /* real X11 */
 #  include <GL/gl.h>
 # endif
+
 # ifdef HAVE_JWZGLES
 #  include "jwzgles.h"
 # endif /* HAVE_JWZGLES */
+
 # undef APIENTRY
 # define APIENTRY /**/
 #endif
index 185571d167cd31e0da097c10e97adad56c4741b8..b165a0a4c25d5077ad75a3b59ab93e3299195466 100644 (file)
 # ifdef HAVE_CONFIG_H
 #  include "config.h"
 # endif
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
 #  include <GL/gl.h>
 # endif
+#ifdef HAVE_ANDROID
+#include <GLES/gl.h>
+#define Bool int
+#endif
 # ifdef HAVE_JWZGLES
 #  include "jwzgles.h"
 # endif /* HAVE_JWZGLES */
index 5127b494a6136a5be847c1993f95d4f32d0f8757..f57bd9aa5436ce770f78dbb13cc93db0c785d5f7 100644 (file)
 #include <stdio.h>
 #include <string.h>
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_ANDROID
+#include <GLES/gl.h>
+#endif
+
+#ifdef HAVE_JWXYZ
 # include "jwxyz.h"
 # ifndef HAVE_JWZGLES
 #  include <OpenGL/glu.h>
@@ -70,7 +74,7 @@ extern char *progname;
 
 #include <sys/time.h>
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
 # include "jwxyz.h"
 #else
 # include <X11/Xutil.h>
index 8374dec363d7eef2ff24caba4ff84f3a4e945520..fd0a1a2805e1937b7f5b9fd2ee9fe6c24f1b2fc7 100644 (file)
@@ -18,7 +18,8 @@
                        "*count:        30          \n" \
                        "*showFPS:      False       \n" \
                        "*wireframe:    False       \n" \
-                       "*geometry:     800x800\n"
+                       "*geometry:     800x800\n" \
+                       "*suppressRotationAnimation: True\n" \
 
 # define refresh_hilbert 0
 # define release_hilbert 0
@@ -769,6 +770,14 @@ reshape_hilbert (ModeInfo *mi, int width, int height)
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
   glClear(GL_COLOR_BUFFER_BIT);
 }
 
diff --git a/hacks/glx/hydrostat.c b/hacks/glx/hydrostat.c
new file mode 100644 (file)
index 0000000..ea3de9d
--- /dev/null
@@ -0,0 +1,778 @@
+/* hydrostat, Copyright (C) 2012 by Justin Windle
+ * Copyright (c) 2016 Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * Tentacle simulation using inverse kinematics.
+ *
+ *   http://soulwire.co.uk/experiments/muscular-hydrostats/
+ *   https://github.com/soulwire/Muscular-Hydrostats/
+ *
+ * Ported to C from Javascript by jwz, May 2016
+ */
+
+#define DEFAULTS       "*delay:        20000       \n" \
+                       "*count:        3           \n" \
+                       "*showFPS:      False       \n" \
+                       "*wireframe:    False       \n" \
+                       "*suppressRotationAnimation: True\n" \
+
+# define refresh_hydrostat 0
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+#include "xlockmore.h"
+#include "colors.h"
+#include "sphere.h"
+#include "normals.h"
+#include "gltrackball.h"
+#include <ctype.h>
+
+#ifdef USE_GL /* whole file */
+
+/* It looks bad when you rotate it with the trackball, because it reveals
+   that the tentacles are moving in a 2d plane.  But it's useful for
+   debugging. */
+#undef USE_TRACKBALL
+
+#define DEF_SPEED       "1.0"
+#define DEF_PULSE       "True"
+#define DEF_HEAD_RADIUS "60"
+#define DEF_TENTACLES   "35"
+#define DEF_THICKNESS   "18"
+#define DEF_LENGTH      "55"
+#define DEF_GRAVITY     "0.5"
+#define DEF_CURRENT     "0.25"
+#define DEF_FRICTION    "0.02"
+#define DEF_OPACITY     "0.8"
+
+
+typedef struct {
+  XYZ pos, opos, v;
+} node;
+
+typedef struct {
+  int length;
+  GLfloat radius;
+  GLfloat spacing;
+  GLfloat friction;
+  GLfloat th;
+  node *nodes;
+  GLfloat color[4];
+} tentacle;
+
+typedef struct {
+  XYZ pos, from, to;
+  GLfloat ratio, pulse, rate;
+  GLfloat head_radius;
+  GLfloat thickness;
+  int ntentacles;
+  tentacle *tentacles;
+  GLfloat color[4];
+} squid;
+
+typedef struct {
+  GLXContext *glx_context;
+  Bool button_down_p;
+  int dragging;
+  squid **squids;
+# ifdef USE_TRACKBALL
+  trackball_state *trackball;
+# endif
+} hydrostat_configuration;
+
+static hydrostat_configuration *bps = NULL;
+
+static Bool do_pulse;
+static GLfloat speed_arg;
+static GLfloat head_radius_arg;
+static GLfloat ntentacles_arg;
+static GLfloat thickness_arg;
+static GLfloat length_arg;
+static GLfloat gravity_arg;
+static GLfloat current_arg;
+static GLfloat friction_arg;
+static GLfloat opacity_arg;
+
+static XrmOptionDescRec opts[] = {
+  { "-pulse",       ".pulse",      XrmoptionNoArg, "True"  },
+  { "+pulse",       ".pulse",      XrmoptionNoArg, "False" },
+  { "-speed",       ".speed",      XrmoptionSepArg, 0 },
+  { "-head-radius", ".headRadius", XrmoptionSepArg, 0 },
+  { "-tentacles",   ".tentacles",  XrmoptionSepArg, 0 },
+  { "-thickness",   ".thickness",  XrmoptionSepArg, 0 },
+  { "-length",      ".length",     XrmoptionSepArg, 0 },
+  { "-gravity",     ".gravity",    XrmoptionSepArg, 0 },
+  { "-current",     ".current",    XrmoptionSepArg, 0 },
+  { "-friction",    ".friction",   XrmoptionSepArg, 0 },
+  { "-opacity",     ".opacity",    XrmoptionSepArg, 0 },
+};
+
+static argtype vars[] = {
+  { &do_pulse,        "pulse",      "Pulse",      DEF_PULSE,       t_Bool  },
+  { &speed_arg,       "speed",      "Speed",      DEF_SPEED,       t_Float },
+  { &head_radius_arg, "headRadius", "HeadRadius", DEF_HEAD_RADIUS, t_Float },
+  { &ntentacles_arg,  "tentacles",  "Tentacles",  DEF_TENTACLES,   t_Float },
+  { &thickness_arg,   "thickness",  "Thickness",  DEF_THICKNESS,   t_Float },
+  { &length_arg,      "length",     "Length",     DEF_LENGTH,      t_Float },
+  { &gravity_arg,     "gravity",    "Gravity",    DEF_GRAVITY,     t_Float },
+  { &current_arg,     "current",    "Current",    DEF_CURRENT,     t_Float },
+  { &friction_arg,    "friction",   "Friction",   DEF_FRICTION,    t_Float },
+  { &opacity_arg,     "opacity",    "Opacity",    DEF_OPACITY,     t_Float },
+};
+
+ENTRYPOINT ModeSpecOpt hydrostat_opts = {countof(opts), opts,
+                                         countof(vars), vars, NULL};
+
+
+static void
+move_tentacle (squid *sq, tentacle *t)
+{
+  int i, j;
+  node *prev = &t->nodes[0];
+  int rot = (int) current_device_rotation();
+
+  for (i = 1, j = 0; i < t->length; i++, j++)
+    {
+      XYZ d, p;
+      GLfloat da;
+      node *n = &t->nodes[i];
+
+      /* Sadly, this is still computing motion in a 2d plane, so the
+         tentacles look dumb if the scene is rotated. */
+
+      n->pos.x += n->v.x;
+      n->pos.y += n->v.y;
+      n->pos.z += n->v.z;
+
+      d.x = prev->pos.x - n->pos.x;
+      d.y = prev->pos.y - n->pos.y;
+      d.z = prev->pos.z - n->pos.z;
+      da = atan2 (d.z, d.x);
+
+      p.x = n->pos.x + cos (da) * t->spacing * t->length;
+      p.y = n->pos.y + cos (da) * t->spacing * t->length;
+      p.z = n->pos.z + sin (da) * t->spacing * t->length;
+
+      n->pos.x = prev->pos.x - (p.x - n->pos.x);
+      n->pos.y = prev->pos.y - (p.y - n->pos.y);
+      n->pos.z = prev->pos.z - (p.z - n->pos.z);
+
+      n->v.x = n->pos.x - n->opos.x;
+      n->v.y = n->pos.y - n->opos.y;
+      n->v.z = n->pos.z - n->opos.z;
+
+      n->v.x *= t->friction * (1 - friction_arg);
+      n->v.y *= t->friction * (1 - friction_arg);
+      n->v.z *= t->friction * (1 - friction_arg);
+
+      switch (rot) {
+      case 90: case -270:
+        n->v.x += gravity_arg;
+        n->v.y -= current_arg;
+        n->v.z -= current_arg;
+        break;
+      case -90: case 270:
+        n->v.x -= gravity_arg;
+        n->v.y += current_arg;
+        n->v.z += current_arg;
+        break;
+      case 180: case -180:
+        n->v.x -= current_arg;
+        n->v.y -= current_arg;
+        n->v.z -= gravity_arg;
+        break;
+      default:
+        n->v.x += current_arg;
+        n->v.y += current_arg;
+        n->v.z += gravity_arg;
+        break;
+      }
+
+      n->opos.x = n->pos.x;
+      n->opos.y = n->pos.y;
+      n->opos.z = n->pos.z;
+
+      prev = n;
+    }
+}
+
+
+static GLfloat
+ease_fn (GLfloat r)
+{
+  return cos ((r/2 + 1) * M_PI) + 1; /* Smooth curve up, end at slope 1. */
+}
+
+
+/* Squirty motion: fast acceleration, then fade. */
+static GLfloat
+ease_ratio (GLfloat r)
+{
+  GLfloat ease = 0.05;
+  GLfloat ease2 = 1-ease;
+  if      (r <= 0)     r = 0;
+  else if (r >= 1)     r = 1;
+  else if (r <= ease)  r =     ease  * ease_fn (r / ease);
+  else                 r = 1 - ease2 * ease_fn ((1 - r) / ease2);
+  return r;
+}
+
+
+static void
+move_squid (ModeInfo *mi, squid *sq)
+{
+  hydrostat_configuration *bp = &bps[MI_SCREEN(mi)];
+  GLfloat step = M_PI * 2 / sq->ntentacles;
+  int i;
+  GLfloat radius = head_radius_arg;
+  GLfloat r;
+
+  /* Move to a new position */
+
+  if (! bp->button_down_p)
+    {
+      sq->ratio += speed_arg * 0.01;
+      if (sq->ratio >= 1)
+        {
+          sq->ratio = -(frand(2.0) + frand(2.0) + frand(2.0));
+          sq->from.x = sq->to.x;
+          sq->from.y = sq->to.y;
+          sq->from.z = sq->to.z;
+          sq->to.x = 250 - frand(500);
+          sq->to.y = 250 - frand(500);
+          sq->to.z = 250 - frand(500);
+        }
+
+      r = sq->ratio > 0 ? ease_ratio (sq->ratio) : 0;
+      sq->pos.x = sq->from.x + r * (sq->to.x - sq->from.x);
+      sq->pos.y = sq->from.y + r * (sq->to.y - sq->from.y);
+      sq->pos.z = sq->from.z + r * (sq->to.z - sq->from.z);
+    }
+
+  if (do_pulse)
+    {
+      GLfloat p = pow (sin (sq->pulse * M_PI), 18);
+      sq->head_radius = (head_radius_arg * 0.7 +
+                         head_radius_arg * 0.3 * p);
+      radius = sq->head_radius * 0.25;
+      sq->pulse += sq->rate * speed_arg * 0.02;
+      if (sq->pulse > 1) sq->pulse = 0;
+    }
+
+  for (i = 0; i < sq->ntentacles; i++)
+    {
+      tentacle *tt = &sq->tentacles[i];
+      GLfloat th = i * step;
+      GLfloat px = cos (th) * radius;
+      GLfloat py = sin (th) * radius;
+      tt->th = th;
+      tt->nodes[0].pos.x = sq->pos.x + px;
+      tt->nodes[0].pos.y = sq->pos.y + py;
+      tt->nodes[0].pos.z = sq->pos.z;
+      move_tentacle (sq, tt);
+    }
+}
+
+
+/* Find the angle at which the head should be tilted in the XY plane.
+ */
+static GLfloat
+head_angle (ModeInfo *mi, squid *sq)
+{
+  int i;
+  XYZ sum = { 0, };
+
+  for (i = 0; i < sq->ntentacles; i++)
+    {
+      tentacle *t = &sq->tentacles[i];
+      int j = t->length / 3;  /* Pick a node toward the top */
+      node *n = &t->nodes[j];
+      sum.x += n->pos.x;
+      sum.y += n->pos.y;
+      sum.z += n->pos.z;
+    }
+
+  sum.x /= sq->ntentacles;
+  sum.y /= sq->ntentacles;
+  sum.z /= sq->ntentacles;
+
+  sum.x -= sq->pos.x;
+  sum.y -= sq->pos.y;
+  sum.z -= sq->pos.z;
+
+  return (-atan2 (sum.x, sum.z) * (180 / M_PI));
+}
+
+
+static void
+draw_head (ModeInfo *mi, squid *sq, GLfloat scale)
+{
+  int wire = MI_IS_WIREFRAME(mi);
+  int i = wire ? 8 : 64;
+  GLfloat c2[4];
+  GLfloat angle = head_angle (mi, sq);
+
+  scale *= 1.1;
+
+  glPushMatrix();
+  glTranslatef (sq->pos.x, sq->pos.y, sq->pos.z);
+  glScalef (sq->head_radius, sq->head_radius, sq->head_radius);
+  glScalef (scale, scale, scale);
+  glRotatef (90, 1, 0, 0);
+
+  memcpy (c2, sq->color, sizeof(c2));
+  if (opacity_arg < 1.0 && scale >= 1.0)
+    c2[3] *= 0.6;
+  glColor4fv (c2);
+  glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, c2);
+
+  glTranslatef (0, 0.3, 0);
+  glRotatef (angle, 0, 0, 1);
+
+  glScalef (1, 1.1, 1);
+  unit_dome (i, i/2, wire);
+  glRotatef (180, 0, 0, 1);
+  glScalef (1, 0.5, 1);
+  unit_dome (i, i/2, wire);
+
+  mi->polygon_count += i * i;
+  glPopMatrix();
+}
+
+
+static void
+draw_squid (ModeInfo *mi, squid *sq)
+{
+  int wire = MI_IS_WIREFRAME(mi);
+  int i;
+  glPushMatrix();
+  glRotatef (90, 1, 0, 0);
+
+  if (opacity_arg < 1.0)
+    draw_head (mi, sq, 0.75);
+
+  for (i = 0; i < sq->ntentacles; i++)
+    {
+      tentacle *t = &sq->tentacles[i];
+      int j;
+
+      glColor4fv (t->color);
+      glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, t->color);
+
+      if (wire)
+        {
+          glBegin (GL_LINE_STRIP);
+          for (j = 0; j < t->length; j++)
+            glVertex3f (t->nodes[j].pos.x,
+                        t->nodes[j].pos.y,
+                        t->nodes[j].pos.z);
+          glEnd();
+          mi->polygon_count += t->length;
+        }
+      else
+        {
+          GLfloat radius = t->radius * thickness_arg;
+          GLfloat rstep = radius / t->length;
+          int faces = 8;
+          glFrontFace (GL_CCW);
+          for (j = 0; j < t->length-1; j++)
+            {
+              int k;
+              node *n1 = &t->nodes[j];
+              node *n2 = &t->nodes[j+1];
+              GLfloat X = (n1->pos.x - n2->pos.x);
+              GLfloat Y = (n1->pos.y - n2->pos.y);
+              GLfloat Z = (n1->pos.z - n2->pos.z);
+              GLfloat L = sqrt (X*X + Y*Y + Z*Z);
+              GLfloat r2 = radius - rstep;
+
+              glPushMatrix();
+              glTranslatef (n1->pos.x, n1->pos.y, n1->pos.z);
+              glRotatef (-atan2 (X, Y)               * (180 / M_PI), 0, 0, 1);
+              glRotatef ( atan2 (Z, sqrt(X*X + Y*Y)) * (180 / M_PI), 1, 0, 0);
+
+              glBegin (wire ? GL_LINE_LOOP : GL_QUAD_STRIP);
+              for (k = 0; k <= faces; k++)
+                {
+                  GLfloat th  = k * M_PI * 2 / faces;
+                  GLfloat c = cos(th);
+                  GLfloat s = sin(th);
+                  GLfloat x1 = radius * c;
+                  GLfloat y1 = radius * s;
+                  GLfloat z1 = 0;
+                  GLfloat x2 = r2 * c;
+                  GLfloat y2 = r2 * s;
+                  GLfloat z2 = L;
+
+                  glNormal3f (x1, z1, y1);
+                  glVertex3f (x1, z1, y1);
+                  glVertex3f (x2, z2, y2);
+                  mi->polygon_count++;
+                }
+              glEnd();
+              glPopMatrix();
+              radius = r2;
+            }
+        }
+    }
+
+  draw_head (mi, sq, 1.0);
+
+  glPopMatrix();
+}
+
+
+static squid *
+make_squid (ModeInfo *mi, int which)
+{
+  squid *sq = calloc (1, sizeof(*sq));
+  int i;
+
+  sq->head_radius = head_radius_arg;
+  sq->thickness   = thickness_arg;
+  sq->ntentacles  = ntentacles_arg;
+
+  sq->color[0] = 0.1 + frand(0.7);
+  sq->color[1] = 0.5 + frand(0.5);
+  sq->color[2] = 0.1 + frand(0.7);
+  sq->color[3] = opacity_arg;
+
+  sq->from.x = sq->to.x = sq->pos.x = 200 - frand(400);
+  sq->from.y = sq->to.y = sq->pos.y = 200 - frand(400);
+  sq->from.z = sq->to.z = sq->pos.z = -frand(200);
+
+  sq->ratio = -frand(3);
+
+  if (which > 0)   /* Start others off screen, and moving in */
+    {
+      sq->from.x = sq->to.x = sq->pos.x = 800 + frand(500)
+        * (random()&1 ? 1 : -1);
+      sq->from.y = sq->to.y = sq->pos.y = 800 + frand(500)
+        * (random()&1 ? 1 : -1);
+      sq->ratio = 0;
+    }
+
+  if (do_pulse)
+    sq->pulse = frand(1.0);
+  sq->rate = 0.8 + frand(0.2);
+
+  sq->tentacles = (tentacle *)
+    calloc (sq->ntentacles, sizeof(*sq->tentacles));
+  for (i = 0; i < sq->ntentacles; i++)
+    {
+      int j;
+      tentacle *t = &sq->tentacles[i];
+      GLfloat shade = 0.75 + frand(0.25);
+
+      t->length   = 2 + length_arg * (0.8 + frand (0.4));
+      t->radius   = 0.05 + frand (0.95);
+      t->spacing  = 0.02 + frand (0.08);
+      t->friction = 0.7  + frand (0.18);
+      t->nodes = (node *) calloc (t->length + 1, sizeof (*t->nodes));
+
+      t->color[0] = shade * sq->color[0];
+      t->color[1] = shade * sq->color[1];
+      t->color[2] = shade * sq->color[2];
+      t->color[3] = sq->color[3];
+
+      for (j = 0; j < t->length; j++)
+        {
+          node *n = &t->nodes[j];
+          n->pos.x = sq->pos.x;
+          n->pos.y = sq->pos.y;
+          n->pos.z = sq->pos.z + j;
+        }
+    }
+
+  return sq;
+}
+
+/* qsort comparator for sorting squid by depth */
+static int
+cmp_squid (const void *aa, const void *bb)
+{
+  const squid *a = (squid *) aa;
+  const squid *b = (squid *) bb;
+  return ((int) (b->pos.y * 10000) -
+          (int) (a->pos.y * 10000));
+}
+
+
+static void
+free_squid (squid *sq)
+{
+  int i;
+  for (i = 0; i < sq->ntentacles; i++)
+    free (sq->tentacles[i].nodes);
+  free (sq->tentacles);
+  free (sq);
+}
+
+
+/* Window management, etc
+ */
+ENTRYPOINT void
+reshape_hydrostat (ModeInfo *mi, int width, int height)
+{
+  GLfloat h = (GLfloat) height / (GLfloat) width;
+
+  glViewport (0, 0, (GLint) width, (GLint) height);
+
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  gluPerspective (30.0, 1/h, 1.0, 100.0);
+
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+  gluLookAt( 0.0, 0.0, 30.0,
+             0.0, 0.0, 0.0,
+             0.0, 1.0, 0.0);
+
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
+  glClear(GL_COLOR_BUFFER_BIT);
+}
+
+
+
+ENTRYPOINT Bool
+hydrostat_handle_event (ModeInfo *mi, XEvent *event)
+{
+  hydrostat_configuration *bp = &bps[MI_SCREEN(mi)];
+  int w = MI_WIDTH(mi);
+  int h = MI_HEIGHT(mi);
+  int x, y;
+
+# ifdef USE_TRACKBALL
+  if (gltrackball_event_handler (event, bp->trackball,
+                                 MI_WIDTH (mi), MI_HEIGHT (mi),
+                                 &bp->button_down_p))
+    return True;
+# endif
+
+  switch (event->xany.type) {
+  case ButtonPress: case ButtonRelease:
+    x = event->xbutton.x;
+    y = event->xbutton.y;
+    break;
+  case MotionNotify:
+    x = event->xmotion.x;
+    y = event->xmotion.y;
+    break;
+  default:
+    x = y = 0;
+  }
+
+  x -= w/2;
+  y -= h/2;
+  x *= 0.7;
+  y *= 0.7;
+
+  if (event->xany.type == ButtonPress)
+    {
+      int i;
+      GLfloat D0 = 999999;
+
+      /* This is pretty halfassed hit detection, but it works ok... */
+      for (i = 0; i < MI_COUNT(mi); i++)
+        {
+          squid *s = bp->squids[i];
+          GLfloat X = s->pos.x - x;
+          GLfloat Y = s->pos.z - y;
+          GLfloat D = sqrt(X*X + Y*Y);
+          if (D < D0)
+            {
+              bp->dragging = i;
+              D0 = D;
+            }
+        }
+
+      if (D0 > 300)    /* Too far away, missed hit */
+        {
+          bp->dragging = -1;
+          return False;
+        }
+
+      bp->squids[bp->dragging]->ratio = -3;
+      bp->button_down_p = True;
+
+      return True;
+    }
+  else if (event->xany.type == ButtonRelease && bp->dragging >= 0)
+    {
+      bp->button_down_p = False;
+      bp->dragging = -1;
+      return True;
+    }
+  else if (event->xany.type == MotionNotify && bp->dragging >= 0)
+    {
+      squid *s = bp->squids[bp->dragging];
+      s->from.x = s->to.x = s->pos.x = x;
+      s->from.z = s->to.z = s->pos.z = y;
+      s->from.y = s->to.y = s->pos.y;
+      return True;
+    }
+
+  return False;
+}
+
+
+ENTRYPOINT void 
+init_hydrostat (ModeInfo *mi)
+{
+  int wire = MI_IS_WIREFRAME(mi);
+  hydrostat_configuration *bp;
+  int i;
+
+  if (!bps) {
+    bps = (hydrostat_configuration *)
+      calloc (MI_NUM_SCREENS(mi), sizeof (hydrostat_configuration));
+    if (!bps) {
+      fprintf(stderr, "%s: out of memory\n", progname);
+      exit(1);
+    }
+  }
+
+  bp = &bps[MI_SCREEN(mi)];
+
+  bp->glx_context = init_GL(mi);
+
+  reshape_hydrostat (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+
+  if (!wire)
+    {
+      GLfloat pos[4] = {1.0, 1.0, 1.0, 0.0};
+      GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0};
+      GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0};
+      GLfloat spc[4] = {0.0, 1.0, 1.0, 1.0};
+
+      glEnable(GL_LIGHTING);
+      glEnable(GL_LIGHT0);
+      glEnable(GL_DEPTH_TEST);
+      glEnable(GL_CULL_FACE);
+
+      glLightfv(GL_LIGHT0, GL_POSITION, pos);
+      glLightfv(GL_LIGHT0, GL_AMBIENT,  amb);
+      glLightfv(GL_LIGHT0, GL_DIFFUSE,  dif);
+      glLightfv(GL_LIGHT0, GL_SPECULAR, spc);
+    }
+
+  glShadeModel(GL_SMOOTH);
+
+  glEnable(GL_DEPTH_TEST);
+  glEnable(GL_NORMALIZE);
+
+  if (MI_COUNT(mi) <= 0)
+    MI_COUNT(mi) = 1;
+
+  if (random() & 1)
+    current_arg = -current_arg;
+
+  if (MI_COUNT(mi) == 1 || wire)
+    opacity_arg = 1.0;
+  if (opacity_arg < 0.1) opacity_arg = 0.1;
+  if (opacity_arg > 1.0) opacity_arg = 1.0;
+
+  bp->squids = (squid **) calloc (MI_COUNT(mi), sizeof(*bp->squids));
+  for (i = 0; i < MI_COUNT(mi); i++)
+    bp->squids[i] = make_squid (mi, i);
+
+  bp->dragging = -1;
+
+  if (opacity_arg < 1.0)
+    {
+      glEnable (GL_BLEND);
+      glBlendFunc (GL_SRC_ALPHA, GL_ONE);
+    }
+
+# ifdef USE_TRACKBALL
+  bp->trackball = gltrackball_init (True);
+# endif
+}
+
+
+ENTRYPOINT void
+draw_hydrostat (ModeInfo *mi)
+{
+  hydrostat_configuration *bp = &bps[MI_SCREEN(mi)];
+  Display *dpy = MI_DISPLAY(mi);
+  Window window = MI_WINDOW(mi);
+  int i;
+
+  if (!bp->glx_context)
+    return;
+
+  glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context));
+
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  glPushMatrix ();
+
+  glScalef (0.03, 0.03, 0.03);
+
+# ifdef USE_TRACKBALL
+  gltrackball_rotate (bp->trackball);
+# endif
+
+  mi->polygon_count = 0;
+
+  if (opacity_arg < 1.0)
+    qsort (bp->squids, MI_COUNT(mi), sizeof(*bp->squids), cmp_squid);
+
+  for (i = 0; i < MI_COUNT(mi); i++)
+    {
+      squid *sq = bp->squids[i];
+      move_squid (mi, sq);
+      draw_squid (mi, sq);
+      if (opacity_arg < 1.0)
+        glClear (GL_DEPTH_BUFFER_BIT);
+    }
+
+  if (! (random() % 700))  /* Reverse the flow every now and then */
+    current_arg = -current_arg;
+
+  glPopMatrix ();
+
+  if (mi->fps_p) do_fps (mi);
+  glFinish();
+
+  glXSwapBuffers(dpy, window);
+}
+
+
+ENTRYPOINT void
+release_hydrostat (ModeInfo *mi)
+{
+  hydrostat_configuration *bp = &bps[MI_SCREEN(mi)];
+  int i;
+  for (i = 0; i < MI_COUNT(mi); i++)
+    free_squid (bp->squids[i]);
+  free (bp->squids);
+}
+
+XSCREENSAVER_MODULE ("Hydrostat", hydrostat)
+
+#endif /* USE_GL */
diff --git a/hacks/glx/hydrostat.man b/hacks/glx/hydrostat.man
new file mode 100644 (file)
index 0000000..de75525
--- /dev/null
@@ -0,0 +1,103 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+hydrostat - Wiggly squid or jellyfish with many tentacles.
+.SH SYNOPSIS
+.B hydrostat
+[\-display \fIhost:display.screen\fP]
+[\-visual \fIvisual\fP]
+[\-window]
+[\-root]
+[\-delay \fInumber\fP]
+[\-speed \fInumber\fP]
+[\-count \fInumber\fP]
+[\-head-radius \fInumber\fP]
+[\-tentacles \fInumber\fP]
+[\-thickness \fInumber\fP]
+[\-length \fInumber\fP]
+[\-gravity \fInumber\fP]
+[\-current \fInumber\fP]
+[\-friction \fInumber\fP]
+[\-no-pulse]
+[\-wireframe]
+[\-fps]
+.SH DESCRIPTION
+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.
+.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 \-count \fInumber\fP
+Number of squid.  1 - 100.  Default: 10.
+.TP 8
+.B \-head-radius \fInumber\fP
+Head size.  10 - 100.  Default: 60.
+.TP 8
+.B \-tentacles \fInumber\fP
+Number of tentacles.  3 - 100.  Default: 40.
+.TP 8
+.B \-thickness \fInumber\fP
+Thickness of tentacles.  3 - 40.  Default: 18.
+.TP 8
+.B \-length \fInumber\fP
+Length of tentacles.  10 - 150.  Default: 70.
+.TP 8
+.B \-gravity \fInumber\fP
+Strength of gravity.  0 - 10.0.  Default: 0.5.
+.TP 8
+.B \-current \fInumber\fP
+Strength of current.  0.0 - 10.0.  Default: 0.25.
+.TP 8
+.B \-friction \fInumber\fP
+Coefficient of friction.  0.0 - 0.1.  Default: 0.02.
+.TP 8
+.B \-pulse | \-no-pulse
+Whether the squid should pulse. Default true.
+.TP 8
+.B \-wireframe | \-no-wireframe
+Render in wireframe instead of solid.
+.TP 8
+.B \-fps | \-no-fps
+Whether to show a frames-per-second display at the bottom 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)
+
+.BR http://soulwire.co.uk/experiments/muscular-hydrostats/
+.SH COPYRIGHT
+Copyright \(co 2016 by Justin Windle and 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
+Justin Windle and Jamie Zawinski.
index b4cc8afb24860239bf1e9f5ce28dd57a2b1ce561..4b81aef9ddb7f9e5e853c6f4be8e3730d6488bab 100644 (file)
@@ -87,6 +87,7 @@ static const char sccsid[] = "@(#)hypertorus.c  1.2 05/09/28 xlockmore";
 #ifdef STANDALONE
 # define DEFAULTS           "*delay:      25000 \n" \
                             "*showFPS:    False \n" \
+                           "*suppressRotationAnimation: True\n" \
 
 # define refresh_hypertorus 0
 # include "xlockmore.h"         /* from the xscreensaver distribution */
@@ -95,9 +96,6 @@ static const char sccsid[] = "@(#)hypertorus.c  1.2 05/09/28 xlockmore";
 #endif /* !STANDALONE */
 
 #ifdef USE_GL
-#ifndef HAVE_COCOA
-# include <X11/keysym.h>
-#endif
 
 #include "gltrackball.h"
 
@@ -505,6 +503,17 @@ static int hypertorus(ModeInfo *mi, double umin, double umax, double vmin,
     }
   }
 
+#if 0 /* #### not working */
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+#endif
+
   skew = num_spirals;
   ur = umax-umin;
   vr = vmax-vmin;
index 508229016decf6a94b2f80e09c54db7304f4647a..d92e147b0baf539c09a5b6d5b6ee9345e7ccc2c9 100644 (file)
@@ -22,6 +22,7 @@
                        "*showFPS:      False       \n" \
                        "*fpsSolid:     True        \n" \
                        "*wireframe:    False       \n" \
+                       "*suppressRotationAnimation: True\n" \
 
 # define refresh_hypnowheel 0
 # define release_hypnowheel 0
@@ -149,6 +150,14 @@ reshape_hypnowheel (ModeInfo *mi, int width, int height)
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
   glClear(GL_COLOR_BUFFER_BIT);
 }
 
index 5ad8a95fa24d6ab0db90c9b5595103ebfffe8465..5b49bf0cbb0227343d712de909778f2b15e43a1f 100644 (file)
 
 #include "screenhackI.h"
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # include <GL/glx.h>
 # include <GL/glu.h>
-#endif /* !HAVE_COCOA */
+#endif
+
+#ifdef HAVE_ANDROID
+# include <GLES/gl.h>
+#endif
 
 #ifdef HAVE_JWZGLES
 # include "jwzgles.h"
index a65e99fa94acfd4897688fe27d0b523753833ab3..2e94c1d498bb7ddef3b01517e4459c8133e17473 100644 (file)
@@ -39,6 +39,7 @@
 # define DEFAULTS           "*delay: 20000\n" \
                             "*showFPS: False\n" \
                             "*wireframe: False\n" \
+                           "*suppressRotationAnimation: True\n" \
 
 # define refresh_jigglypuff 0
 # define release_jigglypuff 0
@@ -960,6 +961,16 @@ ENTRYPOINT void draw_jigglypuff(ModeInfo *mi)
     glLoadIdentity();
     glTranslatef(0,0,-10);
 
+
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+    {
+      GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+      int o = (int) current_device_rotation();
+      if (o != 0 && o != 180 && o != -180)
+        glScalef (1/h, 1/h, 1/h);
+    }
+# endif
+
     glRotatef(js->angle, sin(js->axis), cos(js->axis), -sin(js->axis));
     glTranslatef(0, 0, 5);
     if(!(js->button_down)) {
index dc7b8c3db654e36527790693a3351d14c776d82a..541239308576d7b1daa96e459f16c36667b2d49f 100644 (file)
@@ -55,7 +55,8 @@
                  "*wireframe:          False   \n" \
                  "*desktopGrabber:   xscreensaver-getimage -no-desktop %s\n" \
                  "*grabDesktopImages:  False   \n" \
-                 "*chooseRandomImages: True    \n"
+                 "*chooseRandomImages: True    \n" \
+                 "*suppressRotationAnimation: True\n" \
 
 
 # define refresh_jigsaw 0
@@ -63,7 +64,7 @@
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
 # include "jwxyz.h"
 #else
 # include <X11/Xlib.h>
@@ -1337,6 +1338,14 @@ reshape_jigsaw (ModeInfo *mi, int width, int height)
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
   glClear(GL_COLOR_BUFFER_BIT);
 
   jc->line_thickness = (MI_IS_WIREFRAME (mi) ? 1 : MAX (1, height / 300.0));
@@ -1434,7 +1443,7 @@ draw_jigsaw (ModeInfo *mi)
   mi->polygon_count = 0;
 
   glPushMatrix ();
-  glRotatef(current_device_rotation(), 0, 0, 1);
+/*  glRotatef(current_device_rotation(), 0, 0, 1); */
   gltrackball_rotate (jc->trackball);
 
   animate (mi);
index fe2b93681aaadacf5be522c25aa32e80a4790afc..29df0d4e6cc24c9f51d61577f118f17044ca71ff 100644 (file)
@@ -2092,8 +2092,7 @@ show_europeanclub(ModeInfo *mi, unsigned long color, Trace *s)
   GLfloat gcolor1[4] = { 0, 0, 0, 1 };
   GLfloat gcolor2[4] = { 1, 1, 1, 1 };
   int slices = 16;
-  int divs = s->divisions;
-  divs = 4;
+  int divs = 4;
 
   /*    6   6
          +-+
diff --git a/hacks/glx/jwzgles.c b/hacks/glx/jwzgles.c
deleted file mode 100644 (file)
index 5b0b51a..0000000
+++ /dev/null
@@ -1,4166 +0,0 @@
-/* xscreensaver, Copyright (c) 2012-2015 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 compatibility shim to allow OpenGL 1.3 source code to work in an
-   OpenGLES environment, where almost every OpenGL 1.3 function has
-   been "deprecated".
-
-   There are two major operations going on here:
-
-     - Converting calls to glBegin + glVertex3f + glEnd to glDrawArrays
-     - Implementing display lists.
-
-
-   From an API point of view, OpenGL 1.3 and earlier code looks like this:
-
-      glLightfv (GL_LIGHT0, GL_POSITION, ...);
-      glLightfv (GL_LIGHT0, GL_AMBIENT,  ...);
-
-      glMatrixMode (GL_PROJECTION);
-      glLoadIdentity ();
-      gluPerspective (...);
-
-      glMatrixMode (GL_MODELVIEW);
-      glLoadIdentity ();
-      gluLookAt (...);
-
-      glPushMatrix ();
-
-      glRotatef (...);
-
-      glColor3f (...);
-
-      glBegin (GL_TRIANGLES);
-      glNormal3f (...);
-      glVertex3f (...);
-      glVertex3f (...);
-      glVertex3f (...);
-      glEnd ();
-
-      glPopMatrix ();
-
-      glFinish ();
-
-
-   OpenGLES broke that model by eliminating glBegin().  Instead of
-   iterating a sequence of vertexes, you need to pack your points into
-   an array first, e.g.:
-
-      GLfloat coords[] = {
-         0, 0, 0,
-         0, 1, 0,
-         ...
-      };
-
-      glDrawArrays (GL_TRIANGLES, 0, 3);
-
-   The projection model (glRotatef, etc.) works the same, but glColor()
-   is missing.  You're expected to encode that into your arrays.
-
-   Also, OpenGLES doesn't support display lists at all.
-
-
-   So this code shadows all of the functions that are allowed within
-   glBegin, builds up an array, and calls glDrawArrays at the end.
-
-   Likewise, it shadows all of the functions that are allowed within
-   glNewList and records those calls for later playback.
-
-
-   This code only handles OpenGLES 1.x, not 2.x.
-
-   OpenGLES 2.0 broke things further by eliminating the whole OpenGL
-   lighting model.  Instead of specifying the positions and properties
-   of your lights using the glLight* API, now you are expected to
-   implement it all yourself by downloading C-like code into the GPU
-   directly.  This is more flexible, in that if you wanted a completely
-   different lighting model than what OpenGL provides, you could do
-   that, but it leaves you needing to download boilerplate to reproduce
-   what used to be built in.
-
-
-   Incidentally, the OpenGL numbering scheme goes something like this:
-
-   OpenGL   1.0         1992
-   OpenGL   1.1         1997 (improved texture support)
-   OpenGL   1.2         1998 (nothing interesting)
-   OpenGL   1.3         2001 (multisampling, cubemaps)
-   OpenGL   1.4         2002 (added auto-mipmapping)
-   OpenGLES 1.0         2003 (deprecated 80% of the language; fork of OpenGL 1.3)
-   OpenGL   1.5         2003 (added VBOs)
-   OpenGLES 1.1         2004 (fork of OpenGL 1.5)
-   OpenGL   2.0         2004 (a political quagmire)
-   OpenGLES 2.0         2007 (deprecated 95% of the language; fork of OpenGL 2.0)
-   OpenGL   3.0         2008 (added FBOs, VAOs, deprecated 60% of the language)
-
-
-   Some things that are missing:
-
-    - glTexGeni, meaning no spherical environment-mapping textures.
-
-    - gluNewTess, meaning no tesselation of complex objects.
-
-    - glMap2f mesh evaluators, meaning no Utah Teapot.
-
-    - glPolygonMode with GL_LINE or GL_POINT, meaning no wireframe modes
-      that do hidden-surface removal.
-
-    - glSelectBuffer, meaning no mouse-hit detection on rendered objects.
-
-    - gluNewQuadric, gluCylinder, etc: rewrite your code to use tube.c, etc.
-
-    - Putting verts in a display list without a wrapping glBegin.
-      I didn't realize that even worked!  Lockward used to do that,
-      before I fixed it to not.
-
-    - Not every function is implemented; just the ones that I needed for
-      xscreensaver.  However, the trivial ones are trivial to enable
-      as they come up.  Harder ones will be harder.
-
-   As a result of that, these savers look wrong:
-
-      atlantis        Uses EYE_PLANE.
-      blocktube       Uses SPHERE_MAP.
-      dnalogo         Uses GLUtesselator.
-      extrusion       Uses all kinds of GLUT crap.
-      flyingtoasters  Uses SPHERE_MAP.
-      winduprobot     Uses SPHERE_MAP.
-      jigglypuff      Uses SPHERE_MAP (in chrome mode), GL_LINE (in wireframe)
-      jigsaw          Uses GLUtesselator.
-      pinion         Uses glSelectBuffer and gluPickMatrix for mouse-clicks.
-      pipes           Uses glMap2f for the Utah Teapot.
-      polyhedra       Uses GLUtesselator (concave objects); also Utah Teapot.
-      skytentacles    Uses GL_LINE in -cel mode.
-      timetunnel      Uses GL_CONSTANT_ALPHA and all kinds of other stuff.
-*/
-
-
-#undef DEBUG
-
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif /* HAVE_CONFIG_H */
-
-#ifdef HAVE_JWZGLES    /* whole file */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <math.h>
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-
-#if defined(USE_IPHONE)
-# include <OpenGLES/ES1/gl.h>
-# include <OpenGLES/ES1/glext.h>
-#elif defined(HAVE_COCOA)
-# include <OpenGL/gl.h>
-# include <OpenGL/glu.h>
-#elif defined(HAVE_ANDROID)
-# include <GLES/gl.h>
-#else /* real X11 */
-# ifndef  GL_GLEXT_PROTOTYPES
-#  define GL_GLEXT_PROTOTYPES /* for glBindBuffer */
-# endif
-# include <GL/glx.h>
-# include <GL/glu.h>
-#endif
-
-#include "jwzglesI.h"
-
-#define STRINGIFY(X) #X
-
-#undef countof
-#define countof(x) (sizeof((x))/sizeof((*x)))
-
-#undef  Assert
-
-#ifdef HAVE_COCOA
-  extern void jwxyz_abort (const char *fmt, ...) __dead2;
-# define Assert(C,S) do { if (!(C)) { jwxyz_abort ("%s",S); }} while(0)
-#else
-# define Assert(C,S) do { \
-    if (!(C)) { \
-      fprintf (stderr, "jwzgles: %s\n", S); \
-      abort(); \
-    }} while(0)
-#endif
-
-
-typedef struct { GLfloat x, y, z; }    XYZ;
-typedef struct { GLfloat x, y, z, w; } XYZW;
-typedef struct { GLfloat s, t, r, q; } STRQ;
-typedef struct { GLfloat r, g, b, a; } RGBA;
-
-
-/* Used to record all calls to glVertex3f, glNormal3f, etc. 
-   while inside glBegin / glEnd so that we can convert that
-   to a single call to glDrawArrays.
- */
-typedef struct {
-  int mode;
-  int count, size;     /* size of each array */
-
-  XYZW *verts;         /* Arrays being built */
-  XYZ  *norms;
-  STRQ *tex;
-  RGBA *color;
-
-  int ncount;          /* How many normals, tex coords and colors were */
-  int tcount;          /* used.  We optimize based on "0, 1, or many". */
-  int ccount;
-  int materialistic;   /* Whether glMaterial was called inside glBegin */
-
-  XYZ  cnorm;          /* Prevailing normal/texture/color while building */
-  STRQ ctex;
-  RGBA ccolor;
-
-} vert_set;
-
-
-typedef void (*list_fn_cb) (void);
-
-
-/* We need this nonsense because you can't cast a double to a void*
-   or vice versa.  They tend to be passed in different registers,
-   and you need to know about that because it's still 1972 here.
- */
-typedef union {
-  const void *v; GLfloat f; GLuint i; GLshort s; GLdouble d;
-} void_int;
-
-typedef struct {               /* saved args for glDrawArrays */
-  int binding, size, type, stride, bytes;
-  void *data;
-} draw_array;
-
-typedef enum {                 /* shorthand describing arglist signature */
-  PROTO_VOID,  /* no args */
-  PROTO_I,     /* 1 int arg */
-  PROTO_F,     /* 1 float arg */
-  PROTO_II,    /* int, int */
-  PROTO_FF,    /* float, float */
-  PROTO_IF,    /* int, float */
-  PROTO_III,   /* int, int, int */
-  PROTO_FFF,   /* float, float, float */
-  PROTO_IIF,   /* int, int, float */
-  PROTO_IIII,  /* int, int, int, int */
-  PROTO_FFFF,  /* float, float, float, float */
-  PROTO_IIV,   /* int, int[4] */
-  PROTO_IFV,   /* int, float[4] */
-  PROTO_IIIV,  /* int, int, int[4] */
-  PROTO_IIFV,  /* int, int, float[4] */
-  PROTO_FV16,  /* float[16] */
-  PROTO_ARRAYS /* glDrawArrays */
-} fn_proto;
-
-typedef struct {               /* A single element of a display list */
-  const char *name;
-  list_fn_cb fn;               /* saved function pointer */
-  fn_proto proto;              /* arglist prototype */
-  draw_array *arrays;          /* args for glDrawArrays */
-  void_int argv[16];           /* args for everything else */
-} list_fn;
-
-
-typedef struct {       /* a display list: saved activity within glNewList */
-  int id;
-  int size, count;
-  list_fn *fns;
-
-  /* Named buffer that should be freed when this display list is deleted. */
-  GLuint buffer;
-
-} list;
-
-
-typedef struct {       /* All display lists */
-  list *lists;
-  int count, size;
-} list_set;
-
-
-#define ISENABLED_TEXTURE_2D   (1<<0)
-#define ISENABLED_TEXTURE_GEN_S        (1<<1)
-#define ISENABLED_TEXTURE_GEN_T        (1<<2)
-#define ISENABLED_TEXTURE_GEN_R        (1<<3)
-#define ISENABLED_TEXTURE_GEN_Q        (1<<4)
-#define ISENABLED_LIGHTING     (1<<5)
-#define ISENABLED_BLEND                (1<<6)
-#define ISENABLED_DEPTH_TEST   (1<<7)
-#define ISENABLED_CULL_FACE    (1<<8)
-#define ISENABLED_NORMALIZE    (1<<9)
-#define ISENABLED_FOG          (1<<10)
-#define ISENABLED_COLMAT       (1<<11)
-#define ISENABLED_VERT_ARRAY   (1<<12)
-#define ISENABLED_NORM_ARRAY   (1<<13)
-#define ISENABLED_TEX_ARRAY    (1<<14)
-#define ISENABLED_COLOR_ARRAY  (1<<15)
-#define ISENABLED_ALPHA_TEST   (1<<16)
-
-
-typedef struct {
-  GLuint mode;
-  GLfloat obj[4], eye[4];
-} texgen_state;
-
-
-typedef struct {       /* global state */
-
-  vert_set set;                /* set being built */
-
-  int compiling_list;  /* list id if inside glNewList; 0 means immediate */
-  int replaying_list;  /* depth of call stack to glCallList */
-  int compiling_verts; /* inside glBegin */
-
-  list_set lists;      /* saved lists */
-
-  unsigned long enabled;       /* enabled flags, immediate mode */
-  unsigned long list_enabled;  /* and for the list-in-progress */
-
-  texgen_state s, t, r, q;
-
-} jwzgles_state;
-
-
-static jwzgles_state *state = 0;
-
-
-#ifdef DEBUG
-# define LOG(A)                fprintf(stderr,"jwzgles: " A "\n")
-# define LOG1(A,B)             fprintf(stderr,"jwzgles: " A "\n",B)
-# define LOG2(A,B,C)           fprintf(stderr,"jwzgles: " A "\n",B,C)
-# define LOG3(A,B,C,D)         fprintf(stderr,"jwzgles: " A "\n",B,C,D)
-# define LOG4(A,B,C,D,E)       fprintf(stderr,"jwzgles: " A "\n",B,C,D,E)
-# define LOG5(A,B,C,D,E,F)     fprintf(stderr,"jwzgles: " A "\n",B,C,D,E,F)
-# define LOG6(A,B,C,D,E,F,G)   fprintf(stderr,"jwzgles: " A "\n",B,C,D,E,F,G)
-# define LOG7(A,B,C,D,E,F,G,H) fprintf(stderr,"jwzgles: " A "\n",B,C,D,E,F,G,H)
-# define LOG8(A,B,C,D,E,F,G,H,I)\
-         fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I)
-# define LOG9(A,B,C,D,E,F,G,H,I,J)\
-         fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I,J)
-# define LOG10(A,B,C,D,E,F,G,H,I,J,K)\
-         fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I,J,K)
-# define LOG17(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R)\
-         fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R)
-# define CHECK(S) check_gl_error(S)
-#else
-# define LOG(A)                       /* */
-# define LOG1(A,B)                    /* */
-# define LOG2(A,B,C)                  /* */
-# define LOG3(A,B,C,D)                /* */
-# define LOG4(A,B,C,D,E)              /* */
-# define LOG5(A,B,C,D,E,F)            /* */
-# define LOG6(A,B,C,D,E,F,G)          /* */
-# define LOG7(A,B,C,D,E,F,G,H)        /* */
-# define LOG8(A,B,C,D,E,F,G,H,I)      /* */
-# define LOG9(A,B,C,D,E,F,G,H,I,J)    /* */
-# define LOG10(A,B,C,D,E,F,G,H,I,J,K) /* */
-# define LOG17(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R) /* */
-# define CHECK(S)              /* */
-#endif
-
-#ifdef DEBUG
-static const char *
-mode_desc (int mode)   /* for debugging messages */
-{
-  switch (mode) {
-# define SS(X) case GL_##X: return STRINGIFY(X);
-  SS(ALPHA)
-  SS(ALPHA_TEST)
-  SS(AMBIENT)
-  SS(AMBIENT_AND_DIFFUSE)
-  SS(ARRAY_BUFFER)
-  SS(AUTO_NORMAL)
-  SS(BACK)
-  SS(BLEND)
-  SS(BLEND_DST)
-  SS(BLEND_SRC)
-  SS(BLEND_SRC_ALPHA)
-  SS(BYTE)
-  SS(C3F_V3F)
-  SS(C4F_N3F_V3F)
-  SS(C4UB_V2F)
-  SS(C4UB_V3F)
-  SS(CCW)
-  SS(CLAMP)
-  SS(COLOR_ARRAY)
-  SS(COLOR_ARRAY_BUFFER_BINDING);
-  SS(COLOR_MATERIAL)
-  SS(COLOR_MATERIAL_FACE)
-  SS(COLOR_MATERIAL_PARAMETER)
-  SS(COMPILE)
-  SS(CULL_FACE)
-  SS(CW)
-  SS(DECAL)
-  SS(DEPTH_BUFFER_BIT)
-  SS(DEPTH_TEST)
-  SS(DIFFUSE)
-  SS(DOUBLEBUFFER)
-  SS(DST_ALPHA)
-  SS(DST_COLOR)
-  SS(DYNAMIC_DRAW)
-  SS(ELEMENT_ARRAY_BUFFER)
-  SS(EYE_LINEAR)
-  SS(EYE_PLANE)
-  SS(FEEDBACK)
-  SS(FILL)
-  SS(FLAT)
-  SS(FLOAT)
-  SS(FOG)
-  SS(FRONT)
-  SS(FRONT_AND_BACK)
-  SS(GREATER)
-  SS(INTENSITY)
-  SS(INVALID_ENUM)
-  SS(INVALID_OPERATION)
-  SS(INVALID_VALUE)
-  SS(LESS)
-  SS(LIGHT0)
-  SS(LIGHT1)
-  SS(LIGHT2)
-  SS(LIGHT3)
-  SS(LIGHTING)
-  SS(LIGHT_MODEL_AMBIENT)
-  SS(LIGHT_MODEL_COLOR_CONTROL)
-  SS(LIGHT_MODEL_LOCAL_VIEWER)
-  SS(LIGHT_MODEL_TWO_SIDE)
-  SS(LINE)
-  SS(LINEAR)
-  SS(LINEAR_MIPMAP_LINEAR)
-  SS(LINEAR_MIPMAP_NEAREST)
-  SS(LINES)
-  SS(LINE_LOOP)
-  SS(LINE_STRIP)
-  SS(LUMINANCE)
-  SS(LUMINANCE_ALPHA)
-  SS(MATRIX_MODE)
-  SS(MODELVIEW)
-  SS(MODULATE)
-  SS(N3F_V3F)
-  SS(NEAREST)
-  SS(NEAREST_MIPMAP_LINEAR)
-  SS(NEAREST_MIPMAP_NEAREST)
-  SS(NORMALIZE)
-  SS(NORMAL_ARRAY)
-  SS(NORMAL_ARRAY_BUFFER_BINDING);
-  SS(OBJECT_LINEAR)
-  SS(OBJECT_PLANE)
-  SS(ONE_MINUS_DST_ALPHA)
-  SS(ONE_MINUS_DST_COLOR)
-  SS(ONE_MINUS_SRC_ALPHA)
-  SS(ONE_MINUS_SRC_COLOR)
-  SS(OUT_OF_MEMORY)
-  SS(PACK_ALIGNMENT)
-  SS(POINTS)
-  SS(POLYGON)
-  SS(POLYGON_OFFSET_FILL)
-  SS(POLYGON_SMOOTH)
-  SS(POLYGON_STIPPLE)
-  SS(POSITION)
-  SS(PROJECTION)
-  SS(Q)
-  SS(QUADS)
-  SS(QUAD_STRIP)
-  SS(R)
-  SS(RENDER)
-  SS(REPEAT)
-  SS(RGB)
-  SS(RGBA)
-  SS(RGBA_MODE)
-  SS(S)
-  SS(SELECT)
-  SS(SEPARATE_SPECULAR_COLOR)
-  SS(SHADE_MODEL)
-  SS(SHININESS)
-  SS(SHORT)
-  SS(SINGLE_COLOR)
-  SS(SMOOTH)
-  SS(SPECULAR)
-  SS(SPHERE_MAP)
-  SS(SRC_ALPHA)
-  SS(SRC_ALPHA_SATURATE)
-  SS(SRC_COLOR)
-  SS(STACK_OVERFLOW)
-  SS(STACK_UNDERFLOW)
-  SS(STATIC_DRAW)
-  SS(STENCIL_BUFFER_BIT)
-  SS(T)
-  SS(T2F_C3F_V3F)
-  SS(T2F_C4F_N3F_V3F)
-  SS(T2F_C4UB_V3F)
-  SS(T2F_N3F_V3F)
-  SS(T2F_V3F)
-  SS(T4F_C4F_N3F_V4F)
-  SS(T4F_V4F)
-  SS(TEXTURE)
-  SS(TEXTURE_1D)
-  SS(TEXTURE_2D)
-  SS(TEXTURE_ALPHA_SIZE)
-  SS(TEXTURE_BINDING_2D)
-  SS(TEXTURE_BLUE_SIZE)
-  SS(TEXTURE_BORDER)
-  SS(TEXTURE_BORDER_COLOR)
-  SS(TEXTURE_COMPONENTS)
-  SS(TEXTURE_COORD_ARRAY)
-  SS(TEXTURE_COORD_ARRAY_BUFFER_BINDING);
-  SS(TEXTURE_ENV)
-  SS(TEXTURE_ENV_COLOR)
-  SS(TEXTURE_ENV_MODE)
-  SS(TEXTURE_GEN_MODE)
-  SS(TEXTURE_GEN_Q)
-  SS(TEXTURE_GEN_R)
-  SS(TEXTURE_GEN_S)
-  SS(TEXTURE_GEN_T)
-  SS(TEXTURE_GREEN_SIZE)
-  SS(TEXTURE_HEIGHT)
-  SS(TEXTURE_INTENSITY_SIZE)
-  SS(TEXTURE_LUMINANCE_SIZE)
-  SS(TEXTURE_MAG_FILTER)
-  SS(TEXTURE_MIN_FILTER)
-  SS(TEXTURE_RED_SIZE)
-  SS(TEXTURE_WRAP_S)
-  SS(TEXTURE_WRAP_T)
-  SS(TRIANGLES)
-  SS(TRIANGLE_FAN)
-  SS(TRIANGLE_STRIP)
-  SS(UNPACK_ALIGNMENT)
-  SS(UNPACK_ROW_LENGTH)
-  SS(UNSIGNED_BYTE)
-  SS(UNSIGNED_INT_8_8_8_8_REV)
-  SS(UNSIGNED_SHORT)
-  SS(V2F)
-  SS(V3F)
-  SS(VERTEX_ARRAY)
-  SS(VERTEX_ARRAY_BUFFER_BINDING);
-/*SS(COLOR_BUFFER_BIT) -- same value as GL_LIGHT0 */
-# undef SS
-  case (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT):
-    return "DEPTH_BUFFER_BIT | COLOR_BUFFER_BIT";
-/* Oops, same as INVALID_ENUM.
-  case (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT):
-    return "DEPTH_BUFFER_BIT | STENCIL_BUFFER_BIT";
-*/
-  case (GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT):
-    return "COLOR_BUFFER_BIT | STENCIL_BUFFER_BIT";
-  case (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT):
-    return "DEPTH_BUFFER_BIT | COLOR_BUFFER_BIT | STENCIL_BUFFER_BIT";
-  default:
-    {
-      static char buf[255];
-      sprintf (buf, "0x%04X", mode);
-      return buf;
-    }
-  }
-}
-
-static void
-check_gl_error (const char *s)
-{
-  GLenum i = glGetError();
-  if (i == GL_NO_ERROR) return;
-  fprintf (stderr, "jwzgles: GL ERROR: %s: %s\n", s, mode_desc(i));
-}
-
-#endif /* DEBUG */
-
-
-static void
-make_room (const char *name, void **array, int span, int *count, int *size)
-{
-  if (*count + 1 >= *size)
-    {
-      int new_size = (*count + 20) * 1.2;   /* mildly exponential */
-      *array = realloc (*array, new_size * span);
-      Assert (*array, "out of memory");
-      /* LOG3("%s: grew %d -> %d", name, *size, new_size); */
-      *size = new_size;
-    }
-}
-
-
-void
-jwzgles_reset (void)
-{
-  if (! state)
-    state = (jwzgles_state *) calloc (1, sizeof (*state));
-
-  if (state->lists.lists)
-    {
-      state->compiling_list = 0;
-      if (state->lists.count)
-        jwzgles_glDeleteLists (1, state->lists.count);
-      free (state->lists.lists);
-    }
-
-  if (state->set.verts)   free (state->set.verts);
-  if (state->set.norms)   free (state->set.norms);
-  if (state->set.tex)     free (state->set.tex);
-  if (state->set.color)   free (state->set.color);
-
-  memset (state, 0, sizeof(*state));
-
-  state->s.mode = state->t.mode = state->r.mode = state->q.mode =
-    GL_EYE_LINEAR;
-  state->s.obj[0] = state->s.eye[0] = 1;  /* s = 1 0 0 0 */
-  state->t.obj[1] = state->t.eye[1] = 1;  /* t = 0 1 0 0 */
-}
-
-
-int
-jwzgles_glGenLists (int n)
-{
-  int i;
-  int ret = 0;
-
-  Assert (!state->compiling_verts, "glGenLists not allowed inside glBegin");
-
-  /* Ensure space in state->lists, clear the one at the end, and tick counter
-     Note that lists are never really deleted, and we can never re-use elements
-     of this array.  glDeleteLists zeroes out the contents of the list, but
-     the list ID is still valid for use with glNewList forever.
-     #### So maybe this should be a linked list instead of an array.
-  */
-  for (i = 0; i < n; i++)
-    {
-      list *L;
-      int id = 0;
-      make_room ("glGenLists", 
-                 (void **) &state->lists.lists,
-                 sizeof (*state->lists.lists),
-                 &state->lists.count, &state->lists.size);
-      state->lists.count++;
-      id = state->lists.count;
-      L = &state->lists.lists[id-1];
-
-      memset (L, 0, sizeof (*L));
-      L->id = id;
-      if (ret == 0) ret = id;
-      LOG1("glGenLists -> %d", L->id);
-    }
-
-  /* Return the ID of the first list allocated */
-
-  return ret;
-}
-
-
-void
-jwzgles_glNewList (int id, int mode)
-{
-  list *L;
-  Assert (id > 0 && id <= state->lists.count, "glNewList: bogus ID");
-  Assert (mode == GL_COMPILE, "glNewList: bad mode");
-  Assert (!state->compiling_verts, "glNewList not allowed inside glBegin");
-  Assert (!state->compiling_list, "nested glNewList");
-  Assert (state->set.count == 0, "missing glEnd");
-
-  L = &state->lists.lists[id-1];
-  Assert (L->id == id, "glNewList corrupted");
-
-  if (L->count != 0) jwzgles_glDeleteLists (L->id, 1); /* Overwriting */
-  Assert (L->count == 0, "glNewList corrupted");
-  
-  state->compiling_list = id;
-
-  state->list_enabled = state->enabled;
-
-  LOG1("glNewList -> %d", id);
-}
-
-
-static void save_arrays (list_fn *, int);
-static void restore_arrays (list_fn *, int);
-static void copy_array_data (draw_array *, int, const char *);
-static void optimize_arrays (void);
-static void generate_texture_coords (GLuint, GLuint);
-
-
-void
-jwzgles_glEndList (void)
-{
-  Assert (state->compiling_list, "extra glEndList");
-  Assert (state->set.count == 0, "missing glEnd");
-  Assert (!state->compiling_verts, "glEndList not allowed inside glBegin");
-  LOG1("glEndList %d", state->compiling_list);
-  optimize_arrays();
-  state->compiling_list = 0;
-  state->list_enabled = state->enabled;
-}
-
-
-static void
-list_push (const char * const name, 
-           list_fn_cb fn, fn_proto proto, void_int *av)
-{
-  list *L;
-  list_fn *F;
-  int i;
-
-  Assert (state->compiling_list > 0, "not inside glNewList");
-  Assert (state->compiling_list <= state->lists.count, "glNewList corrupted");
-
-  L = &state->lists.lists[state->compiling_list-1];
-  Assert (L, "glNewList: no list");
-
-  make_room ("glNewLists", 
-             (void **) &L->fns, sizeof (*L->fns),
-             &L->count, &L->size);
-  memset (&L->fns[L->count], 0, sizeof (*L->fns));
-  F = L->fns + L->count;
-
-  F->name = name;
-  F->fn = fn;
-  F->proto = proto;
-  if (proto != PROTO_VOID)
-    for (i = 0; i < countof(F->argv); i++)
-      F->argv[i] = av[i];
-
-# ifdef DEBUG
-  switch (proto) {
-  case PROTO_VOID:
-    LOG1 ("  push %-12s", name);
-    break;
-  case PROTO_I:
-    if (fn == (list_fn_cb) &jwzgles_glBegin ||
-        fn == (list_fn_cb) &jwzgles_glFrontFace ||
-        fn == (list_fn_cb) &jwzgles_glEnable ||
-        fn == (list_fn_cb) &jwzgles_glDisable ||
-        fn == (list_fn_cb) &jwzgles_glEnableClientState ||
-        fn == (list_fn_cb) &jwzgles_glDisableClientState ||
-        fn == (list_fn_cb) &jwzgles_glShadeModel ||
-        fn == (list_fn_cb) &jwzgles_glMatrixMode)
-      LOG2 ("  push %-12s %s", name, mode_desc (av[0].i));
-    else
-      LOG2 ("  push %-12s %d", name, av[0].i);
-    break;
-  case PROTO_F:
-    LOG2 ("  push %-12s %7.3f", name, av[0].f);
-    break;
-  case PROTO_II:
-    if (fn == (list_fn_cb) &jwzgles_glBindTexture ||
-        fn == (list_fn_cb) &jwzgles_glBindBuffer)
-      LOG3 ("  push %-12s %s %d", name, mode_desc (av[0].i), av[1].i);
-    else
-      LOG3 ("  push %-12s %d %d", name, av[0].i, av[1].i);
-    break;
-  case PROTO_FF:
-    LOG3 ("  push %-12s %7.3f %7.3f", name, av[0].f, av[1].f);
-    break;
-  case PROTO_IF:
-    LOG3 ("  push %-12s %s %7.3f", name, mode_desc (av[0].i), av[1].f);
-    break;
-  case PROTO_III:
-  case PROTO_ARRAYS:
-    if (fn == (list_fn_cb) &jwzgles_glDrawArrays ||
-        fn == (list_fn_cb) &jwzgles_glTexParameteri)
-      LOG4 ("  push %-12s %s %d %d", name, mode_desc (av[0].i), 
-            av[1].i, av[2].i);
-    else
-      LOG4 ("  push %-12s %d %d %d", name, av[0].i, av[1].i, av[2].i);
-    break;
-  case PROTO_FFF:
-    LOG4 ("  push %-12s %7.3f %7.3f %7.3f", name, av[0].f, av[1].f, av[2].f);
-    break;
-  case PROTO_IIF:
-    LOG4 ("  push %-12s %s %s %7.3f", name,
-             mode_desc(av[0].i), mode_desc(av[1].i), av[2].f);
-    break;
-  case PROTO_IIII:
-    LOG5 ("  push %-12s %d %d %d %d", name, 
-          av[0].i, av[1].i, av[2].i, av[3].i);
-    break;
-  case PROTO_FFFF:
-    LOG5 ("  push %-12s %7.3f %7.3f %7.3f %7.3f", name,
-             av[0].f, av[1].f, av[2].f, av[3].f);
-    break;
-  case PROTO_IFV:
-    LOG6 ("  push %-12s %s %3.1f %3.1f %3.1f %3.1f", name, mode_desc (av[0].i),
-             av[1].f, av[2].f, av[3].f, av[4].f);
-    break;
-  case PROTO_IIV:
-    LOG6 ("  push %-12s %s %d %d %d %d", name, mode_desc (av[0].i),
-             av[1].i, av[2].i, av[3].i, av[4].i);
-    break;
-  case PROTO_IIFV:
-    LOG7 ("  push %-12s %s %-8s %3.1f %3.1f %3.1f %3.1f", name,
-          mode_desc (av[0].i), mode_desc (av[1].i),
-             av[2].f, av[3].f, av[4].f, av[5].f);
-    break;
-  case PROTO_IIIV:
-    LOG7 ("  push %-12s %s %-8s %3d %3d %3d %3d", name,
-          mode_desc (av[0].i), mode_desc (av[1].i),
-             av[2].i, av[3].i, av[4].i, av[5].i);
-    break;
-  case PROTO_FV16:
-    LOG17 ("  push %-12s ["
-           "%8.3f %8.3f %8.3f %8.3f "  "\n\t\t\t       "
-           "%8.3f %8.3f %8.3f %8.3f "  "\n\t\t\t       "
-           "%8.3f %8.3f %8.3f %8.3f "  "\n\t\t\t       "
-           "%8.3f %8.3f %8.3f %8.3f ]",
-           name,
-           av[0].f,  av[1].f,  av[2].f,  av[3].f,
-           av[4].f,  av[5].f,  av[6].f,  av[7].f,
-           av[8].f,  av[9].f,  av[10].f, av[11].f,
-           av[12].f, av[13].f, av[14].f, av[15].f);
-    break;
-  default:
-    Assert (0, "bogus prototype");
-    break;
-  }
-# endif /* DEBUG */
-
-  if (proto == PROTO_ARRAYS) /* glDrawArrays */
-    save_arrays (F, av[1].i + av[2].i);
-
-  L->count++;
-}
-
-
-void
-jwzgles_glBegin (int mode)
-{
-  Assert (!state->compiling_verts, "nested glBegin");
-  state->compiling_verts++;
-
-  /* Only these commands are allowed inside glBegin:
-
-     glVertex          -- not allowed outside
-     glColor
-     glSecondaryColor
-     glIndex
-     glNormal
-     glFogCoord
-     glTexCoord
-     glMultiTexCoord
-     glVertexAttrib
-     glEvalCoord
-     glEvalPoint
-     glArrayElement    -- not allowed outside
-     glMaterial
-     glEdgeFlag
-     glCallList
-     glCallLists
-   */
-
-  if (!state->replaying_list)
-    LOG2 ("%sglBegin %s", 
-          (state->compiling_list || state->replaying_list ? "  " : ""),
-          mode_desc (mode));
-
-  Assert (state->set.count == 0, "glBegin corrupted");
-  state->set.mode   = mode;
-  state->set.count  = 0;
-  state->set.ncount = 0;
-  state->set.tcount = 0;
-  state->set.ccount = 0;
-}
-
-
-void
-jwzgles_glDeleteLists (int id0, int range)
-{
-  Assert (!state->compiling_verts, "glDeleteLists not allowed inside glBegin");
-
-  if (state->compiling_list)
-    {
-      void_int vv[2];
-      vv[0].i = id0;
-      vv[1].i = range;
-      list_push ("glDeleteLists", (list_fn_cb) &jwzgles_glDeleteLists, 
-                 PROTO_II, vv);
-    }
-  else
-    {
-      int id;
-
-      if (!state->replaying_list)
-        LOG2 ("glDeleteLists %d %d", id0, range);
-
-      for (id = id0 + range - 1; id >= id0; id--)
-        {
-          int i;
-          list *L;
-          if (id == 0) continue;  /* People do this stupid thing */
-          if (id > state->lists.count) break;  /* this too */
-          Assert (id > 0 && id <= state->lists.count,
-                  "glDeleteLists: bogus ID");
-          L = &state->lists.lists[id-1];
-          Assert (L->id == id, "glDeleteLists corrupted");
-
-          for (i = 0; i < L->count; i++)
-            {
-              list_fn *lf = &L->fns[i];
-              if (lf->arrays)
-                {
-                  int j;
-                  for (j = 0; j < 4; j++)
-                    /* If there's a binding, 'data' is an index, not a ptr. */
-                    if (!lf->arrays[j].binding &&
-                        lf->arrays[j].data)
-                      free (lf->arrays[j].data);
-                  free (lf->arrays);
-                }
-            }
-          if (L->fns) 
-            free (L->fns);
-          if (L->buffer)
-            glDeleteBuffers (1, &L->buffer);
-
-          memset (L, 0, sizeof (*L));
-          L->id = id;
-        }
-    }
-}
-
-
-extern GLboolean
-jwzgles_glIsList (GLuint id)
-{
-  return (id > 0 && id < state->lists.count);
-}
-
-
-
-void
-jwzgles_glNormal3fv (const GLfloat *v)
-{
-  if (state->compiling_list && !state->compiling_verts)
-    {
-      void_int vv[3];
-      vv[0].f = v[0];
-      vv[1].f = v[1];
-      vv[2].f = v[2];
-      list_push ("glNormal3f", (list_fn_cb) &jwzgles_glNormal3f, 
-                 PROTO_FFF, vv);
-    }
-  else
-    {
-      if (!state->replaying_list)
-        LOG5 ("%s%sglNormal3f   %7.3f %7.3f %7.3f",
-              (state->compiling_list || state->replaying_list ? "  " : ""),
-              (state->compiling_verts ? "  rec  " : ""),
-              v[0], v[1], v[2]);
-
-      if (state->compiling_verts)      /* inside glBegin */
-        {
-          state->set.cnorm.x = v[0];
-          state->set.cnorm.y = v[1];
-          state->set.cnorm.z = v[2];
-          state->set.ncount++;
-          if (state->set.count > 0 && state->set.ncount == 1)  /* not first! */
-            state->set.ncount++;
-        }
-      else                             /* outside glBegin */
-        {
-          glNormal3f (v[0], v[1], v[2]);
-          CHECK("glNormal3f");
-        }
-    }
-}
-
-
-void
-jwzgles_glNormal3f (GLfloat x, GLfloat y, GLfloat z)
-{
-  GLfloat v[3];
-  v[0] = x;
-  v[1] = y;
-  v[2] = z;
-  jwzgles_glNormal3fv (v);
-}
-
-
-void
-jwzgles_glTexCoord4fv (const GLfloat *v)
-{
-  if (state->compiling_list && !state->compiling_verts)
-    {
-      void_int vv[4];
-      vv[0].f = v[0];
-      vv[1].f = v[1];
-      vv[2].f = v[2];
-      vv[3].f = v[3];
-      list_push ("glTexCoord4f", (list_fn_cb) &jwzgles_glTexCoord4f,
-                 PROTO_FFFF, vv);
-    }
-  else
-    {
-      if (!state->replaying_list)
-        LOG6 ("%s%sglTexCoord4f %7.3f %7.3f %7.3f %7.3f", 
-              (state->compiling_list || state->replaying_list ? "  " : ""),
-              (state->compiling_verts ? "  rec  " : ""),
-              v[0], v[1], v[2], v[3]);
-
-      Assert (state->compiling_verts, "glTexCoord4fv outside glBegin");
-
-      if (state->compiling_verts)      /* inside glBegin */
-        {
-          state->set.ctex.s = v[0];
-          state->set.ctex.t = v[1];
-          state->set.ctex.r = v[2];
-          state->set.ctex.q = v[3];
-          state->set.tcount++;
-          if (state->set.count > 0 && state->set.tcount == 1)  /* not first! */
-            state->set.tcount++;
-        }
-    }
-}
-
-
-void
-jwzgles_glTexCoord4f (GLfloat s, GLfloat t, GLfloat r, GLfloat q)
-{
-  GLfloat v[4];
-  v[0] = s;
-  v[1] = t;
-  v[2] = r;
-  v[3] = q;
-  jwzgles_glTexCoord4fv (v);
-}
-
-
-void
-jwzgles_glTexCoord3fv (const GLfloat *v)
-{
-  GLfloat vv[4];
-  vv[0] = v[0];
-  vv[1] = v[1];
-  vv[2] = v[2];
-  vv[3] = 1;
-  jwzgles_glTexCoord4fv (vv);
-}
-
-
-void
-jwzgles_glTexCoord2fv (const GLfloat *v)
-{
-  GLfloat vv[4];
-  vv[0] = v[0];
-  vv[1] = v[1];
-  vv[2] = 0;
-  vv[3] = 1;
-  jwzgles_glTexCoord4fv (vv);
-}
-
-
-void
-jwzgles_glTexCoord3f (GLfloat s, GLfloat t, GLfloat r)
-{
-  jwzgles_glTexCoord4f (s, t, r, 1);
-}
-
-
-void
-jwzgles_glTexCoord2f (GLfloat s, GLfloat t)
-{
-  jwzgles_glTexCoord4f (s, t, 0, 1);
-}
-
-
-void
-jwzgles_glTexCoord1f (GLfloat s)
-{
-  jwzgles_glTexCoord4f (s, 0, 0, 1);
-}
-
-
-/* glColor: GLfloat */
-
-void
-jwzgles_glColor4fv (const GLfloat *v)
-{
-  if (state->compiling_list && !state->compiling_verts)
-    {
-      void_int vv[4];
-      vv[0].f = v[0];
-      vv[1].f = v[1];
-      vv[2].f = v[2];
-      vv[3].f = v[3];
-      list_push ("glColor4f", (list_fn_cb) &jwzgles_glColor4f, 
-                 PROTO_FFFF, vv);
-    }
-  else
-    {
-      if (!state->replaying_list)
-        LOG6 ("%s%sglColor4f    %7.3f %7.3f %7.3f %7.3f", 
-              (state->compiling_list || state->replaying_list ? "  " : ""),
-              (state->compiling_verts ? "  rec  " : ""),
-              v[0], v[1], v[2], v[3]);
-
-      if (state->compiling_verts)      /* inside glBegin */
-        {
-          state->set.ccolor.r = v[0];
-          state->set.ccolor.g = v[1];
-          state->set.ccolor.b = v[2];
-          state->set.ccolor.a = v[3];
-          state->set.ccount++;
-          if (state->set.count > 0 && state->set.ccount == 1)  /* not first! */
-            state->set.ccount++;
-        }
-      else                             /* outside glBegin */
-        {
-          glColor4f (v[0], v[1], v[2], v[3]);
-          CHECK("glColor4");
-        }
-    }
-}
-
-
-void
-jwzgles_glColor4f (GLfloat r, GLfloat g, GLfloat b, GLfloat a)
-{
-  GLfloat v[4];
-  v[0] = r;
-  v[1] = g;
-  v[2] = b;
-  v[3] = a;
-  jwzgles_glColor4fv (v);
-}
-
-void
-jwzgles_glColor3f (GLfloat r, GLfloat g, GLfloat b)
-{
-  jwzgles_glColor4f (r, g, b, 1);
-}
-
-void
-jwzgles_glColor3fv (const GLfloat *v)
-{
-  jwzgles_glColor3f (v[0], v[1], v[2]);
-}
-
-
-/* glColor: GLdouble */
-
-void
-jwzgles_glColor4d (GLdouble r, GLdouble g, GLdouble b, GLdouble a)
-{
-  jwzgles_glColor4f (r, g, b, a);
-}
-
-void
-jwzgles_glColor4dv (const GLdouble *v)
-{
-  jwzgles_glColor4d (v[0], v[1], v[2], v[3]);
-}
-
-void
-jwzgles_glColor3d (GLdouble r, GLdouble g, GLdouble b)
-{
-  jwzgles_glColor4d (r, g, b, 1.0);
-}
-
-void
-jwzgles_glColor3dv (const GLdouble *v)
-{
-  jwzgles_glColor3d (v[0], v[1], v[2]);
-}
-
-
-/* glColor: GLint (INT_MIN - INT_MAX) */
-
-void
-jwzgles_glColor4i (GLint r, GLint g, GLint b, GLint a)
-{
-  /* -0x8000000 - 0x7FFFFFFF  =>  0.0 - 1.0 */
-  jwzgles_glColor4f (0.5 + (GLfloat) r / 0xFFFFFFFF,
-                     0.5 + (GLfloat) g / 0xFFFFFFFF, 
-                     0.5 + (GLfloat) b / 0xFFFFFFFF,
-                     0.5 + (GLfloat) a / 0xFFFFFFFF);
-}
-
-void
-jwzgles_glColor4iv (const GLint *v)
-{
-  jwzgles_glColor4i (v[0], v[1], v[2], v[3]);
-}
-
-
-void
-jwzgles_glColor3i (GLint r, GLint g, GLint b)
-{
-  jwzgles_glColor4i (r, g, b, 0x7FFFFFFF);
-}
-
-void
-jwzgles_glColor3iv (const GLint *v)
-{
-  jwzgles_glColor3i (v[0], v[1], v[2]);
-}
-
-
-/* glColor: GLuint (0 - UINT_MAX) */
-
-void
-jwzgles_glColor4ui (GLuint r, GLuint g, GLuint b, GLuint a)
-{
-  /* 0 - 0xFFFFFFFF  =>  0.0 - 1.0 */
-  jwzgles_glColor4f ((GLfloat) r / 0xFFFFFFFF,
-                     (GLfloat) g / 0xFFFFFFFF, 
-                     (GLfloat) b / 0xFFFFFFFF,
-                     (GLfloat) a / 0xFFFFFFFF);
-}
-
-void
-jwzgles_glColor4uiv (const GLuint *v)
-{
-  jwzgles_glColor4ui (v[0], v[1], v[2], v[3]);
-}
-
-void
-jwzgles_glColor3ui (GLuint r, GLuint g, GLuint b)
-{
-  jwzgles_glColor4ui (r, g, b, 0xFFFFFFFF);
-}
-
-void
-jwzgles_glColor3uiv (const GLuint *v)
-{
-  jwzgles_glColor3ui (v[0], v[1], v[2]);
-}
-
-
-/* glColor: GLshort (SHRT_MIN - SHRT_MAX) */
-
-void
-jwzgles_glColor4s (GLshort r, GLshort g, GLshort b, GLshort a)
-{
-  /* -0x8000 - 0x7FFF  =>  0.0 - 1.0 */
-  jwzgles_glColor4f (0.5 + (GLfloat) r / 0xFFFF,
-                     0.5 + (GLfloat) g / 0xFFFF,
-                     0.5 + (GLfloat) b / 0xFFFF,
-                     0.5 + (GLfloat) a / 0xFFFF);
-}
-
-void
-jwzgles_glColor4sv (const GLshort *v)
-{
-  jwzgles_glColor4s (v[0], v[1], v[2], v[3]);
-}
-
-void
-jwzgles_glColor3s (GLshort r, GLshort g, GLshort b)
-{
-  jwzgles_glColor4s (r, g, b, 0x7FFF);
-}
-
-void
-jwzgles_glColor3sv (const GLshort *v)
-{
-  jwzgles_glColor3s (v[0], v[1], v[2]);
-}
-
-
-/* glColor: GLushort (0 - USHRT_MAX) */
-
-void
-jwzgles_glColor4us (GLushort r, GLushort g, GLushort b, GLushort a)
-{
-  /* 0 - 0xFFFF  =>  0.0 - 1.0 */
-  jwzgles_glColor4f ((GLfloat) r / 0xFFFF,
-                     (GLfloat) g / 0xFFFF,
-                     (GLfloat) b / 0xFFFF,
-                     (GLfloat) a / 0xFFFF);
-}
-
-void
-jwzgles_glColor4usv (const GLushort *v)
-{
-  jwzgles_glColor4us (v[0], v[1], v[2], v[3]);
-}
-
-void
-jwzgles_glColor3us (GLushort r, GLushort g, GLushort b)
-{
-  jwzgles_glColor4us (r, g, b, 0xFFFF);
-}
-
-void
-jwzgles_glColor3usv (const GLushort *v)
-{
-  jwzgles_glColor3us (v[0], v[1], v[2]);
-}
-
-
-/* glColor: GLbyte (-128 - 127) */
-
-void
-jwzgles_glColor4b (GLbyte r, GLbyte g, GLbyte b, GLbyte a)
-{
-  /* -128 - 127  =>  0.0 - 1.0 */
-  jwzgles_glColor4f (0.5 + (GLfloat) r / 255,
-                     0.5 + (GLfloat) g / 255,
-                     0.5 + (GLfloat) b / 255,
-                     0.5 + (GLfloat) a / 255);
-}
-
-void
-jwzgles_glColor4bv (const GLbyte *v)
-{
-  jwzgles_glColor4b (v[0], v[1], v[2], v[3]);
-}
-
-void
-jwzgles_glColor3b (GLbyte r, GLbyte g, GLbyte b)
-{
-  jwzgles_glColor4b (r, g, b, 127);
-}
-
-void
-jwzgles_glColor3bv (const GLbyte *v)
-{
-  jwzgles_glColor3b (v[0], v[1], v[2]);
-}
-
-
-/* glColor: GLubyte (0 - 255) */
-
-void
-jwzgles_glColor4ub (GLubyte r, GLubyte g, GLubyte b, GLubyte a)
-{
-  /* 0 - 255  =>  0.0 - 1.0 */
-  jwzgles_glColor4f (r / 255.0, g / 255.0, b / 255.0, a / 255.0);
-}
-
-void
-jwzgles_glColor4ubv (const GLubyte *v)
-{
-  jwzgles_glColor4ub (v[0], v[1], v[2], v[3]);
-}
-
-void
-jwzgles_glColor3ub (GLubyte r, GLubyte g, GLubyte b)
-{
-  jwzgles_glColor4ub (r, g, b, 255);
-}
-
-void
-jwzgles_glColor3ubv (const GLubyte *v)
-{
-  jwzgles_glColor3ub (v[0], v[1], v[2]);
-}
-
-
-
-void
-jwzgles_glMaterialfv (GLenum face, GLenum pname, const GLfloat *color)
-{
-  /* If this is called inside glBegin/glEnd with a front ambient color,
-     then treat it the same as glColor: set the color of the upcoming
-     vertex.
-
-     Other faces or lighting types within glBegin are ignored.
-   */
-
-  if (state->compiling_verts)
-    {
-      if ((face == GL_FRONT || 
-           face == GL_FRONT_AND_BACK) &&
-          (pname == GL_AMBIENT || 
-           pname == GL_DIFFUSE || 
-           pname == GL_AMBIENT_AND_DIFFUSE))
-        {
-          jwzgles_glColor4f (color[0], color[1], color[2], color[3]);
-          state->set.materialistic++;
-        }
-      else
-        LOG2 ("  IGNORING glMaterialfv %s %s",
-              mode_desc(face), mode_desc(pname));
-    }
-  else if (state->compiling_list)
-    {
-      void_int vv[6];
-      vv[0].i = face;
-      vv[1].i = pname;
-      vv[2].f = color[0];
-      vv[3].f = color[1];
-      vv[4].f = color[2];
-      vv[5].f = color[3];
-      list_push ("glMaterialfv", (list_fn_cb) &jwzgles_glMaterialfv, 
-                 PROTO_IIFV, vv);
-    }
-  else
-    {
-      /* If this is called outside of glBegin/glEnd with a front
-         ambient color, then the intent is presumably for that color
-         to apply to the upcoming vertexes (which may be played back
-         from a list that does not have vertex colors in it).  In that
-         case, the only way to make the colors show up is to call
-         glColor() with GL_COLOR_MATERIAL enabled.
-
-         I'm not sure if this will have other inappropriate side effects...
-       */
-      if ((face == GL_FRONT ||
-           face == GL_FRONT_AND_BACK) &&
-          (pname == GL_AMBIENT ||
-           pname == GL_DIFFUSE ||
-           pname == GL_AMBIENT_AND_DIFFUSE))
-        {
-          jwzgles_glEnable (GL_COLOR_MATERIAL);
-          jwzgles_glColor4f (color[0], color[1], color[2], color[3]);
-        }
-
-      /* OpenGLES seems to throw "invalid enum" for GL_FRONT -- but it
-         goes ahead and sets the material anyway!  No error if we just
-         always use GL_FRONT_AND_BACK.
-       */
-      if (face == GL_FRONT)
-        face = GL_FRONT_AND_BACK;
-      if (! state->replaying_list)
-        LOG7 ("direct %-12s %s %s %7.3f %7.3f %7.3f %7.3f", "glMaterialfv",
-              mode_desc(face), mode_desc(pname),
-              color[0], color[1], color[2], color[3]);
-      glMaterialfv (face, pname, color);  /* the real one */
-      CHECK("glMaterialfv");
-    }
-}
-
-
-void
-jwzgles_glMaterialiv (GLenum face, GLenum pname, const GLint *v)
-{
-  GLfloat vv[4];
-  vv[0] = v[0];
-  vv[1] = v[1];
-  vv[2] = v[2];
-  vv[3] = 1;
-  jwzgles_glMaterialfv (face, pname, vv);
-}
-
-void
-jwzgles_glMaterialf (GLenum face, GLenum pname, const GLfloat c)
-{
-  GLfloat vv[4];
-  vv[0] = c;
-  vv[1] = c;
-  vv[2] = c;
-  vv[3] = 1;
-  jwzgles_glMaterialfv (face, pname, vv);
-}
-
-
-void
-jwzgles_glMateriali (GLenum face, GLenum pname, const GLuint c)
-{
-  jwzgles_glMaterialf (face, pname, c);
-}
-
-
-void
-jwzgles_glColorMaterial (GLenum face, GLenum mode)
-{
-  Assert (!state->compiling_verts,
-          "glColorMaterial not allowed inside glBegin");
-#if 0
-  if (state->compiling_list)
-    {
-      void_int vv[2];
-      vv[0].i = face;
-      vv[1].i = mode;
-      list_push ("glColorMaterial", (list_fn_cb) &jwzgles_glColorMaterial, 
-                 PROTO_II, vv);
-    }
-  else
-    {
-      /* No real analog to this distinction in OpenGLES, since color
-         arrays don't distinguish between "color" and "material", */
-      Assert (0, "glColorMaterial: unimplemented mode");
-    }
-#endif
-}
-
-
-
-
-void
-jwzgles_glVertex4fv (const GLfloat *v)
-{
-  vert_set *s = &state->set;
-  int count = s->count;
-
-  Assert (state->compiling_verts, "glVertex4fv not inside glBegin");
-
-  LOG5("%s  rec  glVertex4f   %7.3f %7.3f %7.3f %7.3f",
-       (state->compiling_list || state->replaying_list ? "  " : ""),
-       v[0], v[1], v[2], v[3]);
-
-  if (count >= s->size - 1)
-    {
-      int new_size = 20 + (s->size * 1.2);
-
-      /* 4 arrays, different element sizes...
-         We allocate all 4 arrays just in case we need them,
-         but we might not end up using them all at the end.
-      */
-
-      s->verts = (XYZW *) realloc (s->verts, new_size * sizeof (*s->verts));
-      Assert (s->verts, "out of memory");
-
-      s->norms = (XYZ *) realloc (s->norms, new_size * sizeof (*s->norms));
-      Assert (s->norms, "out of memory");
-
-      s->tex = (STRQ *) realloc (s->tex, new_size * sizeof (*s->tex));
-      Assert (s->tex, "out of memory");
-
-      s->color = (RGBA *) realloc (s->color, new_size * sizeof (*s->color));
-      Assert (s->color, "out of memory");
-
-      s->size = new_size;
-    }
-
-  s->verts [count].x = v[0];
-  s->verts [count].y = v[1];
-  s->verts [count].z = v[2];
-  s->verts [count].w = v[3];
-  s->norms [count] = s->cnorm;
-  s->tex   [count] = s->ctex;
-  s->color [count] = s->ccolor;
-  s->count++;
-}
-
-
-void
-jwzgles_glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-{
-  GLfloat v[4];
-  v[0] = x;
-  v[1] = y;
-  v[2] = z;
-  v[3] = w;
-  jwzgles_glVertex4fv (v);
-}
-
-void
-jwzgles_glVertex4i (GLint x, GLint y, GLint z, GLint w)
-{
-  jwzgles_glVertex4f (x, y, z, w);
-}
-
-void
-jwzgles_glVertex3f (GLfloat x, GLfloat y, GLfloat z)
-{
-  GLfloat v[4];
-  v[0] = x;
-  v[1] = y;
-  v[2] = z;
-  v[3] = 1;
-  jwzgles_glVertex4fv (v);
-}
-
-void
-jwzgles_glVertex3i (GLint x, GLint y, GLint z)
-{
-  jwzgles_glVertex3f (x, y, z);
-}
-
-void
-jwzgles_glVertex3fv (const GLfloat *v)
-{
-  jwzgles_glVertex3f (v[0], v[1], v[2]);
-}
-
-void
-jwzgles_glVertex3dv (const GLdouble *v)
-{
-  jwzgles_glVertex3f (v[0], v[1], v[2]);
-}
-
-
-void
-jwzgles_glVertex2f (GLfloat x, GLfloat y)
-{
-  GLfloat v[3];
-  v[0] = x;
-  v[1] = y;
-  v[2] = 0;
-  jwzgles_glVertex3fv (v);
-}
-
-void
-jwzgles_glVertex2dv (const GLdouble *v)
-{
-  jwzgles_glVertex2f (v[0], v[1]);
-}
-
-void
-jwzgles_glVertex2fv (const GLfloat *v)
-{
-  jwzgles_glVertex2f (v[0], v[1]);
-}
-
-void
-jwzgles_glVertex2i (GLint x, GLint y)
-{
-  jwzgles_glVertex2f (x, y);
-}
-
-
-void
-jwzgles_glLightiv (GLenum light, GLenum pname, const GLint *params)
-{
-  GLfloat v[4];
-  v[0] = params[0];
-  v[1] = params[1];
-  v[2] = params[2];
-  v[3] = params[3];
-  jwzgles_glLightfv (light, pname, v);
-}
-
-void
-jwzgles_glLightModeliv (GLenum pname, const GLint *params)
-{
-  GLfloat v[4];
-  v[0] = params[0];
-  v[1] = params[1];
-  v[2] = params[2];
-  v[3] = params[3];
-  jwzgles_glLightModelfv (pname, v);
-}
-
-void
-jwzgles_glFogiv (GLenum pname, const GLint *params)
-{
-  GLfloat v[4];
-  v[0] = params[0];
-  v[1] = params[1];
-  v[2] = params[2];
-  v[3] = params[3];
-  jwzgles_glFogfv (pname, v);
-}
-
-void
-jwzgles_glLighti (GLenum light, GLenum pname, GLint param)
-{
-  jwzgles_glLightf (light, pname, param);
-}
-
-void
-jwzgles_glLightModeli (GLenum pname, GLint param)
-{
-  jwzgles_glLightModelf (pname, param);
-}
-
-void
-jwzgles_glFogi (GLenum pname, GLint param)
-{
-  jwzgles_glFogf (pname, param);
-}
-
-
-void
-jwzgles_glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z)
-{
-  jwzgles_glRotatef (angle, x, y, z);
-}
-
-
-void
-jwzgles_glClipPlane (GLenum plane, const GLdouble *equation)
-{
-  Assert (state->compiling_verts, "glClipPlane not inside glBegin");
-  Assert (0, "glClipPlane unimplemented");  /* no GLES equivalent... */
-}
-
-
-void
-jwzgles_glPolygonMode (GLenum face, GLenum mode)
-{
-  Assert (!state->compiling_verts, "not inside glBegin");
-  if (state->compiling_list)
-    {
-      void_int vv[2];
-      vv[0].i = face;
-      vv[1].i = mode;
-      list_push ("glPolygonMode", (list_fn_cb) &jwzgles_glPolygonMode, 
-                 PROTO_II, vv);
-    }
-  else
-    {
-      /* POINT and LINE don't exist in GLES */
-      Assert (mode == GL_FILL, "glPolygonMode: unimplemented mode");
-    }
-}
-
-
-void
-jwzgles_glDrawBuffer (GLenum buf)
-{
-  Assert (!state->compiling_verts, "not inside glBegin");
-  if (state->compiling_list)
-    {
-      void_int vv[1];
-      vv[0].i = buf;
-      list_push ("glDrawBuffer", (list_fn_cb) &jwzgles_glDrawBuffer, 
-                 PROTO_I, vv);
-    }
-  else
-    {
-/*      Assert (buf == GL_BACK, "glDrawBuffer: back buffer only"); */
-# ifndef GL_VERSION_ES_CM_1_0  /* not compiling against OpenGLES 1.x */
-      if (! state->replaying_list)
-        LOG1 ("direct %-12s", "glDrawBuffer");
-      glDrawBuffer (buf);      /* the real one */
-      CHECK("glDrawBuffer");
-# endif
-    }
-}
-
-
-/* Given an array of sets of 4 elements of arbitrary size, convert it
-   to an array of sets of 6 elements instead: ABCD becomes ABC BCD.
- */
-static int
-cq2t (unsigned char **arrayP, int stride, int count)
-{
-  int count2 = count * 6 / 4;
-  int size  = stride * count;
-  int size2 = stride * count2;
-  const unsigned char    *oarray,  *in;
-  unsigned char *array2, *oarray2, *out;
-  int i;
-
-  oarray = *arrayP;
-  if (!oarray || count == 0)
-    return count2;
-
-  array2 = (unsigned char *) malloc (size2);
-  Assert (array2, "out of memory");
-  oarray2 = array2;
-
-  in =  oarray;
-  out = oarray2;
-  for (i = 0; i < count / 4; i++)
-    {
-      const unsigned char *a, *b, *c, *d;      /* the 4 corners */
-      a = in; in += stride;
-      b = in; in += stride;
-      c = in; in += stride;
-      d = in; in += stride;
-
-# define PUSH(IN) do {                 \
-         const unsigned char *ii = IN; \
-         int j;                                \
-         for (j = 0; j < stride; j++) {        \
-           *out++ = *ii++;             \
-         }} while(0)
-
-      PUSH (a); PUSH (b); PUSH (d);            /* the 2 triangles */
-      PUSH (b); PUSH (c); PUSH (d);
-# undef PUSH
-    }
-
-  Assert (in  == oarray  + size,  "convert_quads corrupted");
-  Assert (out == oarray2 + size2, "convert_quads corrupted");
-
-  free (*arrayP);
-  *arrayP = oarray2;
-  return count2;
-}
-                              
-
-/* Convert all coordinates in a GL_QUADS vert_set to GL_TRIANGLES.
- */
-static void
-convert_quads_to_triangles (vert_set *s)
-{
-  int count2;
-  Assert (s->mode == GL_QUADS, "convert_quads bad mode");
-  count2 =
-   cq2t ((unsigned char **) &s->verts, sizeof(*s->verts), s->count);
-   cq2t ((unsigned char **) &s->norms, sizeof(*s->norms), s->count);
-   cq2t ((unsigned char **) &s->tex,   sizeof(*s->tex),   s->count);
-   cq2t ((unsigned char **) &s->color, sizeof(*s->color), s->count);
-  s->count = count2;
-  s->size  = count2;
-  s->mode = GL_TRIANGLES;
-}
-
-
-void
-jwzgles_glEnd (void)
-{
-  vert_set *s = &state->set;
-  int was_norm, was_tex, was_color, was_mat;
-  int  is_norm,  is_tex,  is_color,  is_mat;
-
-  Assert (state->compiling_verts == 1, "missing glBegin");
-  state->compiling_verts--;
-
-  Assert (!state->replaying_list, "how did glEnd get into a display list?");
-
-  if (!state->replaying_list)
-    {
-      LOG5 ("%s  [V = %d, N = %d, T = %d, C = %d]",
-            (state->compiling_list || state->replaying_list ? "  " : ""),
-            s->count, s->ncount, s->tcount, s->ccount);
-      LOG1 ("%sglEnd",
-            (state->compiling_list || state->replaying_list ? "  " : ""));
-    }
-
-  if (s->count == 0) return;
-
-  if (s->mode == GL_QUADS)
-    convert_quads_to_triangles (s);
-  else if (s->mode == GL_QUAD_STRIP)
-    s->mode = GL_TRIANGLE_STRIP;       /* They do the same thing! */
-  else if (s->mode == GL_POLYGON)
-    s->mode = GL_TRIANGLE_FAN;         /* They do the same thing! */
-
-  jwzgles_glColorPointer   (4,GL_FLOAT, sizeof(*s->color),s->color); /* RGBA */
-  jwzgles_glNormalPointer  (  GL_FLOAT, sizeof(*s->norms),s->norms); /* XYZ  */
-  jwzgles_glTexCoordPointer(4,GL_FLOAT, sizeof(*s->tex),  s->tex);   /* STRQ */
-  jwzgles_glVertexPointer  (4,GL_FLOAT, sizeof(*s->verts),s->verts); /* XYZW */
-  /* glVertexPointer must come after glTexCoordPointer */
-
-  /* If there were no calls to glNormal3f inside of glBegin/glEnd,
-     don't bother enabling the normals array.
-
-     If there was exactly *one* call to glNormal3f inside of glBegin/glEnd,
-     and it was before the first glVertex3f, then also don't enable the
-     normals array, but do emit that call to glNormal3f before calling
-     glDrawArrays.
-
-     Likewise for texture coordinates and colors.
-
-     Be careful to leave the arrays' enabled/disabled state the same as
-     before, or a later caller might end up using one of our arrays by
-     mistake.  (Remember that jwzgles_glIsEnabled() tracks the enablement
-     of the list-in-progress as well as the global state.)
-  */
-  was_norm  = jwzgles_glIsEnabled (GL_NORMAL_ARRAY);
-  was_tex   = jwzgles_glIsEnabled (GL_TEXTURE_COORD_ARRAY);
-  was_color = jwzgles_glIsEnabled (GL_COLOR_ARRAY);
-  was_mat   = jwzgles_glIsEnabled (GL_COLOR_MATERIAL);
-
-  /* If we're executing glEnd in immediate mode, not from inside a display
-     list (which is the only way it happens, because glEnd doesn't go into
-     display lists), make sure we're not stomping on a saved buffer list:
-     in immediate mode, vertexes are client-side only.
-   */
-  if (! state->compiling_list)
-    jwzgles_glBindBuffer (GL_ARRAY_BUFFER, 0);
-
-  if (s->ncount > 1)
-    {
-      is_norm = 1;
-      jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
-    }
-  else
-    {
-      is_norm = 0;
-      if (s->ncount == 1)
-        jwzgles_glNormal3f (s->cnorm.x, s->cnorm.y, s->cnorm.z);
-      jwzgles_glDisableClientState (GL_NORMAL_ARRAY);
-    }
-
-  if (s->tcount > 1 ||
-      ((state->compiling_list ? state->list_enabled : state->enabled)
-       & (ISENABLED_TEXTURE_GEN_S | ISENABLED_TEXTURE_GEN_T |
-          ISENABLED_TEXTURE_GEN_R | ISENABLED_TEXTURE_GEN_Q)))
-    {
-      /* Enable texture coords if any were specified; or if generation
-         is on in immediate mode; or if this list turned on generation. */
-      is_tex = 1;
-      jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
-    }
-  else
-    {
-      is_tex = 0;
-      if (s->tcount == 1)
-        jwzgles_glTexCoord4f (s->ctex.s, s->ctex.t, s->ctex.r, s->ctex.q);
-      jwzgles_glDisableClientState (GL_TEXTURE_COORD_ARRAY);
-    }
-
-  if (s->ccount > 1)
-    {
-      is_color = 1;
-      jwzgles_glEnableClientState (GL_COLOR_ARRAY);
-    }
-  else
-    {
-      is_color = 0;
-      if (s->ccount == 1)
-        jwzgles_glColor4f (s->ccolor.r, s->ccolor.g, s->ccolor.b, s->ccolor.a);
-      jwzgles_glDisableClientState (GL_COLOR_ARRAY);
-    }
-
-  jwzgles_glEnableClientState (GL_VERTEX_ARRAY);
-
-  /* We translated the glMaterial calls to per-vertex colors, which are
-     of the glColor sort, not the glMaterial sort, so automatically
-     turn on material mapping.  Maybe this is a bad idea.
-   */
-  if (s->materialistic && !jwzgles_glIsEnabled (GL_COLOR_MATERIAL))
-    {
-      is_mat = 1;
-      jwzgles_glEnable (GL_COLOR_MATERIAL);
-    }
-  else
-    is_mat = 0;
-
-  glBindBuffer (GL_ARRAY_BUFFER, 0);    /* This comes later. */
-  jwzgles_glDrawArrays (s->mode, 0, s->count);
-  glBindBuffer (GL_ARRAY_BUFFER, 0);    /* Keep out of others' hands */
-
-# define RESET(VAR,FN,ARG) do { \
-         if (is_##VAR != was_##VAR) { \
-            if (was_##VAR) jwzgles_glEnable##FN (ARG); \
-            else jwzgles_glDisable##FN (ARG); \
-         }} while(0)
-  RESET (norm,  ClientState, GL_NORMAL_ARRAY);
-  RESET (tex,   ClientState, GL_TEXTURE_COORD_ARRAY);
-  RESET (color, ClientState, GL_COLOR_ARRAY);
-  RESET (mat,   ,            GL_COLOR_MATERIAL);
-# undef RESET
-
-  s->count  = 0;
-  s->ncount = 0;
-  s->tcount = 0;
-  s->ccount = 0;
-  s->materialistic = 0;
-}
-
-
-/* The display list is full of calls to glDrawArrays(), plus saved arrays
-   of the values we need to restore before calling it.  "Restore" means
-   "ship them off to the GPU before each call".
-
-   So instead, this function walks through the display list and
-   combines all of those vertex, normal, texture and color values into
-   a single VBO array; ships those values off to the GPU *once* at the
-   time of glEndList; and when running the list with glCallList, the
-   values are already on the GPU and don't need to be sent over again.
-
-   The VBO persists in the GPU until the display list is deleted.
- */
-static void
-optimize_arrays (void)
-{
-  list *L = &state->lists.lists[state->compiling_list-1];
-  int i, j;
-  GLfloat *combo = 0;
-  int combo_count = 0;
-  int combo_size = 0;
-  GLuint buf_name = 0;
-
-  Assert (state->compiling_list, "not compiling a list");
-  Assert (L, "no list");
-  Assert (!L->buffer, "list already has a buffer");
-
-  glGenBuffers (1, &buf_name);
-  CHECK("glGenBuffers");
-  if (! buf_name) return;
-
-  L->buffer = buf_name;
-
-  /* Go through the list and dump the contents of the various saved arrays
-     into one large array.
-   */
-  for (i = 0; i < L->count; i++)
-    {
-      list_fn *F = &L->fns[i];
-/*      int count; */
-      if (! F->arrays)
-        continue;
-/*      count = F->argv[2].i;*/  /* 3rd arg to glDrawArrays */
-
-      for (j = 0; j < 4; j++)
-        {
-          draw_array *A = &F->arrays[j];
-          int ocount = combo_count;
-
-          /* If some caller is using arrays that don't have floats in them,
-             we just leave them as-is and ship them over at each call.
-             Doubt this ever really happens.
-           */
-          if (A->type != GL_FLOAT)
-            continue;
-
-          if (! A->data)       /* No array. */
-            continue;
-
-          Assert (A->bytes > 0, "no bytes in draw_array");
-          Assert (((unsigned long) A->data > 0xFFFF),
-                  "buffer data not a pointer");
-
-          combo_count += A->bytes / sizeof(*combo);
-          make_room ("optimize_arrays",
-                     (void **) &combo, sizeof(*combo),
-                     &combo_count, &combo_size);
-          memcpy (combo + ocount, A->data, A->bytes);
-          A->binding = buf_name;
-          free (A->data);
-          /* 'data' is now the byte offset into the VBO. */
-          A->data = (void *) (ocount * sizeof(*combo));
-          /* LOG3("    loaded %lu floats to pos %d of buffer %d",
-               A->bytes / sizeof(*combo), ocount, buf_name); */
-        }
-    }
-
-  if (combo_count == 0)                /* Nothing to do! */
-    {
-      if (combo) free (combo);
-      glDeleteBuffers (1, &buf_name);
-      L->buffer = 0;
-      return;
-    }
-
-  glBindBuffer (GL_ARRAY_BUFFER, buf_name);
-  glBufferData (GL_ARRAY_BUFFER, 
-                combo_count * sizeof (*combo),
-                combo,
-                GL_STATIC_DRAW);
-  glBindBuffer (GL_ARRAY_BUFFER, 0);    /* Keep out of others' hands */
-
-  LOG3("  loaded %d floats of list %d into VBO %d",
-       combo_count, state->compiling_list, buf_name);
-
-# ifdef DEBUG
-#  if 0
-  for (i = 0; i < combo_count; i++)
-    {
-      if (i % 4 == 0)
-        fprintf (stderr, "\njwzgles:    %4d: ", i);
-      fprintf (stderr, " %7.3f", combo[i]);
-    }
-  fprintf (stderr, "\n");
-#  endif
-# endif /* DEBUG */
-
-  if (combo) free (combo);
-}
-
-
-void
-jwzgles_glCallList (int id)
-{
-  if (state->compiling_list)
-    {
-      /* Yes, you can call lists inside of lists.
-         Yes, recursion would be a mistake. */
-      void_int vv[1];
-      vv[0].i = id;
-      list_push ("glCallList", (list_fn_cb) &jwzgles_glCallList, PROTO_I, vv);
-    }
-  else
-    {
-      list *L;
-      int i;
-
-      state->replaying_list++;
-
-# ifdef DEBUG
-      fprintf (stderr, "\n");
-      LOG1 ("glCallList %d", id);
-# endif
-
-      Assert (id > 0 && id <= state->lists.count, "glCallList: bogus ID");
-      L = &state->lists.lists[id-1];
-      Assert (id == L->id, "glCallList corrupted");
-
-      for (i = 0; i < L->count; i++)
-        {
-          list_fn *F = &L->fns[i];
-          list_fn_cb fn = F->fn;
-          void_int *av = F->argv;
-
-          switch (F->proto) {
-          case PROTO_VOID:
-            LOG1 ("  call %-12s", F->name);
-            ((void (*) (void)) fn) ();
-            break;
-
-          case PROTO_I:
-            if (fn == (list_fn_cb) &jwzgles_glBegin ||
-                fn == (list_fn_cb) &jwzgles_glFrontFace ||
-                fn == (list_fn_cb) &jwzgles_glEnable ||
-                fn == (list_fn_cb) &jwzgles_glDisable ||
-                fn == (list_fn_cb) &jwzgles_glEnableClientState ||
-                fn == (list_fn_cb) &jwzgles_glDisableClientState ||
-                fn == (list_fn_cb) &jwzgles_glShadeModel ||
-                fn == (list_fn_cb) &jwzgles_glMatrixMode)
-              LOG2 ("  call %-12s %s", F->name, mode_desc (av[0].i));
-            else
-              LOG2 ("  call %-12s %d", F->name, av[0].i);
-            ((void (*) (int)) fn) (av[0].i);
-            break;
-
-          case PROTO_F:
-            LOG2 ("  call %-12s %7.3f", F->name, av[0].f);
-            ((void (*) (GLfloat)) fn) (av[0].f);
-            break;
-
-          case PROTO_II:
-            if (fn == (list_fn_cb) &jwzgles_glBindTexture ||
-                fn == (list_fn_cb) &jwzgles_glBindBuffer)
-              LOG3 ("  call %-12s %s %d", F->name, 
-                    mode_desc (av[0].i), av[1].i);
-            else
-              LOG3 ("  call %-12s %d %d", F->name, av[0].i, av[1].i);
-            ((void (*) (int, int)) fn) (av[0].i, av[1].i);
-            break;
-
-          case PROTO_FF:
-            LOG3 ("  call %-12s %7.3f %7.3f", F->name, av[0].f, av[1].f);
-            ((void (*) (GLfloat, GLfloat)) fn) (av[0].f, av[1].f);
-            break;
-
-          case PROTO_IF:
-            LOG3 ("  call %-12s %s %7.3f", F->name, 
-                  mode_desc (av[0].f), av[1].f);
-            ((void (*) (GLint, GLfloat)) fn) (av[0].i, av[1].f);
-            break;
-
-          case PROTO_III: III:
-            if (fn == (list_fn_cb) &jwzgles_glDrawArrays ||
-                fn == (list_fn_cb) &jwzgles_glTexParameteri)
-              LOG4 ("  call %-12s %s %d %d", F->name, 
-                    mode_desc (av[0].i), av[1].i, av[2].i);
-            else
-              LOG4 ("  call %-12s %d %d %d", F->name, 
-                    av[0].i, av[1].i, av[2].i);
-            ((void (*) (int, int, int)) fn) (av[0].i, av[1].i, av[2].i);
-            break;
-
-          case PROTO_FFF:
-            LOG4 ("  call %-12s %7.3f %7.3f %7.3f", F->name,
-                  av[0].f, av[1].f, av[2].f);
-            ((void (*) (GLfloat, GLfloat, GLfloat)) fn)
-              (av[0].f, av[1].f, av[2].f);
-            break;
-
-          case PROTO_IIF:
-            LOG4 ("  call %-12s %s %s %7.3f", F->name,
-                  mode_desc (av[0].i), mode_desc (av[1].i), av[2].f);
-            ((void (*) (int, int, GLfloat)) fn) (av[0].i, av[1].i, av[2].f);
-            break;
-
-          case PROTO_IIII:
-            LOG5 ("  call %-12s %d %d %d %d", F->name,
-                  av[0].i, av[1].i, av[2].i, av[3].i);
-            ((void (*) (int, int, int, int)) fn) 
-              (av[0].i, av[1].i, av[2].i, av[3].i);
-            break;
-
-          case PROTO_FFFF:
-            LOG5 ("  call %-12s %7.3f %7.3f %7.3f %7.3f", F->name,
-                  av[0].f, av[1].f, av[2].f, av[3].f);
-            ((void (*) (GLfloat, GLfloat, GLfloat, GLfloat)) fn)
-              (av[0].f, av[1].f, av[2].f, av[3].f);
-            break;
-
-          case PROTO_IFV:
-            {
-              GLfloat v[4];
-              v[0] = av[1].f;
-              v[1] = av[2].f;
-              v[2] = av[3].f;
-              v[3] = av[4].f;
-              LOG6 ("  call %-12s %s %3.1f %3.1f %3.1f %3.1f", F->name,
-                    mode_desc (av[0].i),
-                    av[1].f, av[2].f, av[3].f, av[4].f);
-              ((void (*) (int, const GLfloat *)) fn) (av[0].i, v);
-            }
-            break;
-
-          case PROTO_IIFV:
-            {
-              GLfloat v[4];
-              v[0] = av[2].f;
-              v[1] = av[3].f;
-              v[2] = av[4].f;
-              v[3] = av[5].f;
-              LOG7 ("  call %-12s %s %-8s %3.1f %3.1f %3.1f %3.1f", F->name,
-                    mode_desc (av[0].i), mode_desc (av[1].i), 
-                    av[2].f, av[3].f, av[4].f, av[5].f);
-              ((void (*) (int, int, const GLfloat *)) fn) 
-                (av[0].i, av[1].i, v);
-            }
-            break;
-
-          case PROTO_IIV:
-            {
-              int v[4];
-              v[0] = av[1].i;
-              v[1] = av[2].i;
-              v[2] = av[3].i;
-              v[3] = av[4].i;
-              LOG6 ("  call %-12s %s %3d %3d %3d %3d", F->name, 
-                    mode_desc (av[0].i),
-                    av[1].i, av[2].i, av[3].i, av[4].i);
-              ((void (*) (int, const int *)) fn) (av[0].i, v);
-            }
-            break;
-
-          case PROTO_IIIV:
-            {
-              int v[4];
-              v[0] = av[2].i;
-              v[1] = av[3].i;
-              v[2] = av[4].i;
-              v[3] = av[5].i;
-              LOG7 ("  call %-12s %s %-8s %3d %3d %3d %3d", F->name,
-                    mode_desc (av[0].i), mode_desc (av[1].i), 
-                    av[2].i, av[3].i, av[4].i, av[5].i);
-              ((void (*) (int, int, const int *)) fn) 
-                (av[0].i, av[1].i, v);
-            }
-            break;
-
-          case PROTO_ARRAYS:
-            restore_arrays (F, av[1].i + av[2].i);
-            goto III;
-            break;
-
-          case PROTO_FV16:
-            {
-              GLfloat m[16];
-              int i;
-              for (i = 0; i < countof(m); i++)
-                m[i] = av[i].f;
-              LOG17 ("  call %-12s ["
-                     "%8.3f %8.3f %8.3f %8.3f "        "\n\t\t\t       "
-                     "%8.3f %8.3f %8.3f %8.3f "        "\n\t\t\t       "
-                     "%8.3f %8.3f %8.3f %8.3f "        "\n\t\t\t       "
-                     "%8.3f %8.3f %8.3f %8.3f ]",
-                     F->name,
-                     m[0],  m[1],  m[2],  m[3],
-                     m[4],  m[5],  m[6],  m[7],
-                     m[8],  m[9],  m[10], m[11],
-                     m[12], m[13], m[14], m[15]);
-              ((void (*) (GLfloat *)) fn) (m);
-            }
-            break;
-
-          default:
-            Assert (0, "bogus prototype");
-            break;
-          }
-        }
-
-      LOG1 ("glCallList %d done\n", id);
-
-      state->replaying_list--;
-      Assert (state->replaying_list >= 0, "glCallList corrupted");
-    }
-}
-
-
-/* When we save a call to glDrawArrays into a display list, we also need to
-   save the prevailing copy of the arrays that it will use, and restore them
-   later.
- */
-static void
-save_arrays (list_fn *F, int count)
-{
-  int i = 0;
-  draw_array *A = (draw_array *) calloc (4, sizeof (*A));
-  Assert (A, "out of memory");
-
-/*  if (state->set.count > 0) */
-    {
-      glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A[i].binding);
-      glGetIntegerv (GL_VERTEX_ARRAY_SIZE,    &A[i].size);
-      glGetIntegerv (GL_VERTEX_ARRAY_TYPE,    &A[i].type);
-      glGetIntegerv (GL_VERTEX_ARRAY_STRIDE,  &A[i].stride);
-      glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A[i].data);
-      CHECK("glGetPointerv");
-      copy_array_data (&A[i], count, "vert");
-    }
-
-  i++;
-  if (state->set.ncount > 1)
-    {
-      A[i].size = 3;
-      glGetIntegerv (GL_NORMAL_ARRAY_BUFFER_BINDING, &A[i].binding);
-      glGetIntegerv (GL_NORMAL_ARRAY_TYPE,    &A[i].type);
-      glGetIntegerv (GL_NORMAL_ARRAY_STRIDE,  &A[i].stride);
-      glGetPointerv (GL_NORMAL_ARRAY_POINTER, &A[i].data);
-      CHECK("glGetPointerv");
-      copy_array_data (&A[i], count, "norm");
-    }
-
-  i++;
-  if (state->set.tcount > 1)
-    {
-      glGetIntegerv (GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, &A[i].binding);
-      glGetIntegerv (GL_TEXTURE_COORD_ARRAY_SIZE,    &A[i].size);
-      glGetIntegerv (GL_TEXTURE_COORD_ARRAY_TYPE,    &A[i].type);
-      glGetIntegerv (GL_TEXTURE_COORD_ARRAY_STRIDE,  &A[i].stride);
-      glGetPointerv (GL_TEXTURE_COORD_ARRAY_POINTER, &A[i].data);
-      CHECK("glGetPointerv");
-      copy_array_data (&A[i], count, "tex ");
-    }
-
-  i++;
-  if (state->set.ccount > 1)
-    {
-      glGetIntegerv (GL_COLOR_ARRAY_BUFFER_BINDING, &A[i].binding);
-      glGetIntegerv (GL_COLOR_ARRAY_SIZE,    &A[i].size);
-      glGetIntegerv (GL_COLOR_ARRAY_TYPE,    &A[i].type);
-      glGetIntegerv (GL_COLOR_ARRAY_STRIDE,  &A[i].stride);
-      glGetPointerv (GL_COLOR_ARRAY_POINTER, &A[i].data);
-      CHECK("glGetPointerv");
-      copy_array_data (&A[i], count, "col ");
-    }
-
-  /* Freed by glDeleteLists. */
-
-  Assert (!F->arrays, "save_arrays corrupted");
-  F->arrays = A;
-}
-
-
-#ifdef DEBUG
-
-static void
-dump_array_data (draw_array *A, int count,
-                 const char *action, const char *name, const void *old)
-{
-  int bytes = count * A->stride;
-
-  if (A->binding)
-    {
-      fprintf (stderr, 
-               "jwzgles:     %s %s %d %s %2d, %4d = %5d   bind %d @ %d\n", 
-               action, name,
-               A->size, mode_desc(A->type), A->stride, 
-               count, bytes, A->binding, (int) A->data);
-    }
-  else
-    {
-      Assert (bytes == A->bytes, "array data corrupted");
-
-      fprintf (stderr, "jwzgles:     %s %s %d %s %2d, %4d = %5d @ %lX", 
-               action, name,
-               A->size, mode_desc(A->type), A->stride, 
-               count, bytes, (unsigned long) A->data);
-      if (old)
-        fprintf (stderr, " / %lX", (unsigned long) old);
-      fprintf (stderr, "\n");
-    }
-
-  if (A->binding)
-    {
-      Assert (((unsigned long) A->data < 0xFFFF),
-              "buffer binding should be a numeric index,"
-              " but looks like a pointer");
-
-# if 0
-      /* glGetBufferSubData doesn't actually exist in OpenGLES, but this
-         was helpful for debugging on real OpenGL... */
-      GLfloat *d;
-      int i;
-      fprintf (stderr, "jwzgles: read back:\n");
-      d = (GLfloat *) malloc (A->bytes);
-      glGetBufferSubData (GL_ARRAY_BUFFER, (int) A->data,
-                          count * A->stride, (void *) d);
-      CHECK("glGetBufferSubData");
-      for (i = 0; i < count * A->size; i++)
-        {
-          if (i % 4 == 0)
-            fprintf (stderr, "\njwzgles:    %4d: ", 
-                     i + (int) A->data / sizeof(GLfloat));
-          fprintf (stderr, " %7.3f", d[i]);
-        }
-      fprintf (stderr, "\n");
-      free (d);
-# endif
-    }
-# if 0
-  else
-    {
-      unsigned char *b = (unsigned char *) A->data;
-      int i;
-      if ((unsigned long) A->data < 0xFFFF)
-        {
-          Assert (0, "buffer data not a pointer");
-          return;
-        }
-      for (i = 0; i < count; i++)
-        {
-          int j;
-          GLfloat *f = (GLfloat *) b;
-          int s = A->size;
-          if (s == 0) s = 3;  /* normals */
-          fprintf (stderr, "jwzgles:    ");
-          for (j = 0; j < s; j++)
-            fprintf (stderr, " %7.3f", f[j]);
-          fprintf (stderr, "\n");
-          b += A->stride;
-        }
-    }
-# endif
-}
-
-static void
-dump_direct_array_data (int count)
-{
-  draw_array A = { 0, };
-
-  if (jwzgles_glIsEnabled (GL_VERTEX_ARRAY))
-    {
-      glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A.binding);
-      glGetIntegerv (GL_VERTEX_ARRAY_SIZE,    &A.size);
-      glGetIntegerv (GL_VERTEX_ARRAY_TYPE,    &A.type);
-      glGetIntegerv (GL_VERTEX_ARRAY_STRIDE,  &A.stride);
-      glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A.data);
-      A.bytes = count * A.stride;
-      dump_array_data (&A, count, "direct", "vertex ", 0);
-    }
-  if (jwzgles_glIsEnabled (GL_NORMAL_ARRAY))
-    {
-      A.size = 0;
-      glGetIntegerv (GL_NORMAL_ARRAY_BUFFER_BINDING, &A.binding);
-      glGetIntegerv (GL_NORMAL_ARRAY_TYPE,    &A.type);
-      glGetIntegerv (GL_NORMAL_ARRAY_STRIDE,  &A.stride);
-      glGetPointerv (GL_NORMAL_ARRAY_POINTER, &A.data);
-      A.bytes = count * A.stride;
-      dump_array_data (&A, count, "direct", "normal ", 0);
-    }
-  if (jwzgles_glIsEnabled (GL_TEXTURE_COORD_ARRAY))
-    {
-      glGetIntegerv (GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, &A.binding);
-      glGetIntegerv (GL_TEXTURE_COORD_ARRAY_SIZE,    &A.size);
-      glGetIntegerv (GL_TEXTURE_COORD_ARRAY_TYPE,    &A.type);
-      glGetIntegerv (GL_TEXTURE_COORD_ARRAY_STRIDE,  &A.stride);
-      glGetPointerv (GL_TEXTURE_COORD_ARRAY_POINTER, &A.data);
-      A.bytes = count * A.stride;
-      dump_array_data (&A, count, "direct", "texture", 0);
-    }
-  if (jwzgles_glIsEnabled (GL_COLOR_ARRAY))
-    {
-      glGetIntegerv (GL_COLOR_ARRAY_BUFFER_BINDING, &A.binding);
-      glGetIntegerv (GL_COLOR_ARRAY_SIZE,    &A.size);
-      glGetIntegerv (GL_COLOR_ARRAY_TYPE,    &A.type);
-      glGetIntegerv (GL_COLOR_ARRAY_STRIDE,  &A.stride);
-      glGetPointerv (GL_COLOR_ARRAY_POINTER, &A.data);
-      A.bytes = count * A.stride;
-      dump_array_data (&A, count, "direct", "color ", 0);
-    }
-}
-
-#endif /* DEBUG */
-
-
-static void
-copy_array_data (draw_array *A, int count, const char *name)
-{
-  /* Instead of just memcopy'ing the whole array and obeying its previous
-     'stride' value, we make up a more compact array.  This is because if
-     the same array data is being used with multiple component types,
-     e.g. with glInterleavedArrays, we don't want to copy all of the
-     data multiple times.
-   */
-  int stride2, bytes, i, j;
-  void *data2;
-  const GLfloat *IF;
-  GLfloat *OF;
-  const unsigned char *IB;
-  unsigned char *OB;
-
-  if (((unsigned long) A->data) < 0xFFFF)
-    {
-      Assert (0, "buffer data not a pointer");
-      return;
-    }
-
-  Assert (A->size >= 2 && A->size <= 4, "bogus array size");
-
-  switch (A->type) {
-  case GL_FLOAT:         stride2 = A->size * sizeof(GLfloat); break;
-  case GL_UNSIGNED_BYTE: stride2 = A->size; break;
-  default: Assert (0, "bogus array type"); break;
-  }
-
-  bytes = count * stride2;
-  Assert (bytes > 0, "bogus array count or stride");
-  Assert (A->data, "missing array data");
-  data2 = (void *) malloc (bytes);
-  Assert (data2, "out of memory");
-
-  IB = (const unsigned char *) A->data;
-  OB = (unsigned char *) data2;
-  IF = (const GLfloat *) A->data;
-  OF = (GLfloat *) data2;
-
-  switch (A->type) {
-  case GL_FLOAT:
-    for (i = 0; i < count; i++)
-      {
-        for (j = 0; j < A->size; j++)
-          *OF++ = IF[j];
-        IF = (const GLfloat *) (((const unsigned char *) IF) + A->stride);
-      }
-    break;
-  case GL_UNSIGNED_BYTE:
-    for (i = 0; i < count; i++)
-      {
-        for (j = 0; j < A->size; j++)
-          *OB++ = IB[j];
-        IB += A->stride;
-      }
-    break;
-  default:
-    Assert (0, "bogus array type");
-    break;
-  }
-
-  A->data = data2;
-  A->bytes = bytes;
-  A->stride = stride2;
-
-# ifdef DEBUG
-  dump_array_data (A, count, "saved", name, 0);
-# endif
-}
-
-
-static void
-restore_arrays (list_fn *F, int count)
-{
-  int i = 0;
-  draw_array *A = F->arrays;
-  Assert (A, "missing array");
-
-  for (i = 0; i < 4; i++)
-    {
-      const char *name = 0;
-
-      if (!A[i].size)
-        continue;
-
-      Assert ((A[i].binding || A[i].data),
-              "array has neither buffer binding nor data");
-
-      glBindBuffer (GL_ARRAY_BUFFER, A[i].binding);
-      CHECK("glBindBuffer");
-
-      switch (i) {
-      case 0: glVertexPointer  (A[i].size, A[i].type, A[i].stride, A[i].data);
-        name = "vertex ";
-        CHECK("glVertexPointer");
-        break;
-      case 1: glNormalPointer  (           A[i].type, A[i].stride, A[i].data);
-        name = "normal ";
-        CHECK("glNormalPointer");
-        break;
-      case 2: glTexCoordPointer(A[i].size, A[i].type, A[i].stride, A[i].data);
-        name = "texture";
-        CHECK("glTexCoordPointer");
-        break;
-      case 3: glColorPointer   (A[i].size, A[i].type, A[i].stride, A[i].data);
-        name = "color  ";
-        CHECK("glColorPointer");
-        break;
-      default: Assert (0, "wat"); break;
-      }
-
-# ifdef DEBUG
-      dump_array_data (&A[i], count, "restored", name, 0);
-# endif
-    }
-
-  glBindBuffer (GL_ARRAY_BUFFER, 0);    /* Keep out of others' hands */
-}
-
-
-void
-jwzgles_glDrawArrays (GLuint mode, GLuint first, GLuint count)
-{
-  /* If we are auto-generating texture coordinates, do that now, after
-     the vertex array was installed, but before drawing, This happens
-     when recording into a list, or in direct mode.  It must happen
-     before calling optimize_arrays() from glEndList().
-   */
-  if (! state->replaying_list &&
-      ((state->compiling_list ? state->list_enabled : state->enabled)
-       & (ISENABLED_TEXTURE_GEN_S | ISENABLED_TEXTURE_GEN_T |
-          ISENABLED_TEXTURE_GEN_R | ISENABLED_TEXTURE_GEN_Q)))
-    generate_texture_coords (first, count);
-
-  if (state->compiling_list)
-    {
-      void_int vv[3];
-      vv[0].i = mode;
-      vv[1].i = first;
-      vv[2].i = count;
-      list_push ("glDrawArrays", (list_fn_cb) &jwzgles_glDrawArrays,
-                 PROTO_ARRAYS, vv);
-    }
-  else
-    {
-# ifdef DEBUG
-      if (! state->replaying_list) {
-        LOG4("direct %-12s %d %d %d", "glDrawArrays", mode, first, count);
-        dump_direct_array_data (first + count);
-      }
-# endif
-      glDrawArrays (mode, first, count);  /* the real one */
-      CHECK("glDrawArrays");
-    }
-}
-
-
-void
-jwzgles_glInterleavedArrays (GLenum format, GLsizei stride, const void *data)
-{
-  /* We can implement this by calling the various *Pointer functions
-     with offsets into the same data, taking advantage of stride.
-   */
-  const unsigned char *c = (const unsigned char *) data;
-# define B 1
-# define F sizeof(GLfloat)
-
-  Assert (!state->compiling_verts,
-          "glInterleavedArrays not allowed inside glBegin");
-
-  jwzgles_glEnableClientState (GL_VERTEX_ARRAY);
-
-  if (!state->replaying_list)
-    LOG4 ("%sglInterleavedArrays %s %d %lX", 
-          (state->compiling_list || state->replaying_list ? "  " : ""),
-          mode_desc (format), stride, (unsigned long) data);
-
-  switch (format) {
-  case GL_V2F:
-    glVertexPointer (2, GL_FLOAT, stride, c);
-    CHECK("glVertexPointer");
-    if (!state->replaying_list)
-      LOG3 ("%s  -> glVertexPointer 2 FLOAT %d %lX", 
-            (state->compiling_list || state->replaying_list ? "  " : ""),
-            stride, (unsigned long) c);
-    break;
-  case GL_V3F:
-    glVertexPointer (3, GL_FLOAT, stride, c);
-    CHECK("glVertexPointer");
-    if (!state->replaying_list)
-      LOG3 ("%s  -> glVertexPointer 3 FLOAT %d %lX", 
-            (state->compiling_list || state->replaying_list ? "  " : ""),
-            stride, (unsigned long) c);
-    break;
-  case GL_C4UB_V2F:    
-    if (stride == 0)
-      stride = 4*B + 2*F;
-    jwzgles_glEnableClientState (GL_COLOR_ARRAY);
-    glColorPointer (4, GL_UNSIGNED_BYTE, stride, c);
-    CHECK("glColorPointer");
-    c += 4*B;  /* #### might be incorrect float-aligned address */
-    glVertexPointer (2, GL_FLOAT, stride, c);
-    break;
-  case GL_C4UB_V3F:
-    if (stride == 0)
-      stride = 4*B + 3*F;
-    jwzgles_glEnableClientState (GL_COLOR_ARRAY);
-    glColorPointer (4, GL_UNSIGNED_BYTE, stride, c);
-    CHECK("glColorPointer");
-    c += 4*B;
-    glVertexPointer (3, GL_FLOAT, stride, c);
-    CHECK("glVertexPointer");
-    break;
-  case GL_C3F_V3F:
-    if (stride == 0)
-      stride = 3*F + 3*F;
-    jwzgles_glEnableClientState (GL_COLOR_ARRAY);
-    glColorPointer (3, GL_FLOAT, stride, c);
-    CHECK("glColorPointer");
-    c += 3*F;
-    glVertexPointer (3, GL_FLOAT, stride, c);
-    CHECK("glVertexPointer");
-    break;
-  case GL_N3F_V3F:
-    if (stride == 0)
-      stride = 3*F + 3*F;
-    jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
-    glNormalPointer (GL_FLOAT, stride, c);
-    CHECK("glNormalPointer");
-    if (!state->replaying_list)
-      LOG3 ("%s  -> glNormalPointer   FLOAT %d %lX", 
-            (state->compiling_list || state->replaying_list ? "  " : ""),
-            stride, (unsigned long) c);
-    c += 3*F;
-    glVertexPointer (3, GL_FLOAT, stride, c);
-    CHECK("glVertexPointer");
-    if (!state->replaying_list)
-      LOG3 ("%s  -> glVertexPointer 3 FLOAT %d %lX", 
-            (state->compiling_list || state->replaying_list ? "  " : ""),
-            stride, (unsigned long) c);
-    break;
-  case GL_C4F_N3F_V3F:
-    if (stride == 0)
-      stride = 4*F + 3*F + 3*F;
-    jwzgles_glEnableClientState (GL_COLOR_ARRAY);
-    glColorPointer (4, GL_FLOAT, stride, c);
-    CHECK("glColorPointer");
-    c += 4*F;
-    jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
-    glNormalPointer (GL_FLOAT, stride, c);
-    CHECK("glNormalPointer");
-    c += 3*F;
-    glVertexPointer (3, GL_FLOAT, stride, c);
-    CHECK("glVertexPointer");
-    break;
-  case GL_T2F_V3F:
-    if (stride == 0)
-      stride = 2*F + 3*F;
-    jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
-    glTexCoordPointer (2, GL_FLOAT, stride, c);
-    CHECK("glTexCoordPointer");
-    c += 2*F;
-    glVertexPointer (3, GL_FLOAT, stride, c);
-    CHECK("glVertexPointer");
-    break;
-  case GL_T4F_V4F:
-    if (stride == 0)
-      stride = 4*F + 4*F;
-    jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
-    glTexCoordPointer (4, GL_FLOAT, stride, c);
-    CHECK("glTexCoordPointer");
-    c += 4*F;
-    glVertexPointer (4, GL_FLOAT, stride, c);
-    CHECK("glVertexPointer");
-    break;
-  case GL_T2F_C4UB_V3F:
-    if (stride == 0)
-      stride = 2*F + 4*B + 3*F;
-    jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
-    glTexCoordPointer (2, GL_FLOAT, stride, c);
-    CHECK("glTexCoordPointer");
-    c += 2*F;
-    jwzgles_glEnableClientState (GL_COLOR_ARRAY);
-    glColorPointer  (4, GL_UNSIGNED_BYTE, stride, c);
-    CHECK("glColorPointer");
-    c += 4*B;
-    glVertexPointer (3, GL_FLOAT, stride, c);
-    CHECK("glVertexPointer");
-    break;
-  case GL_T2F_C3F_V3F:
-    if (stride == 0)
-      stride = 2*F + 3*F + 3*F;
-    jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
-    glTexCoordPointer (2, GL_FLOAT, stride, c);
-    CHECK("glTexCoordPointer");
-    c += 2*F;
-    jwzgles_glEnableClientState (GL_COLOR_ARRAY);
-    glColorPointer  (3, GL_FLOAT, stride, c);
-    CHECK("glColorPointer");
-    c += 3*F;
-    glVertexPointer (3, GL_FLOAT, stride, c);
-    CHECK("glVertexPointer");
-    break;
-  case GL_T2F_N3F_V3F:
-    if (stride == 0)
-      stride = 2*F + 3*F + 3*F;
-    jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
-    glTexCoordPointer (2, GL_FLOAT, stride, c);
-    CHECK("glTexCoordPointer");
-    c += 2*F;
-    jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
-    glNormalPointer (GL_FLOAT, stride, c);
-    CHECK("glNormalPointer");
-    c += 3*F;
-    glVertexPointer (3, GL_FLOAT, stride, c);
-    CHECK("glVertexPointer");
-    break;
-  case GL_T2F_C4F_N3F_V3F:
-    if (stride == 0)
-      stride = 2*F + 4*F + 3*F + 3*F;
-    jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
-    glTexCoordPointer (2, GL_FLOAT, stride, c);
-    CHECK("glTexCoordPointer");
-    c += 2*F;
-    jwzgles_glEnableClientState (GL_COLOR_ARRAY);
-    glColorPointer  (3, GL_FLOAT, stride, c);
-    CHECK("glColorPointer");
-    c += 3*F;
-    jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
-    glNormalPointer (GL_FLOAT, stride, c);
-    CHECK("glNormalPointer");
-    c += 3*F;
-    glVertexPointer (3, GL_FLOAT, stride, c);
-    CHECK("glVertexPointer");
-    break;
-  case GL_T4F_C4F_N3F_V4F:
-    if (stride == 0)
-      stride = 4*F + 4*F + 3*F + 4*F;
-    jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
-    glTexCoordPointer (4, GL_FLOAT, stride, c);
-    CHECK("glTexCoordPointer");
-    c += 4*F;
-    jwzgles_glEnableClientState (GL_COLOR_ARRAY);
-    glColorPointer  (4, GL_FLOAT, stride, c);
-    CHECK("glColorPointer");
-    c += 4*F;
-    jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
-    glNormalPointer (GL_FLOAT, stride, c);
-    CHECK("glNormalPointer");
-    c += 3*F;
-    glVertexPointer (3, GL_FLOAT, stride, c);
-    CHECK("glVertexPointer");
-    break;
-  default:
-    Assert (0, "glInterleavedArrays: bogus format");
-    break;
-  }
-
-# undef B
-# undef F
-}
-
-
-
-void
-jwzgles_glMultMatrixf (const GLfloat *m)
-{
-  Assert (!state->compiling_verts,
-          "glMultMatrixf not allowed inside glBegin");
-  if (state->compiling_list)
-    {
-      void_int vv[16];
-      int i;
-      for (i = 0; i < countof(vv); i++)
-        vv[i].f = m[i];
-      list_push ("glMultMatrixf", (list_fn_cb) &jwzgles_glMultMatrixf,
-                 PROTO_FV16, vv);
-    }
-  else
-    {
-      if (! state->replaying_list)
-        LOG1 ("direct %-12s", "glMultMatrixf");
-      glMultMatrixf (m);  /* the real one */
-      CHECK("glMultMatrixf");
-    }
-}
-
-
-void
-jwzgles_glClearIndex(GLfloat c)
-{
-  /* Does GLES even do indexed color? */
-  Assert (0, "glClearIndex unimplemented");
-}
-
-
-void
-jwzgles_glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig,
-                  GLfloat xmove, GLfloat ymove, const GLubyte *bitmap)
-{
-  Assert (0, "glBitmap unimplemented");
-}
-
-void
-jwzgles_glPushAttrib(int flags)
-{
-  Assert (0, "glPushAttrib unimplemented");
-}
-
-void
-jwzgles_glPopAttrib(void)
-{
-  Assert (0, "glPopAttrib unimplemented");
-}
-
-
-/* These are needed for object hit detection in pinion.
-   Might need to rewrite that code entirely.  Punt for now.
- */
-void
-jwzgles_glInitNames (void)
-{
-/*  Assert (0, "glInitNames unimplemented");*/
-}
-
-void
-jwzgles_glPushName (GLuint name)
-{
-/*  Assert (0, "glPushName unimplemented");*/
-}
-
-GLuint
-jwzgles_glPopName (void)
-{
-/*  Assert (0, "glPopName unimplemented");*/
-  return 0;
-}
-
-GLuint
-jwzgles_glRenderMode (GLuint mode)
-{
-/*  Assert (0, "glRenderMode unimplemented");*/
-  return 0;
-}
-
-void
-jwzgles_glSelectBuffer (GLsizei size, GLuint *buf)
-{
-/*  Assert (0, "glSelectBuffer unimplemented");*/
-}
-
-
-void
-jwzgles_glGenTextures (GLuint n, GLuint *ret)
-{
-  Assert (!state->compiling_verts,
-          "glGenTextures not allowed inside glBegin");
-  /* technically legal, but stupid! */
-  Assert (!state->compiling_list,
-          "glGenTextures not allowed inside glNewList");
-  if (! state->replaying_list)
-    LOG1 ("direct %-12s", "glGenTextures");
-  glGenTextures (n, ret);  /* the real one */
-  CHECK("glGenTextures");
-}
-
-
-/* return the next larger power of 2. */
-static int
-to_pow2 (int value)
-{
-  int i = 1;
-  while (i < value) i <<= 1;
-  return i;
-}
-
-void
-jwzgles_glTexImage1D (GLenum target, GLint level,
-                      GLint internalFormat,
-                      GLsizei width, GLint border,
-                      GLenum format, GLenum type,
-                      const GLvoid *data)
-{
-  Assert (!state->compiling_verts, "glTexImage1D not allowed inside glBegin");
-  /* technically legal, but stupid! */
-  Assert (!state->compiling_list, "glTexImage1D inside glNewList");
-  Assert (width  == to_pow2(width), "width must be a power of 2");
-
-  if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D;
-  jwzgles_glTexImage2D (target, level, internalFormat, width, 1,
-                        border, format, type, data);
-}
-
-void
-jwzgles_glTexImage2D (GLenum target,
-                      GLint    level,
-                      GLint    internalFormat,
-                      GLsizei          width,
-                      GLsizei          height,
-                      GLint    border,
-                      GLenum   format,
-                      GLenum   type,
-                      const GLvoid *data)
-{
-  GLvoid *d2 = (GLvoid *) data;
-  Assert (!state->compiling_verts, "glTexImage2D not allowed inside glBegin");
-  Assert (!state->compiling_list,  /* technically legal, but stupid! */
-          "glTexImage2D not allowed inside glNewList");
-
-  Assert (width  == to_pow2(width),   "width must be a power of 2");
-  Assert (height == to_pow2(height), "height must be a power of 2");
-
-  /* OpenGLES no longer supports "4" as a synonym for "RGBA". */
-  switch (internalFormat) {
-  case 1: internalFormat = GL_LUMINANCE; break;
-  case 2: internalFormat = GL_LUMINANCE_ALPHA; break;
-  case 3: internalFormat = GL_RGB; break;
-  case 4: internalFormat = GL_RGBA; break;
-  }
-
-  /* GLES does not let us omit the data pointer to create a blank texture. */
-  if (! data)
-    {
-      d2 = (GLvoid *) calloc (1, width * height * sizeof(GLfloat) * 4);
-      Assert (d2, "out of memory");
-    }
-
-  if (internalFormat == GL_RGB && format == GL_RGBA)
-    internalFormat = GL_RGBA;  /* WTF */
-  if (type == GL_UNSIGNED_INT_8_8_8_8_REV)
-    type = GL_UNSIGNED_BYTE;
-
-  if (! state->replaying_list)
-    LOG10 ("direct %-12s %s %d %s %d %d %d %s %s 0x%lX", "glTexImage2D", 
-           mode_desc(target), level, mode_desc(internalFormat),
-           width, height, border, mode_desc(format), mode_desc(type),
-           (unsigned long) d2);
-  glTexImage2D (target, level, internalFormat, width, height, border,
-                format, type, d2);  /* the real one */
-  CHECK("glTexImage2D");
-
-  if (d2 != data) free (d2);
-}
-
-void
-jwzgles_glTexSubImage2D (GLenum target, GLint level,
-                         GLint xoffset, GLint yoffset,
-                         GLsizei width, GLsizei height,
-                         GLenum format, GLenum type,
-                         const GLvoid *pixels)
-{
-  Assert (!state->compiling_verts,
-          "glTexSubImage2D not allowed inside glBegin");
-  Assert (!state->compiling_list,   /* technically legal, but stupid! */
-          "glTexSubImage2D not allowed inside glNewList");
-
-  if (! state->replaying_list)
-    LOG10 ("direct %-12s %s %d %d %d %d %d %s %s 0x%lX", "glTexSubImage2D", 
-           mode_desc(target), level, xoffset, yoffset, width, height,
-           mode_desc (format), mode_desc (type), (unsigned long) pixels);
-  glTexSubImage2D (target, level, xoffset, yoffset, width, height,
-                   format, type, pixels);  /* the real one */
-  CHECK("glTexSubImage2D");
-}
-
-void
-jwzgles_glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat,
-                          GLint x, GLint y, GLsizei width, GLsizei height,
-                          GLint border)
-{
-  Assert (!state->compiling_verts, 
-          "glCopyTexImage2D not allowed inside glBegin");
-  Assert (!state->compiling_list,    /* technically legal, but stupid! */
-          "glCopyTexImage2D not allowed inside glNewList");
-  if (! state->replaying_list)
-    LOG9 ("direct %-12s %s %d %s %d %d %d %d %d", "glCopyTexImage2D", 
-          mode_desc(target), level, mode_desc(internalformat),
-          x, y, width, height, border);
-  glCopyTexImage2D (target, level, internalformat, x, y, width, height,
-                    border);  /* the real one */
-  CHECK("glCopyTexImage2D");
-}
-
-
-/* OpenGLES doesn't have auto texture-generation at all!
-   "Oh, just rewrite that code to use GPU shaders", they say.
-   How fucking convenient.
- */
-void
-jwzgles_glTexGenfv (GLenum coord, GLenum pname, const GLfloat *params)
-{
-  texgen_state *s;
-
-  if (pname == GL_TEXTURE_GEN_MODE)
-    LOG5 ("%sdirect %-12s %s %s %s", 
-          (state->compiling_list || state->replaying_list ? "  " : ""),
-          "glTexGenfv",
-          mode_desc(coord), mode_desc(pname), mode_desc(params[0]));
-  else
-    LOG8 ("%sdirect %-12s %s %s %3.1f %3.1f %3.1f %3.1f",
-          (state->compiling_list || state->replaying_list ? "  " : ""),
-          "glTexGenfv",
-          mode_desc(coord), mode_desc(pname),
-          params[0], params[1], params[2], params[3]);
-
-  switch (coord) {
-  case GL_S: s = &state->s; break;
-  case GL_T: s = &state->t; break;
-  case GL_R: s = &state->r; break;
-  case GL_Q: s = &state->q; break;
-  default: Assert (0, "glGetTexGenfv: unknown coord"); break;
-  }
-
-  switch (pname) {
-  case GL_TEXTURE_GEN_MODE: s->mode = params[0]; break;
-  case GL_OBJECT_PLANE:     memcpy (s->obj, params, sizeof(s->obj)); break;
-  case GL_EYE_PLANE:        memcpy (s->eye, params, sizeof(s->eye)); break;
-  default: Assert (0, "glTexGenfv: unknown pname"); break;
-  }
-}
-
-void
-jwzgles_glTexGeni (GLenum coord, GLenum pname, GLint param)
-{
-  GLfloat v = param;
-  jwzgles_glTexGenfv (coord, pname, &v);
-}
-
-void
-jwzgles_glGetTexGenfv (GLenum coord, GLenum pname, GLfloat *params)
-{
-  texgen_state *s;
-
-  switch (coord) {
-  case GL_S: s = &state->s; break;
-  case GL_T: s = &state->t; break;
-  case GL_R: s = &state->r; break;
-  case GL_Q: s = &state->q; break;
-  default: Assert (0, "glGetTexGenfv: unknown coord"); break;
-  }
-
-  switch (pname) {
-  case GL_TEXTURE_GEN_MODE: params[0] = s->mode; break;
-  case GL_OBJECT_PLANE:     memcpy (params, s->obj, sizeof(s->obj)); break;
-  case GL_EYE_PLANE:        memcpy (params, s->eye, sizeof(s->eye)); break;
-  default: Assert (0, "glGetTexGenfv: unknown pname"); break;
-  }
-
-  if (pname == GL_TEXTURE_GEN_MODE)
-    LOG5 ("%sdirect %-12s %s %s -> %s", 
-          (state->compiling_list || state->replaying_list ? "  " : ""),
-          "glGetTexGenfv",
-          mode_desc(coord), mode_desc(pname), mode_desc(params[0]));
-  else
-    LOG8 ("%sdirect %-12s %s %s -> %3.1f %3.1f %3.1f %3.1f",
-          (state->compiling_list || state->replaying_list ? "  " : ""),
-          "glGetTexGenfv",
-          mode_desc(coord), mode_desc(pname),
-          params[0], params[1], params[2], params[3]);
-}
-
-
-static GLfloat
-dot_product (int rank, GLfloat *a, GLfloat *b)
-{
-  /* A dot B  =>  (A[1] * B[1]) + ... + (A[n] * B[n]) */
-  GLfloat ret = 0;
-  int i;
-  for (i = 0; i < rank; i++) 
-    ret += a[i] * b[i];
-  return ret;
-}
-
-
-
-/* Compute the texture coordinates of the prevailing list of verts as per
-   http://www.opengl.org/wiki/Mathematics_of_glTexGen
- */
-static void
-generate_texture_coords (GLuint first, GLuint count)
-{
-  GLfloat *tex_out, *tex_array;
-  GLsizei tex_stride;
-  GLuint i;
-  draw_array A = { 0, };
-  char *verts_in;
-
-  struct { GLuint which, flag, mode; GLfloat plane[4]; } tg[4] = {
-    { GL_S, ISENABLED_TEXTURE_GEN_S, 0, { 0, } },
-    { GL_T, ISENABLED_TEXTURE_GEN_T, 0, { 0, } },
-    { GL_R, ISENABLED_TEXTURE_GEN_R, 0, { 0, } },
-    { GL_Q, ISENABLED_TEXTURE_GEN_Q, 0, { 0, }}};
-                                                    
-  int tcoords = 0;
-
-  /* Read the texture plane configs that were stored with glTexGen.
-   */
-  for (i = 0; i < countof(tg); i++)
-    {
-      GLfloat mode = 0;
-      if (! ((state->compiling_list ? state->list_enabled : state->enabled)
-             & tg[i].flag))
-        continue;
-      jwzgles_glGetTexGenfv (tg[i].which, GL_TEXTURE_GEN_MODE, &mode);
-      jwzgles_glGetTexGenfv (tg[i].which, GL_OBJECT_PLANE, tg[i].plane);
-      tg[i].mode = mode;
-      tcoords++;
-    }
-
-  if (tcoords == 0) return;  /* Nothing to do! */
-
-
-  /* Make the array to store our texture coords in. */
-
-  tex_stride = tcoords * sizeof(GLfloat);
-  tex_array = (GLfloat *) calloc (first + count, tex_stride);
-  tex_out = tex_array;
-
-
-  /* Read the prevailing vertex array, that was stored with
-     glVertexPointer or glInterleavedArrays.
-   */
-  glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A.binding);
-  glGetIntegerv (GL_VERTEX_ARRAY_SIZE,    &A.size);
-  glGetIntegerv (GL_VERTEX_ARRAY_TYPE,    &A.type);
-  glGetIntegerv (GL_VERTEX_ARRAY_STRIDE,  &A.stride);
-  glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A.data);
-  A.bytes = count * A.stride;
-
-  verts_in = (char *) A.data;
-
-  /* Iterate over each vertex we're drawing.
-     We just skip the ones < start, but the tex array has
-     left room for zeroes there anyway.
-   */
-  for (i = first; i < first + count; i++)
-    {
-      GLfloat vert[4] = { 0, };
-      int j, k;
-
-      /* Extract this vertex into `vert' as a float, whatever its type was. */
-      for (j = 0; j < A.size; j++)
-        {
-          switch (A.type) {
-          case GL_SHORT:  vert[j] = ((GLshort *)  verts_in)[j]; break;
-          case GL_INT:    vert[j] = ((GLint *)    verts_in)[j]; break;
-          case GL_FLOAT:  vert[j] = ((GLfloat *)  verts_in)[j]; break;
-          case GL_DOUBLE: vert[j] = ((GLdouble *) verts_in)[j]; break;
-          default: Assert (0, "unknown vertex type"); break;
-          }
-        }
-
-      /* Compute the texture coordinate for this vertex.
-         For GL_OBJECT_LINEAR, these coordinates are static, and can go
-         into the display list.  But for GL_EYE_LINEAR, GL_SPHERE_MAP and
-         GL_REFLECTION_MAP, they depend on the prevailing ModelView matrix,
-         and so need to be computed afresh each time glDrawArrays is called.
-         Unfortunately, our verts and norms are gone by then, dumped down
-         into the VBO and discarded from CPU RAM.  Bleh.
-       */
-      for (j = 0, k = 0; j < countof(tg); j++)
-        {
-          if (! ((state->compiling_list ? state->list_enabled : state->enabled)
-                 & tg[j].flag))
-            continue;
-          switch (tg[j].mode) {
-          case GL_OBJECT_LINEAR:
-            tex_out[k] = dot_product (4, vert, tg[j].plane);
-            break;
-          default:
-            Assert (0, "unimplemented texture mode");
-            break;
-          }
-          k++;
-        }
-
-      /* fprintf (stderr, "%4d: V %-5.1f %-5.1f %-5.1f  T %-5.1f %-5.1f\n",
-               i, vert[0], vert[1], vert[2], tex_out[0], tex_out[1]); */
-
-      /* Move verts_in and tex_out forward to the next vertex by stride. */
-      verts_in += A.stride;
-      tex_out = (GLfloat *) (((char *) tex_out) + tex_stride);
-    }
-
-  jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
-  jwzgles_glTexCoordPointer (tcoords, GL_FLOAT, tex_stride,
-                             (GLvoid *) tex_array);
-  free (tex_array);
-}
-
-
-int
-jwzgles_gluBuild2DMipmaps (GLenum target,
-                           GLint       internalFormat,
-                           GLsizei     width,
-                           GLsizei     height,
-                           GLenum      format,
-                           GLenum      type,
-                           const GLvoid *data)
-{
-  /* Not really bothering with mipmapping; only making one level.
-     Note that this required a corresponding hack in glTexParameterf().
-   */
-
-  int w2 = to_pow2(width);
-  int h2 = to_pow2(height);
-
-  void *d2 = (void *) data;
-
-  /* OpenGLES no longer supports "4" as a synonym for "RGBA". */
-  switch (internalFormat) {
-  case 1: internalFormat = GL_LUMINANCE; break;
-  case 2: internalFormat = GL_LUMINANCE_ALPHA; break;
-  case 3: internalFormat = GL_RGB; break;
-  case 4: internalFormat = GL_RGBA; break;
-  }
-
-/*  if (w2 < h2) w2 = h2;
-  if (h2 < w2) h2 = w2;*/
-
-  if (w2 != width || h2 != height)
-    {
-      /* Scale up the image bits to fit the power-of-2 texture.
-         We have to do this because the mipmap API assumes that
-         the texture bits go to texture coordinates 1.0 x 1.0.
-         This could be more efficient, but it doesn't happen often.
-      */
-      int istride = (format == GL_RGBA ? 4 : 3);
-      int ostride = 4;
-      int ibpl = istride * width;
-      int obpl = ostride * w2;
-      int oy;
-      const unsigned char *in = (unsigned char *) data;
-      unsigned char *out = (void *) malloc (h2 * obpl);
-      Assert (out, "out of memory");
-      d2 = out;
-
-      for (oy = 0; oy < h2; oy++)
-        {
-          int iy = oy * height / h2;
-          const unsigned char *iline = in  + (iy * ibpl);
-          unsigned char       *oline = out + (oy * obpl);
-          int ox;
-          for (ox = 0; ox < w2; ox++)
-            {
-              int ix = ox * width / w2;
-              const unsigned char *i = iline + (ix * istride);
-              unsigned char       *o = oline + (ox * ostride);
-              *o++ = *i++;  /* R */
-              *o++ = *i++;  /* G */
-              *o++ = *i++;  /* B */
-              *o++ = (istride == 4 ? *i : 0xFF); /* A */
-            }
-        }
-      width  = w2;
-      height = h2;
-      internalFormat = GL_RGBA;
-      format = GL_RGBA;
-    }
-
-  jwzgles_glTexImage2D (target, 0, internalFormat, w2, h2, 0, 
-                        format, type, d2);
-  if (d2 != data) free (d2);
-
-  return 0;
-}
-
-
-void
-jwzgles_glRectf (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
-{
-  jwzgles_glBegin (GL_POLYGON);
-  jwzgles_glVertex2f (x1, y1);
-  jwzgles_glVertex2f (x2, y1);
-  jwzgles_glVertex2f (x2, y2);
-  jwzgles_glVertex2f (x1, y2);
-  jwzgles_glEnd ();
-}
-
-void
-jwzgles_glRecti (GLint x1, GLint y1, GLint x2, GLint y2)
-{
-  jwzgles_glRectf (x1, y1, x2, y2);
-}
-
-void
-jwzgles_glClearDepth (GLfloat d)
-{
-  /* Not sure what to do here */
-  Assert (d == 1.0, "glClearDepth unimplemented");
-}
-
-
-/* When in immediate mode, we store a bit into state->enabled, and also
-   call the real glEnable() / glDisable().
-
-   When recording a list, we store a bit into state->list_enabled instead,
-   so that we can see what the prevailing enablement state will be when
-   the list is run.
-
-   set: 1 = set, -1 = clear, 0 = query.
-*/
-static int
-enable_disable (GLuint bit, int set)
-{
-  int result = (set > 0);
-  int omitp = 0;
-  int csp = 0;
-  unsigned long flag = 0;
-
-  switch (bit) {
-  case GL_TEXTURE_1D:     /* We implement 1D textures as 2D textures. */
-  case GL_TEXTURE_2D:     flag = ISENABLED_TEXTURE_2D;              break;
-  case GL_TEXTURE_GEN_S:  flag = ISENABLED_TEXTURE_GEN_S; omitp = 1; break;
-  case GL_TEXTURE_GEN_T:  flag = ISENABLED_TEXTURE_GEN_T; omitp = 1; break;
-  case GL_TEXTURE_GEN_R:  flag = ISENABLED_TEXTURE_GEN_R; omitp = 1; break;
-  case GL_TEXTURE_GEN_Q:  flag = ISENABLED_TEXTURE_GEN_Q; omitp = 1; break;
-  case GL_LIGHTING:       flag = ISENABLED_LIGHTING;                break;
-  case GL_BLEND:          flag = ISENABLED_BLEND;                   break;
-  case GL_DEPTH_TEST:     flag = ISENABLED_DEPTH_TEST;              break;
-  case GL_ALPHA_TEST:     flag = ISENABLED_ALPHA_TEST;              break;
-  case GL_CULL_FACE:      flag = ISENABLED_CULL_FACE;               break;
-  case GL_NORMALIZE:      flag = ISENABLED_NORMALIZE;               break;
-  case GL_FOG:            flag = ISENABLED_FOG;                             break;
-  case GL_COLOR_MATERIAL: flag = ISENABLED_COLMAT;                  break;
-
-  /* Maybe technically these only work with glEnableClientState,
-     but we treat that as synonymous with glEnable. */
-  case GL_VERTEX_ARRAY:   flag = ISENABLED_VERT_ARRAY;     csp = 1;  break;
-  case GL_NORMAL_ARRAY:   flag = ISENABLED_NORM_ARRAY;     csp = 1;  break;
-  case GL_COLOR_ARRAY:    flag = ISENABLED_COLOR_ARRAY;    csp = 1;  break;
-  case GL_TEXTURE_COORD_ARRAY: flag = ISENABLED_TEX_ARRAY; csp = 1;  break;
-
-  default:
-    Assert (set != 0, "glIsEnabled unimplemented bit");
-    break;
-  }
-
-  if (set)  /* setting or unsetting, not querying */
-    {
-      const char *fns[4] = { "glEnable", "glDisable",
-                             "glEnableClientState", "glDisableClientState" };
-      list_fn_cb fs[4] = { (list_fn_cb) &jwzgles_glEnable,
-                           (list_fn_cb) &jwzgles_glDisable,
-                           (list_fn_cb) &jwzgles_glEnableClientState,
-                           (list_fn_cb) &jwzgles_glDisableClientState };
-      const char *fn = fns[(csp ? 2 : 0) + (set < 0 ? 1 : 0)];
-      list_fn_cb  f  =  fs[(csp ? 2 : 0) + (set < 0 ? 1 : 0)];
-
-      Assert (!state->compiling_verts,
-              "glEnable/glDisable not allowed inside glBegin");
-
-      if (state->compiling_list)
-        {
-          void_int vv[1];
-          vv[0].i = bit;
-          list_push (fn, f,PROTO_I, vv);
-        }
-
-      if (! state->replaying_list &&
-          ! state->compiling_list)
-        LOG2 ("direct %-12s %s", fn, mode_desc(bit));
-
-      if (csp && !state->compiling_verts)
-        {
-          if (set > 0)
-            switch (bit) {
-            case GL_NORMAL_ARRAY: state->set.ncount        += 2; break;
-            case GL_TEXTURE_COORD_ARRAY: state->set.tcount += 2; break;
-            case GL_COLOR_ARRAY: state->set.ccount         += 2; break;
-            default: break;
-            }
-          else
-            switch (bit) {
-            case GL_NORMAL_ARRAY: state->set.ncount        = 0; break;
-            case GL_TEXTURE_COORD_ARRAY: state->set.tcount = 0; break;
-            case GL_COLOR_ARRAY: state->set.ccount         = 0; break;
-            default: break;
-            }
-        }
-
-      if (omitp || state->compiling_list)
-        ;
-      else if (set > 0 && csp)
-        glEnableClientState (bit);     /* the real one */
-      else if (set < 0 && csp)
-        glDisableClientState (bit);    /* the real one */
-      else if (set > 0)
-        glEnable (bit);                        /* the real one */
-      else
-        glDisable (bit);               /* the real one */
-
-      CHECK(fn);
-    }
-
-  /* Store the bit in our state as well, or query it.
-   */
-  if (flag)
-    {
-      unsigned long *enabled = (state->compiling_list
-                                ? &state->list_enabled
-                                : &state->enabled);
-      if (set > 0)
-        *enabled |= flag;
-      else if (set < 0)
-        *enabled &= ~flag;
-      else
-        result = !!(*enabled & flag);
-    }
-
-  return result;
-}
-
-
-void
-jwzgles_glEnable (GLuint bit)
-{
-  enable_disable (bit, 1);
-}
-
-void
-jwzgles_glDisable (GLuint bit)
-{
-  enable_disable (bit, -1);
-}
-
-GLboolean
-jwzgles_glIsEnabled (GLuint bit)
-{
-  return enable_disable (bit, 0);
-}
-
-void
-jwzgles_glEnableClientState (GLuint cap)
-{
-  enable_disable (cap, 1);
-}
-
-void
-jwzgles_glDisableClientState (GLuint cap)
-{
-  enable_disable (cap, -1);
-}
-
-
-
-/* The spec says that OpenGLES 1.x doesn't implement glGetFloatv.
-   Were this true, it would suck, for it would mean that there was no
-   way to retrieve the prevailing matrixes.  To implement this, we'd
-   have to keep track of them all on the client side by combining in
-   all the actions of glMultMatrixf, glRotatef, etc.
-
-   However, Apple's iOS OpenGLES *does* provide glGetFloatv!
- */
-void
-jwzgles_glGetFloatv (GLenum pname, GLfloat *params)
-{
-  if (! state->replaying_list)
-    LOG2 ("direct %-12s %s", "glGetFloatv", mode_desc(pname));
-  glGetFloatv (pname, params);  /* the real one */
-  CHECK("glGetFloatv");
-}
-
-
-/* Likewise: not supposed to be there, but it is. */
-void
-jwzgles_glGetPointerv (GLenum pname, GLvoid *params)
-{
-  if (! state->replaying_list)
-    LOG2 ("direct %-12s %s", "glGetPointerv", mode_desc(pname));
-  glGetPointerv (pname, params);  /* the real one */
-  CHECK("glGetPointerv");
-}
-
-
-/* How many cells are written into the *params array.
-   We need to know this to avoid smashing the caller's stack
-   if they asked for a single-value parameter.
- */
-static int
-glGet_ret_count (GLenum pname)
-{
-  switch (pname) {
-/*case GL_COLOR_MATRIX: */
-  case GL_MODELVIEW_MATRIX:
-  case GL_PROJECTION_MATRIX:
-  case GL_TEXTURE_MATRIX:
-/*case GL_TRANSPOSE_COLOR_MATRIX: */
-/*case GL_TRANSPOSE_MODELVIEW_MATRIX: */
-/*case GL_TRANSPOSE_PROJECTION_MATRIX: */
-/*case GL_TRANSPOSE_TEXTURE_MATRIX: */
-    return 16;
-/*case GL_ACCUM_CLEAR_VALUE: */
-/*case GL_BLEND_COLOR: */
-  case GL_COLOR_CLEAR_VALUE:
-  case GL_COLOR_WRITEMASK:
-  case GL_CURRENT_COLOR:
-/*case GL_CURRENT_RASTER_COLOR: */
-/*case GL_CURRENT_RASTER_POSITION: */
-/*case GL_CURRENT_RASTER_SECONDARY_COLOR: */
-/*case GL_CURRENT_RASTER_TEXTURE_COORDS: */
-/*case GL_CURRENT_SECONDARY_COLOR: */
-  case GL_CURRENT_TEXTURE_COORDS:
-  case GL_FOG_COLOR:
-  case GL_LIGHT_MODEL_AMBIENT:
-/*case GL_MAP2_GRID_DOMAIN: */
-  case GL_SCISSOR_BOX:
-  case GL_VIEWPORT:
-    return 4;
-  case GL_CURRENT_NORMAL:
-  case GL_POINT_DISTANCE_ATTENUATION:
-    return 3;
-  case GL_ALIASED_LINE_WIDTH_RANGE:
-  case GL_ALIASED_POINT_SIZE_RANGE:
-  case GL_DEPTH_RANGE:
-/*case GL_LINE_WIDTH_RANGE: */
-/*case GL_MAP1_GRID_DOMAIN: */
-/*case GL_MAP2_GRID_SEGMENTS: */
-  case GL_MAX_VIEWPORT_DIMS:
-/*case GL_POINT_SIZE_RANGE: */
-  case GL_POLYGON_MODE:
-  case GL_SMOOTH_LINE_WIDTH_RANGE:
-  case GL_SMOOTH_POINT_SIZE_RANGE:
-    return 2;
-  default:
-    return 1;
-  }
-}
-
-
-void
-jwzgles_glGetDoublev (GLenum pname, GLdouble *params)
-{
-  GLfloat m[16];
-  int i, j = glGet_ret_count (pname);
-  jwzgles_glGetFloatv (pname, m);
-  for (i = 0; i < j; i++)
-    params[i] = m[i];
-}
-
-
-void
-jwzgles_glGetIntegerv (GLenum pname, GLint *params)
-{
-  GLfloat m[16];
-  int i, j = glGet_ret_count (pname);
-  jwzgles_glGetFloatv (pname, m);
-  for (i = 0; i < j; i++)
-    params[i] = m[i];
-}
-
-
-void
-jwzgles_glGetBooleanv (GLenum pname, GLboolean *params)
-{
-  GLfloat m[16];
-  int i, j = glGet_ret_count (pname);
-  jwzgles_glGetFloatv (pname, m);
-  for (i = 0; i < j; i++)
-    params[i] = (m[i] != 0.0);
-}
-
-
-const char *
-jwzgles_gluErrorString (GLenum error)
-{
-  static char s[20];
-  sprintf (s, "0x%lX", (unsigned long) error);
-  return s;
-}
-
-
-/* These four *Pointer calls (plus glBindBuffer and glBufferData) can
-   be included inside glNewList, but they actually execute immediately
-   anyway, because their data is recorded in the list by the
-   subsequently-recorded call to glDrawArrays.  This is a little weird.
- */
-void
-jwzgles_glVertexPointer (GLuint size, GLuint type, GLuint stride, 
-                         const GLvoid *ptr)
-{
-  if (! state->replaying_list)
-    LOG5 ("direct %-12s %d %s %d 0x%lX", "glVertexPointer", 
-          size, mode_desc(type), stride, (unsigned long) ptr);
-  glVertexPointer (size, type, stride, ptr);  /* the real one */
-  CHECK("glVertexPointer");
-}
-
-
-void
-jwzgles_glNormalPointer (GLuint type, GLuint stride, const GLvoid *ptr)
-{
-  if (! state->replaying_list)
-    LOG4 ("direct %-12s %s %d 0x%lX", "glNormalPointer", 
-          mode_desc(type), stride, (unsigned long) ptr);
-  glNormalPointer (type, stride, ptr);  /* the real one */
-  CHECK("glNormalPointer");
-}
-
-void
-jwzgles_glColorPointer (GLuint size, GLuint type, GLuint stride, 
-                        const GLvoid *ptr)
-{
-  if (! state->replaying_list)
-    LOG5 ("direct %-12s %d %s %d 0x%lX", "glColorPointer", 
-          size, mode_desc(type), stride, (unsigned long) ptr);
-  glColorPointer (size, type, stride, ptr);  /* the real one */
-  CHECK("glColorPointer");
-}
-
-void
-jwzgles_glTexCoordPointer (GLuint size, GLuint type, GLuint stride, 
-                           const GLvoid *ptr)
-{
-  if (! state->replaying_list)
-    LOG5 ("direct %-12s %d %s %d 0x%lX", "glTexCoordPointer", 
-          size, mode_desc(type), stride, (unsigned long) ptr);
-  glTexCoordPointer (size, type, stride, ptr);  /* the real one */
-  CHECK("glTexCoordPointer");
-}
-
-void
-jwzgles_glBindBuffer (GLuint target, GLuint buffer)
-{
-  if (! state->replaying_list)
-    LOG3 ("direct %-12s %s %d", "glBindBuffer", mode_desc(target), buffer);
-  glBindBuffer (target, buffer);  /* the real one */
-  CHECK("glBindBuffer");
-}
-
-void
-jwzgles_glBufferData (GLenum target, GLsizeiptr size, const void *data,
-                      GLenum usage)
-{
-  if (! state->replaying_list)
-    LOG5 ("direct %-12s %s %ld 0x%lX %s", "glBufferData",
-          mode_desc(target), size, (unsigned long) data, mode_desc(usage));
-  glBufferData (target, size, data, usage);  /* the real one */
-  CHECK("glBufferData");
-}
-
-
-void
-jwzgles_glTexParameterf (GLuint target, GLuint pname, GLfloat param)
-{
-  Assert (!state->compiling_verts,
-          "glTexParameterf not allowed inside glBegin");
-
-  /* We don't *really* implement mipmaps, so just turn this off. */
-  if (param == GL_LINEAR_MIPMAP_LINEAR)   param = GL_LINEAR;
-  if (param == GL_NEAREST_MIPMAP_LINEAR)  param = GL_LINEAR;
-  if (param == GL_LINEAR_MIPMAP_NEAREST)  param = GL_NEAREST;
-  if (param == GL_NEAREST_MIPMAP_NEAREST) param = GL_NEAREST;
-
-  /* We implement 1D textures as 2D textures. */
-  if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D;
-
-  /* Apparently this is another invalid enum. Just ignore it. */
-  if ((pname == GL_TEXTURE_WRAP_S || pname == GL_TEXTURE_WRAP_T) &&
-      param == GL_CLAMP)
-    return;
-
-  if (state->compiling_list)
-    {
-      void_int vv[3];
-      vv[0].i = target;
-      vv[1].i = pname;
-      vv[2].f = param;
-      list_push ("glTexParameterf", (list_fn_cb) &jwzgles_glTexParameterf,
-                 PROTO_IIF, vv);
-    }
-  else
-    {
-      if (! state->replaying_list)
-        LOG4 ("direct %-12s %s %s %7.3f", "glTexParameterf", 
-              mode_desc(target), mode_desc(pname), param);
-      glTexParameterf (target, pname, param);  /* the real one */
-      CHECK("glTexParameterf");
-    }
-}
-
-void
-jwzgles_glTexParameteri (GLuint target, GLuint pname, GLuint param)
-{
-  jwzgles_glTexParameterf (target, pname, param);
-}
-
-
-void
-jwzgles_glBindTexture (GLuint target, GLuint texture)
-{
-  Assert (!state->compiling_verts,
-          "glBindTexture not allowed inside glBegin");
-
-  /* We implement 1D textures as 2D textures. */
-  if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D;
-
-  if (state->compiling_list)
-    {
-      void_int vv[2];
-      vv[0].i = target;
-      vv[1].i = texture;
-      list_push ("glBindTexture", (list_fn_cb) &jwzgles_glBindTexture,
-                 PROTO_II, vv);
-    }
-
-  /* Do it immediately as well, for generate_texture_coords */
-  /* else */
-    {
-      if (! state->replaying_list)
-        LOG3 ("direct %-12s %s %d", "glBindTexture", 
-              mode_desc(target), texture);
-      glBindTexture (target, texture);  /* the real one */
-      CHECK("glBindTexture");
-    }
-}
-
-
-
-/* Matrix functions, mostly cribbed from Mesa.
- */
-
-void
-jwzgles_glFrustum (GLfloat left,   GLfloat right,
-                   GLfloat bottom, GLfloat top,
-                   GLfloat near,   GLfloat far)
-{
-  GLfloat m[16];
-  GLfloat x = (2 * near)        / (right-left);
-  GLfloat y = (2 * near)        / (top - bottom);
-  GLfloat a = (right + left)    / (right - left);
-  GLfloat b = (top + bottom)    / (top - bottom);
-  GLfloat c = -(far + near)     / (far - near);
-  GLfloat d = -(2 * far * near) / (far - near);
-
-# define M(X,Y)  m[Y * 4 + X]
-  M(0,0) = x; M(0,1) = 0; M(0,2) =  a; M(0,3) = 0;
-  M(1,0) = 0; M(1,1) = y; M(1,2) =  b; M(1,3) = 0;
-  M(2,0) = 0; M(2,1) = 0; M(2,2) =  c; M(2,3) = d;
-  M(3,0) = 0; M(3,1) = 0; M(3,2) = -1; M(3,3) = 0;
-# undef M
-
-  jwzgles_glMultMatrixf (m);
-}
-
-
-void
-jwzgles_glOrtho (GLfloat left,   GLfloat right,
-                 GLfloat bottom, GLfloat top,
-                 GLfloat near,   GLfloat far)
-{
-  GLfloat m[16];
-  GLfloat a = 2 / (right - left);
-  GLfloat b = -(right + left) / (right - left);
-  GLfloat c = 2 / (top - bottom);
-  GLfloat d = -(top + bottom) / (top - bottom);
-  GLfloat e = -2 / (far - near);
-  GLfloat f = -(far + near) / (far - near);
-
-# define M(X,Y)  m[Y * 4 + X]
-  M(0,0) = a; M(0,1) = 0; M(0,2) = 0; M(0,3) = b;
-  M(1,0) = 0; M(1,1) = c; M(1,2) = 0; M(1,3) = d;
-  M(2,0) = 0; M(2,1) = 0; M(2,2) = e; M(2,3) = f;
-  M(3,0) = 0; M(3,1) = 0; M(3,2) = 0; M(3,3) = 1;
-# undef M
-
-  jwzgles_glMultMatrixf (m);
-}
-
-
-void
-jwzgles_gluPerspective (GLdouble fovy, GLdouble aspect, 
-                        GLdouble near, GLdouble far)
-{
-  GLfloat m[16];
-  double si, co, dz;
-  double rad = fovy / 2 * M_PI / 180;
-  double a, b, c, d;
-
-  dz = far - near;
-  si = sin(rad);
-  if (dz == 0 || si == 0 || aspect == 0)
-    return;
-  co = cos(rad) / si;
-
-  a = co / aspect;
-  b = co;
-  c = -(far + near) / dz;
-  d = -2 * near * far / dz;
-
-# define M(X,Y)  m[Y * 4 + X]
-  M(0,0) = a; M(0,1) = 0; M(0,2) = 0;  M(0,3) = 0;
-  M(1,0) = 0; M(1,1) = b; M(1,2) = 0;  M(1,3) = 0;
-  M(2,0) = 0; M(2,1) = 0; M(2,2) = c;  M(2,3) = d;
-  M(3,0) = 0; M(3,1) = 0; M(3,2) = -1; M(3,3) = 0;
-# undef M
-
-  jwzgles_glMultMatrixf (m);
-}
-
-
-void
-jwzgles_gluLookAt (GLfloat eyex, GLfloat eyey, GLfloat eyez,
-                   GLfloat centerx, GLfloat centery, GLfloat centerz,
-                   GLfloat upx, GLfloat upy, GLfloat upz)
-{
-  GLfloat m[16];
-  GLfloat x[3], y[3], z[3];
-  GLfloat mag;
-    
-  /* Make rotation matrix */
-    
-  /* Z vector */
-  z[0] = eyex - centerx;
-  z[1] = eyey - centery;
-  z[2] = eyez - centerz;
-  mag = sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
-  if (mag) {          /* mpichler, 19950515 */
-    z[0] /= mag;
-    z[1] /= mag;
-    z[2] /= mag;
-  }
-    
-  /* Y vector */
-  y[0] = upx;
-  y[1] = upy;
-  y[2] = upz;
-    
-  /* X vector = Y cross Z */
-  x[0] = y[1] * z[2] - y[2] * z[1];
-  x[1] = -y[0] * z[2] + y[2] * z[0];
-  x[2] = y[0] * z[1] - y[1] * z[0];
-    
-  /* Recompute Y = Z cross X */
-  y[0] = z[1] * x[2] - z[2] * x[1];
-  y[1] = -z[0] * x[2] + z[2] * x[0];
-  y[2] = z[0] * x[1] - z[1] * x[0];
-    
-  /* mpichler, 19950515 */
-  /* cross product gives area of parallelogram, which is < 1.0 for
-   * non-perpendicular unit-length vectors; so normalize x, y here
-   */
-    
-  mag = sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
-  if (mag) {
-    x[0] /= mag;
-    x[1] /= mag;
-    x[2] /= mag;
-  }
-    
-  mag = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
-  if (mag) {
-    y[0] /= mag;
-    y[1] /= mag;
-    y[2] /= mag;
-  }
-    
-#define M(row,col)  m[col*4+row]
-  M(0, 0) = x[0]; M(0, 1) = x[1]; M(0, 2) = x[2]; M(0, 3) = 0.0;
-  M(1, 0) = y[0]; M(1, 1) = y[1]; M(1, 2) = y[2]; M(1, 3) = 0.0;
-  M(2, 0) = z[0]; M(2, 1) = z[1]; M(2, 2) = z[2]; M(2, 3) = 0.0;
-  M(3, 0) = 0.0;  M(3, 1) = 0.0;  M(3, 2) = 0.0;  M(3, 3) = 1.0;
-#undef M
-
-  jwzgles_glMultMatrixf(m);
-    
-  /* Translate Eye to Origin */
-  jwzgles_glTranslatef(-eyex, -eyey, -eyez);
-}
-
-
-static void __gluMultMatrixVecd (const GLdouble matrix[16],
-                                 const GLdouble in[4],
-                                 GLdouble out[4])
-{
-  int i;
-
-  for (i=0; i<4; i++) {
-    out[i] = 
-      in[0] * matrix[0*4+i] +
-      in[1] * matrix[1*4+i] +
-      in[2] * matrix[2*4+i] +
-      in[3] * matrix[3*4+i];
-  }
-}
-
-GLint
-jwzgles_gluProject (GLdouble objx, GLdouble objy, GLdouble objz, 
-                    const GLdouble modelMatrix[16], 
-                    const GLdouble projMatrix[16],
-                    const GLint viewport[4],
-                    GLdouble *winx, GLdouble *winy, GLdouble *winz)
-{
-  GLdouble in[4];
-  GLdouble out[4];
-
-  /* #### I suspect this is not working right.  I was seeing crazy values
-     in lament.c.  Maybe there's some float-vs-double confusion going on?
-   */
-
-  in[0]=objx;
-  in[1]=objy;
-  in[2]=objz;
-  in[3]=1.0;
-  __gluMultMatrixVecd(modelMatrix, in, out);
-  __gluMultMatrixVecd(projMatrix, out, in);
-  if (in[3] == 0.0) return(GL_FALSE);
-  in[0] /= in[3];
-  in[1] /= in[3];
-  in[2] /= in[3];
-  /* Map x, y and z to range 0-1 */
-  in[0] = in[0] * 0.5 + 0.5;
-  in[1] = in[1] * 0.5 + 0.5;
-  in[2] = in[2] * 0.5 + 0.5;
-
-  /* Map x,y to viewport */
-  in[0] = in[0] * viewport[2] + viewport[0];
-  in[1] = in[1] * viewport[3] + viewport[1];
-
-  *winx=in[0];
-  *winy=in[1];
-  *winz=in[2];
-  return(GL_TRUE);
-}
-
-
-void jwzgles_glViewport (GLuint x, GLuint y, GLuint w, GLuint h)
-{
-# if TARGET_IPHONE_SIMULATOR
-/*  fprintf (stderr, "glViewport %dx%d\n", w, h); */
-# endif
-  glViewport (x, y, w, h);  /* the real one */
-}
-
-
-/* The following functions are present in both OpenGL 1.1 and in OpenGLES 1,
-   but are allowed within glNewList/glEndList, so we must wrap them to allow
-   them to either be recorded in lists, or run directly.
-
-   All this CPP obscenity is me screaming in rage at all the ways that C is
-   not Lisp, as all I want to do here is DEFADVICE.
- */
-
-#define PROTO_V   PROTO_VOID
-#define TYPE_V    GLuint
-#define ARGS_V    void
-#define VARS_V    /* */
-#define LOGS_V    "\n"
-#define FILL_V    /* */
-
-#define TYPE_I    GLuint
-#define TYPE_II   TYPE_I
-#define TYPE_III  TYPE_I
-#define TYPE_IIII TYPE_I
-#define ARGS_I    TYPE_I a
-#define ARGS_II   TYPE_I a, TYPE_I b
-#define ARGS_III  TYPE_I a, TYPE_I b, TYPE_I c
-#define ARGS_IIII TYPE_I a, TYPE_I b, TYPE_I c, TYPE_I d
-#define LOGS_I    "%s\n", mode_desc(a)
-#define LOGS_II   "%s %d\n", mode_desc(a), b
-#define LOGS_III  "%s %s %s\n", mode_desc(a), mode_desc(b), mode_desc(c)
-#define LOGS_IIII "%d %d %d %d\n", a, b, c, d
-#define VARS_I    a
-#define VARS_II   a, b
-#define VARS_III  a, b, c
-#define VARS_IIII a, b, c, d
-#define FILL_I    vv[0].i = a;
-#define FILL_II   vv[0].i = a; vv[1].i = b;
-#define FILL_III  vv[0].i = a; vv[1].i = b; vv[2].i = c;
-#define FILL_IIII vv[0].i = a; vv[1].i = b; vv[2].i = c; vv[3].i = d;
-
-#define TYPE_F    GLfloat
-#define TYPE_FF   TYPE_F
-#define TYPE_FFF  TYPE_F
-#define TYPE_FFFF TYPE_F
-#define ARGS_F    TYPE_F a
-#define ARGS_FF   TYPE_F a, TYPE_F b
-#define ARGS_FFF  TYPE_F a, TYPE_F b, TYPE_F c
-#define ARGS_FFFF TYPE_F a, TYPE_F b, TYPE_F c, TYPE_F d
-#define LOGS_F    "%7.3f\n", a
-#define LOGS_FF   "%7.3f %7.3f\n", a, b
-#define LOGS_FFF  "%7.3f %7.3f %7.3f\n", a, b, c
-#define LOGS_FFFF "%7.3f %7.3f %7.3f %7.3f\n", a, b, c, d
-#define VARS_F    VARS_I
-#define VARS_FF   VARS_II
-#define VARS_FFF  VARS_III
-#define VARS_FFFF VARS_IIII
-#define FILL_F    vv[0].f = a;
-#define FILL_FF   vv[0].f = a; vv[1].f = b;
-#define FILL_FFF  vv[0].f = a; vv[1].f = b; vv[2].f = c;
-#define FILL_FFFF vv[0].f = a; vv[1].f = b; vv[2].f = c; vv[3].f = d;
-
-#define ARGS_IF   TYPE_I a, TYPE_F b
-#define VARS_IF   VARS_II
-#define LOGS_IF   "%s %7.3f\n", mode_desc(a), b
-#define FILL_IF   vv[0].i = a; vv[1].f = b;
-
-#define ARGS_IIF  TYPE_I a, TYPE_I b, TYPE_F c
-#define VARS_IIF  VARS_III
-#define LOGS_IIF  "%s %s %7.3f\n", mode_desc(a), mode_desc(b), c
-#define FILL_IIF  vv[0].i = a; vv[1].i = b; vv[2].f = c;
-
-#define TYPE_IV   GLint
-#define ARGS_IIV  TYPE_I a, const TYPE_IV *b
-#define VARS_IIV  VARS_II
-#define LOGS_IIV  "%s %d %d %d %d\n", mode_desc(a), b[0], b[1], b[2], b[3]
-#define FILL_IIV  vv[0].i = a; \
-                 vv[1].i = b[0]; vv[2].i = b[1]; \
-                 vv[3].i = b[2]; vv[4].i = b[3];
-
-#define ARGS_IFV  TYPE_I a, const TYPE_F *b
-#define VARS_IFV  VARS_II
-#define LOGS_IFV  "%s %7.3f %7.3f %7.3f %7.3f\n", mode_desc(a), \
-                 b[0], b[1], b[2], b[3]
-#define FILL_IFV  vv[0].i = a; \
-                 vv[1].f = b[0]; vv[2].f = b[1]; \
-                 vv[3].f = b[2]; vv[4].f = b[3];
-
-#define ARGS_IIIV TYPE_I a, TYPE_I b, const TYPE_IV *c
-#define VARS_IIIV VARS_III
-#define LOGS_IIIV "%s %-8s %3d %3d %3d %3d\n", mode_desc(a), mode_desc(b), \
-                 c[0], c[1], c[2], c[3]
-#define FILL_IIIV vv[0].i = a; vv[1].i = b; \
-                 vv[2].i = c[0]; vv[3].i = c[1]; \
-                 vv[4].i = c[2]; vv[5].i = c[3];
-
-#define ARGS_IIFV TYPE_I a, TYPE_I b, const TYPE_F *c
-#define VARS_IIFV VARS_III
-#define LOGS_IIFV "%s %-8s %7.3f %7.3f %7.3f %7.3f\n", \
-                 mode_desc(a), mode_desc(b), \
-                 c[0], c[1], c[2], c[3]
-#define FILL_IIFV vv[0].i = a; vv[1].i = b; \
-                 vv[2].f = c[0]; vv[3].f = c[1]; \
-                 vv[4].f = c[2]; vv[5].f = c[3];
-
-#ifdef DEBUG
-# define WLOG(NAME,ARGS) \
-  fprintf (stderr, "jwzgles: direct %-12s ", NAME); \
-  fprintf (stderr, ARGS)
-#else
-# define WLOG(NAME,ARGS) /* */
-#endif
-
-#define WRAP(NAME,SIG) \
-void jwzgles_##NAME (ARGS_##SIG)                                       \
-{                                                                      \
-  Assert (!state->compiling_verts,                                     \
-          STRINGIFY(NAME) " not allowed inside glBegin");              \
-  if (state->compiling_list) {                                         \
-    void_int vv[10];                                                   \
-    FILL_##SIG                                                         \
-    list_push (STRINGIFY(NAME), (list_fn_cb) &jwzgles_##NAME,          \
-              PROTO_##SIG, vv);                                        \
-  } else {                                                             \
-    if (! state->replaying_list) {                                     \
-      WLOG (STRINGIFY(NAME), LOGS_##SIG);                              \
-    }                                                                  \
-    NAME (VARS_##SIG);                                                 \
-    CHECK(STRINGIFY(NAME));                                            \
-  }                                                                    \
-}
-
-WRAP (glActiveTexture, I)
-WRAP (glAlphaFunc,     IF)
-WRAP (glBlendFunc,     II)
-WRAP (glClear,         I)
-WRAP (glClearColor,    FFFF)
-WRAP (glClearStencil,  I)
-WRAP (glColorMask,     IIII)
-WRAP (glCullFace,      I)
-WRAP (glDepthFunc,     I)
-WRAP (glDepthMask,     I)
-WRAP (glFinish,                V)
-WRAP (glFlush,         V)
-WRAP (glFogf,          IF)
-WRAP (glFogfv,         IFV)
-WRAP (glFrontFace,     I)
-WRAP (glHint,          II)
-WRAP (glLightModelf,   IF)
-WRAP (glLightModelfv,  IFV)
-WRAP (glLightf,                IIF)
-WRAP (glLightfv,       IIFV)
-WRAP (glLineWidth,     F)
-WRAP (glLoadIdentity,  V)
-WRAP (glLogicOp,       I)
-WRAP (glMatrixMode,    I)
-WRAP (glPixelStorei,   II)
-WRAP (glPointSize,     F)
-WRAP (glPolygonOffset, FF)
-WRAP (glPopMatrix,     V)
-WRAP (glPushMatrix,    V)
-WRAP (glRotatef,       FFFF)
-WRAP (glScalef,                FFF)
-WRAP (glScissor,       IIII)
-WRAP (glShadeModel,    I)
-WRAP (glStencilFunc,   III)
-WRAP (glStencilMask,   I)
-WRAP (glStencilOp,     III)
-WRAP (glTexEnvf,       IIF)
-WRAP (glTexEnvi,       III)
-WRAP (glTranslatef,    FFF)
-#undef  TYPE_IV
-#define TYPE_IV GLuint
-WRAP (glDeleteTextures,        IIV)
-
-
-#endif /* HAVE_JWZGLES - whole file */
diff --git a/hacks/glx/jwzgles.h b/hacks/glx/jwzgles.h
deleted file mode 100644 (file)
index 43b02c6..0000000
+++ /dev/null
@@ -1,519 +0,0 @@
-/* xscreensaver, Copyright (c) 2012 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 compatibility shim to allow OpenGL 1.3 source code to work in an
-   OpenGLES environment, where almost every OpenGL 1.3 function has
-   been "deprecated".  See jwzgles.c for details.
- */
-
-#ifndef __JWZGLES_H__
-#define __JWZGLES_H__
-
-#ifndef HAVE_JWZGLES
-# error: do not include this without HAVE_JWZGLES
-#endif
-
-
-#include "jwzglesI.h"
-
-
-/* These are the OpenGL 1.3 functions that are not present in OpenGLES 1.
-   As you can see from the length of this list, OpenGL and OpenGLES have
-   almost nothing to do with each other.  To claim that GLES is a dialect
-   of OpenGL is absurd -- English and Latin have more in common!
- */
-
-#define glAccum                                jwzgles_glAccum
-#define glAntialiasing                 jwzgles_glAntialiasing
-#define glAreTexturesResident          jwzgles_glAreTexturesResident
-#define glArrayElement                 jwzgles_glArrayElement
-#define glBegin                                jwzgles_glBegin
-#define glBitmap                       jwzgles_glBitmap
-#define glBlendColor                   jwzgles_glBlendColor
-#define glBlendEquation                        jwzgles_glBlendEquation
-#define glCallList                     jwzgles_glCallList
-#define glCallLists                    jwzgles_glCallLists
-#define glClearAccum                   jwzgles_glClearAccum
-#define glClearDepth                   jwzgles_glClearDepth
-#define glClearIndex                   jwzgles_glClearIndex
-#define glClipPlane                    jwzgles_glClipPlane
-#define glColor3b                      jwzgles_glColor3b
-#define glColor3bv                     jwzgles_glColor3bv
-#define glColor3d                      jwzgles_glColor3f
-#define glColor3dv                     jwzgles_glColor3dv
-#define glColor3f                      jwzgles_glColor3f
-#define glColor3fv                     jwzgles_glColor3fv
-#define glColor3i                      jwzgles_glColor3i
-#define glColor3iv                     jwzgles_glColor3iv
-#define glColor3s                      jwzgles_glColor3s
-#define glColor3sv                     jwzgles_glColor3sv
-#define glColor3ub                     jwzgles_glColor3ub
-#define glColor3ubv                    jwzgles_glColor3ubv
-#define glColor3ui                     jwzgles_glColor3ui
-#define glColor3uiv                    jwzgles_glColor3uiv
-#define glColor3us                     jwzgles_glColor3us
-#define glColor3usv                    jwzgles_glColor3usv
-#define glColor4b                      jwzgles_glColor4b
-#define glColor4bv                     jwzgles_glColor4bv
-#define glColor4d                      jwzgles_glColor4d
-#define glColor4dv                     jwzgles_glColor4dv
-#define glColor4fv                     jwzgles_glColor4fv
-#define glColor4i                      jwzgles_glColor4i
-#define glColor4iv                     jwzgles_glColor4iv
-#define glColor4s                      jwzgles_glColor4s
-#define glColor4sv                     jwzgles_glColor4sv
-#define glColor4ub                     jwzgles_glColor4ub
-#define glColor4ubv                    jwzgles_glColor4ubv
-#define glColor4ui                     jwzgles_glColor4ui
-#define glColor4uiv                    jwzgles_glColor4uiv
-#define glColor4us                     jwzgles_glColor4us
-#define glColor4usv                    jwzgles_glColor4usv
-#define glColorMaterial                        jwzgles_glColorMaterial
-#define glColorSubTable                        jwzgles_glColorSubTable
-#define glColorTable                   jwzgles_glColorTable
-#define glColorTableParameter          jwzgles_glColorTableParameter
-#define glColorTableParameterfv                jwzgles_glColorTableParameterfv
-#define glColorub                      jwzgles_glColorub
-#define glColorui                      jwzgles_glColorui
-#define glColorus                      jwzgles_glColorus
-#define glCompressedTexImage           jwzgles_glCompressedTexImage
-#define glCompressedTexImage1D         jwzgles_glCompressedTexImage1D
-#define glCompressedTexImage3D         jwzgles_glCompressedTexImage3D
-#define glCompressedTexSubImage1D      jwzgles_glCompressedTexSubImage1D
-#define glCompressedTexSubImage3D      jwzgles_glCompressedTexSubImage3D
-#define glConvolutionFilter1D          jwzgles_glConvolutionFilter1D
-#define glConvolutionFilter2D          jwzgles_glConvolutionFilter2D
-#define glConvolutionParameter         jwzgles_glConvolutionParameter
-#define glConvolutionParameterfv       jwzgles_glConvolutionParameterfv
-#define glConvolutionParameteriv       jwzgles_glConvolutionParameteriv
-#define glCopyColorSubTable            jwzgles_glCopyColorSubTable
-#define glCopyColorTable               jwzgles_glCopyColorTable
-#define glCopyConvolutionFilter1D      jwzgles_glCopyConvolutionFilter1D
-#define glCopyConvolutionFilter2D      jwzgles_glCopyConvolutionFilter2D
-#define glCopyPixels                   jwzgles_glCopyPixels
-#define glCopyTexImage1D               jwzgles_glCopyTexImage1D
-#define glCopyTexImage3D               jwzgles_glCopyTexImage3D
-#define glCopyTexSubImage1D            jwzgles_glCopyTexSubImage1D
-#define glCopyTexSubImage3D            jwzgles_glCopyTexSubImage3D
-#define glDeleteLists                  jwzgles_glDeleteLists
-#define glDepthRange                   jwzgles_glDepthRange
-#define glDrawBuffer                   jwzgles_glDrawBuffer
-#define glDrawPixels                   jwzgles_glDrawPixels
-#define glDrawRangeElements            jwzgles_glDrawRangeElements
-#define glEdgeFlag                     jwzgles_glEdgeFlag
-#define glEdgeFlagPointer              jwzgles_glEdgeFlagPointer
-#define glEdgeFlagv                    jwzgles_glEdgeFlagv
-#define glEnd                          jwzgles_glEnd
-#define glEndList                      jwzgles_glEndList
-#define glEvalCoord1d                  jwzgles_glEvalCoord1d
-#define glEvalCoord1dv                 jwzgles_glEvalCoord1dv
-#define glEvalCoord1f                  jwzgles_glEvalCoord1f
-#define glEvalCoord1fv                 jwzgles_glEvalCoord1fv
-#define glEvalCoord2d                  jwzgles_glEvalCoord2d
-#define glEvalCoord2dv                 jwzgles_glEvalCoord2dv
-#define glEvalCoord2f                  jwzgles_glEvalCoord2f
-#define glEvalCoord2fv                 jwzgles_glEvalCoord2fv
-#define glEvalMesh1                    jwzgles_glEvalMesh1
-#define glEvalMesh2                    jwzgles_glEvalMesh2
-#define glEvalPoint1                   jwzgles_glEvalPoint1
-#define glEvalPoint2                   jwzgles_glEvalPoint2
-#define glFeedbackBuffer               jwzgles_glFeedbackBuffer
-#define glFogi                         jwzgles_glFogi
-#define glFogiv                                jwzgles_glFogiv
-#define glFrustum                      jwzgles_glFrustum
-#define glGenLists                     jwzgles_glGenLists
-#define glGet                          jwzgles_glGet
-#define glGetBooleanv                  jwzgles_glGetBooleanv
-#define glGetClipPlane                 jwzgles_glGetClipPlane
-#define glGetColorTable                        jwzgles_glGetColorTable
-#define glGetColorTableParameter       jwzgles_glGetColorTableParameter
-#define glGetCompressedTexImage                jwzgles_glGetCompressedTexImage
-#define glGetConvolutionFilter         jwzgles_glGetConvolutionFilter
-#define glGetConvolutionParameter      jwzgles_glGetConvolutionParameter
-#define glGetConvolutionParameteriv    jwzgles_glGetConvolutionParameteriv
-#define glGetDoublev                   jwzgles_glGetDoublev
-#define glGetFloatv                    jwzgles_glGetFloatv
-#define glGetHistogram                 jwzgles_glGetHistogram
-#define glGetHistogramParameter                jwzgles_glGetHistogramParameter
-#define glGetLightfv                   jwzgles_glGetLightfv
-#define glGetLightiv                   jwzgles_glGetLightiv
-#define glGetMapdv                     jwzgles_glGetMapdv
-#define glGetMapfv                     jwzgles_glGetMapfv
-#define glGetMapiv                     jwzgles_glGetMapiv
-#define glGetMaterialfv                        jwzgles_glGetMaterialfv
-#define glGetMaterialiv                        jwzgles_glGetMaterialiv
-#define glGetPixelMapfv                        jwzgles_glGetPixelMapfv
-#define glGetPixelMapuiv               jwzgles_glGetPixelMapuiv
-#define glGetPixelMapusv               jwzgles_glGetPixelMapusv
-#define glGetPointerv                  jwzgles_glGetPointerv
-#define glGetPolygonStipple            jwzgles_glGetPolygonStipple
-#define glGetSeparableFilter           jwzgles_glGetSeparableFilter
-#define glGetTexEnvfv                  jwzgles_glGetTexEnvfv
-#define glGetTexEnviv                  jwzgles_glGetTexEnviv
-#define glGetTexGendv                  jwzgles_glGetTexGendv
-#define glGetTexGenfv                  jwzgles_glGetTexGenfv
-#define glGetTexGeniv                  jwzgles_glGetTexGeniv
-#define glGetTexImage                  jwzgles_glGetTexImage
-#define glGetTexImage1D                        jwzgles_glGetTexImage1D
-#define glGetTexImage2D                        jwzgles_glGetTexImage2D
-#define glGetTexImage3D                        jwzgles_glGetTexImage3D
-#define glGetTexLevelParameterfv       jwzgles_glGetTexLevelParameterfv
-#define glGetTexLevelParameteriv       jwzgles_glGetTexLevelParameteriv
-#define glGetTexParameterfv            jwzgles_glGetTexParameterfv
-#define glGetTexParameteriv            jwzgles_glGetTexParameteriv
-#define glHistogram                    jwzgles_glHistogram
-#define glIndex                                jwzgles_glIndex
-#define glIndexMask                    jwzgles_glIndexMask
-#define glIndexPointer                 jwzgles_glIndexPointer
-#define glIndexd                       jwzgles_glIndexd
-#define glIndexdv                      jwzgles_glIndexdv
-#define glIndexf                       jwzgles_glIndexf
-#define glIndexfv                      jwzgles_glIndexfv
-/*#define glIndexi                     jwzgles_glIndexi*/
-#define glIndexiv                      jwzgles_glIndexiv
-#define glIndexs                       jwzgles_glIndexs
-#define glIndexsv                      jwzgles_glIndexsv
-#define glIndexub                      jwzgles_glIndexub
-#define glIndexubv                     jwzgles_glIndexubv
-#define glInitNames                    jwzgles_glInitNames
-#define glInterleavedArrays            jwzgles_glInterleavedArrays
-#define glIsEnabled                    jwzgles_glIsEnabled
-#define glIsList                       jwzgles_glIsList
-#define glIsTexture                    jwzgles_glIsTexture
-#define glLightModeli                  jwzgles_glLightModeli
-#define glLightModeliv                 jwzgles_glLightModeliv
-#define glLighti                       jwzgles_glLighti
-#define glLightiv                      jwzgles_glLightiv
-#define glLightf                       jwzgles_glLightf
-#define glLightfv                      jwzgles_glLightfv
-#define glLineStipple                  jwzgles_glLineStipple
-#define glListBase                     jwzgles_glListBase
-#define glLoadMatrix                   jwzgles_glLoadMatrix
-#define glLoadMatrixd                  jwzgles_glLoadMatrixd
-#define glLoadName                     jwzgles_glLoadName
-#define glLoadTransposeMatrix          jwzgles_glLoadTransposeMatrix
-#define glLoadTransposeMatrixd         jwzgles_glLoadTransposeMatrixd
-#define glLoadTransposeMatrixf         jwzgles_glLoadTransposeMatrixf
-#define glMap1d                                jwzgles_glMap1d
-#define glMap1f                                jwzgles_glMap1f
-#define glMap2d                                jwzgles_glMap2d
-#define glMap2f                                jwzgles_glMap2f
-#define glMapGrid1d                    jwzgles_glMapGrid1d
-#define glMapGrid1f                    jwzgles_glMapGrid1f
-#define glMapGrid2d                    jwzgles_glMapGrid2d
-#define glMapGrid2f                    jwzgles_glMapGrid2f
-#define glMateriali                    jwzgles_glMateriali
-#define glMaterialiv                   jwzgles_glMaterialiv
-#define glMultMatrixd                  jwzgles_glMultMatrixd
-#define glMultTransposeMatrix          jwzgles_glMultTransposeMatrix
-#define glMultTransposeMatrixd         jwzgles_glMultTransposeMatrixd
-#define glMultTransposeMatrixf         jwzgles_glMultTransposeMatrixf
-#define glMultiTexCoord                        jwzgles_glMultiTexCoord
-#define glNewList                      jwzgles_glNewList
-#define glNormal3b                     jwzgles_glNormal3b
-#define glNormal3bv                    jwzgles_glNormal3bv
-#define glNormal3d                     jwzgles_glNormal3f
-#define glNormal3dv                    jwzgles_glNormal3dv
-#define glNormal3fv                    jwzgles_glNormal3fv
-#define glNormal3i                     jwzgles_glNormal3i
-#define glNormal3iv                    jwzgles_glNormal3iv
-#define glNormal3s                     jwzgles_glNormal3s
-#define glNormal3sv                    jwzgles_glNormal3sv
-#define glOrtho                                jwzgles_glOrtho
-#define glPassThrough                  jwzgles_glPassThrough
-#define glPixelMapfv                   jwzgles_glPixelMapfv
-#define glPixelMapuiv                  jwzgles_glPixelMapuiv
-#define glPixelMapusv                  jwzgles_glPixelMapusv
-#define glPixelStoref                  jwzgles_glPixelStoref
-#define glPixelTransferf               jwzgles_glPixelTransferf
-#define glPixelTransferi               jwzgles_glPixelTransferi
-#define glPixelZoom                    jwzgles_glPixelZoom
-#define glPolygonMode                  jwzgles_glPolygonMode
-#define glPolygonStipple               jwzgles_glPolygonStipple
-#define glPopAttrib                    jwzgles_glPopAttrib
-#define glPopClientAttrib              jwzgles_glPopClientAttrib
-#define glPopName                      jwzgles_glPopName
-#define glPrioritizeTextures           jwzgles_glPrioritizeTextures
-#define glPushAttrib                   jwzgles_glPushAttrib
-#define glPushClientAttrib             jwzgles_glPushClientAttrib
-#define glPushName                     jwzgles_glPushName
-#define glRasterPos2d                  jwzgles_glRasterPos2d
-#define glRasterPos2dv                 jwzgles_glRasterPos2dv
-#define glRasterPos2f                  jwzgles_glRasterPos2f
-#define glRasterPos2fv                 jwzgles_glRasterPos2fv
-#define glRasterPos2i                  jwzgles_glRasterPos2i
-#define glRasterPos2iv                 jwzgles_glRasterPos2iv
-#define glRasterPos2s                  jwzgles_glRasterPos2s
-#define glRasterPos2sv                 jwzgles_glRasterPos2sv
-#define glRasterPos3d                  jwzgles_glRasterPos3d
-#define glRasterPos3dv                 jwzgles_glRasterPos3dv
-#define glRasterPos3f                  jwzgles_glRasterPos3f
-#define glRasterPos3fv                 jwzgles_glRasterPos3fv
-#define glRasterPos3i                  jwzgles_glRasterPos3i
-#define glRasterPos3iv                 jwzgles_glRasterPos3iv
-#define glRasterPos3s                  jwzgles_glRasterPos3s
-#define glRasterPos3sv                 jwzgles_glRasterPos3sv
-#define glRasterPos4d                  jwzgles_glRasterPos4d
-#define glRasterPos4dv                 jwzgles_glRasterPos4dv
-#define glRasterPos4f                  jwzgles_glRasterPos4f
-#define glRasterPos4fv                 jwzgles_glRasterPos4fv
-#define glRasterPos4i                  jwzgles_glRasterPos4i
-#define glRasterPos4iv                 jwzgles_glRasterPos4iv
-#define glRasterPos4s                  jwzgles_glRasterPos4s
-#define glRasterPos4sv                 jwzgles_glRasterPos4sv
-#define glReadBuffer                   jwzgles_glReadBuffer
-#define glRectd                                jwzgles_glRectf
-#define glRectdv                       jwzgles_glRectdv
-#define glRectf                                jwzgles_glRectf
-#define glRectfv                       jwzgles_glRectfv
-#define glRecti                                jwzgles_glRecti
-#define glRectiv                       jwzgles_glRectiv
-#define glRects                                jwzgles_glRects
-#define glRectsv                       jwzgles_glRectsv
-#define glRenderMode                   jwzgles_glRenderMode
-#define glResetHistogram               jwzgles_glResetHistogram
-#define glResetMinmax                  jwzgles_glResetMinmax
-#define glRotated                      jwzgles_glRotated
-#define glScaled                       jwzgles_glScalef
-#define glSelectBuffer                 jwzgles_glSelectBuffer
-#define glSeparableFilter2D            jwzgles_glSeparableFilter2D
-#define glTexCoord1d                   jwzgles_glTexCoord1d
-#define glTexCoord1dv                  jwzgles_glTexCoord1dv
-#define glTexCoord1f                   jwzgles_glTexCoord1f
-#define glTexCoord1fv                  jwzgles_glTexCoord1fv
-#define glTexCoord1i                   jwzgles_glTexCoord1i
-#define glTexCoord1iv                  jwzgles_glTexCoord1iv
-#define glTexCoord1s                   jwzgles_glTexCoord1s
-#define glTexCoord1sv                  jwzgles_glTexCoord1sv
-#define glTexCoord2d                   jwzgles_glTexCoord2f
-#define glTexCoord2dv                  jwzgles_glTexCoord2dv
-#define glTexCoord2f                   jwzgles_glTexCoord2f
-#define glTexCoord2fv                  jwzgles_glTexCoord2fv
-#define glTexCoord2i                   jwzgles_glTexCoord2i
-#define glTexCoord2iv                  jwzgles_glTexCoord2iv
-#define glTexCoord2s                   jwzgles_glTexCoord2s
-#define glTexCoord2sv                  jwzgles_glTexCoord2sv
-#define glTexCoord3d                   jwzgles_glTexCoord3d
-#define glTexCoord3dv                  jwzgles_glTexCoord3dv
-#define glTexCoord3f                   jwzgles_glTexCoord3f
-#define glTexCoord3fv                  jwzgles_glTexCoord3fv
-#define glTexCoord3i                   jwzgles_glTexCoord3i
-#define glTexCoord3iv                  jwzgles_glTexCoord3iv
-#define glTexCoord3s                   jwzgles_glTexCoord3s
-#define glTexCoord3sv                  jwzgles_glTexCoord3sv
-#define glTexCoord4d                   jwzgles_glTexCoord4d
-#define glTexCoord4dv                  jwzgles_glTexCoord4dv
-#define glTexCoord4f                   jwzgles_glTexCoord4f
-#define glTexCoord4fv                  jwzgles_glTexCoord4fv
-#define glTexCoord4i                   jwzgles_glTexCoord4i
-#define glTexCoord4iv                  jwzgles_glTexCoord4iv
-#define glTexCoord4s                   jwzgles_glTexCoord4s
-#define glTexCoord4sv                  jwzgles_glTexCoord4sv
-#define glTexEnvi                      jwzgles_glTexEnvi
-#define glTexEnviv                     jwzgles_glTexEnviv
-#define glTexGend                      jwzgles_glTexGend
-#define glTexGendv                     jwzgles_glTexGendv
-#define glTexGenf                      jwzgles_glTexGenf
-#define glTexGenfv                     jwzgles_glTexGenfv
-#define glTexGeni                      jwzgles_glTexGeni
-#define glTexGeniv                     jwzgles_glTexGeniv
-#define glTexImage1D                   jwzgles_glTexImage1D
-#define glTexImage3D                   jwzgles_glTexImage3D
-#define glTexParameterfv               jwzgles_glTexParameterfv
-#define glTexParameteri                        jwzgles_glTexParameteri
-#define glTexParameteriv               jwzgles_glTexParameteriv
-#define glTexSubImage1D                        jwzgles_glTexSubImage1D
-#define glTexSubImage3D                        jwzgles_glTexSubImage3D
-#define glTranslated                   jwzgles_glTranslatef
-#define glVertex2d                     jwzgles_glVertex2d
-#define glVertex2dv                    jwzgles_glVertex2dv
-#define glVertex2f                     jwzgles_glVertex2f
-#define glVertex2fv                    jwzgles_glVertex2fv
-#define glVertex2i                     jwzgles_glVertex2i
-#define glVertex2iv                    jwzgles_glVertex2iv
-#define glVertex2s                     jwzgles_glVertex2s
-#define glVertex2sv                    jwzgles_glVertex2sv
-#define glVertex3d                     jwzgles_glVertex3f
-#define glVertex3dv                    jwzgles_glVertex3dv
-#define glVertex3f                     jwzgles_glVertex3f
-#define glVertex3fv                    jwzgles_glVertex3fv
-#define glVertex3i                     jwzgles_glVertex3i
-#define glVertex3iv                    jwzgles_glVertex3iv
-#define glVertex3s                     jwzgles_glVertex3s
-#define glVertex3sv                    jwzgles_glVertex3sv
-#define glVertex4d                     jwzgles_glVertex4d
-#define glVertex4dv                    jwzgles_glVertex4dv
-#define glVertex4f                     jwzgles_glVertex4f
-#define glVertex4fv                    jwzgles_glVertex4fv
-#define glVertex4i                     jwzgles_glVertex4i
-#define glVertex4iv                    jwzgles_glVertex4iv
-#define glVertex4s                     jwzgles_glVertex4s
-#define glVertex4sv                    jwzgles_glVertex4sv
-
-#define gluOrtho2D(L,R,B,T)            glOrtho(L,R,B,T,-1,1)
-#define gluPerspective                 jwzgles_gluPerspective
-
-#define glXChooseVisual                        jwzgles_glXChooseVisual
-#define glXCopyContext                 jwzgles_glXCopyContext
-/*#define glXCreateContext             jwzgles_glXCreateContext*/
-#define glXCreateGLXPixmap             jwzgles_glXCreateGLXPixmap
-#define glXDestroyContext              jwzgles_glXDestroyContext
-#define glXDestroyGLXPixmap            jwzgles_glXDestroyGLXPixmap
-#define glXFreeContextEXT              jwzgles_glXFreeContextEXT
-#define glXGetClientString             jwzgles_glXGetClientString
-#define glXGetConfig                   jwzgles_glXGetConfig
-#define glXGetContextIDEXT             jwzgles_glXGetContextIDEXT
-#define glXGetCurrentContext           jwzgles_glXGetCurrentContext
-#define glXGetCurrentDisplay           jwzgles_glXGetCurrentDisplay
-#define glXGetCurrentDrawable          jwzgles_glXGetCurrentDrawable
-#define glXImportContextEXT            jwzgles_glXImportContextEXT
-#define glXIntro                       jwzgles_glXIntro
-#define glXIsDirect                    jwzgles_glXIsDirect
-/*#define glXMakeCurrent               jwzgles_glXMakeCurrent*/
-#define glXQueryContextInfoEXT         jwzgles_glXQueryContextInfoEXT
-#define glXQueryExtension              jwzgles_glXQueryExtension
-#define glXQueryExtensionsString       jwzgles_glXQueryExtensionsString
-#define glXQueryServerString           jwzgles_glXQueryServerString
-#define glXQueryVersion                        jwzgles_glXQueryVersion
-/*#define glXSwapBuffers               jwzgles_glXSwapBuffers*/
-#define glXUseXFont                    jwzgles_glXUseXFont
-#define glXWaitGL                      jwzgles_glXWaitGL
-#define glXWaitX                       jwzgles_glXWaitX
-
-#define gluBeginCurve                  jwzgles_gluBeginCurve
-#define gluBeginPolygon                        jwzgles_gluBeginPolygon
-#define gluBeginSurface                        jwzgles_gluBeginSurface
-#define gluBeginTrim                   jwzgles_gluBeginTrim
-#define gluBuild1DMipmaps              jwzgles_gluBuild1DMipmaps
-#define gluBuild2DMipmaps              jwzgles_gluBuild2DMipmaps
-#define gluCylinder                    jwzgles_gluCylinder
-#define gluDeleteNurbsRenderer         jwzgles_gluDeleteNurbsRenderer
-#define gluDeleteQuadric               jwzgles_gluDeleteQuadric
-#define gluDeleteTess                  jwzgles_gluDeleteTess
-#define gluDisk                                jwzgles_gluDisk
-#define gluEndCurve                    jwzgles_gluEndCurve
-#define gluEndPolygon                  jwzgles_gluEndPolygon
-#define gluEndSurface                  jwzgles_gluEndSurface
-#define gluEndTrim                     jwzgles_gluEndTrim
-#define gluErrorString                 jwzgles_gluErrorString
-#define gluGetNurbsProperty            jwzgles_gluGetNurbsProperty
-#define gluGetString                   jwzgles_gluGetString
-#define gluGetTessProperty             jwzgles_gluGetTessProperty
-#define gluLoadSamplingMatrices                jwzgles_gluLoadSamplingMatrices
-#define gluLookAt                      jwzgles_gluLookAt
-#define gluNewNurbsRenderer            jwzgles_gluNewNurbsRenderer
-#define gluNewQuadric                  jwzgles_gluNewQuadric
-#define gluNewTess                     jwzgles_gluNewTess
-#define gluNextContour                 jwzgles_gluNextContour
-#define gluNurbsCallback               jwzgles_gluNurbsCallback
-#define gluNurbsCurve                  jwzgles_gluNurbsCurve
-#define gluNurbsProperty               jwzgles_gluNurbsProperty
-#define gluNurbsSurface                        jwzgles_gluNurbsSurface
-#define gluPartialDisk                 jwzgles_gluPartialDisk
-#define gluPickMatrix                  jwzgles_gluPickMatrix
-#define gluProject                     jwzgles_gluProject
-#define gluPwlCurve                    jwzgles_gluPwlCurve
-#define gluQuadricCallback             jwzgles_gluQuadricCallback
-#define gluQuadricDrawStyle            jwzgles_gluQuadricDrawStyle
-#define gluQuadricNormals              jwzgles_gluQuadricNormals
-#define gluQuadricOrientation          jwzgles_gluQuadricOrientation
-#define gluQuadricTexture              jwzgles_gluQuadricTexture
-#define gluScaleImage                  jwzgles_gluScaleImage
-#define gluSphere                      jwzgles_gluSphere
-#define gluTessBeginContour            jwzgles_gluTessBeginContour
-#define gluTessBeginPolygon            jwzgles_gluTessBeginPolygon
-#define gluTessCallback                        jwzgles_gluTessCallback
-#define gluTessEndPolygon              jwzgles_gluTessEndPolygon
-#define gluTessEndContour              jwzgles_gluTessEndContour
-#define gluTessNormal                  jwzgles_gluTessNormal
-#define gluTessProperty                        jwzgles_gluTessProperty
-#define gluTessVertex                  jwzgles_gluTessVertex
-#define gluUnProject                   jwzgles_gluUnProject
-
-
-/* These functions are present in both OpenGL 1.1 and in OpenGLES 1,
-   but are allowed within glNewList/glEndList, so we must wrap them
-   to allow them to be recorded.
- */
-#define glActiveTexture                        jwzgles_glActiveTexture
-#define glAlphaFunc                    jwzgles_glAlphaFunc
-#define glBindTexture                  jwzgles_glBindTexture
-#define glBlendFunc                    jwzgles_glBlendFunc
-#define glClear                                jwzgles_glClear
-#define glClearColor                   jwzgles_glClearColor
-#define glClearStencil                 jwzgles_glClearStencil
-#define glColor4f                      jwzgles_glColor4f
-#define glColorMask                    jwzgles_glColorMask
-#define glColorPointer                 jwzgles_glColorPointer
-#define glCompressedTexImage2D         jwzgles_glCompressedTexImage2D
-#define glCompressedTexSubImage2D      jwzgles_glCompressedTexSubImage2D
-#define glCopyTexImage2D               jwzgles_glCopyTexImage2D
-#define glCopyTexSubImage2D            jwzgles_glCopyTexSubImage2D
-#define glCullFace                     jwzgles_glCullFace
-#define glDeleteTextures               jwzgles_glDeleteTextures
-#define glDepthFunc                    jwzgles_glDepthFunc
-#define glDepthMask                    jwzgles_glDepthMask
-#define glDisable                      jwzgles_glDisable
-#define glDrawArrays                   jwzgles_glDrawArrays
-#define glDrawElements                 jwzgles_glDrawElements
-#define glEnable                       jwzgles_glEnable
-#define glFinish                       jwzgles_glFinish
-#define glFlush                                jwzgles_glFlush
-#define glFogf                         jwzgles_glFogf
-#define glFogfv                                jwzgles_glFogfv
-#define glFrontFace                    jwzgles_glFrontFace
-#define glGenTextures                  jwzgles_glGenTextures
-#define glGetIntegerv                  jwzgles_glGetIntegerv
-#define glHint                         jwzgles_glHint
-#define glLightModelf                  jwzgles_glLightModelf
-#define glLightModelfv                 jwzgles_glLightModelfv
-#define glLightf                       jwzgles_glLightf
-#define glLightfv                      jwzgles_glLightfv
-#define glLineWidth                    jwzgles_glLineWidth
-#define glLoadIdentity                 jwzgles_glLoadIdentity
-#define glLoadMatrixf                  jwzgles_glLoadMatrixf
-#define glLogicOp                      jwzgles_glLogicOp
-#define glMaterialf                    jwzgles_glMaterialf
-#define glMateriali                    jwzgles_glMateriali
-#define glMaterialfv                   jwzgles_glMaterialfv
-#define glMaterialiv                   jwzgles_glMaterialiv
-#define glMatrixMode                   jwzgles_glMatrixMode
-#define glMultMatrixf                  jwzgles_glMultMatrixf
-#define glNormal3f                     jwzgles_glNormal3f
-#define glNormalPointer                        jwzgles_glNormalPointer
-#define glPixelStorei                  jwzgles_glPixelStorei
-#define glPointSize                    jwzgles_glPointSize
-#define glPolygonOffset                        jwzgles_glPolygonOffset
-#define glPopMatrix                    jwzgles_glPopMatrix
-#define glPushMatrix                   jwzgles_glPushMatrix
-#define glReadPixels                   jwzgles_glReadPixels
-#define glRotatef                      jwzgles_glRotatef
-#define glScalef                       jwzgles_glScalef
-#define glSampleCoverage               jwzgles_glSampleCoverage
-#define glScissor                      jwzgles_glScissor
-#define glShadeModel                   jwzgles_glShadeModel
-#define glStencilFunc                  jwzgles_glStencilFunc
-#define glStencilMask                  jwzgles_glStencilMask
-#define glStencilOp                    jwzgles_glStencilOp
-#define glTexCoordPointer              jwzgles_glTexCoordPointer
-#define glTexEnvf                      jwzgles_glTexEnvf
-#define glTexEnvfv                     jwzgles_glTexEnvfv
-#define glTexImage2D                   jwzgles_glTexImage2D
-#define glTexParameterf                        jwzgles_glTexParameterf
-#define glTexSubImage2D                        jwzgles_glTexSubImage2D
-#define glTranslatef                   jwzgles_glTranslatef
-#define glVertexPointer                        jwzgles_glVertexPointer
-#define glViewport                     jwzgles_glViewport
-#define glEnableClientState            jwzgles_glEnableClientState
-#define glDisableClientState           jwzgles_glDisableClientState
-#define glClipPlane                    jwzgles_glClipPlane
-
-#endif /* __JWZGLES_H__ */
diff --git a/hacks/glx/jwzglesI.h b/hacks/glx/jwzglesI.h
deleted file mode 100644 (file)
index 89bd881..0000000
+++ /dev/null
@@ -1,342 +0,0 @@
-/* xscreensaver, Copyright (c) 2012-2015 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 compatibility shim to allow OpenGL 1.3 source code to work in an
-   OpenGLES environment, where almost every OpenGL 1.3 function has
-   been "deprecated".  See jwzgles.c for details.
- */
-
-#ifndef __JWZGLES_I_H__
-#define __JWZGLES_I_H__
-
-#ifdef GL_VERSION_ES_CM_1_0  /* compiling against OpenGLES 1.x */
-
-/* These OpenGL 1.3 constants are not present in OpenGLES 1.
-   Fortunately, it looks like they didn't re-use any of the numbers,
-   so we can just keep using the OpenGL 1.3 values.  I'm actually
-   kind of shocked that the GLES folks passed up that opportunity
-   for further clusterfuckery.
- */
-# define GLdouble double
-
-# define GL_ACCUM_BUFFER_BIT                   0x00000200
-# define GL_ALL_ATTRIB_BITS                    0x000FFFFF
-# define GL_AUTO_NORMAL                                0x0D80
-# define GL_BLEND_SRC_ALPHA                    0x80CB
-# define GL_C3F_V3F                            0x2A24
-# define GL_C4F_N3F_V3F                                0x2A26
-# define GL_C4UB_V2F                           0x2A22
-# define GL_C4UB_V3F                           0x2A23
-# define GL_CLAMP                              0x2900
-# define GL_COLOR_BUFFER_BIT                   0x00004000
-# define GL_COLOR_MATERIAL_FACE                        0x0B55
-# define GL_COLOR_MATERIAL_PARAMETER           0x0B56
-# define GL_COMPILE                            0x1300
-# define GL_CURRENT_BIT                                0x00000001
-# define GL_DEPTH_BUFFER_BIT                   0x00000100
-# define GL_DOUBLEBUFFER                       0x0C32
-# define GL_ENABLE_BIT                         0x00002000
-# define GL_EVAL_BIT                           0x00010000
-# define GL_EYE_LINEAR                         0x2400
-# define GL_EYE_PLANE                          0x2502
-# define GL_FEEDBACK                           0x1C01
-# define GL_FILL                               0x1B02
-# define GL_FOG_BIT                            0x00000080
-# define GL_HINT_BIT                           0x00008000
-# define GL_INTENSITY                          0x8049
-# define GL_LIGHTING_BIT                       0x00000040
-# define GL_LIGHT_MODEL_COLOR_CONTROL          0x81F8
-# define GL_LIGHT_MODEL_LOCAL_VIEWER           0x0B51
-# define GL_LINE                               0x1B01
-# define GL_LINE_BIT                           0x00000004
-# define GL_LIST_BIT                           0x00020000
-# define GL_N3F_V3F                            0x2A25
-# define GL_OBJECT_LINEAR                      0x2401
-# define GL_OBJECT_PLANE                       0x2501
-# define GL_PIXEL_MODE_BIT                     0x00000020
-# define GL_POINT_BIT                          0x00000002
-# define GL_POLYGON                            0x0009
-# define GL_POLYGON_BIT                                0x00000008
-# define GL_POLYGON_MODE                       0x0B40
-# define GL_POLYGON_SMOOTH                     0x0B41
-# define GL_POLYGON_STIPPLE                    0x0B42
-# define GL_POLYGON_STIPPLE_BIT                        0x00000010
-# define GL_Q                                  0x2003
-# define GL_QUADS                              0x0007
-# define GL_QUAD_STRIP                         0x0008
-# define GL_R                                  0x2002
-# define GL_RENDER                             0x1C00
-# define GL_RGBA_MODE                          0x0C31
-# define GL_S                                  0x2000
-# define GL_SCISSOR_BIT                                0x00080000
-# define GL_SELECT                             0x1C02
-# define GL_SEPARATE_SPECULAR_COLOR            0x81FA
-# define GL_SINGLE_COLOR                       0x81F9
-# define GL_SPHERE_MAP                         0x2402
-# define GL_STENCIL_BUFFER_BIT                 0x00000400
-# define GL_T                                  0x2001
-# define GL_T2F_C3F_V3F                                0x2A2A
-# define GL_T2F_C4F_N3F_V3F                    0x2A2C
-# define GL_T2F_C4UB_V3F                       0x2A29
-# define GL_T2F_N3F_V3F                                0x2A2B
-# define GL_T2F_V3F                            0x2A27
-# define GL_T4F_C4F_N3F_V4F                    0x2A2D
-# define GL_T4F_V4F                            0x2A28
-# define GL_TEXTURE_1D                         0x0DE0
-# define GL_TEXTURE_ALPHA_SIZE                 0x805F
-# define GL_TEXTURE_BIT                                0x00040000
-# define GL_TEXTURE_BLUE_SIZE                  0x805E
-# define GL_TEXTURE_BORDER                     0x1005
-# define GL_TEXTURE_BORDER_COLOR               0x1004
-# define GL_TEXTURE_COMPONENTS                 0x1003
-# define GL_TEXTURE_GEN_MODE                   0x2500
-# define GL_TEXTURE_GEN_Q                      0x0C63
-# define GL_TEXTURE_GEN_R                      0x0C62
-# define GL_TEXTURE_GEN_S                      0x0C60
-# define GL_TEXTURE_GEN_T                      0x0C61
-# define GL_TEXTURE_GREEN_SIZE                 0x805D
-# define GL_TEXTURE_HEIGHT                     0x1001
-# define GL_TEXTURE_INTENSITY_SIZE             0x8061
-# define GL_TEXTURE_LUMINANCE_SIZE             0x8060
-# define GL_TEXTURE_RED_SIZE                   0x805C
-# define GL_TEXTURE_WIDTH                      0x1000
-# define GL_TRANSFORM_BIT                      0x00001000
-# define GL_UNPACK_ROW_LENGTH                  0x0CF2
-# define GL_UNSIGNED_INT_8_8_8_8_REV           0x8367
-# define GL_V2F                                        0x2A20
-# define GL_V3F                                        0x2A21
-# define GL_VIEWPORT_BIT                       0x00000800
-# define GL_INT                                        0x1404
-# define GL_DOUBLE                             0x140A
-
-#endif
-
-
-extern void jwzgles_reset (void);
-
-
-/* Prototypes for the things re-implemented in jwzgles.c 
- */
-
-extern int  jwzgles_glGenLists (int n);
-extern void jwzgles_glNewList (int id, int mode);
-extern void jwzgles_glEndList (void);
-extern void jwzgles_glDeleteLists (int list, int range);
-extern void jwzgles_glBegin (int mode);
-extern void jwzgles_glNormal3fv (const GLfloat *);
-extern void jwzgles_glNormal3f (GLfloat x, GLfloat y, GLfloat z);
-extern void jwzgles_glTexCoord1f (GLfloat s);
-extern void jwzgles_glTexCoord2fv (const GLfloat *);
-extern void jwzgles_glTexCoord2f (GLfloat s, GLfloat t);
-extern void jwzgles_glTexCoord3fv (const GLfloat *);
-extern void jwzgles_glTexCoord3f (GLfloat s, GLfloat t, GLfloat r);
-extern void jwzgles_glTexCoord4fv (const GLfloat *);
-extern void jwzgles_glTexCoord4f (GLfloat s, GLfloat t, GLfloat r, GLfloat q);
-extern void jwzgles_glVertex2f (GLfloat x, GLfloat y);
-extern void jwzgles_glVertex2dv (const GLdouble *);
-extern void jwzgles_glVertex2fv (const GLfloat *);
-extern void jwzgles_glVertex2i (GLint x, GLint y);
-extern void jwzgles_glVertex3f (GLfloat x, GLfloat y, GLfloat z);
-extern void jwzgles_glVertex3dv (const GLdouble *);
-extern void jwzgles_glVertex3fv (const GLfloat *);
-extern void jwzgles_glVertex3i (GLint x, GLint y, GLint z);
-extern void jwzgles_glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-extern void jwzgles_glVertex4fv (const GLfloat *);
-extern void jwzgles_glVertex4i (GLint x, GLint y, GLint z, GLint w);
-extern void jwzgles_glEnd (void);
-extern void jwzgles_glCallList (int id);
-extern void jwzgles_glClearIndex(GLfloat c);
-extern void jwzgles_glBitmap (GLsizei, GLsizei, GLfloat, GLfloat, GLfloat,
-                              GLfloat, const GLubyte *);
-extern void jwzgles_glPushAttrib(int);
-extern void jwzgles_glPopAttrib(void);
-
-
-/* These functions are present in both OpenGL 1.3 and in OpenGLES 1,
-   but are allowed within glNewList/glEndList, so we must wrap them
-   to allow them to be recorded.
- */
-extern void jwzgles_glActiveTexture (GLuint);
-extern void jwzgles_glBindTexture (GLuint, GLuint);
-extern void jwzgles_glBlendFunc (GLuint, GLuint);
-extern void jwzgles_glClear (GLuint);
-extern void jwzgles_glClearColor (GLclampf, GLclampf, GLclampf, GLclampf);
-extern void jwzgles_glClearStencil (GLuint);
-extern void jwzgles_glColorMask (GLuint, GLuint, GLuint, GLuint);
-extern void jwzgles_glCullFace (GLuint);
-extern void jwzgles_glDepthFunc (GLuint);
-extern void jwzgles_glDepthMask (GLuint);
-extern void jwzgles_glDisable (GLuint);
-extern void jwzgles_glDrawArrays (GLuint, GLuint, GLuint);
-extern GLboolean jwzgles_glIsEnabled (GLuint);
-extern void jwzgles_glEnable (GLuint);
-extern void jwzgles_glFrontFace (GLuint);
-extern void jwzgles_glHint (GLuint, GLuint);
-extern void jwzgles_glLineWidth (GLfloat);
-extern void jwzgles_glLoadIdentity (void);
-extern void jwzgles_glLogicOp (GLuint);
-extern void jwzgles_glMatrixMode (GLuint);
-extern void jwzgles_glMultMatrixf (const GLfloat *);
-extern void jwzgles_glPointSize (GLfloat);
-extern void jwzgles_glPolygonOffset (GLfloat, GLfloat);
-extern void jwzgles_glPopMatrix (void);
-extern void jwzgles_glPushMatrix (void);
-extern void jwzgles_glScissor (GLuint, GLuint, GLuint, GLuint);
-extern void jwzgles_glShadeModel (GLuint);
-extern void jwzgles_glStencilFunc (GLuint, GLuint, GLuint);
-extern void jwzgles_glStencilMask (GLuint);
-extern void jwzgles_glStencilOp (GLuint, GLuint, GLuint);
-extern void jwzgles_glViewport (GLuint, GLuint, GLuint, GLuint);
-extern void jwzgles_glTranslatef (GLfloat, GLfloat, GLfloat);
-extern void jwzgles_glRotatef (GLfloat, GLfloat, GLfloat, GLfloat);
-extern void jwzgles_glRotated (GLdouble, GLdouble x, GLdouble y, GLdouble z);
-extern void jwzgles_glScalef (GLfloat, GLfloat, GLfloat);
-extern void jwzgles_glColor3f (GLfloat, GLfloat, GLfloat);
-extern void jwzgles_glColor4f (GLfloat, GLfloat, GLfloat, GLfloat);
-extern void jwzgles_glColor3fv (const GLfloat *);
-extern void jwzgles_glColor4fv (const GLfloat *);
-extern void jwzgles_glColor3s (GLshort, GLshort, GLshort);
-extern void jwzgles_glColor4s (GLshort, GLshort, GLshort, GLshort);
-extern void jwzgles_glColor3sv (const GLshort *);
-extern void jwzgles_glColor4sv (const GLshort *);
-extern void jwzgles_glColor3us (GLushort, GLushort, GLushort);
-extern void jwzgles_glColor4us (GLushort, GLushort, GLushort, GLushort);
-extern void jwzgles_glColor3usv (const GLushort *);
-extern void jwzgles_glColor4usv (const GLushort *);
-extern void jwzgles_glColor3d (GLdouble, GLdouble, GLdouble);
-extern void jwzgles_glColor4d (GLdouble, GLdouble, GLdouble, GLdouble);
-extern void jwzgles_glColor3dv (const GLdouble *);
-extern void jwzgles_glColor4dv (const GLdouble *);
-extern void jwzgles_glColor4i (GLint, GLint, GLint, GLint);
-extern void jwzgles_glColor3i (GLint, GLint, GLint);
-extern void jwzgles_glColor3iv (const GLint *);
-extern void jwzgles_glColor4iv (const GLint *);
-extern void jwzgles_glColor4ui (GLuint, GLuint, GLuint, GLuint);
-extern void jwzgles_glColor3ui (GLuint, GLuint, GLuint);
-extern void jwzgles_glColor3uiv (const GLuint *);
-extern void jwzgles_glColor4uiv (const GLuint *);
-extern void jwzgles_glColor4b (GLbyte, GLbyte, GLbyte, GLbyte);
-extern void jwzgles_glColor3b (GLbyte, GLbyte, GLbyte);
-extern void jwzgles_glColor4bv (const GLbyte *);
-extern void jwzgles_glColor3bv (const GLbyte *);
-extern void jwzgles_glColor4ub (GLubyte, GLubyte, GLubyte, GLubyte);
-extern void jwzgles_glColor3ub (GLubyte, GLubyte, GLubyte);
-extern void jwzgles_glColor4ubv (const GLubyte *);
-extern void jwzgles_glColor3ubv (const GLubyte *);
-extern void jwzgles_glMaterialf (GLuint, GLuint, GLfloat);
-extern void jwzgles_glMateriali (GLuint, GLuint, GLuint);
-extern void jwzgles_glMaterialfv (GLuint, GLuint, const GLfloat *);
-extern void jwzgles_glMaterialiv (GLuint, GLuint, const GLint *);
-extern void jwzgles_glFinish (void);
-extern void jwzgles_glFlush (void);
-extern void jwzgles_glPixelStorei (GLuint, GLuint);
-extern void jwzgles_glEnableClientState (GLuint);
-extern void jwzgles_glDisableClientState (GLuint);
-
-extern void jwzgles_glInitNames (void);
-extern void jwzgles_glPushName (GLuint);
-extern GLuint jwzgles_glPopName (void);
-extern GLuint jwzgles_glRenderMode (GLuint);
-extern void jwzgles_glSelectBuffer (GLsizei, GLuint *);
-extern void jwzgles_glLightf (GLenum, GLenum, GLfloat);
-extern void jwzgles_glLighti (GLenum, GLenum, GLint);
-extern void jwzgles_glLightfv (GLenum, GLenum, const GLfloat *);
-extern void jwzgles_glLightiv (GLenum, GLenum, const GLint *);
-extern void jwzgles_glLightModelf (GLenum, GLfloat);
-extern void jwzgles_glLightModeli (GLenum, GLint);
-extern void jwzgles_glLightModelfv (GLenum, const GLfloat *);
-extern void jwzgles_glLightModeliv (GLenum, const GLint *);
-extern void jwzgles_glGenTextures (GLuint, GLuint *);
-extern void jwzgles_glFrustum (GLfloat, GLfloat, GLfloat, GLfloat,
-                               GLfloat, GLfloat);
-extern void jwzgles_glOrtho (GLfloat, GLfloat, GLfloat, GLfloat, 
-                             GLfloat, GLfloat);
-extern void jwzgles_glTexImage1D (GLenum target, GLint level,
-                                  GLint internalFormat,
-                                  GLsizei width, GLint border,
-                                  GLenum format, GLenum type,
-                                  const GLvoid *pixels);
-extern void jwzgles_glTexImage2D (GLenum target,
-                                  GLint        level,
-                                  GLint        internalFormat,
-                                  GLsizei      width,
-                                  GLsizei      height,
-                                  GLint        border,
-                                  GLenum       format,
-                                  GLenum       type,
-                                  const GLvoid *data);
-extern void jwzgles_glTexSubImage2D (GLenum target, GLint level,
-                                     GLint xoffset, GLint yoffset,
-                                     GLsizei width, GLsizei height,
-                                     GLenum format, GLenum type,
-                                     const GLvoid *pixels);
-extern void jwzgles_glCopyTexImage2D (GLenum target, GLint level, 
-                                      GLenum internalformat,
-                                      GLint x, GLint y, 
-                                      GLsizei width, GLsizei height, 
-                                      GLint border);
-extern void jwzgles_glInterleavedArrays (GLenum, GLsizei, const GLvoid *);
-extern void jwzgles_glTexEnvf (GLuint, GLuint, GLfloat);
-extern void jwzgles_glTexEnvi (GLuint, GLuint, GLuint);
-extern void jwzgles_glTexParameterf (GLuint, GLuint, GLfloat);
-extern void jwzgles_glTexParameteri (GLuint, GLuint, GLuint);
-extern void jwzgles_glTexGeni (GLenum, GLenum, GLint);
-extern void jwzgles_glTexGenfv (GLenum, GLenum, const GLfloat *);
-extern void jwzgles_glGetTexGenfv (GLenum, GLenum, GLfloat *);
-extern void jwzgles_glRectf (GLfloat, GLfloat, GLfloat, GLfloat);
-extern void jwzgles_glRecti (GLint, GLint, GLint, GLint);
-extern void jwzgles_glLightModelfv (GLenum, const GLfloat *);
-extern void jwzgles_glClearDepth (GLfloat);
-extern GLboolean jwzgles_glIsList (GLuint);
-extern void jwzgles_glColorMaterial (GLenum, GLenum);
-extern void jwzgles_glPolygonMode (GLenum, GLenum);
-extern void jwzgles_glFogf (GLenum, GLfloat);
-extern void jwzgles_glFogi (GLenum, GLint);
-extern void jwzgles_glFogfv (GLenum, const GLfloat *);
-extern void jwzgles_glFogiv (GLenum, const GLint *);
-extern void jwzgles_glAlphaFunc (GLenum, GLfloat);
-extern void jwzgles_glClipPlane (GLenum, const GLdouble *);
-extern void jwzgles_glDrawBuffer (GLenum);
-extern void jwzgles_glDeleteTextures (GLuint, const GLuint *);
-
-extern void jwzgles_gluPerspective (GLdouble fovy, GLdouble aspect, 
-                                    GLdouble near, GLdouble far);
-extern void jwzgles_gluLookAt (GLfloat eyex, GLfloat eyey, GLfloat eyez,
-                               GLfloat centerx, GLfloat centery, 
-                               GLfloat centerz,
-                               GLfloat upx, GLfloat upy, GLfloat upz);
-extern GLint jwzgles_gluProject (GLdouble objx, GLdouble objy, GLdouble objz, 
-                                 const GLdouble modelMatrix[16], 
-                                 const GLdouble projMatrix[16],
-                                 const GLint viewport[4],
-                                 GLdouble *winx, GLdouble *winy, 
-                                 GLdouble *winz);
-extern int jwzgles_gluBuild2DMipmaps (GLenum target,
-                                      GLint internalFormat,
-                                      GLsizei width,
-                                      GLsizei height,
-                                      GLenum format,
-                                      GLenum type,
-                                      const GLvoid *data);
-extern void jwzgles_glGetFloatv (GLenum pname, GLfloat *params);
-extern void jwzgles_glGetPointerv (GLenum pname, GLvoid *params);
-extern void jwzgles_glGetDoublev (GLenum pname, GLdouble *params);
-extern void jwzgles_glGetIntegerv (GLenum pname, GLint *params);
-extern void jwzgles_glGetBooleanv (GLenum pname, GLboolean *params);
-extern void jwzgles_glVertexPointer (GLuint, GLuint, GLuint, const void *);
-extern void jwzgles_glNormalPointer (GLenum, GLuint, const void *);
-extern void jwzgles_glColorPointer (GLuint, GLuint, GLuint, const void *);
-extern void jwzgles_glTexCoordPointer (GLuint, GLuint, GLuint, const void *);
-extern void jwzgles_glBindBuffer (GLuint, GLuint);
-extern void jwzgles_glBufferData (GLenum, GLsizeiptr, const void *, GLenum);
-extern const char *jwzgles_gluErrorString (GLenum error);
-
-#endif /* __JWZGLES_I_H__ */
index f88ccc662a2fde3fdc7ff0dc1cbbbe9ac3a8a184..58bf2861be49bcd71fbfc4861c629a01f6189c83 100644 (file)
@@ -19,6 +19,7 @@
                        "*count:        16          \n" \
                        "*showFPS:      False       \n" \
                        "*wireframe:    False       \n" \
+                       "*suppressRotationAnimation: True\n" \
 
 # define refresh_kaleidocycle 0
 # define release_kaleidocycle 0
@@ -102,6 +103,14 @@ reshape_kaleidocycle (ModeInfo *mi, int width, int height)
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
   glClear(GL_COLOR_BUFFER_BIT);
 }
 
index 63ea7599c94db12ff0009759cffbf8c28acda7a6..46466738b23d50f69fb5494f495bb65ca81c0c8e 100644 (file)
@@ -145,7 +145,7 @@ static const char sccsid[] = "@(#)klein.c  1.1 08/10/04 xlockmore";
 
 #ifdef USE_GL
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # include <X11/keysym.h>
 #endif
 
index 214aaf6208a5d455addf242f15224249f1370441..2a4b6395bb74f982c9dcfa77d01a5c17073552e9 100644 (file)
@@ -29,7 +29,9 @@
 
 #define DEFAULTS       "*delay:        20000   \n"     \
                        "*showFPS:      False   \n"     \
-                       "*wireframe:    False   \n"
+                       "*wireframe:    False   \n"     \
+                       "*suppressRotationAnimation: True\n" \
+
 # define refresh_lament 0
 # define release_lament 0
 #include "xlockmore.h"
@@ -325,7 +327,7 @@ scale_for_window (ModeInfo *mi)
 
   /* Constrain it to roughly life-sized on the screen, not huge.
    */
-# ifdef USE_IPHONE
+# ifdef HAVE_MOBILE
   if (size > 768)  /* iPad retina / iPhone 6 */
     target_size *= 1.5;
   else
@@ -453,8 +455,8 @@ leviathan (ModeInfo *mi, GLfloat ratio, GLfloat alpha, Bool top_p)
       int j = (i + 1) % countof(p);
 /*      if (top_p)*/
         do_normal (z, 0, 0,
-                   0, p[i].y, p[i].z,
-                   0, p[j].y, p[j].z);
+                   0, p[i].x, p[i].y,
+                   0, p[j].x, p[j].y);
 /*
       else
         do_normal (z, 0, 0,
index 77230771c188b4ec26e170008755ced1c9d0476c..b3357dd6b4ce261a1774c41f884869c6f7a73985 100644 (file)
 #include <stdio.h>
 #include <math.h>
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # include <GL/gl.h>
 #endif
 
+#ifdef HAVE_ANDROID
+# include <GLES/gl.h>
+#endif
+
 #ifdef HAVE_JWZGLES
 # include "jwzgles.h"
 #endif /* HAVE_JWZGLES */
index ef7ddce2fff6ae2c2b97b8864837519ac26e1f41..e26e2d31de4afe182d9ac34861c034a7c802f0c0 100644 (file)
@@ -53,6 +53,7 @@
 #define DEFAULTS       "*delay:         30000          \n" \
                        "*showFPS:       False          \n" \
                        "*wireframe:     False          \n" \
+                       "*suppressRotationAnimation: True\n" \
 
 
 # define refresh_sponge 0
@@ -140,6 +141,14 @@ reshape_sponge (ModeInfo *mi, int width, int height)
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
   glClear(GL_COLOR_BUFFER_BIT);
 }
 
index 825eb66a6f419356e340cdbe86ece57e6b588976..2fe9fc84ff15097b0f1b4156c963e13c9d583910 100644 (file)
@@ -41,7 +41,8 @@
                  "*useSHM:              True       \n"                      \
                  "*desktopGrabber:  xscreensaver-getimage -no-desktop %s\n" \
                  "*grabDesktopImages:   True  \n"                           \
-                 "*chooseRandomImages:  True  \n"
+                 "*chooseRandomImages:  True  \n"                           \
+                "*suppressRotationAnimation: True\n"                       \
 
 # define refresh_mirrorblob 0
 # include "xlockmore.h"
@@ -1415,7 +1416,7 @@ draw_blob (mirrorblobstruct *gp)
 
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
-  glRotatef(current_device_rotation(), 0, 0, 1);
+/*  glRotatef(current_device_rotation(), 0, 0, 1); */
 
   /* Move down the z-axis. */
   glTranslatef (0.0, 0.0, -4.0);
@@ -1472,13 +1473,15 @@ draw_background (ModeInfo *mi)
   glPushMatrix();
   glLoadIdentity();
 
-  glRotatef (rot, 0, 0, 1);
+  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);
     }
+*/
 
   glOrtho(0.0, MI_WIDTH(mi), MI_HEIGHT(mi), 0.0, -1000.0, 1000.0);
 
index feb1a488233c2be68ecf5b40925db43589119329..8c92ff7f073844886c58459ccb657752de1efc8c 100644 (file)
@@ -81,14 +81,15 @@ static const char sccsid[] = "@(#)moebius.c 5.01 2001/03/01 xlockmore";
 # define MODE_moebius
 # define refresh_moebius 0
 # define DEFAULTS                      "*delay:                20000   \n"                     \
-                                                       "*showFPS:      False   \n"
+                                                       "*showFPS:      False   \n"                     \
+                                                       "*suppressRotationAnimation: True\n" \
 
 # include "xlockmore.h"                /* from the xscreensaver distribution */
 #else /* !STANDALONE */
 # include "xlock.h"            /* from the xlockmore distribution */
 #endif /* !STANDALONE */
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
 # include "jwxyz.h"
 #else
 # include <X11/Xlib.h>
@@ -730,6 +731,7 @@ draw_moebius (ModeInfo * mi)
 
        glPushMatrix();
 
+
        glTranslatef(0.0, 0.0, -10.0);
 
     gltrackball_rotate (mp->trackball);
@@ -740,6 +742,18 @@ draw_moebius (ModeInfo * mi)
                glScalef(Scale4Iconic * mp->WindH / mp->WindW, Scale4Iconic, Scale4Iconic);
        }
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+    {
+      GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+      int o = (int) current_device_rotation();
+      if (o != 0 && o != 180 && o != -180) {
+        glScalef (1/h, h, 1);  /* #### not quite right */
+        h = 1.7;
+        glScalef (h, h, h);
+      }
+    }
+# endif
+
     {
       double x, y, z;
       get_rotation (mp->rot, &x, &y, &z, !mp->button_down_p);
index b8dd5a41160c76f74a55a02bc11cfd74e8956369..a65f5fcef2984740178c30e24b3e4962669c156b 100644 (file)
@@ -13,6 +13,7 @@
                        "*count:        17          \n" \
                        "*showFPS:      False       \n" \
                        "*wireframe:    False       \n" \
+                       "*suppressRotationAnimation: True\n" \
 
 # define refresh_mgears 0
 # define release_mgears 0
@@ -104,6 +105,14 @@ reshape_mgears (ModeInfo *mi, int width, int height)
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
   glClear(GL_COLOR_BUFFER_BIT);
 }
 
index cbc07b1aa037e4f6a92f889d2c269fa547148a22..4cc3d0849463a39e5e97879e3afd0d57f8c97766 100644 (file)
@@ -1,4 +1,4 @@
-/* molecule, Copyright (c) 2001-2014 Jamie Zawinski <jwz@jwz.org>
+/* molecule, Copyright (c) 2001-2016 Jamie Zawinski <jwz@jwz.org>
  * Draws molecules, based on coordinates from PDB (Protein Data Base) files.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -31,6 +31,7 @@
        "*titleFont:  -*-helvetica-medium-r-normal-*-*-180-*-*-*-*-*-*\n" \
                        "*noLabelThreshold:    150    \n" \
                        "*wireframeThreshold:  150    \n" \
+                       "*suppressRotationAnimation: True\n" \
 
 # define refresh_molecule 0
 # define release_molecule 0
@@ -91,7 +92,7 @@ static const char * const builtin_pdb_data[] = {
 };
 
 
-#ifndef USE_IPHONE
+#ifndef HAVE_MOBILE
 # define LOAD_FILES
 #endif
 
@@ -479,9 +480,12 @@ draw_bounding_box (ModeInfo *mi)
 
   glColor3f (c2[0], c2[1], c2[2]);
   glBegin(GL_LINES);
-  if (x1 > 0) x1 = 0; if (x2 < 0) x2 = 0;
-  if (y1 > 0) y1 = 0; if (y2 < 0) y2 = 0;
-  if (z1 > 0) z1 = 0; if (z2 < 0) z2 = 0;
+  if (x1 > 0) x1 = 0;
+  if (x2 < 0) x2 = 0;
+  if (y1 > 0) y1 = 0;
+  if (y2 < 0) y2 = 0;
+  if (z1 > 0) z1 = 0;
+  if (z2 < 0) z2 = 0;
   glVertex3f(x1, 0,  0);  glVertex3f(x2, 0,  0); 
   glVertex3f(0 , y1, 0);  glVertex3f(0,  y2, 0); 
   glVertex3f(0,  0,  z1); glVertex3f(0,  0,  z2); 
@@ -1196,6 +1200,14 @@ reshape_molecule (ModeInfo *mi, int width, int height)
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
   glClear(GL_COLOR_BUFFER_BIT);
 }
 
@@ -1419,11 +1431,13 @@ draw_labels (ModeInfo *mi)
       {
         XCharStruct e;
         int w, h;
+        GLfloat s;
+
         texture_string_metrics (mc->atom_font, a->label, &e, 0, 0);
         w = e.width;
         h = e.ascent + e.descent;
 
-        GLfloat s = 1.0 / h;           /* Scale to unit */
+        s = 1.0 / h;                   /* Scale to unit */
         s *= mc->overall_scale;                /* Scale to size of atom */
         s *= 0.8;                      /* Shrink a bit */
         glScalef (s, s, 1);
index 9519d2f528bb2d48172008b31830c1ac869f1759..daedcec50086c06c2c525a57834c9a79517a0611 100755 (executable)
@@ -6,6 +6,7 @@ SRCS=$*
 
 TMP=molecules.h.$$
 rm -f $TMP
+trap "rm -f $TMP" 1 2 3 15 ERR EXIT
 
 if [ -z "$UTILS_SRC" ]; then UTILS_SRC="../../utils"; fi
 
index c1675aeb1ba8d41b4062c47bef926e229cab6b58..e96309acc5817fd2f1f3d2571e481a9f40dc9915 100644 (file)
@@ -55,7 +55,9 @@ static const char sccsid[] = "@(#)morph3d.c   5.01 2001/03/01 xlockmore";
 # define MODE_moebius
 # define DEFAULTS              "*delay:                40000   \n"             \
                                                "*showFPS:      False   \n"             \
-                                               "*count:                0               \n"
+                                               "*count:                0               \n"             \
+                                               "*suppressRotationAnimation: True\n" \
+
 # define refresh_morph3d 0
 # define morph3d_handle_event 0
 # include "xlockmore.h"                /* from the xscreensaver distribution */
@@ -770,6 +772,15 @@ draw_morph3d(ModeInfo * mi)
                glScalef(Scale4Iconic * mp->WindH / mp->WindW, Scale4Iconic, Scale4Iconic);
        }
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+    {
+      GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+      int o = (int) current_device_rotation();
+      if (o != 0 && o != 180 && o != -180)
+        glScalef (1/h, h, 1);
+    }
+# endif
+
        glRotatef(mp->step * 100, 1, 0, 0);
        glRotatef(mp->step * 95, 0, 1, 0);
        glRotatef(mp->step * 90, 0, 0, 1);
index 4ca77679f8f19feabb577174e712fa64a0ed247b..a10d685ea5467e67f5d54db333476c29632521e8 100644 (file)
@@ -17,6 +17,7 @@
                        "*showFPS:      False       \n" \
                        "*fpsSolid:     True        \n" \
                        "*doubleBuffer: False       \n" \
+                       "*suppressRotationAnimation: True\n" \
 
 # define refresh_noof 0
 # define release_noof 0
index a707a0c94871f2706d621461ce2c61522270a2e0..2200dfea41d2dd07394c345dc2d8311a25e52bdc 100644 (file)
 # include "config.h"
 #endif /* HAVE_CONFIG_H */
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # include <GL/gl.h>
 #endif
 
+#ifdef HAVE_ANDROID
+# include <GLES/gl.h>
+#endif
+
 #ifdef HAVE_JWZGLES
 # include "jwzgles.h"
 #endif /* HAVE_JWZGLES */
index 29617aa05ef4004d7581e0a90719dbae64bab596..d2ea5b402aed92a30f06fb294eba15212bfcbcf6 100644 (file)
@@ -21,7 +21,8 @@
                   "*font:          " DEF_FONT "\n" \
                   "*desktopGrabber:  xscreensaver-getimage -no-desktop %s\n" \
                   "*grabDesktopImages:   False \n" \
-                  "*chooseRandomImages:  True  \n"
+                  "*chooseRandomImages:  True  \n" \
+                 "*suppressRotationAnimation: True\n" \
 
 # define refresh_photopile 0
 # define release_photopile 0
@@ -30,7 +31,7 @@
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # include <X11/Intrinsic.h>     /* for XrmDatabase in -debug mode */
 #endif
 #include <math.h>
@@ -433,6 +434,15 @@ reshape_photopile (ModeInfo *mi, int width, int height)
   glLoadIdentity();
   glOrtho(0, MI_WIDTH(mi), 0, MI_HEIGHT(mi), -1, 1);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, h, 1);
+  }
+# endif
+
   glClear(GL_COLOR_BUFFER_BIT);
 }
 
@@ -442,7 +452,7 @@ reshape_photopile (ModeInfo *mi, int width, int height)
 static void
 hack_resources (Display *dpy)
 {
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
   char *res = "desktopGrabber";
   char *val = get_string_resource (dpy, res, "DesktopGrabber");
   char buf1[255];
@@ -454,7 +464,7 @@ hack_resources (Display *dpy)
   value.addr = buf2;
   value.size = strlen(buf2);
   XrmPutResource (&db, buf1, "String", &value);
-# endif /* !HAVE_COCOA */
+# endif /* !HAVE_JWXYZ */
 }
 
 
index 2de9d8a0c9a8257c004819ae532840a3c22eeb49..2b83bbfd23a11c9e3bcb1d29419b180fc42c3191 100644 (file)
@@ -65,7 +65,8 @@ static const char sccsid[] = "@(#)pipes.c     4.07 97/11/24 xlockmore";
                                        "*size:                 500     \n"                     \
                        "*showFPS:      False   \n"                 \
                        "*fpsSolid:     True    \n"                 \
-                       "*wireframe:    False   \n"
+                       "*wireframe:    False   \n"                 \
+                                       "*suppressRotationAnimation: True\n" \
 
 # define refresh_pipes 0
 # include "xlockmore.h"                                /* from the xscreensaver distribution */
@@ -75,7 +76,7 @@ static const char sccsid[] = "@(#)pipes.c     4.07 97/11/24 xlockmore";
 
 #ifdef USE_GL
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
 # include "jwxyz.h"
 #else
 # include <X11/Xlib.h>
index b931069ce37f243b3819ab85fc49ff2f803bf396..7d8d820b448c235b953325e40b14f4d5b0387b3f 100644 (file)
@@ -21,6 +21,7 @@
        "*titleFont:  -*-helvetica-medium-r-normal-*-*-140-*-*-*-*-*-*\n" \
        "*titleFont2: -*-helvetica-medium-r-normal-*-*-100-*-*-*-*-*-*\n" \
        "*titleFont3: -*-helvetica-medium-r-normal-*-*-80-*-*-*-*-*-*\n"  \
+       "*suppressRotationAnimation: True\n" \
 
 
 # define refresh_polyhedra 0
@@ -30,7 +31,7 @@
 
 #include "xlockmore.h"
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
 # include "jwxyz.h"
 #else
 # include <X11/Xlib.h>
@@ -57,7 +58,7 @@
 #include "gltrackball.h"
 #include "teapot.h"
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # define XK_MISCELLANY
 # include <X11/keysymdef.h>
 #endif
@@ -625,6 +626,15 @@ draw_polyhedra (ModeInfo *mi)
 
   glPushMatrix ();
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
   glScalef(1.1, 1.1, 1.1);
 
   {
index 26f66d3a5338d232eba795ff55695ba0786b8146..d179de348b1f134d0f0311e8b42f74b286f663f4 100644 (file)
@@ -200,18 +200,7 @@ static const struct {
    *           Dihedral Schwarz Triangles (D5 only)
    ***************************************************************************/
 
-  /*   {"3|2 5/2",     "xyz",
-                               "xyz",
-                               "xyz",
-                               "",
-                               "",
-                               0, 0},
-*/
-
-
-
-                                                          /* (2 2 5) (D1/5) */
-  /*  1 */     {"2 5|2",       "Pentagonal Prism",
+  /*  0 */     {"2 5|2",       "Pentagonal Prism",
                                "Pentagonal Dipyramid",
                                "Dihedral (D[1/5])",
                                "",
@@ -225,14 +214,14 @@ static const struct {
                                "",
                                0, 0},
                                                         /* (2 2 5/2) (D2/5) */
-  /*  3 */     {"2 5/2|2",     "Pentagrammic Prism",
+  /*  4 */     {"2 5/2|2",     "Pentagrammic Prism",
                                "Pentagrammic Dipyramid",
                                "Dihedral (D[2/5])",
                                "",
                                "",
                                0, 0},
 
-  /*  4 */     {"|2 2 5/2",    "Pentagrammic Antiprism",
+  /*  6 */     {"|2 2 5/2",    "Pentagrammic Antiprism",
                                "Pentagrammic Deltohedron",
                                "Dihedral (D[2/5])",
                                "",
@@ -240,7 +229,7 @@ static const struct {
                                0, 0},
                                                         /* (5/3 2 2) (D3/5) */
 
-  /*  5 */     {"|2 2 5/3",    "Pentagrammic Crossed Antiprism",
+  /*  8 */     {"|2 2 5/3",    "Pentagrammic Crossed Antiprism",
                                "Pentagrammic Concave Deltohedron",
                                "Dihedral (D[3/5])",
                                "",
@@ -252,21 +241,21 @@ static const struct {
    ***************************************************************************/
 
                                                             /* (2 3 3) (T1) */
-  /*  6 */     {"3|2 3",       "Tetrahedron",
+  /*  10 */    {"3|2 3",       "Tetrahedron",
                                "Tetrahedron",
                                "Tetrahedral (T[1])",
                                "Platonic Solid",
                                "Platonic Solid",
                                15, 1},
 
-  /*  7 */     {"2 3|3",       "Truncated Tetrahedron",
+  /*  12 */    {"2 3|3",       "Truncated Tetrahedron",
                                "Triakistetrahedron",
                                "Tetrahedral (T[1])",
-                               "Archimedian Solid",
+                               "Archimedean Solid",
                                "Catalan Solid",
                                16, 6},
                                                           /* (3/2 3 3) (T2) */
-  /*  8 */     {"3/2 3|3",     "Octahemioctahedron",
+  /*  14 */    {"3/2 3|3",     "Octahemioctahedron",
                                "Octahemioctacron",
                                "Tetrahedral (T[2])",
                                "",
@@ -274,7 +263,7 @@ static const struct {
                                37, 68},
 
                                                           /* (3/2 2 3) (T3) */
-  /*  9 */     {"3/2 3|2",     "Tetrahemihexahedron",
+  /*  16 */    {"3/2 3|2",     "Tetrahemihexahedron",
                                "Tetrahemihexacron",
                                "Tetrahedral (T[3])",
                                "",
@@ -286,64 +275,68 @@ static const struct {
    ***************************************************************************/
 
                                                             /* (2 3 4) (O1) */
-  /* 10 */     {"4|2 3",       "Octahedron",
+  /* 18 */     {"4|2 3",       "Octahedron",
                                "Cube",
                                "Octahedral (O[1])",
                                "Platonic Solid",
                                "Platonic Solid",
                                17, 2},
 
-  /* 11 */     {"3|2 4",       "Cube",
+  /* 20 */     {"3|2 4",       "Cube",
                                "Octahedron",
                                "Octahedral (O[1])",
                                "Platonic Solid",
                                "Platonic Solid",
                                18, 3},
 
-  /* 12 */     {"2|3 4",       "Cuboctahedron",
+  /* 22 */     {"2|3 4",       "Cuboctahedron",
                                "Rhombic Dodecahedron",
                                "Octahedral (O[1])",
-                               "Archimedian Solid",
+                               "Archimedean Solid",
                                "Catalan Solid",
                                19, 11},
 
-  /* 13 */     {"2 4|3",       "Truncated Octahedron",
+  /* 24 */     {"2 4|3",       "Truncated Octahedron",
                                "Tetrakishexahedron",
                                "Octahedral (O[1])",
-                               "Archimedian Solid",
+                               "Archimedean Solid",
                                "Catalan Solid",
                                20, 7},
 
-  /* 14 */     {"2 3|4",       "Truncated Cube",
+  /* 26 */     {"2 3|4",       "Truncated Cube",
                                "Triakisoctahedron",
                                "Octahedral (O[1])",
-                               "Archimedian Solid",
+                               "Archimedean Solid",
                                "Catalan Solid",
                                21, 8},
 
-  /* 15 */     {"3 4|2",       "Rhombicuboctahedron",
+  /* 28 */     {"3 4|2",       "Rhombicuboctahedron",
                                "Deltoidal Icositetrahedron",
                                "Octahedral (O[1])",
-                               "Archimedian Solid",
+                               "Archimedean Solid",
                                "Catalan Solid",
                                22, 13},
 
-  /* 16 */     {"2 3 4|",      "Truncated Cuboctahedron",
+  /* 30 */     {"2 3 4|",      "Truncated Cuboctahedron",
                                "Disdyakisdodecahedron",
                                "Octahedral (O[1])",
-                               "Archimedian Solid",
+                               "Archimedean Solid",
                                "Catalan Solid",
                                23, 15},
 
-  /* 17 */     {"|2 3 4",      "Snub Cube",
+  /* 32, 33, 66, and 67 are chiral, existing in both left and right handed
+     (enantiomeric) forms, so it would make sense to display both versions.
+  */
+
+  /* 32 */     {"|2 3 4",      "Snub Cube",
                                "Pentagonal Icositetrahedron",
-                               "Octahedral (O[1])",
-                               "Archimedian Solid",
+                               "Octahedral (O[1]), Chiral",
+                               "Archimedean Solid",
                                "Catalan Solid",
                                24, 17},
                                                          /* (3/2 4 4) (O2b) */
 
-  /* 18 */     {"3/2 4|4",     "Small Cubicuboctahedron",
+  /* 34 */     {"3/2 4|4",     "Small Cubicuboctahedron",
                                "Small Hexacronic Icositetrahedron",
                                "Octahedral (O[2b])",
                                "",
@@ -351,21 +344,21 @@ static const struct {
                                38, 69},
                                                           /* (4/3 3 4) (O4) */
 
-  /* 19 */     {"3 4|4/3",     "Great Cubicuboctahedron",
+  /* 36 */     {"3 4|4/3",     "Great Cubicuboctahedron",
                                "Great Hexacronic Icositetrahedron",
                                "Octahedral (O[4])",
                                "",
                                "",
                                50, 77},
 
-  /* 20 */     {"4/3 4|3",     "Cubohemioctahedron",
+  /* 38 */     {"4/3 4|3",     "Cubohemioctahedron",
                                "Hexahemioctacron",
                                "Octahedral (O[4])",
                                "",
                                "",
                                51, 78},
 
-  /* 21 */     {"4/3 3 4|",    "Cubitruncated Cuboctahedron",
+  /* 40 */     {"4/3 3 4|",    "Cubitruncated Cuboctahedron",
                                "Tetradyakishexahedron",
                                "Octahedral (O[4])",
                                "",
@@ -373,14 +366,14 @@ static const struct {
                                52, 79},
                                                           /* (3/2 2 4) (O5) */
 
-  /* 22 */     {"3/2 4|2",     "Great Rhombicuboctahedron",
+  /* 42 */     {"3/2 4|2",     "Great Rhombicuboctahedron",
                                "Great Deltoidal Icositetrahedron",
                                "Octahedral (O[5])",
                                "",
                                "",
                                59, 85},
 
-  /* 23 */     {"3/2 2 4|",    "Small Rhombihexahedron",
+  /* 44 */     {"3/2 2 4|",    "Small Rhombihexahedron",
                                "Small Rhombihexacron",
                                "Octahedral (O[5])",
                                "",
@@ -388,14 +381,14 @@ static const struct {
                                60, 86},
                                                           /* (4/3 2 3) (O7) */
 
-  /* 24 */     {"2 3|4/3",     "Stellated Truncated Hexahedron",
+  /* 46 */     {"2 3|4/3",     "Stellated Truncated Hexahedron",
                                "Great Triakisoctahedron",
                                "Octahedral (O[7])",
                                "",
                                "",
                                66, 92},
 
-  /* 25 */     {"4/3 2 3|",    "Great Truncated Cuboctahedron",
+  /* 48 */     {"4/3 2 3|",    "Great Truncated Cuboctahedron",
                                "Great Disdyakisdodecahedron",
                                "Octahedral (O[7])",
                                "",
@@ -403,7 +396,7 @@ static const struct {
                                67, 93},
                                                        /* (4/3 3/2 2) (O11) */
 
-  /* 26 */     {"4/3 3/2 2|",  "Great Rhombihexahedron",
+  /* 50 */     {"4/3 3/2 2|",  "Great Rhombihexahedron",
                                "Great Rhombihexacron",
                                "Octahedral (O[11])",
                                "",
@@ -415,78 +408,82 @@ static const struct {
    ***************************************************************************/
 
                                                             /* (2 3 5) (I1) */
-  /* 27 */     {"5|2 3",       "Icosahedron",
+  /* 52 */     {"5|2 3",       "Icosahedron",
                                "Dodecahedron",
                                "Icosahedral (I[1])",
                                "Platonic Solid",
                                "Platonic Solid",
                                25, 4},
 
-  /* 28 */     {"3|2 5",       "Dodecahedron",
+  /* 54 */     {"3|2 5",       "Dodecahedron",
                                "Icosahedron",
                                "Icosahedral (I[1])",
                                "Platonic Solid",
                                "Platonic Solid",
                                26, 5},
 
-  /* 29 */     {"2|3 5",       "Icosidodecahedron",
+  /* 56 */     {"2|3 5",       "Icosidodecahedron",
                                "Rhombic Triacontahedron",
                                "Icosahedral (I[1])",
-                               "Archimedian Solid",
+                               "Archimedean Solid",
                                "Catalan Solid",
                                28, 12},
 
-  /* 30 */     {"2 5|3",       "Truncated Icosahedron",
+  /* 58 */     {"2 5|3",       "Truncated Icosahedron",
                                "Pentakisdodecahedron",
                                "Icosahedral (I[1])",
-                               "Archimedian Solid",
+                               "Archimedean Solid",
                                "Catalan Solid",
                                27, 9},
 
-  /* 31 */     {"2 3|5",       "Truncated Dodecahedron",
+  /* 60 */     {"2 3|5",       "Truncated Dodecahedron",
                                "Triakisicosahedron",
                                "Icosahedral (I[1])",
-                               "Archimedian Solid",
+                               "Archimedean Solid",
                                "Catalan Solid",
                                29, 10},
 
-  /* 32 */     {"3 5|2",       "Rhombicosidodecahedron",
+  /* 62 */     {"3 5|2",       "Rhombicosidodecahedron",
                                "Deltoidal Hexecontahedron",
                                "Icosahedral (I[1])",
-                               "Archimedian Solid",
+                               "Archimedean Solid",
                                "Catalan Solid",
                                30, 14},
 
-  /* 33 */     {"2 3 5|",      "Truncated Icosidodecahedron",
+  /* 64 */     {"2 3 5|",      "Truncated Icosidodecahedron",
                                "Disdyakistriacontahedron",
                                "Icosahedral (I[1])",
-                               "Archimedian Solid",
+                               "Archimedean Solid",
                                "Catalan Solid",
                                31, 16},
 
-  /* 34 */     {"|2 3 5",      "Snub Dodecahedron",
+  /* 32, 33, 66, and 67 are chiral, existing in both left and right handed
+     (enantiomeric) forms, so it would make sense to display both versions.
+  */
+
+  /* 66 */     {"|2 3 5",      "Snub Dodecahedron",
                                "Pentagonal Hexecontahedron",
-                               "Icosahedral (I[1])",
-                               "Archimedian Solid",
+                               "Icosahedral (I[1]), Chiral",
+                               "Archimedean Solid",
                                "Catalan Solid",
                                32, 18},
                                                          /* (5/2 3 3) (I2a) */
 
-  /* 35 */     {"3|5/2 3",     "Small Ditrigonal Icosidodecahedron",
+  /* 68 */     {"3|5/2 3",     "Small Ditrigonal Icosidodecahedron",
                                "Small Triambic Icosahedron",
                                "Icosahedral (I[2a])",
                                "",
                                "",
                                39, 70},
 
-  /* 36 */     {"5/2 3|3",     "Small Icosicosidodecahedron",
+  /* 70 */     {"5/2 3|3",     "Small Icosicosidodecahedron",
                                "Small Icosacronic Hexecontahedron",
                                "Icosahedral (I[2a])",
                                "",
                                "",
                                40, 71},
 
-  /* 37 */     {"|5/2 3 3",    "Small Snub Icosicosidodecahedron",
+  /* 72 */     {"|5/2 3 3",    "Small Snub Icosicosidodecahedron",
                                "Small Hexagonal Hexecontahedron",
                                "Icosahedral (I[2a])",
                                "",
@@ -494,7 +491,7 @@ static const struct {
                                41, 110},
                                                          /* (3/2 5 5) (I2b) */
 
-  /* 38 */     {"3/2 5|5",     "Small Dodecicosidodecahedron",
+  /* 74 */     {"3/2 5|5",     "Small Dodecicosidodecahedron",
                                "Small Dodecacronic Hexecontahedron",
                                "Icosahedral (I[2b])",
                                "",
@@ -502,49 +499,49 @@ static const struct {
                                42, 72},
                                                           /* (2 5/2 5) (I3) */
 
-  /* 39 */     {"5|2 5/2",     "Small Stellated Dodecahedron",
+  /* 76 */     {"5|2 5/2",     "Small Stellated Dodecahedron",
                                "Great Dodecahedron",
                                "Icosahedral (I[3])",
-                               "Truncated Kepler-Poinsot Solid",
+                               "",
                                "",
                                43, 20},
 
-  /* 40 */     {"5/2|2 5",     "Great Dodecahedron",
+  /* 78 */     {"5/2|2 5",     "Great Dodecahedron",
                                "Small Stellated Dodecahedron",
                                "Icosahedral (I[3])",
                                "",
                                "",
                                44, 21},
 
-  /* 41 */     {"2|5/2 5",     "Great Dodecadodecahedron",
+  /* 80 */     {"2|5/2 5",     "Great Dodecadodecahedron",
                                "Medial Rhombic Triacontahedron",
                                "Icosahedral (I[3])",
                                "",
                                "",
                                45, 73},
 
-  /* 42 */     {"2 5/2|5",     "Truncated Great Dodecahedron",
+  /* 82 */     {"2 5/2|5",     "Truncated Great Dodecahedron",
                                "Small Stellapentakisdodecahedron",
                                "Icosahedral (I[3])",
-                               "Truncated Kepler-Poinsot Solid",
+                               "",
                                "",
                                47, 75},
 
-  /* 43 */     {"5/2 5|2",     "Rhombidodecadodecahedron",
+  /* 84 */     {"5/2 5|2",     "Rhombidodecadodecahedron",
                                "Medial Deltoidal Hexecontahedron",
                                "Icosahedral (I[3])",
                                "",
                                "",
                                48, 76},
 
-  /* 44 */     {"2 5/2 5|",    "Small Rhombidodecahedron",
+  /* 86 */     {"2 5/2 5|",    "Small Rhombidodecahedron",
                                "Small Rhombidodecacron",
                                "Icosahedral (I[3])",
                                "",
                                "",
                                46, 74},
 
-  /* 45 */     {"|2 5/2 5",    "Snub Dodecadodecahedron",
+  /* 88 */     {"|2 5/2 5",    "Snub Dodecadodecahedron",
                                "Medial Pentagonal Hexecontahedron",
                                "Icosahedral (I[3])",
                                "",
@@ -552,71 +549,71 @@ static const struct {
                                49, 111},
                                                           /* (5/3 3 5) (I4) */
 
-  /* 46 */     {"3|5/3 5",     "Ditrigonal Dodecadodecahedron",
+  /* 90 */     {"3|5/3 5",     "Ditrigonal Dodecadodecahedron",
                                "Medial Triambic Icosahedron",
                                "Icosahedral (I[4])",
                                "",
                                "",
                                53, 80},
 
-  /* 47 */     {"3 5|5/3",     "Great Ditrigonal Dodecicosidodecahedron",
+  /* 92 */     {"3 5|5/3",     "Great Ditrigonal Dodecicosidodecahedron",
                               "Great Ditrigonal Dodecacronic Hexecontahedron",
                                "Icosahedral (I[4])",
                                "",
                                "",
                                54, 81},
 
-  /* 48 */     {"5/3 3|5",     "Small Ditrigonal Dodecicosidodecahedron",
+  /* 94 */     {"5/3 3|5",     "Small Ditrigonal Dodecicosidodecahedron",
                               "Small Ditrigonal Dodecacronic Hexecontahedron",
                                "Icosahedral (I[4])",
                                "",
                                "",
                                55, 82},
 
-  /* 49 */     {"5/3 5|3",     "Icosidodecadodecahedron",
+  /* 96 */     {"5/3 5|3",     "Icosidodecadodecahedron",
                                "Medial Icosacronic Hexecontahedron",
                                "Icosahedral (I[4])",
                                "",
                                "",
                                56, 83},
 
-  /* 50 */     {"5/3 3 5|",    "Icositruncated Dodecadodecahedron",
+  /* 98 */     {"5/3 3 5|",    "Icositruncated Dodecadodecahedron",
                                "Tridyakisicosahedron",
                                "Icosahedral (I[4])",
                                "",
                                "",
                                57, 84},
 
-  /* 51 */     {"|5/3 3 5",    "Snub Icosidodecadodecahedron",
+  /* 100 */    {"|5/3 3 5",    "Snub Icosidodecadodecahedron",
                                "Medial Hexagonal Hexecontahedron",
                                "Icosahedral (I[4])",
                                "",
-                               "",
+                               "Kepler-Poinsot Solid",
                                58, 112},
                                                          /* (3/2 3 5) (I6b) */
 
-  /* 52 */     {"3/2|3 5",     "Great Ditrigonal Icosidodecahedron",
+  /* 102 */    {"3/2|3 5",     "Great Ditrigonal Icosidodecahedron",
                                "Great Triambic Icosahedron",
                                "Icosahedral (I[6b])",
                                "",
                                "",
                                61, 87},
 
-  /* 53 */     {"3/2 5|3",     "Great Icosicosidodecahedron",
+  /* 104 */    {"3/2 5|3",     "Great Icosicosidodecahedron",
                                "Great Icosacronic Hexecontahedron",
                                "Icosahedral (I[6b])",
                                "",
                                "",
                                62, 88},
 
-  /* 54 */     {"3/2 3|5",     "Small Icosihemidodecahedron",
+  /* 106 */    {"3/2 3|5",     "Small Icosihemidodecahedron",
                                "Small Icosihemidodecacron",
                                "Icosahedral (I[6b])",
                                "",
                                "",
                                63, 89},
 
-  /* 55 */     {"3/2 3 5|",    "Small Dodecicosahedron",
+  /* 108 */    {"3/2 3 5|",    "Small Dodecicosahedron",
                                "Small Dodecicosacron",
                                "Icosahedral (I[6b])",
                                "",
@@ -624,7 +621,7 @@ static const struct {
                                64, 90},
                                                          /* (5/4 5 5) (I6c) */
 
-  /* 56 */     {"5/4 5|5",     "Small Dodecahemidodecahedron",
+  /* 110 */    {"5/4 5|5",     "Small Dodecahemidodecahedron",
                                "Small Dodecahemidodecacron",
                                "Icosahedral (I[6c])",
                                "",
@@ -632,101 +629,101 @@ static const struct {
                                65, 91},
                                                           /* (2 5/2 3) (I7) */
 
-  /* 57 */     {"3|2 5/2",     "Great Stellated Dodecahedron",
+  /* 112 */    {"3|2 5/2",     "Great Stellated Dodecahedron",
                                "Great Icosahedron",
                                "Icosahedral (I[7])",
                                "",
                                "",
                                68, 22},
 
-  /* 58 */     {"5/2|2 3",     "Great Icosahedron",
+  /* 114 */    {"5/2|2 3",     "Great Icosahedron",
                                "Great Stellated Dodecahedron",
                                "Icosahedral (I[7])",
                                "",
                                "",
                                69, 41},
 
-  /* 59 */     {"2|5/2 3",     "Great Icosidodecahedron",
+  /* 116 */    {"2|5/2 3",     "Great Icosidodecahedron",
                                "Great Rhombic Triacontahedron",
                                "Icosahedral (I[7])",
-                               "Truncated Kepler-Poinsot Solid",
+                               "",
                                "",
                                70, 94},
 
-  /* 60 */     {"2 5/2|3",     "Great Truncated Icosahedron",
+  /* 118 */    {"2 5/2|3",     "Great Truncated Icosahedron",
                                "Great Stellapentakisdodecahedron",
                                "Icosahedral (I[7])",
-                               "Truncated Kepler-Poinsot Solid",
+                               "",
                                "",
                                71, 95},
 
-  /* 61 */     {"2 5/2 3|",    "Rhombicosahedron",
+  /* 120 */    {"2 5/2 3|",    "Rhombicosahedron",
                                "Rhombicosacron",
                                "Icosahedral (I[7])",
                                "",
                                "",
                                72, 96},
 
-  /* 62 */     {"|2 5/2 3",    "Great Snub Icosidodecahedron",
+  /* 122 */    {"|2 5/2 3",    "Great Snub Icosidodecahedron",
                                "Great Pentagonal Hexecontahedron",
                                "Icosahedral (I[7])",
                                "",
-                               "",
+                               "Kepler-Poinsot Solid",
                                73, 113},
                                                           /* (5/3 2 5) (I9) */
 
-  /* 63 */     {"2 5|5/3",     "Small Stellated Truncated Dodecahedron",
-                               "Great Pentakisdodekahedron",
+  /* 124 */    {"2 5|5/3",     "Small Stellated Truncated Dodecahedron",
+                               "Great Pentakisdodecahedron",
                                "Icosahedral (I[9])",
                                "",
                                "",
                                74, 97},
 
-  /* 64 */     {"5/3 2 5|",    "Truncated Dodecadodecahedron",
+  /* 126 */    {"5/3 2 5|",    "Truncated Dodecadodecahedron",
                                "Medial Disdyakistriacontahedron",
                                "Icosahedral (I[9])",
                                "",
                                "",
                                75, 98},
 
-  /* 65 */     {"|5/3 2 5",    "Inverted Snub Dodecadodecahedron",
+  /* 128 */    {"|5/3 2 5",    "Inverted Snub Dodecadodecahedron",
                                "Medial Inverted Pentagonal Hexecontahedron",
                                "Icosahedral (I[9])",
                                "",
-                               "",
+                               "Kepler-Poinsot Solid",
                                76, 114},
                                                       /* (5/3 5/2 3) (I10a) */
 
-  /* 66 */     {"5/2 3|5/3",   "Great Dodecicosidodecahedron",
+  /* 130 */    {"5/2 3|5/3",   "Great Dodecicosidodecahedron",
                                "Great Dodecacronic Hexecontahedron",
                                "Icosahedral (I[10a])",
                                "",
                                "",
                                77, 99},
 
-  /* 67 */     {"5/3 5/2|3",   "Small Dodecahemicosahedron",
+  /* 132 */    {"5/3 5/2|3",   "Small Dodecahemicosahedron",
                                "Small Dodecahemicosacron",
                                "Icosahedral (I[10a])",
                                "",
                                "",
                                78, 100},
 
-  /* 68 */     {"5/3 5/2 3|",  "Great Dodecicosahedron",
+  /* 134 */    {"5/3 5/2 3|",  "Great Dodecicosahedron",
                                "Great Dodecicosacron",
                                "Icosahedral (I[10a])",
                                "",
                                "",
                                79, 101},
 
-  /* 69 */     {"|5/3 5/2 3",  "Great Snub Dodecicosidodecahedron",
+  /* 136 */    {"|5/3 5/2 3",  "Great Snub Dodecicosidodecahedron",
                                "Great Hexagonal Hexecontahedron",
                                "Icosahedral (I[10a])",
                                "",
-                               "",
+                               "Kepler-Poinsot Solid",
                                80, 115},
                                                         /* (5/4 3 5) (I10b) */
 
-  /* 70 */     {"5/4 5|3",     "Great Dodecahemicosahedron",
+  /* 138 */    {"5/4 5|3",     "Great Dodecahemicosahedron",
                                "Great Dodecahemicosacron",
                                "Icosahedral (I[10b])",
                                "",
@@ -734,28 +731,28 @@ static const struct {
                                81, 102},
                                                          /* (5/3 2 3) (I13) */
 
-  /* 71 */     {"2 3|5/3",     "Great Stellated Truncated Dodecahedron",
+  /* 140 */    {"2 3|5/3",     "Great Stellated Truncated Dodecahedron",
                                "Great Triakisicosahedron",
                                "Icosahedral (I[13])",
                                "",
                                "",
                                83, 104},
 
-  /* 72 */     {"5/3 3|2",     "Great Rhombicosidodecahedron",
+  /* 142 */    {"5/3 3|2",     "Great Rhombicosidodecahedron",
                                "Great Deltoidal Hexecontahedron",
                                "Icosahedral (I[13])",
                                "",
                                "",
                                84, 105},
 
-  /* 73 */     {"5/3 2 3|",    "Great Truncated Icosidodecahedron",
+  /* 144 */    {"5/3 2 3|",    "Great Truncated Icosidodecahedron",
                                "Great Disdyakistriacontahedron",
                                "Icosahedral (I[13])",
                                "",
                                "",
                                87, 108},
 
-  /* 74 */     {"|5/3 2 3",    "Great Inverted Snub Icosidodecahedron",
+  /* 146 */    {"|5/3 2 3",    "Great Inverted Snub Icosidodecahedron",
                                "Great Inverted Pentagonal Hexecontahedron",
                                "Icosahedral (I[13])",
                                "",
@@ -763,7 +760,7 @@ static const struct {
                                88, 116},
                                                     /* (5/3 5/3 5/2) (I18a) */
 
-  /* 75 */     {"5/3 5/2|5/3", "Great Dodecahemidodecahedron",
+  /* 148 */    {"5/3 5/2|5/3", "Great Dodecahemidodecahedron",
                                "Great Dodecahemidodecacron",
                                "Icosahedral (I[18a])",
                                "",
@@ -771,15 +768,15 @@ static const struct {
                                86, 107},
                                                       /* (3/2 5/3 3) (I18b) */
 
-  /* 76 */     {"3/2 3|5/3",   "Great Icosihemidodecahedron",
+  /* 150 */    {"3/2 3|5/3",   "Great Icosihemidodecahedron",
                                "Great Icosihemidodecacron",
                                "Icosahedral (I[18b])",
-                               "",
+                               "Kepler-Poinsot Solid",
                                "",
                                85, 106},
                                                      /* (3/2 3/2 5/3) (I22) */
 
-  /* 77 */     {"|3/2 3/2 5/2","Small Retrosnub Icosicosidodecahedron",
+  /* 152 */    {"|3/2 3/2 5/2","Small Retrosnub Icosicosidodecahedron",
                                "Small Hexagrammic Hexecontahedron",
                                "Icosahedral (I[22])",
                                "",
@@ -787,17 +784,17 @@ static const struct {
                                91, 118},
                                                        /* (3/2 5/3 2) (I23) */
 
-  /* 78 */     {"3/2 5/3 2|",  "Great Rhombidodecahedron",
+  /* 154 */    {"3/2 5/3 2|",  "Great Rhombidodecahedron",
                                "Great Rhombidodecacron",
                                "Icosahedral (I[23])",
                                "",
                                "",
                                89, 109},
 
-  /* 79 */     {"|3/2 5/3 2",  "Great Retrosnub Icosidodecahedron",
+  /* 156 */    {"|3/2 5/3 2",  "Great Retrosnub Icosidodecahedron",
                                "Great Pentagrammic Hexecontahedron",
                                "Icosahedral (I[23])",
-                               "",
+                               "Kepler-Poinsot Solid",
                                "",
                                90, 117},
 
@@ -805,7 +802,7 @@ static const struct {
    *           Last But Not Least
    ***************************************************************************/
 
-  /* 80 */    {"3/2 5/3 3 5/2",        "Great Dirhombicosidodecahedron",
+  /* 158 */    {"3/2 5/3 3 5/2",       "Great Dirhombicosidodecahedron",
                                "Great Dirhombicosidodecacron",
                                "Non-Wythoffian",
                                "",
@@ -817,7 +814,7 @@ static int last_uniform = sizeof (uniform) / sizeof (uniform[0]);
 
 
 
-static int unpacksym(char *sym, Polyhedron *P);
+static int unpacksym(const char *sym, Polyhedron *P);
 static int moebius(Polyhedron *P);
 static int decompose(Polyhedron *P);
 static int guessname(Polyhedron *P);
@@ -830,7 +827,8 @@ static int faces(Polyhedron *P);
 static int edgelist(Polyhedron *P);
 
 static Polyhedron *
-kaleido(char *sym, int need_coordinates, int need_edgelist, int need_approx,
+kaleido(const char *sym,
+        int need_coordinates, int need_edgelist, int need_approx,
        int just_list)
 {
   Polyhedron *P;
@@ -1016,7 +1014,7 @@ frac(double x)
  * allow no bars only if it result from the input symbol #80.
  */
 static int
-unpacksym(char *sym, Polyhedron *P)
+unpacksym(const char *sym, Polyhedron *P)
 {
   int i = 0, n, d, bars = 0;
   char c;
@@ -1381,7 +1379,7 @@ decompose(Polyhedron *P)
 }
 
 
-static int dihedral(Polyhedron *P, char *name, char *dual_name);
+static int dihedral(Polyhedron *P, const char *name, const char *dual_name);
 
 
 /*
@@ -1454,7 +1452,7 @@ guessname(Polyhedron *P)
 }
 
 static int
-dihedral(Polyhedron *P, char *name, char *dual_name)
+dihedral(Polyhedron *P, const char *name, const char *dual_name)
 {
   char *s;
   int i;
@@ -2037,7 +2035,8 @@ push_face4 (polyhedron *p, int x, int y, int z, int w)
 
 static polyhedron *
 construct_polyhedron (Polyhedron *P, Vector *v, int V, Vector *f, int F,
-                      char *name, char *dual, char *class, char *star,
+                      const char *name, const char *dual,
+                      const char *class, const char *star,
                       double azimuth, double elevation, double freeze)
 {
   int i, j, k=0, l, ll, ii, *hit=0, facelets;
index c99f50d92081e9d5215f535a3d84f0fec23ba8cc..4f401d50a3b9b9b14f45f3fe0976b67a00a0d343 100644 (file)
@@ -90,7 +90,8 @@ static const char sccsid[] = "@(#)polytopes.c  1.2 05/09/28 xlockmore";
 
 #ifdef STANDALONE
 # define DEFAULTS           "*delay:      25000 \n" \
-                            "*showFPS:    False \n"
+                            "*showFPS:    False \n" \
+                           "*suppressRotationAnimation: True\n" \
 
 # define refresh_polytopes 0
 # include "xlockmore.h"         /* from the xscreensaver distribution */
@@ -100,7 +101,7 @@ static const char sccsid[] = "@(#)polytopes.c  1.2 05/09/28 xlockmore";
 
 #ifdef USE_GL
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # include <X11/keysym.h>
 #endif
 #include "gltrackball.h"
@@ -2827,6 +2828,7 @@ static void display_polytopes(ModeInfo *mi)
   {
     gluPerspective(60.0,pp->aspect,0.1,100.0);
   }
+
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
 
index 10ca677859549befe42a51bc4d7643d488420e42..ac0cd5172079229fa0c94f66db456c2716572a4b 100644 (file)
@@ -227,7 +227,7 @@ static const char sccsid[] = "@(#)projectiveplane.c  1.1 14/01/01 xlockmore";
 
 #ifdef USE_GL
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # include <X11/keysym.h>
 #endif
 
index fcf8d316f540206ab8ed51cd1d07a1f09ba4e418..695ef7571ab170c77fb0453809da78466beb62c9 100644 (file)
@@ -767,6 +767,15 @@ ENTRYPOINT void draw_providence(ModeInfo * mi)
   gltrackball_rotate(mp->trackball);
   glRotatef(mp->theta * 180.0 / Pi, 0.0, -1.0, 0.0);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
   /* draw providence */
   draw_providence_strip(mi);
   glPopMatrix();
index e342b17f692724b7ef7110fd2a06f24f06de18ce..708794a6f7108be09ad54627ee85bcfc72f3fe7e 100644 (file)
@@ -22,6 +22,7 @@
                        "*contrast:     30          \n" \
                        "*showFPS:      False       \n" \
                        "*wireframe:    False       \n" \
+                       "*suppressRotationAnimation: True\n" \
 
 # define refresh_quasicrystal 0
 # define release_quasicrystal 0
index 67e668a3d26716c1c3f28f6f9fc2d54720579cf3..804d3a34f41984fba8df86b173f6759104cad3f8 100644 (file)
@@ -23,7 +23,6 @@ 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 "symmetric" option, above) or random. See also the
 "RD-Bomb", "CWaves" and "Penrose" screen savers.
-https://en.wikipedia.org/wiki/Quasicrystal
 .SH OPTIONS
 .TP 8
 .B \-visual \fIvisual\fP
index 71535c118c27944154a671095d81fb86fc0f1a70..ecada1d98c13513ae190d71c59fd3a3eaa1faef9 100644 (file)
@@ -29,7 +29,7 @@
 # include "xlock.h"
 #endif
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
 # include "jwxyz.h"
 #else
 # include <X11/Xlib.h>
@@ -412,7 +412,7 @@ static int drawBoard(Queenscreen *qs)
   return polys;
 }
 
-static int display(Queenscreen *qs) 
+static int display(ModeInfo *mi, Queenscreen *qs) 
 {
   int max = 1024;
   int polys = 0;
@@ -591,7 +591,7 @@ ENTRYPOINT void draw_queens(ModeInfo *mi)
   else
     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
 
-  mi->polygon_count = display(qs);
+  mi->polygon_count = display(mi, qs);
   mi->recursion_depth = qs->BOARDSIZE;
 
   if(mi->fps_p) do_fps(mi);
diff --git a/hacks/glx/raverhoop.c b/hacks/glx/raverhoop.c
new file mode 100644 (file)
index 0000000..9931067
--- /dev/null
@@ -0,0 +1,767 @@
+/* raverhoop, 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.
+ *
+ * Simulates an LED hula hoop in a dark room. Oontz oontz oontz.
+ */
+
+#define DEFAULTS       "*delay:        20000       \n" \
+                       "*ncolors:      12          \n" \
+                       "*showFPS:      False       \n" \
+                       "*wireframe:    False       \n" \
+
+# define refresh_hoop 0
+# define release_hoop 0
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+#include "xlockmore.h"
+#include "colors.h"
+#include "rotator.h"
+#include "gltrackball.h"
+#include <ctype.h>
+
+#ifdef USE_GL /* whole file */
+
+
+#define DEF_SPIN        "False"
+#define DEF_WANDER      "False"
+#define DEF_LIGHTS      "200"
+#define DEF_SPEED       "1.0"
+#define DEF_LIGHT_SPEED "1.0"
+#define DEF_SUSTAIN     "1.0"
+
+typedef struct {
+  GLfloat x,y,z;
+} XYZ;
+
+typedef struct afterimage afterimage;
+struct afterimage {
+  GLfloat color[4];
+  XYZ position;
+  afterimage *next;
+};
+
+typedef struct {
+  GLfloat color[4];
+  int duty_cycle[10];   /* off, on, off, on... values add to 100 */
+  GLfloat ratio;
+  Bool on;
+} light;
+
+
+typedef struct oscillator oscillator;
+struct oscillator {
+  GLfloat ratio, from, to, speed, *var;
+  int remaining;
+  oscillator *next;
+};
+
+
+typedef struct {
+  GLXContext *glx_context;
+  rotator *rot;
+  trackball_state *trackball;
+  Bool button_down_p;
+
+  int nlights;
+  light *lights;
+  GLfloat radius;
+  GLfloat axial_radius;
+  XYZ midpoint;
+  GLfloat tilt;
+  GLfloat spin;
+  GLfloat th;
+  GLfloat speed;
+  afterimage *trail;
+  oscillator *oscillators;
+
+} hoop_configuration;
+
+static hoop_configuration *bps = NULL;
+
+static Bool do_spin;
+static Bool do_wander;
+static int nlights;
+static GLfloat speed, light_speed, sustain;
+
+static XrmOptionDescRec opts[] = {
+  { "-spin",   ".spin",   XrmoptionNoArg, "True" },
+  { "+spin",   ".spin",   XrmoptionNoArg, "False" },
+  { "-wander", ".wander", XrmoptionNoArg, "True" },
+  { "+wander", ".wander", XrmoptionNoArg, "False" },
+  { "-lights", ".lights", XrmoptionSepArg, 0 },
+  { "-speed",  ".speed",  XrmoptionSepArg, 0 },
+  { "-light-speed", ".lightSpeed",  XrmoptionSepArg, 0 },
+  { "-sustain", ".sustain", XrmoptionSepArg, 0 },
+};
+
+static argtype vars[] = {
+  {&do_spin,   "spin",   "Spin",   DEF_SPIN,   t_Bool},
+  {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool},
+  {&nlights,   "lights", "Lights", DEF_LIGHTS, t_Int},
+  {&speed,     "speed",  "Speed",  DEF_SPEED,  t_Float},
+  {&light_speed, "lightSpeed", "Speed", DEF_LIGHT_SPEED, t_Float},
+  {&sustain,   "sustain", "Sustain",  DEF_SUSTAIN, t_Float},
+};
+
+ENTRYPOINT ModeSpecOpt hoop_opts = {countof(opts), opts, countof(vars), vars, NULL};
+
+
+static void
+decay_afterimages (ModeInfo *mi)
+{
+  hoop_configuration *bp = &bps[MI_SCREEN(mi)];
+  afterimage *prev = 0;
+  afterimage *a = bp->trail;
+  GLfloat tick = 0.05 / sustain;
+
+  while (a)
+    {
+      afterimage *next = a->next;
+      a->color[3] -= tick;
+      if (a->color[3] < 0)
+        {
+          if (prev)
+            prev->next = next;
+          else
+            bp->trail = next;
+          free (a);
+        }
+      else
+        prev = a;
+      a = next;
+    }
+}
+
+static void
+add_afterimage (ModeInfo *mi, GLfloat x, GLfloat y, GLfloat z,
+                GLfloat color[4])
+{
+  hoop_configuration *bp = &bps[MI_SCREEN(mi)];
+  afterimage *a = (afterimage *) calloc (1, sizeof (*a));
+  afterimage *b;
+  a->position.x = x;
+  a->position.y = y;
+  a->position.z = z;
+  memcpy (a->color, color, sizeof(a->color));
+
+  /* Put it at the end so that the older, dimmer ones are laid down on
+     the frame buffer before the newer, brighter ones. */
+  if (!bp->trail)
+    bp->trail = a;
+  else
+    {
+      for (b = bp->trail; b->next; b = b->next)
+        ;
+      b->next = a;
+    }
+}
+
+
+static void
+tick_light (light *L)
+{
+  int i;
+  int n = 0;
+
+  L->ratio += 0.05 * light_speed;
+  while (L->ratio > 1)
+    L->ratio -= 1;
+
+  for (i = 0; i < countof(L->duty_cycle); i++)
+    {
+      n += L->duty_cycle[i];
+      if (n > 100) abort();
+      if (n / 100.0 > L->ratio)
+        {
+          L->on = (i & 1);
+          break;
+        }
+    }
+}
+
+
+
+static void
+tick_hoop (ModeInfo *mi)
+{
+  hoop_configuration *bp = &bps[MI_SCREEN(mi)];
+  GLfloat m0[16];
+  int i;
+
+  glGetFloatv (GL_MODELVIEW_MATRIX, m0);
+
+  for (i = 0; i < bp->nlights; i++)
+    {
+      light *L = &bp->lights[i];
+      GLfloat m1[16];
+      GLfloat th = M_PI * 2 * i / bp->nlights;
+      GLfloat x = cos (th);
+      GLfloat y = sin (th);
+      GLfloat z;
+      
+      tick_light (L);
+      if (! L->on)
+        continue;
+
+      glPushMatrix();
+
+      glTranslatef (bp->midpoint.x, bp->midpoint.y, bp->midpoint.z);
+      glRotatef (bp->th * 180 / M_PI, 0, 0, 1);
+      glRotatef (bp->tilt, 0, 1, 0);
+      glRotatef (bp->spin, 1, 0, 0);
+      glTranslatef (x * bp->radius, y * bp->radius, 0);
+      glGetFloatv (GL_MODELVIEW_MATRIX, m1);
+      glPopMatrix();
+
+      /* After all of our translations and rotations, figure out where
+         it actually ended up.
+       */
+      x = m1[12] - m0[12];
+      y = m1[13] - m0[13];
+      z = m1[14] - m0[14];
+      add_afterimage (mi, x, y, z, L->color);
+    }
+}
+
+
+static void
+draw_lights (ModeInfo *mi)
+{
+  hoop_configuration *bp = &bps[MI_SCREEN(mi)];
+  int wire = MI_IS_WIREFRAME(mi);
+  afterimage *a;
+  GLfloat m[4][4];
+
+  if (wire)
+    {
+      int n = 360;
+      int i;
+      glPushMatrix();
+
+      glBegin (GL_LINES);
+      glVertex3f (0, 0, -bp->radius);
+      glVertex3f (0, 0,  bp->radius);
+      glEnd();
+
+      glTranslatef (bp->midpoint.x, bp->midpoint.y, bp->midpoint.z);
+      glRotatef (bp->th * 180 / M_PI, 0, 0, 1);
+      glRotatef (bp->tilt, 0, 1, 0);
+      glRotatef (bp->spin, 1, 0, 0);
+
+      glBegin (GL_LINE_LOOP);
+      glVertex3f (0, 0, 0);
+      for (i = 0; i <= n; i++)
+        {
+          GLfloat th = i * M_PI * 2 / n;
+          glVertex3f (bp->radius * -cos(th),
+                      bp->radius * -sin(th), 0);
+        }
+      for (i = 0; i <= n; i++)
+        {
+          GLfloat th = i * M_PI * 2 / n;
+          glVertex3f (bp->axial_radius * -cos(th),
+                      bp->axial_radius * -sin(th), 0);
+        }
+      glEnd();
+      glPopMatrix();
+    }
+
+  /* Billboard the lights to always face the camera */
+  glGetFloatv (GL_MODELVIEW_MATRIX, &m[0][0]);
+  m[0][0] = 1; m[1][0] = 0; m[2][0] = 0;
+  m[0][1] = 0; m[1][1] = 1; m[2][1] = 0;
+  m[0][2] = 0; m[1][2] = 0; m[2][2] = 1;
+  glLoadIdentity();
+  glMultMatrixf (&m[0][0]);
+
+  for (a = bp->trail; a; a = a->next)
+    {
+      glPushMatrix();
+
+      glTranslatef (a->position.x, a->position.y, a->position.z);
+
+      if (wire)
+        {
+          GLfloat c[3];
+          c[0] = a->color[0] * a->color[3];
+          c[1] = a->color[1] * a->color[3];
+          c[2] = a->color[2] * a->color[3];
+          glColor3fv (c);
+        }
+      else
+        glColor4fv (a->color);
+
+      glRotatef (45, 0, 0, 1);
+      glScalef (0.15, 0.15, 0.15);
+      glBegin (GL_QUADS);
+      glTexCoord2f (0, 0); glVertex3f (-1, -1, 0);
+      glTexCoord2f (1, 0); glVertex3f ( 1, -1, 0);
+      glTexCoord2f (1, 1); glVertex3f ( 1,  1, 0);
+      glTexCoord2f (0, 1); glVertex3f (-1,  1, 0);
+      glEnd();
+      mi->polygon_count++;
+
+      glPopMatrix();
+    }
+}
+
+
+static GLfloat
+ease_fn (GLfloat r)
+{
+  return cos ((r/2 + 1) * M_PI) + 1; /* Smooth curve up, end at slope 1. */
+}
+
+
+static GLfloat
+ease_ratio (GLfloat r)
+{
+  GLfloat ease = 0.35;
+  if      (r <= 0)     return 0;
+  else if (r >= 1)     return 1;
+  else if (r <= ease)  return     ease * ease_fn (r / ease);
+  else if (r > 1-ease) return 1 - ease * ease_fn ((1 - r) / ease);
+  else                 return r;
+}
+
+
+static void
+tick_oscillators (ModeInfo *mi)
+{
+  hoop_configuration *bp = &bps[MI_SCREEN(mi)];
+  oscillator *prev = 0;
+  oscillator *a = bp->oscillators;
+  GLfloat tick = 0.1 / speed;
+
+  while (a)
+    {
+      oscillator *next = a->next;
+      a->ratio += tick * a->speed;
+      if (a->ratio > 1)
+        a->ratio = 1;
+
+      *a->var = a->from + (a->to - a->from) * ease_ratio (a->ratio);
+
+      if (a->ratio < 1)                        /* mid cycle */
+        prev = a;
+      else if (--a->remaining <= 0)    /* ended, and expired */
+        {
+          if (prev)
+            prev->next = next;
+          else
+            bp->oscillators = next;
+          free (a);
+        }
+      else                             /* keep going the other way */
+        {
+          GLfloat swap = a->from;
+          a->from = a->to;
+          a->to = swap;
+          a->ratio = 0;
+          prev = a;
+        }
+
+      a = next;
+    }
+}
+
+
+static void
+calm_oscillators (ModeInfo *mi)
+{
+  hoop_configuration *bp = &bps[MI_SCREEN(mi)];
+  oscillator *a;
+  for (a = bp->oscillators; a && a->next; a = a->next)
+    a->remaining = 1;
+}
+
+
+static void
+add_oscillator (ModeInfo *mi, GLfloat *var, GLfloat speed, GLfloat to,
+                int repeat)
+{
+  hoop_configuration *bp = &bps[MI_SCREEN(mi)];
+  oscillator *a;
+
+  /* If an oscillator is already running on this variable, don't
+     add another. */
+  for (a = bp->oscillators; a && a->next; a = a->next)
+    if (a->var == var)
+      return;
+
+  a = (oscillator *) calloc (1, sizeof (*a));
+  if (repeat <= 0) abort();
+  a->ratio = 0;
+  a->from = *var;
+  a->to = to;
+  a->speed = speed;
+  a->var = var;
+  a->remaining = repeat;
+  a->next = bp->oscillators;
+  bp->oscillators = a;
+# if 0
+  fprintf (stderr, "%s: %3d %6.2f -> %6.2f %s\n",
+           progname, repeat, *var, to,
+           (var == &bp->midpoint.z ? "z" :
+            var == &bp->tilt ? "tilt" :
+            var == &bp->axial_radius ? "r" :
+            var == &bp->speed ? "speed" : "?"));
+# endif
+}
+
+
+static void
+add_random_oscillator (ModeInfo *mi)
+{
+  hoop_configuration *bp = &bps[MI_SCREEN(mi)];
+  int n = random() % 12;
+  switch (n) {
+  case 0: case 1: case 2:
+    add_oscillator (mi, &bp->midpoint.z, 1,
+                    bp->radius * (0.8 + frand(0.2))
+                    * (random() & 1 ? 1 : -1),
+                    (3 + (random() % 10)));
+    break;
+  case 3: case 4: case 5:
+    add_oscillator (mi, &bp->tilt, 1,
+                    -(GLfloat) (random() % 15),
+                    3 + (random() % 20));
+    break;
+  case 6: case 7: case 8:
+    add_oscillator (mi, &bp->axial_radius, 1,
+                    0.1 + bp->radius * frand(1.4),
+                    1 + (random() % 4));
+    break;
+  case 9: case 10:
+    add_oscillator (mi, &bp->speed, 3,
+                    (0.7 + frand(0.9)) * (random() & 1 ? 1 : -1),
+                    ((random() % 5)
+                     ? 1
+                     : 2 + (random() % 5)));
+    break;
+  case 11: 
+    add_oscillator (mi, &bp->spin, 0.1,
+                    180 * (1 + (random() % 2)),
+                    2 * (1 + (random() % 5)));
+    break;
+  default:
+    abort();
+    break;
+  }
+}
+
+
+static void
+randomize_colors (ModeInfo *mi)
+{
+  hoop_configuration *bp = &bps[MI_SCREEN(mi)];
+  int ncolors = MI_NCOLORS(mi);
+  GLfloat *colors;
+  int ncycles;
+  int i;
+
+  if (ncolors < 1)
+    ncolors = 1;
+  if (ncolors > bp->nlights)
+    ncolors = bp->nlights;
+
+  if (! (random() % 10))
+    ncolors = 1;
+
+  colors = calloc (ncolors, 4 * sizeof(*colors));
+  for (i = 0; i < ncolors; i++)
+    {
+      GLfloat *c = &colors[i * 4];
+# define QUANTIZE() (((random() % 16) << 4) | 0xF) / 255.0
+      c[0] = QUANTIZE();
+      c[1] = QUANTIZE();
+      c[2] = QUANTIZE();
+      c[3] = 1;
+    }
+
+  switch (random() % 5) {
+  case 0:  ncycles = 1; break;
+  case 2:  ncycles = ncolors * (1 + (random() % 5)); break;
+  default: ncycles = ncolors; break;
+  }
+
+  for (i = 0; i < bp->nlights; i++)
+    {
+      light *L = &bp->lights[i];
+      int n = i * ncolors / bp->nlights;
+      int m = i * ncycles / bp->nlights;
+      if (n >= ncolors) abort();
+      if (m >= ncycles) abort();
+      memcpy (L->color, &colors[n], sizeof (L->color));
+
+      if (ncycles <= 1)
+        {
+          L->duty_cycle[0] = 0;
+          L->duty_cycle[1] = 100;
+        }
+      else if (m & 1)
+        {
+          L->duty_cycle[0] = 50;
+          L->duty_cycle[1] = 50;
+        }
+      else
+        {
+          L->duty_cycle[0] = 0;
+          L->duty_cycle[1] = 50;
+          L->duty_cycle[2] = 50;
+        }
+    }
+  free (colors);
+}
+
+
+static void
+move_hoop (ModeInfo *mi)
+{
+  hoop_configuration *bp = &bps[MI_SCREEN(mi)];
+
+  bp->th += 0.2 * speed * bp->speed;
+  while (bp->th > M_PI*2)
+    bp->th -= M_PI*2;
+  while (bp->th < 0)
+    bp->th += M_PI*2;
+
+  bp->midpoint.x = bp->axial_radius * cos (bp->th);
+  bp->midpoint.y = bp->axial_radius * sin (bp->th);
+
+  tick_oscillators (mi);
+
+  if (! (random() % 80))
+    add_random_oscillator (mi);
+
+  if (! (random() % 120))
+    randomize_colors (mi);
+}
+
+
+static void
+build_texture (ModeInfo *mi)
+{
+  int x, y;
+  int size = 128;
+  int s2 = size / 2;
+  int bpl = size * 2;
+  unsigned char *data = malloc (bpl * size);
+
+  for (y = 0; y < size; y++)
+    {
+      for (x = 0; x < size; x++)
+        {
+          double dist = (sqrt (((s2 - x) * (s2 - x)) +
+                               ((s2 - y) * (s2 - y)))
+                         / s2);
+          unsigned char *c = &data [y * bpl + x * 2];
+          c[0] = 0xFF;
+          c[1] = 0xFF * sin (dist > 1 ? 0 : (1 - dist));
+        }
+    }
+
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+  glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+  glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
+  check_gl_error ("texture param");
+
+  glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, size, size, 0,
+                GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, data);
+  check_gl_error ("light texture");
+  free (data);
+}
+
+
+
+/* Window management, etc
+ */
+ENTRYPOINT void
+reshape_hoop (ModeInfo *mi, int width, int height)
+{
+  GLfloat h = (GLfloat) height / (GLfloat) width;
+
+  glViewport (0, 0, (GLint) width, (GLint) height);
+
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  gluPerspective (30.0, 1/h, 1.0, 100.0);
+
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+  gluLookAt( 0.0, 0.0, 30.0,
+             0.0, 0.0, 0.0,
+             0.0, 1.0, 0.0);
+
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
+  glClear(GL_COLOR_BUFFER_BIT);
+}
+
+
+ENTRYPOINT Bool
+hoop_handle_event (ModeInfo *mi, XEvent *event)
+{
+  hoop_configuration *bp = &bps[MI_SCREEN(mi)];
+
+  if (gltrackball_event_handler (event, bp->trackball,
+                                 MI_WIDTH (mi), MI_HEIGHT (mi),
+                                 &bp->button_down_p))
+    return True;
+  else if (event->xany.type == KeyPress)
+    {
+      KeySym keysym;
+      char c = 0;
+      XLookupString (&event->xkey, &c, 1, &keysym, 0);
+      if (c == ' ' || c == '\t')
+        {
+          randomize_colors (mi);
+          calm_oscillators (mi);
+          add_random_oscillator (mi);
+          return True;
+        }
+    }
+
+  return False;
+}
+
+
+ENTRYPOINT void 
+init_hoop (ModeInfo *mi)
+{
+  hoop_configuration *bp;
+  int wire = MI_IS_WIREFRAME(mi);
+
+  if (!bps) {
+    bps = (hoop_configuration *)
+      calloc (MI_NUM_SCREENS(mi), sizeof (hoop_configuration));
+    if (!bps) {
+      fprintf(stderr, "%s: out of memory\n", progname);
+      exit(1);
+    }
+  }
+
+  bp = &bps[MI_SCREEN(mi)];
+
+  bp->glx_context = init_GL(mi);
+
+  reshape_hoop (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+
+  glDisable (GL_LIGHTING);
+  glDisable (GL_DEPTH_TEST);
+  glEnable (GL_CULL_FACE);
+  glEnable (GL_NORMALIZE);
+  glEnable (GL_BLEND);
+  glBlendFunc (GL_SRC_ALPHA, GL_ONE);
+  glPolygonMode (GL_FRONT, GL_FILL);
+  glShadeModel (GL_FLAT);
+
+  if (! wire)
+    {
+      build_texture (mi);
+      glEnable (GL_TEXTURE_2D);
+    }
+
+  {
+    double spin_speed   = 0.3;
+    double wander_speed = 0.005;
+    double spin_accel   = 2.0;
+
+    bp->rot = make_rotator (do_spin ? spin_speed : 0,
+                            do_spin ? spin_speed : 0,
+                            do_spin ? spin_speed : 0,
+                            spin_accel,
+                            do_wander ? wander_speed : 0,
+                            False);
+    bp->trackball = gltrackball_init (True);
+  }
+
+  bp->radius = 30;
+  bp->axial_radius = bp->radius * 0.3;
+  bp->tilt = - (GLfloat) (5 + (random() % 12));
+  bp->speed = (random() % 1 ? 1 : -1);
+  bp->nlights = nlights;
+  bp->lights = (light *) calloc (bp->nlights, sizeof (*bp->lights));
+  randomize_colors (mi);
+  move_hoop (mi);
+  add_random_oscillator (mi);
+}
+
+
+ENTRYPOINT void
+draw_hoop (ModeInfo *mi)
+{
+  hoop_configuration *bp = &bps[MI_SCREEN(mi)];
+  Display *dpy = MI_DISPLAY(mi);
+  Window window = MI_WINDOW(mi);
+
+  if (!bp->glx_context)
+    return;
+
+  glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context));
+
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  glPushMatrix ();
+
+  {
+    double x, y, z;
+    get_position (bp->rot, &x, &y, &z, !bp->button_down_p);
+    glTranslatef((x - 0.5) * 7,
+                 (y - 0.5) * 0.5,
+                 (z - 0.5) * 15);
+
+    gltrackball_rotate (bp->trackball);
+    glRotatef (current_device_rotation(), 0, 0, 1);
+
+    get_rotation (bp->rot, &x, &y, &z, !bp->button_down_p);
+    glRotatef (x * 360, 1.0, 0.0, 0.0);
+    glRotatef (y * 360, 0.0, 1.0, 0.0);
+    glRotatef (z * 360, 0.0, 0.0, 1.0);
+  }
+
+  mi->polygon_count = 0;
+
+  glScalef (0.2, 0.2, 0.2);
+
+# ifdef HAVE_MOBILE
+  glScalef (0.7, 0.7, 0.7);
+# endif
+
+  glRotatef (70, 1, 0, 0);
+
+  if (! bp->button_down_p)
+    move_hoop (mi);
+
+  decay_afterimages (mi);
+  tick_hoop (mi);
+  draw_lights (mi);
+
+  glPopMatrix ();
+
+  if (mi->fps_p) do_fps (mi);
+  glFinish();
+
+  glXSwapBuffers(dpy, window);
+}
+
+XSCREENSAVER_MODULE_2 ("RaverHoop", raverhoop, hoop)
+
+#endif /* USE_GL */
diff --git a/hacks/glx/raverhoop.man b/hacks/glx/raverhoop.man
new file mode 100644 (file)
index 0000000..e7e70fa
--- /dev/null
@@ -0,0 +1,83 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+raverhoop - Simulates an LED hula hoop in a dark room.
+.SH SYNOPSIS
+.B raverhoop
+[\-display \fIhost:display.screen\fP]
+[\-visual \fIvisual\fP]
+[\-window]
+[\-root]
+[\-delay \fInumber\fP]
+[\-ncolors \fInumber\fP]
+[\-lights \fInumber\fP]
+[\-speed \fInumber\fP]
+[\-light-speed \fInumber\fP]
+[\-sustain \fInumber\fP]
+[\-no-wander]
+[\-no-spin]
+[\-fps]
+.SH DESCRIPTION
+Simulates an LED hula hoop in a dark room. Oontz oontz oontz.
+.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 \-ncolors \fInumber\fP
+The number of colors to use on the hoop.  Default: 12.
+.TP 8
+.B \-lights \fInumber\fP
+The number of LEDs comprising the hoop.  Default: 200.
+.TP 8
+.B \-speed \fInumber\fP
+Speed of the motion of the object.
+2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-light-speed \fInumber\fP
+Speed at which the lights animate.
+2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-sustain \fInumber\fP
+Speed at which the after-images / vapor trails fade away.
+2.0 means they last twice as long, 0.5 means half as long.
+.TP 8
+.B \-wander | \-no-wander
+Whether the object should wander around the screen.
+.TP 8
+.B \-spin | \-no-spin
+Whether the scene itself should spin.
+.TP 8
+.B \-fps | \-no-fps
+Whether to show a frames-per-second display at the bottom 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 2016 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 09a3ca73a61e996578e6fdadb84047f1f6c485fe..768e52bc25795c64137ff92d92222acf825473df 100644 (file)
@@ -213,7 +213,7 @@ static const char sccsid[] = "@(#)romanboy.c  1.1 14/10/03 xlockmore";
 
 #ifdef USE_GL
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # include <X11/keysym.h>
 #endif
 
@@ -767,8 +767,6 @@ static int roman_boy(ModeInfo *mi, double umin, double umax,
         continue;
       for (j=0; j<=numu; j++)
       {
-        l = i;
-        m = j;
         o = i*(numu+1)+j;
         u = ur*j/numu+umin;
         v = vr*i/numv+vmin;
index 89fa6ffd965566a1cef5aa4d224b27bd813698d6..ab0513073710d0cb795ce88b74c0232993c1a813 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1998-2002 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1998-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
 
 struct rotator {
 
-  double spin_x_speed, spin_y_speed, spin_z_speed;
+  double spin_x_speed, spin_y_speed, spin_z_speed; /* scaling factors >= 0. */
   double wander_speed;
 
-  double rotx, roty, rotz;        /* current object rotation */
-  double dx, dy, dz;              /* current rotational velocity */
-  double ddx, ddy, ddz;                   /* current rotational acceleration */
-  double d_max;                           /* max rotational velocity */
-
-  int wander_frame;               /* position in the wander cycle */
-
+  double rotx, roty, rotz;     /* current object rotation, -1 to +1.
+                                   Sign indicates direction of motion.
+                                   0.25 means +90 deg, positive velocity.
+                                   -0.25 means +90 deg, negative velocity
+                                   (not +270 deg or -90 deg!)
+                                   Yes, this is stupid.
+                                 */
+  double dx, dy, dz;           /* current rotational velocity, >= 0. */
+  double ddx, ddy, ddz;                /* current rotational acceleration, +/-. */
+  double d_max;                        /* max rotational velocity, > 0. */
+
+  int wander_frame;            /* position in the wander cycle, >= 0. */
 };
 
 
@@ -41,27 +46,44 @@ struct rotator {
 #define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3)
 #define RANDSIGN() ((random() & 1) ? 1 : -1)
 
+/* Stay in the range [0-1). 
+    1.01 => 0.01.
+   -0.01 => 0.99
+ */
+#define CLAMP(i) do {   \
+    while ((i) <  0) (i)++; \
+    while ((i) >= 1) (i)--; \
+  } while (0)
+
+#undef EPSILON
+#define EPSILON 0.000001
+
+
 static void
 rotate_1 (double *pos, double *v, double *dv, double speed, double max_v)
 {
+  /* Sign of *pos is direction of motion.
+     Sign of *v is always positive.
+     It would make way more sense for *v to indicate direction of motion.
+     What was I thinking?
+   */
+
   double ppos = *pos;
 
   if (speed == 0) return;
 
   /* tick position */
   if (ppos < 0)
+    /* Ignore but preserve the sign on ppos.  It's kind of like: 
+       ppos = old_sign * (abs(ppos) + (v * old_sign))
+       This is why it would make more sense for that sign bit to be on v.
+     */
     ppos = -(ppos + *v);
   else
     ppos += *v;
 
-  if (ppos > 1.0)
-    ppos -= 1.0;
-  else if (ppos < 0)
-    ppos += 1.0;
-
-  if (ppos < 0) abort();
-  if (ppos > 1.0) abort();
-  *pos = (*pos > 0 ? ppos : -ppos);
+  CLAMP (ppos);
+  *pos = (*pos > 0 ? ppos : -ppos);  /* preserve old sign bit on pos. */
 
   /* accelerate */
   *v += *dv;
@@ -72,24 +94,23 @@ rotate_1 (double *pos, double *v, double *dv, double speed, double max_v)
       *dv = -*dv;
     }
   /* If it stops, start it going in the other direction. */
+  /* Since *v is always positive, <= 0 means stopped. */
   else if (*v < 0)
     {
       if (random() % 4)
        {
-         *v = 0;
+         *v = 0;            /* don't let velocity be negative */
 
-         /* keep going in the same direction */
-         if (random() % 2)
+         if (random() % 2)  /* stay stopped, and kill acceleration */
            *dv = 0;
-         else if (*dv < 0)
+         else if (*dv < 0)  /* was decelerating, accelerate instead */
            *dv = -*dv;
        }
       else
        {
-         /* reverse gears */
-         *v = -*v;
-         *dv = -*dv;
-         *pos = -*pos;
+         *v = -*v;      /* switch to tiny positive velocity, or zero */
+         *dv = -*dv;    /* toggle acceleration */
+         *pos = -*pos;  /* reverse direction of motion */
        }
     }
 
@@ -100,8 +121,13 @@ rotate_1 (double *pos, double *v, double *dv, double speed, double max_v)
   /* Change acceleration very occasionally. */
   if (! (random() % 200))
     {
+#if 0 /* this might make more sense: */
+      if (*dv > -EPSILON && *dv < EPSILON)
+       *dv += 10 * (*dv < 0 ? -EPSILON : EPSILON);
+#else
       if (*dv == 0)
        *dv = 0.00001;
+#endif
       else if (random() & 1)
        *dv *= 1.2;
       else
@@ -149,6 +175,7 @@ make_rotator (double spin_x_speed,
 
   if (randomize_initial_state_p)
     {
+      /* Sign on position is direction of travel. Stripped before returned. */
       r->rotx = frand(1.0) * RANDSIGN();
       r->roty = frand(1.0) * RANDSIGN();
       r->rotz = frand(1.0) * RANDSIGN();
@@ -213,9 +240,9 @@ get_rotation (rotator *rot, double *x_ret, double *y_ret, double *z_ret,
   x = rot->rotx;
   y = rot->roty;
   z = rot->rotz;
-  if (x < 0) x = 1 - (x + 1);
-  if (y < 0) y = 1 - (y + 1);
-  if (z < 0) z = 1 - (z + 1);
+  if (x < 0) x = -x;
+  if (y < 0) y = -y;
+  if (z < 0) z = -z;
 
   if (x_ret) *x_ret = x;
   if (y_ret) *y_ret = y;
index 99641c097f1b128a0c0b0b722995cb0158e7d9bc..0cc99019ebc19ab8dc4970a6f2ee9e127117f28e 100644 (file)
@@ -109,7 +109,9 @@ static const char sccsid[] = "@(#)rubik.c   5.01 2001/03/01 xlockmore";
                                        "*count: -30 \n"                \
                                        "*showFPS: False \n"    \
                                        "*cycles: 20 \n"                \
-                                       "*size:  -6 \n"
+                                       "*size:  -6 \n"         \
+                                       "*suppressRotationAnimation: True\n" \
+
 # define refresh_rubik 0
 # include "xlockmore.h"                                /* from the xscreensaver distribution */
 #else /* !STANDALONE */
@@ -471,6 +473,7 @@ faceSizes(rubikstruct * rp, int face, int * sizeOfRow, int * sizeOfColumn)
                        *sizeOfRow = MAXSIZEX;
                        *sizeOfColumn = MAXSIZEY;
                        break;
+                default: abort();
        }
 }
 
@@ -1816,7 +1819,6 @@ reshape_rubik(ModeInfo * mi, int width, int height)
        glLoadIdentity();
        glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0);
        glMatrixMode(GL_MODELVIEW);
-
 }
 
 ENTRYPOINT Bool
@@ -2007,6 +2009,18 @@ draw_rubik(ModeInfo * mi)
                glScalef(Scale4Iconic * rp->WindH / rp->WindW, Scale4Iconic, Scale4Iconic);
        }
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180) {
+      glScalef (1/h, h, 1); /* #### not quite right */
+      h = 1.8;
+      glScalef (h, h, h);
+    }
+  }
+# endif
+
     gltrackball_rotate (rp->trackball);
 
        glRotatef(rp->step * 100, 1, 0, 0);
index 14872367e3dbcdf7208a35aa1d9c5ea1e19dd9a1..71682fc3f738039e7cc6cfcc495320438e828b53 100644 (file)
@@ -19,7 +19,8 @@
 
 #define DEFAULTS   "*delay:         20000         \n" \
                    "*showFPS:       False         \n" \
-                   "*wireframe:     False         \n"
+                   "*wireframe:     False         \n" \
+                  "*suppressRotationAnimation: True\n" \
 
 # define refresh_rubikblocks 0
 #include "xlockmore.h"
@@ -259,6 +260,7 @@ draw_main(ModeInfo *mi, rubikblocks_conf *cp)
 
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   glLoadIdentity();
+
   get_position(cp->rot, &x, &y, &z, !cp->button_down);
   glTranslatef((x-0.5)*6, (y-0.5)*6, -20);
 
@@ -270,6 +272,15 @@ draw_main(ModeInfo *mi, rubikblocks_conf *cp)
   glRotatef(z*360, 0, 0, 1);
   glScalef(size, size, size);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
   if(cp->wire) glColor3f(0.7, 0.7, 0.7);
   if(!cp->pause)
     for(i = 0; i < 27; i++)
index 87a17d23713a29816873b2469314ef50d5078a61..4e731ea2ba932568d02f244123794200e237a7e8 100644 (file)
@@ -564,7 +564,7 @@ static void Draw(ModeInfo * mi)
        glColor3f(0, 0, 0);
     }
     glBegin(GL_QUAD_STRIP);
-#ifndef USE_IPHONE
+#ifndef HAVE_MOBILE
     /* Letterbox the background image */
     glNormal3f(0, 0, 1); glTexCoord2f(0,0); glVertex3f(8, 4.1, -4);
     glNormal3f(0, 0, 1); glTexCoord2f(0,1); glVertex3f(8, -4.1, -4);
@@ -597,8 +597,8 @@ static void Draw(ModeInfo * mi)
     if (do_texture)
 #ifdef HAVE_GLBINDTEXTURE
        glBindTexture(GL_TEXTURE_2D, sb->faceid);
-#endif /* HAVE_GLBINDTEXTURE */
     else
+#endif /* HAVE_GLBINDTEXTURE */
        glEnable(GL_LIGHTING);
     for (sphere=0;sphere<spheres;sphere++)
     {
index 7b74d5a58aff732bafbb9e3c72cfcecdec983982..5be6862cd7c5e2dc50b9de3d20c83cd1cd4f783f 100644 (file)
@@ -30,6 +30,7 @@ static const char sccsid[] = "@(#)sierpinski3D.c      00.01 99/11/04 xlockmore";
 # define DEFAULTS                                      "*delay:                20000   \n"                     \
                                                                        "*showFPS:      False   \n"                     \
                                                                        "*wireframe:    False   \n"                     \
+                                                                       "*suppressRotationAnimation: True\n" \
 
 # define refresh_gasket 0
 # include "xlockmore.h"                /* from the xscreensaver distribution */
@@ -396,6 +397,14 @@ reshape_gasket(ModeInfo *mi, int width, int height)
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);
   
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
   glClear(GL_COLOR_BUFFER_BIT);
 }
 
index 50861259e768e8bca7305d37db57c9b33ecf2da6..253cb8eb8d41e6fb60d9967bfd46d2096b549677 100644 (file)
@@ -40,7 +40,7 @@
   */
 #endif
 
-#ifndef USE_IPHONE
+#ifndef HAVE_MOBILE
 # define READ_FILES
 #endif
 
@@ -53,7 +53,9 @@
 # include <sys/types.h>
 # include <sys/time.h>
 # include <sys/ipc.h>
-# include <sys/shm.h>
+# ifndef HAVE_ANDROID
+#  include <sys/shm.h>
+# endif
 # include <sys/socket.h>
 # include <netinet/in_systm.h>
 # include <netinet/in.h>
@@ -88,7 +90,7 @@
 # undef HAVE_PING
 #endif
 
-#ifndef USE_IPHONE
+#ifndef HAVE_MOBILE
 # define LOAD_FILES
 #endif
 
@@ -448,7 +450,7 @@ read_hosts_file (sonar_sensor_data *ssd, const char *filename)
     {
       char buf[1024];
       sprintf(buf, "%s:  %s", progname, filename);
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
       if (pd->debug_p)  /* on OSX don't syslog this */
 #endif
         perror (buf);
@@ -1410,7 +1412,7 @@ ping_scan (sonar_sensor_data *ssd)
 
           if (sb && !pb->lookup_addr)
             {
-              assert (pb->addrlen);
+              if (!pb->addrlen) abort();
               send_ping (pd, sb);
               pd->last_pinged = sb;
             }
index 3690c88e0ae1a63fc87fdd33c03fb404c0c2dc59..70b7ff6eb19486861c214e72f6057bb83facbd28 100644 (file)
@@ -63,6 +63,7 @@
 #define DEFAULTS "*delay:      30000       \n" \
                 "*showFPS:     False       \n" \
                 "*wireframe:   False       \n" \
+                "*suppressRotationAnimation: True\n" \
         "*labelfont:   -*-helvetica-medium-r-normal-*-*-180-*-*-*-*-*-*\n"
 
 # define refresh_spheremonics 0
@@ -178,6 +179,14 @@ reshape_spheremonics (ModeInfo *mi, int width, int height)
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+
+# endif
   glClear(GL_COLOR_BUFFER_BIT);
 }
 
index 8a0df74cc97921694add922e0265ea216a1e67d9..922417545697afe9ac44d11c485523f20aa8fde3 100644 (file)
@@ -213,6 +213,14 @@ reshape_splitflap (ModeInfo *mi, int width, int height)
              0, 0, 0,
              0, 1, 0);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (h, h, h);
+  }
+# endif
+
   glClear(GL_COLOR_BUFFER_BIT);
 }
 
@@ -1362,7 +1370,7 @@ draw_splitflap (ModeInfo *mi)
                  ? grid_width * r
                  : grid_height);
     GLfloat s = 8;
-# ifdef USE_IPHONE
+# ifdef HAVE_MOBILE
     s *= 2; /* #### What. Why is this necessary? */
 #endif
     s /= cells;
index 11bbcf5f1a4e9b7721dba31738106c31009f1b16..4752d41d79a59a0c00ff58636d7d062e85169be5 100644 (file)
@@ -36,7 +36,7 @@ static const char sccsid[] = "@(#)sproingies.c        4.04 97/07/28 xlockmore";
 
 #ifdef USE_GL
 
-#if !defined(HAVE_COCOA) && !defined(HAVE_ANDROID)
+#if !defined(HAVE_JWZGLES) && !defined(HAVE_COCOA)
 # include <GL/glu.h>
 #endif
 
@@ -764,6 +764,9 @@ void
 CleanupSproingies(int screen)
 {
        sp_instance *si = &si_list[screen];
+
+    if (! si) return;
+
 /*
        int         t;
        if (si->SproingieBoom) {
@@ -808,6 +811,9 @@ InitSproingies(int wfmode, int grnd, int mspr, int smrtspr,
        sp_instance *si;
        int         t;
 
+       active_screens++;
+       CleanupSproingies(screen);
+
        if (si_list == NULL) {
                if ((si_list = (sp_instance *) calloc(numscreens,
                                              sizeof (sp_instance))) == NULL)
@@ -815,9 +821,6 @@ InitSproingies(int wfmode, int grnd, int mspr, int smrtspr,
        }
        si = &si_list[screen];
 
-       active_screens++;
-       CleanupSproingies(screen);
-
        if (mspr < 0)
                mspr = 0;
        if (mspr >= MAXSPROING)
index 7fabea1ad32f61af464600e32f1879f7215fd976..91f40ac46a919853c077b3b7b11a33d8ab398dce 100644 (file)
@@ -482,12 +482,6 @@ draw_stairs (ModeInfo * mi)
        glPushMatrix();
 
     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.0, 0.0, -10.0);
 
@@ -497,6 +491,14 @@ draw_stairs (ModeInfo * mi)
                glScalef(Scale4Iconic * sp->WindH / sp->WindW, Scale4Iconic, Scale4Iconic);
        }
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+    if (rot != 0 && rot != 180 && rot != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
     gltrackball_rotate (sp->trackball);
 
     glTranslatef(0, 0.5, 0);
index f4a5850380eddb9bc71341f746efa41578e5fd37..a726bb300a006840e5aaaed5db4b88575d70b9a1 100644 (file)
@@ -86,7 +86,7 @@
 #define MAX_THICK_LINES   25
 #define FONT_WEIGHT       14
 
-#ifndef USE_IPHONE
+#ifndef HAVE_MOBILE
 # define KEEP_ASPECT   /* Letterboxing looks dumb on iPhone. */
 #endif
 
@@ -283,7 +283,6 @@ get_more_lines (sws_configuration *sc)
 {
   /* wrap anyway, if it's absurdly long. */
   int wrap_pix = (wrap_p ? sc->line_pixel_width : 10000);
-  int col_pix = 0;
 
   char *s = sc->buf;
 
@@ -410,7 +409,6 @@ get_more_lines (sws_configuration *sc)
 
               sc->buf[sc->buf_tail] = 0;
               s = sc->buf;
-              col_pix = 0;
 
               break;
             }
@@ -620,9 +618,11 @@ reshape_sws (ModeInfo *mi, int width, int height)
     }
 #endif
 
-    glMatrixMode (GL_PROJECTION);
     glViewport (0, yoff, w, h);
 
+    glMatrixMode (GL_PROJECTION);
+    glLoadIdentity();
+
     glMatrixMode (GL_MODELVIEW);
     glLoadIdentity ();
     gluPerspective (80.0, 1/desired_aspect, 1000, 55000);
@@ -630,8 +630,6 @@ reshape_sws (ModeInfo *mi, int width, int height)
                0.0, 0.0, 0.0,
                0.0, 1.0, 0.0);
 
-    glRotatef(rot, 0, 0, 1);
-
     /* Horrible kludge to prevent the text from materializing already
        on screen on iPhone in landscape mode.
      */
@@ -877,9 +875,6 @@ draw_stars (ModeInfo *mi)
       glRotatef (sc->star_theta, 0.0, 0.0, 1.0);
       if (textures_p) glDisable (GL_TEXTURE_2D);
 
-      /* Keep the stars pointing in the same direction after rotation */
-      glRotatef(current_device_rotation(), 0, 0, 1);
-
       glCallList (sc->star_list);
       if (textures_p) glEnable (GL_TEXTURE_2D);
     }
@@ -911,7 +906,7 @@ draw_sws (ModeInfo *mi)
   glMatrixMode (GL_MODELVIEW);
   glPushMatrix ();
 
-# ifdef USE_IPHONE
+# ifdef HAVE_MOBILE
   /* Need to do this every time to get device rotation right */
   reshape_sws (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
 # endif
index e504709d7b7e0dcff8dd9583b86a4b8f1f10e4b7..7e150b3963bf84a15f53b9611b7a79c933d4517b 100644 (file)
@@ -114,6 +114,15 @@ draw_stonerview (ModeInfo *mi)
   glRotatef( current_device_rotation(), 0, 0, 1);
   gltrackball_rotate (bp->trackball);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (h, h, h);
+  }
+# endif
+
   stonerview_win_draw(bp->st);
   if (! bp->button_down_p)
     stonerview_move_increment(bp->st);
index f52cc6b28e11f7e8a7162c37bbd47a6ea4f77bbc..9293218f2f56c5ba11da0802896707fcf019dbc6 100644 (file)
@@ -75,7 +75,8 @@ static const char sccsid[] = "@(#)superquadrics.c     4.07 97/11/24 xlockmore";
                                        "*count:                25      \n"                     \
                                        "*cycles:               40      \n"                     \
                                        "*showFPS:      False   \n"                     \
-                                       "*wireframe:    False   \n"
+                                       "*wireframe:    False   \n"                     \
+                                       "*suppressRotationAnimation: True\n" \
 
 # define superquadrics_handle_event 0
 # include "xlockmore.h"                                /* from the xscreensaver distribution */
@@ -547,8 +548,9 @@ NextSuperquadric(superquadricsstruct * sp)
 }
 
 static int
-DisplaySuperquadrics(superquadricsstruct * sp)
+DisplaySuperquadrics(ModeInfo *mi)
 {
+       superquadricsstruct *sp = &superquadrics[MI_SCREEN(mi)];
     int polys = 0;
        glDrawBuffer(GL_BACK);
        if (sp->wireframe)
@@ -569,6 +571,16 @@ DisplaySuperquadrics(superquadricsstruct * sp)
        SetCull(0, sp);
 
     glScalef(0.7, 0.7, 0.7);  /* jwz: scale it down a bit */
+
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
        polys = DoneScale(sp);
 
        glPopMatrix();
@@ -578,10 +590,11 @@ DisplaySuperquadrics(superquadricsstruct * sp)
 }
 
 static int
-NextSuperquadricDisplay(superquadricsstruct * sp)
+NextSuperquadricDisplay(ModeInfo *mi)
 {
+       superquadricsstruct *sp = &superquadrics[MI_SCREEN(mi)];
        NextSuperquadric(sp);
-       return DisplaySuperquadrics(sp);
+       return DisplaySuperquadrics(mi);
 }
 
 #define MINSIZE 200
@@ -740,7 +753,7 @@ init_superquadrics(ModeInfo * mi)
                                  MI_COUNT(mi), MI_CYCLES(mi), spinspeed, sp);
                ReshapeSuperquadrics(MI_WIDTH(mi), MI_HEIGHT(mi));
 
-               DisplaySuperquadrics(sp);
+               DisplaySuperquadrics(mi);
                glFinish();
                glXSwapBuffers(display, window);
        } else {
@@ -760,7 +773,7 @@ draw_superquadrics(ModeInfo * mi)
 
        glXMakeCurrent(display, window, *(sp->glx_context));
 
-    mi->polygon_count = NextSuperquadricDisplay(sp);
+    mi->polygon_count = NextSuperquadricDisplay(mi);
 
     if (mi->fps_p) do_fps (mi);
        glFinish();
index ddca134794a17cb9e54220daf22188350671795b..9ea84cddfa07cd12ad4f10413e24efc448f1b6cc 100644 (file)
@@ -43,7 +43,8 @@
 
 #ifdef STANDALONE
 # define DEFAULTS                   "*delay:        20000   \n" \
-                                    "*showFPS:      False   \n"
+                                    "*showFPS:      False   \n" \
+                                  "*suppressRotationAnimation: True\n" \
 
 # define refresh_surface 0
 # include "xlockmore.h"     /* from the xscreensaver distribution */
@@ -428,6 +429,14 @@ ENTRYPOINT void reshape_surface(ModeInfo *mi, int width, int height)
   glLoadIdentity();
   gluLookAt(0.0, 0.0, 30.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
     
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
   glClear(GL_COLOR_BUFFER_BIT);
 }
 
index 8fab0493efbbf2f903d61718900dd1db5a4c3ad6..c084af588b586fcab6af76f1972cbd11db9ee14d 100644 (file)
@@ -742,6 +742,15 @@ static void draw_shapes(ModeInfo * mi)
 {
     tangram_configuration *tp = &tps[MI_SCREEN(mi)];
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+    {
+      GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+      int o = (int) current_device_rotation();
+      if (o != 0 && o != 180 && o != -180)
+        glScalef (h, 1/h, 1);
+    }
+# endif
+
     draw_tangram_shape(tp->tsm1);
 
     draw_tangram_shape(tp->tsm2);
@@ -768,23 +777,9 @@ static void draw_shapes(ModeInfo * mi)
       }
 }
 
-static void set_perspective(void)
-{
-    glPushMatrix();
-    glMatrixMode(GL_PROJECTION);
-    glLoadIdentity();
-    gluPerspective(60, -1, 0.1, 50);
-    gluLookAt(0, 5, -5, 0, 0, 0, 0, -1, 0);
-    glMatrixMode(GL_MODELVIEW);
-    glPopMatrix();
-
-}
-
 ENTRYPOINT void reshape_tangram(ModeInfo * mi, int w, int h)
 {
     glViewport(0, 0, w, h);
-    set_perspective();
-    glLoadIdentity();
 }
 
 static void set_camera(tangram_configuration *tp)
index 19f065b056f2dd43be07047bf255d1d2c1cf3ace..267b1873b3e154103790cb31ee4488a793ddbbf4 100644 (file)
 # include "config.h"
 #endif /* HAVE_CONFIG_H */
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # include <GL/gl.h>
 #endif
 
+#ifdef HAVE_ANDROID
+#include <GLES/gl.h>
+#endif
+
 #ifdef HAVE_JWZGLES
 # include "jwzgles.h"
 #endif /* HAVE_JWZGLES */
index 05d652ed11e121ce03121dcba052f0ff2aa0fdb7..c885d27be725454faf6d1ea81db06781e9e94d84 100644 (file)
@@ -50,9 +50,12 @@ OpenGL(TM) is a trademark of Silicon Graphics, Inc.
 
 #include "teapot.h"
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # include <GL/gl.h>
 #endif
+#ifdef HAVE_ANDROID
+# include <GLES/gl.h>
+#endif
 
 #ifdef HAVE_JWZGLES
 # include "jwzgles.h"
index a88b6216cdb0c38b0a9ac4efec2fe6ab179f5b1b..7daa2d50d43746c62975001e3f4acbff086df094 100644 (file)
@@ -1,4 +1,4 @@
-/* texfonts, Copyright (c) 2005-2015 Jamie Zawinski <jwz@jwz.org>
+/* texfonts, Copyright (c) 2005-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
@@ -193,7 +193,7 @@ bitmap_to_texture (Display *dpy, Pixmap p, Visual *visual, int depth,
 
 # ifdef DUMP_BITMAPS
       if (sx < ow && sy < oh)
-#  ifdef HAVE_COCOA
+#  ifdef HAVE_JWXYZ
         fprintf (stderr, "%c", 
                  r >= 0xFF000000 ? '#' : 
                  r >= 0x88000000 ? '%' : 
@@ -485,6 +485,7 @@ get_cache (texture_font_data *data, const char *string)
    */
   if (count > data->cache_size)
     {
+      if (!prev) abort();
       free (prev->string);
       prev->string     = 0;
       prev->tex_width  = 0;
@@ -805,7 +806,8 @@ print_texture_label (Display *dpy,
       XCharStruct cs;
       int ascent, descent;
       int x, y, w, h, swap;
-      int rot = (int) current_device_rotation();
+      /* int rot = (int) current_device_rotation(); */
+      int rot = 0;  /* Since GL hacks rotate now */
 
       glLoadIdentity();
       glViewport (0, 0, window_width, window_height);
@@ -821,7 +823,9 @@ print_texture_label (Display *dpy,
 # ifdef USE_IPHONE
       {
         /* Size of the font is in points, so scale iOS pixels to points. */
-        GLfloat scale = window_width / 768.0;
+        GLfloat scale = ((window_width > window_height
+                          ? window_width : window_height)
+                         / 768.0);
         if (scale < 1) scale = 1;
 
         /* jwxyz-XLoadFont has already doubled the font size, to compensate
@@ -919,6 +923,17 @@ print_texture_label (Display *dpy,
 }
 
 
+#ifdef HAVE_JWXYZ
+char *
+texfont_unicode_character_name (texture_font_data *data, unsigned long uc)
+{
+  Font fid = data->xftfont->xfont->fid;
+  return jwxyz_unicode_character_name (fid, uc);
+}
+#endif /* HAVE_JWXYZ */
+
+
+
 /* Releases the font and texture.
  */
 void
index 7fbdb786bc6b7e1b082903400c09384b44f8adb7..8f86dab21b3bdd53bccfbd129af4729a37732647 100644 (file)
@@ -1,4 +1,4 @@
-/* texfonts, Copyright (c) 2005-2015 Jamie Zawinski <jwz@jwz.org>
+/* texfonts, Copyright (c) 2005-2016 Jamie Zawinski <jwz@jwz.org>
  * Loads X11 fonts into textures for use with OpenGL.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -62,4 +62,11 @@ void enable_texture_string_parameters (void);
  */
 extern void free_texture_font (texture_font_data *);
 
+
+#ifdef HAVE_JWXYZ
+extern char *texfont_unicode_character_name (texture_font_data *,
+                                             unsigned long uc);
+#endif
+
+
 #endif /* __TEXTURE_FONT_H__ */
index 1b18a54715ab1be0a7cee516d33634d32b1907a6..eed2fd54f775fa0522bbb19a2fcf54ed88613b02 100644 (file)
@@ -47,7 +47,7 @@ History
 
 #ifdef USE_GL /* whole file */
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # include <GL/glu.h>
 #endif
 
@@ -327,6 +327,15 @@ draw_topBlock (ModeInfo *mi)
        /* rotate the world */
        glRotatef(tb->rotation, 0.0, 0.0, 1.0);         
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+        {
+          GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+          int o = (int) current_device_rotation();
+          if (o != 0 && o != 180 && o != -180)
+            glScalef (1/h, 1/h, 1/h);
+        }
+# endif
+
        llCurrent = tb->blockNodeRoot;
        if (drawCarpet) {
                /* center carpet */
index 3c82428136a347681f5b1f70416c673bc776a2d4..2571964ff82e2159cd749027ba3b3045b1105b3d 100644 (file)
@@ -301,7 +301,7 @@ draw_histogram (ModeInfo *mi, GLfloat ratio)
     glPushMatrix();
 
     glLoadIdentity();
-    glRotatef(current_device_rotation(), 0, 0, 1);
+    /* glRotatef(current_device_rotation(), 0, 0, 1); */
     glOrtho (0, mi->xgwa.width, 0, mi->xgwa.height, -1, 1);
 
     for (k = 0; k < overlays; k++)
@@ -483,9 +483,18 @@ draw_bit (ModeInfo *mi)
     }
 
   glPushMatrix ();
-  glRotatef(current_device_rotation(), 0, 0, 1);
   glScalef(1.1, 1.1, 1.1);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+    glRotatef(o, 0, 0, 1);
+  }
+# endif
+
   {
     double x, y, z;
     get_position (bp->rot, &x, &y, &z, !bp->button_down_p);
index 333161bb5d50ef3e71187288f6783efebfb78627..8a87c7673d5bc142b764802b3adc920595020a0f 100644 (file)
@@ -45,11 +45,15 @@ static const char sccsid[] = "@(#)tunnel_draw.c     5.13 2004/05/25 xlockmore";
 #include <math.h>
 
 #ifdef STANDALONE
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
 #  include <GL/gl.h>
 #  include <GL/glu.h>
 # endif
 #endif
+#ifdef HAVE_ANDROID
+#include <GLES/gl.h>
+#endif
+
 
 #include "tunnel_draw.h"
 
@@ -240,7 +244,7 @@ atunnel_DrawTunnel(struct tunnel_state *st,
                 int do_texture, int do_light, GLuint *textures)
 {
        tnPath *p, *p1, *cmpos;
-       cvPoint op, p4[4], T, ppp, ppp1, op1, op2;
+       cvPoint op, p4[4], T, ppp, op1, op2;
        float t;
        int i, j, k, flag;
        cvPoint points[10];
@@ -387,10 +391,6 @@ atunnel_DrawTunnel(struct tunnel_state *st,
                        
                cvCatmullRom(p4, t, &op1);
 
-               ppp1.x = op1.x;
-               ppp1.y = op1.y;
-               ppp1.z = op1.z + 0.25;
-
                T.x = op1.x - op.x;
                T.y = op1.y - op.y;
                T.z = op1.z - op.z;
diff --git a/hacks/glx/unicrud.c b/hacks/glx/unicrud.c
new file mode 100644 (file)
index 0000000..6a42a27
--- /dev/null
@@ -0,0 +1,956 @@
+/* unicrud, 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.
+ */
+
+#define DEFAULTS       "*delay:        20000       \n" \
+                       "*showFPS:      False       \n" \
+                       "*suppressRotationAnimation: True\n" \
+       "*titleFont: -*-helvetica-bold-r-normal-*-*-180-*-*-*-*-*-*\n" \
+       "*font:      -*-helvetica-bold-r-normal-*-*-2400-*-*-*-*-iso10646-1\n" \
+
+# define refresh_unicrud 0
+# define release_unicrud 0
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+#include "xlockmore.h"
+#include "rotator.h"
+#include "gltrackball.h"
+#include "texfont.h"
+#include "utf8wc.h"
+#include <ctype.h>
+
+#ifdef USE_GL /* whole file */
+
+#define DEF_SPIN        "True"
+#define DEF_WANDER      "True"
+#define DEF_SPEED       "1.0"
+#define DEF_BLOCK       "ALL"
+
+typedef struct {
+  GLXContext *glx_context;
+  rotator *rot;
+  trackball_state *trackball;
+  Bool button_down_p;
+
+  GLfloat color[4];
+  texture_font_data *title_font, *char_font;
+  unsigned long unichar;
+  const char *charplane, *charblock, *charname;
+  enum { IN, LINGER, OUT } state;
+  int spin_direction;
+  GLfloat ratio;
+
+} unicrud_configuration;
+
+static unicrud_configuration *bps = NULL;
+
+static Bool do_spin;
+static GLfloat speed;
+static Bool do_wander;
+static char *do_block;
+
+static XrmOptionDescRec opts[] = {
+  { "-spin",   ".spin",   XrmoptionNoArg, "True" },
+  { "+spin",   ".spin",   XrmoptionNoArg, "False" },
+  { "-wander", ".wander", XrmoptionNoArg, "True" },
+  { "+wander", ".wander", XrmoptionNoArg, "False" },
+  { "-speed",  ".speed",  XrmoptionSepArg, 0 },
+  { "-block",  ".block",  XrmoptionSepArg, 0 },
+};
+
+static argtype vars[] = {
+  {&do_spin,   "spin",   "Spin",   DEF_SPIN,   t_Bool},
+  {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool},
+  {&speed,     "speed",  "Speed",  DEF_SPEED,  t_Float},
+  {&do_block,  "block",  "Block",  DEF_BLOCK,  t_String},
+};
+
+ENTRYPOINT ModeSpecOpt unicrud_opts = {countof(opts), opts, countof(vars), vars, NULL};
+
+static const struct {
+  unsigned long start;
+  const char * const name;
+} unicode_block_names[] = {
+
+  /* Through Unicode 8.0, early 2016. */
+
+  { 0x0000, "*Basic Multilingual" },
+  { 0x0000, "Unassigned" },
+  { 0x0021, "ASCII" },
+  { 0x0080, "Unassigned" },
+  { 0x00A1, "Latin1" },
+  { 0x0100, "Latin Extended-A" },
+  { 0x0180, "Latin Extended-B" },
+  { 0x0250, "IPA Extensions" },
+  { 0x02B0, "Spacing Modifier Letters" },
+  { 0x0300, "Combining Diacritical Marks" },
+  { 0x0370, "Greek and Coptic" },
+  { 0x0400, "Cyrillic" },
+  { 0x0500, "Cyrillic Supplement" },
+  { 0x0530, "Armenian" },
+  { 0x058B, "Unassigned" },
+  { 0x0590, "Hebrew" },
+  { 0x05F5, "Unassigned" },
+  { 0x0600, "Arabic" },
+  { 0x0700, "Syriac" },
+  { 0x0750, "Arabic Supplement" },
+  { 0x0780, "Thaana" },
+  { 0x07C0, "N'Ko" },
+  { 0x0800, "Samaritan" },
+  { 0x0840, "Mandaic" },
+  { 0x0860, "Unassigned" },
+  { 0x08A0, "Arabic Extended-A" },
+  { 0x0900, "Devanagari" },
+  { 0x0980, "Bengali" },
+  { 0x09FC, "Unassigned" },
+  { 0x0A00, "Gurmukhi" },
+  { 0x0A76, "Unassigned" },
+  { 0x0A80, "Gujarati" },
+  { 0x0AF2, "Unassigned" },
+  { 0x0B00, "Oriya" },
+  { 0x0B80, "Tamil" },
+  { 0x0BFB, "Unassigned" },
+  { 0x0C00, "Telugu" },
+  { 0x0C80, "Kannada" },
+  { 0x0CF0, "Unassigned" },
+  { 0x0D00, "Malayalam" },
+  { 0x0D80, "Sinhala" },
+  { 0x0DF5, "Unassigned" },
+  { 0x0E00, "Thai" },
+  { 0x0E5C, "Unassigned" },
+  { 0x0E80, "Lao" },
+  { 0x0EE0, "Unassigned" },
+  { 0x0F00, "Tibetan" },
+  { 0x0FDB, "Unassigned" },
+  { 0x1000, "Myanmar" },
+  { 0x10A0, "Georgian" },
+  { 0x1100, "Hangul Jamo" },
+  { 0x1200, "Ethiopic" },
+  { 0x1380, "Ethiopic Supplement" },
+  { 0x13A0, "Cherokee" },
+  { 0x1400, "Unified Canadian Aboriginal Syllabics" },
+  { 0x1677, "Unassigned" },
+  { 0x1680, "Ogham" },
+  { 0x16A0, "Runic" },
+  { 0x16F1, "Unassigned" },
+  { 0x1700, "Tagalog" },
+  { 0x1715, "Unassigned" },
+  { 0x1720, "Hanunoo" },
+  { 0x1737, "Unassigned" },
+  { 0x1740, "Buhid" },
+  { 0x1754, "Unassigned" },
+  { 0x1760, "Tagbanwa" },
+  { 0x1774, "Unassigned" },
+  { 0x1780, "Khmer" },
+  { 0x17FA, "Unassigned" },
+  { 0x1800, "Mongolian" },
+  { 0x18AB, "Unassigned" },
+  { 0x18B0, "Unified Canadian Aboriginal Syllabics Extended" },
+  { 0x18F6, "Unassigned" },
+  { 0x1900, "Limbu" },
+  { 0x1950, "Tai Le" },
+  { 0x1975, "Unassigned" },
+  { 0x1980, "Tai Lue" },
+  { 0x19E0, "Khmer Symbols" },
+  { 0x1A00, "Buginese" },
+  { 0x1A20, "Tai Tham" },
+  { 0x1AAE, "Unassigned" },
+  { 0x1AB0, "Combining Diacritical Marks Extended" },
+  { 0x1ABF, "Unassigned" },
+  { 0x1B00, "Balinese" },
+  { 0x1B80, "Sundanese" },
+  { 0x1BC0, "Batak" },
+  { 0x1C00, "Lepcha" },
+  { 0x1C50, "Ol Chiki" },
+  { 0x1C80, "Unassigned" },
+  { 0x1CC0, "Sundanese Supplement" },
+  { 0x1CC8, "Unassigned" },
+  { 0x1CD0, "Vedic Extensions" },
+  { 0x1CFA, "Unassigned" },
+  { 0x1D00, "Phonetic Extensions" },
+  { 0x1D80, "Phonetic Extensions Supplement" },
+  { 0x1DC0, "Combining Diacritical Marks Supplement" },
+  { 0x1E00, "Latin Extended Additional" },
+  { 0x1F00, "Greek Extended" },
+  { 0x2000, "General Punctuation" },
+  { 0x2070, "Superscripts and Subscripts" },
+  { 0x2095, "Unassigned" },
+  { 0x20A0, "Currency Symbols" },
+  { 0x20BE, "Unassigned" },
+  { 0x20D0, "Combining Diacritical Marks for Symbols" },
+  { 0x20F1, "Unassigned" },
+  { 0x2100, "Letterlike Symbols" },
+  { 0x2150, "Number Forms" },
+  { 0x2190, "Arrows" },
+  { 0x2200, "Mathematical Operators" },
+  { 0x2300, "Miscellaneous Technical" },
+  { 0x2400, "Control Pictures" },
+  { 0x2437, "Unassigned" },
+  { 0x2440, "Optical Character Recognition" },
+  { 0x244B, "Unassigned" },
+  { 0x2460, "Enclosed Alphanumerics" },
+  { 0x2500, "Box Drawing" },
+  { 0x2580, "Block Elements" },
+  { 0x25A0, "Geometric Shapes" },
+  { 0x2600, "Miscellaneous Symbols" },
+  { 0x2700, "Dingbats" },
+  { 0x27C0, "Miscellaneous Mathematical Symbols-A" },
+  { 0x27F0, "Supplemental Arrows-A" },
+  { 0x2800, "Braille Patterns" },
+  { 0x2900, "Supplemental Arrows-B" },
+  { 0x2980, "Miscellaneous Mathematical Symbols-B" },
+  { 0x2A00, "Supplemental Mathematical Operators" },
+  { 0x2B00, "Miscellaneous Symbols and Arrows" },
+  { 0x2B56, "Unassigned" }, /* Unicode 5.1 */
+  { 0x2BF0, "Unassigned" },
+  { 0x2C00, "Glagolitic" },
+  { 0x2C60, "Latin Extended-C" },
+  { 0x2C80, "Coptic" },
+  { 0x2D00, "Georgian Supplement" },
+  { 0x2D26, "Unassigned" },
+  { 0x2D30, "Tifinagh" },
+  { 0x2D80, "Ethiopic Extended" },
+  { 0x2DE0, "Cyrillic Extended-A" },
+  { 0x2E00, "Supplemental Punctuation" },
+  { 0x2E43, "Unassigned" },
+  { 0x2E80, "CJK Radicals Supplement" },
+  { 0x2EF5, "Unassigned" },
+  { 0x2F00, "Kangxi Radicals" },
+  { 0x2FD6, "Unassigned" },
+  { 0x2FE0, "Unassigned" },
+  { 0x2FF0, "Ideographic Description Characters" },
+  { 0x2FFC, "Unassigned" },
+  { 0x3000, "CJK Symbols and Punctuation" },
+  { 0x3040, "Hiragana" },
+  { 0x30A0, "Katakana" },
+  { 0x3100, "Bopomofo" },
+  { 0x3130, "Hangul Compatibility Jamo" },
+  { 0x3190, "Kanbun" },
+  { 0x31A0, "Bopomofo Extended" },
+  { 0x31BB, "Unassigned" },
+  { 0x31C0, "CJK Strokes" },
+  { 0x31E4, "Unassigned" },
+  { 0x31F0, "Katakana Phonetic Extensions" },
+  { 0x3200, "Enclosed CJK Letters and Months" },
+  { 0x3300, "CJK Compatibility" },
+  { 0x3400, "CJK Unified Ideographs Extension A" },
+  { 0x4DB6, "Unassigned" },
+  { 0x4DC0, "Yijing Hexagram Symbols" },
+  { 0x4E00, "CJK Unified Ideographs" },
+  { 0x9FD6, "Unassigned" },
+  { 0xA000, "Yi Syllables" },
+  { 0xA48D, "Unassigned" },
+  { 0xA490, "Yi Radicals" },
+  { 0xA4C7, "Unassigned" },
+  { 0xA4D0, "Lisu" },
+  { 0xA500, "Vai" },
+  { 0xA62C, "Unassigned" },
+  { 0xA640, "Cyrillic Extended-B" },
+  { 0xA6A0, "Bamum" },
+  { 0xA700, "Modifier Tone Letters" },
+  { 0xA720, "Latin Extended-D" },
+  { 0xA800, "Syloti Nagri" },
+  { 0xA82C, "Unassigned" },
+  { 0xA830, "Common Indic Number Forms" },
+  { 0xA83A, "Unassigned" },
+  { 0xA840, "Phags-pa" },
+  { 0xA878, "Unassigned" },
+  { 0xA880, "Saurashtra" },
+  { 0xA8DA, "Unassigned" },
+  { 0xA8E0, "Devanagari Extended" },
+  { 0xA8FE, "Unassigned" },
+  { 0xA900, "Kayah Li" },
+  { 0xA930, "Rejang" },
+  { 0xA960, "Hangul Jamo Extended-A" },
+  { 0xA97D, "Unassigned" },
+  { 0xA980, "Javanese" },
+  { 0xA9E0, "Myanmar Extended-B" },
+  { 0xAA00, "Cham" },
+  { 0xAA60, "Myanmar Extended-A" },
+  { 0xAA80, "Tai Viet" },
+  { 0xAAE0, "Meetei Mayek Extensions" },
+  { 0xAB00, "Ethiopic Extended-A" },
+  { 0xAB30, "Latin Extended-E" },
+  { 0xAB66, "Unassigned" },
+  { 0xAB70, "Cherokee Supplement" },
+  { 0xABC0, "Meetei Mayek" },
+  { 0xABFA, "Unassigned" },
+  { 0xAC00, "Hangul Syllables" },
+  { 0xD7B0, "Hangul Jamo Extended-B" },
+  { 0xD7FC, "Unassigned" },
+/*{ 0xD800, "High Surrogates" }, */  /* UTF-16 compatibility */
+/*{ 0xDC00, "Low Surrogates" },  */  /* UTF-16 compatibility */
+  { 0xE000, "Private Use Area" },
+  { 0xF900, "CJK Compatibility Ideographs" },
+  { 0xFAEA, "Unassigned" },
+  { 0xFB00, "Alphabetic Presentation Forms" },
+  { 0xFB50, "Arabic Presentation Forms-A" },
+  { 0xFE00, "Variation Selectors" },
+  { 0xFE10, "Vertical Forms" },
+  { 0xFE1A, "Unassigned" },
+  { 0xFE20, "Combining Half Marks" },
+  { 0xFE30, "CJK Compatibility Forms" },
+  { 0xFE50, "Small Form Variants" },
+  { 0xFE6C, "Unassigned" },
+  { 0xFE70, "Arabic Presentation Forms-B" },
+  { 0xFF00, "Halfwidth and Fullwidth Forms" },
+  { 0xFFF0, "Unassigned" },
+  { 0xFFF9, "Specials" },
+  { 0xFFFE, "Unassigned" },
+
+  { 0x10000, "*Supplementary Multilingual" },
+  { 0x10000, "Linear B Syllabary" },
+  { 0x1007E, "Unassigned" },
+  { 0x10080, "Linear B Ideograms" },
+  { 0x100FB, "Unassigned" },
+  { 0x10100, "Aegean Numbers" },
+  { 0x10140, "Ancient Greek Numbers" },
+  { 0x1018D, "Unassigned" },
+  { 0x10190, "Ancient Symbols" },
+  { 0x1019C, "Unassigned" },
+  { 0x101D0, "Phaistos Disc" },
+  { 0x10200, "Unassigned" },
+  { 0x10280, "Lycian" },
+  { 0x1029D, "Unassigned" },
+  { 0x102A0, "Carian" },
+  { 0x102D1, "Unassigned" },
+  { 0x102E0, "Coptic Epact Numbers" },
+  { 0x102FC, "Unassigned" },
+  { 0x10300, "Old Italic" },
+  { 0x10324, "Unassigned" },
+  { 0x10330, "Gothic" },
+  { 0x1034B, "Unassigned" },
+  { 0x10350, "Old Permic" },
+  { 0x10380, "Ugaritic" },
+  { 0x103A0, "Old Persian" },
+  { 0x103D6, "Unassigned" },
+  { 0x103E0, "Unassigned" },
+  { 0x10400, "Deseret" },
+  { 0x10450, "Shavian" },
+  { 0x10480, "Osmanya" },
+  { 0x104AA, "Unassigned" },
+  { 0x104B0, "Unassigned" },
+  { 0x10500, "Elbasan" },
+  { 0x10528, "Unassigned" },
+  { 0x10530, "Caucasian Albanian" },
+  { 0x10570, "Unassigned" },
+  { 0x10600, "Linear A" },
+  { 0x10768, "Unassigned" },
+  { 0x10780, "Unassigned" },
+  { 0x10800, "Cypriot Syllabary" },
+  { 0x10840, "Imperial Aramaic" },
+  { 0x10860, "Palmyrene" },
+  { 0x10880, "Nabataean" },
+  { 0x108B0, "Unassigned" },
+  { 0x108E0, "Hatran" },
+  { 0x10900, "Phoenician" },
+  { 0x10920, "Lydian" },
+  { 0x10940, "Unassigned" },
+  { 0x10980, "Meroitic Hieroglyphs" },
+  { 0x109A0, "Meroitic Cursive" },
+  { 0x10A00, "Kharoshthi" },
+  { 0x10A59, "Unassigned" },
+  { 0x10A60, "Old South Arabian" },
+  { 0x10A80, "Old North Arabian" },
+  { 0x10AA0, "Unassigned" },
+  { 0x10AC0, "Manichaean" },
+  { 0x10AF7, "Unassigned" },
+  { 0x10B00, "Avestan" },
+  { 0x10B40, "Inscriptional Parthian" },
+  { 0x10B60, "Inscriptional Pahlavi" },
+  { 0x10B80, "Psalter Pahlavi" },
+  { 0x10BB0, "Unassigned" },
+  { 0x10C00, "Old Turkic" },
+  { 0x10C49, "Unassigned" },
+  { 0x10C50, "Unassigned" },
+  { 0x10C80, "Old Hungarian" },
+  { 0x10D00, "Unassigned" },
+  { 0x10E60, "Rumi Numeral Symbols" },
+  { 0x10E80, "Unassigned" },
+  { 0x11000, "Brahmi" },
+  { 0x11070, "Unassigned" },
+  { 0x11080, "Kaithi" },
+  { 0x110C2, "Unassigned" },
+  { 0x110D0, "Sora Sompeng" },
+  { 0x110FA, "Unassigned" },
+  { 0x11100, "Chakma" },
+  { 0x11144, "Unassigned" },
+  { 0x11150, "Mahajani" },
+  { 0x11177, "Unassigned" },
+  { 0x11180, "Sharada" },
+  { 0x111E0, "Sinhala Archaic Numbers" },
+  { 0x111F5, "Unassigned" },
+  { 0x11200, "Khojki" },
+  { 0x1123E, "Unassigned" },
+  { 0x11250, "Unassigned" },
+  { 0x11280, "Multani" },
+  { 0x112AA, "Unassigned" },
+  { 0x112B0, "Khudawadi" },
+  { 0x112FA, "Unassigned" },
+  { 0x11300, "Grantha" },
+  { 0x11375, "Unassigned" },
+  { 0x11380, "Unassigned" },
+  { 0x11480, "Tirhuta" },
+  { 0x114DA, "Unassigned" },
+  { 0x114E0, "Unassigned" },
+  { 0x11580, "Siddham" },
+  { 0x115DE, "Unassigned" },
+  { 0x11600, "Modi" },
+  { 0x1165A, "Unassigned" },
+  { 0x11660, "Unassigned" },
+  { 0x11680, "Takri" },
+  { 0x116CA, "Unassigned" },
+  { 0x116D0, "Unassigned" },
+  { 0x11700, "Ahom" },
+  { 0x11740, "Unassigned" },
+  { 0x118A0, "Warang Citi" },
+  { 0x11900, "Unassigned" },
+  { 0x11AC0, "Pau Cin Hau" },
+  { 0x11AF9, "Unassigned" },
+  { 0x11B00, "Unassigned" },
+  { 0x12000, "Cuneiform" },
+  { 0x1239A, "Unassigned" },
+  { 0x12400, "Cuneiform Numbers and Punctuation" },
+  { 0x12475, "Unassigned" },
+  { 0x12480, "Early Dynastic Cuneiform" },
+  { 0x12544, "Unassigned" },
+  { 0x12550, "Unassigned" },
+  { 0x13000, "Egyptian Hieroglyphs" },
+  { 0x13430, "Unassigned" },
+  { 0x14400, "Anatolian Hieroglyphs" },
+  { 0x14647, "Unassigned" },
+  { 0x14680, "Unassigned" },
+  { 0x16800, "Bamum Supplement" },
+  { 0x16A39, "Unassigned" },
+  { 0x16A40, "Mro" },
+  { 0x16A70, "Unassigned" },
+  { 0x16AD0, "Bassa Vah" },
+  { 0x16AF6, "Unassigned" },
+  { 0x16B00, "Pahawh Hmong" },
+  { 0x16B90, "Unassigned" },
+  { 0x16F00, "Miao" },
+  { 0x16FA0, "Unassigned" },
+  { 0x1B000, "Kana Supplement" },
+  { 0x1B002, "Unassigned" },
+  { 0x1B100, "Unassigned" },
+  { 0x1BC00, "Duployan Shorthand" },
+  { 0x1BCA4, "Unassigned" },
+  { 0x1BCB0, "Unassigned" },
+  { 0x1D000, "Byzantine Musical Symbols" },
+  { 0x1D0F5, "Unassigned" },
+  { 0x1D100, "Musical Symbols" },
+  { 0x1D1E9, "Unassigned" },
+  { 0x1D200, "Ancient Greek Musical Notation" },
+  { 0x1D246, "Unassigned" },
+  { 0x1D250, "Unassigned" },
+  { 0x1D300, "Tai Xuan Jing Symbols" },
+  { 0x1D357, "Unassigned" },
+  { 0x1D360, "Counting Rod Numerals" },
+  { 0x1D372, "Unassigned" },
+  { 0x1D380, "Unassigned" },
+  { 0x1D400, "Mathematical Alphanumeric Symbols" },
+  { 0x1D800, "Sutton SignWriting" },
+  { 0x1DAB0, "Unassigned" },
+  { 0x1E800, "Mende Kikakui" },
+  { 0X1E8D7, "Unassigned" },
+  { 0x1E8E0, "Unassigned" },
+  { 0x1EE00, "Arabic Mathematical Alphabetic Symbols" },
+  { 0X1EEFC, "Unassigned" },
+  { 0x1EF00, "Unassigned" },
+  { 0x1F000, "Mahjong Tiles" },
+  { 0x1F02C, "Unassigned" },
+  { 0x1F030, "Domino Tiles" },
+  { 0x1F094, "Unassigned" },
+  { 0x1F0A0, "Playing Cards" },
+  { 0x1F0F6, "Unassigned" },
+  { 0x1F100, "Enclosed Alphanumeric Supplement" },
+  { 0x1F19B, "Unassigned" },
+  { 0x1F1E6, "Enclosed Alphanumeric Supplement" },
+  { 0x1F200, "Enclosed Ideographic Supplement" },
+  { 0x1F252, "Unassigned" },
+  { 0x1F300, "Miscellaneous Symbols and Pictographs" },
+  { 0x1F600, "Emoticons" },
+  { 0x1F650, "Ornamental Dingbats" },
+  { 0x1F680, "Transport and Map Symbols" },
+  { 0x1F6F4, "Unassigned" },
+  { 0x1F700, "Alchemical Symbols" },
+  { 0x1F774, "Unassigned" },
+  { 0x1F780, "Geometric Shapes Extended" },
+  { 0x1F7D5, "Unassigned" },
+  { 0x1F800, "Supplemental Arrows-C" },
+  { 0x1F8AD, "Unassigned" },
+  { 0x1F910, "Supplemental Symbols and Pictographs" },
+  { 0x1F9C1, "Unassigned" },
+  { 0x1FA00, "Unassigned" },
+
+  { 0x20000, "*Supplementary Ideographic" },
+  { 0x20000, "CJK Unified Ideographs Extension B" },
+  { 0x2A6D7, "Unassigned" },
+  { 0x2A6E0, "Unassigned" },
+  { 0x2A700, "CJK Unified Ideographs Extension C" },
+  { 0x2B740, "Unassigned" },
+  { 0x2B740, "CJK Unified Ideographs Extension D" },
+  { 0x2B820, "Unassigned" },
+  { 0x2B820, "CJK Unified Ideographs Extension E" },
+  { 0x2CEA2, "Unassigned" },
+  { 0x2CEB0, "Unassigned" },
+  { 0x2F800, "CJK Compatibility Ideographs Supplement" },
+  { 0x2FA20, "Unassigned" },
+
+  { 0x30000, "*Unassigned Plane 3" },
+  { 0x40000, "*Unassigned Plane 4" },
+  { 0x50000, "*Unassigned Plane 5" },
+  { 0x60000, "*Unassigned Plane 6" },
+  { 0x70000, "*Unassigned Plane 7" },
+  { 0x80000, "*Unassigned Plane 8" },
+  { 0x90000, "*Unassigned Plane 9" },
+  { 0xA0000, "*Unassigned Plane 10" },
+  { 0xB0000, "*Unassigned Plane 11" },
+  { 0xC0000, "*Unassigned Plane 12" },
+  { 0xD0000, "*Unassigned Plane 13" },
+
+  { 0xE0000, "*Supplementary Special-Purpose" },
+  { 0xE0080, "Unassigned" },
+  { 0xE0020, "Tags" },
+  { 0xE0080, "Unassigned" },
+  { 0xE0100, "Variation Selectors Supplement" },
+  { 0xE01F0, "Unassigned" },
+
+  { 0xF0000,  "*Supplementary Private Use Area A" },
+  { 0x100000, "*Supplementary Private Use Area B" },
+};
+
+
+static char 
+*strip (char *s)
+{
+  int L;
+  while (*s == ' ' || *s == '\t' || *s == '\n')
+    s++;
+  L = strlen (s);
+  while (s[L-1] == ' ' || s[L-1] == '\t' || s[L-1] == '\n')
+    s[--L] = 0;
+  return s;
+}
+
+
+/* matches ("AA, BB, CC", "CC")  => True
+   matches ("AA, BB, CC", "CCx") => False
+ */
+static Bool
+matches (const char *pattern, const char *string)
+{
+  char *token = strdup (pattern ? pattern : "");
+  char *otoken = token;
+  char *name;
+  Bool match = False;
+  while ((name = strtok (token, ","))) {
+    token = 0;
+    name = strip (name);
+    if (*name && !strcasecmp (name, string))
+      {
+        match = True;
+        break;
+      }
+  }
+
+  free (otoken);
+  return match;
+}
+
+
+static void
+pick_unichar (ModeInfo *mi)
+{
+  unicrud_configuration *bp = &bps[MI_SCREEN(mi)];
+  int i;
+  unsigned long min = 0;
+  unsigned long max = 0x2F800;
+  unsigned long last = 0;
+  int retries = 0;
+
+ AGAIN:
+  bp->unichar = min + (random() % (max - min));
+
+  if (++retries > 0xF0000 / 2)
+    {
+      fprintf (stderr, "%s: internal error: too many retries\n", progname);
+      exit (1);
+    }
+
+  /* bp->unichar = 0x1F4A9; */
+
+  last = 0;
+  bp->charplane = "Unassigned";
+  bp->charblock = "Unassigned";
+  for (i = 0; i < countof(unicode_block_names); i++)
+    {
+      if (unicode_block_names[i].start < last)
+        {
+          fprintf (stderr, "%s: progname: internal error: misordered: 0x%lX\n",
+                   progname, unicode_block_names[i].start);
+          exit (1);
+        }
+      last = unicode_block_names[i].start;
+      if (bp->unichar >= unicode_block_names[i].start)
+        {
+          if (unicode_block_names[i].name[0] == '*')
+            {
+              bp->charplane = unicode_block_names[i].name + 1;
+              bp->charblock = "Unassigned";
+            }
+          else
+            bp->charblock = unicode_block_names[i].name;
+        }
+      else
+        break;
+    }
+
+  if (!strncmp (bp->charblock, "Unassigned", 10) ||
+      !strncmp (bp->charblock, "Combining", 9))
+    goto AGAIN;
+
+  if (*do_block && !matches (do_block, bp->charblock))
+    goto AGAIN;
+
+  /* Skip blank characters */
+  {
+    XCharStruct e;
+    char text[10];
+    int i;
+    i = utf8_encode (bp->unichar, text, sizeof(text) - 1);
+    text[i] = 0;
+    texture_string_metrics (bp->char_font, text, &e, 0, 0);
+    if (e.width < 2 || e.ascent + e.descent < 2)
+      goto AGAIN;
+  }
+
+# ifdef HAVE_JWXYZ
+  bp->charname = texfont_unicode_character_name (bp->char_font, bp->unichar);
+# endif
+
+  bp->color[0] = 0.5 + frand(0.5);
+  bp->color[1] = 0.5 + frand(0.5);
+  bp->color[2] = 0.5 + frand(0.5);
+  bp->color[3] = 1;
+}
+
+
+static void
+draw_unichar (ModeInfo *mi)
+{
+  unicrud_configuration *bp = &bps[MI_SCREEN(mi)];
+
+  char text[10];
+  char title[400];
+  XCharStruct e;
+  int w, h, i, j;
+  GLfloat s;
+
+  i = utf8_encode (bp->unichar, text, sizeof(text) - 1);
+  text[i] = 0;
+
+  *title = 0;
+  sprintf (title + strlen(title), "Plane:\t%s\n", bp->charplane);
+  sprintf (title + strlen(title), "Block:\t%s\n", bp->charblock);
+# ifdef HAVE_JWXYZ
+  sprintf (title + strlen(title), "Name:\t%s\n",
+           (bp->charname ? bp->charname : ""));
+#endif
+  sprintf (title + strlen(title), "Unicode:\t%04lX\n", bp->unichar);
+  sprintf (title + strlen(title), "UTF-8:\t");
+  for (j = 0; j < i; j++)
+    sprintf (title + strlen(title), "%02X ", ((unsigned char *)text)[j]);
+
+  texture_string_metrics (bp->char_font, text, &e, 0, 0);
+  w = e.width;
+  h = e.ascent;
+
+  s = 9;
+  glScalef (s, s, s);
+  
+  s = 1.0 / (h > w ? h : w);   /* Scale to unit */
+  glScalef (s, s, s);
+
+  glTranslatef (-w/2, -h/2, 0);
+  glColor4fv (bp->color);
+  print_texture_string (bp->char_font, text);
+
+  glColor3f (1, 1, 0);
+  print_texture_label (mi->dpy, bp->title_font,
+                       mi->xgwa.width, mi->xgwa.height,
+                       1, title);
+}
+
+
+/* Window management, etc
+ */
+ENTRYPOINT void
+reshape_unicrud (ModeInfo *mi, int width, int height)
+{
+  GLfloat h = (GLfloat) height / (GLfloat) width;
+
+  glViewport (0, 0, (GLint) width, (GLint) height);
+
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  gluPerspective (30.0, 1/h, 1.0, 100.0);
+
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+  gluLookAt( 0.0, 0.0, 30.0,
+             0.0, 0.0, 0.0,
+             0.0, 1.0, 0.0);
+
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
+  glClear(GL_COLOR_BUFFER_BIT);
+}
+
+
+ENTRYPOINT Bool
+unicrud_handle_event (ModeInfo *mi, XEvent *event)
+{
+  unicrud_configuration *bp = &bps[MI_SCREEN(mi)];
+
+  if (gltrackball_event_handler (event, bp->trackball,
+                                 MI_WIDTH (mi), MI_HEIGHT (mi),
+                                 &bp->button_down_p))
+    return True;
+  else if (event->xany.type == KeyPress)
+    {
+      KeySym keysym;
+      char c = 0;
+      XLookupString (&event->xkey, &c, 1, &keysym, 0);
+      if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
+        {
+          if (bp->state == LINGER) bp->ratio = 1;
+          return True;
+        }
+    }
+
+  return False;
+}
+
+
+ENTRYPOINT void 
+init_unicrud (ModeInfo *mi)
+{
+  unicrud_configuration *bp;
+
+  if (!bps) {
+    bps = (unicrud_configuration *)
+      calloc (MI_NUM_SCREENS(mi), sizeof (unicrud_configuration));
+    if (!bps) {
+      fprintf(stderr, "%s: out of memory\n", progname);
+      exit(1);
+    }
+  }
+
+  bp = &bps[MI_SCREEN(mi)];
+
+  bp->glx_context = init_GL(mi);
+
+  reshape_unicrud (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+
+  {
+    double spin_speed   = 0.05;
+    double wander_speed = 0.01;
+    double spin_accel   = 1.0;
+
+    bp->rot = make_rotator (do_spin ? spin_speed : 0,
+                            do_spin ? spin_speed : 0,
+                            do_spin ? spin_speed : 0,
+                            spin_accel,
+                            do_wander ? wander_speed : 0,
+                            False);
+    bp->trackball = gltrackball_init (True);
+  }
+
+  bp->title_font = load_texture_font (mi->dpy, "titleFont");
+  bp->char_font  = load_texture_font (mi->dpy, "font");
+  bp->state = IN;
+  bp->ratio = 0;
+  bp->spin_direction = (random() & 1) ? 1 : -1;
+
+
+
+  if (matches ("all", do_block))
+    do_block = "";
+
+  {
+    char *s;
+    for (s = do_block; *s; s++)
+      if (*s == '_') *s = ' ';
+  }
+
+  if (matches ("help", do_block))
+    {
+      int i;
+      fprintf (stderr,
+               "%s: --blocks must contain one or more of these,"
+               " separated by commas:\n\n", progname);
+      for (i = 0; i < countof(unicode_block_names); i++)
+        {
+          const char *n = unicode_block_names[i].name;
+          if (*n == '*')
+            continue;
+          if (!strncmp (n, "Unassigned", 10) ||
+              !strncmp (n, "Combining", 9))
+            continue;
+          fprintf (stderr, "\t%s\n", n);
+        }
+      fprintf (stderr, "\n");
+      exit (1);
+    }
+
+
+  /* Make sure all elements in --block are valid.
+   */
+  if (*do_block)
+    {
+      char *token = strdup (do_block ? do_block : "");
+      char *otoken = token;
+      char *name;
+      while ((name = strtok (token, ","))) {
+        token = 0;
+        name = strip (name);
+        if (*name)
+          {
+            Bool match = False;
+            int i;
+            for (i = 0; i < countof(unicode_block_names); i++)
+              {
+                const char *n = unicode_block_names[i].name;
+                if (*n == '*')
+                  continue;
+                if (!strncmp (n, "Unassigned", 10) ||
+                    !strncmp (n, "Combining", 9))
+                  continue;
+                if (!strcasecmp (name, n))
+                  {
+                    match = True;
+                    break;
+                  }
+              }
+            if (! match)
+              {
+                fprintf (stderr, "%s: unknown block name: \"%s\"\n", 
+                         progname, name);
+                fprintf (stderr, "%s: use '--block help' for a list\n", 
+                         progname);
+                exit (1);
+              }
+          }
+      }
+      free (otoken);
+    }
+
+  pick_unichar (mi);
+}
+
+
+ENTRYPOINT void
+draw_unicrud (ModeInfo *mi)
+{
+  unicrud_configuration *bp = &bps[MI_SCREEN(mi)];
+  Display *dpy = MI_DISPLAY(mi);
+  Window window = MI_WINDOW(mi);
+
+  if (!bp->glx_context)
+    return;
+
+  glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context));
+
+  glShadeModel (GL_FLAT);
+  glEnable (GL_NORMALIZE);
+  glDisable (GL_CULL_FACE);
+  glDisable (GL_LIGHTING);
+
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  if (! bp->button_down_p)
+    switch (bp->state) {
+    case IN:     bp->ratio += speed * 0.05;  break;
+    case OUT:    bp->ratio += speed * 0.05;  break;
+    case LINGER: bp->ratio += speed * 0.005; break;
+    default:     abort();
+    }
+
+  if (bp->ratio > 1.0)
+    {
+      bp->ratio = 0;
+      switch (bp->state) {
+      case IN:
+        bp->state = LINGER;
+        break;
+      case LINGER:
+        bp->state = OUT;
+        bp->spin_direction = (random() & 1) ? 1 : -1;
+        break;
+      case OUT:
+        bp->state = IN;
+        pick_unichar(mi);
+        break;
+      default:     abort();
+      }
+    }
+
+  glPushMatrix ();
+
+  {
+    double x, y, z;
+    get_position (bp->rot, &x, &y, &z, !bp->button_down_p);
+    glTranslatef((x - 0.5) * 6,
+                 (y - 0.5) * 6,
+                 (z - 0.5) * 6);
+
+    gltrackball_rotate (bp->trackball);
+
+    get_rotation (bp->rot, &x, &y, &z, !bp->button_down_p);
+    x = y = 0;
+    glRotatef (x * 360, 1.0, 0.0, 0.0);
+    glRotatef (y * 360, 0.0, 1.0, 0.0);
+    glRotatef (z * 360, 0.0, 0.0, 1.0);
+  }
+
+# define SINOID(N) (sin(M_PI - (N) / 2 * M_PI))
+  {
+    GLfloat s;
+    switch (bp->state) {
+    case IN:  s = SINOID (bp->ratio);   break;
+    case OUT: s = SINOID (1-bp->ratio); break;
+    default:  s = 1; break;
+    }
+    glScalef (s, s, s);
+    glRotatef (360 * s * bp->spin_direction * (bp->state == IN ? -1 : 1),
+               0, 0, 1);
+  }
+
+  draw_unichar (mi);
+
+  glPopMatrix ();
+
+  if (mi->fps_p) do_fps (mi);
+  glFinish();
+
+  glXSwapBuffers(dpy, window);
+}
+
+XSCREENSAVER_MODULE_2 ("Unicrud", unicrud, unicrud)
+
+#endif /* USE_GL */
diff --git a/hacks/glx/unicrud.man b/hacks/glx/unicrud.man
new file mode 100644 (file)
index 0000000..54dfdda
--- /dev/null
@@ -0,0 +1,70 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+unicrud - Bounces a random Unicode character on the screen.
+.SH SYNOPSIS
+.B unicrud
+[\-display \fIhost:display.screen\fP]
+[\-visual \fIvisual\fP]
+[\-window]
+[\-root]
+[\-delay \fInumber\fP]
+[\-speed \fInumber\fP]
+[\-block \fIstring\fP]
+[\-no-wander]
+[\-no-roll]
+[\-fps]
+.SH DESCRIPTION
+Chooses a random Unicode character and displays it full screen, along with
+some information about it. https://en.wikipedia.org/wiki/Unicode
+.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 \-wander | \-no-wander
+Whether the object should wander around the screen.
+.TP 8
+.B \-roll | \-no-roll
+Whether the object should rotate.  Boolean.
+.TP 8
+.B \-block \fIstring\fP
+Which block or blocks of Unicode characters to display.  Default: "all".
+Use \fI\-block help\fP to see the full list.
+.TP 8
+.B \-fps | \-no-fps
+Whether to show a frames-per-second display at the bottom 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 2016 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 1a6544f58570dd2c3bc0eeac2d12f3ca636c0cd2..236fd8e6bd5ddcd57694a52731409c4f4a1c32e1 100644 (file)
@@ -365,7 +365,7 @@ draw_unk (ModeInfo *mi)
       xinc *= 3;
     }
 
-# ifdef USE_IPHONE
+# ifdef HAVE_MOBILE
   /* Lower it even further for iPhone 3 */
   if (mi->xgwa.width <= 480 || mi->xgwa.height <= 480)
     {
@@ -379,7 +379,7 @@ draw_unk (ModeInfo *mi)
     xinc *= 2;
 */
 
-# endif /* USE_IPHONE */
+# endif /* USE_MOBILE */
 
 
   /* Make the image fill the screen a little more fully */
index b207bbc0e58f224756c4b3506efeca36228ca66c..ea700c303a176a97f31fb4ae474bf8aa3dd08262 100644 (file)
@@ -11,7 +11,7 @@
 
 #define DEFAULTS        "*delay:        20000              \n" \
                         "*showFPS:      False              \n" \
-
+                       "*suppressRotationAnimation: True\n" \
 
 # define refresh_voronoi 0
 # define release_voronoi 0
@@ -299,6 +299,25 @@ draw_cells (ModeInfo *mi)
           glPopMatrix();
         }
     }
+
+#if 0
+  glPushMatrix();
+  glColor3f(1,1,1);
+  glBegin(GL_LINE_LOOP);
+  glVertex3f(0,0,0);
+  glVertex3f(1,0,0);
+  glVertex3f(1,1,0);
+  glVertex3f(0,1,0);
+  glEnd();
+  glScalef(0.25, 0.25, 1);
+  glBegin(GL_LINE_LOOP);
+  glVertex3f(0,0,0);
+  glVertex3f(1,0,0);
+  glVertex3f(1,1,0);
+  glVertex3f(0,1,0);
+  glEnd();
+  glPopMatrix();
+#endif
 }
 
 
@@ -315,6 +334,27 @@ reshape_voronoi (ModeInfo *mi, int width, int height)
   glLoadIdentity();
   glOrtho (0, 1, 1, 0, -1, 1);
 
+# ifdef HAVE_MOBILE    /* So much WTF */
+  {
+    int rot = current_device_rotation();
+
+    glTranslatef (0.5, 0.5, 0);
+    //  glScalef(0.19, 0.19, 0.19);
+
+    if (rot == 180 || rot == -180) {
+      glTranslatef (1, 1, 0);
+    } else if (rot == 90 || rot == -270) {
+      glRotatef (180, 0, 0, 1);
+      glTranslatef (0, 1, 0);
+    } else if (rot == -90 || rot == 270) {
+      glRotatef (180, 0, 0, 1);
+      glTranslatef (1, 0, 0);
+    }
+
+    glTranslatef(-0.5, -0.5, 0);
+  }
+# endif
+
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
 
index 84dc4ccf46de1def697b3ff7d1e98ccc9565dacf..f0f42bae1a06355c44c08d0d30f49806a9621fd5 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/perl -w
-# Copyright © 2003-2011 Jamie Zawinski <jwz@jwz.org>
+# Copyright Â© 2003-2011 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
@@ -26,7 +26,7 @@ use diagnostics;
 use strict;
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my $version = q{ $Revision: 1.1 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/;
+my ($version) = ('$Revision: 1.2 $' =~ m/\s(\d[.\d]+)\s/s);
 
 my $verbose = 0;
 
index 69c28a6409ee8592395fd5aa70e91bb13226e87c..c78974e5094e738a602a81fb8de44f8aba4d39af 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/perl -w
-# Copyright © 2003-2012 Jamie Zawinski <jwz@jwz.org>
+# Copyright Â© 2003-2012 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
@@ -27,7 +27,7 @@ use diagnostics;
 use strict;
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my $version = q{ $Revision: 1.5 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/;
+my ($version) = ('$Revision: 1.6 $' =~ m/\s(\d[.\d]+)\s/s);
 
 my $verbose = 0;
 
index b73533e78c082eab2cbb545b9f462184cf3b0f90..603a1c40a94cecc77918ff0ccded75140bbbbda3 100644 (file)
@@ -14,7 +14,7 @@
  * came for us to throw the Cocktail Robotics Grand Challenge at DNA Lounge, I
  * photographed this robot (holding a tiny martini glass) to make a flyer for
  * the event.  You can see that photo here:
- * http://www.dnalounge.com/flyers/2014/09/14.html
+ * https://www.dnalounge.com/flyers/2014/09/14.html
  *
  * Then I decided to try and make award statues for the contest by modeling
  * this robot and 3D-printing it (a robot on a post, with the DNA Lounge
@@ -35,8 +35,8 @@
  *
  * We did eventually end up with robotic award statues, but we constructed
  * them out of mass-produced wind-up robots, rather than 3D printing them:
- * http://www.dnalounge.com/gallery/2014/09-14/045.html
- * http://www.youtube.com/watch?v=EZF4ZAAy49g
+ * https://www.dnalounge.com/gallery/2014/09-14/045.html
+ * https://www.youtube.com/watch?v=EZF4ZAAy49g
  */
 
 #define LABEL_FONT "-*-helvetica-bold-r-normal-*-*-240-*-*-*-*-*-*"
@@ -428,7 +428,7 @@ init_robot (ModeInfo *mi)
       char *key = 0;
       GLfloat spec1[4] = {1.00, 1.00, 1.00, 1.0};
       GLfloat spec2[4] = {0.40, 0.40, 0.70, 1.0};
-      GLfloat *spec = spec1;
+      GLfloat *spec = 0;
       GLfloat shiny = 20;
 
       glNewList (bp->dlists[i], GL_COMPILE);
@@ -2293,7 +2293,22 @@ draw_robot (ModeInfo *mi)
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
   glPushMatrix ();
-  glRotatef(current_device_rotation(), 0, 0, 1);
+
+# ifdef HAVE_MOBILE
+  {
+    int rot = current_device_rotation();
+
+    if (rot == 180 || rot == -180)             /* so much WTF */
+      glRotatef (-68, 1, 0, 0);
+    else if (rot == 90 || rot == -270)
+      glRotatef (68, 0, 1, 0);
+    else if (rot == -90 || rot == 270)
+      glRotatef (-68, 0, 1, 0);
+
+    glRotatef (rot, 0, 0, 1);  /* right side up */
+  }
+# endif
+
   gltrackball_rotate (bp->user_trackball);
 
   robot_size = size * 7;
index 07e41683e890dd1aa0ffc29e8e3d14a8f708bfac..024f95bc1277d5f8ca1410834fe9e150a8bd76b4 100644 (file)
@@ -19,7 +19,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 
-#if defined(HAVE_COCOA) || defined(HAVE_ANDROID)
+#ifdef HAVE_JWXYZ
 # include "jwxyz.h"
 #else
 # include <X11/Xlib.h>
index 119fec55f277ccda63c42010aa6ee06260522d89..0f5c139e34968bbf89536ffa4b3ed067332b4c65 100644 (file)
@@ -274,9 +274,9 @@ make_layer (Display *dpy, Window window, int width, int height, int nblobs)
   layer->pixmap = XCreatePixmap (dpy, window, width, height, 1);
   layer->gc = XCreateGC (dpy, layer->pixmap, 0, &gcv);
 
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
   jwxyz_XSetAlphaAllowed (dpy, layer->gc, True);
-# endif /* HAVE_COCOA */
+# endif /* HAVE_JWXYZ */
 
   return layer;
 }
@@ -294,7 +294,7 @@ free_layer(struct layer *layer, Display *dpy)
 }
 
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 static void
 draw_layer_plane (Display *dpy, struct layer *layer, int width, int height)
 {
@@ -306,7 +306,7 @@ draw_layer_plane (Display *dpy, struct layer *layer, int width, int height)
       draw_blob (dpy, layer->pixmap, layer->gc, layer->blobs[i], True);
     }
 }
-#endif /* !HAVE_COCOA */
+#endif /* !HAVE_JWXYZ */
 
 
 static void
@@ -335,7 +335,7 @@ make_goop (Screen *screen, Visual *visual, Window window, Colormap cmap,
   int nblobs = get_integer_resource (dpy, "count", "Count");
 
   unsigned long *plane_masks = 0;
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
   unsigned long base_pixel = 0;
 # endif
   char *s;
@@ -370,7 +370,7 @@ make_goop (Screen *screen, Visual *visual, Window window, Colormap cmap,
   if (mono_p && goop->mode == transparent)
     goop->mode = opaque;
 
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
   /* Try to allocate some color planes before committing to nlayers.
    */
   if (goop->mode == transparent)
@@ -389,7 +389,7 @@ make_goop (Screen *screen, Visual *visual, Window window, Colormap cmap,
          goop->mode = opaque;
        }
     }
-# endif /* !HAVE_COCOA */
+# endif /* !HAVE_JWXYZ */
 
   {
     int lblobs[32];
@@ -404,21 +404,21 @@ make_goop (Screen *screen, Visual *visual, Window window, Colormap cmap,
                                    (nblobs > 0 ? nblobs : lblobs[i]));
   }
 
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
   if (goop->mode == transparent && plane_masks)
     {
       for (i = 0; i < goop->nlayers; i++)
        goop->layers[i]->pixel = base_pixel | plane_masks[i];
       goop->background = base_pixel;
     }
-# endif /* !HAVE_COCOA */
+# endif /* !HAVE_JWXYZ */
 
   if (plane_masks)
     free (plane_masks);
 
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
   if (goop->mode != transparent)
-# endif /* !HAVE_COCOA */
+# endif /* !HAVE_JWXYZ */
     {
       XColor color;
       color.flags = DoRed|DoGreen|DoBlue;
@@ -437,7 +437,7 @@ make_goop (Screen *screen, Visual *visual, Window window, Colormap cmap,
          else
            goop->layers[i]->pixel =
              WhitePixelOfScreen(DefaultScreenOfDisplay(dpy));
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
           if (goop->mode == transparent)
             {
               /* give a non-opaque alpha to the color */
@@ -447,7 +447,7 @@ make_goop (Screen *screen, Visual *visual, Window window, Colormap cmap,
               pixel = (pixel & (~amask)) | a;
               goop->layers[i]->pixel = pixel;
             }
-# endif /* HAVE_COCOA */
+# endif /* HAVE_JWXYZ */
        }
     }
 
@@ -460,9 +460,9 @@ make_goop (Screen *screen, Visual *visual, Window window, Colormap cmap,
   goop->pixmap_gc = XCreateGC (dpy, goop->pixmap, GCLineWidth, &gcv);
   goop->window_gc = XCreateGC (dpy, window, GCForeground|GCBackground, &gcv);
 
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
   jwxyz_XSetAlphaAllowed (dpy, goop->pixmap_gc, True);
-# endif /* HAVE_COCOA */
+# endif /* HAVE_JWXYZ */
   
   return goop;
 }
@@ -499,7 +499,7 @@ goop_draw (Display *dpy, Window window, void *closure)
 
   switch (goop->mode)
     {
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
     case transparent:
 
       for (i = 0; i < goop->nlayers; i++)
@@ -533,7 +533,7 @@ goop_draw (Display *dpy, Window window, void *closure)
       XCopyArea (dpy, goop->pixmap, window, goop->window_gc, 0, 0,
                 goop->width, goop->height, 0, 0);
       break;
-#endif /* !HAVE_COCOA */
+#endif /* !HAVE_JWXYZ */
 
     case xor:
       XSetFunction (dpy, goop->pixmap_gc, GXcopy);
@@ -550,7 +550,7 @@ goop_draw (Display *dpy, Window window, void *closure)
                  goop->width, goop->height, 0, 0, 1L);
       break;
 
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
     case transparent:
 # endif
     case opaque:
@@ -582,10 +582,13 @@ goop_reshape (Display *dpy, Window window, void *closure,
 {
   struct goop *goop = (struct goop *) closure;
 
-  struct goop *goop2 = goop_init (dpy, window);
-  free_goop(goop, dpy);
-  memcpy (goop, goop2, sizeof(*goop));
-  free(goop2);
+  if (w != goop->width || h != goop->height)
+    {
+      struct goop *goop2 = goop_init (dpy, window);
+      free_goop(goop, dpy);
+      memcpy (goop, goop2, sizeof(*goop));
+      free(goop2);
+    }
 }
 
 static Bool
@@ -617,7 +620,7 @@ static const char *goop_defaults [] = {
   "*torque:            0.0075",
   "*elasticity:                0.9",
   "*maxVelocity:       0.5",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation:     True",
 #endif
   0
index 38e97de8c9658c50d98737c719f109a7085d95e4..b909e8348dd40744ce22038b2c03fb53d3f878f9 100644 (file)
@@ -144,7 +144,7 @@ init_planet(ModeInfo * mi, planetstruct * planet)
        GC          gc = MI_GC(mi);
        gravstruct *gp = &gravs[MI_SCREEN(mi)];
 
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
     jwxyz_XSetAntiAliasing (MI_DISPLAY(mi), MI_GC(mi), False);
 # endif
 
index dc71f75015c27baa95d061817fa218360da9dee1..586fdffb04a132753eef19814559d84c2987a034 100644 (file)
@@ -11,7 +11,7 @@
 
 #include "screenhack.h"
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # define DO_STIPPLE
 #endif
 
@@ -130,9 +130,9 @@ greynetic_init (Display *dpy, Window window)
 
 # ifndef DO_STIPPLE
   st->gc = XCreateGC (st->dpy, st->window, GCForeground, &gcv);
-#  ifdef HAVE_COCOA /* allow non-opaque alpha components in pixel values */
+#  ifdef HAVE_JWXYZ /* allow non-opaque alpha components in pixel values */
   jwxyz_XSetAlphaAllowed (st->dpy, st->gc, True);
-#  endif /* HAVE_COCOA */
+#  endif /* HAVE_JWXYZ */
 # else /* DO_STIPPLE */
   gcv.fill_style= FillOpaqueStippled;
   st->gc = XCreateGC (st->dpy, st->window, GCForeground|GCBackground|GCFillStyle, &gcv);
@@ -230,7 +230,7 @@ greynetic_draw (Display *dpy, Window window, void *closure)
     DONE:
       ;
 
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
       {
         /* give a non-opaque alpha to the color */
         unsigned long pixel = gcv.foreground;
@@ -239,7 +239,7 @@ greynetic_draw (Display *dpy, Window window, void *closure)
         pixel = (pixel & (~amask)) | a;
         gcv.foreground = pixel;
       }
-# endif /* !HAVE_COCOA */
+# endif /* !HAVE_JWXYZ */
     }
 # ifndef DO_STIPPLE
   XChangeGC (st->dpy, st->gc, GCForeground, &gcv);
@@ -257,7 +257,7 @@ static const char *greynetic_defaults [] = {
   "*fpsSolid:  true",
   "*delay:     10000",
   "*grey:      false",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
   0
@@ -287,6 +287,9 @@ greynetic_event (Display *dpy, Window window, void *closure, XEvent *event)
 static void
 greynetic_free (Display *dpy, Window window, void *closure)
 {
+  struct state *st = (struct state *) closure;
+  XFreeGC (st->dpy, st->gc);
+  free (st);
 }
 
 XSCREENSAVER_MODULE ("Greynetic", greynetic)
index 84503c1fc77ee07d90109429886b1664e79d4d3a..b70a636d1dae3230c1c386815a9e201b12ef121e 100644 (file)
@@ -85,7 +85,7 @@ static void update_buffer(halftone_screen *halftone, XWindowAttributes * attrs)
 
     halftone->buffer_width = attrs->width;
     halftone->buffer_height = attrs->height;
-#ifdef HAVE_COCOA      /* Don't second-guess Quartz's double-buffering */
+#ifdef HAVE_JWXYZ      /* Don't second-guess Quartz's double-buffering */
     halftone->buffer = halftone->window;
 #else
     halftone->buffer = XCreatePixmap(halftone->dpy, halftone->window, halftone->buffer_width, halftone->buffer_height, attrs->depth);
@@ -373,7 +373,7 @@ static const char *halftone_defaults [] = {
   "*sizeFactor:                1.5",
   "*colors:            200",
   "*cycleSpeed:                10",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation:     True",
 #endif
   0
index 40a55402a95b5491908cc6bdea686781dba9c4b5..42b6a552e8843c07734f2ba4130299bb523fc083 100644 (file)
@@ -185,7 +185,7 @@ halo_init (Display *dpy, Window window)
   gcv.background = st->bg_pixel;
   st->copy_gc = XCreateGC (st->dpy, st->window, GCForeground | GCBackground, &gcv);
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
   jwxyz_XSetAntiAliasing (dpy, st->draw_gc,  False);
   jwxyz_XSetAntiAliasing (dpy, st->erase_gc, False);
   jwxyz_XSetAntiAliasing (dpy, st->copy_gc,  False);
@@ -405,7 +405,7 @@ static const char *halo_defaults [] = {
   "*delay2:            20",
   "*increment:         0",
   "*animate:           False",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation:     True",
 #endif
   0
index 3b6f0f8c22b4e70b47049e1ffb57f688bc480176..0fdaa90e749e2c73ef5544e424e456f397619b96 100644 (file)
@@ -341,7 +341,7 @@ static const char *helix_defaults [] = {
   "*fpsSolid:  true",
   "*delay:      5",
   "*subdelay:  20000",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
   0
index d9a706c57de80959ec2b8bf7854c55eebf9dbfac..515cb4cd4e05455e3bd75669ce920c28963074e5 100644 (file)
@@ -56,7 +56,6 @@ make_cells (state *st)
   int size, r, gw, gh, x, y, i;
   double th = 0;
 
-  grid_size = get_integer_resource (st->dpy, "size", "Size");
   if (grid_size < 5) grid_size = 5;
 
   size = ((st->xgwa.width > st->xgwa.height
@@ -386,7 +385,7 @@ static const char *hexadrop_defaults [] = {
   "*ncolors:           128",
   "*uniform:           Maybe",
   "*lockstep:          Maybe",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation:     True",
 #endif
   0
index 8a26cef7ca01c08153d170d8feccea3bbf0ccca9..70120d6cabf1b5680af64d04dcd106d67b711d5c 100644 (file)
@@ -227,7 +227,7 @@ hyperball_draw (Display *dpy, Window window, void *closure)
   if (icon || !(hs->roted | resize))
     goto skip1;
 
-#ifdef HAVE_COCOA      /* Don't second-guess Quartz's double-buffering */
+#ifdef HAVE_JWXYZ      /* Don't second-guess Quartz's double-buffering */
   XClearWindow (dpy, window);
 #endif
 
@@ -498,7 +498,7 @@ hyperball_event (Display *dpy, Window win, void *closure, XEvent *event)
         }
       break;
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
     case UnmapNotify:
       hs->hs_icon = 1;
       hs->hs_redraw = 0;
index ab131b199b1050d93250e014c2fe2c37311bc336..4fb16c584c80fb417a574ba496b6cb73b25eec2d 100644 (file)
@@ -244,7 +244,7 @@ hypercube_draw (Display *dpy, Window window, void *closure)
   struct hyper_state *hs = (struct hyper_state *) closure;
   int this_delay = hs->hs_delay;
 
-#ifdef HAVE_COCOA      /* Don't second-guess Quartz's double-buffering */
+#ifdef HAVE_JWXYZ      /* Don't second-guess Quartz's double-buffering */
   XClearWindow (dpy, window);
 #endif
 
index 63cb1a8c7f9082fd106a6b2d2414abc4f84753cd..9adbdf2f2c54b7fa74ba87b30ff7d23189fec6c3 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright © Chris Le Sueur and Robby Griffin, 2005-2006
+/* Copyright Â© Chris Le Sueur and Robby Griffin, 2005-2006
 
 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the
@@ -102,12 +102,12 @@ static const char *ifs_defaults [] = {
   "*rotate:            True",
   "*recurse:           False",
   "*multi:              True",
-# ifdef HAVE_COCOA     /* Don't second-guess Quartz's double-buffering */
+# ifdef HAVE_JWXYZ     /* Don't second-guess Quartz's double-buffering */
   "*doubleBuffer:      False",
 #else
   "*doubleBuffer:      True",
 #endif
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation:     True",
 #endif
   0
@@ -436,6 +436,7 @@ ifs_init (Display *d_arg, Window w_arg)
   if (st->ncolours < st->lensnum)
     st->ncolours = st->lensnum;
   if (st->colours) free(st->colours);
+  if (st->ncolours < 1) st->ncolours = 1;
   st->colours = (XColor *)calloc(st->ncolours, sizeof(XColor));
   if (!st->colours) exit(1);
   make_smooth_colormap (xgwa.screen, xgwa.visual, xgwa.colormap, 
diff --git a/hacks/images/dymaxionmap.xpm b/hacks/images/dymaxionmap.xpm
new file mode 100644 (file)
index 0000000..93957cd
--- /dev/null
@@ -0,0 +1,557 @@
+/* XPM */
+static char *dymaxionmap_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"1024 512 39 1 ",
+"  c #011119",
+". c #011C2A",
+"X c #0A2B30",
+"o c #275031",
+"O c #023B56",
+"+ c #05415E",
+"@ c #264554",
+"# c #32704D",
+"$ c #035075",
+"% c #2A576D",
+"& c #166979",
+"* c #247979",
+"= c #465153",
+"- c #328D7B",
+"; c #468F59",
+": c #479D6D",
+"> c #53B277",
+", c #5EC27B",
+"< c #62C87C",
+"1 c #045C88",
+"2 c #04618F",
+"3 c #227D82",
+"4 c #0E79A1",
+"5 c #1C8498",
+"6 c #289398",
+"7 c #38A99B",
+"8 c #1B88A2",
+"9 c #2898A2",
+"0 c #37ABA2",
+"q c #45B89A",
+"w c #44BBA2",
+"e c #55CD9D",
+"r c #68D788",
+"t c #7CFE9E",
+"y c #56D0A1",
+"u c #61DEA0",
+"i c #6CEBA0",
+"p c #80FF9E",
+"a c #82FFA0",
+/* pixels */
+"=%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%=%%%%%%%%%%%%%=%%%%%%%%%%%%$%%%%%%%%%%%%%%%%%%%%=%%%%%%%%%%%=%%%%%%%%=%%%%%$%%%%%%%%%%%%%%=%%%%%%%%%%%%%%=%%%%%=%%%%%%%%%=%$%%%%%%%%%%%%%%%%%=%%%%%%%%%%%=%%%%%%%%=%%%%%%%%$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%=%%%%%%%%%%%%%%$%%%%%@%%%%%%%%%+=@@@=%%%%%%%%%%%%%%%%%%%%%%%%%%$%%%%%%%%%%%@%%%%%%%%=%%%%%%%%=1=%%%=1=%%%=%%%%%$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%=%%%%%$%%%%%%%%%%%%%%%%%=%%%%%%%%%%%%%%=%%%%%%%%=%%%%%$%%%%%%%%%%%%%%%%%=%%%%%%%%%%%%%%=%%%%%%%%=%%%%%$%%%%%%%%%%%%%%=%%%%%%%%%%%%%%=%%%%%%%%=%%%%%=%%$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%=%%%%%%%%=%%%%%=%%$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%=%%%%%%%%=%%%%%$%%%%%%%%%%%%%%%%%=%%%%%%%%%%%%%%=%%%%%%%%=%%%%%$%%%%%%%%%%%%%%=%%%%%%%%%%%%%%=%%%%%%%%=%%%%%=%%$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%=%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%=%%%%%%%%%%%%%%%%%%%%%%=%%%%%%=%%%%%%%%%%%%%%+@=@@@%%%@%%%%%%%%%%%%%%%%%%%%%%=%%%%%%%%%%%%%%%%%%%%=%%%%%%%%%%%%%%@%%%%%%%%=%%%%%$%%%%%%%%%%%%%%%%%=%%%%%%%%%%%%%%=%%%%%%%%=%%%%%$%%%%%%%%%%%%%%=%%%%%%%%%%%%%%=%%%%%%%%=%%%%%=%=",
+"%112121311122212211122212111212212111222221221211222222221211%22122222212211122111212222112211122222222122222222222221211221111222221222212112222222222222221222112222212221221211222222112122212222222222$$1121121222221211122112%222222122121211222221122%2222112211$1112111222211$$$$$+$111221211222%22221121122221211221$12%29i%4224221222212222222222222222211112222111112222%22212211211222%22222222222222212222212112122111222222222211112222222122222222212222212112121211222222222211212222222122222222222212221112121122222122212212222222222222222222112212121221221222%22222112122222222212122222222221222122112122121%22222112222121122222112222222212222212112122111222222222211112222222122222222222222211211121122222122212212222222222222222222212211222211111222%22222122212212222122222%222121222112122121111$122211122222121121122222222222222211212122221221$$$$@O$111122112112212211111124221112122122221222212222221222121$1111211212222221222221211221121122222222221121222222122222222122221212211212112222212221222122222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221212222222222222222222222222$22222222222222222222222222222222222222222222222222222222222$22222222222222111121$$$$+$12222222222222222222222221$12224ia422222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222122222222222222222222222222222222222222222222222122222222222122222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222122222222222222222222222222222222222$11222222222222222222222222222222222222222222222122111+1$$$$$$11222222222242222222222222222222222222222222222222$12222222222222222222222222222221222222222221222222222222222222222222222222222222222222222222222222222212222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222$22222222222222222222222222222222222222222222222242222222221$12222222222222221222111111$$$$$$12222222222222222222$12224iu222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222$1122222222222222222222222222222222222222222222222222$1111111&$$$$$$22212212222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222224222222221$122222222222222222222222222111111$$$$$122212222221222$2222294%42222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%2222222222222222222222222222222222222222222222664212$11222222121111$$$$+122222222222222222222222222222222222111$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222212222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222222222222$22222222222222222222222222222221111$11%$$$$$122222222+12222424w2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$1222222221222222222222222222222222222222222222wiu612$22222222222221$11111$$$$$12222222222222222222222222221211$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%122222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222111111$$$$$$221122222222i2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222$12222222222222222222222222222222222222222222228iae41$222222222222222222211$111$$$$$122221222222222222222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211222222222222222222222222222222222222222222222222222222222222222%1222221222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222122222221$1111$$+$$1222214u4222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221112222222222222222222222222222222222222222222222122222222222222222222222222222222222222$12222222222222222222222222222222222222222222223iap41$12222222222222222222221221$11$1$$$1$1122222222222222222211222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$11122222222222222222222222222222222222222222222222222222222$222222222222222222222222222222222222221222222222221$+$1$$1%$1294222222222222222222222222222222222222222222222222221122222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$11$$1222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222226pptqq&$22222222222222222222222222222211$$1$1$1$111122222222212$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222221$22222222221222222222222222222222222222222222222222222222221$1222222222222222222222122222222222222222222222222222$222$$11$%121$122222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222221$1$$11$11$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222221222222222222222222222222222222222222222222222222222222$1222222222222222222222221222222222222222222246upppprq62222222222222222122222222222221221111$$$111%1$122222211$1222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222221$122222221$$$1$$1$$1122222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221221$$$$$1$12222222222222222222222222212222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222257uatttt<pi622222222222222222222222222222222122212221$$$$$$111111111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%22222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222222$1222222222221221$$$$$111$112212222222222222222222222222222222$122222222222122222222222222222222222122222222222212222222222222222222222222222222222222222222222212222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222$$11112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222$12222222222222222222222222222222222222222225uitpptt>tti6222222222222222222222222222222222222222222222$$$$$$1+$1112222212222222222222222221222222222222221222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$2222222222222222222222222222222212222222222222222222222221$2221222222222222222222222222222222222222222222222221$122222222222222222222$$$$$$1111111222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$$$1112222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222245669eqeittt>qut7222222222212222222222222222222222222222222222222221$O$1$$1111112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222=",
+"%2222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222222222$1222222222222222222222122222222222222222222222222222$122222222222222222222222221$$$$$$1111111222222222222222222221$222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222122222222222222222222222222222222222222122222222222222222222222222222222222222222211$$11122222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222221122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222223quw792226eti*24e5222222222222222222222222222222222222222222222222222$12221$$$$$11112222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222%",
+"=2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222221$222222222222222222222222222222121$$$$$1111112222222222222222$222222222222222222222222222222222222222222222222222222222222222122212222222222221222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222122222222222222222222221$$$12122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222$112222221222222222222222222222222222220uu62222222iq$1222222222222222222222222222222222222222222222222222222$1222211121$$$$2222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222211$22222222222222222222222222222222221221$$$$$$1112112222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222242222222221222$$$11222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222$112222222212222222222222222222222222227642222222252$120e722222222222222222222222222222222222222222222222221$122222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221221$1222222222222222222222222222222122222222222222222222222222$1222222222212222222222222222222222222222222222222221$112222222222222222222222222222222222222122221$$$$$1122222222$1222222222122222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$$1112222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222221222222222222222222222222222222222222242222222222222$22uttq2222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221221112$11222222222222222222122222222222222222222222222222222222221$1222222222222222222222222222222212222222122222222222$22222222222222222212222122222222222222222222222211$$11222221$122222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$$$212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222221222222122222222222222222222222222$$27utaiq42222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$$+11222222222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222212$$122221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222111$$$122222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222$15ipttatqq222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222%",
+"%222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222122+$$122222222222222222222222222222222222222222222222222222211$22222222222222222222222222222222222222222222222222211222222222222222222222222222222222222222222222222222211$$122$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222211$$$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222221$226qttaaiy222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222222222222222222222222221222222222222221222222222222222222222222222%",
+"%22222222222222222222212222222212222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$111$$$222222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222221122222212222222222222222222222222222222222222222222222211$11$122222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222212$$$1222222122222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222$2224etttai222222222222222222222212222222222222222222222$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222$122211$$$22222222222222222222222222221222222222222222222222$1222222222222222222222222222222222222222222222222222$22222222222222222222222222222122222222222222222122222222211+1222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222111$$$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222221222222222222212222222222222221$222246utaae6422222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222112222211$$$122222221222222222222222222222222222222222222221$2222222222222222222222222221222222222221222222222222$12222222222222222222222222222222222222222222222222222222221+$$112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222221111222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222224222$22222222222222222222222222222222222222222222222221$2222223iaaaue72222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222211$$$122222222222222222222222222222222222222222211$2222222222222222222222222222222122222222222222222221$22222222222222222222212222222222222222222222222222222222221$11$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222122222222222222222222222222222222222222222222222222224422222$12222222222222222222222222222222222222222222222211$22222229uaaaaiw422222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222221222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$1$$$222222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222222222222$1121$$111222122222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222242224222222$12222222222222222222222222222222222222222222222221$12222222eaaaappq22222222222222222222212222222222222222$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222%",
+"%2222222222222222222222222222222222222222221222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$1$122122222222222222222222222222222222222$1122222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222222222$2222211$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222224422222222%$12242221212222222222222222222222222222122222222221$122222224aaapppi52222222222212222222222222222212222222$12222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222221$$11111222222222222222222222222222222221$2222222222222222222222222222222222222222222222222221$12222222222222221222222222222222222222222222222222222222221$2222221$111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222212222222222222222222222222222222222221222222222222222222$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222%44222222222$11222222222222222222222222222222222222222222222222$122222222eaapppi6222222222222222222222222222222222222$122222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222221222222222%",
+"%12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222121$$$11222222222222222222222222222222222$222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222122222222222222$1122222211$1112222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222249442222222222$12222222212222222222222222222222222222222222222221$2222222229aatppi4222222222222222222222222222222222221$122222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$1$1122222222222222222222222222221$122222222222222222222222222222222222222222222222221$22222222222222222222222222122222222222222222222222222222221$222222222211$1122222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222240222222222222$24424422222222222222222222222222212222222222222221$22222222240uptt04522222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22221222222222222222222222222222221222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$$11122222222222222222222222222$1222222222222222222222222222222212222222222222222221$2222222222222222222222222222222222222221222222222222222222$122222222222211$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222$11249922222222222222222222222222222222222222222221$222222222248utt55522222222222222212222222222222222221$122222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222212221121$$11122222222222222222222221$1222222222122222222222222212222222222222222222222221$1222222222222222222222222222222222222222222222222222222221$1222222222222221$$122222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222242222222222222222222222222$1%29y222222222222222222222222222222222222222222222$2222222222226ee22222222222222222222222222212222221222$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222221$$$111222222222222222222221222222222222222222222222222222222222222222222222222$12222222222222224022222222222222222222222222222222222222221$222222222222222221$$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$124e9222222222222222222222222222222222222122222221$21222222222212222222222222222222222222222222222222221$122222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"$2222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$$111122222222222222221$12222222222222222222222222221222222222222222222222112222222222222222442222222222222222222222222222222222222221$122222222222222222221112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222212222222222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221212222222222222222222222222222222222222$14ew411222222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222$222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222$",
+"%1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$$11122222222222222$1222222222222222222222222222222222222122222222222221$2222222222222224422222222222222222222222222222222222222221$2222222222222222222211122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222221222222222222222222222222222$1222222222222222212222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222212222222222222222222222222222222222221%2ya4121222222222222222222122222222222222222222221$122222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222%",
+"%222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222212$$$12222222222222$222222222222222222222222222222222222222222222222222111222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222$122222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$7u32222222222222122222222222222222222222222222222$12222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212211$$$21222222211$122222222222222222222222222222222222222222222222221$1122222222222222222222222222222222222222222222222222222221$22222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222$222222222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$4412222222222222222222222222222222222222221222222$12122222222222222222222222222222222222222221212222222+2222222222222222222222222222222222222122222222222222222222222222212222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222111$$$2212121$1222222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222212222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$122222221222222222222222222222222222222222222222222222211$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%2222222222222222222222222222222222222222222222221$12212222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222111$$12122$2222222222222222222222222222222222222222222122222221$122222222222222222222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222$2222222222221222222222222222222222222222222222222222222111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222221$2222222222222222222222222222222222222222222222221$12222222222222222222222222222222222221222222222222221+1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%12222222222222212222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222212111$$$22$122222222222222222222222222222222222222222222222221$1222222222122222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222222$2222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222+2222222222222222222222222221222222222222222222222$12222222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222221222222222222222222222222222222222221111$+$122222222222222222221222222222222222222222222222222$2222222222222222222222222222222222222222222222222222222221$222222222222222222122222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222212222222222221$1222222222222222222222222222222222222222222222212222222222222222222222222222212222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222%",
+"%222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222221$$$$$222222222222222222222222222222222222222222222222$112222222222222222222222222222222222222222222222222222221$1222222222222221222222222222222222222222222222222222222222122222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$1222222222222222222222242222222222222222222222222222222$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222262222222222222222222222221$1222222222222222222222222222222222222222222222222$12222221222222222222222222222222222222222222222222222$1222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$1111$$122222221222222222222222222222222222222222222$1222222222222222222222222222222222221222222222222122222222$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$2222222222222222222222242222222222222222222222222222222$122222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222224w2222222222222221222222222$1222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222211$$$$$$$$$$O$$$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$2221111$1122222222222222222222222222222222222222222$122222212222222222222222222222222222222222122222222222221$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222232492222222222222222222222222$1222222222222222222222222222222222222222222222211$111111122122121$$$$1$$$$1$$$$1$$$$$1$$$1111111$111$1$+1$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12221121$$$$1222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222244222222222222222222221$22122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222224942242222222222222222222212221$222222122222221222222212222222222222$1$1$$1$$1$11O11$1$1$11$$1$1$1$1$1$$1$111$1$11$1$$1$1$1$11122222222$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222221$2222222221111$11111212222222222222222222122222222221$222222222222222222212222222222222222222222222222222222221$22222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222221222221$112222222222222222222222222222224422222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222212222222222222222222222246623222222221211121212211211121+2222212211$$11$11$1$1$1$11$1$1$1$111$1$$$1$$$1$$$+1$111$11$1$111122222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$$2222222222211$$$11122212222222222222222222222222221$222222222222222222222222222222222122222222222222222222221$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222422222222222222222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222222223246w22222221111111111111$11111$+1$111111$$1$$$1$$$$1$$$$$$1$1$$$$$$$2222222222222$11122112221221222222222222222222222222222222222222222$2222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222222222222222211$111112222222222222222222222222222$122222222222222222222222222222222222222222222222222222222$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222$2222221222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222112222222222222222221111113q712112111$$$$$$$1$$$$1$1$$1$O$$1$$$$$122122222222222222222222222222222222222211$2222222222212222222222222222222222222222222222222222+2222222222222222122222222222222222222222222222212222222222222222222222222222222222222222222222222222222122222222122222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222221$222222222222222222211$$11122222222222222222222222211$122222222222222222222222222222222222222212222222222222221$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222211$12222222222222221111111$$:*$$$$$$$$2222222121122122122$22212221122222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222$122222222222222222222221$$11122222222222222222222221$222222222222122222222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$112222222222222222222222222222222222212222222222222222$122222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222221$1222222212211111$$$$%234234112222222222222222222222222112222222222222222222222222222222222222222222222221$122222222222222122222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$22222222222222222222222121$$$11122222222222222222221$222222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222$222222222222222222222222222222222222222222222222222221$222222222122222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222221$122221211111$$$$112125422222222222222222222222222222221$1222222222122222222222222222222222222222222222222$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122221$22222222222222222222222221222$$$11212222222222222221$12222222222222222222222222222222222222222222222222222222$1122222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$22222222222122222222222222222222222222222222122222221$1122222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222221$2111111$$$$11122222229222222222222222222222222222222221$2222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222122222222222222222222222$12222222222221222222222222222221$$$11122222222222221$122222222222222222222222222222221222222122222222212222221$2222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222211$12222222222222122222222222222222224222222222222222222$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222221222221$11$$$$$112122222222244222222222222222222222222221222221$12222222222222222222222222222222222222222222222211222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222122222222222222222222222222222221$$11222222222221$122222222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$22221222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221++$12212222122222222242222222222222222222222222222222221$1122222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222111$$22122222221$22222222222222222222222222222222222222222222222222222222$22222212212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222122222222222$122222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222212242222222222222222222222222222211$2122222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222221222222222$122222222222222222222222222222222222222111$$$2122221$122222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222222$122222222122222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$222222222222222222222442222222222222222222222222222221$2222222222222222222222222222222222222222222222221$122222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222$1222222222222222222122222222222222222222112111$$12221$22222222222222222222222222222222212222222222222222222222$122222222222222222222122222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222221112222222222222222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$222222222222222222242642222222222222222222222222222221$1222222122222222222222222222222222222222222222221$222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$122222222222222222222122222222221222222222222211$$$11$22222221222222222222222222222222222222222222222222221222$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222111222222222222222222222222222222222222222222222222221111222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222255%422222222212222222222222222222222$2222222222222222222222222222222222222212222222221$122222222222222222222222222222222122222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%1222222222212222222222222222222222221222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222111122222222222222222222222222222222222222222222222111$O$12222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222211122222222222222222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222222222122222222745222222222222222222222222222222221$2222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222$12222222222222222222222222222222222222222222222222221+1$$$2222222212222222222222222222222222222222222222222222$1222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222122222222222222222222222222222222222221222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$22222222222222222924222222222222222222222222222222221$1222222222222222222222122122222222222222222222221$222222222221222222222222222222222222222222222222221222222222222222222222222222222222222222222212222222222222222222222222222222221222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222222$11111$$$2222222222222122222222222222222222222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222212222222211$22222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$22222222222222222222222222222222222222222222222222221$1222222222222122222225442422222122222222222222222$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222$12222222222222222222222222222222222222222222222222221$12222111$$1122122222222222222222222222222222222221222222112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222221122222222222222222222222222222222222222222222222222221112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$11222222222222224822222222222222222222222222222222221$21222222222222222246euuueq07w942222222222222222221$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$22222222222222222222222222212222222222222222222222211$222222111$1$11222222222222222222222222222222222222222211$12222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222221$122222222221222222222222222222222222222222222222222221122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222121$2222222222222224wy22222222222222222212222222222222221$11222222222245467qqitppaapaaaiy0422222222222222222$12222222222222222222222222122222222222222222122222212222222222222222221222221222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$11222222222222222222222222222222222222222222222222221$12222222212111$111121222222222222222222222222222222222221$22222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$22222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222122$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$2222222222222228y92222222222222212222222222222222222211122222222222weitpppttppapaaaaaay92222222222222222$22222222222222212222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222122222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222221$22222222222222222222221222222222222222222222222222222$222222222222111$$1111222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222221$12222222222222222222222222222222222212222222222222221$122222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222$122222222222222962222222222222222222222222222222222222$122222222226uttttpttptpaaiaaaaaaiw044222112222211$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222$122222222222222222222222222222222222222222222222222221$1222222222222222211$111212222222222222222222222222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222221222222222222$12222222222222222222222222222222222222222222222222222$1122222221222222222222222221222222222222222222222222222222222222222222222222222222222222222222212222222$$22222222222224922222222222222222222222222222222222222$12222222225uptptatttattattttattttaaiu098885322222$11222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$",
+"%22222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222211122222222222222222221$$$112222222222222222222222222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222$12222222222221222222221222222222222222222222222222221$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$22222222222222122222222222222222222222222222222222222$1222222224ippttttttttttttattttttatttatiuuuye42222$22222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$122222212222222222222222222222222222222222222222222221$122222222222222222222221$$111122222222222222212222222222$122222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222122222222222222$22222222222222222222222222222222222222222222222222221$22222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222221222222$2222222229tttttttttttattttttttttttttttttaaat62222$22466532222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222221$22222222222222222222222121$$$1112222222222222222222222211122222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222212222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$12222222221222222222222222222222222222122222222222211$122222226ittttptpttattttattattatttattattttttw2222&22etttu6422222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222221$122222222222222222222222222222222222222222222222222211$222222222222222222222222222222$$$111222222222222222222221$222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122221$1222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$22222222222422222222222422222222222222222222222222222$1222247yttttttttattttttttttattttattttttattttu42222$1qtttttw42222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%122222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211212222222222221$222222222222222222222222122222222222222222222222222211$221222222222222222222222222222212$$$12222222222212122222$1222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122121121222222222$2222222222222222222222222222221222222222222122222$12222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$22221222226q22222222222222222222222222222222222222222$122222uttttttattttattattttttttttttatttatttttae4221$25itttti52222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222122222222222%",
+"%22222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222221$11222222222221$12222222222221222222222222222222222222222222222222222211122222222222222222222222222222222111$$111222222222222221$2222222222222222222222222222222222222222222222222222222111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$$$$$$$$$122112111$1222222222222222222222221222222222222222222222222$2222222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222$$222222222qq42222222222222222222222222222222222222222$122223ettttttttttatattttttattattttttattttattttq221$12qttttu22222222222222222222212222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222111$122222222211$2222222222222222222222222222222222222222212222222222221122222222222222222222222222222222222211$$122222222222222$12222222222222222222222222222222222222222222222222222222111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222111111121$$$$$$+$$O$$12222212122222222222222222222222222222222222211$1222222222222222122222222222222222221222222222222221$22222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222221$22222222446q5522222222212422222222222222212222222222$12225wtttttttttttttttttattttattttattttatatttati642$12wttiu522222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222111$122222222$1222222222222222222222222222222222222222222222222222221$22212222222222222222222222222222222222211$$$122222222222$12222222222222222222222222222212222222222222222122222222112222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222221111121111$1$$$$$$$$$$1122212222222222122222222222222222221$12222222222222222122222222222222222222222222222222221112222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222$2222222142qtiu222222222244412222221222222222222222212$24qitttattttttttatttttttattttttttattttttttattte22$14ity84122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222221%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$$122222$1222222222222222222222222222222222222222222222222222222$122222222222222222222222222222222222222222211$$122222222$$22222222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12111111111$$$$$$$121222222222222222222222222221$1222222222222222222222222222222222222222222222222222$111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222222244266eiu52222222292672222222222222222222222221$3qtttttttattatttttttatattttttattttttatttttttti622$$2q7322222222221222222212222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$$2222$2222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222211$$2222222$22222222222222222222222222222222222222222222222222222221$112222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222221$222222222221111111$$$$$$$12222222222222222222222$1222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222+2222221422244ete2222222242y02222222222222222222222221*uittttttttatatattttttattttttttatttttatattatttq4222$142222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$11$12222222222222222222222222222222222222222222222222222211$2222222222222222222222222222222222222222222222111$$12222$222222222222222222222222222222222222222212222222222222111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$2222222222221222211111111$$$$$$11222222222222222$22222222222222222222222222222222222222222222222222211222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222$22222224222223ui3222222219i322222222222222222222222115ttpttttttatttttttattttttttatatttatttttttttatt02222$12222222222222222222222222222221$$$1222212222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222111$$$2222222222122222222221222222222222222222222222222222221$1222222222222222222222222222222222222222222222222211$$12$12222222222222222222222222222222222222222222222222222222$1222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222112222222222222222222222221$1222222222222222222222222111111$$$$$12222122222$122222222222222222222222222222222222222222222222222111222222222222222222222222222222222212222222222222222222222222222222222212222222222222222222222222222222222222$$2222222122222ei622222222yi42222222222222222222222222:ttttttattatttttttaatttttatttttttttattttttatatuw422$2222222222222222222222222221$$$$1112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222122222222222%",
+"%2222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222122222222222222222222221$$$122222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222221$$$+22222222222222222222222222222222222222222222222222222221$2222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$1222222222222222222212222222122111111$$$1122221$2222222222222222222222222222222222222222212222222221$22222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222221222222$1222254222224et02222222wit22222222222222222222222226,ttatttttttttttttttttttttttattttttatttttttttttttq22$12222222222222222222222$11111$112212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%2222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$1$$11222222222222222222222212222222222222222222222222221122222222222222222222222222222222222222222222222222222211+$122222222222222222222222222222222222222222222222222211$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$2222222222222222222222222222222221221$11$$$1$$1$1212222222222222222222222222222222222222222222222211112222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222$12212522222227t62222222iat2222222222222222222222212e,tttttttttttpattatattattttatttttattatattatatatttq22$$2222222222222212211$$$1111122222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222221$11211112222222222222222222222222222222222222222222222222$12222221222222222222222222222222222222222222222222222222$$11$$222222222222222222222222222222222222222222222222211122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$1222222222222222222222222222222222222222211$$1$O1$1222222222222212222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222212222222222222222$22221422222224i52222229aai4222222222222222222222214irittatttaattttttttttttttattttatttttttttttttttttt6222$222222222222211$1$1$1$1211122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221111122211$1112222222222222222222222221222222222222222222221$12222222222222222222222222222222222222222222222222222222$2211$11121222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$2222222222222222212222222222222222222222222222$$$$1$1$112222222222222222222222222222222222222222222$222222222222222222222222222222222222222222122222222222222222222222222222122222222222222222222222222222222222222$12222222222224i3222226utti4222222222222222222212237ti,ttttttpttptattttttttttttptpttptttttttttttptttt4222$11222222211$1$$1$$22222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$22222111$11222222212222222222222222222222222122222222221$222222222222222222222222222222222222222222222222222222221$12121$$$11222222222222222222222222222222222222222222211$222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222221$11211$$$111$22212222222222222222222222222222222222211222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222221$22222222222222q212226itttq22222222222222222222448eitt,ttttttttttttttattatttptttttpttttptptptpptttttt5222$222222$11$$$$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%222222222222221222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222111222222211$$112222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222222222$122222221$111222222222222221222222222222222222222212221$2222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222$22222222$$$$111112212222222222222222222222222222222$1122222222222222222222222222222212222222222222222222222222222122222222222222222222222222222222222222222222222221$12222222222222426424rpptu322222222222222122223qeutptt<tttpttttpttttttttttptpttttttttttptttpttttptttt5222$1&1$1$$$$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222221$222222222221$1112222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222221122222222211$$111222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122221$2222222222222222222222222222222222222222222221$122222222221$$$$11112222222222222222222222222222221$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$222222222222144uq47ttti722222122222222212223ypaatttt<ttttttpttpttttttaattttttptpptptttttttttpttpttt2211$$$$$$122222212222222222222222222222222222222222222222222222222222122222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222222222222221$$1122222222221222222222222122222122222221$22222222222222222222222222222222222122222222222222222221$12222222222221$$111222222222222222212222122222222222221$11222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$1122222222221222222222222222222222222222222221$12222222222222221$$$1112221222222222222222222222221$22222222222222222222222222222222222222222222222222222222222222222222212222222212222222222222222222222222222222222$222222222222226ti7ttpt722222222222222224430yattttttt,ttttttttppttttttattpttpttptttpttptpttttpttptte1$$$$O1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222221$$1222222222222222222222222222222222222$122222222222222222222222222222222222222222222222212222221$2222222222222222$$1112222222222222222222222222222222211122222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222221$222222222222222222222222222222222222222222222$122222222222222221121$$$$11112222222222222222222222$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222221$222222222222246tttttie2222222222222222290itaatatptpt,tttpttpttttatatttttttttttttttttttttpttppitii>&$$221$2222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$112222222222222222222222222222222221$1222222222222222222222222222222222222222222222222222222211222222222222222222$$$112222222222222222222222222222221$122222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222$1222222222222222222222211$$$11122222222222222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$22222222222222ettttte422222222222222226attttattttttt<ttttptttttttattttttattptppttppttttptttti<r:*5222222$1222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$$1122222222222222222222222222222221$22222222222222222222222222222222222222222222222222222221$1222222222222222222211$$1222222222222222222222222222221112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222$1222222222222222122222222222222222222222222222$1222222222222222222222222211$$$1222222222222222222$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$22222522222222uttttt022222222222222224uatttttttttptpt,ttttttpttptttttatttttttttttttttttpr<,,rte3222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212$$1222222222222222222222222222222$122222222222222222222222222222222222222222222222222222211$122222222222222222222121$$1122222222222222222222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222221$2222222222222222222222222222222222222222222221$22222222222222222122222222222211$$$122222222222222$1222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222$12222422222226tttptt522222222212222227ttttttttttttttt<tttpttttttttttatttttttttpttttt<<<<rttttq22222222222$222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222212222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$112222222222222222222222222221$122222222222222222222222222222222222222222222222222221211122222222222222222222222221$$1222222222222222222222222112222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222211222222222222222222222222222222222222222222212$12222222222222222222222222212222221$$$$122222222221$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222221$22221222222uitttttt422222222222222224ittttatatttpptt<tttttpptptttttttatttttttttr<,,rptpttttti42222222221$122222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$122222222222222222222222221$122222222222222222222222222222222222222222222122222222221$22222222222222222222222222211$$11222222222222222222221$1222222222222212221222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222221$122222222222222222222222222222222221111$$$11222222$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$12222222226tttttttu22222222222222223wttttttttatttttt<ttttttttptattttatttttar<<,rttttttttttt6534222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222122222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222111$$2222222222222222222222222$222222222222222222222222222222222222222222222222222222222$1222222222222222222222222222221$$112222222222222222221$1222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222$222212222222222222222222222222222222222222221$22222222222222222222222222222222222222111$$$121121$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$2222222222wttattpti222222222222240uutttatttatttttptt<tttptptttttttattttr<rrrtttppttttpttttq54462222222221$22222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222212222222222212222222222211$$2111222222222222222222$122222222222222222222222222222222122222212222222222222222$122222222222222222222222222222221111$12222222222222221$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222221$112222222222222222222222122222222222222222221$222222222222222222222222222222222222222222111$$121$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221+2222222226ttatttttt5422222222223eitttttttpttttapttpt<ppttttaappaappr<<<iiiitatttptptttteeyuqe4u2222221222$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222%",
+"%122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222111122222222222222222221$222222222222222222222222222222222222222222222222222222222$2222222222222212222222222222222222111$$122122222222221$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222$22222212222222222222222222222222222222222221$122222222222222222222222222222222222222222222111$$+1222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$2222222220ttttttttti72621222149utttttttattttttttttttt<ptptpaaptr<<<iirttttttttttttttptew55536274222222221$12222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221221$11112222222222222221112222222222222222222222222222222222222222222222222222222$12222222222222222222122222222122222222111$112222222222$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222$12222222222222222222212222222222222222222222222211+$$$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$122222222uttttttttppieu64114qyittttttppppppatatpttttt<aaati<r<rrtirppaatatatttatttttttiiuq2222422222222221$2222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222212222222222222222122222222222222222222222222222222222212111$12222222222222211$122222222222222222222222222222222222222222222222222222221$121222222222222222222222222222222222221211$11222222221$122222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222$11$1$1$22222222222222222222222222222222222222222222222222222222222222222222222222212222222222222122222222212222222222221$22222224ittatttttttptty22147yuttttttue777wqeyitttppt<<rr<rrrtrpppttppptttttttttptptttttttq542222222222221$2221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222212222111112221222222221$222222222222222222222222222222222222222222222222222222221$112222222222222222222222222222222222222212111$$122222$1122222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221122222222222222222222222222222222222222222221$2222222222222222222222222222222222222222212222222$122211$1$111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$22222226tttttptpttttptu1222345qq77675522244356ipprrr><<p<pppptttttttatttttttttttttttttttatuq4222222222222$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$",
+"%22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$$122222222222$1222222222222222222222222122222222222222222222222222222211112222222222222222222222222222222222222221221111$11222$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$2222222222222221222222222222222222222222222$12222222222222222222222222222222222222222222222222$222222211$11122222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222221$22222226ttttttttpttptti222222224222211222222217rrr<<>ppptppttttatatatttaatttattppttatattttu0222222222222111222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211111122222211$222222222222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222211$$111$2222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222221$2222222212222222222222222222222222222222222$12222222222222222222222222222212222222222222222221$22222222221$1$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$12222226tptttpttttttttt222222222222222211$1$$$-rrppt<ippttpttpttattttttttttattttttttatttty6222222222222211$122222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222121$$12222221$1222222222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222221222221$$+12222222222222222222222222222222222222122222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$1221222222222222222222222222222222222222211$2222222222222222222222222222222222222122222222221$12222222222211$$111222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$1222222wtttttttattttptt422222222221$111$$$$3$2uppptttrpttttttttttttataatattttattptttttati62222222222222222$122222222222222222222222222222222222222222222222222222222222222222222222221222222222122222222222222222222222222222222222222222222222222222122222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$1122221$122222222222222222222222222222222222222222222222222222222112222222222222222222222222222222222222222222222222222$+$1122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222221$2222222222222222$$1111222222222222222212222222222222222222222222222221222222222222222222222222222222212222222222222222222$1222222utttttttttpttptu42222$1111$$$$$$1222946ittttpt<tptptttttattttttttttatttptattttttiw222222222222222221122222222222222222222222222222222222222222222221122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212$$1111$1222222222222222222222222222222212222222222222222222222221$12222222222222222222222222222222222222222222222222222$11$112222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222221111222222222222222222222222222222222222222222222221$2222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222221$122224ipttptttappptpi511$11$$$$$$22222222224ittptttt<tttttppttttttattattatttatttttttatu6222222222222222221+11122222222222222221222222222222222222222222221112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$111$2222222222222222222222212222222222222222222222222222222221112222222222222222222222222222222222222222222222221222$2211$$112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222221122222222222222222222222222222222222222222222222222222221222222222222222222222222222222212222222222222222222222222222222222$122223itttppptttitir7$$$$$$22222222222222226tttptttt<ttttttttttttttattattatatptttatttt52222222222212222222$1122222222222222222222222222222222222222222211$112222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222122222222222222222222222$$$1222222222222222222222222222222222222222222222222222222221$11222222222222212222222222222222222222222222222222222$2222241$$1122222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222221$12222222222212222222222222222222222222222211222222222222222222222222221222222222222222222221$122122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$122226tttttitttr<<<<&$1222222222222222222220ttttttpt<tttptpttatttatttttttttttttpttttti22222222222222222222111222222222222222222222222222222222222222221$$2122222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222221%",
+"%1222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$$$12222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222122222222222221$222222222$$11222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$12222qippt<<,<<rtttt52222222222222222222224itpttpttp<rptttttptttatttttattttattttttttti222222222222222222221$222222222222222222222222222222222222222211$122222222222222222222222222222222221222222222222222222222222222222222222222222222222222222212222222222222222222222222%",
+"%222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$11$$122222222222222222222222222222222222222222122222222222$122222222122222222222222222222222222222222222222222211122222222221$$$12122222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222221$22222222222222222222222222222222222222222$1122222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222$2211$*r,,<ttttttttite4222222222222222222220tttttttptt<ttpptttattttttattttttttttatatttu222222222122222222221$1222222222222222222222222222222222222211$$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222212222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$2222$$1222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222222$122422222222211$$112222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222$221222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222221222222222222222222112122$O$$$+16rpptttttttte9ti522222222222222222222ittttttpttt<tttptttttattttttttatattttttttttt4222222222222221222221$1222222222222222222222122222222221221$1121222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222212222222222222222222222222222222222222222222222221$1222211$122222222222222222222222222222222222222222222222221122222222222222222222222222222222222222222222222222211$22222222222222211$$1222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222211$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$$$$$$$$2121etpptattttu542ut722222222222222222222uttptpttttt<ttttttpttttattttttttttataatttttu2222222222222222222222$222222222222222222222222222222222111$11222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222122222222222%",
+"%22222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222221$$122222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222662%24422222222222222211$$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222221222222222222222222222222222$122222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222$12222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$$$1111112$1224ipttttttt7422245522222222222222552224uaatptttptt,ptttpttttattattatttatttttattptte2222222222222222222222$1222222222222222222222222222222221$1112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222$122222222111$1222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222229ae14822222222222222222221$$$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222211$222222222222222222222222222222222222222222222222$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222211112222222+1224ippttptti322221222222222222093254225uttttttttttt<itpttpttttttttttttattttttttttttq22222222222222222222221$1222122222222222222222222222222$112222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$2222222222211$$22222222222222222222222222222222222222222211$222222212222222222222222222222222222222222222222129a61222222222222222222222211$$$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222221222222222222222221$12222222222222221222222222222222222222222212222111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$2228pttttttte222222222222222424wiu545227ttatttptptptp<ttttttattttttatttttttttttttptti42222222222122222222222$12222222222221221222222222212$$1122222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$11222222222221111122222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222224%2222222222222222222222222111$$122222222222222222222222222222222222222222222222222222222122222222222222222222222222222222221222222222222222222221$12222222222222222222222222212222222222222$222222222222222222222222222222222222222222222211$1222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222$222wtppttptt62222222222222222229ttueuuqitttttpttttttp<tttpttttttattttattttattttattttt6222222222222222222222211222222222222222222222222221$111222222222222222222222222222221122222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211222222222222222211$1122222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222211$222222222222222222222222222211$$1222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222$22222222222222222222222222222221222222221$122222222222222222222222222212222222222222222222$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$2225eitttttt5222222222222222222ettttattttttttptptpttt<tptttttttpttptatttattttattttattw22222222222222222222221$2222222222222222222222221$111222222222122222222222222222222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222221$12222222222222222211$11222222222222222222222222222222222222$12222222221222222222222222222222222222222222222222222$12222222222212222221222222222221$$$11222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222221$12222222222222222222222222222222222222221$122222222222222222222222222222222222212222222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$$2225ettttti22222222222222222220tttttattttttttttttttp<ttttpttpttttttttttttatttatttttti22222222222222222222221$12222222222212222222221$$11122222222222222222222222222222222111$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%22222222222222222221212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$122222222222222222211$$$12222222222222212222222221222222222$12222222222222222222222222222222222222222222222222221$222222222222222222222222222222222111$122222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222221$222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222$22245uttttu22222221222222222225ttttttattttattttatatp<<tpttttttptptptttttatttatttttttt722222222222222222222211$122222222222222221121$11222222222222222222222222222222222222221112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222221112222222221222222222222111122222222222222222222222222222222$$2222222222222222222222222222222222222222222221222221$12222222222222222222222222222222222111$$1222222222222222222222222222222222222122222222222222222222222222221222222222222222222222222222222212222222$1222222212222222222222222222222222222221$222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222122222$224425witty42222222222222222225ttatttttatttpttpttttpp<tttpttptttttttatttttttttttttattt72222222222222222222212$12222222222222222111$122222222222222222222222222222222222222221$12112222222222222222222222222222222222222222222222222122222222222222222222222222222222222222%",
+"%1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$1222222222222222222222221$$11222222222222222222222222222222$22222222222222222222222222222222222222222222222222222$122222222222222222222222222222222222221$$111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$2222222222222222222122222222122222222222$12222222222222222222222222222222222122222222222$1122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$15342227ttu22212122222222222228titttattttttttttttattt,tpttptattttttttttatttatttatttttti6222222222222222222222$1222222222222221111$12222222222221222222222222222222222222222221$$$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222211222222222222222222222222221$$122222221222222212222222222221$22222222222222221222222222222222222222222222222222221$22222222222222222222222222222222222222222$$1112222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222$1222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222$15222222utw22265422222222222226tttttttttattttattttttt,ptttttttptptpttattttattttttatttaty3222222222222222222211$122222122222211$$12222222222222222222222122222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222221222222221$$112222222222222222222222221$12222222222222222222222222222222222122222222222222222$12222222222222222222222222222222222222222221$$$1122222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222$122222222222222222222222222222222222222$112222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222$22222226tt522477652222222222220ttatttttttattttttttttt<ttttttttttttttatatttttttatatttatai02222222222222222222211122222222222111122222221222222222222222222222222222222222222221$$$11222222222221222222222222222222222222222222222222222222222222222222222222222222222122222%",
+"%22222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222$$11112222222222222222222221$22222222222222122222222222222222222222222222222222211$22222222222222222222222222222222222222222222211$$22221222222222222222222222222222222222222222222222222211222222222222222222222222222222222222222221$122222222222222222222222222222222222221$12222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$2222226itt42222442222222222222wttttatttattttaatttatttt<ttptatttptptttttttttttttttttttttay2222222222222222222221$12222222211$$1222222222222222222222222222222222222222222222211122$1122222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$22222222221222222222222222222222221$$11122222222222222222221$2222222222222222222222222222222222222222222221222222$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$122222222222222222222222222222222222222222$122222222222222222221222222222222222222$22222222222222222222222222222222222222222222221$222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221+22243etie22222222222222222224eutttttttttatttattttttatrtttttttatttttttattttattttttatttttt42222222222222222222221$22222211$$12222222222222222222222222222222222222222222222211$2222$112222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$12222222222222222222222222122222222222$$$1112222222222222221$12222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222221$122222222222222222222222222222222222221$12222222222222222222222222222222222222222222221$122222222222222222222222221222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$24euuytu64221422222222222222442utttttattttttttttatttt>tptttttttatatttttttatttaattttttattw4222222222222222222222$1122211$12212222222222222222222222222222222222222222222222111222211$1222212222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222221222222222222222222222222222222222222222222222222222222222222222222222222222212222222221$22222222222222221222222222222222222222211$$$1112222222122221$22222222222222222222222222222222212222222222222222221$222222222222222222212222222222222222222222222222222222222212222222222222222222222222222222222222222222221$222222222222222222222222222212222212222222$11222222222222222222222222222222222221$12222222222222222222222212222222222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$27tti4ttiy2224222222222222222426tttatttttttttttattttt<ppttttttttattttttatatattttttttttttt04222222222222222222222$1212$$222222222222222222222222222222222222222222222222221$122222211$122222222222222222222222222222222222222222222222221222222222222222222222222222222222%",
+"%122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222221$$$1222222222221$2222222222222222222222222222222222222222222222222221$1222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$122222222222222222222222222222222222222221$11222222222222222222222222221222222222$12222222222122222222222222222222222222222221222$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$2qttt7uty62222222222222222222224tptttttttttttatttatptrittttattttttttatttttttttttattattatti72222222222222222222211$1$$1222222222222222222222222222222222222222222222222211121222222211$11222222222222222222222222222222222222222222222222222222222222222222222221222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222211$$1221222222$22222222222222221222222222222222222222222222222222222$12222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$12222222222122212212221121221112221121121$12221121122222222222222222222222222221$2222222222222222222222222222221222222222222221$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$2itttw6e322222222222222222222eq4uttttttptttatttttttptt<ttptttatttttaatttttttttattttttattttt7222222222222222222221$$11222222222222222222222222222222222222222222222222221$12222222222211$112222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$122122222222222222222222222222222222222222222222211$$$1222221$1222222222222222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222$222222222221122111$$$$$$$$$$$$$$$$$$$$$$$O$$$$$$$$122222122222222222222222222221$1222222222222222222222222222222222222222222222$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$1ttttq5022222222226e5222222226e24itttpttttttattttttttt<ttttattttttttttttttattttttatatttttatiee622222222222222222$$$122222222222222222222222222222222222222222212222222111122222222222221$12222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222122222222221$12222222222222222222222222222222222222222222222222121111$$122$11222222222222222222222222222222222222122222222222222+2222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211121222221$$$$$$$$$11111111111111111111111+11111111$$$$$$$$$12221122222222222222$1222222222222222222222122222222222222222222222$1222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$uttu6242222222222432222222224722600tpttittattattttttt<tttttattttattatattattttttttttttttttttttu2222222222222211$11$$22222222222222222222222222222222222222222222222212112222222222222222111111222222222222222222222212222222222222222222222222222222222222122222222122222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222222221111$$$$22222222222222222222222222222222222222222222222222222$222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222$121$$$$$$11111111122222212222222222212221$22222221111111111$$$$$112222222222222$2222222222222221222222222222222222222222222222$1222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222+5ut622222222222222222222222225222225yu6ettttttttaattt,tttttttatttttttttttttattattttatatttttttt62222222222221$$1121$2222222222222222222222222222222222222222222222221$122222222222222222111$12222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222122222222222222222222222222222222222222$12222222222212222222222222222222222222222222222222222222222111O$112212222222222222222222222222222222122222222222222112222222222222222222222221222222222222222222222222222222221222222222222222222222222222222222222222222222221$$O$$11111112222222222222222222222222222221$122222222222212222111111$$$$$122222222$122222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$1qi322224222222222222222222222222222354utttttpttpttttt<tttttatattttattattttttptptttttptpttptttu22222222221$11122221$122222222221222222222222222222222222222122222221$122222222222222222222111112222122222222222222222222222222212222222222222222222222222222222222222222$",
+"%222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222222222222222$$1$$$122222222222222222222222222222222222222222222221$22222222222222221222222222222222222222222222222222222222221222222222222222222222222222222222222222222221$$$11$$111212222222222222222222221222222222221$122222222222222222222122111$1$$$$$2222$122222222222222222222222222222222222222222222$22222222222222222222222222222222222222222222122222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222$44q42225q422222222224222222222222222112utpptttttttpttt,tttttttttttttttttttptttttttptttttttttptt422222222$$112222222$1222222222222222222222222222222222222222222221111222222222222221222222211$$1221$12222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212112222222222222222222222222222222222222222222222222222222222221$21111$$$222222222222222222222222222222222222222222221$12221222222222222222222222222222222222222222222221222222111222222222222222222222222212222222222222222221111111$112222222222222222222222222222222222221$2222222222222222222222222212211111$$$$111221222222222222222222222222222222222222222$112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222$62524226e2222222222222222222222222222226uittpttttpttpt,ttatttttatattttttapttpttttpttptttttptttt71222221$111222222221$122222222222222222222222222222222222222222211$12222222222222222222221222111$1$122222222222222222222222222222222222222222222222222222222222222222222%",
+"%21222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222122211$12222212222222222222222222222222222222222222222222222222222211$2222211$1$$22222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222221122211$222222222222222222222222222222222222222$12222222222222222222222222222212211$$O1$1121222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222221$32226427q222222222222222222222222222214eutttttppttttpt,ppttttattttttattttttttptptttttptptttttttu222111$112222222122111222222222222222222222222222222222222222222111122212222222222222222222221111$O112222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222122222222222222222222222212222222222222222221$1222222221$$1$112222222222222222222122222222222222221$1222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222221$122222222222222122222222222222222222221$2222222222222222222222222222222222222$$$1$1111212222222222222122222222222222222222$12222222222222222222222224222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222221$222522qu42222222222222222222222222224qtpttttttpttttpt<rpttttttattattttttttttttptttttttptttttttt621$111122222222222221111222222222221222222222222222222222222221$12222222222222222222222222221222$$$11221222222222222222222222222221222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$22222222222222222222222222222222222222222222222222222222222221$222222222222$1$11122222222222222222222222222222222211$222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222$222222222222222222222222222222222222221$2222222222222222222222222222222222221$2211$$$1112222222222222222212222222222222221$22222222222222222222222522222222222222222222222221222222222222222222222222222222222222222222222222222222122222222222222222222222222222222221$2222226u22222222222222222222222222225ttptttttpttpttttt<ptattttttttttttatpttptpttpttptptttptppptu11$$22122222222221221$11221222222222222222222222222222222222211112222222222222222222222222222222$21$$$11222222222222222222222222222222222222222222222222222221222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$12222222222221222222222222222222222222222222222222222222222222$1221222222222221$$$$122222222222222222222222222222222$1222222222222222222222122222222222222222222222222222222221$22222222222222122222222222222222222222222222222222221$222222222222222222222222222212222212122$122222222222222222222222222222222222$12222221$$11111222222222222222222222222222263124212222222222222222247e72222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$2222225i5222222222222222222222222222qtttttttttttptttpt,tttatattttttaatttttttttttttttttttttttpppr6&412222222222222222211122222222222222222222222222222222222221$222222222222222222222212222122221$2221$$1111222222222222222222222222222222222222222222222222222222222221%",
+"%122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221112222222222222222222222222222222222222222222222222222222222221$2222222222222222221$$11112222222222222222222222222221$222222222222222222222222222222222222222222222122222222222$122222222222222222222222222222222222222222222222212222$122222222222222222222222222222222222222+222222222222221222222222222222222221$22222222121$$$11122222222222222222222222220p66q664222246322222222227tuq2222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222221222222222222222222222$2222222i62222222222222222222222222226uppttttttpttttptp,patttttttattttttapttpttptpttpttptptptpr<<iq74422222222222222221$122222222222222222222222222222222222211112222222222222222222222222222222$12222211$$$111222222222222222222222222222222212222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222111122222222222222222222222222222222222222222222222222222222222211$2222222222222222222221$$11$12222222222222222222222211$122222222222222222222222222222222222222222222222222222221$1122222222222222222222222222222222222222222222222222221$12222222222222222222222221222222222221$222222222222222222222222222222222222$12222222222221$$11122122222222222222222224trqiteiiq466et72242223216ipi62222222222222222222222222222222222222212222222122222222222222222$12222222222222222222222222222222222222222222421639$22242220542222222222245222222222222229itttttttttpttpttrittttttattttttttttttttatttttttttptttr<<pptaty0522222222222222222$12222222222222222222222222222222221112222222222222222222222222222222221$2222222222$$$1111222222222222222222222222222222222222222222222212222221%",
+"%22222212222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211122222222222222222222222222222222222222222222222222222122222222$12222222222222222222222211$$1111222222222222222222121$222222222222222222222222222222222222222222222222221222221112222222222222222222222222222222222222222222222222222222$22222222221222222222222222222222222221$222222222222222222222222222222222221$12222222222221211$$1112222222222222222223qt,pppappt7qtpte24q637y43uttq42222222222222222222222222222222222222222222222222222222222222222$22222221222222222222222222222222222222222222564uee&4625522222222222222235y3222222222222246itattttttttttttt<ttattttttpatatttpttattttpttppttpit<<pptpatttti32222222222222222111212222222222222222222222222222211$1222222222222222122222222222222222$12222222222221$$$$112222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222221$112222222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222$$$1112222222222222222222$122222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222221222222$11222222222222222222222222222222222222$22222222222222222222222222222222222$12222222222222221121$$1112222122222222222etr<pppttttuittu64uttetu4qttu442222222222222222222222222222222222222222222222222222222222222221$112222222222222222222222222222222222222222224430eu6-525522256222222222474yw422222222212222eitttttttttttttt<ttttttttttttttttttpttttattttttit<<pptptptttttte422222221222222221111222222222222222222222222222221111122222222222222222222222222222221$222222222222222221$12222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221122222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222221$$$1212222222222222221$222222222222222222222222222222222212222222212222222222221$22222222222222122222222122222222222222222222222222222221$12222222222222222222222222222222222221$22222222222222222222222222222222222$12222222222222222122111$$1122222222222226tt<aapptpttttttu64qiuiiu47ttq042222222222222222222222222222222222222222222222222222222222222222$1222222222222221222222222222222222222222222225que62$4224222ei2222222223w27t52222222222222244eitttttptttptt<tttttttatptttttattttatttpttttt<<ptttttttttatttt62222222222222222111122222222222222222222222222211112222222222222222221222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222221$$1111222222222221$122222222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222+22222222222222222222222222222222221$1222222222222222222212221$$1222222222224etrrtttttttttiutti796457427ttie324222222222222222222222222222222222222222222222222222222222122221$12222222222222222222222222222222222222222222224222$1222222ei2222222222424te42222222222222224qwyupttttttppritttattttptpttttttttttttpttt<<ttttttttttttatttt7212222222212222221$112222222222222222222222222111112222222222222222222222222222222221$1222222222222222222222222222222222222222222222222222222222222122222222222%",
+"%1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222122222222222222222222122222222211122222222212222222222222222222222222211$$$212122222222$222222222222222222222222222222222222222222122222222222222$121222222122222221222222222222222122222221222222222222222$22222222222212222222222222222222222222$12222222222222222222222222222222221$222222222222222222222212211$$11122222267tt<ttttttttti54utttttuq5764qtuu222222222222222222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222221221$1222222662222222222122etw2222222222222222224ettttttttttrtttttattttttptptpttttattt<<ttttattatptptttttttq2222222222222222222$2222222222222222222222222211$12222222222222222222222222222222122112222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%222222222222222222222222222222222222222222222222222222222222222222222212222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222$122222222222222222222222222122222222222111$$1112222221$22222222222222222222222222222222222222222222222222222222$11222222222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222221$22222222222222222222222222222222211$222222222222222222222222222111$$112227tttiriy73446e632146etttttiitu6644222222222222222222222222222222222222222221222222222222222222222222$22222222222222222222222222222222222222222222222222$22228422222222222222294eiu522222222222222224ie7etptttpt,ttatattpttptpttpttpptti<<ttttttttttttttatttttt622222222222222222221$122222222222222222222222211222122222222222222221222222222222222$11222222222222222212222222212222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222221112222222222222222222222222222222222222222111$$122221$122222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222222111$1222222222222222222222222222222222221$2222222222222222222222222222222222$122222222222222222222222222221111$122eittt,e346214q622222245qtppiueq4222222222222222222222222222222222222222222222222222212222222222222211$21222222221222222222222222222222222222222222222211$122242222222222222222023utu22222222222222222324uttttppp<itttttttttttttttttttt<ritttttattttpttptttttttt6222222222222222222111122222222222222221222222111222222222222222222222222222222222222$12222222222222222222222222211112222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222221122222222222222222222222222222222222222222222111$$$111$122222222222212222222222222222222222222222222222222222222$22222222222222222222222222222222222222222222222222222222221$122222222222222221222222222222222222212222222222222222222222222222222222$1122222222222122222222222222222222$$1ittti-32242224222222222477554342222222222422222222222222222222222222222222222222222222222222222222221$222222122222222222222222222222246222222222222222221$122222222222222222224426tt6222222221222222225uttttttttrrptttttpttptptpttti<<tttttptpttpttptttttttiq7e422222222222222222222111112222222222222222222111222222222222222222222222222222222221$122222222222222222222222222222$12222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$122222222222222222222222222222222222222222122222111$$$$22222222222222222222222222222221222222212222222222222222$122222222222222222222222222222222222222212222222222222222221$222222222222222222222222222222222222112222222222222222222222222222122222$222222222222222222222222222222222211&<ipi>122222222222222221122222212224222222052222222222222222122222222222222222222222222222222222222221$122222222222222222222222222244wuaw41222222222224221$2225522222222222222214244643222222222222222220ttiytattt<tptpttttttttttpt<<itpptttttttttttttttttte542322222222222222222222221$122222222222222212221112222222222222122222222222222222222221$122222222222222222222222212221$12222222222212222222222222222222222222222221%",
+"%22222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222211$+$1222222222222222222222222222222222222222222222222222221$112222222222222222222222222222221222222222222222222222222221$2222222222222222222222222222222222222$222222222222222222222222222222221111222222222222222222222222222222222222rr<r&122222122222222222222222222224222222342222222222222222222222222222222222222222222222222222222221$1222222222222222222222222224wyiau34672222222222eq42$222352222222222222222622222432222222222222222250637iaat,tttptptptptppt<<tttpttttttttptppipptptiq4222222222222222222222222222111222222222222222221$11222222222222222222222222222222222221$1222222222222222222222222222221112222222222222222222222222222222222222222222%",
+"%1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222221$11$$$1222222222222222122222222222222222222222222222222221$122222222222222222222221222222222222222222222222222222222221$2222222222222222222222222222222222221$222222222222222212222222222222222$11222222212222222222222222222222222224tti:$122222222222222222222222222222122222212222222222222222222222222222222222222222222222222222222222$122222222222222222222222222waaaaaequq22222222226uu5$22242222222222222222252222224222222222222222222222269yt<tttttttttttt<<prtpttptpttptpttppaatttt62222222222222222222222222222221$122122222222222211111221222222222222222222222222222222222$2222222222222222222222222222221112222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$222221222222222222222222222222222222222222222222222221$121111$$122222222222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222212222211222222222222222222222222222222222222$222222222222222222222222222222221$22222222222222222222222222222221322226wir$$1$1222222222222222222222222267654544222222222222222222222222222222222222222222422222222222222222$1222222222222222222222441247waaaaattq122222222226ie$122222222242252222222492222222222222222222222222222225qrrpttppptaprrrtpptttptptttttttpaaaaaaaq2222222222222222222222222222222211112222222122222$1122222222222222222222222222222222222221$122222222222222222212222222221$122222212222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221122222222222221222222222222222222222222222222222222222111221211$1$1222221222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222222222222+12222222222222222222222222222222222$1222222222222222222222221222212221$12222222222222222222222222234424w022254631211$1122222222222222222222225eiiyyue62222222222222222222222222222222222222222222422222222222122221$222222222222222222250q537224iiatapp6222222222221qi$2346222222459w62222222032222222222222222222222222222222e<ppptprrrrrtptpppttttttpttptttiaiaaay42222222222222222222222222222222211$122222222222211212222222222222222222222222222222222222$1222221222222222222222222222222$222222222222222222222222222222222222222222222%",
+"%222221222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222221$122222122111$$1212222222222222222222222222222222222222221$22222222222222222222222222221222222222122222222222222222222221$12222222222222222222222222222222222$1222222222222222222222222222222221$2222222222222222222222222225ee7etu522566$22211$$1122222222222222222222eppppppt62222222222222222222221222222222222222222222222222222222222222+2222222222222222224uieq673226iaiuie42222222222226i1$670222222507y522222226622222222222222222222222222222222:rrrrirrrrppttttptttttpttpttttaaaaaa6222222222222222222222222222222222121112222222221112222222222222222222222222221222222222221$2222222222222222222222221222222$222222222222222222222222222222222222222122222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222211$122222222222222222222222222222222222222222222222222221$1222221122111$$11122222222222222222122222222222222222221$122222222222222222222222222222222222222222222222222222222222221$22222222222222222122222222222222221$122222222222222222222222222222222$12222222222222222122222421446tpppttu646u-12222221$$12222222222222222226tttttppu22222222222222222222222222222222222222222222222222222222222222$2222122222222222222iw4e6405227uq96422222222222225i2$5w0222256uu76422222224w2222222222222222222222221$11$11$#<rrrrpppppptptttttptpttttpttpaaaaaq2222222222222222222222222222222222121111222222211$1222222222222222222222222222222222222222$12222222222222222222222222222221$221222222222222222222222222222222222222222222%",
+"%22222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$1122222222222222222222222222222222221222222222222222221$12222222222222111$11112222222222222222222222222222222222$222222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222$222222222222222222222222222222222$12222222222222222432248642556etttptpue6r$222222222$$112222222222222224utttptti722222222222222221222222222222222222222222222222222222222222222$1222222222222222222742546w7225e621222222222222224i2$2qu6126uutte4412222222i322222222221212111$1111$$$$$1$$22qaptatattttattattttattptptpttaaaaw422222222222222222222222222222222222222$111222221111222222222222222222222222122222222222222$12222222222222222222222222222221$122222222221222222222222222222222222222222222%",
+"%12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222122222222222222221$222222222222222222222122222122222222222222222222222222$1222222222222221121$$$11222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222122$12222222222222222222222222222222222+222222222222222222222222222222221$222222222222242224524494122242utttttituq122222222222$$1222222222222227ttttttt7222222222222222222222222222222222222222222222222222222222222222$222222222222222222445228e6422ete42222222222222225t3$25ti46ittteq2222222225i624032222111111111$$$$$$222222222-tpttttttttttttttttttttttttttaau021222222222222222222222222222222222222222$1122221111222222222222222222222222222222222222222$122222222222222222222222222222221$122222222222222222222222222222222222222222222%",
+"%22222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222221$2222222222222122222221$$$1121222222222222222222222222222$1222222222222222222222222222222222222222222222222212222222222221$11222222222222222222222222222222221$222222222222222221222222222222211$2222222222222822222222212222224utptu6e6&22222222222221$$1222222222222etpttttt9222222222222222222222222222222222222222222222222222222222222222$22222222222222124078w4230w0640ii32222222222222223t6$22ut7uptiu222222222225t626r511111$$$$$$$2222222222222222*rtttttatatttttatatttttttttptaa042222212222222222222222222222222222222222221122211111222222222222222222222222222222222222221$122222222222222222222222222222221$222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222122222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222222221$122222222222222222222222$$$11122221222222222222222222221$12222222222212222222222222222222222222222222222222222222222222211$2222222222222222222222222222222222$22222222222222222222222222222221$122222222222222222222222112222227tti622$$222222222222222$$112222222222ettttptt4222222222222222222222222222222222222222222222222222222222222221+2222222222222214eu556250iiuy329u54222222222222224tq$227iitt776222222222214r62qr$$$$$$21222122122222222222222$&ittatttttttatttttttpttptpttau422222222222222221222222222222222222222222222$1111$222222222222222222122222222222222222222221$122222222222222222222222222222221$222222222222222222222222222222222221222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$22222222222222222222222222222222222222222222222222222211122122222222222222222222222$$$11122222222222222222222211$12222222222222222222222222222222222222222222222222222222222222221$2222222222221222222222222222222222$22222222222222222222222222222221$222222222222222222222222222222224ti6222$222222222222222222$$1222222222ettttttu5222222222222222222222212222222222222222222222222222222222222222$2222222222222226u94222yy04e5222eu7541222222222225ie$1227tti324234561111$$$3&$6q221222222222222222222222222222$qittttatttatttatttapttptttti92222222222222222222222222222222122222222222222$$1$122122222222222222222222222222221222222221$2222222222222222222222222222222221$222222222222222222222222222222222222221222222%",
+"%2222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222211$222222222222222222222222222222222212222222222222222221$2222222222222222222222222222221$$$12122222222222222222221112222222222222222222222222222222222222222222222222222222222222222$1222222222222222222222222222224422$24222222222222222222222222222222$122222222222222222222222222222222ue222$$22222222222222222222$122222222wtpttte76222222222222222222222222222222222222222222222222222222222222222+122222222222222ee52224ytw222222243442222222222225ii2$22qttte6euir<>&$$$&12222q0221222222221222222222222222222$2qtttttatttttttatttttttptptw222222222222222222222222222222222222222222222221$$1222222222222222222222222222222222222222221$1222222222222222222122222222222221$222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$2222222222222222222222222221222222222222212222222222221$1222222222222222221222222222222221$$$1112222222222222222$122222222222222222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222122222222222222222222222222222221$222222222222222222222222222222222e7222$2222222222222222222221$$1222222qtttpt722222222222222222222222222222222222222222222222222222422222222222$122222222222222ee62246qw74222222222222222222222223u5$26tti<>r,>qrii622222223234222222222222222122222222222222$$4ittttttttttttttttttttttti4222222222222222222222222222222222222222222222221$$112222222222222222222222222222222222222222$1222222222222222222222222222222221$1122222222222222222222222222222122222222222222%",
+"%22222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222112222222222222222222222222222222222222222222222222222211$2222222222222222222222222222222222211$112212222222222222$122222222222222222222222222222222222222222222222222222222222222221$2222222222222222222222222422222222$2222222222222122222222222222222$12222222222222222222222222222232222422$1222222222222222222222221$1122227ttttt522222222222222222222222222222222222222222222222222222222222222222$22222224522222246622242222222222222242122222222222wq#*:>r<ittt6332622222222y6222222222222222222222222222222222$2wtattttattattttattptptti6222222222222222122222222222222222222222222212211$21112222222222222222222222212222222222222221$2222222222222222222222222222222222$1222222222222222222222222222222222222222222222%",
+"%22222222222222222212221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222222221$11222222222222222222222222222222222222111$$12222222222221$122222222221222222222222222222222222222222222222222212222222222222$1222222222122222222222222222122221$1122222222222222222222222222221$12222244422222122222222222222292262222$22222222222222222222222221$$11225itttt7422222222222222222222222222222222222222222222222222222222222222221$122424uiu7222456256522222222222122222222211$$$$$$$&&16euutttu2222222222222u6222222222222222222222222222222221$18aaaiaatttttatttatttttt7222222222222222222222222222222222222222222222222$12221$1222222222222222222222222222222222222211112222222222222222222222222222222211222222222222222222222222222222222222222222212$",
+"%22222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222122222222222222222222222221$2222222222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222111$$$1212222222$12222222222222222222222222222222222222222222222222222222222222222221$222222222222222222222222222222221$1222222222222222222222222222222$1222229412222222222222222222226ww0222$12222222222455342222222222211$1222uttttie62222222222222222222222222222222222222222222222222222222222222221$2220iittti767iii5ut72222222222212222$$$$$$$11222112$2222437w62222222222224e0222222222222222222222222222222222$24eaaaiatatattttttptpttt422222222222222222222222222222222222222222222222$1222211$2222222222222222222222222222222222211$12222222222222222222222222222222221$2222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222221222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222221222221$2222222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222211$$$2222221$22222222222222222222222222222222222222222222222222222222222222222222$222222222222222822222222222222222$1222222222222222222222222222222%2229614122222222222222222222216ii5222$2222222225yiiiiie22222222244533&26ittttptu4222222222222222222222222221222222222222222222222222222222222222$2226ttpttttiittu6i74222222222$$$$$$$111111122222222$11221223422222222222225w7122222222222222222222222222222221$24raaapptttattttttty0q022222222222222222222222222222222222222222222212$122222211$222222222222222222222222222222222221122222222222222222222222222222222222$1222222222222222222222222222222222222222222222%",
+"%2222222122222222222222221222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222122222222222222222222212222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222211$1222222222212222222222222222222222222222222222222222222$11222222222222222222222222222222222222222222221111$$$2211$22222222222222222222222222222222222222222212222222222222222222222221$122222222222240422222222222222222$222222222222222222222222222222$122ya022122222222222222212222224iw222$$2222225quutttttttw22222222eiuii>7eatppppii5222222222222222222222222222222222222222222222222222222222222222$222etttptpttty76562242$$$$$$$11111$12222222222222721$2222222222222222222214yi222222222222222122222222222222221$2149aapttttttttatpi48552222222222222222222222222222222222222222222221111122222211$12222222222222222222222222222222221122222222222222222222222222122222222$1222222222222222222222122222222222222222222222%",
+"%2222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222111$$$1$22222222222222222222222222222122222222222222222222222222222222222221$111222222222824222222222222222221$122222222222222222222222222221$227aa922222222222221222222222226u4222$22225weuttttttttttu2222425qtpppptirrttttt652222222222222222222222222222222222222222222222222144222222222221$122uppaaptpate21&$$$$$1$11$11122222222q4222222226i22$1222222222222222222222ei422222222222222222222222222222222$12226yaaaatttttttp72342222222222222222222222222222222222222222222222$1222222222221$122222222222222222222222222222221$122222222222222222442222222212222222$1222222221222222222222222222222222222112222222%",
+"%122222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222122222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222$12222222222222222222221222222222222222222222222222222221$222222222222222222222222222222222222222222221222222111$1+$12222222222222222222222222222222222222222222222222222222212222222222$122221222223022222222222222222222$122222222222222222222222222221$24iaa32222222222222222222222223w6222$$225eutppattttptpttt0quqeeuitpttttairrtpu62222222222222222222222222222222222222222222222222225uueeqw52222221$2246qq706-<q7*$$$111112576222222222224i732212222ui52$2222222222222222222222672222222222222222222222222222222221$22224aaatttttatti42412222222222222222222222222222222222222222222111112222222222221$$222222222222222222222222222222$1122222222222222224092222222222222221$1222222222222222222222222222222222221$12222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222212222222221$22222222222222222222222222222222222222222222222222222221+1$$$22222222222222222222222222222222222222222222222212222222222222212$122222222243422222222222222222222$222222222222222222222222222221%90aaa2222222222222222222224422qu2222$126utptttttttattttttitptpppptttttttttr<ir42222222222222222222222222222222221122224121222222226taptatuq322222$2211&1$$$26*&1$22222222490722122222225tye4222377ttu6&63$1222222222222222222qy4222222222222222222222222222222221$222227uatttttttt62222222222222222222222222222222222222222222222211112221222222222211$12222222222222222222222222221$1222222222222222224402222222222222222$2222222222222222222222222222222222222112222221%",
+"%222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222221$2222222122222212222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222222$2111$1$222222222222222222222222222222222222222221222222222222222222111122222221222222222222222222222211$12222222222222222422222222222$0aaaaa4222222222222222222224w67ty2221$6qupttptttatttttttttpttpptttpttptttttat<e022222222222222222222222222222222224227qe666222222222qutaaate4211$$+$$$$$$1$$422222222222222230e5222222220ttt0422wttttpu>ye722222222222222222226e5222222222212222222212222222222211$2222229wiaaaatty2222222222222222222222222222222222222222222222221112222222222222222111122222222222222222122222222$12222222222222222222482222222222222221$2222222222222222222222222222222222222112222222%",
+"%22222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$11222222222222222222222222222222222222222222222222222222$122222222222222221222222222222222222222222222222222222221$2122$1$11$222222222222222222222222222222222222222222222222222222222221$12222226212222222222222222222222$12222222222222222224222222222&iataai2222222222222222222222iiii6224*quppttttattttatttwytpttptpttptttattttappi<r521222222222244222222222222222264qu34uttiiu62212222126qureq2$1$$1$+$12222222222222222222222224qe52222225utttue60ttttptp<tptq426423422222222222282222222222222222222222222222222122112222224yueqwue4222222222222222222222222222222222222222222222221111222222222222222222$111222222122222222222222222$2222222222222222222222222222222222211$112222222222222222222222222222222222221$1222222%",
+"%22222222222222222222222222222222222222122222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222221221222222122222122222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222221222222222$22222212222222222222222222122222222222222222222222222222$222222222222222222222222222222222222222222222222222222221$2222222$$$111112222222222222222222222222222222222222222222222222222221$222224we422222222222222222222221$22222222222222222224222222556-tttaiu4222222222222222222223ttte2227<pptttptatttttttti5wtttttttttttttttatttppttrq752222222222e92222222222222240q7ipe6ipppppu7622211$1$133&$$1$1211$1222222222222222222222222222qq422226yttttttittttttttt<tpt7qiw906222222224223q32222222222222222222222222222222222+12222449642242222222222222222222222222222222222222222222222221111222222222222212222221$1122222222222222222222221$1222222222222222222222222222222222221$122222222222222222222222122222222222222$2222222%",
+"%22222222211222222222222222222222222222112222211222222222222222222222222222221222222222222222222222222222222222212222112222222222222222222222222222222222222222222222211112222222222222221222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222211$12222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222212222222$122222222211$$111222222222222222222222222222212222222222222222222222222$212246q522222222222222222222211$112222222222222222224222222yurrtttaay2222222222222222222225tti3226>tttpttpttatttttattyittttttttpptatttttttpttpar<q6632122223te322222222222140aquppp7ppppprrir72$$$$$$$$2122222222$12222222222222222222212222222e62222qttttttppatttptptt,ttttttaty6222222224226i52222222222222212222222222222222222$222222221122122222222222222222222222222222222222222222212222211222222222222222222222211112222222222222222222221$222222222222222222222222222222222222221222222222222222222222222222222222222222$1222222%",
+"%1222222211112222222222222222222222222111222221112212222222222222222222222222$12222222222222222222222222222222111222111122222222222222222222222222222222222222222222221111222222222222222$12222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222221222222222222222222222222222222221$22222222222222222222222222222222222222222222222222222222$112222222222222222222222221222222222222222222222222222211$12222222221221$$1112222222222222222222222222222222222222222222222222221$11227622222222222222222222222211112222222222222222222222222eprrpataiq222212222222222222222witq225rrtttttttttttttatttttttpttptptttttttattattpttapp<tuw7322224ut72222222222240aa6tppterirtir<<<<q655422222222222221$22222222222222222222222222222242222qtttattttttttttttt,ttttttttty422222222224w22222222222222222222222222222222222$122222222222222222222221222222222222222222222222222222222222112222222222222222222222221212222222222222222222222122222222222222222222222222222222222222122222222222222222222222222222222222222221222222%",
+"%22222222221$2222222222222222222222211$112222221112222222222222222222222222211222222222222222222222222222222221$1222221$1222222222222222222222222222222222222222222211$122222222222222222$12222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222222222222212222$12222222222222222222222222222222222222222222222222222222$22222222222222222222222222222222222222221222222222222222$11222222222222222$$111112222222222222222222222222222222222222222222222222+439u411222222222222222222222222$12222222222222222222222424ut>ttttttq222222222222222222222ypi422e<tptptttttttttttttttattattattttttttttttatttttappt<pptq52222rti5422222223qaappqppr<<<<<<rtapppttttq522222222222211122222222222222222222222222222222224uitttttttttattttt,tttttttttt612222222226742222222222222222222222222222222222$122222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%222222222221$22222222222222222222211$1212222221$1222212222222222222222222221$22222222222222222222222222222221$12222221111222212222222222222222222222222122222222221$112221222222222222221$22222222222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222222222222222222221$12222222222222222222222122222222222222222222222222222221$12222222222222212222222222222222222222222222222222222222$22222222222222222221$$111222122222222222222222222222222222222222222222222$30we222222222222222222222222222$12222222222222222222222447tt<tttttt3222222222222222222224ti6226<ittttttptattaatttatttttttttttpttaatttttttttttppttu,i7462224ttti03222223eprpr,>>,,tptttpttaptpttttpu72222222222212$1222222222222222222222222222222222247uttattttttptptt,tptttatati02222222225iu52222222222222222222222222222222221$122222222222222222222222222222122222222221222222222222222222222222221222222222222212222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222221222222222%",
+"%2222212222221$22222222222222222121$11222222222211122222222222222222222222221$2222222222222222222222222222221$12222222221$11222222222222222222222212222222222222211$1222222222222222222222$1222222222222222222222222222222222222222222222222222222222112222222222222122222222222222222222222222222222222222222222222222222$22222222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222222221$22222222222222222221211$$11222222122222222222222222222222222222222222222226ey4222222222222222222222222222$1222222222222222222222299tpt<tattti4122222222222222222226ty223e<tttttptptttttatatttatattttttatttttttttatttttttttq4$&4222224utttt7321$$-q<q<aaappptttpptttttttptpttpt7422212222221$22221222222222222222222222222222222225iitatttttttttt,ttttttttt622222222526ti42222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222$1222222222222222211$21122222222221$122222222222222222222222221$122222222222222222222222222221$1222222212211112222222222222222222222222222222222221$1122222222222222222222211$2222222222222222222222222222222222222222222222222222222211$1222222222222222222222222222222222222222222222222222222222222222211$2222222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222222221$12222222222222222222222221$$1122222222222222222222222222222222222222222222qq622222222222222222222222222221$122222222222222222222228atp<itttttw222222222222222222223utq43urtptptpttttttttttttttttttttattttattttattttattttttt321$22221114er<,>>-&22uttaaaaaappttttttatttpttttttttiq52222222211$2122222222222222222222222222122222222240ttttatttptpp,tttatttty222222222q45te22222222222221222222222222222222221+222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222122222222222222%",
+"$222222222222211111222222222222111112222222222221$122222222222222222222222221$222222222222222222222222222221112222222222211$12222222222222222222222222222222221$$11222222222222222222222221$1122222222222222222222222222222222222222222222222222222222$1222222222222222222222222222122222222222222222222222222222222222222$1222222222222212222222222222222222222222222222222222222$22222222222222222222222222222222222222222222222222222221$2222222222222222222222222221$$$2122222222222222222222222222222212222222226ur322222222222222222222222222222$122222222222222222222216tpt<tttttt922222222222222222224ettqqiyittttttttttttttatttattttattttttttttttttattttttattt621$112$$$$$$3ittttuw9ttttttttttttttattttptptttatttttti4222222222$2222222222222222222222222222222222222229tttttttatttt,pttttttty222222222764tq22222222222222222222222222222222221$222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%222222222222211112222222222221$111122222222222221122222222222222222222222221$12222222222222222222222222211$12222222222222111212222222222222222222222222222221$1122222222222222222222222222112222222222222222222222222222222222222122222222222222222221$122222222222222222222222222112212221222122222222222222222222222221$2222222222222222222222221222222222222222222222222222222$1222222222212222222222222222222222222222222222222222222$12222222222222222222222222222211$$12122222222222222222222222222222222222225uw$22222222222222222222222222222$22222222222222222222224uttt,ttttte222222222222222222226tteqiirtttatatatatatatttttttattttttttattttatattttttttttptte64$1$$212113utttttttttttattatatattttatttttttttttattttu322222222$1222222222222222222222222222222222222222ytttttttttat,tttttttt6222222224697tu22222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222%",
+"%1212222222222221$222222222211$1222222222222222221$12222222222222222222222222$2222222222222222222222222221$122222222222222221$112222222222222222222222222221$$122222222222222222222222222222$1122222222222222222222222222222222222222222222222222222221$2222222222222222222212221$$$$$$$$$$$$$$$2122222122222222222222221$1222222212222222222222222222222222222222222222122222222111122222222222222222222222222222222222222222222222222221$22222222222222222222222222222221111$12222222222222222222222222222222222222uu3$22222222222222212222222222222$22222222222222222222224etpr<tttte422222222222222222222qte4ui<ttattttattatattttttttatttttttataattttattttttttttttpptii#$12222223iatttatttatattatttattttttattptpttttttatttty922222221$1222222222222222222222222222222222222225tattttttttt,tttatttt42222222224eitu22222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%12222222222222221$2222222211112222222222222222222$12222222222222222222222211$122222222222222222212222221$1222222222222222221$11222222222222222222222222221$11222222222222221222222222222221$1222222222222222221222222222222222222222222222222222222222$2222222222222222222211$$$111111111111111$$$1122122222222222222221$2222222222222222222222222222222222222222222222222222221$1122222222222222222222222222222222222222222222222222212$122222222222222222221222222222222211112222222222222222222222222222222222220te41$2222222222222222222222222222+222222222222222222222215ip<tptt93222222222222222222222we63trtttttttttattttttttatttttttttatttttttattttttatttattpppti<:q5522227uatttattttttttttattttttttattttttattttttttttti62222221$22222222222222222222222222222222222222225yttattattt<tttttttty2222222227tttq42222222222222222222222222222222221$122222222222222222222121222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%22222222222222222111122222$11122222222222222222221$1222222222222222222222221$12222222222222222222222222$122222222222222222211112222222212222222222222222$11222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222221$222222222222222122$$$$1112222222122222221111$$$$$2212222222222222$1222222222222222222222222222222212222222222222222222221$2222222212222222222222222222222222222222222222222222222$12222222222222222222222222222222222211112222222222222222222222222222222222it622$2222222222222222221222222221$22222222222222222222652qtt<tiuw22222222222222222222226544ee<atattatatattttttttatttattattttattttttttttattttatpttaa<<tr,iu5224yttattttattttatatattatttttattttttpttaattttttttq2222222$1222222222222222222222222222222222222222257ttttttatirptattttt222222222qtttw22222222222222222222222222222222222$111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222%",
+"%2222222222222222211112122$111222222222222222222221$1122222222222222222222221$2222222212222222222222222$122222222222221222222211122222222222222222222211$111222222222222222222222222222222222$2222222222222222222222222222222222222222222222222222222211122222222222221$$$1111222222222222222222222211111$$$$122222222221$2222222222222222222222222222222222222222222222222222222$2222222222222222222212222222222222222222222222122222221$22222222222222222222222222222222222221111122222222122222222222222222259424it622$$222222222222222212222$$$$$$+$$$$$$$$$12222222222647ipt<e64322222222222222222222225222eqtptttttttttttattttttattttttttatttttptpttttttattttpptr<ttpt<tpq224ittttattttttattttttttattttttttptttttttttaatatti3222221$22222222222222222222222222222222222222222226tpattttt,ttttttpt322222222utttq22222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222221222222222222222122222222222222222222222222222222222222222222222222222%",
+"%2222222222222222221$1111$1122222222222222222222222$1122222222222122222222222$2222222222222222222222221$12222222222222222222222111222222222222222222111$1122222222212222222222222222222222222$1122222222222222222222222222222222222222222222222222222221$12222222211$$11111222222222222222222222222222221111$$$$$$2222221$1222222222222222222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222$12222222222222222222222222212222222222211112222222222222222222222222220y626tt7222$24522222222221$$$$$1$11$1$1+$$11$111$$$$&$$&122226iptr7322222222222222222222222222222qrppttttttttatatattttatttttatattpttptpttattttattttaptrrittptrrti88yttattttttttttttatatatatattttttttpptttttttattttt6222211$22222222222222222222122222222222222222222222yptttttt<ttttati7222222222uttt622222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222221111$1222222222222222222222222221222222222222222222222221$122222222222222222222222$1221222222222222222222222111222222222222222211$1122222222222222222122222222222222222222$222222222222222222222222222222222222222222222222222222221$2222221$$$$111222222222222222222222222222222222222221111$1$$$122$122222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222221111222222222222222222222222224uy93uttu24033yy222222211$$1$111$1222222$222222222113e1$$22$3$utpt-322222222222222222222222222222&:tuitttatttatttttttatttttttttttttttttttttttatttttttirrtptttpt<ttuutttttattattatttattttttttttattttpttttatttttttttttu222221$112222222222222222222222222222222222222222220tttattt<tttttti4222222226tttt622222222222222222222222222222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222221$$1222222222222222222122222222$122222222222222222222221$22222222222222222222222$1222222222222222222222222211$12222222222222111111222222222222222222222222222222222122222$122222222222222222222222222222222222222222222222222222221$1221$$$11$122222222222222222222222222222222222122222222211$1$$$1O122222222222222212222222222222222222122222222222221222$112222222222212222222222222222222222222222222222222222$12222222222222222222122222222222222222222211112221222222222222222222224y947tttu6eur-tt326&&1q6&112222222222221$22222222227utq67eqqq>rre-$222222122222222222222222222221$3057ittttatttaattttatattattttatttttttptpttttptppaarrrptptptpt<ppaattttttttattatttatttattttattttattattatttattttatttt6222221$22222222222222222222222122222222222222222225ittptpt,tatattt8222222226qtpi422222222222222222222222222222222222$112222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222%",
+"%122222222222222222222$$22222222222222222222222222221$12222222222222222222222$12222222222222222222211$222222222222222222222222221111112222222222211$1212222222222222222222222222222222222222221$22222222222222222222222122222222222222222222222222212221$$$1$1$122122222222222222222222222122222222222222222222222222211$+$$1$11222222222222222222222222222222222222222222222222$122222222222222222222222222222222222222222222122222222$12222222222222222222222222222222222222221211112222222222222222222222222942etttuettt<tr7*<q32762222222222222222$222222224qipptuititaprq3$+$1222263222222222222222222222$12226qttptttttttttttttttttttatttttpptttttttpttttpprriatttttttt<rtttttatttttttttttttattttttttttattttttttttttatttttttt0222221$122222222222222222222222222222222222222222226wetttt<ttttttt52222222223ttq222222222222222222212222222222222222$122222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222112222222222222222222222222222222122222%",
+"%22222222222222222221$$$$2222222122222222222222222221$22222222222222212222221$1222222222222222222221$122222222222222222222222222221$11222222222111$12222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222122211$+$$122222222222222212222222222222222222222222222222222222222222$111$$1$111122112222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222212221$22222222222222222222222222222222222222222212111122222222222222222222222354etttttppt<,<rqpp94112222212222222221$22222225qttttttptttte7321+$$1$24ey005222222222222222221$22446ytttttttttttatttttattttttttatttttttppttpttatrrtatatttttptt<ptattttttattttttatattttttttttttatattttttatatttttttat0422221$12222222222222222222222222222122222222222222243rttt<ttttaiu42222222224tt5222222222222222222222222222222222221$122222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222221222222222222222222222222222222222222222222222221%",
+"%2222222222222222222$222$2222222222222222222222222222$12222222222222222222222$2222222222222222222221$222222222222222222212222222221111222212211$$22222222222222222222222222222222222222222222111122222222222222222222222222222222222222222222222221111$$$$22222222222222222222222222222222222222222222222222222222222222$122222$$$$1$1112222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222221111$122222222222222222222221442qetttttr<<:ttettyw312222222222222222$$22124qytttttppttttu2226&222$$$&qttu522222222222222221$122025itptatttatatttttattttattattttptttpttttttptr<rpttttpttptttt<ttttttttattttattttttttttaattttttttttatttttttttttatttu542222$12222222222222222222222222222222222222222222222uttt>tatuyq522222222225tt4222212222222222222222222222222222222$222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222%",
+"%222221222222222222$12222$1222222222222122222222222221$2222222222222222221221$222222222222222222221$122222222222222222222222222222221112221211$112222222222222222222222222221222222222222222222112222222222222222212222222222222222222221222212111$$$$221$22222222222222222222222222222222222222222222222221222222222222$11122221221$$$1111111122222222222222222222222222222221$122222222222222222222222222222222222222222222222222211122222222222222222222222222222222222222222222222111222212222222222222222212216ttri<rip<ttuttiiq422222222222222221$6346etttttpttpttttq35qt&2222337rrtu62222222222222222$12215227ttttttttttattttttattatttttttptpttttpttpti<tapppttptpttpttrrtttttttattttttattattattttttattattattttttatttattttattwq2221$12222222222222222222222222222222222212222222224tttt<tiq542222222222225ti4222222222222222222222222222222222222$112222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222%",
+"%222222221222222221$222221$122222222222222222222222221$12222222222222222222211122222222222222222222$122222222222222222222222222222221$122211$$22222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222121111$$$1222221$22222222222222222222221222222222222222222222222222222222222222$122222222122222$$$$$1111121222222222222222222222222221$12222222222222222222222222222222222222222222222222221111222222222222222222222222222222222222222222222221112222222222222222222224522qir<<ttppt<tpttaat622222222222222222&ieqittttatttttttpi67iti&22247uttr<rr5564222222222221$22234555ttttataattttatttttttttttttatttttptpttpirrpppptttptttttttpp<tttttttttatttttttttttttaatttttttttttttatttttttatttttaa4222112222222222212222222222222222222222222222222224tttt<tq2122222222222224tt6222222222221222222222122222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222221$22222222$12222222222222222222222222$1222222222222222222221$222222222222222222221$2222222222222222222222222222222221$1211$1222222122222122222222222222222222222222222222222222$122222222222222222222222222222222222222111$$$$1222222222$22222222222222212222222222222222222222222222222222222222222221$22222222222222222221$$$$111111222222222222222222222222$22222222222222222222222222222222222222222222222222221$22222212222222222222222222222222222222222222222221111222222222222222222227e21q<raptpttt<tptpppt922221222222222222$uttttatattpttpptte5ittr6325etpptppr<<eie52222222222$2456weyiitttttatttttttatattttttattttpttptpttppt<raptpttptttttttttpp<itatattttttaattttttatattttatattttttaattttttatattttttaa72211$2222222222222222222222222222222222222222222226uttt>e41222222222222227tt7222222222222222222222222222222222222$122222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222122222221$2222222221$22222222222222222222222221$122222222222222222222$12222222222222222221$222222222222222222222222222222222221$1$1122222222222222222222222222222222222222222222222222221$22222222222222222222222212222222222111$$$12122222222221$12222222222222222222222222222222222222222222222222222222222211$2222222222222222222221221$$$$1111222222222222122222221122222222222222222222222222222222222222222222222222221$2222222222222222222222122222222222222222222222222111112222222222222222222ee-$eppppttpppr<pttppt522224242222222222$qtttttttttttttttiqettt,iyeyttttttpppi<<tu742222222&36eitttatttttttttttttatttttttattttatttttttttptr<tttttttttttptptpttpprutttttttattttttattttttttttttttttattttttattttttttattptpu4211$22122222222222222222222212222222222222222222225eeq&22122222222222227ttt6222222222222221222222222222222222222$122222222222222222122222222222222222222222222222222222222222222222222221222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222221$122222222221$2222222222222222222222222$122222222222222222221$12222222222222222221$122222222222222222222222222222222111$+22222222222222222222222222222222222222222222222222222221$22222222222222222222212222222222111$$$222222222222222222$2222222222222222222222222222222222222222222222222222222222221$22222222222222222122222222221$$$$$11112222222222222211$2222222222222222222222222222222222222222212222212221$12222222222222222222222122222222222222221222222222221111122222222222222213erq2uttattttatt<tttttt222229006222222222$5ttttttaattttatttttttt,ttttttttttttatttrrie322446q,ttttttpttpttpttttttttttattttatttattttttptttttrrptptttttttptptttttttttrppppttptttttttttttatttttttttatattttatattttattattttatai9212&52122222222222222222222222222222222222222222222222$1222222322222222wtti3222222222222222222222212222222222222$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$",
+"%22222222222221$2222222222222$$2222222222222222123224422$22122222222222222221$2222222222212222221$222222222222222222222222222222222221$1$12222222222222222222222212222222222222222222222222222222$1222222222222222222222222221212$$$$111222222222222122221$1222222122222222222222222222222222222222222222222222222222211$1222222212222222222222222222211111$$$$121222222222221$12222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222222211$12222222212222221:rti5uttttttttttritptti222222568222222222$1etiitttttttttattttatt<ttttppttpatttttttr<rie9eit<ttttttttttttttpttppttatttttattttttptpttptttti<itppttpttpttttttttatatttqptpttttttptatttattttttatattttttattttttttatttttttattttai422*iu742222222222222222222222222222222222222222222222$2222225i82222222ytpu2222222222222222222222222222222222221$222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222221222222222222222222%",
+"%2222222222222$1222222222222221$2222222222222124eu97uiti-22222664222222222221$2222222222222222221$12222222222222222222222222222222111$121$12222222222222221222222222222222222222222222222222222221$222222222222222222222212211$$$1112222222222222222222222$222222222222222222222222222222222222222222222222222222222222$122222222222222222222222222222222222112$$$$$2211222222$12222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222222221$1122222222221213tttu8ittattttttat>tti55222222222234222221$24eetttttttttattttttt<tttpttttttttatttttptr,tptt<tttttttttptpttpttptttttttttttatttttttttttttpr<ptttapttttptppttptattttttrrttpttpptptatattttttttttttatttttatattatttattttttttttttt66e&ttte2222222222222462432222222221222222222222222222$$222224w22222226tppe4222222222222222222222222222221222222$112222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222221$2122222222222222$12222224222224qitttttttt<qq59ettuw34222222221$22222222222222222211222222222222222222222222222222221$$1222$12222222222222222222222222222222222222222222222222222221$222222222222222222222211$$$1112222222222222222222222222$122222222222222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222221111$$$$$212222$2222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222222222221112222222222$$44wuy90tttttttattttrtu62222222222247e882211&eu77ttattatttttttattt<ttttttpttptttttattpptt<<pi<ttttttttptttttttttttattatttttttttattptptptt<rtpttttttpttttttttttttatttap<ttttttttttttttttattattatttattttttttattttttattatatatttttie&rptt72222222246euittti72222222222222222122222222222$122222212222224tapq2222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222221$122222222222222222$122225u45666wttttttttttt,iittttttuq222222221$222222222222222221$12222222222222222222222222222122$$1222221$1222222222222222222222222222222222222222222222222122222$112222222222222212211$$11112222222222222222222222222221$112222222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222211121$$$$11$1212212222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222222222221$122222221$14423uiyyttttataatttatr62222222222222etuu2221-ittutttttttttttttttttrttptpttpttttattattttttt<<<tttptttttptptttttttatttttttatptpttatttttppt<tttttatttttttttattttatttttttp<tpttttttttttatttattatttttttttatataatatttattattttttattt7642qtai622222227uitttttpti4222222222222222222222222222+222222112222222tiw42222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222$12222222222222222222$225uitiiiiittpttttttttt<tttttttttw222222221$22222222222222221111222222222222222222222222222211$1122222221$2222222222222222222222222222222222222222222222222222221$1222222222222121$$$111122222222222222222222212222222221$22222222222222222222222222222222222222222222222222222212211$22222222222222222222222222222222222222222222222211111+O+112211222222222222222222222222222222222222222222211$2222222222222222222222222222222222222222221122222222222222111222222&677w66yiaiyutttttttttttt,e4256we0222222etttq574:tttttttttttaattaatttrrtttttttttttttttttttptttt<,ppttptptttttpttptttttattattttttttatttttpp<<ipptttttttatttttttattttttttatp<rtttptttattttttttttttttttatatttttttttttttttttttatttttt6211&eti62222226ittpttttttte422222222222222222222222222$222224q42222222ya911222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222221%",
+"%1222222222$$222222222222222222221&eittpattttttttttttttatrrtttttttte422222221+22222222222222221$112222222222222222122222222222$112222222221$1222222222222222222222222122222222222222222222222222221$222222222222$$$1111212222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222222221$22222222222221222222122222222222222222222222222222111$111$$$$111112222222222222222222222222222222222122222$1122222222222222222222222222222222222248095642222222222222222$11221&utiitiutttttuttttttatatttrr63uitiu222240itttiii6-tttatatttatattttttttriptttttttptattttttatptppp<t<ittttptttttttptattttttattatttttttattttt<rtttptpttttttttattttttatttttattpt<tptptttttttttattttttattttttattatttatattttttatttatttti4221+453222222qitttttttttttt722222222222222222222222221$22223ww444256755w422222222222221222222222222222222222222$122222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222%",
+"%2222222221$2222222222222222622227r<tttttttttttpttttatttttrtatttttte222222222$22221222222222221$1122222222222222222222222222$$11222222222221$222222222122222222222222222222222222122222222222222222$222222221$$$1111212222222222222222222222222222222222222$22222222222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222221$12111111$$112222212222222222222222222222222222222221$122222221222222222222221222222222222222250we4222222221222221211133qrappttattttttttattttttttttireetttttuw226ittttttteqttttttttttttttttttat<tppptpttpttttttattttttpp<rttrrptttttptpttttttttattttttttptpttttatirtppttttttatttaatttttattttattttatpt<ttttttaatttattttattttatttttttttatttttatttattttattttat6221$122222225iptttpttttttttu22222222221222222222222221$2226e0euuruuii622222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222$22222222222222222w547yiprraapptttttptttttpttppt<tttttttt9222222222+2222222222222222$1222222222122222222222212211$$1222222222221221112222222222222222222222222222222222222222222222222221$122221$$$1111222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222$221122211111$$$$112222222222222222222222222222222222&522222122222221222222221222222222222222224q92242222642222244377&><ttptptptpttttatttatttatatttt<iptttttt5226iatuitttt>tttpttpttatttaattppprttttpttttatttttttattttt<rppptr<appptttttttttttatttaptttttttptppprripttttttttttttatttttttattttttatttpp<tttptttttttttatttatttatttttttttattttttattttattttattatw442$11222222etttttptpttttttt62222222222222222222222221$2225y5itttatpt722222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222221%",
+"%22222222$$222222222222222226eetapptrrppppptttttttpttttttttrtttttte2222222222$2222222222222221$122222222222222222222221121$112222222222222221$222222222222222222222222222222222222222222222222222221$2$$$$$112212222222222222222222222222221222222222222222$12222222222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222221$222122222122111$1$1$$222222211222222222211222236qew7ru754343222222222222222222222225522222222214224993449666066eequt-,tptttttttttttttttattttttttttti<pttutt642226uywwtttt<ttttttttttttttttttprrttttttttttttattttttptpi<tpptppi<pppttatattatatttttttttppttpttptrrtttptptppttptptttttattttttattttttttpi<ttttttttatatttttttattttattatttttttattttttttttttttaitt822$12222220ttattttttttatttti0422222222222222222222222$222459tatttttt022222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%12222222$2222222222222222225iatttttt<tptttttpptpttptttttpt<tttttt52222222222$122222222222221112222222222222222222222221$11222222222222222221$12222222222222222222222222222222222222222222222222221$$$$1112222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222221222222$122222222221222222222222222222222222222222222222222221$1222222222222212111$1$1$$121212222222222242584eutpp<tptueeee04122222222222222221247e0222222224222240ww996990u07ypiir<i<ttttttptpptatttttattatttttapt,pu66uq2222225565ittt<tttttpptttttttatttt<tttattptttttttatatttttp<tttttppp<rtpttttttttttattttttttptpttttrrraatttttttttttttttttttatttttatatttttttt<ttptattttattttttttttttttttttttttattttttaatttttttttttay42$1222225ittttttttppttttttate52222222222222222222111$22225ytttttatt622222222222222222222222222222222221222211$222222212222222222222222222222222222222222222222222221222222221222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"@$$12221$1222222222222222214ettaptpttt<ptptttttttttttpptttt<rttptt22222222221$222222221222221$122222222222222222212222111122222222222222222211$2222222221222222222222222222222222222222222212221$11$+$222222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222122222222222222$11222222222222212122211$$$1111122222222146e7yyeitttp<itppppptte6442122222222222246qie0742225448541446w699040w9wwettirtttrtptptttttttttttttttttattttttr,9225222222222226ettritttttttattttttttpp>tttttpttatttatttttttppt<ttptttttpt<ptaatttttttttttatpttttttttrrtppttptpttpttptptatttatttattttttttatttpt<tttttttattttttattatttttttaattttatttattttttttttattataaau91$22226ytttttptpttttttattttte6222222222222222222241$4237eattatttte42222222222222222222222222222222222222221$1122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%1$11121$222222222222222224qtttttttttti<ttptptpttttpttpttttt<ppttq2222222222$1222222222222221$222222222222222222222211$112212222222222222222211$12222222222222222222222222222222222222222221$111$$12$1222222221222222222222222222222222222222222222222222222$112222222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222222$222222222222222222222222221$1$$11$122536epattttttttrrttttttttppteq63411112222226euti6wi0060uqqey049800490y8009euipt<tpptrrtptpttttttttattattattttttttt:00652222222222223eitrttttttttttttptpttt<tttttptttttatttttttttt<ppppttptptt<rtttttttttttattttttptppppr<pptttttttttttpttttttatttttttattttttaattpt<ipttttttttatttttattttttttattatttttttattttttataattttttttu7$2226upttttatttttttttttppiiiq222222222222222136441$447tattttttte412222222222222222222222222222222222222222$1222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%22$$11$1222222222222222227tatttttatatpi<tppttttpttttttttttt<ptti42222222221$222212222221211$11222222222222222222211$$2222222222222222222222221$22222222222222222222222222222222222222221111$$$122221$222222222222222222222222222222222222222222222222222221$122222222222222222222222222222212222222222222222222222221$22222222222222222222222222222222222222222222222222221$12222222222222222222222222222221$$$$*qqrppattttpptt<pptpttptttttttty05444455349itiyy6ytituttpttateyyyyeeuuy00uuuuprrpttptrtttttpttpatttttttttttttattpt<tuuu642222222222147i>tttpttptttatttttt<ittattttatatttttttattt<ipttttttttptpirttttataattttattttttpprrrpppttatttpttpttttpttatttttttattttttttttttpp<tptttatttttttattttaatatttttttatattttttaatttttttattttatat:655utpttattttaatatttattiq7752222222222221125qu411&12qtatttttti5222222222222222222222222222222222222222212$2222222222222222222222222222222222222122222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222%",
+"%2222$$$122222222222222222qittttptptttttrrppttttpttttpttttttrrttq22222222222+222222222222221$2222222222222222222111$12222222222222222222222222211222222222222222222222222222222222122111$$$$222222221$122222222222222222222222222222222222222122222222222222$222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222221222222221$122222222222222222222222222222222222q<<<ttripttpptp<pptttptttttttttateueeyyu9eiiw75yittatttttttttttaitttttttitatti<ttttptarrtttttttttttattttttatatttptt<ttttq62222222222227>tttttttuytttttttt<ptttttttttttttttattatr<ppttttttttttptrrtttttattttatattppptr<itppptattptpttttpptptttattttattatattatattttpt>ttttatttttttatttttttatttttttattttttttttttttttattatattatt>tiitpttatattttatttatttte2222222222221222246iai522-77ipttatttte2222222222222222222222122222222222222222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222%",
+"%22221$$$112222122222222222utttattttttatprraptpttttpttpttpptp<tt622222222222$122222222222221112222222222222222221$$22222222222222222222222222221$122222222222222222222222222222221111$$$1222222222222$222222222222222222222222222222122222222222222222222211$122222222222222222222222222222222222222222222222222222222$22222212222222222222222222222222212222222222222222221$122222222222222222222222222222222227tppp<<<<<ittrti<pppttttpttptttattiaattteeiu9367tttttttttttttttatptttttattttttrttttppppa<ittpttpttattttatttttttatttt<tttttt5222222222222&etttatt73utpptptt<ptatttattttatattttttt<ppppttptptpttttptrittttttttttttttppr<tttttttttatttttpttttttttttatttttttttttttttttttrtattttatttatttatttttttttatttttttttatattttattttttttttttttrtttptttttttttttttttttat642222222222224689qiatu546<tppptttttti32222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22221$11$$1122222222222243utttttttttptptt<ttttttptttttattttt<ttw22222222222$12222222222221$22222222222222222121$2222222222222222222222222222221$112222222222222222222222222222111$$$1222212222222222$112222222222222222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222222112222222222222222222222222222222222222222222222222221$22222222122222222222222222222222225ttttattatr<<<rt<<tttttpptttttttttatttieu575547ttttttttttttttatttttpttptttptppirtpttttttttripppptttttptptttttttttptttrrtttti5222222222221$47uiitt747iitttti<ptttttttttpttttttptp<ttttttttttttttptptrippppttttttttttrrrptptpttatttatttttttttttttttttttattttttttttttttt<rappttttttttatttttatttattttatttttttatttttttpttpttttpttpt,ttttttatttattttatttttti64222222222220ttatattt927qrrppttpttti722222222222222222222222221222222222222222222$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222221222222222222222222222222222222222222222222%",
+"%1221$22211$1122222222227eytttttttptttttttt<ttptttpttatttttatt<i622222222222$1222212222222$$2222222222222222221$122222222222222222222221222222221$2222222222222222222212222111$$$1122222222222222222211122222222222222222222222122222222222222222222222222221$22222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222221$11222222222222222222222222222222245ytttttttttppptt<;,<rttttptptptptptttttt773249ettttttattttatttttttpttttttptttpt<tpttpttptptt<ttttttpttttttttattttttttpp<tptu52222222222222$114556qw5755qiti,tptataptpttttpttpttpt<tttatatttptpptttpparrappttpttptptt<tpptttttttttttttattatattatattttattttattatattapttpt,ppttpttptptttttatttttttatattttttattttattatttttttptttttt,ttttatttttttattttttttt02222222222226ttttttttu22utt<ttttttti6222222222222222222222222222222222222222222211$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2221$222222$$122222222wttttttttptptttttpttt,tttttttttatttttpp<te22222222222$1222222222222$1222222222222222221$1122222222222222222222222222222222$1222222222222212222222111$$$111222222222222222222221$122222222222222222222222222222222222222222222222222211$1222222222222222222222222222222222222222222222222222221$12222222222222222221222222222222222222222222222222221$1222222222222222222222222222222225utttttttttttttptt<pp<<,<<pttpttptttttattieyeyttttttatatttaatatttttttpttptttppp<tttptpttttttttrrppttptppttptataatttttttprrpt622222222222211$1122222222222566>ttttttttpttpttpttptt<ptttttttttpttttpttpppi<ttptttttttrrttptttttpttttttttttatttttttttttattttttttttttttttttt,ttptptttttttttttattttttttatttatattttttttttttttpttpttttt<tttatttttttttttttattty6222222222225ttttttttt029ttt<tttttpt62222222222222222222222222222222221111111111111+2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%222$122222211$$2222228itptttttttttttptpttttt<tptattttttattttp<iu22122222222$2222222222222$222222212222222222111222222222222222222222222222222222$122222222222222222221$$$$112222222222222222222222221$122222212222222212222222222222222222222222222222222222$2222222122222222222222222222222222222222222222222222222$22221222222222222222222222222222222222122222222222222$2222222222222222222222222222240weiaattttttatttptttt<ttttttr<,,,ittppttttttttttttttttttttattttttttattptttttttttpr<tttttttptpttptt<ttptttttttttttttttatptptt<tt522222222222124$2222222222222222:tttttttttttttptttpt<ittttttaatttttptttttppp<rtttptttt<ittttptptptttattttttttattttttaattttatttttaatttttttptt<tpttttptptatttttttttattttttttttttatttttaattptptttttptptt<tttttttattattttttttq22222222222220ttttattty25ettt<tttttt62222222222222222222122122122121121$$$$$$$$$$$11$1221221222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222%",
+"%211$22222222211$122244etttptptppttpttptpttpti<pttttptpttptpptt<i22442212222$122222222222$122222222222222222$1222222222222222222222222222222222222$11222222222222221$$$1121222222222222222222222222221$122222222222222222122222222222222222222222222222222222$1122222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222221$2222222222222222222222222440yittttttttttttttpttppp<rttttttttttt<r><<ttpptptpttttttttttptptpttttttaatttpttptptpt<tttpttptttptttptp<iptptpttttattttttttpttttrtt42222222222224eq6222222222222221rttttttptpttpttpttt<rppttattattttttttttttttpt<ttttpti<ptttaattttptttattatttattttttttatttattttttttatttttpttttrrtttatttpttttattttttatttttatttattttttttatttpttpttttptttt,tttttatttttttatttty42222221222227ittttttty527ittt>tttti7222222222222221121221211$$$$$$$$$$$111212111211$O$$$$$$$$$1212222211222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%21$1222222222221$$20weattttttttttttttttttttttrttattttttttttttt<te67utu75221$222222222222$12222222222222222$12222222222222222222221222222222222221$122222222221111$$1121222222222222222222222222222222$222222222122222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222221222222211$2222222222222222222422290yiatttttattattaatttttttpp<ttptptpptptpptttir<,<<tpptttttttttpttttttttttttttttttttttttrrttttpttttttttpttpp<itttttpptttttttattttttti<e222222222222220-322222222222222$utttttttttttttttttt,tpptttttttttatttppttpttttt<tttp<rtptttttttattttttatttatttttatatttttttttttattttttatattptpt<ttttttttttattttpttatttttttttattttatatttttttpttttpttpttt,pttttttatattattatt51122222222222etptpttt0424itttt<tttq43211222221221$$$$$$$$$$+1111111211111222222222111$111111111$$$$$$$$$$$12112222112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222%",
+"%11$222222222222211$%4uatpttttttpttptpptpttppttrrttppttttttttttrri6ittttiu72+222222221221$2222222222222122$1222222222222222222222222222222222222221$222222212$$$$11122222222222222222222222222222222221$22222222222222222222222222222222222222222222222122221$2222222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222222$12222222222222222662220aaaaaatttttttttttatattttptt<tttttttttttttatttitti<<,<rtttttttttttttttattatatttatpptptpp<pttttttpttpptttttpptrttttttttttttttttttptttt:4222212222222222$122222222222222$6yitttttptptppttpt<ttttttttttttatattttttptpttpt<tt<<ttptatatttttttttatttattttttattttttttttttatatttttttapttttt<tatpttpptttatattpttattttatatttttttatttttttttttttttttttt,tattttattttttatttu22222222222224itttttu02223ipppp<te6222$$$$$$$$$$$$111$21111112222122222222222222222221$11222212211111111111$$$$$$$$$$$$12221222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222%",
+"%2$122222222222222211%rattpttptpttttttttttttttttrtttttpttptptptp,titttptttte$22222222222$1222222222222222$11222222222222222222222222222222222222221$222222$$$111122222222222222222222222222221222222211$22222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222222$122222221222222226u024yaiyyywutatttatttttttttpttttt<pptptttptpttptttappttpprpr<rttttattptptptttttttttttttttttprrppttpptttttttttptpttt<itpttpttatttaattpttttt6$222222222222221$122222222222222+2346eitttttttttttt<ttptttatattttttttptttttttttt<><tpttttttttttttptatttttttttattttttattttttatttttttattttttpttt<tttttttttttttttttttttattttttttatttttttatttpttpttptpttpt,ttttattttttttttttu22222222222120tttye652222etr<<<::&$$$$111111$11111222222222222222222222222222222222222$12222222222222221222111111111111$$$$$112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%1$1222222222222222216r<pappptptttttpttpttptptptt<tptpttttttpttt<tttttpttttt:75112222221$322222222221222$112222222222222222222222222222222222222221$111$$$111122222222222222222222222222222222222222221$122222222222222222222122222221222222222222222222222221$222222222222222221222222222222222222222222222222222221$1222222222212222222222222222222222222222222222222221$11222222222222114itieaay63436ittttattttttatttatttprrptttttttttttttttttttttptpptrr<ippapptpttttttttptpttttatttp<ptttttttattttttattttatt<pptttttpttptttptttii72$122222222222222+22222222222221$$22224wttttattttpt<tttpttaatttattttttttpptpttptt<<raappptatttaatptpttttttttttatttattttatattttatttttttttttttttt<tttttttatttptptpttptpttttttttattttatttaatptttpttppttptt<tpttpttpptapttti65222222222247etpq*&$$$$$$-<<tttr-&1$1$2222222222122221222222221222222222222222222222211$2222222222222122222222221122222211111112222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%1$121222222222222224upr<rpppptttptpttttttttttttpt<atttptptpttptt<tttttttttt<iue7422121$6e72222222222221$222222222222222222222222222222222222222222$+$$111222222222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222212222222222122$1222222222222214qtpppa9422220ttttttttatatttttttatirppttpttptpttattttttatttttttptttr<<aapptttpttpttttttttttttt<ipppttpttttttatttttttttpr<ppttpttatttpttite0e42$122222222222222$22222222222221$2222226itptttttaa<tptttttttttttttppttptttttttpr<ta<ppptttttttttttttttptpatattttttttttattttattttttatatttttpttttt<ttatttttttttttttttttttptattttttatttttttttttptttttttttt<pttttptppttpppti222222$$$$$&-q<r-&1111$117rtrtppu&124722222222222222222222222222222222222222222222222211$1222222222222222222222222122222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%$122222222222222229qitptrrrpppptpttpttptpttttttpti<tppttpttttttt,tppttttttt<tppiuq79ww-eti726794w09411$1222222222122222222222222122222222221121$$$1+11212222222222222122222222222222222222222222222221$122222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222221$11222222222222222222222222222222222222222222222222222$122222222222224eittuq6422225uttttttttattttttttattt,ttpttttttttataattttttttptttptpptt<<<ppptttptptttttatttttat<ptptptttttttattttttatttppt<ptppttttppiy556543221$22222222222222$22222222222222$2222223etttpttttrrtttttttatttttttttttttpttppt<rtptr<tttptttttatttttttpppttttttttttttttattttttttatttttttapttpttt<tttttttttpttttttttttpttpttttttttptpattatttttttttpppatt<ptppptaaptirrr<r*3*-$$1$$$3rrrr7$12222224uppptr75$226722222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%$22222222222222224uttttpttr<ippttttttttttptptptttprrtppttttttptt<tpttpttttt,tttppptitrrtttieutu7iiue63$22222222222222222222222222222221222211$11$11$222222222222222222222222222222222222222222222222211122222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222122222222222$22222222222222222222222222222222222222222222222222222$12222222225eqqette643424667rpttttattttttttattttttt,ttttptptpttttttttataatttptttttppppirrrtttttttttptptttatatrrttttttttttatttatttatttappprrtpptttie764222222221$12222222222222$$2222222222221$2222222qttpttttt<tttpttptttttttatptttpttptpp<ittppp<rttttattttttptptttppatattttaattttttttattttttttptatttttttptt<ttpttttattptpttptptpttttttattattttpattttptptatpppppapt:<rrrrrrrrrrrtrirrrrrq765450pppe2222222217tppi7522$225422222222222222222222222222212222222222222222222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222%",
+"@$222222222222228weaaaaattpt<rrptpttttttttttttttptpt<ippttttptptt<rpptpttptt<ppttttppp,ppttpppttuapptre622222222222222222222222222222221111$11$122221122222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222212222221$2222222226eppiiu742247qqupuppttttttattttttatttttatrttttttttptatttttttttatttptptptttptptrrtrtpptttttptttptttt<tttttptttattttttattttttttpttrrapaau632222222222221$22222222222221$222212222222$$2222222qiuyttptrippptpttattttttttptptptptpr<<ppttttt<tpttttttttttpttaaiuwuiiattttttatttatattatttpttpttttttttptt<ttttatttptttttpptpttppptpppptttapppaaattpprrrrrrrrrrr<,,irrrrrrr<tptappppppaiuuuyitte4222222225uppie2222+222222222222222222222222222222222222221222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"=222222222222222eaaaaaaitpttptrrrttttpptpttpttpttttttrrpttattttttt<pttttttt<itppptttpi<ttttpttttaapprrpi622222222222222222222221222221111$$1111122221$12222222222222222222222222222222222222222222222222$12222122222222222222222222122222212222222222222222222$12222222222222222222222222222222222222222222222222222$12222222222222212222222222222222222222222222222222221$122222225utiuq761224qpaaaaapptttttattttttttatatttrrttptptttttttttttattttttpttttttttttttpp<<<tttttttttptttttrrttpttttpttatttttttatatttttttarrrqw6222222222222222$12222222222221$222222222222$22222222469wttttrtttttttptttaatattttttttptr<tptppptttrttttatatttttttteq74239quttttatttttttttttttatttttpttpttpttt<itttttattttpptpptttpaapptppaattirrrrrriurtrrrrrrrrrrrrp,ppaatppppttpppppiuee7qeeeeeu6222222225eppap62262$222222222222222222222222221222222222222222222222222222$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"@122222222222222yaaaaiaatptptptrrittatttttttpttppttpttrrtapttptptt,tttttttt,ttttttttp<tppttptptpaptrttttu5222222222222222222222221111$$$$122222222221$22222222222222222222122222222222222222222222222221$12222222222222222222222222222222222222212222222222222$12222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222222$112222236ue765222223eaaaauappitttattatattttattttttrtttttpttptpttttttttttttttttttttttpttptpaar<<prpppttttttpp<aptpttptttattattttttttttttttuee75222222222222222222$$2222222212221$122222222222$12222222225rtpp:uttpttptttttttattptpttppti<ppttttttttp<tttttatttttttt066796429utattatattttttattttpttppttptttttttt<ptatattttttttaapatiprrpritrrirrrrrrrryu<rttppaatpppaat,ttpptttpptpttptuq54422422255222222225uppaiq428q3$$22222222222222222122222222222222222222222222222222221$2222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222%",
+"$122222222222222waaaaaaatttttttpa<rrttptpttpttttttttpptrtttttttttt<tptptttt<tpttptttt<tptttttttpairrtttpte732222222222222222222111$$$1222222222222221$12222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222222$2222222qiu422222225wttaaaaapppattttttttttatttttttt,tttittttttttatttaatttatttptptpttpttttppppppp<<iitptptptpirttttttttttttttttatattttatttu5221$1222222222222222222$2222222222221$222222222221$22222222224qtiq29uttttttpttttttttttttttpr<tpptptpttpppi<tttttttttttttuiiaiuw089yittttttttattttattttttttttpttptttt<ptttttttpttttrrtrt<r<<<<<<r<rratptpppaappttppppptpppat<ttpppttttpppiue422222222222222222222ettti72226422$22222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222224ttttattttatatttppt<rttptptptttttttttptrrptttttttt<<aptpttt,tttttppp<rppptttttppprittttttptu5222222222222221111$$$22222222222222212211$2222222222222222222222222222222222222222222222222$22222222222222222222222222222222222222222222222222222112222222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222222221+2222222qq52222123wittttttatattttattattttpttptttttt>tieeitttatttatttaatttatttttttttattttttatttttttrrrttttttt<pptttttttpttatatttattttttttiq22221$122222222222222222$1222222222221$11222222222$1222221122243763247itpppttatttpttttttptt<tttttttttatttttrtttptttpttpptptptataty960uttttttattttttttttttattttttttttt>ptttttpp<ttr<<r<<rtttttaaaaaiatttttttttptttttattttatttrttttttttiiuu752222222222222222222221uaap722222221$22222222222222222222222222222222222222222222222222221$1122222222222222222222222222222222222222222222221222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$",
+"%2222222222222224ittttttttttttttppptr<rttpttttpttptptttt<tpttptpttp<ppttttt<ttptttpp<ppptttpptpprrptttattttte52222222222211$$$$22222222222222222222222$1222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222$12222222222222222222122222222222222222222222222222222$1222222222222222222222222222222222222222222222222222$2222222222222444wtttttttttttttttttttttpttttttptttt<tq5yttattttttttttttttttttatattttttaattttttatattar<ritttr<ppptpttpttttttttttttttttattti422222$122222222222222221$212222222222$22222222221$12221441222672$22226iietttttattttpptpt<<tpttatttttttatttirtttttpttttttttttttttpae65uttattttttattatttttttatptpttptt,ptptt<tt<<<<tapppattttttttttttttataatatpptptttttattttp>ttatattt0532122222222222222222222224uaau122222221122222222222222222222222222222222222222222222222221222$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%1222222222222223utttttatatttttaptttpt<<ttppptttttttptpttrtpttttptt,ttttttt,ttttttt<rttptttptttrtttatattpttttu75222222211$$112222222222222222222222222$1222222222222222222222222222222222222222222222222$$2222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222221$1222222222222222222222222222221222222222222222222221$2222222222223eywtattttatttttatattttttattpttptttptt<tuuuttttttttttttatttttttatttttttattttttttttttttttti<<tt<itptttttttpattttttatttatattte92222221$22222222222212221$122222222221$22222222221$122220w22226i&122222q64itttatttttttti<<ttttataattttatttttrttpttttttttttpptttttttate5ttttattttttataattttatttttttttt<<<pt<<<<tpttpttptttpttptaattttaattttttattttatttttttttt<ttttttte2222222222222222222222222222uai6224422221$22222222222222222222222222222222222222122222222222222+1222122222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222221222222222222222222222222222222222222212222%",
+"%222222222222226itttattttttattttttpttppp<<tpttptptpttttttrrpptptttt<tttpppt<tttptpt,ttttpttttti<tttttttattttpttu2222211$$12221222222222222122222222221$22222222222222222222221222222222222222222222222222$2222222222222222222122222222222222222222222222222222$1222222222222222222222222222222222222222222222222221$11222222222222222222222222222222222222222222222222221$222222222222wittttttttttttattttttattttptttttttttt<tttttttttttatatttttttttatttatttattttttattatttttatatapt<,,ttttptttptttttattttttttttttte222222221$2222222222222222$122222222221$12222222221$222224e622225$222221422ittttttpttttt<tpttttttttttatttttttt,tttttptpttpttttttattttti5tttttttatttttttttatttttptpttttp;<<<tptpttpttptppptttttttttattttttaatttpttpttttttatptt<ttttttu52222222222222222222222222224ai62226122222$12222222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222%",
+"%22222222222225uttatttattattpttptpttttttti<rtptptttptttttt<ttttttttt,tttttt,tpttttt<tttppttttt<tttttattttttttttq22211$$2222222212222222222222222222221$12222222222222222222222222212222222222222222222221$1222222222222222222222222222222222222222222222222222$2222222222222222222222222222212222222222222222222221$22222222222222222222222222222222222222222222222222222$222222222246ittattttttttttttattattttttttpttptpttt,tttttattattttttttttatatttttttttttattttattattatttttttttpt;,ttttttttttttttttttatttttttue222222222$$2222222222222221$22222222222$2222222222$1222222343842&2222222226ttpttttttttr<ttpttptattttttttttattt<tpttppttttattttttttattttutttttttttattttptppttttptttr<<<<<tttttttttttptptttttttttatttatttttttttttttttttatpttttt<tttaatiu6222222222222222222212222227iw22222222221$12222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222267uttttttttttttttttttttptptpptp<<rtpttttttptttt<ttttptpt<tptttp,tttptt<tpttttpttrrpttptpttttatatttte22$$$212222222222222122222222222222222$12212222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222222$$2222222226uttttttttatttattttttttttttattttttttttpt<ttpttttttttatataatttttattttttatattatttttttttttatattttpt<pt,,tptttptpttttiytttttatttt0022222222221$222222222222222$12222222221$1222222222$222222224uyq*2122222227upttatttatt<rtttpttttttttattatttttatt,tpttttattttattttattttatttttttatatttttatppatttt<>,,itttp<tptttppttptttttatttppttttttttaattttaatpttaattttttpttt<ttttttttu4222222222222222222222222244222222222222$12222222222222222222222222222222222222222222222222222+2222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%12222222225iittttttattttttapttptpttttttttttt<ritptpptpttttt<ppttttt<ttpptt<tttttt<tptttppprrppttttttttttattttte$$1222222222222222222222222222222222222$2222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222221$1222222222222222222222122222222222222222222222222211$1222222222222222221222222222222222222222222222222222$1222222226ittttttttttttttatattttttaattttptpptpttpt,tttptttatatttttatttttattatttatttttttattttttattttttttptp<tttt<<rptttttwytyytttatttttt08222222222221$222222222222221$1222222221$1222222222$222222222wyir022222227ttttttttati<tpptpptttttttttttttttttttt<rpttttttttatattatttttttttttttttttttttattpr<,rrttttpptpp<tttpttttptttttttattttttttttattittattatttpttttttpttttt<ttttttttty422222222222222222222222224222222222221$22222222222222222222222222222222222222222222222222212$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"@$1222222222ettptttatttattttttttttttptpttpttpptrrtttttttptpprrttttttt<ttttt,ttttt<tttttpparrtpttttpttattttttttr>&1222222222222222222222222222222222222111222222212222222222222222222222212222222222222221$1222222222222222222222222222222222222222222222222222$1222222222222221222222222222222222222222222222222221$2222212222222222222222222222222222222222222222222222$22222224qittttttatttaatatttttttattttttattttttttttt<tttttttttttttttttttttttttttatttattattttatttttattttatttr<tturppr<<ttpu40u0uttttttttti42222222222222$122222222222221$1222222222$122222221$$22222222240>i04222224ippttpttttrrtptptttttptatttaattttatatttt<ppttptttttttttttatttttttttattttattati<<<<tpiitttptpttt<tttttttttttptpattttattatttaitaatttttttttttttatttttttt<tttatttttt622222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%$$$$$$21223utppattttpttpttpttttttttttptpttaattt<>tppttpttttt<ttttttt<ttttt<tpttt<pptttptt<pttttptttttttpppp<<ri222222222221222222222222222222222222221$2222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222221$1222116uttttttttttttatttttttttttttttttttttpttpttpt,ttttattttttatttattttttttttttattttttaatttatttattttptttt<tttwitttti<<tww4e3itapttttteu622222222222222$112122222222211$222222221$122222221$12222222222$qq62222223ittttpppa<ittttptpttptttttttttpttptttttt<tttpttaatttatttptpttpptppttpaaaar<,<rtittttttttpttpptp<ttttptattttttttttttttttttttttttattatatpttptttttttpttt<ptptpttttt522222222222222122222222222222222222221$22222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%21111$$$$$5itppttttttptttttpttptptpttttttttttttat<tttttttpttt<tpptpt<tttpt,tttt<rtpptttrrtpptptttptpttpaa<<tttt522222222222222221222222222222222222211$2222222222222222222222222222222222222222222222221$12222222222222222222122222222222222222222222222222221$222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222224-q41467uppttpttptatttttttttttattttatattttptttttttpt<tttptttaattttttttataattatattttatatttttttttattttttttppt,ti0ittttttti<66239itttttpt7344222222222222221112122222222221$212222211$222222221$22222222221124222222217tpptppt<rtttttttttttttatatttttttttpttttt<ttttttttttttttttttttttpptatr<<<<rtitppttttttttttttttp<rtpttttttattattttttatttatatttatiatttttttttttpttptttttrrtttyq66qq422222222222222222222222222222222222221$12222222222222222222222212222222222222222222222222211$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222211111><<<ttatatttttppttpttttttpttttttttttppr<<pppptptptrrpptpt<tpptt,ttpt<tttttpp<tttttttpttttttt<<titttt622222222222222222222222222222222222221$1222222222221222222222222222222222222222212222221$12222222221222222222222222222222222222222222222222222$222222222122222222222222222222222222212222222222222$122222222222222222222222222222222222222222222222226u,tuquittttttttttttattttttttaatattatttttttttptptppp<rtpttttttttatttttttatttttttttattttatatttttttttttatatttr<t09tttttttaair6$&4tttttttee4222222222222222221111222222222221112122212$112212221$2222222221$121222222224tuupt<rippttatttptpptttattttattttpttpttt,tpttttattttttppatttptpp<r<ritritappttttttppttpttttttpt<tttpttttttttttttaatatttatatattttattatttttpttptttpttptrtu7342242222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222eirprrrrittaptppttttatptttptttattattppttt<tatttttpprrtttti<pttt,ttpi<tptptp<tttptptpttptpt<rirtatttty22222222222222222222222212222222222221$2222222222222222222222222222222222222222222222221112222222222222222222222222222222222222222222222222211$122222222222222222222222222222222222222222222222221$22222222222222222222222122222222222222222222222222yt,tttttpttttttptpatttatttattttttttttatttatpttttttpp<ttttttatttttttatttttttttttaatttatttttttattattttttttttt<tt36ittuttttati6&6&itatttt062222222222222222221111222222222211$1212211$+$$$1$$12$1222222222$1122222222221646r<tpttpttttpttttttttttatttptpttttttttt<tptttttttatpppappt<r<<triitpapppptttptpttttttptpttptt<tpttttttttaatatttttttttttttttattttatttatptttttptttttt>uq4222221222222222212222222222222222222222222222$12222222122222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222%",
+"%22222222230tttprrirr<r<<ppaaatpttpttppttttttattptttprrrtppptttt<pptpt<pttt<tpt<ttttptrittttptttttttr<rttatttattu22222222222222222222222222222222222222$12222212222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222221qtt<tttttptptptttttttttttattttttttaatttttttattttttttt,ttttttttatttttttatttttttttattttttttttttttatttattttptpt,tt42qeyyttatttt64rqr<raaape22222242222222222221211111222222222111$$$1111+11111$$O$112222221$2222212222222221qrtttpttttattttttttattpttptpttpttptttt,pptpppattataptr<<rrrrtpatttppttpttpttttttttpttttttttt<ttttttttttatttttttttaaiattatatttattttttatptttttttttpt-332222222222222242442122222222222222222222222221$12222222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222%",
+"%222222222yttpttappttrrtrrrrrrtaatppttpptattttattptptttrrrpatptttrpttp,ppt<<tpt<tttpprrtttttttpppt<<rtpptttttttty22222222222222222222222222222222222222112222222222222222222222222222222222222222222221221$2222222222222222212222212222222222222222222222222221$222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222223qitt,ttttptttttttptttttttatttattttttttttttattttatptptt,tttptattttttatattttttatattttttatttatattattttatttatpttp,tt7145wittttattu7ttitr<rpi7222356q22222222222212111122221222221+$11$1211$1221111+$1$122222$122222222222222$17tttttttattttapttptttttttttttttttttptt<tpttppaattrrr<rtirppppttttapptptttttpttpttptttpttpttt,tptptatattttttatttttttttttttttttttatatttttttptpttttti&1222222222222224434422222222222222222222222222221$1222222222222222222222222222222222222222222222122221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222euttttaptpptpppirrrrirrrpppppptttttattttttptppi<rpptttp<rptt<rpt<appr<ttpprrpptpttptttr<rttpttattttttti222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222221$122221222222222222222222222222222222222222222222221$212222222222222222222222222122222222222222222226ttpt<tttttttpttttptptttattattttttttttttttatttttttttttt<tpttpttttttttttattttaatttttttttattttttatttttttattpptt<rpte26witttttttttutttpprrq62222weitq4222222222222111$22222211211O12112221$1222221$21$$1121$122222222222221$$2etpttttattttttttttttttttttttpttttptpttt<paptt<rrrrrrrppptttpttttttttttpttptptptttttttppttppt,ttttttattttttttttttttattatattttttttatttttttttptttppt7$1222222222222221222222222222222222222222222222222$1222222222222222222222222222222122222222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222%",
+"%122222222567ipppptttppptaappprrrrrirrrptatattttptptttppaprrrtttpprrttt<tp<ppa<ttttrrppptttptt<r<iptttpttttattttw222222222222122222222222222222222212221$1222222222222222222222221222222222222222222222211$1222212222222222222222222222222222222222222222222221$222222222222222222222222222222222122222222222212221$22222222222222222222222222221222222222222222222ettprrtptttptttptttttattttttttaatttattattttatttttptpttt<tttttttattattttttatttttttattttattttattttattttttttiqtt<pppu4ettttttattttptpptppe&$1$22ytttte2222222222222211112222211$$$12212221$122222$12221$$11$12222222222211$122qttttptttattttptptatttatpttpttpttttttpp<rirrrrrriappptppptttttatttpttpttttttttpttppttttttttt,ttptttttttatttaatttatttttttatttatttttttatpttpttpttu72$2222222222222222222222222222222222222222222221222$2222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222%",
+"%222222222222ippattttattttatttaaptrrrrrrrtrtaapptttttttttptr<tttppt<ppp<tt,tpt<pppr<ttpptpttt<<rappptttttttpttti4412212222222222222222222222222222222222$1222222222222222222222222222222222222222222222222$121221221221221221221212121211$111$1111$111$11$11122$222222222122122121212122212122222222222222122222221$22222222122222222222222222222222222222222222226tttt>ppttpttpptptttttttttpttpttatttttttttttttttttttttpt<tptttattttttttttattttttatttttttttatttttttttttattti5utrttti0wttttttttatttttttty4221$$$qtpptt75222222222222221111121$1121$1122222$122222$2222221+$11122222222211$12224uutttttttttpttptptttttttttttttpptpttrt<<<rrtttttttaatttattattttatttttttttttattttatttttttttt,ttttpttttatttttattatttaattttttattattttaatttatttueq522$2222222222222222222222222222222122222222222222222$1222222222222222222222222222222222222222222222222221$1122222222222222222222222222222222212222222222222211122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222utpttttttattttttttttppppppr<r<<rriitppttpptttptp<<ippp<<pp<tt,tp<rpttrtpppattr<<tataptpptpttpttttteq622222122222222222222222222222222222221$1222222222222222222212222222221222222212222212221+11111111111111111111111111111$$$$$$$$$$$$$$$$$$$$$11+$11111111111111111111111111111$111$112222221222211$122212222112222222222222222222222222222222222227tttt<tttttttttttttptttptttttttttttatattttatatpttptptttt<ttttptttattatattttattttttttatattttttattatatttttatt07ietttai9utattattttttttytt6334242&&erptpte522222222222221$1111$12222$1222222$122222+1222221$$1112222222211$2222229uttttppttpttttttpttppttptpptptptt<<<<<<patttttpttttttttttttttattptptpttpttttattttttatatttt<tttttttttttattattttattttttatattttttttttttttttty522222$2222222222222222222222222222222222222222222222221$2222222222222222222222222222222212222222222222222222$222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%122222222222utttttttattttttattttttttttaaapt<<<rtpitptpptttttp<tpppp<pp<<t,tt,pp<rttttprr<<tpppttttttttttttpttpti021224122222222222222222222222222222221$1222222222122222221$11111$1111111$111111111$11111O$$$$$$$$$$$$$$$$$$$$$$$$$$$$$222212222212222222221$$O$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$1111111111111+11111111111111111221222222211222222222222222226itttt<ttptpttptttttptppttptttttttttttaattaattttttttptptt<ttttpttttttttttttttattttttatttttttatttatttttttatttq3qrptttt9wttttttttttttu3uu4eu45w4763rrippu2222222222222212$1$$2221221$222221$122221$22222211111112222211$122212246ttttttttttttttttttpttpttpppiitr<<<ttpt<patptptpttattttttttttttatttptttttattttttttttttttattt<tttpattttattttttttttttttattttattattatattttttt9222222+2222222222222222222222222222222222222222212222221$1222222222222222222222222222222222222222122222222221$222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222%",
+"%222222222222utttatttttttttatttatptpttttpapaaatt<<<<trtpptpttppt<<<pa<tt<t,tt<pprptttti<rppttpttptpttptttptttttt9322546222222222222222112222111111111111$$11111111111111111$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$1221122221222122122222122212222222222222222222222121$222211222221222221222122212222222222$$$$$$$$$$$$$$O$$$$++$$$$$$$$$$111111111111112222222222222225rttttt<tpttttttptpttttttttttpptttattttttttttttttptpttttpp>tpttttttttaattttttatttttatttatttatttttttatttatttttw0-iptttt0yttattttttttt62740tt4utwii6er<rrq22222222222222221$$12222222$122221$22221$2222221$2221$1122211$1122245575euttttptttpttptptttttttttrt<<<<apppttt,ttttttttttttttttaatttttttttttpttptttattattattatttttt<tttttttatttttataatatattatttattatiatttttttttate622222$2222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222211$1222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222ettttttttttatttttttttttpttpppttttatpttr<<<ip<ttttttp<<ppp<p<p<p<pr<ppttr<rppppttttttttttptptttttttt4244rui6222211111111111111111$$$$$$$$$$$O$$$$$$$$$$$$$$$$$$1222212222222122222221222222221$2222222222222222222222222222222222222222222222222121$12222222122222222222221222222222222222222222122222$12222222122221221$$$$$$$$$$$$1111111111111112epptttt<ttpttttttpttpttptttpttpttaatttttttttttattptttptttt<tpttttttttatttttttttttattttttttttttttatttttpttttttyu,ppttatyittttttttttti2407utt4tiettiwtpe3$2124222222222221$11122222211111222$12221$122221$1222111111111122127etu7506utptttpttpttttttttttirrr,tttattttttt<tttttttttattttttttttatttatttatpttttttttattttttttatpt<ttptttattatttattttttttttttattatattttattttttttue52222$1222222222222222222122222222222222212222222222222$1122222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222224qtttttaattattatattttpptttttppttttttttttppp<<,,tttttppp<<pr<,t<<<<<pptr,<tppppttpttpttptttttttttttti37q6itpe2111$$$$$$+$$$$$$$$$$21121221121$1122221211222212122222222222222122222222222222221$1222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222122222$122212222222212112211222122111$$$$$$$$$$%$$$2rtttttt<ittttpptttttttttpttttpttttttttttttattttttttttttpt,ttpttpatatttttattttpptttatttttatattatattttpttttttttut,ppttttttttattatatttu23tttte0tttttt0tty22$&2w622222222211121$12222222$12221$12221$22222$11222111$11$1112224itttttuq9yttttttttpttttttt<<<rttttttttttptptt,ttpttptttttaatattattttttatttttttattttttttattttttttt<tttttttttttttttttattttattttttttttatttttaatatttte2221$2222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222211$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%122222222226ttttatatttttattttttttttpttpttptatttttttppttppt<<,<tpppp<rp<t,,,p<par<<ptpttttptttpppttptptttttttttr>,,,,<r-$$$$1221212222122211222222221222$1222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222221222221$22222222222222222222222222222122222222222222222221$122222222222222222222222222222212221211122225,,,,>,<;,><,<ppptttttttpttttttttttttattttatttttttpptttttt,tttptttattttttatattttttattatttiatattttttttttttattttut<tpptttttatttttattttu46ttttwittttit9e642226&>722222221111122111122221$12222$22211$22221$222222211$$12222225ttttttptiyytttptpptttt<<,<ttpptttttattpttpptt,tttapttptttttattttatatttttttatattttttattttatttttttt<ttpttattttttttttttattattttttttttttattttttattptti4222+2222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222222$122222222222222222122222222222222222222222222222222$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222%",
+"%22222222226ittttttttttttttttttattpttttttptttttaptpttttttppppp<,<<<ppr<p,>,,<p<<rtpptttttttttttptti<,<<<,,<<<<<rtttttpi922112222222222222222222222222222$1222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222221222222222221$22222222222222222222222222222222222222222214uttpttpp>ttpt<<<<,<<<<,<<<<rtttttttttttttttattttatttttptpt,tttttttttttatttttttptttttttttattttattatattptpttttattirtttttatttttttttttti927ttttttttttu7432125764e>&&2222221$122211$1122221$2211$1221$22222$122222221$+122222224ittttptttttptttttpr,,,<ttttpppttattttattttttp,ttttttttttttttttttttttttttttttttttattttaattttattttt<tttttttatttaattttatttttatttaatttattttttttttttttt6222$2222222222222222222222222222222222222222222221221$1222221222222222222222222222222222212222222222222221$222222222222222222222222222222222222212222222222222$122222222222221222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222226ttttttptptatttttpttpattttattttpttpttttttpttpptpttpttpt<<,<r<<;;<,<<tpppptt<<,,,,,,<<,,<tttttttttttttttttttaw22222222222222222222222222222221$1222222222222222222222222222222222222222222222222$1122222222222222222122222222222222222222222222222222$22222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222229attttttt,ttpttttttttttrppttr<<<,,,,,<<<<<itptttttppptttttt<pptttpttptpttpppttpttpttttttppttattttttptpttttptptpt,tttpttttttatttattye5450ttttattttiu222255ue04yt7$$11111$122222211122222$1222$1222$12221$12222211$11$112222229ittptttatpttptr<<<tttppttatttttttatttpttpptt<ppptptttatttttttattttttattttatttttttattttttatttttttetttttattttattttttatttattttattattttatttttatttattt0221$2222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222211$222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222%",
+"%22222222214uttttttttttttpttttttttattttttttttttttptptttttttpttttpppptpr<>oo#,<<<<<<<<<<tttttttrtttttttttttptttttttattty822222222222222222222222222222222$1222222222222222222222212222222222222222222222222$2222222222221222222222222222222222222122222222222221$22222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222uapttptpt<tttttttttttpttptpttttitttttttittrr<<<<<<<<<<<<ttt,ppttppttppttttppttttttttpttptpattttatattttttpttttttp,ttttttpptttttttttuyy9e8ttttttttt942225u6yti56u5221$11$1122222221$122221$122$1221$2221111222221$111$22222222uittttttttpp<<<rtpttttpptpttttatattttttttttttr<ptptttpttatattttttaatttatttttttatattttttttttatattarttpttttttttttattttttttttttttttttttttatatttttttttq222+2222222222222222222222222222222122222222222222221$1222222222222222222222221222222222222222222222222211$122222222222222222122222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222227ttttpptttttpttpttttttttattatpppttptptpptpptpptppt<<<<<<<<<;;oo;><ppttrtitpptttptttttptpttptttptttttataatt8222222222222222222222222222222222$1122222222222222222122222222222222222222222222221$1222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222220aatttttpt<ttpttttttttttttttttpptptttpttttatiiptttrtrrttr<<,;<<,<,<r,<rttptappapppppttptpapttatatttptppptpttttttt,ptttttttttttttatttttew6uttattpptw42225t0tt9443222111$$12122222221$12222$122$112$1212$1222212$112221$122222witptppppi<<<ittttttttttttttttttattttttptttpttt<ttttttptattttttttttttatatattttttattttttttttttatppi<tttptttaattttttattttttttattttttatttttatttttttttu5222$2222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222226tttttttptptttttptpttattttttpppapttppr<<<<<<<<<<<<rtrprtrp,<,;;;<<<<<tppptpppttttptpttttttttttttttttttaati4222222222222222222222222222222221$1122222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222211$12222222222222221222222222222222222222222222222221$222222222222222222222222222222222222222224uaapttpttt<ttttptptttpttpttptttttttttttttttttaatpppppptttptt,<ttritittr<r<<<<<<<<rtptttptaatttttttattppttttptpttt,tptptttpttattttttttai08ettttti09422222iu792222422111$+$1122222222111211$121$111$121$1222221$1222221$222634ytappp<<<<trtpttpttpttpttpttatpttttttattttptttt<tptptttttttttattatttttttttttattttttttattatttttttpp<ttttttttttttatttattttttatttaatttatttttttttatttai9222+222222222222222222222222222222222222222222222222211122222221222122222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222$222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222212222222222222222222222222222222222222222221222222222%",
+"%12222222222etttptptpppatttapppppaaattr<<<<<<<<<rrtirtrtprrittttpppprrt<<<;<<<rptr<<<aaappttttppttttttttttttttptaaaiau2222222222222222222222222222222221$2222222222222222222222222222222222222222222222221$1222222222222222222222221222222222222222222222222222$22222222222222222222222222222222222222222222222222$122222222222222222222222222222222222222229aaattpttt<itppiqqeueeetptpptttttptpttttttttttttttttttttttptt,pptptppttttrtiirtrrtr<r<<<<<r<<tpaatttappppppattttap<pttpppttpttttatttttt630ttttpptuue92222ey54224e642221$111$1111122211$1221$121$11$112$1221211112222221$14ue2806>qritrtttttpttptttttptttttttttttatttttttpttt<tptttttttttattttttatttttttttaatttttattttttattttttt,ttttattttttatttttttaattttttttttttttattttatttatttu422$22222222222222222222222222222222222222222222222222$222222222222222222212222222222222222222222222222222$222222222222222222222222222222212222222222222222221$222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222wu77ytptppppaatar<<rrr<r<rrtrtrt<titrrpppptpppaatttttpp<rtrrr<<<<<prrpprir<<rtaptttpptpptpttpptptttttaiaaai4222222222222222222222222222222221$2222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222221$22222222222222222222222122222222222222222222222221$12222222222222222222222222222222222222222eaaattttpp<ti7q644343440itteuttttttttpptptatptptttttptptptttt,tttpttttttttpptppppppirirtriprrr<<yuru<<<rtppaptppaa<ptptptttttttattttttu24utttttttiiue4222uiw7622e7q2221$11111$112222211$2211121$11121$12221$$1222222221$29iu3$$1&6rtppptttttttttpttpttpttpttttttttatpttptttt<tttpttpatttttatattttttattttttttttttttattatttttttpt,tttptttaattttttatattttatattttttatattttttttatttattueq$22222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222211$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222266225qrt<<rrrtrrrrtrrrtrirrtpptppppptptpttpttppptpptrrrtrprrp<<p<rrtt<pppprtr<r<rptapttttttttttptpttpaaaaaa422222222222222222222222222222221$12222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222221$12222222222212222222222222222222222221222222222222$22222222222222222222222222222222222222224uaaatppttprq622212212222776567etttttttttttttttpttptptttttttpp,tttttttttpptpttttpppptppaatptpaprtreri<ttr<<<<<<<<<r>patappppttaattttatu620tuate666666u3224utq6522447222111222111$111122211111$12$1$121$22211$12222222211$1&:-311224utpttttttttttttpttpttttttpattttatttptttttt>appttptttttttttttttttttattatattattttattttattttatat<ttttttttttttttttttatttttttttttttttttattttatttattaaat:22222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222222$22222222222222222221222222222221222222222222222222$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222122222%",
+"%222221$$1$1$1$$-r<<irrrrrrtppppppaaaptttttttptttpttttpttptppt<rrrpptrp<<<p<p<rar<rpppppp<trrrrrtptptptpttttttttaaaaai422222222222222222222222222222221$22222222222222222122222222222222222222222222222221$2222222222222222222222222222222222222222222222222211$22222222222222222222222222222222222222222222222211$22122222222222222222222222222222222222223paaattttte-32222222222222211226utptptptttptptttttttttptpttttt,tttpttpttttttppttttptttppptptpppie66etppparit<tt<irr:rrrrrrrrrrttttatatq425w0iy3222214622247742222222222$112221211$1112222$112$12$1$1111211$1112222222111+*qq1221223yaptpttptptttpttttttpttptttttattttttttptttrrpptttttttatattttattatttttttttttttattttttttatttttt<tttttattttatattttttttattttattattttattttatttttttttttt<52222222222222222222222222222222222222222222222211$2222122222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"@&1$$1$$11$1$11$1wiittttttatttatttttttttttttttpttpptttttptpt<rrttttt<pp<p<t<tt<ttrrrppptttptrrr<rirpappppptttttttttpti222222222222222222222222222222221$12222222222222222222222222222222222222222222222222$1222222222222222222222221222222222222222222222222222$1222122222222222222222222222222222222222222222221$222222222222222222222222222222222222222225itttttttq3$222222222222212222249ytttttttattttattttattaatttttt,ttptpttptttttttttttttttttattttti02220yttttatattptttr<rrrrrrrrrrrrrrrrtr7$1254e52222652122244234232222421$12222222221$$111111111$1$1$2$1111112211221$$1$$32:tt2222222qttttttattptpttttttttatttttpttttpttttttptpt,ttttttttattattttatatttttatatttttttatttttttpttptpp<tptttttttttatttttpttattttttttttatttttptttttttptttttt>e2222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222212222222221$22222222222222222222222222222222222222222222222121$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$",
+"@$$1$122221111222279utttatttttttpttattttatattptttttttptppt<<<ppttpiritr<p<pr<pr<pppr<ttptpttptpt<<rrtrrppptppttppttti7222222222222222222222222222222221$22222222222222222222221222222222222222222222222221$1222222222222222222222222222222222222222222222222222+1222222222222222222222212222222222222222222222221$122222222222222222222222222222222222222222uttttptq22$222222222222222222222wtttattttttatttttttttttttatat<ttttttttptpttattttatattattttiti024560yttttttttpttpp<tpppaptaaattrrrr<<<6$$2$12$$12*q6342222489528426662$12222222222221$$1111$11$1$$$1$11$$1221211111$$14qequ022222225uttattttttttttpttattttatttttpptttttptttttt,ttttptttttttttttttttttttttttttttattttatpttttttttp<tttptattattttatttttptttattatattttatttttpptpttttppttt<i7222222222222212222222222222222222222222222212221$2222222222222222222222222222222222122222222222222222$22222222222222222222212222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222221222222126tatttttttttttttattaatttttttttttpptii<<tapptpt<ptt<tt<tt<pp<rpttrrpptptptpptaaprr<<ttrttttpttttty2222222222222222222222222222222221$22222222222212222222222222222222222222222222221222$2222222222222222222222222222222222222222222222222222$2222222222222222222222222222122222222222222222221$1222222222222222222222222222222222222222226tttttt621$222222222222222222222watttttttttttttattttttttatttt,ttttttttttttttattaatttttattiwyw90eutttttttttttttttt<ttttppttttttppppaat052q&$$$$&6q<-76$$12*9512245uy72$1222222222221211$1111$1$1+$1$11$1121111$$$$22224ur-72222222225ttttttttttttpttpttttttattpttttptpttpttttt,ttptptattttttatatttttatatttttatattttttpttptttttptr<tttttttttttttattpttttttttttttttttattattttpttptttttt<ti722222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222221$12222222222222222222222222221222222222222222222222$122222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222224yttttatttatpttpttttttttttptpttpprt<<tptpptpr<tptt<pt,tt<ppa<ttppr<tttttttttaappppp<<<<titttpttt72222222222222222222222222222222221$12222222222222222222222222222222222222222222222211$2222222222222222222222222222222222222222222222222122$2222222222222222222222222222222222222222222222222$1222222222222222222222221222222222222222224tpttte221$2222222222222222222225yutttattattatttatttatattttat,ttptpttpttpttpttttttttttttti99wiaatatttttttttatpttt<tttpttttttptttppaat0e7iq32226tttrrq$$$:7>q11237r721+112222222222222111$$11$$$$+1$$$11111$$$12222222246132222242222wiatatttatpttttttttttattttttpttttttttptpp,tpttttttttattttttatttttttattttttatttttttttptpttttt<ttttaatttttattttttptttttaattttttatttttptttttttptttt<tti73222221222222222222222222222222222222222222211$1222222222222222222222212222222222222222222222222222$12222222222222222222222222222222222222222222222222$222222212222222222122222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222247qttatttttttttpttptptttttatpptttt<<ppttttttt<pttt<rpt,ttrrppr<atptt<rttttttpttttpttpptr<<<titipi32222222222222222222222222222222221$22222222222222222222222222222222222222222222222221$1222222222222222222222222222212222222222222222222222$2222222222222222222222222222222222222222222222221$2222222222212222222222222222222222222222227tptpi4222$122222222222222222222246ittttttattttttttattttttttt,ttttatptptttttttttttatttattaaippattttttattatttttppp<tppttttttttattptptuewuiu63325uiu0uw4220yuu41$&3*$$$+$$111$11111111112221$$1$$+O$$$11$$$$22222222222411$112222222222qiitttttttattttttttttttttttttttpttpttptt,ppttttttttttattatttttttattttttttattttttttpttpttttt<tttttattttttttatptttttttatttttttattttattttttttttptt<tttt6212222222222222222222222222222222222222222221$1122222222222222222222222222222222222222222222222222$22222222222222222222222222222222222222222222222221$222222211111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222220tttttttaatatttttttttttttttppttr<<ttpttptttt<tpttp<tpt,ttp<ttt<ppttttrrtpttttptptppttttpppt<r<<iq1222222222222122222222222222222212$122222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222222+1222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222224utttpi4222$222222222222222222222224tttattttttttatattatattaatt<ttttttttttpttpttatttttttttttatpptttttttttttttatttii>ittttttttttttttttt7747747e705666544223542432250w224$21$$$$$$$$$$$$$1111111$++XO$$$$$122222222222222222$1222222222224676tttttttttttatttptpttptpptptttttttttt,ttpttptattttttttttttatttttttatttttpttapttttptttptt<ttttttttatattttttttatatttttatttttttttttptpttppttttt<tttti522222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222122$12222222222222222222222222222221122222222112111111+1111111$$$$1122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222utpptttttattttpttttttattttttir<rtpttptttptt<tptptr<ppt,ttt<tttt<tttttpr<ttpttttptpttptttpptttpi>&$11$222222222222222222222222222222$122222222222222222222222222222222222222222222222212$2222222222222212222222222222222222222222222222222222$2222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222236itttpt7221$122222222222222222222224rtttttatttttttttttttattttt<ttattttttttptttatttttttttttttattttattatttatttttti66*7eiipttpttttttttttuu4435iptty660yw724ei429e46qe6246&342222121122221$$$$$+$$$.. O$221111111112222222221$1222222222222224itttttttitpatatttttttttttttpttptpttt<tttttttttaattttttatatttttatatttttttttttttttttttttt<tttttttttattttttppttattttttatatttttttttttttttttpttt<ttttti42222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222222221$12222222222222222222222222221211111111111111$$$$$$O$$$$$$121222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%122222222122222222wipppttttttttttpttptptttattrr<pttttttptttt<tttttt<pppp,ttt<ttttt<ttptppp<rptpttttttttptttttttpte32$$$$12222222222222222222222222221$122222222222222222222222222222222222222222222222221$1222222222222222222222222122222222222222222221222222$2212222222222222222222221222222222222222222222221$12222222222222222222222222222122222222225ttttpttq221$122222222222222222222222uttattttatattttatttttatatt<ttttptptptttttttattttaatttatttptptttttattttatttte21$224qtttttttttttttttte0yetptty40ettt64eq24e6402444erqqe82222222222222211111++O.OO++$+$$+$$$$$2121111221$2222222222222222utttiweq7ittttttpttptpttpttttttttptt,ttpttpattttttatttttttatttttttatttatptptttattptpttt<ttpttatttttttattttttttttattttttattttttatptpttpttttt<tttttte2222222222222222222222222222222221222222222$2222222222222222222222222221222222222222222222222222$1222222222222222112121211212111$$$$$$$$$$$$$112111$121122122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%2222222222222222225tttatattttattttttptttpttr<rtptptpttptpttrrppppaa<ttpt,ttt<<atpt<ttttptttr<tpattttptpttpttptatttw22221$$$12221122222222222222222222$122222222222222222222222222222222222222222222222222$1222222222122222222222222222222222222222212222222222+2222222222222222222222222222222222222222222222221$1122222222222222222222222222222222222227tttttttte122$222222222222222222222222itttttttttattttatatattttttettttttttttttttttttttttttttattttttttttttttttttttu622$22226iittytttatttttttttiiiq64225ttt54509ww4222yyyut>uq56222222222221111+$$$$OOO$$$1212122222$$$$$$$$$$O$$11122221122222uttt6uq65wtttttptatpttptttpttttptptp,tttttttttttttttttttpttatttttttttttttttattttatttptt<ttttaatttattpttptttttttatttttpttptaattttattttpttptt<ttttttt7222222222222222222222222242222222222222221$1222222222222222222222222222222222222222222222212221$11211121211121111$$$$$1$$$$$$$11212122122122222221$122222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222%",
+"%222222222222222224yttttttattttttppttttttp<<itttppttttttttprrtpptpp<itttp,tttt<ptttt,tptttttar<ittattttttttttttttte322222112$+$$1122222222222222222221$122222222222222222222222222222222222222222222122221$2122222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222$222222222222222222222222222222222222216ittttptttt222+222222222222222222222224tttatatttttttttttttttttattetttpptattatatttttatattattttttattatattatttatt0642222+1222140ttutttttttaptttt7452222225qu24iie982224wiiit>880w04222222111$$$111$$$$+$$$1$$112222221111121112$1$$$$$+$$$$$$$126eq65uiitppttttttttttttttttptppttttp<tppttptttttatttppttttttttatattpttptpttttattttttttt<tttttttttttttttttptttttttattpttttttttattttttptttttt,tpttptttu4222222222222222222214w90422222222222222211222222222222222222222222222222222222222222222112211$111$$$$$$$$$$$$$$121111212121122222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%122222222222222226ttttttattttttttpptttt<<rppptatptppttpttrrtttttta<ppttt,pttt<pptpt<<aptttpapt<rtttptpttpptptttte62242222221111$$$121212222222222222$122222222222222222222222222222221222222222222222221$12222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222444$22222222222222222222222221222222222225itttpttptti421$122222222222222222222223itttttttttttaattttttttatat<ttttttttttttttatttiaatttttttttttttttttttttptw222222$2222224iuitatttttttttw642222555524425ti648q22480utw*49yyw922212$$$11111111$$+$1$$$111$1122222222222221$21121121121222$$$$&&:,<<<<<ttttttttptpptptptttptptpp,aatptttttaatatttpptttttttttttattpptptptattttttppar<ttptatttttttpptptttattttatttttttttttatttttttttttttt<ttttptttt51222222222222222223qiiaiy4222222221222221$12222222222222222222122222222221122112211$$$$$$$$$$O$$$21111121111211222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%222222222222222224ttttttttttttatppptt<<ttttptttttttttttttrppttppt<<tttpt,tttp,pttttp<pppttpppttrrtttttttttttttte424ee22222222221111$$112222222222211$222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222904$1222222222222222222222222222222222224etttptttttt7221$222222222222222222222224itatttttatttttttattatttttt>tttptttttttaatttti0ittttattatttaattttttattpai422222$222222266ittttutttttie022265uiiiu6227ie427i7u4y00ew63eytiw41$$$1&11122$$11$1$$2$21$111$$11222222122222$22222222222222112236itttitrr<<<<<<<<<<,,,<<<<<<ttttp<aattttattttttttppptptatattattttptptttttttttttappp<tptttttttttattttttpttttattttttpttptptttttttattpttptt,tttttttppq422222222222222224eiaaaaa0222222222222211$122222222222221222222222221$$$$$$$$$$$$$$1111111111+11122222222122222222222222222222222222222222222221$222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222122222222222%",
+"%222222222222222222ittttatptattttptr<<rtttttttttttttptppr<tttttttp,tptttp<ttptt<tttttt<pttptttpttt<rapptttttptptiy7wtu47274222222221111$$$11111222221$122221222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222242$1222222222222222222222222222222222229tttttptttttu411$22222222222222222222222qttttttattattttttttaatttttt<pptptptttttatttttiw7ttttttttttttattttttttatte222222$2222222245itaqetttatui6224u7ttptti640ty42qti9wwy9ye-5uu<<>q5&11222212$112$$2$$$1$11$22111$122222222222+222222222222222222277twtttttitttiittirtititittr<<<<<><<<<<<<<<<r<<<<<<<<<rr<<rpttttaappppppppppatttppp<papappaatttappptppaappaattttpppttttttpppatttpppttppp<paatttppptq2222222222222224raaaaaaay222222222112222$1212121222212$$$$$$$$$$1$$$111111111111112212222222112222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222etttttttttttapt<rttpptttttpattpttttptrptttptpti<ttttt<<ttttt,tttttpt<ttttttttttir<ppptpttttttttitttuuu93222222222221111$$$12222221$222222222222222222222222222222222222122222222222221$12222222222222222222222222222222222222222222222222222+222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222qttttttttptttu52$22222222222222222222224iptatatttttttaattttttttttttrrtttttatatttttptpt520tttatttattttttatatatttt8222222$$222222212itt0iattw5452225tuty7997728uy225ut0eiuwiq---7qituw22222221$112$11$11$1$211$12211$$$222222222$122222222222222222245q0ttptpi7qyettptapptpaptpttirt<>t<prtiritiiirttrtrpiiittr<rrrr<<<r<<<<<<<<rr<<<<<:<<<<rpaaatttaappppaappaatatapappptpptttptttapapptppp<paaptptaate222222342222212quaa<<r<<-%$$$$$$$$$1$$$$O$$$$$$$$$$$$$11$111111111111222222221222222222222221$1222222222222222222222222222222222222222222222221$222222221222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222122222222222222222221222%",
+"%2222222222222222227tttattttpptr<rrttptttttttttttptpppi<pptttpttt<tpptpt<ptttpt,tttpttt<ittptptttpttt<pptptpttttttttttttt822222222221222221111$$$11111122222222222122222222222222122222222222222222222221$1222222222222222222222222222222222222222222222222222$1222222122222222222222222222222222222222222222222$2222222222222122222222222222222222222etttatttttptptuq*32222222222222222222224ttuttttttatttttttttattatttpt<tttttattttttttttt524etatttatttttttttatttttu42222221$1222222225qu0ttitw622222wtywwwq65424ei024yrytrrr<>>rq7ippii922211$11121$12$21$2$122$1121211$$1222422$$2222222222222222244677yttttrqeeeitttttpptttpttttpppt,tpppppaaattpaatpttppttpttrtrriirritrtrirrttrittrr>trirt<<r<<rr<<<<<<<<<<<r<rre<r<rr<uitpapppi<<<<<<<<<:<<<r<r<<rrr-*6-67>:-%1$%1$3336eeq732111111111111111+1111111111111122222221122222222222222222222222222211$2222222222222222222222222222222222222222222222121$222222222222222222222222221212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222212222226ttttttptprrirtppttttptpttpttttttti<pppptttttt<tptttp<pptttp<ttttttpt<tttttttietppr<pptttptptttttttttt7222222222222222221111111$$O1122222222222222222222222222222222222222222222222222$1222222221222222222222222222222222222222222222222222$1222222222222222212222222222222222222222222222222$1222222222222222222222222222222222224itatttpttpttttpt>eu322222222222222222223it0tttattttattttattttttttatt,ttptpttttattpttttu215ytttttattttattttttatt022222222$2222211464599wyetiue74q0uttyittue613uai44qqq<rtrqr<ttippptt02221$11222$121$21$21$2211122222111$12632$222222222222221221424uititttu7tpitptptttttttpttpttppt,tttppppattppppttpptpatttttpppptpt7tpppaattppttppa<ppptpirrtirit<tirtrirtrrtrtrrrtrtriurr<rrrrrtrtrtrpr,rrrprririrrurrrrrrtirqqq71$$13433422221221221221211$2122122122122222222222222222222222222222222222222211$1222222222222222222222222222122222222222222222221$212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222122222222222226ippttpp<r<ttptttttttattttptpttpptrttptptttpp<ttttttt,tttttti<ptpttptrrpppptt03q7qeqq:qipttttttttttaatu522222222222222222222221$1+1$1$111212222222222222222222222222222222222222222221$2222222222212222222222222122222222222222222222222221$1222222222222222222222222122222222222222212222222$222222222222222222222222222222222222qpppttttttttttttt,tt722222222222222222224qt0tttttttttattttttttttptptt<tttttttttttttttttt6415uttptptttttttttttttq422222221$22222222weeeq65uttptteieutttapppt022qqq&2q656eiu90erttttttt0221$122221$22$$22$12$2121111222221111362$2222222464222222244656q76qiiu6iiiptttttttttttpttpttpt<ttttttttttttttttttatttttttttpttti9ttttttttttttttt<ttttppptptpptpptatataaaaaaaaaaaatatirrirritptpptptpt<pptptptttptaataapppaaaatt64222222222222222222221222$1222222222222122222222221222222222222222222222222221$1222222222222222222222222222222222222222222222222$112222222222222222222222222222222222222222212222222222221222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222%",
+"%2222222222222222222etpttrr<tpptttatattttttattttpppprrtttttttppp,ttppttt<tttpttt,pttttttp<rattte422223521$qitttttttttttyuy52222222222222222222222111$1$11$11112122222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222$122222222222222222222222222222222224utttttptpttttptpt<ttq22222222222222212224566tttttatttttttatttpttttttt<ttttttttttatatttttw9226qttttttatatttttttt3222222221$12222229upptu54etttpttt0uttttiueq7$$3&$123314506450:uiteytiw21$122221$122$222$21$11221$112222222123$$22222225i6222222256ieq66666662666utttttttttattttttttt<tttppttatattttatttttttpttptptttat0tttttatattttatt<tttppttttttttttttttttttttitttttitatapppaptpttttptttt,tttpttptpttttttaptpttttttiw622222222222222222222221$1222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%2222222222222222222qtir<<ippttttttptttttattptptttp<rptpttttptt<<tptpttt<tttttpt,ppptptpttrti77622222222213qttttatattttq652222222222222212222222222$1222111$$11$11122222222122222222222222222222222222222$2222222222222222222222222222222222222212222222222222$1222222222222222222222222222222222222222222222221$122222222222222222122222222222222225tttttttttptpttptt<tte22222222222222222224224ttatattttttatttpttptttttt<tttttaaaappttttttt45224qttptpttattttattti2222222222$12222126utttq246tttueuw40ppir>75qr$$212222222224223267098yu6$$122222$1222$222+222$22221$12222222444$$12222223re22222225epptuiie76667536wttttttatattptpttpt,ttttttttattttaatatttttttttttttttt0tttttttaattattt<ttpttptpptpttptpttttttttttatttttttiaptpptptttptttttt<ttttpttttptpttptpptptpttttte22222222222222222222222$1222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222$112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%12222222122222222227r<rttppttptpttttttatttttttpttirppttptptttp<pptttttt<ttttttt<ttttttttpiru22422222222221$eitttttttttt622222222222222222222222221$1222212111$1$$1$1122222122222222222222222222222222221$1222222222222222222122222222222222222222222222222222$2222222222222222222222222222222222221222222222222$12222222222222222222222222222222222ettppttqippppptttt<tti42222222222222222222222ttttttttttatttatttttptptt<tptttiyeeeyyeuutte22224etttttttttatttttiw2222222221$122223426qtu4223quu756313rrrr<>7it2222222222229w3221$667386312222221$1221$122$222$12222$11222222434$$$$112222qu422222227ipptttpptuitue42etttatttttpttttttt,tttpttttttattttttttattpttpttptttiwtttattttttttttt<tttttttttttttttttttaatttttttttatttatttppttptttttpttt,ttptttttpttttttttttttttttttt75222222222222222222222$2222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"+222222222222222221$&rttpttptpttttptpttpttttatpptt<ppttptptttti<tttttttt<tttpttpt<tptttttti:622222222222222237rttttttttte22254222222222222222222221122222222222222$$$$1$11112211222222222222222222222222$11222222222222222222222222222222222222222222222222221$1222222222222222222221222222222222222222222222222$11122222222222222222222222222222214ittttti46uuuiuuttrrttt52222222222222222222222uptttatatttttttpttpttpttt>ptttr7422243666ut612224ettttttattttttttu42222222222$1222206226i72222255$11$$37<tptty00222222222244utu021&uui57664222222$1222$$222$1221$2222211122222421&22$$$22127i4122222226eittttptpttpty55ytattttttptpttttt<ttpttptatttttttttttaattttttptpttewtttttattttttttt>pttttttpttttatttttttttttatatttttatttttttptpttptpttpt<tpttttttptptttttttpttttttpttty522222222222222222221$1122222222222222222222222222222222222222212222222221$22222222222222222222222222222222122222222222222222$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"@22222222222222211$$2uttttttttptttttttttatttttppr<ppttttttttpt<ptptptptt<tttttttt<tttptpti62$1222222222222222$-rtatttpttt752e622222222222222222222$1222222212222222212$$$$111111222222222222222212222222$12222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222221$12222222222122222222222222222222222iptptti22434657ttrttti52222222222122222222224ettttttttatattttttttttttt,tttte22222422227te42247tttptpttttttttttt22222222221$122224742uq412211$$$$$4226ttttti82222222222464yttt067qtr,<uu942232$12222+1222$2221$122222$11122462$222221$$12qt51222222222ettpttpttpttte8utttttttttttptptt<tttttttttttattttttttttpttpttttttwetttttttttptpttt<ttpttpttttpttttaatataitatttttatatttapttptttttttttttt,tttptptttttpttptpttttptptttttt722222222222222222222$1222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"@122222222222111$$222itttttttttttptttttttttttttrrtpppttpttptpp<ttttttttt<tttttttt<pptttttu22$$22222222222222222&qitttptptte90622222222222222222211$122222222222222222222221$$$11111222222222222222222221$22222222221222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222222$12222222222222222222222222222222224utttpti42222247yu:rttt42222222222222222222224ittattttatttttttttatpttpp<ttttt75437707522rt4227tttttttttttttttttt42222222222$$22222222e311$$$$$2222224uttpti7222222222245u9ettttat,<<ttty908894&62222$2222+22221$222222$1122691122222221$$qiq12222222226uuittiuuttttu0ttttattattttttptt,ttpttpttttttatattatattttpttttttt0ettttptpttptttat<tttttttppttttttttatttattttatttatatattptttttttttttttt,tttttptttttttpttttpptptttptttu522222222222222222222$1222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222211$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222%",
+"@122222222211$$$22224utptptptpttttpttpptttatttirtptttttttpttpr<ttpttpttt<tpttppttr<tttptte422$122222222222222221$3qttttttttt022222222222222222221$11222222222222222222222112211$$$$111122222222222222221$12222222222222222222222222221222222222222222222222211$1222222222222222222222222222222222222222222222222$22222222222222222222212222222212256uttpttu2222222222$5eti42222222222222222222222etttttttttttttattttttpppa<rtttttieutptau44qi6247tatttatatttattttai322222222222$2221121&&$$$112222432440tptti9222222222217ytw0tttttr<,pptpieu0y96yu0222$2222$22221$1122222112286$22222222221-<r42222222222426uq540tttttttttttttttptpttttt<ttttttatttattttttttttttttttptptte5yittttttttttttt<ttpttpttttptttttttttttatatttttttttttttttpttptptptttt<ttptttttptptttttptttttttpptiu52222222222222222222221$1222222222222212222221222222222222222222222222222221$2222222222222222222222222222222222222222222222221$12222222222222221222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%$222222221$$$222222wyttttttptptpttttttttpttpirtptttttttttttt<tttpttpttt<tttttptpt<tttptt62222$2222222222222222221$etppttttty22222222222222222221$122222222222222222222222222222211$$$$11122222222222222$12222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222122222222$122222222222222222222222222222126itttttatu2222222222+28eq22222222222222222222222wattttatttattttattttatttpt,tptptttattttty77y46uttttttptpttptttttii322222222221$112&3$$$2222422223eu660ittttu4222222222226uttttttt<rar<tttpti7y7ue0w92$11222$122221$2222222$222$2222222222225i<512222222222222425utattttttattttttptttttt,ttttttttttatttttattttattttttttattt057eitttttttptpi,ttttttattattattttatttattttattttattttttttatttttttpttt<tptptpttttattttttttttttttty7222222222222222222222221$1222222222222222222222222222222222212222222222222221$1222221222222222222222222222222222222222222222222$11222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222%",
+"%$2222211$$222222222uttttptttttttttppttptttttrttttptpttptpptirtttttttttt<ttttptttt,tttttu22222$&2222222222222222221$qittttatt0242222222222222222112222222222222222222222222222222222221$$+$1111222222222$12222222222222222222222222122222222222222122222222221$1222222222222222222222222222222222222222222222221$1222222212222222222222222222224qtttatttttu2222222222$222222222222222222222222222uatatttattttatttttattttttt,ttttttttttpttty5yettttttttttttttttue06422222222221$+$$$22222224eq22224uu74ettttti62222222222240ttttt<<ptpa<ittttttt<ttty92$22222$222221$12222222$1$12222222222221ete$$$1222222222226tttttttattttptpttttppttt,ttppttptatttttatttttttttattattttttt00ittppttptttpprtattttttttttttattttttttttattattttattttattttatptptttt,tttttttattttattttttttttie622222222222222222212222221$1222222222222222222222222222212222222222222222222222$1212222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%$$1211$$22222222224tttttptptptptttptptttptt<tttptpttttttttt<tptttpttttt<ttttttttt<tttttq222222$12222222222222222221$&etttttti242222222222222211$112222222222222222222222222222222222221121$$$$$21122221$22222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222211$112222222222222222222222222224yttttttatttu2222222221$222222222222222222222222229tttttttttttttattttttttaptt<tttpttttttttpt745tttpttttptttttttq62222222221$$$$$$$12224225526tt622222566itptpt742222222222222yttr<rpttppt<ttpttt,tiitty3$22221$122222$122222221$$12222222222222qti72$$1222222222qttttttttttattttpttttttttt,tptttttttattttttttaattttttttttttttttttttttttttpptrittatattttttatattttttatttttatttttttattatttttttptttptt,ptttttttttttttttattttu722222222222222222222222222222$1222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222221$12222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222%",
+"%1$11$$1222222222222itttttttttttptttttttttt,ttttttttpttptttt,ptptpttpttt<ttpttptttt<ttti52222222$122222222222222222211$6ittttu52222222222222221$111222222222222222222222222222222222222222212111$$$$221$122222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222211111222222222222221222222224958eyutttttttttt4222222222$22222222222222222222222223utttttatttttattttattatttttt<ttttttattt6iiq425tpttttpttpttttt640222222$$$$$121521$296et92414qtq2222245uttttpe4222222222222227i<rttpptpptt<tttt,tty99ey6$22221$1222221$2222222$$$1222222222222140ty522$$$122222qtttptpattttttatttttptpttpt,pttpttpttttatttattttttataatttttttttttttttpttpttttrtttttttttattttttttttaiatattttttttatttttattttttttttttt,ttpptpttttttatttttttu5222222222222222222222222222221$2222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222221$2222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222%",
+"%1O$$122222222222222etttttttttttttptpttptt<ttttattatttpttpt<tttttpptttpt<ttttpptttt<ttte22222222$$222222222222222222211$&etttte4222222222222221$2222222222222222222222122222222222222222222222212111$$$O112122212222222222222222222222222222222222222222222221$222222222222122222222222222222222222222222222222$12222222222222222222222222uaue43uttatttttti2222222221+22222222222222222222222224tttttttattttttattattttttttt<ttttttttttu442238ttttttttppttttu4232$$$$$11112226i62&uittt522225uu5we645ittttttu422222222222222-rttapttpttttt<tp<tttiiu631112222$1122122$1222211121$122212222222224wie2211$$$2216ttttpttttattatttttttttttptp<tpttpttttattattttttttttttattttttttattttpttptttttt,tttatttttttattattatttttattttattttttatttattttttttttttt,pptattttttttttttatiw52222222222222222222222222222222$2222222222222222222222222222222222222212222222222221$12222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"@$1$12222222222222225ittattttpptttttttttt<rtatttttttttttttt<tattttttptp<rttpttttttt<ttpe222222222$22222222222222222222211&ettti482222222222222112222222222222222222422112222222222212222222222222211111$$$$$12212222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222$22222222222222122222222224waaq3etttttttattt2222222222$22222222222222222222222224ytttattttatttttttttttttatpt<tttteeiitie221269tttptttttpptt03$$$$126312222222ettu>ptttt622222wtuttiiittttptu52222222222222$$6itttttttpttptt<<rttttteq9$4422221$1222221$1222$$2222$222222222222225yy022222$$$1etttttttttttttttpttptppttttr<ttttttttttttttttttaattttttttataattttttttttttptttt,ttttttatttttttttttttattttattttattttttttttpttattptpttt<pptttttatttttttu764222222222222222222222222222222221$2222222222222122222222222222222222222222222222222221$22222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"@12$122222222222222220utuetttttttpttttpp<ippttttattttpptttrrtttpttttttt<ttptttttttt<<pp72222222221$22222222222222222222221&rttt342222222222222$12222222222222222222442942222212222222222222222222222211$1111$$$$1222122222222222222222222222222222222122222221$122222222222222222222222222222222222222222222221$22222222222222222222222247iaiqeitttttttttti4222222221$222225222222222222222222219tatttttatatttttttatttttttpi<ttt95yyi54222449ttttttpattrr<311&126qty3222225wtttt<ttttt642224utpttaatttttiey5222222222221$$5uttttptttttppttr,rpttttie03ee22222$1222222$23311222221$122222222222225yu61222226--qwtppatattttttattttttttptt<tptttpptttttttatttttttttttttttatttttttattttppttptt,ptttttttaattttttatatttattttttatatttttttttttttptptptttqatttttataattti03222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222122222%",
+"%22$1222222222222222223759eettptttpttppt<pppttatttptttttpp<tttttpttpttt<ttttpttptptt<pt422222222221$222222222222222222222217rtt94222222222221$122222222222222222404422444944412222222222222222222222211$12221111$$$$12222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222221$1222222222222222222222226iaaaiapttattatttte2222222221$22224ew22222222222221222220tttttttttttatttattttatttptt,ttt72wttq6qq6624tttptt<r<rrrir6427euttty64247utttpprrttati6222qtttpttttttty07422222222222$$12etpttttttppttppr<tr<ttpttqeety22221$2222222135q322222221$12222222222224wtiq42254651$&qittttttatttttptpttptttt<ttptttttatttattttattttatttatttttttttatttptttttttpt,tatttattttttattttttttttatatttttttattttttapttpttttttttrttattttttttte522222222222222222222222222222222222221$1222222222222222222222222222222122222222222222222222$12222222222222222222222222222222222222222221222221$1222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%221$12222222222222222222244yaapppttpp<raptptptttpttptpttp<tptttpttpttt<ttattattpapp,aa422222222222$122222222222222222222222qra73222222222221$122222222222222222yy9ee44499990e5422222222222222222222221$2222222211111$+$$$$$112121221121122222222222222222221$1222222222222222222222222222222222222222222222222$122222222222222222222243utttpttpttpattttaa02222222222+22222qi6222222222222222225uatattttttttttttttttattttttt<tttu437ttittq42epr<r<<iriittatyy0itpttttiy7eitattttt,tptti3224ittttttttttt0242222222222$$$225tttttattttpttpt<tttr<<aaiu>ee422222$12222222#qt9222222221$22222222222216uaiueq0242227q<<<raaappppppttttpttptt<tttptpttptttttttttpttptptaatttatttttttttatttatttat<ptttpttttttttattttttattttttttttattttaattttatttttttttt<tttptppptte63222222222222222222222222222222222222221$12222222222222222222222222222222222221222222222222221$2222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222221$",
+"%221$12222222222222222222224eaaappttpprppptttttttttttttttrrttttptttttpt<ttttttttprpp,aq2222222222221$222222222222222222222226rr6222222222222$112222222222222222909wwe4weuyuu0y944224422222222222222221$122222222221211111111$$1$1$$1$$11222122222122222222221$1222222222222222222222222222222222222222222222221$2222222222222222222222wutttu767qyutaapattu42222222222$222224ie22222222222222224utttttttatattttatattttttapttt,tptty23uppat7$*rrrit<ttpaatttttaittpptptapttttttttat<tttte228ettttttauattt822222222221$12224ytttattpttpttttrtttppir<ritqw3222222$12222$&6&qq3422222222$$22222222222146tpitt622225iit<rtr<rptppatpptttttttp<ttttttttttpttptptpttttttttttttttttatttttttatttttai<tptttttatattttttaattttttatatttttttattttattttttttttttt<tpppppiue7522222222222222222222222222222222222222222$22222222222222222222222222221222222222222222222222221$12222222222221222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%1221122222222222222222222246quiiiaprqqetttttppttpptptttt<pptttpttttptt>tttttttappapre422222222222221$22222222222222222222222qr611222222222111222222222222228080y9y9e0utttat0y004423q22222222222222222$2222222222222122222111111111$11111$$$$$11$$$1211121221$2222222221222222222222222122222222222222222222221$2222222222222222222220iptiq622245667quaat622222222222$122224ei2222222222222566epttttttttttattapttttttatttttt<ppttt72qrr<rq6rrrttppptpptttttttttatttttttttttttatttrrtte5229ttttttty0uttt5222222222$$$2224etttttattptttptripttppttrrrr-32222222$1$1$136q6*4222222222221$2222222222112yu006222224ipppaprrir<rtatptttppaptrrtttpptptpttttttttttttttttatttttttataattttatttttttrittttttatttttttatttttttttttttaattttttttatttttttippaptrtpiiiew6642222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222222$22222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222%",
+"%2222+2122222222222222222222224676qq7326tttpttttttttttptrrttpttttptpttt<tttatttttpaap*222222222222222$$2222222222222222222222qq6$$422222222$1222222222222244qi96eywytitttttaitiu9w45tw2222222222222211$222222222222212222221211212112111$11$$1$$1$11111$1$111O1122222222222222222222222222222222222222222222222+122222222222222222222etpi722222222222500q4222222222221$222623u822222222126wuuutpatttatttattttttttttatttttptprrppire&3qqrrrttaatattttpptatttattttpttptattttttttttptrtt62226tttttte88uttt42222222$$$222227ttttttttttttpprrtttattttatr:311$$1$1$+$$$$2eeuu-82222222222221$22222222122255442222225iptpppppprrr<rrrtppppatt<tptttttttttptttptttptpttptttttttatttttttattttttatt<ptpttptttatttattttttattattatttttttttattttttttat7ewew6-qq666421221222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222221122222222222222222222222222222222222222222222222222$121222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222211122222222222222222222222111111224ettttttttttttttp<ttptttttptttat<tttttttttttta31222222222222222$2222222222222222222224q9521312221221111222222222224wwty9860wtattattatattiyieeyw2222222222222222$122222222222221222222222212122222222222222221$1$1$$1$$O$$111$1$1$1$2221222221222222221222345661222222222$222222222222222222222ytu722222222222122211222222222222+224622e02222222249tttpptpttttppptttttttptttppttttaapp<>rrrr<q5q77tpttttttttttttttattttttttttttttaattttatttt>pa62220ieutti528ttte22222211$1221226ittttttttpttptrraatttttttatt:42$1$$$$$+12224yiute67422222222222$12222222222222222222225ttttttptptpttrrrrrttpapa,ttttttpttttptptptpttpttttatttttttatttttttttttatttt<tttpttatttttttttttattttttttttatttattatatttatttt765422+322112222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22221$122222222222222212222222221$122227tttpttptttttptt<pttpttpttptttt<ttttttattptpa31122222222222222$$212222222222222222221264221$122221$221222222222229wituu408itttttttttttttatat942422222222222211$122222222222222222222222222222222222212222222121222221$11$1$1$$$1$$1111111$11112222222226yquii5222232221$222222222222222222425tt9222222222222222222222122222222$222124eq22222223quttttttptueqeittttatatttptppatpirprt<><<tpaauee2qttpatttpttpattttttattatpttaattttttatttttteru5324yt6utty24etti42222$$$12222490uttttttttatttpi<pattttttatati*222222222$222226ieeu&eq222222222222$1222222222222222222296ittptttttttttppprr<rrrrr<tpttpttptpttttttttttttptttttaatatttttttatatttttatt<tpttttttttttatattttttatattttttattttttttttttttattue522$222222222222222222222222222222222222212222222222222222$2222222222222222222222222222222222222222222222222222$22222212222222221222222222222222222222222222222222$122222221222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%12221$12222222222222222222222221$122222wtutttpttttttpt<ttttttptttttttt<ttatatttttttw212222222222222222$112122222222222222222241222111111$11222222222222290taaaqieutttttttttttttttttq6444222322222222$1222222222222222222222222222222222222222222222222222221$121222222222$$$$$$$$$$$$11111$123rippppu3247q6621$22222222222221222229etu2222222222222222222222222222222$122227uq2222224utattttttu062237etttatttattttrrtt<<<<<a<ppptapttt54ttttttttttttttttattatttttpttttttttttatiute-54222eu8tttw25tttt52221$$2222228eittttttttttttpt<tpptttttattti7$222222221$222224q0eu&6r4222222222221$1222222222222222224yutttptpttttttptppaapr<<<,rttttpttttttpttptptttppttptttttattttttttttttttttttt>ttttpttttttattttttttttttatttttttttattttttatatttptte21$22222222222222222222222222222222222222222222222222222112222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222$$22222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222%",
+"%222222$122222222222222222222121111122227u6uttiittppttp<tttttttttpttttt<ttttttttttte21$1222222222222222211222222222222222222222122421$1111112222222222224euttiiituytattatttaattttttttuw44222q64222222$1222222222222222222221222222222222222222222222222222222$121222222222222222222221$$$$$$$*q,<trtir716irti62$2222222222222222224ettq2222222222222222222222222222221$22222itq222228qtttttttie32222224qutttttittit<<<<taaaaa<ittppptpt62yttttatpttpttattttttttattttttattttttaaiee3$22222e05itw526eewu521$$2222222424ettttttttttptp<ittpttatttattq$1222222222$22222246ii4$422222212222221$122222222222221222etttttttptptpttttpppppapp><<rtitptptttttttttpttttttttttttttttatttaattttatattt<tttptttattttatttattattattttattttattttattttttttttttt21$122222222222222222222222222222222222222222222222222211$12222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222%",
+"%222222$11222222222222222222121$122222224327ew67yeuiptrrttatatttattttat<tttttptttiu322$222222222222222221$2222222222222222222222222222$+$1222222222222224ytiuq7wy0eittttttattttatttattiyw822eue611121$1222222222222222222222222222222222222222222222222222221$2222222222222212222222222211490itttr<<<<>**><<riq%211111$21221222222qipt72222222222222222222222222222221$12222it712222utppattuqq2212222111qtriit<<<<<patttattttt<tttttptt727ittttttttttttttttttttttattttatattttttti21$22222942ee5222234411$122222244724ettpttptttttp<ttpttptpttttti3$2222222222$22222225wt4$1222222222222221$22222222222224322ytttttttatttttttttttttptt<ttr<<<rtttptttttttttttpttpatttttttattttatttttttptt<tttpttptttttttttttttttatttaatttttttttttatttttutttttt22$122222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222$12222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222$1222222222222222122211112222222222222222247it,tttttttttttatttt<ttttttttt64222$122222222222222221$12222222222222222222222222221$$1112222222222229uw6221224q70ettttttatttattttttuyi9425er34411$2222222222212222222222222222222222222222222222222222221$22222222222222222222222222249iaattttppppptittti<>>>$$$$$$$$111111$22iiiti2222222222222222222222222222222$12224ttq122227rtitie312121111$$$$*<<<<<ptptpptttttttatt<tpttpttti54etttatttptpttpttatatttttttttttttatttiiu222$22222242222222211$$22222222weu46ttttttttptttr<ttttttttttttti624222222222$22222222qi3111222222222222221$222222222222qu42etttttattttattpttptptttt<ittpptt<<<ittttptpttptpttttttatattttttattttptpttttt<ttttttttttatttttattattttttttttatataattttttattwwttttu22$222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222$12222222222222222222222222122222222222222222222222$22222222212222222222211111$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222%",
+"%2222221$11222222222222222222111222222222222222222226i<tttttttaatattttt,ttttttttu222221$222222222222222221$1222222222222222222222222211111$122222222222264222222222222wttttttttttttttttttttu5224uu741$222222222222222222222222222222222222222222222222222222$1222222222222222222222222430qiattattttttttttttttt<tt62212221$$$$$$$$$*&6ti3221111122222222222222222222222$22226ti611212267q7&$$+$$$$$$$122217ttppptttpttttttatttt>ttpttptttuyutttttptpttttttattttttttatattttatttaai9422$222452222222221$$2222222225uee8etttttttptptt<pppttptptptttti322222222221$222222224752$12222222222222221$222222222229e22qttttattttttptpttttttttt<ppttttppptr<<<ttttttttttttptattttttttttpttpttpttptt<ttppttptataatttttatttttttttatattttttttttattttq5ttty522$122222222222222222222221222222222222222222222222222222$12222222222222222222222222222222222222222222222222222$22222222222222222222222222222222222222222222222222$122222222222222211111$$$11122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222$122222222222222221$122222222222222222222222&qttatattaattttttt<tttttptt7222221$222222222222222222$11222221222222222222224222111111$111122222224222222222222222utattttatttattatttttttq44iaaa-2212222222222222222222222222222222222222222222222221221$1222222222222222222222257uitatattttttttpttpttpttt,ttu421222222221221211$->-$+$$$$$$2212221212112222222122+2122etr&$$$$+$$$$$122222122121222126etttttpttatttttttpt<ttttttttttttttattttttpttptttatttaattttttttttttttti6422$222222222222$$112222222222769etttttppttttt<ttpttttttttttt73q32222222221$122222222242$122222222222222221$222221222222227ttttttattttttttttattttt<ptptptttpttptr<><ttttptpttttttttttttatttttttttttttt<ttttttttttttttatattttttttatttttatatttatttttttq4itw2222$2222222222222212222222222222222222222222222222222222211$2222222222222222222222122222222222222222222222222221$222222222222212222222222222222222222222222122222221$1222222222221211$$$$22211122222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%122222221$22222222222222221$222222222222222222222221$2qitttaaaattttttt<ttttttt72222222$1222222222222221222$12222222222222222222222211222221111122222222122222222222222yiatttttttttattttttattiywaaai>7112222222222222222222222222222222222222222222222222222$122222222222222222224qyitttattattatttttttptpttptt,ttte5222222122222222222qi4122221$+$$$$$+$$$$1212211$$+$OO$$$>re221212222222222222222222222223qapptpttttttttttttt<tptttpttttattattpttpttptattttttttttatttattattatttiy0y>32222222212$11222222222222250tttpttpttppt<tttpttttttttpti4$222222222222$1222222222121$122222222222222221$22222222222226ttttattttttattttttttpt<tttptptttttapttttt<<<rttttppttppttttttptttttptpttptp<ttptptttatttttttttatttaattttattttttatttttattt62e52221$$2222222222222222122222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222222$111222222222222222222222222222222222222222222222222$22222221121$$$$$121122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%222222221$1222222221222221$122221222222222222222222$1224ete0uiitittttrrtttiu7622222221$12222222222222222221$22222222222222222222221$122222211$112222222222222222222222yitattattattttattttttttttaaaaqapew984222222222222222222222222222222222222222222222222$1212222222222212222wuttttttttttttttpttptttttttttt,ttttuu42222222222222222ei2222222221121112211$$$$$$$1221$1113ii32212222222222222222222222222224upptttttttttiw000t<tttpttptttttttttttttttttttttttatttttatttttttttttttttt6$22222222$$222222222220w0800ttptttttttpa<tttttttpttptttttw$4222222222221$222222222221$222222222222222221$122222222467227ttttttttattttaatatttt<ttttttptatttttptttttpr,,<tppttppptttattttpptttttttt<itttttpttttttatttttttattttatttatttttttatattte542422222$22222222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222221$22222222222222222222222222222222221222222222222221$2211211$$$$11112222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222%",
+"%2222222221$22222222222211$1222222222222222222222222$22226642244660eyi<ti053422222222221$12222222222222222221$2222222222222222222111112222222111111222222222222222222224wtttttatttttttatatttttttppareaaaaauu222222222222222222222222222222222222222222222221$122222222222244249yttttttattttttttttttttpttttppaa,ttaptt52222222222222226iu222222222222222222211122112222$1226ti4222222222262222222222222222222240itttttttue95eitu>ttttttttattttttatttttppttttttattttttttttattttttatttte2$222221$$112222222224eti0uttttttpttpptarrttttpptpttptpttu>24222222222222$1222222212221$122222222222222222$11222222qtu224tttttttatattttatttptrrttttttttttttpttttttpptttr<<<tttpttetttupttpttptptpp,ptttttttttttttttttttttatatttttttattttatttat62222222222$22222222212222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222211$$1$$$$1121112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222%",
+"%2222222222$122222222222111222222222222222222222222$$22222222222222345:t6222222222222222$12222222222222222221$12222222222112222211$12222222222111$12222222222222222222224ytttattttttatttttttttatpairaaaaaaai822222222222222222222222222222222222222222222222$1222222222114wuwyaaattatttttattatttpttpttpttpppp<,ttttppq2222222222226q6it7222222222222222222122222222221$1226tu22222222222542222222222222222222226ttuiuty509ett9irtttptptttttattttptpttttttattttattattttattttattttttti621$2221$1122222222224witaittptptttttttt<rpttptttttttttttt0622222222122221$1222222222222$1222222222222222221$12222246ui65wtttttattttttttttttpp<tttpttpttttatttptttttttttpptrrrertt09054uttttttttttt,tptptptttatttaatttatttttttatatattttattttiuw42222222222+22222222222222222222222222221222222222222222222222222211$12222222222222222222222222222222222222222222222222221$2222222222222222212222222222222222222222222222221$$O$11111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222%",
+"%22222222221$22222222221$12222222222212222222222221$122222222222222222$e2222222222222222$122222222222222222211$12222222222222222111222222222222211$12222222222222222222225ttttttttptpttttttttattppt<tttpttttiw2222222222222222222222222222222222222222222221$122222222224etttttttaatttatttattttatttttatttpttpt,tpttttte3442222226qiiute4222222222222222222222222222221$125etw222224e6222242222222222222222222222w7qi9w52436765ut<iettttttttttattatttutatttttttpttttatttattptptttttu7222$21$$1222222222222yittttttaatttatpptrtppttttatttttttttt63q2222222222222$12222221222221112222222222222222221$2222225eyutttatttatttattttatttrrttptptpttttattttttttatattttatrtir<r652226tttpttttttt<ppttttttptttttttpttpttattattttattattttie44222222222221$12222222222222222222222222222222222222222222222222222222$11222222222222222222222222222222222222222222222222221$12222222222221222222222222222222222222222222$$$$$11+122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%12222222222111222222211122222222222222222222222221$222222222222222222$622222222222222211$222222222222222222211$2222222222222222$111222222222222221$$222222222222222222222ittttppttttttttattttttttp<tttttttatie622222222222222222222222222222222222222222222$22222222214yttttttatttttttttttttattttattttttttttt,tttpttptewuuyywwqitpttu51212222222222222222222222222121$15utt9222245e32222222222222222222222222222257422222244255&67qttttttatttttttttuyyyttattttttatttttttttttttttte4222$+$112222222222228itttttattttttttppi<tpttatttttttatatee5242222222222221$12222222222221$12222222222222222222$$122221456itttttattttttatttttp<pptttttttttttttattatttttttttttppptirr&$$&47ttttpptttr<pppttptptttppttptttttttttttttttttttttt6322222222222221$12222222222222222222222222222222222222122222222122222222$22222222222222222221222222222222222222222222222222222$2222222222222222222222222222222222222221$$$$11$1121$122222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222221222222222222%",
+"%222222221221$12222211$122222222222222222122222222$1222222222222222221$222222222222122221$1221222222222222222221122222222222112111222222222222222222$$22222222222222222224utppiqqttttttaatatttttttrrtttttatatttue522222222222222222222222222222222222222221$12222222124ettttttttttatttttatttttttptpttttatppttt<tptptttttiaaaattittttq522222222222222222222222222274122$17tpe5222242342144222222222222222222222222222222222121221$230wttttttttttattttiiiyw7uttpppttattttttpptttttty5222$$$$22222222222222yitttttttattttttpr<tttttttttttatyywtw7&222222212222222$12222222222222$1222222222222222222211$$12222227ittattttttttttttttt<ttttttttptatttttatttttttatatttpptpppi211$$$qppttttpt<tpttttttttttttpttptttttttttatatttttttti2222222222222221112222222222222222222222222222222222222222222222222222221$12222222222222222222222222222212222222222212222222222$12222222222222222222222222222222221$1$$$111112222211122222222222222222222212222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%2222222222211$12222111122222222222222222222222222$1222222222222222221$122222222222222221$2222222222222222222211$2222222222211$12222222222222222222221$12222222222222222227tpe644qttattttttttattpt<ttttptttttatatyq5222222222222222222222222222222222222221$11222222227attatttttttttttatttttttattttttttttttttt,tttttttttttttaptttttuq4222222222222222222222222226i6222&2wtp6422224222214222222222222222222222222222222222222222111268tttttatattttattaatty05wtpppttttttatttttattye822$$121$22222222222229tttatatttttttttat<tttttpttttattu0w0iy3$222222222222221$122222222222221$12222222222222222222211*67522quttttttttattattttatritapttptptttttatattttttatttttattpttppt0221$&q<r<ttppp,pttptptptpttptttttttpatttattttttttttttu422222222222221$1222222222222222222222222122222222222222222222222222222221$22222221222222222222222222222222222222222222122222221$2222222222222222222212222221111$$$1$111122222222211$22222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222221$222111112222222222222222222222222$12222222222222222222$122222222222222222$112222222222222222222211122222222111$122222222222222122222221$$2242222222222222240i52224ittttttttttaattt<tptpttatttttttttue65422222122222222222222222222222222222$1222222226aattttatttattttttttttattattattattttttttt,ttatttttttttttttatttiue22222221222222222222222222ei6222-6eti422222122222222222222222222222222222222222222222222221$244qitttittatttttttattptq47qiptttattttttttttt7422$1$222$12222222222247yiatattttttattttrttttttttttttttiww096$2222222222222222$122222222222222$1222222222222222124567qreru52utttttttattttttttttteatttttttptptttttttatttatttaattttpttttti72226trirrrrra<atttpttptttpttttttttttttatttatttaatttty222222222222221$1222222222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222222$122222222222222222222112211$$11$1112222222222222222$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%122222222222111121$11212222222222212222222222222$12222212222222222222$122222222222222221111222222222222222222221$11222222211121222222222222222222222221$1642222222222222223622222etattttttttttttt<ptttttttttatttttptiuq66666654222222222222222222222222221$222222224eaattattttatttaatatattttttttttttttapttptp,ttttttttttataattttttatt72222222222222222222222222ut4222-iite222222222422222222222222222222222222222222222222222221+2123etw767wiatttattttttttw226itttttattpttptti511$$222221$12222222224qeyttttttattttattrittttttttatttuti0w041$2222222222222221$222222222222222$122222224254221226qeitptrrr63utttatttttattptpattritttatatttttattttttttatttttttttttttttttat765etttptrrr<<rtptpttttttttttptpttatattttttattttttaty222222222222221$2222222222222222221222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222221$222222222222222212221111$$$$11212222222222222222221$11222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222221111$22222222222222222222222222221$12222222222222222222$2222222222222222222$12222222222222222222211112222221$12222222222222222222222222222&q&2222222222222222222222wttttttttattatt<iptptpttttttttptpttppptiiitiuw466321222222222222222222221$222222223aaatattttttttttatttttatattttttattttttpppt,ptttatatttttattttttttttt5422222222222222222222222qe2122*itt32222222224222222222222222222222222222222222222222222221$2228e22222wuttatttttatttt712qttttatatttptttu1$$222222221$2222222220ttttttttttatttaairtatattttttattyuie002$$2222222222222221$1222222222221222$221222268eq24440tppppttptr7$rttttttttatttptttptrtttttttattttttttttttttatttttttttttpttttttttuitttppttp><<<rttpppttpttptpttpttttttttttttttttttte222222222222221$2222222222222222222222222222222222222222222212222222222222$12222222222222222222222222222222222222222222222222221$122222222222221111$11$$1$222222222222222222222222221$2222222222222222222222222222222222222222222222222222212222222222222222222122222222222222222222222222222222222222222222222222222222222122222%",
+"%2222222222222221$$22222222222222222222222222222$122222222222222222222$2222222222222222212$122222222222222222222111$2222211112222222222222222222222222224eq31222222222222222222222etttttatttttttt<tttttttatttaattttttttttaatatttuuiw44222222222222222222221$12222224uaaatttattttttttttttttttttttattttattptppp<<tttttttttttttttttttttttteq65222222222222212222222662222*tti42222222222122222222222222222222222222222222222222222222$122252222225uttttattttutti426itttttttptttpiq$12222222222$222222222utttttattttttptprrptttttttttttiue0it842$22222222222222221$1222222222222221$12222240ytw3ewqtttppttttpp6&quittttattttttttpprutatattttpttpttatttattttttatttatttptttttttttttatptttpp<apt<<rrirttptpttttttttttattattttattattp6222222222222221$2222222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222221$1222222212211111$$$$12212222222222222222222222222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222221$$$11222222222222222222222222221$122222222222222122221$2222222222222222221$12222222222222222222222111111111222222222222222222222222222225iw4$$12222222222222222222uttttttptpttttt<pptttttttttattpttpttattttttattapptte952222222222222222222$2222224qttttttatttttttttatttattttttatttttttatttat<ttattttttatttattttttattatappu422222221222222222222422221*pty22222222222222222222222222222222222222222222222222222222$222222222222waapptpttaeuaa424ytatttttttitt<&2222222222221$22222224tttttttttttttttt<pttttpttttttiy9u8yi922$22222222222222222$22222222222222221$122269wti0wttatttttttpttu42$66rttpttttttptptt<tttattttattttattttaatttattatttaattptttttttttttttttpttt<tppptt<<<itrtpppttttttptpttttatttatpttt4222222222222221$1222221222222222222222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222221$22222211111$$$$222222222222222222222222222222222222$1222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222211$11$1122222222222222222222222211$222222222222222222221$22222222222222222211$1222222222222222222221111111$12222222222222222221222222222225u022$$12222222222222222224uttttttttttttr<pptppttptptttttttttttttattttttappttttiq543222222222222221$1222227atttattttttatatattttttttaattttttatattttttp,tttttaattttttttatattttttttptt512222222222222222222222222*ttq22222222422222222222222222222222212222222222222222222222$$222222222224wuipttttaw7au3499ttttpptpt7r<u62222222222222$1222222wtttttttttattattrittptttttttttu0wy4wt92$122222222222222222$22222222222222222$1224e0tttattttttttppttie5122&-<tttttpttttttt<tttttttattttattttattttttttttttttttttttttptpttptptttttt<itttppttpa<<<<trtttpttttttttattttttttttt522222222222222$22222222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222$211111$$$$1222222222222222222222222222222222222222111222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222%",
+"%2212222222211112212$$1122222222222222222222221$2222222222222222222222+22222222222222222222$222222212222222222222212$11$122222222222222222222222222222222q42221$12222222222222222226rtttttttpttt<tpttttttttttttttttaattttttatttttttttatattiu65543422222221$1222226aatptttttttatatatttttttattttttttttttatttttt,ttttttttatttttttatatttttttttt622222222222221222222222222*ty2222222422222222222222222222222222222222222222222221222222$22222222222224wattttew44323w4uttttpptr-qit722222222222222$222224yattttattttttttrittttttptttttti0054wi92$222222222222222222$122222222222222221$228yetatttttttttttttu722225eii,tttptttttttt<ttattttatatattttttttattttttttttatttttttitttttttptptttt<pttptttttpptti<<<ttttttttttttattttttpttu222222222222221$11222222222222222222222222222222222222222222222212222222222$112222222222222222222222222222222222222222222222222111$$$$$$$2211222222222222222222222222221222222222222222$112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222211$2222211$112222222222222222222221$2222222222212222222222$22222222222222222221$2222222222222222222222111O112222222222222222222222222222222222122222$$2222222222222222222wtttptptttt<ttttpttptptatttttttttttatttatttttattttttttttaauyeq4322221$12223eaaattttttatttttttttttatttttttattattttttttatt,tttatttttttatttttttttattttttte4222222222222222222222222&*iu2222224222222222222222212222222222222222222222222222222222$222222222222243uttty2222229y40tttttt<<iqwuw22222222222222$$12120itatatttttttttrrtttttttteutttatttt9592$$222222222222222221$122222222222222221$248ytttttatttttttiu7322227uyutt,<ttttttptt<ttttttatttttttattttttttttattattttttpttiy7ettptptttttppt<ttpttpttpppptpppt<<<rttttppttttttatttttu222222222222222$122222222222222222222122222222222222222222222222222222222221$122222222222222222222222222222222222222222222121111$$O$122122222222222222212222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222221222222222%",
+"%22222222221112222222211$112222222222222222221$12222222222222222222222$122222222222222222221112222222222222222212221$1$122222222222222222222222222222222212222222$$2222222222222222224iitttttptt<ttttttpttttttatattttttatttttttattatttttttattttttttie64442$4224eaatttatttaatttttttttatttttttattttttattttttattrtttttatttttttatttttatttttatttt62222222222222222222222222$te2222222222222222222222222222221222222222222222222222222222$$222222222220043waa44222223w26tppir<ttttt97222222222222221$12229tttttttttati7q7u0wttttuw60uttptttiw622$2222222222222222222$122222222222222222$14yittatttttttttu084772226746tttr<ttttttprrtptttttttattattttttatttttttttttttptte6524uttptttttttttrrtttttttptpttptttpttt<<<<ppttttptttttptty222222222222222$122222222222122222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222211211$$$$12$22222222222222222222222222222222222222222222222222221122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"=22222222211$112222222221$11122222222222222222$12222222222222222222221$122222222222222222211$122222222222222222121$112$12222222222122222222222221222222222222222221$12222222222222222206tuttppt<ttpttpttttpttatttttaattttttatatttattttttttttttttttttttttti:uuiutaaptttttttttttttttttttatattttttatatttttatattpqtpattttttatatttttttttttatttttt22222222222222222222252221$e422222242222222222222222222222222222222222222222222222222222$22222222227iaiw6we92222222422qir<rtttpttw22222222222222222$122wtttatttattue1$234wutue522447quii064222$2222222222222222221$2222222222222222222$5ytttttttttttttttttttw22423etttpp<<tttpt<ttttatttttttttttttattttaatattataattt722227tttttttttttpp<ttttptptttttttttttttpttpr,<<ittptatttptte222222222222221$222222222222222222222222222222222222222222222222222222222221$122222212222222222222222222212222222211221$$$$$112111$12222222222222222222222222222222222222221222222222221$12222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222%",
+"%2222222221$122222222222211$12222222222222222111222222222222222222221$1222222222222222222221$12222222222222222111$11221$12222222222222222222222222222222222222222222$$222222222222222247637qipt,tttttttpptptttatttttttttttttttatttattttattatattattattttttt>tttttaapttitttattatttattttattttttttttttttttttttatp,ptttttttttttattttatttattttttpt622222222222222222224e6221$6422224822222222222222222222222222222222222222222222222222222$22222222220iaai0i7722222222223>riptttttu5222222222222222221$229ittttttttiy2$222225542222222244422222$22222222222222222222+2222222221222222224$wttattttttatttttttttttu77utttttpptt<rtt<ttptptttttatttttttatattttattttttattti52222etttpttttttttp<ttttttpttptptppttttppttttttt<<<rtitappaa72222222222222111122222222222222222222222222222222222222222212222222222222222$2222222222222222222222222222222211211$$$$$112112222211$1222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222%",
+"%222222221112222222222222211$$122222222222221$11222222122222222222221$2222222222222222222222$122222222122222221$11111111122222222222222221222222222222222222222222222$$1222222222222227u42426tt,tttttptttttttttttattttatatttttttttttatttttttttttttttttattt<pttttaippi4ettttttttatttattttttattattttatatttttttp,ptttattattttttatttatttttttttppu22222222122222222223i5221$22222222222222222222222222222222222222222222222222222222222221$222222222237waiu70922222222$$47quttpttt72222222222222222221$226ittatuy004$2222222222222222212222221$22222222222222222221$222222222222222222577ttttttattttttttttttttttitttpttptpppr<rrtttttttattttatttattttttttttttttttttt022227tttttttttuqett<tptptttttttttttttptttttptttptptr<rrtppau422222222222211$1222221222222222222222222222222222222222222222222222222222211$122222222222222222212222222222222$$$$11111222222222222$1222222222222212222222222222222222222222222222222222$11222221222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"$12222211112222222222212222211$11222222222221122222222222222222222221$12222222222222222222221$122222222221211$11122222211$2222222222222222222222222222222222222222222211112222122222226w4224rtrttatatataatttttttttattattttttatttttttattttttttttapttpttttp<itpttpttti99ittatatatttttttttatattttatptptttttttptp,ttatttttttatttttttttttttttttttt52222222222222222222w4222$22292222222222222222222222222222222222222222222222222222222221$1222222222222wia058222222$$112223eaaaa042221222222222222222$124uaaaa8222$12222222222222222222222221$22222222222222222221$1222222222222222229wqptptptptttttttattttattatattttaatttatr><aaptpttptttttttttptptttttttttatttttt022227ttttttpt6325trtttttttttttttttttatttttttttatttttitirrqr7222222122222222$2222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222221$$$$111122222222222222222$2222222222222222222222222222212222222222222222222222111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$",
+"%2222221112222222222222222222111$$2122222222$122222222222222222122221$22222222222222222222221$2222222222211$$112222222221$1222222222222222222222222212222222222222222221$122222222222214113eit>ptttttttttttattatttttttttttattttattattttatattatttttttttptp<tttttttti98uattttttttatatttttttttttttttttttpttptttt,ttttttttattttattattttatptqytatte4222222222222222222y2623622204222222222222222222222222222222222222222222222222222222222$12222222222224waa62%2221$112212224yaaw4222222222222222222222$19aaai0422$12222222222222222222222221$122221222222222222222$122222222222222224eprrttttttttppttttttatttttttttttttttttt<tr<rpppttttptpttpttttttttatttttttatttt022226yttttiut4220t>tttpppttattatattttttaattatatttattttatrpr&$$2222222222221$2222222222222222222222222222222222222222222222222222222222221$122222222222222222222211$$$$$1111122222222222222222222142222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222221$11222222222222222222222211$$12122221$122222222222222222222222$22222122222222222222221$22222222221$1112222222222221$22222222222222222222222222222222222222222222211$1222222222222226apt<ttttttattttttttttattttttatatttttttattttttttttttttttttpttpt<tttttttttyuttttatttattttatatttttatatttttttpttpttttt,tttttatattttttttttttttte5230uuqie422222222222222224u476e:222822222222222222222222222222222222222222222222222222222222221$122222222222240a0qww4$$11424249www99422222222222222222222221$7aae84221122222222222222222222222222$222222222222222222222$2222222222222222446pp<tttttttttttttttttattttttttttatttttrippir<ppttpttttttttptttatataattttattttt0222247tttu66q544ur>eettppttttttttttttatttttattttttttttttape12$$$$1222222222$1222221222222222222222222222222222222221222222222222222222221$1222222222222222222$$$1$111112221222222222222222222221$2222222222222222222222222222222222222222222222222222211222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22221112122222222222222222222222211$$12221$1122222222222222222222211$12222222222222222222222$12222222$$$11222222222222222$122222222222222222222222222222222222222122222111$12222222222222yit<tttaattttatttttaattttatttttttattttttattttttaattttttptpttttt<tttpptttttttttttattttaatttttttatttttttptptttttptptt<tttttttttatttttaattatttu449ee53ut522222222222222222uqiip-222222222222222222222222222222222222222222222222222222222222221$12222222222222476au4%12q6qeqeauuyw4422222222222222222222222213q84221$122222222122222222222222222$$222222222222222222211$1222222222222222466rp<tptptpttptttttttttttttatatttttttpirtpptpr<ttptttptptpttattttttttttattttttt622222e7675224422q63539wuiatttttttttattttattttatatattttttpp71221$11$$$22221$122222222222222222222222222222222222222222222222222222222222221$22222222222222$$$$111112222222222222222222222222222221$22222222222222222222222222222222222222222222222222211$222222222122222222222212222222211222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2221$122222222222222222222222222222111$$12$1222222222222221222222221$222222222222222222222211$12111$$$11222222222222222221$1222222222222222222222222222222222222222222222211$122222222224uttrttttttattttttttatttatttttttattttttttatttttttattttttpttptttt,ptttpttttttttattttttattttatttatttatttatpttpttpttptt>ptatttattttttttatttttattyeuti525q422222222222222224itpai&122222322222222222222222222222222222222222222222222222222222222112222222222222222661114eaaaiaa9345222222222222222222222222222121122%1212222222222222222222222221$1222222222222222222222$11222222222222224q9ipi<ttttttptpttttttttaatttttatttttpt<ttatttttr<tpppptttttttttaatttttttttttatt041222522222212122$22224567ttttttttattattttttttttattattttty3222222133$$$$21$222222222222222221222222222222222222222222222222222222222222122$2222222221$$$$1111122222222222222222222222222222222222$22222222222222122222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222%",
+"%22111112222222222222222222222222222221$1$+$1122222222222222222222221$122222222222222222222222$211$$112222222222222222222221$2222222222222222222222222222222222222222222222211$12222222211uarrpptaatttttatatttttttttttatttttttattttttttatttttatattpttttpt,tttpttatatattttatatatttttttattttttatttttttttttttttt<tptttattttatattttttattttaaptaq22422222222222222226uttppt&1222224222222222222222222222222222212222222222222222222222222221$22222222222222111322215aaaaaa9222222222222222222222222222222211121$2222222222222222222222222221$2222222222222222222221$1222222222222222960itp<tptttttpttttttatttttatatttptpttrrtttttttttr<rptptptattttttttttttatattttttu52222222222222221$22111126ttttttttttttttatattattttttttttt022222256euq11$$$O122222222222222222222222222221222222222222222222222222222222222$122221$$$$1$1$2122222222222222222222222222222222222222$228422222222222222222222222222222222222222222122222211$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222%",
+"%1211122222222222222222222222222222222221$O1$1$1112222222222222222221$122222222222222222222121+$1$11222222222222222222222222$12222222222222222222222222222222222222222222222221$$222222222qyriaptttttttttatttttttttaattttttttatatttttatattttttatttttttppr<tttttttattttatttttttttttttttatttttttttttptpttptttt<ttptatttttttattttttttttttttttti42122222222222222224ettttt-2222242222222222222222222222222222222222222222222222222222222222111222222222221$$1222222eppaaa6222222222222222222222222222222222$$$2222222222222222222222246042112222222222222222222222$122222222222222244eaaprrptttttq7qttattttttatttaattpptrrppttttttatptr<iappttatttttttttttttttttttty3222222222222222$12222222ettttttattttttattttatttatttatttt422224qeuaat6221$+$$$122222221222222222222222222222222222222222222222222222222222$11$$$$1$1122222222222222222222222222222222222222221222$220422222222222222222222222222222222222222222212222222$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222%",
+"%11$22222222222222222222222222222222222221111$1$111122222222222222222$12222221222222222121111$+$12222222222222212222222222221$22222122222222222222122222222222222222222222222211$11222222223:iapatattatttttttattattttttatttatttttttattttttattttttpttptpp<ttpttpttttttttttatttatattattttttattttattptttttttptt<ttttttttatttttttattttattttttttt573222222222222222223etttp>22222222222222222222222222222222222222222222222222222222222222221$22122222221$$1211222227ippia6222222222222222222222222222222222$$1222222122222222222222225wu32$12212222222222222222222$122222222222222244yaapp<ptatt7422ettttttttttttuywquttrttpattttattppp<rrppattttatttatttaattttatatw4222222222222222$22222222utttttttttattttattattatttatiyyyq222226tatttti5122$11$1$11222222222222222222222222222222222222222222222222222211$$+$$1$12222222222222222222222222222222221222222222222222$%22222222222222222222122222222222222222222222222222222$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%$122222222222222222222222222222222222222$122221$$1$1$1$1121221222211$212212222212211111$1$1$11112222222222222222222222222222%122222122222222222222222222222222222222222222222222$112222222$&yepttttattttatttaatttttttttttttttttattttatttttattttattttatt<ttttpptttttatttttttttttttattttattttattttptptptttttt<tttttttattttatttaattattttattatt0e5222222222222222222qtttt-12222222222222222222222222222222222222222222222222222222222222222$122222221$$122222222222eiptte4121222222222222222222222222222221$11222222222222222222222236u83132241122222221222222221$222222222222222224utttttrttte2222qttttttattttt93226i<tpttptptttatpttptrrptttttttttttttttttttattttq22222222222124$$22222222utatatttattttattttttattttttq442222224upttattte421$2221$$11$111111222222222222222222222222222222222122212111111$$$O1222222222122222222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222$2222222222222222222122221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"@1222222222222222222222222222212222222221$2222222221$$$$$111111112211$212211111111111$$$$122111$122222122222222222222222222222$122222222222222222222222222222222222222221222222222$$1222222$243uattttttatttttttttttatatttttattttttattttttattttttttattttt<tttttttattttttattatattttattttttattttttattttttttptpt<tttattttttatttttttttttttttttttte42222222222222222224etttt*122222222222222222222222222222222222222222222222222222222222222221122222111$22222222222225itati522222222222222222222222222222221$11$122222222222222222222449y6-qq9864222222222222222221$122222222222222227itttptrrttq2222wtttttttttttt52215<pttttttttttttttttpa<<itpptptptppttpttattttattt72242222234457$122222224itttttttttttttttattttttttti622322222qttttttttpw2$22222212$$$1111122222222222222222222222222222222212111111$$$$122$2222222222222222222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222122$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222%",
+"@222222222222222222222222222222222222221$1212222222222221$$1$$$$11111+1111111$$$$$$$$2221222121$2222222222222222222222222424221$1122222222222222222222222222222222122222222222222221$111222$214utatattttttttttattttttttatataattttattttttttattttatatttttt<ttttttttttttatttatatatattatttttttttttttttttttpttttt<tttttttttttttttttattttaattttttt6222222222222222222226ttpu&222222222222222222222222222222222222222222222222222222222222222221$12221112222222222222246uiai752222222222222222222222222222211$122111222222222222222222228uit<tiiut0222222222222222221$12222222222222222wtpttpttrrpe2222wtttptatttttte7636<ppttptttattttttptpptr<itppttttttttttatttttttppi77775335weeiu&122222240ttttttatttattttttattttttttte26764257tttatttatti5$222222221221$1$1111222222222222222222222222222211111$$$$11222222$1222222222222222222222222222222222222222222222222222221+2222222212222122222222222222222222222222222222222222211$222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222221$222222222222222222222221$$$$+$$$$$$$121222212222221222$1222222222222222222222222844221112222222222222222222222222222222222222222222222222222$$1122$227atttttattattttttttattattttttttttatttttttattttattttttttttt<tttpttptttattttttttttttttttttatttattatttptptptttttt,tttttattattatttttttattttttatatt4242222222222222222224ttt6$2222222222222222222222222222222222222222222222222222222222222222211$221$$22222222222222226wyuw22222222222221222222222222222221$221111$122222212222222222224itrrtpattu422222222222222222$12222222222222222ettttttttrtt64220tatttttttttttpierppttttatttatttpttttpptpr<tttpttptttptttttttatttttptpiiuittaa<e62212257ttttatttatttatttatttattttttte24qieqipttpttttttti6$222222222221121$$$111122222222222222122222211111$$$$2222212222211$222222222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222%",
+"%12222222222222222222222222222222222222$12222222222222222222222212221$11222212222222222222222221$2222222222222222222222214422222$122222222222222222222222222222222222222222222222222221$$1+224iaattttatttttttttatttttttattptptpttattatttttatptpttttttttriptpttttttattattatttttttttttttttttttatttatttttttttptetatatattttatttttttattttttttttie2222222222222222222224ti02$2222222222212222222222222222222222222222222222222222222222222222221$11$112222222222222222247644122222122222222222222222222211$22222221$11222222222222222246ip,ttttttt622222222222222222$12222222222222224utttpttpttrtu3220tttttttattttiiqrttttttttttttttattptttttttt<<ppptptpttttttttpttpptptttttttttpp,py42126utttttttattttttttattttttatttttw226tttptptttttattttr*3222222222222212221$$$111122222221222211111$$$+122222222222222221$1122222222222222222222222222222222222212222222222222221$222222222222222221222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%22222222222221222222221221222222222222$12222222222222222222222212221$11222222222222222222222221$22222222222222222222222222222221$1222222222222121222222222222222222222222222222222222221$+124aatttttttttataattttatttttttptttttttttttttatttttttttptpttt<ttttattattttttttttttttatattaatttttatttttttttpttptpttetttttttattttataattttttaattttq222242222222222222222226ty42$$22222222222222222222222122222222222222222222222222222222222222222$$+$22222222222222222222etq2222222222222222222222222222221$1122222221$1222222222222222226ut<tpttttpe22222222222222222$12222222222222222tttttttttprri5229tattttttttte66>ttttttpttttatatttttttpptttttr<ttttttattaatttttttttttpttptpttpi<tt0544ytattattttttttatatttttttattttttu222etttttptattttttt<iye22222222212222221121$$$1111121111211$$$$$1122222222222222222221$2222222222222122222222222222222222222222222222222222222+1222222222222222222222222222222222222222222222122222221$22222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222221$22222222222222222222222222221122222222222222222222222222$1122222222222222222222222222222211122222222222222222222222222222222222222222222222222222$$$13aatttatttattatttttttattttttttttttttttatatttttttttttpttttt<tttattttattttttattttttttttttatatattttttatttatttttttt,pattttttatattatttttttttttttt622222222222222222222222wtw222$22222222222222222222222222222222222222222222222222222222222222211$1$122222222222222222222uu6222222222222222222222222222222$12222222222211122222222222222223qittttttiq42222222222222221$12222222222222222utttpttptttrr522yittttttttti51&ittttttpttttttttttppttttttttttt,<tptattttatattttppttpttttpttpt,pptttyetttatttattttttttttttttattatttti72224itttttttttttttt,tti22222222222222221222221$$$$$$$$$$$$$112212222222222222221222221$1222222222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222222222222$1222222222222222222222222222221121$222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222%",
+"%2222222222222222222222222222222222222$12222222222222222222222222222$122222222222222212222222222$122222222222222222222222222222221$122222222222222222222222222222222222222222222222222222$11+3pattttttttttttttttattttattttptptptttttttttatttatptttttptt<tttttttttttatttttatttaattttttttttttattttttttpttpttpt,ttttaattttttttttttttatttttttw22222222222222222222222372221$122222222222222222222222222222222222222222222222222222222222221$$12$122222222222222222222542222222222222222222212222222211122222222222211$12222212222222211*ittitii6222222222222222221$12221222222222222utttttttttttr324itttatttttt61$6ttttttttttattttattttttpttpttttttt<ittttttttttptttttttpttpttttt<tptttttttttttttttatattttatattttttttaty22221etttptttptptttt<tti422222222222222222222221111211211121222222222222222222222222222$2222222222222222222222222222122222222222222222222222222$12222222222222222222222222222222222222222222222222222221$1222222222222222222222222222211$$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222221$12222222222222222222222222221$1222222222222222222222222221$222222222222222222222222222222221$22222222222222222222222222222222222222222222222222222$122qr>er>ripppttapptptppptttttttttttptatttpttptttttttptpttptt<tttttttttattttattttatttattttttttptatttttattttttattttrttpttattttatttttttatttatttate22222222222222222222222222211$2222222222222222222222222222222222222222222222222222222222221$$11221$22222212222222222222222222222222222222222222222222111122222222222222111112222222222221$5q655422222222222222222221$12222222222222222uttttttttttte$22yttttattttw2$1ettttatttttttatttttptpttpttttttttttrrtippppttptttttttttttttttt<ttpttttttttttttttttttttptptpttptttttty8222225utatttpttptttt<ppt722222222222222222222222222222222222222222222222222222222122221$2222222222222222222222222222222222222222222222222222221112222222222222222222222222222222222222222222222222222222$1222222222222222222222222122$$$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222$112222222222221222222222222222$1222222222222222222222222221$22222222222222222222222222212222211122222222222222222222222222222222221222222222222221$1222uuaitti<<,<<<<pppttpptpptpttptatptttttattttpttpptttttttttrrtppttatatttttttttattttttptpttpttttttttattttaattttttt>pttttttattttttatatttatttttttu22222222222222222222222222211$212222222222222222222222222222222222222222222222222222222221$1112222$122222222222212222222222222222222222222222222222221$1222222222222222211$1222122222221$222222222222222222222222222$22222222222222224utttttatattt52$23itttttati3$4ei7ittttattattttatttttttttttttattttttirrptpttttpttptptttatttttt,tttttpttptpttatattttptptttttttttptpiy422222146ttttattttpttrrptti02222222222222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222222222221111122222222222222222222211$$111222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222%",
+"%222222222222222222222222222222222222$122222222222222222222222222222$2222222222222222212222222221$2222222222221222222221222222222221$112222222222222222222222222222222222222222222222122%2224aaatptpttittrt<<<<<<rpptpppttttttppttttttppttpttttttppttt<ttttttttatttattttttattttttttttttptttttatttatttttttttt<tttatttttttttttttatttttttttty22222222222222222222222222221$1222222222222222222222222222222222222222222222222222222221$$122222221$1222222222222222222222222222222222222221222222221$122222222222222222211$112222222222$222222222222222222222222222$12222222222222222yttttatttttt421$25ettttttq13utt6wtttttttttttttattttttapttataatttttttr<ttpttpttpttptaatattttt<tttptttttttattttttttptttttttttttptu54222222126ttattpttpttt<tttttt6222222222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222212221$12222222222222222222222222222222222222222222222222222221$11222222222222222222211$$11122222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%122222222222222222222222222222222211$222222222222222222222222222221$22222222222222222222222222111$2222222222222222222222222222222221$2222222222222222222222222222222222222222222222211112222aaatttttppttttrttrttr<<<<<<ttattppptattpttpttttpttpttttpt<tttptttttatttatttttttttattptptptttttatttattttttattatt<ttptttattattattttttttattattt622222222222222222222229y42221$22222222222222222222222222222222222222222222222222222211$$112222222221112222222222222222222222222222222222222222222221$122222222222222222222211$222222222$$222221222222222222222222221$12222222222222225tttttttattti422$123itattr22etttiuitttaatttttattttptptttttttttttatttapt<rttttttttttttttttttt<tttpttptptpttttattatttttptpttptpppt72222222222qtttttttttttt<tttttt6222222222222222222222222222222222222222222222222222222222221112222222222222222222222222222222222222222222222222222221$12222222222222221222222222222222222222212222222122222221111222222222222222221$$11112222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222%",
+"%22222222222222222122222222222222221$1222222222222222222222222222222$11122222222212222221222222221$22221212222222222222222222222222221112222222222222222222222222222222222222222222221$122224iaatptttptatttttpttttirtiiirr<<<<<atapppppppppatpttppptpt,tptttpttttttttttatttttttttptttptttattttttttttatttptp<ittpttttttattttatttttttatatt722222222222222222222222wa42222$2222222222222222222222222222222222222222222222222222121$11222222222221$1222222222222222222222222222222222222222222222$12222222222222222222222211$11222221$2222222222222222222222222222$12222222222222225tttttttttppi2222$127iyrq326ttpttattatattttttttatttattatttattttttttttterr<pppptpttttttttaptt<tpttttptttptttttttatttttttttiye966542222222224ittattttptppp<tttttt52122222212222222222222222222222222222222222222222222222222222$11222222222222212222222222222222222222222222222222222221112222222222222222222222222222222222222222222222222222222112222222222222221111112222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222%",
+"%22222222222212222222222222222222222$2222222222222222222222222222222$12222122222222222222222222221$12222222222222222222222222222222221$122222212222222222222222222222221222221222222211122224iaattptttttttttttpttppppaatirritpt<rurr<iaapppattatpatptp,ptttttttttttatattatattatatttttttpttatttttattttttattp,ptttattttttttatttttaattttttt622222222222222222222222wi62222$12222222222222222222222222222222222222222222222222221111222222222222211122222222222222222222222222222222222222222222$1222222222222222222222222221$1222122$2222222222222122222222222221$22222222222222226itatttttttti32221$24543122uptpattttttttttatttttttttttttttttttattttttu7ttt<<ptttttatatttttt<ttttpptttttttatttttttpttptttu634222222221222228tttttttptttprrtttptte2222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222221$11222222222222222222222222222222222222222222222222222222112222222222222111111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222$12222222222222222222222222222221$12222222222222222222222222221$122222222222222222222221222222222221$12222222222222222222222222222222222222222211$111222229yattpttttttu7qttttttttptatppppptt<rirrtr<rrrrrtattaatttt<ptttptttattttttttttatatttptpttptttattatttttttttttttt,tttttttttattttttttttttttttti4122222222222222222222227a42221$22222222222222222222222222222222222222222222222222222112222222222222221122222222222212222222222222222222222222222222122222222222222222222222222221112222212222222222222222222222222222122222222222222227ttttattttttie42221$$221122qituttttttttttatatttttattttttattttttttttttw6taprpr<pttaiiattttpt<tttttttpttppttttttatttttttti7222222222226541126tttttatttptt<tttpttti7222222222222222222222222222222222222222222222222222122222222112222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222122222112222222222222111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222%",
+"%1222222222222222222222222222222222$11222222222222222222222222222221$222222222222222222222222222221$22222222222222222222222222222212222$1222222222222222222122222222222222222222221$122222222248ttttpttpi72ettptttptptttpptttpttaaaaprt<rrrrrrrr<<<tpt<pppttattttattttatattttttatttttttptttttttattattattptt<tttpttattttattatatttttttattt422222222222222222222222372221$122222222222222222222222222222222222221222222222222222222222222222222222222212222222222222222222212222222222122222222222222222222222222222222222222222222222222222222222222222222122222222222222222222227tutttttatpttt72222211$22265975ittattatttttttattttttatttttatttaatattt66qippprrrttq667itatprrtptttptttttttttattttaattptte422222222222que726etattttttpppr<tttttttpi222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222221$12222222222222222222222222222221$112222222222222222222222222222$122222222222222222222222222222222211112222222222221222222222222222222222222221$1222222222222qttte7eu726ttttttttatttttattttatatttttatppatirrrrrrrrr><rtpppppppppaptttttttatttptttttttptpttttttttttptpttp<ttttttttttttttttttptttttttat942222222222222222212222222222$222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222212222222222222222212222222222222222222222222222222222222222222222222222222222222222222222224uetpttptttttti622221$$222569226uttttttttttattttatattttattttttatttttt634etttate>742227tttt<pptptpttptatttttttattttttttte2222222124226uai0utpttpttpttpt<tttttttttw222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222122222222222222122222222221$22222222222222222222222222222222$122222222222222222222221222222+12222222222222222222222222222122222211222222222222222222122222122222222222211$1122222222222226ee524522etttpttattttttttttttttttttttttppttpppaptprr<><<rrrrrriippattttataatttatttppttttttttpttttptttttptp<tttptpatattttptppttttatttttt044222222222222222222222222222$2222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222227ettpttttpttpttq566&1$$222662225tttatatttttttatttttttttttatttttttttt5227tttie62$$1226tttrrttttttttttttttatattttttttatte222222247q055etatttttttptttttirttttttttu3222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222212222222222222222222%",
+"%1222222222222222222222222222222222$22222222222222222222222222222222$122222222222222222222222222222$1222222222222222222222222222222222221$2222222222222222222222222222222222221$$2222222222222222243222225itttttttattttatttaattttttatatatttttppptppta<ppaprrrrrr<rprrrtttttapptttttptttpttttpttppttpttttttt<tttttttttttttpttttptatatttttq5222222222222222222222222221$12222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222221222222222222222222222222222222222222222222222222222222222222240ittttpttptptttteirq22$$22434666ittttttaattttttttttattttttatttttttti2224tie62222$$115tpp,tttptpttppttttttatttttttttttty855356wetptuuttttttttttttptpp<pptatttttw2222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222221222222222222222222222222222$12222222222222222222222222222221$22222222222222222222222222222211222222222222222222222222222222222221$122222222222222222222222222222222211$12222222222222222222212222wttttptttttatttattttttatttttttttptptttpttttp<pppppppptta<<r<<<riiiiiittptpptpttptpttttttttttptpttrrttpttptttttattttptttttttattte2222222222222222222222222222$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222221222222222222222222222222222222222222222225ettptttttttttttterri5221$2226piitattatttttttttatatttatttatttatttttti4226eq42222222$$2ttr<ttptttttttttattttttttatatttttayuyyytattttattttttttttatttppr<ptpttttttq2222222222222222222222222222222212222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222%",
+"%2222222222222222122222222222222221$22222222212222222222222222222221$1222222222222222222222222222222+2222222222222222222222222222222222221$2222222212222222222222222222222111$122222212222222222222222222ettpttpttattattttttttttatttttttatttttttpttpt<ttpttptttaappppttir<<<<<rttirprttttpptppptptptttpttt>ttttttptptttttttttttttttttatu72222222222222222222222222221+2222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222ytttttttttpttttte<ieq4221$216ipptttttttatttattattttttttattttttattttu424q222222222222:it,pppttttttttttaatttttatttattttttatataatttpttptttatttattttttt<ttattattpt62222222222222222222222221122222222222212222222222222222222222222222222222222222222222212222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222$222222222222222222222222222222222$2222222222222222222222222222222$2222222222222222222222222222222222221$12222222222222222222222222222221111222222222222222222222222222etttttttttttttttttaattttttattattttapttpttttt<ttttttatttpppttttatppppp<<<<<<<trttirtpappttttttttpp<ttppttttttptptptptpptttttaiy05222222222222222222222212222112222222222222222222222221222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222utttptptpttttttirteeu22212$22qpptattttttattttttttttatatttttttattatti426q222222222225pr<<ttttptpttpttttttttttttattttatatttttttttatttttatttttttattttirttttttttpi22222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222221$122222222222222222222222222222222$1122222222222222222222222222221$12222222222222222222222222222222222221$222222222222222222222222222211$112222222222222222222222222224uttattpttttttattttttttttatttattttttttttptttt<ttpttptttttttttptttttttpaptpppp<<<<<<<tritttttpptttt<tttttptpttptttttttttttttat0492222222222222222222222222222$22222222222222221222222222222222222222212222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222224itttttttttptppr<ttptu122241$14itttatttttttttattttttttttttttattatttty97e422222222222qtt<<<ttttttttttatattattttatttttttatttatattttattpttatattttttaatrttttttttatu42222222222224222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222%",
+"%122222222222222222222222222222221$121222222222222222222222222212222$1222222222222222222222222222222$12222222222222222222222222222222222221$1222222222222222222222222211111122222222222222222222222222222ittttttatttattttattttattttttttattttptptttttt,ttttttttattpttttpttptptpppttpppatttppp<<,,<<<ttrtttt<tptptttttttttptptttttattti6222222222222222222222222222211$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222wttttptptttttirptttte4226722$29utatttattttattttatattttatatttttttttiyttt222222222224utrrpt<<tttpttptttttttttattttttttttttttttttttttttttttttttattttrrttattattttu4222222222223e222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222$1222222222222222222222222222222221$1222222222222222222222222222221$12222222222222222222222222222222222221$2222222222222222222222211$$112222222222222222222222222222222uppttttptptttattttatttatattttattttatttttttttratttttatttptptttttttttattttattttattttatttttti<<<<<<<,ptt<pppppppttttttttttaaaaq4642222222222222222222222222111112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222221222222yittttpttatt<rpiitttte224u222$$3wttttpttpttttttttttttttttttatttttteqttt42222222222qtp<tttt<<rttpttttttptttttptptattttattttttttttttttattttattttatp<pttttpttpttt72122222222277222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222$",
+"%222222222222222222222222222222222$1222222222222222222222222222222222$2222222222222222222222222222222$12222222222222222222222212222222222221$222222222212222222222222$122222222222222222222222222222222226tptptttttttttttatttttttttttatttttttatattttteitattttttatttttpptattttttatttttttttattttttttptttttt><<,,<<<pppttttpttptpttauaa37a8222222222222222222222222221$1122222222222221222222222222222222222222221222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222220tttttttttt<itt66tttti742242221126itttattttpatttattatattatttttttei5qiui52222222237tt<ittppptrrttattapttttpttttttttattttttatattttatttttttttattttt<ipptpttttttttt6222222222564222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%122222222222222222222222222222221$2222222222212222221222222222222221$2222222222222222222222222222221$222222222222221222222222222222222222221$222222222222222222221$$1122222222222222212222222222222222224qitttttatpatttttttttttttttttattttttttaattat<aatttttttttttttttttttttttttttattttttattttttttttptpp,ttttttt,><<<<<ppppttttq6742484222222222222224422222222222$122212222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222wttuitpptt>tttt72utttti04222222$15itattttttptttttttttttttttttttw4445326222222227eitt<ppttttppirrttttttttattptttttattttttttattttaatattttttattttttritttttptppttpt4222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222221$12222222222222222222222222222222221$2222222222222222222222222222221$122222122222222222222222222222222222221$12222222222222222222$11222222222222222222222222222222212222226itttttttttttttattattatttttttttatttttttttt,tpttattattptpttpttttattattatttatttttttttatatttttttt,tttttttt<ptpp<<<<<<<ttq2222222422222222242422422222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222witwytpprrtyittu5ttpttat032222211-ttttttptttttattttttaatttttttt0222222222222250ittt<tptttttppptr<tttptptttttptpttttttttattttattttttttatttttttttrttattpttttttppi4222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222221222222222212222222222221$12222222222222222222222221222222222$12222222222222222222222222222221$222222222222222222222222222222222222221$22212222222222222$$1122222222222222222222222222222222222222225itatttttttatttatttttttatttattatttttttttt,ptttttttttttttpttattattatttttttttaattttttttttatpttt,ttttttttttpptttitrit<<%%$$$11222222222244222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222$1222222228utyiiprrtti60ttetptttttu922222225<ptttattptpttptttttatttttttatw2222222222222ettttt<ttttpttpattti<<ppppttattttpttattattttatttttttttttaatttttttirttattttttttptti2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222122222222222222122222222222222222222222%",
+"%22222222222222222222222222222221$22222222222222222222222222222222221$22222222222222222222222122222222$122222222222222222222222222222222222211$1222222222222211$1122222222222222222222222222222222222222222226taatatatttattttatttatttttttattttttptptt,ttttatptpttatttttttttttttttttatatttttaatattatttttpp,ttttpttptpttttptttpptq41111$$$1$$$2122242222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222221$2222222229wiuirrtttt329witttttttt022221446r<ttttttttttttatattttttattttti4122222222226ttttt,tttptttttttttptt<rppttttttptttttttttatttttatttttttttttptttt<ttttttatttptttte4222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%12222222222222222222222222222221$22122222222222222222222222222222221$22222222222222222222222222222222$122222222222222222222222222222222222222112222222222222$$112222222222222222222222222222222222222222222246uttttttttttttttatttatatttttattttattpttrttatttttptttttttttattttttattttttttttttatttttatttttt,tpptptptttttttptttptw4221221111111$$$$$$1222222222222222$12222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$2222222245uyqrptttu22246etatttti522222eertr<ttttpttttttatttttttatattttt422222222224uttttrrttpptpttpttttpttirrttattatttttttatattttttttatattatattpttpprrptttttttttttptt62222222222222222222222222222222222122222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222221%",
+"%22222222222222222222222222222221$22222222222222212222222222222222221112222222222222222222222222222221$1122222222122222222222222222212222222221$22222222222$$1122222222222222222222222222222222212222222222211247iitttatttttatttttttttttttttatttttpp<rtptttatttttaatttattttatttttattttattttttttttttttptt<tttttttttttptpttttiiq3222222212222111$1$11$$$$112222222111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222122221$2222222226y6rptttt222224quattt7222247ttttptritttpttpptttttatttttttttttq32222222226tttpt<ttttttttttttatttpptrrrttttttptttttttttatttatttttttttttttttp<tptatttaattptttt52222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222221$22222222222222222222222222222222221$112222222222222222222222222222221$22222222222222222222222222222222222222111222222221$$1222222222222222222222222222222222222222222222222222277ettttttttatttttattttattatatttpttt,tttttttttttttatttttttattttttttttttttattttatttpttptt<ttttptppttpttttatt564122222222222222222221111$11$$$1$$$1$121121222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211122222222&4ettttt222452267rtte222220ttttttirtppppttptttttttttttttttttt72222222226ttptrrttptptttttttttttttptrrrrappptpatttttptpttpttatttpttttttpttrrpptttttttttatttu32222222222112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222221%",
+"%2222122222212222222222222222222$122222222222122222222222222222122222$222222222222222222222222222222222$1222222222222222222222222221222222222221$1222222$11222222222222222222222222222222222222222222222222222222254yatttattttattttttatttttttttttttt<ttttpptpttpttttttatttttttattatattatttattttttttttttt<ttatttttttttttttte22222222222222222222222221221211$1$$11O$11$1122222222212222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222221$122222221$20etttu2226e22225uti34222etttttptt<rptttpttttttatattatatttttw2222222227ttpa<pttttttttutttatpttpttparrrppptptttattttttttttttattttptptttp<ptttatattttttttte2222222227e422222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222$122222222222222222222222222222222221$122222222222222222212222222222222+2222222222222222222222222222222222222222$12211$$$112222222222222222222222222222222222222222222222222222222556quttttttattattttttttatttttatptt<tpttttttttttttttatattttatttatttattatatttttttptttttt<tttttttptttttttiq422222222222222222222222222222222222221+$$1$$1122222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222122222222222221$1222222$2247iue62227t744226qw42424ittttattpirrptttttatttattttttaattate4122222220tttrrpttpttpau6itttttpttptppptr<rtpptttttpttpttptptttttttptttttrrtptttattttattttt0422222222tteq5222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222$222222222222222222222222222222222221$222222222222222222222222222222222$12222222222222222222222222222222222222221$2211$1222222222222222222222222222222222222222222222222222222222226647itttattttttttttattttatttttttt<tttttptpttpttattttttttatttatttatttttttttttattptattt,ttttatptttpttti7222222222222222222222222222222222221222112122111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222221222222222222222222222222122111$22222$122257652222etiq52224222227ttatttptptprrtttpttttatttttttttttttt7422222226tti<pptptttti026ytttttttttpppaai<trptattttptttttttptttptttttptt<ptttttttatttatttty222222214itttu422222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222$122222222222222222222222222222222222$1222222222222222222222221222222221$2222222222222222222222222222222222222222$$1$122222222222222222222222222222222222222222222222222222222222222666itttttatttttattattatttttttptt<tptptpttttttaatttttatttttttattatataatatatttpttttttt<tptttptttttpttq2222222222222222122222222222222222222221+1222222112222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222212222222122222222222222222222222222222222222222222222222222222222222222122222222222221222222222111222$$222222222222uttt7222221642etttttttttapp<ippppttttttattattttttttt62222222qtprrtttttptte2224quttptpttttttptprrittpttpptttttptpttttttptpttrrpptttatttttttttapt222222224utttt722222222222222222222222222222122222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222%",
+"%2222222222222222222222222222222$222222222222222222222222222222222221$1222222222222222222222222222222222$2222222222222222222222222222222222122211$+$2122222222222222222222222222222222222222222222222222222222222222259iatttttttatttttttttttttattttt<ttttttttpttttttttttttatatttttttttttttttttattttptttrrtttttttpttpttt72222222222222222222222222222222222222222$222222222222222222221222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222221$121$22222222222227tttw222224qq9etttttatatttppr<tppttattttttttttattttte3222227ttt<tattattttw222226ttttttppttptttptrrippttttpttpttttatatttttttrttttttttttatttttttu222222226ttttti62222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222221222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%2222222222222222222222222222222$122222222222222222222222222222222221$2221222222222222222222222222222221+222222222222222222222222222222222221211$$$122222222222222222222222212222222222222222222222222222222222222222240utttttttttttattttttatatttttt<ttttttttptptattattttatttttttttttattttattatttttpptt<tppttppttpttttt42222222212222222222222222222222222222211$2222222222222222222222222222222222222222222212222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222212$1$222222222222222ettu222225ipaattttttttatttttrrpptattttttttttttatttti522225upt<tttttttttte222222utttttttttttttttti<rptttttpttttttatttptppt<ttatatttttttatttttt622222222etttttti2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222212222222222222222222111222222222222222222222222222222222221$2222222222222222222222222222222222$2222222222222222222222222222222222211$$122$222222222222222222222222222222222122222222222222222222221222222222124ytatttattattttatttttttatptt,tttptpttttttttttttatttttttatattttattattttttptttttt<ttttttttttttptt2222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222241O22222222222222222qet74234qtttttaatttttttptptpr<pttattttaattttattttpte54250eprrtttttttttt72822226tttptpttttptptttpprrttttttttptptttttttpprrttttttatttattttattt422222222uttttttt6212222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"$12222222222222222222222222222112222222222222222222222122222222222221$12222222222222222222222222222222221$2222222222222222222222222212222211$$12222$1222222222222222222222222122122222222222222222222222222222222222222224etppttttttttttttttatttttttrtttatttttttatatattttttttttttttttatttaatttattptpttp<tptttttttppaaau4222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222271$$222222222222222224wiu6e0ittttttatttttttttptttirtattpttptttttttpatttttywy3eirtttttttttti42w62222uttttttttttttttttpp<<itttptpttptttatpttt<tttttttpttptttttttti222222220ttttatttw222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222212222222222222222222221$2222222222222222222222222222222222221$12222222222222222222222222222222221$22222222222222222222222222222211$$12222221$2222222222222222222222222222222222222222222222222222222222222222222224uttpttttattttatattttttttrrtttttttttattttttttaatatattatattttttttttttttttttttp<ttttpttptppiaau2222222222222222122222222222222222222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222422222222$12$12222222222222222226itttpttattttttattatattttpptrittttttpttppttttttttttt64erttttatttti6525i722225ttttttatattttattpptp<<ttttppttttttttttrrttppttpttttptptpttpt42222222wtttttttti222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%222222222222222222222222222221$1222222222222222222222222222222222222$22222222222222222222222222222222221$22222222222222222222122222221$$$1122222222$12222222222222222122222222222222222222222222222222222222222222222222216itttttttattaatttttttttt<tttttttatattttatttttttttttttttatttttttatttttpttpptt<tpptttttptppape222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222122222222222222222222442222221$1222$$2222222222222222226ittttttttttttttatttttttpttt<iptttpttptttttttttattt4qrrttttttate22225i6222227ttttttttattatatptpttt<<tppttpttttttti<ptptttttpttpttpttttte22222229utttattttt822222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222221$2222222222222222222222222222122222221$12222222222222222222222222222222221$222222222222222222222222222$$11222222222211$222222222222222222222222222222222222212222222222222222222222222222222256wiuyittttttttttatttpt<taattttttttaattttattatatttttatttatttttttttattttttti<ttttpttpttpppu9222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$22222$1222222222222222222qttattttatttttttatttptttttpprrtptpttttpttptatttttt6i<pttattttt522225722222227tatttattttttttttttpttt<<ttttttttapp<tptttpttptttttttttpti52222226iatttttattt022222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222%",
+"%222212222221222222222222222222$2222222222222222222222222222222222221$112222222222222212222222222222222221$222222222222222222222112$$1112222222222222$12222222222222222222222222222222222222222222222222222222222222222222222234243qtttttttttatttpt<ttttatttattttaiatttttatttttattttttatattttttttttttt<tttptttttpttpa02222222222222222222222222222222222222221$122222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$2222222$1222222222222222250ittttatttatttatttttttttttpttrrppptttttptttttttttew<tttttttttte22222222222222utttttttttttttttttptptt<<pppptatttirttttttpttttttttttpttw2222222wtttttattatti22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222221$12222222222222222222222222222222222221$22222222222222222222222222222222221$1222222222222222222221$$1122222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222247tttttttttatttt<tttttttatttttttttttattatataitttttatttttaatattppttt,ttttttptpttttu42222222222221222222222222222222222222222$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222212222222222222222222222222222222222222222222222222$$222422221$2222222222222222uitttttttatttatttttatattatattttrrpattattttttttati566rtpttttttptq22222222222222ettattttttttatptptttttttt<<ppttttp<tttttttttttpptttptttt622222226tttttttttttt42222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222112222222222$122222222222222222222222222222222222222$12222222222222222222222222222222221$1222222222222222221$$1112222222222222222221$222222222222222222221222222222222222222212222222222222222222222222222222222224uttattttattttt<tttttatttttttttttaaitttttttttttattatttttatttttpptt,ttttttptttttt922222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222422222$$222222222222227utpattttttttattttttatttttatttttpi<atattttpttatti621*q0yttttttwq422222222222222ettttitattttatttttttpttptrt<ttttt<rptptttttptttttpttpptt722222220tttttttatttty2222222222222222222222222112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222%",
+"%22222222222222222222222222221$122222222222222222222222222222222222222$12222222222222222222222222222222221$22222222212222211$$1112222222222222222222211$222222222222222222222222222222222222222222222222222222222222222222222222222223uttttattttttt<ttattttttattttattttatatttataattttttttttttttttptipt<tptptttttttte22222222222222222222222222222212222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$122222e5245221$2222222222226uttttttatatttttttattttttttttptptptr<ttattpttttttw22&1555e0ity042222222222222224ittttiyttttaittttppteq7eeipi<rttt<ttapptuuuuppttpttttttt72222226itttatttttatta422222222222222222222221$112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222$122222222222222222222222222222212222221$222222222222222222222222222222222221$1222222222211$$$112222222222222222222222222$2222222222222222222222122222222221222222222222222222222222222222222222222222227tttttpttpttp<ttptattttatttatttttattttttttttttatattattttatttt07q>tttttttttttw422222222222222222222222222222222222222222+22222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$122222qi54eq222$1222222222240uatttattttatttttattttttatttttttttppirtpppptttttt64$422235467945222222222222224qtttttiwe665666655we7522346uttp<<65667q7655356upppttttttt5222225utttattttatttta9222222222222222222221111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222%",
+"%12222222222222222222222222221$222222222222222222222222222222222222221$122222222222222222222222222222222221$2222222221$$$1122222222222221222222222222211$222222222222222222222222222222222222222222212222222222221222222222222222222222etpttttttttrrttttttttttatttatattttttatttaatatttttttatttttttt623rtptptptptu73222222222222222222222222222222222212222222$2222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222212222222222222222222222222222212222222222222222222222222222222222222222222212222222222222222222222222222221$1221222et9qti2222$1222222222296utpttttttttattttttatattttttttptttptrrtatttttpppu1$222242222225222222222222250iitpptpi722222222124212222146qe7&$$222242212225qeipppptte2222226tatttttattttttai4222222222222222222211$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222221$122222222222222222222222222222222222221$122222222222222222222222222222222221$2222221$$11112222222222222222222222222222212$1222222222222222222222222222222222222222222222222222222222222222222222222222226tttptttttt<ttptptttttatttatttatatataatatittattattattattttttw4$6tttppttuu722222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$11222142qtyttt42221$222222222296uptttatattttttttattttattttapttpttttpirrttpttttq7&12222222222222222222222227uitteqquue62222222222222222222245&$$$1122222222224557eepai62222225ttttttttattttaaaw22222222222222222221$11222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222221$122222222222122222222222222222222222222$122222222122222222222222222222221211$222$1$1$$12212222222222222222222222222222221$1222222222222222222222222222222222222222222222222222222222222222122222222222222uttttppttt<ttttttatttttttttttttttttttttttatttatttttttttapttuq&6eptuq765642222222222222222222212222222222222222222222$122222222122222222222222222222222222222222222222212222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$1222222655ttptt72222$12222222224uippattttttttttattttttttattttttttpatptt<rpttttte&22254522222222222222222222ettttyq977764222222222222222222222$122$$11222222222222457q62222222qtttttattttatttaay22222222222222222221121222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222221222222222%",
+"%1222222222222222222222222212$1122222222222222222222222222222222222222$122222222222222222222222222222222222$$1$1$$122222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222222222222222222222222222etttttpttt<tttttttttttttatttttttaiattatattattttttttttttuuttti&65eu62221222222222222222222222222222222222222222222222$12222222222222212222222222222222222222222222222222222222222212222222222222222222222222222222222222222222221222222222222222222222212222222222222222222222222222222222222222222222222222222222222222221$11222222655ettttq77722$1122222222yitttttatttattattattttatttttpttttttttpttripppttrqe8809522422222222222222229ittatpiueeueq765534224222222222221$22222$1$22222222222222965222225ittttttttatttttaiy22222222222222222111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222221222222%",
+"%2222222222222222222222222212$1222222222222222222222222222222222222222$122222222222222222222222222212221$11$O$$2222222222222222222222222222222222222222211$222222222222222212222222222222222122222222222222221222222222222222221222222227ttttptttt<ttptptttatptttttataiatttttttttttttttaattattayeutte$222522222222222222222222222222222222222222222222221222$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$1222222222498ttttutptq56*2221122229uttttttattttttttttttttttttittttpptiiueee<<ttprrptwyy042222222422222222222wttttttttppppptuueww77q32266654222$1222222$$112222224367qeitu45567ittaatattttttattaai422222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222$111111$2222222222222222222222222222222222222221$222222212222222222222222122111$11$$$1$122222222222222222222221222222222222222222222$122222222222222222222222222222222222222222222222222222222212222222222222222224utttttttt<ttttttatatptpttttatatattatatttttttatattttataau0itq$222222222222222222222222222222222222222222221222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$12222222222424euittttttiiu*328622229itattttttttattttttatttttyte7uitiuww754227<ttr<tppiuy622222225322222222222qtptpttptppttttatattaate00uttue73$$222222222$$122257qeiappttu7uitatttttattttttttataap32222222222222211$12222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222%",
+"%222222222222222222222$$$$$1$$1112222222222222212222222222222222222222$1222222222222222222222111111$$$$12222$122222222222222122222222222222222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222120tttttttt<tttptttttttttttttttttttttttatttatttttttttttttt7er7$22222222222222222222222222122222222122222222222222221$12222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222221222211122211$$222222222222222890uttitppptr74ut6224uatttattttattttattttattau5e0246q06222122227,r>utttuyuy5222227q422222222224ettttttttttttttttttttttppptttppte*421457565221$237uttattttttiuttttatttttttatttattttaaq2222222222222211112222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%122222222222222222222222221$O$$$11111$1122222222222222222222222222222+1222222222222222111111$$$$$$2222222221$2222222222222222222222222222222222222222222211122222222212222222222222222222222222222222222222222222222222222222122222222222iaaaaatt<ptptptpttpttpatattatattatttattttattttttttttttti94&112222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$2211$122222222222222224459aiwaattttrqttq125tttttttpttptatttatttttatq2241222222222222226--7qeuwttu722246u522222222224qttptptttttttattttatttttttattatttuu098yttttiy9446qttpptttttttptptpttpttttttattttatttttu222222222222222$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$",
+"%2222222222222222222222222111$221$$$$$$$111121111122212222212222212221$1222222111111111$$$$$$$121222222222221$2222222222222222222222222122222222222222222211122222222222222222222222222222222222222222222222222222222222222222222222222222aaaaait<ipttttttttttttttttttttatiattttattttttatattttattai2$122222222222222222222222222222222222222222222222222222$12222221222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$11$$122222222222222222244%y04w0ttttt<it7127ttttttttttttttttttatttttw422222222222224232$14$$227utie52267222222222224yttttttttpptttttattttttatattttttttrpttttttttttauiup<<rpptpptptttttttttptattttttatttttttt42222222222221$2222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222$12212222211$$$$$$$$$$21111111111111111111$1111211$$$$$$$$$1122222222222222222211$2222222222222222122222222222222222222222222211$12222222222222222222222222222222222222222222222222222222222222222222222222224aaaaaat<tttttttpptpttpttattattttatttttttatttttttattattttu4$222222222212222222222222222222222222222222222222222221$222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222221+$22222222222222222222222282224uptptt<t073ytttttttptttatttttattttttty42222222243256ye51222$24347642225222222222227ittttttttttttatttttttttttttatttttp<iattttttttttatttatp<rppttttttttttttttttttttttttttatttt52222222222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222$122222222221222121111$$$$$$$$$$$$$$$$$$$$O$$+$$$$1221121212222222222222222222221$1222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222222222222222222222222224iaaaaat<tttptptttttttttattttatttttttatttttatttatttttttttw2$122222222222222222222222222222222222222222222222222111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$O11222222222222222222226aw82422qtttttt<te2wtttptpttattttattttttttttttrwuue5423euett71$22222$$22222222222222222227ttttatptptttattttattattattttttatttrrppatttttttttatttttppr<tttttpttptpttpttpttptattattttttt622222222222$$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222122222222222222222222222222%",
+"%222222222222222222222222221112222222222222222221221222112211122122111$112122222222222222222222222222222222221$2222222222222222222222222222222222222222222221$2222222222222222222222222222212222222222222222222222222222222222222212222240ttiaaat<tttptptptpttttattttaatttatttttttattattttttttttpi41$1121222222222222222222222222222222222222222222222222111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222211$$11$122222222222222222229eaaq2229iptttttir624ittttttttttattttattttattttttttttuuutttti3$2222221$1222222222222222226ttptttttttattttttttttattttattttttpt<ppptttttttataattttttttt<<pptptpttttptpttttttattttttttatw22222222222$122222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%122222222222222222222222222$12222222222222212222222222222221222222221$122222222222222222222222222222222222221$22222222222222222221222222222222222222222222211122222222222222222222222222222222222222222222222222222222222122222222222222wttaaaap<ttttttttttptptttttttttatttattatttttttttttatatttq22$12222222222222122222222222222222222222222222222222222112222222222222222222222222222222222222222222222222222222222222122222222222222222221222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222$$1222$12222222222222221222waaa72220itptttttq123ittptattttttttattttatttttapttttttttttttiq652222222$$2222222222222146itttptatattttattattttttttatttttaptt<pptttataattttttttttttttttr<rtttttpttttttpttptttttttattttq2222222222$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222212222$22222222222222222222222222222222222222222$122222222222222222222222222222222222222$12222222222222222222222222222222222222222222211$122222222222222222222222222222222222222222222222222221122222222222222222224utttaap<ttttttttttttpttttatattttatatttattttttattttttati31$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221122221$12222222222222222228uaae61246tttippe2$27ttttttattttttatattttttiiutttttttttttuur>iie222222221$2222222222226utttttttptttttatattttttattttttttttttritptpttattttttattatttptpttttr<tttpttptttttpttttatttttatptw222222222$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%222222222222222222222212221$12222222222222222222222222222222222222222$122222222222222222222222222222222222221$12222222222222222222222222222222222222222222212$2222222221222222222222222222222222222222222222222222221112222222222222222228ttttirrtttptptptpttttataittttattttttattttatttattttttu921$2222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222224uaaaa4224ituuti511&7ttttattttattttttttttty644quituiuie54431257i4222222221$22222222226itpttttttttttttttttttattttattatatttp<rttttttttttttttttttttatttttppptr<tttttptptttttattttatttttpy22222222$122222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222%",
+"%12222222212222222222222222$122222222222222222222222222222222222222222$122222222222222222222222222222222222221$122222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222111$$$$122222222222224uaatt<ttttttttpttttptttattattiaatttatttttattttpttttty222$22222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222221222222222222221$112222222222222224yaaiat0226uw0iiq221$7tpttttttttttattttattt5222234534554121$2224e62222222221$2222226ueittttttttptpttttatttttttatttpttptttpt<ttttttttattttaatatttattttptttattrrtptttttttttatttttttttttty42222221$222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222212222221%",
+"%222222222222222222222222221222222222222222222222212222222222222222221$1222222222222222222222222222222222222221$222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222111111$$$$$$12222222236utt,ttttttptttpptttttttttttttttttttattttttattttee95221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222221112222222222222224yaapaau42664yi622367<<ttttttttattttttttttt822242222222221$122226722222222222$12226itttttpptptttttatttttttatatttttttttptpp<ttptttptttttattttttttttptttatttttpirrtptattattttttatattatttu2222222$1222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222122222222222222222222222222222222222222222222222222222222221$222222222222212222222222222222222222222$122222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222211111111$$$$$$222226up<ttttptttpttttptattttttatatttatattttttttttttw422222$222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222222222222222229uippay22324ti4124ettrtpptttaatattttttatte4224q322222222$122223w422222222222$1$22etptttptttptttttatattttttattttttttttttpr<pptttttttttttattttttattptttttttptpptrrpttatttttttttttattttte222222$$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222$222222222222222222222222222222222222211$2222222222222222222222222222222222222222222222222222222222221222222222222222222222222122222222222222222222222212221$11111$$11$6e,ttttttttttptttttttattttttttttttttattatttptti222211$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$1222222222222222226quti622212iq22226utt<paattttttttatttttt62223ie2222222$2222227i222222222222211$2tttttttttttttptptttttattttttttattpptttt<ppptptptattatttttaattttatttpttatttttpprrtattttttatttatttttat0222221$22222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222$112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$1$$1$1*;rrtaapaptptappptattttttattttttattttatttttttu22221$11222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222221$1222222222222222220uty222222q322222utti<atttttttattttttpt62224qi622221$$222225ite62222222222222$2pppttattattttptttttttaatttttattttpttpp<tttptttptttatttttttttattttttttppttttttpprrtpttttatttttttattai622222$222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222221222222222222222222222222222222222222222222222222222222222222222222122222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222211$2222222222222222222222222222222222222222$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222111+%6q,rrrrrptaaappttatttattttaatttttattttttptt022222$22222222222222222222222222222222222222222222222222222222222222222212222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$1222222222222222226pp7222224422225qttpprrtattttttpttattti422214667521$1222227uptu622222222222222&<ptptttttttattttttttttttttttttatttptarrapttttttttattatattatattttpttpttttpttpttttiriptatttatttttttttt52222$1222222221222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%2222222222212222222222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222212222222222222222222222222$24537<r<rrrip<iattaaatttttitattaattttttttttu222221$122222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222221$222222222222222227uu322222422225etttpppriptttttttttptuq622222226te5$1222224uueq64222222222222222-etptttatatttpptattatattattttatttttti<tttttttppttttttttattttttttttptttttttptttttp<<patttttattttttttt3222$$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222122222222222222222222221$2222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$22223qutarr<r<rriiiuiaaaatattttttttattttttt7222222$122222222222221222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222$1222222222222222246522222222224utttiippp<iatttattptiq62222222226it>522222237522222222222222222222*qiattttttttttttttttttttttatttttttt<tttptptttttttatatttattattatttttpttpttttptptpptriattatttttatttti6222$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222221$12222222222222222222222212222222222222221122222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222221222221$12222246wyiuiaprrrrrrirpiipppppppttptttttti3222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222222222222222222222222222224yiuq60iiit<tptpttttte222222222226q<ie2222222222222222222222222222227<ppttpttptttttattttattpttttptpttrrtttttttttttattttattatttattttattttatatttttttptti<tttpttpttpttatt522$222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222212222222222222222222222222222222222222222222222221$11222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222222212477qqyiitttrr<<<rrptrrttptptppttte1222221$1222222222222222222222222222222222222222222222222222222222222222222212222222222122222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$122222222222222222222222222224472222565urrpttpttpt7222222222221$qtu222222222222222222222222222222qi<tppttttpttptttttttttttpptttttt<pptpttatattttttattttttttttattttttttttttattatppppt<iptttttttttttt62$1222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%2222122222222222222222222222222222222222122222222122222222222222222222$22222222222222222222222222222222221222221$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$2222222222212226wtttttppat<r<<<<ttrttttttte2222221112222222222122222122222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222221$222222222222222222222222222222222222224urrtttttttw42222222221$13e7222222412222222222222222222226utt<tppttptttttttaattttptttttttt<tttttattttttttttttttatttttatttttatatttttttattpttppt<ttppptptptttt61$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222$22222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222$122222222222222222uttppppttttpppt<,<<,<tttiq222221$222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222etrtttttptte222222221$12222222232622222222222222222224qwtpttt,rttttpttpattttttattttptttt<ttptpttttattattattattttatttttttttttttatttttttattttttt<<pptttttttttq$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222221222222222222222222222222222222222222222222222121$12222222222221222222222222221222222222222$1222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222211$122222222222222222qttttptttttatttttttt<<<,>-121111$1112222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$122222222222222222222222222222222222223ut<tttttttt6222222$$2222222226e0y2222222222222222246tttttttptrrtttptttttttttttttttttttirttttptattttttttattttttttttatttatttatttatttatttttttptpt<<pptttttpttq322222222122222122222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%1222222222222222222122222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222221$121222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222221$1222222222222222222etttttttatttttttttttppti2$$$+$$$1111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222212222222222$1222222122222222222222222222222222222227tt<tpatttt6222221$2222222222utti52222222222229532etttttptttttrrtttttttttaattttptatppt<tttttttttttttattttttttattattttatttattttttatttttpttpttttai<ptptptttrq222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222221$222222222222222222221222222222222222222222$222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222224qttptattttttaptttttpti62222221O$$$$$111122221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222122utirptttti322221$22222222224itttttq222222227uttuutttptpttttptpr<ppttptttttttttattppp<pppttppttttttattttattttttatatttttttttttttatttttttpttttttaar<ttttptrrr322222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222212222222222222222222222222222222222222122222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222221221$22222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222112222222222222222222227ttttttatttttttttttt622222221$11111$$$$$1221212222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222221$122222222222222222222222222222222222222qttrrttttw2222$122222222214utttttpi4222225uttttttttttttpttpttppt<tttttattttatttttpp<rttttttttttattttaattttatttttttttttattttattttttattttttptptpapi<tpttt<tt422222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222211$122222222222222222222222222222222222222222$12222222222222222222222222222222222222222222122222222222222222222222222222222222222212222222222222222222222222222222222221$12222222222222222222223etttttttttttttpttu6222222221$22221111111$$$$$11212122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222221$22222222222222222222222222222222222225itttrtpti3222&522222222225ytpttttat422124yttatttatttatpttpttttttt<tppttttttttttpttrrtptpttpttptptattttttatttttttatttttttatttttttttttttatpttttppptt<ttt<ttt622222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222221$122222222222222222222214uttttttpatptttty5422222222$12222222222111111$$$$$$12112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222221222222$1122222222222222222222222122222222220ittattritq222$6e2222222226itttatttti24447yttttttttttttttttttptttttt,tptattatattttttrtttttttttttttttttttttttatatttttttaattttttatatattattttttttttpttti<r<ttttq22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%1222222222122222222222222222222222222222222222222222222221222222222222$2222222222222222122222222222222222222222222$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$222222222212222222222222qttttttttttttty32222222222$11222222222222212111111$$$$$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212221$1222222222222222222222222222222222wtttttttt<tq21$145222222222utttttttttt50ueittttttttttttttpptpttttttptr<itttaattttppa<rpptptpptpttptpttttttttttattttttatatttttttttttaattttttttttttttttpp,<tppte22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222211$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$1222222222222222222222214etatttpttttti522222222222$1222222222222222222222211111$$$$$$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222212222222222222222211112222222222222222222222222222223ettatttttprre&$121222222222wttttattatttutppattttttttttattttttttpttttppptrrattttttppp<ttpptttttttttttttatttattttttttatttttttattatttttttttty6ipttttptpttpt<rrppte222222222222222222222222222222222%2222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222221222222$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$22222222222222222222222225ittatttpttt0222222222222$2222222222222222222222222221111111$$$$$112212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222221121$2222222222222222222222222222247utttttttttttr>1122222222225wttttttttttttpptptttttttttattttttttttttptpttpttrrtattatpp<rttptttttptttttttpttttttatttttaattttttttatttttatttttti77eutttpttptt<ttrrpae22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222%",
+"%2222222222222222222222222222222222222222222222222221222222222222222221$22222222222222222222222222222222222222222211$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$1222222222222222222222222226ittttttptt8222222222222$22222222222222222222222222222212211$1111$$111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222eipptttaattttt<>$22222222225uttttatttpatptttttpttataattttattptptptptttttttttpirattttpirppttttpttttpttpttttattatttttttttttttttttttatttttttatttieeuuttttttt<rpttrriy22222222222222222222222222222222200944122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222212222221112222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212$11222222222222222222222222227etapptppi322222222222$$122222222222222222222222222222222222222111$112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222221$222222222222222222222222226etptttttttttti<ri5$222222226uatttatatttttttttttttttatttttttatttttttpttptpptptpprrtttttrtttttttttppttttttpptttttattttattatattaattttttatttttttttttiiittttppr<ppptprru222222222222222222222222222222222uiiw9222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222%",
+"%2222212222222222222222222222222222222222222222222222222222222222222221112222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$1222222222222222222222222222257euuuee7222222222222$12222222222122222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$12222222222222222222222227utptttttttttat<taprq22221222etattttttttpttpttptpttttttttttattttptptttttttttttttptrrttarrttptpttpttttpttpttttptttttatttttttttttttttatttattttaattattpptttppp<tpppppprr4222221222222222222222222222222220aaay822222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"$12222222222222122222222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222$22222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222211$12222222222222222222222222222224842222222222222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222221222222221222222222222222211122222222222222222222224utpptttttptpptriptptu&1222227ttttttttttttttttttttttattttattttatatttattttatttttttttairtr<ppptttttattttatatattatatattttattattttatttttattttttatattpttptttttttrippttpttprq122222222222222222222222222222222ittttu7422222222222222222222222222222222212222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$",
+"%22222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222211$2222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222221122222222222222222222222222222222222222222222222211$2222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$2222222222222222222222222222222222$122222222222222222222227tttttttptttpr<ipttttu$$2222qttttttatatttatattttatatttttttatttttttttttatttttttatatttti<<ppptttpttttttttttttttttttttttttttttttttttatttttatattttatttttttptptrrtptpttptttr312222222222222222222222222222224ittpttu722222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222122221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222$12222222222222222222222222222222221$1222222222222222222222qiptttttttptt<ttptttti4$1226tttttttttttatttaattaattttttttatttttttttttattttttatttttttpp<<ppttptptttatatttttatttttttatattttttatattttattttttatattttpttpptptpirptttttttttttq$1222222222222222222222222222224uptttte722222222222222222222222222222222222222222222221222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222212222222222222222222222222222222222122222222$12222222222222222222222222222222222222222211$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222221$22222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222$122222222222222222222226itptttptpr<pttttttti22$13ettpttattattttttttttttttttatttttttttatatttttttttatttattattprr<rtpttttattttttttatttaatattttttttttttttaatttatttttttttatttttttttt<ppttpttpttttti2$122222222222222222222222222224ytatttu622222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222221$22222222222222222222222221222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222$122222222222122222222227ttttttt<rtttaptptt7121$5tttpttttttttatatttttttttttaatatttatttttttatttattttttttttprrppt<iptttttttatttatttttttttttatttaatttatttttttttattataatattttttttt<ttttptptppttttt541222222222222222222222222222227iattttt72222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222$112222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222$122222222222222222222222qttttt<ttttttttttt72221-ttptttatttttttttttattttttttttttttttatttattttattatatttttpt<ptptt<ttpttttttattttaatatatttttattttttatttttttttatttttttttttppttttr<tttttttttttpttte22$11222222222222222222222222222utttttti2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%12222222222222222222222222222222222222222222222222222222222222222222222$112222222222222222222222222222222222222222221$2222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221122222222122222222222222222222222221$122222222222222222222222rtpi<ttttatatttpt72214rrppttttatttttttttttatattatatttttatatttatattttttttttttptp<ttptptp<ippptttttttttttttttttttttttttttttttttttattattattttatttttttirittttttttttttpttt632$1222222222222222222222222224ittttttt6222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222$112222222222222222222222222222222122222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222211$1222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222111222222222222222222222227t<<ttttttttttttu4222etritttattttattattttatttttttttttttttttttttttttttattttattt<itpttpppa<<pptattttatatatattatattttattattttatattttttttttatattttttte-qitttpttppttptttttu422&$22222222222222222222222224yttttttti522222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222221%",
+"%22222222222222222222222222222222222222222222222222222222222222222222221$222222222222222222122222222222222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$112222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222221$222222222222222222222222222222222221$222222222222222222222223>ipttatttttttt742222utt<tpptttattattttttatttttatattattttatttatttaattptttttpt<pptttttptttrrptttttttttttttttttttatttaatttattttttttttattttattttttte&12iataatttttttttttttyey61$1222222222254222222222227aaatttattu22222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222$222222222222222222222222222222222221222222222$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222111122222222222222222212222222222222222222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222222222222222222222222222221222122$12222222222222222222221$etptttttatttt7422224tttt<pptttttptttattttttatttttttttattttttttttttttttpptpp<rtppttpttptttrrtatttttttttatttttattttttttttttattattatttattttttatpptq$229itttttattatattatttttu61$122222222222222222222220yaaatttttt72222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222221$2222222222221222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222122222111222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222221$222222222222222222222222222222222221$12222222222222222222$$27tttttttttate222225ettttrrptttttttttttattttttttttattttttttaptpttattttttttpr<tptttttttttpttiettttttttataatttttattttttttttattttattttttttttatttttu&2224yttttttttttttttttttttu21$22222222222222222222227waattttttti3212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%22221222222222222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222221$122222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222$122222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222$122222222221222222222222222222222222$1212222222222222212$1126tttttttattt32223qutattttirttatttptatttatttatttattttatttttttttttttttptpttp<ttptpttptattttptirttattttttttttattttttattatttttttatttttttttattttttt>&2222wittttttaattttttttttppu76$122222222222222222228auaattatattt02$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222122222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222$1112222222222222222222222222222222222222222222$12222222222221211$$11222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$1222221222222222222222222222222222221$2222222222222222$$1222277ttttw9upu4225utttttttttriptttppttttttttattatttattattatttttttttpttttttt<ipppttttttttattttpr<ptttttatttttttttattttttttattttttatttatttatattpt<q222225qtttttttatttttpttptptttue:qe322222222222222217aaaptpttttttr112222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%12222222222222222222222222222222222222222222222222222222222222222222222$1222222222222222222222222212222222222222222221$12222222222211$111112222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222$122222222222221$112222222wttq42366935ytttttatatttrtpptttttttatatttttttttttttttttatpptpttttpptp<ttttttpttptatttttappp<iatatttttattattttattttattttatttttattttttttttptrtq42224utttattttttatattttttttpptirie2222222222222225uaaaatttatttt<722222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222%",
+"%22222222222222222222222222222222222122222222222222222222222222222222221$12222222222122222222221222222222222222222222221$1222222$$$$111122222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$2222222222222222222222222122222222221$222222222222$$12222222224u7322225iuutttttatattttrrppttttttttttatttatattttttattttttttttpttpttrttptttttpttttttttttpptirittttttttttttttatattatattttttttttatatttttttt<ttiq2236uptatattttttttttttttpttttti<r6222222222222228aaiaitttttptrii42222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222$2211$$$11$1111122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$1222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$2222222222222222222222222222222222221$12222222221$112222222222252222224tttttttttttttttprrppttpattttttttattttttattttatttpttptttttprrtttptptttttttatattttpppprrttatttaatttttttttttttttttttatttttttttattt<itttt746uittttttttattptptpttptttptppt<q722222222222225uaaaatattpprrtt72222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222122222222222$12222222222222222212222222222222222222222222221O1$1$1$11222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$12222222222222222222222222222221222221$22222221$1$222222222222222222224iptptatttatttttpp<rtptpttttpttpatatattttattttattpttpttttpi<ttptttttttttattttttttttpttrrpptttttttttttptptptttttttaatttattttttpprtttttttqwttttttttattttattttttttttaattttre622222222222227tttttppptriptti5222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222111$1$+$$$2222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222122222122222212222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222221111222222222222222222222222222222222221$12222211$11222222222222222222222ettttttttttttatppp<ittttpttttttttttttttttattttttttttttttr<ptttttattattatttattatpttttpprrtpptptptppttttttttttttatttttttttpptttr<ttptpttpittattttttattttttatatttttttttttarrq3122222222225etttttpprrpptttw222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222$1222222222222222222222222222222212111111$1$$$$21$222222222222222222222222222222222222222222222222222222222222221222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$22222222222222222222222222222222222221$22211$1122222222222222222222222wtttttttttttatapttt<tttpttptttttaattttttatttttttpptptttt<pptptttttttttttttttattttttttttritptttttttttttttppttatattattttttttttt<tptptttttattaattttattttttttattttattatatatprrq5222222222226ettptpi<tpptttt522222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222$122222222222222222222222222222111111$$$$$1222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222212222222212222222$212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222111$12222222222222222122222222222222222221$111$$12222222222222222222222222wttpttpttatttttptppt<tttttttppttttttatttttttttattttttpt<tppttpttaatttttttttttatpttpttptpr<pptptttpttptpttttttttttttttatttttt<tttttttptttttttttatttttttattttatttttttttttppr<e7222222222222qeitrrptpttttte22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222$222222212222222222222221111111$$$$$122222222222$222222222222212222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222221$222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$122222222222222222222222222222222222211$1$1222222222222222222222222222ytttttataattttttptttrrpttttttpttatttaatatttatttttttppp<rattptptttatttttatttattttttttptptpr<ttttpttppttptaatttttatttttttptttrrttttptpttptattttttatttattttttttttttttttttapttirr622222222222246rrtpptpttttt62222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222122222222222222222222222222222222221$122222222221222221111111$$$$$$22221222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222221$1222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222212222222221$22222222222222222222212222222222222111O$22222222222222222222222222229tatatttttttttttttttttrtatattpttttatttttttttttatpttpppripptptttttttttttttttattttpttpttttpppt<ttttttttttttttttttttttaatattttt<ttpptttttttttttttttttttttattttttttttatttttttttpt<q222222222221116ttttttttattu4222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222221$12222222211111111$$$$$$1121222222222222122222221$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222221$2222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222222222222221222211$$1$1222222222222222222222222222uttatttttattatttttptttt<tttttttttttttttttttatatttttpt<rpppttttttttttttttttttttttttpttttttttpt<tttttttttttattattattttatttttt<ppttttptttttaatttttttttatattttttttttttttttttttttti7$222222222221$3ttttttptptttq222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222%",
+"%222212222222222222222222222222222222222222222222222222222222222222222221$111121211$$$$$$$$1212212222222222222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222111222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222221$2222222222212122222222222222222211$$112$1222222222222222222222222227tttttttttttttttatptttttt<tttttptatattatatttttttttptttrttptttptptttattttttttuitatttttpttpttttpp<<ttptptpttttttttttttttttttt<tpptpttttttquitttttttttttttttty0ytatttaatttatttttttu$$2222222222$12uptptpttttttt422222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%122222222122222222222222222222222221222222122222222222222222111111111111+$$$$$$$$$121222212222222222222222222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222211$2222222222222222222222222222121$1222222$122222222222222222222222227ttttttattttatatttptptpttt<ppttpttptpttttattttatttttt<ptttttttttttaattttuqie30ttttttatattpttttttrrappttttttttpttptttttttptrtptpttptptttu69ittttttatttttttti05eittttattatttttttti2$222222222$1226ttttttptpttt722222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222122222222222222222222222222222222222222222211$$$$$$$$$$$$+121111112222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$12222222222122222222222222221$$22222222$11222222222222222222222222qttttttttttttttttttttttttp<rpptttttttttptttatttttttrrtpptattatattttttttt94222wtatttttttttttpttpttrrpptpttttptttttatatpttti<tpttttttttttti546utttttttattatttti96ettttttttttattptt22$$222222$12226ttpttttttptte22222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222212222222222222222222222222222222222222222221$1$$$1111221111211$2222222222222222222222222212222222222222222222221$122222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222221$122222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222222222221$$11222222222$22222222222222222222222226ttttttttatttttattttttppttt<ittttttttpttptttttttaptrtptpttttttttttattttt04224itttatttttatptttttttt<<tttttpttptttttattttpp<ttttppttttatatti653eywutitttattttttu34uttttttttatattti422$$2222$122224itptptttttttq22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222111111221222212221$1222222222222222222222222222222222221222222222221$222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222122222222222222222212222222222222222222222222222$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$222222222222222212222222$$11122222222221$12222222222222222222222226ttttttttttttatttpttpttttppp<tttptptptttttattttttirtttttttttttaatttttataiiiueitttttttatttttptptptttt<tttttttttptptttttpp<ttttttttattttttttti932490yuttttattttpu26itatatttttttpte22221$221$2222216tttttptpttu422222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222221222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222221$1122222222222222222222222222222222222222222222222$222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222122222222212222222222222222222222222222222222222222$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211222222122222222222222$$12222222222222221$1222222222222222222222226tttttttattttttattattttttpttt<ppptpttttttttttattiriatattttttttatttttttttaattitttattttttatttptttpttptt<<pppttpttptttttatrrttttptpttttttttaatttyeeiy06ttttttttattw46yiitatttttttt5222221$$$2222222257ettttttt7222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222122222222222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222221$12222222222222222211$1112222222222222222$1222222222222222222222224ttttattttattttttttttpttattttt<ppttptpttpttptttiuttattttaatattttttatttttttttttttttattttttptttttttttttai<ptttttttttatatirttttttttttttatatttttttttatiittttttatttttu0650ttttttttti42222221+2222222222247tptttt5222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222221$2222222222222222222222222222221222222222222222221111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221212222222222222222221$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222122222222222222222222222221$1222222222222121$$$1121222222222222222221$2222222222222222222222220tatttttttatattttttatttttttptrrattttttttpttpptuttatattttatttttttttatttttttttttttttatatttttpttppttpttapr<iptptptttattteiptptpptttttttttatattattttaatattttttttttttiueutttttttate2222222$$$2222222222226eyy762222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222122222%",
+"%222222222222222222222222222222222122222222212222222222222222222222222221$22222222222222222222222222222222222222222222222211$1222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222221$22222222222211$1111122222222222222222222$1122222222222222222222224ettttttatttttttattttattptttpt<itpttpttptttttripttttttttttttattttattttatattttattatttttttatttttttttppppptrrttttptttttuippttttttptattttttttttttttttttttttattattttattttttttatttiw2222221$22$122222222222443222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222211222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$1222222211$$11122222222222222222222222221$1222222222222222222222223ittttatttattttttttttttptttttt<tptttpttptpt<tptatttattttattttattttatttattttattttattttattttatatttttttttatrrtptttttprrttttattttttttattattttttatttttattattttatatttttattattttttte22222$$2221$12222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222221222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$",
+"%222222222222222222222222222222222222222222222222222222222222222222222221$12222222222222222212222222222222222222222222222221$1222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222$222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$122212$1$$1111222222222222222222222222222$1222222222222222222222224tttatttttttatattttattttttpatpi<pptttttttptrptpttttttattttttttttattttttattttttatttttttttattttatttatttttttrrtptppttrtttatttttpttttttttttttattttatttttttttttttttttttttttttttttt22222$2222211$222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222211122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222221$222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222221$122$11$11112212222222222222222221222222221$122222222222222222222222ttttttttttttattttaatattttptttt<ittptptpt<<tttttttttttttttaattttttttttttttttttttttatttttttttatttataatttttprrrtpttrttattttatattpattttttatattttttattttttatatttttaattttttatatttt4222$12222222$122122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222221$122122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222$$$11$$122222222222222222222222222222222222$122222222222222222222224ttttattattttttatttttttptttttatarrttttptrippttpttattattttttttttttattattttattattatttattttatatiattttttttapppptrrttrrtttttattttttttttatttttttattttttttattttttatttttttatttttttttu222$1222222222$$2222222222222222222222221212222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%122222222222222221222222222222222222222222222222222222222222222122222221$122222222222222222222222222222222222222222222222221122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$12122212222222222222222222222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221111$O$$2222222222222222222222222222222222222221$2222222222222222222222qttattttttattttttttttatttptpttpap<tptpprrpttpttttttatttattttttatttatttttttttatttttttttatatattttttptpttpttttatrrr<aatttttttapttttatttttttattttttttttttattatttttttttttttttatttu22$122222222222$1112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222221221122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$11111212222222222222222222222221$2222222222212222222222222222222222222222222222222222222222222222222222222222222122222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222111111$$$1$222222222222222222222222222222222222222222$1222222222222222222224itttttatattttttttatttttttttttttppp<ttp<ttttttttttattttatttaatttattttattttattttttttatatttttttatttpttttttatttttt<>rpptttatttttttpttttttatttttttattattttttttttttattattttattttttt31$22222222221221$11222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222%",
+"%222222222222222221122222222222222222222222222222222222222222222222222222$22222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211221$$$$111112222222222222222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222121111111$$$$1222$1222212222222222222222222222222222222222221$222222222222222222226tttttttttattttatttttttttpttttttptti<t<<pptttppttattttttttttttttttttttatattttttatttttttttattttattttttttttttttttrr<ttttattttttttptttaattttttttatatttaattttttatattttatattttttttt2$2222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$1$$$1111122222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222111111$$$$$222222221$222222222222222222222222222222222222222221$12222222222222222224uttattttttttattttaatttatttpttpptpttt<<ttttpttttttttatttttattttatttttattttttatttttattttatttttatttttptptpttttatatrpp<<tttttattptttattttttatttattttattttttatttttttaattttttatttapi&2222222222222222111122222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%222222222222222222222222222222222222222222222222212222222222222222222222111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122$$$$$11111222222222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222111111$$$$$$12222222222221$2222222222222222222222222222222222222222222$122222222222224223ytttttattttpttpttttattttttattttptppaa<,tptptptpttattttatttttatttttttttttttttttttttttttttattaiattapttpttttttttpi<tpptrrtttptttttttttttttttttttttttttttttttttttttttttttttttttptt<e3322222222222222121$12222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222211122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222211$$$$$111121222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221122121$$$$$$12122222222222222222$1222222222222222222222222221222222222222222$122222222222225226ttattttatpttttttpttttttattttttttttppr<t,tttttttttttttttatattttatttaatatattatattattattattttattttttttttpttptptptrttppttt<rttttppttptttatatttttatttttttatattttattttttttttatttttt<ttiiq52222222222222221$1221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222212222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222112111$$$$1111211$1122222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222$$$1$$$21221112222222222222222222$12222222222222222222222222222222222222222221$12222222222224226itttatattttpttptttttttatttttttpttpt<rapt<tpptttpttttttattttttttattttttttattttatttattatttttttttttttttpttptptpt<itttptptt<rttttttpttttttttatataatttttttttattataattttttaatatttpr<pttttie6222222222222221$111222222222222222222222222222212222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%1222222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222121121$$$$$11$11222222222222222222222222122222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221111121222221222222222222222222211$1222222222221222222222222222222222222222222$12222222232822226tttttttttpttttttttttatttatttattptt<ipppp<<ptptptttatttttttttttattttatattttttatttattttattttatatattptttttttttpt<ptattttttpt<ttptttttattattttttttttaatttattttttttttaatttttttttt<pptptttti6222222222222221111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222$112222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222212111$O$$121122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222122222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222221$1222222454922228ttattttttttpttptptattttttatatttpt<rpppttt<tpptttptttttttttttttattatttatttatttttttataitttatatattttttptpttpttt<ttttttttptptt<rptttttttttttatatttttttttttttaattttttttttttttapp<ttttttttttu422221222222221111112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211O111$$$$1122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$22222221222222222222222222222222222222222221$122222224122222wttttttattttttttttttatttttttttttt<ttppttttt<tppttttttaattaattttttttttattatttatattttttatatttttttatttpttttttpt<ttttttpttttttttrrttattatttttttttttatttattttttttttttatattattttp<ttptpttttttte42222222222222111112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222%",
+"%2222212222222222222222222222222222222222222222222222222222222222222222222$1222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$2221111$$$$$122112222212222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$22222222222222222222222122222222222222222221$22222222212224utttttttattptpptpttattattttttatrrttttttttpti<ptttttatattttatatttttatatattttattttttttttttiatattttatttttttttpr<pttttpttpptttptprriatttatttttttttttttttatttttttttttttttttatttrittttptatattti022222222222222111$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222221222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222222111111$$$$12222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222221112222222222222itattttatttttttttttttttttatatiriiatpttptttppirtttpttttttttttttatttttttttattttttttatattttattttatattttptptptt<tpattttttttttpttpttritattttatttatttaattattttattatttaatttttttairttpttttttttttty2222222222222211111112222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"$2222222222222222222222222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$1222222222222111111$$$$22222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222221$1222222222222etttttattttptpttttpttptppptprrittttttttttttttrrptptptptttttttttttatattttatatttttttttatttttttptptptttttatttrtpttpattttpttpttattttrraapppttttttttatttttattttttattttttpttptt<ttttttttttttttt02222222222222222221111222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222%",
+"%1222222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222221$12222222222222221211111$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$122222222222222222222222222222222222222222221$12222222222220tttttttatttttttptttttttpprritattatpptptpttpttrtttttttttpttptptattttttttttttttttattatttatatttttttttptptttritptttttpttttpttttattttr<pppttpttptptttttttttttatttttatatttttt<tppptpttpttttati822222222222222222211$1212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$22222222222222222211221111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222221$2222222222226ttttttattptptpttttttttpt<rratattttttttttttattp<ttptptptttttttttattttaattttttatattttattttttptttttttpttttrrttatttttpttttttttattttpt<ripttttttttptpttttttataatttatttptpttrrptttttttttttapty22222222222222222222211112222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222221222222222222222$222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122221222221+22222222222222222221222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222221222222222222222222222222222222212222222222222222222222222222222222222222111$222222222222222222222222222222222221222222222$1122222222226atttattttttttttptpttpprrrpattttttttpttptpttttpi<tttttttptptptttttattttttatttttttattttatatttptptptttttttrtttttpttptttpttptttttptptpp<rptptptptttttttattttttttatttatttprraattpttptpattttpq42222222222222222222211$12222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222221$12222222222qittattattttttttttttttrrtppttpttttptttttttttptpt<rpttttttttttattttttttttttatttatttttattttttttttptttppptrtpttattatttttttpptttatttptptt<<tpptttptttttaattttttttttatttttp<tttptpttttttptptt722222222222222222222222111112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222122222222222222222222222222222222222222222222222$222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$2122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222122222211222222222222222222222222222122222222222222221$11222222222wtttttttttptptttptttrrrtttpptttatattpttpttpttttparrtpttptttttttttatttaattttttatttttttataiatttptttptttp<rtpttttttttpttpttttttttttttttttrripptttttptttttttttatatttatptt<rttttttttpttttttptq4422222222222222222222211$112222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%1222222222222222222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222221222222222222222222222222222212222222222222211222222222222222222222222222222222222222222222222222221222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222221$2222222222qttattttttttttptpptrrttpttpttttttapttttptpttpttppp<ttppttppttttttttttttttttattttttataiiywyttpttpttttpr<tptattttttattptttttatpttppttttpatrrtttpptttttatattatttattttptirpptppttttptpttttttie7222222222222222222222222$11221222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222212222222$12222222220ttttatttatpttptti<rttttpttttpttttttptttttptttttppt<ttttttttatattttattttatttttttataiu008487itttttptpt<ptttttttatttttttpttpttttttttpttttptrrtttttptttttttttttttatatpt<ttpttttpttttttptpttppt7222222222222221222222222$1122222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222222222222222222221222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222122222222222222222222222222222222222222222222221112222222222222222222222222222222222222222222222$1122222227ttattttttttttpt<<pptpttpttttttttttattttatttttttttti<pppptattttttttttatttatttattttty4224222qittttttt<tttttttttttattttttttttttattttttttttttr<rttpttttttttttattttattp<ttptptttttattttptttattti52222222222222222222222221$11222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222221$1222222222222222222222222222222222222222222222$1222222226tttttptpttpttr<tttttttttttatattttttttttttttpttptatt<ptttttttattattatttttttttttttttw223e22246itttttrrtpttptpptttttttatattaattttttatatattttpp<ttttttattttpttttattttriptttttttattttattptttttttu42222222222222212222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222112222222222222222222222222222222122222222222221$12222222222222222222222222222222122222222222222$112212229ttttattppppr<rptttttttpptttattttattatatttptpttatttttrrptttttttatttttttttttttttttte4222422222qttppt<ppttttttttttttttttttttttttttttttttattappp<<pttttatatptatattttiritatttttatttttttttttttttttq22222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222%",
+"%2222221222222222222222222222222222222222222222222222222222222222222222222$22222222222222221222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$22222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222122222112222222222222222222222222222222222222222222222$12222222222222221222222222222222222222222222222$11222222wttttttptpt<<ptttptptpttttttttatttatttttttttttttttpttt<ptpttttttatttatttattttttatu2222222221246utp<ttptptpttpttttttaatttttttattattttptttttppppr<tpattttttttttttttuttttpttptttatttttpttattttttu222222222222222222222222221$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222%",
+"%2222222222222222122222222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$22222222222222222222222222222222222222222222211122222222222222222222222222222222222222222222221$12222225tatppttp<<ttttttttttttttttatttttttttatttattattattpttpp<ttatttattttttttattttitttte22222222222226qqipttttttptttttttttattttttttattttpttttttttttpti<ttattttttttttttirtattttttttatttttptttttatttty2222222222222222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%12222222222222222222222222222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222221$1222222222222222222222222222222221122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222212211$12222222222222222222222222222222222222222222222$12222222wttppp<<rttpttptptptppttptttttattttttatttttttttttttttpirtttatttttttattti9436ttti4222222222222226rtttttttttttttttttttttatatttttatttttptpttptttttp<rtttpttpptptttrtttttttatttttttattttttattttty22222222222222222222222221222$112222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222122222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222$122222222222222222222222222222222222222222222221$222122249qii<itttttttptttpttttttttttttatttttttttattttttapttpttrrtattttttttttat942225ww5222222222222221$qttttpptttttttittttttttatattttttatttppttpptttttptr<ttttttttptp<iptttttatttttttatatttattatpttt522222222122222222122222222221$$2222222222222122222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222122222222122222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222122211222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221112222222222222222222222222222222222222222222222112222222222222222222222222222222222222222221222211222222224:rttptttttttttttttpttpatttattttattttattttatttttttttttrtttttatttattt622222142222222222222222$16tttttttiew765437uttattttttttatttpttttttttttppttppi<ttptpttpprrtpttattttatttattttatttttttttate2222222222222222222222222222221$222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222221$122222222222222212222222222222222222222222222221$122221222222222222222222122222222222222222222221$2222221$$6tptpttattttattptatttattttttttattttttattttttttttttttttrtttttttttttq32222222212222222222222$12236q777444222222246777ytttttptttptpttttttttttttttttt<<apttttt<tttttttptpttttttttttttttttaptptu42222222222222222222222222222211$22221$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$",
+"%222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222122222222122222222221$1222222222222222212222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222$222222222222222222222222222222222222222222222222$12221$$123ettttttttttttttttttttttatattttttaattttttatattttatttttirttpttptptu41222222222222222222222$1222242444222222222222244356uptttttttttttatattttatattptit<tptpt<tttttptttttttttatttttattatttttttp722222222222222212222222222222211$2211122222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$11222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$222222222222222222222222222222222222222222222222$2122222222222222222222222222222222222222222222221$22$$112225ettttttaatttttttttttatttttttttttttattttttttatataatttpt<pttttttt622222222222222222222221$22222222112222222222222222226ippptttttpttttaattaatttttttpr<tpp<rtptttttptptptataatttttatttttttttpe122222222222222222222222222222221$$11122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222211122222222222222222222222222222222222222221222222$$$$12222224ittattttttatptptatttttattattatttttttattattttttttttatprrtptpttq22222222222222222222222$1222222222122222222222222222226queutttpttttttttttttttttptppt<rt<pttpttptttttttttttttatattttttpttppi422222222222222222222222222222221$$$2222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$12222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222$12222222222222222222222222212222222222222222222$$+1222222222qtttttttttttttattttattttttttttatttttttttttaatttttttttt<tpptti422222222222222222222221112212222222222222222222222222222445epatatttttttttttatpttptttt<<tppppttptttttttatttttttttapttatpttti52222222222222222222222222222221111$1112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222122222222222222$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$1222222222222222222222222222221222222222222222221$2222222222222222222222222222222222222222222221$1$$12222222224tttttaatttattttattttttttatattttttatattttttttttttattppi<tppte2222222222222222222222111122222222222222222222222222222222223qttttttttttattttttttttttt<<r<tttttttptptptttttatttttttttttttttt92222222222222222222222222222221$1111122222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%22222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222111222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222221211$1$221$1222222224itttttttttttttttattttttattttttttttttatttttttttttttttttrrppt72222222222222222222221$222222222222222222222212222222222222224yttttttatattttttpttpptptrpi<<ppttpttttttttttttttttttpttpttptttw222222222222222222222222222211$12221$11222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222%",
+"%22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222221$222222222222222222222222222222222222222111$$22222$1222222222yttattttatttttatttttattttattattatttatttatttatttaattptpprrpt6222222222222222222221$12222222222222222222222222222222222222227tttatttttattttattttttp<pppt<ttttttpttpttatttaatttattttttpttatu2222222222222222222222221222111222221$1222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222122222222222222222222222222222222222222222222222222222222222221222222222222222222%",
+"%2222222221222222222222222222222222222222222222221222222222222222222212222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$22222222222222222222222222122222222222222222222222$2222222222222222222222222222222222222111$112222211$2222222227ttttttttttttttattttttatttttttatttttatttttttttttttttttpp<iq222222222222222222222$$12222222222222222222222222222222222222228tatttttttttattttpttptrrttttp<<itptpttpttttttatttaatttattttatti22222222212222222222222222211112212222$112222222122222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%1222222222212222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222221$12222222222222222222222222222222222222222222222221$1222222222222222222222122222222222111$$$2222222222$1222222222utttttpattattttttatatttttttattttatatttaattatatttttptttpp<2222222222222222222221$222222222222222222222222222222222222222224tttttatttttttatttttpi<ptptppptriptttpttpttptttttttttttttattttt422222222222222222222222221$12222222221$11222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222%",
+"%2222222222222222222212222222222222222222212222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222221222222222222221$122222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222221$12222222222222222222222222222222222222222222222221$12222222222222222222222222222222211$$11222221222221$122222222ettttttttatatttttattttttttatttttttttttttttttaattatptpttte$22222222222222222221$2222222222222222222222222222222222222222222uatttttattttatttpttt<apttttpttt<ttttttttttttpptttatttttaaaattt822222222222222222222222211112222222222211122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$222222221222222212222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$122212222222222222222222222222222222222122222222222$12222222222222222222222222222221$$1122222222222222$122222222qtttttatttttttatttttttatttttatttttataatatttttttttttttptte1$222222221222222221$122222222222222222222222222222222222222212226ittaattttatttttttt<rpptpttptttp<<tttptpttpttttttttttataiaaati92222222222222222222222211$222222222222221$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222221$222222222222222222222222222111$$1222222222222222222$12222222qtttttttatttttaattttttatttatttttttttttatttattttttttttttt64$12222222222222222$1222222222222222222222222222222222222222222222etttttttattatttttt<tttttttpttpptr<ttttttttptttatttttttaaaiaia9222222222222212222222221$1222222222222221112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222221%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222221$1222222222222222222222222211$$112222222222222222222$12222222ettttatttttttttttttttttatttttttattatattattttttattpttpttu422$$222222222222221$22222222222222222222222222222222222222222222224utattttttttttttt<tttptppttttttttt<rtpptttttpttttaatataaaaaaa822222222222222222222221$22222222222222221111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$222222222222222222222222222222222222222222222222221$122222222212222222112221$$$122222222222222222222222$22222225ettttttttttattatattttatttttttataattttttttttttttptttttt72222$22222222222222$1222222222222222222222222222222222222222222222123uatttattttttttt<ttttttttpttpttttp<<ptttpptttttttatttaaaiaau42222222222222222222221$122222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222221$222222122222222222222222222222222222222222222222221$2222222222222222222121$$112222222222222222222222222$1222222249ttttttattttttttttatttttttatttttttattatattttattpttptt522221$122222222221$122222222222222212222222222222222222222222222222224itttttatttatt<ttptpttptttttpttpppt<ttttttptttttttttaaaaaa42222222222222222222222$1222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222$22222222222121222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$122222222222222222212222222222222222222222222222222$12222222222222222211$$112222222222222222222222222222$1122222229utttattatatttttptttttattttttatttttttttptpttttatttpt2222221$1222222211$12222222222222222222222222222222222222222222222222220tttttttattp<ttttttpttpttttttpttttt<tppttttttttttttttttat6222222222222222222211112222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222221222222222222222222222222222222222222222222222222222222222221222222222221222222222222222222222222222222222222222222221$222222222212222222222222222222222222222222222222221111222222222222221$$111222222222222222242242242222222$1122222226tpttttttttttapttttptptttaattttttatatttttttttttttte6222222111$122222111112222222222222222222122222222222222222222222222222229tatatttttt<tttttttttttpptpttttttttrrptptpatatttatttttti4222222222222222222211112222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222%",
+"%222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222221$2222222222222222222222221222222222222222221222222221$22222222222211$$111122222222222222222222222222222221$212222224uppptuttttttttttttptttatttttttttttttaptptattttttw4222222211111$11221112221222222222222222222222222222222222222222222222222226ypptttat<ppattptptttttttttpttpttttr<tttttatttataattttu222222222222222222221$112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221%",
+"%222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222221222222222222222222221$12212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$2222222222222222222222222222222222222222222222222221$22222222222$$$1122222222222222222222222222222222222111122222227euuqiaatttttptptttttttttttattattattttttttttapi7422222222222211$122$12222222222222222222222222222222222222222222222222222222250eeeeeeetpapppptttpttptptttttpttttt<rpptttttttttttai62222222222222222222211122222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211122222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222212222222222222222222221$122222211$$111222222222222222222222222222226222222221$1222222224564ytiattttttpttptpttttattttttttttatttttpppr5222222222222221211$$1122222222222222222222222222222222222222222222222222122222244334314669qqqytttttttpttpttttttttti<rpttttptttttai622222222222222222222$11222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222%",
+"%12222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222122222221$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$22222222222222222222222222222222222222222222222222221$12221$$$1121222222222222222222222222222224422222222211222222212112467qttatttttttttattttttatatttttttpptttti62222222222222221111$+$122222222222222222222222222122222222222222222222222222222222221$1112224247ttttttttttttppttttpttt<itpattttattq222222222222222222211121222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222221221211$111122222122222222222222222222222222222222221222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$122222222222222222222222222222222222222222222222212222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$22222222222212222222222222222222222222222222221222222$22$1$111222222222222222222222222222222222222222222221$12222222222422240weittptpttptttttttttaattttttttttppq222222222222222222211$1$11222222222222222222222222222222222222222222222222222222222121$12222212227utpttttppttttttttttptrrraaatttttu522222222222222222211$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$11$1$$11112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211$12222222222222222222122222222222222222222222222222222+$1$$1221222222222222222222222222222222222222222222111112222222222222222236qtttttttttattatttttttatttpttttq4222222222222222212111111$112222222222222222222222222222222222222122222222222222222222$12222222222267quppttttttptpttptttttrrptttatt72222222222222222222111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222122222222222222222222222222222222222222222222222222222222222222222222222221111$11221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222222222222222211$+$$2222222222222222222222222222222222222222222222222221$22222222122222222214qitttttatttttpttattttttappptq412222222222222222111112221$11222222222222222222222222222222222222222222222222122222221$2222222222222226eitpttttttttttttttpprrtptttt52222222222222222211112222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222%",
+"%222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222122221122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222$12222222222222222222222222122222222222222222222111$$$1$222222222222222222222222222222222222222222222222222211122222222222222212222qippptttttptttttatatiaaapiq222222222222222222211$12222211$11222222222222222222222222222222222222222222222222222222$1222222222222222225quitttiuittpppttppa<rrppti62222222222222222221$22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222122222222222221222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$12222222222222222222222222222222222222222222111$$$1222$222222222222222222222222222222222222222222222222222221$1222222222222222222227uitpatttttpttttttaataaau422222222222222222221$1212222221$$11222222222222222222221222222222222222222222222222221$$2222222222222222221257qq76677euittttppti<tttq2222222222222221221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222%",
+"%122222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222221$22222222222222222222222222222222222222222111$$$1122221$222222222222222222222222222222222222222222222222222221$11222222222222222222225quuuuitttppatatttttaau41122222222222222222211222222222221$$112222222221222222222222222222222222222222222222221$222222122222222222222222212222246qqwetpppp<ri5222222222212222222$1122222222222222222212222222222222222222222222222222222222222222212222222222222222222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222%",
+"%222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$12222222222222222222221222222222222222111$$$1122222222$1222222222222222222222222222222222222122222222222222222$1222222222222222222221442246eeuuiitatttataa4222222222222222222211$222222222222221$1122222222222222222222222222222222222222222222221$12222222222222222222222222222222222222qttpttrr222222222222122222111122222222222222222222222222222222222222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$2222222222222222222222222222222212111$$$12122222222221$222222222222212222222212222222222222222222222222222221$1222222222222222222222222222222249eiiitiiuw222222222222222222221$22222222221222222$$12222222222222222222212222222222222222222222221$222222222222222222222222222222222222222eiittie$22222222222222221$12222222122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%",
+"%2222212222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222$1222222222222222222222222222222111$$$11222222222122221$2222222222222222222222222222122222222222222222222222222$22222222222212222222222222222222222990984222222222222222222221$11222222222222222221$$12222222222222222222222222222222222222222222$222222222222222222222222222222222222222257qie621$$22222222222222$122222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222122222%",
+"%2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222212222222222222222222222222222222222222222222222222222222222222222221222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221$1222222222222222222222222222221$$$12122222222222222221$1222222222222222222222222222222222222222222222222222221$1222222222222222222222222222222222222244222222222222222222222$12222222222222122222111$1222222222222222222222222222222222221222211$2222222222222222222222222222222222222222222542222$$2222222222221$222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222%"
+};
index f329a86cb369567394a2b840a3654eeb5572b585..1877243dcf00c2bce88dddb93a0fda7871f73fe1 100644 (file)
@@ -186,6 +186,7 @@ init_map (struct state *st)
 
   if (!mono_p)
     {
+      if (st->ncolors < 1) st->ncolors = 1;
       st->colors = (XColor *) malloc (st->ncolors * sizeof(*st->colors));
 
       make_smooth_colormap (st->xgwa.screen, st->xgwa.visual, st->cmap,
@@ -401,7 +402,7 @@ static const char *imsmap_defaults [] = {
   "*iterations:        7",
   "*delay:     5",
   "*delay2:    20000",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
   0
index f83677760a09adfe368f7336aaf7698acb397014..01043265d108424adfed298e91fed24762ff7026 100644 (file)
@@ -85,7 +85,7 @@ static const char *interaggregate_defaults[] =
     "*baseOrbits: 75",
     "*baseOnCenter: False",
     "*drawCenters: False",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
     "*ignoreRotation: True",
 #endif
     0
@@ -259,7 +259,7 @@ static inline void point2rgb(int depth, unsigned long c, int *r, int *g, int *b)
     {
     case 32:
     case 24:
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
         /* This program idiotically does not go through a color map, so
            we have to hardcode in knowledge of how jwxyz.a packs pixels!
            Fix it to go through st->colors[st->ncolors] instead!
@@ -294,7 +294,7 @@ static inline unsigned long rgb2point(int depth, int r, int g, int b)
     {
     case 32:
     case 24:
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
         /* This program idiotically does not go through a color map, so
            we have to hardcode in knowledge of how jwxyz.a packs pixels!
            Fix it to go through st->colors[st->ncolors] instead!
@@ -440,6 +440,7 @@ static void build_colors(struct field *f, Display *dpy, XWindowAttributes *xgwa)
        ;
     }
 
+    if (f->numcolors < 1) f->numcolors = 1;
     f->parsedcolors = (unsigned long *) calloc(f->numcolors,
                                               sizeof(unsigned long));
     if ( f->parsedcolors == NULL )
index 2112d27a9004be4335a4571e89be0add7c5239d2..fe3084e4c2a78ee7ba3e46f2403b190d143bc3ae 100644 (file)
@@ -130,7 +130,7 @@ static const char *interference_defaults [] = {
 #ifdef HAVE_XSHM_EXTENSION
   "*useSHM:      True", /* use shared memory extension */
 #endif /*  HAVE_XSHM_EXTENSION */
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
   THREAD_DEFAULTS
@@ -779,7 +779,7 @@ static void inter_init(Display* dpy, Window win, struct inter_context* c)
   unsigned long valmask = 0;
 #endif
 
-# ifdef HAVE_COCOA     /* Don't second-guess Quartz's double-buffering */
+# ifdef HAVE_JWXYZ     /* Don't second-guess Quartz's double-buffering */
   dbuf = False;
 # endif
 
@@ -904,6 +904,7 @@ static void inter_init(Display* dpy, Window win, struct inter_context* c)
   c->radius = radius;
 #endif
 
+  if (c->radius < 1) c->radius = 1;
   c->wave_height = calloc(c->radius, sizeof(unsigned));
   check_no_mem(dpy, c, c->wave_height);
 
@@ -1040,7 +1041,7 @@ interference_reshape (Display *dpy, Window window, void *closure,
 {
   struct inter_context *c = (struct inter_context *) closure;
   XWindowAttributes xgwa;
-  Bool dbuf = (c->pix_buf
+  Bool dbuf = (!!c->pix_buf
 # ifdef HAVE_DOUBLE_BUFFER_EXTENSION
                || c->back_buf
 # endif
index bcbd19ee3a6dc07f3b67553bdc8e46c7ad3bd670..96c6b29dbdb0c7ffb1e6d01036eebf7a01942cda 100644 (file)
@@ -251,7 +251,7 @@ moverender_rider(struct state *st, Drawable drawable,
     rid->vt += frand(0.002) - 0.001;
 
     /* apply friction brakes */
-    if (abs(rid->vt) > 0.02)
+    if (fabsf(rid->vt) > 0.02)
         rid->vt *= 0.9;
 
     /* draw */
@@ -302,7 +302,7 @@ render_disc(struct state *st, Drawable drawable, GC fgc, struct field *f, int dn
         /* intersection test */
         if (d < (f->discs[n].r + di->r)) {
             /* complete containment test */
-            if (d > abs(f->discs[n].r - di->r)) {
+            if (d > fabsf(f->discs[n].r - di->r)) {
                 /* find solutions */
                 a = (di->r * di->r - f->discs[n].r * f->discs[n].r + d * d) / (2 * d);
                 p2x = di->x + a * (f->discs[n].x - di->x) / d;
@@ -360,7 +360,8 @@ static void build_img(Display *dpy, Window window, struct field *f)
 
     memset(f->off_alpha, 0, sizeof(unsigned char) * f->width * f->height);
 
-# ifdef HAVE_COCOA     /* Don't second-guess Quartz's double-buffering */
+# ifdef HAVE_JWXYZ     /* Don't second-guess Quartz's double-buffering */
+                        /* Or Android's */
     f->off_map = window;
 # else
     f->off_map = XCreatePixmap(dpy, window, f->width, f->height, f->visdepth);
@@ -554,9 +555,9 @@ static const char *intermomentary_defaults[] = {
     "*maxRiders: 40",
     "*maxRadius: 100",
     "*colors: 256",
-#ifdef USE_IPHONE
+# ifdef HAVE_MOBILE
     "*ignoreRotation: True",
-#endif
+# endif
     0
 };
 
index 12101fa4474106c99210775f3c32a1c0ea4dddb8..c10a8dec38506669e2a563ecc3dbe52e8e89a270 100644 (file)
@@ -2642,7 +2642,7 @@ draw_juggle (ModeInfo * mi)
 
   MI_IS_DRAWN(mi) = True;
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
   /* Don't worry about flicker, trust Quartz's double-buffering.
      This is a fast fix for the pixel-turds I can't track down...
    */
index d7066b0896e94d2dad8b8d8156423482292330ab..a121711d423aad4dce911732e6305519e1888f52 100644 (file)
@@ -74,7 +74,7 @@ typedef struct {
        int         nbuffers;
        int         redrawing, redrawpos;
        Pixmap      pixmap;
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
        Cursor      cursor;
 #endif
        GC          stippledGC;
@@ -176,7 +176,7 @@ init_julia(ModeInfo * mi)
                jp->depth = 10;
 
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
        if (jp->button_down_p && !jp->cursor && !jp->cursor)
          {
                Pixmap bit;
@@ -190,7 +190,7 @@ init_julia(ModeInfo * mi)
                                                                                  0, 0);
                XFreePixmap (display, bit);
          }
-#endif /* HAVE_COCOA */
+#endif /* HAVE_JWXYZ */
 
        if (jp->pixmap != None &&
            jp->circsize != (MIN(jp->centerx, jp->centery) / 60) * 2 + 1) {
@@ -219,14 +219,14 @@ init_julia(ModeInfo * mi)
                        XFreeGC(display, bg_gc);
        }
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
        if (MI_WIN_IS_INROOT(mi))
          ;
        else if (jp->circsize > 0)
          XDefineCursor (display, window, jp->cursor);
        else
          XUndefineCursor (display, window);
-#endif /* HAVE_COCOA */
+#endif /* HAVE_JWXYZ */
 
        if (!jp->stippledGC) {
                gcv.foreground = MI_WIN_BLACK_PIXEL(mi);
@@ -334,11 +334,11 @@ draw_julia (ModeInfo * mi)
        /* draw a circle at the c-parameter so you can see it's effect on the
           structure of the julia set */
        XSetForeground(display, jp->stippledGC, MI_WIN_WHITE_PIXEL(mi));
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
        XSetTSOrigin(display, jp->stippledGC, new_circle.x, new_circle.y);
        XSetStipple(display, jp->stippledGC, jp->pixmap);
        XSetFillStyle(display, jp->stippledGC, FillOpaqueStippled);
-#endif /* HAVE_COCOA */
+#endif /* HAVE_JWXYZ */
        XDrawArc(display, window, jp->stippledGC, 
              new_circle.x-jp->circsize/2,
              new_circle.y-jp->circsize/2,
@@ -435,7 +435,7 @@ release_julia (ModeInfo * mi)
                                XFreeGC(display, jp->stippledGC);
                        if (jp->pixmap != None)
                                XFreePixmap(display, jp->pixmap);
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
                        if (jp->cursor)
                          XFreeCursor (display, jp->cursor);
 #endif
index f260360d251397e1eb93ddae575443e687b72573..87a823604a198c8c4489b26ef9bb4ed84593956e 100644 (file)
@@ -100,7 +100,7 @@ static const char *kaleidescope_defaults [] = {
   "*greenrange:     20000",
   "*bluemin:        30000",
   "*bluerange:      20000",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
   0
@@ -431,7 +431,7 @@ init_g (GLOBAL *g)
   gcv.foreground = get_pixel_resource (g->dpy, g->cmap, "background", "Background");
   g->erase_gc     = XCreateGC (g->dpy, g->window, GCForeground|GCLineWidth|GCCapStyle,&gcv);
 
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
   jwxyz_XSetAntiAliasing (g->dpy, g->draw_gc, False);
   jwxyz_XSetAntiAliasing (g->dpy, g->erase_gc, False);
 # endif
index c444bd5fb3c36577665408e6114bc9d512af5c78..548be6ab91d4d2e0b4641149a2f5c56f7d5e6938 100644 (file)
@@ -55,7 +55,7 @@ static const char *kumppa_defaults [] ={
   "*random:            True",
   /* leave this off by default, since it slows things down.  -- jwz. */
   "*useDBE:            False",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation:     True",
 #endif
   0
index e681f99def3015ad538962e0e8451d4a8a4c04c0..3439bf443a5980b4951ab16b225579bc8e7ae115 100644 (file)
@@ -166,7 +166,7 @@ init_laser(ModeInfo * mi)
                        free_laser(display, lp);
                        return;
                }
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
     jwxyz_XSetAntiAliasing (MI_DISPLAY(mi), lp->stippledGC, False);
 # endif
        }
index e7f220c08aa28e242a2a1e1e574409ae3239ea61..5fd165e3c1d45f73d03aa7fc7c2f663fcf40fc16 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2008-2013 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2008-2015 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
@@ -27,6 +27,7 @@ struct state {
          DIAG_W, DIAG_B, 
          WHITE, BLACK,
          RGB,
+         RANDOM,
          END } mode;
   unsigned int enabled_mask;
   int count;
@@ -35,6 +36,8 @@ struct state {
   int delay;
   int spread;
   int cycles;
+  XImage *collisions;
+  long ncollisions;
 };
 
 
@@ -56,6 +59,8 @@ lcdscrub_init (Display *dpy, Window window)
 {
   struct state *st = (struct state *) calloc (1, sizeof(*st));
   XGCValues gcv;
+  unsigned long fgp, bgp;
+
   st->dpy = dpy;
   st->window = window;
   st->delay  = get_integer_resource (st->dpy, "delay",  "Integer");
@@ -63,15 +68,20 @@ lcdscrub_init (Display *dpy, Window window)
   st->cycles = get_integer_resource (st->dpy, "cycles", "Integer");
 
   XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
-  gcv.foreground = BlackPixelOfScreen (st->xgwa.screen);
-  gcv.background = WhitePixelOfScreen (st->xgwa.screen);
+  fgp = get_pixel_resource (st->dpy, st->xgwa.colormap, 
+                            "foreground", "Foreground");
+  bgp = get_pixel_resource (st->dpy, st->xgwa.colormap,
+                            "background", "Background");
+
+  gcv.foreground = bgp;
+  gcv.background = fgp;
   st->bg  = XCreateGC (st->dpy, st->window, GCForeground, &gcv);
   st->bg2 = XCreateGC (st->dpy, st->window, GCForeground, &gcv);
-  gcv.foreground = WhitePixelOfScreen (st->xgwa.screen);
-  gcv.background = BlackPixelOfScreen (st->xgwa.screen);
+  gcv.foreground = fgp;
+  gcv.background = bgp;
   st->fg = XCreateGC (st->dpy, st->window, GCForeground, &gcv);
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
   jwxyz_XSetAntiAliasing (st->dpy, st->fg,  False);
   jwxyz_XSetAntiAliasing (st->dpy, st->bg,  False);
   jwxyz_XSetAntiAliasing (st->dpy, st->bg2, False);
@@ -89,6 +99,7 @@ lcdscrub_init (Display *dpy, Window window)
   PREF("modeW",  WHITE);
   PREF("modeB",  BLACK);
   PREF("modeRGB", RGB);
+  PREF("modeRandom", RANDOM);
 # undef PREF
   if (! st->enabled_mask) 
     {
@@ -101,6 +112,143 @@ lcdscrub_init (Display *dpy, Window window)
   return st;
 }
 
+
+/* A test harness for visualizing different random number generators.
+   This doesn't really belong in lcdscrub, but it was a convenient
+   place to put it.
+ */
+#if 0                                                          /* mwc1616 */
+
+static unsigned long mwc1616_x = 1;
+static unsigned long mwc1616_y = 2;
+
+static void
+mwc1616_srand (unsigned long seed)
+{
+  mwc1616_x = seed | 1;
+  mwc1616_y = seed | 2;
+}
+
+static unsigned long
+mwc1616 (void)
+{
+  mwc1616_x = 18000 * (mwc1616_x & 0xFFFF) + (mwc1616_x >> 16);
+  mwc1616_y = 30903 * (mwc1616_y & 0xFFFF) + (mwc1616_y >> 16);
+  return (mwc1616_x << 16) + (mwc1616_y & 0xFFFF);
+}
+
+# undef random
+# undef srand
+# define srand mwc1616_srand
+# define random() ((unsigned int) (mwc1616() & (unsigned int) (~0)))
+
+
+#elif 0                                                /* xorshift128plus */
+
+
+static uint64_t xo_state0 = 1;
+static uint64_t xo_state1 = 2;
+
+static void
+xorshift128plus_srand (unsigned long seed)
+{
+  xo_state0 = seed | 1;
+  xo_state1 = seed | 2;
+}
+
+static uint64_t
+xorshift128plus (void)
+{
+  register uint64_t s1 = xo_state0;
+  register uint64_t s0 = xo_state1;
+  xo_state0 = s0;
+  s1 ^= s1 << 23;
+  s1 ^= s1 >> 17;
+  s1 ^= s0;
+  s1 ^= s0 >> 26;
+  xo_state1 = s1;
+  return s1;
+}
+
+# undef random
+# undef srand
+# define srand xorshift128plus_srand
+# define random() ((unsigned int) (xorshift128plus() & (unsigned int) (~0)))
+
+
+#else                                                          /* ya_random */
+# undef srand
+# define srand(n)
+
+#endif                                                         /* ya_random */
+
+
+
+/* If you see patterns in this image, the PRNG sucks.
+ */
+static void
+lcdscrub_random (struct state *st)
+{
+  unsigned long steps_per_frame = 3000000;
+  unsigned long segments = 0x8000;  /* 2^15 */
+
+  if (! st->collisions)
+    {
+      struct timeval tp;
+# if GETTIMEOFDAY_TWO_ARGS
+      gettimeofday (&tp, 0);
+# else
+      gettimeofday (&tp);
+# endif
+      srand ((unsigned int) (tp.tv_sec ^ tp.tv_usec));
+
+      st->collisions = 
+        XCreateImage (st->dpy, st->xgwa.visual, 1, XYPixmap,
+                      0, NULL, segments, segments, 8, 0);
+      if (! st->collisions) abort();
+      st->collisions->data = (char *)
+        calloc (segments, st->collisions->bytes_per_line);  /* 128 MB */
+      if (! st->collisions->data) abort();
+    }
+
+  while (--steps_per_frame)
+    {
+      unsigned long x = random() & (segments-1);
+      unsigned long y = random() & (segments-1);
+      unsigned long p = XGetPixel (st->collisions, x, y) ? 0 : 1;
+      XPutPixel (st->collisions, x, y, p);
+      st->ncollisions += (p ? 1 : -1);
+    }
+
+  {
+    int w, h;
+    Pixmap p;
+    GC gc;
+
+    XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
+    w = st->xgwa.width;
+    h = st->xgwa.height;
+
+    p = XCreatePixmap (st->dpy, st->window, w, h, 1);
+    gc = XCreateGC (st->dpy, p, 0, 0);
+    XSetBackground (st->dpy, gc, 0);
+    XSetForeground (st->dpy, gc, 1);
+    XPutImage (st->dpy, p, gc, st->collisions, 0, 0, 0, 0, w, h);
+    XFreeGC (st->dpy, gc);
+
+    gc = st->fg;
+    XClearWindow (st->dpy, st->window);
+    XSetClipMask (st->dpy, gc, p);
+    XFillRectangle (st->dpy, st->window, gc, 0, 0, w, h);
+    XFreePixmap (st->dpy, p);
+  }
+
+  /*
+    fprintf(stderr, "%.2f\n", st->ncollisions / (float) (segments*segments));
+  */
+}
+
+
 static unsigned long
 lcdscrub_draw (Display *dpy, Window window, void *closure)
 {
@@ -167,6 +315,9 @@ lcdscrub_draw (Display *dpy, Window window, void *closure)
     XFillRectangle (st->dpy, st->window, bg, 0, 0,
                     st->xgwa.width, st->xgwa.height);
     break;
+  case RANDOM:
+    lcdscrub_random (st);
+    break;
   default: 
     abort(); 
     break;
@@ -199,6 +350,12 @@ lcdscrub_free (Display *dpy, Window window, void *closure)
   XFreeGC (dpy, st->fg);
   XFreeGC (dpy, st->bg);
   XFreeGC (dpy, st->bg2);
+  if (st->collisions)
+    {
+      free (st->collisions->data);
+      st->collisions->data = 0;
+      XDestroyImage (st->collisions);
+    }
   free (st);
 }
 
@@ -206,6 +363,7 @@ lcdscrub_free (Display *dpy, Window window, void *closure)
 static const char *lcdscrub_defaults [] = {
   ".background:                black",
   ".foreground:                white",
+  "*fpsSolid:          True",
   "*delay:             100000",
   "*spread:            8",
   "*cycles:            60",
@@ -218,6 +376,7 @@ static const char *lcdscrub_defaults [] = {
   "*modeW:             True",
   "*modeB:             True",
   "*modeRGB:           True",
+  "*modeRandom:                False",
   0
 };
 
@@ -234,6 +393,7 @@ static XrmOptionDescRec lcdscrub_options [] = {
   { "-no-w",           ".modeW",       XrmoptionNoArg, "False" },
   { "-no-b",           ".modeB",       XrmoptionNoArg, "False" },
   { "-no-rgb",         ".modeRGB",     XrmoptionNoArg, "False" },
+  { "-random",         ".modeRandom",  XrmoptionNoArg, "True" },
   { 0, 0, 0, 0 }
 };
 
index bc022bf3405f2325fb75ac98da0b4155ee43914a..df25c96d5f5615c5106200fa9990328fdc53321e 100644 (file)
@@ -721,7 +721,7 @@ draw_lisa (ModeInfo * mi)
        if (lc->lissajous == NULL)
                return;
 
-#ifdef HAVE_COCOA      /* Don't second-guess Quartz's double-buffering */
+#ifdef HAVE_JWXYZ      /* Don't second-guess Quartz's double-buffering */
     XClearWindow (MI_DISPLAY(mi), MI_WINDOW(mi));
 #endif
 
index ac18c52fe6620d4dcb799ad0f817aee34307f62c..e10e721832cb5b7344e5f0a1aa56daa70e639b97 100644 (file)
@@ -230,7 +230,7 @@ init_lissie (ModeInfo * mi)
 
        lp->width = MI_WIDTH(mi);
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
     jwxyz_XSetAntiAliasing (MI_DISPLAY(mi), MI_GC(mi),  False);
 #endif
 
index 45cfad39ee0e6053416d3390808de7f0e5c7a0ba..f5ce869d36ec60487bce41f64620c4d9b4b41e9b 100644 (file)
@@ -79,7 +79,7 @@ static const char sccsid[] = "@(#)loop.c      5.01 2000/03/15 xlockmore";
    there is handedness at both the initial condition and the transition rule.
  */
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # define DO_STIPPLE
 #endif
 
index 6e9147dcbe039c144d500789399e1d51fbbd38bf..4f90a6a10acf8b1f396556c372c6e3e4cd2ac005 100644 (file)
@@ -28,7 +28,7 @@ static const char * const demo_files[] = {
 };
 
 
-#ifndef USE_IPHONE
+#ifndef HAVE_MOBILE
 # define READ_FILES
 #endif
 
@@ -244,7 +244,7 @@ m6502_draw (Display *dpy, Window window, void *closure)
     start_rand_bin_prog(st->machine,st);
   }
 
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   return 0;
 #else
   return 5000;
index f592111d96597e3f6a8de6767527bc7d5ea11962..50cebfcc03e1bb434911721a501861c8e2d8a20d 100755 (executable)
@@ -7,6 +7,7 @@ SRCS=$*
 TMP1=m6502.h.1.$$
 TMP2=m6502.h.2.$$
 rm -f $TMP1 $TMP2
+trap "rm -f $TMP1 $TMP2" 1 2 3 15 ERR EXIT
 
 if [ -z "$UTILS_SRC" ]; then UTILS_SRC="../utils"; fi
 
@@ -16,9 +17,9 @@ for f in $SRCS ; do
     sed 's/",$/\\n"/' >> $TMP2
   echo ',' >> $TMP2
 done
-rm $TMP1
+rm -f $TMP1
 if cmp -s $TMP2 $TARGET ; then
-  rm $TMP2
+  rm -f $TMP2
 else
   mv $TMP2 $TARGET
 fi
index d5f4ef27a8873aeeecab731055969d0d9c18f39d..9afe44159c2c59a5eff02d263b32ae9cb371cc44 100644 (file)
@@ -1470,6 +1470,10 @@ maze_init (Display *dpy_arg, Window window_arg)
   XSetForeground (st->dpy, st->erase_gc, bg);
   XSetBackground (st->dpy, st->erase_gc, bg);
 
+# ifdef HAVE_JWXYZ
+  jwxyz_XSetAntiAliasing (st->dpy, st->gc, False);
+# endif
+
   {
     Window r;
     int x, y;
index 52119122900164221bdf49143f1062420a2b95d9..b1ca148644c290322b27c6b7fcdd18a5fd6aa508 100644 (file)
@@ -21,7 +21,7 @@
 #undef countof
 #define countof(x) (sizeof(x)/sizeof(*(x)))
 
-#ifndef USE_IPHONE
+#ifndef HAVE_MOBILE
 # define READ_FILES
 #endif
 
@@ -335,7 +335,7 @@ more_bits (state *st, scroller *sc)
   vv = sc->value;
 
   /* Pack RGB into a pixel according to the XImage component masks;
-     set the remaining bits to 1 for the benefit of HAVE_COCOA alpha.
+     set the remaining bits to 1 for the benefit of HAVE_JWXYZ alpha.
    */
 # undef PACK
 # define PACK() ((((r << 24) | (r << 16) | (r << 8) | r) & rmsk) | \
@@ -368,7 +368,7 @@ more_bits (state *st, scroller *sc)
         }
 
       /* I don't understand what's going on there, but on MacOS X, we're
-         getting insane values for lomem and himem (both Xlib and HAVE_COCOA).
+         getting insane values for lomem and himem (both Xlib and HAVE_JWXYZ).
          Does malloc() draw from more than one heap? */
       if ((unsigned long) himem - (unsigned long) lomem > 0x0FFFFFFF) {
 # if 0
@@ -626,21 +626,21 @@ static const char *memscroller_defaults [] = {
   ".foreground:                   #00FF00",
   "*borderSize:                   2",
 
-#if defined(HAVE_COCOA)
+#if defined(HAVE_COCOA) || defined(HAVE_ANDROID)
   ".font1:                OCR A Std 192, Lucida Console 192, Monaco 192",
   ".font2:                OCR A Std 144, Lucida Console 144, Monaco 144",
   ".font3:                OCR A Std 128, Lucida Console 128, Monaco 128",
   ".font4:                OCR A Std 96,  Lucida Console 96,  Monaco 96",
   ".font5:                OCR A Std 48,  Lucida Console 48,  Monaco 48",
   ".font6:                OCR A Std 24,  Lucida Console 24,  Monaco 24",
-#else  /* !HAVE_COCOA */
+#else  /* real X11 */
   ".font1:                -*-courier-bold-r-*-*-*-1440-*-*-m-*-*-*",
   ".font2:                -*-courier-bold-r-*-*-*-960-*-*-m-*-*-*",
   ".font3:                -*-courier-bold-r-*-*-*-480-*-*-m-*-*-*",
   ".font4:                -*-courier-bold-r-*-*-*-320-*-*-m-*-*-*",
   ".font5:                -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
   ".font6:                fixed",
-#endif /* !HAVE_COCOA */
+#endif /* real X11 */
 
   "*delay:                10000",
   "*offset:               0",
index b79dd95d94151550f4fd346a4753791a6e410008..d2e8806bc62a00780fd27325b7181be0c520dede 100644 (file)
@@ -408,7 +408,7 @@ static const char *metaballs_defaults [] = {
   "*delay:    10000",
   "*radius:   100",
   "*delta:   3",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
   0
index d55a9b85db7264ec07b166913a6f3011a13d1348..5b1155a86a2b74c4318d1b81a94e6e072dc999b2 100644 (file)
@@ -260,7 +260,7 @@ static const char *moire_defaults [] = {
 #else
   "*useSHM:          False",
 #endif
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
   0
index 69bfe696089af92d48fd08ef122e4c3a606fb305..0b6c9cd62b80d46ebfc16080973441df0b668131 100644 (file)
@@ -329,7 +329,7 @@ static const char *moire2_defaults [] = {
   "*thickness:         0",
   "*colors:            150",
   "*colorShift:                5",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation:     True",
 #endif
 
index 6116a595d633c868835c04906f1ead39f8874272..a76e4e42ca3445f94265839e558f23c459525e62 100644 (file)
@@ -451,7 +451,7 @@ static const char *munch_defaults [] = {
   "*simul:            5",
   "*clear:            65",
   "*xor:              True",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation:   True",
 #endif
   0
index fe58ea1a5d1779c8b02157e357904ef1fa19277e..081dbcab728d84bcbcd522e475af340d78dbf957 100644 (file)
@@ -1114,7 +1114,7 @@ static void eraseAndDraw (struct state *st)
     for (n = 0; n < st->segCount; n++)
     {
        LineSegment *seg = &st->segsToErase[n];
-#ifdef HAVE_COCOA      /* Don't second-guess Quartz's double-buffering */
+#ifdef HAVE_JWXYZ      /* Don't second-guess Quartz's double-buffering */
        XDrawLine (st->dpy, st->drawable, st->gcs[0], 
                   seg->x1, seg->y1, seg->x2, seg->y2);
 #endif
@@ -1173,7 +1173,7 @@ static void initParams (struct state *st)
     
     st->doubleBuffer = get_boolean_resource (st->dpy, "doubleBuffer", "Boolean");
 
-# ifdef HAVE_COCOA     /* Don't second-guess Quartz's double-buffering */
+# ifdef HAVE_JWXYZ     /* Don't second-guess Quartz's double-buffering */
     st->doubleBuffer = False;
 # endif
 
@@ -1325,7 +1325,7 @@ static const char *nerverot_defaults [] = {
     "*maxRadius:        25",
     "*maxNerveRadius:  0.7",
     "*nervousness:     0.3",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
     "*ignoreRotation:   True",
 #endif
     0
index b491224be11fec30373d2fd40113a93540dc2ebe..c5cc9c08d491e5ff7639e4d3a61493533be68780 100644 (file)
@@ -19,7 +19,7 @@
 #include "textclient.h"
 #include "xft.h"
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
 # define HAVE_XPM
 #endif
 
index 1cd7690b536a318e14a808fa052acc88dd388d31..58b2bed6114562d8d2b0f0e427646a5a748c09f8 100644 (file)
@@ -603,9 +603,9 @@ drawlevelblock (ModeInfo * mi, pacmangamestruct * pp,
     if (pp->ys % 2 == 1)
         dy = -1;
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
     XSetFillStyle (display, pp->stippledGC, FillSolid);
-#endif /* !HAVE_COCOA */
+#endif /* !HAVE_JWXYZ */
     XSetLineAttributes (display, pp->stippledGC, pp->wallwidth,
                         LineSolid, CapRound, JoinMiter);
 
@@ -955,16 +955,12 @@ draw_pacman_sprite (ModeInfo * mi)
     Display *display = MI_DISPLAY (mi);
     Window window = MI_WINDOW (mi);
     pacmangamestruct *pp = &pacman_games[MI_SCREEN (mi)];
-    unsigned int dir;
 
     pp->pacman.cf = pp->pacman.col * pp->xs + pp->pacman.delta.x *
         pp->pacman.cfactor + pp->xb + pp->spritedx;
     pp->pacman.rf = pp->pacman.row * pp->ys + pp->pacman.delta.y *
         pp->pacman.rfactor + pp->yb + pp->spritedy;
 
-    dir = (ABS (pp->pacman.cfactor) * (2 - pp->pacman.cfactor) +
-           ABS (pp->pacman.rfactor) * (1 + pp->pacman.rfactor)) % 4;
-
     XSetForeground (display, pp->stippledGC, MI_BLACK_PIXEL (mi));
     if (pp->pacman.oldcf != NOWHERE && pp->pacman.oldrf != NOWHERE) {
 
@@ -1571,7 +1567,7 @@ init_pacman (ModeInfo * mi)
         }
     }
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
     jwxyz_XSetAntiAliasing (display, pp->stippledGC, False);
 #endif
 
index 652ee3142e60183575180395bb602c2bcbfafa52..bd6fbe4ae3b232e0a97f32f608780e56d3eddbc3 100644 (file)
@@ -31,7 +31,7 @@
 
 #include "xlockmoreI.h"
 
-#if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM) || defined(HAVE_COCOA)
+#if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM) || defined(HAVE_JWXYZ)
 # define USE_PIXMAP
 #include "xpm-pixmap.h"
 # else
index 745b99380b4dc37e3dc3eb474d43d7b1d011f287..87820bec332ed70b47c7c51022488de77020086f 100644 (file)
@@ -318,7 +318,7 @@ static const char *pedal_defaults [] = {
   "*fpsSolid:                  true",
   "*delay:                     5",
   "*maxlines:                  1000",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation:             True",
 #endif
   0
index 611cf84e099e7298a9fc3cccb1609f09297a332e..b2b17e3b4383834f086161719330d4feec77dbda 100644 (file)
@@ -172,10 +172,11 @@ static void launch (struct state *st, int xlim, int ylim, int src)
   m->splits = 0;
   if (m->jenis < 50) {
     int j = ylim * 0.4;
-    if (j)
+    if (j) {
         m->splits = random() % j;
         if (m->splits < ylim * 0.08)
                m->splits = 0;
+    }
   }
 
   /* special if we're from another missile */
@@ -436,7 +437,7 @@ penetrate_init (Display *dpy, Window window)
   gcv.foreground = get_pixel_resource(st->dpy, st->cmap, "background", "Background");
   st->erase_gc = XCreateGC(st->dpy, st->window, GCForeground, &gcv);
 
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
   jwxyz_XSetAntiAliasing (st->dpy, st->erase_gc, False);
   jwxyz_XSetAntiAliasing (st->dpy, st->draw_gc, False);
 # endif
index 603db735ebeadd22562326f5eb61354a1843f78e..dd6e9929966dd9e33a1d8c2c1eeec6872d6f49f5 100644 (file)
@@ -1121,7 +1121,7 @@ add_forced_tile(ModeInfo * mi, forced_node_c * node)
 {
        tiling_c   *tp = &tilings[MI_SCREEN(mi)];
        unsigned    side;
-       vertex_type_c vtype;
+       vertex_type_c vtype = 0;
        rule_match_c hits[MAX_TILES_PER_VERTEX * N_VERTEX_RULES];
        int         n;
 
index e08beee377b1d25e57aa497ce5ccad08b0219260..97299d65073154fed5362aa9f4db5f08d231182f 100644 (file)
@@ -732,7 +732,7 @@ static const char *petri_defaults [] = {
   "*originalcolors:    false",
   "*memThrottle:        22M",  /* don't malloc more than this much.
                                    Scale the pixels up if necessary. */
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation:     True",
 #endif
     0
index 825ad56931d25ff9858ae5a2744ed8841924cb8e..1238048976d0e3dd6c8eebb1fa36e52f464acdf9 100644 (file)
@@ -17,7 +17,7 @@
 # include "config.h"
 #endif /* HAVE_CONFIG_H */
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # include <X11/Intrinsic.h>
 #endif
 
@@ -220,7 +220,7 @@ phosphor_init (Display *dpy, Window window)
   state->gcs = (GC *) calloc (sizeof(GC), state->ticks + 1);
 
   {
-    int ncolors = MAX (0, state->ticks - 3);
+    int ncolors = MAX (1, state->ticks - 3);
     XColor *colors = (XColor *) calloc (ncolors, sizeof(XColor));
     int h1, h2;
     double s1, s2, v1, v2;
@@ -426,7 +426,7 @@ capture_font_bits (p_state *state)
                            GCCapStyle | GCLineWidth),
                           &state->gcv);
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
   jwxyz_XSetAntiAliasing (state->dpy, state->gc0, False);
   jwxyz_XSetAntiAliasing (state->dpy, state->gc1, False);
 #endif
index 980600c75220782d09e663d3ea2055c4a4aa6d28..6e6e484f1db9fadf0af19d27cd2be1f8851bac21 100644 (file)
@@ -848,7 +848,7 @@ piecewise_init (Display *dd, Window ww)
   st->colorspeed = get_integer_resource(st->dpy, "colorspeed", "Integer");
   st->dbuf = get_boolean_resource(st->dpy, "doubleBuffer", "Boolean");
 
-# ifdef HAVE_COCOA     /* Don't second-guess Quartz's double-buffering */
+# ifdef HAVE_JWXYZ     /* Don't second-guess Quartz's double-buffering */
   st->dbuf = False;
 # endif
 
@@ -981,7 +981,7 @@ static const char *piecewise_defaults [] = {
 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
   "*useDBE:             True",
 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation:     True",
 #endif
   0
index a3037d281c381e11ae6130b0cc39973356a7a03c..0c410eafb77ab5e08cac73d99b6f5e1c1c6123c7 100644 (file)
@@ -513,7 +513,7 @@ static int
 score_point(polyominoesstruct *sp, int x, int y, int min_score_so_far)
 {
   int poly_no, point_no, transform_index, i, attachable;
-  point_type attach_point, target_point;
+  point_type attach_point = { 0, 0 }, target_point = { 0, 0 };
   int score = 0;
 
   if (x>=1 && x<sp->width-1 && y>=1 && y<sp->height-1 &&
@@ -586,7 +586,7 @@ static
 void detach(polyominoesstruct *sp, int *poly_no, int *point_no, int *transform_index, point_type *attach_point, int rot180)
 {
   int i;
-  point_type target_point;
+  point_type target_point = { 0, 0 };
 
   if (sp->nr_attached == 0) return;
   sp->nr_attached--;
@@ -614,7 +614,7 @@ void detach(polyominoesstruct *sp, int *poly_no, int *point_no, int *transform_i
 static
 int attach(polyominoesstruct *sp, int poly_no, int point_no, int transform_index, point_type attach_point, int rot180,
            int *reason_to_not_attach) {
-  point_type target_point;
+  point_type target_point = { 0, 0 };
   int i;
   int attachable = 1, worst_reason_not_to_attach = 1000000000;
 
index a68872865b44e3765ca6c2bff15ef7577ae98229..fe200c35a65620d7c46e63f756dc4c44a615096f 100644 (file)
  * not displaying seconds, who cares. While I was at it, I added a -noise option
  * to control the noisyness of the display.
  *
+ * Modified by Dave Odell <dmo2118@gmail.com> to add -p1 and -p2 options.
+ * JWXYZ doesn't support XWarpPointer, so PLAYER_MOUSE only works on native
+ * X11. JWXYZ also doesn't support cursors, so PLAYER_TABLET doesn't hide the
+ * mouse pointer.
+ *
  * 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
 
 #include "screenhack.h"
 #include "analogtv.h"
+#include <time.h>
+#ifndef HAVE_JWXYZ
+# include <X11/keysym.h>
+#endif
 /* #define OUTPUT_POS */
 
+typedef enum {
+  PLAYER_AI,
+  PLAYER_MOUSE,
+  PLAYER_TABLET,
+  PLAYER_KEYBOARD,
+  PLAYER_KEYBOARD_LEFT
+} PlayerType;
+
 typedef struct _paddle {
+  PlayerType player;
   int x;
   int y;
   int w;
@@ -96,6 +114,18 @@ struct state {
   int net_ntsc[4];
 
   analogtv_font score_font;
+
+# ifndef HAVE_JWXYZ
+  Cursor null_cursor;
+# endif
+  int mouse_y;
+  unsigned w, h, screen_h, screen_h_mm;
+  Bool is_focused;
+  Bool key_w: 1;
+  Bool key_s: 1;
+  Bool key_up: 1;
+  Bool key_down: 1;
+  unsigned int dragging : 2;
 };
 
 
@@ -250,12 +280,83 @@ hit_paddle(struct state *st)
     }
 }
 
+static PlayerType
+get_player_type(Display *dpy, char *rsrc)
+{
+  PlayerType result;
+  char *s = get_string_resource(dpy, rsrc, "String");
+  if (!strcmp(s, "ai") || !strcmp(s, "AI"))
+  {
+    result = PLAYER_AI;
+  }
+# ifndef HAVE_JWXYZ
+  else if (!strcmp(s, "mouse"))
+  {
+    result = PLAYER_MOUSE;
+  }
+# endif
+  else if (!strcmp(s, "tab") || !strcmp(s, "tablet"))
+  {
+    result = PLAYER_TABLET;
+  }
+  else if (!strcmp(s, "kb") || !strcmp(s, "keyb") || !strcmp(s, "keyboard") ||
+           !strcmp(s, "right") || !strcmp(s, "kbright") ||
+           !strcmp(s, "arrows"))
+  {
+    result = PLAYER_KEYBOARD;
+  }
+  else if (!strcmp(s, "left") || !strcmp(s, "kbleft") ||
+           !strcmp(s, "ws") || !strcmp(s, "wasd"))
+  {
+    result = PLAYER_KEYBOARD_LEFT;
+  }
+  else
+  {
+    fprintf(stderr, "%s: invalid player type\n", progname);
+    result = PLAYER_AI;
+  }
+  free(s);
+  return result;
+}
+
+static void
+do_shape (struct state *st, const XWindowAttributes *xgwa)
+{
+  st->w = xgwa->width;
+  st->h = xgwa->height;
+  st->screen_h = XHeightOfScreen(xgwa->screen);
+  st->screen_h_mm = XHeightMMOfScreen(xgwa->screen);
+}
+
+#ifndef HAVE_JWXYZ
+static Bool
+needs_grab (struct state *st)
+{
+  return
+  st->l_paddle.player == PLAYER_MOUSE ||
+  st->r_paddle.player == PLAYER_MOUSE;
+/*
+  st->l_paddle.player == PLAYER_TABLET ||
+  st->r_paddle.player == PLAYER_TABLET;
+ */
+}
+
+static void
+grab_pointer (struct state *st)
+{
+  st->is_focused = True;
+  XGrabPointer(st->dpy, st->window, True, PointerMotionMask, GrabModeAsync,
+               GrabModeAsync, st->window, st->null_cursor, CurrentTime);
+}
+#endif /* !HAVE_JWXYZ */
+
 static void *
 pong_init (Display *dpy, Window window)
 {
   struct state *st = (struct state *) calloc (1, sizeof(*st));
 
   int i;
+  XWindowAttributes xgwa;
   struct {
     int w, h;
     char *s[10];
@@ -500,6 +601,7 @@ pong_init (Display *dpy, Window window)
 #endif
 
   /*Init the paddles*/
+  st->l_paddle.player = get_player_type(dpy, "p1");
   st->l_paddle.x = 8;
   st->l_paddle.y = 100;
   st->l_paddle.w = 16;
@@ -507,6 +609,7 @@ pong_init (Display *dpy, Window window)
   st->l_paddle.wait = 1;
   st->l_paddle.lock = 0;
   st->r_paddle = st->l_paddle;
+  st->r_paddle.player = get_player_type(dpy, "p2");
   st->r_paddle.x = PONG_W - 8 - st->r_paddle.w;
   st->r_paddle.wait = 0;
   /*Init the ball*/
@@ -515,6 +618,59 @@ pong_init (Display *dpy, Window window)
   st->ball.w = 16;
   st->ball.h = 8;
 
+  /* The mouse warping business breaks tablet input. */
+  if (st->l_paddle.player == PLAYER_MOUSE &&
+      st->r_paddle.player == PLAYER_TABLET)
+  {
+    st->l_paddle.player = PLAYER_TABLET;
+  }
+  if (st->r_paddle.player == PLAYER_MOUSE &&
+      st->l_paddle.player == PLAYER_TABLET)
+  {
+    st->r_paddle.player = PLAYER_TABLET;
+  }
+
+  if (st->clock) {
+    st->l_paddle.player = PLAYER_AI;
+    st->r_paddle.player = PLAYER_AI;
+    fprintf(stderr, "%s: clock mode requires AI control\n", progname);
+
+  }
+
+# ifndef HAVE_JWXYZ
+  if (st->l_paddle.player == PLAYER_MOUSE ||
+      st->r_paddle.player == PLAYER_MOUSE ||
+      st->l_paddle.player == PLAYER_TABLET ||
+      st->r_paddle.player == PLAYER_TABLET)
+  {
+    XColor black = {0, 0, 0, 0};
+    Pixmap cursor_pix = XCreatePixmap(dpy, window, 4, 4, 1);
+    XGCValues gcv;
+    GC mono_gc;
+
+    gcv.foreground = 0;
+    mono_gc = XCreateGC(dpy, cursor_pix, GCForeground, &gcv);
+    st->null_cursor = XCreatePixmapCursor(dpy, cursor_pix, cursor_pix,
+                                          &black, &black, 0, 0);
+    XFillRectangle(dpy, cursor_pix, mono_gc, 0, 0, 4, 4);
+    XFreeGC(dpy, mono_gc);
+
+    XSelectInput(dpy, window,
+                 PointerMotionMask | FocusChangeMask |
+                 KeyPressMask | KeyReleaseMask |
+                 ButtonPressMask | ButtonReleaseMask);
+
+    if (needs_grab(st))
+    {
+      grab_pointer(st);
+    }
+    else
+    {
+      XDefineCursor(dpy, window, st->null_cursor);
+    }
+  }
+# endif
+
   st->m_unit = get_integer_resource (st->dpy, "speed", "Integer");
   st->noise  = get_float_resource(st->dpy, "noise", "Float");
   st->clock  = get_boolean_resource(st->dpy, "clock", "Boolean");
@@ -540,41 +696,94 @@ pong_init (Display *dpy, Window window)
                       ANALOGTV_TOP, ANALOGTV_BOT,
                       st->field_ntsc);
 
+  XGetWindowAttributes(dpy, window, &xgwa);
+  do_shape(st, &xgwa);
+
   return st;
 }
 
 static void
 p_logic(struct state *st, Paddle *p)
 {
-  int targ;
-  if (st->bx > 0) {
-    targ = st->ball.y + st->by * (st->r_paddle.x-st->ball.x) / st->bx;
-  }
-  else if (st->bx < 0) {
-    targ = st->ball.y - st->by * (st->ball.x - st->l_paddle.x - st->l_paddle.w) / st->bx;
+  if (p->player == PLAYER_AI)
+  {
+    if (!p->wait)
+    {
+      int targ;
+      if (st->bx > 0) {
+        targ = st->ball.y + st->by * (st->r_paddle.x-st->ball.x) / st->bx;
+      }
+      else if (st->bx < 0) {
+        targ = st->ball.y - st->by * (st->ball.x - st->l_paddle.x - st->l_paddle.w) / st->bx;
+      }
+      else {
+        targ = st->ball.y;
+      }
+      if (targ > PONG_H) targ=PONG_H;
+      if (targ < 0) targ=0;
+
+      if (targ < p->y && !p->lock)
+      {
+        p->y -= st->paddle_rate;
+      }
+      else if (targ > (p->y + p->h) && !p->lock)
+      {
+        p->y += st->paddle_rate;
+      }
+      else
+      {
+        int move=targ - (p->y + p->h/2);
+        if (move>st->paddle_rate) move=st->paddle_rate;
+        if (move<-st->paddle_rate) move=-st->paddle_rate;
+        p->y += move;
+        p->lock = 1;
+      }
+    }
   }
-  else {
-    targ = st->ball.y;
+# ifndef HAVE_JWXYZ
+  else if (p->player == PLAYER_MOUSE)
+  {
+    /* Clipping happens elsewhere. */
+    /* As the screen resolution increases, the mouse moves faster in terms of
+       pixels, so divide by DPI. */
+    p->y += (int)(st->mouse_y - (st->h / 2)) * 4 * (int)st->screen_h_mm / (3 * (int)st->screen_h);
+    if (st->is_focused)
+      XWarpPointer (st->dpy, None, st->window, 0, 0, 0, 0, st->w / 2, st->h / 2);
   }
-  if (targ > PONG_H) targ=PONG_H;
-  if (targ < 0) targ=0;
-
-  if (targ < p->y && !p->lock)
+# endif
+  else if (p->player == PLAYER_TABLET)
   {
-    p->y -= st->paddle_rate;
+    p->y = st->mouse_y * (PONG_H - PONG_TMARG) / st->h + PONG_TMARG - p->h / 2;
   }
-  else if (targ > (p->y + p->h) && !p->lock)
+  else if (p->player == PLAYER_KEYBOARD)
   {
-    p->y += st->paddle_rate;
+    if (st->key_up)
+      p->y -= 8;
+    if (st->key_down)
+      p->y += 8;
   }
-  else
+  else if (p->player == PLAYER_KEYBOARD_LEFT)
   {
-    int move=targ - (p->y + p->h/2);
-    if (move>st->paddle_rate) move=st->paddle_rate;
-    if (move<-st->paddle_rate) move=-st->paddle_rate;
-    p->y += move;
-    p->lock = 1;
+    if (st->key_w)
+      p->y -= 8;
+    if (st->key_s)
+      p->y += 8;
   }
+
+  if ((st->dragging == 1 && p == &st->l_paddle) ||
+      (st->dragging == 2 && p == &st->r_paddle))
+    {
+      /* Not getting MotionNotify. */
+      Window root1, child1;
+      int mouse_x, mouse_y, root_x, root_y;
+      unsigned int mask;
+      if (XQueryPointer (st->dpy, st->window, &root1, &child1,
+                         &root_x, &root_y, &mouse_x, &mouse_y, &mask))
+        st->mouse_y = mouse_y;
+
+      if (st->mouse_y < 0) st->mouse_y = 0;
+      p->y = st->mouse_y * (PONG_H - PONG_TMARG) / st->h + PONG_TMARG - p->h / 2;
+    }
 }
 
 static void
@@ -681,11 +890,26 @@ paint_net(struct state *st)
   }
 }
 
+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 unsigned long
 pong_draw (Display *dpy, Window window, void *closure)
 {
   struct state *st = (struct state *) closure;
   const analogtv_reception *reception = &st->reception;
+  double then = double_time(), now, timedelta;
 
   if (st->clock)
   {
@@ -716,14 +940,8 @@ pong_draw (Display *dpy, Window window, void *closure)
     }
   }
 
-  if (!st->r_paddle.wait)
-  {
-    p_logic(st, &st->r_paddle);
-  }
-  if (!st->l_paddle.wait)
-  {
-    p_logic(st, &st->l_paddle);
-  }
+  p_logic(st, &st->r_paddle);
+  p_logic(st, &st->l_paddle);
 
   p_hit_top_bottom(&st->r_paddle);
   p_hit_top_bottom(&st->l_paddle);
@@ -748,11 +966,9 @@ pong_draw (Display *dpy, Window window, void *closure)
   analogtv_reception_update(&st->reception);
   analogtv_draw(st->tv, st->noise, &reception, 1);
 
-#ifdef USE_IPHONE
-  return 0;
-#else
-  return 5000;
-#endif
+  now = double_time();
+  timedelta = (1 / 29.97) - (now - then);
+  return timedelta > 0 ? timedelta * 1000000 : 0;
 }
 
 \f
@@ -763,6 +979,8 @@ static const char *pong_defaults [] = {
   "*speed:      6",
   "*noise:      0.04",
   "*clock:      false",
+  "*p1:         ai",
+  "*p2:         ai",
   ANALOGTV_DEFAULTS
   0
 };
@@ -771,6 +989,8 @@ static XrmOptionDescRec pong_options [] = {
   { "-speed",           ".speed",     XrmoptionSepArg, 0 },
   { "-noise",           ".noise",     XrmoptionSepArg, 0 },
   { "-clock",           ".clock",     XrmoptionNoArg, "true" },
+  { "-p1",              ".p1",        XrmoptionSepArg, 0 },
+  { "-p2",              ".p2",        XrmoptionSepArg, 0 },
   ANALOGTV_OPTIONS
   { 0, 0, 0, 0 }
 };
@@ -780,12 +1000,110 @@ pong_reshape (Display *dpy, Window window, void *closure,
                  unsigned int w, unsigned int h)
 {
   struct state *st = (struct state *) closure;
+  XWindowAttributes xgwa;
   analogtv_reconfigure (st->tv);
+
+  XGetWindowAttributes(dpy, window, &xgwa); /* AnalogTV does this too. */
+  xgwa.width = w;
+  xgwa.height = h;
+  do_shape(st, &xgwa);
 }
 
 static Bool
 pong_event (Display *dpy, Window window, void *closure, XEvent *event)
 {
+  struct state *st = (struct state *) closure;
+  switch (event->type)
+  {
+  case MotionNotify:
+    st->mouse_y = event->xmotion.y;
+    break;
+# ifndef HAVE_JWXYZ
+  case FocusIn:
+    if (needs_grab(st))
+    {
+      grab_pointer(st);
+    }
+    break;
+  case FocusOut:
+    if (needs_grab(st))
+    {
+      XUngrabPointer (dpy, CurrentTime);
+      st->is_focused = False;
+    }
+    break;
+# endif /* !HAVE_JWXYZ */
+  case KeyPress:
+  case KeyRelease:
+    {
+      char c;
+      KeySym key;
+      XLookupString(&event->xkey, &c, 1, &key, 0);
+      Bool is_pressed = event->type == KeyPress;
+      switch(key)
+      {
+      case XK_Up:
+        if (st->l_paddle.player == PLAYER_KEYBOARD ||
+            st->r_paddle.player == PLAYER_KEYBOARD)
+          {
+            st->key_up = is_pressed;
+            return True;
+          }
+        break;
+      case XK_Down:
+        if (st->l_paddle.player == PLAYER_KEYBOARD ||
+            st->r_paddle.player == PLAYER_KEYBOARD)
+          {
+            st->key_down = is_pressed;
+            return True;
+          }
+        break;
+      case 'w':
+        if (st->l_paddle.player == PLAYER_KEYBOARD_LEFT ||
+            st->r_paddle.player == PLAYER_KEYBOARD_LEFT)
+          {
+            st->key_w = is_pressed;
+            return True;
+          }
+        break;
+      case 's':
+        if (st->l_paddle.player == PLAYER_KEYBOARD_LEFT ||
+            st->r_paddle.player == PLAYER_KEYBOARD_LEFT)
+          {
+            st->key_s = is_pressed;
+            return True;
+          }
+        break;
+      }
+    }
+
+  /* Allow the user to pick up and drag either paddle with the mouse,
+     even when not in a mouse-paddle mode. */
+
+  case ButtonPress:
+    if (st->dragging != 0)
+      return False;
+    else if (event->xbutton.x < st->w * 0.2)
+      {
+        if (st->l_paddle.player != PLAYER_MOUSE)
+          st->dragging = 1;
+        return True;
+      }
+    else if (event->xbutton.x > st->w * 0.8)
+      {
+        if (st->r_paddle.player != PLAYER_MOUSE)
+          st->dragging = 2;
+        return True;
+      }
+    break;
+  case ButtonRelease:
+    if (st->dragging != 0)
+      {
+        st->dragging = 0;
+        return True;
+      }
+    break;
+  }
   return False;
 }
 
index d9d7f4acc6c328de50d8093be593bb9aabeda738..c37364a239d83583cb5250110674af7ac0159d36 100644 (file)
@@ -42,6 +42,10 @@ How noisy the video signal should be (between 0.0 and 4.0 or so).
 .TP 8
 .B \-fps
 Display the current frame rate and CPU load.
+.TP 8
+.B (\-p1 | \-p2) \fImode\fP
+Set a player to either \fIai\fP, \fImouse\fP, \fItablet\fP, \fIkbleft\fP (for W and S), or
+\fIkbright\fP (or just \fIkb\fP, for arrow keys).
 .SH ENVIRONMENT
 .PP
 .TP 8
index 55d3db175e808e3e44577ccd90a123f006159770..065ad06d4e9189642e06dffb75826d20a57ccf1b 100644 (file)
@@ -69,7 +69,7 @@ popsquares_init (Display *dpy, Window window)
   st->twitch = get_boolean_resource(st->dpy, "twitch", "Boolean");
   st->dbuf = get_boolean_resource(st->dpy, "doubleBuffer", "Boolean");
 
-# ifdef HAVE_COCOA     /* Don't second-guess Quartz's double-buffering */
+# ifdef HAVE_JWXYZ     /* Don't second-guess Quartz's double-buffering */
   st->dbuf = False;
 # endif
 
@@ -86,6 +86,8 @@ popsquares_init (Display *dpy, Window window)
   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;
+  if (st->nsquares < 1) st->nsquares = 1;
+  if (st->ncolors < 1) st->ncolors = 1;
 
   gcv.foreground = fg.pixel;
   gcv.background = bg.pixel;
@@ -196,6 +198,7 @@ popsquares_reshape (Display *dpy, Window window, void *closure,
   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++)
@@ -246,7 +249,7 @@ static const char *popsquares_defaults [] = {
   "*useDBE: True",
   "*useDBEClear: True",
 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
   0
index 6e3e9aebe987ef5b747da1c8e2c62b4d0c285d5d..1498af76d35f61578c2b6d5caf6fb8433b8b05a9 100644 (file)
@@ -80,7 +80,7 @@ init_one_qix (struct state *st, int nlines)
     qix->lines[i].p = (struct qpoint *)
       calloc(qix->npoly, sizeof(struct qpoint));
 
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
   if (!mono_p && !st->transparent_p)
 # endif
     {
@@ -129,7 +129,7 @@ init_one_qix (struct state *st, int nlines)
       qix->lines[i].color = qix->lines[0].color;
       qix->lines[i].dead = qix->lines[0].dead;
   
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
       if (!mono_p && !st->transparent_p)
 # endif
        if (!XAllocColor (st->dpy, st->cmap, &qix->lines[i].color))
@@ -212,7 +212,7 @@ qix_init (Display *dpy, Window window)
   st->additive_p = get_boolean_resource (st->dpy, "additive", "Boolean");
   st->cmap_p = has_writable_cells (xgwa.screen, xgwa.visual);
 
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
   if (st->transparent_p)
     {
       unsigned long *plane_masks = 0;
@@ -274,7 +274,7 @@ qix_init (Display *dpy, Window window)
              st->gcs [1][i] = XCreateGC (st->dpy, st->window, 
                                           GCForeground|GCPlaneMask,
                                           &gcv);
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
            /* jwxyz_XSetAntiAliasing (st->dpy, st->gcs [0][i], False);
               jwxyz_XSetAntiAliasing (st->dpy, st->gcs [1][i], False); */
               if (st->transparent_p)
@@ -282,7 +282,7 @@ qix_init (Display *dpy, Window window)
                   jwxyz_XSetAlphaAllowed (dpy, st->gcs [0][i], True);
                   jwxyz_XSetAlphaAllowed (dpy, st->gcs [1][i], True);
                 }
-# endif /* HAVE_COCOA */
+# endif /* HAVE_JWXYZ */
            }
        }
 
@@ -293,10 +293,10 @@ qix_init (Display *dpy, Window window)
       XClearWindow (st->dpy, st->window);
     }
   else
-#endif /* !HAVE_COCOA */
+#endif /* !HAVE_JWXYZ */
   if (st->xor_p)
     {
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
     NON_TRANSPARENT_XOR:
 #endif
       gcv.function = GXxor;
@@ -307,7 +307,7 @@ qix_init (Display *dpy, Window window)
     }
   else
     {
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
     NON_TRANSPARENT:
 #endif
       st->draw_gc = XCreateGC (st->dpy, st->window, GCForeground, &gcv);
@@ -316,7 +316,7 @@ qix_init (Display *dpy, Window window)
       st->erase_gc = XCreateGC (st->dpy, st->window, GCForeground, &gcv);
     }
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
   if (st->transparent_p)
     jwxyz_XSetAlphaAllowed (dpy, st->draw_gc, True);
 #endif
@@ -329,7 +329,7 @@ qix_init (Display *dpy, Window window)
       st->qixes [st->count]->id = st->count;
     }
 
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
   /* line-mode leaves turds without this. */
   jwxyz_XSetAntiAliasing (st->dpy, st->erase_gc, False);
   jwxyz_XSetAntiAliasing (st->dpy, st->draw_gc,  False);
@@ -437,7 +437,7 @@ add_qline (struct state *st,
          - (st->random_p ? random() % st->max_spread : 0);
     }
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
   if (!mono_p && !st->transparent_p)
 #endif
     {
@@ -470,7 +470,7 @@ add_qline (struct state *st,
            abort (); /* same color should work */
        }
 
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
           if (st->transparent_p)
             {
               /* give a non-opaque alpha to the color */
@@ -480,7 +480,7 @@ add_qline (struct state *st,
               pixel = (pixel & (~amask)) | a;
               qline->color.pixel = pixel;
             }
-# endif /* HAVE_COCOA */
+# endif /* HAVE_JWXYZ */
 
       XSetForeground (st->dpy, st->draw_gc, qline->color.pixel);
     }
@@ -592,7 +592,7 @@ static const char *qix_defaults [] = {
   "*transparent:true",
   "*gravity:   false",
   "*additive:  true",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
   0
index 08ec7a753d9c84dd8c2a6accab19ac5b607c8ecd..4833c370d83d53fbe586080461bf787e8f8aae03 100644 (file)
@@ -145,12 +145,6 @@ pixack_frame(struct state *st, char *pix_buf)
 
   if (!(st->frame%st->epoch_time)) {
     int s;
-    if (0 != st->frame) {
-      int tt = st->epoch_time / 500;
-      if (tt > 15)
-       tt = 15;
-      /*sleep(tt);*/
-    }
          
     for (i = 0; i < st->npix; i++) {
       /* equilibrium */
@@ -314,7 +308,7 @@ static const char *rd_defaults [] = {
 #else
   "*useSHM:    False",
 #endif
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
   0
@@ -378,7 +372,6 @@ rd_init (Display *dpy, Window win)
 {
   struct state *st = (struct state *) calloc (1, sizeof(*st));
   XGCValues gcv;
-  int w2;
   int vdepth;
 
   st->dpy = dpy;
@@ -418,7 +411,6 @@ rd_init (Display *dpy, Window win)
 
   }
   st->npix = (st->width + 2) * (st->height + 2);
-  w2 = st->width + 2;
 /*  gcv.function = GXcopy;*/
   st->gc = XCreateGC(st->dpy, win, 0 /*GCFunction*/, &gcv);
   vdepth = visual_depth(DefaultScreenOfDisplay(st->dpy), st->xgwa.visual);
index feeb91335ca6e2a9e569fe1b817bff00b16dd74c..51379ed0a2ce2fa4903004233f4e4e2b0ff09c1c 100644 (file)
 #endif /* HAVE_CONFIG_H */
 
 #ifdef USE_GL
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
 #  include "jwxyz.h"
-# else /* !HAVE_COCOA -- real Xlib */
+# else /* !HAVE_JWXYZ -- real Xlib */
 #  include <GL/glx.h>
 #  include <GL/glu.h>
-# endif /* !HAVE_COCOA */
+# endif /* !HAVE_JWXYZ */
 # ifdef HAVE_JWZGLES
 #  include "jwzgles.h"
 # endif /* HAVE_JWZGLES */
@@ -119,9 +119,9 @@ screenhack_record_anim_init (Screen *screen, Window window, int target_frames)
 # endif /* !USE_GL */
 
 
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
   XFetchName (dpy, st->window, &st->title);
-# endif /* !HAVE_COCOA */
+# endif /* !HAVE_JWXYZ */
 
   return st;
 }
@@ -246,7 +246,7 @@ screenhack_record_anim (record_anim_state *st)
 #  error GDK_PIXBUF is required
 # endif /* !HAVE_GDK_PIXBUF */
 
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
   {  /* Put percent done in window title */
     int pct = 100 * (st->frame_count + 1) / st->target_frames;
     if (pct != st->pct && st->title)
@@ -260,7 +260,7 @@ screenhack_record_anim (record_anim_state *st)
         st->pct = pct;
       }
   }
-# endif /* !HAVE_COCOA */
+# endif /* !HAVE_JWXYZ */
 
   if (++st->frame_count >= st->target_frames)
     screenhack_record_anim_free (st);
index 76586488be5900b1fea18bba359c48f6cdbb06e1..74c2c09817403b21de23f64adb24afafc0cc11ed 100644 (file)
@@ -1114,7 +1114,7 @@ static const char *ripples_defaults[] =
 #else
   "*useSHM: False",
 #endif
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
   "*rotateImages:   True",
 #endif
index d44e75208fec0778b4443cd0437b6296262fda87..7e82b24db8e70e02fc0802ce21712bde9b022be3 100644 (file)
@@ -523,7 +523,7 @@ static const char *rocks_defaults [] = {
   "*left3d:    Blue",
   "*right3d:   Red",
   "*delta3d:   1.5",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
   0
index ad96f99f94eaeb46471b0388103967d26eadc159..6b2d7a3b88d49b7f0f85762489994a2d9cd6c1bd 100644 (file)
@@ -194,7 +194,7 @@ static const char *rorschach_defaults [] = {
   "*iterations:        4000",
   "*offset:    7",
   "*delay:     5",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
   0
index eb1a0b78313e25525db2feef4c7b653f38e68365..1b3d5b39b51396a505cc96fb727c889ab10be454 100644 (file)
@@ -134,7 +134,7 @@ init_rotor (ModeInfo * mi)
        }
        rp = &rotors[MI_SCREEN(mi)];
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
     jwxyz_XSetAntiAliasing (MI_DISPLAY(mi), MI_GC(mi),  False);
 #endif
 
index 3ccb4668eb456cb88335d8f67630b26217fc8293..e4cd8536c85cf3b4c740c6992961917acb62303a 100644 (file)
@@ -97,9 +97,6 @@ rotzoom (struct state *st, struct zoom_area *za)
         int dy = y - cy;
         int d2 = (dx*dx) + (dy*dy);
 
-        ox = x;
-        oy = y;
-
         if (d2 > w2) {
           ox = x;
           oy = y;
@@ -269,7 +266,7 @@ create_zoom (struct state *st)
 {
   struct zoom_area *za;
 
-  za = malloc (sizeof (struct zoom_area));
+  za = calloc (1, sizeof (struct zoom_area));
   reset_zoom (st, za);
 
   return za;
@@ -533,7 +530,7 @@ static const char *rotzoomer_defaults[] = {
   "*numboxes: 2",
   "*delay: 10000",
   "*duration: 120",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
   "*rotateImages:   True",
 #endif
index 0b5a1b604d9d5f8acf266c55ccf6ceec2b0e141d..8689d4f5da36f5b4f4af3dbb32a536188e1798db 100644 (file)
@@ -783,7 +783,7 @@ main (int argc, char **argv)
                      !strcmp(argv[1], "--help"));
       fprintf (stderr, "%s\n", version);
       for (s = progclass; *s; s++) fprintf(stderr, " ");
-      fprintf (stderr, "  http://www.jwz.org/xscreensaver/\n\n");
+      fprintf (stderr, "  https://www.jwz.org/xscreensaver/\n\n");
 
       if (!help_p)
        fprintf(stderr, "Unrecognised option: %s\n", argv[1]);
index 1f9a561d690ffa7ab5d6d3a9e3150425d0b6b438..2e55d8930122a0e53371660c65f787f72f5c56e3 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1992-2008 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1992-2015 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
    a struct in `MODULENAME_xscreensaver_function_table',
    and a pointer to that in `xscreensaver_function_table'.
 
-   In a Cocoa world, we only define the prefixed symbol;
+   In a Cocoa/Android world, we only define the prefixed symbol;
    the un-prefixed symbol does not exist.
  */
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
 # define XSCREENSAVER_LINK(NAME)
 #else
 # define XSCREENSAVER_LINK(NAME) \
@@ -29,7 +29,7 @@
 #endif
 
 
-#if defined(HAVE_COCOA) && !defined(__XLOCKMORE_INTERNAL_H__)
+#if defined(HAVE_JWXYZ) && !defined(__XLOCKMORE_INTERNAL_H__)
   /* this is one enormous kludge... */
 # undef ya_rand_init
   static void
index b5a1709f1038561be77833d5f58fce3e4e712636..8b4212de132ccb9c5c2332524564c8312e3858ce 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1992-2014 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1992-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
@@ -60,6 +60,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
+#include <time.h>
 
 #ifdef __hpux
  /* Which of the ten billion standards does values.h belong to?
 # include <values.h>
 #endif
 
-#if defined(HAVE_COCOA) || defined(HAVE_ANDROID)
+#ifdef HAVE_JWXYZ
 # include "jwxyz.h"
 #else  /* real X11 */
 # include <X11/Xlib.h>
 # include <X11/Xutil.h>
 # include <X11/Xresource.h>
 # include <X11/Xos.h>
-#endif /* !HAVE_COCOA */
+#endif /* !HAVE_JWXYZ */
+
+#if defined(USE_IPHONE) || defined(HAVE_ANDROID)
+# define HAVE_MOBILE
+#endif
+
+#ifdef HAVE_ANDROID
+ /* So that hacks' debug output shows up in logcat... */
+ extern void Log(const char *fmt, ...);  /* jwxyz-android.c */
+# define fprintf(S, ...) Log(__VA_ARGS__)
+#endif
 
 /* M_PI ought to have been defined in math.h, but... */
 #ifndef M_PI
index d1361dd3aa4f23ed8d460cb3d65f73e7efe9e22d..7a1a0ffc13c258bad17567ba44150f7e6ee809d3 100644 (file)
@@ -52,7 +52,7 @@ static const char *shadebobs_defaults [] = {
   "*cycles:   10",
   "*ncolors:  64",    /* changing this doesn't work particularly well */
   "*delay:    10000",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
   0
index 4ba8b7ff42a229bca254da293ca1c0c2df202709..313f0eecff0ad5bce43621e379bf91e9095caf62 100644 (file)
@@ -108,7 +108,7 @@ slidescreen_init (Display *dpy, Window window)
     else
       st->bg = 1;
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
     if (!fg_ok || bg_ok)
       {
         int i;
@@ -167,7 +167,7 @@ slidescreen_init (Display *dpy, Window window)
          }
        XFree(all);
       }
-#endif /* !HAVE_COCOA */
+#endif /* !HAVE_JWXYZ */
   }
 
   gcv.foreground = st->fg;
@@ -475,7 +475,7 @@ static const char *slidescreen_defaults [] = {
   "*delay:                     50000",
   "*delay2:                    1000000",
   "*duration:                  120",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation:             True",
   "*rotateImages:               True",
 #endif
index 81c468686760db0eb49c289fc04d204385d54ac0..17a3f2a4d695d6de696f12bdfd3c46d90e2d09f8 100644 (file)
  */
 
 /* Define or undefine NDEBUG to turn assert and abort debugging off or on */
-#define NDEBUG
-#include <assert.h>
+/*#define NDEBUG*/
+/*#include <assert.h>*/
+#define assert(X)
+#define DEBUG_FLAG 0
 
 #include <math.h>
 
 /* No. of shades of each color (ground, walls, bonuses) */
 #define MAX_COLORS 32
 
-#ifdef NDEBUG
-#define DEBUG_FLAG 0
-#else
-#define DEBUG_FLAG 1
-#endif
 
 
 #define FORWARDS 1
@@ -478,7 +475,8 @@ generate_terrain (struct state *st, int start, int end, int final)
        for (w= diff/2, l=TERRAIN_BREADTH/4;
             w >= final || l >= final; w /= 2, l /= 2) {
 
-               if (w<1) w=1; if (l<1) l=1;
+               if (w<1) w=1;
+        if (l<1) l=1;
 
                for (i=start+w-1; i < end; i += (w*2)) {
                        ip = i-w; MODULO(ip, TERRAIN_LENGTH);
@@ -1442,7 +1440,7 @@ speedmine_init (Display *dpy, Window window)
 
   st->verbose_flag = get_boolean_resource (st->dpy, "verbose", "Boolean");
 
-# ifdef HAVE_COCOA     /* Don't second-guess Quartz's double-buffering */
+# ifdef HAVE_JWXYZ     /* Don't second-guess Quartz's double-buffering */
   st->dbuf = st->window;
 #else
   st->dbuf = XCreatePixmap (st->dpy, st->window, st->width, st->height, xgwa.depth);
index 7a2a302995d7baaad2d0f5f8751e075dda444713..bfef07d8b6a30ebcdf7b89882d9ef3ace230cd64 100644 (file)
@@ -134,7 +134,7 @@ init_spiral(ModeInfo * mi)
        }
        sp = &spirals[MI_SCREEN(mi)];
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
     jwxyz_XSetAntiAliasing (MI_DISPLAY(mi), MI_GC(mi),  False);
 #endif
 
index ccf768ece989a3f24ddb12a631c3b2592687fde0..7224ee855406918ed1e49c1b6a0a6cd09e364d24 100644 (file)
@@ -144,7 +144,7 @@ spotlight_init (Display *dpy, Window window)
   st->first_time = 1;
 
   /* create buffer to reduce flicker */
-#ifdef HAVE_COCOA      /* Don't second-guess Quartz's double-buffering */
+#ifdef HAVE_JWXYZ      /* Don't second-guess Quartz's double-buffering */
   st->buffer = 0;
 #else
   st->buffer = XCreatePixmap(st->dpy, st->window, st->sizex, st->sizey, xgwa.depth);
@@ -325,7 +325,7 @@ static const char *spotlight_defaults [] = {
   "*delay:                     10000",
   "*duration:                  120",
   "*radius:                    125",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation:             True",
   "*rotateImages:               True",
 #endif
index 57afa54a5d78835eee0441ec68f0e6775341b4c9..48cd5f8c9049e11b5560973d0e0820a89bff58e1 100644 (file)
@@ -14,7 +14,7 @@
 #include "erase.h"
 #include "yarandom.h"
 
-#define R(x)  (abs(random())%x)
+#define R(x)  (random()%x)
 #define PROB(x) (frand(1.0) < (x))
 
 #define NCOLORSMAX 255
@@ -268,7 +268,7 @@ static const char *squiral_defaults[] = {
   "*disorder:   0.005",
   "*cycle:      False",
   "*handedness: 0.5",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
   0
index 2e06ee9e297b3853b9ede5f6cb83bf63772a531f..5fa3395e9aa979f72ab07752df1a47f326096185 100644 (file)
@@ -71,7 +71,6 @@ make_starfish (struct state *st, int maxx, int maxy, int size)
 {
   struct starfish *s = (struct starfish *) calloc(1, sizeof(*s));
   int i;
-  int mid;
 
   s->blob_p = st->blob_p;
   s->elasticity = SCALE * get_float_resource (st->dpy, "thickness", "Thickness");
@@ -121,7 +120,6 @@ make_starfish (struct state *st, int maxx, int maxy, int size)
   s->min_r = 0;
 
   if (s->min_r < (5*SCALE)) s->min_r = (5*SCALE);
-  mid = ((s->min_r + s->max_r) / 2);
 
   s->x = maxx/2;
   s->y = maxy/2;
@@ -390,7 +388,7 @@ reset_starfish (struct state *st)
   flags |= GCFillRule;
   gcv.fill_rule = EvenOddRule;
   st->gc = XCreateGC (st->dpy, st->window, flags, &gcv);
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
   if (!st->blob_p)
     jwxyz_XSetAntiAliasing (st->dpy, st->gc, False);
 #endif
@@ -532,7 +530,7 @@ static const char *starfish_defaults [] = {
   "*duration:          30",
   "*delay2:            5",
   "*mode:              random",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation:     True",
 #endif
   0
index 148bbcadcd5820f981ce45eba6c162165c5adf70..b1739acd534a7977e46bdd7c05de57c5325261d1 100644 (file)
@@ -82,7 +82,7 @@ ModStruct   strange_description =
 "Shows strange attractors", 0, NULL};
 #endif
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
 # define NO_DBUF
 #endif
 
@@ -577,18 +577,18 @@ init_strange(ModeInfo * mi)
 
                gcv.foreground = 0;
                gcv.background = 0;
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
                gcv.graphics_exposures = False;
-#endif /* HAVE_COCOA */
+#endif /* HAVE_JWXYZ */
                gcv.function = GXcopy;
 
                if (Attractor->dbuf_gc != None)
                        XFreeGC(display, Attractor->dbuf_gc);
 
                if ((Attractor->dbuf_gc = XCreateGC(display, Attractor->dbuf,
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
                                GCGraphicsExposures |
-#endif /* HAVE_COCOA */
+#endif /* HAVE_JWXYZ */
                                GCFunction | GCForeground | GCBackground,
                                &gcv)) == None) {
                        XFreePixmap(display, Attractor->dbuf);
index c63ceb957aadeddd73999e6cf9bbe74a220d6063..278a3bd6a4fb18151c52f0f466977b335604c1ba 100644 (file)
@@ -287,7 +287,7 @@ static inline void point2rgb(int depth, unsigned long c, int *r, int *g, int *b)
     switch(depth) {
         case 32:
         case 24:
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
             /* This program idiotically does not go through a color map, so
                we have to hardcode in knowledge of how jwxyz.a packs pixels!
                Fix it to go through st->colors[st->ncolors] instead!
@@ -321,7 +321,7 @@ static inline unsigned long rgb2point(int depth, int r, int g, int b)
     switch(depth) {
         case 32:
         case 24:
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
             /* This program idiotically does not go through a color map, so
                we have to hardcode in knowledge of how jwxyz.a packs pixels!
                Fix it to go through st->colors[st->ncolors] instead!
@@ -515,7 +515,7 @@ movedrawcrack(struct state *st, GC fgc, struct field *f, int cracknum)
         cr->y += ((float) cr->xs * sin(cr->t * M_PI/180 - M_PI / 2));
 
         cr->t += cr->t_inc;
-        cr->degrees_drawn += abs(cr->t_inc);
+        cr->degrees_drawn += fabsf(cr->t_inc);
     }
     if (f->seamless) {
         cr->x = fmod(cr->x + f->width, f->width);
@@ -547,10 +547,10 @@ movedrawcrack(struct state *st, GC fgc, struct field *f, int cracknum)
         }
         /* safe to check */
         else if ((f->cgrid[cy * f->width + cx] > 10000) ||
-                 (abs(f->cgrid[cy * f->width + cx] - cr->t) < 5)) {
+                 (fabsf(f->cgrid[cy * f->width + cx] - cr->t) < 5)) {
             /* continue cracking */
             f->cgrid[cy * f->width + cx] = (int) cr->t;
-        } else if (abs(f->cgrid[cy * f->width + cx] - cr->t) > 2) {
+        } else if (fabsf(f->cgrid[cy * f->width + cx] - cr->t) > 2) {
             /* crack encountered (not self), stop cracking */
             start_crack(f, cr); /* restart ourselves */
             make_crack(f); /* generate a new crack */
@@ -750,7 +750,7 @@ static const char *substrate_defaults[] = {
     "*maxCracks: 100",
     "*sandGrains: 64",
     "*circlePercent: 33",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
     0
index d647b0432dc4c4c892ba6feab3a96bc23b24b4d5..49529f6eace625348344374a7968245616883e96 100644 (file)
@@ -1355,78 +1355,78 @@ draw_swirl(ModeInfo * mi)
                        rotate_colors(mi->xgwa.screen, MI_COLORMAP(mi),
                                                  swirl->rgb_values, swirl->colours, 1);
 #else  /* !STANDALONE */
-                       /* rotate the colours */
-                       install_map(MI_DISPLAY(mi), swirl, swirl->dshift);
+          /* rotate the colours */
+          install_map(MI_DISPLAY(mi), swirl, swirl->dshift);
 #endif /* !STANDALONE */
 
-                       /* draw a batch of points */
-                       swirl->batch_todo = BATCH_DRAW;
-                       while ((swirl->batch_todo > 0) && swirl->drawing) {
-                               /* draw a point */
-                               draw_point(mi, swirl);
+          /* draw a batch of points */
+          swirl->batch_todo = BATCH_DRAW;
+          while ((swirl->batch_todo > 0) && swirl->drawing) {
+            /* draw a point */
+            draw_point(mi, swirl);
 
-                               /* move to the next point */
-                               next_point(swirl);
+            /* move to the next point */
+            next_point(swirl);
 
-                               /* done a point */
-                               swirl->batch_todo--;
-                       }
+            /* done a point */
+            swirl->batch_todo--;
+          }
                } else {
 #ifdef STANDALONE
                  if (mi->writable_p)
                        rotate_colors(mi->xgwa.screen, MI_COLORMAP(mi),
                                                  swirl->rgb_values, swirl->colours, 1);
 #else  /* !STANDALONE */
-                       /* rotate the colours */
-                       install_map(MI_DISPLAY(mi), swirl, swirl->shift);
+          /* rotate the colours */
+          install_map(MI_DISPLAY(mi), swirl, swirl->shift);
 #endif /* !STANDALONE */
 
-                       /* time for a higher resolution? */
-                       if (swirl->resolution > swirl->max_resolution) {
-                               /* move to higher resolution */
-                               swirl->resolution--;
-
-                               /* calculate the pixel step for this resulution */
-                               swirl->r = (1 << (swirl->resolution - 1));
-
-                               /* start drawing again */
-                               swirl->drawing = True;
-
-                               /* start in the middle of the screen */
-                               swirl->x = (swirl->width - swirl->r) / 2;
-                               swirl->y = (swirl->height - swirl->r) / 2;
-
-                               /* initialise spiral drawing parameters */
-                               swirl->direction = DRAW_RIGHT;
-                               swirl->dir_todo = 1;
-                               swirl->dir_done = 0;
-                       } else {
-                               /* all done, decide when to restart */
-                               if (swirl->start_again == -1) {
-                                       /* start the counter */
-                                       swirl->start_again = RESTART;
-                               } else if (swirl->start_again == 0) {
-                                       /* reset the counter */
-                                       swirl->start_again = -1;
+          /* time for a higher resolution? */
+          if (swirl->resolution > swirl->max_resolution) {
+            /* move to higher resolution */
+            swirl->resolution--;
+
+            /* calculate the pixel step for this resulution */
+            swirl->r = (1 << (swirl->resolution - 1));
+
+            /* start drawing again */
+            swirl->drawing = True;
+
+            /* start in the middle of the screen */
+            swirl->x = (swirl->width - swirl->r) / 2;
+            swirl->y = (swirl->height - swirl->r) / 2;
+
+            /* initialise spiral drawing parameters */
+            swirl->direction = DRAW_RIGHT;
+            swirl->dir_todo = 1;
+            swirl->dir_done = 0;
+          } else {
+            /* all done, decide when to restart */
+            if (swirl->start_again == -1) {
+              /* start the counter */
+              swirl->start_again = RESTART;
+            } else if (swirl->start_again == 0) {
+              /* reset the counter */
+              swirl->start_again = -1;
 
 #ifdef STANDALONE
-                                       /* Pick a new colormap! */
-                                       XClearWindow (MI_DISPLAY(mi), MI_WINDOW(mi));
-                                       free_colors (mi->xgwa.screen, MI_COLORMAP(mi),
-                                                                mi->colors, mi->npixels);
-                                       make_smooth_colormap (mi->xgwa.screen, MI_VISUAL(mi),
-                                                                                 MI_COLORMAP(mi),
-                                                                                 mi->colors, &mi->npixels, True,
-                                                                                 &mi->writable_p, True);
-                                       swirl->colours = mi->npixels;
+              /* Pick a new colormap! */
+              XClearWindow (MI_DISPLAY(mi), MI_WINDOW(mi));
+              free_colors (mi->xgwa.screen, MI_COLORMAP(mi),
+                           mi->colors, mi->npixels);
+              make_smooth_colormap (mi->xgwa.screen, MI_VISUAL(mi),
+                                    MI_COLORMAP(mi),
+                                    mi->colors, &mi->npixels, True,
+                                    &mi->writable_p, True);
+              swirl->colours = mi->npixels;
 #endif /* STANDALONE */
 
-                                       /* start again */
-                                       init_swirl(mi);
-                               } else
-                                       /* decrement the counter */
-                                       swirl->start_again--;
-                       }
+              /* start again */
+              init_swirl(mi);
+            } else
+              /* decrement the counter */
+              swirl->start_again--;
+          }
                }
        }
 }
index 08df87132a658590d7dcbb0e83174b3f624430c1..6a7e0cdec898a4a88dca2d7bb758fe7fd08a2956 100644 (file)
                           of the command-line options provided by screenhack.c.
 */
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # define FASTDRAW
 # define FASTCOPY
-#endif /* !HAVE_COCOA */
+#endif /* !HAVE_JWXYZ */
 
 #include <stdio.h>
 #include <math.h>
@@ -325,7 +325,7 @@ initialize (struct state *st)
 
   st->planes=st->xgwa.depth;
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
 # define GXandInverted GXcopy  /* #### this can't be right, right? */
 #endif
  st->gc = XCreateGC (st->dpy, st->window, 0,  xgc);
@@ -563,10 +563,15 @@ fill_kugel(struct state *st, int i, Pixmap buf, int setcol)
          else if(-ra<40.0) inc=2;
          if(setcol)
            {
-             if (m==27) col=33;
+             if (m==27)
+                col=33;
              else
                col=(int)(m);
-             if (col>33) col=33;       col/=3;
+
+             if (col>33)
+                col=33;
+
+              col/=3;
              setink(st->colors[col].pixel);
            }
 
index d018f0cde4927ec531a693d815c401e0dc98049e..d361eb3fb4f4944d1c0dea114b7d3a6f16ae7cb1 100644 (file)
@@ -15,7 +15,7 @@
 #undef DO_VORONOI
 
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # define XK_MISCELLANY
 # include <X11/keysymdef.h>
 #endif
@@ -67,13 +67,11 @@ static void *
 tessellimage_init (Display *dpy, Window window)
 {
   struct state *st = (struct state *) calloc (1, sizeof(*st));
-  Colormap cmap;
 
   st->dpy = dpy;
   st->window = window;
 
   XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
-  cmap = st->xgwa.colormap;
 
   st->delay = get_integer_resource (st->dpy, "delay", "Integer");
   if (st->delay < 1) st->delay = 1;
@@ -932,7 +930,7 @@ static const char *tessellimage_defaults [] = {
   "*outline:                   True",
   "*fillScreen:                        True",
   "*cache:                     True",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation:             True",
   "*rotateImages:               True",
 #endif
index 35702da6a02bfc3ba362bf12dd00c1ffca010b55..8284d16b41c75f050cdcd279498fdbaaac78e9ac 100644 (file)
@@ -1,4 +1,4 @@
-/* testx11.c, Copyright (c) 2015 Dave Odell <dmo2118@gmail.com>
+/* testx11.c, Copyright (c) 2015-2016 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
  */
 
 #include "screenhack.h"
+#include "glx/rotator.h"
 
 #include <assert.h>
 #include <errno.h>
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # define jwxyz_XSetAntiAliasing(dpy, gc, p)
 #endif
 
@@ -32,6 +33,9 @@
 static const char *testx11_defaults [] = {
   ".background: #a020f0", /* purple */
   ".foreground: white",
+#ifdef HAVE_MOBILE
+  "*ignoreRotation: True",
+#endif
   0
 };
 
@@ -39,16 +43,13 @@ static XrmOptionDescRec testx11_options [] = {
   { 0, 0, 0, 0 }
 };
 
-#if defined HAVE_COCOA || defined HAVE_ANDROID
-# define HAVE_JWXYZ 1
-#endif
-
 enum
 {
   mode_welcome,
   mode_primitives,
   mode_images,
   mode_copy,
+  mode_preserve,
 
   mode_count
 };
@@ -65,17 +66,36 @@ struct testx11 {
 
   unsigned mode;
 
+  /* Pixels from XAllocPixel. */
   unsigned long rgb[3], salmon, magenta, gray50, dark_slate_gray1, cyan;
 
-  Pixmap backdrop_tile, clip_mask_tile, backdrop_scratch;
-  XColor backdrop_colors[64];
-  int backdrop_ncolors;
   unsigned frame;
 
-  GC copy_gc, black_gc, mono_gc, thick_line_gc, xor_gc, point_gc;
   Bool anti_alias_p;
 
-  Pixmap mini_pix, pix64;
+  /* These X11 objects aren't altered after creation, except for:
+     - copy_gc and thick_line_gc get anti-aliasing toggled.
+     - xor_gc's clip mask (if it's turned on) always covers the entire window.
+   */
+  GC copy_gc, mono_gc, thick_line_gc, xor_gc, graph_gc;
+  Pixmap clip_mask_tile;
+
+  /* Backdrop stuff, naturally. */
+  GC backdrop_black_gc;
+  Pixmap backdrop_tile, backdrop_scratch;
+  XColor backdrop_colors[64];
+  int backdrop_ncolors;
+
+  /* The following items may be modified by various test modes. */
+  Pixmap primitives_mini_pix;
+
+  GC images_point_gc;
+
+  Pixmap copy_pix64;
+
+  Pixmap preserve[2];
+
+  rotator *rot;
 };
 
 
@@ -117,52 +137,55 @@ create_backbuffer(struct testx11 *st)
 # endif
 }
 
+static Bool
+toggle_antialiasing (struct testx11 *st)
+{
+  st->anti_alias_p ^= True;
+  jwxyz_XSetAntiAliasing (st->dpy, st->copy_gc, st->anti_alias_p);
+  jwxyz_XSetAntiAliasing (st->dpy, st->thick_line_gc, st->anti_alias_p);
+  return True;
+}
+
 
 static void
-copy_test (Display *dpy, Drawable src, Drawable dst, GC gc, int x, int y,
-           unsigned long cells)
+primitives_mini_rect(struct testx11 *st, Drawable t, int x, int y)
 {
-  XCopyArea(dpy, src, dst, gc, 0, 0, 3, 2, x, y);
+  XFillRectangle(st->dpy, t, st->copy_gc, x, y, 2, 2);
+}
+
+static void
+images_copy_test (Display *dpy, Drawable src, Drawable dst, GC gc,
+                  int src_y, int dst_x, int dst_y, unsigned long cells)
+{
+  XCopyArea(dpy, src, dst, gc, 0, src_y, 3, 2, dst_x, dst_y);
 
   {
-    XImage *image = XGetImage(dpy, src, 0, 0, 3, 2, cells, ZPixmap);
-    XPutImage(dpy, dst, gc, image, 0, 0, x, y + 2, 3, 2);
+    XImage *image = XGetImage(dpy, src, 0, src_y, 3, 2, cells, ZPixmap);
+    XPutImage(dpy, dst, gc, image, 0, 0, dst_x, dst_y + 2, 3, 2);
     XDestroyImage(image);
   }
 }
 
 static void
-test_pattern (struct testx11 *st, Drawable d)
+images_pattern (struct testx11 *st, Drawable d, unsigned y)
 {
   unsigned x;
   for (x = 0; x != 3; ++x) {
-    XSetForeground(st->dpy, st->point_gc, st->rgb[x]);
-    XDrawPoint(st->dpy, d, st->point_gc, x, 0);
-    XSetForeground(st->dpy, st->point_gc, st->rgb[2 - x]);
-    XFillRectangle(st->dpy, d, st->point_gc, x, 1, 1, 1);
+    XSetForeground(st->dpy, st->images_point_gc, st->rgb[x]);
+    XDrawPoint(st->dpy, d, st->images_point_gc, x, y);
+    XSetForeground(st->dpy, st->images_point_gc, st->rgb[2 - x]);
+    XFillRectangle(st->dpy, d, st->images_point_gc, x, y + 1, 1, 1);
   }
 
-  copy_test (st->dpy, d, d, st->point_gc, 0, 2,
-             st->rgb[0] | st->rgb[1] | st->rgb[2]);
-}
-
-static void
-mini_rect(struct testx11 *st, Drawable t, int x, int y)
-{
-  XFillRectangle(st->dpy, t, st->copy_gc, x, y, 2, 2);
-}
-
-static Bool
-toggle_antialiasing (struct testx11 *st)
-{
-  st->anti_alias_p ^= True;
-  jwxyz_XSetAntiAliasing(st->dpy, st->copy_gc, st->anti_alias_p);
-  return True;
+  images_copy_test (st->dpy, d, d, st->images_point_gc, y, 0, y + 2,
+                    st->rgb[0] | st->rgb[1] | st->rgb[2]);
 }
 
 static const unsigned tile_size = 16;
 static const unsigned tile_count = 8;
 
+static const unsigned preserve_size = 128;
+
 static void
 make_clip_mask (struct testx11 *st)
 {
@@ -248,7 +271,13 @@ testx11_init (Display *dpy, Window win)
 
   st->frame = 0;
 
+# ifdef HAVE_ANDROID
+  st->mode = mode_primitives;
+# else
   st->mode = mode_welcome;
+# endif
+
+  st->anti_alias_p = False;
 
   gcv.function = GXcopy;
   gcv.foreground = st->cyan;
@@ -257,29 +286,32 @@ testx11_init (Display *dpy, Window win)
   gcv.cap_style = CapRound;
   /* TODO: Real X11 uses fixed by default. */
   gcv.font = XLoadFont (dpy, "fixed");
-  st->copy_gc = XCreateGC (dpy, win, GCFunction | GCForeground | GCBackground | GCLineWidth | GCCapStyle | GCFont, &gcv);
+  st->copy_gc = XCreateGC (dpy, win,
+                           GCFunction | GCForeground | GCBackground
+                             | GCLineWidth | GCCapStyle | GCFont, &gcv);
 
   gcv.foreground = BlackPixelOfScreen (st->xgwa.screen);
-  st->black_gc = XCreateGC (dpy, win, GCForeground, &gcv);
-
-  st->anti_alias_p = False;
-  jwxyz_XSetAntiAliasing (dpy, st->copy_gc, False);
+  st->backdrop_black_gc = XCreateGC (dpy, win, GCForeground, &gcv);
 
   gcv.foreground = alloc_color (st, 0x8000, 0x4000, 0xffff);
   gcv.line_width = 8;
   gcv.cap_style = CapProjecting;
-  st->thick_line_gc = XCreateGC (dpy, win, GCForeground | GCLineWidth | GCCapStyle, &gcv);
+  st->thick_line_gc = XCreateGC (dpy, win,
+                                 GCForeground | GCLineWidth | GCCapStyle,
+                                 &gcv);
 
   gcv.function = GXxor;
   st->xor_gc = XCreateGC (dpy, win, GCFunction, &gcv);
 
-  st->point_gc = XCreateGC (dpy, win, 0, NULL);
+  st->images_point_gc = XCreateGC (dpy, win, 0, NULL);
+
+  st->graph_gc = XCreateGC (dpy, win, 0, &gcv);
 
   st->mono_gc = XCreateGC (dpy, st->clip_mask_tile, 0, &gcv);
 
-  st->pix64 = XCreatePixmap(dpy, win, 64, 64, st->xgwa.depth);
+  st->copy_pix64 = XCreatePixmap(dpy, win, 64, 64, st->xgwa.depth);
 
-  st->mini_pix = XCreatePixmap (dpy, win, 16, 16, st->xgwa.depth);
+  st->primitives_mini_pix = XCreatePixmap (dpy, win, 16, 16, st->xgwa.depth);
 
   {
     static const char text[] = "Welcome from testx11_init().";
@@ -289,8 +321,16 @@ testx11_init (Display *dpy, Window win)
 
   make_clip_mask (st);
 
+  st->preserve[0] =
+    XCreatePixmap(dpy, win, preserve_size, preserve_size, st->xgwa.depth);
+  st->preserve[1] =
+    XCreatePixmap(dpy, win, preserve_size, preserve_size, st->xgwa.depth);
+
+  toggle_antialiasing (st);
+
   jwxyz_assert_display (dpy);
 
+  st->rot = make_rotator (2, 2, 2, 2, 0.01, False);
   return st;
 }
 
@@ -307,13 +347,15 @@ backdrop (struct testx11 *st, Drawable t)
     for (x = 0; x != tile_count; ++x) {
       unsigned c = ((sin ((x + st->frame / 8.0) * s0) * y_fac) - 1) / 2 * st->backdrop_ncolors / 2;
       c = (c + st->frame) % st->backdrop_ncolors;
-      XSetBackground (st->dpy, st->black_gc, st->backdrop_colors[c].pixel);
-      XCopyPlane (st->dpy, st->backdrop_tile, st->backdrop_scratch, st->black_gc,
-                  0, st->frame % tile_size, tile_size, tile_size, x * tile_size, y * tile_size, 1);
+      XSetBackground (st->dpy, st->backdrop_black_gc,
+                      st->backdrop_colors[c].pixel);
+      XCopyPlane (st->dpy, st->backdrop_tile, st->backdrop_scratch,
+                  st->backdrop_black_gc, 0, st->frame % tile_size,
+                  tile_size, tile_size, x * tile_size, y * tile_size, 1);
     }
   }
 
-  /* XFillRectangle (st->dpy, t, st->black_gc, 0, 0, w, h); */
+  /* XFillRectangle (st->dpy, t, st->backdrop_black_gc, 0, 0, w, h); */
 
   for (y = 0; y < h; y += tile_count * tile_size) {
     for (x = 0; x < w; x += tile_count * tile_size) {
@@ -327,6 +369,162 @@ static const unsigned button_pad = 16;
 static const unsigned button_size = 64;
 
 
+static void
+testx11_graph_rotator (struct testx11 *st)
+{
+  double x, y, z;
+
+  int boxw = st->xgwa.width / 3;
+  int boxh = (st->xgwa.height - (22 * 5)) / 4;
+  int boxx = st->xgwa.width - boxw - 20;
+  int boxy = st->xgwa.height - boxh - 20;
+  
+  /* position */
+
+  get_position (st->rot, &x, &y, &z, True);
+  if (x < 0 || x >= 1 || y < 0 || y >= 1 || z < 0 || z >= 1) abort();
+      
+
+  XSetForeground (st->dpy, st->graph_gc, st->dark_slate_gray1);
+  XDrawRectangle (st->dpy, st->win, st->graph_gc,
+                  boxx-1, boxy-1, boxw+2, boxh+2);
+
+  XCopyArea (st->dpy, st->win, st->win, st->graph_gc,
+             boxx+1, boxy, boxw-1, boxh, boxx, boxy);
+
+  XSetForeground (st->dpy, st->graph_gc, BlackPixelOfScreen (st->xgwa.screen));
+  XDrawLine (st->dpy, st->win, st->graph_gc,
+             boxx + boxw - 1, boxy,
+             boxx + boxw - 1, boxy + boxh);
+
+  XSetForeground (st->dpy, st->graph_gc, st->salmon);
+  XDrawPoint (st->dpy, st->win, st->graph_gc,
+              boxx + boxw - 1,
+              boxy + boxh - 1 - (int) (x * (boxh - 1)));
+
+  XSetForeground (st->dpy, st->graph_gc, st->magenta);
+  XDrawPoint (st->dpy, st->win, st->graph_gc,
+              boxx + boxw - 1,
+              boxy + boxh - 1 - (int) (y * (boxh - 1)));
+
+  XSetForeground (st->dpy, st->graph_gc, st->gray50);
+  XDrawPoint (st->dpy, st->win, st->graph_gc,
+              boxx + boxw - 1,
+              boxy + boxh - 1 - (int) (z * (boxh - 1)));
+
+  /* spin */
+
+  get_rotation (st->rot, &x, &y, &z, True);
+  if (x < 0 || x >= 1 || y < 0 || y >= 1 || z < 0 || z >= 1) abort();
+
+  /* put 0 in the middle */
+  x += 0.5; if (x > 1) x--;
+  y += 0.5; if (y > 1) y--;
+  z += 0.5; if (z > 1) z--;
+
+
+  boxy -= boxh + 20;
+
+  XSetForeground (st->dpy, st->graph_gc, st->dark_slate_gray1);
+  XDrawRectangle (st->dpy, st->win, st->graph_gc,
+                  boxx-1, boxy-1, boxw+2, boxh+2);
+
+  XCopyArea (st->dpy, st->win, st->win, st->graph_gc,
+             boxx+1, boxy, boxw-1, boxh, boxx, boxy);
+
+  XSetForeground (st->dpy, st->graph_gc, BlackPixelOfScreen (st->xgwa.screen));
+  XDrawLine (st->dpy, st->win, st->graph_gc,
+             boxx + boxw - 1, boxy,
+             boxx + boxw - 1, boxy + boxh);
+
+  XSetForeground (st->dpy, st->graph_gc, st->magenta);
+  XDrawPoint (st->dpy, st->win, st->graph_gc,
+              boxx + boxw - 1,
+              boxy + boxh - 1 - (int) (x * (boxh - 1)));
+
+
+  boxy -= boxh + 20;
+
+  XSetForeground (st->dpy, st->graph_gc, st->dark_slate_gray1);
+  XDrawRectangle (st->dpy, st->win, st->graph_gc,
+                  boxx-1, boxy-1, boxw+2, boxh+2);
+
+  XCopyArea (st->dpy, st->win, st->win, st->graph_gc,
+             boxx+1, boxy, boxw-1, boxh, boxx, boxy);
+
+  XSetForeground (st->dpy, st->graph_gc, BlackPixelOfScreen (st->xgwa.screen));
+  XDrawLine (st->dpy, st->win, st->graph_gc,
+             boxx + boxw - 1, boxy,
+             boxx + boxw - 1, boxy + boxh);
+
+  XSetForeground (st->dpy, st->graph_gc, st->magenta);
+  XDrawPoint (st->dpy, st->win, st->graph_gc,
+              boxx + boxw - 1,
+              boxy + boxh - 1 - (int) (y * (boxh - 1)));
+
+
+  boxy -= boxh + 20;
+
+  XSetForeground (st->dpy, st->graph_gc, st->dark_slate_gray1);
+  XDrawRectangle (st->dpy, st->win, st->graph_gc,
+                  boxx-1, boxy-1, boxw+2, boxh+2);
+
+  XCopyArea (st->dpy, st->win, st->win, st->graph_gc,
+             boxx+1, boxy, boxw-1, boxh, boxx, boxy);
+
+  XSetForeground (st->dpy, st->graph_gc, BlackPixelOfScreen (st->xgwa.screen));
+  XDrawLine (st->dpy, st->win, st->graph_gc,
+             boxx + boxw - 1, boxy,
+             boxx + boxw - 1, boxy + boxh);
+
+  XSetForeground (st->dpy, st->graph_gc, st->magenta);
+  XDrawPoint (st->dpy, st->win, st->graph_gc,
+              boxx + boxw - 1,
+              boxy + boxh - 1 - (int) (z * (boxh - 1)));
+}
+
+
+/* Draws a blinking box in what should be the upper left corner of the
+   device, as physically oriented. The box is taller than it is wide.
+ */
+static void
+testx11_show_orientation (struct testx11 *st)
+{
+#ifdef HAVE_MOBILE
+  int x, y;
+  int w = st->xgwa.width;
+  int h = st->xgwa.height;
+  int ww = 15;
+  int hh = ww*2;
+  static int tick = 0;
+  static int oo = -1;
+  int o = (int) current_device_rotation ();
+
+  if (o != oo) {
+//    fprintf (stderr,"ROT %d -> %d\n", oo, o);
+    oo = o;
+  }
+
+  switch (o) {
+  case    0: case  360: x = 0;    y = 0;    w = ww; h = hh; break;
+  case   90: case -270: x = 0;    y = h-ww; w = hh; h = ww; break;
+  case  -90: case  270: x = w-hh; y = 0;    w = hh; h = ww; break;
+  case  180: case -180: x = w-ww; y = h-hh; w = ww; h = hh; break;
+  default: return;
+  }
+
+  if (++tick > 20) tick = 0;
+
+  XSetForeground (st->dpy, st->graph_gc, 
+                  (tick > 10
+                   ? WhitePixelOfScreen (st->xgwa.screen)
+                   : BlackPixelOfScreen (st->xgwa.screen)));
+  XFillRectangle (st->dpy, st->win, st->graph_gc,
+                  x, y, w, h);
+#endif
+}
+
+
 static unsigned long
 testx11_draw (Display *dpy, Window win, void *st_raw)
 {
@@ -335,10 +533,7 @@ testx11_draw (Display *dpy, Window win, void *st_raw)
 # ifdef HAVE_JWXYZ
   Drawable t = win;
 # else
-  Drawable t =
-    st->mode == mode_welcome ||
-    st->mode == mode_images ||
-    st->mode == mode_copy ? win : st->backbuffer;
+  Drawable t = st->mode == mode_primitives ? st->backbuffer : win;
 # endif
   unsigned i;
 
@@ -347,6 +542,8 @@ testx11_draw (Display *dpy, Window win, void *st_raw)
 
   jwxyz_assert_display (dpy);
 
+  XSetWindowBackground (dpy, win, st->gray50);
+
   switch (st->mode)
   {
   case mode_primitives:
@@ -357,23 +554,23 @@ testx11_draw (Display *dpy, Window win, void *st_raw)
     XDrawPoint (dpy, t, st->thick_line_gc, 1, 0);
     XDrawPoint (dpy, t, st->thick_line_gc, 1, 1);
 
-    mini_rect (st, t, 2, 0);
-    mini_rect (st, t, 0, 2);
-    mini_rect (st, t, 4, 2);
-    mini_rect (st, t, 2, 4);
+    primitives_mini_rect (st, t, 2, 0);
+    primitives_mini_rect (st, t, 0, 2);
+    primitives_mini_rect (st, t, 4, 2);
+    primitives_mini_rect (st, t, 2, 4);
 
-    mini_rect (st, t, 30, -2);
-    mini_rect (st, t, 32, 0);
+    primitives_mini_rect (st, t, 30, -2);
+    primitives_mini_rect (st, t, 32, 0);
 
-    mini_rect (st, t, 30, h - 2);
-    mini_rect (st, t, 32, h);
+    primitives_mini_rect (st, t, 30, h - 2);
+    primitives_mini_rect (st, t, 32, h);
 
-    mini_rect (st, t, -2, 30);
-    mini_rect (st, t, 0, 32);
-    mini_rect (st, t, w - 2, 30);
-    mini_rect (st, t, w, 32);
+    primitives_mini_rect (st, t, -2, 30);
+    primitives_mini_rect (st, t, 0, 32);
+    primitives_mini_rect (st, t, w - 2, 30);
+    primitives_mini_rect (st, t, w, 32);
 
-    mini_rect (st, t, w / 2 + 4, h / 2 + 4);
+    primitives_mini_rect (st, t, w / 2 + 4, h / 2 + 4);
 
     XFillArc (dpy, t, st->copy_gc, 16, 16, 256, 256, 45 * 64, -135 * 64);
     /* XCopyArea(dpy, t, t, st->copy_gc, 48, 48, 128, 128, 64, 64); */
@@ -500,18 +697,23 @@ testx11_draw (Display *dpy, Window win, void *st_raw)
     /* Box 3 */
 
     {
-      XCopyArea (dpy, t, st->mini_pix, st->copy_gc, 104, 55, 16, 16, 0, 0);
-      /* XCopyArea (dpy, t, st->mini_pix, st->copy_gc, 105, 56, 14, 14, 1, 1);
-         XCopyArea (dpy, t, st->mini_pix, st->copy_gc, 1, 1, 14, 14, 1, 1);
+      XCopyArea (dpy, t, st->primitives_mini_pix, st->copy_gc,
+                 104, 55, 16, 16, 0, 0);
+      /* XCopyArea (dpy, t, st->primitives_mini_pix, st->copy_gc,
+                    105, 56, 14, 14, 1, 1);
+         XCopyArea (dpy, t, st->primitives_mini_pix, st->copy_gc,
+                    1, 1, 14, 14, 1, 1);
        */
 
       /* This point gets hidden. */
       XDrawPoint (dpy, t, st->copy_gc, 104 + 8, 55 + 8);
 
-      XDrawPoint (dpy, st->mini_pix, st->copy_gc, 0, 0);
-      XDrawPoint (dpy, st->mini_pix, st->copy_gc, 15, 15);
-      XDrawRectangle (dpy, st->mini_pix, st->copy_gc, 1, 1, 13, 13);
-      XCopyArea (dpy, st->mini_pix, t, st->copy_gc, 0, 0, 16, 16, 104, 55);
+      XDrawPoint (dpy, st->primitives_mini_pix, st->copy_gc, 0, 0);
+      XDrawPoint (dpy, st->primitives_mini_pix, st->copy_gc, 15, 15);
+      XDrawRectangle (dpy, st->primitives_mini_pix, st->copy_gc,
+                      1, 1, 13, 13);
+      XCopyArea (dpy, st->primitives_mini_pix, t, st->copy_gc,
+                 0, 0, 16, 16, 104, 55);
     }
 
     {
@@ -534,6 +736,13 @@ testx11_draw (Display *dpy, Window win, void *st_raw)
 
     /* if(w >= 9 && h >= 10) */
     {
+#ifdef HAVE_ANDROID
+      /* Draw below the status bar. */
+      const unsigned y = 64;
+#else
+      const unsigned y = 0;
+#endif
+
       Screen *screen = st->xgwa.screen;
       Visual *visual = st->xgwa.visual;
       Pixmap pixmap = XCreatePixmap (dpy, t, 3, 10,
@@ -541,21 +750,23 @@ testx11_draw (Display *dpy, Window win, void *st_raw)
       unsigned long cells = cells = st->rgb[0] | st->rgb[1] | st->rgb[2];
 
       {
-        XSetForeground (dpy, st->point_gc, st->salmon);
-        XDrawPoint(dpy, t, st->point_gc, 0, h - 1);
+        XSetForeground (dpy, st->images_point_gc, st->salmon);
+        XDrawPoint (dpy, t, st->images_point_gc, 0, h - 1);
+        XDrawLine (dpy, t, st->images_point_gc, 0, y - 1, 8, y - 1);
       }
 
-      test_pattern (st, t);
-      test_pattern (st, pixmap);
+      images_pattern (st, t, y);
+      images_pattern (st, pixmap, 0);
       /* Here's a good spot to verify that the pixmap contains the right colors
          at the top.
        */
-      copy_test (dpy, t, pixmap, st->copy_gc, 0, 6, cells);
+      images_copy_test (dpy, t, pixmap, st->copy_gc, y, 0, 6, cells);
+
+      XCopyArea (dpy, pixmap, t, st->copy_gc, 0, 0, 3, 10, 3, y);
 
-      XCopyArea (dpy, pixmap, t, st->copy_gc, 0, 0, 3, 10, 3, 0);
       {
         XImage *image = XGetImage (dpy, pixmap, 0, 0, 3, 10, cells, ZPixmap);
-        XPutImage (dpy, t, st->copy_gc, image, 0, 0, 6, 0, 3, 10);
+        XPutImage (dpy, t, st->copy_gc, image, 0, 0, 6, y, 3, 10);
         XDestroyImage (image);
       }
 
@@ -592,20 +803,44 @@ testx11_draw (Display *dpy, Window win, void *st_raw)
     if (use_copy)
     {
       GC gc = st->copy_gc;
-      XCopyArea (st->dpy, t, st->pix64, gc, 0, h - 64, 64, 64, 0, 0);
+      XCopyArea (st->dpy, t, st->copy_pix64, gc, 0, h - 64, 64, 64, 0, 0);
 
       XSetForeground (st->dpy, st->xor_gc, st->rgb[1]);
       XSetBackground (st->dpy, st->xor_gc, st->cyan);
 
-      /* XCopyArea (st->dpy, st->pix64, st->pix64, gc, 32, 32, 64, 64, 0, 0);
-         XCopyArea (st->dpy, st->pix64, t, gc, 0, 0, 64, 64, 4, h - 68);
+      /* XCopyArea (st->dpy, st->copy_pix64, st->copy_pix64, gc,
+                    32, 32, 64, 64, 0, 0);
+         XCopyArea (st->dpy, st->copy_pix64, t, gc, 0, 0, 64, 64, 4, h - 68);
        */
-      XCopyArea (st->dpy, st->pix64, t, gc, 32, 32, 128, 64, 0, h - 64);
+      XCopyArea (st->dpy, st->copy_pix64, t, gc, 32, 32, 128, 64, 0, h - 64);
     }
 
     break;
+
+  case mode_preserve:
+    backdrop (st, t);
+
+    if(!(st->frame % 10)) {
+      const unsigned r = 16;
+      unsigned n = st->frame / 10;
+      unsigned m = n >> 1;
+      XFillArc (st->dpy, st->preserve[n & 1],
+                m & 1 ? st->copy_gc : st->thick_line_gc,
+                NRAND(preserve_size) - r, NRAND(preserve_size) - r,
+                r * 2, r * 2, 0, 360 * 64);
+    }
+
+    XCopyArea (st->dpy, st->preserve[0], t, st->copy_gc, 0, 0,
+               preserve_size, preserve_size, 0, 0);
+    XCopyArea (st->dpy, st->preserve[1], t, st->copy_gc, 0, 0,
+               preserve_size, preserve_size, preserve_size, 0);
+    XCopyArea (st->dpy, st->preserve[1], t, st->copy_gc, 0, 0,
+               preserve_size, preserve_size,
+               w - preserve_size / 2, preserve_size);
+    break;
   }
 
+  /* Mode toggle buttons */
   for (i = 1; i != mode_count; ++i) {
     unsigned i0 = i - 1;
     char str[32];
@@ -615,7 +850,7 @@ testx11_draw (Display *dpy, Window win, void *st_raw)
     button_dims.width = button_size;
     button_dims.height = button_size;
     if (!st->mode)
-      XFillRectangles (dpy, t, st->black_gc, &button_dims, 1);
+      XFillRectangles (dpy, t, st->backdrop_black_gc, &button_dims, 1);
     XDrawRectangle (dpy, t, st->copy_gc, button_dims.x, button_dims.y,
                     button_dims.width, button_dims.height);
 
@@ -628,6 +863,9 @@ testx11_draw (Display *dpy, Window win, void *st_raw)
   if (t != win)
     XCopyArea (dpy, t, win, st->copy_gc, 0, 0, w, h, 0, 0);
 
+  testx11_graph_rotator (st);
+  testx11_show_orientation (st);
+
   ++st->frame;
   return 1000000 / 20;
 }
index cb5541de2e99b9bc12e3c697f558c7971a03e997..c2edeb7c90f2d21ae0f5dfa84378ae733cd8e528 100644 (file)
@@ -222,6 +222,7 @@ draw_thornbird(ModeInfo * mi)
 
        MI_IS_DRAWN(mi) = True;
 
+    if (MI_COUNT(mi) < 1) MI_COUNT(mi) = 1;
        if (hp->pointBuffer[erase] == NULL) {
                if ((hp->pointBuffer[erase] = (XPoint *) malloc(MI_COUNT(mi) *
                                sizeof (XPoint))) == NULL) {
index dda5ac8cf5081bfaf6c7598d52275cd73f009862..d0276f7825d02d1a0b3c709e120ced4515884e21 100644 (file)
@@ -61,7 +61,7 @@ static const char *truchet_defaults [] = {
   "*anim-delay:               100",
   "*anim-step-size:           3",
   "*randomize:               true",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation:           True",
 #endif
    0
index cc30b002a6740de4f3e985d0caa53563f9b2f2a7..4c434d0dff834a0308a57c3411fbeee3b3163585 100644 (file)
@@ -592,6 +592,7 @@ static void setupModel (struct state *st)
     leftX = (st->windowWidth - (st->columns * st->tileSize) + st->tileSize) / 2;
     topY = (st->windowHeight - (st->rows * st->tileSize) + st->tileSize) / 2;
 
+    if (st->tileCount < 1) st->tileCount = 1;
     st->tiles = calloc (st->tileCount, sizeof (Tile));
     st->sortedTiles = calloc (st->tileCount, sizeof (Tile *));
 
@@ -784,7 +785,7 @@ static const char *twang_defaults [] = {
 #else
     "*useSHM: False",
 #endif
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
   "*rotateImages:   True",
 #endif
index 4d816ff63adbf5271c5496a77c04f8e1347d7e0a..ca28c6bbfb7f2cbd542bd29e57c043e517f0be5d 100644 (file)
@@ -1212,7 +1212,7 @@ static const char *vermiculate_defaults[] = {
   "*fpsSolid:  true",
   "*speed: 0",
   "*instring: ",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
   0
index 80b16f6f263e6b75dc57b460e1e2d67d647a9e78..9646f6bd95dd67ca61fdf9acc4897f0854dbddcb 100755 (executable)
@@ -21,7 +21,7 @@ use diagnostics;
 use strict;
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my $version = q{ $Revision: 1.32 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/;
+my ($version) = ('$Revision: 1.33 $' =~ m/\s(\d[.\d]+)\s/s);
 
 my $verbose = 0;
 my $use_stdin = 0;
@@ -440,7 +440,7 @@ sub error($) {
 
 sub usage() {
   print STDERR "VidWhacker, Copyright (c) 2001 Jamie Zawinski <jwz\@jwz.org>\n";
-  print STDERR "            http://www.jwz.org/xscreensaver/";
+  print STDERR "            https://www.jwz.org/xscreensaver/";
   print STDERR "\n";
   print STDERR "usage: $0 [-display dpy] [-verbose]\n";
   print STDERR "\t\t[-root | -window | -window-id 0xXXXXX ]\n";
index 29fcb0ae1d6345c24c2aff3db79203820e26b754..1ac0c6cff2dabd4ee93d525f3fc22f1d5448b3a1 100644 (file)
@@ -239,6 +239,9 @@ wander_event (Display *dpy, Window window, void *closure, XEvent *event)
 static void
 wander_free (Display *dpy, Window window, void *closure)
 {
+  struct state *st = (struct state *) closure;
+  XFreeGC (st->dpy, st->context);
+  free (st);
 }
 
 static const char *wander_defaults [] =
@@ -253,7 +256,7 @@ static const char *wander_defaults [] =
     ".reset:      2500000",
     ".circles:    False",
     ".size:       1",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
     0
index 96e245e5613f3ecbd616e1b2b3f593daac2cfe37..2d342a5643d32cbd7a12894894436033c667ea5e 100755 (executable)
@@ -19,7 +19,7 @@
 #     webcollage --root --filter 'vidwhacker --stdin --stdout'
 #
 #
-# You can see this in action at http://www.jwz.org/webcollage/ --
+# You can see this in action at https://www.jwz.org/webcollage/ --
 # it auto-reloads about once a minute.  To make a page similar to
 # that on your own system, do this:
 #
@@ -57,10 +57,10 @@ use bytes;
 
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my ($version) = ('$Revision: 1.172 $' =~ m/\s(\d[.\d]+)\s/s);
+my ($version) = ('$Revision: 1.173 $' =~ m/\s(\d[.\d]+)\s/s);
 my $copyright = "WebCollage $version, Copyright (c) 1999-2015" .
     " Jamie Zawinski <jwz\@jwz.org>\n" .
-    "                  http://www.jwz.org/webcollage/\n";
+    "                  https://www.jwz.org/webcollage/\n";
 
 
 
index 0b621c8c3c5f1cd8caff3ffedfa649357f474004..e8bc2b255beddaf1ac81a925481f350f6f847fed 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2006-2014 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2006-2015 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
@@ -96,6 +96,7 @@ display_image (Display *dpy, Window window, state *st, const char *file)
   CGFloat h = [image size].height;
   if (w <= 1 || h <= 1) {
     fprintf (stderr, "webcollage: unparsable image \"%s\"\n", file);
+    [image release];
     return;
   }
 
@@ -124,26 +125,26 @@ open_pipe (state *st)
   char *filter  = get_string_resource  (st->dpy, "filter",  "Filter");
   char *filter2 = get_string_resource  (st->dpy, "filter2", "Filter2");
 
-  av[ac++] = "webcollage";
-  av[ac++] = "-cocoa";
+  av[ac++] = strdup ("webcollage");
+  av[ac++] = strdup ("-cocoa");
 
-  av[ac++] = "-size";
+  av[ac++] = strdup ("-size");
   sprintf (buf, "%dx%d", st->xgwa.width, st->xgwa.height);
   av[ac++] = strdup (buf);
 
-  av[ac++] = "-timeout"; sprintf (buf, "%d", timeout);
+  av[ac++] = strdup ("-timeout"); sprintf (buf, "%d", timeout);
   av[ac++] = strdup (buf);
-  av[ac++] = "-delay";   sprintf (buf, "%d", delay);
+  av[ac++] = strdup ("-delay");   sprintf (buf, "%d", delay);
   av[ac++] = strdup (buf);
-  av[ac++] = "-opacity"; sprintf (buf, "%.2f", opacity);
+  av[ac++] = strdup ("-opacity"); sprintf (buf, "%.2f", opacity);
   av[ac++] = strdup (buf);
 
   if (filter && *filter) {
-    av[ac++] = "-filter";
+    av[ac++] = strdup ("-filter");
     av[ac++] = filter;
   }
   if (filter2 && *filter2) {
-    av[ac++] = "-filter2";
+    av[ac++] = strdup ("-filter2");
     av[ac++] = filter2;
   }
 
@@ -207,6 +208,9 @@ open_pipe (state *st)
       }
     }
 
+  while (ac > 0)
+    free (av[--ac]);
+
   if (! st->pipe_fd) abort();
 
   st->pid = forked;
index 673e8b4260109165172325da8febdb57ca503990..19786ba129f3204bdc08e5a293bc0fec631a9801 100644 (file)
@@ -419,7 +419,7 @@ add_jpeg_comment (struct jpeg_compress_struct *cinfo)
     "    Generated by WebCollage: Exterminate All Rational Thought. \r\n"
     "    Copyright (c) 1999-%Y by Jamie Zawinski <jwz@jwz.org> \r\n"
     "\r\n"
-    "        http://www.jwz.org/webcollage/ \r\n"
+    "        https://www.jwz.org/webcollage/ \r\n"
     "\r\n"
     "    This is what the web looked like on %d %b %Y at %I:%M:%S %p %Z. \r\n"
     "\r\n";
index 5ad662520bf640e82ef0da88d7779754541ebf22..335aa3f65133fcec4fd971ad4adc635c2222c8fb 100644 (file)
@@ -121,7 +121,7 @@ If this option is specified, then instead of writing an image to the
 root window, two files will be created: "\fIbase\fP.html" and "\fIbase\fP.jpg".
 The JPEG will be the collage; the HTML file will include that image, and
 an image-map making the sub-images be linked to the pages on which they
-were found (just like \fIhttp://www.jwz.org/webcollage/\fP.)
+were found (just like \fIhttps://www.jwz.org/webcollage/\fP.)
 .TP 8
 .B \-filter \fIcommand\fP
 Filter all source images through this command.  The command must take
@@ -210,9 +210,9 @@ Animating GIFs are not supported: only the first frame will be used.
 .SH UPGRADES
 The latest version of webcollage can be found as a part of
 xscreensaver, at 
-.B http://www.jwz.org/xscreensaver/,
+.B https://www.jwz.org/xscreensaver/,
 or on the WebCollage page at 
-.B http://www.jwz.org/webcollage/.
+.B https://www.jwz.org/webcollage/.
 
 DriftNet:
 .B http://www.ex-parrot.com/~chris/driftnet/
index e643b28d1b7eab8a757fd189454c0ef27a744cb3..3525e498b134c5461d4a4d230332387c0b3b276e 100644 (file)
@@ -490,7 +490,7 @@ static const char *whirlwindwarp_defaults [] = {
   "*points:    400",
   "*tails:     8",
   "*meters:    false",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
   0
index 5ae36ed0e2c6f7c1ef43a6758361086f53258bcb..22c7ddd650908981b4002950a994c2b507312a35 100644 (file)
@@ -342,7 +342,7 @@ whirlygig_init (Display *dpy, Window window)
 
     st->dbuf = get_boolean_resource (st->dpy, "doubleBuffer", "Boolean");
 
-# ifdef HAVE_COCOA     /* Don't second-guess Quartz's double-buffering */
+# ifdef HAVE_JWXYZ     /* Don't second-guess Quartz's double-buffering */
     st->dbuf = False;
 # endif
 
@@ -382,7 +382,7 @@ whirlygig_init (Display *dpy, Window window)
     st->gcv.foreground = get_pixel_resource(st->dpy, st->xgwa.colormap, "background", "Background");
     st->bgc = XCreateGC (st->dpy, st->b, GCForeground, &st->gcv);
 
-#ifdef HAVE_COCOA  /* #### should turn off double-buffering instead */
+#ifdef HAVE_JWXYZ  /* #### should turn off double-buffering instead */
     jwxyz_XSetAntiAliasing (dpy, st->fgc, False);
     jwxyz_XSetAntiAliasing (dpy, st->bgc, False);
 #endif
@@ -503,11 +503,9 @@ whirlygig_draw (Display *dpy, Window window, void *closure)
     st->current_color = 0;
   for (wcount = 0; wcount < st->info->whirlies; wcount++) {
     int lcount; /* lcount is a counter for every line -- take note of the offsets changing */
-    int internal_time = st->current_time;
+    int internal_time = 0;
     int color_offset = (st->current_color + (st->info->color_modifier * wcount)) % NCOLORS;
-    if (st->current_time == 0)
-      internal_time = 0;
-    else
+    if (st->current_time != 0)
       /* I want the distance between whirlies to increase more each whirly */
       internal_time = st->current_time + (10 * wcount) + (wcount * wcount); 
     switch (st->xmode) {
index 4529d5d68b1f37eb0a61714af48287a5b7b845a8..c8cdfcdac746ad3d3b837958d89c7f5bacbb9c7b 100644 (file)
@@ -303,7 +303,7 @@ static void resizeWormhole( struct state *st, wormhole * worm )
        st->SCREEN_X = attr.width;
        st->SCREEN_Y = attr.height;
 
-# ifndef HAVE_COCOA    /* Don't second-guess Quartz's double-buffering */
+# ifndef HAVE_JWXYZ    /* Don't second-guess Quartz's double-buffering */
        XFreePixmap( st->dpy, worm->work );
        worm->work = XCreatePixmap( st->dpy, st->window, st->SCREEN_X, st->SCREEN_Y, attr.depth );
 # endif
@@ -323,7 +323,7 @@ static void initWormhole( struct state *st, wormhole * worm, Display * display,
        st->SCREEN_X = attr.width;
        st->SCREEN_Y = attr.height;
 
-# ifdef HAVE_COCOA     /* Don't second-guess Quartz's double-buffering */
+# ifdef HAVE_JWXYZ     /* Don't second-guess Quartz's double-buffering */
         worm->work = st->window;
 # else
        worm->work = XCreatePixmap( st->dpy, st->window, st->SCREEN_X, st->SCREEN_Y, attr.depth );
@@ -708,7 +708,7 @@ static const char *wormhole_defaults [] = {
   "*delay:     10000",
   "*zspeed:    10",
   "*stars:     20",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
 #endif
   0
index a10e517269e1ba68eed8449d13b945564986969d..1565c8927581b6c3f82319f4adc26b9ca099429e 100644 (file)
@@ -34,7 +34,7 @@
 # include <unistd.h>
 #endif
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # include <X11/Intrinsic.h> /* for XtDatabase in hack_resources() */
 #endif
 
@@ -238,8 +238,8 @@ static const char *xanalogtv_defaults [] = {
   ".background:                black",
   ".foreground:                white",
   "*delay:             5",
-  "*grabDesktopImages:  False",   /* HAVE_COCOA */
-  "*chooseRandomImages: True",    /* HAVE_COCOA */
+  "*grabDesktopImages:  False",   /* HAVE_JWXYZ */
+  "*chooseRandomImages: True",    /* HAVE_JWXYZ */
   ANALOGTV_DEFAULTS
   0,
 };
@@ -281,7 +281,7 @@ getticks(struct state *st)
 static void
 hack_resources (Display *dpy)
 {
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
   static int count = -1;
   count++;
 
@@ -301,7 +301,7 @@ hack_resources (Display *dpy)
       value.size = strlen(buf2);
       XrmPutResource (&db, buf1, "String", &value);
     }
-#endif /* HAVE_COCOA */
+#endif /* HAVE_JWXYZ */
 }
 
 
@@ -573,7 +573,7 @@ xanalogtv_draw (Display *dpy, Window window, void *closure)
   }
   analogtv_draw(st->tv, st->cs->noise_level, recs, rec_count);
 
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   return 0;
 #else
   return 5000;
index 0a3739b567b51af172a91b1e657d98c36b2045ae..2c1db6ef9b0fb79ff040fae2df4be76d12cf10a2 100644 (file)
@@ -611,11 +611,11 @@ FlamePasteData(struct state *st,
 static unsigned char *
 loadBitmap(struct state *st, int *w, int *h)
 {
+# ifdef HAVE_JWXYZ
+  const char *bitmap_name = "(default)"; /* #### always use builtin */
+# else
   char *bitmap_name = get_string_resource (st->dpy, "bitmap", "Bitmap");
-
-#ifdef HAVE_COCOA
-  bitmap_name = "(default)"; /* #### always use builtin */
-#endif /* HAVE_COCOA */
+# endif
   
   if (!bitmap_name ||
       !*bitmap_name ||
@@ -625,13 +625,13 @@ loadBitmap(struct state *st, int *w, int *h)
     {
       XImage *ximage;
       unsigned char *result, *o;
-      char *bits = (char *) malloc (sizeof(bob_bits));
+      unsigned char *bits = (unsigned char *) malloc (sizeof(bob_bits));
       int x, y;
       int scale = ((st->width > bob_width * 10) ? 2 : 1);
  
       memcpy (bits, bob_bits, sizeof(bob_bits));
-      ximage = XCreateImage (st->dpy, st->visual, 1, XYBitmap, 0, bits,
-                             bob_width, bob_height, 8, 0);
+      ximage = XCreateImage (st->dpy, st->visual, 1, XYBitmap, 0, 
+                             (char *) bits, bob_width, bob_height, 8, 0);
       ximage->byte_order = LSBFirst;
       ximage->bitmap_bit_order = LSBFirst;
       *w = ximage->width * scale;
@@ -644,7 +644,7 @@ loadBitmap(struct state *st, int *w, int *h)
       return result;
     }
   else  /* load a bitmap file */
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
     abort(); /* #### fix me */
 #else
    {
@@ -703,7 +703,7 @@ loadBitmap(struct state *st, int *w, int *h)
       *h = st->height;
       return result;
     }
-#endif /* !HAVE_COCOA */
+#endif /* !HAVE_JWXYZ */
 
   *w = 0;
   *h = 0;
index 2716f30184d9934161e0c5105a852d3af8958ae9..00994ac878d93763e22f2a28f69e00e473afda34 100644 (file)
@@ -19,9 +19,9 @@
 #include "xlockmoreI.h"
 #include "screenhack.h"
 
-#if !defined(HAVE_COCOA) && !defined(HAVE_ANDROID)
+#ifndef HAVE_JWXYZ
 # include <X11/Intrinsic.h>
-#endif /* !HAVE_COCOA */
+#endif /* !HAVE_JWXYZ */
 
 #define countof(x) (sizeof((x))/sizeof(*(x)))
 
@@ -157,7 +157,7 @@ xlockmore_setup (struct xscreensaver_function_table *xsft, void *arg)
   /* Put on the PROGCLASS.background/foreground resources. */
   s = (char *) malloc(50);
   *s = 0;
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
   strcpy (s, progclass);
 # endif
   strcat (s, ".background: black");
@@ -165,7 +165,7 @@ xlockmore_setup (struct xscreensaver_function_table *xsft, void *arg)
 
   s = (char *) malloc(50);
   *s = 0;
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
   strcpy (s, progclass);
 # endif
   strcat (s, ".foreground: white");
@@ -292,7 +292,7 @@ xlockmore_init (Display *dpy, Window window,
   mi->window = window;
   XGetWindowAttributes (dpy, window, &mi->xgwa);
   
-#if defined(HAVE_COCOA) || defined(HAVE_ANDROID)
+#ifdef HAVE_JWXYZ
   
 # if 0
   /* In Cocoa and Android-based xscreensaver, all hacks run in the
@@ -337,7 +337,7 @@ xlockmore_init (Display *dpy, Window window,
   /* Everybody gets motion events, just in case. */
   XSelectInput (dpy, window, (mi->xgwa.your_event_mask | PointerMotionMask));
 
-#endif /* !HAVE_COCOA */
+#endif /* !HAVE_JWXYZ */
   
   color.flags = DoRed|DoGreen|DoBlue;
   color.red = color.green = color.blue = 0;
@@ -351,7 +351,6 @@ xlockmore_init (Display *dpy, Window window,
 
   if (mono_p)
     {
-      static unsigned long pixels[2];
       static XColor colors[2];
     MONO:
       mi->npixels = 2;
@@ -361,8 +360,6 @@ xlockmore_init (Display *dpy, Window window,
       if (!mi->colors)
         mi->colors = (XColor *) 
           calloc (mi->npixels, sizeof (*mi->colors));
-      pixels[0] = mi->black;
-      pixels[1] = mi->white;
       colors[0].flags = DoRed|DoGreen|DoBlue;
       colors[1].flags = DoRed|DoGreen|DoBlue;
       colors[0].red = colors[0].green = colors[0].blue = 0;
index d477970f54f9cc2edd82e1981e7ee1ecc92750d6..5572580d8e6e4dfe226e1768cd3bbe978080451d 100644 (file)
@@ -115,7 +115,7 @@ ERROR!  Sorry, xlockmore.h requires ANSI C (gcc, for example.)
    In a Cocoa or Android world, we only define the prefixed symbol;
    the un-prefixed symbol does not exist.
  */
-#if defined(HAVE_COCOA) || defined(HAVE_ANDROID)
+#ifdef HAVE_MOBILE
 # define XSCREENSAVER_LINK(NAME)
 #else
 # define XSCREENSAVER_LINK(NAME) \
index 2d36cb9dde02a4b0fde963cc452c4e0648694660..cbd493794c194c607ba172dcaa13cfef1f684b1d 100644 (file)
@@ -43,7 +43,7 @@
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # include <X11/cursorfont.h> 
 #endif
 
@@ -78,7 +78,7 @@ static const char *xlyap_defaults [] = {
   "*delay:              10000",
   "*linger:             5",
   "*colors:             200",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation:     True",
 #endif
   0
@@ -161,7 +161,7 @@ typedef struct {
 #endif
 
 typedef struct {
-# ifndef HAVE_COCOA
+# ifndef HAVE_JWXYZ
   Cursor band_cursor;
 # endif
   double p_min, p_max, q_min, q_max;
@@ -827,7 +827,7 @@ Getkey(struct state *st, XKeyEvent *event)
   unsigned char key;
   int i;
   if (XLookupString(event, (char *)&key, sizeof(key), (KeySym *)0,
-                    (XComposeStatus *) 0) > 0)
+                    (XComposeStatus *) 0) > 0) {
 
     if (st->reset_countdown)
       st->reset_countdown = st->linger;
@@ -956,6 +956,7 @@ Getkey(struct state *st, XKeyEvent *event)
     case 'H': print_help(st); return True;
     default:  return False;
     }
+  }
 
   return False;
 }
index 04e96fb0d90c5f8562b8da1beedf668b22b9d599..adccb0c66dd091a696bcd9a2e903c5fca6fa81a5 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1999-2014 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1999-2015 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 <stdio.h>
 #include <sys/wait.h>
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
 # define HAVE_XPM
 #else
 # define DO_XBM     /* only do mono bitmaps under real X11 */
 #endif
 
-#ifndef HAVE_COCOA
+#ifndef HAVE_JWXYZ
 # include <X11/Intrinsic.h>
 #endif
 
@@ -461,25 +461,22 @@ static void
 init_trace (m_state *state)
 {
   char *s = get_string_resource (state->dpy, "tracePhone", "TracePhone");
-  char *s2, *s3;
-  int i;
+  const char *s2;
+  signed char *s3;
   if (!s)
     goto FAIL;
 
   state->tracing = (signed char *) malloc (strlen (s) + 1);
-  s3 = (char *) state->tracing;
+  s3 = state->tracing;
 
   for (s2 = s; *s2; s2++)
     if (*s2 >= '0' && *s2 <= '9')
-      *s3++ = *s2;
+      *s3++ = -*s2;
   *s3 = 0;
 
-  if (s3 == (char *) state->tracing)
+  if (s3 == state->tracing)
     goto FAIL;
 
-  for (i = 0; i < strlen((char *) state->tracing); i++)
-    state->tracing[i] = -state->tracing[i];
-
   state->glyph_map = decimal_encoding;
   state->nglyphs = countof(decimal_encoding);
 
index 5e13a18e22ed487de49ee384b3a7586238585769..635a5018d0ea686bd115aaf1257700cf856dac3e 100644 (file)
@@ -17,7 +17,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
 # include "jwxyz.h"
 #else
 # include <X11/Xlib.h>
index d36055de7608386a99912173d7309626dc4fb647..464fa7a601cc0f7a25c5e8487179a41237496fbd 100644 (file)
@@ -49,7 +49,7 @@ from the X Consortium.
 #include <sys/time.h>
 #include "screenhack.h"
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
 # define HAVE_GETTIMEOFDAY 1
 #endif
 
@@ -63,7 +63,7 @@ static const char *xrayswarm_defaults [] ={
        ".background:           black",
        "*delay:                20000",
        "*fpsSolid:             true",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
         "*ignoreRotation:       True",
 #endif
        0
@@ -302,7 +302,7 @@ static int initGraphics(struct state *st)
   
   xgcv.foreground=get_pixel_resource (st->dpy, cmap, "background", "Background");
   st->fgc[0]=XCreateGC(st->dpy, st->win, GCForeground|GCFunction,&xgcv);
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
   jwxyz_XSetAntiAliasing (st->dpy, st->fgc[0], False);
 #endif
   
@@ -310,7 +310,7 @@ static int initGraphics(struct state *st)
   if (mono_p) {
     xgcv.foreground=get_pixel_resource (st->dpy, cmap, "foreground", "Foreground");
     st->fgc[1]=XCreateGC(st->dpy,st->win,GCForeground|GCFunction,&xgcv);
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
     jwxyz_XSetAntiAliasing (st->dpy, st->fgc[1], False);
 #endif
     for (i=0;i<st->numColors;i+=2) st->fgc[i]=st->fgc[0];
@@ -324,14 +324,14 @@ static int initGraphics(struct state *st)
       XAllocColor(st->dpy,cmap,&color);
       xgcv.foreground=color.pixel;
       st->fgc[i] = XCreateGC(st->dpy, st->win, GCForeground | GCFunction,&xgcv);
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
       jwxyz_XSetAntiAliasing (st->dpy, st->fgc[i], False);
 #endif
     }
   }
   st->cgc = XCreateGC(st->dpy,st->win,GCForeground|GCFunction,&xgcv);
   XSetGraphicsExposures(st->dpy,st->cgc,False);
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
   jwxyz_XSetAntiAliasing (st->dpy, st->cgc, False);
 #endif
 
index 3c241fc36fdc7ee36051931a3bcf4b3f379b3017..e6504ff53d2bdcdbece86f1bc39ed156e085a460 100644 (file)
@@ -315,7 +315,7 @@ static const char *xspirograph_defaults [] = {
   "*subdelay:          20000",
   "*layers:            2",
   "*alwaysfinish:      false",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation:     True",
 #endif
   0
index 3c691aaff37063e0cdca44a4dac457d246e7fff6..99a652a54cd5f5d9abc9842fbece4bc37904e4f0 100644 (file)
@@ -25,8 +25,8 @@
 #define MINX 0.0
 #define MINY 0.0
 /* This should be *way* slower than the spotlight hack was */
-#define X_PERIOD 45000.0
-#define Y_PERIOD 36000.0
+#define X_PERIOD (45000.0 * 3)
+#define Y_PERIOD (36000.0 * 3)
 
 struct state {
   Display *dpy;
@@ -254,13 +254,13 @@ static const char *zoom_defaults[] = {
   "*lenses:      true",
   "*delay:       10000",
   "*duration:    120",
-  "*pixwidth:    10",
-  "*pixheight:   10",
+  "*pixwidth:    40",
+  "*pixheight:   40",
   "*pixspacex:   2",
   "*pixspacey:   2",
   "*lensoffsetx: 5",
   "*lensoffsety: 5",
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
   "*ignoreRotation: True",
   "*rotateImages:   True",
 #endif
diff --git a/jwxyz/Makefile.in b/jwxyz/Makefile.in
new file mode 100644 (file)
index 0000000..06993cf
--- /dev/null
@@ -0,0 +1,142 @@
+# utils/Makefile.in --- xscreensaver, Copyright (c) 1997-2010 Jamie Zawinski.
+# the `../configure' script generates `jwxyz/Makefile' from this file.
+
+# JWXYZ Is Not Xlib.
+#
+# But it's a bunch of function definitions that bear some resemblance to
+# Xlib and that kinda sorta implement Xlib in terms of the native graphics
+# substrate (Cocoa, OpenGL, GLES, Java).
+
+@SET_MAKE@
+.SUFFIXES:
+.SUFFIXES: .c .o
+
+srcdir         = @srcdir@
+VPATH          = @srcdir@
+prefix         = @prefix@
+datarootdir    = @datarootdir@
+
+CC             = @CC@
+CFLAGS         = @CFLAGS@
+DEFS           = @DEFS@
+
+DEPEND         = @DEPEND@
+DEPEND_FLAGS   = @DEPEND_FLAGS@
+DEPEND_DEFINES = @DEPEND_DEFINES@
+
+SHELL          = /bin/sh
+INSTALL                = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA   = @INSTALL_DATA@
+INSTALL_DIRS   = @INSTALL_DIRS@
+
+X_CFLAGS       = @X_CFLAGS@
+
+INCLUDES_1     = -I$(srcdir) -I..
+INCLUDES       = $(INCLUDES_1) @INCLUDES@
+
+SRCS           = jwxyz-android.c jwxyz-cocoa.m jwxyz-common.c jwxyz-gl.c \
+                 jwxyz-timers.c jwxyz.m jwzgles.c
+OBJS           = 
+HDRS           = jwxyz-android.h jwxyz-cocoa.h jwxyz-timers.h jwxyz.h \
+                 jwxyzI.h jwzgles.h jwzglesI.h
+EXTRAS         = README Makefile.in
+
+TARFILES       = $(EXTRAS) $(SRCS) $(HDRS) $(LOGOS)
+
+
+default: all
+all: $(OBJS)
+
+install:   install-program   install-man
+uninstall: uninstall-program uninstall-man
+
+install-strip:
+       $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install
+
+install-program:
+install-man:
+uninstall-program:
+uninstall-man:
+
+clean:
+       -rm -f *.o a.out core
+
+distclean: clean
+       -rm -f Makefile TAGS *~ "#"*
+
+# Adds all current dependencies to Makefile
+depend:
+       $(DEPEND) -s '# DO NOT DELETE: updated by make depend'              \
+       $(DEPEND_FLAGS) --                                                  \
+       $(INCLUDES) $(DEFS) $(DEPEND_DEFINES) $(CFLAGS) $(X_CFLAGS) --      \
+       $(SRCS)
+
+# Adds some dependencies to Makefile.in -- not totally accurate, but pretty
+# close.  This excludes dependencies on files in /usr/include, etc.  It tries
+# to include only dependencies on files which are themselves a part of this
+# package.
+distdepend::
+       @echo updating dependencies in `pwd`/Makefile.in... ;               \
+       $(DEPEND) -w 0 -f -                                                 \
+       -s '# DO NOT DELETE: updated by make distdepend' $(DEPEND_FLAGS) -- \
+       $(INCLUDES_1) $(DEFS) $(DEPEND_DEFINES) $(CFLAGS) $(X_CFLAGS) --    \
+       $(SRCS) 2>/dev/null |                                               \
+       sort -d |                                                           \
+       (                                                                   \
+         awk '/^# .*Makefile.in ---/,/^# DO .*distdepend/' < Makefile.in ; \
+         sed -e '/^#.*/d'                                                  \
+             -e 's@ \./@ @g;s@ /[^ ]*@@g;/^.*:$$/d'                        \
+             -e 's@ \([^$$]\)@ $$(srcdir)/\1@g'                            \
+             -e 's@ $$(srcdir)/\(.*config.h\)@ \1@g' ;                     \
+         echo ''                                                           \
+       ) > /tmp/distdepend.$$$$ &&                                         \
+       mv Makefile.in Makefile.in.bak &&                                   \
+       mv /tmp/distdepend.$$$$ Makefile.in
+
+TAGS: tags
+tags:
+       find $(srcdir) -name '*.[chly]' -print | xargs etags -a
+
+echo_tarfiles:
+       @echo $(TARFILES)
+
+
+# How we build object files in this directory.
+.c.o:
+       $(CC) -c $(INCLUDES) $(DEFS) $(CPPFLAGS) $(CFLAGS) $(X_CFLAGS) $<
+
+
+# Rules for generating the VMS makefiles on Unix, so that it doesn't have to
+# be done by hand...
+#
+VMS_AXP_COMPILE=$$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-])
+
+compile_axp.com: Makefile.in
+       @echo generating $@ from $<...  ;                                   \
+       ( ( for c in $(SRCS) vms-*.c ; do                                   \
+             c=`echo $$c | tr a-z A-Z` ;                                   \
+             echo "$(VMS_AXP_COMPILE) $$c" ;                               \
+            done ;                                                         \
+         ) | sort -d ;                                                     \
+          echo '$$ lib/cre utils.olb_axp' ;                                \
+         echo '$$ lib utils.olb_axp *.obj' ;                               \
+         echo '$$! delete/noconf *.obj;' ;                                 \
+        ) > $@
+
+compile_decc.com: compile_axp.com
+       @echo generating $@ from $<...  ;                                   \
+       sed 's/axp/decc/g' < $< > $@
+
+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
+
diff --git a/jwxyz/README b/jwxyz/README
new file mode 100644 (file)
index 0000000..7c350bb
--- /dev/null
@@ -0,0 +1,30 @@
+JWXYZ Is Not Xlib.
+
+But it's a bunch of function definitions that bear some resemblance to
+Xlib and that kinda sorta implement Xlib in terms of the native graphics
+substrate (Cocoa, OpenGL, GLES, Java).
+
+When porting XScreenSaver to other platforms, my goal is to keep a single
+code base that compiles for multiple platforms.  That is, I don't want to
+end up with two different files that implement "Attraction" using different
+APIs or different languages,
+
+Since the vast majority of xscreensaver was originally written in C for
+the vintage-1985 X11 API and the vintage-1992 OpenGL API, this presents
+something of a challenge.
+
+  1:  To do the MacOS port, I implemented X11 in terms of Cocoa.
+      That's what jwxyz.m is.
+
+  2:  To do the iOS port, I used that X11/Cocoa layer from #1, but also
+      had to implement OpenGL 1.1 in terms of OpenGLES 1.0.  That's what
+      jwzgles.c is.  I have some things to say about that.  You can
+      read it on my blog: http://jwz.org/b/yhM9
+
+  3:  To do the Android port, we used the OpenGL/OpenGLES layer from #2,
+      but implemented X11 in terms of OpenGL.  That's what jwxyz-gl.c,
+      jwxyz-common.c and jwxyz-android.c are.
+
+Perhaps some day we can re-target MacOS and iOS at the OpenGL port of X11
+instead of the Cocoa port of X11, and replace jwxyz.m with jwxyz-gl.c and
+jwxyz-cocoa.m.  That day has not yet arrived.
diff --git a/jwxyz/jwxyz-android.c b/jwxyz/jwxyz-android.c
new file mode 100644 (file)
index 0000000..420cd56
--- /dev/null
@@ -0,0 +1,1211 @@
+/* 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 file is three related things:
+ *
+ *   - It is the Android-specific C companion to jwxyz-gl.c;
+ *   - It is how C calls into Java to do things that OpenGL does not
+ *     have access to without Java-based APIs;
+ *   - 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>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <math.h>
+#include <setjmp.h>
+
+#include <GLES/gl.h>
+#include <jni.h>
+#include <android/log.h>
+#include <pthread.h>
+
+#include "screenhackI.h"
+#include "jwxyzI.h"
+#include "jwzglesI.h"
+#include "jwxyz-android.h"
+#include "textclient.h"
+#include "grabscreen.h"
+
+
+#define countof(x) (sizeof(x)/sizeof(*(x)))
+
+extern struct xscreensaver_function_table *xscreensaver_function_table;
+
+struct function_table_entry {
+  const char *progname;
+  struct xscreensaver_function_table *xsft;
+};
+
+#include "gen/function-table.h"
+
+struct event_queue {
+  XEvent event;
+  struct event_queue *next;
+};
+
+static void send_queued_events (struct running_hack *rh);
+
+const char *progname;
+const char *progclass;
+int mono_p = 0;
+
+static JavaVM *global_jvm;
+static jmp_buf jmp_target;
+
+static double current_rotation = 0;
+
+extern void check_gl_error (const char *type);
+
+void
+do_logv(int prio, const char *fmt, va_list args)
+{
+  __android_log_vprint(prio, "xscreensaver", fmt, args);
+
+  /* The idea here is that if the device/emulator dies shortly after a log
+     message, then waiting here for a short while should increase the odds
+     that adb logcat can pick up the message before everything blows up. Of
+     course, doing this means dumping a ton of messages will slow things down
+     significantly.
+  */
+# if 0
+  struct timespec ts;
+  ts.tv_sec = 0;
+  ts.tv_nsec = 25 * 1000000;
+  nanosleep(&ts, NULL);
+# endif
+}
+
+void Log(const char *fmt, ...)
+{
+  va_list args;
+  va_start (args, fmt);
+  Logv(fmt, args);
+  va_end (args);
+}
+
+/* Handle an abort on Android
+   TODO: Test that Android handles aborts properly
+ */
+void
+jwxyz_abort (const char *fmt, ...)
+{
+  /* Send error to Android device log */
+  if (!fmt || !*fmt)
+    fmt = "abort";
+
+  va_list args;
+  va_start (args, fmt);
+  do_logv(ANDROID_LOG_ERROR, fmt, args);
+  va_end (args);
+
+  char buf[10240];
+  va_start (args, fmt);
+  vsprintf (buf, fmt, args);
+  va_end (args);
+
+  JNIEnv *env;
+  (*global_jvm)->AttachCurrentThread (global_jvm, &env, NULL);
+
+  if (! (*env)->ExceptionOccurred(env)) {
+    // If there's already an exception queued, let's just go with that one.
+    // Else, queue a Java exception to be thrown.
+    (*env)->ThrowNew (env, (*env)->FindClass(env, "java/lang/RuntimeException"),
+                      buf);
+  }
+
+  // Nonlocal exit out of the jwxyz code.
+  longjmp (jmp_target, 1);
+}
+
+
+/* We get to keep live references to Java classes in use because the VM can
+   unload a class that isn't being used, which invalidates field and method
+   IDs.
+   https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/design.html#wp17074
+*/
+
+
+// #### only need one var I think
+static size_t classRefCount = 0;
+static jobject globalRefjwxyz, globalRefIterable, globalRefIterator,
+    globalRefMapEntry;
+
+static jfieldID runningHackField;
+static jmethodID iterableIterator, iteratorHasNext, iteratorNext;
+static jmethodID entryGetKey, entryGetValue;
+
+static pthread_mutex_t mutg = PTHREAD_MUTEX_INITIALIZER;
+
+static void screenhack_do_fps (Display *, Window, fps_state *, void *);
+
+
+// Initialized OpenGL and runs the screenhack's init function.
+//
+static void
+doinit (jobject jwxyz_obj, struct running_hack *rh, JNIEnv *env,
+        const struct function_table_entry *chosen, jint api, 
+        jobject defaults, jint w, jint h)
+{
+  if (setjmp (jmp_target)) goto END;  // Jump here from jwxyz_abort and return.
+
+  progname = chosen->progname;
+  rh->xsft = chosen->xsft;
+  rh->api = api;
+  rh->jni_env = env;
+  rh->jobject = jwxyz_obj;  // update this every time we call into C
+
+  (*env)->GetJavaVM (env, &global_jvm);
+
+# undef ya_rand_init  // This is the one and only place it is allowed
+  ya_rand_init (0);
+
+  Window wnd = (Window) calloc(1, sizeof(*wnd));
+  wnd->window.rh = rh;
+  wnd->frame.width = w;
+  wnd->frame.height = h;
+  wnd->type = WINDOW;
+
+  rh->egl_window_ctx = eglGetCurrentContext();
+  Assert(rh->egl_window_ctx != EGL_NO_CONTEXT, "doinit: EGL_NO_CONTEXT");
+
+  wnd->egl_surface = eglGetCurrentSurface(EGL_DRAW);
+  Assert(eglGetCurrentSurface(EGL_READ) == wnd->egl_surface,
+         "doinit: EGL_READ != EGL_DRAW");
+
+  rh->egl_display = eglGetCurrentDisplay();
+  Assert(rh->egl_display != EGL_NO_DISPLAY, "doinit: EGL_NO_DISPLAY");
+
+  EGLint config_attribs[3];
+  config_attribs[0] = EGL_CONFIG_ID;
+  eglQueryContext(rh->egl_display, rh->egl_window_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");
+
+  rh->egl_xlib_ctx = eglCreateContext(rh->egl_display, rh->egl_config,
+                                      EGL_NO_CONTEXT, NULL);
+  Assert(rh->egl_xlib_ctx != EGL_NO_CONTEXT, "doinit: EGL_NO_CONTEXT");
+  Assert(rh->egl_xlib_ctx != rh->egl_window_ctx, "Only one context here?!");
+
+  rh->window = wnd;
+  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
+
+  progclass = rh->xsft->progclass;
+
+  if ((*env)->ExceptionOccurred(env)) abort();
+  jwzgles_reset();
+
+  // This has to come before resource processing. It does not do graphics.
+  if (rh->xsft->setup_cb)
+    rh->xsft->setup_cb(rh->xsft, rh->xsft->setup_arg);
+
+  if ((*env)->ExceptionOccurred(env)) abort();
+
+  // Load the defaults.
+  // Unceremoniously stolen from [PrefsReader defaultsToDict:].
+
+  jclass     c = (*env)->GetObjectClass (env, defaults);
+  jmethodID  m = (*env)->GetMethodID (env, c, "put",
+                 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
+  if (! m) abort();
+  if ((*env)->ExceptionOccurred(env)) abort();
+
+  const struct { const char *key, *val; } default_defaults[] = {
+    { "doubleBuffer", "false" },
+    { "multiSample",  "false" },
+    { "texFontCacheSize", "30" },
+    { "textMode", "date" },
+    { "textURL",
+      "https://en.wikipedia.org/w/index.php?title=Special:NewPages&feed=rss" },
+    { "grabDesktopImages",  "true" },
+    { "chooseRandomImages", "true" },
+  };
+
+  for (int i = 0; i < countof(default_defaults); i++) {
+    const char *key = default_defaults[i].key;
+    const char *val = default_defaults[i].val;
+    char *key2 = malloc (strlen(progname) + strlen(key) + 2);
+    strcpy (key2, progname);
+    strcat (key2, "_");
+    strcat (key2, key);
+
+    // defaults.put(key2, val);
+    jstring jkey = (*env)->NewStringUTF (env, key2);
+    jstring jval = (*env)->NewStringUTF (env, val);
+    (*env)->CallObjectMethod (env, defaults, m, jkey, jval);
+    (*env)->DeleteLocalRef (env, jkey);
+    (*env)->DeleteLocalRef (env, jval);
+    // Log ("default0: \"%s\" = \"%s\"", key2, val);
+    free (key2);
+  }
+
+  const char *const *defs = rh->xsft->defaults;
+  while (*defs) {
+    char *line = strdup (*defs);
+    char *key, *val;
+    key = line;
+    while (*key == '.' || *key == '*' || *key == ' ' || *key == '\t')
+      key++;
+    val = key;
+    while (*val && *val != ':')
+      val++;
+    if (*val != ':') abort();
+    *val++ = 0;
+    while (*val == ' ' || *val == '\t')
+      val++;
+
+    unsigned long L = strlen(val);
+    while (L > 0 && (val[L-1] == ' ' || val[L-1] == '\t'))
+      val[--L] = 0;
+
+    char *key2 = malloc (strlen(progname) + strlen(key) + 2);
+    strcpy (key2, progname);
+    strcat (key2, "_");
+    strcat (key2, key);
+
+    // defaults.put(key2, val);
+    jstring jkey = (*env)->NewStringUTF (env, key2);
+    jstring jval = (*env)->NewStringUTF (env, val);
+    (*env)->CallObjectMethod (env, defaults, m, jkey, jval);
+    (*env)->DeleteLocalRef (env, jkey);
+    (*env)->DeleteLocalRef (env, jval);
+    // Log ("default: \"%s\" = \"%s\"", key2, val);
+    free (key2);
+    free (line);
+    defs++;
+  }
+
+  (*env)->DeleteLocalRef (env, c);
+  if ((*env)->ExceptionOccurred(env)) abort();
+
+ END: ;
+}
+
+
+#undef DEBUG_FPS
+
+// Animates a single frame of the current hack.
+//
+static void
+drawXScreenSaver (JNIEnv *env, struct running_hack *rh)
+{
+  double now = 0;
+# ifdef DEBUG_FPS
+  double fps0=0, fps1=0, fps2=0, fps3=0, fps4=0;
+# endif
+
+  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)
+    goto END;
+
+  /* Some of the screen hacks want to delay for long periods, and letting
+     the framework run the update function at 30 FPS when it really wanted
+     half a minute between frames would be bad.  So instead, we assume that
+     the framework's animation timer might fire whenever, but we only invoke
+     the screen hack's "draw frame" method when enough time has expired.
+  */
+  struct timeval tv;
+  gettimeofday (&tv, 0);
+  now = tv.tv_sec + (tv.tv_usec / 1000000.0);
+# ifdef DEBUG_FPS
+  fps0 = fps1 = fps2 = fps3 = fps4 = now;
+#endif
+  if (now < rh->next_frame_time) goto END;
+
+  prepare_context(rh);
+
+# ifdef DEBUG_FPS
+  gettimeofday (&tv, 0);
+  fps1 = tv.tv_sec + (tv.tv_usec / 1000000.0);
+# endif
+
+  // The init function might do graphics (e.g. XClearWindow) so it has
+  // to be run from inside onDrawFrame, not onSurfaceChanged.
+
+  if (! rh->initted_p) {
+
+    void *(*init_cb) (Display *, Window, void *) =
+      (void *(*)(Display *, Window, void *)) rh->xsft->init_cb;
+
+    unsigned int bg =
+      get_pixel_resource (rh->dpy, 0, "background", "Background");
+    XSetWindowBackground (rh->dpy, rh->window, bg);
+    XClearWindow (rh->dpy, rh->window);
+
+    rh->closure = init_cb (rh->dpy, rh->window, rh->xsft->setup_arg);
+    rh->initted_p = True;
+
+    rh->ignore_rotation_p =
+      (rh->api == API_XLIB &&
+       get_boolean_resource (rh->dpy, "ignoreRotation", "IgnoreRotation"));
+
+    if (get_boolean_resource (rh->dpy, "doFPS", "DoFPS")) {
+      rh->fpst = fps_init (rh->dpy, rh->window);
+      if (! rh->xsft->fps_cb) rh->xsft->fps_cb = screenhack_do_fps;
+    } else {
+      rh->fpst = NULL;
+      rh->xsft->fps_cb = 0;
+    }
+
+    if ((*env)->ExceptionOccurred(env)) abort();
+  }
+
+# ifdef DEBUG_FPS
+  gettimeofday (&tv, 0);
+  fps2 = tv.tv_sec + (tv.tv_usec / 1000000.0);
+# endif
+
+  // Apparently events don't come in on the drawing thread, and JNI flips
+  // out.  So we queue them there and run them here.
+  send_queued_events (rh);
+
+# ifdef DEBUG_FPS
+  gettimeofday (&tv, 0);
+  fps3 = tv.tv_sec + (tv.tv_usec / 1000000.0);
+# endif
+
+  unsigned long delay = rh->xsft->draw_cb(rh->dpy, rh->window, rh->closure);
+
+# ifdef __arm__
+  /* #### Until we work out why eglMakeCurrent is so slow on ARM. */
+  if (delay <= 40000) delay = 0;
+# endif
+
+
+# ifdef DEBUG_FPS
+  gettimeofday (&tv, 0);
+  fps4 = tv.tv_sec + (tv.tv_usec / 1000000.0);
+# endif
+  if (rh->fpst && rh->xsft->fps_cb)
+    rh->xsft->fps_cb (rh->dpy, rh->window, rh->fpst, rh->closure);
+
+  gettimeofday (&tv, 0);
+  now = tv.tv_sec + (tv.tv_usec / 1000000.0);
+  rh->next_frame_time = now + (delay / 1000000.0);
+
+ END: ;
+
+# ifdef DEBUG_FPS
+  Log("## FPS prep = %-6d init = %-6d events = %-6d draw = %-6d fps = %-6d\n",
+      (int) ((fps1-fps0)*1000000),
+      (int) ((fps2-fps1)*1000000),
+      (int) ((fps3-fps2)*1000000),
+      (int) ((fps4-fps3)*1000000),
+      (int) ( (now-fps4)*1000000));
+# endif
+}
+
+
+// Extracts the C structure that is stored in the jwxyz Java object.
+static struct running_hack *
+getRunningHack (JNIEnv *env, jobject thiz)
+{
+  jlong result = (*env)->GetLongField (env, thiz, runningHackField);
+  struct running_hack *rh = (struct running_hack *)(intptr_t)result;
+  if (rh)
+    rh->jobject = thiz;  // update this every time we call into C
+  return rh;
+}
+
+// Look up a class and mark it global in the provided variable.
+static jclass
+acquireClass (JNIEnv *env, const char *className, jobject *globalRef)
+{
+  jclass clazz = (*env)->FindClass(env, className);
+  *globalRef = (*env)->NewGlobalRef(env, clazz);
+  return clazz;
+}
+
+
+/* Note: to find signature strings for native methods:
+   cd ./project/xscreensaver/build/intermediates/classes/debug/
+   javap -s -p org.jwz.xscreensaver.jwxyz
+ */
+
+
+// Implementation of jwxyz's nativeInit Java method.
+//
+JNIEXPORT void JNICALL
+Java_org_jwz_xscreensaver_jwxyz_nativeInit (JNIEnv *env, jobject thiz,
+                                            jstring jhack, jint api,
+                                            jobject defaults,
+                                            jint w, jint h)
+{
+  pthread_mutex_lock(&mutg);
+
+  struct running_hack *rh = calloc(1, sizeof(struct running_hack));
+
+  if ((*env)->ExceptionOccurred(env)) abort();
+
+  // #### simplify
+  if (!classRefCount) {
+    jclass classjwxyz = (*env)->GetObjectClass(env, thiz);
+    globalRefjwxyz = (*env)->NewGlobalRef(env, classjwxyz);
+    runningHackField = (*env)->GetFieldID
+      (env, classjwxyz, "nativeRunningHackPtr", "J");
+    if ((*env)->ExceptionOccurred(env)) abort();
+
+    jclass classIterable =
+      acquireClass(env, "java/lang/Iterable", &globalRefIterable);
+    iterableIterator = (*env)->GetMethodID
+      (env, classIterable, "iterator", "()Ljava/util/Iterator;");
+    if ((*env)->ExceptionOccurred(env)) abort();
+
+    jclass classIterator =
+      acquireClass(env, "java/util/Iterator", &globalRefIterator);
+    iteratorHasNext = (*env)->GetMethodID
+      (env, classIterator, "hasNext", "()Z");
+    iteratorNext = (*env)->GetMethodID
+      (env, classIterator, "next", "()Ljava/lang/Object;");
+    if ((*env)->ExceptionOccurred(env)) abort();
+
+    jclass classMapEntry =
+      acquireClass(env, "java/util/Map$Entry", &globalRefMapEntry);
+    entryGetKey = (*env)->GetMethodID
+      (env, classMapEntry, "getKey", "()Ljava/lang/Object;");
+    entryGetValue = (*env)->GetMethodID
+      (env, classMapEntry, "getValue", "()Ljava/lang/Object;");
+    if ((*env)->ExceptionOccurred(env)) abort();
+  }
+
+  ++classRefCount;
+
+  // Store the C struct into the Java object.
+  (*env)->SetLongField(env, thiz, runningHackField, (jlong)(intptr_t)rh);
+
+  // TODO: Sort the list so binary search works.
+  const char *hack =(*env)->GetStringUTFChars(env, jhack, NULL);
+
+  int chosen = 0;
+  for (;;) {
+    if (!chosen == countof(function_table)) {
+      Log ("Hack not found: %s", hack);
+      abort();
+    }
+    if (!strcmp(function_table[chosen].progname, hack))
+      break;
+    chosen++;
+  }
+
+  (*env)->ReleaseStringUTFChars(env, jhack, hack);
+
+  doinit (thiz, rh, env, &function_table[chosen], api, defaults, w, h);
+
+  pthread_mutex_unlock(&mutg);
+}
+
+
+JNIEXPORT void JNICALL
+Java_org_jwz_xscreensaver_jwxyz_nativeResize (JNIEnv *env, jobject thiz,
+                                              jint w, jint h, jdouble rot)
+{
+  pthread_mutex_lock(&mutg);
+  if (setjmp (jmp_target)) goto END;  // Jump here from jwxyz_abort and return.
+
+  current_rotation = rot;
+
+  Log ("native rotation: %f", current_rotation);
+
+  struct running_hack *rh = getRunningHack(env, thiz);
+
+  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;
+    w = h;
+    h = swap;
+    wnd->frame.width  = w;
+    wnd->frame.height = h;
+  }
+
+  jwxyz_window_resized (rh->dpy);
+  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) {
+    glMatrixMode (GL_PROJECTION);
+    glRotatef (-rot, 0, 0, 1);
+    glMatrixMode (GL_MODELVIEW);
+  }
+
+ END:
+  pthread_mutex_unlock(&mutg);
+}
+
+
+JNIEXPORT void JNICALL
+Java_org_jwz_xscreensaver_jwxyz_nativeRender (JNIEnv *env, jobject thiz)
+{
+  pthread_mutex_lock(&mutg);
+  struct running_hack *rh = getRunningHack(env, thiz);
+  drawXScreenSaver(env, rh);
+  pthread_mutex_unlock(&mutg);
+}
+
+
+// TODO: Check Java side is calling this properly
+JNIEXPORT void JNICALL
+Java_org_jwz_xscreensaver_jwxyz_nativeDone (JNIEnv *env, jobject thiz)
+{
+  pthread_mutex_lock(&mutg);
+  if (setjmp (jmp_target)) goto END;  // Jump here from jwxyz_abort and return.
+
+  struct running_hack *rh = getRunningHack(env, thiz);
+
+  prepare_context (rh);
+
+  if (rh->initted_p)
+    rh->xsft->free_cb (rh->dpy, rh->window, rh->closure);
+  jwxyz_free_display(rh->dpy);
+
+  free(rh);
+  (*env)->SetLongField(env, thiz, runningHackField, 0);
+
+  --classRefCount;
+  if (!classRefCount) {
+    (*env)->DeleteGlobalRef(env, globalRefjwxyz);
+    (*env)->DeleteGlobalRef(env, globalRefIterable);
+    (*env)->DeleteGlobalRef(env, globalRefIterator);
+    (*env)->DeleteGlobalRef(env, globalRefMapEntry);
+  }
+
+ END:
+  pthread_mutex_unlock(&mutg);
+}
+
+
+static int
+send_event (struct running_hack *rh, XEvent *e)
+{
+  // Assumes mutex is locked and context is prepared
+
+  int *xP = 0, *yP = 0;
+  switch (e->xany.type) {
+  case ButtonPress: case ButtonRelease:
+    xP = &e->xbutton.x;
+    yP = &e->xbutton.y;
+    break;
+  case MotionNotify:
+    xP = &e->xmotion.x;
+    yP = &e->xmotion.y;
+    break;
+  }
+
+  // Rotate the coordinates in the events to match the pixels.
+  if (xP) {
+    if (ignore_rotation_p (rh->dpy)) {
+      Window win = XRootWindow (rh->dpy, 0);
+      int w = win->frame.width;
+      int h = win->frame.height;
+      int swap;
+      switch ((int) current_rotation) {
+      case 180: case -180:                             // #### untested
+        *xP = w - *xP;
+        *yP = h - *yP;
+        break;
+      case 90: case -270:
+        swap = *xP; *xP = *yP; *yP = swap;
+        *yP = h - *yP;
+        break;
+      case -90: case 270:                              // #### untested
+        swap = *xP; *xP = *yP; *yP = swap;
+        *xP = w - *xP;
+        break;
+      }
+    }
+
+    rh->window->window.last_mouse_x = *xP;
+    rh->window->window.last_mouse_y = *yP;
+  }
+
+  return (rh->xsft->event_cb
+          ? rh->xsft->event_cb (rh->dpy, rh->window, rh->closure, e)
+          : 0);
+}
+
+
+static void
+send_queued_events (struct running_hack *rh)
+{
+  struct event_queue *event, *next;
+  if (! rh->event_queue) return;
+  for (event = rh->event_queue, next = event->next;
+       event;
+       event = next, next = (event ? event->next : 0)) {
+    if (! send_event (rh, &event->event)) {
+      // #### flash the screen or something
+    }
+    free (event);
+  }
+  rh->event_queue = 0;
+}
+
+
+static void
+queue_event (JNIEnv *env, jobject thiz, XEvent *e)
+{
+  pthread_mutex_lock (&mutg);
+  struct running_hack *rh = getRunningHack (env, thiz);
+  struct event_queue *q = (struct event_queue *) malloc (sizeof(*q));
+  memcpy (&q->event, e, sizeof(*e));
+  q->next = 0;
+
+  // Put it at the end.
+  struct event_queue *oq;
+  for (oq = rh->event_queue; oq && oq->next; oq = oq->next)
+    ;
+  if (oq)
+    oq->next = q;
+  else
+    rh->event_queue = q;
+
+  pthread_mutex_unlock (&mutg);
+}
+
+
+JNIEXPORT void JNICALL
+Java_org_jwz_xscreensaver_jwxyz_sendButtonEvent (JNIEnv *env, jobject thiz,
+                                                 int x, int y, jboolean down)
+{
+  XEvent e;
+  memset (&e, 0, sizeof(e));
+  e.xany.type = (down ? ButtonPress : ButtonRelease);
+  e.xbutton.button = Button1;
+  e.xbutton.x = x;
+  e.xbutton.y = y;
+  queue_event (env, thiz, &e);
+}
+
+JNIEXPORT void JNICALL
+Java_org_jwz_xscreensaver_jwxyz_sendMotionEvent (JNIEnv *env, jobject thiz,
+                                                 int x, int y)
+{
+  XEvent e;
+  memset (&e, 0, sizeof(e));
+  e.xany.type = MotionNotify;
+  e.xmotion.x = x;
+  e.xmotion.y = y;
+  queue_event (env, thiz, &e);
+}
+
+JNIEXPORT void JNICALL
+Java_org_jwz_xscreensaver_jwxyz_sendKeyEvent (JNIEnv *env, jobject thiz,
+                                              jboolean down_p, 
+                                              int code, int mods)
+{
+  XEvent e;
+  memset (&e, 0, sizeof(e));
+  e.xkey.keycode = code;
+  e.xkey.state = code;
+  e.xany.type = (down_p ? KeyPress : KeyRelease);
+  queue_event (env, thiz, &e);
+  e.xany.type = KeyRelease;
+  queue_event (env, thiz, &e);
+}
+
+
+
+/***************************************************************************
+  Backend functions for jwxyz-gl.c
+ */
+
+void
+prepare_context (struct running_hack *rh)
+{
+  Window w = rh->window;
+  eglMakeCurrent (rh->egl_display, w->egl_surface, w->egl_surface,
+                  rh->egl_window_ctx);
+  rh->current_drawable = rh->window;
+}
+
+void
+jwxyz_bind_drawable (Display *dpy, Window w, Drawable d)
+{
+  struct running_hack *rh = w->window.rh;
+  JNIEnv *env = w->window.rh->jni_env;
+  if ((*env)->ExceptionOccurred(env)) abort();
+  if (rh->current_drawable != d) {
+    EGLContext ctx = d == w ? rh->egl_window_ctx : rh->egl_xlib_ctx;
+    eglMakeCurrent (rh->egl_display, d->egl_surface, d->egl_surface, ctx);
+    // Log("%p %p %p %p %p", rh->egl_display, d->egl_surface, ctx, w, d);
+    rh->current_drawable = d;
+    jwxyz_assert_gl ();
+
+    if (d != w) {
+      glViewport (0, 0, d->frame.width, d->frame.height);
+      jwxyz_set_matrices (dpy, d->frame.width, d->frame.height, False);
+    }
+  }
+}
+
+
+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)
+{
+#if 0
+  // Hilarious display corruption ahoy!
+  jwxyz_gl_copy_area_copy_tex_image (dpy, src, dst, gc, src_x, src_y,
+                                     width, height, dst_x, dst_y);
+#else
+  jwxyz_gl_copy_area_read_pixels (dpy, src, dst, gc, src_x, src_y,
+                                  width, height, dst_x, dst_y);
+#endif
+  jwxyz_assert_gl ();
+}
+
+
+void
+jwxyz_assert_drawable (Window main_window, Drawable d)
+{
+  check_gl_error("jwxyz_assert_drawable");
+}
+
+
+void
+jwxyz_assert_gl (void)
+{
+  check_gl_error("jwxyz_assert_gl");
+}
+
+
+Pixmap
+XCreatePixmap (Display *dpy, Drawable d,
+               unsigned int width, unsigned int height, unsigned int depth)
+{
+  // See also:
+  // https://web.archive.org/web/20140213220709/http://blog.vlad1.com/2010/07/01/how-to-go-mad-while-trying-to-render-to-a-texture/
+  // https://software.intel.com/en-us/articles/using-opengl-es-to-accelerate-apps-with-legacy-2d-guis
+  // https://www.khronos.org/registry/egl/extensions/ANDROID/EGL_ANDROID_image_native_buffer.txt
+
+  Window win = XRootWindow(dpy, 0);
+
+  Pixmap p = malloc(sizeof(*p));
+  p->type = PIXMAP;
+  p->frame.x = 0;
+  p->frame.y = 0;
+  p->frame.width = width;
+  p->frame.height = height;
+
+  Assert(depth == 1 || depth == visual_depth(NULL, NULL),
+         "XCreatePixmap: bad depth");
+  p->pixmap.depth = depth;
+
+  // Native EGL is Android 2.3/API 9. EGL in Java is available from API 1.
+  struct running_hack *rh = win->window.rh;
+  EGLint attribs[5];
+  attribs[0] = EGL_WIDTH;
+  attribs[1] = width;
+  attribs[2] = EGL_HEIGHT;
+  attribs[3] = 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");
+
+  jwxyz_bind_drawable (dpy, win, p);
+  glClearColor (frand(1), frand(1), frand(1), 0);
+  glClear (GL_COLOR_BUFFER_BIT);
+
+  return p;
+}
+
+
+int
+XFreePixmap (Display *d, Pixmap p)
+{
+  struct running_hack *rh = XRootWindow(d, 0)->window.rh;
+  if (rh->current_drawable == p)
+    rh->current_drawable = NULL;
+  eglDestroySurface(rh->egl_display, p->egl_surface);
+  free (p);
+  return 0;
+}
+
+
+double
+current_device_rotation (void)
+{
+  return current_rotation;
+}
+
+Bool
+ignore_rotation_p (Display *dpy)
+{
+  struct running_hack *rh = XRootWindow(dpy, 0)->window.rh;
+  return rh->ignore_rotation_p;
+}
+
+
+char *
+get_string_resource (Display *dpy, char *name, char *class)
+{
+  Window window = RootWindow (dpy, 0);
+  JNIEnv *env = window->window.rh->jni_env;
+  jobject obj = window->window.rh->jobject;
+
+  if ((*env)->ExceptionOccurred(env)) abort();
+  jstring jstr = (*env)->NewStringUTF (env, name);
+  jclass     c = (*env)->GetObjectClass (env, obj);
+  jmethodID  m = (*env)->GetMethodID (env, c, "getStringResource",
+                           "(Ljava/lang/String;)Ljava/lang/String;");
+  if ((*env)->ExceptionOccurred(env)) abort();
+
+  jstring jvalue = (m
+                  ? (*env)->CallObjectMethod (env, obj, m, jstr)
+                  : NULL);
+  (*env)->DeleteLocalRef (env, c);
+  (*env)->DeleteLocalRef (env, jstr);
+  char *ret = 0;
+  if (jvalue) {
+    const char *cvalue = (*env)->GetStringUTFChars (env, jvalue, 0);
+    ret = strdup (cvalue);
+    (*env)->ReleaseStringUTFChars (env, jvalue, cvalue);
+  }
+
+  Log("pref %s = %s", name, (ret ? ret : "(null)"));
+  return ret;
+}
+
+
+/* Returns the contents of the URL. */
+char *
+textclient_mobile_url_string (Display *dpy, const char *url)
+{
+  Window window = RootWindow (dpy, 0);
+  JNIEnv *env = window->window.rh->jni_env;
+  jobject obj = window->window.rh->jobject;
+
+  jstring jstr  = (*env)->NewStringUTF (env, url);
+  jclass      c = (*env)->GetObjectClass (env, obj);
+  jmethodID   m = (*env)->GetMethodID (env, c, "loadURL",
+                            "(Ljava/lang/String;)Ljava/nio/ByteBuffer;");
+  if ((*env)->ExceptionOccurred(env)) abort();
+  jobject buf = (m
+                 ? (*env)->CallObjectMethod (env, obj, m, jstr)
+                 : NULL);
+  (*env)->DeleteLocalRef (env, c);
+  (*env)->DeleteLocalRef (env, jstr);
+
+  char *body = (char *) (buf ? (*env)->GetDirectBufferAddress (env, buf) : 0);
+  char *body2;
+  if (body) {
+    int L = (*env)->GetDirectBufferCapacity (env, buf);
+    body2 = malloc (L + 1);
+    memcpy (body2, body, L);
+    body2[L] = 0;
+  } else {
+    body2 = strdup ("ERROR");
+  }
+
+  if (buf)
+    (*env)->DeleteLocalRef (env, buf);
+
+  return body2;
+}
+
+
+void *
+jwxyz_load_native_font (Display *dpy, const char *name,
+                        char **native_name_ret, float *size_ret,
+                        int *ascent_ret, int *descent_ret)
+{
+  Window window = RootWindow (dpy, 0);
+  JNIEnv *env = window->window.rh->jni_env;
+  jobject obj = window->window.rh->jobject;
+
+  jstring jstr = (*env)->NewStringUTF (env, name);
+  jclass     c = (*env)->GetObjectClass (env, obj);
+  jmethodID  m = (*env)->GetMethodID (env, c, "loadFont",
+                           "(Ljava/lang/String;)[Ljava/lang/Object;");
+  if ((*env)->ExceptionOccurred(env)) abort();
+
+  jobjectArray array = (m
+                        ? (*env)->CallObjectMethod (env, obj, m, jstr)
+                        : NULL);
+  (*env)->DeleteLocalRef (env, c);
+  (*env)->DeleteLocalRef (env, jstr);
+  jstr = 0;
+
+  if (array) {
+    jobject font = (*env)->GetObjectArrayElement (env, array, 0);
+    jobject name = (jstring) ((*env)->GetObjectArrayElement (env, array, 1));
+    jobject size = (*env)->GetObjectArrayElement (env, array, 2);
+    jobject asc  = (*env)->GetObjectArrayElement (env, array, 3);
+    jobject desc = (*env)->GetObjectArrayElement (env, array, 4);
+    if ((*env)->ExceptionOccurred(env)) abort();
+
+    const char *cname = (*env)->GetStringUTFChars (env, name, 0);
+    *native_name_ret = strdup (cname);
+    (*env)->ReleaseStringUTFChars (env, name, cname);
+
+    c = (*env)->GetObjectClass(env, font);
+    m = (*env)->GetMethodID (env, c, "longValue", "()J");
+    long font_id = (*env)->CallLongMethod (env, font, m);
+    if ((*env)->ExceptionOccurred(env)) abort();
+
+    c = (*env)->GetObjectClass(env, size);
+    m = (*env)->GetMethodID (env, c, "floatValue", "()F");
+    if ((*env)->ExceptionOccurred(env)) abort();
+
+    *size_ret    =       (*env)->CallFloatMethod (env, size, m);
+    *ascent_ret  = (int) (*env)->CallFloatMethod (env, asc,  m);
+    *descent_ret = (int) (*env)->CallFloatMethod (env, desc, m);
+
+    return (void *) font_id;
+  } else {
+    return 0;
+  }
+}
+
+
+void
+jwxyz_release_native_font (Display *dpy, void *native_font)
+{
+  Window window = RootWindow (dpy, 0);
+  JNIEnv *env = window->window.rh->jni_env;
+  jobject obj = window->window.rh->jobject;
+  if ((*env)->ExceptionOccurred(env)) abort();
+  jclass    c = (*env)->GetObjectClass (env, obj);
+  jmethodID m = (*env)->GetMethodID (env, c, "releaseFont", "(J)V");
+  (*env)->CallVoidMethod (env, obj, m, (jobject) native_font);
+  if ((*env)->ExceptionOccurred(env)) abort();
+}
+
+
+/* If the local reference table fills up, use this to figure out where
+   you missed a call to DeleteLocalRef. */
+/*
+static void dump_reference_tables(JNIEnv *env)
+{
+  jclass c = (*env)->FindClass(env, "dalvik/system/VMDebug");
+  jmethodID m = (*env)->GetStaticMethodID (env, c, "dumpReferenceTables",
+                                           "()V");
+  (*env)->CallStaticVoidMethod (env, c, m);
+  (*env)->DeleteLocalRef (env, c);
+}
+*/
+
+
+// Returns the metrics of the multi-character, single-line UTF8 or Latin1
+// string.  If pixmap_ret is provided, also renders the text.
+//
+void
+jwxyz_render_text (Display *dpy, void *native_font,
+                   const char *str, size_t len, int utf8,
+                   XCharStruct *cs, char **pixmap_ret)
+{
+  Window window = RootWindow (dpy, 0);
+  JNIEnv *env = window->window.rh->jni_env;
+  jobject obj = window->window.rh->jobject;
+
+  char *s2;
+
+  if (utf8) {
+    s2 = malloc (len + 1);
+    memcpy (s2, str, len);
+    s2[len] = 0;
+  } else {     // Convert Latin1 to UTF8
+    s2 = malloc (len * 2 + 1);
+    unsigned char *s3 = (unsigned char *) s2;
+    int i;
+    for (i = 0; i < len; i++) {
+      unsigned char c = ((unsigned char *) str)[i];
+      if (! (c & 0x80)) {
+        *s3++ = c;
+      } else {
+        *s3++ = (0xC0 | (0x03 & (c >> 6)));
+        *s3++ = (0x80 | (0x3F & c));
+      }
+    }
+    *s3 = 0;
+  }
+
+  jstring jstr  = (*env)->NewStringUTF (env, s2);
+  jclass      c = (*env)->GetObjectClass (env, obj);
+  jmethodID   m = (*env)->GetMethodID (env, c, "renderText",
+                            "(JLjava/lang/String;Z)Ljava/nio/ByteBuffer;");
+  if ((*env)->ExceptionOccurred(env)) abort();
+  jobject buf =
+    (m
+     ? (*env)->CallObjectMethod (env, obj, m,
+                                 (jlong) (long) native_font,
+                                 jstr,
+                                 (pixmap_ret ? JNI_TRUE : JNI_FALSE))
+     : NULL);
+  (*env)->DeleteLocalRef (env, c);
+  (*env)->DeleteLocalRef (env, jstr);
+  free (s2);
+
+  if ((*env)->ExceptionOccurred(env)) abort();
+  unsigned char *bits = (unsigned char *)
+    (buf ? (*env)->GetDirectBufferAddress (env, buf) : 0);
+  if (bits) {
+    int i = 0;
+    int L = (*env)->GetDirectBufferCapacity (env, buf);
+    if (L < 10) abort();
+    cs->lbearing = (bits[i] << 8) | (bits[i+1] & 0xFF); i += 2;
+    cs->rbearing = (bits[i] << 8) | (bits[i+1] & 0xFF); i += 2;
+    cs->width    = (bits[i] << 8) | (bits[i+1] & 0xFF); i += 2;
+    cs->ascent   = (bits[i] << 8) | (bits[i+1] & 0xFF); i += 2;
+    cs->descent  = (bits[i] << 8) | (bits[i+1] & 0xFF); i += 2;
+
+    if (pixmap_ret) {
+      char *pix = malloc (L - i);
+      if (! pix) abort();
+      memcpy (pix, bits + i, L - i);
+      *pixmap_ret = pix;
+    }
+  } else {
+    memset (cs, 0, sizeof(*cs));
+    if (pixmap_ret)
+      *pixmap_ret = 0;
+  }
+
+  if (buf)
+    (*env)->DeleteLocalRef (env, buf);
+}
+
+
+/* Called from utils/grabclient.c */
+char *
+jwxyz_load_random_image (Display *dpy,
+                         int *width_ret, int *height_ret,
+                         char **name_ret)
+{
+  Window window = RootWindow (dpy, 0);
+  struct running_hack *rh = window->window.rh;
+  JNIEnv *env = rh->jni_env;
+  jobject obj = rh->jobject;
+
+  Bool images_p =
+    get_boolean_resource (rh->dpy, "chooseRandomImages", "ChooseRandomImages");
+  Bool grab_p =
+    get_boolean_resource (rh->dpy, "grabDesktopImages", "GrabDesktopImages");
+  Bool rotate_p =
+    get_boolean_resource (rh->dpy, "rotateImages", "RotateImages");
+
+  if (!images_p && !grab_p)
+    return 0;
+
+  if (grab_p && images_p) {
+    grab_p = !(random() & 5);    /* if both, screenshot 1/5th of the time */
+    images_p = !grab_p;
+  }
+
+  jclass      c = (*env)->GetObjectClass (env, obj);
+  jmethodID   m = (*env)->GetMethodID (env, c, 
+                                       (grab_p
+                                        ? "getScreenshot"
+                                        : "loadRandomImage"),
+                                       "(IIZ)Ljava/nio/ByteBuffer;");
+  if ((*env)->ExceptionOccurred(env)) abort();
+  jobject buf = (m
+                 ? (*env)->CallObjectMethod (env, obj, m,
+                                             window->frame.width,
+                                             window->frame.height,
+                                             (rotate_p ? JNI_TRUE : JNI_FALSE))
+                 : NULL);
+  (*env)->DeleteLocalRef (env, c);
+
+  unsigned char *bits = (unsigned char *)
+    (buf ? (*env)->GetDirectBufferAddress (env, buf) : 0);
+
+  if (bits) {
+    int i = 0;
+    int L = (*env)->GetDirectBufferCapacity (env, buf);
+    if (L < 100) abort();
+    int width  = (bits[i] << 8) | (bits[i+1] & 0xFF); i += 2;
+    int height = (bits[i] << 8) | (bits[i+1] & 0xFF); i += 2;
+    char *name = (char *) bits + i;
+    int L2 = strlen (name);
+    i += L2 + 1;
+    if (width * height * 4 != L - i) abort();
+    char *pix = malloc (L - i);
+    if (! pix) abort();
+    memcpy (pix, bits + i, L - i);
+    *width_ret  = width;
+    *height_ret = height;
+    *name_ret   = strdup (name);
+    return (char *) pix;
+  }
+
+  if (buf)
+    (*env)->DeleteLocalRef (env, buf);
+
+  return 0;
+}
+
+#endif /* HAVE_ANDROID */
diff --git a/jwxyz/jwxyz-android.h b/jwxyz/jwxyz-android.h
new file mode 100644 (file)
index 0000000..949531f
--- /dev/null
@@ -0,0 +1,115 @@
+/* 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.
+ */
+
+#ifndef __JWXYZ_ANDROID_H__
+#define __JWXYZ_ANDROID_H__
+
+#include "jwxyz.h"
+#include "../hacks/fps.h"
+
+#include <android/log.h>
+#include <EGL/egl.h>
+#include <jni.h>
+
+/* Keep synchronized with check-configs.pl and jwxyz.java. */
+#define API_XLIB 0
+#define API_GL   1
+
+struct running_hack {
+  struct xscreensaver_function_table *xsft;
+  jint api;
+  Display *dpy;
+  Window window;
+  fps_state *fpst;
+  void *closure;
+  JNIEnv *jni_env;
+  jobject jobject;
+
+  EGLDisplay egl_display;
+  EGLConfig egl_config;
+  EGLContext egl_window_ctx, egl_xlib_ctx;
+  Drawable current_drawable;
+  Bool ignore_rotation_p;
+
+  unsigned long frame_count;
+  Bool initted_p;
+  double next_frame_time;  // time_t in milliseconds of when to tick the frame
+  struct event_queue *event_queue;
+};
+
+struct jwxyz_Drawable {
+  enum { WINDOW, PIXMAP } type;
+  XRectangle frame;
+  EGLSurface egl_surface;
+  union {
+    struct {
+      struct running_hack *rh;
+      int last_mouse_x, last_mouse_y;
+    } window;
+    struct {
+      int depth;
+    } pixmap;
+  };
+};
+
+extern void do_logv(int prio, const char *fmt, va_list args);
+
+extern void Log(const char *format, ...); // TODO: GCC can verify printf strings.
+#define Logv(format, args) (do_logv(ANDROID_LOG_INFO, format, args))
+
+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, jint api,
+                                            jobject defaults,
+                                            jint w, jint h);
+
+JNIEXPORT void JNICALL
+Java_org_jwz_xscreensaver_jwxyz_nativeResize (JNIEnv *, jobject thiz,
+                                              jint w, jint h, jdouble rot);
+
+JNIEXPORT void JNICALL
+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);
+
+JNIEXPORT void JNICALL
+Java_org_jwz_xscreensaver_jwxyz_sendMotionEvent (JNIEnv *, jobject thiz,
+                                                 int x, int y);
+
+JNIEXPORT void JNICALL
+Java_org_jwz_xscreensaver_jwxyz_sendKeyEvent (JNIEnv *, jobject thiz,
+                                              jboolean down_p,
+                                              int code, int mods);
+
+#endif // __JWXYZ_ANDROID_H__
diff --git a/jwxyz/jwxyz-cocoa.h b/jwxyz/jwxyz-cocoa.h
new file mode 100644 (file)
index 0000000..6c57577
--- /dev/null
@@ -0,0 +1,96 @@
+/* xscreensaver, Copyright (c) 1991-2015 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.
+ */
+
+#ifndef __JWXYZ_COCOA_H__
+#define __JWXYZ_COCOA_H__
+
+#import "XScreenSaverView.h"
+
+#ifdef USE_IPHONE
+# import <UIKit/UIKit.h>
+# define NSView           UIView
+# define NSOpenGLContext  EAGLContext
+#endif
+
+#ifdef JWXYZ_QUARTZ
+
+struct jwxyz_Drawable {
+  enum { WINDOW, PIXMAP } type;
+  CGContextRef cgc;
+  CGImageRef cgi;
+  XRectangle frame;
+  union {
+    struct {
+      XScreenSaverView *view;
+      int last_mouse_x, last_mouse_y;
+    } window;
+    struct {
+      int depth;
+      void *cgc_buffer;                // the bits to which CGContextRef renders
+    } pixmap;
+  };
+};
+
+#elif defined JWXYZ_GL
+
+struct jwxyz_Drawable {
+  enum { WINDOW, PIXMAP } type;
+  /* OS X: Contexts are unique for each pixmap, 'cause life is hectic. (OS X
+           appears to dislike it when you attach different pbuffers to the
+           same context one after the other, apparently.) The Window has this
+           CFRetained because of garbage collection. For both Pixmaps and
+           Windows, CFRelease this when done.
+     iOS:  ogl_ctx here is set to either XScreenSaverView.ogl_ctx or
+           XRootWindow()->window.ogl_ctx_pixmap. No garbage collection antics
+           here, so no need to CFRetain anything. Plus, if a screenhack leaks
+           a Pixmap (and they do that all the time), ogl_ctx_pixmap will also
+           get leaked if a Pixmap CFRetains this.
+   */
+  NSOpenGLContext *ogl_ctx;      // OpenGL rendering context (OS X)
+# ifdef USE_IPHONE
+  // TODO: Also on OS X as extensions.
+  GLuint gl_framebuffer, gl_renderbuffer;
+# endif // USE_IPHONE
+  CGImageRef cgi;
+  XRectangle frame;
+  union {
+    struct {
+      XScreenSaverView *view;
+      int last_mouse_x, last_mouse_y;
+      struct jwxyz_Drawable *current_drawable;
+# ifndef USE_IPHONE
+      NSOpenGLPixelFormat *pixfmt;
+      GLint virtual_screen;
+# else // USE_IPHONE
+      NSOpenGLContext *ogl_ctx_pixmap;
+# endif
+    } window;
+    struct {
+      int depth;
+# ifndef USE_IPHONE
+      NSOpenGLPixelBuffer *gl_pbuffer;
+      // GLuint blit_texture; // TODO: For blitting from Pbuffers
+# endif
+    } pixmap;
+  };
+};
+
+#endif // JWXYZ_GL
+
+#ifdef USE_IPHONE
+extern void create_framebuffer (GLuint *gl_framebuffer,
+                                GLuint *gl_renderbuffer);
+extern void check_framebuffer_status (void);
+#endif // USE_IPHONE
+
+#define jwxyz_window_view(w) ((w)->window.view)
+
+#endif
diff --git a/jwxyz/jwxyz-cocoa.m b/jwxyz/jwxyz-cocoa.m
new file mode 100644 (file)
index 0000000..3b6bf41
--- /dev/null
@@ -0,0 +1,577 @@
+/* xscreensaver, Copyright (c) 1991-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.
+ */
+
+/* JWXYZ Is Not Xlib.
+
+   But it's a bunch of function definitions that bear some resemblance to
+   Xlib and that do Cocoa-ish or OpenGL-ish things that bear some resemblance
+   to the things that Xlib might have done.
+
+   This code is used by both the original jwxyz.m and the new jwxyz-gl.c.
+ */
+
+#import "jwxyzI.h"
+#import "jwxyz-cocoa.h"
+
+#include <stdarg.h>
+
+#ifdef USE_IPHONE
+# import <OpenGLES/ES1/gl.h>
+# import <OpenGLES/ES1/glext.h>
+# define NSOpenGLContext EAGLContext
+#endif
+
+/* OS X/iOS-specific JWXYZ implementation. */
+
+/* Instead of calling abort(), throw a real exception, so that
+   XScreenSaverView can catch it and display a dialog.
+ */
+void
+jwxyz_abort (const char *fmt, ...)
+{
+  char s[10240];
+  if (!fmt || !*fmt)
+    strcpy (s, "abort");
+  else
+    {
+      va_list args;
+      va_start (args, fmt);
+      vsprintf (s, fmt, args);
+      va_end (args);
+    }
+  [[NSException exceptionWithName: NSInternalInconsistencyException
+                reason: [NSString stringWithCString: s
+                                  encoding:NSUTF8StringEncoding]
+                userInfo: nil]
+    raise];
+  abort();  // not reached
+}
+
+
+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)
+{
+# ifdef USE_IPHONE
+
+  xvpos->x = 0;
+  xvpos->y = 0;
+
+  if (xp) {
+    xp->x = w->window.last_mouse_x;
+    xp->y = w->window.last_mouse_y;
+  }
+
+# else  // !USE_IPHONE
+
+  NSWindow *nsw = [w->window.view window];
+
+  // get bottom left of window on screen, from bottom left
+
+# if (MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_6)
+  NSRect rr1 = [w->window.view convertRect: NSMakeRect(0,0,0,0) toView:nil];
+  NSRect rr2 = [nsw convertRectToScreen: rr1];
+  NSPoint wpos = NSMakePoint (rr2.origin.x - rr1.origin.x,
+                              rr2.origin.y - rr1.origin.y);
+# else
+  // deprecated as of 10.7
+  NSPoint wpos = [nsw convertBaseToScreen: NSMakePoint(0,0)];
+# endif
+
+
+  // get bottom left of view on window, from bottom left
+  NSPoint vpos;
+  vpos.x = vpos.y = 0;
+  vpos = [w->window.view convertPoint:vpos toView:[nsw contentView]];
+
+  // get bottom left of view on screen, from bottom left
+  vpos.x += wpos.x;
+  vpos.y += wpos.y;
+
+  // get top left of view on screen, from bottom left
+  vpos.y += w->frame.height;
+
+  // get top left of view on screen, from top left
+  NSArray *screens = [NSScreen screens];
+  NSScreen *screen = (screens && [screens count] > 0
+                      ? [screens objectAtIndex:0]
+                      : [NSScreen mainScreen]);
+  NSRect srect = [screen frame];
+  vpos.y = srect.size.height - vpos.y;
+
+  xvpos->x = vpos.x;
+  xvpos->y = vpos.y;
+
+  if (xp) {
+    // get the mouse position on window, from bottom left
+    NSEvent *e = [NSApp currentEvent];
+    NSPoint p = [e locationInWindow];
+
+    // get mouse position on screen, from bottom left
+    p.x += wpos.x;
+    p.y += wpos.y;
+
+    // get mouse position on screen, from top left
+    p.y = srect.size.height - p.y;
+
+    xp->x = (int) p.x;
+    xp->y = (int) p.y;
+  }
+
+# endif // !USE_IPHONE
+}
+
+
+#ifdef USE_IPHONE
+
+void
+check_framebuffer_status (void)
+{
+  int err = glCheckFramebufferStatusOES (GL_FRAMEBUFFER_OES);
+  switch (err) {
+  case GL_FRAMEBUFFER_COMPLETE_OES:
+    break;
+  case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES:
+    Assert (0, "framebuffer incomplete attachment");
+    break;
+  case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES:
+    Assert (0, "framebuffer incomplete missing attachment");
+    break;
+  case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES:
+    Assert (0, "framebuffer incomplete dimensions");
+    break;
+  case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES:
+    Assert (0, "framebuffer incomplete formats");
+    break;
+  case GL_FRAMEBUFFER_UNSUPPORTED_OES:
+    Assert (0, "framebuffer unsupported");
+    break;
+/*
+  case GL_FRAMEBUFFER_UNDEFINED:
+    Assert (0, "framebuffer undefined");
+    break;
+  case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
+    Assert (0, "framebuffer incomplete draw buffer");
+    break;
+  case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
+    Assert (0, "framebuffer incomplete read buffer");
+    break;
+  case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
+    Assert (0, "framebuffer incomplete multisample");
+    break;
+  case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
+    Assert (0, "framebuffer incomplete layer targets");
+    break;
+ */
+  default:
+    NSCAssert (0, @"framebuffer incomplete, unknown error 0x%04X", err);
+    break;
+  }
+}
+
+
+void
+create_framebuffer (GLuint *gl_framebuffer, GLuint *gl_renderbuffer)
+{
+  glGenFramebuffersOES  (1, gl_framebuffer);
+  glBindFramebufferOES  (GL_FRAMEBUFFER_OES,  *gl_framebuffer);
+
+  glGenRenderbuffersOES (1, gl_renderbuffer);
+  glBindRenderbufferOES (GL_RENDERBUFFER_OES, *gl_renderbuffer);
+}
+
+#endif // USE_IPHONE
+
+
+#if defined JWXYZ_QUARTZ
+
+/* Pushes a GC context; sets Fill and Stroke colors to the background color.
+ */
+static void
+push_bg_gc (Display *dpy, Drawable d, GC gc, Bool fill_p)
+{
+  XGCValues *gcv = jwxyz_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)
+{
+  XRectangle src_frame = src->frame, dst_frame = dst->frame;
+  XGCValues *gcv = jwxyz_gc_gcv (gc);
+
+  BOOL mask_p = src->type == PIXMAP && src->pixmap.depth == 1;
+
+
+  /* If we're copying from a bitmap to a bitmap, and there's nothing funny
+     going on with clipping masks or depths or anything, optimize it by
+     just doing a memcpy instead of going through a CGI.
+   */
+  if (gcv->function == GXcopy &&
+      !gcv->clip_mask &&
+      jwxyz_drawable_depth (src) == jwxyz_drawable_depth (dst)) {
+
+    Assert(!src_frame.x &&
+           !src_frame.y &&
+           !dst_frame.x &&
+           !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;
+    }
+
+    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),
+    dst_rect = CGRectMake(dst_x, dst_y, width, height);
+
+    src_rect.origin = map_point (src, src_rect.origin.x,
+                                 src_rect.origin.y + src_rect.size.height);
+    dst_rect.origin = map_point (dst, dst_rect.origin.x,
+                                 dst_rect.origin.y + src_rect.size.height);
+
+    NSObject *releaseme = 0;
+    CGImageRef cgi;
+    BOOL free_cgi_p = NO;
+
+    // We must first copy the bits to an intermediary CGImage object, then
+    // copy that to the destination drawable's CGContext.
+    //
+    // First we get a CGImage out of the pixmap CGContext -- it's the whole
+    // pixmap, but it presumably shares the data pointer instead of copying
+    // it.  We then cache that CGImage it inside the Pixmap object.  Note:
+    // invalidate_drawable_cache() must be called to discard this any time a
+    // modification is made to the pixmap, or we'll end up re-using old bits.
+    //
+    if (!src->cgi)
+      src->cgi = CGBitmapContextCreateImage (src->cgc);
+    cgi = src->cgi;
+
+    // if doing a sub-rect, trim it down.
+    if (src_rect.origin.x    != src_frame.x   ||
+        src_rect.origin.y    != src_frame.y   ||
+        src_rect.size.width  != src_frame.width ||
+        src_rect.size.height != src_frame.height) {
+      // #### I don't understand why this is needed...
+      src_rect.origin.y = (src_frame.height -
+                           src_rect.size.height - src_rect.origin.y);
+      // This does not copy image data, so it should be fast.
+      cgi = CGImageCreateWithImageInRect (cgi, src_rect);
+      free_cgi_p = YES;
+    }
+
+    CGContextRef cgc = dst->cgc;
+
+    if (mask_p) {              // src depth == 1
+
+      push_bg_gc (dpy, dst, gc, YES);
+
+      // fill the destination rectangle with solid background...
+      CGContextFillRect (cgc, dst_rect);
+
+      Assert (cgc, "no CGC with 1-bit XCopyArea");
+
+      // 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),
+                 gcv->alpha_allowed_p, YES);
+      CGContextClipToMask (cgc, dst_rect, cgi);
+      CGContextFillRect (cgc, dst_rect);
+
+      pop_gc (dst, gc);
+
+    } else {           // src depth > 1
+
+      push_gc (dst, gc);
+
+      // copy the CGImage onto the destination CGContext
+      //Assert(CGImageGetColorSpace(cgi) == dpy->colorspace, "bad colorspace");
+      CGContextDrawImage (cgc, dst_rect, cgi);
+
+      pop_gc (dst, gc);
+    }
+
+    if (free_cgi_p) CGImageRelease (cgi);
+    
+    if (releaseme) [releaseme release];
+  }
+  
+  invalidate_drawable_cache (dst);
+}
+
+#elif defined JWXYZ_GL
+
+/* Warning! The JWXYZ_GL code here is experimental and provisional and not at
+   all ready for prime time. Please be careful.
+ */
+
+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)
+{
+  /* TODO:
+   - glCopyPixels if src == dst
+   - Pixel buffer copying
+   - APPLE_framebuffer_multisample has ResolveMultisampleFramebufferAPPLE,
+     which is like a blit.
+   */
+
+  /* Strange and ugly flickering when going the glCopyTexImage2D route on
+     OS X. (Early 2009 Mac mini, OS X 10.10)
+   */
+# ifdef USE_IPHONE
+  jwxyz_gl_copy_area_copy_tex_image (dpy, src, dst, gc, src_x, src_y,
+                                     width, height, dst_x, dst_y);
+# else // !USE_IPHONE
+  jwxyz_gl_copy_area_read_pixels (dpy, src, dst, gc,
+                                  src_x, src_y, width, height, dst_x, dst_y);
+# endif // !USE_IPHONE
+  jwxyz_assert_gl ();
+}
+
+
+void
+jwxyz_assert_gl ()
+{
+  // This is like check_gl_error, except this happens for debug builds only.
+#ifndef __OPTIMIZE__
+  if([NSOpenGLContext currentContext])
+  {
+    // glFinish here drops FPS into the toilet. It might need to be on if
+    // something goes wrong.
+    // glFinish();
+    GLenum error = glGetError();
+    Assert (!error, "jwxyz_assert_gl: OpenGL error");
+  }
+#endif // !__OPTIMIZE__
+}
+
+void
+jwxyz_assert_drawable (Window main_window, Drawable d)
+{
+#if !defined USE_IPHONE && !defined __OPTIMIZE__
+  XScreenSaverView *view = main_window->window.view;
+  NSOpenGLContext *ogl_ctx = [view oglContext];
+
+  if (d->type == WINDOW) {
+    Assert([ogl_ctx view] == view,
+           "jwxyz_assert_display: ogl_ctx view not set!");
+  }
+
+  @try {
+    /* Assert([d->ctx isKindOfClass:[NSOpenGLContext class]], "Not a context."); */
+    Class c = [ogl_ctx class];
+    Assert([c isSubclassOfClass:[NSOpenGLContext class]], "Not a context.");
+    // [d->ctx makeCurrentContext];
+  }
+  @catch (NSException *exception) {
+    perror([[exception reason] UTF8String]);
+    abort();
+  }
+#endif // !USE_IPHONE && !__OPTIMIZE__
+}
+
+
+void
+jwxyz_bind_drawable (Window main_window, Drawable d)
+{
+  /* Windows and Pixmaps need to use different contexts with OpenGL
+     screenhacks, because an OpenGL screenhack sets state in an arbitrary
+     fashion, but jwxyz-gl.c has its own ideas w.r.t. OpenGL state.
+
+     On iOS, all pixmaps can use the same context with different FBOs. Which
+     is nice.
+   */
+
+  /* OpenGL screenhacks in general won't be drawing on the Window, but they
+     can and will draw on a Pixmap -- but an OpenGL call following an Xlib
+     call won't be able to fix the fact that it's drawing offscreen.
+   */
+
+  /* EXT_direct_state_access might be appropriate, but it's apparently not
+     available on Mac OS X.
+   */
+
+  // jwxyz_assert_display (dpy);
+  jwxyz_assert_drawable (main_window, main_window);
+  jwxyz_assert_gl ();
+  jwxyz_assert_drawable (main_window, d);
+
+#if defined USE_IPHONE && !defined __OPTIMIZE__
+  Drawable current_drawable = main_window->window.current_drawable;
+  Assert (!current_drawable
+            || current_drawable->ogl_ctx == [EAGLContext currentContext],
+          "bind_drawable: Wrong context.");
+  if (current_drawable) {
+    GLint framebuffer;
+    glGetIntegerv (GL_FRAMEBUFFER_BINDING_OES, &framebuffer);
+    Assert (framebuffer == current_drawable->gl_framebuffer,
+            "bind_drawable: Wrong framebuffer.");
+  }
+#endif
+
+  if (main_window->window.current_drawable != d) {
+    main_window->window.current_drawable = d;
+
+    /* Doing this repeatedly is probably not OK performance-wise. Probably. */
+#ifndef USE_IPHONE
+    [d->ogl_ctx makeCurrentContext];
+#else
+    [EAGLContext setCurrentContext:d->ogl_ctx];
+    glBindFramebufferOES(GL_FRAMEBUFFER_OES, d->gl_framebuffer);
+    if (d->type == PIXMAP) {
+      glViewport (0, 0, d->frame.width, d->frame.height);
+      jwxyz_set_matrices (d->frame.width, d->frame.height);
+    }
+#endif
+  }
+
+  jwxyz_assert_gl ();
+}
+
+
+Pixmap
+XCreatePixmap (Display *dpy, Drawable d,
+               unsigned int width, unsigned int height, unsigned int depth)
+{
+  Pixmap p = (Pixmap) calloc (1, sizeof(*p));
+  p->type = PIXMAP;
+  p->frame.width  = width;
+  p->frame.height = height;
+  p->pixmap.depth = depth;
+
+  Assert (depth == 1 || depth == 32, "XCreatePixmap: depth must be 32");
+
+  /* TODO: If Pixel buffers are not supported, do something about it. */
+  Window w = XRootWindow (dpy, 0);
+
+# ifndef USE_IPHONE
+
+  p->ogl_ctx = [[NSOpenGLContext alloc]
+                initWithFormat:w->window.pixfmt
+                shareContext:w->ogl_ctx];
+  CFRetain (p->ogl_ctx);
+
+  [p->ogl_ctx makeCurrentContext]; // This is indeed necessary.
+
+  p->pixmap.gl_pbuffer = [[NSOpenGLPixelBuffer alloc]
+                          /* TODO: Only if there are rectangluar textures. */
+                          initWithTextureTarget:GL_TEXTURE_RECTANGLE_EXT
+                          /* TODO: Make sure GL_RGBA isn't better. */
+                          textureInternalFormat:GL_RGB
+                          textureMaxMipMapLevel:0
+                          pixelsWide:width
+                          pixelsHigh:height];
+  CFRetain (p->pixmap.gl_pbuffer);
+
+  [p->ogl_ctx setPixelBuffer:p->pixmap.gl_pbuffer
+                 cubeMapFace:0
+                 mipMapLevel:0
+        currentVirtualScreen:w->window.virtual_screen];
+
+# else // USE_IPHONE
+
+  p->ogl_ctx = w->window.ogl_ctx_pixmap;
+
+  [EAGLContext setCurrentContext:p->ogl_ctx];
+  create_framebuffer (&p->gl_framebuffer, &p->gl_renderbuffer);
+
+  glRenderbufferStorageOES (GL_RENDERBUFFER_OES, GL_RGBA8_OES, width, height);
+  glFramebufferRenderbufferOES (GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES,
+                                GL_RENDERBUFFER_OES, p->gl_renderbuffer);
+
+  check_framebuffer_status ();
+
+  glBindFramebufferOES(GL_FRAMEBUFFER_OES, p->gl_framebuffer);
+
+# endif // USE_IPHONE
+
+  w->window.current_drawable = p;
+  glViewport (0, 0, width, height);
+  jwxyz_set_matrices (width, height);
+
+# ifndef __OPTIMIZE__
+  glClearColor (frand(1), frand(1), frand(1), 0);
+  glClear (GL_COLOR_BUFFER_BIT);
+# endif
+
+  return p;
+}
+
+int
+XFreePixmap (Display *d, Pixmap p)
+{
+  Assert (p && p->type == PIXMAP, "not a pixmap");
+
+  Window w = RootWindow (d, 0);
+
+# ifndef USE_IPHONE
+  CFRelease (p->ogl_ctx);
+  [p->ogl_ctx release];
+
+  CFRelease (p->pixmap.gl_pbuffer);
+  [p->pixmap.gl_pbuffer release];
+# else  // USE_IPHONE
+  glDeleteRenderbuffersOES (1, &p->gl_renderbuffer);
+  glDeleteFramebuffersOES (1, &p->gl_framebuffer);
+# endif // USE_IPHONE
+
+  if (w->window.current_drawable == p) {
+    w->window.current_drawable = NULL;
+  }
+
+  free (p);
+  return 0;
+}
+
+#endif // JWXYZ_GL
diff --git a/jwxyz/jwxyz-common.c b/jwxyz/jwxyz-common.c
new file mode 100644 (file)
index 0000000..a168bda
--- /dev/null
@@ -0,0 +1,971 @@
+/* xscreensaver, Copyright (c) 1991-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.
+ */
+
+/* JWXYZ Is Not Xlib.
+
+   But it's a bunch of function definitions that bear some resemblance to
+   Xlib and that do Cocoa-ish or OpenGL-ish things that bear some resemblance
+   to the things that Xlib might have done.
+
+   This is the version of jwxyz for Android.  The version used by MacOS
+   and iOS is in jwxyz.m.
+ */
+
+#include "config.h"
+
+#ifdef HAVE_JWXYZ /* whole file */
+
+#include "jwxyzI.h"
+
+/* There's only one Window for a given jwxyz_Display. */
+#define assert_window(dpy, w) \
+  Assert (w == RootWindow (dpy, 0), "not a window")
+
+int
+XDisplayWidth (Display *dpy, int screen)
+{
+  return jwxyz_frame (XRootWindow (dpy, 0))->width;
+}
+
+int
+XDisplayHeight (Display *dpy, int screen)
+{
+  return jwxyz_frame (XRootWindow (dpy, 0))->height;
+}
+
+
+/* XLFDs use dots per inch, but Xlib uses millimeters. Go figure. */
+static const unsigned dpi = 75;
+
+int
+XDisplayWidthMM (Display *dpy, int screen)
+{
+  const unsigned denom = dpi * 10 / 2;
+  return (254 * XDisplayWidth (dpy, screen) + denom) / (2 * denom);
+}
+
+int
+XDisplayHeightMM (Display *dpy, int screen)
+{
+  const unsigned denom = dpi * 10 / 2;
+  return (254 * XDisplayHeight (dpy, screen) + denom) / (2 * denom);
+}
+
+
+void
+jwxyz_validate_pixel (Display *dpy, unsigned long pixel, unsigned int depth,
+                      Bool alpha_allowed_p)
+{
+  Assert (depth == 1 || depth == visual_depth(NULL, NULL),
+          "invalid depth: %d", depth);
+
+  if (depth == 1)
+    Assert ((pixel == 0 || pixel == 1), "bogus mono  pixel: 0x%08X", pixel);
+  else if (!alpha_allowed_p)
+    Assert (((pixel & BlackPixel(dpy,0)) == BlackPixel(dpy,0)),
+            "bogus color pixel: 0x%08X", pixel);
+}
+
+
+int
+XDrawPoint (Display *dpy, Drawable d, GC gc, int x, int y)
+{
+  XPoint p;
+  p.x = x;
+  p.y = y;
+  return XDrawPoints (dpy, d, gc, &p, 1, CoordModeOrigin);
+}
+
+
+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);
+
+  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);
+    jwxyz_fill_rect (dpy, d, 0, x, y, width, height,
+                     (gcv->function == GXset
+                      ? (depth == 1 ? 1 : WhitePixel(dpy,0))
+                      : (depth == 1 ? 0 : BlackPixel(dpy,0))));
+    return True;
+  }
+
+  return False;
+}
+
+
+int
+XCopyArea (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)
+{
+  Assert (gc, "no GC");
+  Assert ((width  < 65535), "improbably large width");
+  Assert ((height < 65535), "improbably large height");
+  Assert ((src_x  < 65535 && src_x  > -65535), "improbably large src_x");
+  Assert ((src_y  < 65535 && src_y  > -65535), "improbably large src_y");
+  Assert ((dst_x  < 65535 && dst_x  > -65535), "improbably large dst_x");
+  Assert ((dst_y  < 65535 && dst_y  > -65535), "improbably large dst_y");
+
+  if (width == 0 || height == 0)
+    return 0;
+
+  if (jwxyz_dumb_drawing_mode (dpy, dst, gc, dst_x, dst_y, width, height))
+    return 0;
+
+  XRectangle src_frame, dst_frame; // Sizes and origins of the two drawables
+  Bool clipped = False;            // Whether we did any clipping of the rects.
+
+  src_frame = *jwxyz_frame (src);
+  dst_frame = *jwxyz_frame (dst);
+  
+  // Initialize src_rect...
+  //
+  src_x += src_frame.x;
+  src_y += src_frame.y;
+  if (src_y < -65535) Assert(0, "src.origin.y went nuts");
+
+  // Initialize dst_rect...
+  //
+  dst_x += dst_frame.x;
+  dst_y += dst_frame.y;
+  if (dst_y < -65535) Assert(0, "dst.origin.y went nuts");
+
+  // Use signed width and height for this...
+  int width0 = width, height0 = height;
+
+  // Clip rects to frames...
+  //
+
+# define CLIP(THIS,THAT,VAL,SIZE) do { \
+  int off = THIS##_##VAL; \
+  if (off < 0) { \
+    clipped = True; \
+    SIZE##0      += off; \
+    THIS##_##VAL -= off; \
+    THAT##_##VAL -= off; \
+  } \
+  off = (( THIS##_##VAL +  SIZE##0) - \
+         (THIS##_frame.VAL + THIS##_frame.SIZE)); \
+  if (off > 0) { \
+    clipped = True; \
+    SIZE##0 -= off; \
+  }} while(0)
+
+  CLIP (dst, src, x, width);
+  CLIP (dst, src, y, height);
+
+  // Not actually the original dst_rect, just the one before it's clipped to
+  // the src_frame.
+  int orig_dst_x = dst_x;
+  int orig_dst_y = dst_y;
+  int orig_width  = width0;
+  int orig_height = height0;
+
+  if (width0 <= 0 || height0 <= 0)
+    return 0;
+
+  CLIP (src, dst, x, width);
+  CLIP (src, dst, y, height);
+# undef CLIP
+
+  // Sort-of-special case where no pixels can be grabbed from the source,
+  // and the whole destination is filled with the background color.
+  if (width0 <= 0 || height0 <= 0) {
+    width0  = 0;
+    height0 = 0;
+  } else {
+    jwxyz_copy_area (dpy, src, dst, gc,
+                     src_x, src_y, width0, height0, dst_x, dst_y);
+  }
+
+  // If either the src or dst rects did not lie within their drawables, then
+  // we have adjusted both the src and dst rects to account for the clipping;
+  // that means we need to clear to the background, so that clipped bits end
+  // up in the bg color instead of simply not being copied.
+  //
+  // This has to happen after the copy, because if it happens before, the
+  // cleared area will get grabbed if it overlaps with the source rectangle.
+  //
+  if (clipped && dst == XRootWindow (dpy,0)) {
+    int dst_x0 = dst_x;
+    int dst_y0 = dst_y;
+
+    Assert (orig_dst_x >= 0 &&
+            orig_dst_x + orig_width  <= dst_frame.width &&
+            orig_dst_y >= 0 &&
+            orig_dst_y + orig_height <= dst_frame.height,
+            "wrong dimensions");
+
+    XRectangle rects[4];
+    XRectangle *rects_end = rects;
+
+    if (orig_dst_y < dst_y0) {
+      rects_end->x = orig_dst_x;
+      rects_end->y = orig_dst_y;
+      rects_end->width = orig_width;
+      rects_end->height = dst_y0 - orig_dst_y;
+      ++rects_end;
+    }
+
+    if (orig_dst_y + orig_height > dst_y0 + height0) {
+      rects_end->x = orig_dst_x;
+      rects_end->y = dst_y0 + height0;
+      rects_end->width = orig_width;
+      rects_end->height = orig_dst_y + orig_height - dst_y0 - height0;
+      ++rects_end;
+    }
+
+    if (orig_dst_x < dst_x0) {
+      rects_end->x = orig_dst_x;
+      rects_end->y = dst_y0;
+      rects_end->width = dst_x0 - orig_dst_x;
+      rects_end->height = height0;
+      ++rects_end;
+    }
+
+    if (dst_x0 + width0 < orig_dst_x + orig_width) {
+      rects_end->x = dst_x0 + width0;
+      rects_end->y = dst_y0;
+      rects_end->width = orig_dst_x + orig_width - dst_x0 - width0;
+      rects_end->height = height0;
+      ++rects_end;
+    }
+
+    XGCValues *gcv = jwxyz_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));
+    gcv->function = old_function;
+  }
+
+  return 0;
+}
+
+
+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!");
+  
+  // This isn't right: XCopyPlane() is supposed to map 1/0 to fg/bg,
+  // not to white/black.
+  return XCopyArea (dpy, src, dest, gc,
+                    src_x, src_y, width, height, dest_x, dest_y);
+}
+
+
+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);
+}
+
+int
+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);
+  return 0;
+}
+
+int
+XDrawRectangle (Display *dpy, Drawable d, GC gc, int x, int y, 
+                unsigned int width, unsigned int height)
+{
+  XPoint points[5] = {
+    {x, y},
+    {x, y + height},
+    {x + width, y + height},
+    {x + width, y},
+    {x, y}
+  };
+
+  XDrawLines(dpy, d, gc, points, 5, CoordModeOrigin);
+  return 0;
+}
+
+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);
+  return 0;
+}
+
+
+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,
+                         False);
+}
+
+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,
+                         True);
+}
+
+int
+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,
+                    arcs[i].x, arcs[i].y,
+                    arcs[i].width, arcs[i].height,
+                    arcs[i].angle1, arcs[i].angle2,
+                    False);
+  return 0;
+}
+
+int
+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,
+                    arcs[i].x, arcs[i].y,
+                    arcs[i].width, arcs[i].height,
+                    arcs[i].angle1, arcs[i].angle2,
+                    True);
+  return 0;
+}
+
+void
+jwxyz_gcv_defaults (Display *dpy, XGCValues *gcv, int depth)
+{
+  memset (gcv, 0, sizeof(*gcv));
+  gcv->function   = GXcopy;
+  gcv->foreground = (depth == 1 ? 1 : WhitePixel(dpy,0));
+  gcv->background = (depth == 1 ? 0 : BlackPixel(dpy,0));
+  gcv->line_width = 1;
+  gcv->cap_style  = CapButt;
+  gcv->join_style = JoinMiter;
+  gcv->fill_rule  = EvenOddRule;
+
+  gcv->alpha_allowed_p = False;
+  gcv->antialias_p     = True;
+}
+
+
+int
+XChangeGC (Display *dpy, GC gc, unsigned long mask, XGCValues *from)
+{
+  if (! mask) return 0;
+  Assert (gc && from, "no gc");
+  if (!gc || !from) return 0;
+
+  XGCValues *to = jwxyz_gc_gcv (gc);
+  unsigned depth = jwxyz_gc_depth (gc);
+
+  if (mask & GCFunction)        to->function            = from->function;
+  if (mask & GCForeground)      to->foreground          = from->foreground;
+  if (mask & GCBackground)      to->background          = from->background;
+  if (mask & GCLineWidth)       to->line_width          = from->line_width;
+  if (mask & GCCapStyle)        to->cap_style           = from->cap_style;
+  if (mask & GCJoinStyle)       to->join_style          = from->join_style;
+  if (mask & GCFillRule)        to->fill_rule           = from->fill_rule;
+  if (mask & GCClipXOrigin)     to->clip_x_origin       = from->clip_x_origin;
+  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 & GCForeground)
+    jwxyz_validate_pixel (dpy, from->foreground, depth, to->alpha_allowed_p);
+  if (mask & GCBackground)
+    jwxyz_validate_pixel (dpy, from->background, depth, to->alpha_allowed_p);
+
+  Assert ((! (mask & (GCLineStyle |
+                      GCPlaneMask |
+                      GCFillStyle |
+                      GCTile |
+                      GCStipple |
+                      GCTileStipXOrigin |
+                      GCTileStipYOrigin |
+                      GCGraphicsExposures |
+                      GCDashOffset |
+                      GCDashList |
+                      GCArcMode))),
+          "unimplemented gcvalues mask");
+
+  return 0;
+}
+
+
+Status
+XGetWindowAttributes (Display *dpy, Window w, XWindowAttributes *xgwa)
+{
+  assert_window(dpy, w);
+  memset (xgwa, 0, sizeof(*xgwa));
+  const XRectangle *frame = jwxyz_frame (w);
+  xgwa->x      = frame->x;
+  xgwa->y      = frame->y;
+  xgwa->width  = frame->width;
+  xgwa->height = frame->height;
+  xgwa->depth  = visual_depth (NULL, NULL);
+  xgwa->screen = DefaultScreenOfDisplay (dpy);
+  xgwa->visual = XDefaultVisualOfScreen (xgwa->screen);
+  return 0;
+}
+
+Status
+XGetGeometry (Display *dpy, Drawable d, Window *root_ret,
+              int *x_ret, int *y_ret,
+              unsigned int *w_ret, unsigned int *h_ret,
+              unsigned int *bw_ret, unsigned int *d_ret)
+{
+  const XRectangle *frame = jwxyz_frame (d);
+  *x_ret    = frame->x;
+  *y_ret    = frame->y;
+  *w_ret    = frame->width;
+  *h_ret    = frame->height;
+  *d_ret    = jwxyz_drawable_depth (d);
+  *root_ret = RootWindow (dpy, 0);
+  *bw_ret   = 0;
+  return True;
+}
+
+
+Status
+XAllocColor (Display *dpy, Colormap cmap, XColor *color)
+{
+  color->pixel = jwxyz_alloc_color (dpy,
+                                    color->red,
+                                    color->green,
+                                    color->blue,
+                                    0xFFFF);
+  return 1;
+}
+
+Status
+XAllocColorCells (Display *dpy, Colormap cmap, Bool contig,
+                  unsigned long *pmret, unsigned int npl,
+                  unsigned long *pxret, unsigned int npx)
+{
+  return 0;
+}
+
+int
+XStoreColors (Display *dpy, Colormap cmap, XColor *colors, int n)
+{
+  Assert(0, "XStoreColors called");
+  return 0;
+}
+
+int
+XStoreColor (Display *dpy, Colormap cmap, XColor *c)
+{
+  Assert(0, "XStoreColor called");
+  return 0;
+}
+
+int
+XFreeColors (Display *dpy, Colormap cmap, unsigned long *px, int npixels,
+             unsigned long planes)
+{
+  return 0;
+}
+
+Status
+XParseColor (Display *dpy, Colormap cmap, const char *spec, XColor *ret)
+{
+  unsigned char r=0, g=0, b=0;
+  if (*spec == '#' && strlen(spec) == 7) {
+    static unsigned const char hex[] = {   // yeah yeah, shoot me.
+      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,
+      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,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,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};
+    const unsigned char *uspec = (const unsigned char *)spec;
+    r = (hex[uspec[1]] << 4) | hex[uspec[2]];
+    g = (hex[uspec[3]] << 4) | hex[uspec[4]];
+    b = (hex[uspec[5]] << 4) | hex[uspec[6]];
+  } else if (!strcasecmp(spec,"black")) {
+    //  r = g = b = 0;
+  } else if (!strcasecmp(spec,"white")) {
+    r = g = b = 255;
+  } else if (!strcasecmp(spec,"red")) {
+    r = 255;
+  } else if (!strcasecmp(spec,"green")) {
+    g = 255;
+  } else if (!strcasecmp(spec,"blue")) {
+    b = 255;
+  } else if (!strcasecmp(spec,"cyan")) {
+    g = b = 255;
+  } else if (!strcasecmp(spec,"magenta")) {
+    r = b = 255;
+  } else if (!strcasecmp(spec,"yellow")) {
+    r = g = 255;
+  } else {
+    return 0;
+  }
+
+  ret->red   = (r << 8) | r;
+  ret->green = (g << 8) | g;
+  ret->blue  = (b << 8) | b;
+  ret->flags = DoRed|DoGreen|DoBlue;
+  return 1;
+}
+
+Status
+XAllocNamedColor (Display *dpy, Colormap cmap, char *name,
+                  XColor *screen_ret, XColor *exact_ret)
+{
+  if (! XParseColor (dpy, cmap, name, screen_ret))
+    return False;
+  *exact_ret = *screen_ret;
+  return XAllocColor (dpy, cmap, screen_ret);
+}
+
+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];
+  color->flags = DoRed|DoGreen|DoBlue;
+  return 0;
+}
+
+int
+XQueryColors (Display *dpy, Colormap cmap, XColor *c, int n)
+{
+  int i;
+  for (i = 0; i < n; i++)
+    XQueryColor (dpy, cmap, &c[i]);
+  return 0;
+}
+
+
+static unsigned long
+ximage_getpixel_1 (XImage *ximage, int x, int y)
+{
+  return ((ximage->data [y * ximage->bytes_per_line + (x>>3)] >> (x & 7)) & 1);
+}
+
+static int
+ximage_putpixel_1 (XImage *ximage, int x, int y, unsigned long pixel)
+{
+  if (pixel)
+    ximage->data [y * ximage->bytes_per_line + (x>>3)] |=  (1 << (x & 7));
+  else
+    ximage->data [y * ximage->bytes_per_line + (x>>3)] &= ~(1 << (x & 7));
+
+  return 0;
+}
+
+static unsigned long
+ximage_getpixel_32 (XImage *ximage, int x, int y)
+{
+  return ((unsigned long)
+          *((uint32_t *) ximage->data +
+            (y * (ximage->bytes_per_line >> 2)) +
+            x));
+}
+
+static int
+ximage_putpixel_32 (XImage *ximage, int x, int y, unsigned long pixel)
+{
+  *((uint32_t *) ximage->data +
+    (y * (ximage->bytes_per_line >> 2)) +
+    x) = (uint32_t) pixel;
+  return 0;
+}
+
+
+Status
+XInitImage (XImage *ximage)
+{
+  if (!ximage->bytes_per_line)
+    ximage->bytes_per_line = (ximage->depth == 1
+                              ? (ximage->width + 7) / 8
+                              : ximage->width * 4);
+
+  if (ximage->depth == 1) {
+    ximage->f.put_pixel = ximage_putpixel_1;
+    ximage->f.get_pixel = ximage_getpixel_1;
+  } else if (ximage->depth == 32 || ximage->depth == 24) {
+    ximage->f.put_pixel = ximage_putpixel_32;
+    ximage->f.get_pixel = ximage_getpixel_32;
+  } else {
+    Assert (0, "unknown depth");
+  }
+  return 1;
+}
+
+
+XImage *
+XCreateImage (Display *dpy, Visual *visual, unsigned int depth,
+              int format, int offset, char *data,
+              unsigned int width, unsigned int height,
+              int bitmap_pad, int bytes_per_line)
+{
+  XImage *ximage = (XImage *) calloc (1, sizeof(*ximage));
+  ximage->width = width;
+  ximage->height = height;
+  ximage->format = format;
+  ximage->data = data;
+  ximage->bitmap_unit = 8;
+  ximage->byte_order = LSBFirst;
+  ximage->bitmap_bit_order = ximage->byte_order;
+  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->bits_per_pixel = (depth == 1 ? 1 : visual_depth (NULL, NULL));
+  ximage->bytes_per_line = bytes_per_line;
+
+  XInitImage (ximage);
+  return ximage;
+}
+
+XImage *
+XSubImage (XImage *from, int x, int y, unsigned int w, unsigned int h)
+{
+  XImage *to = (XImage *) malloc (sizeof(*to));
+  memcpy (to, from, sizeof(*from));
+  to->width = w;
+  to->height = h;
+  to->bytes_per_line = 0;
+  XInitImage (to);
+
+  to->data = (char *) malloc (h * to->bytes_per_line);
+
+  if (x >= from->width)
+    w = 0;
+  else if (x+w > from->width)
+    w = from->width - x;
+
+  if (y >= from->height)
+    h = 0;
+  else if (y+h > from->height)
+    h = from->height - y;
+
+  int tx, ty;
+  for (ty = 0; ty < h; ty++)
+    for (tx = 0; tx < w; tx++)
+      XPutPixel (to, tx, ty, XGetPixel (from, x+tx, y+ty));
+  return to;
+}
+
+
+XPixmapFormatValues *
+XListPixmapFormats (Display *dpy, int *n_ret)
+{
+  XPixmapFormatValues *ret = calloc (2, sizeof(*ret));
+  ret[0].depth = visual_depth (NULL, NULL);
+  ret[0].bits_per_pixel = 32;
+  ret[0].scanline_pad = 8;
+  ret[1].depth = 1;
+  ret[1].bits_per_pixel = 1;
+  ret[1].scanline_pad = 8;
+  *n_ret = 2;
+  return ret;
+}
+
+
+unsigned long
+XGetPixel (XImage *ximage, int x, int y)
+{
+  return ximage->f.get_pixel (ximage, x, y);
+}
+
+
+int
+XPutPixel (XImage *ximage, int x, int y, unsigned long pixel)
+{
+  return ximage->f.put_pixel (ximage, x, y, pixel);
+}
+
+int
+XDestroyImage (XImage *ximage)
+{
+  if (ximage->data) free (ximage->data);
+  free (ximage);
+  return 0;
+}
+
+
+Pixmap
+XCreatePixmapFromBitmapData (Display *dpy, Drawable drawable,
+                             const char *data,
+                             unsigned int w, unsigned int h,
+                             unsigned long fg, unsigned int bg,
+                             unsigned int depth)
+{
+  Pixmap p = XCreatePixmap (dpy, drawable, w, h, depth);
+  XImage *image = XCreateImage (dpy, 0, 1, XYPixmap, 0,
+                                (char *) data, w, h, 0, 0);
+  XGCValues gcv;
+  gcv.foreground = fg;
+  gcv.background = bg;
+  GC gc = XCreateGC (dpy, p, GCForeground|GCBackground, &gcv);
+  XPutImage (dpy, p, gc, image, 0, 0, 0, 0, w, h);
+  XFreeGC (dpy, gc);
+  image->data = 0;
+  XDestroyImage (image);
+  return p;
+}
+
+
+char *
+XGetAtomName (Display *dpy, Atom atom)
+{
+  if (atom == XA_FONT)
+    return strdup ("FONT");
+
+  // Note that atoms (that aren't predefined) are just char *.
+  return strdup ((char *) atom);
+}
+
+
+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);
+  gcv->foreground = fg;
+  return 0;
+}
+
+
+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);
+  gcv->background = bg;
+  return 0;
+}
+
+int
+jwxyz_XSetAlphaAllowed (Display *dpy, GC gc, Bool allowed)
+{
+  jwxyz_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;
+  return 0;
+}
+
+
+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);
+  gcv->line_width = line_width;
+  Assert (line_style == LineSolid, "only LineSolid implemented");
+//  gc->gcv.line_style = line_style;
+  gcv->cap_style = cap_style;
+  gcv->join_style = join_style;
+  return 0;
+}
+
+int
+XSetGraphicsExposures (Display *dpy, GC gc, Bool which)
+{
+  return 0;
+}
+
+int
+XSetFunction (Display *dpy, GC gc, int which)
+{
+  jwxyz_gc_gcv (gc)->function = which;
+  return 0;
+}
+
+int
+XSetSubwindowMode (Display *dpy, GC gc, int which)
+{
+  jwxyz_gc_gcv (gc)->subwindow_mode = which;
+  return 0;
+}
+
+
+Bool
+XQueryPointer (Display *dpy, Window w, Window *root_ret, Window *child_ret,
+               int *root_x_ret, int *root_y_ret,
+               int *win_x_ret, int *win_y_ret, unsigned int *mask_ret)
+{
+  assert_window (dpy, w);
+
+  XPoint vpos, p;
+  jwxyz_get_pos (w, &vpos, &p);
+
+  if (root_x_ret) *root_x_ret = p.x;
+  if (root_y_ret) *root_y_ret = p.y;
+  if (win_x_ret)  *win_x_ret  = p.x - vpos.x;
+  if (win_y_ret)  *win_y_ret  = p.y - vpos.y;
+  if (mask_ret)   *mask_ret   = 0;  // #### poll the keyboard modifiers?
+  if (root_ret)   *root_ret   = 0;
+  if (child_ret)  *child_ret  = 0;
+  return True;
+}
+
+Bool
+XTranslateCoordinates (Display *dpy, Window w, Window dest_w,
+                       int src_x, int src_y,
+                       int *dest_x_ret, int *dest_y_ret,
+                       Window *child_ret)
+{
+  assert_window (dpy, w);
+
+  XPoint vpos, p;
+  jwxyz_get_pos (w, &vpos, NULL);
+
+  // point starts out relative to top left of view
+  p.x = src_x;
+  p.y = src_y;
+
+  // get point relative to top left of screen
+  p.x += vpos.x;
+  p.y += vpos.y;
+
+  *dest_x_ret = p.x;
+  *dest_y_ret = p.y;
+  if (child_ret)
+    *child_ret = w;
+  return True;
+}
+
+
+KeySym
+XKeycodeToKeysym (Display *dpy, KeyCode code, int index)
+{
+  return code;
+}
+
+int
+XLookupString (XKeyEvent *e, char *buf, int size, KeySym *k_ret,
+               XComposeStatus *xc)
+{
+  KeySym ks = XKeycodeToKeysym (0, e->keycode, 0);
+  char c = 0;
+  // Do not put non-ASCII KeySyms like XK_Shift_L and XK_Page_Up in the string.
+  if ((unsigned int) ks <= 255)
+    c = (char) ks;
+
+  // Put control characters in the string.  Not meta.
+  if (e->state & ControlMask) {
+    if (c >= 'a' && c <= 'z')    // Upcase control.
+      c -= 'a'-'A';
+    if (c >= '@' && c <= '_')    // Shift to control page.
+      c -= '@';
+    if (c == ' ')               // C-SPC is NULL.
+      c = 0;
+  }
+
+  if (k_ret) *k_ret = ks;
+  if (size > 0) buf[0] = c;
+  if (size > 1) buf[1] = 0;
+  return (size > 0 ? 1 : 0);
+}
+
+
+int
+XFlush (Display *dpy)
+{
+  // Just let the event loop take care of this on its own schedule.
+  return 0;
+}
+
+int
+XSync (Display *dpy, Bool flush)
+{
+  return XFlush (dpy);
+}
+
+
+// declared in utils/visual.h
+int
+has_writable_cells (Screen *s, Visual *v)
+{
+  return 0;
+}
+
+int
+visual_depth (Screen *s, Visual *v)
+{
+  return 32;
+}
+
+int
+visual_cells (Screen *s, Visual *v)
+{
+  return (int)(v->red_mask | v->green_mask | v->blue_mask);
+}
+
+int
+visual_class (Screen *s, Visual *v)
+{
+  return TrueColor;
+}
+
+int
+get_bits_per_pixel (Display *dpy, int depth)
+{
+  Assert (depth == 32 || depth == 1, "unexpected depth");
+  return depth;
+}
+
+int
+screen_number (Screen *screen)
+{
+  Display *dpy = DisplayOfScreen (screen);
+  int i;
+  for (i = 0; i < ScreenCount (dpy); i++)
+    if (ScreenOfDisplay (dpy, i) == screen)
+      return i;
+  abort ();
+  return 0;
+}
+
+// declared in utils/grabclient.h
+Bool
+use_subwindow_mode_p (Screen *screen, Window window)
+{
+  return False;
+}
+
+#endif /* HAVE_JWXYZ */
diff --git a/jwxyz/jwxyz-gl.c b/jwxyz/jwxyz-gl.c
new file mode 100644 (file)
index 0000000..66944ed
--- /dev/null
@@ -0,0 +1,3114 @@
+/* xscreensaver, Copyright (c) 1991-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.
+ */
+
+/* JWXYZ Is Not Xlib.
+
+   But it's a bunch of function definitions that bear some resemblance to
+   Xlib and that do OpenGL-ish things that bear some resemblance to the
+   things that Xlib might have done.
+
+   This is the version of jwxyz for Android.  The version used by MacOS
+   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. */
+
+/* TODO:
+   - malloc error checking
+   - Check max texture sizes for XGet/PutImage, XCopyArea.
+   - Optional 5:5:5 16-bit color
+*/
+
+/* Techniques & notes:
+   - 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.
+       - OS X: Drawable objects, including: pixel buffers and offscreen
+         memory.
+         - Offscreen buffers w/ CGLSetOffScreen (10.0+)
+         - http://lists.apple.com/archives/mac-opengl/2002/Jun/msg00087.html
+           provides a very ugly solution for hardware-accelerated offscreen
+           rendering with CGLSetParameter(*, kCGLCPSurfaceTexture, *) on OS X
+           10.1+. Apple docs say it's actually for OS X 10.3+, instead.
+         - Pixel buffers w/ CGLSetPBuffer (10.3+, now deprecated)
+           - Requires APPLE_pixel_buffer.
+             - Available in software on x86 only.
+             - Always available on hardware.
+           - Need to blit? Use OpenGL pixel buffers. (GL_PIXEL_PACK_BUFFER)
+         - Framebuffer objects w/ GL_(ARB|EXT)_framebuffer_object
+           - TODO: Can EXT_framebuffers be different sizes?
+           - Preferred on 10.7+
+       - iOS: Use OES_framebuffer_object, it's always present.
+ */
+
+/* OpenGL hacks call a number of X11 functions, including
+ * XCopyArea, XDrawString, XGetImage
+ * XCreatePixmap, XCreateGC, XCreateImage
+ * XPutPixel
+ * Check these, of course. */
+
+#ifdef JWXYZ_GL /* entire file */
+
+#include <math.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <wchar.h>
+
+#ifdef HAVE_COCOA
+# ifdef USE_IPHONE
+#  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
+#else
+/* TODO: Does this work on iOS? */
+# ifndef HAVE_JWZGLES
+#  include <gl/glu.h>
+# else
+#  include <GLES/gl.h>
+#  include <GLES/glext.h>
+# endif
+#endif
+
+#ifdef HAVE_JWZGLES
+# include "jwzglesI.h"
+#endif
+
+#ifdef HAVE_ANDROID
+# include <android/log.h>
+#endif
+
+#include "jwxyzI.h"
+#include "jwxyz-timers.h"
+#include "yarandom.h"
+#include "utf8wc.h"
+#include "xft.h"
+
+#if defined HAVE_COCOA
+# include <CoreGraphics/CGGeometry.h>
+#else
+
+
+#ifdef HAVE_ANDROID
+ extern void Log(const char *fmt, ...);
+#else
+static void
+Log (const char *fmt, ...)
+{
+  va_list args;
+  va_start (args, fmt);
+  vfprintf (stderr, fmt, args);
+  va_end (args);
+}
+#endif
+
+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;
+  uint8_t bytes[4];
+};
+
+struct jwxyz_Display {
+  Window main_window;
+  Screen *screen;
+  int screen_count;
+  struct jwxyz_sources_data *timers_data;
+
+  Bool gl_texture_npot_p;
+  /* Bool opengl_core_p */;
+  GLenum gl_texture_target;
+  
+// #if defined USE_IPHONE
+  GLuint rect_texture; // Also can work on the desktop.
+// #endif
+
+  unsigned long window_background;
+};
+
+struct jwxyz_Screen {
+  Display *dpy;
+  GLenum pixel_format, pixel_type;
+  unsigned long black, white;
+  Visual *visual;
+  int screen_number;
+};
+
+struct jwxyz_GC {
+  XGCValues gcv;
+  unsigned int depth;
+  // CGImageRef clip_mask;  // CGImage copy of the Pixmap in gcv.clip_mask
+};
+
+struct jwxyz_Font {
+  Display *dpy;
+  char *ps_name;
+  void *native_font;
+  int refcount; // for deciding when to release the native font
+  float size;   // points
+  int ascent, descent;
+  char *xa_font;
+
+  // In X11, "Font" is just an ID, and "XFontStruct" contains the metrics.
+  // But we need the metrics on both of them, so they go here.
+  XFontStruct metrics;
+};
+
+struct jwxyz_XFontSet {
+  XFontStruct *font;
+};
+
+
+/* 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)
+{
+  if(!dpy)
+    return;
+  jwxyz_assert_gl ();
+  jwxyz_assert_drawable (dpy->main_window, dpy->main_window);
+}
+
+
+void
+jwxyz_set_matrices (Display *dpy, unsigned width, unsigned height,
+                    Bool window_p)
+{
+  /* TODO: Check registration pattern from Interference with rectangles instead of points. */
+
+  // The projection matrix is always set as follows. The modelview matrix is
+  // usually identity, but for points and thin lines, it's translated by 0.5.
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  
+# if defined(USE_IPHONE) || defined(HAVE_ANDROID)
+
+  if (window_p && ignore_rotation_p(dpy)) {
+    int o = (int) current_device_rotation();
+    glRotatef (-o, 0, 0, 1);
+  }
+
+  // glPointSize(1); // This is the default.
+  
+#ifdef HAVE_JWZGLES
+  glOrthof /* TODO: Is glOrthox worth it? Signs point to no. */
+#else
+  glOrtho
+#endif
+    (0, width, height, 0, -1, 1);
+
+  glMatrixMode(GL_MODELVIEW);
+# endif // HAVE_MOBILE
+}
+
+#ifndef HAVE_JWZGLES
+
+struct gl_version
+{
+  // iOS always uses OpenGL ES 1.1.
+  unsigned major;
+  unsigned minor;
+};
+
+static GLboolean
+gl_check_ver (const struct gl_version *caps,
+              unsigned gl_major,
+              unsigned gl_minor)
+{
+  return caps->major > gl_major ||
+           (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;
+
+/* We keep a list of all of the Displays that have been created and not
+   yet freed so that they can have sensible display numbers.  If three
+   displays are created (0, 1, 2) and then #1 is closed, then the fourth
+   display will be given the now-unused display number 1. (Everything in
+   here assumes a 1:1 Display/Screen mapping.)
+
+   The size of this array is the most number of live displays at one time.
+   So if it's 20, then we'll blow up if the system has 19 monitors and also
+   has System Preferences open (the small preview window).
+
+   Note that xlockmore-style savers tend to allocate big structures, so
+   setting this to 1000 will waste a few megabytes.  Also some of them assume
+   that the number of screens never changes, so dynamically expanding this
+   array won't work.
+ */
+# ifndef USE_IPHONE
+static Display *jwxyz_live_displays[20] = { 0, };
+# endif
+
+
+Display *
+jwxyz_make_display (Window w)
+{
+  Display *d = (Display *) calloc (1, sizeof(*d));
+  d->screen = (Screen *) calloc (1, sizeof(Screen));
+  d->screen->dpy = d;
+  
+  d->screen_count = 1;
+  d->screen->screen_number = 0;
+# ifndef USE_IPHONE
+  {
+    // Find the first empty slot in live_displays and plug us in.
+    int size = sizeof(jwxyz_live_displays) / sizeof(*jwxyz_live_displays);
+    int i;
+    for (i = 0; i < size; i++) {
+      if (! jwxyz_live_displays[i])
+        break;
+    }
+    if (i >= size) abort();
+    jwxyz_live_displays[i] = d;
+    d->screen_count = size;
+    d->screen->screen_number = i;
+  }
+# endif // !USE_IPHONE
+
+# ifndef HAVE_JWZGLES
+  struct gl_version version;
+
+  {
+    const GLubyte *version_str = glGetString (GL_VERSION);
+
+    /* iPhone is always OpenGL ES 1.1. */
+    if (sscanf ((const char *) version_str, "%u.%u",
+                &version.major, &version.minor) < 2)
+    {
+      version.major = 1;
+      version.minor = 1;
+    }
+  }
+# endif // !HAVE_JWZGLES
+
+  const GLubyte *extensions = glGetString (GL_EXTENSIONS);
+
+  /* See:
+     - Apple TN2080: Understanding and Detecting OpenGL Functionality.
+     - OpenGL Programming Guide for the Mac - Best Practices for Working with
+       Texture Data - Optimal Data Formats and Types
+   */
+
+  // If a video adapter suports BGRA textures, then that's probably as fast as
+  // 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; /*
+    gluCheckExtension ((const GLubyte *) "GL_APPLE_texture_format_BGRA8888",
+                       extensions) ? GL_BGRA_EXT : GL_RGBA; */
+  d->screen->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;
+    // 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;
+  } else {
+    d->screen->pixel_format = GL_RGBA;
+    d->screen->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.
+# ifndef HAVE_JWZGLES
+  d->gl_texture_npot_p = gluCheckExtension ((const GLubyte *)
+                                            "GL_ARB_texture_rectangle",
+                                            extensions);
+  d->gl_texture_target = d->gl_texture_npot_p ?
+                         GL_TEXTURE_RECTANGLE_EXT :
+                         GL_TEXTURE_2D;
+# else
+  d->gl_texture_npot_p = jwzgles_gluCheckExtension
+      ((const GLubyte *) "GL_APPLE_texture_2D_limited_npot", extensions) ||
+    jwzgles_gluCheckExtension
+      ((const GLubyte *) "GL_OES_texture_npot", extensions) ||
+    jwzgles_gluCheckExtension // From PixelFlinger 1.4
+      ((const GLubyte *) "GL_ARB_texture_non_power_of_two", extensions);
+
+  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));
+  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);
+  v->bits_per_rgb = 8;
+  d->screen->visual = v;
+
+  d->timers_data = jwxyz_sources_init (XtDisplayToApplicationContext (d));
+
+  d->window_background = BlackPixel(d,0);
+
+  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);
+  }
+  // In case a GL hack wants to use X11 to draw offscreen, the rect_texture is available.
+  Assert (d->main_window == w, "Uh-oh.");
+  glGenTextures (1, &d->rect_texture);
+  // TODO: Check for (ARB|EXT|NV)_texture_rectangle. (All three are alike.)
+  // Rectangle textures should be present on OS X with the following exceptions:
+  // - Generic renderer on PowerPC OS X 10.4 and earlier
+  // - ATI Rage 128
+  glBindTexture (d->gl_texture_target, d->rect_texture);
+  // TODO: This is all somewhere else. Refactor.
+  glTexParameteri (d->gl_texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+  glTexParameteri (d->gl_texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+  // This might be redundant for rectangular textures.
+# ifndef HAVE_JWZGLES
+  const GLint wrap = GL_CLAMP;
+# else  // HAVE_JWZGLES
+  const GLint wrap = GL_CLAMP_TO_EDGE;
+# endif // HAVE_JWZGLES
+
+  // In OpenGL, CLAMP_TO_EDGE is OpenGL 1.2 or GL_SGIS_texture_edge_clamp.
+  // This is always present with OpenGL ES.
+  glTexParameteri (d->gl_texture_target, GL_TEXTURE_WRAP_S, wrap);
+  glTexParameteri (d->gl_texture_target, GL_TEXTURE_WRAP_T, wrap);
+
+  jwxyz_assert_display(d);
+  return d;
+}
+
+void
+jwxyz_free_display (Display *dpy)
+{
+  /* TODO: Go over everything. */
+
+  jwxyz_sources_free (dpy->timers_data);
+
+# ifndef USE_IPHONE
+  {
+    // Find us in live_displays and clear that slot.
+    int size = ScreenCount(dpy);
+    int i;
+    for (i = 0; i < size; i++) {
+      if (dpy == jwxyz_live_displays[i]) {
+        jwxyz_live_displays[i] = 0;
+        break;
+      }
+    }
+    if (i >= size) abort();
+  }
+# endif // !USE_IPHONE
+
+  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
+jwxyz_window_resized (Display *dpy)
+{
+  const XRectangle *new_frame = jwxyz_frame (dpy->main_window);
+  unsigned new_width = new_frame->width;
+  unsigned new_height = new_frame->height;
+
+  Assert (new_width, "jwxyz_window_resized: No width.");
+  Assert (new_height, "jwxyz_window_resized: No height.");
+
+/*if (cgc) w->cgc = cgc;
+  Assert (w->cgc, "no CGContext"); */
+
+  Log("resize: %d, %d\n", new_width, new_height);
+
+  jwxyz_bind_drawable (dpy, dpy->main_window, dpy->main_window);
+
+  // TODO: What does the iPhone need?
+  
+  // iOS only: If the main_window is not the current_drawable, then set_matrices
+  // was already called in bind_drawable.
+  jwxyz_set_matrices (dpy, new_width, new_height, True);
+
+/*
+  GLint draw_buffer;
+  glGetIntegerv (GL_DRAW_BUFFER, &draw_buffer);
+  
+  glDrawBuffer (GL_FRONT);
+  glClearColor (1, 0, 1, 0);
+  glClear (GL_COLOR_BUFFER_BIT);
+  glDrawBuffer (GL_BACK);
+  glClearColor (0, 1, 1, 0);
+  glClear (GL_COLOR_BUFFER_BIT);
+  
+  glDrawBuffer (draw_buffer); */
+  
+  // Stylish and attractive purple!
+  // glClearColor (1, 0, 1, 0.5);
+  // glClear (GL_COLOR_BUFFER_BIT);
+  
+  invalidate_drawable_cache (dpy->main_window);
+}
+
+
+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 s? s->screen_number : 0;
+}
+
+int
+jwxyz_ScreenCount (Display *dpy)
+{
+  return dpy ? dpy->screen_count : 0;
+}
+
+unsigned long
+XBlackPixelOfScreen(Screen *screen)
+{
+  return screen->black;
+}
+
+unsigned long
+XWhitePixelOfScreen(Screen *screen)
+{
+  return screen->white;
+}
+
+unsigned long
+XCellsOfScreen(Screen *screen)
+{
+  Visual *v = screen->visual;
+  return v->red_mask | v->green_mask | v->blue_mask;
+}
+
+
+/* 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
+*/
+
+static void
+set_clip_mask (GC gc)
+{
+  Assert (!gc->gcv.clip_mask, "set_gc: TODO");
+}
+
+static void
+set_function (int function)
+{
+  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
+}
+
+
+static void
+set_color (Display *dpy, unsigned long pixel, unsigned int depth,
+           Bool alpha_allowed_p)
+{
+  jwxyz_validate_pixel (dpy, pixel, depth, alpha_allowed_p);
+
+  if (depth == 1) {
+    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
+  }
+}
+
+/* Pushes a GC context; sets Function, ClipMask, and color.
+ */
+static void
+set_color_gc (Display *dpy, GC gc, unsigned long color)
+{
+  // GC is NULL for XClearArea and XClearWindow.
+  unsigned int depth;
+  int function;
+  if (gc) {
+    function = gc->gcv.function;
+    depth = gc->depth;
+    set_clip_mask (gc);
+  } else {
+    function = GXcopy;
+    depth = visual_depth (NULL, NULL);
+    // TODO: Set null clip mask here.
+  }
+
+  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;
+  }
+
+  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_color_gc (dpy, gc, gc->gcv.foreground);
+}
+
+static void
+next_point(short *v, XPoint p, int mode)
+{
+  switch (mode) {
+    case CoordModeOrigin:
+      v[0] = p.x;
+      v[1] = p.y;
+      break;
+    case CoordModePrevious:
+      v[0] += p.x;
+      v[1] += p.y;
+      break;
+    default:
+      Assert (False, "next_point: bad mode");
+      break;
+  }
+}
+
+int
+XDrawPoints (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.
+  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)
+{
+#ifdef HAVE_JWZGLES
+  return dpy->screen->pixel_format;
+#else
+  return GL_RGBA;
+#endif
+}
+
+static GLenum gl_pixel_type(const Display *dpy)
+{
+  return dpy->screen->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);
+}
+
+static void set_white (void)
+{
+#ifdef HAVE_JWZGLES
+  glColor4f (1, 1, 1, 1);
+#else
+  glColor3ub (0xff, 0xff, 0xff);
+#endif
+}
+
+
+static GLsizei to_pow2 (size_t x);
+
+
+void
+jwxyz_gl_copy_area_copy_tex_image (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)
+{
+  const XRectangle *src_frame = jwxyz_frame (src);
+
+  Assert(gc->gcv.function == GXcopy, "XCopyArea: Unknown function");
+
+  jwxyz_bind_drawable (dpy, dpy->main_window, src);
+
+#  if defined HAVE_COCOA && !defined USE_IPHONE
+  /* TODO: Does this help? */
+  /* glFinish(); */
+#  endif
+
+  unsigned tex_w = width, tex_h = height;
+  if (!dpy->gl_texture_npot_p) {
+    tex_w = to_pow2(tex_w);
+    tex_h = to_pow2(tex_h);
+  }
+
+  GLint internalformat = texture_internalformat(dpy);
+
+  glBindTexture (dpy->gl_texture_target, dpy->rect_texture);
+
+  if (tex_w == width && tex_h == height) {
+    glCopyTexImage2D (dpy->gl_texture_target, 0, internalformat,
+                      src_x, src_frame->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);
+    glCopyTexSubImage2D (dpy->gl_texture_target, 0, 0, 0,
+                         src_x, src_frame->height - src_y - height,
+                         width, height);
+  }
+
+  jwxyz_bind_drawable (dpy, dpy->main_window, dst);
+  set_white ();
+  glBindTexture (dpy->gl_texture_target, dpy->rect_texture);
+  glEnable (dpy->gl_texture_target);
+
+  glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+  glEnableClientState (GL_VERTEX_ARRAY);
+    
+  /* TODO: Copied from XPutImage. Refactor. */
+  /* TODO: EXT_draw_texture or whatever it's called. */
+  GLfloat vertices[4][2] =
+  {
+    {dst_x, dst_y},
+    {dst_x, dst_y + height},
+    {dst_x + width, dst_y + height},
+    {dst_x + width, dst_y}
+  };
+  
+#ifdef HAVE_JWZGLES
+  static const GLshort tex_coords[4][2] = {{0, 1}, {0, 0}, {1, 0}, {1, 1}};
+#else
+  GLshort tex_coords[4][2] = {{0, height}, {0, 0}, {width, 0}, {width, height}};
+#endif
+
+  glVertexPointer (2, GL_FLOAT, 0, vertices);
+  glTexCoordPointer (2, GL_SHORT, 0, tex_coords);
+  glDrawArrays (GL_TRIANGLE_FAN, 0, 4);
+  
+  clear_texture (dpy);
+  
+  glDisable (dpy->gl_texture_target);
+}
+
+void
+jwxyz_gl_copy_area_read_pixels (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)
+{
+# if 1
+  XImage *img = XGetImage (dpy, src, src_x, src_y, width, height, ~0, ZPixmap);
+  XPutImage (dpy, dst, gc, img, 0, 0, dst_x, dst_y, width, height);
+  XDestroyImage (img);
+# endif
+
+# if 0
+  /* Something may or may not be broken in here. (shrug) */
+  bind_drawable(dpy, src);
+
+  /* Error checking would be nice. */
+  void *pixels = malloc (src_rect.size.width * 4 * src_rect.size.height);
+
+  glPixelStorei (GL_PACK_ROW_LENGTH, 0);
+  glPixelStorei (GL_PACK_ALIGNMENT, 4);
+
+  glReadPixels (src_rect.origin.x, dst_frame.size.height - (src_rect.origin.y + src_rect.size.height),
+                src_rect.size.width, src_rect.size.height,
+                GL_RGBA, GL_UNSIGNED_BYTE, // TODO: Pick better formats.
+                pixels);
+
+  bind_drawable (dpy, dst);
+
+  glPixelZoom (1.0f, 1.0f);
+
+  glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
+  glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
+
+  glRasterPos2i (dst_rect.origin.x, dst_rect.origin.y + dst_rect.size.height);
+  glDrawPixels (dst_rect.size.width, dst_rect.size.height,
+                GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+
+  free(pixels);
+# endif
+}
+
+
+#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)
+{
+  jwxyz_bind_drawable (dpy, dpy->main_window, d);
+  set_fg_gc (dpy, gc);
+
+  /* TODO: Thick lines
+   * Zero-length line segments
+   * Paths with zero length total (Remember line width, cap style.)
+   * Closed loops
+   */
+  
+  if (!count)
+    return 0;
+
+  GLshort *vertices = malloc(2 * sizeof(GLshort) * count); // TODO malloc NULL sigh
+  
+  glMatrixMode (GL_MODELVIEW);
+  glTranslatef (0.5f, 0.5f, 0);
+  
+  short p[2] = {0, 0};
+  for (unsigned i = 0; i < count; i++) {
+    next_point (p, points[i], mode);
+    vertices[2 * i] = p[0];
+    vertices[2 * i + 1] = p[1];
+  }
+  
+  glEnableClientState (GL_VERTEX_ARRAY);
+  glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+  glVertexPointer (2, GL_SHORT, 0, vertices);
+  glDrawArrays (GL_LINE_STRIP, 0, count);
+  
+  free (vertices);
+
+  if (gc->gcv.cap_style != CapNotLast) {
+    // TODO: How does this look with multisampling?
+    // TODO: Disable me for closed loops.
+    glVertexPointer (2, GL_SHORT, 0, p);
+    glDrawArrays (GL_POINTS, 0, 1);
+  }
+
+  glLoadIdentity ();
+  
+  return 0;
+}
+
+
+int
+XDrawSegments (Display *dpy, Drawable d, GC gc, XSegment *segments, int count)
+{
+  jwxyz_bind_drawable (dpy, dpy->main_window, d);
+  set_fg_gc (dpy, gc);
+  
+  /* TODO: 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);
+  }
+  
+  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++;
+  }
+  CGContextStrokePath (cgc);
+  pop_gc (d, gc);
+  invalidate_drawable_cache (d); */
+  return 0;
+}
+
+
+int
+XClearWindow (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;
+}
+
+int
+XSetWindowBackground (Display *dpy, Window w, unsigned long pixel)
+{
+  Assert (w == dpy->main_window, "not a window");
+  jwxyz_validate_pixel (dpy, pixel, visual_depth (NULL, NULL), False);
+  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)
+{
+  jwxyz_bind_drawable (dpy, dpy->main_window, d);
+  set_color_gc (dpy, gc, pixel);
+/*
+  glBegin(GL_QUADS);
+  for (unsigned i = 0; i != nrectangles; ++i) {
+    const XRectangle *r = &rectangles[i];
+    glVertex2i(r->x, r->y);
+    glVertex2i(r->x, r->y + r->height);
+    glVertex2i(r->x + r->width, r->y + r->height);
+    glVertex2i(r->x + r->width, r->y);
+  }
+  glEnd(); */
+  
+  glEnableClientState (GL_VERTEX_ARRAY);
+  glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+    
+  for (unsigned long i = 0; i != nrectangles; ++i)
+  {
+    const XRectangle *r = &rectangles[i];
+    
+    GLfloat coords[4][2] =
+    {
+      {r->x, r->y},
+      {r->x, r->y + r->height},
+      {r->x + r->width, r->y + r->height},
+      {r->x + r->width, r->y}
+    };
+    
+    // TODO: Several rects at once. Maybe even tune for XScreenSaver workloads.
+    glVertexPointer (2, GL_FLOAT, 0, coords);
+    jwxyz_assert_gl ();
+    glDrawArrays (GL_TRIANGLE_FAN, 0, 4);
+    jwxyz_assert_gl ();
+  }
+}
+
+
+int
+XClearArea (Display *dpy, Window win, int x, int y, int w, int h, Bool exp)
+{
+  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);
+  
+  // TODO: Re-implement the GLU tesselation functions.
+
+  /* Complex: Pedal, and for some reason Attraction, Mountain, Qix, SpeedMine, Starfish
+   * Nonconvex: Goop, Pacman, Rocks, Speedmine
+   */
+  
+  Assert(shape == Convex, "XFillPolygon: (TODO) Unimplemented shape");
+  
+  // TODO: Feed vertices straight to OpenGL for CoordModeOrigin.
+  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];
+  }
+
+  glEnableClientState (GL_VERTEX_ARRAY);
+  glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+  
+  glVertexPointer (2, GL_SHORT, 0, vertices);
+  glDrawArrays (GL_TRIANGLE_FAN, 0, npoints);
+  
+  free(vertices);
+
+  /*
+  CGRect wr = d->frame;
+  int i;
+  push_fg_gc (dpy, d, gc, YES);
+  CGContextRef cgc = d->cgc;
+  CGContextBeginPath (cgc);
+  float x = 0, y = 0;
+  for (i = 0; i < npoints; i++) {
+    if (i > 0 && mode == CoordModePrevious) {
+      x += points[i].x;
+      y -= points[i].y;
+    } else {
+      x = wr.origin.x + points[i].x;
+      y = wr.origin.y + wr.size.height - points[i].y;
+    }
+        
+    if (i == 0)
+      CGContextMoveToPoint (cgc, x, y);
+    else
+      CGContextAddLineToPoint (cgc, x, y);
+  }
+  CGContextClosePath (cgc);
+  if (gc->gcv.fill_rule == EvenOddRule)
+    CGContextEOFillPath (cgc);
+  else
+    CGContextFillPath (cgc);
+  pop_gc (d, gc);
+  invalidate_drawable_cache (d);
+  */
+  return 0;
+}
+
+#define radians(DEG) ((DEG) * M_PI / 180.0)
+#define degrees(RAD) ((RAD) * 180.0 / M_PI)
+
+static void
+arc_xy(GLfloat *p, double cx, double cy, double w2, double h2, double theta)
+{
+  p[0] = cos(theta) * w2 + cx;
+  p[1] = -sin(theta) * h2 + cy;
+}
+
+static unsigned
+mod_neg(int a, unsigned b)
+{
+  /* Normal modulus is implementation defined for negative numbers. This is 
+   * well-defined such that the repeating pattern for a >= 0 is maintained for 
+   * a < 0. */
+  return a < 0 ? (b - 1) - (-(a + 1) % b) : a % b;
+}
+
+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)
+{
+  jwxyz_bind_drawable (dpy, dpy->main_window, d);
+  set_fg_gc(dpy, 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...) */
+
+  double w2 = width * 0.5f, h2 = height * 0.5f;
+  double a, b; /* Semi-major/minor axes. */
+  if(w2 > h2) {
+    a = w2;
+    b = h2;
+  } else {
+    a = h2;
+    b = w2;
+  }
+  
+  const double two_pi = 2 * M_PI;
+
+  double amb = a - b, apb = a + b;
+  double h = (amb * amb) / (apb * apb);
+  // TODO: Math cleanup.
+  double C_approx = M_PI * apb * (1 + 3 * h / (10 + sqrtf(4 - 3 * h)));
+  double segments_f = 4 * sqrtf(C_approx / (2 * M_PI));
+
+  // TODO: Explain how drawing works what with the points of overlapping arcs
+  // matching up.
+#if 1
+  unsigned segments_360 = segments_f;
+  
+  /* TODO: angle2 == 0. This is a tilted square with CapSquare. */
+  /* TODO: color, thick lines, CapNotLast for thin lines */
+  /* TODO: Transformations. */
+
+  double segment_angle = two_pi / segments_360;
+
+  const unsigned deg64 = 360 * 64;
+  const double rad_from_deg64 = two_pi / deg64;
+  
+  if (angle2 < 0) {
+    angle1 += angle2;
+    angle2 = -angle2;
+  }
+
+  angle1 = mod_neg(angle1, deg64); // TODO: Is this OK? Consider negative numbers.
+
+  if (angle2 > deg64)
+    angle2 = deg64; // TODO: Handle circles special.
+  
+  double
+    angle1_f = angle1 * rad_from_deg64,
+    angle2_f = angle2 * rad_from_deg64;
+  
+  if (angle2_f > two_pi) // TODO: Move this up.
+    angle2_f = two_pi;
+  
+  double segment1_angle_part = fmodf(angle1_f, segment_angle);
+  
+  unsigned segment1 = ((angle1_f - segment1_angle_part) / segment_angle) + 1.5;
+
+  double angle_2r = angle2_f - segment1_angle_part;
+  unsigned segments = angle_2r / segment_angle;
+  
+  GLfloat cx = x + w2, cy = y + h2;
+
+  GLfloat *data = malloc((segments + 3) * sizeof(GLfloat) * 2); // TODO: Check result.
+  
+  GLfloat *data_ptr = data;
+  if (fill_p) {
+    data_ptr[0] = cx;
+    data_ptr[1] = cy;
+    data_ptr += 2;
+  }
+  
+  arc_xy (data_ptr, cx, cy, w2, h2, angle1_f);
+  data_ptr += 2;
+  
+  for (unsigned s = 0; s != segments; ++s) {
+    // TODO: Make sure values of theta for the following arc_xy call are between
+    // angle1_f and angle1_f + angle2_f.
+    arc_xy (data_ptr, cx, cy, w2, h2, (segment1 + s) * segment_angle);
+    data_ptr += 2;
+  }
+  
+  arc_xy (data_ptr, cx, cy, w2, h2, angle1_f + angle2_f);
+  data_ptr += 2;
+
+  glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+  glEnableClientState (GL_VERTEX_ARRAY);
+  
+  glVertexPointer (2, GL_FLOAT, 0, data);
+  glDrawArrays (fill_p ? GL_TRIANGLE_FAN : GL_LINE_STRIP,
+                0,
+                (GLsizei)((data_ptr - data) / 2));
+
+  free(data);
+  
+#endif
+  
+#if 0
+  unsigned segments = segments_f * (fabs(angle2) / (360 * 64));
+  glBegin (fill_p ? GL_TRIANGLE_FAN : GL_LINE_STRIP);
+  
+  if (fill_p /* && gc->gcv.arc_mode == ArcPieSlice */)
+    glVertex2f (cx, cy);
+  
+  /* TODO: This should fix the middle points of the arc so that the starting and ending points are OK. */
+  
+  float to_radians = 2 * M_PI / (360 * 64);
+  float theta = angle1 * to_radians, d_theta = angle2 * to_radians / segments;
+  
+  for (unsigned s = 0; s != segments + 1; ++s) /* TODO: This is the right number of segments, yes? */
+  {
+    glVertex2f(cos(theta) * w2 + cx, -sin(theta) * h2 + cy);
+    theta += d_theta;
+  }
+  
+  glEnd ();
+#endif
+  
+  return 0;
+}
+
+
+XGCValues *
+jwxyz_gc_gcv (GC gc)
+{
+  return &gc->gcv;
+}
+
+
+unsigned int
+jwxyz_gc_depth (GC gc)
+{
+  return gc->depth;
+}
+
+
+GC
+XCreateGC (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);
+
+  jwxyz_gcv_defaults (dpy, &gc->gcv, gc->depth);
+  XChangeGC (dpy, gc, mask, xgcv);
+  return gc;
+}
+
+
+int
+XFreeGC (Display *dpy, GC gc)
+{
+  if (gc->gcv.font)
+    XUnloadFont (dpy, gc->gcv.font);
+
+  // 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);
+  }
+*/
+  free (gc);
+  return 0;
+}
+
+
+/*
+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++];
+}
+*/
+
+// Copied and pasted from OSX/XScreenSaverView.m
+static GLsizei
+to_pow2 (size_t x)
+{
+  if (x <= 1)
+    return 1;
+
+  size_t mask = (size_t)-1;
+  unsigned bits = sizeof(x) * CHAR_BIT;
+  unsigned log2 = bits;
+
+  --x;
+  while (bits) {
+    if (!(x & mask)) {
+      log2 -= bits;
+      x <<= bits;
+    }
+
+    bits >>= 1;
+    mask <<= bits;
+  }
+
+  return 1 << log2;
+}
+
+
+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)
+{
+  jwxyz_assert_display (dpy);
+  const XRectangle *wr = jwxyz_frame (d);
+
+  Assert (gc, "no GC");
+  Assert ((w < 65535), "improbably large width");
+  Assert ((h < 65535), "improbably large height");
+  Assert ((src_x  < 65535 && src_x  > -65535), "improbably large src_x");
+  Assert ((src_y  < 65535 && src_y  > -65535), "improbably large src_y");
+  Assert ((dest_x < 65535 && dest_x > -65535), "improbably large dest_x");
+  Assert ((dest_y < 65535 && dest_y > -65535), "improbably large dest_y");
+
+  // Clip width and height to the bounds of the Drawable
+  //
+  if (dest_x + w > wr->width) {
+    if (dest_x > wr->width)
+      return 0;
+    w = wr->width - dest_x;
+  }
+  if (dest_y + h > wr->height) {
+    if (dest_y > wr->height)
+      return 0;
+    h = wr->height - dest_y;
+  }
+  if (w <= 0 || h <= 0)
+    return 0;
+
+  // Clip width and height to the bounds of the XImage
+  //
+  if (src_x + w > ximage->width) {
+    if (src_x > ximage->width)
+      return 0;
+    w = ximage->width - src_x;
+  }
+  if (src_y + h > ximage->height) {
+    if (src_y > ximage->height)
+      return 0;
+    h = ximage->height - src_y;
+  }
+  if (w <= 0 || h <= 0)
+    return 0;
+
+  /* Assert (d->win */
+
+  if (jwxyz_dumb_drawing_mode(dpy, d, gc, dest_x, dest_y, w, h))
+    return 0;
+
+  jwxyz_bind_drawable (dpy, dpy->main_window, d);
+  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;
+*/
+
+  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);
+
+    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;
+
+    /* GL_UNPACK_ROW_LENGTH is not allowed to be negative. (sigh) */
+# ifndef HAVE_JWZGLES
+    glPixelStorei (GL_UNPACK_ROW_LENGTH, src_w);
+    src_w = w;
+# endif
+
+    glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
+
+# 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);
+    }
+
+    GLint internalformat = texture_internalformat(dpy);
+
+    glBindTexture (dpy->gl_texture_target, dpy->rect_texture);
+
+    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);
+    }
+    
+    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);
+
+    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
+#  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
+    glEnable (GL_BLEND);
+    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+    glDrawArrays (GL_TRIANGLE_FAN, 0, 4);
+
+    glDisable (GL_BLEND);
+
+//  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);
+# 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;
+}
+
+/* At the moment nothing actually uses XGetSubImage. */
+/* #### Actually lots of things call XGetImage, which calls XGetSubImage.
+   E.g., 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. */
+static 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)
+{
+  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_bind_drawable (dpy, dpy->main_window, d);
+  
+  // TODO: What if this reads off the edge? What is supposed to happen?
+
+  {
+    // In case the caller tries to write off the edge.
+    int
+      max_width = dest_image->width - dest_x,
+      max_height = dest_image->height - dest_y;
+
+    if (width > max_width) {
+      width = max_width;
+    }
+    
+    if (height > max_height) {
+      height = max_height;
+    }
+  }
+  
+  Assert (jwxyz_drawable_depth (d) == dest_image->depth, "XGetSubImage: depth mismatch");
+  
+  if (dest_image->depth == visual_depth (NULL, NULL)) {
+    Assert (!(dest_image->bytes_per_line % 4), "XGetSubImage: bytes_per_line not divisible by 4");
+    unsigned pixels_per_line = dest_image->bytes_per_line / 4;
+#ifdef HAVE_JWZGLES
+    Assert (pixels_per_line == width, "XGetSubImage: (TODO) pixels_per_line != width");
+#else
+    glPixelStorei (GL_PACK_ROW_LENGTH, pixels_per_line);
+#endif
+    glPixelStorei (GL_PACK_ALIGNMENT, 4);
+    
+    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);
+
+    /* Flip this upside down. :( */
+    uint32_t *top = dest_data;
+    uint32_t *bottom = dest_data + pixels_per_line * (height - 1);
+    for (unsigned y = height / 2; y; --y) {
+      for (unsigned x = 0; x != width; ++x) {
+        uint32_t px = top[x];
+        top[x] = bottom[x];
+        bottom[x] = px;
+      }
+      top += pixels_per_line;
+      bottom -= pixels_per_line;
+    }
+  } else {
+
+    /* TODO: Actually get pixels. */
+
+    Assert (!(dest_x % 8), "XGetSubImage: dest_x not byte-aligned");
+    uint8_t *dest_data =
+      (uint8_t *)dest_image->data + dest_image->bytes_per_line * dest_y
+      + dest_x / 8;
+    for (unsigned y = height / 2; y; --y) {
+      memset (dest_data, y & 1 ? 0x55 : 0xAA, width / 8);
+      dest_data += dest_image->bytes_per_line;
+    }
+  }
+
+  return dest_image;
+}
+
+XImage *
+XGetImage (Display *dpy, Drawable d, int x, int y,
+           unsigned int width, unsigned int height,
+           unsigned long plane_mask, int format)
+{
+  unsigned depth = jwxyz_drawable_depth (d);
+  XImage *image = XCreateImage (dpy, 0, depth, format, 0, 0, width, height,
+                                0, 0);
+  image->data = (char *) malloc (height * image->bytes_per_line);
+
+  return XGetSubImage (dpy, d, x, y, width, height, plane_mask, format,
+                       image, 0, 0);
+}
+
+/* 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)
+{
+  if (!p) return 0;
+  Assert (p->type == PIXMAP, "not a pixmap");
+
+  Pixmap p2 = 0;
+
+  Window root;
+  int x, y;
+  unsigned int width, height, border_width, depth;
+  if (XGetGeometry (dpy, p, &root,
+                    &x, &y, &width, &height, &border_width, &depth)) {
+    XGCValues gcv;
+    gcv.function = GXcopy;
+    GC gc = XCreateGC (dpy, p, GCFunction, &gcv);
+    if (gc) {
+      p2 = XCreatePixmap (dpy, p, width, height, depth);
+      if (p2)
+        XCopyArea (dpy, p, p2, gc, 0, 0, width, height, 0, 0);
+      XFreeGC (dpy, gc);
+    }
+  }
+
+  Assert (p2, "could not copy pixmap");
+
+  return p2;
+}
+#endif
+
+
+// This is XQueryFont, but for the XFontStruct embedded in 'Font'
+//
+static void
+query_font (Font fid)
+{
+  if (!fid || !fid->native_font) {
+    Assert (0, "no native font in fid");
+    return;
+  }
+
+  int first = 32;
+  int last = 255;
+
+  Display *dpy = fid->dpy;
+  void *native_font = fid->native_font;
+
+  XFontStruct *f = &fid->metrics;
+  XCharStruct *min = &f->min_bounds;
+  XCharStruct *max = &f->max_bounds;
+
+  f->fid               = fid;
+  f->min_char_or_byte2 = first;
+  f->max_char_or_byte2 = last;
+  f->default_char      = 'M';
+  f->ascent            = fid->ascent;
+  f->descent           = fid->descent;
+
+  min->width    = 32767;  // set to smaller values in the loop
+  min->ascent   = 32767;
+  min->descent  = 32767;
+  min->lbearing = 32767;
+  min->rbearing = 32767;
+
+  f->per_char = (XCharStruct *) calloc (last-first+2, sizeof (XCharStruct));
+
+  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, GL_FALSE, cs, 0);
+
+    max->width    = MAX (max->width,    cs->width);
+    max->ascent   = MAX (max->ascent,   cs->ascent);
+    max->descent  = MAX (max->descent,  cs->descent);
+    max->lbearing = MAX (max->lbearing, cs->lbearing);
+    max->rbearing = MAX (max->rbearing, cs->rbearing);
+
+    min->width    = MIN (min->width,    cs->width);
+    min->ascent   = MIN (min->ascent,   cs->ascent);
+    min->descent  = MIN (min->descent,  cs->descent);
+    min->lbearing = MIN (min->lbearing, cs->lbearing);
+    min->rbearing = MIN (min->rbearing, cs->rbearing);
+/*
+    Log (" %3d %c: w=%3d lb=%3d rb=%3d as=%3d ds=%3d\n",
+         i, i, cs->width, cs->lbearing, cs->rbearing, 
+         cs->ascent, cs->descent);
+ */
+  }
+}
+
+
+// Since 'Font' includes the metrics, this just makes a copy of that.
+//
+XFontStruct *
+XQueryFont (Display *dpy, Font fid)
+{
+  // copy XFontStruct
+  XFontStruct *f = (XFontStruct *) calloc (1, sizeof(*f));
+  *f = fid->metrics;
+  f->fid = fid;
+
+  // build XFontProps
+  f->n_properties = 1;
+  f->properties = malloc (sizeof(*f->properties) * f->n_properties);
+  f->properties[0].name = XA_FONT;
+  Assert (sizeof (f->properties[0].card32) >= sizeof (char *),
+          "atoms probably needs a real implementation");
+  // If XInternAtom is ever implemented, use it here.
+  f->properties[0].card32 = (unsigned long)(char *)fid->xa_font;
+
+  // copy XCharStruct array
+  int size = (f->max_char_or_byte2 - f->min_char_or_byte2) + 1;
+  f->per_char = (XCharStruct *) calloc (size + 2, sizeof (XCharStruct));
+
+  memcpy (f->per_char, fid->metrics.per_char,
+          size * sizeof (XCharStruct));
+
+  return f;
+}
+
+
+static Font
+copy_font (Font fid)
+{
+  fid->refcount++;
+  return fid;
+}
+
+
+#if 0
+
+
+static NSArray *
+font_family_members (NSString *family_name)
+{
+# ifndef USE_IPHONE
+  return [[NSFontManager sharedFontManager]
+          availableMembersOfFontFamily:family_name];
+# else
+  return [UIFont fontNamesForFamilyName:family_name];
+# endif
+}
+
+
+static NSString *
+default_font_family (NSFontTraitMask require)
+{
+  return require & NSFixedPitchFontMask ? @"Courier" : @"Verdana";
+}
+
+
+static NSFont *
+try_font (NSFontTraitMask traits, NSFontTraitMask mask,
+          NSString *family_name, float size,
+          char **name_ret)
+{
+  Assert (size > 0, "zero font size");
+
+  NSArray *family_members = font_family_members (family_name);
+  if (!family_members.count)
+    family_members = font_family_members (default_font_family (traits));
+
+# ifndef USE_IPHONE
+  for (unsigned k = 0; k != family_members.count; ++k) {
+
+    NSArray *member = [family_members objectAtIndex:k];
+    NSFontTraitMask font_mask =
+    [(NSNumber *)[member objectAtIndex:3] unsignedIntValue];
+
+    if ((font_mask & mask) == traits) {
+
+      NSString *name = [member objectAtIndex:0];
+      NSFont *f = [NSFont fontWithName:name size:size];
+      if (!f)
+        break;
+
+      /* Don't use this font if it (probably) doesn't include ASCII characters.
+       */
+      NSStringEncoding enc = [f mostCompatibleStringEncoding];
+      if (! (enc == NSUTF8StringEncoding ||
+             enc == NSISOLatin1StringEncoding ||
+             enc == NSNonLossyASCIIStringEncoding ||
+             enc == NSISOLatin2StringEncoding ||
+             enc == NSUnicodeStringEncoding ||
+             enc == NSWindowsCP1250StringEncoding ||
+             enc == NSWindowsCP1252StringEncoding ||
+             enc == NSMacOSRomanStringEncoding)) {
+        // NSLog(@"skipping \"%@\": encoding = %d", name, enc);
+        break;
+      }
+      // NSLog(@"using \"%@\": %d", name, enc);
+
+      // *name_ret = strdup ([name cStringUsingEncoding:NSUTF8StringEncoding]);
+      *name_ret = strdup (name.UTF8String);
+      return f;
+    }
+  }
+# else // USE_IPHONE
+
+  for (NSString *fn in family_members) {
+# define MATCH(X) \
+         ([fn rangeOfString:X options:NSCaseInsensitiveSearch].location \
+         != NSNotFound)
+
+    // The magic invocation for getting font names is
+    // [[UIFontDescriptor
+    //   fontDescriptorWithFontAttributes:@{UIFontDescriptorNameAttribute: name}]
+    //  symbolicTraits]
+    // ...but this only works on iOS 7 and later.
+    NSFontTraitMask font_mask = 0;
+    if (MATCH(@"Bold"))
+      font_mask |= NSBoldFontMask;
+    if (MATCH(@"Italic") || MATCH(@"Oblique"))
+      font_mask |= NSItalicFontMask;
+
+    if ((font_mask & mask) == traits) {
+
+      /* Check if it can do ASCII.  No good way to accomplish this!
+         These are fonts present in iPhone Simulator as of June 2012
+         that don't include ASCII.
+       */
+      if (MATCH(@"AppleGothic") ||     // Korean
+          MATCH(@"Dingbats") ||                // Dingbats
+          MATCH(@"Emoji") ||           // Emoticons
+          MATCH(@"Geeza") ||           // Arabic
+          MATCH(@"Hebrew") ||          // Hebrew
+          MATCH(@"HiraKaku") ||                // Japanese
+          MATCH(@"HiraMin") ||         // Japanese
+          MATCH(@"Kailasa") ||         // Tibetan
+          MATCH(@"Ornaments") ||       // Dingbats
+          MATCH(@"STHeiti")            // Chinese
+       )
+         break;
+
+      *name_ret = strdup (fn.UTF8String);
+      return [UIFont fontWithName:fn size:size];
+    }
+# undef MATCH
+  }
+
+# endif
+
+  return NULL;
+}
+
+
+
+/* On Cocoa and iOS, fonts may be specified as "Georgia Bold 24" instead
+   of XLFD strings; also they can be comma-separated strings with multiple
+   font names.  First one that exists wins.
+ */
+static NSFont *
+try_native_font (const char *name, float scale,
+                 char **name_ret, float *size_ret, char **xa_font)
+{
+  if (!name) return 0;
+  const char *spc = strrchr (name, ' ');
+  if (!spc) return 0;
+
+  NSFont *f = 0;
+  char *token = strdup (name);
+  char *name2;
+
+  while ((name2 = strtok (token, ","))) {
+    token = 0;
+
+    while (*name2 == ' ' || *name2 == '\t' || *name2 == '\n')
+      name2++;
+
+    spc = strrchr (name2, ' ');
+    if (!spc) continue;
+
+    int dsize = 0;
+    if (1 != sscanf (spc, " %d ", &dsize))
+      continue;
+    float size = dsize;
+
+    if (size <= 4) continue;
+
+    size *= scale;
+
+    name2[strlen(name2) - strlen(spc)] = 0;
+
+    NSString *nsname = [NSString stringWithCString:name2
+                                          encoding:NSUTF8StringEncoding];
+    f = [NSFont fontWithName:nsname size:size];
+    if (f) {
+      *name_ret = name2;
+      *size_ret = size;
+      *xa_font = strdup (name); // Maybe this should be an XLFD?
+      break;
+    } else {
+      NSLog(@"No native font: \"%@\" %.0f", nsname, size);
+    }
+  }
+
+  free (token);
+  return f;
+}
+
+
+/* Returns a random font in the given size and face.
+ */
+static NSFont *
+random_font (NSFontTraitMask traits, NSFontTraitMask mask,
+             float size, NSString **family_ret, char **name_ret)
+{
+
+# ifndef USE_IPHONE
+  // Providing Unbold or Unitalic in the mask for availableFontNamesWithTraits
+  // returns an empty list, at least on a system with default fonts only.
+  NSArray *families = [[NSFontManager sharedFontManager]
+                       availableFontFamilies];
+  if (!families) return 0;
+# else
+  NSArray *families = [UIFont familyNames];
+
+  // There are many dups in the families array -- uniquify it.
+  {
+    NSArray *sorted_families =
+    [families sortedArrayUsingSelector:@selector(compare:)];
+    NSMutableArray *new_families =
+    [NSMutableArray arrayWithCapacity:sorted_families.count];
+
+    NSString *prev_family = nil;
+    for (NSString *family in sorted_families) {
+      if ([family compare:prev_family])
+        [new_families addObject:family];
+    }
+
+    families = new_families;
+  }
+# endif // USE_IPHONE
+
+  long n = [families count];
+  if (n <= 0) return 0;
+
+  int j;
+  for (j = 0; j < n; j++) {
+    int i = random() % n;
+    NSString *family_name = [families objectAtIndex:i];
+
+    NSFont *result = try_font (traits, mask, family_name, size, name_ret);
+    if (result) {
+      [*family_ret release];
+      *family_ret = family_name;
+      [*family_ret retain];
+      return result;
+    }
+  }
+
+  // None of the fonts support ASCII?
+  return 0;
+}
+
+
+// Fonts need this. XDisplayHeightMM and friends should probably be consistent
+// with this as well if they're ever implemented.
+static const unsigned dpi = 75;
+
+
+static const char *
+xlfd_field_end (const char *s)
+{
+  const char *s2 = strchr(s, '-');
+  if (!s2)
+    s2 = s + strlen(s);
+  return s2;
+}
+
+
+static size_t
+xlfd_next (const char **s, const char **s2)
+{
+  if (!**s2) {
+    *s = *s2;
+  } else {
+    Assert (**s2 == '-', "xlfd parse error");
+    *s = *s2 + 1;
+    *s2 = xlfd_field_end (*s);
+  }
+
+  return *s2 - *s;
+}
+
+static NSFont *
+try_xlfd_font (const char *name, float scale,
+               char **name_ret, float *size_ret, char **xa_font)
+{
+  NSFont *nsfont = 0;
+  NSString *family_name = nil;
+  NSFontTraitMask require = 0, forbid = 0;
+  GLboolean rand  = GL_FALSE;
+  float size = 0;
+  char *ps_name = 0;
+
+  const char *s = (name ? name : "");
+
+  size_t L = strlen (s);
+# define CMP(STR) (L == strlen(STR) && !strncasecmp (s, (STR), L))
+# define UNSPEC   (L == 0 || L == 1 && *s == '*')
+  if      (CMP ("6x10"))     size = 8,  require |= NSFixedPitchFontMask;
+  else if (CMP ("6x10bold")) size = 8,  require |= NSFixedPitchFontMask | NSBoldFontMask;
+  else if (CMP ("fixed"))    size = 12, require |= NSFixedPitchFontMask;
+  else if (CMP ("9x15"))     size = 12, require |= NSFixedPitchFontMask;
+  else if (CMP ("9x15bold")) size = 12, require |= NSFixedPitchFontMask | NSBoldFontMask;
+  else if (CMP ("vga"))      size = 12, require |= NSFixedPitchFontMask;
+  else if (CMP ("console"))  size = 12, require |= NSFixedPitchFontMask;
+  else if (CMP ("gallant"))  size = 12, require |= NSFixedPitchFontMask;
+  else {
+
+    // Incorrect fields are ignored.
+
+    if (*s == '-')
+      ++s;
+    const char *s2 = xlfd_field_end(s);
+
+    // Foundry (ignore)
+
+    L = xlfd_next (&s, &s2); // Family name
+    // This used to substitute Georgia for Times. Now it doesn't.
+    if (CMP ("random")) {
+      rand = GL_TRUE;
+    } else if (CMP ("fixed")) {
+      require |= NSFixedPitchFontMask;
+      family_name = @"Courier";
+    } else if (!UNSPEC) {
+      family_name = [[[NSString alloc] initWithBytes:s
+                                              length:L
+                                            encoding:NSUTF8StringEncoding]
+                     autorelease];
+    }
+
+    L = xlfd_next (&s, &s2); // Weight name
+    if (CMP ("bold") || CMP ("demibold"))
+      require |= NSBoldFontMask;
+    else if (CMP ("medium") || CMP ("regular"))
+      forbid |= NSBoldFontMask;
+
+    L = xlfd_next (&s, &s2); // Slant
+    if (CMP ("i") || CMP ("o"))
+      require |= NSItalicFontMask;
+    else if (CMP ("r"))
+      forbid |= NSItalicFontMask;
+
+    xlfd_next (&s, &s2); // Set width name (ignore)
+    xlfd_next (&s, &s2); // Add style name (ignore)
+
+    xlfd_next (&s, &s2); // Pixel size (ignore)
+
+    xlfd_next (&s, &s2); // Point size
+    char *s3;
+    uintmax_t n = strtoumax(s, &s3, 10);
+    if (s2 == s3)
+      size = n / 10.0;
+
+    xlfd_next (&s, &s2); // Resolution X (ignore)
+    xlfd_next (&s, &s2); // Resolution Y (ignore)
+
+    xlfd_next (&s, &s2); // Spacing
+    if (CMP ("p"))
+      forbid |= NSFixedPitchFontMask;
+    else if (CMP ("m") || CMP ("c"))
+      require |= NSFixedPitchFontMask;
+
+    // Don't care about average_width or charset registry.
+  }
+# undef CMP
+# undef UNSPEC
+
+  if (!family_name && !rand)
+    family_name = default_font_family (require);
+
+  if (size < 6 || size > 1000)
+    size = 12;
+
+  size *= scale;
+
+  NSFontTraitMask mask = require | forbid;
+
+  if (rand) {
+    nsfont   = random_font (require, mask, size, &family_name, &ps_name);
+    [family_name autorelease];
+  }
+
+  if (!nsfont)
+    nsfont   = try_font (require, mask, family_name, size, &ps_name);
+
+  // if that didn't work, turn off attibutes until it does
+  // (e.g., there is no "Monaco-Bold".)
+  //
+  if (!nsfont && (mask & NSItalicFontMask)) {
+    require &= ~NSItalicFontMask;
+    mask &= ~NSItalicFontMask;
+    nsfont = try_font (require, mask, family_name, size, &ps_name);
+  }
+  if (!nsfont && (mask & NSBoldFontMask)) {
+    require &= ~NSBoldFontMask;
+    mask &= ~NSBoldFontMask;
+    nsfont = try_font (require, mask, family_name, size, &ps_name);
+  }
+  if (!nsfont && (mask & NSFixedPitchFontMask)) {
+    require &= ~NSFixedPitchFontMask;
+    mask &= ~NSFixedPitchFontMask;
+    nsfont = try_font (require, mask, family_name, size, &ps_name);
+  }
+
+  if (nsfont) {
+    *name_ret = ps_name;
+    *size_ret = size;
+    float actual_size = size / scale;
+    asprintf(xa_font, "-*-%s-%s-%c-*-*-%u-%u-%u-%u-%c-0-iso10646-1",
+             family_name.UTF8String,
+             (require & NSBoldFontMask) ? "bold" : "medium",
+             (require & NSItalicFontMask) ? 'o' : 'r',
+             (unsigned)(dpi * actual_size / 72.27 + 0.5),
+             (unsigned)(actual_size * 10 + 0.5), dpi, dpi,
+             (require & NSFixedPitchFontMask) ? 'm' : 'p');
+    return nsfont;
+  } else {
+    return 0;
+  }
+}
+
+#endif
+
+Font
+XLoadFont (Display *dpy, const char *name)
+{
+  Font fid = (Font) calloc (1, sizeof(*fid));
+  fid->refcount = 1;
+  fid->dpy = dpy;
+
+  // (TODO) float scale = 1;
+
+# ifdef USE_IPHONE
+  /* Since iOS screens are physically smaller than desktop screens, scale up
+     the fonts to make them more readable.
+
+     Note that X11 apps on iOS also have the backbuffer sized in points
+     instead of pixels, resulting in an effective X11 screen size of 768x1024
+     or so, even if the display has significantly higher resolution.  That is
+     unrelated to this hack, which is really about DPI.
+   */
+  /* scale = 2; */
+# endif
+
+  fid->dpy = dpy;
+  fid->native_font = jwxyz_load_native_font (dpy, name,
+                                             &fid->ps_name, &fid->size,
+                                             &fid->ascent, &fid->descent);
+  if (!fid->native_font) {
+    free (fid);
+    return 0;
+  }
+  query_font (fid);
+
+  return fid;
+}
+
+
+XFontStruct *
+XLoadQueryFont (Display *dpy, const char *name)
+{
+  Font fid = XLoadFont (dpy, name);
+  if (!fid) return 0;
+  return XQueryFont (dpy, fid);
+}
+
+int
+XUnloadFont (Display *dpy, Font fid)
+{
+  if (--fid->refcount < 0) abort();
+  if (fid->refcount > 0) return 0;
+
+  if (fid->native_font)
+    jwxyz_release_native_font (fid->dpy, fid->native_font);
+
+  if (fid->ps_name)
+    free (fid->ps_name);
+  if (fid->metrics.per_char)
+    free (fid->metrics.per_char);
+
+  // #### DAMMIT!  I can't tell what's going wrong here, but I keep getting
+  //      crashes in [NSFont ascender] <- query_font, and it seems to go away
+  //      if I never release the nsfont.  So, fuck it, we'll just leak fonts.
+  //      They're probably not very big...
+  //
+  //  [fid->nsfont release];
+  //  CFRelease (fid->nsfont);
+
+  free (fid);
+  return 0;
+}
+
+int
+XFreeFontInfo (char **names, XFontStruct *info, int n)
+{
+  int i;
+  if (names) {
+    for (i = 0; i < n; i++)
+      if (names[i]) free (names[i]);
+    free (names);
+  }
+  if (info) {
+    for (i = 0; i < n; i++)
+      if (info[i].per_char) {
+        free (info[i].per_char);
+        free (info[i].properties);
+      }
+    free (info);
+  }
+  return 0;
+}
+
+int
+XFreeFont (Display *dpy, XFontStruct *f)
+{
+  Font fid = f->fid;
+  XFreeFontInfo (0, f, 1);
+  XUnloadFont (dpy, fid);
+  return 0;
+}
+
+
+int
+XSetFont (Display *dpy, GC gc, Font fid)
+{
+  Font font2 = copy_font (fid);
+  if (gc->gcv.font)
+    XUnloadFont (dpy, gc->gcv.font);
+  gc->gcv.font = font2;
+  return 0;
+}
+
+
+XFontSet
+XCreateFontSet (Display *dpy, char *name, 
+                char ***missing_charset_list_return,
+                int *missing_charset_count_return,
+                char **def_string_return)
+{
+  char *name2 = strdup (name);
+  char *s = strchr (name, ',');
+  if (s) *s = 0;
+  XFontSet set = 0;
+  XFontStruct *f = XLoadQueryFont (dpy, name2);
+  if (f)
+    {
+      set = (XFontSet) calloc (1, sizeof(*set));
+      set->font = f;
+    }
+  free (name2);
+  if (missing_charset_list_return)  *missing_charset_list_return = 0;
+  if (missing_charset_count_return) *missing_charset_count_return = 0;
+  if (def_string_return) *def_string_return = 0;
+  return set;
+}
+
+
+void
+XFreeFontSet (Display *dpy, XFontSet set)
+{
+  XFreeFont (dpy, set->font);
+  free (set);
+}
+
+
+const char *
+jwxyz_nativeFontName (Font f, float *size)
+{
+  if (size) *size = f->size;
+  return f->ps_name;
+}
+
+
+void
+XFreeStringList (char **list)
+{
+  int i;
+  if (!list) return;
+  for (i = 0; list[i]; i++)
+    XFree (list[i]);
+  XFree (list);
+}
+
+
+// Returns the verbose Unicode name of this character, like "agrave" or
+// "daggerdouble".  Used by fontglide debugMetrics.
+//
+char *
+jwxyz_unicode_character_name (Font fid, unsigned long uc)
+{
+  /* TODO Fonts
+  char *ret = 0;
+  CTFontRef ctfont =
+    CTFontCreateWithName ((CFStringRef) [fid->nsfont fontName],
+                          [fid->nsfont pointSize],
+                          NULL);
+  Assert (ctfont, @"no CTFontRef for UIFont");
+
+  CGGlyph cgglyph;
+  if (CTFontGetGlyphsForCharacters (ctfont, (UniChar *) &uc, &cgglyph, 1)) {
+    NSString *name = (NSString *)
+      CGFontCopyGlyphNameForGlyph (CTFontCopyGraphicsFont (ctfont, 0),
+                                   cgglyph);
+    ret = (name ? strdup ([name UTF8String]) : 0);
+  }
+
+  CFRelease (ctfont);
+  return ret;
+   */
+  return NULL;
+}
+
+
+// Given a UTF8 string, return an NSString.  Bogus UTF8 characters are ignored.
+// We have to do this because stringWithCString returns NULL if there are
+// any invalid characters at all.
+//
+/* TODO
+static NSString *
+sanitize_utf8 (const char *in, int in_len, Bool *latin1_pP)
+{
+  int out_len = in_len * 4;   // length of string might increase
+  char *s2 = (char *) malloc (out_len);
+  char *out = s2;
+  const char *in_end  = in  + in_len;
+  const char *out_end = out + out_len;
+  Bool latin1_p = True;
+
+  while (in < in_end)
+    {
+      unsigned long uc;
+      long L1 = utf8_decode ((const unsigned char *) in, in_end - in, &uc);
+      long L2 = utf8_encode (uc, out, out_end - out);
+      in  += L1;
+      out += L2;
+      if (uc > 255) latin1_p = False;
+    }
+  *out = 0;
+  NSString *nsstr =
+    [NSString stringWithCString:s2 encoding:NSUTF8StringEncoding];
+  free (s2);
+  if (latin1_pP) *latin1_pP = latin1_p;
+  return (nsstr ? nsstr : @"");
+}
+*/
+
+int
+XTextExtents (XFontStruct *f, const char *s, int length,
+              int *dir_ret, int *ascent_ret, int *descent_ret,
+              XCharStruct *cs)
+{
+  // Unfortunately, adding XCharStructs together to get the extents for a
+  // string doesn't work: Cocoa uses non-integral character advancements, but
+  // XCharStruct.width is an integer. Plus that doesn't take into account
+  // kerning pairs, alternate glyphs, and fun stuff like the word "Zapfino" in
+  // Zapfino.
+
+  Font ff = f->fid;
+  Display *dpy = ff->dpy;
+  jwxyz_render_text (dpy, ff->native_font, s, length, GL_FALSE, cs, 0);
+  *dir_ret = 0;
+  *ascent_ret  = f->ascent;
+  *descent_ret = f->descent;
+  return 0;
+}
+
+int
+XTextWidth (XFontStruct *f, const char *s, int length)
+{
+  int ascent, descent, dir;
+  XCharStruct cs;
+  XTextExtents (f, s, length, &dir, &ascent, &descent, &cs);
+  return cs.width;
+}
+
+
+int
+XTextExtents16 (XFontStruct *f, const XChar2b *s, int length,
+                int *dir_ret, int *ascent_ret, int *descent_ret,
+                XCharStruct *cs)
+{
+  // Bool latin1_p = True;
+  int i, utf8_len = 0;
+  char *utf8 = XChar2b_to_utf8 (s, &utf8_len);   // already sanitized
+
+  for (i = 0; i < length; i++)
+    if (s[i].byte1 > 0) {
+      // latin1_p = False;
+      break;
+    }
+
+  {
+    Font ff = f->fid;
+    Display *dpy = ff->dpy;
+    jwxyz_render_text (dpy, ff->native_font, utf8, strlen(utf8),
+                       GL_TRUE, cs, 0);
+  }
+
+  *dir_ret = 0;
+  *ascent_ret  = f->ascent;
+  *descent_ret = f->descent;
+  free (utf8);
+  return 0;
+}
+
+
+/* "Returns the distance in pixels in the primary draw direction from
+   the drawing origin to the origin of the next character to be drawn."
+
+   "overall_ink_return is set to the bbox of the string's character ink."
+
+   "The overall_ink_return for a nondescending, horizontally drawn Latin
+   character is conventionally entirely above the baseline; that is,
+   overall_ink_return.height <= -overall_ink_return.y."
+
+     [So this means that y is the top of the ink, and height grows down:
+      For above-the-baseline characters, y is negative.]
+
+   "The overall_ink_return for a nonkerned character is entirely at, and to
+   the right of, the origin; that is, overall_ink_return.x >= 0."
+
+     [So this means that x is the left of the ink, and width grows right.
+      For left-of-the-origin characters, x is negative.]
+
+   "A character consisting of a single pixel at the origin would set
+   overall_ink_return fields y = 0, x = 0, width = 1, and height = 1."
+ */
+int
+Xutf8TextExtents (XFontSet set, const char *str, int len,
+                  XRectangle *overall_ink_return,
+                  XRectangle *overall_logical_return)
+{
+#if 0
+  Bool latin1_p;
+  NSString *nsstr = sanitize_utf8 (str, len, &latin1_p);
+  XCharStruct cs;
+
+  utf8_metrics (set->font->fid, nsstr, &cs);
+
+  /* "The overall_logical_return is the bounding box that provides minimum
+     spacing to other graphical features for the string. Other graphical
+     features, for example, a border surrounding the text, should not
+     intersect this rectangle."
+
+     So I think that means they're the same?  Or maybe "ink" is the bounding
+     box, and "logical" is the advancement?  But then why is the return value
+     the advancement?
+   */
+  if (overall_ink_return)
+    XCharStruct_to_XmbRectangle (cs, *overall_ink_return);
+  if (overall_logical_return)
+    XCharStruct_to_XmbRectangle (cs, *overall_logical_return);
+
+  return cs.width;
+#endif
+  abort();
+}
+
+
+static int
+draw_string (Display *dpy, Drawable d, GC gc, int x, int y,
+             const char *str, size_t len, GLboolean utf8)
+{
+  Font ff = gc->gcv.font;
+  XCharStruct cs;
+
+  char *data = 0;
+  jwxyz_render_text (dpy, ff->native_font, str, len, utf8, &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.
+   */
+  {
+    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;
+    }
+  }
+
+  XPutImage (dpy, d, gc, img, 0, 0, 
+             x + cs.lbearing,
+             y - cs.ascent,
+             w, h);
+  XDestroyImage (img);
+
+  return 0;
+}
+
+int
+XDrawString (Display *dpy, Drawable d, GC gc, int x, int y,
+             const char  *str, int len)
+{
+  return draw_string (dpy, d, gc, x, y, str, len, GL_FALSE);
+}
+
+
+int
+XDrawString16 (Display *dpy, Drawable d, GC gc, int x, int y,
+             const XChar2b *str, int len)
+{
+  XChar2b *b2 = malloc ((len + 1) * sizeof(*b2));
+  char *s2;
+  int ret;
+  memcpy (b2, str, len * sizeof(*b2));
+  b2[len].byte1 = b2[len].byte2 = 0;
+  s2 = XChar2b_to_utf8 (b2, 0);
+  free (b2);
+  ret = draw_string (dpy, d, gc, x, y, s2, strlen(s2), GL_TRUE);
+  free (s2);
+  return ret;
+}
+
+
+void
+Xutf8DrawString (Display *dpy, Drawable d, XFontSet set, GC gc,
+                 int x, int y, const char *str, int len)
+{
+  draw_string (dpy, d, gc, x, y, str, len, GL_TRUE);
+}
+
+
+int
+XDrawImageString (Display *dpy, Drawable d, GC gc, int x, int y,
+                  const char *str, int len)
+{
+  int ascent, descent, dir;
+  XCharStruct cs;
+  XTextExtents (&gc->gcv.font->metrics, str, len,
+                &dir, &ascent, &descent, &cs);
+  jwxyz_fill_rect (dpy, d, gc,
+                   x + MIN (0, cs.lbearing),
+                   y - MAX (0, ascent),
+                   MAX (MAX (0, cs.rbearing) -
+                        MIN (0, cs.lbearing),
+                        cs.width),
+                   MAX (0, ascent) + MAX (0, descent),
+                   gc->gcv.background);
+  return XDrawString (dpy, d, gc, x, y, str, len);
+}
+
+
+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)
+{
+  gc->gcv.clip_x_origin = x;
+  gc->gcv.clip_y_origin = y;
+  return 0;
+}
+
+#endif /* JWXYZ_GL -- entire file */
diff --git a/jwxyz/jwxyz-timers.c b/jwxyz/jwxyz-timers.c
new file mode 100644 (file)
index 0000000..7da705a
--- /dev/null
@@ -0,0 +1,351 @@
+/* xscreensaver, Copyright (c) 2006-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 is the portable implementation of Xt timers and inputs, for libjwxyz.
+ */
+
+#include "config.h"
+
+#ifdef HAVE_JWXYZ /* whole file */
+
+
+#undef DEBUG_TIMERS
+#undef DEBUG_SOURCES
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/select.h>
+#include "jwxyz.h"
+#include "jwxyz-timers.h"
+
+#ifdef HAVE_ANDROID
+extern void Log(const char *format, ...);
+#endif
+
+#ifdef HAVE_COCOA
+# define Log(S, ...) fprintf(stderr, "xscreensaver: " S "\n", __VA_ARGS__)
+#endif
+
+#ifdef DEBUG_TIMERS
+# define LOGT(...) Log(__VA_ARGS__)
+#else
+# define LOGT(...)
+#endif
+
+#ifdef DEBUG_SOURCES
+# define LOGI(...) Log(__VA_ARGS__)
+#else
+# define LOGI(...)
+#endif
+
+#define ASSERT_RET(C,S) do {                    \
+    if (!(C)) {                                 \
+      jwxyz_abort ("jwxyz-timers: %s",(S));     \
+      return;                                   \
+ }} while(0)
+
+#define ASSERT_RET0(C,S) do {                   \
+    if (!(C)) {                                 \
+      jwxyz_abort ("jwxyz-timers: %s",(S));     \
+      return 0;                                 \
+ }} while(0)
+
+
+XtAppContext
+XtDisplayToApplicationContext (Display *dpy)
+{
+  return (XtAppContext) dpy;
+}
+
+#define app_to_display(APP) ((Display *) (APP))
+
+
+struct jwxyz_sources_data {
+  int fd_count;
+  XtInputId ids[FD_SETSIZE];
+  XtIntervalId all_timers;
+};
+
+struct jwxyz_XtIntervalId {
+  XtAppContext app;
+  int refcount;
+
+  double run_at;
+  XtTimerCallbackProc cb;
+  XtPointer closure;
+
+  XtIntervalId next;
+};
+
+struct jwxyz_XtInputId {
+  XtAppContext app;
+  int refcount;
+
+  XtInputCallbackProc cb;
+  XtPointer closure;
+  int fd;
+};
+
+
+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));
+}
+
+
+jwxyz_sources_data *
+jwxyz_sources_init (XtAppContext app)
+{
+  jwxyz_sources_data *td = (jwxyz_sources_data *) calloc (1, sizeof (*td));
+  return td;
+}
+
+XtIntervalId
+XtAppAddTimeOut (XtAppContext app, unsigned long msecs,
+                 XtTimerCallbackProc cb, XtPointer closure)
+{
+  jwxyz_sources_data *td = display_sources_data (app_to_display (app));
+  XtIntervalId data = (XtIntervalId) calloc (1, sizeof(*data));
+  double now = double_time();
+  data->app = app;
+  data->cb = cb;
+  data->closure = closure;
+  data->refcount++;
+  data->run_at = now + (msecs / 1000.0);
+
+  data->next = td->all_timers;
+  td->all_timers = data;
+
+  LOGT("timer  0x%08lX: alloc %lu %.2f", (unsigned long) data, msecs,
+       data->run_at - now);
+
+  return data;
+}
+
+
+/* This is called both by the user to manually kill a timer,
+   and by the run loop after a timer has fired.
+ */
+void
+XtRemoveTimeOut (XtIntervalId data)
+{
+  jwxyz_sources_data *td = display_sources_data (app_to_display (data->app));
+
+  LOGT("timer  0x%08lX: remove", (unsigned long) data);
+  ASSERT_RET (data->refcount > 0, "already freed");
+
+  data->refcount--;
+  LOGT("timer  0x%08lX: release %d", (unsigned long) data, data->refcount);
+  ASSERT_RET (data->refcount >= 0, "double free");
+
+  if (data->refcount == 0) {
+
+    /* Remove it from the list of live timers. */
+    XtIntervalId prev, timer;
+    int hit = 0;
+    for (timer = td->all_timers, prev = 0;
+         timer;
+         prev = timer, timer = timer->next) {
+      if (timer == data) {
+        ASSERT_RET (!hit, "circular timer list");
+        if (prev)
+          prev->next = timer->next;
+        else
+          td->all_timers = timer->next;
+        timer->next = 0;
+        hit = 1;
+      } else {
+        ASSERT_RET (timer->refcount > 0, "timer list corrupted");
+      }
+    }
+
+    free (data);
+  }
+}
+
+
+XtInputId
+XtAppAddInput (XtAppContext app, int fd, XtPointer flags,
+               XtInputCallbackProc cb, XtPointer closure)
+{
+  jwxyz_sources_data *td = display_sources_data (app_to_display (app));
+  XtInputId data = (XtInputId) calloc (1, sizeof(*data));
+  data->cb = cb;
+  data->fd = fd;
+  data->closure = closure;
+  data->app = app;
+  data->refcount++;
+
+  LOGI("source 0x%08lX %2d: alloc", (unsigned long) data, data->fd);
+
+  ASSERT_RET0 (fd > 0 && fd < FD_SETSIZE, "fd out of range");
+  ASSERT_RET0 (td->ids[fd] == 0, "sources corrupted");
+  td->ids[fd] = data;
+  td->fd_count++;
+
+  return data;
+}
+
+
+void
+XtRemoveInput (XtInputId id)
+{
+  jwxyz_sources_data *td = display_sources_data (app_to_display (id->app));
+
+  LOGI("source 0x%08lX %2d: remove", (unsigned long) id, id->fd);
+  ASSERT_RET (id->refcount > 0, "sources corrupted");
+  ASSERT_RET (td->fd_count > 0, "sources corrupted");
+  ASSERT_RET (id->fd > 0 && id->fd < FD_SETSIZE, "fd out of range");
+  ASSERT_RET (td->ids[id->fd] == id, "sources corrupted");
+
+  td->ids[id->fd] = 0;
+  td->fd_count--;
+  id->refcount--;
+
+  LOGI("source 0x%08lX %2d: release %d", (unsigned long) id, id->fd,
+       id->refcount);
+  ASSERT_RET (id->refcount >= 0, "double free");
+  if (id->refcount == 0) {
+    memset (id, 0xA1, sizeof(*id));
+    id->fd = -666;
+    free (id);
+  }
+}
+
+
+static void
+jwxyz_timers_run (jwxyz_sources_data *td)
+{
+  /* Iterate the timer list, being careful because XtRemoveTimeOut removes
+     the current item from that list. */
+  if (td->all_timers) {
+    XtIntervalId timer, next;
+    double now = double_time();
+    int count = 0;
+
+    for (timer = td->all_timers, next = timer->next;
+         timer;
+         timer = next, next = (timer ? timer->next : 0)) {
+      if (timer->run_at <= now) {
+        LOGT("timer  0x%08lX: fire %.02f", (unsigned long) timer,
+             now - timer->run_at);
+        timer->cb (timer->closure, &timer);
+        XtRemoveTimeOut (timer);
+        count++;
+        ASSERT_RET (count < 10000, "way too many timers to run");
+      }
+    }
+  }
+}
+
+
+static void
+jwxyz_sources_run (jwxyz_sources_data *td)
+{
+  if (td->fd_count == 0) return;
+
+  struct timeval tv = { 0, };
+  fd_set fds;
+  int i;
+  int max = 0;
+
+  FD_ZERO (&fds);
+  for (i = 0; i < FD_SETSIZE; i++) {
+    if (td->ids[i]) {
+      FD_SET (i, &fds);
+      max = i;
+    }
+  }
+
+  ASSERT_RET (max > 0, "no fds");
+
+  if (0 < select (max+1, &fds, NULL, NULL, &tv)) {
+    for (i = 0; i < FD_SETSIZE; i++) {
+      if (FD_ISSET (i, &fds)) {
+        XtInputId id = td->ids[i];
+        ASSERT_RET (id && id->cb, "sources corrupted");
+        ASSERT_RET (id->fd == i, "sources corrupted");
+        id->cb (id->closure, &id->fd, &id);
+      }
+    }
+  }
+}
+
+
+static void
+jwxyz_XtRemoveInput_all (jwxyz_sources_data *td)
+{
+  int i;
+  for (i = 0; i < FD_SETSIZE; i++) {
+    XtInputId id = td->ids[i];
+    if (id) XtRemoveInput (id);
+  }
+}
+
+
+static void
+jwxyz_XtRemoveTimeOut_all (jwxyz_sources_data *td)
+{
+  XtIntervalId timer, next;
+  int count = 0;
+
+  /* Iterate the timer list, being careful because XtRemoveTimeOut removes
+     the current item from that list. */
+  if (td->all_timers) {
+    for (timer = td->all_timers, next = timer->next;
+         timer;
+         timer = next, next = (timer ? timer->next : 0)) {
+      XtRemoveTimeOut (timer);
+      count++;
+      ASSERT_RET (count < 10000, "way too many timers to free");
+    }
+    ASSERT_RET (!td->all_timers, "timer list didn't empty");
+  }
+}
+
+
+void
+jwxyz_sources_free (jwxyz_sources_data *td)
+{
+  jwxyz_XtRemoveInput_all (td);
+  jwxyz_XtRemoveTimeOut_all (td);
+  memset (td, 0xA1, sizeof(*td));
+  free (td);
+}
+
+
+XtInputMask
+XtAppPending (XtAppContext app)
+{
+  return XtIMAlternateInput;  /* just always say yes */
+}
+
+void
+XtAppProcessEvent (XtAppContext app, XtInputMask mask)
+{
+  jwxyz_sources_data *td = display_sources_data (app_to_display (app));
+  if (mask & XtIMAlternateInput)
+    jwxyz_sources_run (td);
+  if (mask & XtIMTimer)
+    jwxyz_timers_run (td);
+}
+
+#endif /* HAVE_JWXYZ */
diff --git a/jwxyz/jwxyz-timers.h b/jwxyz/jwxyz-timers.h
new file mode 100644 (file)
index 0000000..5326d82
--- /dev/null
@@ -0,0 +1,25 @@
+/* xscreensaver, Copyright (c) 2006-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 is an implementation of Xt timers, for libjwxyz.
+ */
+
+#ifndef __JWXYZ_TIMERS_H__
+#define __JWXYZ_TIMERS_H__
+
+#include "jwxyz.h"
+
+typedef struct jwxyz_sources_data jwxyz_sources_data;
+
+extern jwxyz_sources_data *jwxyz_sources_init (XtAppContext);
+extern void jwxyz_sources_free (jwxyz_sources_data *);
+
+#endif /* __JWXYZ_TIMERS_H__ */
diff --git a/jwxyz/jwxyz.h b/jwxyz/jwxyz.h
new file mode 100644 (file)
index 0000000..335df69
--- /dev/null
@@ -0,0 +1,816 @@
+/* xscreensaver, Copyright (c) 1991-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.
+ */
+
+/* JWXYZ Is Not Xlib.
+
+   But it's a bunch of function definitions that bear some resemblance to
+   Xlib and that do Cocoa-ish or OpenGL-ish things that bear some resemblance
+   to the things that Xlib might have done.
+ */
+
+#ifndef __JWXYZ_H__
+#define __JWXYZ_H__
+
+#include <stdlib.h> /* For abort(). */
+
+#if defined __FreeBSD__ || defined __MACH__ && defined __APPLE__
+# include <sys/cdefs.h>
+#endif
+
+#ifndef __dead2
+/* __dead2 is an undocumented FreeBSD-ism (and by extension, an OSX-ism),
+   normally #defined in <sys/cdefs.h>.
+ */
+# if defined __GNUC__ || defined __clang__
+#  define __dead2 __attribute__((__noreturn__))
+# else
+#  define __dead2
+# endif
+#endif
+
+extern void jwxyz_abort(const char *fmt, ...) __dead2;
+#define abort() jwxyz_abort("abort in %s:%d", __FUNCTION__, __LINE__)
+
+typedef int Bool;
+typedef int Status;
+typedef void * XPointer;
+typedef unsigned long Time;
+typedef unsigned int KeySym;
+typedef unsigned int KeyCode;
+typedef unsigned int VisualID;
+typedef unsigned long Atom; /* Must be as large as a char *. */
+
+typedef struct jwxyz_Display           Display;
+typedef struct jwxyz_Screen            Screen;
+typedef struct jwxyz_Visual            Visual;
+typedef struct jwxyz_Drawable *                Drawable;
+typedef struct jwxyz_Colormap *                Colormap;
+typedef struct jwxyz_GC        *               GC;
+typedef struct jwxyz_XColor            XColor;
+typedef struct jwxyz_XGCValues         XGCValues;
+typedef struct jwxyz_XPoint            XPoint;
+typedef struct jwxyz_XSegment          XSegment;
+typedef struct jwxyz_XRectangle                XRectangle;
+typedef struct jwxyz_XArc              XArc;
+typedef struct jwxyz_XWindowAttributes XWindowAttributes;
+typedef struct jwxyz_XrmOptionDescRec  XrmOptionDescRec;
+typedef struct jwxyz_XrmDatabase *      XrmDatabase;
+typedef struct jwxyz_XImage            XImage;
+typedef struct jwxyz_XFontProp          XFontProp;
+typedef struct jwxyz_XFontStruct       XFontStruct;
+typedef struct jwxyz_Font *            Font;
+typedef struct jwxyz_XFontSet *                XFontSet;
+typedef struct jwxyz_XCharStruct       XCharStruct;
+typedef struct jwxyz_XComposeStatus    XComposeStatus;
+typedef struct jwxyz_XPixmapFormatValues XPixmapFormatValues;
+typedef struct jwxyz_XChar2b            XChar2b;
+
+typedef union  jwxyz_XEvent            XEvent;
+typedef struct jwxyz_XAnyEvent         XAnyEvent;
+typedef struct jwxyz_XKeyEvent         XKeyEvent;
+typedef struct jwxyz_XMotionEvent      XMotionEvent;
+typedef struct jwxyz_XButtonEvent      XButtonEvent;
+typedef XKeyEvent                      XKeyPressedEvent;
+typedef XKeyEvent                      XKeyReleasedEvent;
+typedef XMotionEvent                   XPointerMovedEvent;
+typedef XButtonEvent                   XButtonPressedEvent;
+typedef XButtonEvent                   XButtonReleasedEvent;
+
+
+/* Not technically Xlib... */
+typedef struct jwxyz_GLXContext *      GLXContext;
+typedef struct jwxyz_XtAppContext *    XtAppContext;
+typedef struct jwxyz_XtIntervalId *    XtIntervalId;
+typedef struct jwxyz_XtInputId *       XtInputId;
+typedef void *                         XtPointer;
+typedef unsigned long                  XtInputMask;
+#define XtInputReadMask                        (1L<<0)
+#define XtInputWriteMask               (1L<<1)
+#define XtInputExceptMask              (1L<<2)
+#define XtIMXEvent                     1
+#define XtIMTimer                      2
+#define XtIMAlternateInput             4
+#define XtIMSignal                     8
+#define XtIMAll (XtIMXEvent | XtIMTimer | XtIMAlternateInput | XtIMSignal)
+
+#define True 1
+#define TRUE 1
+#define False 0
+#define FALSE 0
+#define None 0
+
+#define Window Drawable
+#define Pixmap Drawable
+
+#define XrmoptionNoArg  0
+#define XrmoptionSepArg 1
+
+#define CoordModeOrigin                0
+#define CoordModePrevious       1
+
+#define LineSolid              0
+#define LineOnOffDash          1
+#define LineDoubleDash         2
+
+#define CapNotLast             0
+#define CapButt                        1
+#define CapRound               2
+#define CapProjecting          3
+
+#define JoinMiter              0
+#define JoinRound              1
+#define JoinBevel              2
+
+#define FillSolid              0
+#define FillTiled              1
+#define FillStippled           2
+#define FillOpaqueStippled     3
+
+#define EvenOddRule            0
+#define WindingRule            1
+
+#define Complex                        0
+#define Nonconvex              1
+#define Convex                 2
+
+#define XYBitmap               0
+#define XYPixmap               1
+#define ZPixmap                        2
+
+#define AllocNone              0
+#define AllocAll               1
+
+#define StaticGray             0
+#define GrayScale              1
+#define StaticColor            2
+#define PseudoColor            3
+#define TrueColor              4
+#define DirectColor            5
+
+#define LSBFirst               0
+#define MSBFirst               1
+
+#define DoRed                  (1<<0)
+#define DoGreen                        (1<<1)
+#define DoBlue                 (1<<2)
+
+#define GCFunction              (1L<<0)
+#define GCPlaneMask             (1L<<1)
+#define GCForeground            (1L<<2)
+#define GCBackground            (1L<<3)
+#define GCLineWidth             (1L<<4)
+#define GCLineStyle             (1L<<5)
+#define GCCapStyle              (1L<<6)
+#define GCJoinStyle            (1L<<7)
+#define GCFillStyle            (1L<<8)
+#define GCFillRule             (1L<<9) 
+#define GCTile                 (1L<<10)
+#define GCStipple              (1L<<11)
+#define GCTileStipXOrigin      (1L<<12)
+#define GCTileStipYOrigin      (1L<<13)
+#define GCFont                         (1L<<14)
+#define GCSubwindowMode                (1L<<15)
+#define GCGraphicsExposures     (1L<<16)
+#define GCClipXOrigin          (1L<<17)
+#define GCClipYOrigin          (1L<<18)
+#define GCClipMask             (1L<<19)
+#define GCDashOffset           (1L<<20)
+#define GCDashList             (1L<<21)
+#define GCArcMode              (1L<<22)
+
+#define KeyPress               2
+#define KeyRelease             3
+#define ButtonPress            4
+#define ButtonRelease          5
+#define MotionNotify           6
+#define Expose                 12
+#define GraphicsExpose         13
+#define NoExpose               14
+#define VisibilityNotify       15
+
+#define ClipByChildren         0
+#define IncludeInferiors       1
+
+#define KeyPressMask           (1L<<0)
+#define KeyReleaseMask         (1L<<1)
+#define ButtonPressMask                (1L<<2)
+#define ButtonReleaseMask      (1L<<3)
+#define PointerMotionMask      (1L<<6)
+
+#define Button1                        1
+#define Button2                        2
+#define Button3                        3
+#define Button4                        4
+#define Button5                        5
+
+#define ShiftMask              (1<<0)
+#define LockMask               (1<<1)
+#define ControlMask            (1<<2)
+#define Mod1Mask               (1<<3)
+#define Mod2Mask               (1<<4)
+#define Mod3Mask               (1<<5)
+#define Mod4Mask               (1<<6)
+#define Mod5Mask               (1<<7)
+#define Button1Mask            (1<<8)
+#define Button2Mask            (1<<9)
+#define Button3Mask            (1<<10)
+#define Button4Mask            (1<<11)
+#define Button5Mask            (1<<12)
+
+#define XK_Shift_L             0xFFE1
+#define XK_Shift_R             0xFFE2
+#define XK_Control_L           0xFFE3
+#define XK_Control_R           0xFFE4
+#define XK_Caps_Lock           0xFFE5
+#define XK_Shift_Lock          0xFFE6
+#define XK_Meta_L              0xFFE7
+#define XK_Meta_R              0xFFE8
+#define XK_Alt_L               0xFFE9
+#define XK_Alt_R               0xFFEA
+#define XK_Super_L             0xFFEB
+#define XK_Super_R             0xFFEC
+#define XK_Hyper_L             0xFFED
+#define XK_Hyper_R             0xFFEE
+
+#define XK_Home                        0xFF50
+#define XK_Left                        0xFF51
+#define XK_Up                  0xFF52
+#define XK_Right               0xFF53
+#define XK_Down                        0xFF54
+#define XK_Prior               0xFF55
+#define XK_Page_Up             0xFF55
+#define XK_Next                        0xFF56
+#define XK_Page_Down           0xFF56
+#define XK_End                 0xFF57
+#define XK_Begin               0xFF58
+
+#define XK_F1                  0xFFBE
+#define XK_F2                  0xFFBF
+#define XK_F3                  0xFFC0
+#define XK_F4                  0xFFC1
+#define XK_F5                  0xFFC2
+#define XK_F6                  0xFFC3
+#define XK_F7                  0xFFC4
+#define XK_F8                  0xFFC5
+#define XK_F9                  0xFFC6
+#define XK_F10                 0xFFC7
+#define XK_F11                 0xFFC8
+#define XK_F12                 0xFFC9
+
+
+#define GXclear                        0x0             /* 0 */
+#define GXand                  0x1             /* src AND dst */
+// #define GXandReverse                0x2             /* src AND NOT dst */
+#define GXcopy                 0x3             /* src */
+// #define GXandInverted       0x4             /* NOT src AND dst */
+// #define GXnoop              0x5             /* dst */
+#define GXxor                  0x6             /* src XOR dst */
+#define GXor                   0x7             /* src OR dst */
+// #define GXnor               0x8             /* NOT src AND NOT dst */
+// #define GXequiv             0x9             /* NOT src XOR dst */
+// #define GXinvert            0xa             /* NOT dst */
+// #define GXorReverse         0xb             /* src OR NOT dst */
+// #define GXcopyInverted      0xc             /* NOT src */
+// #define GXorInverted                0xd             /* NOT src OR dst */
+// #define GXnand              0xe             /* NOT src OR NOT dst */
+#define GXset                  0xf             /* 1 */
+
+#define XA_FONT                 18
+
+#define DefaultScreen(dpy) (0)
+#define BlackPixelOfScreen XBlackPixelOfScreen
+#define WhitePixelOfScreen XWhitePixelOfScreen
+#define BlackPixel(dpy,n) BlackPixelOfScreen(ScreenOfDisplay(dpy,n))
+#define WhitePixel(dpy,n) WhitePixelOfScreen(ScreenOfDisplay(dpy,n))
+#define CellsOfScreen XCellsOfScreen
+#define XFree(x) free(x)
+#define BitmapPad(dpy) (8)
+#define BitmapBitOrder(dpy) (MSBFirst)
+#define ImageByteOrder(dpy) (MSBFirst)
+#define DisplayOfScreen XDisplayOfScreen
+#define DefaultScreenOfDisplay XDefaultScreenOfDisplay
+#define ScreenOfDisplay(dpy,n) DefaultScreenOfDisplay(dpy)
+#define DefaultVisualOfScreen XDefaultVisualOfScreen
+#define DefaultColormapOfScreen(s) (0)
+#define RootWindow XRootWindow
+#define RootWindowOfScreen(s) RootWindow(DisplayOfScreen(s),0)
+#define DisplayWidth XDisplayWidth
+#define DisplayHeight XDisplayHeight
+#define XMaxRequestSize(dpy) (65535)
+#define XWidthOfScreen(s) (DisplayWidth(DisplayOfScreen(s),0))
+#define XHeightOfScreen(s) (DisplayHeight(DisplayOfScreen(s),0))
+#define XWidthMMOfScreen(s) (XDisplayWidthMM(DisplayOfScreen(s),0))
+#define XHeightMMOfScreen(s) (XDisplayHeightMM(DisplayOfScreen(s),0))
+
+#define ScreenCount(dpy) jwxyz_ScreenCount(dpy)
+extern int jwxyz_ScreenCount(Display *);
+
+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);
+extern int XDisplayHeightMM (Display *, int);
+
+unsigned long XBlackPixelOfScreen(Screen *);
+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 *);
+extern Status XGetGeometry (Display *, Drawable, Window *root_ret,
+                            int *x_ret, int *y_ret, 
+                            unsigned int *w_ret, unsigned int *h_ret,
+                            unsigned int *bw_ret, unsigned int *depth_ret);
+extern Status XAllocColor (Display *, Colormap, XColor *);
+extern Status XAllocColorCells (Display *, Colormap, Bool contig,
+                                unsigned long *pmret, unsigned int npl,
+                                unsigned long *pxret, unsigned int npx);
+extern int XStoreColors (Display *, Colormap, XColor *, int n);
+extern int XStoreColor (Display *, Colormap, XColor *);
+extern Status XParseColor(Display *, Colormap, const char *spec, XColor *ret);
+extern Status XAllocNamedColor (Display *, Colormap, char *name,
+                                XColor *screen_ret, XColor *exact_ret);
+extern int XQueryColor (Display *, Colormap, XColor *);
+extern int XQueryColors(Display *, Colormap colormap, XColor *, int ncolors);
+
+extern int XSetForeground (Display *, GC, unsigned long);
+extern int XSetBackground (Display *, GC, unsigned long);
+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);
+
+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, 
+                      int dest_x, int dest_y);
+extern int XCopyPlane (Display *, Drawable, Drawable, GC,
+                       int src_x, int src_y,
+                       unsigned width, int height,
+                       int dest_x, int dest_y,
+                       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);
+extern int XFillArc (Display *, Drawable, GC, int x, int y, 
+                     unsigned int width, unsigned int height,
+                     int angle1, int angle2);
+extern int XDrawArcs (Display *, Drawable, GC, XArc *arcs, int narcs);
+extern int XFillArcs (Display *, Drawable, GC, XArc *arcs, int narcs);
+extern int XDrawRectangle (Display *, Drawable, GC, int x, int y, 
+                           unsigned int width, unsigned int height);
+extern int XFillRectangle (Display *, Drawable, GC, int x, int y, 
+                           unsigned int width, unsigned int height);
+extern int XFillRectangles (Display *, Drawable, GC, XRectangle *, int n);
+
+extern int XDrawString (Display *, Drawable, GC, int x, int y, const char *,
+                        int len);
+extern int XDrawImageString (Display *, Drawable, GC, int x, int y, 
+                             const char *, int len);
+extern int XDrawString16 (Display *, Drawable, GC, int x, int y,
+                          const XChar2b *, int len);
+
+extern Bool XQueryPointer (Display *, Window, Window *root_ret,
+                           Window *child_ret,
+                           int *root_x_ret, int *root_y_ret,
+                           int *win_x_ret, int *win_y_ret,
+                           unsigned int *mask_ret);
+extern int XLookupString (XKeyEvent *, char *ret, int size, KeySym *ks_ret,
+                          XComposeStatus *);
+extern KeySym XKeycodeToKeysym (Display *, KeyCode, int index);
+
+extern Status XInitImage (XImage *);
+extern XImage *XCreateImage (Display *, Visual *, unsigned int depth,
+                             int format, int offset, char *data,
+                             unsigned int width, unsigned int height,
+                             int bitmap_pad, int bytes_per_line);
+extern XImage *XSubImage (XImage *, int x, int y, 
+                          unsigned int w, unsigned int h);
+
+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 *XGetImage (Display *, Drawable, int x, int y,
+                          unsigned int w, unsigned int h,
+                          unsigned long pm, int fmt);
+extern Pixmap XCreatePixmapFromBitmapData (Display *, Drawable,
+                                           const char *data,
+                                           unsigned int w, unsigned int h,
+                                           unsigned long fg,
+                                           unsigned int bg,
+                                           unsigned int depth);
+extern XPixmapFormatValues *XListPixmapFormats (Display *, int *count_ret);
+
+extern void jwxyz_draw_NSImage_or_CGImage (Display *, Drawable, 
+                                           Bool nsimg_p, void *NSImage_arg,
+                                           XRectangle *geom_ret, 
+                                           int exif_rotation);
+
+extern int XSetGraphicsExposures (Display *, GC, Bool);
+extern Bool XTranslateCoordinates (Display *, Window src_w, Window dest_w,
+                                   int src_x, int src_y,
+                                   int *dest_x_ret, int *dest_y_ret,
+                                   Window *child_ret);
+
+extern Font XLoadFont (Display *, const char *);
+extern XFontStruct * XQueryFont (Display *, Font);
+extern XFontStruct * XLoadQueryFont (Display *, const char *);
+extern int XFreeFontInfo (char **names, XFontStruct *info, int n);
+extern int XFreeFont (Display *, XFontStruct *);
+extern int XUnloadFont (Display *, Font);
+extern int XTextExtents (XFontStruct *, const char *, int length,
+                         int *dir_ret, int *ascent_ret, int *descent_ret,
+                         XCharStruct *overall_ret);
+extern char * jwxyz_unicode_character_name (Font, unsigned long uc);
+extern int XTextExtents16 (XFontStruct *, const XChar2b *, int length,
+                           int *dir_ret, int *ascent_ret, int *descent_ret,
+                           XCharStruct *overall_ret);
+extern int XTextWidth (XFontStruct *, const char *, int length);
+extern int XSetFont (Display *, GC, Font);
+
+extern XFontSet XCreateFontSet (Display *, char *name, 
+                                char ***missing_charset_list_return,
+                                int *missing_charset_count_return,
+                                char **def_string_return);
+extern void XFreeFontSet (Display *, XFontSet);
+extern void XFreeStringList (char **);
+extern int Xutf8TextExtents (XFontSet, const char *, int num_bytes,
+                             XRectangle *overall_ink_return,
+                             XRectangle *overall_logical_return);
+extern void Xutf8DrawString (Display *, Drawable, XFontSet, GC,
+                             int x, int y, const char *, int num_bytes);
+extern const char *jwxyz_nativeFontName (Font, float *size);
+
+extern Pixmap XCreatePixmap (Display *, Drawable,
+                             unsigned int width, unsigned int height,
+                             unsigned int depth);
+extern int XFreePixmap (Display *, Pixmap);
+
+extern char *XGetAtomName (Display *, Atom);
+
+// Xt timers and fds
+extern XtAppContext XtDisplayToApplicationContext (Display *);
+typedef void (*XtTimerCallbackProc) (XtPointer closure, XtIntervalId *);
+typedef void (*XtInputCallbackProc) (XtPointer closure, int *fd, XtInputId *);
+extern XtIntervalId XtAppAddTimeOut (XtAppContext, unsigned long usecs,
+                                     XtTimerCallbackProc, XtPointer closure);
+extern void XtRemoveTimeOut (XtIntervalId);
+extern XtInputId XtAppAddInput (XtAppContext, int fd, XtPointer flags,
+                               XtInputCallbackProc, XtPointer closure);
+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
+extern void glXSwapBuffers (Display *, Window);
+extern void glXMakeCurrent (Display *, Window, GLXContext);
+
+// also declared in utils/visual.h
+extern int has_writable_cells (Screen *, Visual *);
+extern int visual_depth (Screen *, Visual *);
+extern int visual_cells (Screen *, Visual *);
+extern int visual_class (Screen *, Visual *);
+extern int get_bits_per_pixel (Display *, int);
+extern int screen_number (Screen *);
+
+// also declared in utils/grabclient.h
+extern Bool use_subwindow_mode_p (Screen *, Window);
+
+// also declared in xlockmoreI.h
+extern void clear_gl_error (void);
+extern void check_gl_error (const char *type);
+
+struct jwxyz_Visual {
+  VisualID visualid;   /* visual id of this visual */
+  int class;           /* class of screen (monochrome, etc.) */
+  unsigned long red_mask, green_mask, blue_mask;       /* mask values */
+  int bits_per_rgb;    /* log base 2 of distinct color values */
+//  int map_entries;   /* color map entries */
+};
+
+struct jwxyz_XGCValues {
+  int function;                /* logical operation */
+#if 0
+  unsigned long plane_mask;/* plane mask */
+#endif
+  unsigned long foreground;/* foreground pixel */
+  unsigned long background;/* background pixel */
+  int line_width;      /* line width */
+#if 0
+  int line_style;      /* LineSolid, LineOnOffDash, LineDoubleDash */
+#endif
+  int cap_style;       /* CapNotLast, CapButt, CapRound, CapProjecting */
+  int join_style;      /* JoinMiter, JoinRound, JoinBevel */
+#if 0
+  int fill_style;      /* FillSolid, FillTiled, 
+                          FillStippled, FillOpaeueStippled */
+#endif
+  int fill_rule;       /* EvenOddRule, WindingRule */
+#if 0
+  int arc_mode;                /* ArcChord, ArcPieSlice */
+  Pixmap tile;         /* tile pixmap for tiling operations */
+  Pixmap stipple;      /* stipple 1 plane pixmap for stipping */
+  int ts_x_origin;     /* offset for tile or stipple operations */
+  int ts_y_origin;
+#endif
+  Font font;           /* default text font for text operations */
+  int subwindow_mode;     /* ClipByChildren, IncludeInferiors */
+#if 0
+  Bool graphics_exposures;/* boolean, should exposures be generated */
+#endif
+  int clip_x_origin;   /* origin for clipping */
+  int clip_y_origin;
+  Pixmap clip_mask;    /* bitmap clipping; other calls for rects */
+#if 0
+  int dash_offset;     /* patterned/dashed line information */
+  char dashes;
+#endif
+
+  Bool alpha_allowed_p;        /* jwxyz extension: whether pixel values may have
+                           a non-opaque alpha component. */
+  Bool antialias_p;    /* jwxyz extension: whether Quartz should draw
+                           with antialiasing. */
+};
+
+struct jwxyz_XWindowAttributes {
+    int x, y;                  /* location of window */
+    int width, height;         /* width and height of window */
+    int border_width;          /* border width of window */
+    int depth;                 /* depth of window */
+    Visual *visual;            /* the associated visual structure */
+#if 0
+    Window root;               /* root of screen containing window */
+    int class;                 /* InputOutput, InputOnly*/
+    int bit_gravity;           /* one of bit gravity values */
+    int win_gravity;           /* one of the window gravity values */
+    int backing_store;         /* NotUseful, WhenMapped, Always */
+    unsigned long backing_planes;/* planes to be preserved if possible */
+    unsigned long backing_pixel;/* value to be used when restoring planes */
+    Bool save_under;           /* boolean, should bits under be saved? */
+#endif
+    Colormap colormap;         /* color map to be associated with window */
+#if 0
+    Bool map_installed;                /* boolean, is color map currently installed*/
+    int map_state;             /* IsUnmapped, IsUnviewable, IsViewable */
+    long all_event_masks;      /* set of events all people have interest in*/
+    long your_event_mask;      /* my event mask */
+    long do_not_propagate_mask; /* set of events that should not propagate */
+    Bool override_redirect;    /* boolean value for override-redirect */
+#endif
+    Screen *screen;            /* back pointer to correct screen */
+};
+
+struct jwxyz_XColor {
+  unsigned long pixel;
+  unsigned short red, green, blue;
+  char flags;  /* do_red, do_green, do_blue */
+  char pad;
+};
+
+struct jwxyz_XPoint {
+  short x, y;
+};
+
+struct jwxyz_XSegment {
+  short x1, y1, x2, y2;
+};
+
+struct jwxyz_XRectangle {
+  short x, y;
+  unsigned short width, height;
+};
+
+struct jwxyz_XArc {
+  short x, y;
+  unsigned short width, height;
+  short angle1, angle2;
+};
+
+
+struct jwxyz_XrmOptionDescRec {
+  char *option;
+  char *specifier;
+  int argKind;
+  void *value;
+};
+
+struct jwxyz_XAnyEvent {
+  int type;
+#if 0
+  unsigned long serial;
+  Bool send_event;
+  Display *display;
+  Window window;
+#endif
+};
+
+struct jwxyz_XKeyEvent {
+  int type;
+#if 0
+  unsigned long serial;
+  Bool send_event;
+  Display *display;
+  Window window;
+  Window root;
+  Window subwindow;
+  Time time;
+  int x, y;
+  int x_root, y_root;
+#endif
+  unsigned int state;
+  unsigned int keycode;
+#if 0
+  Bool same_screen;
+#endif
+};
+
+struct jwxyz_XButtonEvent {
+  int type;
+#if 0
+  unsigned long serial;
+  Bool send_event;
+  Display *display;
+  Window window;
+  Window root;
+  Window subwindow;
+  Time time;
+#endif
+  int x, y;
+#if 0
+  int x_root, y_root;
+#endif
+  unsigned int state;
+  unsigned int button;
+#if 0
+  Bool same_screen;
+#endif
+};
+
+struct jwxyz_XMotionEvent {
+  int type;
+#if 0
+  unsigned long serial;
+  Bool send_event;
+  Display *display;
+  Window window;
+  Window root;
+  Window subwindow;
+  Time time;
+#endif
+  int x, y;
+#if 0
+  int x_root, y_root;
+#endif
+  unsigned int state;
+#if 0
+  char is_hint;
+  Bool same_screen;
+#endif
+};
+
+union jwxyz_XEvent {
+  int type;
+  XAnyEvent xany;
+  XKeyEvent xkey;
+  XButtonEvent xbutton;
+  XMotionEvent xmotion;
+};
+
+struct jwxyz_XImage {
+    int width, height;         /* size of image */
+    int xoffset;               /* number of pixels offset in X direction */
+    int format;                        /* XYBitmap, XYPixmap, ZPixmap */
+    char *data;                        /* pointer to image data */
+    int byte_order;            /* data byte order, LSBFirst, MSBFirst */
+    int bitmap_unit;           /* quant. of scanline 8, 16, 32 */
+    int bitmap_bit_order;      /* LSBFirst, MSBFirst */
+    int bitmap_pad;            /* 8, 16, 32 either XY or ZPixmap */
+    int depth;                 /* depth of image */
+    int bytes_per_line;                /* accelarator to next line */
+    int bits_per_pixel;                /* bits per pixel (ZPixmap) */
+    unsigned long red_mask;    /* bits in z arrangment */
+    unsigned long green_mask;
+    unsigned long blue_mask;
+//  XPointer obdata;           /* hook for the object routines to hang on */
+    struct funcs {             /* image manipulation routines */
+#if 0
+      XImage *(*create_image)(
+               Display*        /* display */,
+               Visual*         /* visual */,
+               unsigned int    /* depth */,
+               int             /* format */,
+               int             /* offset */,
+               char*           /* data */,
+               unsigned int    /* width */,
+               unsigned int    /* height */,
+               int             /* bitmap_pad */,
+               int             /* bytes_per_line */);
+       int (*destroy_image)        (XImage *);
+#endif
+       unsigned long (*get_pixel)  (XImage *, int, int);
+       int (*put_pixel)            (XImage *, int, int, unsigned long);
+#if 0
+       XImage *(*sub_image)        (XImage *, int, int, unsigned int, unsigned int);
+       int (*add_pixel)            (XImage *, long);
+#endif
+    } f;
+};
+
+struct jwxyz_XCharStruct {
+  short        lbearing;       /* origin to left edge of ink */
+  short        rbearing;       /* origin to right edge of ink */
+  short        width;          /* advance to next char's origin */
+  short        ascent;         /* baseline to top edge of ink */
+  short        descent;        /* baseline to bottom edge of ink */
+#if 0
+  unsigned short attributes;   /* per char flags (not predefined) */
+#endif
+};
+
+struct jwxyz_XFontProp {
+  Atom          name;
+  unsigned long card32; /* Careful: This holds (32- or 64-bit) pointers. */
+};
+
+struct jwxyz_XFontStruct {
+#if 0
+  XExtData     *ext_data;      /* hook for extension to hang data */
+#endif
+  Font          fid;            /* Font id for this font */
+#if 0
+  unsigned     direction;      /* hint about direction the font is painted */
+#endif
+  unsigned     min_char_or_byte2;      /* first character */
+  unsigned     max_char_or_byte2;      /* last character */
+#if 0
+  unsigned     min_byte1;      /* first row that exists */
+  unsigned     max_byte1;      /* last row that exists */
+  Bool all_chars_exist;        /* flag if all characters have non-zero size*/
+#endif
+  unsigned     default_char;   /* char to print for undefined character */
+  int         n_properties;   /* how many properties there are */
+  XFontProp    *properties;    /* pointer to array of additional properties*/
+  XCharStruct  min_bounds;     /* minimum bounds over all existing char*/
+  XCharStruct  max_bounds;     /* maximum bounds over all existing char*/
+  XCharStruct  *per_char;      /* first_char to last_char information */
+  int          ascent;         /* log. extent above baseline for spacing */
+  int          descent;        /* log. descent below baseline for spacing */
+};
+
+struct jwxyz_XComposeStatus {
+  char dummy;
+};
+
+struct  jwxyz_XPixmapFormatValues {
+  int depth;
+  int bits_per_pixel;
+  int scanline_pad;
+};
+
+struct jwxyz_XChar2b {
+  unsigned char byte1;
+  unsigned char byte2;
+};
+
+#endif /* __JWXYZ_H__ */
diff --git a/jwxyz/jwxyz.m b/jwxyz/jwxyz.m
new file mode 100644 (file)
index 0000000..bb189b0
--- /dev/null
@@ -0,0 +1,2902 @@
+/* xscreensaver, Copyright (c) 1991-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.
+ */
+
+/* JWXYZ Is Not Xlib.
+
+   But it's a bunch of function definitions that bear some resemblance to
+   Xlib and that do Cocoa-ish things that bear some resemblance to the
+   things that Xlib might have done.
+
+   This is the original version of jwxyz for MacOS and iOS.
+   The version used by Android is in jwxyz-gl.c and jwxyz-common.c.
+   Both versions depend on jwxyz-cocoa.m.
+ */
+
+#ifdef JWXYZ_QUARTZ // entire file
+
+#import <stdlib.h>
+#import <stdint.h>
+#import <wchar.h>
+
+#ifdef USE_IPHONE
+# import <UIKit/UIKit.h>
+# import <UIKit/UIScreen.h>
+# import <QuartzCore/QuartzCore.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
+#else
+# import <Cocoa/Cocoa.h>
+#endif
+
+#import <CoreText/CTFont.h>
+#import <CoreText/CTLine.h>
+#import <CoreText/CTRun.h>
+
+#import "jwxyzI.h"
+#import "jwxyz-cocoa.h"
+#import "jwxyz-timers.h"
+#import "yarandom.h"
+#import "utf8wc.h"
+#import "xft.h"
+
+# undef MAX
+# undef MIN
+# define MAX(a,b) ((a)>(b)?(a):(b))
+# define MIN(a,b) ((a)<(b)?(a):(b))
+
+
+struct jwxyz_Display {
+  Window main_window;
+  Screen *screen;
+  int screen_count;
+  struct jwxyz_sources_data *timers_data;
+
+# ifndef USE_IPHONE
+  CGDirectDisplayID cgdpy;  /* ...of the one and only Window, main_window.
+                               This can change if the window is dragged to
+                               a different screen. */
+# endif
+
+  CGColorSpaceRef colorspace;  /* Color space of this screen.  We tag all of
+                                  our images with this to avoid translation
+                                  when rendering. */
+
+  unsigned long window_background;
+};
+
+struct jwxyz_Screen {
+  Display *dpy;
+  CGBitmapInfo bitmap_info;
+  unsigned long black, white;
+  Visual *visual;
+  int screen_number;
+};
+
+struct jwxyz_GC {
+  XGCValues gcv;
+  unsigned int depth;
+  CGImageRef clip_mask;  // CGImage copy of the Pixmap in gcv.clip_mask
+};
+
+struct jwxyz_Font {
+  Display *dpy;
+  char *ps_name;
+  NSFont *nsfont;
+  float size;   // points
+  char *xa_font;
+
+  // In X11, "Font" is just an ID, and "XFontStruct" contains the metrics.
+  // But we need the metrics on both of them, so they go here.
+  XFontStruct metrics;
+};
+
+struct jwxyz_XFontSet {
+  XFontStruct *font;
+};
+
+
+// 24/32bpp -> 32bpp image conversion.
+// Any of RGBA, BGRA, ABGR, or ARGB can be represented by a rotate of 0/8/16/24
+// bits and an optional byte order swap.
+
+// This type encodes such a conversion.
+typedef unsigned convert_mode_t;
+
+// It's rotate, then swap.
+// A rotation here shifts bytes forward in memory. On x86/ARM, that's a left
+// rotate, and on PowerPC, a rightward rotation.
+static const convert_mode_t CONVERT_MODE_ROTATE_MASK = 0x3;
+static const convert_mode_t CONVERT_MODE_SWAP = 0x4;
+
+
+// Converts an array of pixels ('src') from one format to another, placing the
+// result in 'dest', according to the pixel conversion mode 'mode'.
+static void
+convert_row (uint32_t *dest, const void *src, size_t count,
+             convert_mode_t mode, size_t src_bpp)
+{
+  Assert (src_bpp == 24 || src_bpp == 32, "weird bpp");
+
+  // This works OK iff src == dest or src and dest do not overlap.
+
+  if (!mode) {
+    if (src != dest)
+      memcpy (dest, src, count * 4);
+    return;
+  }
+
+  // This is correct, but not fast.
+  convert_mode_t rot = (mode & CONVERT_MODE_ROTATE_MASK) * 8;
+  convert_mode_t flip = mode & CONVERT_MODE_SWAP;
+
+  src_bpp /= 8;
+
+  uint32_t *dest_end = dest + count;
+  while (dest != dest_end) {
+    uint32_t x;
+
+    if (src_bpp == 4)
+      x = *(const uint32_t *)src;
+    else { // src_bpp == 3
+      const uint8_t *src8 = (const uint8_t *)src;
+      // __LITTLE/BIG_ENDIAN__ are defined by the compiler.
+# if defined __LITTLE_ENDIAN__
+      x = src8[0] | (src8[1] << 8) | (src8[2] << 16) | 0xff000000;
+# elif defined __BIG_ENDIAN__
+      x = (src8[0] << 24) | (src8[1] << 16) | (src8[2] << 8) | 0xff;
+# else
+#  error "Can't determine system endianness."
+# endif
+    }
+
+    src = (const uint8_t *)src + src_bpp;
+
+    /* The naive (i.e. ubiquitous) portable implementation of bitwise rotation,
+       for 32-bit integers, is:
+
+       (x << rot) | (x >> (32 - rot))
+
+       This works nearly everywhere. Compilers on x86 wil generally recognize
+       the idiom and convert it to a ROL instruction. But there's a problem
+       here: according to the C specification, bit shifts greater than or equal
+       to the length of the integer are undefined. And if rot = 0:
+       1. (x << 0) | (x >> (32 - 0))
+       2. (x << 0) | (x >> 32)
+       3. (x << 0) | (Undefined!)
+
+       Still, when the compiler converts this to a ROL on x86, everything works
+       as intended. But, there are two additional problems when Clang does
+       compile-time constant expression evaluation with the (x >> 32)
+       expression:
+       1. Instead of evaluating it to something reasonable (either 0, like a
+          human would intuitively expect, or x, like x86 would with SHR), Clang
+          seems to pull a value out of nowhere, like -1, or some other random
+          number.
+       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.
+
+       http://blog.regehr.org/archives/1063
+       http://llvm.org/bugs/show_bug.cgi?id=17332
+       As described in those links, there is a solution here: Masking the
+       undefined shift with '& 31' as below makes the experesion well-defined
+       again. And LLVM is set to pick up on this safe version of the idiom and
+       use a rotation instruction on architectures (like x86) that support it,
+       just like it does with the unsafe version.
+
+       Too bad LLVM doesn't want to pick up on that particular optimization
+       here. Oh well. At least this code usually isn't critical w.r.t.
+       performance.
+     */
+
+# if defined __LITTLE_ENDIAN__
+    x = (x << rot) | (x >> ((32 - rot) & 31));
+# elif defined __BIG_ENDIAN__
+    x = (x >> rot) | (x << ((32 - rot) & 31));
+# endif
+
+    if (flip)
+      x = __builtin_bswap32(x); // LLVM/GCC built-in function.
+
+    *dest = x;
+    ++dest;
+  }
+}
+
+
+// Converts a single pixel.
+static uint32_t
+convert_px (uint32_t px, convert_mode_t mode)
+{
+  convert_row (&px, &px, 1, mode, 32);
+  return px;
+}
+
+
+// This returns the inverse conversion mode, such that:
+// pixel
+//   == convert_px(convert_px(pixel, mode), convert_mode_invert(mode))
+//   == convert_px(convert_px(pixel, convert_mode_invert(mode)), mode)
+static convert_mode_t
+convert_mode_invert (convert_mode_t mode)
+{
+  // swap(0); rot(n) == rot(n); swap(0)
+  // swap(1); rot(n) == rot(-n); swap(1)
+  return mode & CONVERT_MODE_SWAP ? mode : CONVERT_MODE_ROTATE_MASK & -mode;
+}
+
+
+// This combines two conversions into one, such that:
+// convert_px(convert_px(pixel, mode0), mode1)
+//   == convert_px(pixel, convert_mode_merge(mode0, mode1))
+static convert_mode_t
+convert_mode_merge (convert_mode_t m0, convert_mode_t m1)
+{
+  // rot(r0); swap(s0); rot(r1); swap(s1)
+  // rot(r0); rot(s0 ? -r1 : r1); swap(s0); swap(s1)
+  // rot(r0 + (s0 ? -r1 : r1)); swap(s0 + s1)
+  return
+    ((m0 + (m0 & CONVERT_MODE_SWAP ? -m1 : m1)) & CONVERT_MODE_ROTATE_MASK) |
+    ((m0 ^ m1) & CONVERT_MODE_SWAP);
+}
+
+
+// This returns a conversion mode that converts an arbitrary 32-bit format
+// specified by bitmap_info to RGBA.
+static convert_mode_t
+convert_mode_to_rgba (CGBitmapInfo bitmap_info)
+{
+  // Former default: kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little
+  // i.e. BGRA
+  // red   = 0x00FF0000;
+  // green = 0x0000FF00;
+  // blue  = 0x000000FF;
+
+  // RGBA: kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder32Big
+
+  CGImageAlphaInfo alpha_info =
+    (CGImageAlphaInfo)(bitmap_info & kCGBitmapAlphaInfoMask);
+
+  Assert (! (bitmap_info & kCGBitmapFloatComponents),
+          "kCGBitmapFloatComponents unsupported");
+  Assert (alpha_info != kCGImageAlphaOnly, "kCGImageAlphaOnly not supported");
+
+  convert_mode_t rot = alpha_info == kCGImageAlphaFirst ||
+                       alpha_info == kCGImageAlphaPremultipliedFirst ||
+                       alpha_info == kCGImageAlphaNoneSkipFirst ?
+                       3 : 0;
+
+  CGBitmapInfo byte_order = bitmap_info & kCGBitmapByteOrderMask;
+
+  Assert (byte_order == kCGBitmapByteOrder32Little ||
+          byte_order == kCGBitmapByteOrder32Big,
+          "byte order not supported");
+
+  convert_mode_t swap = byte_order == kCGBitmapByteOrder32Little ?
+                        CONVERT_MODE_SWAP : 0;
+  if (swap)
+    rot = CONVERT_MODE_ROTATE_MASK & -rot;
+  return swap | rot;
+}
+
+
+union color_bytes
+{
+  uint32_t pixel;
+  uint8_t bytes[4];
+};
+
+
+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)
+{
+  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);
+}
+
+
+/* We keep a list of all of the Displays that have been created and not
+   yet freed so that they can have sensible display numbers.  If three
+   displays are created (0, 1, 2) and then #1 is closed, then the fourth
+   display will be given the now-unused display number 1. (Everything in
+   here assumes a 1:1 Display/Screen mapping.)
+
+   The size of this array is the most number of live displays at one time.
+   So if it's 20, then we'll blow up if the system has 19 monitors and also
+   has System Preferences open (the small preview window).
+
+   Note that xlockmore-style savers tend to allocate big structures, so
+   setting this to 1000 will waste a few megabytes.  Also some of them assume
+   that the number of screens never changes, so dynamically expanding this
+   array won't work.
+ */
+# ifndef USE_IPHONE
+static Display *jwxyz_live_displays[20] = { 0, };
+# endif
+
+
+Display *
+jwxyz_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_count = 1;
+  d->screen->screen_number = 0;
+# ifndef USE_IPHONE
+  {
+    // Find the first empty slot in live_displays and plug us in.
+    int size = sizeof(jwxyz_live_displays) / sizeof(*jwxyz_live_displays);
+    int i;
+    for (i = 0; i < size; i++) {
+      if (! jwxyz_live_displays[i])
+        break;
+    }
+    if (i >= size) abort();
+    jwxyz_live_displays[i] = d;
+    d->screen_count = size;
+    d->screen->screen_number = i;
+  }
+# endif // !USE_IPHONE
+
+  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);
+
+# if 0
+  // Tests for the image conversion modes.
+  {
+    const uint32_t key = 0x04030201;
+#  ifdef __LITTLE_ENDIAN__
+    assert (convert_px (key, 0) == key);
+    assert (convert_px (key, 1) == 0x03020104);
+    assert (convert_px (key, 3) == 0x01040302);
+    assert (convert_px (key, 4) == 0x01020304);
+    assert (convert_px (key, 5) == 0x04010203);
+#  endif
+    for (unsigned i = 0; i != 8; ++i) {
+      assert (convert_px(convert_px(key, i), convert_mode_invert(i)) == key);
+      assert (convert_mode_invert(convert_mode_invert(i)) == i);
+    }
+
+    for (unsigned i = 0; i != 8; ++i) {
+      for (unsigned j = 0; j != 8; ++j)
+        assert (convert_px(convert_px(key, i), j) ==
+                convert_px(key, convert_mode_merge(i, j)));
+    }
+  }
+# endif
+
+  Visual *v = (Visual *) calloc (1, sizeof(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) &&
+          (byte_order == kCGBitmapByteOrder32Little ||
+           byte_order == kCGBitmapByteOrder32Big),
+          "invalid bits per channel");
+  v->bits_per_rgb = 8;
+  d->screen->visual = v;
+  
+  d->timers_data = jwxyz_sources_init (XtDisplayToApplicationContext (d));
+
+  d->window_background = BlackPixel(d,0);
+
+  d->main_window = w;
+
+  Assert (cgc, "no CGContext");
+  return d;
+}
+
+void
+jwxyz_free_display (Display *dpy)
+{
+  jwxyz_sources_free (dpy->timers_data);
+  
+# ifndef USE_IPHONE
+  {
+    // Find us in live_displays and clear that slot.
+    int size = ScreenCount(dpy);
+    int i;
+    for (i = 0; i < size; i++) {
+      if (dpy == jwxyz_live_displays[i]) {
+        jwxyz_live_displays[i] = 0;
+        break;
+      }
+    }
+    if (i >= size) abort();
+  }
+# endif // !USE_IPHONE
+
+  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.
+ */
+void
+invalidate_drawable_cache (Drawable d)
+{
+  if (d && d->cgi) {
+    CGImageRelease (d->cgi);
+    d->cgi = 0;
+  }
+}
+
+
+/* Call this when the View changes size or position.
+ */
+void
+jwxyz_window_resized (Display *dpy)
+{
+  Window w = dpy->main_window;
+
+# ifndef USE_IPHONE
+  // Figure out which screen the window is currently on.
+  {
+    int wx, wy;
+    XTranslateCoordinates (dpy, w, NULL, 0, 0, &wx, &wy, NULL);
+    CGPoint p;
+    p.x = wx;
+    p.y = wy;
+    CGDisplayCount n;
+    dpy->cgdpy = 0;
+    CGGetDisplaysWithPoint (p, 1, &dpy->cgdpy, &n);
+    // Auuugh!
+    if (! dpy->cgdpy) {
+      p.x = p.y = 0;
+      CGGetDisplaysWithPoint (p, 1, &dpy->cgdpy, &n);
+    }
+    Assert (dpy->cgdpy, "unable to find CGDisplay");
+  }
+# endif // USE_IPHONE
+
+/*
+  {
+    // Figure out this screen's colorspace, and use that for every CGImage.
+    //
+    CMProfileRef profile = 0;
+    CMGetProfileByAVID ((CMDisplayIDType) dpy->cgdpy, &profile);
+    Assert (profile, "unable to find colorspace profile");
+    dpy->colorspace = CGColorSpaceCreateWithPlatformColorSpace (profile);
+    Assert (dpy->colorspace, "unable to find colorspace");
+  }
+ */
+
+  // WTF?  It's faster if we *do not* use the screen's colorspace!
+  //
+  dpy->colorspace = CGColorSpaceCreateDeviceRGB();
+
+  invalidate_drawable_cache (w);
+}
+
+
+void
+jwxyz_flush_context (Display *dpy)
+{
+  // CGContextSynchronize is another possibility.
+  CGContextFlush(dpy->main_window->cgc);
+}
+
+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 s? s->screen_number : 0;
+}
+
+int
+jwxyz_ScreenCount (Display *dpy)
+{
+  return dpy ? dpy->screen_count : 0;
+}
+
+unsigned long
+XBlackPixelOfScreen(Screen *screen)
+{
+  return screen->black;
+}
+
+unsigned long
+XWhitePixelOfScreen(Screen *screen)
+{
+  return screen->white;
+}
+
+unsigned long
+XCellsOfScreen(Screen *screen)
+{
+  Visual *v = screen->visual;
+  return v->red_mask | v->green_mask | v->blue_mask;
+}
+
+
+void
+set_color (Display *dpy, CGContextRef cgc, unsigned long argb,
+           unsigned int depth, Bool alpha_allowed_p, Bool fill_p)
+{
+  jwxyz_validate_pixel (dpy, argb, depth, alpha_allowed_p);
+  if (depth == 1) {
+    if (fill_p)
+      CGContextSetGrayFillColor   (cgc, (argb ? 1.0 : 0.0), 1.0);
+    else
+      CGContextSetGrayStrokeColor (cgc, (argb ? 1.0 : 0.0), 1.0);
+  } else {
+    float rgba[4];
+    query_color_float (dpy, argb, rgba);
+    if (fill_p)
+      CGContextSetRGBFillColor   (cgc, rgba[0], rgba[1], rgba[2], rgba[3]);
+    else
+      CGContextSetRGBStrokeColor (cgc, rgba[0], rgba[1], rgba[2], rgba[3]);
+  }
+}
+
+static void
+set_line_mode (CGContextRef cgc, XGCValues *gcv)
+{
+  CGContextSetLineWidth (cgc, gcv->line_width ? gcv->line_width : 1);
+  CGContextSetLineJoin  (cgc,
+                         gcv->join_style == JoinMiter ? kCGLineJoinMiter :
+                         gcv->join_style == JoinRound ? kCGLineJoinRound :
+                         kCGLineJoinBevel);
+  CGContextSetLineCap   (cgc, 
+                         gcv->cap_style == CapNotLast ? kCGLineCapButt  :
+                         gcv->cap_style == CapButt    ? kCGLineCapButt  :
+                         gcv->cap_style == CapRound   ? kCGLineCapRound :
+                         kCGLineCapSquare);
+}
+
+static void
+set_clip_mask (Drawable d, GC gc)
+{
+  Assert (!!gc->gcv.clip_mask == !!gc->clip_mask, "GC clip mask mixup");
+
+  Pixmap p = gc->gcv.clip_mask;
+  if (!p) return;
+  Assert (p->type == PIXMAP, "not a pixmap");
+
+  XRectangle wr = d->frame;
+  CGRect to;
+  to.origin.x    = wr.x + gc->gcv.clip_x_origin;
+  to.origin.y    = wr.y + wr.height - gc->gcv.clip_y_origin
+                    - p->frame.height;
+  to.size.width  = p->frame.width;
+  to.size.height = p->frame.height;
+
+  CGContextClipToMask (d->cgc, to, gc->clip_mask);
+}
+
+
+/* Pushes a GC context; sets BlendMode and ClipMask.
+ */
+void
+push_gc (Drawable d, GC gc)
+{
+  CGContextRef cgc = d->cgc;
+  CGContextSaveGState (cgc);
+
+  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;
+  }
+
+  if (gc->gcv.clip_mask)
+    set_clip_mask (d, gc);
+}
+
+
+/* Pushes a GC context; sets BlendMode, ClipMask, Fill, and Stroke colors.
+ */
+void
+push_color_gc (Display *dpy, Drawable d, GC gc, unsigned long color,
+               Bool antialias_p, Bool fill_p)
+{
+  push_gc (d, gc);
+
+  int 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;
+  }
+
+  CGContextRef cgc = d->cgc;
+  set_color (dpy, cgc, color, depth, gc->gcv.alpha_allowed_p, fill_p);
+  CGContextSetShouldAntialias (cgc, antialias_p);
+}
+
+
+/* Pushes a GC context; sets Fill and Stroke colors to the foreground color.
+ */
+static void
+push_fg_gc (Display *dpy, Drawable d, GC gc, Bool fill_p)
+{
+  push_color_gc (dpy, d, gc, gc->gcv.foreground, gc->gcv.antialias_p, fill_p);
+}
+
+static Bool
+bitmap_context_p (Drawable d)
+{
+  return True;
+}
+
+
+
+/* You've got to be fucking kidding me!
+
+   It is *way* faster to draw points by creating and drawing a 1x1 CGImage
+   with repeated calls to CGContextDrawImage than it is to make a single
+   call to CGContextFillRects() with a list of 1x1 rectangles!
+
+   I still wouldn't call it *fast*, however...
+ */
+#define XDRAWPOINTS_IMAGES
+
+/* Update, 2012: Kurt Revis <krevis@snoize.com> points out that diddling
+   the bitmap data directly is faster.  This only works on Pixmaps, though,
+   not Windows.  (Fortunately, on iOS, the Window is really a Pixmap.)
+ */
+#define XDRAWPOINTS_CGDATA
+
+int
+XDrawPoints (Display *dpy, Drawable d, GC gc, 
+             XPoint *points, int count, int mode)
+{
+  int i;
+  XRectangle wr = d->frame;
+
+# ifdef XDRAWPOINTS_CGDATA
+
+  if (bitmap_context_p (d))
+  {
+    CGContextRef cgc = d->cgc;
+    void *data = CGBitmapContextGetData (cgc);
+    size_t bpr = CGBitmapContextGetBytesPerRow (cgc);
+    size_t w = CGBitmapContextGetWidth (cgc);
+    size_t h = CGBitmapContextGetHeight (cgc);
+
+    Assert (data, "no bitmap data in Drawable");
+
+    unsigned long argb = gc->gcv.foreground;
+    jwxyz_validate_pixel (dpy, argb, gc->depth, gc->gcv.alpha_allowed_p);
+    if (gc->depth == 1)
+      argb = (gc->gcv.foreground ? WhitePixel(dpy,0) : BlackPixel(dpy,0));
+
+    CGFloat x0 = wr.x;
+    CGFloat y0 = wr.y; // Y axis is refreshingly not flipped.
+
+    // It's uglier, but faster, to hoist the conditional out of the loop.
+    if (mode == CoordModePrevious) {
+      CGFloat x = x0, y = y0;
+      for (i = 0; i < count; i++, points++) {
+        x += points->x;
+        y += points->y;
+
+        if (x >= 0 && x < w && y >= 0 && y < h) {
+          unsigned int *p = (unsigned int *)
+            ((char *) data + (size_t) y * bpr + (size_t) x * 4);
+          *p = (unsigned int) argb;
+        }
+      }
+    } else {
+      for (i = 0; i < count; i++, points++) {
+        CGFloat x = x0 + points->x;
+        CGFloat y = y0 + points->y;
+
+        if (x >= 0 && x < w && y >= 0 && y < h) {
+          unsigned int *p = (unsigned int *)
+            ((char *) data + (size_t) y * bpr + (size_t) x * 4);
+          *p = (unsigned int) argb;
+        }
+      }
+    }
+
+  } else       /* d->type == WINDOW */
+
+# endif /* XDRAWPOINTS_CGDATA */
+  {
+    push_fg_gc (dpy, d, gc, YES);
+
+# ifdef XDRAWPOINTS_IMAGES
+
+    unsigned long argb = gc->gcv.foreground;
+    jwxyz_validate_pixel (dpy, argb, gc->depth, gc->gcv.alpha_allowed_p);
+    if (gc->depth == 1)
+      argb = (gc->gcv.foreground ? WhitePixel(dpy,0) : BlackPixel(dpy,0));
+
+    CGDataProviderRef prov = CGDataProviderCreateWithData (NULL, &argb, 4,
+                                                           NULL);
+    CGImageRef cgi = CGImageCreate (1, 1,
+                                    8, 32, 4,
+                                    dpy->colorspace, 
+                                    /* Host-ordered, since we're using the
+                                       address of an int as the color data. */
+                                    dpy->screen->bitmap_info,
+                                    prov, 
+                                    NULL,  /* decode[] */
+                                    NO, /* interpolate */
+                                    kCGRenderingIntentDefault);
+    CGDataProviderRelease (prov);
+
+    CGContextRef cgc = d->cgc;
+    CGRect rect;
+    rect.size.width = rect.size.height = 1;
+    for (i = 0; i < count; i++) {
+      if (i > 0 && mode == CoordModePrevious) {
+        rect.origin.x += points->x;
+        rect.origin.x -= points->y;
+      } else {
+        rect.origin.x = wr.x + points->x;
+        rect.origin.y = wr.y + wr.height - points->y - 1;
+      }
+
+      //Assert(CGImageGetColorSpace (cgi) == dpy->colorspace,"bad colorspace");
+      CGContextDrawImage (cgc, rect, cgi);
+      points++;
+    }
+
+    CGImageRelease (cgi);
+
+# else /* ! XDRAWPOINTS_IMAGES */
+
+    CGRect *rects = (CGRect *) malloc (count * sizeof(CGRect));
+    CGRect *r = rects;
+  
+    for (i = 0; i < count; i++) {
+      r->size.width = r->size.height = 1;
+      if (i > 0 && mode == CoordModePrevious) {
+        r->origin.x = r[-1].origin.x + points->x;
+        r->origin.y = r[-1].origin.x - points->y;
+      } else {
+        r->origin.x = wr.origin.x + points->x;
+        r->origin.y = wr.origin.y + wr.size.height - points->y;
+      }
+      points++;
+      r++;
+    }
+
+    CGContextFillRects (d->cgc, rects, count);
+    free (rects);
+
+# endif /* ! XDRAWPOINTS_IMAGES */
+
+    pop_gc (d, gc);
+  }
+
+  invalidate_drawable_cache (d);
+
+  return 0;
+}
+
+
+CGPoint
+map_point (Drawable d, int x, int y)
+{
+  const XRectangle *wr = &d->frame;
+  CGPoint p;
+  p.x = wr->x + x;
+  p.y = wr->y + wr->height - y;
+  return p;
+}
+
+
+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;
+  }
+}
+
+
+static CGPoint
+point_for_line (Drawable d, GC gc, int x, int y)
+{
+  CGPoint result = map_point (d, x, y);
+  adjust_point_for_line (gc, &result);
+  return result;
+}
+
+
+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,
+            int mode)
+{
+  int i;
+  CGPoint p;
+  push_fg_gc (dpy, d, gc, NO);
+
+  CGContextRef cgc = d->cgc;
+
+  set_line_mode (cgc, &gc->gcv);
+  
+  // if the first and last points coincide, use closepath to get
+  // the proper line-joining.
+  BOOL closed_p = (points[0].x == points[count-1].x &&
+                   points[0].y == points[count-1].y);
+  if (closed_p) count--;
+  
+  p = point_for_line(d, gc, points->x, points->y);
+  points++;
+  CGContextBeginPath (cgc);
+  CGContextMoveToPoint (cgc, p.x, p.y);
+  for (i = 1; i < count; i++) {
+    if (mode == CoordModePrevious) {
+      p.x += points->x;
+      p.y -= points->y;
+    } else {
+      p = point_for_line(d, gc, points->x, points->y);
+    }
+    CGContextAddLineToPoint (cgc, p.x, p.y);
+    points++;
+  }
+  if (closed_p) CGContextClosePath (cgc);
+  CGContextStrokePath (cgc);
+  pop_gc (d, gc);
+  invalidate_drawable_cache (d);
+  return 0;
+}
+
+
+int
+XDrawSegments (Display *dpy, Drawable d, GC gc, XSegment *segments, int count)
+{
+  int i;
+
+  CGContextRef cgc = d->cgc;
+
+  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++;
+  }
+  CGContextStrokePath (cgc);
+  pop_gc (d, gc);
+  invalidate_drawable_cache (d);
+  return 0;
+}
+
+
+int
+XClearWindow (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)
+{
+  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)
+{
+  Assert (!gc || gc->depth == jwxyz_drawable_depth (d), "depth mismatch");
+
+  CGContextRef cgc = d->cgc;
+
+  Bool fast_fill_p =
+    bitmap_context_p (d) &&
+    (!gc || (gc->gcv.function == GXcopy &&
+             !gc->gcv.alpha_allowed_p &&
+             !gc->gcv.clip_mask));
+
+  if (!fast_fill_p) {
+    if (gc)
+      push_color_gc (dpy, d, gc, pixel, gc->gcv.antialias_p, YES);
+    else
+      set_color (dpy, d->cgc, pixel, jwxyz_drawable_depth (d), NO, YES);
+  }
+
+  for (unsigned i = 0; i != nrectangles; ++i) {
+
+    int x = rectangles[i].x;
+    int y = rectangles[i].y;
+    unsigned long width = rectangles[i].width;
+    unsigned long height = rectangles[i].height;
+
+    if (fast_fill_p) {
+      long   // negative_int > unsigned_int == 1
+        dw = CGBitmapContextGetWidth (cgc),
+        dh = CGBitmapContextGetHeight (cgc);
+
+      if (x >= dw || y >= dh)
+        continue;
+
+      if (x < 0) {
+        width += x;
+        x = 0;
+      }
+
+      if (y < 0) {
+        height += y;
+        y = 0;
+      }
+
+      if (width <= 0 || height <= 0)
+        continue;
+
+      unsigned long max_width = dw - x;
+      if (width > max_width)
+        width = max_width;
+      unsigned long max_height = dh - y;
+      if (height > max_height)
+        height = max_height;
+
+      if (jwxyz_drawable_depth (d) == 1)
+        pixel = pixel ? WhitePixel(dpy, 0) : BlackPixel(dpy, 0);
+
+      size_t dst_bytes_per_row = CGBitmapContextGetBytesPerRow (d->cgc);
+      void *dst = seek_xy (CGBitmapContextGetData (d->cgc),
+                           dst_bytes_per_row, x, y);
+
+      Assert(sizeof(wchar_t) == 4, "somebody changed the ABI");
+      while (height) {
+        // Would be nice if Apple used SSE/NEON in wmemset. Maybe someday.
+        wmemset (dst, (wchar_t) pixel, width);
+        --height;
+        dst = (char *) dst + dst_bytes_per_row;
+      }
+
+    } else {
+      CGRect r;
+      r.origin = map_point (d, x, y);
+      r.origin.y -= height;
+      r.size.width = width;
+      r.size.height = height;
+      CGContextFillRect (cgc, r);
+    }
+  }
+
+  if (!fast_fill_p && gc)
+    pop_gc (d, gc);
+  invalidate_drawable_cache (d);
+}
+
+
+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)
+{
+  XRectangle wr = d->frame;
+  int i;
+  push_fg_gc (dpy, d, gc, YES);
+  CGContextRef cgc = d->cgc;
+  CGContextBeginPath (cgc);
+  float x = 0, y = 0;
+  for (i = 0; i < npoints; i++) {
+    if (i > 0 && mode == CoordModePrevious) {
+      x += points[i].x;
+      y -= points[i].y;
+    } else {
+      x = wr.x + points[i].x;
+      y = wr.y + wr.height - points[i].y;
+    }
+        
+    if (i == 0)
+      CGContextMoveToPoint (cgc, x, y);
+    else
+      CGContextAddLineToPoint (cgc, x, y);
+  }
+  CGContextClosePath (cgc);
+  if (gc->gcv.fill_rule == EvenOddRule)
+    CGContextEOFillPath (cgc);
+  else
+    CGContextFillPath (cgc);
+  pop_gc (d, gc);
+  invalidate_drawable_cache (d);
+  return 0;
+}
+
+#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,
+                unsigned int width, unsigned int height,
+                int angle1, int angle2, Bool fill_p)
+{
+  XRectangle wr = d->frame;
+  CGRect bound;
+  bound.origin.x = wr.x + x;
+  bound.origin.y = wr.y + wr.height - y - (int)height;
+  bound.size.width = width;
+  bound.size.height = height;
+  
+  CGPoint ctr;
+  ctr.x = bound.origin.x + bound.size.width /2;
+  ctr.y = bound.origin.y + bound.size.height/2;
+  
+  float r1 = radians (angle1/64.0);
+  float r2 = radians (angle2/64.0) + r1;
+  BOOL clockwise = angle2 < 0;
+  BOOL closed_p = (angle2 >= 360*64 || angle2 <= -360*64);
+  
+  push_fg_gc (dpy, d, gc, fill_p);
+
+  CGContextRef cgc = d->cgc;
+  CGContextBeginPath (cgc);
+  
+  CGContextSaveGState(cgc);
+  CGContextTranslateCTM (cgc, ctr.x, ctr.y);
+  CGContextScaleCTM (cgc, width/2.0, height/2.0);
+  if (fill_p)
+    CGContextMoveToPoint (cgc, 0, 0);
+
+  CGContextAddArc (cgc, 0.0, 0.0, 1, r1, r2, clockwise);
+  CGContextRestoreGState (cgc);  // restore before stroke, for line width
+
+  if (closed_p)
+    CGContextClosePath (cgc); // for proper line joining
+  
+  if (fill_p) {
+    CGContextFillPath (cgc);
+  } else {
+    set_line_mode (cgc, &gc->gcv);
+    CGContextStrokePath (cgc);
+  }
+
+  pop_gc (d, gc);
+  invalidate_drawable_cache (d);
+  return 0;
+}
+
+
+XGCValues *
+jwxyz_gc_gcv (GC gc)
+{
+  return &gc->gcv;
+}
+
+
+unsigned int
+jwxyz_gc_depth (GC gc)
+{
+  return gc->depth;
+}
+
+
+GC
+XCreateGC (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);
+
+  jwxyz_gcv_defaults (dpy, &gc->gcv, gc->depth);
+  XChangeGC (dpy, gc, mask, xgcv);
+  return gc;
+}
+
+
+int
+XFreeGC (Display *dpy, GC gc)
+{
+  if (gc->gcv.font)
+    XUnloadFont (dpy, gc->gcv.font);
+
+  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);
+  }
+  free (gc);
+  return 0;
+}
+
+
+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)
+{
+  XRectangle wr = d->frame;
+
+  Assert (gc, "no GC");
+  Assert ((w < 65535), "improbably large width");
+  Assert ((h < 65535), "improbably large height");
+  Assert ((src_x  < 65535 && src_x  > -65535), "improbably large src_x");
+  Assert ((src_y  < 65535 && src_y  > -65535), "improbably large src_y");
+  Assert ((dest_x < 65535 && dest_x > -65535), "improbably large dest_x");
+  Assert ((dest_y < 65535 && dest_y > -65535), "improbably large dest_y");
+
+  // Clip width and height to the bounds of the Drawable
+  //
+  if (dest_x + (int)w > wr.width) {
+    if (dest_x > wr.width)
+      return 0;
+    w = wr.width - dest_x;
+  }
+  if (dest_y + (int)h > wr.height) {
+    if (dest_y > wr.height)
+      return 0;
+    h = wr.height - dest_y;
+  }
+  if (w <= 0 || h <= 0)
+    return 0;
+
+  // Clip width and height to the bounds of the XImage
+  //
+  if (src_x + w > ximage->width) {
+    if (src_x > ximage->width)
+      return 0;
+    w = ximage->width - src_x;
+  }
+  if (src_y + h > ximage->height) {
+    if (src_y > ximage->height)
+      return 0;
+    h = ximage->height - src_y;
+  }
+  if (w <= 0 || h <= 0)
+    return 0;
+
+  CGContextRef cgc = d->cgc;
+
+  if (jwxyz_dumb_drawing_mode(dpy, d, gc, dest_x, dest_y, w, h))
+    return 0;
+
+  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 - (int)h;
+  r.size.width = w;
+  r.size.height = h;
+
+  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);
+    CGDataProviderRef prov = 
+      CGDataProviderCreateWithData (NULL, data, bsize, NULL);
+
+    CGImageRef cgi = CGImageCreate (w, h,
+                                    bpp/4, bpp, bpl,
+                                    dpy->colorspace, 
+                                    dpy->screen->bitmap_info,
+                                    prov, 
+                                    NULL,  /* decode[] */
+                                    NO, /* interpolate */
+                                    kCGRenderingIntentDefault);
+    CGDataProviderRelease (prov);
+    //Assert (CGImageGetColorSpace (cgi) == dpy->colorspace, "bad colorspace");
+    CGContextDrawImage (cgc, r, cgi);
+    CGImageRelease (cgi);
+
+  } else {   // (bpp == 1)
+
+    /* 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[] */
+                                         NO); /* interpolate */
+    push_fg_gc (dpy, d, gc, YES);
+
+    CGContextFillRect (cgc, r);                                // foreground color
+    CGContextClipToMask (cgc, r, mask);
+    set_color (dpy, cgc, gc->gcv.background, gc->depth, NO, YES);
+    CGContextFillRect (cgc, r);                                // background color
+    pop_gc (d, gc);
+
+    free (flipped);
+    CGDataProviderRelease (prov);
+    CGImageRelease (mask);
+  }
+
+  invalidate_drawable_cache (d);
+
+  return 0;
+}
+
+
+XImage *
+XGetImage (Display *dpy, Drawable d, int x, int y,
+           unsigned int width, unsigned int height,
+           unsigned long plane_mask, int format)
+{
+  const unsigned char *data = 0;
+  size_t depth, ibpp, ibpl;
+  convert_mode_t mode;
+
+  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");
+
+  CGContextRef cgc = d->cgc;
+
+  {
+    depth = jwxyz_drawable_depth (d);
+    mode = convert_mode_to_rgba (dpy->screen->bitmap_info);
+    ibpp = CGBitmapContextGetBitsPerPixel (cgc);
+    ibpl = CGBitmapContextGetBytesPerRow (cgc);
+    data = CGBitmapContextGetData (cgc);
+    Assert (data, "CGBitmapContextGetData failed");
+  }
+  
+  // data points at (x,y) with ibpl rowstride.  ignore x,y from now on.
+  data += (y * ibpl) + (x * (ibpp/8));
+  
+  format = (depth == 1 ? XYPixmap : ZPixmap);
+  XImage *image = XCreateImage (dpy, 0, (unsigned int) depth,
+                                format, 0, 0, width, height, 0, 0);
+  image->data = (char *) malloc (height * image->bytes_per_line);
+  
+  int obpl = image->bytes_per_line;
+  
+  /* both PPC and Intel use word-ordered ARGB frame buffers, which
+     means that on Intel it is BGRA when viewed by bytes (And BGR
+     when using 24bpp packing).
+
+     BUT! Intel-64 stores alpha at the other end! 32bit=RGBA, 64bit=ARGB.
+     The NSAlphaFirstBitmapFormat bit in bitmapFormat seems to be the
+     indicator of this latest kink.
+   */
+  int xx, yy;
+  if (depth == 1) {
+    const unsigned char *iline = data;
+    for (yy = 0; yy < height; yy++) {
+
+      const unsigned char *iline2 = iline;
+      for (xx = 0; xx < width; xx++) {
+
+        iline2++;                     // ignore R  or  A  or  A  or  B
+        iline2++;                     // ignore G  or  B  or  R  or  G
+        unsigned char r = *iline2++;  // use    B  or  G  or  G  or  R
+        if (ibpp == 32) iline2++;     // ignore A  or  R  or  B  or  A
+
+        XPutPixel (image, xx, yy, (r ? 1 : 0));
+      }
+      iline += ibpl;
+    }
+  } else {
+    const unsigned char *iline = data;
+    unsigned char *oline = (unsigned char *) image->data;
+
+    mode = convert_mode_merge (mode,
+             convert_mode_invert (
+               convert_mode_to_rgba (dpy->screen->bitmap_info)));
+
+    for (yy = 0; yy < height; yy++) {
+
+      convert_row ((uint32_t *)oline, iline, width, mode, ibpp);
+
+      oline += obpl;
+      iline += ibpl;
+    }
+  }
+
+  return image;
+}
+
+
+
+/* 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)
+{
+  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);
+
+  XRectangle winr = d->frame;
+  float rw = winr.width  / imgr.width;
+  float rh = winr.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.width  - dst.size.width)  / 2;
+  dst.origin.y = (winr.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.width, winr.height,
+                     jwxyz_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);
+}
+
+
+
+Pixmap
+XCreatePixmap (Display *dpy, Drawable d,
+               unsigned int width, unsigned int height, unsigned int depth)
+{
+  if (!dpy) abort();
+  char *data = (char *) malloc (width * height * 4);
+  if (! data) return 0;
+
+  Pixmap p = (Pixmap) calloc (1, sizeof(*p));
+  p->type = PIXMAP;
+  p->frame.width       = width;
+  p->frame.height      = height;
+  p->pixmap.depth      = depth;
+  p->pixmap.cgc_buffer = data;
+  
+  /* Quartz doesn't have a 1bpp image type.
+     Used to use 8bpp gray images instead of 1bpp, but some Mac video cards
+     don't support that!  So we always use 32bpp, regardless of depth. */
+
+  p->cgc = CGBitmapContextCreate (data, width, height,
+                                  8, /* bits per component */
+                                  width * 4, /* bpl */
+                                  dpy->colorspace,
+                                  dpy->screen->bitmap_info);
+  Assert (p->cgc, "could not create CGBitmapContext");
+  return p;
+}
+
+
+int
+XFreePixmap (Display *d, Pixmap p)
+{
+  Assert (p && p->type == PIXMAP, "not a pixmap");
+  invalidate_drawable_cache (p);
+  CGContextRelease (p->cgc);
+  if (p->pixmap.cgc_buffer)
+    free (p->pixmap.cgc_buffer);
+  free (p);
+  return 0;
+}
+
+
+static Pixmap
+copy_pixmap (Display *dpy, Pixmap p)
+{
+  if (!p) return 0;
+  Assert (p->type == PIXMAP, "not a pixmap");
+
+  Pixmap p2 = 0;
+
+  Window root;
+  int x, y;
+  unsigned int width, height, border_width, depth;
+  if (XGetGeometry (dpy, p, &root,
+                    &x, &y, &width, &height, &border_width, &depth)) {
+    XGCValues gcv;
+    gcv.function = GXcopy;
+    GC gc = XCreateGC (dpy, p, GCFunction, &gcv);
+    if (gc) {
+      p2 = XCreatePixmap (dpy, p, width, height, depth);
+      if (p2)
+        XCopyArea (dpy, p, p2, gc, 0, 0, width, height, 0, 0);
+      XFreeGC (dpy, gc);
+    }
+  }
+
+  Assert (p2, "could not copy pixmap");
+
+  return p2;
+}
+
+
+/* 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.
+ */
+static void
+utf8_metrics (Font fid, NSString *nsstr, XCharStruct *cs)
+{
+  // Returns the metrics of the multi-character, single-line UTF8 string.
+
+  NSFont *nsfont = fid->nsfont;
+  Drawable d = XRootWindow (fid->dpy, 0);
+
+  CGContextRef cgc = d->cgc;
+  NSDictionary *attr =
+    [NSDictionary dictionaryWithObjectsAndKeys:
+                    nsfont, NSFontAttributeName,
+                  nil];
+  NSAttributedString *astr = [[NSAttributedString alloc]
+                               initWithString:nsstr
+                                   attributes:attr];
+  CTLineRef ctline = CTLineCreateWithAttributedString (
+                       (__bridge CFAttributedStringRef) astr);
+  CGContextSetTextPosition (cgc, 0, 0);
+  CGContextSetShouldAntialias (cgc, True);  // #### Guess?
+
+  memset (cs, 0, sizeof(*cs));
+
+  // "CTRun represents set of consecutive glyphs sharing the same
+  // attributes and direction".
+  //
+  // We also get multiple runs any time font subsitution happens:
+  // E.g., if the current font is Verdana-Bold, a &larr; character
+  // in the NSString will actually be rendered in LucidaGrande-Bold.
+  //
+  int count = 0;
+  for (id runid in (NSArray *)CTLineGetGlyphRuns(ctline)) {
+    CTRunRef run = (CTRunRef) runid;
+    CFRange r = { 0, };
+    CGRect bbox = CTRunGetImageBounds (run, cgc, r);
+    CGFloat ascent, descent, leading;
+    CGFloat advancement =
+      CTRunGetTypographicBounds (run, r, &ascent, &descent, &leading);
+
+# ifndef USE_IPHONE
+    // Only necessary for when LCD smoothing is enabled, which iOS doesn't do.
+    bbox.origin.x    -= 2.0/3.0;
+    bbox.size.width  += 4.0/3.0;
+    bbox.size.height += 1.0/2.0;
+# endif
+
+    // Create the metrics for this run:
+    XCharStruct cc;
+    cc.ascent   = ceil  (bbox.origin.y + bbox.size.height);
+    cc.descent  = ceil (-bbox.origin.y);
+    cc.lbearing = floor (bbox.origin.x);
+    cc.rbearing = ceil  (bbox.origin.x + bbox.size.width);
+    cc.width    = floor (advancement + 0.5);
+
+    // Add those metrics into the cumulative metrics:
+    if (count == 0)
+      *cs = cc;
+    else
+      {
+        cs->ascent   = MAX (cs->ascent,     cc.ascent);
+        cs->descent  = MAX (cs->descent,    cc.descent);
+        cs->lbearing = MIN (cs->lbearing,   cs->width + cc.lbearing);
+        cs->rbearing = MAX (cs->rbearing,   cs->width + cc.rbearing);
+        cs->width    = MAX (cs->width,      cs->width + cc.width);
+      }
+
+    // Why no y? What about vertical text?
+    // XCharStruct doesn't encapsulate that but XGlyphInfo does.
+
+    count++;
+  }
+
+  [astr release];
+  CFRelease (ctline);
+}
+
+
+
+// This is XQueryFont, but for the XFontStruct embedded in 'Font'
+//
+static void
+query_font (Font fid)
+{
+  if (!fid || !fid->nsfont) {
+    Assert (0, "no NSFont in fid");
+    return;
+  }
+  if (![fid->nsfont fontName]) {
+    Assert(0, "broken NSFont in fid");
+    return;
+  }
+
+  int first = 32;
+  int last = 255;
+
+  XFontStruct *f = &fid->metrics;
+  XCharStruct *min = &f->min_bounds;
+  XCharStruct *max = &f->max_bounds;
+
+  f->fid               = fid;
+  f->min_char_or_byte2 = first;
+  f->max_char_or_byte2 = last;
+  f->default_char      = 'M';
+  f->ascent            =  ceil ([fid->nsfont ascender]);
+  f->descent           = -floor ([fid->nsfont descender]);
+
+  min->width    = 32767;  // set to smaller values in the loop
+  min->ascent   = 32767;
+  min->descent  = 32767;
+  min->lbearing = 32767;
+  min->rbearing = 32767;
+
+  f->per_char = (XCharStruct *) calloc (last-first+2, sizeof (XCharStruct));
+
+  for (int i = first; i <= last; i++) {
+    XCharStruct *cs = &f->per_char[i-first];
+
+    char s2[2];
+    s2[0] = i;
+    s2[1] = 0;
+    NSString *nsstr = [NSString stringWithCString:s2
+                               encoding:NSISOLatin1StringEncoding];
+    utf8_metrics (fid, nsstr, cs);
+
+    max->width    = MAX (max->width,    cs->width);
+    max->ascent   = MAX (max->ascent,   cs->ascent);
+    max->descent  = MAX (max->descent,  cs->descent);
+    max->lbearing = MAX (max->lbearing, cs->lbearing);
+    max->rbearing = MAX (max->rbearing, cs->rbearing);
+
+    min->width    = MIN (min->width,    cs->width);
+    min->ascent   = MIN (min->ascent,   cs->ascent);
+    min->descent  = MIN (min->descent,  cs->descent);
+    min->lbearing = MIN (min->lbearing, cs->lbearing);
+    min->rbearing = MIN (min->rbearing, cs->rbearing);
+
+# if 0
+    fprintf(stderr, " %3d %c: w=%3d lb=%3d rb=%3d as=%3d ds=%3d "
+                    " bb=%5.1f x %5.1f @ %5.1f %5.1f  adv=%5.1f %5.1f\n",
+            i, i, cs->width, cs->lbearing, cs->rbearing, 
+            cs->ascent, cs->descent,
+            bbox.size.width, bbox.size.height,
+            bbox.origin.x, bbox.origin.y,
+            advancement.width, advancement.height);
+# endif // 0
+  }
+}
+
+
+// Since 'Font' includes the metrics, this just makes a copy of that.
+//
+XFontStruct *
+XQueryFont (Display *dpy, Font fid)
+{
+  // copy XFontStruct
+  XFontStruct *f = (XFontStruct *) calloc (1, sizeof(*f));
+  *f = fid->metrics;
+
+  // build XFontProps
+  f->n_properties = 1;
+  f->properties = malloc (sizeof(*f->properties) * f->n_properties);
+  f->properties[0].name = XA_FONT;
+  Assert (sizeof (f->properties[0].card32) >= sizeof (char *),
+          "atoms probably needs a real implementation");
+  // If XInternAtom is ever implemented, use it here.
+  f->properties[0].card32 = (char *)fid->xa_font;
+
+  // copy XCharStruct array
+  int size = (f->max_char_or_byte2 - f->min_char_or_byte2) + 1;
+  f->per_char = (XCharStruct *) calloc (size + 2, sizeof (XCharStruct));
+  memcpy (f->per_char, fid->metrics.per_char,
+          size * sizeof (XCharStruct));
+
+  return f;
+}
+
+
+static Font
+copy_font (Font fid)
+{
+  // copy 'Font' struct
+  Font fid2 = (Font) malloc (sizeof(*fid2));
+  *fid2 = *fid;
+
+  // copy XCharStruct array
+  int size = fid->metrics.max_char_or_byte2 - fid->metrics.min_char_or_byte2;
+  fid2->metrics.per_char = (XCharStruct *) 
+    malloc ((size + 2) * sizeof (XCharStruct));
+  memcpy (fid2->metrics.per_char, fid->metrics.per_char, 
+          size * sizeof (XCharStruct));
+
+  // copy the other pointers
+  fid2->ps_name = strdup (fid->ps_name);
+  fid2->xa_font = strdup (fid->xa_font);
+//  [fid2->nsfont retain];
+  fid2->metrics.fid = fid2;
+
+  return fid2;
+}
+
+
+static NSArray *
+font_family_members (NSString *family_name)
+{
+# ifndef USE_IPHONE
+  return [[NSFontManager sharedFontManager]
+          availableMembersOfFontFamily:family_name];
+# else
+  return [UIFont fontNamesForFamilyName:family_name];
+# endif
+}
+
+
+static NSString *
+default_font_family (NSFontTraitMask require)
+{
+  return require & NSFixedPitchFontMask ? @"Courier" : @"Verdana";
+}
+
+
+static NSFont *
+try_font (NSFontTraitMask traits, NSFontTraitMask mask,
+          NSString *family_name, float size,
+          char **name_ret)
+{
+  Assert (size > 0, "zero font size");
+
+  NSArray *family_members = font_family_members (family_name);
+  if (!family_members.count)
+    family_members = font_family_members (default_font_family (traits));
+
+# ifndef USE_IPHONE
+  for (unsigned k = 0; k != family_members.count; ++k) {
+
+    NSArray *member = [family_members objectAtIndex:k];
+    NSFontTraitMask font_mask =
+    [(NSNumber *)[member objectAtIndex:3] unsignedIntValue];
+
+    if ((font_mask & mask) == traits) {
+
+      NSString *name = [member objectAtIndex:0];
+      NSFont *f = [NSFont fontWithName:name size:size];
+      if (!f)
+        break;
+
+      /* Don't use this font if it (probably) doesn't include ASCII characters.
+       */
+      NSStringEncoding enc = [f mostCompatibleStringEncoding];
+      if (! (enc == NSUTF8StringEncoding ||
+             enc == NSISOLatin1StringEncoding ||
+             enc == NSNonLossyASCIIStringEncoding ||
+             enc == NSISOLatin2StringEncoding ||
+             enc == NSUnicodeStringEncoding ||
+             enc == NSWindowsCP1250StringEncoding ||
+             enc == NSWindowsCP1252StringEncoding ||
+             enc == NSMacOSRomanStringEncoding)) {
+        // NSLog(@"skipping \"%@\": encoding = %d", name, enc);
+        break;
+      }
+      // NSLog(@"using \"%@\": %d", name, enc);
+
+      // *name_ret = strdup ([name cStringUsingEncoding:NSUTF8StringEncoding]);
+      *name_ret = strdup (name.UTF8String);
+      return f;
+    }
+  }
+# else // USE_IPHONE
+
+  // This trick needs iOS 3.1, see "Using SDK-Based Development".
+  Class has_font_descriptor = [UIFontDescriptor class];
+
+  for (NSString *fn in family_members) {
+# define MATCH(X) \
+         ([fn rangeOfString:X options:NSCaseInsensitiveSearch].location \
+         != NSNotFound)
+
+    NSFontTraitMask font_mask;
+    if (has_font_descriptor) {
+      // This only works on iOS 7 and later.
+      font_mask = [[UIFontDescriptor
+                    fontDescriptorWithFontAttributes:
+                    @{UIFontDescriptorNameAttribute:fn}]
+                   symbolicTraits];
+    } else {
+      font_mask = 0;
+      if (MATCH(@"Bold"))
+        font_mask |= NSBoldFontMask;
+      if (MATCH(@"Italic") || MATCH(@"Oblique"))
+        font_mask |= NSItalicFontMask;
+      if (MATCH(@"Courier"))
+        font_mask |= NSFixedPitchFontMask;
+    }
+
+    if ((font_mask & mask) == traits) {
+
+      /* Check if it can do ASCII.  No good way to accomplish this!
+         These are fonts present in iPhone Simulator as of June 2012
+         that don't include ASCII.
+       */
+      if (MATCH(@"AppleGothic") ||     // Korean
+          MATCH(@"Dingbats") ||                // Dingbats
+          MATCH(@"Emoji") ||           // Emoticons
+          MATCH(@"Geeza") ||           // Arabic
+          MATCH(@"Hebrew") ||          // Hebrew
+          MATCH(@"HiraKaku") ||                // Japanese
+          MATCH(@"HiraMin") ||         // Japanese
+          MATCH(@"Kailasa") ||         // Tibetan
+          MATCH(@"Ornaments") ||       // Dingbats
+          MATCH(@"STHeiti")            // Chinese
+       )
+         break;
+
+      *name_ret = strdup (fn.UTF8String);
+      return [UIFont fontWithName:fn size:size];
+    }
+# undef MATCH
+  }
+
+# endif
+
+  return NULL;
+}
+
+
+/* On Cocoa and iOS, fonts may be specified as "Georgia Bold 24" instead
+   of XLFD strings; also they can be comma-separated strings with multiple
+   font names.  First one that exists wins.
+ */
+static NSFont *
+try_native_font (const char *name, float scale,
+                 char **name_ret, float *size_ret, char **xa_font)
+{
+  if (!name) return 0;
+  const char *spc = strrchr (name, ' ');
+  if (!spc) return 0;
+
+  NSFont *f = 0;
+  char *token = strdup (name);
+  char *otoken = token;
+  char *name2;
+  char *lasts;
+
+  while ((name2 = strtok_r (token, ",", &lasts))) {
+    token = 0;
+
+    while (*name2 == ' ' || *name2 == '\t' || *name2 == '\n')
+      name2++;
+
+    spc = strrchr (name2, ' ');
+    if (!spc) continue;
+
+    int dsize = 0;
+    if (1 != sscanf (spc, " %d ", &dsize))
+      continue;
+    float size = dsize;
+
+    if (size < 4) continue;
+
+    size *= scale;
+
+    name2[strlen(name2) - strlen(spc)] = 0;
+
+    NSString *nsname = [NSString stringWithCString:name2
+                                          encoding:NSUTF8StringEncoding];
+    f = [NSFont fontWithName:nsname size:size];
+    if (f) {
+      *name_ret = strdup (name2);
+      *size_ret = size;
+      *xa_font = strdup (name); // Maybe this should be an XLFD?
+      break;
+    } else {
+      NSLog(@"No native font: \"%@\" %.0f", nsname, size);
+# if 0
+      for (NSString *fam in [UIFont familyNames]) {
+        NSLog(@"Family: %@", fam);
+        for (NSString *f in [UIFont fontNamesForFamilyName:fam]) {
+          NSLog(@"  Font: %@", f);
+        }
+      }
+# endif
+    }
+  }
+
+  free (otoken);
+  return f;
+}
+
+
+/* Returns a random font in the given size and face.
+ */
+static NSFont *
+random_font (NSFontTraitMask traits, NSFontTraitMask mask,
+             float size, NSString **family_ret, char **name_ret)
+{
+
+# ifndef USE_IPHONE
+  // Providing Unbold or Unitalic in the mask for availableFontNamesWithTraits
+  // returns an empty list, at least on a system with default fonts only.
+  NSArray *families = [[NSFontManager sharedFontManager]
+                       availableFontFamilies];
+  if (!families) return 0;
+# else
+  NSArray *families = [UIFont familyNames];
+
+  // There are many dups in the families array -- uniquify it.
+  {
+    NSArray *sorted_families =
+    [families sortedArrayUsingSelector:@selector(compare:)];
+    NSMutableArray *new_families =
+    [NSMutableArray arrayWithCapacity:sorted_families.count];
+
+    NSString *prev_family = @"";
+    for (NSString *family in sorted_families) {
+      if ([family compare:prev_family])
+        [new_families addObject:family];
+      prev_family = family;
+    }
+
+    families = new_families;
+  }
+# endif // USE_IPHONE
+
+  long n = [families count];
+  if (n <= 0) return 0;
+
+  int j;
+  for (j = 0; j < n; j++) {
+    int i = random() % n;
+    NSString *family_name = [families objectAtIndex:i];
+
+    NSFont *result = try_font (traits, mask, family_name, size, name_ret);
+    if (result) {
+      [*family_ret release];
+      *family_ret = family_name;
+      [*family_ret retain];
+      return result;
+    }
+  }
+
+  // None of the fonts support ASCII?
+  return 0;
+}
+
+
+static const char *
+xlfd_field_end (const char *s)
+{
+  const char *s2 = strchr(s, '-');
+  if (!s2)
+    s2 = s + strlen(s);
+  return s2;
+}
+
+
+static size_t
+xlfd_next (const char **s, const char **s2)
+{
+  if (!**s2) {
+    *s = *s2;
+  } else {
+    Assert (**s2 == '-', "xlfd parse error");
+    *s = *s2 + 1;
+    *s2 = xlfd_field_end (*s);
+  }
+
+  return *s2 - *s;
+}
+
+
+static NSFont *
+try_xlfd_font (Display *dpy, const char *name, float scale,
+               char **name_ret, float *size_ret, char **xa_font)
+{
+  NSFont *nsfont = 0;
+  NSString *family_name = nil;
+  NSFontTraitMask require = 0,
+   // Default mask is for the built-in X11 font aliases.
+   mask = NSFixedPitchFontMask | NSBoldFontMask | NSItalicFontMask;
+  BOOL rand  = NO;
+  float size = 0;
+  char *ps_name = 0;
+
+  const char *s = (name ? name : "");
+
+  size_t L = strlen (s);
+# define CMP(STR) (L == strlen(STR) && !strncasecmp (s, (STR), L))
+# define UNSPEC   (L == 0 || L == 1 && *s == '*')
+  if      (CMP ("6x10"))     size = 8,  require |= NSFixedPitchFontMask;
+  else if (CMP ("6x10bold")) size = 8,  require |= NSFixedPitchFontMask | NSBoldFontMask;
+  else if (CMP ("fixed"))    size = 12, require |= NSFixedPitchFontMask;
+  else if (CMP ("9x15"))     size = 12, require |= NSFixedPitchFontMask;
+  else if (CMP ("9x15bold")) size = 12, require |= NSFixedPitchFontMask | NSBoldFontMask;
+  else if (CMP ("vga"))      size = 12, require |= NSFixedPitchFontMask;
+  else if (CMP ("console"))  size = 12, require |= NSFixedPitchFontMask;
+  else if (CMP ("gallant"))  size = 12, require |= NSFixedPitchFontMask;
+  else {
+
+    NSFontTraitMask forbid = 0;
+
+    // Incorrect fields are ignored.
+
+    if (*s == '-')
+      ++s;
+    const char *s2 = xlfd_field_end(s);
+
+    // Foundry (ignore)
+
+    L = xlfd_next (&s, &s2); // Family name
+    // This used to substitute Georgia for Times. Now it doesn't.
+    if (CMP ("random")) {
+      rand = YES;
+    } else if (CMP ("fixed")) {
+      require |= NSFixedPitchFontMask;
+      family_name = @"Courier";
+    } else if (!UNSPEC) {
+      family_name = [[[NSString alloc] initWithBytes:s
+                                              length:L
+                                            encoding:NSUTF8StringEncoding]
+                     autorelease];
+    }
+
+    L = xlfd_next (&s, &s2); // Weight name
+    if (CMP ("bold") || CMP ("demibold"))
+      require |= NSBoldFontMask;
+    else if (CMP ("medium") || CMP ("regular"))
+      forbid |= NSBoldFontMask;
+
+    L = xlfd_next (&s, &s2); // Slant
+    if (CMP ("i") || CMP ("o"))
+      require |= NSItalicFontMask;
+    else if (CMP ("r"))
+      forbid |= NSItalicFontMask;
+
+    xlfd_next (&s, &s2); // Set width name (ignore)
+    xlfd_next (&s, &s2); // Add style name (ignore)
+
+    xlfd_next (&s, &s2); // Pixel size (ignore)
+
+    xlfd_next (&s, &s2); // Point size
+    char *s3;
+    uintmax_t n = strtoumax(s, &s3, 10);
+    if (s2 == s3)
+      size = n / 10.0;
+
+    xlfd_next (&s, &s2); // Resolution X (ignore)
+    xlfd_next (&s, &s2); // Resolution Y (ignore)
+
+    xlfd_next (&s, &s2); // Spacing
+    if (CMP ("p"))
+      forbid |= NSFixedPitchFontMask;
+    else if (CMP ("m") || CMP ("c"))
+      require |= NSFixedPitchFontMask;
+
+    // Don't care about average_width or charset registry.
+
+    mask = require | forbid;
+  }
+# undef CMP
+# undef UNSPEC
+
+  if (!family_name && !rand)
+    family_name = default_font_family (require);
+
+  if (size < 6 || size > 1000)
+    size = 12;
+
+  size *= scale;
+
+  if (rand) {
+    nsfont   = random_font (require, mask, size, &family_name, &ps_name);
+    [family_name autorelease];
+  }
+
+  if (!nsfont)
+    nsfont   = try_font (require, mask, family_name, size, &ps_name);
+
+  // if that didn't work, turn off attibutes until it does
+  // (e.g., there is no "Monaco-Bold".)
+  //
+  if (!nsfont && (mask & NSItalicFontMask)) {
+    require &= ~NSItalicFontMask;
+    mask &= ~NSItalicFontMask;
+    nsfont = try_font (require, mask, family_name, size, &ps_name);
+  }
+  if (!nsfont && (mask & NSBoldFontMask)) {
+    require &= ~NSBoldFontMask;
+    mask &= ~NSBoldFontMask;
+    nsfont = try_font (require, mask, family_name, size, &ps_name);
+  }
+  if (!nsfont && (mask & NSFixedPitchFontMask)) {
+    require &= ~NSFixedPitchFontMask;
+    mask &= ~NSFixedPitchFontMask;
+    nsfont = try_font (require, mask, family_name, size, &ps_name);
+  }
+
+  if (nsfont) {
+    unsigned dpi_d = XDisplayHeightMM (dpy,0) * 10 / 2;
+    unsigned dpi = (254 * XDisplayHeight (dpy,0) + dpi_d) / (2 * dpi_d);
+    *name_ret = ps_name;
+    *size_ret = size;
+    float actual_size = size / scale;
+    asprintf(xa_font, "-*-%s-%s-%c-*-*-%u-%u-%u-%u-%c-0-iso10646-1",
+             family_name.UTF8String,
+             (require & NSBoldFontMask) ? "bold" : "medium",
+             (require & NSItalicFontMask) ? 'o' : 'r',
+             (unsigned)(dpi * actual_size / 72.27 + 0.5),
+             (unsigned)(actual_size * 10 + 0.5), dpi, dpi,
+             (require & NSFixedPitchFontMask) ? 'm' : 'p');
+    return nsfont;
+  } else {
+    if (ps_name) free (ps_name);
+    return 0;
+  }
+}
+
+
+Font
+XLoadFont (Display *dpy, const char *name)
+{
+  Font fid = (Font) calloc (1, sizeof(*fid));
+
+  float scale = 1;
+
+# ifdef USE_IPHONE
+  /* Since iOS screens are physically smaller than desktop screens, scale up
+     the fonts to make them more readable.
+
+     Note that X11 apps on iOS also have the backbuffer sized in points
+     instead of pixels, resulting in an effective X11 screen size of 768x1024
+     or so, even if the display has significantly higher resolution.  That is
+     unrelated to this hack, which is really about DPI.
+   */
+  scale = dpy->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
+
+  fid->dpy = dpy;
+  fid->nsfont = try_native_font (name, scale, &fid->ps_name, &fid->size,
+                                 &fid->xa_font);
+
+  if (!fid->nsfont && name &&
+      strchr (name, ' ') &&
+      !strchr (name, '*')) {
+    // If name contains a space but no stars, it is a native font spec --
+    // return NULL so that we know it really didn't exist.  Else, it is an
+    //  XLFD font, so keep trying.
+    XUnloadFont (dpy, fid);
+    return 0;
+  }
+
+  if (! fid->nsfont)
+    fid->nsfont = try_xlfd_font (dpy, name, scale, &fid->ps_name, &fid->size,
+                                 &fid->xa_font);
+
+  // We should never return NULL for XLFD fonts.
+  if (!fid->nsfont) {
+    Assert (0, "no font");
+    return 0;
+  }
+  CFRetain (fid->nsfont);   // needed for garbage collection?
+
+  //NSLog(@"parsed \"%s\" to %s %.1f", name, fid->ps_name, fid->size);
+
+  query_font (fid);
+
+  return fid;
+}
+
+
+XFontStruct *
+XLoadQueryFont (Display *dpy, const char *name)
+{
+  Font fid = XLoadFont (dpy, name);
+  if (!fid) return 0;
+  return XQueryFont (dpy, fid);
+}
+
+int
+XUnloadFont (Display *dpy, Font fid)
+{
+  if (fid->ps_name)
+    free (fid->ps_name);
+  if (fid->metrics.per_char)
+    free (fid->metrics.per_char);
+
+  // #### DAMMIT!  I can't tell what's going wrong here, but I keep getting
+  //      crashes in [NSFont ascender] <- query_font, and it seems to go away
+  //      if I never release the nsfont.  So, fuck it, we'll just leak fonts.
+  //      They're probably not very big...
+  //
+  //  [fid->nsfont release];
+  //  CFRelease (fid->nsfont);
+
+  free (fid);
+  return 0;
+}
+
+int
+XFreeFontInfo (char **names, XFontStruct *info, int n)
+{
+  int i;
+  if (names) {
+    for (i = 0; i < n; i++)
+      if (names[i]) free (names[i]);
+    free (names);
+  }
+  if (info) {
+    for (i = 0; i < n; i++)
+      if (info[i].per_char) {
+        free (info[i].per_char);
+        free (info[i].properties);
+      }
+    free (info);
+  }
+  return 0;
+}
+
+int
+XFreeFont (Display *dpy, XFontStruct *f)
+{
+  Font fid = f->fid;
+  XFreeFontInfo (0, f, 1);
+  XUnloadFont (dpy, fid);
+  return 0;
+}
+
+
+int
+XSetFont (Display *dpy, GC gc, Font fid)
+{
+  if (gc->gcv.font)
+    XUnloadFont (dpy, gc->gcv.font);
+  gc->gcv.font = copy_font (fid);
+  [gc->gcv.font->nsfont retain];
+  CFRetain (gc->gcv.font->nsfont);   // needed for garbage collection?
+  return 0;
+}
+
+
+XFontSet
+XCreateFontSet (Display *dpy, char *name, 
+                char ***missing_charset_list_return,
+                int *missing_charset_count_return,
+                char **def_string_return)
+{
+  char *name2 = strdup (name);
+  char *s = strchr (name, ",");
+  if (s) *s = 0;
+  XFontSet set = 0;
+  XFontStruct *f = XLoadQueryFont (dpy, name2);
+  if (f)
+    {
+      set = (XFontSet) calloc (1, sizeof(*set));
+      set->font = f;
+    }
+  free (name2);
+  if (missing_charset_list_return)  *missing_charset_list_return = 0;
+  if (missing_charset_count_return) *missing_charset_count_return = 0;
+  if (def_string_return) *def_string_return = 0;
+  return set;
+}
+
+
+void
+XFreeFontSet (Display *dpy, XFontSet set)
+{
+  XFreeFont (dpy, set->font);
+  free (set);
+}
+
+
+const char *
+jwxyz_nativeFontName (Font f, float *size)
+{
+  if (size) *size = f->size;
+  return f->ps_name;
+}
+
+
+void
+XFreeStringList (char **list)
+{
+  int i;
+  if (!list) return;
+  for (i = 0; list[i]; i++)
+    XFree (list[i]);
+  XFree (list);
+}
+
+
+// Returns the verbose Unicode name of this character, like "agrave" or
+// "daggerdouble".  Used by fontglide debugMetrics.
+//
+char *
+jwxyz_unicode_character_name (Font fid, unsigned long uc)
+{
+  char *ret = 0;
+  CTFontRef ctfont =
+    CTFontCreateWithName ((CFStringRef) [fid->nsfont fontName],
+                          [fid->nsfont pointSize],
+                          NULL);
+  Assert (ctfont, "no CTFontRef for UIFont");
+
+  CGGlyph cgglyph;
+  if (CTFontGetGlyphsForCharacters (ctfont, (UniChar *) &uc, &cgglyph, 1)) {
+    CGFontRef cgfont = CTFontCopyGraphicsFont (ctfont, 0);
+    NSString *name = (NSString *) CGFontCopyGlyphNameForGlyph(cgfont, cgglyph);
+    ret = (name ? strdup ([name UTF8String]) : 0);
+    CGFontRelease (cgfont);
+    [name release];
+  }
+
+  CFRelease (ctfont);
+  return ret;
+}
+
+
+// Given a UTF8 string, return an NSString.  Bogus UTF8 characters are ignored.
+// We have to do this because stringWithCString returns NULL if there are
+// any invalid characters at all.
+//
+static NSString *
+sanitize_utf8 (const char *in, int in_len, Bool *latin1_pP)
+{
+  int out_len = in_len * 4;   // length of string might increase
+  char *s2 = (char *) malloc (out_len);
+  char *out = s2;
+  const char *in_end  = in  + in_len;
+  const char *out_end = out + out_len;
+  Bool latin1_p = True;
+
+  while (in < in_end)
+    {
+      unsigned long uc;
+      long L1 = utf8_decode ((const unsigned char *) in, in_end - in, &uc);
+      long L2 = utf8_encode (uc, out, out_end - out);
+      in  += L1;
+      out += L2;
+      if (uc > 255) latin1_p = False;
+    }
+  *out = 0;
+  NSString *nsstr =
+    [NSString stringWithCString:s2 encoding:NSUTF8StringEncoding];
+  free (s2);
+  if (latin1_pP) *latin1_pP = latin1_p;
+  return (nsstr ? nsstr : @"");
+}
+
+
+int
+XTextExtents (XFontStruct *f, const char *s, int length,
+              int *dir_ret, int *ascent_ret, int *descent_ret,
+              XCharStruct *cs)
+{
+  // Unfortunately, adding XCharStructs together to get the extents for a
+  // string doesn't work: Cocoa uses non-integral character advancements, but
+  // XCharStruct.width is an integer. Plus that doesn't take into account
+  // kerning pairs, alternate glyphs, and fun stuff like the word "Zapfino" in
+  // Zapfino.
+
+  NSString *nsstr = [[[NSString alloc] initWithBytes:s
+                                              length:length
+                                            encoding:NSISOLatin1StringEncoding]
+                     autorelease];
+  utf8_metrics (f->fid, nsstr, cs);
+  *dir_ret = 0;
+  *ascent_ret  = f->ascent;
+  *descent_ret = f->descent;
+  return 0;
+}
+
+int
+XTextWidth (XFontStruct *f, const char *s, int length)
+{
+  int ascent, descent, dir;
+  XCharStruct cs;
+  XTextExtents (f, s, length, &dir, &ascent, &descent, &cs);
+  return cs.width;
+}
+
+
+int
+XTextExtents16 (XFontStruct *f, const XChar2b *s, int length,
+                int *dir_ret, int *ascent_ret, int *descent_ret,
+                XCharStruct *cs)
+{
+  // Bool latin1_p = True;
+  int i, utf8_len = 0;
+  char *utf8 = XChar2b_to_utf8 (s, &utf8_len);   // already sanitized
+
+  for (i = 0; i < length; i++)
+    if (s[i].byte1 > 0) {
+      // latin1_p = False;
+      break;
+    }
+
+  {
+    NSString *nsstr = [NSString stringWithCString:utf8
+                                encoding:NSUTF8StringEncoding];
+    utf8_metrics (f->fid, nsstr, cs);
+  }
+
+  *dir_ret = 0;
+  *ascent_ret  = f->ascent;
+  *descent_ret = f->descent;
+  free (utf8);
+  return 0;
+}
+
+
+/* "Returns the distance in pixels in the primary draw direction from
+   the drawing origin to the origin of the next character to be drawn."
+
+   "overall_ink_return is set to the bbox of the string's character ink."
+
+   "The overall_ink_return for a nondescending, horizontally drawn Latin
+   character is conventionally entirely above the baseline; that is,
+   overall_ink_return.height <= -overall_ink_return.y."
+
+     [So this means that y is the top of the ink, and height grows down:
+      For above-the-baseline characters, y is negative.]
+
+   "The overall_ink_return for a nonkerned character is entirely at, and to
+   the right of, the origin; that is, overall_ink_return.x >= 0."
+
+     [So this means that x is the left of the ink, and width grows right.
+      For left-of-the-origin characters, x is negative.]
+
+   "A character consisting of a single pixel at the origin would set
+   overall_ink_return fields y = 0, x = 0, width = 1, and height = 1."
+ */
+int
+Xutf8TextExtents (XFontSet set, const char *str, int len,
+                  XRectangle *overall_ink_return,
+                  XRectangle *overall_logical_return)
+{
+  Bool latin1_p;
+  NSString *nsstr = sanitize_utf8 (str, len, &latin1_p);
+  XCharStruct cs;
+
+  utf8_metrics (set->font->fid, nsstr, &cs);
+
+  /* "The overall_logical_return is the bounding box that provides minimum
+     spacing to other graphical features for the string. Other graphical
+     features, for example, a border surrounding the text, should not
+     intersect this rectangle."
+
+     So I think that means they're the same?  Or maybe "ink" is the bounding
+     box, and "logical" is the advancement?  But then why is the return value
+     the advancement?
+   */
+  if (overall_ink_return)
+    XCharStruct_to_XmbRectangle (cs, *overall_ink_return);
+  if (overall_logical_return)
+    XCharStruct_to_XmbRectangle (cs, *overall_logical_return);
+
+  return cs.width;
+}
+
+
+static int
+draw_string (Display *dpy, Drawable d, GC gc, int x, int y,
+             NSString *nsstr)
+{
+  if (! nsstr) return 1;
+
+  XRectangle wr = d->frame;
+  CGContextRef cgc = d->cgc;
+
+  unsigned long argb = gc->gcv.foreground;
+  if (gc->depth == 1) argb = (argb ? WhitePixel(dpy,0) : BlackPixel(dpy,0));
+  float rgba[4];
+  query_color_float (dpy, argb, rgba);
+  NSColor *fg = [NSColor colorWithDeviceRed:rgba[0]
+                                      green:rgba[1]
+                                       blue:rgba[2]
+                                      alpha:rgba[3]];
+
+  if (!gc->gcv.font) {
+    Assert (0, "no font");
+    return 1;
+  }
+
+  /* This crashes on iOS 5.1 because NSForegroundColorAttributeName,
+      NSFontAttributeName, and NSAttributedString are only present on iOS 6
+      and later.  We could resurrect the Quartz code from v5.29 and do a
+      runtime conditional on that, but that would be a pain in the ass.
+      Probably time to just make iOS 6 a requirement.
+   */
+
+  NSDictionary *attr =
+    [NSDictionary dictionaryWithObjectsAndKeys:
+                    gc->gcv.font->nsfont, NSFontAttributeName,
+                    fg, NSForegroundColorAttributeName,
+                  nil];
+
+  // Don't understand why we have to do both set_color and
+  // NSForegroundColorAttributeName, but we do.
+  //
+  set_color (dpy, cgc, argb, 32, NO, YES);
+
+  NSAttributedString *astr = [[NSAttributedString alloc]
+                               initWithString:nsstr
+                                   attributes:attr];
+  CTLineRef dl = CTLineCreateWithAttributedString (
+                   (__bridge CFAttributedStringRef) astr);
+
+  // Not sure why this is necessary, but xoff is positive when the first
+  // character on the line has a negative lbearing.  Without this, the
+  // string is rendered with the first ink at 0 instead of at lbearing.
+  // I have not seen xoff be negative, so I'm not sure if that can happen.
+  //
+  // Test case: "Combining Double Tilde" U+0360 (\315\240) followed by
+  // a letter.
+  //
+  CGFloat xoff = CTLineGetOffsetForStringIndex (dl, 0, NULL);
+  Assert (xoff >= 0, "unexpected CTLineOffset");
+  x -= xoff;
+
+  CGContextSetTextPosition (cgc,
+                            wr.x + x,
+                            wr.y + wr.height - y);
+  CGContextSetShouldAntialias (cgc, gc->gcv.antialias_p);
+
+  CTLineDraw (dl, cgc);
+  CFRelease (dl);
+  [astr release];
+
+  invalidate_drawable_cache (d);
+  return 0;
+}
+
+
+int
+XDrawString (Display *dpy, Drawable d, GC gc, int x, int y,
+             const char  *str, int len)
+{
+  char *s2 = (char *) malloc (len + 1);
+  strncpy (s2, str, len);
+  s2[len] = 0;
+  NSString *nsstr = [NSString stringWithCString:s2
+                                       encoding:NSISOLatin1StringEncoding];
+  int ret = draw_string (dpy, d, gc, x, y, nsstr);
+  free (s2);
+  return ret;
+}
+
+
+int
+XDrawString16 (Display *dpy, Drawable d, GC gc, int x, int y,
+             const XChar2b *str, int len)
+{
+  char *s2 = XChar2b_to_utf8 (str, 0);   // already sanitized
+  NSString *nsstr =
+    [NSString stringWithCString:s2 encoding:NSUTF8StringEncoding];
+  int ret = draw_string (dpy, d, gc, x, y, nsstr);
+  free (s2);
+  return ret;
+}
+
+
+void
+Xutf8DrawString (Display *dpy, Drawable d, XFontSet set, GC gc,
+                 int x, int y, const char *str, int len)
+{
+  char *s2 = (char *) malloc (len + 1);
+  strncpy (s2, str, len);
+  s2[len] = 0;
+  NSString *nsstr = sanitize_utf8 (str, len, 0);
+  draw_string (dpy, d, gc, x, y, nsstr);
+  free (s2);
+}
+
+
+int
+XDrawImageString (Display *dpy, Drawable d, GC gc, int x, int y,
+                  const char *str, int len)
+{
+  int ascent, descent, dir;
+  XCharStruct cs;
+  XTextExtents (&gc->gcv.font->metrics, str, len,
+                &dir, &ascent, &descent, &cs);
+  jwxyz_fill_rect (dpy, d, gc,
+                   x + MIN (0, cs.lbearing),
+                   y - MAX (0, ascent),
+                   MAX (MAX (0, cs.rbearing) -
+                        MIN (0, cs.lbearing),
+                        cs.width),
+                   MAX (0, ascent) + MAX (0, descent),
+                   gc->gcv.background);
+  return XDrawString (dpy, d, gc, x, y, str, len);
+}
+
+
+int
+XSetClipMask (Display *dpy, GC gc, Pixmap m)
+{
+  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)
+{
+  gc->gcv.clip_x_origin = x;
+  gc->gcv.clip_y_origin = y;
+  return 0;
+}
+
+#endif // JWXYZ_QUARTZ -- entire file
diff --git a/jwxyz/jwxyzI.h b/jwxyz/jwxyzI.h
new file mode 100644 (file)
index 0000000..61b654f
--- /dev/null
@@ -0,0 +1,136 @@
+/* xscreensaver, Copyright (c) 1991-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.
+ */
+
+#ifndef __JWXYZ_I_H__
+#define __JWXYZ_I_H__
+
+#include <inttypes.h>
+
+#include "jwxyz.h"
+
+#define Assert(C, ...) do { if (!(C)) jwxyz_abort (__VA_ARGS__); } while(0)
+
+/* OSX/jwxyz.m, utils/jwxyz-gl.c */
+extern Display *jwxyz_make_display (Window w);
+extern void jwxyz_free_display (Display *);
+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);
+
+/* OSX/jwxyz-cocoa.m, android/jwxyz-android.c */
+extern const XRectangle *jwxyz_frame (Drawable d); /* XGetGeometry sux. */
+extern unsigned int jwxyz_drawable_depth (Drawable d);
+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 *);
+#endif
+
+/* utils/jwxyz-common.c */
+extern void jwxyz_validate_pixel (Display *dpy, unsigned long pixel,
+                                  unsigned int depth, Bool alpha_allowed_p);
+extern Bool jwxyz_dumb_drawing_mode(Display *dpy, Drawable d, GC gc,
+                                    int x, int 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);
+
+# if defined JWXYZ_QUARTZ
+
+#  include <CoreGraphics/CGGeometry.h>
+#  include <CoreGraphics/CGContext.h>
+
+extern void jwxyz_flush_context (Display *);
+
+#  define jwxyz_assert_display(dpy)
+#  define jwxyz_assert_drawable(main_window, d)
+#  define jwxyz_assert_gl()
+
+/* jwxyz-cocoa.m needs these from jwxyz.m for XCopyArea. */
+extern void invalidate_drawable_cache (Drawable d);
+extern void set_color (Display *dpy, CGContextRef cgc, unsigned long argb,
+                       unsigned int depth, Bool alpha_allowed_p, Bool fill_p);
+extern void push_gc (Drawable d, GC gc);
+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))
+
+#define pop_gc(d,gc) CGContextRestoreGState (d->cgc)
+
+# elif defined JWXYZ_GL
+
+/* utils/jwxyz-gl.c */
+extern void jwxyz_prepare_context (Display *dpy);
+extern void jwxyz_set_matrices (Display *dpy, unsigned width, unsigned height,
+                                Bool screen_p);
+
+/* 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
+   also work with FBOs and one context for everything. Surprisingly slow and
+   unreliable.
+ */
+extern void jwxyz_gl_copy_area_copy_tex_image (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);
+
+/* glReadPixels followed by glTexImage2D. This is terrible, so only use this
+   if nothing else works.
+ */
+extern void jwxyz_gl_copy_area_read_pixels (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);
+
+/* Platform-specific */
+extern void jwxyz_bind_drawable (Display *dpy, Window w, Drawable d);
+extern void jwxyz_assert_display (Display *);
+extern void jwxyz_assert_drawable (Window main_window, Drawable d);
+extern void jwxyz_assert_gl (void);
+
+extern void *jwxyz_load_native_font (Display *, const char *name,
+                                     char **native_name_ret, float *size_ret,
+                                     int *ascent_ret, int *descent_ret);
+extern void jwxyz_release_native_font (Display *, void *native_font);
+extern void jwxyz_render_text (Display *, void *native_font,
+                               const char *str, size_t len, int utf8_p,
+                               XCharStruct *cs_ret, char **pixmap_ret);
+
+# endif /* JWXYZ_GL */
+
+#endif
diff --git a/jwxyz/jwzgles.c b/jwxyz/jwzgles.c
new file mode 100644 (file)
index 0000000..042d6a4
--- /dev/null
@@ -0,0 +1,4297 @@
+/* xscreensaver, Copyright (c) 2012-2015 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 compatibility shim to allow OpenGL 1.3 source code to work in an
+   OpenGLES environment, where almost every OpenGL 1.3 function has
+   been "deprecated".
+
+   There are two major operations going on here:
+
+     - Converting calls to glBegin + glVertex3f + glEnd to glDrawArrays
+     - Implementing display lists.
+
+
+   From an API point of view, OpenGL 1.3 and earlier code looks like this:
+
+      glLightfv (GL_LIGHT0, GL_POSITION, ...);
+      glLightfv (GL_LIGHT0, GL_AMBIENT,  ...);
+
+      glMatrixMode (GL_PROJECTION);
+      glLoadIdentity ();
+      gluPerspective (...);
+
+      glMatrixMode (GL_MODELVIEW);
+      glLoadIdentity ();
+      gluLookAt (...);
+
+      glPushMatrix ();
+
+      glRotatef (...);
+
+      glColor3f (...);
+
+      glBegin (GL_TRIANGLES);
+      glNormal3f (...);
+      glVertex3f (...);
+      glVertex3f (...);
+      glVertex3f (...);
+      glEnd ();
+
+      glPopMatrix ();
+
+      glFinish ();
+
+
+   OpenGLES broke that model by eliminating glBegin().  Instead of
+   iterating a sequence of vertexes, you need to pack your points into
+   an array first, e.g.:
+
+      GLfloat coords[] = {
+         0, 0, 0,
+         0, 1, 0,
+         ...
+      };
+
+      glDrawArrays (GL_TRIANGLES, 0, 3);
+
+   The projection model (glRotatef, etc.) works the same, but glColor()
+   is missing.  You're expected to encode that into your arrays.
+
+   Also, OpenGLES doesn't support display lists at all.
+
+
+   So this code shadows all of the functions that are allowed within
+   glBegin, builds up an array, and calls glDrawArrays at the end.
+
+   Likewise, it shadows all of the functions that are allowed within
+   glNewList and records those calls for later playback.
+
+
+   This code only handles OpenGLES 1.1, not 1.0 or 2.x.
+
+   OpenGLES 2.0 broke things further by eliminating the whole OpenGL
+   lighting model.  Instead of specifying the positions and properties
+   of your lights using the glLight* API, now you are expected to
+   implement it all yourself by downloading C-like code into the GPU
+   directly.  This is more flexible, in that if you wanted a completely
+   different lighting model than what OpenGL provides, you could do
+   that, but it leaves you needing to download boilerplate to reproduce
+   what used to be built in.
+
+
+   Incidentally, the OpenGL numbering scheme goes something like this:
+
+   OpenGL   1.0         1992
+   OpenGL   1.1         1997 (improved texture support)
+   OpenGL   1.2         1998 (nothing interesting)
+   OpenGL   1.3         2001 (multisampling, cubemaps)
+   OpenGL   1.4         2002 (added auto-mipmapping)
+   OpenGLES 1.0         2003 (deprecated 80% of the language; fork of OpenGL 1.3)
+   OpenGL   1.5         2003 (added VBOs)
+   OpenGLES 1.1         2004 (fork of OpenGL 1.5)
+   OpenGL   2.0         2004 (a political quagmire)
+   OpenGLES 2.0         2007 (deprecated 95% of the language; fork of OpenGL 2.0)
+   OpenGL   3.0         2008 (added FBOs, VAOs, deprecated 60% of the language)
+
+
+   Some things that are missing:
+
+    - glTexGeni, meaning no spherical environment-mapping textures.
+
+    - gluNewTess, meaning no tesselation of complex objects.
+
+    - glMap2f mesh evaluators, meaning no Utah Teapot.
+
+    - glPolygonMode with GL_LINE or GL_POINT, meaning no wireframe modes
+      that do hidden-surface removal.
+
+    - glSelectBuffer, meaning no mouse-hit detection on rendered objects.
+
+    - gluNewQuadric, gluCylinder, etc: rewrite your code to use tube.c, etc.
+
+    - Putting verts in a display list without a wrapping glBegin.
+      I didn't realize that even worked!  Lockward used to do that,
+      before I fixed it to not.
+
+    - Not every function is implemented; just the ones that I needed for
+      xscreensaver.  However, the trivial ones are trivial to enable
+      as they come up.  Harder ones will be harder.
+
+   As a result of that, these savers look wrong:
+
+      atlantis        Uses EYE_PLANE.
+      blocktube       Uses SPHERE_MAP.
+      dnalogo         Uses GLUtesselator.
+      extrusion       Uses all kinds of GLUT crap.
+      flyingtoasters  Uses SPHERE_MAP.
+      winduprobot     Uses SPHERE_MAP.
+      jigglypuff      Uses SPHERE_MAP (in chrome mode), GL_LINE (in wireframe)
+      jigsaw          Uses GLUtesselator.
+      pinion         Uses glSelectBuffer and gluPickMatrix for mouse-clicks.
+      pipes           Uses glMap2f for the Utah Teapot.
+      polyhedra       Uses GLUtesselator (concave objects); also Utah Teapot.
+      skytentacles    Uses GL_LINE in -cel mode.
+      timetunnel      Uses GL_CONSTANT_ALPHA and all kinds of other stuff.
+*/
+
+
+#undef DEBUG
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#ifdef HAVE_JWZGLES    /* whole file */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <math.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined(USE_IPHONE)
+# include <OpenGLES/ES1/gl.h>
+# include <OpenGLES/ES1/glext.h>
+#elif defined(HAVE_COCOA)
+# include <OpenGL/gl.h>
+# include <OpenGL/glu.h>
+#elif defined(HAVE_ANDROID)
+# include <GLES/gl.h>
+# include <android/log.h>
+#else /* real X11 */
+# ifndef  GL_GLEXT_PROTOTYPES
+#  define GL_GLEXT_PROTOTYPES /* for glBindBuffer */
+# endif
+# include <GL/glx.h>
+# include <GL/glu.h>
+#endif
+
+#include "jwzglesI.h"
+
+#define STRINGIFY(X) #X
+
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+#undef  Assert
+
+#ifdef HAVE_COCOA
+  extern void jwxyz_abort (const char *fmt, ...) __dead2;
+# define Assert(C,S) do { if (!(C)) { jwxyz_abort ("%s",S); }} while(0)
+#elif defined HAVE_ANDROID
+# define Assert(C,S) do { \
+    if (!(C)) { \
+      __android_log_print (ANDROID_LOG_ERROR, "xscreensaver", "jwzgles: %s\n", S); \
+      abort(); \
+    }} while(0)
+#else
+# define Assert(C,S) do { \
+    if (!(C)) { \
+      fprintf (stderr, "jwzgles: %s\n", S); \
+      abort(); \
+    }} while(0)
+#endif
+
+
+typedef struct { GLfloat x, y, z; }    XYZ;
+typedef struct { GLfloat x, y, z, w; } XYZW;
+typedef struct { GLfloat s, t, r, q; } STRQ;
+typedef struct { GLfloat r, g, b, a; } RGBA;
+
+
+/* Used to record all calls to glVertex3f, glNormal3f, etc. 
+   while inside glBegin / glEnd so that we can convert that
+   to a single call to glDrawArrays.
+ */
+typedef struct {
+  int mode;
+  int count, size;     /* size of each array */
+
+  XYZW *verts;         /* Arrays being built */
+  XYZ  *norms;
+  STRQ *tex;
+  RGBA *color;
+
+  int ncount;          /* How many normals, tex coords and colors were */
+  int tcount;          /* used.  We optimize based on "0, 1, or many". */
+  int ccount;
+  int materialistic;   /* Whether glMaterial was called inside glBegin */
+
+  XYZ  cnorm;          /* Prevailing normal/texture/color while building */
+  STRQ ctex;
+  RGBA ccolor;
+
+} vert_set;
+
+
+typedef void (*list_fn_cb) (void);
+
+
+/* We need this nonsense because you can't cast a double to a void*
+   or vice versa.  They tend to be passed in different registers,
+   and you need to know about that because it's still 1972 here.
+ */
+typedef union {
+  const void *v; GLfloat f; GLuint i; GLshort s; GLdouble d;
+} void_int;
+
+typedef struct {               /* saved args for glDrawArrays */
+  int binding, size, type, stride, bytes;
+  void *data;
+} draw_array;
+
+typedef enum {                 /* shorthand describing arglist signature */
+  PROTO_VOID,  /* no args */
+  PROTO_I,     /* 1 int arg */
+  PROTO_F,     /* 1 float arg */
+  PROTO_II,    /* int, int */
+  PROTO_FF,    /* float, float */
+  PROTO_IF,    /* int, float */
+  PROTO_III,   /* int, int, int */
+  PROTO_FFF,   /* float, float, float */
+  PROTO_IIF,   /* int, int, float */
+  PROTO_IIII,  /* int, int, int, int */
+  PROTO_FFFF,  /* float, float, float, float */
+  PROTO_IIV,   /* int, int[4] */
+  PROTO_IFV,   /* int, float[4] */
+  PROTO_IIIV,  /* int, int, int[4] */
+  PROTO_IIFV,  /* int, int, float[4] */
+  PROTO_FV16,  /* float[16] */
+  PROTO_ARRAYS /* glDrawArrays */
+} fn_proto;
+
+typedef struct {               /* A single element of a display list */
+  const char *name;
+  list_fn_cb fn;               /* saved function pointer */
+  fn_proto proto;              /* arglist prototype */
+  draw_array *arrays;          /* args for glDrawArrays */
+  void_int argv[16];           /* args for everything else */
+} list_fn;
+
+
+typedef struct {       /* a display list: saved activity within glNewList */
+  int id;
+  int size, count;
+  list_fn *fns;
+
+  /* Named buffer that should be freed when this display list is deleted. */
+  GLuint buffer;
+
+} list;
+
+
+typedef struct {       /* All display lists */
+  list *lists;
+  int count, size;
+} list_set;
+
+
+#define ISENABLED_TEXTURE_2D   (1<<0)
+#define ISENABLED_TEXTURE_GEN_S        (1<<1)
+#define ISENABLED_TEXTURE_GEN_T        (1<<2)
+#define ISENABLED_TEXTURE_GEN_R        (1<<3)
+#define ISENABLED_TEXTURE_GEN_Q        (1<<4)
+#define ISENABLED_LIGHTING     (1<<5)
+#define ISENABLED_BLEND                (1<<6)
+#define ISENABLED_DEPTH_TEST   (1<<7)
+#define ISENABLED_CULL_FACE    (1<<8)
+#define ISENABLED_NORMALIZE    (1<<9)
+#define ISENABLED_FOG          (1<<10)
+#define ISENABLED_COLMAT       (1<<11)
+#define ISENABLED_VERT_ARRAY   (1<<12)
+#define ISENABLED_NORM_ARRAY   (1<<13)
+#define ISENABLED_TEX_ARRAY    (1<<14)
+#define ISENABLED_COLOR_ARRAY  (1<<15)
+#define ISENABLED_ALPHA_TEST   (1<<16)
+
+
+typedef struct {
+  GLuint mode;
+  GLfloat obj[4], eye[4];
+} texgen_state;
+
+
+typedef struct {       /* global state */
+
+  vert_set set;                /* set being built */
+
+  int compiling_list;  /* list id if inside glNewList; 0 means immediate */
+  int replaying_list;  /* depth of call stack to glCallList */
+  int compiling_verts; /* inside glBegin */
+
+  list_set lists;      /* saved lists */
+
+  unsigned long enabled;       /* enabled flags, immediate mode */
+  unsigned long list_enabled;  /* and for the list-in-progress */
+
+  texgen_state s, t, r, q;
+
+  /* Implementing glPushClientAttrib? Don't forget about these! */
+  draw_array varray, narray, carray, tarray;
+
+} jwzgles_state;
+
+
+static jwzgles_state *state = 0;
+
+
+#ifdef DEBUG
+
+static void Log(const char *fmt, ...)
+{
+  va_list args;
+  va_start (args, fmt);
+#ifdef HAVE_ANDROID
+  /* setprop log.redirect-stdio true is another possibility, but that
+     apparently only works on rooted devices.
+   */
+  __android_log_vprint(ANDROID_LOG_DEBUG, "xscreensaver", fmt, args);
+# else
+  vfprintf(stderr, fmt, args);
+# endif
+  va_end (args);
+}
+
+# define LOG(A)                Log("jwzgles: " A "\n")
+# define LOG1(A,B)             Log("jwzgles: " A "\n",B)
+# define LOG2(A,B,C)           Log("jwzgles: " A "\n",B,C)
+# define LOG3(A,B,C,D)         Log("jwzgles: " A "\n",B,C,D)
+# define LOG4(A,B,C,D,E)       Log("jwzgles: " A "\n",B,C,D,E)
+# define LOG5(A,B,C,D,E,F)     Log("jwzgles: " A "\n",B,C,D,E,F)
+# define LOG6(A,B,C,D,E,F,G)   Log("jwzgles: " A "\n",B,C,D,E,F,G)
+# define LOG7(A,B,C,D,E,F,G,H) Log("jwzgles: " A "\n",B,C,D,E,F,G,H)
+# define LOG8(A,B,C,D,E,F,G,H,I)\
+         Log("jwzgles: "A "\n",B,C,D,E,F,G,H,I)
+# define LOG9(A,B,C,D,E,F,G,H,I,J)\
+         Log("jwzgles: "A "\n",B,C,D,E,F,G,H,I,J)
+# define LOG10(A,B,C,D,E,F,G,H,I,J,K)\
+         Log("jwzgles: "A "\n",B,C,D,E,F,G,H,I,J,K)
+# define LOG17(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R)\
+         Log("jwzgles: "A "\n",B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R)
+# define CHECK(S) jwzgles_check_gl_error(S)
+#else
+# define LOG(A)                       /* */
+# define LOG1(A,B)                    /* */
+# define LOG2(A,B,C)                  /* */
+# define LOG3(A,B,C,D)                /* */
+# define LOG4(A,B,C,D,E)              /* */
+# define LOG5(A,B,C,D,E,F)            /* */
+# define LOG6(A,B,C,D,E,F,G)          /* */
+# define LOG7(A,B,C,D,E,F,G,H)        /* */
+# define LOG8(A,B,C,D,E,F,G,H,I)      /* */
+# define LOG9(A,B,C,D,E,F,G,H,I,J)    /* */
+# define LOG10(A,B,C,D,E,F,G,H,I,J,K) /* */
+# define LOG17(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R) /* */
+# define CHECK(S)              /* */
+#endif
+
+#ifdef DEBUG
+static const char *
+mode_desc (int mode)   /* for debugging messages */
+{
+  switch (mode) {
+# define SS(X) case GL_##X: return STRINGIFY(X);
+  SS(ALPHA)
+  SS(ALPHA_TEST)
+  SS(AMBIENT)
+  SS(AMBIENT_AND_DIFFUSE)
+  SS(ARRAY_BUFFER)
+  SS(AUTO_NORMAL)
+  SS(BACK)
+  SS(BLEND)
+  SS(BLEND_DST)
+  SS(BLEND_SRC)
+  SS(BLEND_SRC_ALPHA)
+  SS(BYTE)
+  SS(C3F_V3F)
+  SS(C4F_N3F_V3F)
+  SS(C4UB_V2F)
+  SS(C4UB_V3F)
+  SS(CCW)
+  SS(CLAMP)
+  SS(COLOR_ARRAY)
+  SS(COLOR_ARRAY_BUFFER_BINDING);
+  SS(COLOR_MATERIAL)
+  SS(COLOR_MATERIAL_FACE)
+  SS(COLOR_MATERIAL_PARAMETER)
+  SS(COMPILE)
+  SS(CULL_FACE)
+  SS(CW)
+  SS(DECAL)
+  SS(DEPTH_BUFFER_BIT)
+  SS(DEPTH_TEST)
+  SS(DIFFUSE)
+  SS(DOUBLEBUFFER)
+  SS(DST_ALPHA)
+  SS(DST_COLOR)
+  SS(DYNAMIC_DRAW)
+  SS(ELEMENT_ARRAY_BUFFER)
+  SS(EYE_LINEAR)
+  SS(EYE_PLANE)
+  SS(FEEDBACK)
+  SS(FILL)
+  SS(FLAT)
+  SS(FLOAT)
+  SS(FOG)
+  SS(FRONT)
+  SS(FRONT_AND_BACK)
+  SS(GREATER)
+  SS(INTENSITY)
+  SS(INVALID_ENUM)
+  SS(INVALID_OPERATION)
+  SS(INVALID_VALUE)
+  SS(LESS)
+  SS(LIGHT0)
+  SS(LIGHT1)
+  SS(LIGHT2)
+  SS(LIGHT3)
+  SS(LIGHTING)
+  SS(LIGHT_MODEL_AMBIENT)
+  SS(LIGHT_MODEL_COLOR_CONTROL)
+  SS(LIGHT_MODEL_LOCAL_VIEWER)
+  SS(LIGHT_MODEL_TWO_SIDE)
+  SS(LINE)
+  SS(LINEAR)
+  SS(LINEAR_MIPMAP_LINEAR)
+  SS(LINEAR_MIPMAP_NEAREST)
+  SS(LINES)
+  SS(LINE_LOOP)
+  SS(LINE_STRIP)
+  SS(LUMINANCE)
+  SS(LUMINANCE_ALPHA)
+  SS(MATRIX_MODE)
+  SS(MODELVIEW)
+  SS(MODULATE)
+  SS(N3F_V3F)
+  SS(NEAREST)
+  SS(NEAREST_MIPMAP_LINEAR)
+  SS(NEAREST_MIPMAP_NEAREST)
+  SS(NORMALIZE)
+  SS(NORMAL_ARRAY)
+  SS(NORMAL_ARRAY_BUFFER_BINDING);
+  SS(OBJECT_LINEAR)
+  SS(OBJECT_PLANE)
+  SS(ONE_MINUS_DST_ALPHA)
+  SS(ONE_MINUS_DST_COLOR)
+  SS(ONE_MINUS_SRC_ALPHA)
+  SS(ONE_MINUS_SRC_COLOR)
+  SS(OUT_OF_MEMORY)
+  SS(PACK_ALIGNMENT)
+  SS(POINTS)
+  SS(POLYGON)
+  SS(POLYGON_OFFSET_FILL)
+  SS(POLYGON_SMOOTH)
+  SS(POLYGON_STIPPLE)
+  SS(POSITION)
+  SS(PROJECTION)
+  SS(Q)
+  SS(QUADS)
+  SS(QUAD_STRIP)
+  SS(R)
+  SS(RENDER)
+  SS(REPEAT)
+  SS(RGB)
+  SS(RGBA)
+  SS(RGBA_MODE)
+  SS(S)
+  SS(SELECT)
+  SS(SEPARATE_SPECULAR_COLOR)
+  SS(SHADE_MODEL)
+  SS(SHININESS)
+  SS(SHORT)
+  SS(SINGLE_COLOR)
+  SS(SMOOTH)
+  SS(SPECULAR)
+  SS(SPHERE_MAP)
+  SS(SRC_ALPHA)
+  SS(SRC_ALPHA_SATURATE)
+  SS(SRC_COLOR)
+  SS(STACK_OVERFLOW)
+  SS(STACK_UNDERFLOW)
+  SS(STATIC_DRAW)
+  SS(STENCIL_BUFFER_BIT)
+  SS(T)
+  SS(T2F_C3F_V3F)
+  SS(T2F_C4F_N3F_V3F)
+  SS(T2F_C4UB_V3F)
+  SS(T2F_N3F_V3F)
+  SS(T2F_V3F)
+  SS(T4F_C4F_N3F_V4F)
+  SS(T4F_V4F)
+  SS(TEXTURE)
+  SS(TEXTURE_1D)
+  SS(TEXTURE_2D)
+  SS(TEXTURE_ALPHA_SIZE)
+  SS(TEXTURE_BINDING_2D)
+  SS(TEXTURE_BLUE_SIZE)
+  SS(TEXTURE_BORDER)
+  SS(TEXTURE_BORDER_COLOR)
+  SS(TEXTURE_COMPONENTS)
+  SS(TEXTURE_COORD_ARRAY)
+  SS(TEXTURE_COORD_ARRAY_BUFFER_BINDING);
+  SS(TEXTURE_ENV)
+  SS(TEXTURE_ENV_COLOR)
+  SS(TEXTURE_ENV_MODE)
+  SS(TEXTURE_GEN_MODE)
+  SS(TEXTURE_GEN_Q)
+  SS(TEXTURE_GEN_R)
+  SS(TEXTURE_GEN_S)
+  SS(TEXTURE_GEN_T)
+  SS(TEXTURE_GREEN_SIZE)
+  SS(TEXTURE_HEIGHT)
+  SS(TEXTURE_INTENSITY_SIZE)
+  SS(TEXTURE_LUMINANCE_SIZE)
+  SS(TEXTURE_MAG_FILTER)
+  SS(TEXTURE_MIN_FILTER)
+  SS(TEXTURE_RED_SIZE)
+  SS(TEXTURE_WRAP_S)
+  SS(TEXTURE_WRAP_T)
+  SS(TRIANGLES)
+  SS(TRIANGLE_FAN)
+  SS(TRIANGLE_STRIP)
+  SS(UNPACK_ALIGNMENT)
+  SS(UNPACK_ROW_LENGTH)
+  SS(UNSIGNED_BYTE)
+  SS(UNSIGNED_INT_8_8_8_8_REV)
+  SS(UNSIGNED_SHORT)
+  SS(V2F)
+  SS(V3F)
+  SS(VERTEX_ARRAY)
+  SS(VERTEX_ARRAY_BUFFER_BINDING);
+/*SS(COLOR_BUFFER_BIT) -- same value as GL_LIGHT0 */
+# undef SS
+  case (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT):
+    return "DEPTH_BUFFER_BIT | COLOR_BUFFER_BIT";
+/* Oops, same as INVALID_ENUM.
+  case (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT):
+    return "DEPTH_BUFFER_BIT | STENCIL_BUFFER_BIT";
+*/
+  case (GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT):
+    return "COLOR_BUFFER_BIT | STENCIL_BUFFER_BIT";
+  case (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT):
+    return "DEPTH_BUFFER_BIT | COLOR_BUFFER_BIT | STENCIL_BUFFER_BIT";
+  default:
+    {
+      static char buf[255];
+      sprintf (buf, "0x%04X", mode);
+      return buf;
+    }
+  }
+}
+
+static void
+jwzgles_check_gl_error (const char *s)
+{
+  GLenum i = glGetError();
+  if (i == GL_NO_ERROR) return;
+  fprintf (stderr, "jwzgles: GL ERROR: %s: %s\n", s, mode_desc(i));
+}
+
+#endif /* DEBUG */
+
+
+static void
+make_room (const char *name, void **array, int span, int *count, int *size)
+{
+  if (*count + 1 >= *size)
+    {
+      int new_size = (*count + 20) * 1.2;   /* mildly exponential */
+      *array = realloc (*array, new_size * span);
+      Assert (*array, "out of memory");
+      /* LOG3("%s: grew %d -> %d", name, *size, new_size); */
+      *size = new_size;
+    }
+}
+
+
+void
+jwzgles_reset (void)
+{
+  if (! state)
+    state = (jwzgles_state *) calloc (1, sizeof (*state));
+
+  if (state->lists.lists)
+    {
+      state->compiling_list = 0;
+      if (state->lists.count)
+        jwzgles_glDeleteLists (1, state->lists.count);
+      free (state->lists.lists);
+    }
+
+  if (state->set.verts)   free (state->set.verts);
+  if (state->set.norms)   free (state->set.norms);
+  if (state->set.tex)     free (state->set.tex);
+  if (state->set.color)   free (state->set.color);
+
+  memset (state, 0, sizeof(*state));
+
+  state->s.mode = state->t.mode = state->r.mode = state->q.mode =
+    GL_EYE_LINEAR;
+  state->s.obj[0] = state->s.eye[0] = 1;  /* s = 1 0 0 0 */
+  state->t.obj[1] = state->t.eye[1] = 1;  /* t = 0 1 0 0 */
+}
+
+
+int
+jwzgles_glGenLists (int n)
+{
+  int i;
+  int ret = 0;
+
+  Assert (!state->compiling_verts, "glGenLists not allowed inside glBegin");
+
+  /* Ensure space in state->lists, clear the one at the end, and tick counter
+     Note that lists are never really deleted, and we can never re-use elements
+     of this array.  glDeleteLists zeroes out the contents of the list, but
+     the list ID is still valid for use with glNewList forever.
+     #### So maybe this should be a linked list instead of an array.
+  */
+  for (i = 0; i < n; i++)
+    {
+      list *L;
+      int id = 0;
+      make_room ("glGenLists", 
+                 (void **) &state->lists.lists,
+                 sizeof (*state->lists.lists),
+                 &state->lists.count, &state->lists.size);
+      state->lists.count++;
+      id = state->lists.count;
+      L = &state->lists.lists[id-1];
+
+      memset (L, 0, sizeof (*L));
+      L->id = id;
+      if (ret == 0) ret = id;
+      LOG1("glGenLists -> %d", L->id);
+    }
+
+  /* Return the ID of the first list allocated */
+
+  return ret;
+}
+
+
+void
+jwzgles_glNewList (int id, int mode)
+{
+  list *L;
+  Assert (id > 0 && id <= state->lists.count, "glNewList: bogus ID");
+  Assert (mode == GL_COMPILE, "glNewList: bad mode");
+  Assert (!state->compiling_verts, "glNewList not allowed inside glBegin");
+  Assert (!state->compiling_list, "nested glNewList");
+  Assert (state->set.count == 0, "missing glEnd");
+
+  L = &state->lists.lists[id-1];
+  Assert (L->id == id, "glNewList corrupted");
+
+  if (L->count != 0) jwzgles_glDeleteLists (L->id, 1); /* Overwriting */
+  Assert (L->count == 0, "glNewList corrupted");
+  
+  state->compiling_list = id;
+
+  state->list_enabled = state->enabled;
+
+  LOG1("glNewList -> %d", id);
+}
+
+
+static void save_arrays (list_fn *, int);
+static void restore_arrays (list_fn *, int);
+static void copy_array_data (draw_array *, int, const char *);
+static void optimize_arrays (void);
+static void generate_texture_coords (GLuint, GLuint);
+
+
+void
+jwzgles_glEndList (void)
+{
+  Assert (state->compiling_list, "extra glEndList");
+  Assert (state->set.count == 0, "missing glEnd");
+  Assert (!state->compiling_verts, "glEndList not allowed inside glBegin");
+  LOG1("glEndList %d", state->compiling_list);
+  optimize_arrays();
+  state->compiling_list = 0;
+  state->list_enabled = state->enabled;
+}
+
+
+static void
+list_push (const char * const name, 
+           list_fn_cb fn, fn_proto proto, void_int *av)
+{
+  list *L;
+  list_fn *F;
+  int i;
+
+  Assert (state->compiling_list > 0, "not inside glNewList");
+  Assert (state->compiling_list <= state->lists.count, "glNewList corrupted");
+
+  L = &state->lists.lists[state->compiling_list-1];
+  Assert (L, "glNewList: no list");
+
+  make_room ("glNewLists", 
+             (void **) &L->fns, sizeof (*L->fns),
+             &L->count, &L->size);
+  memset (&L->fns[L->count], 0, sizeof (*L->fns));
+  F = L->fns + L->count;
+
+  F->name = name;
+  F->fn = fn;
+  F->proto = proto;
+  if (proto != PROTO_VOID)
+    for (i = 0; i < countof(F->argv); i++)
+      F->argv[i] = av[i];
+
+# ifdef DEBUG
+  switch (proto) {
+  case PROTO_VOID:
+    LOG1 ("  push %-12s", name);
+    break;
+  case PROTO_I:
+    if (fn == (list_fn_cb) &jwzgles_glBegin ||
+        fn == (list_fn_cb) &jwzgles_glFrontFace ||
+        fn == (list_fn_cb) &jwzgles_glEnable ||
+        fn == (list_fn_cb) &jwzgles_glDisable ||
+        fn == (list_fn_cb) &jwzgles_glEnableClientState ||
+        fn == (list_fn_cb) &jwzgles_glDisableClientState ||
+        fn == (list_fn_cb) &jwzgles_glShadeModel ||
+        fn == (list_fn_cb) &jwzgles_glMatrixMode)
+      LOG2 ("  push %-12s %s", name, mode_desc (av[0].i));
+    else
+      LOG2 ("  push %-12s %d", name, av[0].i);
+    break;
+  case PROTO_F:
+    LOG2 ("  push %-12s %7.3f", name, av[0].f);
+    break;
+  case PROTO_II:
+    if (fn == (list_fn_cb) &jwzgles_glBindTexture ||
+        fn == (list_fn_cb) &jwzgles_glBindBuffer)
+      LOG3 ("  push %-12s %s %d", name, mode_desc (av[0].i), av[1].i);
+    else
+      LOG3 ("  push %-12s %d %d", name, av[0].i, av[1].i);
+    break;
+  case PROTO_FF:
+    LOG3 ("  push %-12s %7.3f %7.3f", name, av[0].f, av[1].f);
+    break;
+  case PROTO_IF:
+    LOG3 ("  push %-12s %s %7.3f", name, mode_desc (av[0].i), av[1].f);
+    break;
+  case PROTO_III:
+  case PROTO_ARRAYS:
+    if (fn == (list_fn_cb) &jwzgles_glDrawArrays ||
+        fn == (list_fn_cb) &jwzgles_glTexParameteri)
+      LOG4 ("  push %-12s %s %d %d", name, mode_desc (av[0].i), 
+            av[1].i, av[2].i);
+    else
+      LOG4 ("  push %-12s %d %d %d", name, av[0].i, av[1].i, av[2].i);
+    break;
+  case PROTO_FFF:
+    LOG4 ("  push %-12s %7.3f %7.3f %7.3f", name, av[0].f, av[1].f, av[2].f);
+    break;
+  case PROTO_IIF:
+    LOG4 ("  push %-12s %s %s %7.3f", name,
+             mode_desc(av[0].i), mode_desc(av[1].i), av[2].f);
+    break;
+  case PROTO_IIII:
+    LOG5 ("  push %-12s %d %d %d %d", name, 
+          av[0].i, av[1].i, av[2].i, av[3].i);
+    break;
+  case PROTO_FFFF:
+    LOG5 ("  push %-12s %7.3f %7.3f %7.3f %7.3f", name,
+             av[0].f, av[1].f, av[2].f, av[3].f);
+    break;
+  case PROTO_IFV:
+    LOG6 ("  push %-12s %s %3.1f %3.1f %3.1f %3.1f", name, mode_desc (av[0].i),
+             av[1].f, av[2].f, av[3].f, av[4].f);
+    break;
+  case PROTO_IIV:
+    LOG6 ("  push %-12s %s %d %d %d %d", name, mode_desc (av[0].i),
+             av[1].i, av[2].i, av[3].i, av[4].i);
+    break;
+  case PROTO_IIFV:
+    LOG7 ("  push %-12s %s %-8s %3.1f %3.1f %3.1f %3.1f", name,
+          mode_desc (av[0].i), mode_desc (av[1].i),
+             av[2].f, av[3].f, av[4].f, av[5].f);
+    break;
+  case PROTO_IIIV:
+    LOG7 ("  push %-12s %s %-8s %3d %3d %3d %3d", name,
+          mode_desc (av[0].i), mode_desc (av[1].i),
+             av[2].i, av[3].i, av[4].i, av[5].i);
+    break;
+  case PROTO_FV16:
+    LOG17 ("  push %-12s ["
+           "%8.3f %8.3f %8.3f %8.3f "  "\n\t\t\t       "
+           "%8.3f %8.3f %8.3f %8.3f "  "\n\t\t\t       "
+           "%8.3f %8.3f %8.3f %8.3f "  "\n\t\t\t       "
+           "%8.3f %8.3f %8.3f %8.3f ]",
+           name,
+           av[0].f,  av[1].f,  av[2].f,  av[3].f,
+           av[4].f,  av[5].f,  av[6].f,  av[7].f,
+           av[8].f,  av[9].f,  av[10].f, av[11].f,
+           av[12].f, av[13].f, av[14].f, av[15].f);
+    break;
+  default:
+    Assert (0, "bogus prototype");
+    break;
+  }
+# endif /* DEBUG */
+
+  if (proto == PROTO_ARRAYS) /* glDrawArrays */
+    save_arrays (F, av[1].i + av[2].i);
+
+  L->count++;
+}
+
+
+void
+jwzgles_glBegin (int mode)
+{
+  Assert (!state->compiling_verts, "nested glBegin");
+  state->compiling_verts++;
+
+  /* Only these commands are allowed inside glBegin:
+
+     glVertex          -- not allowed outside
+     glColor
+     glSecondaryColor
+     glIndex
+     glNormal
+     glFogCoord
+     glTexCoord
+     glMultiTexCoord
+     glVertexAttrib
+     glEvalCoord
+     glEvalPoint
+     glArrayElement    -- not allowed outside
+     glMaterial
+     glEdgeFlag
+     glCallList
+     glCallLists
+   */
+
+  if (!state->replaying_list)
+    LOG2 ("%sglBegin %s", 
+          (state->compiling_list || state->replaying_list ? "  " : ""),
+          mode_desc (mode));
+
+  Assert (state->set.count == 0, "glBegin corrupted");
+  state->set.mode   = mode;
+  state->set.count  = 0;
+  state->set.ncount = 0;
+  state->set.tcount = 0;
+  state->set.ccount = 0;
+}
+
+
+void
+jwzgles_glDeleteLists (int id0, int range)
+{
+  Assert (!state->compiling_verts, "glDeleteLists not allowed inside glBegin");
+
+  if (state->compiling_list)
+    {
+      void_int vv[2];
+      vv[0].i = id0;
+      vv[1].i = range;
+      list_push ("glDeleteLists", (list_fn_cb) &jwzgles_glDeleteLists, 
+                 PROTO_II, vv);
+    }
+  else
+    {
+      int id;
+
+      if (!state->replaying_list)
+        LOG2 ("glDeleteLists %d %d", id0, range);
+
+      for (id = id0 + range - 1; id >= id0; id--)
+        {
+          int i;
+          list *L;
+          if (id == 0) continue;  /* People do this stupid thing */
+          if (id > state->lists.count) break;  /* this too */
+          Assert (id > 0 && id <= state->lists.count,
+                  "glDeleteLists: bogus ID");
+          L = &state->lists.lists[id-1];
+          Assert (L->id == id, "glDeleteLists corrupted");
+
+          for (i = 0; i < L->count; i++)
+            {
+              list_fn *lf = &L->fns[i];
+              if (lf->arrays)
+                {
+                  int j;
+                  for (j = 0; j < 4; j++)
+                    /* If there's a binding, 'data' is an index, not a ptr. */
+                    if (!lf->arrays[j].binding &&
+                        lf->arrays[j].data)
+                      free (lf->arrays[j].data);
+                  free (lf->arrays);
+                }
+            }
+          if (L->fns) 
+            free (L->fns);
+          if (L->buffer)
+            glDeleteBuffers (1, &L->buffer);
+
+          memset (L, 0, sizeof (*L));
+          L->id = id;
+        }
+    }
+}
+
+
+extern GLboolean
+jwzgles_glIsList (GLuint id)
+{
+  return (id > 0 && id < state->lists.count);
+}
+
+
+
+void
+jwzgles_glNormal3fv (const GLfloat *v)
+{
+  if (state->compiling_list && !state->compiling_verts)
+    {
+      void_int vv[3];
+      vv[0].f = v[0];
+      vv[1].f = v[1];
+      vv[2].f = v[2];
+      list_push ("glNormal3f", (list_fn_cb) &jwzgles_glNormal3f, 
+                 PROTO_FFF, vv);
+    }
+  else
+    {
+      if (!state->replaying_list)
+        LOG5 ("%s%sglNormal3f   %7.3f %7.3f %7.3f",
+              (state->compiling_list || state->replaying_list ? "  " : ""),
+              (state->compiling_verts ? "  rec  " : ""),
+              v[0], v[1], v[2]);
+
+      if (state->compiling_verts)      /* inside glBegin */
+        {
+          state->set.cnorm.x = v[0];
+          state->set.cnorm.y = v[1];
+          state->set.cnorm.z = v[2];
+          state->set.ncount++;
+          if (state->set.count > 0 && state->set.ncount == 1)  /* not first! */
+            state->set.ncount++;
+        }
+      else                             /* outside glBegin */
+        {
+          glNormal3f (v[0], v[1], v[2]);
+          CHECK("glNormal3f");
+        }
+    }
+}
+
+
+void
+jwzgles_glNormal3f (GLfloat x, GLfloat y, GLfloat z)
+{
+  GLfloat v[3];
+  v[0] = x;
+  v[1] = y;
+  v[2] = z;
+  jwzgles_glNormal3fv (v);
+}
+
+
+void
+jwzgles_glTexCoord4fv (const GLfloat *v)
+{
+  if (state->compiling_list && !state->compiling_verts)
+    {
+      void_int vv[4];
+      vv[0].f = v[0];
+      vv[1].f = v[1];
+      vv[2].f = v[2];
+      vv[3].f = v[3];
+      list_push ("glTexCoord4f", (list_fn_cb) &jwzgles_glTexCoord4f,
+                 PROTO_FFFF, vv);
+    }
+  else
+    {
+      if (!state->replaying_list)
+        LOG6 ("%s%sglTexCoord4f %7.3f %7.3f %7.3f %7.3f", 
+              (state->compiling_list || state->replaying_list ? "  " : ""),
+              (state->compiling_verts ? "  rec  " : ""),
+              v[0], v[1], v[2], v[3]);
+
+      Assert (state->compiling_verts, "glTexCoord4fv outside glBegin");
+
+      if (state->compiling_verts)      /* inside glBegin */
+        {
+          state->set.ctex.s = v[0];
+          state->set.ctex.t = v[1];
+          state->set.ctex.r = v[2];
+          state->set.ctex.q = v[3];
+          state->set.tcount++;
+          if (state->set.count > 0 && state->set.tcount == 1)  /* not first! */
+            state->set.tcount++;
+        }
+    }
+}
+
+
+void
+jwzgles_glTexCoord4f (GLfloat s, GLfloat t, GLfloat r, GLfloat q)
+{
+  GLfloat v[4];
+  v[0] = s;
+  v[1] = t;
+  v[2] = r;
+  v[3] = q;
+  jwzgles_glTexCoord4fv (v);
+}
+
+
+void
+jwzgles_glTexCoord3fv (const GLfloat *v)
+{
+  GLfloat vv[4];
+  vv[0] = v[0];
+  vv[1] = v[1];
+  vv[2] = v[2];
+  vv[3] = 1;
+  jwzgles_glTexCoord4fv (vv);
+}
+
+
+void
+jwzgles_glTexCoord2fv (const GLfloat *v)
+{
+  GLfloat vv[4];
+  vv[0] = v[0];
+  vv[1] = v[1];
+  vv[2] = 0;
+  vv[3] = 1;
+  jwzgles_glTexCoord4fv (vv);
+}
+
+
+void
+jwzgles_glTexCoord3f (GLfloat s, GLfloat t, GLfloat r)
+{
+  jwzgles_glTexCoord4f (s, t, r, 1);
+}
+
+
+void
+jwzgles_glTexCoord2f (GLfloat s, GLfloat t)
+{
+  jwzgles_glTexCoord4f (s, t, 0, 1);
+}
+
+
+void
+jwzgles_glTexCoord1f (GLfloat s)
+{
+  jwzgles_glTexCoord4f (s, 0, 0, 1);
+}
+
+
+/* glColor: GLfloat */
+
+void
+jwzgles_glColor4fv (const GLfloat *v)
+{
+  if (state->compiling_list && !state->compiling_verts)
+    {
+      void_int vv[4];
+      vv[0].f = v[0];
+      vv[1].f = v[1];
+      vv[2].f = v[2];
+      vv[3].f = v[3];
+      list_push ("glColor4f", (list_fn_cb) &jwzgles_glColor4f, 
+                 PROTO_FFFF, vv);
+    }
+  else
+    {
+      if (!state->replaying_list)
+        LOG6 ("%s%sglColor4f    %7.3f %7.3f %7.3f %7.3f", 
+              (state->compiling_list || state->replaying_list ? "  " : ""),
+              (state->compiling_verts ? "  rec  " : ""),
+              v[0], v[1], v[2], v[3]);
+
+      if (state->compiling_verts)      /* inside glBegin */
+        {
+          state->set.ccolor.r = v[0];
+          state->set.ccolor.g = v[1];
+          state->set.ccolor.b = v[2];
+          state->set.ccolor.a = v[3];
+          state->set.ccount++;
+          if (state->set.count > 0 && state->set.ccount == 1)  /* not first! */
+            state->set.ccount++;
+        }
+      else                             /* outside glBegin */
+        {
+          glColor4f (v[0], v[1], v[2], v[3]);
+          CHECK("glColor4");
+        }
+    }
+}
+
+
+void
+jwzgles_glColor4f (GLfloat r, GLfloat g, GLfloat b, GLfloat a)
+{
+  GLfloat v[4];
+  v[0] = r;
+  v[1] = g;
+  v[2] = b;
+  v[3] = a;
+  jwzgles_glColor4fv (v);
+}
+
+void
+jwzgles_glColor3f (GLfloat r, GLfloat g, GLfloat b)
+{
+  jwzgles_glColor4f (r, g, b, 1);
+}
+
+void
+jwzgles_glColor3fv (const GLfloat *v)
+{
+  jwzgles_glColor3f (v[0], v[1], v[2]);
+}
+
+
+/* glColor: GLdouble */
+
+void
+jwzgles_glColor4d (GLdouble r, GLdouble g, GLdouble b, GLdouble a)
+{
+  jwzgles_glColor4f (r, g, b, a);
+}
+
+void
+jwzgles_glColor4dv (const GLdouble *v)
+{
+  jwzgles_glColor4d (v[0], v[1], v[2], v[3]);
+}
+
+void
+jwzgles_glColor3d (GLdouble r, GLdouble g, GLdouble b)
+{
+  jwzgles_glColor4d (r, g, b, 1.0);
+}
+
+void
+jwzgles_glColor3dv (const GLdouble *v)
+{
+  jwzgles_glColor3d (v[0], v[1], v[2]);
+}
+
+
+/* glColor: GLint (INT_MIN - INT_MAX) */
+
+void
+jwzgles_glColor4i (GLint r, GLint g, GLint b, GLint a)
+{
+  /* -0x8000000 - 0x7FFFFFFF  =>  0.0 - 1.0 */
+  jwzgles_glColor4f (0.5 + (GLfloat) r / 0xFFFFFFFF,
+                     0.5 + (GLfloat) g / 0xFFFFFFFF, 
+                     0.5 + (GLfloat) b / 0xFFFFFFFF,
+                     0.5 + (GLfloat) a / 0xFFFFFFFF);
+}
+
+void
+jwzgles_glColor4iv (const GLint *v)
+{
+  jwzgles_glColor4i (v[0], v[1], v[2], v[3]);
+}
+
+
+void
+jwzgles_glColor3i (GLint r, GLint g, GLint b)
+{
+  jwzgles_glColor4i (r, g, b, 0x7FFFFFFF);
+}
+
+void
+jwzgles_glColor3iv (const GLint *v)
+{
+  jwzgles_glColor3i (v[0], v[1], v[2]);
+}
+
+
+/* glColor: GLuint (0 - UINT_MAX) */
+
+void
+jwzgles_glColor4ui (GLuint r, GLuint g, GLuint b, GLuint a)
+{
+  /* 0 - 0xFFFFFFFF  =>  0.0 - 1.0 */
+  jwzgles_glColor4f ((GLfloat) r / 0xFFFFFFFF,
+                     (GLfloat) g / 0xFFFFFFFF, 
+                     (GLfloat) b / 0xFFFFFFFF,
+                     (GLfloat) a / 0xFFFFFFFF);
+}
+
+void
+jwzgles_glColor4uiv (const GLuint *v)
+{
+  jwzgles_glColor4ui (v[0], v[1], v[2], v[3]);
+}
+
+void
+jwzgles_glColor3ui (GLuint r, GLuint g, GLuint b)
+{
+  jwzgles_glColor4ui (r, g, b, 0xFFFFFFFF);
+}
+
+void
+jwzgles_glColor3uiv (const GLuint *v)
+{
+  jwzgles_glColor3ui (v[0], v[1], v[2]);
+}
+
+
+/* glColor: GLshort (SHRT_MIN - SHRT_MAX) */
+
+void
+jwzgles_glColor4s (GLshort r, GLshort g, GLshort b, GLshort a)
+{
+  /* -0x8000 - 0x7FFF  =>  0.0 - 1.0 */
+  jwzgles_glColor4f (0.5 + (GLfloat) r / 0xFFFF,
+                     0.5 + (GLfloat) g / 0xFFFF,
+                     0.5 + (GLfloat) b / 0xFFFF,
+                     0.5 + (GLfloat) a / 0xFFFF);
+}
+
+void
+jwzgles_glColor4sv (const GLshort *v)
+{
+  jwzgles_glColor4s (v[0], v[1], v[2], v[3]);
+}
+
+void
+jwzgles_glColor3s (GLshort r, GLshort g, GLshort b)
+{
+  jwzgles_glColor4s (r, g, b, 0x7FFF);
+}
+
+void
+jwzgles_glColor3sv (const GLshort *v)
+{
+  jwzgles_glColor3s (v[0], v[1], v[2]);
+}
+
+
+/* glColor: GLushort (0 - USHRT_MAX) */
+
+void
+jwzgles_glColor4us (GLushort r, GLushort g, GLushort b, GLushort a)
+{
+  /* 0 - 0xFFFF  =>  0.0 - 1.0 */
+  jwzgles_glColor4f ((GLfloat) r / 0xFFFF,
+                     (GLfloat) g / 0xFFFF,
+                     (GLfloat) b / 0xFFFF,
+                     (GLfloat) a / 0xFFFF);
+}
+
+void
+jwzgles_glColor4usv (const GLushort *v)
+{
+  jwzgles_glColor4us (v[0], v[1], v[2], v[3]);
+}
+
+void
+jwzgles_glColor3us (GLushort r, GLushort g, GLushort b)
+{
+  jwzgles_glColor4us (r, g, b, 0xFFFF);
+}
+
+void
+jwzgles_glColor3usv (const GLushort *v)
+{
+  jwzgles_glColor3us (v[0], v[1], v[2]);
+}
+
+
+/* glColor: GLbyte (-128 - 127) */
+
+void
+jwzgles_glColor4b (GLbyte r, GLbyte g, GLbyte b, GLbyte a)
+{
+  /* -128 - 127  =>  0.0 - 1.0 */
+  jwzgles_glColor4f (0.5 + (GLfloat) r / 255,
+                     0.5 + (GLfloat) g / 255,
+                     0.5 + (GLfloat) b / 255,
+                     0.5 + (GLfloat) a / 255);
+}
+
+void
+jwzgles_glColor4bv (const GLbyte *v)
+{
+  jwzgles_glColor4b (v[0], v[1], v[2], v[3]);
+}
+
+void
+jwzgles_glColor3b (GLbyte r, GLbyte g, GLbyte b)
+{
+  jwzgles_glColor4b (r, g, b, 127);
+}
+
+void
+jwzgles_glColor3bv (const GLbyte *v)
+{
+  jwzgles_glColor3b (v[0], v[1], v[2]);
+}
+
+
+/* glColor: GLubyte (0 - 255) */
+
+void
+jwzgles_glColor4ub (GLubyte r, GLubyte g, GLubyte b, GLubyte a)
+{
+  /* 0 - 255  =>  0.0 - 1.0 */
+  jwzgles_glColor4f (r / 255.0, g / 255.0, b / 255.0, a / 255.0);
+}
+
+void
+jwzgles_glColor4ubv (const GLubyte *v)
+{
+  jwzgles_glColor4ub (v[0], v[1], v[2], v[3]);
+}
+
+void
+jwzgles_glColor3ub (GLubyte r, GLubyte g, GLubyte b)
+{
+  jwzgles_glColor4ub (r, g, b, 255);
+}
+
+void
+jwzgles_glColor3ubv (const GLubyte *v)
+{
+  jwzgles_glColor3ub (v[0], v[1], v[2]);
+}
+
+
+
+void
+jwzgles_glMaterialfv (GLenum face, GLenum pname, const GLfloat *color)
+{
+  /* If this is called inside glBegin/glEnd with a front ambient color,
+     then treat it the same as glColor: set the color of the upcoming
+     vertex.
+
+     Other faces or lighting types within glBegin are ignored.
+   */
+
+  if (state->compiling_verts)
+    {
+      if ((face == GL_FRONT || 
+           face == GL_FRONT_AND_BACK) &&
+          (pname == GL_AMBIENT || 
+           pname == GL_DIFFUSE || 
+           pname == GL_AMBIENT_AND_DIFFUSE))
+        {
+          jwzgles_glColor4f (color[0], color[1], color[2], color[3]);
+          state->set.materialistic++;
+        }
+      else
+        LOG2 ("  IGNORING glMaterialfv %s %s",
+              mode_desc(face), mode_desc(pname));
+    }
+  else if (state->compiling_list)
+    {
+      void_int vv[6];
+      vv[0].i = face;
+      vv[1].i = pname;
+      vv[2].f = color[0];
+      vv[3].f = color[1];
+      vv[4].f = color[2];
+      vv[5].f = color[3];
+      list_push ("glMaterialfv", (list_fn_cb) &jwzgles_glMaterialfv, 
+                 PROTO_IIFV, vv);
+    }
+  else
+    {
+      /* If this is called outside of glBegin/glEnd with a front
+         ambient color, then the intent is presumably for that color
+         to apply to the upcoming vertexes (which may be played back
+         from a list that does not have vertex colors in it).  In that
+         case, the only way to make the colors show up is to call
+         glColor() with GL_COLOR_MATERIAL enabled.
+
+         I'm not sure if this will have other inappropriate side effects...
+       */
+      if ((face == GL_FRONT ||
+           face == GL_FRONT_AND_BACK) &&
+          (pname == GL_AMBIENT ||
+           pname == GL_DIFFUSE ||
+           pname == GL_AMBIENT_AND_DIFFUSE))
+        {
+          jwzgles_glEnable (GL_COLOR_MATERIAL);
+          jwzgles_glColor4f (color[0], color[1], color[2], color[3]);
+        }
+
+      /* OpenGLES seems to throw "invalid enum" for GL_FRONT -- but it
+         goes ahead and sets the material anyway!  No error if we just
+         always use GL_FRONT_AND_BACK.
+       */
+      if (face == GL_FRONT)
+        face = GL_FRONT_AND_BACK;
+      if (! state->replaying_list)
+        LOG7 ("direct %-12s %s %s %7.3f %7.3f %7.3f %7.3f", "glMaterialfv",
+              mode_desc(face), mode_desc(pname),
+              color[0], color[1], color[2], color[3]);
+      glMaterialfv (face, pname, color);  /* the real one */
+      CHECK("glMaterialfv");
+    }
+}
+
+
+void
+jwzgles_glMaterialiv (GLenum face, GLenum pname, const GLint *v)
+{
+  GLfloat vv[4];
+  vv[0] = v[0];
+  vv[1] = v[1];
+  vv[2] = v[2];
+  vv[3] = 1;
+  jwzgles_glMaterialfv (face, pname, vv);
+}
+
+void
+jwzgles_glMaterialf (GLenum face, GLenum pname, const GLfloat c)
+{
+  GLfloat vv[4];
+  vv[0] = c;
+  vv[1] = c;
+  vv[2] = c;
+  vv[3] = 1;
+  jwzgles_glMaterialfv (face, pname, vv);
+}
+
+
+void
+jwzgles_glMateriali (GLenum face, GLenum pname, const GLuint c)
+{
+  jwzgles_glMaterialf (face, pname, c);
+}
+
+
+void
+jwzgles_glColorMaterial (GLenum face, GLenum mode)
+{
+  Assert (!state->compiling_verts,
+          "glColorMaterial not allowed inside glBegin");
+#if 0
+  if (state->compiling_list)
+    {
+      void_int vv[2];
+      vv[0].i = face;
+      vv[1].i = mode;
+      list_push ("glColorMaterial", (list_fn_cb) &jwzgles_glColorMaterial, 
+                 PROTO_II, vv);
+    }
+  else
+    {
+      /* No real analog to this distinction in OpenGLES, since color
+         arrays don't distinguish between "color" and "material", */
+      Assert (0, "glColorMaterial: unimplemented mode");
+    }
+#endif
+}
+
+
+
+
+void
+jwzgles_glVertex4fv (const GLfloat *v)
+{
+  vert_set *s = &state->set;
+  int count = s->count;
+
+  Assert (state->compiling_verts, "glVertex4fv not inside glBegin");
+
+  LOG5("%s  rec  glVertex4f   %7.3f %7.3f %7.3f %7.3f",
+       (state->compiling_list || state->replaying_list ? "  " : ""),
+       v[0], v[1], v[2], v[3]);
+
+  if (count >= s->size - 1)
+    {
+      int new_size = 20 + (s->size * 1.2);
+
+      /* 4 arrays, different element sizes...
+         We allocate all 4 arrays just in case we need them,
+         but we might not end up using them all at the end.
+      */
+
+      s->verts = (XYZW *) realloc (s->verts, new_size * sizeof (*s->verts));
+      Assert (s->verts, "out of memory");
+
+      s->norms = (XYZ *) realloc (s->norms, new_size * sizeof (*s->norms));
+      Assert (s->norms, "out of memory");
+
+      s->tex = (STRQ *) realloc (s->tex, new_size * sizeof (*s->tex));
+      Assert (s->tex, "out of memory");
+
+      s->color = (RGBA *) realloc (s->color, new_size * sizeof (*s->color));
+      Assert (s->color, "out of memory");
+
+      s->size = new_size;
+    }
+
+  s->verts [count].x = v[0];
+  s->verts [count].y = v[1];
+  s->verts [count].z = v[2];
+  s->verts [count].w = v[3];
+  s->norms [count] = s->cnorm;
+  s->tex   [count] = s->ctex;
+  s->color [count] = s->ccolor;
+  s->count++;
+}
+
+
+void
+jwzgles_glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+  GLfloat v[4];
+  v[0] = x;
+  v[1] = y;
+  v[2] = z;
+  v[3] = w;
+  jwzgles_glVertex4fv (v);
+}
+
+void
+jwzgles_glVertex4i (GLint x, GLint y, GLint z, GLint w)
+{
+  jwzgles_glVertex4f (x, y, z, w);
+}
+
+void
+jwzgles_glVertex3f (GLfloat x, GLfloat y, GLfloat z)
+{
+  GLfloat v[4];
+  v[0] = x;
+  v[1] = y;
+  v[2] = z;
+  v[3] = 1;
+  jwzgles_glVertex4fv (v);
+}
+
+void
+jwzgles_glVertex3i (GLint x, GLint y, GLint z)
+{
+  jwzgles_glVertex3f (x, y, z);
+}
+
+void
+jwzgles_glVertex3fv (const GLfloat *v)
+{
+  jwzgles_glVertex3f (v[0], v[1], v[2]);
+}
+
+void
+jwzgles_glVertex3dv (const GLdouble *v)
+{
+  jwzgles_glVertex3f (v[0], v[1], v[2]);
+}
+
+
+void
+jwzgles_glVertex2f (GLfloat x, GLfloat y)
+{
+  GLfloat v[3];
+  v[0] = x;
+  v[1] = y;
+  v[2] = 0;
+  jwzgles_glVertex3fv (v);
+}
+
+void
+jwzgles_glVertex2dv (const GLdouble *v)
+{
+  jwzgles_glVertex2f (v[0], v[1]);
+}
+
+void
+jwzgles_glVertex2fv (const GLfloat *v)
+{
+  jwzgles_glVertex2f (v[0], v[1]);
+}
+
+void
+jwzgles_glVertex2i (GLint x, GLint y)
+{
+  jwzgles_glVertex2f (x, y);
+}
+
+
+void
+jwzgles_glLightiv (GLenum light, GLenum pname, const GLint *params)
+{
+  GLfloat v[4];
+  v[0] = params[0];
+  v[1] = params[1];
+  v[2] = params[2];
+  v[3] = params[3];
+  jwzgles_glLightfv (light, pname, v);
+}
+
+void
+jwzgles_glLightModeliv (GLenum pname, const GLint *params)
+{
+  GLfloat v[4];
+  v[0] = params[0];
+  v[1] = params[1];
+  v[2] = params[2];
+  v[3] = params[3];
+  jwzgles_glLightModelfv (pname, v);
+}
+
+void
+jwzgles_glFogiv (GLenum pname, const GLint *params)
+{
+  GLfloat v[4];
+  v[0] = params[0];
+  v[1] = params[1];
+  v[2] = params[2];
+  v[3] = params[3];
+  jwzgles_glFogfv (pname, v);
+}
+
+void
+jwzgles_glLighti (GLenum light, GLenum pname, GLint param)
+{
+  jwzgles_glLightf (light, pname, param);
+}
+
+void
+jwzgles_glLightModeli (GLenum pname, GLint param)
+{
+  jwzgles_glLightModelf (pname, param);
+}
+
+void
+jwzgles_glFogi (GLenum pname, GLint param)
+{
+  jwzgles_glFogf (pname, param);
+}
+
+
+void
+jwzgles_glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z)
+{
+  jwzgles_glRotatef (angle, x, y, z);
+}
+
+
+void
+jwzgles_glClipPlane (GLenum plane, const GLdouble *equation)
+{
+  Assert (state->compiling_verts, "glClipPlane not inside glBegin");
+  Assert (0, "glClipPlane unimplemented");  /* no GLES equivalent... */
+}
+
+
+void
+jwzgles_glPolygonMode (GLenum face, GLenum mode)
+{
+  Assert (!state->compiling_verts, "not inside glBegin");
+  if (state->compiling_list)
+    {
+      void_int vv[2];
+      vv[0].i = face;
+      vv[1].i = mode;
+      list_push ("glPolygonMode", (list_fn_cb) &jwzgles_glPolygonMode, 
+                 PROTO_II, vv);
+    }
+  else
+    {
+      /* POINT and LINE don't exist in GLES */
+      Assert (mode == GL_FILL, "glPolygonMode: unimplemented mode");
+    }
+}
+
+
+void
+jwzgles_glDrawBuffer (GLenum buf)
+{
+  Assert (!state->compiling_verts, "not inside glBegin");
+  if (state->compiling_list)
+    {
+      void_int vv[1];
+      vv[0].i = buf;
+      list_push ("glDrawBuffer", (list_fn_cb) &jwzgles_glDrawBuffer, 
+                 PROTO_I, vv);
+    }
+  else
+    {
+/*      Assert (buf == GL_BACK, "glDrawBuffer: back buffer only"); */
+# ifndef GL_VERSION_ES_CM_1_0  /* not compiling against OpenGLES 1.x */
+      if (! state->replaying_list)
+        LOG1 ("direct %-12s", "glDrawBuffer");
+      glDrawBuffer (buf);      /* the real one */
+      CHECK("glDrawBuffer");
+# endif
+    }
+}
+
+
+/* Given an array of sets of 4 elements of arbitrary size, convert it
+   to an array of sets of 6 elements instead: ABCD becomes ABC BCD.
+ */
+static int
+cq2t (unsigned char **arrayP, int stride, int count)
+{
+  int count2 = count * 6 / 4;
+  int size  = stride * count;
+  int size2 = stride * count2;
+  const unsigned char    *oarray,  *in;
+  unsigned char *array2, *oarray2, *out;
+  int i;
+
+  oarray = *arrayP;
+  if (!oarray || count == 0)
+    return count2;
+
+  array2 = (unsigned char *) malloc (size2);
+  Assert (array2, "out of memory");
+  oarray2 = array2;
+
+  in =  oarray;
+  out = oarray2;
+  for (i = 0; i < count / 4; i++)
+    {
+      const unsigned char *a, *b, *c, *d;      /* the 4 corners */
+      a = in; in += stride;
+      b = in; in += stride;
+      c = in; in += stride;
+      d = in; in += stride;
+
+# define PUSH(IN) do {                 \
+         const unsigned char *ii = IN; \
+         int j;                                \
+         for (j = 0; j < stride; j++) {        \
+           *out++ = *ii++;             \
+         }} while(0)
+
+      PUSH (a); PUSH (b); PUSH (d);            /* the 2 triangles */
+      PUSH (b); PUSH (c); PUSH (d);
+# undef PUSH
+    }
+
+  Assert (in  == oarray  + size,  "convert_quads corrupted");
+  Assert (out == oarray2 + size2, "convert_quads corrupted");
+
+  free (*arrayP);
+  *arrayP = oarray2;
+  return count2;
+}
+                              
+
+/* Convert all coordinates in a GL_QUADS vert_set to GL_TRIANGLES.
+ */
+static void
+convert_quads_to_triangles (vert_set *s)
+{
+  int count2;
+  Assert (s->mode == GL_QUADS, "convert_quads bad mode");
+  count2 =
+   cq2t ((unsigned char **) &s->verts, sizeof(*s->verts), s->count);
+   cq2t ((unsigned char **) &s->norms, sizeof(*s->norms), s->count);
+   cq2t ((unsigned char **) &s->tex,   sizeof(*s->tex),   s->count);
+   cq2t ((unsigned char **) &s->color, sizeof(*s->color), s->count);
+  s->count = count2;
+  s->size  = count2;
+  s->mode = GL_TRIANGLES;
+}
+
+
+void
+jwzgles_glEnd (void)
+{
+  vert_set *s = &state->set;
+  int was_norm, was_tex, was_color, was_mat;
+  int  is_norm,  is_tex,  is_color,  is_mat;
+
+  Assert (state->compiling_verts == 1, "missing glBegin");
+  state->compiling_verts--;
+
+  Assert (!state->replaying_list, "how did glEnd get into a display list?");
+
+  if (!state->replaying_list)
+    {
+      LOG5 ("%s  [V = %d, N = %d, T = %d, C = %d]",
+            (state->compiling_list || state->replaying_list ? "  " : ""),
+            s->count, s->ncount, s->tcount, s->ccount);
+      LOG1 ("%sglEnd",
+            (state->compiling_list || state->replaying_list ? "  " : ""));
+    }
+
+  if (s->count == 0) return;
+
+  if (s->mode == GL_QUADS)
+    convert_quads_to_triangles (s);
+  else if (s->mode == GL_QUAD_STRIP)
+    s->mode = GL_TRIANGLE_STRIP;       /* They do the same thing! */
+  else if (s->mode == GL_POLYGON)
+    s->mode = GL_TRIANGLE_FAN;         /* They do the same thing! */
+
+  jwzgles_glColorPointer   (4,GL_FLOAT, sizeof(*s->color),s->color); /* RGBA */
+  jwzgles_glNormalPointer  (  GL_FLOAT, sizeof(*s->norms),s->norms); /* XYZ  */
+  jwzgles_glTexCoordPointer(4,GL_FLOAT, sizeof(*s->tex),  s->tex);   /* STRQ */
+  jwzgles_glVertexPointer  (4,GL_FLOAT, sizeof(*s->verts),s->verts); /* XYZW */
+  /* glVertexPointer must come after glTexCoordPointer */
+
+  /* If there were no calls to glNormal3f inside of glBegin/glEnd,
+     don't bother enabling the normals array.
+
+     If there was exactly *one* call to glNormal3f inside of glBegin/glEnd,
+     and it was before the first glVertex3f, then also don't enable the
+     normals array, but do emit that call to glNormal3f before calling
+     glDrawArrays.
+
+     Likewise for texture coordinates and colors.
+
+     Be careful to leave the arrays' enabled/disabled state the same as
+     before, or a later caller might end up using one of our arrays by
+     mistake.  (Remember that jwzgles_glIsEnabled() tracks the enablement
+     of the list-in-progress as well as the global state.)
+  */
+  was_norm  = jwzgles_glIsEnabled (GL_NORMAL_ARRAY);
+  was_tex   = jwzgles_glIsEnabled (GL_TEXTURE_COORD_ARRAY);
+  was_color = jwzgles_glIsEnabled (GL_COLOR_ARRAY);
+  was_mat   = jwzgles_glIsEnabled (GL_COLOR_MATERIAL);
+
+  /* If we're executing glEnd in immediate mode, not from inside a display
+     list (which is the only way it happens, because glEnd doesn't go into
+     display lists), make sure we're not stomping on a saved buffer list:
+     in immediate mode, vertexes are client-side only.
+   */
+  if (! state->compiling_list)
+    jwzgles_glBindBuffer (GL_ARRAY_BUFFER, 0);
+
+  if (s->ncount > 1)
+    {
+      is_norm = 1;
+      jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
+    }
+  else
+    {
+      is_norm = 0;
+      if (s->ncount == 1)
+        jwzgles_glNormal3f (s->cnorm.x, s->cnorm.y, s->cnorm.z);
+      jwzgles_glDisableClientState (GL_NORMAL_ARRAY);
+    }
+
+  if (s->tcount > 1 ||
+      ((state->compiling_list ? state->list_enabled : state->enabled)
+       & (ISENABLED_TEXTURE_GEN_S | ISENABLED_TEXTURE_GEN_T |
+          ISENABLED_TEXTURE_GEN_R | ISENABLED_TEXTURE_GEN_Q)))
+    {
+      /* Enable texture coords if any were specified; or if generation
+         is on in immediate mode; or if this list turned on generation. */
+      is_tex = 1;
+      jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+    }
+  else
+    {
+      is_tex = 0;
+      if (s->tcount == 1)
+        jwzgles_glTexCoord4f (s->ctex.s, s->ctex.t, s->ctex.r, s->ctex.q);
+      jwzgles_glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+    }
+
+  if (s->ccount > 1)
+    {
+      is_color = 1;
+      jwzgles_glEnableClientState (GL_COLOR_ARRAY);
+    }
+  else
+    {
+      is_color = 0;
+      if (s->ccount == 1)
+        jwzgles_glColor4f (s->ccolor.r, s->ccolor.g, s->ccolor.b, s->ccolor.a);
+      jwzgles_glDisableClientState (GL_COLOR_ARRAY);
+    }
+
+  jwzgles_glEnableClientState (GL_VERTEX_ARRAY);
+
+  /* We translated the glMaterial calls to per-vertex colors, which are
+     of the glColor sort, not the glMaterial sort, so automatically
+     turn on material mapping.  Maybe this is a bad idea.
+   */
+  if (s->materialistic && !jwzgles_glIsEnabled (GL_COLOR_MATERIAL))
+    {
+      is_mat = 1;
+      jwzgles_glEnable (GL_COLOR_MATERIAL);
+    }
+  else
+    is_mat = 0;
+
+  glBindBuffer (GL_ARRAY_BUFFER, 0);    /* This comes later. */
+  jwzgles_glDrawArrays (s->mode, 0, s->count);
+  glBindBuffer (GL_ARRAY_BUFFER, 0);    /* Keep out of others' hands */
+
+# define RESET(VAR,FN,ARG) do { \
+         if (is_##VAR != was_##VAR) { \
+            if (was_##VAR) jwzgles_glEnable##FN (ARG); \
+            else jwzgles_glDisable##FN (ARG); \
+         }} while(0)
+  RESET (norm,  ClientState, GL_NORMAL_ARRAY);
+  RESET (tex,   ClientState, GL_TEXTURE_COORD_ARRAY);
+  RESET (color, ClientState, GL_COLOR_ARRAY);
+  RESET (mat,   ,            GL_COLOR_MATERIAL);
+# undef RESET
+
+  s->count  = 0;
+  s->ncount = 0;
+  s->tcount = 0;
+  s->ccount = 0;
+  s->materialistic = 0;
+}
+
+
+/* The display list is full of calls to glDrawArrays(), plus saved arrays
+   of the values we need to restore before calling it.  "Restore" means
+   "ship them off to the GPU before each call".
+
+   So instead, this function walks through the display list and
+   combines all of those vertex, normal, texture and color values into
+   a single VBO array; ships those values off to the GPU *once* at the
+   time of glEndList; and when running the list with glCallList, the
+   values are already on the GPU and don't need to be sent over again.
+
+   The VBO persists in the GPU until the display list is deleted.
+ */
+static void
+optimize_arrays (void)
+{
+  list *L = &state->lists.lists[state->compiling_list-1];
+  int i, j;
+  GLfloat *combo = 0;
+  int combo_count = 0;
+  int combo_size = 0;
+  GLuint buf_name = 0;
+
+  Assert (state->compiling_list, "not compiling a list");
+  Assert (L, "no list");
+  Assert (!L->buffer, "list already has a buffer");
+
+  glGenBuffers (1, &buf_name);
+  CHECK("glGenBuffers");
+  if (! buf_name) return;
+
+  L->buffer = buf_name;
+
+  /* Go through the list and dump the contents of the various saved arrays
+     into one large array.
+   */
+  for (i = 0; i < L->count; i++)
+    {
+      list_fn *F = &L->fns[i];
+/*      int count; */
+      if (! F->arrays)
+        continue;
+/*      count = F->argv[2].i;*/  /* 3rd arg to glDrawArrays */
+
+      for (j = 0; j < 4; j++)
+        {
+          draw_array *A = &F->arrays[j];
+          int ocount = combo_count;
+
+          /* If some caller is using arrays that don't have floats in them,
+             we just leave them as-is and ship them over at each call.
+             Doubt this ever really happens.
+           */
+          if (A->type != GL_FLOAT)
+            continue;
+
+          if (! A->data)       /* No array. */
+            continue;
+
+          Assert (A->bytes > 0, "no bytes in draw_array");
+          Assert (((unsigned long) A->data > 0xFFFF),
+                  "buffer data not a pointer");
+
+          combo_count += A->bytes / sizeof(*combo);
+          make_room ("optimize_arrays",
+                     (void **) &combo, sizeof(*combo),
+                     &combo_count, &combo_size);
+          memcpy (combo + ocount, A->data, A->bytes);
+          A->binding = buf_name;
+          free (A->data);
+          /* 'data' is now the byte offset into the VBO. */
+          A->data = (void *) (ocount * sizeof(*combo));
+          /* LOG3("    loaded %lu floats to pos %d of buffer %d",
+               A->bytes / sizeof(*combo), ocount, buf_name); */
+        }
+    }
+
+  if (combo_count == 0)                /* Nothing to do! */
+    {
+      if (combo) free (combo);
+      glDeleteBuffers (1, &buf_name);
+      L->buffer = 0;
+      return;
+    }
+
+  glBindBuffer (GL_ARRAY_BUFFER, buf_name);
+  glBufferData (GL_ARRAY_BUFFER, 
+                combo_count * sizeof (*combo),
+                combo,
+                GL_STATIC_DRAW);
+  glBindBuffer (GL_ARRAY_BUFFER, 0);    /* Keep out of others' hands */
+
+  LOG3("  loaded %d floats of list %d into VBO %d",
+       combo_count, state->compiling_list, buf_name);
+
+# ifdef DEBUG
+#  if 0
+  for (i = 0; i < combo_count; i++)
+    {
+      if (i % 4 == 0)
+        fprintf (stderr, "\njwzgles:    %4d: ", i);
+      fprintf (stderr, " %7.3f", combo[i]);
+    }
+  fprintf (stderr, "\n");
+#  endif
+# endif /* DEBUG */
+
+  if (combo) free (combo);
+}
+
+
+void
+jwzgles_glCallList (int id)
+{
+  if (state->compiling_list)
+    {
+      /* Yes, you can call lists inside of lists.
+         Yes, recursion would be a mistake. */
+      void_int vv[1];
+      vv[0].i = id;
+      list_push ("glCallList", (list_fn_cb) &jwzgles_glCallList, PROTO_I, vv);
+    }
+  else
+    {
+      list *L;
+      int i;
+
+      state->replaying_list++;
+
+# ifdef DEBUG
+      fprintf (stderr, "\n");
+      LOG1 ("glCallList %d", id);
+# endif
+
+      Assert (id > 0 && id <= state->lists.count, "glCallList: bogus ID");
+      L = &state->lists.lists[id-1];
+      Assert (id == L->id, "glCallList corrupted");
+
+      for (i = 0; i < L->count; i++)
+        {
+          list_fn *F = &L->fns[i];
+          list_fn_cb fn = F->fn;
+          void_int *av = F->argv;
+
+          switch (F->proto) {
+          case PROTO_VOID:
+            LOG1 ("  call %-12s", F->name);
+            ((void (*) (void)) fn) ();
+            break;
+
+          case PROTO_I:
+            if (fn == (list_fn_cb) &jwzgles_glBegin ||
+                fn == (list_fn_cb) &jwzgles_glFrontFace ||
+                fn == (list_fn_cb) &jwzgles_glEnable ||
+                fn == (list_fn_cb) &jwzgles_glDisable ||
+                fn == (list_fn_cb) &jwzgles_glEnableClientState ||
+                fn == (list_fn_cb) &jwzgles_glDisableClientState ||
+                fn == (list_fn_cb) &jwzgles_glShadeModel ||
+                fn == (list_fn_cb) &jwzgles_glMatrixMode)
+              LOG2 ("  call %-12s %s", F->name, mode_desc (av[0].i));
+            else
+              LOG2 ("  call %-12s %d", F->name, av[0].i);
+            ((void (*) (int)) fn) (av[0].i);
+            break;
+
+          case PROTO_F:
+            LOG2 ("  call %-12s %7.3f", F->name, av[0].f);
+            ((void (*) (GLfloat)) fn) (av[0].f);
+            break;
+
+          case PROTO_II:
+            if (fn == (list_fn_cb) &jwzgles_glBindTexture ||
+                fn == (list_fn_cb) &jwzgles_glBindBuffer)
+              LOG3 ("  call %-12s %s %d", F->name, 
+                    mode_desc (av[0].i), av[1].i);
+            else
+              LOG3 ("  call %-12s %d %d", F->name, av[0].i, av[1].i);
+            ((void (*) (int, int)) fn) (av[0].i, av[1].i);
+            break;
+
+          case PROTO_FF:
+            LOG3 ("  call %-12s %7.3f %7.3f", F->name, av[0].f, av[1].f);
+            ((void (*) (GLfloat, GLfloat)) fn) (av[0].f, av[1].f);
+            break;
+
+          case PROTO_IF:
+            LOG3 ("  call %-12s %s %7.3f", F->name, 
+                  mode_desc (av[0].f), av[1].f);
+            ((void (*) (GLint, GLfloat)) fn) (av[0].i, av[1].f);
+            break;
+
+          case PROTO_III: III:
+            if (fn == (list_fn_cb) &jwzgles_glDrawArrays ||
+                fn == (list_fn_cb) &jwzgles_glTexParameteri)
+              LOG4 ("  call %-12s %s %d %d", F->name, 
+                    mode_desc (av[0].i), av[1].i, av[2].i);
+            else
+              LOG4 ("  call %-12s %d %d %d", F->name, 
+                    av[0].i, av[1].i, av[2].i);
+            ((void (*) (int, int, int)) fn) (av[0].i, av[1].i, av[2].i);
+            break;
+
+          case PROTO_FFF:
+            LOG4 ("  call %-12s %7.3f %7.3f %7.3f", F->name,
+                  av[0].f, av[1].f, av[2].f);
+            ((void (*) (GLfloat, GLfloat, GLfloat)) fn)
+              (av[0].f, av[1].f, av[2].f);
+            break;
+
+          case PROTO_IIF:
+            LOG4 ("  call %-12s %s %s %7.3f", F->name,
+                  mode_desc (av[0].i), mode_desc (av[1].i), av[2].f);
+            ((void (*) (int, int, GLfloat)) fn) (av[0].i, av[1].i, av[2].f);
+            break;
+
+          case PROTO_IIII:
+            LOG5 ("  call %-12s %d %d %d %d", F->name,
+                  av[0].i, av[1].i, av[2].i, av[3].i);
+            ((void (*) (int, int, int, int)) fn) 
+              (av[0].i, av[1].i, av[2].i, av[3].i);
+            break;
+
+          case PROTO_FFFF:
+            LOG5 ("  call %-12s %7.3f %7.3f %7.3f %7.3f", F->name,
+                  av[0].f, av[1].f, av[2].f, av[3].f);
+            ((void (*) (GLfloat, GLfloat, GLfloat, GLfloat)) fn)
+              (av[0].f, av[1].f, av[2].f, av[3].f);
+            break;
+
+          case PROTO_IFV:
+            {
+              GLfloat v[4];
+              v[0] = av[1].f;
+              v[1] = av[2].f;
+              v[2] = av[3].f;
+              v[3] = av[4].f;
+              LOG6 ("  call %-12s %s %3.1f %3.1f %3.1f %3.1f", F->name,
+                    mode_desc (av[0].i),
+                    av[1].f, av[2].f, av[3].f, av[4].f);
+              ((void (*) (int, const GLfloat *)) fn) (av[0].i, v);
+            }
+            break;
+
+          case PROTO_IIFV:
+            {
+              GLfloat v[4];
+              v[0] = av[2].f;
+              v[1] = av[3].f;
+              v[2] = av[4].f;
+              v[3] = av[5].f;
+              LOG7 ("  call %-12s %s %-8s %3.1f %3.1f %3.1f %3.1f", F->name,
+                    mode_desc (av[0].i), mode_desc (av[1].i), 
+                    av[2].f, av[3].f, av[4].f, av[5].f);
+              ((void (*) (int, int, const GLfloat *)) fn) 
+                (av[0].i, av[1].i, v);
+            }
+            break;
+
+          case PROTO_IIV:
+            {
+              int v[4];
+              v[0] = av[1].i;
+              v[1] = av[2].i;
+              v[2] = av[3].i;
+              v[3] = av[4].i;
+              LOG6 ("  call %-12s %s %3d %3d %3d %3d", F->name, 
+                    mode_desc (av[0].i),
+                    av[1].i, av[2].i, av[3].i, av[4].i);
+              ((void (*) (int, const int *)) fn) (av[0].i, v);
+            }
+            break;
+
+          case PROTO_IIIV:
+            {
+              int v[4];
+              v[0] = av[2].i;
+              v[1] = av[3].i;
+              v[2] = av[4].i;
+              v[3] = av[5].i;
+              LOG7 ("  call %-12s %s %-8s %3d %3d %3d %3d", F->name,
+                    mode_desc (av[0].i), mode_desc (av[1].i), 
+                    av[2].i, av[3].i, av[4].i, av[5].i);
+              ((void (*) (int, int, const int *)) fn) 
+                (av[0].i, av[1].i, v);
+            }
+            break;
+
+          case PROTO_ARRAYS:
+            restore_arrays (F, av[1].i + av[2].i);
+            goto III;
+            break;
+
+          case PROTO_FV16:
+            {
+              GLfloat m[16];
+              int i;
+              for (i = 0; i < countof(m); i++)
+                m[i] = av[i].f;
+              LOG17 ("  call %-12s ["
+                     "%8.3f %8.3f %8.3f %8.3f "        "\n\t\t\t       "
+                     "%8.3f %8.3f %8.3f %8.3f "        "\n\t\t\t       "
+                     "%8.3f %8.3f %8.3f %8.3f "        "\n\t\t\t       "
+                     "%8.3f %8.3f %8.3f %8.3f ]",
+                     F->name,
+                     m[0],  m[1],  m[2],  m[3],
+                     m[4],  m[5],  m[6],  m[7],
+                     m[8],  m[9],  m[10], m[11],
+                     m[12], m[13], m[14], m[15]);
+              ((void (*) (GLfloat *)) fn) (m);
+            }
+            break;
+
+          default:
+            Assert (0, "bogus prototype");
+            break;
+          }
+        }
+
+      LOG1 ("glCallList %d done\n", id);
+
+      state->replaying_list--;
+      Assert (state->replaying_list >= 0, "glCallList corrupted");
+    }
+}
+
+
+/* When we save a call to glDrawArrays into a display list, we also need to
+   save the prevailing copy of the arrays that it will use, and restore them
+   later.
+ */
+static void
+save_arrays (list_fn *F, int count)
+{
+  int i = 0;
+  draw_array *A = (draw_array *) calloc (4, sizeof (*A));
+  Assert (A, "out of memory");
+
+/*  if (state->set.count > 0) */
+    {
+      jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A[i].binding);
+      jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_SIZE,    &A[i].size);
+      jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_TYPE,    &A[i].type);
+      jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_STRIDE,  &A[i].stride);
+      jwzgles_glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A[i].data);
+      CHECK("glGetPointerv");
+      copy_array_data (&A[i], count, "vert");
+    }
+
+  i++;
+  if (state->set.ncount > 1)
+    {
+      A[i].size = 3;
+      jwzgles_glGetIntegerv (GL_NORMAL_ARRAY_BUFFER_BINDING, &A[i].binding);
+      jwzgles_glGetIntegerv (GL_NORMAL_ARRAY_TYPE,    &A[i].type);
+      jwzgles_glGetIntegerv (GL_NORMAL_ARRAY_STRIDE,  &A[i].stride);
+      jwzgles_glGetPointerv (GL_NORMAL_ARRAY_POINTER, &A[i].data);
+      CHECK("glGetPointerv");
+      copy_array_data (&A[i], count, "norm");
+    }
+
+  i++;
+  if (state->set.tcount > 1)
+    {
+      jwzgles_glGetIntegerv (GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, &A[i].binding);
+      jwzgles_glGetIntegerv (GL_TEXTURE_COORD_ARRAY_SIZE,    &A[i].size);
+      jwzgles_glGetIntegerv (GL_TEXTURE_COORD_ARRAY_TYPE,    &A[i].type);
+      jwzgles_glGetIntegerv (GL_TEXTURE_COORD_ARRAY_STRIDE,  &A[i].stride);
+      jwzgles_glGetPointerv (GL_TEXTURE_COORD_ARRAY_POINTER, &A[i].data);
+      CHECK("glGetPointerv");
+      copy_array_data (&A[i], count, "tex ");
+    }
+
+  i++;
+  if (state->set.ccount > 1)
+    {
+      jwzgles_glGetIntegerv (GL_COLOR_ARRAY_BUFFER_BINDING, &A[i].binding);
+      jwzgles_glGetIntegerv (GL_COLOR_ARRAY_SIZE,    &A[i].size);
+      jwzgles_glGetIntegerv (GL_COLOR_ARRAY_TYPE,    &A[i].type);
+      jwzgles_glGetIntegerv (GL_COLOR_ARRAY_STRIDE,  &A[i].stride);
+      jwzgles_glGetPointerv (GL_COLOR_ARRAY_POINTER, &A[i].data);
+      CHECK("glGetPointerv");
+      copy_array_data (&A[i], count, "col ");
+    }
+
+  /* Freed by glDeleteLists. */
+
+  Assert (!F->arrays, "save_arrays corrupted");
+  F->arrays = A;
+}
+
+
+#ifdef DEBUG
+
+static void
+dump_array_data (draw_array *A, int count,
+                 const char *action, const char *name, const void *old)
+{
+  int bytes = count * A->stride;
+
+  if (A->binding)
+    {
+      fprintf (stderr, 
+               "jwzgles:     %s %s %d %s %2d, %4d = %5d   bind %d @ %d\n", 
+               action, name,
+               A->size, mode_desc(A->type), A->stride, 
+               count, bytes, A->binding, (int) A->data);
+    }
+  else
+    {
+      Assert (bytes == A->bytes, "array data corrupted");
+
+      fprintf (stderr, "jwzgles:     %s %s %d %s %2d, %4d = %5d @ %lX", 
+               action, name,
+               A->size, mode_desc(A->type), A->stride, 
+               count, bytes, (unsigned long) A->data);
+      if (old)
+        fprintf (stderr, " / %lX", (unsigned long) old);
+      fprintf (stderr, "\n");
+    }
+
+  if (A->binding)
+    {
+      Assert (((unsigned long) A->binding < 0xFFFF),
+              "buffer binding should be a numeric index,"
+              " but looks like a pointer");
+
+# if 0
+      /* glGetBufferSubData doesn't actually exist in OpenGLES, but this
+         was helpful for debugging on real OpenGL... */
+      GLfloat *d;
+      int i;
+      fprintf (stderr, "jwzgles: read back:\n");
+      d = (GLfloat *) malloc (A->bytes);
+      glGetBufferSubData (GL_ARRAY_BUFFER, (int) A->data,
+                          count * A->stride, (void *) d);
+      CHECK("glGetBufferSubData");
+      for (i = 0; i < count * A->size; i++)
+        {
+          if (i % 4 == 0)
+            fprintf (stderr, "\njwzgles:    %4d: ", 
+                     i + (int) A->data / sizeof(GLfloat));
+          fprintf (stderr, " %7.3f", d[i]);
+        }
+      fprintf (stderr, "\n");
+      free (d);
+# endif
+    }
+# if 0
+  else
+    {
+      unsigned char *b = (unsigned char *) A->data;
+      int i;
+      if ((unsigned long) A->data < 0xFFFF)
+        {
+          Assert (0, "buffer data not a pointer");
+          return;
+        }
+      for (i = 0; i < count; i++)
+        {
+          int j;
+          GLfloat *f = (GLfloat *) b;
+          int s = A->size;
+          if (s == 0) s = 3;  /* normals */
+          fprintf (stderr, "jwzgles:    ");
+          for (j = 0; j < s; j++)
+            fprintf (stderr, " %7.3f", f[j]);
+          fprintf (stderr, "\n");
+          b += A->stride;
+        }
+    }
+# endif
+}
+
+static void
+dump_direct_array_data (int count)
+{
+  draw_array A = { 0, };
+
+  if (jwzgles_glIsEnabled (GL_VERTEX_ARRAY))
+    {
+      jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A.binding);
+      jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_SIZE,    &A.size);
+      jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_TYPE,    &A.type);
+      jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_STRIDE,  &A.stride);
+      jwzgles_glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A.data);
+      A.bytes = count * A.stride;
+      dump_array_data (&A, count, "direct", "vertex ", 0);
+    }
+  if (jwzgles_glIsEnabled (GL_NORMAL_ARRAY))
+    {
+      A.size = 0;
+      jwzgles_glGetIntegerv (GL_NORMAL_ARRAY_BUFFER_BINDING, &A.binding);
+      jwzgles_glGetIntegerv (GL_NORMAL_ARRAY_TYPE,    &A.type);
+      jwzgles_glGetIntegerv (GL_NORMAL_ARRAY_STRIDE,  &A.stride);
+      jwzgles_glGetPointerv (GL_NORMAL_ARRAY_POINTER, &A.data);
+      A.bytes = count * A.stride;
+      dump_array_data (&A, count, "direct", "normal ", 0);
+    }
+  if (jwzgles_glIsEnabled (GL_TEXTURE_COORD_ARRAY))
+    {
+      jwzgles_glGetIntegerv (GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, &A.binding);
+      jwzgles_glGetIntegerv (GL_TEXTURE_COORD_ARRAY_SIZE,    &A.size);
+      jwzgles_glGetIntegerv (GL_TEXTURE_COORD_ARRAY_TYPE,    &A.type);
+      jwzgles_glGetIntegerv (GL_TEXTURE_COORD_ARRAY_STRIDE,  &A.stride);
+      jwzgles_glGetPointerv (GL_TEXTURE_COORD_ARRAY_POINTER, &A.data);
+      A.bytes = count * A.stride;
+      dump_array_data (&A, count, "direct", "texture", 0);
+    }
+  if (jwzgles_glIsEnabled (GL_COLOR_ARRAY))
+    {
+      jwzgles_glGetIntegerv (GL_COLOR_ARRAY_BUFFER_BINDING, &A.binding);
+      jwzgles_glGetIntegerv (GL_COLOR_ARRAY_SIZE,    &A.size);
+      jwzgles_glGetIntegerv (GL_COLOR_ARRAY_TYPE,    &A.type);
+      jwzgles_glGetIntegerv (GL_COLOR_ARRAY_STRIDE,  &A.stride);
+      jwzgles_glGetPointerv (GL_COLOR_ARRAY_POINTER, &A.data);
+      A.bytes = count * A.stride;
+      dump_array_data (&A, count, "direct", "color ", 0);
+    }
+}
+
+#endif /* DEBUG */
+
+
+static void
+copy_array_data (draw_array *A, int count, const char *name)
+{
+  /* Instead of just memcopy'ing the whole array and obeying its previous
+     'stride' value, we make up a more compact array.  This is because if
+     the same array data is being used with multiple component types,
+     e.g. with glInterleavedArrays, we don't want to copy all of the
+     data multiple times.
+   */
+  int stride2, bytes, i, j;
+  void *data2;
+  const GLfloat *IF;
+  GLfloat *OF;
+  const unsigned char *IB;
+  unsigned char *OB;
+
+  if (((unsigned long) A->data) < 0xFFFF)
+    {
+      Assert (0, "buffer data not a pointer");
+      return;
+    }
+
+  Assert (A->size >= 2 && A->size <= 4, "bogus array size");
+
+  switch (A->type) {
+  case GL_FLOAT:         stride2 = A->size * sizeof(GLfloat); break;
+  case GL_UNSIGNED_BYTE: stride2 = A->size; break;
+  default: Assert (0, "bogus array type"); break;
+  }
+
+  bytes = count * stride2;
+  Assert (bytes > 0, "bogus array count or stride");
+  Assert (A->data, "missing array data");
+  data2 = (void *) malloc (bytes);
+  Assert (data2, "out of memory");
+
+  IB = (const unsigned char *) A->data;
+  OB = (unsigned char *) data2;
+  IF = (const GLfloat *) A->data;
+  OF = (GLfloat *) data2;
+
+  switch (A->type) {
+  case GL_FLOAT:
+    for (i = 0; i < count; i++)
+      {
+        for (j = 0; j < A->size; j++)
+          *OF++ = IF[j];
+        IF = (const GLfloat *) (((const unsigned char *) IF) + A->stride);
+      }
+    break;
+  case GL_UNSIGNED_BYTE:
+    for (i = 0; i < count; i++)
+      {
+        for (j = 0; j < A->size; j++)
+          *OB++ = IB[j];
+        IB += A->stride;
+      }
+    break;
+  default:
+    Assert (0, "bogus array type");
+    break;
+  }
+
+  A->data = data2;
+  A->bytes = bytes;
+  A->stride = stride2;
+
+# ifdef DEBUG
+  dump_array_data (A, count, "saved", name, 0);
+# endif
+}
+
+
+static void
+restore_arrays (list_fn *F, int count)
+{
+  int i = 0;
+  draw_array *A = F->arrays;
+  Assert (A, "missing array");
+
+  for (i = 0; i < 4; i++)
+    {
+      const char *name = 0;
+
+      if (!A[i].size)
+        continue;
+
+      Assert ((A[i].binding || A[i].data),
+              "array has neither buffer binding nor data");
+
+      glBindBuffer (GL_ARRAY_BUFFER, A[i].binding);
+      CHECK("glBindBuffer");
+
+      switch (i) {
+      case 0: jwzgles_glVertexPointer  (A[i].size, A[i].type, A[i].stride, A[i].data);
+        name = "vertex ";
+        CHECK("glVertexPointer");
+        break;
+      case 1: jwzgles_glNormalPointer  (           A[i].type, A[i].stride, A[i].data);
+        name = "normal ";
+        CHECK("glNormalPointer");
+        break;
+      case 2: jwzgles_glTexCoordPointer(A[i].size, A[i].type, A[i].stride, A[i].data);
+        name = "texture";
+        CHECK("glTexCoordPointer");
+        break;
+      case 3: jwzgles_glColorPointer   (A[i].size, A[i].type, A[i].stride, A[i].data);
+        name = "color  ";
+        CHECK("glColorPointer");
+        break;
+      default: Assert (0, "wat"); break;
+      }
+
+# ifdef DEBUG
+      dump_array_data (&A[i], count, "restored", name, 0);
+# endif
+      (void)name;
+    }
+
+  glBindBuffer (GL_ARRAY_BUFFER, 0);    /* Keep out of others' hands */
+}
+
+
+void
+jwzgles_glDrawArrays (GLuint mode, GLuint first, GLuint count)
+{
+  /* If we are auto-generating texture coordinates, do that now, after
+     the vertex array was installed, but before drawing, This happens
+     when recording into a list, or in direct mode.  It must happen
+     before calling optimize_arrays() from glEndList().
+   */
+  if (! state->replaying_list &&
+      ((state->compiling_list ? state->list_enabled : state->enabled)
+       & (ISENABLED_TEXTURE_GEN_S | ISENABLED_TEXTURE_GEN_T |
+          ISENABLED_TEXTURE_GEN_R | ISENABLED_TEXTURE_GEN_Q)))
+    generate_texture_coords (first, count);
+
+  if (state->compiling_list)
+    {
+      void_int vv[3];
+      vv[0].i = mode;
+      vv[1].i = first;
+      vv[2].i = count;
+      list_push ("glDrawArrays", (list_fn_cb) &jwzgles_glDrawArrays,
+                 PROTO_ARRAYS, vv);
+    }
+  else
+    {
+# ifdef DEBUG
+      if (! state->replaying_list) {
+        LOG4("direct %-12s %d %d %d", "glDrawArrays", mode, first, count);
+        dump_direct_array_data (first + count);
+      }
+# endif
+      glDrawArrays (mode, first, count);  /* the real one */
+      CHECK("glDrawArrays");
+    }
+}
+
+
+void
+jwzgles_glInterleavedArrays (GLenum format, GLsizei stride, const void *data)
+{
+  /* We can implement this by calling the various *Pointer functions
+     with offsets into the same data, taking advantage of stride.
+   */
+  const unsigned char *c = (const unsigned char *) data;
+# define B 1
+# define F sizeof(GLfloat)
+
+  Assert (!state->compiling_verts,
+          "glInterleavedArrays not allowed inside glBegin");
+
+  jwzgles_glEnableClientState (GL_VERTEX_ARRAY);
+
+  if (!state->replaying_list)
+    LOG4 ("%sglInterleavedArrays %s %d %lX", 
+          (state->compiling_list || state->replaying_list ? "  " : ""),
+          mode_desc (format), stride, (unsigned long) data);
+
+  switch (format) {
+  case GL_V2F:
+    jwzgles_glVertexPointer (2, GL_FLOAT, stride, c);
+    CHECK("glVertexPointer");
+    if (!state->replaying_list)
+      LOG3 ("%s  -> glVertexPointer 2 FLOAT %d %lX", 
+            (state->compiling_list || state->replaying_list ? "  " : ""),
+            stride, (unsigned long) c);
+    break;
+  case GL_V3F:
+    jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
+    CHECK("glVertexPointer");
+    if (!state->replaying_list)
+      LOG3 ("%s  -> glVertexPointer 3 FLOAT %d %lX", 
+            (state->compiling_list || state->replaying_list ? "  " : ""),
+            stride, (unsigned long) c);
+    break;
+  case GL_C4UB_V2F:    
+    if (stride == 0)
+      stride = 4*B + 2*F;
+    jwzgles_glEnableClientState (GL_COLOR_ARRAY);
+    jwzgles_glColorPointer (4, GL_UNSIGNED_BYTE, stride, c);
+    CHECK("glColorPointer");
+    c += 4*B;  /* #### might be incorrect float-aligned address */
+    jwzgles_glVertexPointer (2, GL_FLOAT, stride, c);
+    break;
+  case GL_C4UB_V3F:
+    if (stride == 0)
+      stride = 4*B + 3*F;
+    jwzgles_glEnableClientState (GL_COLOR_ARRAY);
+    jwzgles_glColorPointer (4, GL_UNSIGNED_BYTE, stride, c);
+    CHECK("glColorPointer");
+    c += 4*B;
+    jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
+    CHECK("glVertexPointer");
+    break;
+  case GL_C3F_V3F:
+    if (stride == 0)
+      stride = 3*F + 3*F;
+    jwzgles_glEnableClientState (GL_COLOR_ARRAY);
+    jwzgles_glColorPointer (3, GL_FLOAT, stride, c);
+    CHECK("glColorPointer");
+    c += 3*F;
+    jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
+    CHECK("glVertexPointer");
+    break;
+  case GL_N3F_V3F:
+    if (stride == 0)
+      stride = 3*F + 3*F;
+    jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
+    jwzgles_glNormalPointer (GL_FLOAT, stride, c);
+    CHECK("glNormalPointer");
+    if (!state->replaying_list)
+      LOG3 ("%s  -> glNormalPointer   FLOAT %d %lX", 
+            (state->compiling_list || state->replaying_list ? "  " : ""),
+            stride, (unsigned long) c);
+    c += 3*F;
+    jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
+    CHECK("glVertexPointer");
+    if (!state->replaying_list)
+      LOG3 ("%s  -> glVertexPointer 3 FLOAT %d %lX", 
+            (state->compiling_list || state->replaying_list ? "  " : ""),
+            stride, (unsigned long) c);
+    break;
+  case GL_C4F_N3F_V3F:
+    if (stride == 0)
+      stride = 4*F + 3*F + 3*F;
+    jwzgles_glEnableClientState (GL_COLOR_ARRAY);
+    jwzgles_glColorPointer (4, GL_FLOAT, stride, c);
+    CHECK("glColorPointer");
+    c += 4*F;
+    jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
+    jwzgles_glNormalPointer (GL_FLOAT, stride, c);
+    CHECK("glNormalPointer");
+    c += 3*F;
+    jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
+    CHECK("glVertexPointer");
+    break;
+  case GL_T2F_V3F:
+    if (stride == 0)
+      stride = 2*F + 3*F;
+    jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+    jwzgles_glTexCoordPointer (2, GL_FLOAT, stride, c);
+    CHECK("glTexCoordPointer");
+    c += 2*F;
+    jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
+    CHECK("glVertexPointer");
+    break;
+  case GL_T4F_V4F:
+    if (stride == 0)
+      stride = 4*F + 4*F;
+    jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+    jwzgles_glTexCoordPointer (4, GL_FLOAT, stride, c);
+    CHECK("glTexCoordPointer");
+    c += 4*F;
+    jwzgles_glVertexPointer (4, GL_FLOAT, stride, c);
+    CHECK("glVertexPointer");
+    break;
+  case GL_T2F_C4UB_V3F:
+    if (stride == 0)
+      stride = 2*F + 4*B + 3*F;
+    jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+    jwzgles_glTexCoordPointer (2, GL_FLOAT, stride, c);
+    CHECK("glTexCoordPointer");
+    c += 2*F;
+    jwzgles_glEnableClientState (GL_COLOR_ARRAY);
+    jwzgles_glColorPointer  (4, GL_UNSIGNED_BYTE, stride, c);
+    CHECK("glColorPointer");
+    c += 4*B;
+    jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
+    CHECK("glVertexPointer");
+    break;
+  case GL_T2F_C3F_V3F:
+    if (stride == 0)
+      stride = 2*F + 3*F + 3*F;
+    jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+    jwzgles_glTexCoordPointer (2, GL_FLOAT, stride, c);
+    CHECK("glTexCoordPointer");
+    c += 2*F;
+    jwzgles_glEnableClientState (GL_COLOR_ARRAY);
+    jwzgles_glColorPointer  (3, GL_FLOAT, stride, c);
+    CHECK("glColorPointer");
+    c += 3*F;
+    jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
+    CHECK("glVertexPointer");
+    break;
+  case GL_T2F_N3F_V3F:
+    if (stride == 0)
+      stride = 2*F + 3*F + 3*F;
+    jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+    jwzgles_glTexCoordPointer (2, GL_FLOAT, stride, c);
+    CHECK("glTexCoordPointer");
+    c += 2*F;
+    jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
+    jwzgles_glNormalPointer (GL_FLOAT, stride, c);
+    CHECK("glNormalPointer");
+    c += 3*F;
+    jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
+    CHECK("glVertexPointer");
+    break;
+  case GL_T2F_C4F_N3F_V3F:
+    if (stride == 0)
+      stride = 2*F + 4*F + 3*F + 3*F;
+    jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+    jwzgles_glTexCoordPointer (2, GL_FLOAT, stride, c);
+    CHECK("glTexCoordPointer");
+    c += 2*F;
+    jwzgles_glEnableClientState (GL_COLOR_ARRAY);
+    jwzgles_glColorPointer  (3, GL_FLOAT, stride, c);
+    CHECK("glColorPointer");
+    c += 3*F;
+    jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
+    jwzgles_glNormalPointer (GL_FLOAT, stride, c);
+    CHECK("glNormalPointer");
+    c += 3*F;
+    jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
+    CHECK("glVertexPointer");
+    break;
+  case GL_T4F_C4F_N3F_V4F:
+    if (stride == 0)
+      stride = 4*F + 4*F + 3*F + 4*F;
+    jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+    jwzgles_glTexCoordPointer (4, GL_FLOAT, stride, c);
+    CHECK("glTexCoordPointer");
+    c += 4*F;
+    jwzgles_glEnableClientState (GL_COLOR_ARRAY);
+    jwzgles_glColorPointer  (4, GL_FLOAT, stride, c);
+    CHECK("glColorPointer");
+    c += 4*F;
+    jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
+    jwzgles_glNormalPointer (GL_FLOAT, stride, c);
+    CHECK("glNormalPointer");
+    c += 3*F;
+    jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
+    CHECK("glVertexPointer");
+    break;
+  default:
+    Assert (0, "glInterleavedArrays: bogus format");
+    break;
+  }
+
+# undef B
+# undef F
+}
+
+
+
+void
+jwzgles_glMultMatrixf (const GLfloat *m)
+{
+  Assert (!state->compiling_verts,
+          "glMultMatrixf not allowed inside glBegin");
+  if (state->compiling_list)
+    {
+      void_int vv[16];
+      int i;
+      for (i = 0; i < countof(vv); i++)
+        vv[i].f = m[i];
+      list_push ("glMultMatrixf", (list_fn_cb) &jwzgles_glMultMatrixf,
+                 PROTO_FV16, vv);
+    }
+  else
+    {
+      if (! state->replaying_list)
+        LOG1 ("direct %-12s", "glMultMatrixf");
+      glMultMatrixf (m);  /* the real one */
+      CHECK("glMultMatrixf");
+    }
+}
+
+
+void
+jwzgles_glClearIndex(GLfloat c)
+{
+  /* Does GLES even do indexed color? */
+  Assert (0, "glClearIndex unimplemented");
+}
+
+
+void
+jwzgles_glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig,
+                  GLfloat xmove, GLfloat ymove, const GLubyte *bitmap)
+{
+  Assert (0, "glBitmap unimplemented");
+}
+
+void
+jwzgles_glPushAttrib(int flags)
+{
+  Assert (0, "glPushAttrib unimplemented");
+}
+
+void
+jwzgles_glPopAttrib(void)
+{
+  Assert (0, "glPopAttrib unimplemented");
+}
+
+
+/* These are needed for object hit detection in pinion.
+   Might need to rewrite that code entirely.  Punt for now.
+ */
+void
+jwzgles_glInitNames (void)
+{
+/*  Assert (0, "glInitNames unimplemented");*/
+}
+
+void
+jwzgles_glPushName (GLuint name)
+{
+/*  Assert (0, "glPushName unimplemented");*/
+}
+
+GLuint
+jwzgles_glPopName (void)
+{
+/*  Assert (0, "glPopName unimplemented");*/
+  return 0;
+}
+
+GLuint
+jwzgles_glRenderMode (GLuint mode)
+{
+/*  Assert (0, "glRenderMode unimplemented");*/
+  return 0;
+}
+
+void
+jwzgles_glSelectBuffer (GLsizei size, GLuint *buf)
+{
+/*  Assert (0, "glSelectBuffer unimplemented");*/
+}
+
+
+void
+jwzgles_glGenTextures (GLuint n, GLuint *ret)
+{
+  Assert (!state->compiling_verts,
+          "glGenTextures not allowed inside glBegin");
+  /* technically legal, but stupid! */
+  Assert (!state->compiling_list,
+          "glGenTextures not allowed inside glNewList");
+  if (! state->replaying_list)
+    LOG1 ("direct %-12s", "glGenTextures");
+  glGenTextures (n, ret);  /* the real one */
+  CHECK("glGenTextures");
+}
+
+
+/* return the next larger power of 2. */
+static int
+to_pow2 (int value)
+{
+  int i = 1;
+  while (i < value) i <<= 1;
+  return i;
+}
+
+void
+jwzgles_glTexImage1D (GLenum target, GLint level,
+                      GLint internalFormat,
+                      GLsizei width, GLint border,
+                      GLenum format, GLenum type,
+                      const GLvoid *data)
+{
+  Assert (!state->compiling_verts, "glTexImage1D not allowed inside glBegin");
+  /* technically legal, but stupid! */
+  Assert (!state->compiling_list, "glTexImage1D inside glNewList");
+  Assert (width  == to_pow2(width), "width must be a power of 2");
+
+  if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D;
+  jwzgles_glTexImage2D (target, level, internalFormat, width, 1,
+                        border, format, type, data);
+}
+
+void
+jwzgles_glTexImage2D (GLenum target,
+                      GLint    level,
+                      GLint    internalFormat,
+                      GLsizei          width,
+                      GLsizei          height,
+                      GLint    border,
+                      GLenum   format,
+                      GLenum   type,
+                      const GLvoid *data)
+{
+  GLvoid *d2 = (GLvoid *) data;
+  Assert (!state->compiling_verts, "glTexImage2D not allowed inside glBegin");
+  Assert (!state->compiling_list,  /* technically legal, but stupid! */
+          "glTexImage2D not allowed inside glNewList");
+
+  Assert (width  == to_pow2(width),   "width must be a power of 2");
+  Assert (height == to_pow2(height), "height must be a power of 2");
+
+  /* OpenGLES no longer supports "4" as a synonym for "RGBA". */
+  switch (internalFormat) {
+  case 1: internalFormat = GL_LUMINANCE; break;
+  case 2: internalFormat = GL_LUMINANCE_ALPHA; break;
+  case 3: internalFormat = GL_RGB; break;
+  case 4: internalFormat = GL_RGBA; break;
+  }
+
+  /* GLES does not let us omit the data pointer to create a blank texture. */
+  if (! data)
+    {
+      d2 = (GLvoid *) calloc (1, width * height * sizeof(GLfloat) * 4);
+      Assert (d2, "out of memory");
+    }
+
+  if (internalFormat == GL_RGB && format == GL_RGBA)
+    internalFormat = GL_RGBA;  /* WTF */
+  if (type == GL_UNSIGNED_INT_8_8_8_8_REV)
+    type = GL_UNSIGNED_BYTE;
+
+  if (! state->replaying_list)
+    LOG10 ("direct %-12s %s %d %s %d %d %d %s %s 0x%lX", "glTexImage2D", 
+           mode_desc(target), level, mode_desc(internalFormat),
+           width, height, border, mode_desc(format), mode_desc(type),
+           (unsigned long) d2);
+  glTexImage2D (target, level, internalFormat, width, height, border,
+                format, type, d2);  /* the real one */
+  CHECK("glTexImage2D");
+
+  if (d2 != data) free (d2);
+}
+
+void
+jwzgles_glTexSubImage2D (GLenum target, GLint level,
+                         GLint xoffset, GLint yoffset,
+                         GLsizei width, GLsizei height,
+                         GLenum format, GLenum type,
+                         const GLvoid *pixels)
+{
+  Assert (!state->compiling_verts,
+          "glTexSubImage2D not allowed inside glBegin");
+  Assert (!state->compiling_list,   /* technically legal, but stupid! */
+          "glTexSubImage2D not allowed inside glNewList");
+
+  if (! state->replaying_list)
+    LOG10 ("direct %-12s %s %d %d %d %d %d %s %s 0x%lX", "glTexSubImage2D", 
+           mode_desc(target), level, xoffset, yoffset, width, height,
+           mode_desc (format), mode_desc (type), (unsigned long) pixels);
+  glTexSubImage2D (target, level, xoffset, yoffset, width, height,
+                   format, type, pixels);  /* the real one */
+  CHECK("glTexSubImage2D");
+}
+
+void
+jwzgles_glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat,
+                          GLint x, GLint y, GLsizei width, GLsizei height,
+                          GLint border)
+{
+  Assert (!state->compiling_verts, 
+          "glCopyTexImage2D not allowed inside glBegin");
+  Assert (!state->compiling_list,    /* technically legal, but stupid! */
+          "glCopyTexImage2D not allowed inside glNewList");
+  if (! state->replaying_list)
+    LOG9 ("direct %-12s %s %d %s %d %d %d %d %d", "glCopyTexImage2D", 
+          mode_desc(target), level, mode_desc(internalformat),
+          x, y, width, height, border);
+  glCopyTexImage2D (target, level, internalformat, x, y, width, height,
+                    border);  /* the real one */
+  CHECK("glCopyTexImage2D");
+}
+
+
+/* OpenGLES doesn't have auto texture-generation at all!
+   "Oh, just rewrite that code to use GPU shaders", they say.
+   How fucking convenient.
+ */
+void
+jwzgles_glTexGenfv (GLenum coord, GLenum pname, const GLfloat *params)
+{
+  texgen_state *s;
+
+  if (pname == GL_TEXTURE_GEN_MODE)
+    LOG5 ("%sdirect %-12s %s %s %s", 
+          (state->compiling_list || state->replaying_list ? "  " : ""),
+          "glTexGenfv",
+          mode_desc(coord), mode_desc(pname), mode_desc(params[0]));
+  else
+    LOG8 ("%sdirect %-12s %s %s %3.1f %3.1f %3.1f %3.1f",
+          (state->compiling_list || state->replaying_list ? "  " : ""),
+          "glTexGenfv",
+          mode_desc(coord), mode_desc(pname),
+          params[0], params[1], params[2], params[3]);
+
+  switch (coord) {
+  case GL_S: s = &state->s; break;
+  case GL_T: s = &state->t; break;
+  case GL_R: s = &state->r; break;
+  case GL_Q: s = &state->q; break;
+  default: Assert (0, "glGetTexGenfv: unknown coord"); break;
+  }
+
+  switch (pname) {
+  case GL_TEXTURE_GEN_MODE: s->mode = params[0]; break;
+  case GL_OBJECT_PLANE:     memcpy (s->obj, params, sizeof(s->obj)); break;
+  case GL_EYE_PLANE:        memcpy (s->eye, params, sizeof(s->eye)); break;
+  default: Assert (0, "glTexGenfv: unknown pname"); break;
+  }
+}
+
+void
+jwzgles_glTexGeni (GLenum coord, GLenum pname, GLint param)
+{
+  GLfloat v = param;
+  jwzgles_glTexGenfv (coord, pname, &v);
+}
+
+void
+jwzgles_glGetTexGenfv (GLenum coord, GLenum pname, GLfloat *params)
+{
+  texgen_state *s;
+
+  switch (coord) {
+  case GL_S: s = &state->s; break;
+  case GL_T: s = &state->t; break;
+  case GL_R: s = &state->r; break;
+  case GL_Q: s = &state->q; break;
+  default: Assert (0, "glGetTexGenfv: unknown coord"); break;
+  }
+
+  switch (pname) {
+  case GL_TEXTURE_GEN_MODE: params[0] = s->mode; break;
+  case GL_OBJECT_PLANE:     memcpy (params, s->obj, sizeof(s->obj)); break;
+  case GL_EYE_PLANE:        memcpy (params, s->eye, sizeof(s->eye)); break;
+  default: Assert (0, "glGetTexGenfv: unknown pname"); break;
+  }
+
+  if (pname == GL_TEXTURE_GEN_MODE)
+    LOG5 ("%sdirect %-12s %s %s -> %s", 
+          (state->compiling_list || state->replaying_list ? "  " : ""),
+          "glGetTexGenfv",
+          mode_desc(coord), mode_desc(pname), mode_desc(params[0]));
+  else
+    LOG8 ("%sdirect %-12s %s %s -> %3.1f %3.1f %3.1f %3.1f",
+          (state->compiling_list || state->replaying_list ? "  " : ""),
+          "glGetTexGenfv",
+          mode_desc(coord), mode_desc(pname),
+          params[0], params[1], params[2], params[3]);
+}
+
+
+static GLfloat
+dot_product (int rank, GLfloat *a, GLfloat *b)
+{
+  /* A dot B  =>  (A[1] * B[1]) + ... + (A[n] * B[n]) */
+  GLfloat ret = 0;
+  int i;
+  for (i = 0; i < rank; i++) 
+    ret += a[i] * b[i];
+  return ret;
+}
+
+
+
+/* Compute the texture coordinates of the prevailing list of verts as per
+   http://www.opengl.org/wiki/Mathematics_of_glTexGen
+ */
+static void
+generate_texture_coords (GLuint first, GLuint count)
+{
+  GLfloat *tex_out, *tex_array;
+  GLsizei tex_stride;
+  GLuint i;
+  draw_array A = { 0, };
+  char *verts_in;
+
+  struct { GLuint which, flag, mode; GLfloat plane[4]; } tg[4] = {
+    { GL_S, ISENABLED_TEXTURE_GEN_S, 0, { 0, } },
+    { GL_T, ISENABLED_TEXTURE_GEN_T, 0, { 0, } },
+    { GL_R, ISENABLED_TEXTURE_GEN_R, 0, { 0, } },
+    { GL_Q, ISENABLED_TEXTURE_GEN_Q, 0, { 0, }}};
+                                                    
+  int tcoords = 0;
+
+  /* Read the texture plane configs that were stored with glTexGen.
+   */
+  for (i = 0; i < countof(tg); i++)
+    {
+      GLfloat mode = 0;
+      if (! ((state->compiling_list ? state->list_enabled : state->enabled)
+             & tg[i].flag))
+        continue;
+      jwzgles_glGetTexGenfv (tg[i].which, GL_TEXTURE_GEN_MODE, &mode);
+      jwzgles_glGetTexGenfv (tg[i].which, GL_OBJECT_PLANE, tg[i].plane);
+      tg[i].mode = mode;
+      tcoords++;
+    }
+
+  if (tcoords == 0) return;  /* Nothing to do! */
+
+
+  /* Make the array to store our texture coords in. */
+
+  tex_stride = tcoords * sizeof(GLfloat);
+  tex_array = (GLfloat *) calloc (first + count, tex_stride);
+  tex_out = tex_array;
+
+
+  /* Read the prevailing vertex array, that was stored with
+     glVertexPointer or glInterleavedArrays.
+   */
+  jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A.binding);
+  jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_SIZE,    &A.size);
+  jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_TYPE,    &A.type);
+  jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_STRIDE,  &A.stride);
+  jwzgles_glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A.data);
+  A.bytes = count * A.stride;
+
+  verts_in = (char *) A.data;
+
+  /* Iterate over each vertex we're drawing.
+     We just skip the ones < start, but the tex array has
+     left room for zeroes there anyway.
+   */
+  for (i = first; i < first + count; i++)
+    {
+      GLfloat vert[4] = { 0, };
+      int j, k;
+
+      /* Extract this vertex into `vert' as a float, whatever its type was. */
+      for (j = 0; j < A.size; j++)
+        {
+          switch (A.type) {
+          case GL_SHORT:  vert[j] = ((GLshort *)  verts_in)[j]; break;
+          case GL_INT:    vert[j] = ((GLint *)    verts_in)[j]; break;
+          case GL_FLOAT:  vert[j] = ((GLfloat *)  verts_in)[j]; break;
+          case GL_DOUBLE: vert[j] = ((GLdouble *) verts_in)[j]; break;
+          default: Assert (0, "unknown vertex type"); break;
+          }
+        }
+
+      /* Compute the texture coordinate for this vertex.
+         For GL_OBJECT_LINEAR, these coordinates are static, and can go
+         into the display list.  But for GL_EYE_LINEAR, GL_SPHERE_MAP and
+         GL_REFLECTION_MAP, they depend on the prevailing ModelView matrix,
+         and so need to be computed afresh each time glDrawArrays is called.
+         Unfortunately, our verts and norms are gone by then, dumped down
+         into the VBO and discarded from CPU RAM.  Bleh.
+       */
+      for (j = 0, k = 0; j < countof(tg); j++)
+        {
+          if (! ((state->compiling_list ? state->list_enabled : state->enabled)
+                 & tg[j].flag))
+            continue;
+          switch (tg[j].mode) {
+          case GL_OBJECT_LINEAR:
+            tex_out[k] = dot_product (4, vert, tg[j].plane);
+            break;
+          default:
+            Assert (0, "unimplemented texture mode");
+            break;
+          }
+          k++;
+        }
+
+      /* fprintf (stderr, "%4d: V %-5.1f %-5.1f %-5.1f  T %-5.1f %-5.1f\n",
+               i, vert[0], vert[1], vert[2], tex_out[0], tex_out[1]); */
+
+      /* Move verts_in and tex_out forward to the next vertex by stride. */
+      verts_in += A.stride;
+      tex_out = (GLfloat *) (((char *) tex_out) + tex_stride);
+    }
+
+  jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+  jwzgles_glTexCoordPointer (tcoords, GL_FLOAT, tex_stride,
+                             (GLvoid *) tex_array);
+  free (tex_array);
+}
+
+
+int
+jwzgles_gluBuild2DMipmaps (GLenum target,
+                           GLint       internalFormat,
+                           GLsizei     width,
+                           GLsizei     height,
+                           GLenum      format,
+                           GLenum      type,
+                           const GLvoid *data)
+{
+  /* Not really bothering with mipmapping; only making one level.
+     Note that this required a corresponding hack in glTexParameterf().
+   */
+
+  int w2 = to_pow2(width);
+  int h2 = to_pow2(height);
+
+  void *d2 = (void *) data;
+
+  /* OpenGLES no longer supports "4" as a synonym for "RGBA". */
+  switch (internalFormat) {
+  case 1: internalFormat = GL_LUMINANCE; break;
+  case 2: internalFormat = GL_LUMINANCE_ALPHA; break;
+  case 3: internalFormat = GL_RGB; break;
+  case 4: internalFormat = GL_RGBA; break;
+  }
+
+/*  if (w2 < h2) w2 = h2;
+  if (h2 < w2) h2 = w2;*/
+
+  if (w2 != width || h2 != height)
+    {
+      /* Scale up the image bits to fit the power-of-2 texture.
+         We have to do this because the mipmap API assumes that
+         the texture bits go to texture coordinates 1.0 x 1.0.
+         This could be more efficient, but it doesn't happen often.
+      */
+      int istride = (format == GL_RGBA ? 4 : 3);
+      int ostride = 4;
+      int ibpl = istride * width;
+      int obpl = ostride * w2;
+      int oy;
+      const unsigned char *in = (unsigned char *) data;
+      unsigned char *out = (void *) malloc (h2 * obpl);
+      Assert (out, "out of memory");
+      d2 = out;
+
+      for (oy = 0; oy < h2; oy++)
+        {
+          int iy = oy * height / h2;
+          const unsigned char *iline = in  + (iy * ibpl);
+          unsigned char       *oline = out + (oy * obpl);
+          int ox;
+          for (ox = 0; ox < w2; ox++)
+            {
+              int ix = ox * width / w2;
+              const unsigned char *i = iline + (ix * istride);
+              unsigned char       *o = oline + (ox * ostride);
+              *o++ = *i++;  /* R */
+              *o++ = *i++;  /* G */
+              *o++ = *i++;  /* B */
+              *o++ = (istride == 4 ? *i : 0xFF); /* A */
+            }
+        }
+      // width  = w2;
+      // height = h2;
+      internalFormat = GL_RGBA;
+      format = GL_RGBA;
+    }
+
+  jwzgles_glTexImage2D (target, 0, internalFormat, w2, h2, 0, 
+                        format, type, d2);
+  if (d2 != data) free (d2);
+
+  return 0;
+}
+
+
+void
+jwzgles_glRectf (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
+{
+  jwzgles_glBegin (GL_POLYGON);
+  jwzgles_glVertex2f (x1, y1);
+  jwzgles_glVertex2f (x2, y1);
+  jwzgles_glVertex2f (x2, y2);
+  jwzgles_glVertex2f (x1, y2);
+  jwzgles_glEnd ();
+}
+
+void
+jwzgles_glRecti (GLint x1, GLint y1, GLint x2, GLint y2)
+{
+  jwzgles_glRectf (x1, y1, x2, y2);
+}
+
+void
+jwzgles_glClearDepth (GLfloat d)
+{
+  /* Not sure what to do here */
+  Assert (d == 1.0, "glClearDepth unimplemented");
+}
+
+
+/* When in immediate mode, we store a bit into state->enabled, and also
+   call the real glEnable() / glDisable().
+
+   When recording a list, we store a bit into state->list_enabled instead,
+   so that we can see what the prevailing enablement state will be when
+   the list is run.
+
+   set: 1 = set, -1 = clear, 0 = query.
+*/
+static int
+enable_disable (GLuint bit, int set)
+{
+  int result = (set > 0);
+  int omitp = 0;
+  int csp = 0;
+  unsigned long flag = 0;
+
+  switch (bit) {
+  case GL_TEXTURE_1D:     /* We implement 1D textures as 2D textures. */
+  case GL_TEXTURE_2D:     flag = ISENABLED_TEXTURE_2D;              break;
+  case GL_TEXTURE_GEN_S:  flag = ISENABLED_TEXTURE_GEN_S; omitp = 1; break;
+  case GL_TEXTURE_GEN_T:  flag = ISENABLED_TEXTURE_GEN_T; omitp = 1; break;
+  case GL_TEXTURE_GEN_R:  flag = ISENABLED_TEXTURE_GEN_R; omitp = 1; break;
+  case GL_TEXTURE_GEN_Q:  flag = ISENABLED_TEXTURE_GEN_Q; omitp = 1; break;
+  case GL_LIGHTING:       flag = ISENABLED_LIGHTING;                break;
+  case GL_BLEND:          flag = ISENABLED_BLEND;                   break;
+  case GL_DEPTH_TEST:     flag = ISENABLED_DEPTH_TEST;              break;
+  case GL_ALPHA_TEST:     flag = ISENABLED_ALPHA_TEST;              break;
+  case GL_CULL_FACE:      flag = ISENABLED_CULL_FACE;               break;
+  case GL_NORMALIZE:      flag = ISENABLED_NORMALIZE;               break;
+  case GL_FOG:            flag = ISENABLED_FOG;                             break;
+  case GL_COLOR_MATERIAL: flag = ISENABLED_COLMAT;                  break;
+
+  /* Maybe technically these only work with glEnableClientState,
+     but we treat that as synonymous with glEnable. */
+  case GL_VERTEX_ARRAY:   flag = ISENABLED_VERT_ARRAY;     csp = 1;  break;
+  case GL_NORMAL_ARRAY:   flag = ISENABLED_NORM_ARRAY;     csp = 1;  break;
+  case GL_COLOR_ARRAY:    flag = ISENABLED_COLOR_ARRAY;    csp = 1;  break;
+  case GL_TEXTURE_COORD_ARRAY: flag = ISENABLED_TEX_ARRAY; csp = 1;  break;
+
+  default:
+    Assert (set != 0, "glIsEnabled unimplemented bit");
+    break;
+  }
+
+  if (set)  /* setting or unsetting, not querying */
+    {
+      const char *fns[4] = { "glEnable", "glDisable",
+                             "glEnableClientState", "glDisableClientState" };
+      list_fn_cb fs[4] = { (list_fn_cb) &jwzgles_glEnable,
+                           (list_fn_cb) &jwzgles_glDisable,
+                           (list_fn_cb) &jwzgles_glEnableClientState,
+                           (list_fn_cb) &jwzgles_glDisableClientState };
+      const char *fn = fns[(csp ? 2 : 0) + (set < 0 ? 1 : 0)];
+      list_fn_cb  f  =  fs[(csp ? 2 : 0) + (set < 0 ? 1 : 0)];
+
+      Assert (!state->compiling_verts,
+              "glEnable/glDisable not allowed inside glBegin");
+
+      if (state->compiling_list)
+        {
+          void_int vv[1];
+          vv[0].i = bit;
+          list_push (fn, f,PROTO_I, vv);
+        }
+
+      if (! state->replaying_list &&
+          ! state->compiling_list)
+        LOG2 ("direct %-12s %s", fn, mode_desc(bit));
+
+      if (csp && !state->compiling_verts)
+        {
+          if (set > 0)
+            switch (bit) {
+            case GL_NORMAL_ARRAY: state->set.ncount        += 2; break;
+            case GL_TEXTURE_COORD_ARRAY: state->set.tcount += 2; break;
+            case GL_COLOR_ARRAY: state->set.ccount         += 2; break;
+            default: break;
+            }
+          else
+            switch (bit) {
+            case GL_NORMAL_ARRAY: state->set.ncount        = 0; break;
+            case GL_TEXTURE_COORD_ARRAY: state->set.tcount = 0; break;
+            case GL_COLOR_ARRAY: state->set.ccount         = 0; break;
+            default: break;
+            }
+        }
+
+      if (omitp || state->compiling_list)
+        ;
+      else if (set > 0 && csp)
+        glEnableClientState (bit);     /* the real one */
+      else if (set < 0 && csp)
+        glDisableClientState (bit);    /* the real one */
+      else if (set > 0)
+        glEnable (bit);                        /* the real one */
+      else
+        glDisable (bit);               /* the real one */
+
+      CHECK(fn);
+    }
+
+  /* Store the bit in our state as well, or query it.
+   */
+  if (flag)
+    {
+      unsigned long *enabled = (state->compiling_list
+                                ? &state->list_enabled
+                                : &state->enabled);
+      if (set > 0)
+        *enabled |= flag;
+      else if (set < 0)
+        *enabled &= ~flag;
+      else
+        result = !!(*enabled & flag);
+    }
+
+  return result;
+}
+
+
+void
+jwzgles_glEnable (GLuint bit)
+{
+  enable_disable (bit, 1);
+}
+
+void
+jwzgles_glDisable (GLuint bit)
+{
+  enable_disable (bit, -1);
+}
+
+GLboolean
+jwzgles_glIsEnabled (GLuint bit)
+{
+  return enable_disable (bit, 0);
+}
+
+void
+jwzgles_glEnableClientState (GLuint cap)
+{
+  enable_disable (cap, 1);
+}
+
+void
+jwzgles_glDisableClientState (GLuint cap)
+{
+  enable_disable (cap, -1);
+}
+
+
+#define GET(pname, value) \
+  case pname: \
+    *params = value; \
+    break;
+
+/* The spec says that OpenGLES 1.0 doesn't implement glGetFloatv.
+
+   iOS provides 1.1 (and glGetFloatv by extension) at the very minimum.
+
+   Android goes down to 1.0. In particular, this includes the emulator when
+   running without GPU emulation. Actual devices that don't support 1.1 are
+   extremely rare at this point.
+
+   OpenGL ES 1.0 sucks because without glGetFloatv there is no way to retrieve
+   the prevailing matrixes.  To implement this, we'd have to keep track of
+   them all on the client side by combining in all the actions of
+   glMultMatrixf, glRotatef, etc.  Right now, we're only keeping track of the
+   gl*Pointer functions.
+ */
+void
+jwzgles_glGetFloatv (GLenum pname, GLfloat *params)
+{
+  if (! state->replaying_list)
+    LOG2 ("direct %-12s %s", "glGetFloatv", mode_desc(pname));
+
+  switch (pname)
+  {
+  /* OpenGL ES 1.0 omits a few dozen properties that 1.1 supports. The
+     following, however, is sufficient to get things basically working in the
+     Android emulator.
+   */
+
+  GET(GL_VERTEX_ARRAY_BUFFER_BINDING,        state->varray.binding)
+  GET(GL_VERTEX_ARRAY_SIZE,                  state->varray.size)
+  GET(GL_VERTEX_ARRAY_TYPE,                  state->varray.type)
+  GET(GL_VERTEX_ARRAY_STRIDE,                state->varray.stride)
+
+  GET(GL_NORMAL_ARRAY_BUFFER_BINDING,        state->narray.binding)
+  GET(GL_NORMAL_ARRAY_TYPE,                  state->narray.type)
+  GET(GL_NORMAL_ARRAY_STRIDE,                state->narray.stride)
+
+  GET(GL_COLOR_ARRAY_BUFFER_BINDING,         state->carray.binding)
+  GET(GL_COLOR_ARRAY_SIZE,                   state->carray.size)
+  GET(GL_COLOR_ARRAY_TYPE,                   state->carray.type)
+  GET(GL_COLOR_ARRAY_STRIDE,                 state->carray.stride)
+
+  GET(GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, state->tarray.binding)
+  GET(GL_TEXTURE_COORD_ARRAY_SIZE,           state->tarray.size)
+  GET(GL_TEXTURE_COORD_ARRAY_TYPE,           state->tarray.type)
+  GET(GL_TEXTURE_COORD_ARRAY_STRIDE,         state->tarray.stride)
+
+  default:
+    glGetFloatv (pname, params);  /* the real one */
+    break;
+  }
+
+  CHECK("glGetFloatv");
+}
+
+
+void
+jwzgles_glGetPointerv (GLenum pname, GLvoid **params)
+{
+  if (! state->replaying_list)
+    LOG2 ("direct %-12s %s", "glGetPointerv", mode_desc(pname));
+
+  switch (pname)
+  {
+  GET(GL_VERTEX_ARRAY_POINTER,           state->varray.data)
+  GET(GL_NORMAL_ARRAY_POINTER,           state->narray.data)
+  GET(GL_COLOR_ARRAY_POINTER,            state->carray.data)
+  GET(GL_TEXTURE_COORD_ARRAY_POINTER,    state->tarray.data)
+
+  default:
+    glGetPointerv (pname, params);  /* the real one */
+  }
+
+  CHECK("glGetPointerv");
+}
+
+#undef GET
+
+
+/* How many cells are written into the *params array.
+   We need to know this to avoid smashing the caller's stack
+   if they asked for a single-value parameter.
+ */
+static int
+glGet_ret_count (GLenum pname)
+{
+  switch (pname) {
+/*case GL_COLOR_MATRIX: */
+  case GL_MODELVIEW_MATRIX:
+  case GL_PROJECTION_MATRIX:
+  case GL_TEXTURE_MATRIX:
+/*case GL_TRANSPOSE_COLOR_MATRIX: */
+/*case GL_TRANSPOSE_MODELVIEW_MATRIX: */
+/*case GL_TRANSPOSE_PROJECTION_MATRIX: */
+/*case GL_TRANSPOSE_TEXTURE_MATRIX: */
+    return 16;
+/*case GL_ACCUM_CLEAR_VALUE: */
+/*case GL_BLEND_COLOR: */
+  case GL_COLOR_CLEAR_VALUE:
+  case GL_COLOR_WRITEMASK:
+  case GL_CURRENT_COLOR:
+/*case GL_CURRENT_RASTER_COLOR: */
+/*case GL_CURRENT_RASTER_POSITION: */
+/*case GL_CURRENT_RASTER_SECONDARY_COLOR: */
+/*case GL_CURRENT_RASTER_TEXTURE_COORDS: */
+/*case GL_CURRENT_SECONDARY_COLOR: */
+  case GL_CURRENT_TEXTURE_COORDS:
+  case GL_FOG_COLOR:
+  case GL_LIGHT_MODEL_AMBIENT:
+/*case GL_MAP2_GRID_DOMAIN: */
+  case GL_SCISSOR_BOX:
+  case GL_VIEWPORT:
+    return 4;
+  case GL_CURRENT_NORMAL:
+  case GL_POINT_DISTANCE_ATTENUATION:
+    return 3;
+  case GL_ALIASED_LINE_WIDTH_RANGE:
+  case GL_ALIASED_POINT_SIZE_RANGE:
+  case GL_DEPTH_RANGE:
+/*case GL_LINE_WIDTH_RANGE: */
+/*case GL_MAP1_GRID_DOMAIN: */
+/*case GL_MAP2_GRID_SEGMENTS: */
+  case GL_MAX_VIEWPORT_DIMS:
+/*case GL_POINT_SIZE_RANGE: */
+  case GL_POLYGON_MODE:
+  case GL_SMOOTH_LINE_WIDTH_RANGE:
+  case GL_SMOOTH_POINT_SIZE_RANGE:
+    return 2;
+  default:
+    return 1;
+  }
+}
+
+
+void
+jwzgles_glGetDoublev (GLenum pname, GLdouble *params)
+{
+  GLfloat m[16];
+  int i, j = glGet_ret_count (pname);
+  jwzgles_glGetFloatv (pname, m);
+  for (i = 0; i < j; i++)
+    params[i] = m[i];
+}
+
+
+void
+jwzgles_glGetIntegerv (GLenum pname, GLint *params)
+{
+  GLfloat m[16];
+  int i, j = glGet_ret_count (pname);
+  jwzgles_glGetFloatv (pname, m);
+  for (i = 0; i < j; i++)
+    params[i] = m[i];
+}
+
+
+void
+jwzgles_glGetBooleanv (GLenum pname, GLboolean *params)
+{
+  GLfloat m[16];
+  int i, j = glGet_ret_count (pname);
+  jwzgles_glGetFloatv (pname, m);
+  for (i = 0; i < j; i++)
+    params[i] = (m[i] != 0.0);
+}
+
+
+const char *
+jwzgles_gluErrorString (GLenum error)
+{
+  static char s[20];
+  sprintf (s, "0x%lX", (unsigned long) error);
+  return s;
+}
+
+
+/* These four *Pointer calls (plus glBindBuffer and glBufferData) can
+   be included inside glNewList, but they actually execute immediately
+   anyway, because their data is recorded in the list by the
+   subsequently-recorded call to glDrawArrays.  This is a little weird.
+ */
+void
+jwzgles_glVertexPointer (GLuint size, GLuint type, GLuint stride, 
+                         const GLvoid *ptr)
+{
+  if (! state->replaying_list)
+    LOG5 ("direct %-12s %d %s %d 0x%lX", "glVertexPointer", 
+          size, mode_desc(type), stride, (unsigned long) ptr);
+
+  state->varray.size = size;
+  state->varray.type = type;
+  state->varray.stride = stride;
+  state->varray.data = (GLvoid *)ptr;
+
+  glVertexPointer (size, type, stride, ptr);  /* the real one */
+  CHECK("glVertexPointer");
+}
+
+
+void
+jwzgles_glNormalPointer (GLuint type, GLuint stride, const GLvoid *ptr)
+{
+  if (! state->replaying_list)
+    LOG4 ("direct %-12s %s %d 0x%lX", "glNormalPointer", 
+          mode_desc(type), stride, (unsigned long) ptr);
+
+  state->narray.type = type;
+  state->narray.stride = stride;
+  state->narray.data = (GLvoid *)ptr;
+
+  glNormalPointer (type, stride, ptr);  /* the real one */
+  CHECK("glNormalPointer");
+}
+
+void
+jwzgles_glColorPointer (GLuint size, GLuint type, GLuint stride, 
+                        const GLvoid *ptr)
+{
+  if (! state->replaying_list)
+    LOG5 ("direct %-12s %d %s %d 0x%lX", "glColorPointer", 
+          size, mode_desc(type), stride, (unsigned long) ptr);
+
+  state->carray.size = size;
+  state->carray.type = type;
+  state->carray.stride = stride;
+  state->carray.data = (GLvoid *)ptr;
+
+  glColorPointer (size, type, stride, ptr);  /* the real one */
+  CHECK("glColorPointer");
+}
+
+void
+jwzgles_glTexCoordPointer (GLuint size, GLuint type, GLuint stride, 
+                           const GLvoid *ptr)
+{
+  if (! state->replaying_list)
+    LOG5 ("direct %-12s %d %s %d 0x%lX", "glTexCoordPointer", 
+          size, mode_desc(type), stride, (unsigned long) ptr);
+
+  state->tarray.size = size;
+  state->tarray.type = type;
+  state->tarray.stride = stride;
+  state->tarray.data = (GLvoid *)ptr;
+
+  glTexCoordPointer (size, type, stride, ptr);  /* the real one */
+  CHECK("glTexCoordPointer");
+}
+
+void
+jwzgles_glBindBuffer (GLuint target, GLuint buffer)
+{
+  if (! state->replaying_list)
+    LOG3 ("direct %-12s %s %d", "glBindBuffer", mode_desc(target), buffer);
+  glBindBuffer (target, buffer);  /* the real one */
+  CHECK("glBindBuffer");
+}
+
+void
+jwzgles_glBufferData (GLenum target, GLsizeiptr size, const void *data,
+                      GLenum usage)
+{
+  if (! state->replaying_list)
+    LOG5 ("direct %-12s %s %ld 0x%lX %s", "glBufferData",
+          mode_desc(target), size, (unsigned long) data, mode_desc(usage));
+  glBufferData (target, size, data, usage);  /* the real one */
+  CHECK("glBufferData");
+}
+
+
+void
+jwzgles_glTexParameterf (GLuint target, GLuint pname, GLfloat param)
+{
+  Assert (!state->compiling_verts,
+          "glTexParameterf not allowed inside glBegin");
+
+  /* We don't *really* implement mipmaps, so just turn this off. */
+  if (param == GL_LINEAR_MIPMAP_LINEAR)   param = GL_LINEAR;
+  if (param == GL_NEAREST_MIPMAP_LINEAR)  param = GL_LINEAR;
+  if (param == GL_LINEAR_MIPMAP_NEAREST)  param = GL_NEAREST;
+  if (param == GL_NEAREST_MIPMAP_NEAREST) param = GL_NEAREST;
+
+  /* We implement 1D textures as 2D textures. */
+  if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D;
+
+  /* Apparently this is another invalid enum. Just ignore it. */
+  if ((pname == GL_TEXTURE_WRAP_S || pname == GL_TEXTURE_WRAP_T) &&
+      param == GL_CLAMP)
+    return;
+
+  if (state->compiling_list)
+    {
+      void_int vv[3];
+      vv[0].i = target;
+      vv[1].i = pname;
+      vv[2].f = param;
+      list_push ("glTexParameterf", (list_fn_cb) &jwzgles_glTexParameterf,
+                 PROTO_IIF, vv);
+    }
+  else
+    {
+      if (! state->replaying_list)
+        LOG4 ("direct %-12s %s %s %7.3f", "glTexParameterf", 
+              mode_desc(target), mode_desc(pname), param);
+      glTexParameterf (target, pname, param);  /* the real one */
+      CHECK("glTexParameterf");
+    }
+}
+
+void
+jwzgles_glTexParameteri (GLuint target, GLuint pname, GLuint param)
+{
+  jwzgles_glTexParameterf (target, pname, param);
+}
+
+
+void
+jwzgles_glBindTexture (GLuint target, GLuint texture)
+{
+  Assert (!state->compiling_verts,
+          "glBindTexture not allowed inside glBegin");
+
+  /* We implement 1D textures as 2D textures. */
+  if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D;
+
+  if (state->compiling_list)
+    {
+      void_int vv[2];
+      vv[0].i = target;
+      vv[1].i = texture;
+      list_push ("glBindTexture", (list_fn_cb) &jwzgles_glBindTexture,
+                 PROTO_II, vv);
+    }
+
+  /* Do it immediately as well, for generate_texture_coords */
+  /* else */
+    {
+      if (! state->replaying_list)
+        LOG3 ("direct %-12s %s %d", "glBindTexture", 
+              mode_desc(target), texture);
+      glBindTexture (target, texture);  /* the real one */
+      CHECK("glBindTexture");
+    }
+}
+
+
+
+/* Matrix functions, mostly cribbed from Mesa.
+ */
+
+void
+jwzgles_glFrustum (GLfloat left,   GLfloat right,
+                   GLfloat bottom, GLfloat top,
+                   GLfloat near,   GLfloat far)
+{
+  GLfloat m[16];
+  GLfloat x = (2 * near)        / (right-left);
+  GLfloat y = (2 * near)        / (top - bottom);
+  GLfloat a = (right + left)    / (right - left);
+  GLfloat b = (top + bottom)    / (top - bottom);
+  GLfloat c = -(far + near)     / (far - near);
+  GLfloat d = -(2 * far * near) / (far - near);
+
+# define M(X,Y)  m[Y * 4 + X]
+  M(0,0) = x; M(0,1) = 0; M(0,2) =  a; M(0,3) = 0;
+  M(1,0) = 0; M(1,1) = y; M(1,2) =  b; M(1,3) = 0;
+  M(2,0) = 0; M(2,1) = 0; M(2,2) =  c; M(2,3) = d;
+  M(3,0) = 0; M(3,1) = 0; M(3,2) = -1; M(3,3) = 0;
+# undef M
+
+  jwzgles_glMultMatrixf (m);
+}
+
+
+void
+jwzgles_glOrtho (GLfloat left,   GLfloat right,
+                 GLfloat bottom, GLfloat top,
+                 GLfloat near,   GLfloat far)
+{
+  GLfloat m[16];
+  GLfloat a = 2 / (right - left);
+  GLfloat b = -(right + left) / (right - left);
+  GLfloat c = 2 / (top - bottom);
+  GLfloat d = -(top + bottom) / (top - bottom);
+  GLfloat e = -2 / (far - near);
+  GLfloat f = -(far + near) / (far - near);
+
+# define M(X,Y)  m[Y * 4 + X]
+  M(0,0) = a; M(0,1) = 0; M(0,2) = 0; M(0,3) = b;
+  M(1,0) = 0; M(1,1) = c; M(1,2) = 0; M(1,3) = d;
+  M(2,0) = 0; M(2,1) = 0; M(2,2) = e; M(2,3) = f;
+  M(3,0) = 0; M(3,1) = 0; M(3,2) = 0; M(3,3) = 1;
+# undef M
+
+  jwzgles_glMultMatrixf (m);
+}
+
+
+void
+jwzgles_gluPerspective (GLdouble fovy, GLdouble aspect, 
+                        GLdouble near, GLdouble far)
+{
+  GLfloat m[16];
+  double si, co, dz;
+  double rad = fovy / 2 * M_PI / 180;
+  double a, b, c, d;
+
+  dz = far - near;
+  si = sin(rad);
+  if (dz == 0 || si == 0 || aspect == 0)
+    return;
+  co = cos(rad) / si;
+
+  a = co / aspect;
+  b = co;
+  c = -(far + near) / dz;
+  d = -2 * near * far / dz;
+
+# define M(X,Y)  m[Y * 4 + X]
+  M(0,0) = a; M(0,1) = 0; M(0,2) = 0;  M(0,3) = 0;
+  M(1,0) = 0; M(1,1) = b; M(1,2) = 0;  M(1,3) = 0;
+  M(2,0) = 0; M(2,1) = 0; M(2,2) = c;  M(2,3) = d;
+  M(3,0) = 0; M(3,1) = 0; M(3,2) = -1; M(3,3) = 0;
+# undef M
+
+  jwzgles_glMultMatrixf (m);
+}
+
+
+void
+jwzgles_gluLookAt (GLfloat eyex, GLfloat eyey, GLfloat eyez,
+                   GLfloat centerx, GLfloat centery, GLfloat centerz,
+                   GLfloat upx, GLfloat upy, GLfloat upz)
+{
+  GLfloat m[16];
+  GLfloat x[3], y[3], z[3];
+  GLfloat mag;
+    
+  /* Make rotation matrix */
+    
+  /* Z vector */
+  z[0] = eyex - centerx;
+  z[1] = eyey - centery;
+  z[2] = eyez - centerz;
+  mag = sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
+  if (mag) {          /* mpichler, 19950515 */
+    z[0] /= mag;
+    z[1] /= mag;
+    z[2] /= mag;
+  }
+    
+  /* Y vector */
+  y[0] = upx;
+  y[1] = upy;
+  y[2] = upz;
+    
+  /* X vector = Y cross Z */
+  x[0] = y[1] * z[2] - y[2] * z[1];
+  x[1] = -y[0] * z[2] + y[2] * z[0];
+  x[2] = y[0] * z[1] - y[1] * z[0];
+    
+  /* Recompute Y = Z cross X */
+  y[0] = z[1] * x[2] - z[2] * x[1];
+  y[1] = -z[0] * x[2] + z[2] * x[0];
+  y[2] = z[0] * x[1] - z[1] * x[0];
+    
+  /* mpichler, 19950515 */
+  /* cross product gives area of parallelogram, which is < 1.0 for
+   * non-perpendicular unit-length vectors; so normalize x, y here
+   */
+    
+  mag = sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
+  if (mag) {
+    x[0] /= mag;
+    x[1] /= mag;
+    x[2] /= mag;
+  }
+    
+  mag = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
+  if (mag) {
+    y[0] /= mag;
+    y[1] /= mag;
+    y[2] /= mag;
+  }
+    
+#define M(row,col)  m[col*4+row]
+  M(0, 0) = x[0]; M(0, 1) = x[1]; M(0, 2) = x[2]; M(0, 3) = 0.0;
+  M(1, 0) = y[0]; M(1, 1) = y[1]; M(1, 2) = y[2]; M(1, 3) = 0.0;
+  M(2, 0) = z[0]; M(2, 1) = z[1]; M(2, 2) = z[2]; M(2, 3) = 0.0;
+  M(3, 0) = 0.0;  M(3, 1) = 0.0;  M(3, 2) = 0.0;  M(3, 3) = 1.0;
+#undef M
+
+  jwzgles_glMultMatrixf(m);
+    
+  /* Translate Eye to Origin */
+  jwzgles_glTranslatef(-eyex, -eyey, -eyez);
+}
+
+
+static void __gluMultMatrixVecd (const GLdouble matrix[16],
+                                 const GLdouble in[4],
+                                 GLdouble out[4])
+{
+  int i;
+
+  for (i=0; i<4; i++) {
+    out[i] = 
+      in[0] * matrix[0*4+i] +
+      in[1] * matrix[1*4+i] +
+      in[2] * matrix[2*4+i] +
+      in[3] * matrix[3*4+i];
+  }
+}
+
+GLint
+jwzgles_gluProject (GLdouble objx, GLdouble objy, GLdouble objz, 
+                    const GLdouble modelMatrix[16], 
+                    const GLdouble projMatrix[16],
+                    const GLint viewport[4],
+                    GLdouble *winx, GLdouble *winy, GLdouble *winz)
+{
+  GLdouble in[4];
+  GLdouble out[4];
+
+  /* #### I suspect this is not working right.  I was seeing crazy values
+     in lament.c.  Maybe there's some float-vs-double confusion going on?
+   */
+
+  in[0]=objx;
+  in[1]=objy;
+  in[2]=objz;
+  in[3]=1.0;
+  __gluMultMatrixVecd(modelMatrix, in, out);
+  __gluMultMatrixVecd(projMatrix, out, in);
+  if (in[3] == 0.0) return(GL_FALSE);
+  in[0] /= in[3];
+  in[1] /= in[3];
+  in[2] /= in[3];
+  /* Map x, y and z to range 0-1 */
+  in[0] = in[0] * 0.5 + 0.5;
+  in[1] = in[1] * 0.5 + 0.5;
+  in[2] = in[2] * 0.5 + 0.5;
+
+  /* Map x,y to viewport */
+  in[0] = in[0] * viewport[2] + viewport[0];
+  in[1] = in[1] * viewport[3] + viewport[1];
+
+  *winx=in[0];
+  *winy=in[1];
+  *winz=in[2];
+  return(GL_TRUE);
+}
+
+
+/* OpenGL ES has different extensions vs. regular OpenGL, but the basic
+   principle for checking for extensions is the same.
+ */
+GLboolean
+jwzgles_gluCheckExtension (const GLubyte *ext_name, const GLubyte *ext_string)
+{
+  size_t ext_len = strlen ((const char *)ext_name);
+
+  for (;;) {
+    const GLubyte *found = (const GLubyte *)strstr ((const char *)ext_string,
+                                                    (const char *)ext_name);
+    if (!found)
+      break;
+
+    char last_ch = found[ext_len];
+    if ((found == ext_string || found[-1] == ' ') &&
+        (last_ch == ' ' || !last_ch)) {
+      return GL_TRUE;
+    }
+
+    ext_string = found + ext_len;
+  }
+
+  return GL_FALSE;
+}
+
+
+void jwzgles_glViewport (GLuint x, GLuint y, GLuint w, GLuint h)
+{
+# if TARGET_IPHONE_SIMULATOR
+/*  fprintf (stderr, "glViewport %dx%d\n", w, h); */
+# endif
+  glViewport (x, y, w, h);  /* the real one */
+}
+
+
+/* The following functions are present in both OpenGL 1.1 and in OpenGLES 1,
+   but are allowed within glNewList/glEndList, so we must wrap them to allow
+   them to either be recorded in lists, or run directly.
+
+   All this CPP obscenity is me screaming in rage at all the ways that C is
+   not Lisp, as all I want to do here is DEFADVICE.
+ */
+
+#define PROTO_V   PROTO_VOID
+#define TYPE_V    GLuint
+#define ARGS_V    void
+#define VARS_V    /* */
+#define LOGS_V    "\n"
+#define FILL_V    /* */
+
+#define TYPE_I    GLuint
+#define TYPE_II   TYPE_I
+#define TYPE_III  TYPE_I
+#define TYPE_IIII TYPE_I
+#define ARGS_I    TYPE_I a
+#define ARGS_II   TYPE_I a, TYPE_I b
+#define ARGS_III  TYPE_I a, TYPE_I b, TYPE_I c
+#define ARGS_IIII TYPE_I a, TYPE_I b, TYPE_I c, TYPE_I d
+#define LOGS_I    "%s\n", mode_desc(a)
+#define LOGS_II   "%s %d\n", mode_desc(a), b
+#define LOGS_III  "%s %s %s\n", mode_desc(a), mode_desc(b), mode_desc(c)
+#define LOGS_IIII "%d %d %d %d\n", a, b, c, d
+#define VARS_I    a
+#define VARS_II   a, b
+#define VARS_III  a, b, c
+#define VARS_IIII a, b, c, d
+#define FILL_I    vv[0].i = a;
+#define FILL_II   vv[0].i = a; vv[1].i = b;
+#define FILL_III  vv[0].i = a; vv[1].i = b; vv[2].i = c;
+#define FILL_IIII vv[0].i = a; vv[1].i = b; vv[2].i = c; vv[3].i = d;
+
+#define TYPE_F    GLfloat
+#define TYPE_FF   TYPE_F
+#define TYPE_FFF  TYPE_F
+#define TYPE_FFFF TYPE_F
+#define ARGS_F    TYPE_F a
+#define ARGS_FF   TYPE_F a, TYPE_F b
+#define ARGS_FFF  TYPE_F a, TYPE_F b, TYPE_F c
+#define ARGS_FFFF TYPE_F a, TYPE_F b, TYPE_F c, TYPE_F d
+#define LOGS_F    "%7.3f\n", a
+#define LOGS_FF   "%7.3f %7.3f\n", a, b
+#define LOGS_FFF  "%7.3f %7.3f %7.3f\n", a, b, c
+#define LOGS_FFFF "%7.3f %7.3f %7.3f %7.3f\n", a, b, c, d
+#define VARS_F    VARS_I
+#define VARS_FF   VARS_II
+#define VARS_FFF  VARS_III
+#define VARS_FFFF VARS_IIII
+#define FILL_F    vv[0].f = a;
+#define FILL_FF   vv[0].f = a; vv[1].f = b;
+#define FILL_FFF  vv[0].f = a; vv[1].f = b; vv[2].f = c;
+#define FILL_FFFF vv[0].f = a; vv[1].f = b; vv[2].f = c; vv[3].f = d;
+
+#define ARGS_IF   TYPE_I a, TYPE_F b
+#define VARS_IF   VARS_II
+#define LOGS_IF   "%s %7.3f\n", mode_desc(a), b
+#define FILL_IF   vv[0].i = a; vv[1].f = b;
+
+#define ARGS_IIF  TYPE_I a, TYPE_I b, TYPE_F c
+#define VARS_IIF  VARS_III
+#define LOGS_IIF  "%s %s %7.3f\n", mode_desc(a), mode_desc(b), c
+#define FILL_IIF  vv[0].i = a; vv[1].i = b; vv[2].f = c;
+
+#define TYPE_IV   GLint
+#define ARGS_IIV  TYPE_I a, const TYPE_IV *b
+#define VARS_IIV  VARS_II
+#define LOGS_IIV  "%s %d %d %d %d\n", mode_desc(a), b[0], b[1], b[2], b[3]
+#define FILL_IIV  vv[0].i = a; \
+                 vv[1].i = b[0]; vv[2].i = b[1]; \
+                 vv[3].i = b[2]; vv[4].i = b[3];
+
+#define ARGS_IFV  TYPE_I a, const TYPE_F *b
+#define VARS_IFV  VARS_II
+#define LOGS_IFV  "%s %7.3f %7.3f %7.3f %7.3f\n", mode_desc(a), \
+                 b[0], b[1], b[2], b[3]
+#define FILL_IFV  vv[0].i = a; \
+                 vv[1].f = b[0]; vv[2].f = b[1]; \
+                 vv[3].f = b[2]; vv[4].f = b[3];
+
+#define ARGS_IIIV TYPE_I a, TYPE_I b, const TYPE_IV *c
+#define VARS_IIIV VARS_III
+#define LOGS_IIIV "%s %-8s %3d %3d %3d %3d\n", mode_desc(a), mode_desc(b), \
+                 c[0], c[1], c[2], c[3]
+#define FILL_IIIV vv[0].i = a; vv[1].i = b; \
+                 vv[2].i = c[0]; vv[3].i = c[1]; \
+                 vv[4].i = c[2]; vv[5].i = c[3];
+
+#define ARGS_IIFV TYPE_I a, TYPE_I b, const TYPE_F *c
+#define VARS_IIFV VARS_III
+#define LOGS_IIFV "%s %-8s %7.3f %7.3f %7.3f %7.3f\n", \
+                 mode_desc(a), mode_desc(b), \
+                 c[0], c[1], c[2], c[3]
+#define FILL_IIFV vv[0].i = a; vv[1].i = b; \
+                 vv[2].f = c[0]; vv[3].f = c[1]; \
+                 vv[4].f = c[2]; vv[5].f = c[3];
+
+#ifdef DEBUG
+# define WLOG(NAME,ARGS) \
+  fprintf (stderr, "jwzgles: direct %-12s ", NAME); \
+  fprintf (stderr, ARGS)
+#else
+# define WLOG(NAME,ARGS) /* */
+#endif
+
+#define WRAP(NAME,SIG) \
+void jwzgles_##NAME (ARGS_##SIG)                                       \
+{                                                                      \
+  Assert (!state->compiling_verts,                                     \
+          STRINGIFY(NAME) " not allowed inside glBegin");              \
+  if (state->compiling_list) {                                         \
+    void_int vv[10];                                                   \
+    FILL_##SIG                                                         \
+    list_push (STRINGIFY(NAME), (list_fn_cb) &jwzgles_##NAME,          \
+              PROTO_##SIG, vv);                                        \
+  } else {                                                             \
+    if (! state->replaying_list) {                                     \
+      WLOG (STRINGIFY(NAME), LOGS_##SIG);                              \
+    }                                                                  \
+    NAME (VARS_##SIG);                                                 \
+    CHECK(STRINGIFY(NAME));                                            \
+  }                                                                    \
+}
+
+WRAP (glActiveTexture, I)
+WRAP (glAlphaFunc,     IF)
+WRAP (glBlendFunc,     II)
+WRAP (glClear,         I)
+WRAP (glClearColor,    FFFF)
+WRAP (glClearStencil,  I)
+WRAP (glColorMask,     IIII)
+WRAP (glCullFace,      I)
+WRAP (glDepthFunc,     I)
+WRAP (glDepthMask,     I)
+WRAP (glFinish,                V)
+WRAP (glFlush,         V)
+WRAP (glFogf,          IF)
+WRAP (glFogfv,         IFV)
+WRAP (glFrontFace,     I)
+WRAP (glHint,          II)
+WRAP (glLightModelf,   IF)
+WRAP (glLightModelfv,  IFV)
+WRAP (glLightf,                IIF)
+WRAP (glLightfv,       IIFV)
+WRAP (glLineWidth,     F)
+WRAP (glLoadIdentity,  V)
+WRAP (glLogicOp,       I)
+WRAP (glMatrixMode,    I)
+WRAP (glPixelStorei,   II)
+WRAP (glPointSize,     F)
+WRAP (glPolygonOffset, FF)
+WRAP (glPopMatrix,     V)
+WRAP (glPushMatrix,    V)
+WRAP (glRotatef,       FFFF)
+WRAP (glScalef,                FFF)
+WRAP (glScissor,       IIII)
+WRAP (glShadeModel,    I)
+WRAP (glStencilFunc,   III)
+WRAP (glStencilMask,   I)
+WRAP (glStencilOp,     III)
+WRAP (glTexEnvf,       IIF)
+WRAP (glTexEnvi,       III)
+WRAP (glTranslatef,    FFF)
+#undef  TYPE_IV
+#define TYPE_IV GLuint
+WRAP (glDeleteTextures,        IIV)
+
+
+#endif /* HAVE_JWZGLES - whole file */
diff --git a/jwxyz/jwzgles.h b/jwxyz/jwzgles.h
new file mode 100644 (file)
index 0000000..9c8d1e2
--- /dev/null
@@ -0,0 +1,520 @@
+/* xscreensaver, Copyright (c) 2012 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 compatibility shim to allow OpenGL 1.3 source code to work in an
+   OpenGLES environment, where almost every OpenGL 1.3 function has
+   been "deprecated".  See jwzgles.c for details.
+ */
+
+#ifndef __JWZGLES_H__
+#define __JWZGLES_H__
+
+#ifndef HAVE_JWZGLES
+# error: do not include this without HAVE_JWZGLES
+#endif
+
+
+#include "jwzglesI.h"
+
+
+/* These are the OpenGL 1.3 functions that are not present in OpenGLES 1.
+   As you can see from the length of this list, OpenGL and OpenGLES have
+   almost nothing to do with each other.  To claim that GLES is a dialect
+   of OpenGL is absurd -- English and Latin have more in common!
+ */
+
+#define glAccum                                jwzgles_glAccum
+#define glAntialiasing                 jwzgles_glAntialiasing
+#define glAreTexturesResident          jwzgles_glAreTexturesResident
+#define glArrayElement                 jwzgles_glArrayElement
+#define glBegin                                jwzgles_glBegin
+#define glBitmap                       jwzgles_glBitmap
+#define glBlendColor                   jwzgles_glBlendColor
+#define glBlendEquation                        jwzgles_glBlendEquation
+#define glCallList                     jwzgles_glCallList
+#define glCallLists                    jwzgles_glCallLists
+#define glClearAccum                   jwzgles_glClearAccum
+#define glClearDepth                   jwzgles_glClearDepth
+#define glClearIndex                   jwzgles_glClearIndex
+#define glClipPlane                    jwzgles_glClipPlane
+#define glColor3b                      jwzgles_glColor3b
+#define glColor3bv                     jwzgles_glColor3bv
+#define glColor3d                      jwzgles_glColor3f
+#define glColor3dv                     jwzgles_glColor3dv
+#define glColor3f                      jwzgles_glColor3f
+#define glColor3fv                     jwzgles_glColor3fv
+#define glColor3i                      jwzgles_glColor3i
+#define glColor3iv                     jwzgles_glColor3iv
+#define glColor3s                      jwzgles_glColor3s
+#define glColor3sv                     jwzgles_glColor3sv
+#define glColor3ub                     jwzgles_glColor3ub
+#define glColor3ubv                    jwzgles_glColor3ubv
+#define glColor3ui                     jwzgles_glColor3ui
+#define glColor3uiv                    jwzgles_glColor3uiv
+#define glColor3us                     jwzgles_glColor3us
+#define glColor3usv                    jwzgles_glColor3usv
+#define glColor4b                      jwzgles_glColor4b
+#define glColor4bv                     jwzgles_glColor4bv
+#define glColor4d                      jwzgles_glColor4d
+#define glColor4dv                     jwzgles_glColor4dv
+#define glColor4fv                     jwzgles_glColor4fv
+#define glColor4i                      jwzgles_glColor4i
+#define glColor4iv                     jwzgles_glColor4iv
+#define glColor4s                      jwzgles_glColor4s
+#define glColor4sv                     jwzgles_glColor4sv
+#define glColor4ub                     jwzgles_glColor4ub
+#define glColor4ubv                    jwzgles_glColor4ubv
+#define glColor4ui                     jwzgles_glColor4ui
+#define glColor4uiv                    jwzgles_glColor4uiv
+#define glColor4us                     jwzgles_glColor4us
+#define glColor4usv                    jwzgles_glColor4usv
+#define glColorMaterial                        jwzgles_glColorMaterial
+#define glColorSubTable                        jwzgles_glColorSubTable
+#define glColorTable                   jwzgles_glColorTable
+#define glColorTableParameter          jwzgles_glColorTableParameter
+#define glColorTableParameterfv                jwzgles_glColorTableParameterfv
+#define glColorub                      jwzgles_glColorub
+#define glColorui                      jwzgles_glColorui
+#define glColorus                      jwzgles_glColorus
+#define glCompressedTexImage           jwzgles_glCompressedTexImage
+#define glCompressedTexImage1D         jwzgles_glCompressedTexImage1D
+#define glCompressedTexImage3D         jwzgles_glCompressedTexImage3D
+#define glCompressedTexSubImage1D      jwzgles_glCompressedTexSubImage1D
+#define glCompressedTexSubImage3D      jwzgles_glCompressedTexSubImage3D
+#define glConvolutionFilter1D          jwzgles_glConvolutionFilter1D
+#define glConvolutionFilter2D          jwzgles_glConvolutionFilter2D
+#define glConvolutionParameter         jwzgles_glConvolutionParameter
+#define glConvolutionParameterfv       jwzgles_glConvolutionParameterfv
+#define glConvolutionParameteriv       jwzgles_glConvolutionParameteriv
+#define glCopyColorSubTable            jwzgles_glCopyColorSubTable
+#define glCopyColorTable               jwzgles_glCopyColorTable
+#define glCopyConvolutionFilter1D      jwzgles_glCopyConvolutionFilter1D
+#define glCopyConvolutionFilter2D      jwzgles_glCopyConvolutionFilter2D
+#define glCopyPixels                   jwzgles_glCopyPixels
+#define glCopyTexImage1D               jwzgles_glCopyTexImage1D
+#define glCopyTexImage3D               jwzgles_glCopyTexImage3D
+#define glCopyTexSubImage1D            jwzgles_glCopyTexSubImage1D
+#define glCopyTexSubImage3D            jwzgles_glCopyTexSubImage3D
+#define glDeleteLists                  jwzgles_glDeleteLists
+#define glDepthRange                   jwzgles_glDepthRange
+#define glDrawBuffer                   jwzgles_glDrawBuffer
+#define glDrawPixels                   jwzgles_glDrawPixels
+#define glDrawRangeElements            jwzgles_glDrawRangeElements
+#define glEdgeFlag                     jwzgles_glEdgeFlag
+#define glEdgeFlagPointer              jwzgles_glEdgeFlagPointer
+#define glEdgeFlagv                    jwzgles_glEdgeFlagv
+#define glEnd                          jwzgles_glEnd
+#define glEndList                      jwzgles_glEndList
+#define glEvalCoord1d                  jwzgles_glEvalCoord1d
+#define glEvalCoord1dv                 jwzgles_glEvalCoord1dv
+#define glEvalCoord1f                  jwzgles_glEvalCoord1f
+#define glEvalCoord1fv                 jwzgles_glEvalCoord1fv
+#define glEvalCoord2d                  jwzgles_glEvalCoord2d
+#define glEvalCoord2dv                 jwzgles_glEvalCoord2dv
+#define glEvalCoord2f                  jwzgles_glEvalCoord2f
+#define glEvalCoord2fv                 jwzgles_glEvalCoord2fv
+#define glEvalMesh1                    jwzgles_glEvalMesh1
+#define glEvalMesh2                    jwzgles_glEvalMesh2
+#define glEvalPoint1                   jwzgles_glEvalPoint1
+#define glEvalPoint2                   jwzgles_glEvalPoint2
+#define glFeedbackBuffer               jwzgles_glFeedbackBuffer
+#define glFogi                         jwzgles_glFogi
+#define glFogiv                                jwzgles_glFogiv
+#define glFrustum                      jwzgles_glFrustum
+#define glGenLists                     jwzgles_glGenLists
+#define glGet                          jwzgles_glGet
+#define glGetBooleanv                  jwzgles_glGetBooleanv
+#define glGetClipPlane                 jwzgles_glGetClipPlane
+#define glGetColorTable                        jwzgles_glGetColorTable
+#define glGetColorTableParameter       jwzgles_glGetColorTableParameter
+#define glGetCompressedTexImage                jwzgles_glGetCompressedTexImage
+#define glGetConvolutionFilter         jwzgles_glGetConvolutionFilter
+#define glGetConvolutionParameter      jwzgles_glGetConvolutionParameter
+#define glGetConvolutionParameteriv    jwzgles_glGetConvolutionParameteriv
+#define glGetDoublev                   jwzgles_glGetDoublev
+#define glGetFloatv                    jwzgles_glGetFloatv
+#define glGetHistogram                 jwzgles_glGetHistogram
+#define glGetHistogramParameter                jwzgles_glGetHistogramParameter
+#define glGetLightfv                   jwzgles_glGetLightfv
+#define glGetLightiv                   jwzgles_glGetLightiv
+#define glGetMapdv                     jwzgles_glGetMapdv
+#define glGetMapfv                     jwzgles_glGetMapfv
+#define glGetMapiv                     jwzgles_glGetMapiv
+#define glGetMaterialfv                        jwzgles_glGetMaterialfv
+#define glGetMaterialiv                        jwzgles_glGetMaterialiv
+#define glGetPixelMapfv                        jwzgles_glGetPixelMapfv
+#define glGetPixelMapuiv               jwzgles_glGetPixelMapuiv
+#define glGetPixelMapusv               jwzgles_glGetPixelMapusv
+#define glGetPointerv                  jwzgles_glGetPointerv
+#define glGetPolygonStipple            jwzgles_glGetPolygonStipple
+#define glGetSeparableFilter           jwzgles_glGetSeparableFilter
+#define glGetTexEnvfv                  jwzgles_glGetTexEnvfv
+#define glGetTexEnviv                  jwzgles_glGetTexEnviv
+#define glGetTexGendv                  jwzgles_glGetTexGendv
+#define glGetTexGenfv                  jwzgles_glGetTexGenfv
+#define glGetTexGeniv                  jwzgles_glGetTexGeniv
+#define glGetTexImage                  jwzgles_glGetTexImage
+#define glGetTexImage1D                        jwzgles_glGetTexImage1D
+#define glGetTexImage2D                        jwzgles_glGetTexImage2D
+#define glGetTexImage3D                        jwzgles_glGetTexImage3D
+#define glGetTexLevelParameterfv       jwzgles_glGetTexLevelParameterfv
+#define glGetTexLevelParameteriv       jwzgles_glGetTexLevelParameteriv
+#define glGetTexParameterfv            jwzgles_glGetTexParameterfv
+#define glGetTexParameteriv            jwzgles_glGetTexParameteriv
+#define glHistogram                    jwzgles_glHistogram
+#define glIndex                                jwzgles_glIndex
+#define glIndexMask                    jwzgles_glIndexMask
+#define glIndexPointer                 jwzgles_glIndexPointer
+#define glIndexd                       jwzgles_glIndexd
+#define glIndexdv                      jwzgles_glIndexdv
+#define glIndexf                       jwzgles_glIndexf
+#define glIndexfv                      jwzgles_glIndexfv
+/*#define glIndexi                     jwzgles_glIndexi*/
+#define glIndexiv                      jwzgles_glIndexiv
+#define glIndexs                       jwzgles_glIndexs
+#define glIndexsv                      jwzgles_glIndexsv
+#define glIndexub                      jwzgles_glIndexub
+#define glIndexubv                     jwzgles_glIndexubv
+#define glInitNames                    jwzgles_glInitNames
+#define glInterleavedArrays            jwzgles_glInterleavedArrays
+#define glIsEnabled                    jwzgles_glIsEnabled
+#define glIsList                       jwzgles_glIsList
+#define glIsTexture                    jwzgles_glIsTexture
+#define glLightModeli                  jwzgles_glLightModeli
+#define glLightModeliv                 jwzgles_glLightModeliv
+#define glLighti                       jwzgles_glLighti
+#define glLightiv                      jwzgles_glLightiv
+#define glLightf                       jwzgles_glLightf
+#define glLightfv                      jwzgles_glLightfv
+#define glLineStipple                  jwzgles_glLineStipple
+#define glListBase                     jwzgles_glListBase
+#define glLoadMatrix                   jwzgles_glLoadMatrix
+#define glLoadMatrixd                  jwzgles_glLoadMatrixd
+#define glLoadName                     jwzgles_glLoadName
+#define glLoadTransposeMatrix          jwzgles_glLoadTransposeMatrix
+#define glLoadTransposeMatrixd         jwzgles_glLoadTransposeMatrixd
+#define glLoadTransposeMatrixf         jwzgles_glLoadTransposeMatrixf
+#define glMap1d                                jwzgles_glMap1d
+#define glMap1f                                jwzgles_glMap1f
+#define glMap2d                                jwzgles_glMap2d
+#define glMap2f                                jwzgles_glMap2f
+#define glMapGrid1d                    jwzgles_glMapGrid1d
+#define glMapGrid1f                    jwzgles_glMapGrid1f
+#define glMapGrid2d                    jwzgles_glMapGrid2d
+#define glMapGrid2f                    jwzgles_glMapGrid2f
+#define glMateriali                    jwzgles_glMateriali
+#define glMaterialiv                   jwzgles_glMaterialiv
+#define glMultMatrixd                  jwzgles_glMultMatrixd
+#define glMultTransposeMatrix          jwzgles_glMultTransposeMatrix
+#define glMultTransposeMatrixd         jwzgles_glMultTransposeMatrixd
+#define glMultTransposeMatrixf         jwzgles_glMultTransposeMatrixf
+#define glMultiTexCoord                        jwzgles_glMultiTexCoord
+#define glNewList                      jwzgles_glNewList
+#define glNormal3b                     jwzgles_glNormal3b
+#define glNormal3bv                    jwzgles_glNormal3bv
+#define glNormal3d                     jwzgles_glNormal3f
+#define glNormal3dv                    jwzgles_glNormal3dv
+#define glNormal3fv                    jwzgles_glNormal3fv
+#define glNormal3i                     jwzgles_glNormal3i
+#define glNormal3iv                    jwzgles_glNormal3iv
+#define glNormal3s                     jwzgles_glNormal3s
+#define glNormal3sv                    jwzgles_glNormal3sv
+#define glOrtho                                jwzgles_glOrtho
+#define glPassThrough                  jwzgles_glPassThrough
+#define glPixelMapfv                   jwzgles_glPixelMapfv
+#define glPixelMapuiv                  jwzgles_glPixelMapuiv
+#define glPixelMapusv                  jwzgles_glPixelMapusv
+#define glPixelStoref                  jwzgles_glPixelStoref
+#define glPixelTransferf               jwzgles_glPixelTransferf
+#define glPixelTransferi               jwzgles_glPixelTransferi
+#define glPixelZoom                    jwzgles_glPixelZoom
+#define glPolygonMode                  jwzgles_glPolygonMode
+#define glPolygonStipple               jwzgles_glPolygonStipple
+#define glPopAttrib                    jwzgles_glPopAttrib
+#define glPopClientAttrib              jwzgles_glPopClientAttrib
+#define glPopName                      jwzgles_glPopName
+#define glPrioritizeTextures           jwzgles_glPrioritizeTextures
+#define glPushAttrib                   jwzgles_glPushAttrib
+#define glPushClientAttrib             jwzgles_glPushClientAttrib
+#define glPushName                     jwzgles_glPushName
+#define glRasterPos2d                  jwzgles_glRasterPos2d
+#define glRasterPos2dv                 jwzgles_glRasterPos2dv
+#define glRasterPos2f                  jwzgles_glRasterPos2f
+#define glRasterPos2fv                 jwzgles_glRasterPos2fv
+#define glRasterPos2i                  jwzgles_glRasterPos2i
+#define glRasterPos2iv                 jwzgles_glRasterPos2iv
+#define glRasterPos2s                  jwzgles_glRasterPos2s
+#define glRasterPos2sv                 jwzgles_glRasterPos2sv
+#define glRasterPos3d                  jwzgles_glRasterPos3d
+#define glRasterPos3dv                 jwzgles_glRasterPos3dv
+#define glRasterPos3f                  jwzgles_glRasterPos3f
+#define glRasterPos3fv                 jwzgles_glRasterPos3fv
+#define glRasterPos3i                  jwzgles_glRasterPos3i
+#define glRasterPos3iv                 jwzgles_glRasterPos3iv
+#define glRasterPos3s                  jwzgles_glRasterPos3s
+#define glRasterPos3sv                 jwzgles_glRasterPos3sv
+#define glRasterPos4d                  jwzgles_glRasterPos4d
+#define glRasterPos4dv                 jwzgles_glRasterPos4dv
+#define glRasterPos4f                  jwzgles_glRasterPos4f
+#define glRasterPos4fv                 jwzgles_glRasterPos4fv
+#define glRasterPos4i                  jwzgles_glRasterPos4i
+#define glRasterPos4iv                 jwzgles_glRasterPos4iv
+#define glRasterPos4s                  jwzgles_glRasterPos4s
+#define glRasterPos4sv                 jwzgles_glRasterPos4sv
+#define glReadBuffer                   jwzgles_glReadBuffer
+#define glRectd                                jwzgles_glRectf
+#define glRectdv                       jwzgles_glRectdv
+#define glRectf                                jwzgles_glRectf
+#define glRectfv                       jwzgles_glRectfv
+#define glRecti                                jwzgles_glRecti
+#define glRectiv                       jwzgles_glRectiv
+#define glRects                                jwzgles_glRects
+#define glRectsv                       jwzgles_glRectsv
+#define glRenderMode                   jwzgles_glRenderMode
+#define glResetHistogram               jwzgles_glResetHistogram
+#define glResetMinmax                  jwzgles_glResetMinmax
+#define glRotated                      jwzgles_glRotated
+#define glScaled                       jwzgles_glScalef
+#define glSelectBuffer                 jwzgles_glSelectBuffer
+#define glSeparableFilter2D            jwzgles_glSeparableFilter2D
+#define glTexCoord1d                   jwzgles_glTexCoord1d
+#define glTexCoord1dv                  jwzgles_glTexCoord1dv
+#define glTexCoord1f                   jwzgles_glTexCoord1f
+#define glTexCoord1fv                  jwzgles_glTexCoord1fv
+#define glTexCoord1i                   jwzgles_glTexCoord1i
+#define glTexCoord1iv                  jwzgles_glTexCoord1iv
+#define glTexCoord1s                   jwzgles_glTexCoord1s
+#define glTexCoord1sv                  jwzgles_glTexCoord1sv
+#define glTexCoord2d                   jwzgles_glTexCoord2f
+#define glTexCoord2dv                  jwzgles_glTexCoord2dv
+#define glTexCoord2f                   jwzgles_glTexCoord2f
+#define glTexCoord2fv                  jwzgles_glTexCoord2fv
+#define glTexCoord2i                   jwzgles_glTexCoord2i
+#define glTexCoord2iv                  jwzgles_glTexCoord2iv
+#define glTexCoord2s                   jwzgles_glTexCoord2s
+#define glTexCoord2sv                  jwzgles_glTexCoord2sv
+#define glTexCoord3d                   jwzgles_glTexCoord3d
+#define glTexCoord3dv                  jwzgles_glTexCoord3dv
+#define glTexCoord3f                   jwzgles_glTexCoord3f
+#define glTexCoord3fv                  jwzgles_glTexCoord3fv
+#define glTexCoord3i                   jwzgles_glTexCoord3i
+#define glTexCoord3iv                  jwzgles_glTexCoord3iv
+#define glTexCoord3s                   jwzgles_glTexCoord3s
+#define glTexCoord3sv                  jwzgles_glTexCoord3sv
+#define glTexCoord4d                   jwzgles_glTexCoord4d
+#define glTexCoord4dv                  jwzgles_glTexCoord4dv
+#define glTexCoord4f                   jwzgles_glTexCoord4f
+#define glTexCoord4fv                  jwzgles_glTexCoord4fv
+#define glTexCoord4i                   jwzgles_glTexCoord4i
+#define glTexCoord4iv                  jwzgles_glTexCoord4iv
+#define glTexCoord4s                   jwzgles_glTexCoord4s
+#define glTexCoord4sv                  jwzgles_glTexCoord4sv
+#define glTexEnvi                      jwzgles_glTexEnvi
+#define glTexEnviv                     jwzgles_glTexEnviv
+#define glTexGend                      jwzgles_glTexGend
+#define glTexGendv                     jwzgles_glTexGendv
+#define glTexGenf                      jwzgles_glTexGenf
+#define glTexGenfv                     jwzgles_glTexGenfv
+#define glTexGeni                      jwzgles_glTexGeni
+#define glTexGeniv                     jwzgles_glTexGeniv
+#define glTexImage1D                   jwzgles_glTexImage1D
+#define glTexImage3D                   jwzgles_glTexImage3D
+#define glTexParameterfv               jwzgles_glTexParameterfv
+#define glTexParameteri                        jwzgles_glTexParameteri
+#define glTexParameteriv               jwzgles_glTexParameteriv
+#define glTexSubImage1D                        jwzgles_glTexSubImage1D
+#define glTexSubImage3D                        jwzgles_glTexSubImage3D
+#define glTranslated                   jwzgles_glTranslatef
+#define glVertex2d                     jwzgles_glVertex2d
+#define glVertex2dv                    jwzgles_glVertex2dv
+#define glVertex2f                     jwzgles_glVertex2f
+#define glVertex2fv                    jwzgles_glVertex2fv
+#define glVertex2i                     jwzgles_glVertex2i
+#define glVertex2iv                    jwzgles_glVertex2iv
+#define glVertex2s                     jwzgles_glVertex2s
+#define glVertex2sv                    jwzgles_glVertex2sv
+#define glVertex3d                     jwzgles_glVertex3f
+#define glVertex3dv                    jwzgles_glVertex3dv
+#define glVertex3f                     jwzgles_glVertex3f
+#define glVertex3fv                    jwzgles_glVertex3fv
+#define glVertex3i                     jwzgles_glVertex3i
+#define glVertex3iv                    jwzgles_glVertex3iv
+#define glVertex3s                     jwzgles_glVertex3s
+#define glVertex3sv                    jwzgles_glVertex3sv
+#define glVertex4d                     jwzgles_glVertex4d
+#define glVertex4dv                    jwzgles_glVertex4dv
+#define glVertex4f                     jwzgles_glVertex4f
+#define glVertex4fv                    jwzgles_glVertex4fv
+#define glVertex4i                     jwzgles_glVertex4i
+#define glVertex4iv                    jwzgles_glVertex4iv
+#define glVertex4s                     jwzgles_glVertex4s
+#define glVertex4sv                    jwzgles_glVertex4sv
+
+#define gluOrtho2D(L,R,B,T)            glOrtho(L,R,B,T,-1,1)
+#define gluPerspective                 jwzgles_gluPerspective
+
+#define glXChooseVisual                        jwzgles_glXChooseVisual
+#define glXCopyContext                 jwzgles_glXCopyContext
+/*#define glXCreateContext             jwzgles_glXCreateContext*/
+#define glXCreateGLXPixmap             jwzgles_glXCreateGLXPixmap
+#define glXDestroyContext              jwzgles_glXDestroyContext
+#define glXDestroyGLXPixmap            jwzgles_glXDestroyGLXPixmap
+#define glXFreeContextEXT              jwzgles_glXFreeContextEXT
+#define glXGetClientString             jwzgles_glXGetClientString
+#define glXGetConfig                   jwzgles_glXGetConfig
+#define glXGetContextIDEXT             jwzgles_glXGetContextIDEXT
+#define glXGetCurrentContext           jwzgles_glXGetCurrentContext
+#define glXGetCurrentDisplay           jwzgles_glXGetCurrentDisplay
+#define glXGetCurrentDrawable          jwzgles_glXGetCurrentDrawable
+#define glXImportContextEXT            jwzgles_glXImportContextEXT
+#define glXIntro                       jwzgles_glXIntro
+#define glXIsDirect                    jwzgles_glXIsDirect
+/*#define glXMakeCurrent               jwzgles_glXMakeCurrent*/
+#define glXQueryContextInfoEXT         jwzgles_glXQueryContextInfoEXT
+#define glXQueryExtension              jwzgles_glXQueryExtension
+#define glXQueryExtensionsString       jwzgles_glXQueryExtensionsString
+#define glXQueryServerString           jwzgles_glXQueryServerString
+#define glXQueryVersion                        jwzgles_glXQueryVersion
+/*#define glXSwapBuffers               jwzgles_glXSwapBuffers*/
+#define glXUseXFont                    jwzgles_glXUseXFont
+#define glXWaitGL                      jwzgles_glXWaitGL
+#define glXWaitX                       jwzgles_glXWaitX
+
+#define gluBeginCurve                  jwzgles_gluBeginCurve
+#define gluBeginPolygon                        jwzgles_gluBeginPolygon
+#define gluBeginSurface                        jwzgles_gluBeginSurface
+#define gluBeginTrim                   jwzgles_gluBeginTrim
+#define gluBuild1DMipmaps              jwzgles_gluBuild1DMipmaps
+#define gluBuild2DMipmaps              jwzgles_gluBuild2DMipmaps
+#define gluCheckExtension              jwzgles_gluCheckExtension
+#define gluCylinder                    jwzgles_gluCylinder
+#define gluDeleteNurbsRenderer         jwzgles_gluDeleteNurbsRenderer
+#define gluDeleteQuadric               jwzgles_gluDeleteQuadric
+#define gluDeleteTess                  jwzgles_gluDeleteTess
+#define gluDisk                                jwzgles_gluDisk
+#define gluEndCurve                    jwzgles_gluEndCurve
+#define gluEndPolygon                  jwzgles_gluEndPolygon
+#define gluEndSurface                  jwzgles_gluEndSurface
+#define gluEndTrim                     jwzgles_gluEndTrim
+#define gluErrorString                 jwzgles_gluErrorString
+#define gluGetNurbsProperty            jwzgles_gluGetNurbsProperty
+#define gluGetString                   jwzgles_gluGetString
+#define gluGetTessProperty             jwzgles_gluGetTessProperty
+#define gluLoadSamplingMatrices                jwzgles_gluLoadSamplingMatrices
+#define gluLookAt                      jwzgles_gluLookAt
+#define gluNewNurbsRenderer            jwzgles_gluNewNurbsRenderer
+#define gluNewQuadric                  jwzgles_gluNewQuadric
+#define gluNewTess                     jwzgles_gluNewTess
+#define gluNextContour                 jwzgles_gluNextContour
+#define gluNurbsCallback               jwzgles_gluNurbsCallback
+#define gluNurbsCurve                  jwzgles_gluNurbsCurve
+#define gluNurbsProperty               jwzgles_gluNurbsProperty
+#define gluNurbsSurface                        jwzgles_gluNurbsSurface
+#define gluPartialDisk                 jwzgles_gluPartialDisk
+#define gluPickMatrix                  jwzgles_gluPickMatrix
+#define gluProject                     jwzgles_gluProject
+#define gluPwlCurve                    jwzgles_gluPwlCurve
+#define gluQuadricCallback             jwzgles_gluQuadricCallback
+#define gluQuadricDrawStyle            jwzgles_gluQuadricDrawStyle
+#define gluQuadricNormals              jwzgles_gluQuadricNormals
+#define gluQuadricOrientation          jwzgles_gluQuadricOrientation
+#define gluQuadricTexture              jwzgles_gluQuadricTexture
+#define gluScaleImage                  jwzgles_gluScaleImage
+#define gluSphere                      jwzgles_gluSphere
+#define gluTessBeginContour            jwzgles_gluTessBeginContour
+#define gluTessBeginPolygon            jwzgles_gluTessBeginPolygon
+#define gluTessCallback                        jwzgles_gluTessCallback
+#define gluTessEndPolygon              jwzgles_gluTessEndPolygon
+#define gluTessEndContour              jwzgles_gluTessEndContour
+#define gluTessNormal                  jwzgles_gluTessNormal
+#define gluTessProperty                        jwzgles_gluTessProperty
+#define gluTessVertex                  jwzgles_gluTessVertex
+#define gluUnProject                   jwzgles_gluUnProject
+
+
+/* These functions are present in both OpenGL 1.1 and in OpenGLES 1,
+   but are allowed within glNewList/glEndList, so we must wrap them
+   to allow them to be recorded.
+ */
+#define glActiveTexture                        jwzgles_glActiveTexture
+#define glAlphaFunc                    jwzgles_glAlphaFunc
+#define glBindTexture                  jwzgles_glBindTexture
+#define glBlendFunc                    jwzgles_glBlendFunc
+#define glClear                                jwzgles_glClear
+#define glClearColor                   jwzgles_glClearColor
+#define glClearStencil                 jwzgles_glClearStencil
+#define glColor4f                      jwzgles_glColor4f
+#define glColorMask                    jwzgles_glColorMask
+#define glColorPointer                 jwzgles_glColorPointer
+#define glCompressedTexImage2D         jwzgles_glCompressedTexImage2D
+#define glCompressedTexSubImage2D      jwzgles_glCompressedTexSubImage2D
+#define glCopyTexImage2D               jwzgles_glCopyTexImage2D
+#define glCopyTexSubImage2D            jwzgles_glCopyTexSubImage2D
+#define glCullFace                     jwzgles_glCullFace
+#define glDeleteTextures               jwzgles_glDeleteTextures
+#define glDepthFunc                    jwzgles_glDepthFunc
+#define glDepthMask                    jwzgles_glDepthMask
+#define glDisable                      jwzgles_glDisable
+#define glDrawArrays                   jwzgles_glDrawArrays
+#define glDrawElements                 jwzgles_glDrawElements
+#define glEnable                       jwzgles_glEnable
+#define glFinish                       jwzgles_glFinish
+#define glFlush                                jwzgles_glFlush
+#define glFogf                         jwzgles_glFogf
+#define glFogfv                                jwzgles_glFogfv
+#define glFrontFace                    jwzgles_glFrontFace
+#define glGenTextures                  jwzgles_glGenTextures
+#define glGetIntegerv                  jwzgles_glGetIntegerv
+#define glHint                         jwzgles_glHint
+#define glLightModelf                  jwzgles_glLightModelf
+#define glLightModelfv                 jwzgles_glLightModelfv
+#define glLightf                       jwzgles_glLightf
+#define glLightfv                      jwzgles_glLightfv
+#define glLineWidth                    jwzgles_glLineWidth
+#define glLoadIdentity                 jwzgles_glLoadIdentity
+#define glLoadMatrixf                  jwzgles_glLoadMatrixf
+#define glLogicOp                      jwzgles_glLogicOp
+#define glMaterialf                    jwzgles_glMaterialf
+#define glMateriali                    jwzgles_glMateriali
+#define glMaterialfv                   jwzgles_glMaterialfv
+#define glMaterialiv                   jwzgles_glMaterialiv
+#define glMatrixMode                   jwzgles_glMatrixMode
+#define glMultMatrixf                  jwzgles_glMultMatrixf
+#define glNormal3f                     jwzgles_glNormal3f
+#define glNormalPointer                        jwzgles_glNormalPointer
+#define glPixelStorei                  jwzgles_glPixelStorei
+#define glPointSize                    jwzgles_glPointSize
+#define glPolygonOffset                        jwzgles_glPolygonOffset
+#define glPopMatrix                    jwzgles_glPopMatrix
+#define glPushMatrix                   jwzgles_glPushMatrix
+#define glReadPixels                   jwzgles_glReadPixels
+#define glRotatef                      jwzgles_glRotatef
+#define glScalef                       jwzgles_glScalef
+#define glSampleCoverage               jwzgles_glSampleCoverage
+#define glScissor                      jwzgles_glScissor
+#define glShadeModel                   jwzgles_glShadeModel
+#define glStencilFunc                  jwzgles_glStencilFunc
+#define glStencilMask                  jwzgles_glStencilMask
+#define glStencilOp                    jwzgles_glStencilOp
+#define glTexCoordPointer              jwzgles_glTexCoordPointer
+#define glTexEnvf                      jwzgles_glTexEnvf
+#define glTexEnvfv                     jwzgles_glTexEnvfv
+#define glTexImage2D                   jwzgles_glTexImage2D
+#define glTexParameterf                        jwzgles_glTexParameterf
+#define glTexSubImage2D                        jwzgles_glTexSubImage2D
+#define glTranslatef                   jwzgles_glTranslatef
+#define glVertexPointer                        jwzgles_glVertexPointer
+#define glViewport                     jwzgles_glViewport
+#define glEnableClientState            jwzgles_glEnableClientState
+#define glDisableClientState           jwzgles_glDisableClientState
+#define glClipPlane                    jwzgles_glClipPlane
+
+#endif /* __JWZGLES_H__ */
diff --git a/jwxyz/jwzglesI.h b/jwxyz/jwzglesI.h
new file mode 100644 (file)
index 0000000..588e301
--- /dev/null
@@ -0,0 +1,346 @@
+/* xscreensaver, Copyright (c) 2012-2015 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 compatibility shim to allow OpenGL 1.3 source code to work in an
+   OpenGLES environment, where almost every OpenGL 1.3 function has
+   been "deprecated".  See jwzgles.c for details.
+ */
+
+#ifndef __JWZGLES_I_H__
+#define __JWZGLES_I_H__
+
+#ifdef GL_VERSION_ES_CM_1_0  /* compiling against OpenGLES 1.x */
+
+/* These OpenGL 1.3 constants are not present in OpenGLES 1.
+   Fortunately, it looks like they didn't re-use any of the numbers,
+   so we can just keep using the OpenGL 1.3 values.  I'm actually
+   kind of shocked that the GLES folks passed up that opportunity
+   for further clusterfuckery.
+ */
+# define GLdouble double
+
+# define GL_ACCUM_BUFFER_BIT                   0x00000200
+# define GL_ALL_ATTRIB_BITS                    0x000FFFFF
+# define GL_AUTO_NORMAL                                0x0D80
+# define GL_BLEND_SRC_ALPHA                    0x80CB
+# define GL_C3F_V3F                            0x2A24
+# define GL_C4F_N3F_V3F                                0x2A26
+# define GL_C4UB_V2F                           0x2A22
+# define GL_C4UB_V3F                           0x2A23
+# define GL_CLAMP                              0x2900
+# define GL_COLOR_BUFFER_BIT                   0x00004000
+# define GL_COLOR_MATERIAL_FACE                        0x0B55
+# define GL_COLOR_MATERIAL_PARAMETER           0x0B56
+# define GL_COMPILE                            0x1300
+# define GL_CURRENT_BIT                                0x00000001
+# define GL_DEPTH_BUFFER_BIT                   0x00000100
+# define GL_DOUBLEBUFFER                       0x0C32
+# define GL_ENABLE_BIT                         0x00002000
+# define GL_EVAL_BIT                           0x00010000
+# define GL_EYE_LINEAR                         0x2400
+# define GL_EYE_PLANE                          0x2502
+# define GL_FEEDBACK                           0x1C01
+# define GL_FILL                               0x1B02
+# define GL_FOG_BIT                            0x00000080
+# define GL_HINT_BIT                           0x00008000
+# define GL_INTENSITY                          0x8049
+# define GL_LIGHTING_BIT                       0x00000040
+# define GL_LIGHT_MODEL_COLOR_CONTROL          0x81F8
+# define GL_LIGHT_MODEL_LOCAL_VIEWER           0x0B51
+# define GL_LINE                               0x1B01
+# define GL_LINE_BIT                           0x00000004
+# define GL_LIST_BIT                           0x00020000
+# define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT     0x84FF
+# define GL_N3F_V3F                            0x2A25
+# define GL_OBJECT_LINEAR                      0x2401
+# define GL_OBJECT_PLANE                       0x2501
+# define GL_PIXEL_MODE_BIT                     0x00000020
+# define GL_POINT_BIT                          0x00000002
+# define GL_POLYGON                            0x0009
+# define GL_POLYGON_BIT                                0x00000008
+# define GL_POLYGON_MODE                       0x0B40
+# define GL_POLYGON_SMOOTH                     0x0B41
+# define GL_POLYGON_STIPPLE                    0x0B42
+# define GL_POLYGON_STIPPLE_BIT                        0x00000010
+# define GL_Q                                  0x2003
+# define GL_QUADS                              0x0007
+# define GL_QUAD_STRIP                         0x0008
+# define GL_R                                  0x2002
+# define GL_RENDER                             0x1C00
+# define GL_RGBA_MODE                          0x0C31
+# define GL_S                                  0x2000
+# define GL_SCISSOR_BIT                                0x00080000
+# define GL_SELECT                             0x1C02
+# define GL_SEPARATE_SPECULAR_COLOR            0x81FA
+# define GL_SINGLE_COLOR                       0x81F9
+# define GL_SPHERE_MAP                         0x2402
+# define GL_STENCIL_BUFFER_BIT                 0x00000400
+# define GL_T                                  0x2001
+# define GL_T2F_C3F_V3F                                0x2A2A
+# define GL_T2F_C4F_N3F_V3F                    0x2A2C
+# define GL_T2F_C4UB_V3F                       0x2A29
+# define GL_T2F_N3F_V3F                                0x2A2B
+# define GL_T2F_V3F                            0x2A27
+# define GL_T4F_C4F_N3F_V4F                    0x2A2D
+# define GL_T4F_V4F                            0x2A28
+# define GL_TEXTURE_1D                         0x0DE0
+# define GL_TEXTURE_ALPHA_SIZE                 0x805F
+# define GL_TEXTURE_BIT                                0x00040000
+# define GL_TEXTURE_BLUE_SIZE                  0x805E
+# define GL_TEXTURE_BORDER                     0x1005
+# define GL_TEXTURE_BORDER_COLOR               0x1004
+# define GL_TEXTURE_COMPONENTS                 0x1003
+# define GL_TEXTURE_GEN_MODE                   0x2500
+# define GL_TEXTURE_GEN_Q                      0x0C63
+# define GL_TEXTURE_GEN_R                      0x0C62
+# define GL_TEXTURE_GEN_S                      0x0C60
+# define GL_TEXTURE_GEN_T                      0x0C61
+# define GL_TEXTURE_GREEN_SIZE                 0x805D
+# define GL_TEXTURE_HEIGHT                     0x1001
+# define GL_TEXTURE_INTENSITY_SIZE             0x8061
+# define GL_TEXTURE_LUMINANCE_SIZE             0x8060
+# define GL_TEXTURE_MAX_ANISOTROPY_EXT         0x84FE
+# define GL_TEXTURE_RED_SIZE                   0x805C
+# define GL_TEXTURE_WIDTH                      0x1000
+# define GL_TRANSFORM_BIT                      0x00001000
+# define GL_UNPACK_ROW_LENGTH                  0x0CF2
+# define GL_UNSIGNED_INT_8_8_8_8_REV           0x8367
+# define GL_V2F                                        0x2A20
+# define GL_V3F                                        0x2A21
+# define GL_VIEWPORT_BIT                       0x00000800
+# define GL_INT                                        0x1404
+# define GL_DOUBLE                             0x140A
+
+#endif
+
+
+extern void jwzgles_reset (void);
+
+
+/* Prototypes for the things re-implemented in jwzgles.c 
+ */
+
+extern int  jwzgles_glGenLists (int n);
+extern void jwzgles_glNewList (int id, int mode);
+extern void jwzgles_glEndList (void);
+extern void jwzgles_glDeleteLists (int list, int range);
+extern void jwzgles_glBegin (int mode);
+extern void jwzgles_glNormal3fv (const GLfloat *);
+extern void jwzgles_glNormal3f (GLfloat x, GLfloat y, GLfloat z);
+extern void jwzgles_glTexCoord1f (GLfloat s);
+extern void jwzgles_glTexCoord2fv (const GLfloat *);
+extern void jwzgles_glTexCoord2f (GLfloat s, GLfloat t);
+extern void jwzgles_glTexCoord3fv (const GLfloat *);
+extern void jwzgles_glTexCoord3f (GLfloat s, GLfloat t, GLfloat r);
+extern void jwzgles_glTexCoord4fv (const GLfloat *);
+extern void jwzgles_glTexCoord4f (GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+extern void jwzgles_glVertex2f (GLfloat x, GLfloat y);
+extern void jwzgles_glVertex2dv (const GLdouble *);
+extern void jwzgles_glVertex2fv (const GLfloat *);
+extern void jwzgles_glVertex2i (GLint x, GLint y);
+extern void jwzgles_glVertex3f (GLfloat x, GLfloat y, GLfloat z);
+extern void jwzgles_glVertex3dv (const GLdouble *);
+extern void jwzgles_glVertex3fv (const GLfloat *);
+extern void jwzgles_glVertex3i (GLint x, GLint y, GLint z);
+extern void jwzgles_glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+extern void jwzgles_glVertex4fv (const GLfloat *);
+extern void jwzgles_glVertex4i (GLint x, GLint y, GLint z, GLint w);
+extern void jwzgles_glEnd (void);
+extern void jwzgles_glCallList (int id);
+extern void jwzgles_glClearIndex(GLfloat c);
+extern void jwzgles_glBitmap (GLsizei, GLsizei, GLfloat, GLfloat, GLfloat,
+                              GLfloat, const GLubyte *);
+extern void jwzgles_glPushAttrib(int);
+extern void jwzgles_glPopAttrib(void);
+
+
+/* These functions are present in both OpenGL 1.3 and in OpenGLES 1,
+   but are allowed within glNewList/glEndList, so we must wrap them
+   to allow them to be recorded.
+ */
+extern void jwzgles_glActiveTexture (GLuint);
+extern void jwzgles_glBindTexture (GLuint, GLuint);
+extern void jwzgles_glBlendFunc (GLuint, GLuint);
+extern void jwzgles_glClear (GLuint);
+extern void jwzgles_glClearColor (GLclampf, GLclampf, GLclampf, GLclampf);
+extern void jwzgles_glClearStencil (GLuint);
+extern void jwzgles_glColorMask (GLuint, GLuint, GLuint, GLuint);
+extern void jwzgles_glCullFace (GLuint);
+extern void jwzgles_glDepthFunc (GLuint);
+extern void jwzgles_glDepthMask (GLuint);
+extern void jwzgles_glDisable (GLuint);
+extern void jwzgles_glDrawArrays (GLuint, GLuint, GLuint);
+extern GLboolean jwzgles_glIsEnabled (GLuint);
+extern void jwzgles_glEnable (GLuint);
+extern void jwzgles_glFrontFace (GLuint);
+extern void jwzgles_glHint (GLuint, GLuint);
+extern void jwzgles_glLineWidth (GLfloat);
+extern void jwzgles_glLoadIdentity (void);
+extern void jwzgles_glLogicOp (GLuint);
+extern void jwzgles_glMatrixMode (GLuint);
+extern void jwzgles_glMultMatrixf (const GLfloat *);
+extern void jwzgles_glPointSize (GLfloat);
+extern void jwzgles_glPolygonOffset (GLfloat, GLfloat);
+extern void jwzgles_glPopMatrix (void);
+extern void jwzgles_glPushMatrix (void);
+extern void jwzgles_glScissor (GLuint, GLuint, GLuint, GLuint);
+extern void jwzgles_glShadeModel (GLuint);
+extern void jwzgles_glStencilFunc (GLuint, GLuint, GLuint);
+extern void jwzgles_glStencilMask (GLuint);
+extern void jwzgles_glStencilOp (GLuint, GLuint, GLuint);
+extern void jwzgles_glViewport (GLuint, GLuint, GLuint, GLuint);
+extern void jwzgles_glTranslatef (GLfloat, GLfloat, GLfloat);
+extern void jwzgles_glRotatef (GLfloat, GLfloat, GLfloat, GLfloat);
+extern void jwzgles_glRotated (GLdouble, GLdouble x, GLdouble y, GLdouble z);
+extern void jwzgles_glScalef (GLfloat, GLfloat, GLfloat);
+extern void jwzgles_glColor3f (GLfloat, GLfloat, GLfloat);
+extern void jwzgles_glColor4f (GLfloat, GLfloat, GLfloat, GLfloat);
+extern void jwzgles_glColor3fv (const GLfloat *);
+extern void jwzgles_glColor4fv (const GLfloat *);
+extern void jwzgles_glColor3s (GLshort, GLshort, GLshort);
+extern void jwzgles_glColor4s (GLshort, GLshort, GLshort, GLshort);
+extern void jwzgles_glColor3sv (const GLshort *);
+extern void jwzgles_glColor4sv (const GLshort *);
+extern void jwzgles_glColor3us (GLushort, GLushort, GLushort);
+extern void jwzgles_glColor4us (GLushort, GLushort, GLushort, GLushort);
+extern void jwzgles_glColor3usv (const GLushort *);
+extern void jwzgles_glColor4usv (const GLushort *);
+extern void jwzgles_glColor3d (GLdouble, GLdouble, GLdouble);
+extern void jwzgles_glColor4d (GLdouble, GLdouble, GLdouble, GLdouble);
+extern void jwzgles_glColor3dv (const GLdouble *);
+extern void jwzgles_glColor4dv (const GLdouble *);
+extern void jwzgles_glColor4i (GLint, GLint, GLint, GLint);
+extern void jwzgles_glColor3i (GLint, GLint, GLint);
+extern void jwzgles_glColor3iv (const GLint *);
+extern void jwzgles_glColor4iv (const GLint *);
+extern void jwzgles_glColor4ui (GLuint, GLuint, GLuint, GLuint);
+extern void jwzgles_glColor3ui (GLuint, GLuint, GLuint);
+extern void jwzgles_glColor3uiv (const GLuint *);
+extern void jwzgles_glColor4uiv (const GLuint *);
+extern void jwzgles_glColor4b (GLbyte, GLbyte, GLbyte, GLbyte);
+extern void jwzgles_glColor3b (GLbyte, GLbyte, GLbyte);
+extern void jwzgles_glColor4bv (const GLbyte *);
+extern void jwzgles_glColor3bv (const GLbyte *);
+extern void jwzgles_glColor4ub (GLubyte, GLubyte, GLubyte, GLubyte);
+extern void jwzgles_glColor3ub (GLubyte, GLubyte, GLubyte);
+extern void jwzgles_glColor4ubv (const GLubyte *);
+extern void jwzgles_glColor3ubv (const GLubyte *);
+extern void jwzgles_glMaterialf (GLuint, GLuint, GLfloat);
+extern void jwzgles_glMateriali (GLuint, GLuint, GLuint);
+extern void jwzgles_glMaterialfv (GLuint, GLuint, const GLfloat *);
+extern void jwzgles_glMaterialiv (GLuint, GLuint, const GLint *);
+extern void jwzgles_glFinish (void);
+extern void jwzgles_glFlush (void);
+extern void jwzgles_glPixelStorei (GLuint, GLuint);
+extern void jwzgles_glEnableClientState (GLuint);
+extern void jwzgles_glDisableClientState (GLuint);
+
+extern void jwzgles_glInitNames (void);
+extern void jwzgles_glPushName (GLuint);
+extern GLuint jwzgles_glPopName (void);
+extern GLuint jwzgles_glRenderMode (GLuint);
+extern void jwzgles_glSelectBuffer (GLsizei, GLuint *);
+extern void jwzgles_glLightf (GLenum, GLenum, GLfloat);
+extern void jwzgles_glLighti (GLenum, GLenum, GLint);
+extern void jwzgles_glLightfv (GLenum, GLenum, const GLfloat *);
+extern void jwzgles_glLightiv (GLenum, GLenum, const GLint *);
+extern void jwzgles_glLightModelf (GLenum, GLfloat);
+extern void jwzgles_glLightModeli (GLenum, GLint);
+extern void jwzgles_glLightModelfv (GLenum, const GLfloat *);
+extern void jwzgles_glLightModeliv (GLenum, const GLint *);
+extern void jwzgles_glGenTextures (GLuint, GLuint *);
+extern void jwzgles_glFrustum (GLfloat, GLfloat, GLfloat, GLfloat,
+                               GLfloat, GLfloat);
+extern void jwzgles_glOrtho (GLfloat, GLfloat, GLfloat, GLfloat, 
+                             GLfloat, GLfloat);
+extern void jwzgles_glTexImage1D (GLenum target, GLint level,
+                                  GLint internalFormat,
+                                  GLsizei width, GLint border,
+                                  GLenum format, GLenum type,
+                                  const GLvoid *pixels);
+extern void jwzgles_glTexImage2D (GLenum target,
+                                  GLint        level,
+                                  GLint        internalFormat,
+                                  GLsizei      width,
+                                  GLsizei      height,
+                                  GLint        border,
+                                  GLenum       format,
+                                  GLenum       type,
+                                  const GLvoid *data);
+extern void jwzgles_glTexSubImage2D (GLenum target, GLint level,
+                                     GLint xoffset, GLint yoffset,
+                                     GLsizei width, GLsizei height,
+                                     GLenum format, GLenum type,
+                                     const GLvoid *pixels);
+extern void jwzgles_glCopyTexImage2D (GLenum target, GLint level, 
+                                      GLenum internalformat,
+                                      GLint x, GLint y, 
+                                      GLsizei width, GLsizei height, 
+                                      GLint border);
+extern void jwzgles_glInterleavedArrays (GLenum, GLsizei, const GLvoid *);
+extern void jwzgles_glTexEnvf (GLuint, GLuint, GLfloat);
+extern void jwzgles_glTexEnvi (GLuint, GLuint, GLuint);
+extern void jwzgles_glTexParameterf (GLuint, GLuint, GLfloat);
+extern void jwzgles_glTexParameteri (GLuint, GLuint, GLuint);
+extern void jwzgles_glTexGeni (GLenum, GLenum, GLint);
+extern void jwzgles_glTexGenfv (GLenum, GLenum, const GLfloat *);
+extern void jwzgles_glGetTexGenfv (GLenum, GLenum, GLfloat *);
+extern void jwzgles_glRectf (GLfloat, GLfloat, GLfloat, GLfloat);
+extern void jwzgles_glRecti (GLint, GLint, GLint, GLint);
+extern void jwzgles_glLightModelfv (GLenum, const GLfloat *);
+extern void jwzgles_glClearDepth (GLfloat);
+extern GLboolean jwzgles_glIsList (GLuint);
+extern void jwzgles_glColorMaterial (GLenum, GLenum);
+extern void jwzgles_glPolygonMode (GLenum, GLenum);
+extern void jwzgles_glFogf (GLenum, GLfloat);
+extern void jwzgles_glFogi (GLenum, GLint);
+extern void jwzgles_glFogfv (GLenum, const GLfloat *);
+extern void jwzgles_glFogiv (GLenum, const GLint *);
+extern void jwzgles_glAlphaFunc (GLenum, GLfloat);
+extern void jwzgles_glClipPlane (GLenum, const GLdouble *);
+extern void jwzgles_glDrawBuffer (GLenum);
+extern void jwzgles_glDeleteTextures (GLuint, const GLuint *);
+
+extern void jwzgles_gluPerspective (GLdouble fovy, GLdouble aspect, 
+                                    GLdouble near, GLdouble far);
+extern void jwzgles_gluLookAt (GLfloat eyex, GLfloat eyey, GLfloat eyez,
+                               GLfloat centerx, GLfloat centery, 
+                               GLfloat centerz,
+                               GLfloat upx, GLfloat upy, GLfloat upz);
+extern GLint jwzgles_gluProject (GLdouble objx, GLdouble objy, GLdouble objz, 
+                                 const GLdouble modelMatrix[16], 
+                                 const GLdouble projMatrix[16],
+                                 const GLint viewport[4],
+                                 GLdouble *winx, GLdouble *winy, 
+                                 GLdouble *winz);
+extern int jwzgles_gluBuild2DMipmaps (GLenum target,
+                                      GLint internalFormat,
+                                      GLsizei width,
+                                      GLsizei height,
+                                      GLenum format,
+                                      GLenum type,
+                                      const GLvoid *data);
+extern GLboolean jwzgles_gluCheckExtension (const GLubyte *ext_name,
+                                            const GLubyte *ext_string);
+extern void jwzgles_glGetFloatv (GLenum pname, GLfloat *params);
+extern void jwzgles_glGetPointerv (GLenum pname, GLvoid **params);
+extern void jwzgles_glGetDoublev (GLenum pname, GLdouble *params);
+extern void jwzgles_glGetIntegerv (GLenum pname, GLint *params);
+extern void jwzgles_glGetBooleanv (GLenum pname, GLboolean *params);
+extern void jwzgles_glVertexPointer (GLuint, GLuint, GLuint, const void *);
+extern void jwzgles_glNormalPointer (GLenum, GLuint, const void *);
+extern void jwzgles_glColorPointer (GLuint, GLuint, GLuint, const void *);
+extern void jwzgles_glTexCoordPointer (GLuint, GLuint, GLuint, const void *);
+extern void jwzgles_glBindBuffer (GLuint, GLuint);
+extern void jwzgles_glBufferData (GLenum, GLsizeiptr, const void *, GLenum);
+extern const char *jwzgles_gluErrorString (GLenum error);
+
+#endif /* __JWZGLES_I_H__ */
index a0ed06130f1f89785253d9bcffd65759c87df3db..cb8b2f7a48e410ce0e991ab998c7bfc0f27f7ade 100644 (file)
@@ -1,4 +1,4 @@
-# Auto-generated: Sat Oct 24 12:15:03 PDT 2015
+# Auto-generated: Tue May 24 11:02:33 PDT 2016
 driver/demo-Gtk-conf.c
 driver/demo-Gtk.c
 driver/screensaver-properties.desktop.in
@@ -59,7 +59,9 @@ hacks/config/discrete.xml
 hacks/config/distort.xml
 hacks/config/dnalogo.xml
 hacks/config/drift.xml
+hacks/config/dymaxionmap.xml
 hacks/config/endgame.xml
+hacks/config/energystream.xml
 hacks/config/engine.xml
 hacks/config/epicycle.xml
 hacks/config/eruption.xml
@@ -106,6 +108,7 @@ hacks/config/helix.xml
 hacks/config/hexadrop.xml
 hacks/config/hilbert.xml
 hacks/config/hopalong.xml
+hacks/config/hydrostat.xml
 hacks/config/hyperball.xml
 hacks/config/hypercube.xml
 hacks/config/hypertorus.xml
@@ -174,6 +177,7 @@ hacks/config/pyro.xml
 hacks/config/qix.xml
 hacks/config/quasicrystal.xml
 hacks/config/queens.xml
+hacks/config/raverhoop.xml
 hacks/config/rd-bomb.xml
 hacks/config/rdbomb.xml
 hacks/config/ripples.xml
@@ -220,6 +224,7 @@ hacks/config/triangle.xml
 hacks/config/tronbit.xml
 hacks/config/truchet.xml
 hacks/config/twang.xml
+hacks/config/unicrud.xml
 hacks/config/unknownpleasures.xml
 hacks/config/vermiculate.xml
 hacks/config/vidwhacker.xml
index 5df7f0c6adee9f037adab039c2b0ed3a2b115399..ea5f114470442dddc9ba1358a3ab2b8b93b12187 100644 (file)
@@ -106,12 +106,14 @@ SRCS              = alpha.c colors.c fade.c grabscreen.c grabclient.c hsv.c \
                  overlay.c resources.c spline.c usleep.c visual.c \
                  visual-gl.c xmu.c logo.c yarandom.c erase.c \
                  xshm.c xdbe.c colorbars.c minixpm.c textclient.c \
-                 aligned_malloc.c thread_util.c async_netdb.c xft.c utf8wc.c
+                 textclient-mobile.c aligned_malloc.c thread_util.c \
+                 async_netdb.c xft.c utf8wc.c
 OBJS           = alpha.o colors.o fade.o grabscreen.o grabclient.o hsv.o \
                  overlay.o resources.o spline.o usleep.o visual.o \
                  visual-gl.o xmu.o logo.o yarandom.o erase.o \
                  xshm.o xdbe.o colorbars.o minixpm.o textclient.o \
-                 aligned_malloc.o thread_util.o async_netdb.o xft.o utf8wc.o
+                 textclient-mobile.o aligned_malloc.o thread_util.o \
+                 async_netdb.o xft.o utf8wc.o
 HDRS           = alpha.h colors.h fade.h grabscreen.h hsv.h resources.h \
                  spline.h usleep.h utils.h version.h visual.h vroot.h xmu.h \
                  yarandom.h erase.h xshm.h xdbe.h colorbars.h minixpm.h \
@@ -288,6 +290,8 @@ resources.o: $(srcdir)/utils.h
 spline.o: ../config.h
 spline.o: $(srcdir)/spline.h
 spline.o: $(srcdir)/utils.h
+textclient-mobile.o: ../config.h
+textclient-mobile.o: $(srcdir)/utils.h
 textclient.o: ../config.h
 textclient.o: $(srcdir)/resources.h
 textclient.o: $(srcdir)/textclient.h
index 4db92a41813bc3a969daa5ea31e6909deded1876..c805b9e089c3b7270e7e04bac46d49dc49bcfb8d 100644 (file)
@@ -18,7 +18,7 @@ implied warranty.
 #include <stddef.h>
 #include <stdlib.h>
 
-#if !(_POSIX_VERSION >= 200112L || _XOPEN_VERSION >= 600)
+#if !ALIGNED_MALLOC_HAS_MEMALIGN
 
 #include <assert.h>
 #include <errno.h>
index 819a46cd0af92090a9c5d1726a3ee705a101bd20..43c9219005524a0b3b9cd8696a2aaf8f00b86c68 100644 (file)
@@ -22,18 +22,27 @@ implied warranty.
 # include <unistd.h>
 #endif
 
-#if _POSIX_VERSION >= 200112L || _XOPEN_VERSION >= 600
+#if defined ANDROID
+# include <android/api-level.h>
+#endif
+
+#if (_POSIX_VERSION >= 200112L || _XOPEN_VERSION >= 600) && \
+  (!defined ANDROID || __ANDROID_API__ >= 15)
+# define ALIGNED_MALLOC_HAS_MEMALIGN 1
+#endif
+
+#if ALIGNED_MALLOC_HAS_MEMALIGN
 
 # define aligned_malloc posix_memalign
 # define aligned_free   free
 
-#else /* old POSIX */
+#else /* !ALIGNED_MALLOC_HAS_MEMALIGN */
 
  /* This can't simply be named posix_memalign, since the real thing uses
     free(), but this one can't. */
  int aligned_malloc(void **ptr, unsigned alignment, size_t size);
  void aligned_free(void *);
 
-#endif /* old POSIX */
+#endif /* ALIGNED_MALLOC_HAS_MEMALIGN */
 
 #endif /* __ALIGNED_MALLOC_H__ */
index 5c52161799ecae9928131f6bea893655a0f21270..930da4082495533bfa53045fd3a9dba367e6d83c 100644 (file)
@@ -31,8 +31,8 @@
 
 #if ASYNC_NETDB_USE_GAI
 
-# define _get_addr_family(addr) ((addr)->ss_family)
-# define _get_addr_len(addr) ((addr)->ss_len)
+# define _get_addr_family(addr) ((addr)->x_sockaddr_storage.ss_family)
+# define _get_addr_len(addr) ((addr)->x_sockaddr_storage.ss_len)
 
 static int _has_threads;
 
@@ -45,8 +45,8 @@ int _async_netdb_is_done (struct io_thread *io)
 
 #else /* ASYNC_NETDB_USE_GAI */
 
-# define _get_addr_family(addr) ((addr)->sin_family)
-# define _get_addr_len(addr) ((addr)->sin_len)
+# define _get_addr_family(addr) ((addr)->x_sockaddr_in.sin_family)
+# define _get_addr_len(addr) ((addr)->x_sockaddr_in.sin_len)
 
 static const int _has_threads = -1;
 
@@ -236,12 +236,12 @@ async_name_from_addr_finish (async_name_from_addr_t self_raw,
     switch (_get_addr_family (&self->addr))
       {
       case AF_INET:
-        raw_addr = &((const struct sockaddr_in *)&self->addr)->sin_addr;
+        raw_addr = &self->addr.x_sockaddr_in.sin_addr;
         addrlen = 4;
         break;
 #if ASYNC_NETDB_USE_GAI
       case AF_INET6:
-        raw_addr = &((const struct sockaddr_in6 *)&self->addr)->sin6_addr;
+        raw_addr = &self->addr.x_sockaddr_in6.sin6_addr;
         addrlen = 16;
         break;
 #endif /* ASYNC_NETDB_USE_GAI */
index df6c59c63534081cb8925cea59e196a447505c67..a72f4d599d3aef8962482d3168a47e9d6848b138 100644 (file)
 
 #if ASYNC_NETDB_USE_GAI
 
-typedef struct sockaddr_storage async_netdb_sockaddr_storage_t;
+/* Without using union, gcc-6 warns for
+   breaking strict aliasing rules
+ */
+typedef union {
+       struct sockaddr_storage x_sockaddr_storage;
+       struct sockaddr_in x_sockaddr_in;
+       struct sockaddr_in6 x_sockaddr_in6;
+} async_netdb_sockaddr_storage_t;
 
 int _async_netdb_is_done (struct io_thread *io);
 
 #else
 
-typedef struct sockaddr_in async_netdb_sockaddr_storage_t;
+/* Because the definition for the above case is now union,
+   the definition for this case must also be union...
+*/
+typedef union {
+       struct sockaddr_in x_sockaddr_in;
+} async_netdb_sockaddr_storage_t;
 
 # ifndef EAI_SYSTEM
 /* The EAI_* codes are specified specifically as preprocessor macros, so
index 36e2a95c3facb601746c158d3e29c2eb91391c0a..78a5b553222a3244983c710ecad10e6cb1ac5de5 100644 (file)
@@ -14,6 +14,7 @@ $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-]) OVERLAY.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-]) RESOURCES.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-]) SPLINE.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-]) TEXTCLIENT.C
+$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-]) TEXTCLIENT-MOBILE.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-]) THREAD_UTIL.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-]) USLEEP.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-]) UTF8WC.C
index c7468629256043f938bed3dbd23752ebf134d50f..514f28e0c1fdb2dad8f5fbf75c7a13b66a817f56 100644 (file)
@@ -14,6 +14,7 @@ $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-]) OVERLAY.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-]) RESOURCES.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-]) SPLINE.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-]) TEXTCLIENT.C
+$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-]) TEXTCLIENT-MOBILE.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-]) THREAD_UTIL.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-]) USLEEP.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-]) UTF8WC.C
index ff90820fb4ff0b72bfe9a0e9dfef76711bccde86..6eec38430d320b26e5b6ea7618d4beed788de9b5 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1992-2014 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1992-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
    same API as this program (utils/grabclient.c).
  */
 
+/* This code is a mess.  There's two decades of history in this file.
+   There are several distinct paths through this file depending on what
+   platform it's being compiled for:
+
+
+   X11 execution path:
+
+       load_image_async CB
+           load_random_image_x11
+               fork_exec_cb
+                   "xscreensaver-getimage 0xWINDOW 0xPIXMAP"
+                       "xscreensaver-getimage-file --name /DIR"
+                       draw_colorbars
+                       XPutImage
+                   XtAppAddInput xscreensaver_getimage_cb
+       ...
+       xscreensaver_getimage_cb
+           get_name_from_xprops
+           get_original_geometry_from_xprops
+           CB name, geom, closure
+
+
+   MacOS execution path:
+
+       load_image_async CB
+           load_random_image_cocoa
+               osx_grab_desktop_image (osxgrabscreen.m, MacOS version)
+                   copy_framebuffer_to_ximage
+                   XPutImage
+               draw_colorbars
+               osx_load_image_file_async
+                   open_image_name_pipe
+                       "xscreensaver-getimage-file --name /DIR"
+                 XtAppAddInput xscreensaver_getimage_file_cb
+       ...
+       xscreensaver_getimage_file_cb
+           osx_load_image_file
+               CB name, geom, closure
+
+
+   iOS execution path:
+
+       load_image_async CB
+           load_random_image_cocoa
+               osx_grab_desktop_image (osxgrabscreen.m, iOS version)
+                   CGWindowListCreateImage
+                   jwxyz_draw_NSImage_or_CGImage
+               draw_colorbars
+               ios_load_random_image
+                   ios_load_random_image_cb
+                       jwxyz_draw_NSImage_or_CGImage
+                       CB name, geom, closure
+
+
+   Andrid execution path:
+
+       load_image_async CB
+           load_random_image_android
+               jwxyz_load_random_image (jwxyz-android.c)
+                   XPutImage
+               draw_colorbars
+               CB name, geom, closure
+ */
+
 #include "utils.h"
 #include "grabscreen.h"
 #include "resources.h"
 #include "yarandom.h"
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
 # include "jwxyz.h"
 # include "colorbars.h"
 #else /* !HAVE_COCOA -- real Xlib */
@@ -46,7 +110,35 @@ extern char *progname;
 
 static void print_loading_msg (Screen *, Window);
 
-#ifndef HAVE_COCOA
+
+/* Used for pipe callbacks in X11 or OSX mode.
+   X11: this is the xscreensaver_getimage_cb closure,
+     when waiting on the fork of "xscreensaver-getimage"
+   OSX: this is the xscreensaver_getimage_file_cb closure,
+     when waiting on the fork of "xscreensaver-getimage-file"
+ */
+typedef struct {
+  void (*callback) (Screen *, Window, Drawable,
+                    const char *name, XRectangle *geom, void *closure);
+  Screen *screen;
+  Window window;
+  Drawable drawable;
+  void *closure;
+  XtInputId pipe_id;
+  FILE *pipe;
+
+# if !defined(USE_IPHONE) && !defined(HAVE_COCOA)  /* Real X11 */
+  pid_t pid;
+# endif
+
+# if !defined(USE_IPHONE) && defined(HAVE_COCOA)   /* Desktop OSX */
+  char *directory;
+# endif
+
+} xscreensaver_getimage_data;
+
+
+#if !defined(HAVE_COCOA) && !defined(HAVE_ANDROID)   /* Real X11 */
 
 static Bool error_handler_hit_p = False;
 
@@ -177,8 +269,11 @@ checkerboard (Screen *screen, Drawable drawable)
 }
 
 
+/* Read the image's original name off of the window's X properties.
+   Used only when running "real" X11, not jwxyz.
+ */
 static char *
-get_name (Display *dpy, Window window)
+get_name_from_xprops (Display *dpy, Window window)
 {
   Atom type;
   int format;
@@ -197,8 +292,11 @@ get_name (Display *dpy, Window window)
 }
 
 
+/* Read the image's original geometry off of the window's X properties.
+   Used only when running "real" X11, not jwxyz.
+ */
 static Bool
-get_geometry (Display *dpy, Window window, XRectangle *ret)
+get_original_geometry_from_xprops (Display *dpy, Window window, XRectangle *ret)
 {
   Atom type;
   int format;
@@ -246,10 +344,10 @@ hack_subproc_environment (Display *dpy)
 
   /* Allegedly, BSD 4.3 didn't have putenv(), but nobody runs such systems
      any more, right?  It's not Posix, but everyone seems to have it. */
-#ifdef HAVE_PUTENV
+# ifdef HAVE_PUTENV
   if (putenv (ndpy))
     abort ();
-#endif /* HAVE_PUTENV */
+# endif /* HAVE_PUTENV */
 
   /* don't free (ndpy) -- some implementations of putenv (BSD 4.4,
      glibc 2.0) copy the argument, but some (libc4,5, glibc 2.1.2, MacOS)
@@ -264,6 +362,9 @@ hack_subproc_environment (Display *dpy)
    this is due to the intermediate /bin/sh that system() uses to
    parse arguments?  I'm not sure.  But using fork() and execvp()
    here seems to close the race.
+
+   Used to execute "xscreensaver-getimage".
+   Used only when running "real" X11, not jwxyz.
  */
 static void
 exec_simple_command (const char *command)
@@ -282,48 +383,13 @@ exec_simple_command (const char *command)
 }
 
 
-static void
-fork_exec_wait (const char *command)
-{
-  char buf [255];
-  pid_t forked;
-  int status;
-
-  switch ((int) (forked = fork ()))
-    {
-    case -1:
-      sprintf (buf, "%s: couldn't fork", progname);
-      perror (buf);
-      return;
-
-    case 0:
-      exec_simple_command (command);
-      exit (1);  /* exits child fork */
-      break;
-
-    default:
-      waitpid (forked, &status, 0);
-      break;
-    }
-}
-
-
-typedef struct {
-  void (*callback) (Screen *, Window, Drawable,
-                    const char *name, XRectangle *geom, void *closure);
-  Screen *screen;
-  Window window;
-  Drawable drawable;
-  void *closure;
-  FILE *read_pipe;
-  FILE *write_pipe;
-  XtInputId pipe_id;
-  pid_t pid;
-} grabclient_data;
-
-
-static void finalize_cb (XtPointer closure, int *fd, XtIntervalId *id);
+static void xscreensaver_getimage_cb (XtPointer closure,
+                                      int *fd, XtIntervalId *id);
 
+/* Spawn a program, and run the callback when it finishes.
+   Used to execute "xscreensaver-getimage".
+   Used only when running "real" X11, not jwxyz.
+ */
 static void
 fork_exec_cb (const char *command,
               Screen *screen, Window window, Drawable drawable,
@@ -333,9 +399,10 @@ fork_exec_cb (const char *command,
               void *closure)
 {
   XtAppContext app = XtDisplayToApplicationContext (DisplayOfScreen (screen));
-  grabclient_data *data;
+  xscreensaver_getimage_data *data;
   char buf [255];
   pid_t forked;
+  FILE *wpipe;
 
   int fds [2];
 
@@ -346,16 +413,16 @@ fork_exec_cb (const char *command,
       exit (1);
     }
 
-  data = (grabclient_data *) calloc (1, sizeof(*data));
+  data = (xscreensaver_getimage_data *) calloc (1, sizeof(*data));
   data->callback   = callback;
   data->closure    = closure;
   data->screen     = screen;
   data->window     = window;
   data->drawable   = drawable;
-  data->read_pipe  = fdopen (fds[0], "r");
-  data->write_pipe = fdopen (fds[1], "w");
+  data->pipe       = fdopen (fds[0], "r");
+  wpipe            = fdopen (fds[1], "w");   /* Is this necessary? */
 
-  if (!data->read_pipe || !data->write_pipe)
+  if (!data->pipe || !wpipe)
     {
       sprintf (buf, "%s: fdopen", progname);
       perror (buf);
@@ -363,9 +430,9 @@ fork_exec_cb (const char *command,
     }
 
   data->pipe_id =
-    XtAppAddInput (app, fileno (data->read_pipe),
+    XtAppAddInput (app, fileno (data->pipe),
                    (XtPointer) (XtInputReadMask | XtInputExceptMask),
-                   finalize_cb, (XtPointer) data);
+                   xscreensaver_getimage_cb, (XtPointer) data);
 
   forked = fork ();
   switch ((int) forked)
@@ -377,8 +444,8 @@ fork_exec_cb (const char *command,
 
     case 0:                                    /* child */
 
-      fclose (data->read_pipe);
-      data->read_pipe = 0;
+      fclose (data->pipe);
+      data->pipe = 0;
 
       /* clone the write pipe onto stdout so that it gets closed
          when the fork exits.  This will shut down the pipe and
@@ -395,8 +462,7 @@ fork_exec_cb (const char *command,
       break;
 
     default:                                   /* parent */
-      fclose (data->write_pipe);
-      data->write_pipe = 0;
+      fclose (wpipe);
       data->pid = forked;
       break;
     }
@@ -405,25 +471,27 @@ fork_exec_cb (const char *command,
 
 /* Called in the parent when the forked process dies.
    Runs the caller's callback, and cleans up.
+   This runs when "xscreensaver-getimage" exits.
+   Used only when running "real" X11, not jwxyz.
  */
 static void
-finalize_cb (XtPointer closure, int *fd, XtIntervalId *id)
+xscreensaver_getimage_cb (XtPointer closure, int *fd, XtIntervalId *id)
 {
-  grabclient_data *data = (grabclient_data *) closure;
+  xscreensaver_getimage_data *data = (xscreensaver_getimage_data *) closure;
   Display *dpy = DisplayOfScreen (data->screen);
   char *name;
   XRectangle geom = { 0, 0, 0, 0 };
 
   XtRemoveInput (*id);
 
-  name = get_name (dpy, data->window);
-  get_geometry (dpy, data->window, &geom);
+  name = get_name_from_xprops (dpy, data->window);
+  get_original_geometry_from_xprops (dpy, data->window, &geom);
 
   data->callback (data->screen, data->window, data->drawable,
                   name, &geom, data->closure);
   if (name) free (name);
 
-  fclose (data->read_pipe);
+  fclose (data->pipe);
 
   if (data->pid)       /* reap zombies */
     {
@@ -439,15 +507,14 @@ finalize_cb (XtPointer closure, int *fd, XtIntervalId *id)
 
 /* Loads an image into the Drawable.
    When grabbing desktop images, the Window will be unmapped first.
+   Used only when running "real" X11, not jwxyz.
  */
 static void
-load_random_image_1 (Screen *screen, Window window, Drawable drawable,
-                     void (*callback) (Screen *, Window, Drawable,
-                                       const char *name, XRectangle *geom,
-                                       void *closure),
-                     void *closure,
-                     char **name_ret,
-                     XRectangle *geom_ret)
+load_random_image_x11 (Screen *screen, Window window, Drawable drawable,
+                       void (*callback) (Screen *, Window, Drawable,
+                                         const char *name, XRectangle *geom,
+                                         void *closure),
+                       void *closure)
 {
   Display *dpy = DisplayOfScreen (screen);
   char *grabber = get_string_resource(dpy, "desktopGrabber", "DesktopGrabber");
@@ -487,45 +554,17 @@ load_random_image_1 (Screen *screen, Window window, Drawable drawable,
   XSync (dpy, True);
   hack_subproc_environment (dpy);
 
-  if (callback)
-    {
-      /* Start the image loading in another fork and return immediately.
-         Invoke the callback function when done.
-       */
-      if (name_ret) abort();
-      fork_exec_cb (cmd, screen, window, drawable, callback, closure);
-    }
-  else
-    {
-      /* Wait for the image to load, and return it immediately.
-       */
-      fork_exec_wait (cmd);
-      if (name_ret)
-        *name_ret = get_name (dpy, window);
-      if (geom_ret)
-        get_geometry (dpy, window, geom_ret);
-    }
+  /* Start the image loading in another fork and return immediately.
+     Invoke the callback function when done. */
+  fork_exec_cb (cmd, screen, window, drawable, callback, closure);
 
   free (cmd);
   XSync (dpy, True);
 }
 
-#else  /* HAVE_COCOA */
+#elif defined (HAVE_COCOA) /* OSX or iOS */
 
-struct pipe_closure {
-  FILE *pipe;
-  XtInputId id;
-  Screen *screen;
-  Window xwindow;
-  Drawable drawable;
-  char *directory;
-  void (*callback) (Screen *, Window, Drawable,
-                    const char *name, XRectangle *geom,
-                    void *closure);
-  void *closure;
-};
-
-# ifndef USE_IPHONE
+# ifndef USE_IPHONE   /* HAVE_COCOA && !USE_IPHONE -- desktop OSX */
 
 # define BACKSLASH(c) \
   (! ((c >= 'a' && c <= 'z') || \
@@ -541,7 +580,6 @@ open_image_name_pipe (const char *dir)
 {
   char *s;
 
-# ifdef HAVE_COCOA
   /* /bin/sh on OS X 10.10 wipes out the PATH. */
   const char *path = getenv("PATH");
   char *cmd = s = malloc ((strlen(dir) + strlen(path)) * 2 + 100);
@@ -554,9 +592,6 @@ open_image_name_pipe (const char *dir)
   }
   strcpy (s, "; ");
   s += strlen (s);
-# else
-  char *cmd = s = malloc (strlen(dir) * 2 + 100);
-# endif
 
   strcpy (s, "xscreensaver-getimage-file --name ");
   s += strlen (s);
@@ -565,10 +600,10 @@ open_image_name_pipe (const char *dir)
     if (BACKSLASH(c)) *s++ = '\\';
     *s++ = c;
   }
-# ifdef HAVE_COCOA
+
   strcpy (s, "'");
   s += strlen (s);
-# endif
+
   *s = 0;
 
   FILE *pipe = popen (cmd, "r");
@@ -578,11 +613,11 @@ open_image_name_pipe (const char *dir)
 
 
 static void
-pipe_cb (XtPointer closure, int *source, XtInputId *id)
+xscreensaver_getimage_file_cb (XtPointer closure, int *source, XtInputId *id)
 {
   /* This is not called from a signal handler, so doing stuff here is fine.
    */
-  struct pipe_closure *clo2 = (struct pipe_closure *) closure;
+  xscreensaver_getimage_data *clo2 = (xscreensaver_getimage_data *) closure;
   char buf[10240];
   const char *dir = clo2->directory;
   char *absfile = 0;
@@ -590,8 +625,8 @@ pipe_cb (XtPointer closure, int *source, XtInputId *id)
   fgets (buf, sizeof(buf)-1, clo2->pipe);
   pclose (clo2->pipe);
   clo2->pipe = 0;
-  XtRemoveInput (clo2->id);
-  clo2->id = 0;
+  XtRemoveInput (clo2->pipe_id);
+  clo2->pipe_id = 0;
 
   /* strip trailing newline */
   int L = strlen(buf);
@@ -610,12 +645,12 @@ pipe_cb (XtPointer closure, int *source, XtInputId *id)
       strcat (absfile, buf);
     }
 
-  if (! osx_load_image_file (clo2->screen, clo2->xwindow, clo2->drawable,
+  if (! osx_load_image_file (clo2->screen, clo2->window, clo2->drawable,
                              (absfile ? absfile : buf), &geom)) {
     /* unable to load image - draw colorbars 
      */
     XWindowAttributes xgwa;
-    XGetWindowAttributes (dpy, clo2->xwindow, &xgwa);
+    XGetWindowAttributes (dpy, clo2->window, &xgwa);
     Window r;
     int x, y;
     unsigned int w, h, bbw, d;
@@ -644,7 +679,7 @@ pipe_cb (XtPointer closure, int *source, XtInputId *id)
 
   /* Take the extension off of the file name. */
   /* Duplicated in driver/xscreensaver-getimage.c. */
-  if (buf && *buf)
+  if (*buf)
     {
       char *slash = strrchr (buf, '/');
       char *dot = strrchr ((slash ? slash : buf), '.');
@@ -656,7 +691,7 @@ pipe_cb (XtPointer closure, int *source, XtInputId *id)
     }
 
   if (absfile) free (absfile);
-  clo2->callback (clo2->screen, clo2->xwindow, clo2->drawable, buf, &geom,
+  clo2->callback (clo2->screen, clo2->window, clo2->drawable, buf, &geom,
                   clo2->closure);
   clo2->callback = 0;
   free (clo2->directory);
@@ -664,7 +699,7 @@ pipe_cb (XtPointer closure, int *source, XtInputId *id)
 }
 
 
-# else  /* USE_IPHONE */
+# else   /* HAVE_COCOA && USE_IPHONE -- iOS */
 
 /* Callback for ios_load_random_image(), called after we have loaded an
    image from the iOS device's Photo Library.  See iosgrabimage.m.
@@ -673,7 +708,7 @@ static void
 ios_load_random_image_cb (void *uiimage, const char *filename, 
                           int width, int height, void *closure)
 {
-  struct pipe_closure *clo2 = (struct pipe_closure *) closure;
+  xscreensaver_getimage_data *clo2 = (xscreensaver_getimage_data *) closure;
   Display *dpy = DisplayOfScreen (clo2->screen);
   XRectangle geom;
   XWindowAttributes xgwa;
@@ -682,7 +717,7 @@ ios_load_random_image_cb (void *uiimage, const char *filename,
   unsigned int w, h, bbw, d;
   int rot = 0;
 
-  XGetWindowAttributes (dpy, clo2->xwindow, &xgwa);
+  XGetWindowAttributes (dpy, clo2->window, &xgwa);
   XGetGeometry (dpy, clo2->drawable, &r, &x, &y, &w, &h, &bbw, &d);
 
   /* If the image is portrait and the window is landscape, or vice versa,
@@ -712,14 +747,13 @@ ios_load_random_image_cb (void *uiimage, const char *filename,
       filename = 0;
     }
 
-  clo2->callback (clo2->screen, clo2->xwindow, clo2->drawable,
+  clo2->callback (clo2->screen, clo2->window, clo2->drawable,
                   filename, &geom, clo2->closure);
   clo2->callback = 0;
-  if (clo2->directory) free (clo2->directory);
   free (clo2);
 }
 
-# endif /* USE_IPHONE */
+# endif /* HAVE_COCOA && USE_IPHONE */
 
 
 static void
@@ -731,62 +765,37 @@ osx_load_image_file_async (Screen *screen, Window xwindow, Drawable drawable,
                                              void *closure),
                        void *closure)
 {
-# if 0 /* do it synchronously */
-
-  FILE *pipe = open_image_name_pipe (dir);
-  char buf[10240];
-  *buf = 0;
-  fgets (buf, sizeof(buf)-1, pipe);
-  pclose (pipe);
-
-  /* strip trailing newline */
-  int L = strlen(buf);
-  while (L > 0 && (buf[L-1] == '\r' || buf[L-1] == '\n'))
-    buf[--L] = 0;
-
-  XRectangle geom;
-  if (! osx_load_image_file (screen, xwindow, drawable, buf, &geom)) {
-    /* draw colorbars */
-    abort();
-  }
-  callback (screen, xwindow, drawable, buf, &geom, closure);
-
-# else /* do it asynchronously */
-
-  struct pipe_closure *clo2 = (struct pipe_closure *) calloc (1, sizeof(*clo2));
+  xscreensaver_getimage_data *clo2 =
+    (xscreensaver_getimage_data *) calloc (1, sizeof(*clo2));
 
   clo2->screen = screen;
-  clo2->xwindow = xwindow;
+  clo2->window = xwindow;
   clo2->drawable = drawable;
   clo2->callback = callback;
   clo2->closure = closure;
 
-#  ifndef USE_IPHONE
+# ifndef USE_IPHONE   /* Desktop OSX */
   clo2->directory = strdup (dir);
   clo2->pipe = open_image_name_pipe (dir);
-  clo2->id = XtAppAddInput (XtDisplayToApplicationContext (
-                              DisplayOfScreen (screen)), 
+  clo2->pipe_id = XtAppAddInput (XtDisplayToApplicationContext (
+                            DisplayOfScreen (screen)), 
                             fileno (clo2->pipe),
                             (XtPointer) (XtInputReadMask | XtInputExceptMask),
-                            pipe_cb, (XtPointer) clo2);
-#  else /* USE_IPHONE */
+                            xscreensaver_getimage_file_cb, (XtPointer) clo2);
+# else /* USE_IPHONE */
   ios_load_random_image (ios_load_random_image_cb, clo2);
-#  endif /* USE_IPHONE */
-
-# endif
+# endif /* USE_IPHONE */
 }
 
 
 /* Loads an image into the Drawable, returning once the image is loaded.
  */
 static void
-load_random_image_1 (Screen *screen, Window window, Drawable drawable,
-                     void (*callback) (Screen *, Window, Drawable,
-                                       const char *name, XRectangle *geom,
-                                       void *closure),
-                     void *closure,
-                     char **name_ret,
-                     XRectangle *geom_ret)
+load_random_image_cocoa (Screen *screen, Window window, Drawable drawable,
+                         void (*callback) (Screen *, Window, Drawable,
+                                           const char *name, XRectangle *geom,
+                                           void *closure),
+                         void *closure)
 {
   Display *dpy = DisplayOfScreen (screen);
   XWindowAttributes xgwa;
@@ -794,16 +803,11 @@ load_random_image_1 (Screen *screen, Window window, Drawable drawable,
   Bool filep = get_boolean_resource (dpy, "chooseRandomImages", "Boolean");
   const char *dir = 0;
   Bool done = False;
-  XRectangle geom_ret_2;
-  char *name_ret_2 = 0;
+  XRectangle geom;
+  char *name = 0;
   
   if (!drawable) abort();
 
-  if (callback) {
-    geom_ret = &geom_ret_2;
-    name_ret = &name_ret_2;
-  }
-
   XGetWindowAttributes (dpy, window, &xgwa);
   {
     Window r;
@@ -814,15 +818,10 @@ load_random_image_1 (Screen *screen, Window window, Drawable drawable,
     xgwa.height = h;
   }
 
-  if (name_ret)
-    *name_ret = 0;
-
-  if (geom_ret) {
-    geom_ret->x = 0;
-    geom_ret->y = 0;
-    geom_ret->width  = xgwa.width;
-    geom_ret->height = xgwa.height;
-  }
+  geom.x = 0;
+  geom.y = 0;
+  geom.width  = xgwa.width;
+  geom.height = xgwa.height;
 
 # ifndef USE_IPHONE
   if (filep)
@@ -844,9 +843,8 @@ load_random_image_1 (Screen *screen, Window window, Drawable drawable,
   }
 
   if (deskp && !done) {
-    if (osx_grab_desktop_image (screen, window, drawable, &geom_ret_2)) {
-      if (name_ret)
-        *name_ret = strdup ("desktop");
+    if (osx_grab_desktop_image (screen, window, drawable, &geom)) {
+      name = strdup ("desktop");
       done = True;
     }
   }
@@ -855,15 +853,75 @@ load_random_image_1 (Screen *screen, Window window, Drawable drawable,
     draw_colorbars (screen, xgwa.visual, drawable, xgwa.colormap,
                     0, 0, xgwa.width, xgwa.height);
 
-  if (callback) {
-    /* If we got here, we loaded synchronously even though they wanted async.
-     */
-    callback (screen, window, drawable, name_ret_2, &geom_ret_2, closure);
-    if (name_ret_2) free (name_ret_2);
+  /* If we got here, we loaded synchronously, so we're done. */
+  callback (screen, window, drawable, name, &geom, closure);
+  if (name) free (name);
+}
+
+
+#elif defined(HAVE_ANDROID)
+
+/* Loads an image into the Drawable, returning once the image is loaded.
+ */
+static void
+load_random_image_android (Screen *screen, Window window, Drawable drawable,
+                           void (*callback) (Screen *, Window, Drawable,
+                                             const char *name,
+                                             XRectangle *geom, void *closure),
+                           void *closure)
+{
+  Display *dpy = DisplayOfScreen (screen);
+  XWindowAttributes xgwa;
+  XRectangle geom;
+  char *name = 0;
+  char *data = 0;
+  int width  = 0;
+  int height = 0;
+  
+  if (!drawable) abort();
+
+  XGetWindowAttributes (dpy, window, &xgwa);
+  {
+    Window r;
+    int x, y;
+    unsigned int w, h, bbw, d;
+    XGetGeometry (dpy, drawable, &r, &x, &y, &w, &h, &bbw, &d);
+    xgwa.width = w;
+    xgwa.height = h;
   }
+
+  geom.x = 0;
+  geom.y = 0;
+  geom.width  = xgwa.width;
+  geom.height = xgwa.height;
+
+  data = jwxyz_load_random_image (dpy, &width, &height, &name);
+  if (! data)
+    draw_colorbars (screen, xgwa.visual, drawable, xgwa.colormap,
+                    0, 0, xgwa.width, xgwa.height);
+  else
+    {
+      XImage *img = XCreateImage (dpy, xgwa.visual, 32,
+                                  ZPixmap, 0, data, width, height, 0, 0);
+      XGCValues gcv;
+      GC gc;
+      gcv.foreground = BlackPixelOfScreen (screen);
+      gc = XCreateGC (dpy, drawable, GCForeground, &gcv);
+      XFillRectangle (dpy, drawable, gc, 0, 0, xgwa.width, xgwa.height);
+      XPutImage (dpy, drawable, gc, img, 0, 0, 
+                 (xgwa.width  - width) / 2,
+                 (xgwa.height - height) / 2,
+                 width, height);
+      XDestroyImage (img);
+      XFreeGC (dpy, gc);
+    }
+
+  callback (screen, window, drawable, name, &geom, closure);
+  if (name) free (name);
 }
 
-#endif /* HAVE_COCOA */
+#endif /* HAVE_ANDROID */
+
 
 
 /* Writes the string "Loading..." in the middle of the screen.
@@ -926,7 +984,14 @@ load_image_async (Screen *screen, Window window, Drawable drawable,
                                     void *closure),
                   void *closure)
 {
-  load_random_image_1 (screen, window, drawable, callback, closure, 0, 0);
+  if (!callback) abort();
+# if defined(HAVE_COCOA)
+  load_random_image_cocoa   (screen, window, drawable, callback, closure);
+# elif defined(HAVE_ANDROID)
+  load_random_image_android (screen, window, drawable, callback, closure);
+# else /* real X11 */
+  load_random_image_x11     (screen, window, drawable, callback, closure);
+# endif
 }
 
 struct async_load_state {
index 2baf55ba900c1fba0f30a824148ef95ac20a0efb..237f63ef0422ddc1d662a77340744dad89774322 100644 (file)
@@ -84,13 +84,13 @@ extern void grab_screen_image_internal (Screen *, Window);
 /* For debugging: turn on verbosity. */
 extern void grabscreen_verbose (void);
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
 /* Don't use these: internal interface of grabclient.c. */
 extern Bool osx_grab_desktop_image (Screen *, Window, Drawable,
                                     XRectangle *geom_ret);
 extern Bool osx_load_image_file (Screen *, Window, Drawable,
                                  const char *filename, XRectangle *geom_ret);
-#endif /* HAVE_COCOA */
+#endif /* HAVE_JWXYZ */
 
 #ifdef USE_IPHONE
 extern void ios_load_random_image (void (*callback) (void *uiimage,
@@ -100,4 +100,10 @@ extern void ios_load_random_image (void (*callback) (void *uiimage,
                                    void *closure);
 #endif /* USE_IPHONE */
 
+#ifdef HAVE_ANDROID
+char *jwxyz_load_random_image (Display *dpy,  /* utils/grabclient.c */
+                               int *width_ret, int *height_ret,
+                               char **name_ret);
+#endif
+
 #endif /* __GRABSCREEN_H__ */
index a0cea806a2e662f01d0bd4b715738d0dad2cace2..b093c8f05154714437dd17ce2ec878986815951a 100644 (file)
@@ -4,7 +4,7 @@
    Copyright (c) 2001, 2002 by Jamie Zawinski <jwz@jwz.org>
    Unauthorized use or reproduction prohibited.
 
-   http://www.jwz.org/xscreensaver/
+   https://www.jwz.org/xscreensaver/
  */
 
 static const char * const logo_180_xpm[] = {
index fb93ced0575819486d77aaa7a15156967d9088e0..2661a96001666aaabdbb1eef6e3a8f9fd42d6b4f 100644 (file)
@@ -4,7 +4,7 @@
    Copyright (c) 2001, 2002 by Jamie Zawinski <jwz@jwz.org>
    Unauthorized use or reproduction prohibited.
 
-   http://www.jwz.org/xscreensaver/
+   https://www.jwz.org/xscreensaver/
  */
 
 static const char * const logo_50_xpm[] = {
index ae8f8265a6738e928f6ed07b938ca343ce63eb0b..997e6284066eaeec6981529aa603f5fc9daaf8b7 100644 (file)
 #include <stdio.h>
 #include <string.h>
 
-#if defined (HAVE_COCOA) || defined(HAVE_ANDROID)
+#ifdef HAVE_JWXYZ
 # include "jwxyz.h"
 #else  /* real Xlib */
 # include <X11/Xlib.h>
 # include <X11/Xutil.h>
-#endif /* !HAVE_COCOA && !HAVE_ANDROID */
+#endif /* !HAVE_JWXYZ */
 
 #include "minixpm.h"
 
diff --git a/utils/textclient-mobile.c b/utils/textclient-mobile.c
new file mode 100644 (file)
index 0000000..9aef5df
--- /dev/null
@@ -0,0 +1,813 @@
+/* xscreensaver, Copyright (c) 2012-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.
+ *
+ * Loading URLs and returning the underlying text.
+ *
+ * This is necessary because iOS and Android don't have Perl installed,
+ * so we can't just run "xscreensaver-text" at the end of a pipe to do this.
+ */
+
+#include "utils.h"
+
+#if defined(USE_IPHONE) || defined(HAVE_ANDROID)  /* whole file */
+
+#include "textclient.h"
+#include "resources.h"
+#include "utf8wc.h"
+
+#include <stdio.h>
+
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+
+extern const char *progname;
+
+struct text_data {
+
+  enum { DATE, LITERAL, URL } mode;
+  char *literal, *url;
+
+  Display *dpy;
+  int columns;
+  int max_lines;
+  char *buf;
+  int buf_size;
+  char *fp;
+
+};
+
+
+text_data *
+textclient_open (Display *dpy)
+{
+  text_data *d = (text_data *) calloc (1, sizeof (*d));
+
+# ifdef DEBUG
+  fprintf (stderr, "%s: textclient: init\n", progname);
+# endif
+
+  char *s = get_string_resource (dpy, "textMode", "TextMode");
+  if (!s || !*s || !strcasecmp (s, "date") || !strcmp (s, "0"))
+    d->mode = DATE;
+  else if (!strcasecmp (s, "literal") || !strcmp (s, "1"))
+    d->mode = LITERAL;
+  else if (!strcasecmp (s, "url") || !strcmp (s, "3"))
+    d->mode = URL;
+  else
+    d->mode = DATE;
+
+  d->dpy = dpy;
+  d->literal = get_string_resource (dpy, "textLiteral", "TextLiteral");
+  d->url = get_string_resource (dpy, "textURL", "TextURL");
+
+  return d;
+}
+
+
+void
+textclient_close (text_data *d)
+{
+# ifdef DEBUG
+  fprintf (stderr, "%s: textclient: free\n", progname);
+# endif
+
+  if (d->buf) free (d->buf);
+  if (d->literal) free (d->literal);
+  if (d->url) free (d->url);
+  free (d);
+}
+
+
+/* Returns a copy of the string with some basic HTML entities decoded.
+ */
+static char *
+decode_entities (const char *html)
+{
+  char *ret = (char *) malloc ((strlen(html) * 4) + 1);  // room for UTF8
+  const char *in = html;
+  char *out = ret;
+  *out = 0;
+
+  const struct { const char *c; const char *e; } entities[] = {
+
+    { "amp", "&" },
+    { "lt",  "<" },
+    { "gt",  ">" },
+
+    // Convert Latin1 to UTF8
+    { "nbsp", " " },                   //   160
+    { "iexcl", "\302\241" },           // ¡ 161
+    { "cent", "\302\242" },            // ¢ 162
+    { "pound", "\302\243" },           // £ 163
+    { "curren", "\302\244" },          // ¤ 164
+    { "yen", "\302\245" },             // ¥ 165
+    { "brvbar", "\302\246" },          // ¦ 166
+    { "sect", "\302\247" },            // § 167
+    { "uml", "\302\250" },             // ¨ 168
+    { "copy", "\302\251" },            // © 169
+    { "ordf", "\302\252" },            // ª 170
+    { "laquo", "\302\253" },           // « 171
+    { "not", "\302\254" },             // ¬ 172
+    { "shy", "\302\255" },             // ­ 173
+    { "reg", "\302\256" },             // ® 174
+    { "macr", "\302\257" },            // ¯ 175
+    { "deg", "\302\260" },             // ° 176
+    { "plusmn", "\302\261" },          // ± 177
+    { "sup2", "\302\262" },            // ² 178
+    { "sup3", "\302\263" },            // ³ 179
+    { "acute", "\302\264" },           // ´ 180
+    { "micro", "\302\265" },           // µ 181
+    { "para", "\302\266" },            // ¶ 182
+    { "middot", "\302\267" },          // · 183
+    { "cedil", "\302\270" },           // ¸ 184
+    { "sup1", "\302\271" },            // ¹ 185
+    { "ordm", "\302\272" },            // º 186
+    { "raquo", "\302\273" },           // » 187
+    { "frac14", "\302\274" },          // ¼ 188
+    { "frac12", "\302\275" },          // ½ 189
+    { "frac34", "\302\276" },          // ¾ 190
+    { "iquest", "\302\277" },          // ¿ 191
+    { "Agrave", "\303\200" },          // À 192
+    { "Aacute", "\303\201" },          // Á 193
+    { "Acirc", "\303\202" },           // Â 194
+    { "Atilde", "\303\203" },          // Ã 195
+    { "Auml", "\303\204" },            // Ä 196
+    { "Aring", "\303\205" },           // Å 197
+    { "AElig", "\303\206" },           // Æ 198
+    { "Ccedil", "\303\207" },          // Ç 199
+    { "Egrave", "\303\210" },          // È 200
+    { "Eacute", "\303\211" },          // É 201
+    { "Ecirc", "\303\212" },           // Ê 202
+    { "Euml", "\303\213" },            // Ë 203
+    { "Igrave", "\303\214" },          // Ì 204
+    { "Iacute", "\303\215" },          // Í 205
+    { "Icirc", "\303\216" },           // Î 206
+    { "Iuml", "\303\217" },            // Ï 207
+    { "ETH", "\303\220" },             // Ð 208
+    { "Ntilde", "\303\221" },          // Ñ 209
+    { "Ograve", "\303\222" },          // Ò 210
+    { "Oacute", "\303\223" },          // Ó 211
+    { "Ocirc", "\303\224" },           // Ô 212
+    { "Otilde", "\303\225" },          // Õ 213
+    { "Ouml", "\303\226" },            // Ö 214
+    { "times", "\303\227" },           // × 215
+    { "Oslash", "\303\230" },          // Ø 216
+    { "Ugrave", "\303\231" },          // Ù 217
+    { "Uacute", "\303\232" },          // Ú 218
+    { "Ucirc", "\303\233" },           // Û 219
+    { "Uuml", "\303\234" },            // Ü 220
+    { "Yacute", "\303\235" },          // Ý 221
+    { "THORN", "\303\236" },           // Þ 222
+    { "szlig", "\303\237" },           // ß 223
+    { "agrave", "\303\240" },          // à 224
+    { "aacute", "\303\241" },          // á 225
+    { "acirc", "\303\242" },           // â 226
+    { "atilde", "\303\243" },          // ã 227
+    { "auml", "\303\244" },            // ä 228
+    { "aring", "\303\245" },           // å 229
+    { "aelig", "\303\246" },           // æ 230
+    { "ccedil", "\303\247" },          // ç 231
+    { "egrave", "\303\250" },          // è 232
+    { "eacute", "\303\251" },          // é 233
+    { "ecirc", "\303\252" },           // ê 234
+    { "euml", "\303\253" },            // ë 235
+    { "igrave", "\303\254" },          // ì 236
+    { "iacute", "\303\255" },          // í 237
+    { "icirc", "\303\256" },           // î 238
+    { "iuml", "\303\257" },            // ï 239
+    { "eth", "\303\260" },             // ð 240
+    { "ntilde", "\303\261" },          // ñ 241
+    { "ograve", "\303\262" },          // ò 242
+    { "oacute", "\303\263" },          // ó 243
+    { "ocirc", "\303\264" },           // ô 244
+    { "otilde", "\303\265" },          // õ 245
+    { "ouml", "\303\266" },            // ö 246
+    { "divide", "\303\267" },          // ÷ 247
+    { "oslash", "\303\270" },          // ø 248
+    { "ugrave", "\303\271" },          // ù 249
+    { "uacute", "\303\272" },          // ú 250
+    { "ucirc", "\303\273" },           // û 251
+    { "uuml", "\303\274" },            // ü 252
+    { "yacute", "\303\275" },          // ý 253
+    { "thorn", "\303\276" },           // þ 254
+    { "yuml", "\303\277" },            // ÿ 255
+
+      // And some random others
+    { "bdquo", "\342\200\236" },       // ~
+    { "bull", "\342\200\242" },                // ~
+    { "circ", "\313\206" },            // ~
+    { "cong", "\342\211\205" },                // ~
+    { "empty", "\342\210\205" },       // ~
+    { "emsp", "\342\200\203" },                // ~
+    { "ensp", "\342\200\202" },                // ~
+    { "equiv", "\342\211\241" },       // ~
+    { "frasl", "\342\201\204" },       // ~
+    { "ge", "\342\211\245" },          // ~
+    { "hArr", "\342\207\224" },                // ~
+    { "harr", "\342\206\224" },                // ~
+    { "hellip", "\342\200\246" },      // ~
+    { "lArr", "\342\207\220" },                // ~
+    { "lang", "\342\237\250" },                // ~
+    { "larr", "\342\206\220" },                // ~
+    { "ldquo", "\342\200\234" },       // ~
+    { "le", "\342\211\244" },          // ~
+    { "lowast", "\342\210\227" },      // ~
+    { "loz", "\342\227\212" },         // ~
+    { "lsaquo", "\342\200\271" },      // ~
+    { "lsquo", "\342\200\230" },       // ~
+    { "mdash", "\342\200\224" },       // ~
+    { "minus", "\342\210\222" },       // ~
+    { "ndash", "\342\200\223" },       // ~
+    { "ne", "\342\211\240" },          // ~
+    { "OElig", "\305\222" },           // ~
+    { "oelig", "\305\223" },           // ~
+    { "prime", "\342\200\262" },       // ~
+    { "quot", "\342\200\235" },                // ~
+    { "rArr", "\342\207\222" },                // ~
+    { "rang", "\342\237\251" },                // ~
+    { "rarr", "\342\206\222" },                // ~
+    { "rdquo", "\342\200\235" },       // ~
+    { "rsaquo", "\342\200\272" },      // ~
+    { "rsquo", "\342\200\231" },       // ~
+    { "sbquo", "\342\200\232" },       // ~
+    { "sim", "\342\210\274" },         // ~
+    { "thinsp", "\342\200\211" },      // ~
+    { "tilde", "\313\234" },           // ~
+    { "trade", "\342\204\242" },       // ~
+  };
+
+  while (*in) {
+    if (*in == '&') {
+      int done = 0;
+      if (in[1] == '#' && in[2] == 'x') {                      // &#x41;
+        unsigned long i = 0;
+        in += 2;
+        while ((*in >= '0' && *in <= '9') ||
+               (*in >= 'A' && *in <= 'F') ||
+               (*in >= 'a' && *in <= 'f')) {
+          i = (i * 16) + (*in >= 'a' ? *in - 'a' + 16 :
+                          *in >= 'A' ? *in - 'A' + 16 :
+                          *in - '0');
+          in++;
+        }
+        *out += utf8_encode (i, out, strlen(out));
+        done = 1;
+      } else if (in[1] == '#') {                               // &#65;
+        unsigned long i = 0;
+        in++;
+        while (*in >= '0' && *in <= '9') {
+          i = (i * 10) + (*in - '0');
+          in++;
+        }
+        *out += utf8_encode (i, out, strlen(out));
+        done = 1;
+      } else {
+        int i;
+        for (i = 0; !done && i < countof(entities); i++) {
+          if (!strncmp (in+1, entities[i].c, strlen(entities[i].c))) {
+            strcpy (out, entities[i].e);
+            in  += strlen(entities[i].c) + 1;
+            out += strlen(entities[i].e);
+            done = 1;
+          }
+        }
+      }
+
+      if (done) {
+        if (*in == ';')
+          in++;
+      } else {
+        *out++ = *in++;
+      }
+    } else {
+      *out++ = *in++;
+    }
+  }
+  *out = 0;
+
+  /* Shrink */
+  ret = realloc (ret, out - ret + 1);
+
+  return ret;
+}
+
+
+/* Returns a copy of the HTML string that has been converted to plain text,
+   in UTF8 encoding.  HTML tags are stripped, <BR> and <P> are converted
+   to newlines, and some basic HTML entities are decoded.
+ */
+char *
+textclient_strip_html (const char *html)
+{
+  int tag = 0;
+  int comment = 0;
+  int white = 0;
+  int nl = 0;
+  char *ret = (char *) malloc ((strlen(html) * 4) + 1);  // room for UTF8
+  char *out = ret;
+  *out = 0;
+
+  for (const char *in = html; *in; in++) {
+    if (comment) {
+      if (!strncmp (in, "-->", 3)) {
+        comment = 0;
+      }
+    } else if (tag) {
+      if (*in == '>') {
+        tag = 0;
+      }
+    } else if (*in == '<') {
+      tag = 1;
+      if (!strncmp (in, "<!--", 4)) {
+        comment = 1;
+        tag = 0;
+      } else if (!strncasecmp (in, "<BR", 3)) {
+        *out++ = '\n';
+        white = 1;
+        nl++;
+      } else if (!strncasecmp (in, "<P", 2)) {
+        if (nl < 2) { *out++ = '\n'; nl++; }
+        if (nl < 2) { *out++ = '\n'; nl++; }
+        white = 1;
+      }
+    } else if (*in == ' ' || *in == '\t' || *in == '\r' || *in == '\n') {
+      if (!white && out != html)
+        *out++ = ' ';
+      white = 1;
+    } else {
+      *out++ = *in;
+      white = 0;
+      nl = 0;
+    }
+  }
+  *out = 0;
+
+  {
+    char *ret2 = decode_entities (ret);
+    free (ret);
+    ret = ret2;
+  }
+
+  return ret;
+}
+
+
+static char *
+copy_rss_field (const char *s)
+{
+  if (!s) return 0;
+  while (*s && *s != '>')                      // Skip forward to >
+    s++;
+  if (! *s) return 0;
+  s++;
+
+  if (!strncmp (s, "<![CDATA[", 9)) {          // CDATA quoting
+    s += 9;
+    char *e = strstr (s, "]]");
+    if (e) *e = 0;
+    unsigned long L = strlen (s);
+    char *s2 = (char *) malloc (L+1);
+    memcpy (s2, s, L+1);
+    return s2;
+
+  } else {                                     // Entity-encoded.
+    const char *s2;
+    for (s2 = s; *s2 && *s2 != '<'; s2++)      // Terminate at <
+      ;
+    char *s3 = (char *) malloc (s2 - s + 1);
+    if (! s3) return 0;
+    memcpy (s3, s, s2-s);
+    s3[s2-s] = 0;
+    char *s4 = textclient_strip_html (s3);
+    free (s3);
+    return s4;
+  }
+}
+
+
+static char *
+pick_rss_field (const char *a, const char *b, const char *c, const char *d)
+{
+  // Pick the longest of the fields.
+  char *a2 = copy_rss_field (a);
+  char *b2 = copy_rss_field (b);
+  char *c2 = copy_rss_field (c);
+  char *d2 = copy_rss_field (d);
+  unsigned long al = a2 ? strlen(a2) : 0;
+  unsigned long bl = b2 ? strlen(b2) : 0;
+  unsigned long cl = c2 ? strlen(c2) : 0;
+  unsigned long dl = d2 ? strlen(d2) : 0;
+  char *ret = 0;
+
+  if      (al > bl && al > cl && al > dl) ret = a2;
+  else if (bl > al && bl > cl && bl > dl) ret = b2;
+  else if (cl > al && cl > bl && cl > dl) ret = c2;
+  else ret = d2;
+  if (a2 && a2 != ret) free (a2);
+  if (b2 && b2 != ret) free (b2);
+  if (c2 && c2 != ret) free (c2);
+  if (d2 && d2 != ret) free (d2);
+  return ret;
+}
+
+
+/* Strip some Wikipedia formatting from the string to make it more readable.
+ */
+static void
+strip_wiki (char *text)
+{
+  char *in = text;
+  char *out = text;
+  while (*in) 
+    {
+      if (!strncmp (in, "<!--", 4))            /* <!-- ... --> */
+        {
+          char *e = strstr (in+4, "-->");
+          if (e) in = e + 3;
+        }
+      else if (!strncmp (in, "/*", 2))         /* ... */
+        {
+          char *e = strstr (in+2, "*/");
+          if (e) in = e + 2;
+          else *out++ = *in++;
+        }
+      else if (!strncmp (in, "{{Infobox", 9))  /* {{Infobox ... \n}}\n */
+        {
+          char *e = strstr (in+2, "\n}}");
+          if (e) in = e + 3;
+          else *out++ = *in++;
+        }
+      else if (!strncmp (in, "{{", 2))         /* {{ ...table... }} */
+        {
+          char *e = strstr (in+2, "}}");
+          if (e) in = e + 2;
+          else *out++ = *in++;
+        }
+      else if (!strncmp (in, "{|", 2))         /* {| ...table... |} */
+        {
+          char *e = strstr (in+2, "|}");
+          if (e) in = e + 2;
+          else *out++ = *in++;
+        }
+      else if (!strncmp (in, "|-", 2))         /* |- ...table cell... | */
+        {
+          char *e = strstr (in+2, "|");
+          if (e) in = e + 1;
+          else *out++ = *in++;
+        }
+      else if (!strncmp (in, "<ref", 4))       /* <ref>...</ref> -> "*" */
+        {
+          char *e1 = strstr (in+4, "/>");
+          char *e2 = strstr (in+4, "</ref>");
+          if (e1 && e1 < e2) in = e1 + 2;
+          else if (e2) in = e2 + 6;
+          else *out++ = *in++;
+
+          *out++ = '*';
+        }
+      else if (!strncmp (in, "<", 1))          /* <...> */
+        {
+          char *e = strstr (in+1, ">");
+          if (e) in = e + 1;
+          else *out++ = *in++;
+        }
+      else if (!strncmp (in, "[[", 2))         /* [[ ... ]] */
+        {
+          char *e1 = strstr (in+2, "|");
+          char *e2 = strstr (in+2, "]]");
+          if (e1 && e2 && e1 < e2)             /* [[link|anchor]] */
+            {
+              long L = e2 - e1 - 1;
+              memmove (out, e1+1, L);
+              out += L;
+              in = e2+2;
+            }
+          else if (e2)                         /* [[link]] */
+            {
+              long L = e2 - in - 2;
+              memmove (out, in+2, L);
+              out += L;
+              in = e2+2;
+            }
+          else
+            *out++ = *in++;
+        }
+      else if (!strncmp (in, "[", 1))          /* [ ... ] */
+        {
+          char *e1 = strstr (in+2, " ");
+          char *e2 = strstr (in+2, "]");
+          if (e1 && e2 && e1 < e2)             /* [url anchor] */
+            {
+              long L = e2 - e1 - 1;
+              memmove (out, e1+1, L);
+              out += L;
+              in = e2+2;
+            }
+          else
+            *out++ = *in++;
+        }
+      else if (!strncmp (in, "''''", 4))       /* omit '''' */
+        in += 4;
+      else if (!strncmp (in, "'''", 3))        /* omit ''' */
+        in += 3;
+      else if (!strncmp (in, "''", 2) ||       /* '' or `` or "" -> " */
+               !strncmp (in, "``", 2) ||
+               !strncmp (in, "\"\"", 2))
+        {
+          *out++ = '"';
+          in += 2;
+        }
+      else
+        {
+          *out++ = *in++;
+        }
+    }
+  *out = 0;
+
+  /* Collapse newlines */
+  in = text;
+  out = text;
+  while (*in) 
+    {
+      while (!strncmp(in, "\n\n\n", 3))
+        in++;
+      *out++ = *in++;
+    }
+  *out = 0;
+}
+
+
+/* Returns a copy of the RSS document that has been converted to plain text,
+   in UTF8 encoding.  Rougly, it uses the contents of the <description> field
+   of each <item>, and decodes HTML within it.
+ */
+char *
+textclient_strip_rss (const char *rss)
+{
+  char *ret = malloc (strlen(rss) * 4 + 1);  // room for UTF8
+  char *out = ret;
+  const char *a = 0, *b = 0, *c = 0, *d = 0, *t = 0;
+  int head = 1;
+  int done = 0;
+  int wiki_p = !!strcasestr (rss, "<generator>MediaWiki");
+
+  *out = 0;
+  for (const char *in = rss; *in; in++) {
+    if (*in == '<') {
+      if (!strncasecmp (in, "<item", 5) ||     // New item, dump.
+          !strncasecmp (in, "<entry", 6)) {
+      DONE:
+        head = 0;
+        char *title = copy_rss_field (t);
+        char *body  = pick_rss_field (a, b, c, d);
+
+        a = b = c = d = t = 0;
+
+        if (title && body && !strcmp (title, body)) {
+          free (title);
+          title = 0;
+        }
+
+        if (title) {
+          strcpy (out, title);
+          free (title);
+          out += strlen (out);
+          strcpy (out, "\n\n");
+          out += strlen (out);
+        }
+
+        if (body) {
+          strcpy (out, body);
+          free (body);
+          out += strlen (out);
+          strcpy (out, "<P>");
+          out += strlen (out);
+        }
+
+      } else if (head) {   // still before first <item>
+        ;
+      } else if (!strncasecmp (in, "<title", 6)) {
+        t = in+6;
+      } else if (!strncasecmp (in, "<summary", 8)) {
+        d = in+8;
+      } else if (!strncasecmp (in, "<description", 12)) {
+        a = in+12;
+      } else if (!strncasecmp (in, "<content:encoded", 16)) {
+        c = in+16;
+      } else if (!strncasecmp (in, "<content", 8)) {
+        b = in+8;
+      }
+    }
+  }
+
+  if (! done) {                // Finish off the final item.
+    done = 1;
+    goto DONE;
+  }
+
+  char *ret2 = textclient_strip_html (ret);
+  free (ret);
+  ret = ret2;
+
+  if (wiki_p) {
+    strip_wiki (ret);
+    ret2 = decode_entities (ret);
+    free (ret);
+    ret = ret2;
+  }
+
+  return ret;
+}
+
+
+static void
+wrap_text (char *body, int columns, int max_lines)
+{
+  int col = 0, last_col = 0;
+  char *last_space = 0;
+  int lines = 0;
+  if (! body) return;
+  for (char *p = body; *p; p++) {
+    if (*p == '\r' || *p == '\n' || *p == ' ' || *p == '\t') {
+      if (col > columns && last_space) {
+        *last_space = '\n';
+        col = col - last_col;
+      }
+      last_space = p;
+      last_col = col;
+    }
+    if (*p == '\r' || *p == '\n') {
+      col = 0;
+      last_col = 0;
+      last_space = 0;
+      lines++;
+      if (max_lines && lines >= max_lines)
+        {
+          *p = 0;
+          break;
+        }
+    } else {
+      col++;
+    }
+  }
+}
+
+
+static void
+rewrap_text (char *body, int columns)
+{
+  if (! body) return;
+  for (char *p = body; *p; p++) {
+    if (*p == '\n') {
+      if (p[1] == '\n')
+        p++;
+      else
+        *p = ' ';
+    }
+  }
+  wrap_text (body, columns, 0);
+}
+
+
+
+static void
+strip_backslashes (char *s)
+{
+  char *out = s;
+  for (char *in = s; *in; in++) {
+    if (*in == '\\') {
+      in++;
+      if      (*in == 'n') *out++ = '\n';
+      else if (*in == 'r') *out++ = '\r';
+      else if (*in == 't') *out++ = '\t';
+      else *out++ = *in;
+    } else {
+      *out++ = *in;
+    }
+  }
+  *out = 0;
+}
+
+
+/* Load the raw body of a URL, and convert it to plain text.
+ */
+static char *
+mobile_url_text (Display *dpy, const char *url)
+{
+  char *body = textclient_mobile_url_string (dpy, url);
+  enum { RSS, HTML, TEXT } type;
+  if (!body)
+    return NULL;
+
+  if (!strncasecmp (body, "<?xml", 5) ||
+      !strncasecmp (body, "<!doctype rss", 13))
+    type = RSS;
+  else if (!strncasecmp (body, "<!doctype html", 14) ||
+           !strncasecmp (body, "<html", 5) ||
+           !strncasecmp (body, "<head", 5))
+    type = HTML;
+  else if (strcasestr (body, "<base") ||
+           strcasestr (body, "<body") ||
+           strcasestr (body, "<script") ||
+           strcasestr (body, "<style") ||
+           strcasestr (body, "<a href"))
+    type = HTML;
+  else if (strcasestr (body, "<channel") ||
+           strcasestr (body, "<generator") ||
+           strcasestr (body, "<description") ||
+           strcasestr (body, "<content") ||
+           strcasestr (body, "<feed") ||
+           strcasestr (body, "<entry"))
+    type = RSS;
+  else
+    type = TEXT;
+
+  char *body2 = 0;
+
+  switch (type) {
+  case HTML: body2 = textclient_strip_html (body); break;
+  case RSS:  body2 = textclient_strip_rss (body);  break;
+  case TEXT: break;
+  default: abort(); break;
+  }
+
+  if (body2) {
+    free (body);
+    return body2;
+  } else {
+    return body;
+  }
+}
+
+
+int
+textclient_getc (text_data *d)
+{
+  if (!d->fp || !*d->fp) {
+    if (d->buf) {
+      free (d->buf);
+      d->buf = 0;
+      d->fp = 0;
+    }
+    switch (d->mode) {
+    case DATE: DATE:
+      d->buf = textclient_mobile_date_string();
+      break;
+    case LITERAL:
+      if (!d->literal || !*d->literal)
+        goto DATE;
+      d->buf = (char *) malloc (strlen (d->literal) + 3);
+      strcpy (d->buf, d->literal);
+      strcat (d->buf, "\n");
+      strip_backslashes (d->buf);
+      d->fp = d->buf;
+      break;
+    case URL:
+      if (!d->url || !*d->url)
+        goto DATE;
+      d->buf = mobile_url_text (d->dpy, d->url);
+      break;
+    default:
+      abort();
+    }
+    if (d->columns > 10)
+      wrap_text (d->buf, d->columns, d->max_lines);
+    d->fp = d->buf;
+  }
+
+  if (!d->fp || !*d->fp)
+    return -1;
+
+  unsigned char c = (unsigned char) *d->fp++;
+  return (int) c;
+}
+
+
+Bool
+textclient_putc (text_data *d, XKeyEvent *k)
+{
+  return False;
+}
+
+
+void
+textclient_reshape (text_data *d,
+                    int pix_w, int pix_h,
+                    int char_w, int char_h,
+                    int max_lines)
+{
+  d->columns = char_w;
+  d->max_lines = max_lines;
+  rewrap_text (d->buf, d->columns);
+}
+
+
+#endif /* whole file */
index abb6f1191267a51089d857ea58e93af73752a2a3..f0d7fe898d65f82877ad862db9aeba4b7c4c0d2d 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2012-2014 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2012-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
  * usePty: bool                Whether to run the command interactively.
  * metaSendsESC: bool  Whether to send Alt-x as ESC x in pty-mode.
  * swapBSDEL: bool     Swap Backspace and Delete in pty-mode.
+ *
+ * On iOS and Android, textclient-mobile.c is used instead.
  */
 
 #include "utils.h"
 
-#ifndef USE_IPHONE /* whole file -- see OSX/iostextclient.m */
+#if !defined(USE_IPHONE) && !defined(HAVE_ANDROID)  /* whole file */
 
 #include "textclient.h"
 #include "resources.h"
@@ -50,6 +52,9 @@
 # ifdef HAVE_UTIL_H
 #  include <util.h>
 # endif
+# ifdef HAVE_SYS_TERMIOS_H
+#  include <sys/termios.h>
+# endif
 #endif /* HAVE_FORKPTY */
 
 #undef DEBUG
index 4f9a2bd609f7cd7eb4c441d11df9a92f777f55c9..0d9aca3b88436c761758078690b4c356d9d110b1 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2012-2014 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2012-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
@@ -29,4 +29,11 @@ extern void textclient_reshape (text_data *,
 extern int textclient_getc (text_data *);
 extern Bool textclient_putc (text_data *, XKeyEvent *);
 
+# if defined(USE_IPHONE) || defined(HAVE_ANDROID)
+extern char *textclient_mobile_date_string (void);
+extern char *textclient_mobile_url_string (Display *, const char *url);
+extern char *textclient_strip_html (const char *);
+extern char *textclient_strip_rss (const char *);
+# endif
+
 #endif /* __TEXTCLIENT_H__ */
index 6852a2138fa2e64f8d13700a4f122a39aa688976..5ad5d47cad8efde111b5f2ba15564023fa11ded8 100644 (file)
@@ -13,11 +13,6 @@ software for any purpose.  It is provided "as is" without express or
 implied warranty.
 */
 
-#include "thread_util.h"
-
-#include "aligned_malloc.h"
-#include "resources.h"
-
 #if HAVE_CONFIG_H
 #      include "config.h"
 #endif
@@ -42,6 +37,11 @@ implied warranty.
 #      include <inttypes.h>
 #endif
 
+#include "thread_util.h"
+
+#include "aligned_malloc.h"
+#include "resources.h"
+
 #define IS_POWER_OF_2(x) ((x) > 0 && !((x) & ((x) - 1)))
 
 /*
index b8c88031dce6af0d78b28f8d35b10f7fad233824..6dff8de688bc6d67463123c5a96a5e8e8500ee80 100644 (file)
@@ -83,7 +83,7 @@ implied warranty.
 #      include <unistd.h>
 #endif
 
-#ifdef HAVE_COCOA
+#if defined HAVE_JWXYZ
 #      include "jwxyz.h"
 #else
 #      include <X11/Xlib.h>
index 2fb57e789f34f337fd518ef62d5c89c7aa8aa80e..1f8fcc1393f0ce0b3a79b343f08c9f8f5d0f6ab7 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2014-2015 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2014-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
 #include <stdio.h>
 #include <string.h>
 
-#ifdef HAVE_COCOA
+#ifdef HAVE_JWXYZ
 # include "jwxyz.h"
-# elif defined(HAVE_ANDROID)
-# include "jwxyz.h"
-#else /* !HAVE_COCOA */
+#else /* !HAVE_JWXYZ */
 # include <X11/Xlib.h>
 #endif
 
@@ -239,12 +237,12 @@ utf8_to_XChar2b (const char *string, int *length_ret)
   out->byte1 = 0;
   out->byte2 = 0;
 
-  /* shrink */
-  c2b = (XChar2b *) realloc (c2b, (out - c2b + 1) * sizeof(*c2b));
-
   if (length_ret)
     *length_ret = (int) (out - c2b);
 
+  /* shrink */
+  c2b = (XChar2b *) realloc (c2b, (out - c2b + 1) * sizeof(*c2b));
+
   return c2b;
 }
 
@@ -275,7 +273,12 @@ utf8_split (const char *string, int *length_ret)
       /* If this is a Combining Diacritical, append it to the previous
          character. E.g., "y\314\206\314\206" is one string, not three.
        */
-      if (i > 1 && uc >= 0x300 && uc <= 0x36F)
+      if (i > 1 && 
+          ((uc >=  0x300 && uc <=  0x36F) || /* Combining Diacritical */
+           (uc >= 0x1AB0 && uc <= 0x1AFF) || /* Combining Diacritical Ext. */
+           (uc >= 0x1DC0 && uc <= 0x1DFF) || /* Combining Diacritical Supp. */
+           (uc >= 0x20D0 && uc <= 0x20FF) || /* Combining Diacritical Sym. */
+           (uc >= 0xFE20 && uc <= 0xFE2F)))  /* Combining Half Marks */
         {
           long L1 = strlen(ret[i-2]);
           long L2 = strlen(ret[i-1]);
@@ -290,12 +293,12 @@ utf8_split (const char *string, int *length_ret)
     }
   ret[i] = 0;
 
-  /* shrink */
-  ret = (char **) realloc (ret, (i+1) * sizeof(*ret));
-
   if (length_ret)
     *length_ret = i;
 
+  /* shrink */
+  ret = (char **) realloc (ret, (i+1) * sizeof(*ret));
+
   return ret;
 }
 
@@ -330,13 +333,14 @@ XChar2b_to_utf8 (const XChar2b *in, int *length_ret)
     }
   *out = 0;
 
-  /* shrink */
   out_len = (int) (out - utf8 + 1);
-  utf8 = (char *) realloc (utf8, out_len);
 
   if (length_ret)
     *length_ret = out_len;
 
+  /* shrink */
+  utf8 = (char *) realloc (utf8, out_len);
+
   return utf8;
 }
 
@@ -363,7 +367,16 @@ utf8_to_latin1 (const char *string, Bool ascii_p)
       if (uc == '\240')        /* &nbsp; */
         uc = ' ';
       else if (uc >= 0x300 && uc <= 0x36F)
-        uc = 0;                /* Discard "Unicode Combining Diacriticals Block" */
+        uc = 0;                /* Discard "Combining Diacritical Marks" */
+      else if (uc >= 0x1AB0 && uc <= 0x1AFF)
+        uc = 0;                /* Discard "Combining Diacritical Marks Extended" */
+      else if (uc >= 0x1DC0 && uc <= 0x1DFF)
+        uc = 0;                /* Discard "Combining Diacritical Marks Supplement" */
+      else if (uc >= 0x20D0 && uc <= 0x20FF)
+        uc = 0;                /* Discard "Combining Diacritical Marks for Symbols" */
+      else if (uc >= 0xFE20 && uc <= 0xFE2F)
+        uc = 0;                /* Discard "Combining Half Marks" */
+
       else if (uc > 0xFF)
         switch (uc) {
 
index 52c12e04a9935c717cfff9f3fc7f149a8522c7e0..09b4da8662c99c15d1dd1bbd1d0903ad4796fbb2 100644 (file)
 #include <string.h>
 #include <math.h>
 
-#if defined(HAVE_COCOA) || defined(HAVE_ANDROID)
+#ifdef HAVE_JWXYZ
 # include "jwxyz.h"
 #else /* real X11 */
 # include <X11/Xlib.h>
 # include <X11/Xutil.h>
 # include <X11/Xos.h>
-#endif /* !HAVE_COCOA */
+#endif /* !HAVE_JWXYZ */
index d9923dd14dfc50a2c4bc7cd53c3ee1a6463d422e..eeea0dc654436fd52732d1164ac9b63f12a44f84 100644 (file)
@@ -1,2 +1,2 @@
 static const char screensaver_id[] =
-       "@(#)xscreensaver 5.34 (24-Oct-2015), by Jamie Zawinski (jwz@jwz.org)";
+       "@(#)xscreensaver 5.35 (24-May-2016), by Jamie Zawinski (jwz@jwz.org)";
index f0cd20db5390831ccf0df26d4bbd1abd1ca0c1f1..89b4f33e69f3d7af84fc2a5931ae594c1916a47e 100644 (file)
 #include "visual.h"
 
 #include <string.h>
+#ifndef HAVE_ANDROID
 #include <X11/Xutil.h>
+#else
+#include "../android/android-visual.h"
+#endif
 
 extern char *progname;
 
-
 #ifndef isupper
 # define isupper(c)  ((c) >= 'A' && (c) <= 'Z')
 #endif
index 0b9b7ae5b6a2c52ada2c92094553db09255e4903..0c933b3b4185cc68678ba8aba4ab8be87973e429 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2014-2015 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2014-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
@@ -207,7 +207,7 @@ XftColorAllocValue (Display *dpy,
       result->pixel = (((color->red   >> (16 - red_len))   << red_shift)   |
                        ((color->green >> (16 - green_len)) << green_shift) |
                        ((color->blue  >> (16 - blue_len))  << blue_shift));
-# ifdef HAVE_COCOA
+# ifdef HAVE_JWXYZ
       result->pixel |= BlackPixel(dpy, 0);  /* alpha */
 # endif
     }
index 632dd1eb27fce1e1b57f42a1602686cae3555764..6ea9687584e66d54122ab40729be96cab0830780 100644 (file)
@@ -1,5 +1,5 @@
 %define        name xscreensaver
-%define        version 5.34
+%define        version 5.35
 
 Summary:       X screen saver and locker
 Name:          %{name}
@@ -8,8 +8,8 @@ Release:        1
 Epoch:         1
 License:       BSD
 Group:         Amusements/Graphics
-URL:           http://www.jwz.org/xscreensaver/
-Source0:       http://www.jwz.org/xscreensaver/xscreensaver-%{version}.tar.gz
+URL:           https://www.jwz.org/xscreensaver/
+Source0:       https://www.jwz.org/xscreensaver/xscreensaver-%{version}.tar.gz
 Vendor:                Jamie Zawinski <jwz@jwz.org>
 Buildroot:     %{_tmppath}/%{name}-root