]> git.hungrycats.org Git - xscreensaver/commitdiff
From http://www.jwz.org/xscreensaver/xscreensaver-5.44.tar.gz
authorZygo Blaxell <zblaxell@waya.furryterror.org>
Sat, 21 Mar 2020 07:44:35 +0000 (03:44 -0400)
committerZygo Blaxell <zblaxell@waya.furryterror.org>
Sat, 21 Mar 2020 07:46:09 +0000 (03:46 -0400)
-rw-rw-r-- 1 zblaxell zblaxell 27001826 Mar 20 21:50 xscreensaver-5.44.tar.gz
3e93aa745aa986cf521de31b6e731f990302c920  xscreensaver-5.44.tar.gz

142 files changed:
Makefile.in
OSX/LaunchScreen.storyboard [new file with mode: 0644]
OSX/LaunchScreen.xib [deleted file]
OSX/Makefile
OSX/Media-iOS.xcassets/LaunchImage.launchimage/1242x2208.png [deleted file]
OSX/Media-iOS.xcassets/LaunchImage.launchimage/640x1136.png [deleted file]
OSX/Media-iOS.xcassets/LaunchImage.launchimage/640x960.png [deleted file]
OSX/Media-iOS.xcassets/LaunchImage.launchimage/750x1334.png [deleted file]
OSX/Media-iOS.xcassets/LaunchImage.launchimage/Contents.json [deleted file]
OSX/SaverListController.h
OSX/SaverListController.m
OSX/SaverRunner.h
OSX/SaverRunner.m
OSX/SaverRunner.plist
OSX/Updater.plist
OSX/XScreenSaver.plist
OSX/XScreenSaverConfigSheet.m
OSX/XScreenSaverView.m
OSX/bindist.rtf
OSX/build-fntable.pl
OSX/en.lproj/SaverRunner.nib/designable.nib
OSX/en.lproj/SaverRunner.nib/keyedobjects.nib
OSX/grabclient-ios.m
OSX/iSaverRunner.plist
OSX/icmp-warning.pl
OSX/installer.sh
OSX/ios-function-table.m
OSX/textclient-ios.m
OSX/updates.pl
OSX/xscreensaver.xcodeproj/project.pbxproj
README
README.hacking
android/Makefile
android/README
android/build.gradle
android/gradle/wrapper/gradle-wrapper.properties
android/local.properties [deleted file]
android/xscreensaver/.idea/caches/build_file_checksums.ser [deleted file]
android/xscreensaver/.idea/codeStyles/Project.xml [deleted file]
android/xscreensaver/.idea/compiler.xml [deleted file]
android/xscreensaver/.idea/gradle.xml [deleted file]
android/xscreensaver/.idea/libraries/Gradle__android_arch_core_common_1_1_0_jar.xml [deleted file]
android/xscreensaver/.idea/libraries/Gradle__android_arch_core_runtime_1_1_0.xml [deleted file]
android/xscreensaver/.idea/libraries/Gradle__android_arch_lifecycle_common_1_1_0_jar.xml [deleted file]
android/xscreensaver/.idea/libraries/Gradle__android_arch_lifecycle_livedata_core_1_1_0.xml [deleted file]
android/xscreensaver/.idea/libraries/Gradle__android_arch_lifecycle_runtime_1_1_0.xml [deleted file]
android/xscreensaver/.idea/libraries/Gradle__android_arch_lifecycle_viewmodel_1_1_0.xml [deleted file]
android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_annotations_27_1_1_jar.xml [deleted file]
android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_compat_27_1_1.xml [deleted file]
android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_core_ui_27_1_1.xml [deleted file]
android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_core_utils_27_1_1.xml [deleted file]
android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_fragment_27_1_1.xml [deleted file]
android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_media_compat_27_1_1.xml [deleted file]
android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_v4_27_1_1.xml [deleted file]
android/xscreensaver/.idea/misc.xml [deleted file]
android/xscreensaver/.idea/modules.xml [deleted file]
android/xscreensaver/.idea/runConfigurations.xml [deleted file]
android/xscreensaver/.idea/workspace.xml [deleted file]
android/xscreensaver/build.gradle
android/xscreensaver/gradle/wrapper/gradle-wrapper.properties
android/xscreensaver/local.properties [deleted file]
android/xscreensaver/xscreensaver.iml
driver/Makefile.in
driver/XScreenSaver.ad.in
driver/XScreenSaver_ad.h
driver/demo-Gtk.c
driver/lock.c
driver/passwd.c
driver/prefs.c
driver/subprocs.c
driver/timers.c
driver/types.h
driver/windows.c
driver/xscreensaver-getimage-file
driver/xscreensaver-text
driver/xscreensaver.c
hacks/Makefile.in
hacks/analogtv-cli.c
hacks/barcode.c
hacks/bsod.c
hacks/compile_axp.com
hacks/compile_decc.com
hacks/config/README
hacks/config/bsod.xml
hacks/config/deepstars.xml
hacks/config/dnalogo.xml
hacks/config/etruscanvenus.xml [new file with mode: 0644]
hacks/config/gibson.xml [new file with mode: 0644]
hacks/config/hypertorus.xml
hacks/config/klein.xml
hacks/config/projectiveplane.xml
hacks/config/razzledazzle.xml
hacks/config/romanboy.xml
hacks/config/scooter.xml [new file with mode: 0644]
hacks/drift.c
hacks/eruption.c
hacks/filmleader.c
hacks/fireworkx.c
hacks/glx/Makefile.in
hacks/glx/deepstars.c
hacks/glx/etruscanvenus.c [new file with mode: 0644]
hacks/glx/etruscanvenus.man [new file with mode: 0644]
hacks/glx/gibson.c [new file with mode: 0644]
hacks/glx/gibson.man [new file with mode: 0644]
hacks/glx/glhanoi.c
hacks/glx/glmatrix.c
hacks/glx/gravitywell.c
hacks/glx/hypertorus.c
hacks/glx/hypertorus.man
hacks/glx/klein.c
hacks/glx/klein.man
hacks/glx/polytopes.c
hacks/glx/projectiveplane.c
hacks/glx/projectiveplane.man
hacks/glx/romanboy.c
hacks/glx/romanboy.man
hacks/glx/sonar-icmp.c
hacks/glx/sonar.c
hacks/glx/starwars.c
hacks/halftone.c
hacks/halo.c
hacks/images/Makefile
hacks/images/Makefile.in
hacks/moire2.c
hacks/munch.c
hacks/munge-ad.pl
hacks/rd-bomb.c
hacks/recanim.c
hacks/scooter.c [new file with mode: 0644]
hacks/scooter.man [new file with mode: 0644]
hacks/screenhack.c
hacks/webcollage
hacks/xlockmore.c
hacks/xlyap.c
hacks/xmatrix.c
jwxyz/jwxyz-android.c
jwxyz/jwxyz-gl.c
jwxyz/jwxyzI.h
po/POTFILES.in
setup.com
utils/version.h
xscreensaver.spec

index e0795b2f52fef72cff54a2e3cf9a9c8bb900a272..52f1b4f0bc4505d03bd44ffd97b9a1f3b29b215f 100644 (file)
@@ -69,6 +69,10 @@ tar::
   rm -f configure ;                                                        \
   $(MAKE2) configure ;                                                     \
   $(MAKE2) version-date distdepend ;                                       \
+  $(MAKE2) _tar
+
+_tar:
+       @                                                                   \
   VERS=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ]*\).*/\1/p' utils/version.h` ;  \
   NAME="xscreensaver-$$VERS" ;                                             \
   rm -rf $$NAME ; ln -s . $$NAME ;                                         \
diff --git a/OSX/LaunchScreen.storyboard b/OSX/LaunchScreen.storyboard
new file mode 100644 (file)
index 0000000..bb1a370
--- /dev/null
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14868" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
+    <device id="retina6_1" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14824"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <scenes>
+        <!--View Controller-->
+        <scene sceneID="EHf-IW-A2E">
+            <objects>
+                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
+                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
+                        <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <subviews>
+                            <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="obG-Y5-kRd">
+                                <rect key="frame" x="0.0" y="876" width="414" height="0.0"/>
+                                <fontDescription key="fontDescription" type="system" pointSize="17"/>
+                                <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                        </subviews>
+                        <color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                        <constraints>
+                            <constraint firstItem="Bcu-3y-fUS" firstAttribute="centerX" secondItem="obG-Y5-kRd" secondAttribute="centerX" id="5cz-MP-9tL"/>
+                            <constraint firstItem="obG-Y5-kRd" firstAttribute="leading" secondItem="Bcu-3y-fUS" secondAttribute="leading" constant="20" symbolic="YES" id="SfN-ll-jLj"/>
+                            <constraint firstAttribute="bottom" secondItem="obG-Y5-kRd" secondAttribute="bottom" constant="20" id="Y44-ml-fuU"/>
+                        </constraints>
+                        <viewLayoutGuide key="safeArea" id="Bcu-3y-fUS"/>
+                    </view>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="53" y="375"/>
+        </scene>
+    </scenes>
+</document>
diff --git a/OSX/LaunchScreen.xib b/OSX/LaunchScreen.xib
deleted file mode 100644 (file)
index 15cdbc5..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES">
-    <device id="retina4_7" orientation="portrait">
-        <adaptation id="fullscreen"/>
-    </device>
-    <dependencies>
-        <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
-        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
-    </dependencies>
-    <objects>
-        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
-        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
-        <view contentMode="scaleToFill" id="iN0-l3-epB">
-            <rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
-            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-            <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-            <nil key="simulatedStatusBarMetrics"/>
-            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
-            <point key="canvasLocation" x="404" y="445"/>
-        </view>
-    </objects>
-</document>
index 4f2312b3c959985e4dd45a7f65be5f4a39953321..ca0ed5f03c70b64e184e0179c37142b59780d1f1 100644 (file)
@@ -19,6 +19,10 @@ XCODEBUILD = $(XCODE_APP)/Contents/Developer/usr/bin/xcodebuild
 SETFILE    = $(XCODE_APP)/Contents/Developer/Tools/SetFile
 SETICON    = ./seticon.pl
 
+# Using $(MAKE) directly means the shell executes things even with "make -n"
+MAKE2 = $(MAKE)
+
+
 default: release
 all: debug release
 
@@ -30,7 +34,8 @@ distclean:
        -rm -f config.status config.cache config.log \
          *.bak *.rej TAGS *~ "#"*
        -rm -rf autom4te*.cache
-       -rm -rf build Sparkle.framework
+       -rm -rf build
+#      -rm -rf Sparkle.framework
 
 distdepend:: Sparkle.framework
 distdepend:: update_plist_version
@@ -228,7 +233,7 @@ update_plist_version:
 
 updates.xml::
        ./updates.pl xscreensaver ../README ../archive ~/www/xscreensaver
-       @$(MAKE) $(MAKEFLAGS) test_sig
+       @$(MAKE2) test_sig
 
 test_sig::
        @                                                                   \
@@ -312,7 +317,7 @@ _dmg::
   DST="$$STAGE/Screen Savers" ;                                                      \
   PKG="$$STAGE/Install Everything.pkg" ;                                     \
   rm -f "$$DMG" ;                                                            \
-  rm -rf "$$STAGE" ;                                                         \
+  sudo rm -rf "$$STAGE" ;                                                    \
   echo + mkdir -p "$$DST" ;                                                  \
          mkdir -p "$$DST" ;                                                  \
                                                                              \
@@ -345,6 +350,10 @@ _dmg::
    fi ;                                                                              \
   done ;                                                                     \
                                                                              \
+  true codesign --force --sign $(CERT2) "$$DST/"*.app/Contents/Resources/*.saver ; \
+  rm -rf "$$DST/"*.app/Contents/Resources/*.saver/Contents/_CodeSignature ;   \
+  codesign --force --sign $(CERT2) "$$DST/"*.app ;                           \
+                                                                             \
   set -x ;                                                                   \
   cp -p bindist.rtf "$$STAGE/Read Me.rtf" ;                                  \
   cp -p build/Release/installer.pkg "$$PKG" ;                                \
@@ -364,6 +373,11 @@ _dmg::
   mv "$$STAGE/bindist.webloc"  "$$STAGE/Get the iPhone:iPad Version.webloc" ; \
   mv "$$STAGE/bindist2.webloc" "$$STAGE/Get the Android Version.webloc" ;     \
                                                                              \
+  echo Fuck this shit. ;                                                     \
+  rm -r "$$DST"/Apple2.app ;                                                 \
+  rm -r "$$DST"/Phosphor.app ;                                               \
+  rm -r "$$DST"/WebCollage.saver ;                                           \
+                                                                             \
   set +x ;                                                                   \
                                                                              \
   echo "Chowning..." ;                                                       \
@@ -372,7 +386,7 @@ _dmg::
   echo "Checking signatures..." ;                                            \
   spctl --assess --type install "$$PKG" ;                                    \
   spctl --assess --type execute "$$SRC/XScreenSaverUpdater.app" ;            \
-  spctl --assess --type execute "$$DST/"*.app ;                                      \
+  true spctl --assess --type execute "$$DST/"*.app ;                         \
   spctl --assess --type install "$$DST/"*.saver ;                            \
   set -x ;                                                                   \
                                                                              \
@@ -380,7 +394,7 @@ _dmg::
     -hfs-openfolder "$$STAGE" "$$STAGE" -o "$$TMPDMG" ;                              \
   echo "Chowning back and deleting..." ;                                     \
   sudo chown -R `whoami` "$$STAGE/"* ;                                       \
-  rm -rf "$$STAGE" ;                                                         \
+  sudo rm -rf "$$STAGE" ;                                                    \
                                                                              \
   hdiutil convert -quiet -ov -format UDBZ -imagekey zlib-level=9             \
     "$$TMPDMG" -o "$$DMG" ;                                                  \
@@ -391,7 +405,7 @@ _dmg::
   spctl --assess --type install "$$DMG" ;                                    \
                                                                              \
   ls -ldhgF "$$DMG" ;                                                        \
-  $(MAKE) $(MAKEFLAGS) notarize ;                                            \
+  $(MAKE2) notarize ;                                                        \
 
 
 # To set up notarization:
@@ -425,7 +439,7 @@ notarize::
     --file "$$DMG" $(NOTARGS) ;                                                      \
   echo "" ;                                                                  \
   sleep 3 ;                                                                  \
-  $(MAKE) $(MAKEFLAGS) notarize_wait staple updates.xml
+  $(MAKE2) notarize_wait staple updates.xml
 
 notarize_wait::
        @TODAY=`date +%Y-%m-%d` ;                                             \
diff --git a/OSX/Media-iOS.xcassets/LaunchImage.launchimage/1242x2208.png b/OSX/Media-iOS.xcassets/LaunchImage.launchimage/1242x2208.png
deleted file mode 100644 (file)
index 2f3cd23..0000000
Binary files a/OSX/Media-iOS.xcassets/LaunchImage.launchimage/1242x2208.png and /dev/null differ
diff --git a/OSX/Media-iOS.xcassets/LaunchImage.launchimage/640x1136.png b/OSX/Media-iOS.xcassets/LaunchImage.launchimage/640x1136.png
deleted file mode 100644 (file)
index 6763abe..0000000
Binary files a/OSX/Media-iOS.xcassets/LaunchImage.launchimage/640x1136.png and /dev/null differ
diff --git a/OSX/Media-iOS.xcassets/LaunchImage.launchimage/640x960.png b/OSX/Media-iOS.xcassets/LaunchImage.launchimage/640x960.png
deleted file mode 100644 (file)
index 0bfc1a9..0000000
Binary files a/OSX/Media-iOS.xcassets/LaunchImage.launchimage/640x960.png and /dev/null differ
diff --git a/OSX/Media-iOS.xcassets/LaunchImage.launchimage/750x1334.png b/OSX/Media-iOS.xcassets/LaunchImage.launchimage/750x1334.png
deleted file mode 100644 (file)
index 4ec452d..0000000
Binary files a/OSX/Media-iOS.xcassets/LaunchImage.launchimage/750x1334.png and /dev/null differ
diff --git a/OSX/Media-iOS.xcassets/LaunchImage.launchimage/Contents.json b/OSX/Media-iOS.xcassets/LaunchImage.launchimage/Contents.json
deleted file mode 100644 (file)
index bc0812f..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-{
-  "images" : [
-    {
-      "extent" : "full-screen",
-      "idiom" : "iphone",
-      "subtype" : "736h",
-      "filename" : "1242x2208.png",
-      "minimum-system-version" : "8.0",
-      "orientation" : "portrait",
-      "scale" : "3x"
-    },
-    {
-      "extent" : "full-screen",
-      "idiom" : "iphone",
-      "subtype" : "667h",
-      "filename" : "750x1334.png",
-      "minimum-system-version" : "8.0",
-      "orientation" : "portrait",
-      "scale" : "2x"
-    },
-    {
-      "orientation" : "portrait",
-      "idiom" : "iphone",
-      "filename" : "640x960.png",
-      "extent" : "full-screen",
-      "minimum-system-version" : "7.0",
-      "scale" : "2x"
-    },
-    {
-      "extent" : "full-screen",
-      "idiom" : "iphone",
-      "subtype" : "retina4",
-      "filename" : "640x1136.png",
-      "minimum-system-version" : "7.0",
-      "orientation" : "portrait",
-      "scale" : "2x"
-    },
-    {
-      "orientation" : "portrait",
-      "idiom" : "iphone",
-      "filename" : "640x1136.png",
-      "extent" : "full-screen",
-      "subtype" : "retina4",
-      "scale" : "2x"
-    }
-  ],
-  "info" : {
-    "version" : 1,
-    "author" : "xcode"
-  }
-}
\ No newline at end of file
index 9b46133517ccecc823f3d17b437798d4fc6f4c21..421ea2e46de9473aeee15d2ea7870baac9595ebd 100644 (file)
 
 @interface SaverListController : UITableViewController <UISearchBarDelegate> {
 
+  UIView *v;
+  UILabel *label1;
+  UILabel *label2;
+  UISearchBar *search;
+
   int active_section_count;
   NSMutableArray *list_by_letter[26];  // 27 to get "#" after "Z".
   NSMutableArray *letter_sections;
index 71b5fb5e5026af00c67b2d063ec66ed1ace8e292..ae91d16dfa951f73cf68335e31ac4e90d7b7a4e2 100644 (file)
@@ -51,7 +51,7 @@
                         [year stringByAppendingString:
                                 @" Jamie Zawinski <jwz@jwz.org>"]];
 
-  UIView *v = [[UIView alloc] initWithFrame:CGRectZero];
+  v = [[UIView alloc] initWithFrame:CGRectZero];
 
   // The "go to web page" button on the right
 
@@ -72,8 +72,8 @@
 
   // The title bar
 
-  UILabel *label1 = [[UILabel alloc] initWithFrame:CGRectZero];
-  UILabel *label2 = [[UILabel alloc] initWithFrame:CGRectZero];
+  label1 = [[UILabel alloc] initWithFrame:CGRectZero];
+  label2 = [[UILabel alloc] initWithFrame:CGRectZero];
   [label1 setText: line1];
   [label2 setText: line2];
   [label1 setBackgroundColor:[UIColor clearColor]];
   [label1 sizeToFit];
   [label2 sizeToFit];
 
-  CGRect r1 = [label1 frame];
-  CGRect r2 = [label2 frame];
-  CGRect r3 = r2;
+  label2.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
 
-  CGRect win = [self view].frame;
-  if (win.size.width > 414 && win.size.height > 414) {         // iPad
-    [label1 setTextAlignment: NSTextAlignmentLeft];
-    [label2 setTextAlignment: NSTextAlignmentRight];
-    label2.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
-    r3.size.width = win.size.width;
-    r1 = r3;
-    r1.origin.x   += 6;
-    r1.size.width -= 12;
-    r2 = r1;
-
-  } else {                                                     // iPhone
-    r3.size.width = win.size.width; // force it to be flush-left
-    [label1 setTextAlignment: NSTextAlignmentLeft];
-    [label2 setTextAlignment: NSTextAlignmentLeft];
-    r1.origin.y = -1;    // make it fit in landscape
-    r2.origin.y = r1.origin.y + r1.size.height - 2;
-    r3.size.height = r1.size.height + r2.size.height;
-  }
   v.autoresizingMask = UIViewAutoresizingFlexibleWidth;
-  [label1 setFrame:r1];
-  [label2 setFrame:r2];
-  [v setFrame:r3];
+  [v setFrame:CGRectMake(0, 0, self.view.frame.size.width, 0)];
 
   [v addSubview:label1];
   [v addSubview:label2];
 
   self.navigationItem.titleView = v;
 
-  win.origin.x = 0;
-  win.origin.y = 0;
-  win.size.height = 44; // #### This cannot possibly be right.
-  UISearchBar *search = [[UISearchBar alloc] initWithFrame:win];
+  search = [[UISearchBar alloc] init];
   search.delegate = self;
   search.placeholder = NSLocalizedString(@"Search...", @"");
   self.tableView.tableHeaderView = search;
 # endif
 }
 
+- (void)viewWillLayoutSubviews
+{
+  CGRect r1 = [label1 frame];
+  CGRect r2 = [label2 frame];
+  CGRect r3 = [v frame];
+
+  CGRect win = [self view].frame;
+  if (r3.size.width > 385) {
+    [label1 setTextAlignment: NSTextAlignmentLeft];
+    [label2 setTextAlignment: NSTextAlignmentRight];
+    r1.origin     = CGPointMake(6, 0);
+    r1.size.width = r3.size.width - 12;
+    r2 = r1;
+    r3.size.height = r2.size.height;
+
+  } else {
+    [label1 setTextAlignment: NSTextAlignmentLeft];
+    [label2 setTextAlignment: NSTextAlignmentLeft];
+    r1.origin = CGPointMake(0, -1);    // make it fit in landscape
+    r1.size.width = r3.size.width;
+    r2.origin = CGPointMake(0, r1.origin.y + r1.size.height - 2);
+    r2.size.width = r3.size.width;
+    r3.size.height = r1.size.height + r2.size.height;
+  }
+
+  r3.size.width = win.size.width;
+
+  [label1 setFrame:r1];
+  [label2 setFrame:r2];
+  [v setFrame:r3];
+
+  win.origin.x = 0;
+  win.origin.y = 0;
+  win.size.height = 44; // #### This cannot possibly be right.
+
+  search.frame = win;
+
+  [super viewWillLayoutSubviews];
+}
+
 
 - (id)initWithNames:(NSArray *)_names descriptions:(NSDictionary *)_descs;
 {
index 399eec0eb468949eb1204b8b585d3917a361e3a5..e8f96820c9955afef278c51f6db491e1b7041b4b 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2006-2016 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2006-2019 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
   SaverRunner *_parent;
   NSString *_saverName;
   XScreenSaverView *_saverView;
-
-  /* When a the SaverViewController is presented, iOS automatically changes
-     the status bar orientation. (And, by extension, the notification center
-     orientation.) But there's no willPresentAsModal: event for a
-     UIViewController so that it knows when this is going to happen, and the
-     other event handlers occur after the status bar is changed. So save the
-     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;
-
   BOOL _showAboutBox;
   UIView *aboutBox;
   NSTimer *splashTimer;
index dc4352ec6c7871b32b34b7fc6764f9de59b7c724..7fd4247771dc656bbaf89774262f16fbd735f31c 100644 (file)
@@ -98,7 +98,6 @@
   self = [super init];
   if (self) {
     _parent = parent;
-    // _storedOrientation = UIInterfaceOrientationUnknown;
     _showAboutBox = showAboutBox;
 
     self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
     [_saverView release];
   }
 
-# if 0
-  if (_storedOrientation != UIInterfaceOrientationUnknown) {
-    [[UIApplication sharedApplication]
-     setStatusBarOrientation:_storedOrientation
-     animated:NO];
-  }
-# endif
-
   _saverView = [_parent newSaverView:_saverName
                             withSize:parentView.bounds.size];
 
   [_saverView becomeFirstResponder]; // For shakes on iOS 6.
   [_saverView startAnimation];
   [self aboutPanel:_saverView
-       orientation:/* _storedOrientation */ UIInterfaceOrientationPortrait];
+       orientation: UIInterfaceOrientationPortrait];
 }
 
 
   [name retain];
   [_saverName release];
   _saverName = name;
-  // _storedOrientation =
-  //   [UIApplication sharedApplication].statusBarOrientation;
-
   if (_saverView)
     [self createSaverView];
 }
 
   [self aboutOff:TRUE];  // It does goofy things if we rotate while it's up
 
+# if 1
+  NSLog(@"## orient");
+  [CATransaction commit];
+  [_saverView orientationChanged];
+  return;
+# endif
+
+  BOOL queued =
   [coordinator animateAlongsideTransition:^
                (id <UIViewControllerTransitionCoordinatorContext> context) {
     // This executes repeatedly during the rotation.
+NSLog(@"## animate %@", context);
   } completion:^(id <UIViewControllerTransitionCoordinatorContext> context) {
+NSLog(@"## completion %@", 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.
+
+  NSLog(@"## queued = %d", queued);
+
 }
 
+/* Not called
+- (void)willTransitionToTraitCollection:(UITraitCollection *)collection
+              withTransitionCoordinator:
+                (id<UIViewControllerTransitionCoordinator>)coordinator
+{
+  NSLog(@"#### %@ %@", collection, coordinator);
+}
+*/
+
 @end
 
 #endif // USE_IPHONE
@@ -949,6 +959,10 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str)
                             showAboutBox:[saverNames count] != 1];
   nonrotating_controller.saverName = name;
 
+  // Necessary to prevent "card"-like presentation on Xcode 11 with iOS 13:
+  nonrotating_controller.modalPresentationStyle =
+    UIModalPresentationFullScreen;
+
   /* LAUNCH: */
 
   [rotating_nav presentViewController:nonrotating_controller animated:NO completion:nil];
@@ -1257,17 +1271,6 @@ FAIL:
 {
   rotating_nav.view.hidden = NO; // In case it was hidden during startup.
 
-  /* The XScreenSaverView screws with the status bar orientation, mostly to
-     keep the simulator oriented properly. But on iOS 8.1 (and maybe 8.0
-     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.
    */
index 61045303dda58c1bfcfb0d4545fa467cd435f1c0..d7fd9497a0511a46c1345c92de6c9b0b1d595b3e 100644 (file)
@@ -7,7 +7,7 @@
        <key>CFBundleExecutable</key>
        <string>${EXECUTABLE_NAME}</string>
        <key>CFBundleGetInfoString</key>
-       <string>5.43</string>
+       <string>5.44</string>
        <key>CFBundleIconFile</key>
        <string>SaverRunner</string>
        <key>CFBundleIdentifier</key>
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleLongVersionString</key>
-       <string>5.43</string>
+       <string>5.44</string>
        <key>CFBundleName</key>
        <string>${PRODUCT_NAME}</string>
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleShortVersionString</key>
-       <string>5.43</string>
+       <string>5.44</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.43</string>
+       <string>5.44</string>
        <key>LSMinimumSystemVersion</key>
        <string>${MACOSX_DEPLOYMENT_TARGET}</string>
        <key>NSHumanReadableCopyright</key>
-       <string>5.43</string>
+       <string>5.44</string>
        <key>NSMainNibFile</key>
        <string>SaverRunner</string>
        <key>NSPrincipalClass</key>
index 47088928b3636369f562fb30f524b7af7fb08940..270d72feb310dcf716ad5dca4d7049447347118d 100644 (file)
@@ -9,7 +9,7 @@
        <key>CFBundleExecutable</key>
        <string>${EXECUTABLE_NAME}</string>
        <key>CFBundleGetInfoString</key>
-       <string>5.43</string>
+       <string>5.44</string>
        <key>CFBundleIconFile</key>
        <string>SaverRunner</string>
        <key>CFBundleIdentifier</key>
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleLongVersionString</key>
-       <string>5.43</string>
+       <string>5.44</string>
        <key>CFBundleName</key>
        <string>${PRODUCT_NAME}</string>
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleShortVersionString</key>
-       <string>5.43</string>
+       <string>5.44</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.43</string>
+       <string>5.44</string>
        <key>LSMinimumSystemVersion</key>
        <string>${MACOSX_DEPLOYMENT_TARGET}</string>
        <key>LSUIElement</key>
        <true/>
        <key>NSHumanReadableCopyright</key>
-       <string>5.43</string>
+       <string>5.44</string>
        <key>NSMainNibFile</key>
        <string>Updater</string>
        <key>NSPrincipalClass</key>
index c3fa8c9c5d90b47a84eb0e1cbc0e917f5df28975..d8433d022c4fadac915f76c70b94f1efbb7e2d3f 100644 (file)
        <key>CFBundlePackageType</key>
        <string>BNDL</string>
        <key>CFBundleShortVersionString</key>
-       <string>5.43</string>
+       <string>5.44</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.43</string>
+       <string>5.44</string>
        <key>LSMinimumSystemVersion</key>
        <string>10.8</string>
        <key>NSMainNibFile</key>
index 185377c9aa024c916879af0076b6eef2a8b81394..2b1bde824a918bb72e0a919a5ccff3250773697e 100644 (file)
@@ -332,6 +332,18 @@ typedef enum { SimpleXMLCommentKind,
   [h retain];
   if (html) [html release];
   html = h;
+
+  BOOL dark_mode_p = FALSE;
+  {
+    UITraitCollection *t = [self traitCollection];
+#   pragma clang diagnostic push   // "only available on iOS 12.0 or newer"
+#   pragma clang diagnostic ignored "-Wunguarded-availability-new"
+    if (t && [t respondsToSelector:@selector(userInterfaceStyle)] &&
+        [t userInterfaceStyle] == UIUserInterfaceStyleDark)
+      dark_mode_p = TRUE;
+#   pragma clang diagnostic pop
+  }
+
   NSString *h2 =
     [NSString stringWithFormat:
                 @"<!DOCTYPE HTML PUBLIC "
@@ -351,7 +363,9 @@ typedef enum { SimpleXMLCommentKind,
                       " font-size: %.4fpx;"    // Must be "px", not "pt"!
                       " line-height: %.4fpx;"   // And no spaces before it.
                       " -webkit-text-size-adjust: none;"
+                      " color: %@;"
                       "}"
+                    " a { color: %@ !important; }"
                     "\n//-->\n"
                    "</STYLE>"
                   "</HEAD>"
@@ -359,9 +373,12 @@ typedef enum { SimpleXMLCommentKind,
                    "%@"
                   "</BODY>"
                  "</HTML>",
-              [font fontName],
+              // [font fontName],  // Returns ".SFUI-Regular", doesn't work.
+              @"Helvetica", // "SanFranciscoDisplay-Regular" also doesn't work.
               [font pointSize],
               [font lineHeight],
+              (dark_mode_p ? @"#FFF" : @"#000"),
+              (dark_mode_p ? @"#0DF" : @"#00E"),
               h];
   [webView stopLoading];
   [webView loadHTMLString:h2 baseURL:[NSURL URLWithString:@""]];
@@ -1992,7 +2009,8 @@ set_menu_item_object (NSMenuItem *item, NSObject *obj)
 # else  // USE_IPHONE
 
   txt.adjustsFontSizeToFitWidth = YES;
-  txt.textColor = [UIColor blackColor];
+  // Why did I do this? Messes up dark mode.
+  // txt.textColor = [UIColor blackColor];
   txt.font = [UIFont systemFontOfSize: FONT_SIZE];
   txt.placeholder = @"";
   txt.borderStyle = UITextBorderStyleRoundedRect;
index ad505bdaf09102a224ea69ee66ca462d54842f61..53e27c459a44eb87657e96c49bc03d7d3b68c0db 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2006-2019 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2006-2020 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
@@ -18,6 +18,9 @@
 #import <QuartzCore/QuartzCore.h>
 #import <sys/mman.h>
 #import <zlib.h>
+#ifdef LOG_STACK
+# include <execinfo.h>
+#endif
 #import "XScreenSaverView.h"
 #import "XScreenSaverConfigSheet.h"
 #import "Updater.h"
 # define DO_GC_HACKERY
 #endif
 
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+
 /* Duplicated in xlockmoreI.h and XScreenSaverGLView.m. */
 extern void clear_gl_error (void);
 extern void check_gl_error (const char *type);
@@ -377,6 +384,54 @@ add_default_options (const XrmOptionDescRec *opts,
 }
 
 
+static void sighandler (int sig)
+{
+  const char *s = strsignal(sig);
+  if (!s) s = "Unknowng";
+# ifdef USE_IPHONE
+  jwxyz_abort ("Signal: %s", s);       // Throw NSException, show dialog
+# else
+  NSLog (@"Signal: %s", s);            // Just make sure it is logged
+
+  // Log stack trace too.
+  // Same info shows up in Library/Logs/DiagnosticReports/ScreenSaverEngine*
+#  ifdef LOG_STACK
+  void *stack [20];
+  int frames = backtrace (stack, countof(stack));
+  char **strs = backtrace_symbols (stack, frames);
+  NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames];
+  for (int i = 2; i < frames; i++) {
+    if (strs[i])
+      [backtrace addObject:[NSString stringWithUTF8String: strs[i]]];
+  }
+  // Can't embed newlines in the message for /usr/bin/log
+  NSLog(@"Stack:\\n\t%@", [backtrace componentsJoinedByString:@"\\n\t"]);
+  // free (strs);
+#  endif // LOG_STACK
+
+  signal (sig, SIG_DFL);
+  kill (getpid (), sig);
+# endif
+}
+
+static void catch_signals (void)
+{
+  signal (SIGINT,  sighandler);
+  signal (SIGQUIT, sighandler);
+  signal (SIGILL,  sighandler);
+  signal (SIGTRAP, sighandler);
+  signal (SIGABRT, sighandler);
+  signal (SIGEMT,  sighandler);
+  signal (SIGFPE,  sighandler);
+  signal (SIGBUS,  sighandler);
+  signal (SIGSEGV, sighandler);
+  signal (SIGSYS,  sighandler);
+  signal (SIGTERM, sighandler);
+  signal (SIGXCPU, sighandler);
+  signal (SIGXFSZ, sighandler);
+}
+
+
 - (id) initWithFrame:(NSRect)frame
            saverName:(NSString *)saverName
            isPreview:(BOOL)isPreview
@@ -384,6 +439,7 @@ add_default_options (const XrmOptionDescRec *opts,
   if (! (self = [super initWithFrame:frame isPreview:isPreview]))
     return 0;
   
+  catch_signals();
   xsft = [self findFunctionTable: saverName];
   if (! xsft) {
     [self release];
@@ -444,6 +500,27 @@ add_default_options (const XrmOptionDescRec *opts,
 }
 
 
+#ifndef USE_IPHONE
+/* On 10.15, if "use random screen saver" is checked, then startAnimation
+   is never called.  This may be related to Apple's buggy code in 
+   ScreenSaverEngine calling nonexistent beginExtensionRequestWithUserInfo,
+   but on 10.15 we're not even running in that process: now we're in the
+   not-at-all-ominously-named legacyScreenSaver process.
+ */
+- (void) viewDidMoveToWindow
+{
+  if (self.window)
+    [self startAnimation];
+}
+
+- (void) viewWillMoveToWindow:(NSWindow *)window
+{
+  if (window == nil)
+    [self stopAnimation];
+}
+#endif  // USE_IPHONE
+
+
 #ifdef USE_TOUCHBAR
 - (id) initWithFrame:(NSRect)frame
            saverName:(NSString *)saverName
@@ -581,6 +658,8 @@ add_default_options (const XrmOptionDescRec *opts,
 
 - (void) startAnimation
 {
+  if ([self isAnimating]) return;  // macOS 10.15 stupidity
+
   NSAssert(![self isAnimating], @"already animating");
   NSAssert(!initted_p && !xdata, @"already initialized");
 
@@ -940,9 +1019,17 @@ screenhack_do_fps (Display *dpy, Window w, fps_state *fpst, void *closure)
   CGFloat s = self.window.backingScaleFactor;
 # endif
 
+  /* This notion of "scale fonts differently than the viewport seemed
+     like it made sense for BSOD but it makes -fps text be stupidly
+     large for all other hacks. So instead let's just make BSOD not
+     be lowrez. There are no other lowrez hacks that make heavy use
+     of fonts. */
+  fonts_p = 0;
+
   if (_lowrez_p && !fonts_p) {
     NSSize b = [self bounds].size;  // This is in points, not pixels
     CGFloat wh = b.width > b.height ? b.width : b.height;
+    wh *= s;  // points -> pixels
 
     // Scale down to as close to 1024 as we can get without going under,
     // while keeping an integral scale factor so that we don't get banding
@@ -1644,14 +1731,15 @@ gl_check_ver (const struct gl_version *caps,
       if (_lowrez_p) {
         resized_p = YES;
 
-# if !defined __OPTIMIZE__ || TARGET_IPHONE_SIMULATOR
         NSSize  b = [self bounds].size;
         CGFloat s = self.hackedContentScaleFactor;
-#  ifdef USE_IPHONE
+# ifdef USE_IPHONE
         CGFloat o = self.contentScaleFactor;
-#  else
+# else
         CGFloat o = self.window.backingScaleFactor;
-#  endif
+# endif
+
+# if !defined __OPTIMIZE__ || TARGET_IPHONE_SIMULATOR
         if (o != s)
           NSLog(@"lowrez: scaling %.0fx%.0f -> %.0fx%.0f (%.02f)",
                 b.width * o, b.height * o,
@@ -1866,6 +1954,18 @@ gl_check_ver (const struct gl_version *caps,
     [self handleException: e];
   }
 # endif // USE_IPHONE
+
+# if 0
+  {
+    static int frame = 0;
+    if (++frame == 100) {
+      fprintf(stderr,"BOOM\n");
+      int y = 0;
+      //    int aa = *((int*)y);
+      int x = 30/y;
+    }
+  }
+# endif
 }
 
 
index 5977055638708c08b6f6077b1e4ec6c2fdf7ec4b..d03e99bdf46a51b01c9f4ee2169e5e1bbbe357c9 100644 (file)
@@ -16,8 +16,8 @@
 \b0 by Jamie Zawinski\
 and many others\
 \
-version 5.43\
-09-Jul-2019\
+version 5.44\
+20-Mar-2020\
 \
 {\field{\*\fldinst{HYPERLINK "https://www.jwz.org/xscreensaver/"}}{\fldrslt \cf2 \ul \ulc2 https://www.jwz.org/xscreensaver/}}\
 \pard\pardeftab720
index 1ba18a09dfbfc6f7f5b4604e72be4c23559bec4e..cc89cbfccf9312b7c326768595f531035490bedd 100755 (executable)
@@ -31,6 +31,7 @@ my $verbose = 1;
 #
 my %disable = (
    'extrusion'         => 1,
+   'flurry'            => 1,
    'glitchpeg'         => 1,
    'lcdscrub'          => 1,
    'lockward'          => 1,
@@ -38,56 +39,51 @@ my %disable = (
    'testx11'           => 1,
   );
 
-# Parse the RETIRED_EXES variable from the Makefiles to populate %disable.
-# Duplicated in ../hacks/munge-ad.pl.
+# Parse specified variables from a Makefile.
+# ../hacks/munge-ad.pl also parses Makefiles.
 #
-sub parse_makefiles() {
-  foreach my $mf ( "../hacks/Makefile.in", "../hacks/glx/Makefile.in" ) {
-    open (my $in, '<', $mf) || error ("$mf: $!");
-    print STDERR "$progname: reading $mf\n" if ($verbose > 1);
-    local $/ = undef;  # read entire file
-    my $body = <$in>;
-    close $in;
-
-    $body =~ s/\\\n//gs;
-    my ($var)  = ($body =~ m/^RETIRED_EXES\s*=\s*(.*)$/mi);
-    my ($var2) = ($body =~ m/^RETIRED_GL_EXES\s*=\s*(.*)$/mi);
-    error ("no RETIRED_EXES in $mf") unless $var;
-    $var .= " $var2" if $var2;
-    foreach my $hack (split (/\s+/, $var)) {
-      $disable{$hack} = 2;
+sub parse_makefile_vars($@)
+{
+  my ($mf, @vars) = @_;
+
+  open (my $in, '<', $mf) || error ("$mf: $!");
+  print STDERR "$progname: reading $mf\n" if ($verbose > 1);
+  local $/ = undef;  # read entire file
+  my $body = <$in>;
+  close $in;
+
+  my %vars = map { $_ => 1 } @vars;
+  my %result;
+  while ($body =~ /^([^:#=\s]+)\s*=\s*((?:\\\n|.)*)/mg)
+  {
+    my ($key, $value) = ($1, $2);
+    if (!%vars || $vars{$key}) {
+      $value =~ s/\\\n/ /g;
+      $result{$key} = $value;
     }
   }
+  return \%result;
 }
 
 
 sub build_h($) {
   my ($outfile) = @_;
 
-  parse_makefiles();
-
-  my @schemes = (glob('xscreensaver.xcodeproj/xcuserdata/' .
-                      '*.xcuserdatad/xcschemes/*.xcscheme'),
-                 glob('xscreensaver.xcodeproj/xcshareddata/' .
-                      'xcschemes/*.xcscheme'));
-  error ("no scheme files") unless (@schemes);
-
   my %names = ();
 
-  foreach my $s (@schemes) {
-    open (my $in, '<', $s) || error ("$s: $!");
-    local $/ = undef;  # read entire file
-    my $body = <$in>;
-    close $in;
-    my ($name) = ($body =~ m@BuildableName *= *"([^\"<>]+?)\.saver"@s);
-    next unless $name;
-    $name = lc($name);
-    if ($disable{$name}) {
-      print STDERR "$progname: skipping $name\n" if ($verbose > 1);
-      next;
+  foreach my $var (
+    (values parse_makefile_vars ('../hacks/Makefile.in', 'EXES')),
+    (values parse_makefile_vars ('../hacks/glx/Makefile.in', 'GL_EXES',
+                                 'SUID_EXES'))) {
+    foreach my $name (split (/\s+/, $var)) {
+      if ($name =~ /@/ || $disable{$name}) {
+        print STDERR "$progname: skipping $name\n" if ($verbose > 1);
+        next;
+      }
+      $name =~ s/-//g;
+      print STDERR "$progname: found $name\n" if ($verbose > 1);
+      $names{$name} = 1;
     }
-    print STDERR "$progname: found $name\n" if ($verbose > 1);
-    $names{$name} = 1;
   }
 
   my @names = sort (keys %names);
index 1facee5e557b4c46bcceda91bccc8f126dac3ab5..4161cc4bb32364d0b484944423cccf81c804e139 100644 (file)
 <?xml version="1.0" encoding="UTF-8"?>
-<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="8.00">
-       <data>
-               <int key="IBDocument.SystemTarget">1050</int>
-               <string key="IBDocument.SystemVersion">10K549</string>
-               <string key="IBDocument.InterfaceBuilderVersion">851</string>
-               <string key="IBDocument.AppKitVersion">1038.36</string>
-               <string key="IBDocument.HIToolboxVersion">461.00</string>
-               <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
-                       <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                       <string key="NS.object.0">851</string>
-               </object>
-               <array class="NSMutableArray" key="IBDocument.EditedObjectIDs">
-                       <integer value="57"/>
-               </array>
-               <array key="IBDocument.PluginDependencies">
-                       <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-               </array>
-               <object class="NSMutableDictionary" key="IBDocument.Metadata">
-                       <string key="NS.key.0">PluginDependencyRecalculationVersion</string>
-                       <integer value="1" key="NS.object.0"/>
-               </object>
-               <array class="NSMutableArray" key="IBDocument.RootObjects" id="837227664">
-                       <object class="NSCustomObject" id="838516170">
-                               <object class="NSMutableString" key="NSClassName">
-                                       <characters key="NS.bytes">NSApplication</characters>
-                               </object>
-                       </object>
-                       <object class="NSCustomObject" id="998231172">
-                               <string key="NSClassName">FirstResponder</string>
-                       </object>
-                       <object class="NSCustomObject" id="996827039">
-                               <string key="NSClassName">NSApplication</string>
-                       </object>
-                       <object class="NSMenu" id="45111635">
-                               <string key="NSTitle">MainMenu</string>
-                               <array class="NSMutableArray" key="NSMenuItems">
-                                       <object class="NSMenuItem" id="690370694">
-                                               <reference key="NSMenu" ref="45111635"/>
-                                               <string key="NSTitle">XScreenSaver</string>
-                                               <string key="NSKeyEquiv"/>
-                                               <int key="NSKeyEquivModMask">1048576</int>
-                                               <int key="NSMnemonicLoc">2147483647</int>
-                                               <object class="NSCustomResource" key="NSOnImage" id="301225830">
-                                                       <string key="NSClassName">NSImage</string>
-                                                       <string key="NSResourceName">NSMenuCheckmark</string>
-                                               </object>
-                                               <object class="NSCustomResource" key="NSMixedImage" id="862154113">
-                                                       <string key="NSClassName">NSImage</string>
-                                                       <string key="NSResourceName">NSMenuMixedState</string>
-                                               </object>
-                                               <string key="NSAction">submenuAction:</string>
-                                               <object class="NSMenu" key="NSSubmenu" id="648337178">
-                                                       <string key="NSTitle">XScreenSaver</string>
-                                                       <array class="NSMutableArray" key="NSMenuItems">
-                                                               <object class="NSMenuItem" id="8914611">
-                                                                       <reference key="NSMenu" ref="648337178"/>
-                                                                       <string key="NSTitle">About XScreenSaver</string>
-                                                                       <string key="NSKeyEquiv"/>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="627255583">
-                                                                       <reference key="NSMenu" ref="648337178"/>
-                                                                       <bool key="NSIsDisabled">YES</bool>
-                                                                       <bool key="NSIsSeparator">YES</bool>
-                                                                       <string key="NSTitle"/>
-                                                                       <string key="NSKeyEquiv"/>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="381880730">
-                                                                       <reference key="NSMenu" ref="648337178"/>
-                                                                       <bool key="NSIsDisabled">YES</bool>
-                                                                       <string key="NSTitle">Preferences…</string>
-                                                                       <string key="NSKeyEquiv">,</string>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="862592074">
-                                                                       <reference key="NSMenu" ref="648337178"/>
-                                                                       <bool key="NSIsDisabled">YES</bool>
-                                                                       <bool key="NSIsSeparator">YES</bool>
-                                                                       <string key="NSTitle"/>
-                                                                       <string key="NSKeyEquiv"/>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="923603386">
-                                                                       <reference key="NSMenu" ref="648337178"/>
-                                                                       <string key="NSTitle">Services</string>
-                                                                       <string key="NSKeyEquiv"/>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                                       <string key="NSAction">submenuAction:</string>
-                                                                       <object class="NSMenu" key="NSSubmenu" id="1035646574">
-                                                                               <object class="NSMutableString" key="NSTitle">
-                                                                                       <characters key="NS.bytes">Services</characters>
-                                                                               </object>
-                                                                               <array class="NSMutableArray" key="NSMenuItems"/>
-                                                                               <string key="NSName">_NSServicesMenu</string>
-                                                                       </object>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="819131537">
-                                                                       <reference key="NSMenu" ref="648337178"/>
-                                                                       <bool key="NSIsDisabled">YES</bool>
-                                                                       <bool key="NSIsSeparator">YES</bool>
-                                                                       <string key="NSTitle"/>
-                                                                       <string key="NSKeyEquiv"/>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="632798708">
-                                                                       <reference key="NSMenu" ref="648337178"/>
-                                                                       <string key="NSTitle">Hide XScreenSaver</string>
-                                                                       <string key="NSKeyEquiv">h</string>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="468461345">
-                                                                       <reference key="NSMenu" ref="648337178"/>
-                                                                       <string key="NSTitle">Hide Others</string>
-                                                                       <string key="NSKeyEquiv">h</string>
-                                                                       <int key="NSKeyEquivModMask">1572864</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="437251807">
-                                                                       <reference key="NSMenu" ref="648337178"/>
-                                                                       <string key="NSTitle">Show All</string>
-                                                                       <string key="NSKeyEquiv"/>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="583949930">
-                                                                       <reference key="NSMenu" ref="648337178"/>
-                                                                       <bool key="NSIsDisabled">YES</bool>
-                                                                       <bool key="NSIsSeparator">YES</bool>
-                                                                       <string key="NSTitle"/>
-                                                                       <string key="NSKeyEquiv"/>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="504373960">
-                                                                       <reference key="NSMenu" ref="648337178"/>
-                                                                       <string key="NSTitle">Quit XScreenSaver</string>
-                                                                       <string key="NSKeyEquiv">q</string>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                       </array>
-                                                       <string key="NSName">_NSAppleMenu</string>
-                                               </object>
-                                       </object>
-                                       <object class="NSMenuItem" id="799166226">
-                                               <reference key="NSMenu" ref="45111635"/>
-                                               <string key="NSTitle">File</string>
-                                               <string key="NSKeyEquiv"/>
-                                               <int key="NSKeyEquivModMask">1048576</int>
-                                               <int key="NSMnemonicLoc">2147483647</int>
-                                               <reference key="NSOnImage" ref="301225830"/>
-                                               <reference key="NSMixedImage" ref="862154113"/>
-                                               <string key="NSAction">submenuAction:</string>
-                                               <object class="NSMenu" key="NSSubmenu" id="811240304">
-                                                       <object class="NSMutableString" key="NSTitle">
-                                                               <characters key="NS.bytes">File</characters>
-                                                       </object>
-                                                       <array class="NSMutableArray" key="NSMenuItems">
-                                                               <object class="NSMenuItem" id="222387297">
-                                                                       <reference key="NSMenu" ref="811240304"/>
-                                                                       <string key="NSTitle">Close</string>
-                                                                       <string key="NSKeyEquiv">w</string>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="608174085">
-                                                                       <reference key="NSMenu" ref="811240304"/>
-                                                                       <bool key="NSIsDisabled">YES</bool>
-                                                                       <bool key="NSIsSeparator">YES</bool>
-                                                                       <string key="NSTitle"/>
-                                                                       <string key="NSKeyEquiv"/>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="876081012">
-                                                                       <reference key="NSMenu" ref="811240304"/>
-                                                                       <string key="NSTitle">Page Setup…</string>
-                                                                       <string key="NSKeyEquiv">P</string>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="926886853">
-                                                                       <reference key="NSMenu" ref="811240304"/>
-                                                                       <string key="NSTitle">Print…</string>
-                                                                       <string key="NSKeyEquiv">p</string>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                       </array>
-                                               </object>
-                                       </object>
-                                       <object class="NSMenuItem" id="455143041">
-                                               <reference key="NSMenu" ref="45111635"/>
-                                               <string key="NSTitle">Edit</string>
-                                               <string key="NSKeyEquiv"/>
-                                               <int key="NSKeyEquivModMask">1048576</int>
-                                               <int key="NSMnemonicLoc">2147483647</int>
-                                               <reference key="NSOnImage" ref="301225830"/>
-                                               <reference key="NSMixedImage" ref="862154113"/>
-                                               <string key="NSAction">submenuAction:</string>
-                                               <object class="NSMenu" key="NSSubmenu" id="750267634">
-                                                       <object class="NSMutableString" key="NSTitle">
-                                                               <characters key="NS.bytes">Edit</characters>
-                                                       </object>
-                                                       <array class="NSMutableArray" key="NSMenuItems">
-                                                               <object class="NSMenuItem" id="497437714">
-                                                                       <reference key="NSMenu" ref="750267634"/>
-                                                                       <string key="NSTitle">Undo</string>
-                                                                       <string key="NSKeyEquiv">z</string>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="216516037">
-                                                                       <reference key="NSMenu" ref="750267634"/>
-                                                                       <string key="NSTitle">Redo</string>
-                                                                       <string key="NSKeyEquiv">Z</string>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="50949474">
-                                                                       <reference key="NSMenu" ref="750267634"/>
-                                                                       <bool key="NSIsDisabled">YES</bool>
-                                                                       <bool key="NSIsSeparator">YES</bool>
-                                                                       <string key="NSTitle"/>
-                                                                       <string key="NSKeyEquiv"/>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="734088368">
-                                                                       <reference key="NSMenu" ref="750267634"/>
-                                                                       <string key="NSTitle">Cut</string>
-                                                                       <string key="NSKeyEquiv">x</string>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="56237994">
-                                                                       <reference key="NSMenu" ref="750267634"/>
-                                                                       <string key="NSTitle">Copy</string>
-                                                                       <string key="NSKeyEquiv">c</string>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="838407332">
-                                                                       <reference key="NSMenu" ref="750267634"/>
-                                                                       <string key="NSTitle">Paste</string>
-                                                                       <string key="NSKeyEquiv">v</string>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="285560595">
-                                                                       <reference key="NSMenu" ref="750267634"/>
-                                                                       <string key="NSTitle">Paste and Match Style</string>
-                                                                       <string key="NSKeyEquiv">V</string>
-                                                                       <int key="NSKeyEquivModMask">1572864</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="406944349">
-                                                                       <reference key="NSMenu" ref="750267634"/>
-                                                                       <string key="NSTitle">Delete</string>
-                                                                       <string key="NSKeyEquiv"/>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="24225155">
-                                                                       <reference key="NSMenu" ref="750267634"/>
-                                                                       <string key="NSTitle">Select All</string>
-                                                                       <string key="NSKeyEquiv">a</string>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="785449747">
-                                                                       <reference key="NSMenu" ref="750267634"/>
-                                                                       <bool key="NSIsDisabled">YES</bool>
-                                                                       <bool key="NSIsSeparator">YES</bool>
-                                                                       <string key="NSTitle"/>
-                                                                       <string key="NSKeyEquiv"/>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="18140746">
-                                                                       <reference key="NSMenu" ref="750267634"/>
-                                                                       <string key="NSTitle">Find</string>
-                                                                       <string key="NSKeyEquiv"/>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                                       <string key="NSAction">submenuAction:</string>
-                                                                       <object class="NSMenu" key="NSSubmenu" id="830368365">
-                                                                               <object class="NSMutableString" key="NSTitle">
-                                                                                       <characters key="NS.bytes">Find</characters>
-                                                                               </object>
-                                                                               <array class="NSMutableArray" key="NSMenuItems">
-                                                                                       <object class="NSMenuItem" id="10797587">
-                                                                                               <reference key="NSMenu" ref="830368365"/>
-                                                                                               <string key="NSTitle">Find…</string>
-                                                                                               <string key="NSKeyEquiv">f</string>
-                                                                                               <int key="NSKeyEquivModMask">1048576</int>
-                                                                                               <int key="NSMnemonicLoc">2147483647</int>
-                                                                                               <reference key="NSOnImage" ref="301225830"/>
-                                                                                               <reference key="NSMixedImage" ref="862154113"/>
-                                                                                               <int key="NSTag">1</int>
-                                                                                       </object>
-                                                                                       <object class="NSMenuItem" id="144442828">
-                                                                                               <reference key="NSMenu" ref="830368365"/>
-                                                                                               <string key="NSTitle">Find Next</string>
-                                                                                               <string key="NSKeyEquiv">g</string>
-                                                                                               <int key="NSKeyEquivModMask">1048576</int>
-                                                                                               <int key="NSMnemonicLoc">2147483647</int>
-                                                                                               <reference key="NSOnImage" ref="301225830"/>
-                                                                                               <reference key="NSMixedImage" ref="862154113"/>
-                                                                                               <int key="NSTag">2</int>
-                                                                                       </object>
-                                                                                       <object class="NSMenuItem" id="208214618">
-                                                                                               <reference key="NSMenu" ref="830368365"/>
-                                                                                               <string key="NSTitle">Find Previous</string>
-                                                                                               <string key="NSKeyEquiv">G</string>
-                                                                                               <int key="NSKeyEquivModMask">1048576</int>
-                                                                                               <int key="NSMnemonicLoc">2147483647</int>
-                                                                                               <reference key="NSOnImage" ref="301225830"/>
-                                                                                               <reference key="NSMixedImage" ref="862154113"/>
-                                                                                               <int key="NSTag">3</int>
-                                                                                       </object>
-                                                                                       <object class="NSMenuItem" id="841162955">
-                                                                                               <reference key="NSMenu" ref="830368365"/>
-                                                                                               <string key="NSTitle">Use Selection for Find</string>
-                                                                                               <string key="NSKeyEquiv">e</string>
-                                                                                               <int key="NSKeyEquivModMask">1048576</int>
-                                                                                               <int key="NSMnemonicLoc">2147483647</int>
-                                                                                               <reference key="NSOnImage" ref="301225830"/>
-                                                                                               <reference key="NSMixedImage" ref="862154113"/>
-                                                                                               <int key="NSTag">7</int>
-                                                                                       </object>
-                                                                                       <object class="NSMenuItem" id="912738317">
-                                                                                               <reference key="NSMenu" ref="830368365"/>
-                                                                                               <string key="NSTitle">Jump to Selection</string>
-                                                                                               <string key="NSKeyEquiv">j</string>
-                                                                                               <int key="NSKeyEquivModMask">1048576</int>
-                                                                                               <int key="NSMnemonicLoc">2147483647</int>
-                                                                                               <reference key="NSOnImage" ref="301225830"/>
-                                                                                               <reference key="NSMixedImage" ref="862154113"/>
-                                                                                       </object>
-                                                                               </array>
-                                                                       </object>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="883299468">
-                                                                       <reference key="NSMenu" ref="750267634"/>
-                                                                       <string key="NSTitle">Spelling</string>
-                                                                       <string key="NSKeyEquiv"/>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                                       <string key="NSAction">submenuAction:</string>
-                                                                       <object class="NSMenu" key="NSSubmenu" id="768298486">
-                                                                               <string key="NSTitle">Spelling</string>
-                                                                               <array class="NSMutableArray" key="NSMenuItems">
-                                                                                       <object class="NSMenuItem" id="177276662">
-                                                                                               <reference key="NSMenu" ref="768298486"/>
-                                                                                               <string key="NSTitle">Spelling…</string>
-                                                                                               <string key="NSKeyEquiv">:</string>
-                                                                                               <int key="NSKeyEquivModMask">1048576</int>
-                                                                                               <int key="NSMnemonicLoc">2147483647</int>
-                                                                                               <reference key="NSOnImage" ref="301225830"/>
-                                                                                               <reference key="NSMixedImage" ref="862154113"/>
-                                                                                       </object>
-                                                                                       <object class="NSMenuItem" id="832350994">
-                                                                                               <reference key="NSMenu" ref="768298486"/>
-                                                                                               <string key="NSTitle">Check Spelling</string>
-                                                                                               <string key="NSKeyEquiv">;</string>
-                                                                                               <int key="NSKeyEquivModMask">1048576</int>
-                                                                                               <int key="NSMnemonicLoc">2147483647</int>
-                                                                                               <reference key="NSOnImage" ref="301225830"/>
-                                                                                               <reference key="NSMixedImage" ref="862154113"/>
-                                                                                       </object>
-                                                                                       <object class="NSMenuItem" id="230465977">
-                                                                                               <reference key="NSMenu" ref="768298486"/>
-                                                                                               <string key="NSTitle">Check Spelling as You Type</string>
-                                                                                               <string key="NSKeyEquiv"/>
-                                                                                               <int key="NSKeyEquivModMask">1048576</int>
-                                                                                               <int key="NSMnemonicLoc">2147483647</int>
-                                                                                               <reference key="NSOnImage" ref="301225830"/>
-                                                                                               <reference key="NSMixedImage" ref="862154113"/>
-                                                                                       </object>
-                                                                               </array>
-                                                                       </object>
-                                                               </object>
-                                                       </array>
-                                               </object>
-                                       </object>
-                                       <object class="NSMenuItem" id="224272834">
-                                               <reference key="NSMenu" ref="45111635"/>
-                                               <string key="NSTitle">Window</string>
-                                               <string key="NSKeyEquiv"/>
-                                               <int key="NSKeyEquivModMask">1048576</int>
-                                               <int key="NSMnemonicLoc">2147483647</int>
-                                               <reference key="NSOnImage" ref="301225830"/>
-                                               <reference key="NSMixedImage" ref="862154113"/>
-                                               <string key="NSAction">submenuAction:</string>
-                                               <object class="NSMenu" key="NSSubmenu" id="77346976">
-                                                       <object class="NSMutableString" key="NSTitle">
-                                                               <characters key="NS.bytes">Window</characters>
-                                                       </object>
-                                                       <array class="NSMutableArray" key="NSMenuItems">
-                                                               <object class="NSMenuItem" id="711269442">
-                                                                       <reference key="NSMenu" ref="77346976"/>
-                                                                       <string key="NSTitle">Minimize</string>
-                                                                       <string key="NSKeyEquiv">m</string>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="531690807">
-                                                                       <reference key="NSMenu" ref="77346976"/>
-                                                                       <string key="NSTitle">Zoom</string>
-                                                                       <string key="NSKeyEquiv"/>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="229796363">
-                                                                       <reference key="NSMenu" ref="77346976"/>
-                                                                       <bool key="NSIsDisabled">YES</bool>
-                                                                       <bool key="NSIsSeparator">YES</bool>
-                                                                       <string key="NSTitle"/>
-                                                                       <string key="NSKeyEquiv"/>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                               <object class="NSMenuItem" id="691026595">
-                                                                       <reference key="NSMenu" ref="77346976"/>
-                                                                       <string key="NSTitle">Bring All to Front</string>
-                                                                       <string key="NSKeyEquiv"/>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                       </array>
-                                                       <string key="NSName">_NSWindowsMenu</string>
-                                               </object>
-                                       </object>
-                                       <object class="NSMenuItem" id="372969117">
-                                               <reference key="NSMenu" ref="45111635"/>
-                                               <string key="NSTitle">Help</string>
-                                               <string key="NSKeyEquiv"/>
-                                               <int key="NSKeyEquivModMask">1048576</int>
-                                               <int key="NSMnemonicLoc">2147483647</int>
-                                               <reference key="NSOnImage" ref="301225830"/>
-                                               <reference key="NSMixedImage" ref="862154113"/>
-                                               <string key="NSAction">submenuAction:</string>
-                                               <object class="NSMenu" key="NSSubmenu" id="839568932">
-                                                       <string key="NSTitle">Help</string>
-                                                       <array class="NSMutableArray" key="NSMenuItems">
-                                                               <object class="NSMenuItem" id="148697282">
-                                                                       <reference key="NSMenu" ref="839568932"/>
-                                                                       <bool key="NSIsDisabled">YES</bool>
-                                                                       <string key="NSTitle">XScreenSaver Help</string>
-                                                                       <string key="NSKeyEquiv">?</string>
-                                                                       <int key="NSKeyEquivModMask">1048576</int>
-                                                                       <int key="NSMnemonicLoc">2147483647</int>
-                                                                       <reference key="NSOnImage" ref="301225830"/>
-                                                                       <reference key="NSMixedImage" ref="862154113"/>
-                                                               </object>
-                                                       </array>
-                                               </object>
-                                       </object>
-                               </array>
-                               <string key="NSName">_NSMainMenu</string>
-                       </object>
-                       <object class="NSCustomObject" id="606990062">
-                               <string key="NSClassName">SaverRunner</string>
-                       </object>
-               </array>
-               <object class="IBObjectContainer" key="IBDocument.Objects">
-                       <array class="NSMutableArray" key="connectionRecords">
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">performMiniaturize:</string>
-                                               <reference key="source" ref="998231172"/>
-                                               <reference key="destination" ref="711269442"/>
-                                       </object>
-                                       <int key="connectionID">37</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">arrangeInFront:</string>
-                                               <reference key="source" ref="998231172"/>
-                                               <reference key="destination" ref="691026595"/>
-                                       </object>
-                                       <int key="connectionID">39</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">print:</string>
-                                               <reference key="source" ref="998231172"/>
-                                               <reference key="destination" ref="926886853"/>
-                                       </object>
-                                       <int key="connectionID">86</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">runPageLayout:</string>
-                                               <reference key="source" ref="998231172"/>
-                                               <reference key="destination" ref="876081012"/>
-                                       </object>
-                                       <int key="connectionID">87</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">showHelp:</string>
-                                               <reference key="source" ref="998231172"/>
-                                               <reference key="destination" ref="148697282"/>
-                                       </object>
-                                       <int key="connectionID">122</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">terminate:</string>
-                                               <reference key="source" ref="838516170"/>
-                                               <reference key="destination" ref="504373960"/>
-                                       </object>
-                                       <int key="connectionID">139</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">hideOtherApplications:</string>
-                                               <reference key="source" ref="838516170"/>
-                                               <reference key="destination" ref="468461345"/>
-                                       </object>
-                                       <int key="connectionID">146</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">hide:</string>
-                                               <reference key="source" ref="838516170"/>
-                                               <reference key="destination" ref="632798708"/>
-                                       </object>
-                                       <int key="connectionID">152</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">unhideAllApplications:</string>
-                                               <reference key="source" ref="838516170"/>
-                                               <reference key="destination" ref="437251807"/>
-                                       </object>
-                                       <int key="connectionID">153</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">cut:</string>
-                                               <reference key="source" ref="998231172"/>
-                                               <reference key="destination" ref="734088368"/>
-                                       </object>
-                                       <int key="connectionID">175</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">paste:</string>
-                                               <reference key="source" ref="998231172"/>
-                                               <reference key="destination" ref="838407332"/>
-                                       </object>
-                                       <int key="connectionID">176</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">redo:</string>
-                                               <reference key="source" ref="998231172"/>
-                                               <reference key="destination" ref="216516037"/>
-                                       </object>
-                                       <int key="connectionID">178</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">selectAll:</string>
-                                               <reference key="source" ref="998231172"/>
-                                               <reference key="destination" ref="24225155"/>
-                                       </object>
-                                       <int key="connectionID">179</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">undo:</string>
-                                               <reference key="source" ref="998231172"/>
-                                               <reference key="destination" ref="497437714"/>
-                                       </object>
-                                       <int key="connectionID">180</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">copy:</string>
-                                               <reference key="source" ref="998231172"/>
-                                               <reference key="destination" ref="56237994"/>
-                                       </object>
-                                       <int key="connectionID">181</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">showGuessPanel:</string>
-                                               <reference key="source" ref="998231172"/>
-                                               <reference key="destination" ref="177276662"/>
-                                       </object>
-                                       <int key="connectionID">188</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">checkSpelling:</string>
-                                               <reference key="source" ref="998231172"/>
-                                               <reference key="destination" ref="832350994"/>
-                                       </object>
-                                       <int key="connectionID">190</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">toggleContinuousSpellChecking:</string>
-                                               <reference key="source" ref="998231172"/>
-                                               <reference key="destination" ref="230465977"/>
-                                       </object>
-                                       <int key="connectionID">192</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">performClose:</string>
-                                               <reference key="source" ref="998231172"/>
-                                               <reference key="destination" ref="222387297"/>
-                                       </object>
-                                       <int key="connectionID">193</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">delete:</string>
-                                               <reference key="source" ref="998231172"/>
-                                               <reference key="destination" ref="406944349"/>
-                                       </object>
-                                       <int key="connectionID">195</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">performZoom:</string>
-                                               <reference key="source" ref="998231172"/>
-                                               <reference key="destination" ref="531690807"/>
-                                       </object>
-                                       <int key="connectionID">198</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">performFindPanelAction:</string>
-                                               <reference key="source" ref="998231172"/>
-                                               <reference key="destination" ref="10797587"/>
-                                       </object>
-                                       <int key="connectionID">199</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">performFindPanelAction:</string>
-                                               <reference key="source" ref="998231172"/>
-                                               <reference key="destination" ref="144442828"/>
-                                       </object>
-                                       <int key="connectionID">200</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">performFindPanelAction:</string>
-                                               <reference key="source" ref="998231172"/>
-                                               <reference key="destination" ref="208214618"/>
-                                       </object>
-                                       <int key="connectionID">201</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">performFindPanelAction:</string>
-                                               <reference key="source" ref="998231172"/>
-                                               <reference key="destination" ref="841162955"/>
-                                       </object>
-                                       <int key="connectionID">202</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">centerSelectionInVisibleArea:</string>
-                                               <reference key="source" ref="998231172"/>
-                                               <reference key="destination" ref="912738317"/>
-                                       </object>
-                                       <int key="connectionID">203</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">pasteAsPlainText:</string>
-                                               <reference key="source" ref="998231172"/>
-                                               <reference key="destination" ref="285560595"/>
-                                       </object>
-                                       <int key="connectionID">205</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBOutletConnection" key="connection">
-                                               <string key="label">delegate</string>
-                                               <reference key="source" ref="838516170"/>
-                                               <reference key="destination" ref="606990062"/>
-                                       </object>
-                                       <int key="connectionID">207</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBOutletConnection" key="connection">
-                                               <string key="label">menubar</string>
-                                               <reference key="source" ref="606990062"/>
-                                               <reference key="destination" ref="45111635"/>
-                                       </object>
-                                       <int key="connectionID">209</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">openPreferences:</string>
-                                               <reference key="source" ref="606990062"/>
-                                               <reference key="destination" ref="381880730"/>
-                                       </object>
-                                       <int key="connectionID">212</int>
-                               </object>
-                               <object class="IBConnectionRecord">
-                                       <object class="IBActionConnection" key="connection">
-                                               <string key="label">aboutPanel:</string>
-                                               <reference key="source" ref="606990062"/>
-                                               <reference key="destination" ref="8914611"/>
-                                       </object>
-                                       <int key="connectionID">213</int>
-                               </object>
-                       </array>
-                       <object class="IBMutableOrderedSet" key="objectRecords">
-                               <array key="orderedObjects">
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">0</int>
-                                               <array key="object" id="0"/>
-                                               <reference key="children" ref="837227664"/>
-                                               <nil key="parent"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">-2</int>
-                                               <reference key="object" ref="838516170"/>
-                                               <reference key="parent" ref="0"/>
-                                               <string key="objectName">File's Owner</string>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">-1</int>
-                                               <reference key="object" ref="998231172"/>
-                                               <reference key="parent" ref="0"/>
-                                               <string key="objectName">First Responder</string>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">-3</int>
-                                               <reference key="object" ref="996827039"/>
-                                               <reference key="parent" ref="0"/>
-                                               <string key="objectName">Application</string>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">29</int>
-                                               <reference key="object" ref="45111635"/>
-                                               <array class="NSMutableArray" key="children">
-                                                       <reference ref="224272834"/>
-                                                       <reference ref="690370694"/>
-                                                       <reference ref="799166226"/>
-                                                       <reference ref="372969117"/>
-                                                       <reference ref="455143041"/>
-                                               </array>
-                                               <reference key="parent" ref="0"/>
-                                               <string key="objectName">MainMenu</string>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">19</int>
-                                               <reference key="object" ref="224272834"/>
-                                               <array class="NSMutableArray" key="children">
-                                                       <reference ref="77346976"/>
-                                               </array>
-                                               <reference key="parent" ref="45111635"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">24</int>
-                                               <reference key="object" ref="77346976"/>
-                                               <array class="NSMutableArray" key="children">
-                                                       <reference ref="691026595"/>
-                                                       <reference ref="711269442"/>
-                                                       <reference ref="229796363"/>
-                                                       <reference ref="531690807"/>
-                                               </array>
-                                               <reference key="parent" ref="224272834"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">5</int>
-                                               <reference key="object" ref="691026595"/>
-                                               <reference key="parent" ref="77346976"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">23</int>
-                                               <reference key="object" ref="711269442"/>
-                                               <reference key="parent" ref="77346976"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">92</int>
-                                               <reference key="object" ref="229796363"/>
-                                               <reference key="parent" ref="77346976"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">197</int>
-                                               <reference key="object" ref="531690807"/>
-                                               <reference key="parent" ref="77346976"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">56</int>
-                                               <reference key="object" ref="690370694"/>
-                                               <array class="NSMutableArray" key="children">
-                                                       <reference ref="648337178"/>
-                                               </array>
-                                               <reference key="parent" ref="45111635"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">57</int>
-                                               <reference key="object" ref="648337178"/>
-                                               <array class="NSMutableArray" key="children">
-                                                       <reference ref="8914611"/>
-                                                       <reference ref="381880730"/>
-                                                       <reference ref="923603386"/>
-                                                       <reference ref="632798708"/>
-                                                       <reference ref="504373960"/>
-                                                       <reference ref="862592074"/>
-                                                       <reference ref="819131537"/>
-                                                       <reference ref="468461345"/>
-                                                       <reference ref="583949930"/>
-                                                       <reference ref="437251807"/>
-                                                       <reference ref="627255583"/>
-                                               </array>
-                                               <reference key="parent" ref="690370694"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">58</int>
-                                               <reference key="object" ref="8914611"/>
-                                               <reference key="parent" ref="648337178"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">129</int>
-                                               <reference key="object" ref="381880730"/>
-                                               <reference key="parent" ref="648337178"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">131</int>
-                                               <reference key="object" ref="923603386"/>
-                                               <array class="NSMutableArray" key="children">
-                                                       <reference ref="1035646574"/>
-                                               </array>
-                                               <reference key="parent" ref="648337178"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">130</int>
-                                               <reference key="object" ref="1035646574"/>
-                                               <reference key="parent" ref="923603386"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">134</int>
-                                               <reference key="object" ref="632798708"/>
-                                               <reference key="parent" ref="648337178"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">136</int>
-                                               <reference key="object" ref="504373960"/>
-                                               <reference key="parent" ref="648337178"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">143</int>
-                                               <reference key="object" ref="862592074"/>
-                                               <reference key="parent" ref="648337178"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">144</int>
-                                               <reference key="object" ref="819131537"/>
-                                               <reference key="parent" ref="648337178"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">145</int>
-                                               <reference key="object" ref="468461345"/>
-                                               <reference key="parent" ref="648337178"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">149</int>
-                                               <reference key="object" ref="583949930"/>
-                                               <reference key="parent" ref="648337178"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">150</int>
-                                               <reference key="object" ref="437251807"/>
-                                               <reference key="parent" ref="648337178"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">196</int>
-                                               <reference key="object" ref="627255583"/>
-                                               <reference key="parent" ref="648337178"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">83</int>
-                                               <reference key="object" ref="799166226"/>
-                                               <array class="NSMutableArray" key="children">
-                                                       <reference ref="811240304"/>
-                                               </array>
-                                               <reference key="parent" ref="45111635"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">81</int>
-                                               <reference key="object" ref="811240304"/>
-                                               <array class="NSMutableArray" key="children">
-                                                       <reference ref="222387297"/>
-                                                       <reference ref="608174085"/>
-                                                       <reference ref="876081012"/>
-                                                       <reference ref="926886853"/>
-                                               </array>
-                                               <reference key="parent" ref="799166226"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">73</int>
-                                               <reference key="object" ref="222387297"/>
-                                               <reference key="parent" ref="811240304"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">74</int>
-                                               <reference key="object" ref="608174085"/>
-                                               <reference key="parent" ref="811240304"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">77</int>
-                                               <reference key="object" ref="876081012"/>
-                                               <reference key="parent" ref="811240304"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">78</int>
-                                               <reference key="object" ref="926886853"/>
-                                               <reference key="parent" ref="811240304"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">103</int>
-                                               <reference key="object" ref="372969117"/>
-                                               <array class="NSMutableArray" key="children">
-                                                       <reference ref="839568932"/>
-                                               </array>
-                                               <reference key="parent" ref="45111635"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">106</int>
-                                               <reference key="object" ref="839568932"/>
-                                               <array class="NSMutableArray" key="children">
-                                                       <reference ref="148697282"/>
-                                               </array>
-                                               <reference key="parent" ref="372969117"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">111</int>
-                                               <reference key="object" ref="148697282"/>
-                                               <reference key="parent" ref="839568932"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">163</int>
-                                               <reference key="object" ref="455143041"/>
-                                               <array class="NSMutableArray" key="children">
-                                                       <reference ref="750267634"/>
-                                               </array>
-                                               <reference key="parent" ref="45111635"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">169</int>
-                                               <reference key="object" ref="750267634"/>
-                                               <array class="NSMutableArray" key="children">
-                                                       <reference ref="50949474"/>
-                                                       <reference ref="56237994"/>
-                                                       <reference ref="497437714"/>
-                                                       <reference ref="734088368"/>
-                                                       <reference ref="406944349"/>
-                                                       <reference ref="18140746"/>
-                                                       <reference ref="838407332"/>
-                                                       <reference ref="24225155"/>
-                                                       <reference ref="216516037"/>
-                                                       <reference ref="785449747"/>
-                                                       <reference ref="883299468"/>
-                                                       <reference ref="285560595"/>
-                                               </array>
-                                               <reference key="parent" ref="455143041"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">156</int>
-                                               <reference key="object" ref="50949474"/>
-                                               <reference key="parent" ref="750267634"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">157</int>
-                                               <reference key="object" ref="56237994"/>
-                                               <reference key="parent" ref="750267634"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">158</int>
-                                               <reference key="object" ref="497437714"/>
-                                               <reference key="parent" ref="750267634"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">160</int>
-                                               <reference key="object" ref="734088368"/>
-                                               <reference key="parent" ref="750267634"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">164</int>
-                                               <reference key="object" ref="406944349"/>
-                                               <reference key="parent" ref="750267634"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">168</int>
-                                               <reference key="object" ref="18140746"/>
-                                               <array class="NSMutableArray" key="children">
-                                                       <reference ref="830368365"/>
-                                               </array>
-                                               <reference key="parent" ref="750267634"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">159</int>
-                                               <reference key="object" ref="830368365"/>
-                                               <array class="NSMutableArray" key="children">
-                                                       <reference ref="10797587"/>
-                                                       <reference ref="912738317"/>
-                                                       <reference ref="841162955"/>
-                                                       <reference ref="208214618"/>
-                                                       <reference ref="144442828"/>
-                                               </array>
-                                               <reference key="parent" ref="18140746"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">154</int>
-                                               <reference key="object" ref="10797587"/>
-                                               <reference key="parent" ref="830368365"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">155</int>
-                                               <reference key="object" ref="912738317"/>
-                                               <reference key="parent" ref="830368365"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">161</int>
-                                               <reference key="object" ref="841162955"/>
-                                               <reference key="parent" ref="830368365"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">162</int>
-                                               <reference key="object" ref="208214618"/>
-                                               <reference key="parent" ref="830368365"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">167</int>
-                                               <reference key="object" ref="144442828"/>
-                                               <reference key="parent" ref="830368365"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">171</int>
-                                               <reference key="object" ref="838407332"/>
-                                               <reference key="parent" ref="750267634"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">172</int>
-                                               <reference key="object" ref="24225155"/>
-                                               <reference key="parent" ref="750267634"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">173</int>
-                                               <reference key="object" ref="216516037"/>
-                                               <reference key="parent" ref="750267634"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">174</int>
-                                               <reference key="object" ref="785449747"/>
-                                               <reference key="parent" ref="750267634"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">184</int>
-                                               <reference key="object" ref="883299468"/>
-                                               <array class="NSMutableArray" key="children">
-                                                       <reference ref="768298486"/>
-                                               </array>
-                                               <reference key="parent" ref="750267634"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">185</int>
-                                               <reference key="object" ref="768298486"/>
-                                               <array class="NSMutableArray" key="children">
-                                                       <reference ref="177276662"/>
-                                                       <reference ref="832350994"/>
-                                                       <reference ref="230465977"/>
-                                               </array>
-                                               <reference key="parent" ref="883299468"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">187</int>
-                                               <reference key="object" ref="177276662"/>
-                                               <reference key="parent" ref="768298486"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">189</int>
-                                               <reference key="object" ref="832350994"/>
-                                               <reference key="parent" ref="768298486"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">191</int>
-                                               <reference key="object" ref="230465977"/>
-                                               <reference key="parent" ref="768298486"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">204</int>
-                                               <reference key="object" ref="285560595"/>
-                                               <reference key="parent" ref="750267634"/>
-                                       </object>
-                                       <object class="IBObjectRecord">
-                                               <int key="objectID">206</int>
-                                               <reference key="object" ref="606990062"/>
-                                               <reference key="parent" ref="0"/>
-                                               <string key="objectName">SaverRunner</string>
-                                       </object>
-                               </array>
-                       </object>
-                       <dictionary class="NSMutableDictionary" key="flattenedProperties">
-                               <string key="-3.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="-3.ImportedFromIB2"/>
-                               <string key="103.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="103.ImportedFromIB2"/>
-                               <string key="106.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="106.ImportedFromIB2"/>
-                               <string key="111.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="111.ImportedFromIB2"/>
-                               <string key="129.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="129.ImportedFromIB2"/>
-                               <string key="130.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="130.ImportedFromIB2"/>
-                               <string key="131.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="131.ImportedFromIB2"/>
-                               <string key="134.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="134.ImportedFromIB2"/>
-                               <string key="136.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="136.ImportedFromIB2"/>
-                               <string key="143.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="143.ImportedFromIB2"/>
-                               <string key="144.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="144.ImportedFromIB2"/>
-                               <string key="145.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="145.ImportedFromIB2"/>
-                               <string key="149.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="149.ImportedFromIB2"/>
-                               <string key="150.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="150.ImportedFromIB2"/>
-                               <string key="154.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="154.ImportedFromIB2"/>
-                               <string key="155.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="155.ImportedFromIB2"/>
-                               <string key="156.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="156.ImportedFromIB2"/>
-                               <string key="157.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="157.ImportedFromIB2"/>
-                               <string key="158.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="158.ImportedFromIB2"/>
-                               <string key="159.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="159.ImportedFromIB2"/>
-                               <string key="160.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="160.ImportedFromIB2"/>
-                               <string key="161.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="161.ImportedFromIB2"/>
-                               <string key="162.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="162.ImportedFromIB2"/>
-                               <string key="163.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="163.ImportedFromIB2"/>
-                               <string key="164.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="164.ImportedFromIB2"/>
-                               <string key="167.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="167.ImportedFromIB2"/>
-                               <string key="168.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="168.ImportedFromIB2"/>
-                               <string key="169.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="169.ImportedFromIB2"/>
-                               <string key="171.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="171.ImportedFromIB2"/>
-                               <string key="172.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="172.ImportedFromIB2"/>
-                               <string key="173.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="173.ImportedFromIB2"/>
-                               <string key="174.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="174.ImportedFromIB2"/>
-                               <string key="184.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="184.ImportedFromIB2"/>
-                               <string key="185.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="185.ImportedFromIB2"/>
-                               <string key="187.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="187.ImportedFromIB2"/>
-                               <string key="189.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="189.ImportedFromIB2"/>
-                               <string key="19.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="19.ImportedFromIB2"/>
-                               <string key="191.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="191.ImportedFromIB2"/>
-                               <string key="196.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="196.ImportedFromIB2"/>
-                               <string key="197.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="197.ImportedFromIB2"/>
-                               <string key="204.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="204.ImportedFromIB2"/>
-                               <boolean value="YES" key="206.ImportedFromIB2"/>
-                               <string key="23.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="23.ImportedFromIB2"/>
-                               <string key="24.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="24.ImportedFromIB2"/>
-                               <string key="29.IBEditorWindowLastContentRect">{{72, 1365}, {344, 20}}</string>
-                               <string key="29.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="29.ImportedFromIB2"/>
-                               <string key="5.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="5.ImportedFromIB2"/>
-                               <string key="56.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="56.ImportedFromIB2"/>
-                               <string key="57.IBEditorWindowLastContentRect">{{84, 1182}, {225, 183}}</string>
-                               <string key="57.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="57.ImportedFromIB2"/>
-                               <string key="58.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="58.ImportedFromIB2"/>
-                               <string key="73.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="73.ImportedFromIB2"/>
-                               <string key="74.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="74.ImportedFromIB2"/>
-                               <string key="77.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="77.ImportedFromIB2"/>
-                               <string key="78.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="78.ImportedFromIB2"/>
-                               <string key="81.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="81.ImportedFromIB2"/>
-                               <string key="83.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="83.ImportedFromIB2"/>
-                               <string key="92.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
-                               <boolean value="YES" key="92.ImportedFromIB2"/>
-                       </dictionary>
-                       <dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
-                       <nil key="activeLocalization"/>
-                       <dictionary class="NSMutableDictionary" key="localizations"/>
-                       <nil key="sourceID"/>
-                       <int key="maxID">213</int>
-               </object>
-               <object class="IBClassDescriber" key="IBDocument.Classes">
-                       <array class="NSMutableArray" key="referencedPartialClassDescriptions">
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">SaverRunner</string>
-                                       <string key="superclassName">NSObject</string>
-                                       <dictionary class="NSMutableDictionary" key="actions">
-                                               <string key="aboutPanel:">id</string>
-                                               <string key="openPreferences:">id</string>
-                                       </dictionary>
-                                       <dictionary class="NSMutableDictionary" key="actionInfosByName">
-                                               <object class="IBActionInfo" key="aboutPanel:">
-                                                       <string key="name">aboutPanel:</string>
-                                                       <string key="candidateClassName">id</string>
-                                               </object>
-                                               <object class="IBActionInfo" key="openPreferences:">
-                                                       <string key="name">openPreferences:</string>
-                                                       <string key="candidateClassName">id</string>
-                                               </object>
-                                       </dictionary>
-                                       <object class="NSMutableDictionary" key="outlets">
-                                               <string key="NS.key.0">menubar</string>
-                                               <string key="NS.object.0">NSMenu</string>
-                                       </object>
-                                       <object class="NSMutableDictionary" key="toOneOutletInfosByName">
-                                               <string key="NS.key.0">menubar</string>
-                                               <object class="IBToOneOutletInfo" key="NS.object.0">
-                                                       <string key="name">menubar</string>
-                                                       <string key="candidateClassName">NSMenu</string>
-                                               </object>
-                                       </object>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBProjectSource</string>
-                                               <string key="minorKey">OSX/SaverRunner.h</string>
-                                       </object>
-                               </object>
-                       </array>
-                       <array class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSApplication</string>
-                                       <string key="superclassName">NSResponder</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier" id="559430808">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSApplication.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSApplication</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier" id="632847653">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSApplicationScripting.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSApplication</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier" id="391792136">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSColorPanel.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSApplication</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSHelpManager.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSApplication</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSPageLayout.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSBrowser</string>
-                                       <string key="superclassName">NSControl</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier" id="988770048">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSBrowser.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSControl</string>
-                                       <string key="superclassName">NSView</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier" id="339469989">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSControl.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSDocument</string>
-                                       <string key="superclassName">NSObject</string>
-                                       <dictionary class="NSMutableDictionary" key="actions">
-                                               <string key="printDocument:">id</string>
-                                               <string key="revertDocumentToSaved:">id</string>
-                                               <string key="runPageLayout:">id</string>
-                                               <string key="saveDocument:">id</string>
-                                               <string key="saveDocumentAs:">id</string>
-                                               <string key="saveDocumentTo:">id</string>
-                                       </dictionary>
-                                       <dictionary class="NSMutableDictionary" key="actionInfosByName">
-                                               <object class="IBActionInfo" key="printDocument:">
-                                                       <string key="name">printDocument:</string>
-                                                       <string key="candidateClassName">id</string>
-                                               </object>
-                                               <object class="IBActionInfo" key="revertDocumentToSaved:">
-                                                       <string key="name">revertDocumentToSaved:</string>
-                                                       <string key="candidateClassName">id</string>
-                                               </object>
-                                               <object class="IBActionInfo" key="runPageLayout:">
-                                                       <string key="name">runPageLayout:</string>
-                                                       <string key="candidateClassName">id</string>
-                                               </object>
-                                               <object class="IBActionInfo" key="saveDocument:">
-                                                       <string key="name">saveDocument:</string>
-                                                       <string key="candidateClassName">id</string>
-                                               </object>
-                                               <object class="IBActionInfo" key="saveDocumentAs:">
-                                                       <string key="name">saveDocumentAs:</string>
-                                                       <string key="candidateClassName">id</string>
-                                               </object>
-                                               <object class="IBActionInfo" key="saveDocumentTo:">
-                                                       <string key="name">saveDocumentTo:</string>
-                                                       <string key="candidateClassName">id</string>
-                                               </object>
-                                       </dictionary>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSDocument.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSDocument</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSDocumentScripting.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSMatrix</string>
-                                       <string key="superclassName">NSControl</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSMatrix.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSMenu</string>
-                                       <string key="superclassName">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier" id="1054084886">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSMenu.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSMenuItem</string>
-                                       <string key="superclassName">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSMenuItem.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSMovieView</string>
-                                       <string key="superclassName">NSView</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSMovieView.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSAccessibility.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSAlert.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSAnimation.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <reference key="sourceIdentifier" ref="559430808"/>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <reference key="sourceIdentifier" ref="632847653"/>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <reference key="sourceIdentifier" ref="988770048"/>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <reference key="sourceIdentifier" ref="391792136"/>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSComboBox.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSComboBoxCell.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <reference key="sourceIdentifier" ref="339469989"/>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSDatePickerCell.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSDragging.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier" id="813110203">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSDrawer.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSFontManager.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSFontPanel.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSImage.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSKeyValueBinding.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <reference key="sourceIdentifier" ref="1054084886"/>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSNibLoading.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSOutlineView.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSPasteboard.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSSavePanel.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSSound.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSSpeechRecognizer.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSSpeechSynthesizer.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSSplitView.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSTabView.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier" id="618451181">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSTableView.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier" id="639735868">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSText.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSTextStorage.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSTextView.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSTokenField.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSTokenFieldCell.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSToolbar.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSToolbarItem.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier" id="1040394720">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSView.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier" id="197276517">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSWindow.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSResponder</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSInterfaceStyle.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSResponder</string>
-                                       <string key="superclassName">NSObject</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSResponder.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSTableView</string>
-                                       <string key="superclassName">NSControl</string>
-                                       <reference key="sourceIdentifier" ref="618451181"/>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSText</string>
-                                       <string key="superclassName">NSView</string>
-                                       <reference key="sourceIdentifier" ref="639735868"/>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSView</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSClipView.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSView</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSRulerView.h</string>
-                                       </object>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSView</string>
-                                       <string key="superclassName">NSResponder</string>
-                                       <reference key="sourceIdentifier" ref="1040394720"/>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSWindow</string>
-                                       <reference key="sourceIdentifier" ref="813110203"/>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSWindow</string>
-                                       <string key="superclassName">NSResponder</string>
-                                       <reference key="sourceIdentifier" ref="197276517"/>
-                               </object>
-                               <object class="IBPartialClassDescription">
-                                       <string key="className">NSWindow</string>
-                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
-                                               <string key="majorKey">IBFrameworkSource</string>
-                                               <string key="minorKey">AppKit.framework/Headers/NSWindowScripting.h</string>
-                                       </object>
-                               </object>
-                       </array>
-               </object>
-               <int key="IBDocument.localizationMode">0</int>
-               <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
-               <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies">
-                       <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>
-                       <integer value="1050" key="NS.object.0"/>
-               </object>
-               <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
-                       <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>
-                       <integer value="1040" key="NS.object.0"/>
-               </object>
-               <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
-               <string key="IBDocument.LastKnownRelativeProjectPath">../../xscreensaver.xcodeproj</string>
-               <int key="IBDocument.defaultPropertyAccessControl">3</int>
-               <dictionary class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
-                       <string key="NSMenuCheckmark">{9, 8}</string>
-                       <string key="NSMenuMixedState">{7, 2}</string>
-               </dictionary>
-       </data>
-</archive>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14868" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
+    <dependencies>
+        <deployment version="1050" identifier="macosx"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14868"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
+            <connections>
+                <outlet property="delegate" destination="206" id="207"/>
+            </connections>
+        </customObject>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application"/>
+        <menu title="MainMenu" systemMenu="main" id="29" userLabel="MainMenu">
+            <items>
+                <menuItem title="XScreenSaver" id="56">
+                    <menu key="submenu" title="XScreenSaver" systemMenu="apple" id="57">
+                        <items>
+                            <menuItem title="About XScreenSaver" id="58">
+                                <modifierMask key="keyEquivalentModifierMask"/>
+                                <connections>
+                                    <action selector="aboutPanel:" target="206" id="213"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem isSeparatorItem="YES" id="196">
+                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
+                            </menuItem>
+                            <menuItem title="Preferences…" enabled="NO" keyEquivalent="," id="129">
+                                <connections>
+                                    <action selector="openPreferences:" target="206" id="212"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem isSeparatorItem="YES" id="143">
+                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
+                            </menuItem>
+                            <menuItem title="Services" id="131">
+                                <menu key="submenu" title="Services" systemMenu="services" id="130"/>
+                            </menuItem>
+                            <menuItem isSeparatorItem="YES" id="144">
+                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
+                            </menuItem>
+                            <menuItem title="Hide XScreenSaver" keyEquivalent="h" id="134">
+                                <connections>
+                                    <action selector="hide:" target="-2" id="152"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem title="Hide Others" keyEquivalent="h" id="145">
+                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
+                                <connections>
+                                    <action selector="hideOtherApplications:" target="-2" id="146"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem title="Show All" id="150">
+                                <connections>
+                                    <action selector="unhideAllApplications:" target="-2" id="153"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem isSeparatorItem="YES" id="149">
+                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
+                            </menuItem>
+                            <menuItem title="Quit XScreenSaver" keyEquivalent="q" id="136">
+                                <connections>
+                                    <action selector="terminate:" target="-2" id="139"/>
+                                </connections>
+                            </menuItem>
+                        </items>
+                    </menu>
+                </menuItem>
+                <menuItem title="File" id="83">
+                    <menu key="submenu" title="File" id="81">
+                        <items>
+                            <menuItem title="Close" keyEquivalent="w" id="73">
+                                <connections>
+                                    <action selector="performClose:" target="-1" id="193"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem isSeparatorItem="YES" id="74">
+                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
+                            </menuItem>
+                            <menuItem title="Page Setup…" keyEquivalent="P" id="77">
+                                <connections>
+                                    <action selector="runPageLayout:" target="-1" id="87"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem title="Print…" keyEquivalent="p" id="78">
+                                <connections>
+                                    <action selector="print:" target="-1" id="86"/>
+                                </connections>
+                            </menuItem>
+                        </items>
+                    </menu>
+                </menuItem>
+                <menuItem title="Edit" id="163">
+                    <menu key="submenu" title="Edit" id="169">
+                        <items>
+                            <menuItem title="Undo" keyEquivalent="z" id="158">
+                                <connections>
+                                    <action selector="undo:" target="-1" id="180"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem title="Redo" keyEquivalent="Z" id="173">
+                                <connections>
+                                    <action selector="redo:" target="-1" id="178"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem isSeparatorItem="YES" id="156">
+                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
+                            </menuItem>
+                            <menuItem title="Cut" keyEquivalent="x" id="160">
+                                <connections>
+                                    <action selector="cut:" target="-1" id="175"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem title="Copy" keyEquivalent="c" id="157">
+                                <connections>
+                                    <action selector="copy:" target="-1" id="181"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem title="Paste" keyEquivalent="v" id="171">
+                                <connections>
+                                    <action selector="paste:" target="-1" id="176"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem title="Paste and Match Style" keyEquivalent="v" id="204">
+                                <connections>
+                                    <action selector="pasteAsPlainText:" target="-1" id="205"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem title="Delete" id="164">
+                                <connections>
+                                    <action selector="delete:" target="-1" id="195"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem title="Select All" keyEquivalent="a" id="172">
+                                <connections>
+                                    <action selector="selectAll:" target="-1" id="179"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem isSeparatorItem="YES" id="174">
+                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
+                            </menuItem>
+                            <menuItem title="Find" id="168">
+                                <menu key="submenu" title="Find" id="159">
+                                    <items>
+                                        <menuItem title="Find…" tag="1" keyEquivalent="f" id="154">
+                                            <connections>
+                                                <action selector="performFindPanelAction:" target="-1" id="199"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="Find Next" tag="2" keyEquivalent="g" id="167">
+                                            <connections>
+                                                <action selector="performFindPanelAction:" target="-1" id="200"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="Find Previous" tag="3" keyEquivalent="G" id="162">
+                                            <connections>
+                                                <action selector="performFindPanelAction:" target="-1" id="201"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="161">
+                                            <connections>
+                                                <action selector="performFindPanelAction:" target="-1" id="202"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="Jump to Selection" keyEquivalent="j" id="155">
+                                            <connections>
+                                                <action selector="centerSelectionInVisibleArea:" target="-1" id="203"/>
+                                            </connections>
+                                        </menuItem>
+                                    </items>
+                                </menu>
+                            </menuItem>
+                            <menuItem title="Spelling" id="184">
+                                <menu key="submenu" title="Spelling" id="185">
+                                    <items>
+                                        <menuItem title="Spelling…" keyEquivalent=":" id="187">
+                                            <connections>
+                                                <action selector="showGuessPanel:" target="-1" id="188"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="Check Spelling" keyEquivalent=";" id="189">
+                                            <connections>
+                                                <action selector="checkSpelling:" target="-1" id="190"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="Check Spelling as You Type" id="191">
+                                            <connections>
+                                                <action selector="toggleContinuousSpellChecking:" target="-1" id="192"/>
+                                            </connections>
+                                        </menuItem>
+                                    </items>
+                                </menu>
+                            </menuItem>
+                        </items>
+                    </menu>
+                </menuItem>
+                <menuItem title="Window" id="19">
+                    <menu key="submenu" title="Window" systemMenu="window" id="24">
+                        <items>
+                            <menuItem title="Minimize" keyEquivalent="m" id="23">
+                                <connections>
+                                    <action selector="performMiniaturize:" target="-1" id="37"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem title="Zoom" id="197">
+                                <connections>
+                                    <action selector="performZoom:" target="-1" id="198"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem isSeparatorItem="YES" id="92">
+                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
+                            </menuItem>
+                            <menuItem title="Bring All to Front" id="5">
+                                <connections>
+                                    <action selector="arrangeInFront:" target="-1" id="39"/>
+                                </connections>
+                            </menuItem>
+                        </items>
+                    </menu>
+                </menuItem>
+                <menuItem title="Help" id="103">
+                    <menu key="submenu" title="Help" id="106">
+                        <items>
+                            <menuItem title="XScreenSaver Help" enabled="NO" keyEquivalent="?" id="111">
+                                <connections>
+                                    <action selector="showHelp:" target="-1" id="122"/>
+                                </connections>
+                            </menuItem>
+                        </items>
+                    </menu>
+                </menuItem>
+            </items>
+            <point key="canvasLocation" x="139" y="154"/>
+        </menu>
+        <customObject id="206" userLabel="SaverRunner" customClass="SaverRunner">
+            <connections>
+                <outlet property="menubar" destination="29" id="209"/>
+            </connections>
+        </customObject>
+    </objects>
+</document>
index 96d6891c19180e3ef02fa68453004348827e9178..7c2b9334025848dc537ce35bd6a1a2a146dd0923 100644 (file)
Binary files a/OSX/en.lproj/SaverRunner.nib/keyedobjects.nib and b/OSX/en.lproj/SaverRunner.nib/keyedobjects.nib differ
index 7b873acc7bba79bda19ad5ea6717be3bfe7998fd..ea9220a6922eecbf8f9912a0e5923bd3409b4a51 100644 (file)
@@ -67,7 +67,7 @@ ios_load_random_image (void (*callback) (void *uiimage, const char *fn,
       contentMode: PHImageContentModeDefault
       options: opt
       resultHandler:^void (UIImage *image, NSDictionary *info) {
-        img = image;
+        img = [image retain];
     }];
 
     // Get the image name.
index cfede1e77860f31839ee2acf5200ca53358d912f..002ef1663f6da2600eff7d1812271b9385a60950 100644 (file)
@@ -9,7 +9,7 @@
        <key>CFBundleExecutable</key>
        <string>${EXECUTABLE_NAME}</string>
        <key>CFBundleGetInfoString</key>
-       <string>5.43</string>
+       <string>5.44</string>
        <key>CFBundleIcons</key>
        <dict/>
        <key>CFBundleIcons~ipad</key>
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleLongVersionString</key>
-       <string>5.43</string>
+       <string>5.44</string>
        <key>CFBundleName</key>
        <string>${PRODUCT_NAME}</string>
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleShortVersionString</key>
-       <string>5.43</string>
+       <string>5.44</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.43</string>
+       <string>5.44</string>
        <key>LSRequiresIPhoneOS</key>
        <true/>
        <key>NSHumanReadableCopyright</key>
-       <string>5.43</string>
+       <string>5.44</string>
        <key>NSMainNibFile</key>
        <string>iSaverRunner</string>
+       <key>NSPhotoLibraryUsageDescription</key>
+       <string>XScreenSaver displays manipulated versions of your photos.</string>
        <key>UIAppFonts</key>
        <array>
                <string>OCRAStd.otf</string>
@@ -67,6 +69,5 @@
        </array>
        <key>UIViewControllerBasedStatusBarAppearance</key>
        <true/>
-       <key>NSPhotoLibraryUsageDescription</key>
-       <string>XScreenSaver displays manipulated versions of your photos.</string></dict>
+</dict>
 </plist>
index b0225637990117a681dc3e3a7c698f3290f555c1..13b63ecc8fa3bdfdf9c5a522c73dd572fa416def 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/perl -w
-# Copyright © 2012-2018 Jamie Zawinski <jwz@jwz.org>
+# Copyright © 2012-2019 Jamie Zawinski <jwz@jwz.org>
 #
 # Permission to use, copy, modify, distribute, and sell this software and its
 # documentation for any purpose is hereby granted without fee, provided that
@@ -16,7 +16,7 @@ require 5;
 use strict;
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my ($version) = ('$Revision: 1.4 $' =~ m/\s(\d[.\d]+)\s/s);
+my ($version) = ('$Revision: 1.5 $' =~ m/\s(\d[.\d]+)\s/s);
 
 my $verbose = 0;
 
@@ -54,9 +54,8 @@ sub sanity_check() {
 
   print STDERR "ERROR:\t" . join(' ',  # "\n\t",
      'The "Sonar" module won\'t build properly unless you repair your',
-     'SDK first.  With some versions of Xcode, the ICMP header files',
-     'are present in the iPhone Simulator SDK but are missing from',
-     'the "real device" SDK.  You can fix it by doing this:') .
+     'SDK first.  The ICMP header files are missing from the SDK.',
+     'Fix it by doing this:') .
        "\n\n$fail\n";
   exit (1);
 }
index baa38ea59e2b5337ce3ee194159a5dfa29c24ad6..b3e03e7a0202fe1fce43b8dd4f1399557746c5ec 100755 (executable)
@@ -1,5 +1,5 @@
 #!/bin/sh
-# XScreenSaver, Copyright © 2013-2018 Jamie Zawinski <jwz@jwz.org>
+# XScreenSaver, Copyright © 2013-2019 Jamie Zawinski <jwz@jwz.org>
 #
 # Permission to use, copy, modify, distribute, and sell this software and its
 # documentation for any purpose is hereby granted without fee, provided that
@@ -65,7 +65,6 @@ if [ "$DEBUG" != 0 ]; then DSTVOLUME=/tmp; fi
 SRC=`dirname "$PACKAGE_PATH"`/"Screen Savers"
 DST1="$DSTVOLUME/Library/Screen Savers"
 DST2="$DSTVOLUME/Applications"
-PU="$DSTVOLUME/$HOME/Library/Screen Savers"
 
 # Because of Sparkle.framework weirdness, "XScreenSaverUpdater.app" is
 # in the DMG as a compressed tar file instead of an app, and we unpack
@@ -131,14 +130,46 @@ for f in *.{saver,app} "$UPDATER_SRC" ; do
     spctl --add "$DD"
   fi
 
-  # If this saver or app is also installed in the per-user directory,
-  # delete that copy so that we don't have conflicts.
+  # If this saver or app is also installed in any per-user directory,
+  # delete those copies so that we don't have conflicts.
   #
   if [ "$DEBUG" = 0 ]; then
-    rm -rf "$PU/$f"
+    rm -rf "$DSTVOLUME/Users/"*"/Library/Screen Savers/$f"
   fi
 done
 
+
+# Savers are sandboxed as of 10.15, which means the preferences files
+# moved.  If this is 10.15 or later, and there are old preferences files,
+# move them to the new location.  Without this, all saver preferences
+# would be wiped by the upgrade.
+#
+V=`sw_vers -productVersion`
+V0=`echo $V | sed 's/^\([^.]*\).*/\1/'`
+V1=`echo $V | sed 's/^[^.]*\.\([^.]*\).*$/\1/'`
+
+if [ "$V0" == 10 -a \! "$V1" \< 15 ]; then     # If >= 10.15
+  for HOME2 in "$DSTVOLUME/Users/"* ; do       # for each user
+
+    CON="$HOME2/Library/Containers"
+    LEG="$CON/com.apple.ScreenSaver.Engine.legacyScreenSaver"
+    NBH="$LEG/Data/Library/Preferences/ByHost"
+    OBH="$HOME2/Library/Preferences/ByHost"
+
+    if [ -d "$CON" ]; then             # if there are Containers
+      if ! [ -d "$LEG" ]; then         # but no legacyScreenSaver already
+        UG=`stat -f %u:%g "$CON"`
+        umask 077
+        mkdir -p "$NBH"                        # create tree
+        chown -R "$UG" "$LEG"          # correct user/group
+        echo "Moving old prefs to $NBH" >&2
+        mv "$OBH/org.jwz.xscreensaver."* "$NBH/"
+      fi
+    fi
+  done
+fi
+
+
 # Launch System Preferences with the Screen Saver pane selected.
 #
 open /System/Library/PreferencePanes/DesktopScreenEffectsPref.prefPane &
index 6cb8b7f66b6a3f6061ab1903666cb86cfcf10a1a..6f2e4a0127e241c684cedb583f14754e63499878 100644 (file)
@@ -1,5 +1,5 @@
 /* Generated file, do not edit.
-   Created: Sat Apr 27 19:53:47 2019 by build-fntable.pl 1.7.
+   Created: Sat Mar 14 14:46:37 2020 by build-fntable.pl 1.7.
  */
 
 #import <Foundation/Foundation.h>
@@ -64,7 +64,6 @@ extern struct xscreensaver_function_table
  discoball_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,
@@ -73,6 +72,7 @@ extern struct xscreensaver_function_table
  epicycle_xscreensaver_function_table,
  eruption_xscreensaver_function_table,
  esper_xscreensaver_function_table,
+ etruscanvenus_xscreensaver_function_table,
  euler2d_xscreensaver_function_table,
  fadeplot_xscreensaver_function_table,
  fiberlamp_xscreensaver_function_table,
@@ -92,6 +92,7 @@ extern struct xscreensaver_function_table
  geodesic_xscreensaver_function_table,
  geodesicgears_xscreensaver_function_table,
  gflux_xscreensaver_function_table,
+ gibson_xscreensaver_function_table,
  glblur_xscreensaver_function_table,
  glcells_xscreensaver_function_table,
  gleidescope_xscreensaver_function_table,
@@ -186,6 +187,7 @@ extern struct xscreensaver_function_table
  rubik_xscreensaver_function_table,
  rubikblocks_xscreensaver_function_table,
  sballs_xscreensaver_function_table,
+ scooter_xscreensaver_function_table,
  shadebobs_xscreensaver_function_table,
  sierpinski_xscreensaver_function_table,
  sierpinski3d_xscreensaver_function_table,
@@ -306,7 +308,6 @@ NSDictionary *make_function_table_dict(void)
        [NSValue valueWithPointer:&discoball_xscreensaver_function_table], @"discoball",
        [NSValue valueWithPointer:&discrete_xscreensaver_function_table], @"discrete",
        [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",
@@ -315,6 +316,7 @@ NSDictionary *make_function_table_dict(void)
        [NSValue valueWithPointer:&epicycle_xscreensaver_function_table], @"epicycle",
        [NSValue valueWithPointer:&eruption_xscreensaver_function_table], @"eruption",
        [NSValue valueWithPointer:&esper_xscreensaver_function_table], @"esper",
+       [NSValue valueWithPointer:&etruscanvenus_xscreensaver_function_table], @"etruscanvenus",
        [NSValue valueWithPointer:&euler2d_xscreensaver_function_table], @"euler2d",
        [NSValue valueWithPointer:&fadeplot_xscreensaver_function_table], @"fadeplot",
        [NSValue valueWithPointer:&fiberlamp_xscreensaver_function_table], @"fiberlamp",
@@ -334,6 +336,7 @@ NSDictionary *make_function_table_dict(void)
        [NSValue valueWithPointer:&geodesic_xscreensaver_function_table], @"geodesic",
        [NSValue valueWithPointer:&geodesicgears_xscreensaver_function_table], @"geodesicgears",
        [NSValue valueWithPointer:&gflux_xscreensaver_function_table], @"gflux",
+       [NSValue valueWithPointer:&gibson_xscreensaver_function_table], @"gibson",
        [NSValue valueWithPointer:&glblur_xscreensaver_function_table], @"glblur",
        [NSValue valueWithPointer:&glcells_xscreensaver_function_table], @"glcells",
        [NSValue valueWithPointer:&gleidescope_xscreensaver_function_table], @"gleidescope",
@@ -428,6 +431,7 @@ NSDictionary *make_function_table_dict(void)
        [NSValue valueWithPointer:&rubik_xscreensaver_function_table], @"rubik",
        [NSValue valueWithPointer:&rubikblocks_xscreensaver_function_table], @"rubikblocks",
        [NSValue valueWithPointer:&sballs_xscreensaver_function_table], @"sballs",
+       [NSValue valueWithPointer:&scooter_xscreensaver_function_table], @"scooter",
        [NSValue valueWithPointer:&shadebobs_xscreensaver_function_table], @"shadebobs",
        [NSValue valueWithPointer:&sierpinski_xscreensaver_function_table], @"sierpinski",
        [NSValue valueWithPointer:&sierpinski3d_xscreensaver_function_table], @"sierpinski3d",
index 4759b05bdb6c9b27d37e1fee3300182f7d44b415..c5bc6b7f578e83a838887eae9ef8939c1d46da96 100644 (file)
@@ -81,12 +81,26 @@ textclient_mobile_date_string (void)
 
 - (void) startLoading
 {
-  // NSLog(@"textclient thread loading %@", self.url);
+# ifndef __OPTIMIZE__
+  NSLog(@"textclient thread loading %@", self.url);
+# endif
+  NSError *e = 0;
   self.result = [NSString stringWithContentsOfURL: self.url
                           encoding: NSUTF8StringEncoding
-                          error: nil];
-  // NSLog(@"textclient thread finished %@ (length %d)", self.url,
-  //      (unsigned int) [self.result length]);
+                          error: &e];
+  if (!self.result || [self.result length] == 0) {
+    // Aug 2019: loading URLs in the simulator no longer works, hooray!
+    NSLog(@"URL error: %@: %@", self.url, e);
+    self.result = [[[[self.url host]
+                      stringByAppendingString:@": "]
+                        stringByAppendingString:
+                         (e ? [e localizedDescription] : @"null response")]
+                       stringByAppendingString:@"\n\n"];
+  }
+# ifndef __OPTIMIZE__
+  NSLog(@"textclient thread finished %@ (length %d)", self.url,
+        (unsigned int) [self.result length]);
+# endif
 }
 
 @end
@@ -110,19 +124,25 @@ textclient_mobile_url_string (Display *dpy, const char *url)
   // URL #2, it might get URL #1 instead.  Oh well, who cares.
 
   if (result) {                                                // Thread finished
-    // NSLog(@"textclient finished %s (length %d)", url,
-    //       (unsigned int) [result length]);
+# ifndef __OPTIMIZE__
+    NSLog(@"textclient finished %s (length %d)", url,
+          (unsigned int) [result length]);
+# endif
     char *s = strdup ([result cStringUsingEncoding:NSUTF8StringEncoding]);
     loader.url    = nil;
     loader.result = nil;
     return s;
 
   } else if ([loader url]) {                           // Waiting on thread
-    // NSLog(@"textclient waiting...");
+# ifndef __OPTIMIZE__
+    NSLog(@"textclient waiting...");
+# endif
     return 0;
 
   } else {                                             // Launch thread
-    // NSLog(@"textclient launching %s...", url);
+# ifndef __OPTIMIZE__
+    NSLog(@"textclient launching %s...", url);
+# endif
     loader.url =
       [NSURL URLWithString:
                [NSString stringWithCString: url
index 21ead069c25d81bd659868bf873970e1afc0fb4b..0e08a00e422eaf308881d2f3743337a5b933b01b 100755 (executable)
@@ -81,8 +81,17 @@ sub generate_xml($$$$) {
 
     $entry =~ s/^\s*\d\d?[- ][A-Z][a-z][a-z][- ]\d{4}:?\s+//s;  # lose date
 
-    $entry =~ s/^\s+|\s+$//gs;
+    # unwrap continuation lines
+    $entry =~ s/^[ \t]*[-*][ \t]+/\001/gm;
+    $entry =~ s/\s+/ /gs;
+    $entry =~ s/\001/\n* /gs;
     $entry =~ s/^\s+|\s+$//gm;
+
+    # Since this updater is only for macOS, omit any changelog entry
+    # beginning with "X11:", "Android:" etc.
+    $entry =~ s/^[-*] (X11|Android|Linux|iOS): [^\n]+(\n|$)//gm;
+    $entry =~ s/^([-*] )macOS: /$1/gm;
+
     $entry =~ s/^[-*] /<BR>&bull; /gm;
     $entry =~ s/^<BR>//si;
     $entry =~ s/\s+/ /gs;
@@ -90,6 +99,9 @@ sub generate_xml($$$$) {
     my $v2 = $v1; $v2 =~ s/\.//gs;
     my $zip = undef;
   DONE:
+    # It only makes sense to include entries in this file for releases for
+    # which a DMG still exists. Expired releases and non-macOS releases
+    # aren't helpful.
     #foreach my $ext ('zip', 'dmg', 'tar.gz', 'tar.Z') {
     foreach my $ext ('dmg') {
       foreach my $v ($v1, $v2) {
index 8179ca2c0fbcb23ec578cae7153914b50fc2a243..f652906a4df7d79c1989c7e7c0f27c1d592dad99 100644 (file)
                                AF7779A909B6608100EA3033 /* PBXTargetDependency */,
                                AF7779A709B6608100EA3033 /* PBXTargetDependency */,
                                AF7779A509B6608100EA3033 /* PBXTargetDependency */,
+                               AF436414241D850500966603 /* PBXTargetDependency */,
                                AF7779A109B6608100EA3033 /* PBXTargetDependency */,
                                AF77799B09B6608100EA3033 /* PBXTargetDependency */,
                                AF77799909B6608100EA3033 /* PBXTargetDependency */,
                                AFACE8911CC8365F008B24CD /* PBXTargetDependency */,
                                AF777A3B09B660B500EA3033 /* PBXTargetDependency */,
                                AF21078F1FD23D9800B61EA9 /* PBXTargetDependency */,
+                               AF2D0D43241D7D9F0001D8B8 /* PBXTargetDependency */,
                                AF777A3909B660B400EA3033 /* PBXTargetDependency */,
                                AF777A3709B660B400EA3033 /* PBXTargetDependency */,
                                AF777A3509B660B400EA3033 /* PBXTargetDependency */,
                                AF7ACFDC19FF0BDB00BD752B /* PBXTargetDependency */,
                                AF777A2D09B660B400EA3033 /* PBXTargetDependency */,
                                AF777A2B09B660B400EA3033 /* PBXTargetDependency */,
+                               AFA0B13C241CE82D0071E35D /* PBXTargetDependency */,
                                AF777A2909B660B400EA3033 /* PBXTargetDependency */,
                                AFF4636F0C440B3B00EE6509 /* PBXTargetDependency */,
                                AF777A2509B660B400EA3033 /* PBXTargetDependency */,
                557BF07F1EE90D3B00846DCE /* settings@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 557BF07B1EE90C8B00846DCE /* settings@3x.png */; };
                557BF0801EE90D3B00846DCE /* stop@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 557BF07C1EE90C8B00846DCE /* stop@2x.png */; };
                557BF0811EE90D3B00846DCE /* stop@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 557BF07D1EE90C8B00846DCE /* stop@3x.png */; };
-               55EDCB3D1AD498A800251909 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 55EDCB3C1AD498A800251909 /* LaunchScreen.xib */; };
                AF012918157C1E4C00C396E1 /* chessmodels.c in Sources */ = {isa = PBXBuildFile; fileRef = AFA55E2309935F2B00F3E977 /* chessmodels.c */; };
                AF01590A2077F56000F624F5 /* OCRAStd.otf in Resources */ = {isa = PBXBuildFile; fileRef = AFEC68361BD6CA85004C1B64 /* OCRAStd.otf */; };
                AF0839A609930BAC00277BE9 /* atlantis.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFC258700988A468000655EE /* atlantis.xml */; };
                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 */; };
+               AF2D0D2C241D7C870001D8B8 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AF2D0D2E241D7C870001D8B8 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AF2D0D2F241D7C870001D8B8 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AF2D0D30241D7C870001D8B8 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AF2D0D31241D7C870001D8B8 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AF2D0D32241D7C870001D8B8 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AF2D0D33241D7C870001D8B8 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AF2D0D34241D7C870001D8B8 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AF2D0D3D241D7D610001D8B8 /* etruscanvenus.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF2D0D3C241D7D600001D8B8 /* etruscanvenus.xml */; };
+               AF2D0D3E241D7D610001D8B8 /* etruscanvenus.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF2D0D3C241D7D600001D8B8 /* etruscanvenus.xml */; };
+               AF2D0D40241D7D7F0001D8B8 /* etruscanvenus.c in Sources */ = {isa = PBXBuildFile; fileRef = AF2D0D3F241D7D7F0001D8B8 /* etruscanvenus.c */; };
+               AF2D0D41241D7D7F0001D8B8 /* etruscanvenus.c in Sources */ = {isa = PBXBuildFile; fileRef = AF2D0D3F241D7D7F0001D8B8 /* etruscanvenus.c */; settings = {COMPILER_FLAGS = "-DUSE_GL"; }; };
                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 */; };
                AF41E96C201D4B6B0098E253 /* razzledazzle.c in Sources */ = {isa = PBXBuildFile; fileRef = AF41E969201D4B6B0098E253 /* razzledazzle.c */; settings = {COMPILER_FLAGS = "-DUSE_GL"; }; };
                AF41E96E201D4B940098E253 /* razzledazzle.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF41E96D201D4B940098E253 /* razzledazzle.xml */; };
                AF41E96F201D4B940098E253 /* razzledazzle.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF41E96D201D4B940098E253 /* razzledazzle.xml */; };
+               AF436403241D84CE00966603 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AF436405241D84CE00966603 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AF436406241D84CE00966603 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AF436407241D84CE00966603 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AF436408241D84CE00966603 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AF436409241D84CE00966603 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AF43640A241D84CE00966603 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AF43640B241D84CE00966603 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AF436416241D85B900966603 /* scooter.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF436415241D85B900966603 /* scooter.xml */; };
+               AF436417241D85B900966603 /* scooter.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF436415241D85B900966603 /* scooter.xml */; };
+               AF436419241D85CD00966603 /* scooter.c in Sources */ = {isa = PBXBuildFile; fileRef = AF436418241D85CD00966603 /* scooter.c */; };
+               AF43641A241D85CD00966603 /* scooter.c in Sources */ = {isa = PBXBuildFile; fileRef = AF436418241D85CD00966603 /* scooter.c */; };
                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 */; };
                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 */; };
                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 */; };
                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 */; };
                AF9D4E0409B5BC85006E59CF /* apple2.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFC2586F0988A468000655EE /* apple2.xml */; };
                AF9D4E0609B5BC9D006E59CF /* apple2-main.c in Sources */ = {isa = PBXBuildFile; fileRef = AF9D4E0509B5BC9D006E59CF /* apple2-main.c */; };
                AF9E7EC9190F4C4000A8B01F /* enable_gc.c in Sources */ = {isa = PBXBuildFile; fileRef = AF9E7EC8190F4C4000A8B01F /* enable_gc.c */; };
+               AFA0B122241CE69E0071E35D /* dangerball.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFC258920988A468000655EE /* dangerball.xml */; };
+               AFA0B125241CE69E0071E35D /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AFA0B127241CE69E0071E35D /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AFA0B128241CE69E0071E35D /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AFA0B129241CE69E0071E35D /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AFA0B12A241CE69E0071E35D /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AFA0B12B241CE69E0071E35D /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AFA0B12C241CE69E0071E35D /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AFA0B12D241CE69E0071E35D /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AFA0B136241CE7B60071E35D /* gibson.c in Sources */ = {isa = PBXBuildFile; fileRef = AFA0B135241CE7B60071E35D /* gibson.c */; };
+               AFA0B137241CE7B60071E35D /* gibson.c in Sources */ = {isa = PBXBuildFile; fileRef = AFA0B135241CE7B60071E35D /* gibson.c */; settings = {COMPILER_FLAGS = "-DUSE_GL"; }; };
+               AFA0B139241CE7E10071E35D /* gibson.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFA0B138241CE7E10071E35D /* gibson.xml */; };
+               AFA0B13A241CE7E10071E35D /* gibson.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFA0B138241CE7E10071E35D /* gibson.xml */; };
                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 */; };
                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 */; };
+               AFCE26332337332000BDCE10 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AFCE26322337332000BDCE10 /* LaunchScreen.storyboard */; };
                AFCF453715986A2100E6E8CC /* dnalogo.c in Sources */ = {isa = PBXBuildFile; fileRef = AF77787609B653DC00EA3033 /* dnalogo.c */; settings = {COMPILER_FLAGS = "-DUSE_GL"; }; };
                AFCF453815986A3000E6E8CC /* dnalogo.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF77787909B6545E00EA3033 /* dnalogo.xml */; };
                AFCF4545159878C300E6E8CC /* polyhedra-gl.c in Sources */ = {isa = PBXBuildFile; fileRef = AFA561B209937DCB00F3E977 /* polyhedra-gl.c */; settings = {COMPILER_FLAGS = "-DUSE_GL"; }; };
                        remoteGlobalIDString = AF2107711FD23BDD00B61EA9;
                        remoteInfo = Esper;
                };
+               AF2D0D27241D7C870001D8B8 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AF2D0D42241D7D9F0001D8B8 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF2D0D25241D7C870001D8B8;
+                       remoteInfo = EtruscanVenus;
+               };
                AF32D9E20F3AD0B40080F535 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        remoteGlobalIDString = AF3C71450D624BF50030CC0D;
                        remoteInfo = Hypnowheel;
                };
+               AF4363FE241D84CE00966603 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AF436413241D850500966603 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4363FC241D84CE00966603;
+                       remoteInfo = Scooter;
+               };
                AF4540D10E52BE8800AE87B5 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
                        remoteInfo = jwxyz;
                };
+               AFA0B120241CE69E0071E35D /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AFA0B13B241CE82D0071E35D /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AFA0B11E241CE69E0071E35D;
+                       remoteInfo = Gibson;
+               };
                AFA160911052FF87009B93AA /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                557BF07B1EE90C8B00846DCE /* settings@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "settings@3x.png"; sourceTree = "<group>"; };
                557BF07C1EE90C8B00846DCE /* stop@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "stop@2x.png"; sourceTree = "<group>"; };
                557BF07D1EE90C8B00846DCE /* stop@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "stop@3x.png"; sourceTree = "<group>"; };
-               55EDCB3C1AD498A800251909 /* LaunchScreen.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LaunchScreen.xib; sourceTree = "<group>"; };
                8D1107310486CEB800E47090 /* XScreenSaver.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = XScreenSaver.plist; sourceTree = "<group>"; };
                AF01294C157D31DD00C396E1 /* iSaverRunner.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = iSaverRunner.plist; sourceTree = SOURCE_ROOT; };
                AF0839A209930B6B00277BE9 /* Atlantis.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Atlantis.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                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; };
+               AF2D0D3A241D7C870001D8B8 /* EtruscanVenus.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = EtruscanVenus.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AF2D0D3C241D7D600001D8B8 /* etruscanvenus.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = etruscanvenus.xml; sourceTree = "<group>"; };
+               AF2D0D3F241D7D7F0001D8B8 /* etruscanvenus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = etruscanvenus.c; path = hacks/glx/etruscanvenus.c; sourceTree = "<group>"; };
                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>"; };
                AF41E967201D49DD0098E253 /* RazzleDazzle.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RazzleDazzle.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AF41E969201D4B6B0098E253 /* razzledazzle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = razzledazzle.c; path = hacks/glx/razzledazzle.c; sourceTree = "<group>"; };
                AF41E96D201D4B940098E253 /* razzledazzle.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = razzledazzle.xml; sourceTree = "<group>"; };
+               AF436411241D84CE00966603 /* Scooter.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Scooter.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AF436415241D85B900966603 /* scooter.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = scooter.xml; sourceTree = "<group>"; };
+               AF436418241D85CD00966603 /* scooter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = scooter.c; path = hacks/scooter.c; 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>"; };
                AF9D4E0509B5BC9D006E59CF /* apple2-main.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = "apple2-main.c"; path = "hacks/apple2-main.c"; 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>"; };
+               AFA0B133241CE69E0071E35D /* Gibson.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Gibson.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AFA0B135241CE7B60071E35D /* gibson.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = gibson.c; path = hacks/glx/gibson.c; sourceTree = "<group>"; };
+               AFA0B138241CE7E10071E35D /* gibson.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = gibson.xml; 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>"; };
                AFC7592C158D8E8B00C5458E /* textclient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = textclient.h; path = utils/textclient.h; 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>"; };
+               AFCE26322337332000BDCE10 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; 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>"; };
                AFCF83531AF5B5FD008BB7E1 /* splitflap_obj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = splitflap_obj.c; path = hacks/glx/splitflap_obj.c; sourceTree = "<group>"; };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF2D0D2D241D7C870001D8B8 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF2D0D2E241D7C870001D8B8 /* libjwxyz.a in Frameworks */,
+                               AF2D0D2F241D7C870001D8B8 /* ScreenSaver.framework in Frameworks */,
+                               AF2D0D30241D7C870001D8B8 /* QuartzCore.framework in Frameworks */,
+                               AF2D0D31241D7C870001D8B8 /* Cocoa.framework in Frameworks */,
+                               AF2D0D32241D7C870001D8B8 /* Carbon.framework in Frameworks */,
+                               AF2D0D33241D7C870001D8B8 /* OpenGL.framework in Frameworks */,
+                               AF2D0D34241D7C870001D8B8 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF32D9E80F3AD0B40080F535 /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF436404241D84CE00966603 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF436405241D84CE00966603 /* libjwxyz.a in Frameworks */,
+                               AF436406241D84CE00966603 /* ScreenSaver.framework in Frameworks */,
+                               AF436407241D84CE00966603 /* QuartzCore.framework in Frameworks */,
+                               AF436408241D84CE00966603 /* Cocoa.framework in Frameworks */,
+                               AF436409241D84CE00966603 /* Carbon.framework in Frameworks */,
+                               AF43640A241D84CE00966603 /* OpenGL.framework in Frameworks */,
+                               AF43640B241D84CE00966603 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF46E9D71CBBA2B300240FBC /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFA0B126241CE69E0071E35D /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFA0B127241CE69E0071E35D /* libjwxyz.a in Frameworks */,
+                               AFA0B128241CE69E0071E35D /* ScreenSaver.framework in Frameworks */,
+                               AFA0B129241CE69E0071E35D /* QuartzCore.framework in Frameworks */,
+                               AFA0B12A241CE69E0071E35D /* Cocoa.framework in Frameworks */,
+                               AFA0B12B241CE69E0071E35D /* Carbon.framework in Frameworks */,
+                               AFA0B12C241CE69E0071E35D /* OpenGL.framework in Frameworks */,
+                               AFA0B12D241CE69E0071E35D /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFA211941CD59DAF00C0D2A1 /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                                AF62D62D2180070600C57C42 /* Handsy.saver */,
                                AF6C6D89226AE4FC0065A748 /* GravityWell.saver */,
                                AFF449F52275494400DB8EDB /* DeepStars.saver */,
+                               AFA0B133241CE69E0071E35D /* Gibson.saver */,
+                               AF2D0D3A241D7C870001D8B8 /* EtruscanVenus.saver */,
+                               AF436411241D84CE00966603 /* Scooter.saver */,
                        );
                        name = Products;
                        path = ..;
                                AF14EE300E3CEF1A004CBBD2 /* XScreenSaver.icns */,
                                AF9772E10989DFC6001F8B92 /* SaverRunner.nib */,
                                AF56019B157DAA3D00DB2055 /* iSaverRunner.xib */,
-                               55EDCB3C1AD498A800251909 /* LaunchScreen.xib */,
+                               AFCE26322337332000BDCE10 /* LaunchScreen.storyboard */,
                                550FB5FD1AD64424001A4FA5 /* Media-iOS.xcassets */,
                                AF2D522513E954A0002AA818 /* SaverRunner.icns */,
                                AF73FF201A08AB9400E485E9 /* iSaverRunner57t.png */,
                                AFD5700C0996B49D00BA26F7 /* penrose.c */,
                                AFD572800996EF2B00BA26F7 /* polyominoes.c */,
                                AFD570C40996B98500BA26F7 /* rotor.c */,
+                               AF436418241D85CD00966603 /* scooter.c */,
                                AFD570220996B52700BA26F7 /* sierpinski.c */,
                                AF47793D099DE56A001F091E /* slip.c */,
                                AFD5703B0996B5E300BA26F7 /* sphere.c */,
                                AFACE88A1CC83578008B24CD /* energystream.c */,
                                AFA55C230993435300F3E977 /* engine.c */,
                                AF21078B1FD23D5000B61EA9 /* esper.c */,
+                               AF2D0D3F241D7D7F0001D8B8 /* etruscanvenus.c */,
                                AF642409099FFAF0000F4CD4 /* extrusion-helix2.c */,
                                AF64240A099FFAF0000F4CD4 /* extrusion-helix3.c */,
                                AF64240B099FFAF0000F4CD4 /* extrusion-helix4.c */,
                                AFF3CA0217CCAEB70028F240 /* geodesic.c */,
                                AF7ACFD619FF0B7A00BD752B /* geodesicgears.c */,
                                AFA55BA60993401A00F3E977 /* gflux.c */,
+                               AFA0B135241CE7B60071E35D /* gibson.c */,
                                AFA55E4509935FD300F3E977 /* glblur.c */,
                                AFF463710C440B9200EE6509 /* glcells.c */,
                                AF77778B09B64A2A00EA3033 /* gleidescope.c */,
                                AFC2589D0988A468000655EE /* epicycle.xml */,
                                AFC2589E0988A468000655EE /* eruption.xml */,
                                AF2107881FD23D2800B61EA9 /* esper.xml */,
+                               AF2D0D3C241D7D600001D8B8 /* etruscanvenus.xml */,
                                AFC2589F0988A468000655EE /* euler2d.xml */,
                                AFC258A00988A468000655EE /* extrusion.xml */,
                                AFC258A10988A468000655EE /* fadeplot.xml */,
                                AFF3C9FD17CCAD9A0028F240 /* geodesic.xml */,
                                AF7ACFD819FF0BA600BD752B /* geodesicgears.xml */,
                                AFC258B30988A468000655EE /* gflux.xml */,
+                               AFA0B138241CE7E10071E35D /* gibson.xml */,
                                AFC258B40988A468000655EE /* glblur.xml */,
                                AFF463730C440BAC00EE6509 /* glcells.xml */,
                                AFC258B50988A468000655EE /* gleidescope.xml */,
                                AFC259080988A469000655EE /* rubik.xml */,
                                AF32D9FC0F3AD1330080F535 /* rubikblocks.xml */,
                                AFC259090988A469000655EE /* sballs.xml */,
+                               AF436415241D85B900966603 /* scooter.xml */,
                                AFC2590A0988A469000655EE /* shadebobs.xml */,
                                AFC2590B0988A469000655EE /* sierpinski.xml */,
                                AFC2590C0988A469000655EE /* sierpinski3d.xml */,
                        productReference = AF2107861FD23BDE00B61EA9 /* Esper.saver */;
                        productType = "com.apple.product-type.bundle";
                };
+               AF2D0D25241D7C870001D8B8 /* EtruscanVenus */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AF2D0D37241D7C870001D8B8 /* Build configuration list for PBXNativeTarget "EtruscanVenus" */;
+                       buildPhases = (
+                               AF2D0D28241D7C870001D8B8 /* Resources */,
+                               AF2D0D2A241D7C870001D8B8 /* Sources */,
+                               AF2D0D2D241D7C870001D8B8 /* Frameworks */,
+                               AF2D0D35241D7C870001D8B8 /* Rez */,
+                               AF2D0D36241D7C870001D8B8 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AF2D0D26241D7C870001D8B8 /* PBXTargetDependency */,
+                       );
+                       name = EtruscanVenus;
+                       productName = DangerBall;
+                       productReference = AF2D0D3A241D7C870001D8B8 /* EtruscanVenus.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
                AF32D9E00F3AD0B40080F535 /* RubikBlocks */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = AF32D9F10F3AD0B40080F535 /* Build configuration list for PBXNativeTarget "RubikBlocks" */;
                        productReference = AF41E967201D49DD0098E253 /* RazzleDazzle.saver */;
                        productType = "com.apple.product-type.bundle";
                };
+               AF4363FC241D84CE00966603 /* Scooter */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AF43640E241D84CE00966603 /* Build configuration list for PBXNativeTarget "Scooter" */;
+                       buildPhases = (
+                               AF4363FF241D84CE00966603 /* Resources */,
+                               AF436401241D84CE00966603 /* Sources */,
+                               AF436404241D84CE00966603 /* Frameworks */,
+                               AF43640C241D84CE00966603 /* Rez */,
+                               AF43640D241D84CE00966603 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AF4363FD241D84CE00966603 /* PBXTargetDependency */,
+                       );
+                       name = Scooter;
+                       productName = Attraction;
+                       productReference = AF436411241D84CE00966603 /* Scooter.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
                AF46E9CF1CBBA2B300240FBC /* Unicrud */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = AF46E9E11CBBA2B300240FBC /* Build configuration list for PBXNativeTarget "Unicrud" */;
                        productReference = AF9E7EBF190F4C1B00A8B01F /* enable_gc */;
                        productType = "com.apple.product-type.tool";
                };
+               AFA0B11E241CE69E0071E35D /* Gibson */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AFA0B130241CE69E0071E35D /* Build configuration list for PBXNativeTarget "Gibson" */;
+                       buildPhases = (
+                               AFA0B121241CE69E0071E35D /* Resources */,
+                               AFA0B123241CE69E0071E35D /* Sources */,
+                               AFA0B126241CE69E0071E35D /* Frameworks */,
+                               AFA0B12E241CE69E0071E35D /* Rez */,
+                               AFA0B12F241CE69E0071E35D /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AFA0B11F241CE69E0071E35D /* PBXTargetDependency */,
+                       );
+                       name = Gibson;
+                       productName = DangerBall;
+                       productReference = AFA0B133241CE69E0071E35D /* Gibson.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
                AFA2118C1CD59DAF00C0D2A1 /* RaverHoop */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = AFA2119E1CD59DAF00C0D2A1 /* Build configuration list for PBXNativeTarget "RaverHoop" */;
                29B97313FDCFA39411CA2CEA /* Project object */ = {
                        isa = PBXProject;
                        attributes = {
-                               LastUpgradeCheck = 1020;
+                               LastUpgradeCheck = 1130;
                                TargetAttributes = {
                                        AF08398F09930B6B00277BE9 = {
                                                DevelopmentTeam = 4627ATJELP;
                                        AF2107711FD23BDD00B61EA9 = {
                                                DevelopmentTeam = 4627ATJELP;
                                        };
+                                       AF2D0D25241D7C870001D8B8 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
                                        AF32D9E00F3AD0B40080F535 = {
                                                DevelopmentTeam = 4627ATJELP;
                                        };
                                        AF41E952201D49DB0098E253 = {
                                                DevelopmentTeam = 4627ATJELP;
                                        };
+                                       AF4363FC241D84CE00966603 = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
                                        AF46E9CF1CBBA2B300240FBC = {
                                                DevelopmentTeam = 4627ATJELP;
                                        };
                                        AF9E7EBE190F4C1B00A8B01F = {
                                                DevelopmentTeam = 4627ATJELP;
                                        };
+                                       AFA0B11E241CE69E0071E35D = {
+                                               DevelopmentTeam = 4627ATJELP;
+                                       };
                                        AFA2118C1CD59DAF00C0D2A1 = {
                                                DevelopmentTeam = 4627ATJELP;
                                        };
                                AF77771A09B6416100EA3033 /* Pacman */,
                                AFD56FF80996B43800BA26F7 /* Penrose */,
                                AFD5726D0996EE8500BA26F7 /* Polyominoes */,
+                               AF4363FC241D84CE00966603 /* Scooter */,
                                AFD5700F0996B4CC00BA26F7 /* Sierpinski */,
                                AFD5735D0997411200BA26F7 /* Strange */,
                                AFD572220996E4A300BA26F7 /* Swirl */,
                                AFA55E0D09935EDC00F3E977 /* Endgame */,
                                AFA55C0E0993431300F3E977 /* Engine */,
                                AF2107711FD23BDD00B61EA9 /* Esper */,
+                               AF2D0D25241D7C870001D8B8 /* EtruscanVenus */,
                                AF6423F2099FF9C2000F4CD4 /* Extrusion */,
                                AFA5603209936D5100F3E977 /* FlipFlop */,
                                AF77773E09B6446500EA3033 /* FlipScreen3D */,
                                AFF3C9E817CCAC440028F240 /* Geodesic */,
                                AF7ACFC019FF0A9200BD752B /* GeodesicGears */,
                                AFA55B9109933FDA00F3E977 /* GFlux */,
+                               AFA0B11E241CE69E0071E35D /* Gibson */,
                                AFA55E2F09935F8E00F3E977 /* GLBlur */,
                                AFF463580C440AEF00EE6509 /* GLCells */,
                                AF77777409B6497800EA3033 /* Gleidescope */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF2D0D28241D7C870001D8B8 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF2D0D3D241D7D610001D8B8 /* etruscanvenus.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF32D9E30F3AD0B40080F535 /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF4363FF241D84CE00966603 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF436416241D85B900966603 /* scooter.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF46E9D21CBBA2B300240FBC /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        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 */,
                        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 */,
                        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 */,
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               AFCE26332337332000BDCE10 /* LaunchScreen.storyboard in Resources */,
                                AF918983158FC00A002B5D1E /* iSaverRunner.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 */,
                                AF918AEC158FC53D002B5D1E /* epicycle.xml in Resources */,
                                AF918AED158FC53D002B5D1E /* eruption.xml in Resources */,
                                AF21078A1FD23D2800B61EA9 /* esper.xml in Resources */,
+                               AF2D0D3E241D7D610001D8B8 /* etruscanvenus.xml in Resources */,
                                AF918AEE158FC53D002B5D1E /* euler2d.xml in Resources */,
                                AF918AF0158FC53D002B5D1E /* fadeplot.xml in Resources */,
                                AFD77E7820C2419600A3638D /* filmleader.xml in Resources */,
                                AFF3C9FF17CCAD9A0028F240 /* geodesic.xml in Resources */,
                                AF7ACFDA19FF0BA600BD752B /* geodesicgears.xml in Resources */,
                                AF918B01158FC53D002B5D1E /* gflux.xml in Resources */,
+                               AFA0B13A241CE7E10071E35D /* gibson.xml in Resources */,
                                AF918B02158FC53D002B5D1E /* glblur.xml in Resources */,
                                AF918B03158FC53D002B5D1E /* glcells.xml in Resources */,
                                AF918B04158FC53D002B5D1E /* gleidescope.xml in Resources */,
                                AF918B0A158FC53D002B5D1E /* glschool.xml in Resources */,
                                AF918B0B158FC53D002B5D1E /* glslideshow.xml in Resources */,
                                AF918B0C158FC53D002B5D1E /* glsnake.xml in Resources */,
-                               AF918B10158FC53D002B5D1E /* greynetic.xml in Resources */,
                                AF918B0D158FC53D002B5D1E /* gltext.xml in Resources */,
+                               AF918B10158FC53D002B5D1E /* greynetic.xml in Resources */,
                                AF918B0E158FC53D002B5D1E /* goop.xml in Resources */,
                                AF918B0F158FC53D002B5D1E /* grav.xml in Resources */,
                                AF6C6D8F226AE6370065A748 /* gravitywell.xml in Resources */,
                                AF918B5D158FC53E002B5D1E /* rubik.xml in Resources */,
                                AF918B5E158FC53E002B5D1E /* rubikblocks.xml in Resources */,
                                AF918B5F158FC53E002B5D1E /* sballs.xml in Resources */,
+                               AF436417241D85B900966603 /* scooter.xml in Resources */,
                                AF918B60158FC53E002B5D1E /* shadebobs.xml in Resources */,
                                AF918B61158FC53E002B5D1E /* sierpinski.xml in Resources */,
                                AF918B62158FC53E002B5D1E /* sierpinski3d.xml in Resources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFA0B121241CE69E0071E35D /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFA0B122241CE69E0071E35D /* dangerball.xml in Resources */,
+                               AFA0B139241CE7E10071E35D /* gibson.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFA2118F1CD59DAF00C0D2A1 /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF2D0D35241D7C870001D8B8 /* Rez */ = {
+                       isa = PBXRezBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF32D9EF0F3AD0B40080F535 /* Rez */ = {
                        isa = PBXRezBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF43640C241D84CE00966603 /* Rez */ = {
+                       isa = PBXRezBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF46E9DF1CBBA2B300240FBC /* Rez */ = {
                        isa = PBXRezBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFA0B12E241CE69E0071E35D /* Rez */ = {
+                       isa = PBXRezBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFA2119C1CD59DAF00C0D2A1 /* Rez */ = {
                        isa = PBXRezBuildPhase;
                        buildActionMask = 2147483647;
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
+               AF2D0D36241D7C870001D8B8 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
+                       showEnvVarsInLog = 0;
+               };
                AF32D9F00F3AD0B40080F535 /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
+               AF43640D241D84CE00966603 /* 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;
+               };
                AF46E9E01CBBA2B300240FBC /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                        shellPath = /bin/sh;
-                       shellScript = "$SOURCE_ROOT/icmp-warning.pl";
+                       shellScript = "$SOURCE_ROOT/icmp-warning.pl\n";
                };
                AF7E08021592661100D81407 /* ICMP Sanity Check */ = {
                        isa = PBXShellScriptBuildPhase;
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
+               AFA0B12F241CE69E0071E35D /* 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;
+               };
                AFA2119D1CD59DAF00C0D2A1 /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF2D0D2A241D7C870001D8B8 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF2D0D40241D7D7F0001D8B8 /* etruscanvenus.c in Sources */,
+                               AF2D0D2C241D7C870001D8B8 /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF32D9E50F3AD0B40080F535 /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF436401241D84CE00966603 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF436403241D84CE00966603 /* XScreenSaverSubclass.m in Sources */,
+                               AF436419241D85CD00966603 /* scooter.c in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF46E9D41CBBA2B300240FBC /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                                AF918A04158FC38A002B5D1E /* discrete.c in Sources */,
                                AF9189B2158FC311002B5D1E /* distort.c in Sources */,
                                AF918A05158FC38A002B5D1E /* drift.c in Sources */,
+                               AF4C300F208569AA00BE1DEF /* dymaxionmap-coords.c in Sources */,
                                AF9189B3158FC311002B5D1E /* epicycle.c in Sources */,
                                AF9189B4158FC311002B5D1E /* eruption.c in Sources */,
                                AF918A06158FC38A002B5D1E /* euler2d.c in Sources */,
                                AF918A19158FC38A002B5D1E /* pacman_ai.c in Sources */,
                                AF918A1A158FC38A002B5D1E /* pacman_level.c in Sources */,
                                AF9189D4158FC334002B5D1E /* pedal.c in Sources */,
-                               AF4C300F208569AA00BE1DEF /* dymaxionmap-coords.c in Sources */,
                                AF9189D5158FC334002B5D1E /* penetrate.c in Sources */,
                                AF9189D6158FC334002B5D1E /* petri.c in Sources */,
                                AF9189D7158FC334002B5D1E /* phosphor.c in Sources */,
                                AF9189DF158FC35D002B5D1E /* rocks.c in Sources */,
                                AF9189E0158FC35D002B5D1E /* rorschach.c in Sources */,
                                AF9189E1158FC35D002B5D1E /* rotzoomer.c in Sources */,
+                               AF43641A241D85CD00966603 /* scooter.c in Sources */,
                                AF9189E2158FC35D002B5D1E /* shadebobs.c in Sources */,
                                AF9189E3158FC35D002B5D1E /* slidescreen.c in Sources */,
                                AF9189E4158FC35D002B5D1E /* speedmine.c in Sources */,
                                AFACE88F1CC83617008B24CD /* energystream.c in Sources */,
                                AF918A4B158FC3E5002B5D1E /* engine.c in Sources */,
                                AF21078D1FD23D5000B61EA9 /* esper.c in Sources */,
+                               AF2D0D41241D7D7F0001D8B8 /* etruscanvenus.c in Sources */,
                                AF918A54158FC3E5002B5D1E /* flipflop.c in Sources */,
                                AF918A55158FC3E5002B5D1E /* flipscreen3d.c in Sources */,
                                AF918A56158FC3E5002B5D1E /* fliptext.c in Sources */,
                                AF918A5A158FC3E5002B5D1E /* gears.c in Sources */,
                                AFDDCCED19FF0EBD0072365B /* geodesicgears.c in Sources */,
                                AF918A5B158FC3E5002B5D1E /* gflux.c in Sources */,
+                               AFA0B137241CE7B60071E35D /* gibson.c in Sources */,
                                AF918A5C158FC3E5002B5D1E /* glblur.c in Sources */,
                                AF918A5D158FC3E5002B5D1E /* glcells.c in Sources */,
                                AF918A5E158FC3E5002B5D1E /* gleidescope.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFA0B123241CE69E0071E35D /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFA0B136241CE7B60071E35D /* gibson.c in Sources */,
+                               AFA0B125241CE69E0071E35D /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFA211911CD59DAF00C0D2A1 /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        target = AF2107711FD23BDD00B61EA9 /* Esper */;
                        targetProxy = AF21078E1FD23D9800B61EA9 /* PBXContainerItemProxy */;
                };
+               AF2D0D26241D7C870001D8B8 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AF2D0D27241D7C870001D8B8 /* PBXContainerItemProxy */;
+               };
+               AF2D0D43241D7D9F0001D8B8 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF2D0D25241D7C870001D8B8 /* EtruscanVenus */;
+                       targetProxy = AF2D0D42241D7D9F0001D8B8 /* PBXContainerItemProxy */;
+               };
                AF32D9E10F3AD0B40080F535 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
                        target = AF3C71450D624BF50030CC0D /* Hypnowheel */;
                        targetProxy = AF42C5150D624E9200B27FF6 /* PBXContainerItemProxy */;
                };
+               AF4363FD241D84CE00966603 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AF4363FE241D84CE00966603 /* PBXContainerItemProxy */;
+               };
+               AF436414241D850500966603 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4363FC241D84CE00966603 /* Scooter */;
+                       targetProxy = AF436413241D850500966603 /* PBXContainerItemProxy */;
+               };
                AF4540D20E52BE8800AE87B5 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AFE30BE80E52B14700CCF4A5 /* Sonar */;
                        target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
                        targetProxy = AF9D4DEE09B5BB19006E59CF /* PBXContainerItemProxy */;
                };
+               AFA0B11F241CE69E0071E35D /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AFA0B120241CE69E0071E35D /* PBXContainerItemProxy */;
+               };
+               AFA0B13C241CE82D0071E35D /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AFA0B11E241CE69E0071E35D /* Gibson */;
+                       targetProxy = AFA0B13B241CE82D0071E35D /* PBXContainerItemProxy */;
+               };
                AFA160921052FF87009B93AA /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AF6425CC09A18855000F4CD4 /* HyperCube */;
                        };
                        name = Release;
                };
+               AF2D0D38241D7C870001D8B8 /* 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;
+               };
+               AF2D0D39241D7C870001D8B8 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
                AF32D9F20F3AD0B40080F535 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                        };
                        name = Release;
                };
+               AF43640F241D84CE00966603 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AF436410241D84CE00966603 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
                AF46E9E21CBBA2B300240FBC /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                        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";
                        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";
                        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";
                        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";
                        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";
                        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";
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-                               ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
                                BUNDLE_IDENTIFIER = "org.jwz.${PROJECT_NAME:rfc1034identifier}";
                                CODE_SIGN_IDENTITY = "iPhone Developer";
                                "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-                               ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
                                BUNDLE_IDENTIFIER = "org.jwz.${PROJECT_NAME:rfc1034identifier}";
                                CODE_SIGN_IDENTITY = "iPhone Developer";
                                "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
                AF9771DB0989DC4B001F8B92 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
+                               CODE_SIGN_IDENTITY = "Apple Development";
                                INFOPLIST_FILE = SaverRunner.plist;
                                INSTALL_PATH = "$(HOME)/Applications";
                                PRODUCT_BUNDLE_IDENTIFIER = "${BUNDLE_IDENTIFIER}";
                AF9771DC0989DC4B001F8B92 /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
+                               CODE_SIGN_IDENTITY = "Apple Development";
                                INFOPLIST_FILE = SaverRunner.plist;
                                INSTALL_PATH = "$(HOME)/Applications";
                                PRODUCT_BUNDLE_IDENTIFIER = "${BUNDLE_IDENTIFIER}";
                AF9E7EC6190F4C1C00A8B01F /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
+                               CODE_SIGN_IDENTITY = "Apple Development";
                                PRODUCT_BUNDLE_IDENTIFIER = "${BUNDLE_IDENTIFIER}";
                                PRODUCT_NAME = "$(TARGET_NAME)";
                                SKIP_INSTALL = YES;
                AF9E7EC7190F4C1C00A8B01F /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
+                               CODE_SIGN_IDENTITY = "Apple Development";
                                PRODUCT_BUNDLE_IDENTIFIER = "${BUNDLE_IDENTIFIER}";
                                PRODUCT_NAME = "$(TARGET_NAME)";
                                SKIP_INSTALL = YES;
                        };
                        name = Release;
                };
+               AFA0B131241CE69E0071E35D /* 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;
+               };
+               AFA0B132241CE69E0071E35D /* 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;
+               };
                AFA2119F1CD59DAF00C0D2A1 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                AFA33BCC0B058754002B0E7D /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
+                               CODE_SIGN_IDENTITY = "Apple Development";
                                GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
                                INSTALL_PATH = "$(HOME)/bin";
                                "OTHER_CFLAGS[sdk=macosx*]" = "${OBJC_NO_GC_CFLAGS}";
                AFA33BCD0B058754002B0E7D /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
+                               CODE_SIGN_IDENTITY = "Apple Development";
                                GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
                                INSTALL_PATH = "$(HOME)/bin";
                                "OTHER_CFLAGS[sdk=macosx*]" = "${OBJC_NO_GC_CFLAGS}";
                AFBFE75C178642DC00432B21 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
+                               CODE_SIGN_IDENTITY = "Apple Development";
                                COPY_PHASE_STRIP = NO;
                                INFOPLIST_FILE = SaverRunner.plist;
                                INSTALL_PATH = "$(HOME)/Applications";
                AFBFE77C178647FE00432B21 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
+                               CODE_SIGN_IDENTITY = "Apple Development";
                                COPY_PHASE_STRIP = NO;
                                INFOPLIST_FILE = SaverRunner.plist;
                                INSTALL_PATH = "$(HOME)/Applications";
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
+               AF2D0D37241D7C870001D8B8 /* Build configuration list for PBXNativeTarget "EtruscanVenus" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AF2D0D38241D7C870001D8B8 /* Debug */,
+                               AF2D0D39241D7C870001D8B8 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                AF32D9F10F3AD0B40080F535 /* Build configuration list for PBXNativeTarget "RubikBlocks" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
+               AF43640E241D84CE00966603 /* Build configuration list for PBXNativeTarget "Scooter" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AF43640F241D84CE00966603 /* Debug */,
+                               AF436410241D84CE00966603 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                AF46E9E11CBBA2B300240FBC /* Build configuration list for PBXNativeTarget "Unicrud" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
+               AFA0B130241CE69E0071E35D /* Build configuration list for PBXNativeTarget "Gibson" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AFA0B131241CE69E0071E35D /* Debug */,
+                               AFA0B132241CE69E0071E35D /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                AFA2119E1CD59DAF00C0D2A1 /* Build configuration list for PBXNativeTarget "RaverHoop" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
diff --git a/README b/README
index 118a0615c31d4e2d6ead0ebb127df40db5dcfd68..0b55bd16551faf63bfb2da30e947525574005be5 100644 (file)
--- a/README
+++ b/README
@@ -46,6 +46,20 @@ XScreenSaver has an extensive manual -- please read it!
 
 ===============================================================================
 
+5.44   * New hacks, `gibson', `etruscanvenus' and `scooter'.
+       * BSOD supports Tivo and Nintendo.
+       * New color options in `romanboy', `projectiveplane', `hypertorus'
+          and `klein'.
+       * macOS: Fixed "Use random screen saver" on macOS 10.15.
+       * iOS: Supports dark mode.
+       * iOS: Fixed image loading on iOS 13.
+       * iOS: Fixed rotation on iOS 13 (Apple incompatibly breaks rotation
+          every two years as a matter of policy).
+        * Performance tweaks for `eruption', `fireworkx', `halftone', `halo',
+          `moire2', `rd-bomb'.
+       * X11: Always use $HOME/.xscreensaver, not getpwuid's directory.
+       * Various bug fixes.
+
 5.43   * New hacks, `GravityWell', `DeepStars'.
        * GLPlanet now supports the Mercator projection.
        * Bouncing Cow has mathematically ideal cows (spherical, frictionless).
index 451aec15d25d0e51328225cf8bd0abee88958b8b..f2958b4749cf61576d011bafe288d4086fc6b184 100644 (file)
@@ -90,7 +90,7 @@ The XScreenSaver API
   state machine.
 
   You may not store global state in global variables, or in function-local
-  static variables.  All of your runtime state must be encapsulted in the
+  static variables.  All of your runtime state must be encapsulated in the
   "state" object created by your "init" function.  If you use global or
   static variables, your screen saver will not work properly on macOS.
 
index 868d7f12baa0157b67adc558296f725e805d6363..0e52e124798d3040567afc9a5f9b9f04aac02b99 100644 (file)
@@ -6,10 +6,21 @@ GRADLE = ./gradlew
 default:: debug
 all:: release
 
-clean::
-       $(GRADLE) clean
+# Your sdk.dir and ndk.dir might go in here; gradle wants the file to exist.
+local.properties:
+       touch local.properties
+
+clean:: local.properties
+       @\
+  if [ "x" == x"$$JAVA_HOME" ] && ! ( which java >&- 2>&- ) ; then     \
+    echo "android: not cleaning: no java" >&2 ;                                \
+  else                                                                 \
+    echo $(GRADLE) clean ;                                             \
+         $(GRADLE) clean ;                                             \
+  fi
 
-distdepend::
+
+distdepend:: local.properties
 
 # 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
@@ -97,6 +108,7 @@ export ANDROID_HACKS=                \
        epicycle                \
        eruption                \
        esper                   \
+       etruscanvenus           \
        euler2d                 \
        fadeplot                \
        fiberlamp               \
@@ -114,6 +126,7 @@ export ANDROID_HACKS=               \
        geodesic                \
        geodesicgears           \
        gflux                   \
+       gibson                  \
        glblur                  \
        glcells                 \
        gleidescope             \
@@ -129,6 +142,7 @@ export ANDROID_HACKS=               \
        grav                    \
        gravitywell             \
        greynetic               \
+       halftone                \
        halo                    \
        handsy                  \
        helix                   \
@@ -197,6 +211,7 @@ export ANDROID_HACKS=               \
        rubik                   \
        rubikblocks             \
        sballs                  \
+       scooter                 \
        shadebobs               \
        sierpinski              \
        sierpinski3d            \
@@ -251,7 +266,6 @@ ANDROID_TODO=                       \
        carousel                \
        fliptext                \
        fontglide               \
-       halftone                \
        juggler3d               \
        molecule                \
        pedal                   \
@@ -323,6 +337,7 @@ clean_thumbs::
        done
 
 distclean:: clean_thumbs clean
+       rm -rf .gradle
 
 
 EXTRA_TARFILES = xscreensaver/res/drawable/thumbnail.png \
@@ -337,16 +352,19 @@ echo_tarfiles:
                -o -name '*_settings.xml'       \
                -o -name '*_wallpaper.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 .idea                  \
+               -o -name attrs.xml              \
                -o -name build                  \
+               -o -name caches                 \
+               -o -name drawable               \
                -o -name gen                    \
                -o -name libs                   \
+               -o -name local.properties       \
                -o -name obj                    \
+               -o -name settings.xml           \
+               -o -name strings.xml            \
                \) -prune \)                    \
                -o \( \( -type f -o -type l \)  \
                      -print \)                 \
@@ -360,9 +378,9 @@ images_png_h:
 run_check::
        ../hacks/check-configs.pl --build-android $(ANDROID_HACKS)
 
-debug:: m6502.h run_check images_png_h
+debug::   local.properties m6502.h run_check images_png_h
        $(GRADLE) assembleDebug
-release:: m6502.h run_check images_png_h
+release:: local.properties m6502.h run_check images_png_h
        export APP_ABI=all ; \
        $(GRADLE) assembleRelease
 
index 2843296548b6cae41058a01b737c578e0f4ca360..c355a88ab2f77add8188944ec578e6466c7f4a34 100644 (file)
@@ -23,6 +23,7 @@ To set up your Android development environment:
     On MacOS, the value you want is probably ~/Library/Android/sdk/
     Also set "ndk.dir" in local.properties.
 
+
 To build:
 
     ./configure
@@ -76,6 +77,19 @@ To build:
     thing to boot up again, it will probably work next time.  Probably.
 
 
+WTF is Gradle?
+
+    "gradle" is a yet another re-invention of "make" that is written
+    in Java, because we needed that like another hole in the head.
+    The actual gradle app is bundled here, in a .jar file.
+
+    "gradlew" is an sh script that tries to figure out how to invoke
+    Java to run gradle properly.
+
+    There are identical copies of gradle and gradlew in both
+    "android/" and in "android/xscreensaver/".  I don't know why.
+
+
 Directory structure:
 
     Boilerplate for the Java version of "make":
index 978b94c05229f5a928ba63a878aaee2dca0b4205..542b49203190e270c901e5b71c73285705dcfb4f 100644 (file)
@@ -5,7 +5,7 @@ buildscript {
         jcenter()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:3.1.2'
+        classpath 'com.android.tools.build:gradle:3.5.3'
     }
 
 }
index 0ac000f59d2084939cd0192e7fe589d4758013e7..4f40498223b1869d8248ce7012d8942892a77209 100644 (file)
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.8-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip
diff --git a/android/local.properties b/android/local.properties
deleted file mode 100644 (file)
index 238a21c..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must *NOT* be checked into Version Control Systems,
-# as it contains information specific to your local configuration.
-
-# location of the SDK. This is only used by Ant
-# For customization when using a Version Control System, please read the
-# header note.
-sdk.dir=/Users/jwz/Library/Android/sdk
-ndk.dir=/Users/jwz/Library/Android/sdk/ndk
diff --git a/android/xscreensaver/.idea/caches/build_file_checksums.ser b/android/xscreensaver/.idea/caches/build_file_checksums.ser
deleted file mode 100644 (file)
index c2ab27f..0000000
Binary files a/android/xscreensaver/.idea/caches/build_file_checksums.ser and /dev/null differ
diff --git a/android/xscreensaver/.idea/codeStyles/Project.xml b/android/xscreensaver/.idea/codeStyles/Project.xml
deleted file mode 100644 (file)
index 30aa626..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-<component name="ProjectCodeStyleConfiguration">
-  <code_scheme name="Project" version="173">
-    <Objective-C-extensions>
-      <file>
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
-      </file>
-      <class>
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
-        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
-      </class>
-      <extensions>
-        <pair source="cpp" header="h" fileNamingConvention="NONE" />
-        <pair source="c" header="h" fileNamingConvention="NONE" />
-      </extensions>
-    </Objective-C-extensions>
-  </code_scheme>
-</component>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/compiler.xml b/android/xscreensaver/.idea/compiler.xml
deleted file mode 100644 (file)
index 9a8b7e5..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="CompilerConfiguration">
-    <option name="DEFAULT_COMPILER" value="Javac" />
-    <resourceExtensions />
-    <wildcardResourcePatterns>
-      <entry name="!?*.java" />
-      <entry name="!?*.form" />
-      <entry name="!?*.class" />
-      <entry name="!?*.groovy" />
-      <entry name="!?*.scala" />
-      <entry name="!?*.flex" />
-      <entry name="!?*.kt" />
-      <entry name="!?*.clj" />
-    </wildcardResourcePatterns>
-    <annotationProcessing>
-      <profile default="true" name="Default" enabled="false">
-        <processorPath useClasspath="true" />
-      </profile>
-    </annotationProcessing>
-  </component>
-</project>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/gradle.xml b/android/xscreensaver/.idea/gradle.xml
deleted file mode 100644 (file)
index 3ac097a..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="GradleSettings">
-    <option name="linkedExternalProjectsSettings">
-      <GradleProjectSettings>
-        <option name="distributionType" value="LOCAL" />
-        <option name="externalProjectPath" value="$PROJECT_DIR$" />
-        <option name="gradleHome" value="$APPLICATION_HOME_DIR$/gradle/gradle-4.1" />
-        <option name="modules">
-          <set>
-            <option value="$PROJECT_DIR$/.." />
-            <option value="$PROJECT_DIR$" />
-          </set>
-        </option>
-        <option name="resolveModulePerSourceSet" value="false" />
-      </GradleProjectSettings>
-    </option>
-  </component>
-</project>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/libraries/Gradle__android_arch_core_common_1_1_0_jar.xml b/android/xscreensaver/.idea/libraries/Gradle__android_arch_core_common_1_1_0_jar.xml
deleted file mode 100644 (file)
index 9869803..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<component name="libraryTable">
-  <library name="Gradle: android.arch.core:common:1.1.0@jar">
-    <CLASSES>
-      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/android.arch.core/common/1.1.0/8007981f7d7540d89cd18471b8e5dcd2b4f99167/common-1.1.0.jar!/" />
-    </CLASSES>
-    <JAVADOC />
-    <SOURCES>
-      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/android.arch.core/common/1.1.0/f211e8f994b67f7ae2a1bc06e4f7b974ec72ee50/common-1.1.0-sources.jar!/" />
-    </SOURCES>
-  </library>
-</component>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/libraries/Gradle__android_arch_core_runtime_1_1_0.xml b/android/xscreensaver/.idea/libraries/Gradle__android_arch_core_runtime_1_1_0.xml
deleted file mode 100644 (file)
index 03529f7..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<component name="libraryTable">
-  <library name="Gradle: android.arch.core:runtime-1.1.0">
-    <CLASSES>
-      <root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/runtime-1.1.0.aar/66eddde487cc032a22af511624a2dc1d/jars/classes.jar!/" />
-      <root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/runtime-1.1.0.aar/66eddde487cc032a22af511624a2dc1d/res" />
-    </CLASSES>
-    <JAVADOC />
-    <SOURCES>
-      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/android.arch.core/runtime/1.1.0/62944187d3ae3e7a4644b50da4e7b63c605a696/runtime-1.1.0-sources.jar!/" />
-    </SOURCES>
-  </library>
-</component>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/libraries/Gradle__android_arch_lifecycle_common_1_1_0_jar.xml b/android/xscreensaver/.idea/libraries/Gradle__android_arch_lifecycle_common_1_1_0_jar.xml
deleted file mode 100644 (file)
index 29c0049..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<component name="libraryTable">
-  <library name="Gradle: android.arch.lifecycle:common:1.1.0@jar">
-    <CLASSES>
-      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/android.arch.lifecycle/common/1.1.0/edf3f7bfb84a7521d0599efa3b0113a0ee90f85/common-1.1.0.jar!/" />
-    </CLASSES>
-    <JAVADOC />
-    <SOURCES>
-      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/android.arch.lifecycle/common/1.1.0/72f6113534923e49e8c032107ca638b97775c61b/common-1.1.0-sources.jar!/" />
-    </SOURCES>
-  </library>
-</component>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/libraries/Gradle__android_arch_lifecycle_livedata_core_1_1_0.xml b/android/xscreensaver/.idea/libraries/Gradle__android_arch_lifecycle_livedata_core_1_1_0.xml
deleted file mode 100644 (file)
index c43180e..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<component name="libraryTable">
-  <library name="Gradle: android.arch.lifecycle:livedata-core-1.1.0">
-    <CLASSES>
-      <root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/livedata-core-1.1.0.aar/01d9f7cf052a887e242d3ac9bccb130e/res" />
-      <root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/livedata-core-1.1.0.aar/01d9f7cf052a887e242d3ac9bccb130e/jars/classes.jar!/" />
-    </CLASSES>
-    <JAVADOC />
-    <SOURCES>
-      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/android.arch.lifecycle/livedata-core/1.1.0/300f89e645a95de0bdc6d8833beeee6e3045df06/livedata-core-1.1.0-sources.jar!/" />
-    </SOURCES>
-  </library>
-</component>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/libraries/Gradle__android_arch_lifecycle_runtime_1_1_0.xml b/android/xscreensaver/.idea/libraries/Gradle__android_arch_lifecycle_runtime_1_1_0.xml
deleted file mode 100644 (file)
index 6031fb9..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<component name="libraryTable">
-  <library name="Gradle: android.arch.lifecycle:runtime-1.1.0">
-    <CLASSES>
-      <root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/runtime-1.1.0.aar/625fea47a711c4db819aa2d6df929100/jars/classes.jar!/" />
-      <root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/runtime-1.1.0.aar/625fea47a711c4db819aa2d6df929100/res" />
-    </CLASSES>
-    <JAVADOC />
-    <SOURCES>
-      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/android.arch.lifecycle/runtime/1.1.0/a4b0d6b8e8f51c8f95d5a0641f81ffc13ab406c7/runtime-1.1.0-sources.jar!/" />
-    </SOURCES>
-  </library>
-</component>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/libraries/Gradle__android_arch_lifecycle_viewmodel_1_1_0.xml b/android/xscreensaver/.idea/libraries/Gradle__android_arch_lifecycle_viewmodel_1_1_0.xml
deleted file mode 100644 (file)
index 11a24fb..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<component name="libraryTable">
-  <library name="Gradle: android.arch.lifecycle:viewmodel-1.1.0">
-    <CLASSES>
-      <root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/viewmodel-1.1.0.aar/0c933938d5403a08c5e3efe386ac2b02/res" />
-      <root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/viewmodel-1.1.0.aar/0c933938d5403a08c5e3efe386ac2b02/jars/classes.jar!/" />
-    </CLASSES>
-    <JAVADOC />
-    <SOURCES>
-      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/android.arch.lifecycle/viewmodel/1.1.0/e4c0c5d65f92ccad0b0148ac2f01b540ac7a711e/viewmodel-1.1.0-sources.jar!/" />
-    </SOURCES>
-  </library>
-</component>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_annotations_27_1_1_jar.xml b/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_annotations_27_1_1_jar.xml
deleted file mode 100644 (file)
index 1517ad9..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<component name="libraryTable">
-  <library name="Gradle: com.android.support:support-annotations:27.1.1@jar">
-    <CLASSES>
-      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.support/support-annotations/27.1.1/39ded76b5e1ce1c5b2688e1d25cdc20ecee32007/support-annotations-27.1.1.jar!/" />
-    </CLASSES>
-    <JAVADOC />
-    <SOURCES>
-      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.support/support-annotations/27.1.1/46bebf5bd40146178cb33c7678f3782a09dea6e4/support-annotations-27.1.1-sources.jar!/" />
-    </SOURCES>
-  </library>
-</component>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_compat_27_1_1.xml b/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_compat_27_1_1.xml
deleted file mode 100644 (file)
index fba52e8..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<component name="libraryTable">
-  <library name="Gradle: com.android.support:support-compat-27.1.1">
-    <CLASSES>
-      <root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-compat-27.1.1.aar/64b85698f5c1a639182eb49d0126a2d0/res" />
-      <root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-compat-27.1.1.aar/64b85698f5c1a639182eb49d0126a2d0/jars/classes.jar!/" />
-    </CLASSES>
-    <JAVADOC />
-    <SOURCES>
-      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.support/support-compat/27.1.1/fe233277b6eae25ce5b2afab6daf55d73c86f0b9/support-compat-27.1.1-sources.jar!/" />
-    </SOURCES>
-  </library>
-</component>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_core_ui_27_1_1.xml b/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_core_ui_27_1_1.xml
deleted file mode 100644 (file)
index 3ccece0..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<component name="libraryTable">
-  <library name="Gradle: com.android.support:support-core-ui-27.1.1">
-    <CLASSES>
-      <root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-core-ui-27.1.1.aar/b432dca2f3c4bd72e4ef10511d8d2ba5/res" />
-      <root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-core-ui-27.1.1.aar/b432dca2f3c4bd72e4ef10511d8d2ba5/jars/classes.jar!/" />
-    </CLASSES>
-    <JAVADOC />
-    <SOURCES>
-      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.support/support-core-ui/27.1.1/266c369a3227be5afec33e11c964472269ff2a7c/support-core-ui-27.1.1-sources.jar!/" />
-    </SOURCES>
-  </library>
-</component>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_core_utils_27_1_1.xml b/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_core_utils_27_1_1.xml
deleted file mode 100644 (file)
index 69d23f2..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<component name="libraryTable">
-  <library name="Gradle: com.android.support:support-core-utils-27.1.1">
-    <CLASSES>
-      <root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-core-utils-27.1.1.aar/0980a98a9ec854145d292239910611d4/jars/classes.jar!/" />
-      <root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-core-utils-27.1.1.aar/0980a98a9ec854145d292239910611d4/res" />
-    </CLASSES>
-    <JAVADOC />
-    <SOURCES>
-      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.support/support-core-utils/27.1.1/8fb37fd2f8dbc23482865700d2c340ae030ea561/support-core-utils-27.1.1-sources.jar!/" />
-    </SOURCES>
-  </library>
-</component>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_fragment_27_1_1.xml b/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_fragment_27_1_1.xml
deleted file mode 100644 (file)
index 8eb356f..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<component name="libraryTable">
-  <library name="Gradle: com.android.support:support-fragment-27.1.1">
-    <CLASSES>
-      <root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-fragment-27.1.1.aar/c39b8c3b0b8a6fd39d4cf14a5ed4d9a8/jars/classes.jar!/" />
-      <root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-fragment-27.1.1.aar/c39b8c3b0b8a6fd39d4cf14a5ed4d9a8/res" />
-    </CLASSES>
-    <JAVADOC />
-    <SOURCES>
-      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.support/support-fragment/27.1.1/94732bda44fba11302c58e459b7c1f47e7521bf9/support-fragment-27.1.1-sources.jar!/" />
-    </SOURCES>
-  </library>
-</component>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_media_compat_27_1_1.xml b/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_media_compat_27_1_1.xml
deleted file mode 100644 (file)
index c577eba..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<component name="libraryTable">
-  <library name="Gradle: com.android.support:support-media-compat-27.1.1">
-    <CLASSES>
-      <root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-media-compat-27.1.1.aar/68a94910a2befb2c6cb37bd04aa2aa39/res" />
-      <root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-media-compat-27.1.1.aar/68a94910a2befb2c6cb37bd04aa2aa39/jars/classes.jar!/" />
-    </CLASSES>
-    <JAVADOC />
-    <SOURCES>
-      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.support/support-media-compat/27.1.1/3ab3f968d7cd675d2f97e67a3e9fc0ac63618f46/support-media-compat-27.1.1-sources.jar!/" />
-    </SOURCES>
-  </library>
-</component>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_v4_27_1_1.xml b/android/xscreensaver/.idea/libraries/Gradle__com_android_support_support_v4_27_1_1.xml
deleted file mode 100644 (file)
index 10d3108..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<component name="libraryTable">
-  <library name="Gradle: com.android.support:support-v4-27.1.1">
-    <CLASSES>
-      <root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-v4-27.1.1.aar/4063a17c1f54cf7b4dd719a35d318e61/res" />
-      <root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-v4-27.1.1.aar/4063a17c1f54cf7b4dd719a35d318e61/jars/classes.jar!/" />
-    </CLASSES>
-    <JAVADOC />
-    <SOURCES>
-      <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.support/support-v4/27.1.1/5b8f86fea035328fc9e8c660773037a3401ce25f/support-v4-27.1.1-sources.jar!/" />
-    </SOURCES>
-  </library>
-</component>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/misc.xml b/android/xscreensaver/.idea/misc.xml
deleted file mode 100644 (file)
index 99202cc..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="NullableNotNullManager">
-    <option name="myDefaultNullable" value="android.support.annotation.Nullable" />
-    <option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
-    <option name="myNullables">
-      <value>
-        <list size="5">
-          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
-          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
-          <item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
-          <item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
-          <item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
-        </list>
-      </value>
-    </option>
-    <option name="myNotNulls">
-      <value>
-        <list size="4">
-          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
-          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
-          <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
-          <item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
-        </list>
-      </value>
-    </option>
-  </component>
-  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
-    <output url="file://$PROJECT_DIR$/build/classes" />
-  </component>
-  <component name="ProjectType">
-    <option name="id" value="Android" />
-  </component>
-</project>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/modules.xml b/android/xscreensaver/.idea/modules.xml
deleted file mode 100644 (file)
index 33191fe..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="ProjectModuleManager">
-    <modules>
-      <module fileurl="file://$PROJECT_DIR$/../android.iml" filepath="$PROJECT_DIR$/../android.iml" />
-      <module fileurl="file://$PROJECT_DIR$/xscreensaver.iml" filepath="$PROJECT_DIR$/xscreensaver.iml" />
-    </modules>
-  </component>
-</project>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/runConfigurations.xml b/android/xscreensaver/.idea/runConfigurations.xml
deleted file mode 100644 (file)
index 7f68460..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="RunConfigurationProducerService">
-    <option name="ignoredProducers">
-      <set>
-        <option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
-        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
-        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
-      </set>
-    </option>
-  </component>
-</project>
\ No newline at end of file
diff --git a/android/xscreensaver/.idea/workspace.xml b/android/xscreensaver/.idea/workspace.xml
deleted file mode 100644 (file)
index 9f2ef73..0000000
+++ /dev/null
@@ -1,2205 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="CMakeSettings">
-    <configurations>
-      <configuration PROFILE_NAME="Debug" CONFIG_NAME="Debug" />
-    </configurations>
-  </component>
-  <component name="ChangeListManager">
-    <list default="true" id="41008724-035d-4e24-92b6-6dfb9231c83c" name="Default" comment="" />
-    <ignored path="xscreensaver.iws" />
-    <ignored path=".idea/workspace.xml" />
-    <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
-    <option name="TRACKING_ENABLED" value="true" />
-    <option name="SHOW_DIALOG" value="false" />
-    <option name="HIGHLIGHT_CONFLICTS" value="true" />
-    <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
-    <option name="LAST_RESOLUTION" value="IGNORE" />
-  </component>
-  <component name="CreatePatchCommitExecutor">
-    <option name="PATCH_PATH" value="" />
-  </component>
-  <component name="ExternalProjectsData">
-    <projectState path="$PROJECT_DIR$">
-      <ProjectState />
-    </projectState>
-  </component>
-  <component name="ExternalProjectsManager">
-    <system id="GRADLE">
-      <state>
-        <projects_view />
-      </state>
-    </system>
-  </component>
-  <component name="FavoritesManager">
-    <favorites_list name="xscreensaver" />
-  </component>
-  <component name="FileEditorManager">
-    <leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
-      <file leaf-file-name="gradle-wrapper.properties" pinned="false" current-in-tab="true">
-        <entry file="file://$PROJECT_DIR$/../gradle/wrapper/gradle-wrapper.properties">
-          <provider selected="true" editor-type-id="text-editor">
-            <state relative-caret-position="90">
-              <caret line="6" selection-start-line="6" selection-end-line="6" />
-            </state>
-          </provider>
-        </entry>
-      </file>
-    </leaf>
-  </component>
-  <component name="GradleLocalSettings">
-    <option name="myGradleHomes">
-      <map>
-        <entry key="$PROJECT_DIR$" value="$USER_HOME$/.gradle/wrapper/dists/gradle-4.8-bin/divx0s2uj4thofgytb7gf9fsi/gradle-4.8" />
-      </map>
-    </option>
-    <option name="myGradleVersions">
-      <map>
-        <entry key="$PROJECT_DIR$" value="4.8" />
-      </map>
-    </option>
-    <option name="availableProjects">
-      <map>
-        <entry>
-          <key>
-            <ExternalProjectPojo>
-              <option name="name" value="xscreensaver" />
-              <option name="path" value="$PROJECT_DIR$" />
-            </ExternalProjectPojo>
-          </key>
-          <value>
-            <list>
-              <ExternalProjectPojo>
-                <option name="name" value="android" />
-                <option name="path" value="$PROJECT_DIR$/.." />
-              </ExternalProjectPojo>
-              <ExternalProjectPojo>
-                <option name="name" value=":xscreensaver" />
-                <option name="path" value="$PROJECT_DIR$" />
-              </ExternalProjectPojo>
-            </list>
-          </value>
-        </entry>
-      </map>
-    </option>
-    <option name="availableTasks">
-      <map>
-        <entry key="$PROJECT_DIR$/..">
-          <value>
-            <list>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays all buildscript dependencies declared in root project 'android'." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="buildEnvironment" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="clean" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the components produced by root project 'android'. [incubating]" />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="components" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays all dependencies declared in root project 'android'." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="dependencies" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the insight into a specific dependency in root project 'android'." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="dependencyInsight" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the dependent components of components in root project 'android'. [incubating]" />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="dependentComponents" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="distClean" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays a help message." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="help" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Initializes a new Gradle build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="init" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the configuration model of root project 'android'. [incubating]" />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="model" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the sub-projects of root project 'android'." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="projects" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the properties of root project 'android'." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="properties" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the tasks runnable from root project 'android' (some of the displayed tasks may belong to subprojects)." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="tasks" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Generates Gradle wrapper files." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="wrapper" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the Android dependencies of the project." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="androidDependencies" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles all variants of all applications and secondary packages." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="assemble" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles all the Test applications." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="assembleAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles all Debug builds." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="assembleDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="assembleDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="assembleDebugUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles all Release builds." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="assembleRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="assembleReleaseUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles and tests this project." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="build" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles and tests this project and all projects that depend on it." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="buildDependents" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles and tests this project and all projects it depends on." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="buildNeeded" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="bundleAppClassesDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="bundleAppClassesDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="bundleAppClassesDebugUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="bundleAppClassesRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="bundleAppClassesReleaseUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="bundleDebugAndroidTestResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="bundleDebugResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="bundleReleaseResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs all checks." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="check" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="checkDebugManifest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="checkReleaseManifest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Deletes the build cache directory." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="cleanBuildCache" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="compileDebugAidl" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="compileDebugAndroidTestAidl" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="compileDebugAndroidTestJavaWithJavac" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="compileDebugAndroidTestNdk" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="compileDebugAndroidTestRenderscript" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="compileDebugAndroidTestShaders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="compileDebugAndroidTestSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="compileDebugJavaWithJavac" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="compileDebugNdk" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="compileDebugRenderscript" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="compileDebugShaders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="compileDebugSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="compileDebugUnitTestJavaWithJavac" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="compileDebugUnitTestSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="compileLint" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="compileReleaseAidl" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="compileReleaseJavaWithJavac" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="compileReleaseNdk" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="compileReleaseRenderscript" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="compileReleaseShaders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="compileReleaseSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="compileReleaseUnitTestJavaWithJavac" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="compileReleaseUnitTestSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Installs and runs instrumentation tests for all flavors on connected devices." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="connectedAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs all device checks on currently connected devices." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="connectedCheck" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Installs and runs the tests for debug on connected devices." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="connectedDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="consumeConfigAttr" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="createDebugCompatibleScreenManifests" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="createReleaseCompatibleScreenManifests" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Installs and runs instrumentation tests using all Device Providers." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="deviceAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs all device checks using Device Providers and Test Servers." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="deviceCheck" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="downloadNeededDrawables" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="extractProguardFiles" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="generateDebugAndroidTestAssets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="generateDebugAndroidTestBuildConfig" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="generateDebugAndroidTestResValues" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="generateDebugAndroidTestResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="generateDebugAndroidTestSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="generateDebugAssets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="generateDebugBuildConfig" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="generateDebugResValues" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="generateDebugResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="generateDebugSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="generateReleaseAssets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="generateReleaseBuildConfig" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="generateReleaseResValues" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="generateReleaseResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="generateReleaseSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Installs the Debug build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="installDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Installs the android (on device) tests for the Debug build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="installDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="javaPreCompileDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="javaPreCompileDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="javaPreCompileDebugUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="javaPreCompileRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="javaPreCompileReleaseUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs lint on all variants." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="lint" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs lint on the Debug build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="lintDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs lint on the Release build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="lintRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs lint on just the fatal issues in the release build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="lintVitalRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="mainApkListPersistenceDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="mainApkListPersistenceDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="mainApkListPersistenceRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="mergeDebugAndroidTestAssets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="mergeDebugAndroidTestJniLibFolders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="mergeDebugAndroidTestResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="mergeDebugAndroidTestShaders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="mergeDebugAssets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="mergeDebugJniLibFolders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="mergeDebugResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="mergeDebugShaders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="mergeReleaseAssets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="mergeReleaseJniLibFolders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="mergeReleaseResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="mergeReleaseShaders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Creates a version of android.jar that's suitable for unit tests." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="mockableAndroidJar" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="ndkBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="objlibClean" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="packageDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="packageDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="packageRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="perlBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="perlClean" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="platformAttrExtractor" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="preBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="preDebugAndroidTestBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="preDebugBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="preDebugUnitTestBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="preReleaseBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="preReleaseUnitTestBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="prepareLintJar" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="preparePUBLISHED_DEXDebugAndroidTestForPublishing" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="preparePUBLISHED_DEXDebugForPublishing" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="preparePUBLISHED_DEXReleaseForPublishing" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="preparePUBLISHED_JAVA_RESDebugAndroidTestForPublishing" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="preparePUBLISHED_JAVA_RESDebugForPublishing" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="preparePUBLISHED_JAVA_RESReleaseForPublishing" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="preparePUBLISHED_NATIVE_LIBSDebugAndroidTestForPublishing" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="preparePUBLISHED_NATIVE_LIBSDebugForPublishing" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="preparePUBLISHED_NATIVE_LIBSReleaseForPublishing" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="processDebugAndroidTestJavaRes" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="processDebugAndroidTestManifest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="processDebugAndroidTestResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="processDebugJavaRes" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="processDebugManifest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="processDebugResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="processDebugUnitTestJavaRes" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="processReleaseJavaRes" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="processReleaseManifest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="processReleaseResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="processReleaseUnitTestJavaRes" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="reportBuildArtifactsDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="reportBuildArtifactsRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="resolveConfigAttr" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the signing info for each variant." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="signingReport" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Prints out all the source sets defined in this project." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="sourceSets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="splitsDiscoveryTaskDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="splitsDiscoveryTaskRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Run unit tests for all variants." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="test" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Run unit tests for the debug build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="testDebugUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Run unit tests for the release build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="testReleaseUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="transformClassesWithDexBuilderForDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="transformClassesWithDexBuilderForDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="transformClassesWithDexBuilderForRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="transformDexArchiveWithDexMergerForDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="transformDexArchiveWithDexMergerForDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="transformDexArchiveWithDexMergerForRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="transformDexArchiveWithExternalLibsDexMergerForDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="transformDexArchiveWithExternalLibsDexMergerForDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="transformDexArchiveWithExternalLibsDexMergerForRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="transformNativeLibsWithMergeJniLibsForDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="transformNativeLibsWithMergeJniLibsForDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="transformNativeLibsWithMergeJniLibsForRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="transformNativeLibsWithStripDebugSymbolForDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="transformNativeLibsWithStripDebugSymbolForRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="transformResourcesWithMergeJavaResForDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="transformResourcesWithMergeJavaResForDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="transformResourcesWithMergeJavaResForDebugUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="transformResourcesWithMergeJavaResForRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="transformResourcesWithMergeJavaResForReleaseUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Uninstall all applications." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="uninstallAll" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Uninstalls the Debug build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="uninstallDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Uninstalls the android (on device) tests for the Debug build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="uninstallDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Uninstalls the Release build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="uninstallRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="validateSigningDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="validateSigningDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="writeDebugApplicationId" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$/.." />
-                <option name="name" value="writeReleaseApplicationId" />
-              </ExternalTaskPojo>
-            </list>
-          </value>
-        </entry>
-        <entry key="$PROJECT_DIR$">
-          <value>
-            <list>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the sub-projects of project ':xscreensaver'." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="projects" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="bundleAppClassesRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="validateSigningDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformClassesWithDexBuilderForDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="assembleReleaseUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="bundleReleaseResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processReleaseJavaRes" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateReleaseAssets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs lint on the Debug build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="lintDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preparePUBLISHED_JAVA_RESReleaseForPublishing" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="reportBuildArtifactsRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="assembleDebugUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="createReleaseCompatibleScreenManifests" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Creates a version of android.jar that's suitable for unit tests." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mockableAndroidJar" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the configuration model of project ':xscreensaver'. [incubating]" />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="model" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preparePUBLISHED_DEXReleaseForPublishing" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="bundleAppClassesDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the tasks runnable from project ':xscreensaver'." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="tasks" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="bundleDebugAndroidTestResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs all device checks using Device Providers and Test Servers." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="deviceCheck" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays all dependencies declared in project ':xscreensaver'." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="dependencies" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processDebugResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformNativeLibsWithStripDebugSymbolForRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs lint on all variants." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="lint" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="packageDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformClassesWithDexBuilderForRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileReleaseNdk" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="bundleAppClassesReleaseUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugJavaWithJavac" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mainApkListPersistenceDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles and tests this project and all projects it depends on." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="buildNeeded" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugAndroidTestBuildConfig" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processDebugUnitTestJavaRes" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Run unit tests for the release build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="testReleaseUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Deletes the build cache directory." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="cleanBuildCache" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugAndroidTestShaders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeDebugShaders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preparePUBLISHED_JAVA_RESDebugAndroidTestForPublishing" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugAndroidTestJavaWithJavac" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the components produced by project ':xscreensaver'. [incubating]" />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="components" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileReleaseRenderscript" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles all Debug builds." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="assembleDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processDebugAndroidTestManifest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugUnitTestJavaWithJavac" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformResourcesWithMergeJavaResForReleaseUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preDebugAndroidTestBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processDebugAndroidTestJavaRes" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processReleaseUnitTestJavaRes" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="reportBuildArtifactsDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformDexArchiveWithExternalLibsDexMergerForRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="javaPreCompileDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="splitsDiscoveryTaskDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="bundleAppClassesDebugUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Uninstalls the Release build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="uninstallRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileReleaseShaders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeReleaseResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugAndroidTestSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="checkReleaseManifest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="javaPreCompileDebugUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugAndroidTestSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="createDebugCompatibleScreenManifests" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preparePUBLISHED_NATIVE_LIBSReleaseForPublishing" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeReleaseJniLibFolders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="prepareLintJar" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processReleaseResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Installs and runs instrumentation tests using all Device Providers." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="deviceAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeDebugAndroidTestAssets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preparePUBLISHED_NATIVE_LIBSDebugForPublishing" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processReleaseManifest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Uninstalls the android (on device) tests for the Debug build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="uninstallDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the insight into a specific dependency in project ':xscreensaver'." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="dependencyInsight" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateReleaseSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformDexArchiveWithDexMergerForRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preReleaseBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="writeDebugApplicationId" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles all variants of all applications and secondary packages." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="assemble" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays a help message." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="help" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileReleaseUnitTestSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Installs the android (on device) tests for the Debug build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="installDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mainApkListPersistenceDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformClassesWithDexBuilderForDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeDebugAssets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="javaPreCompileReleaseUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preparePUBLISHED_DEXDebugAndroidTestForPublishing" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="javaPreCompileRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="splitsDiscoveryTaskRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs all device checks on currently connected devices." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="connectedCheck" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Installs and runs the tests for debug on connected devices." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="connectedDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformDexArchiveWithDexMergerForDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Uninstall all applications." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="uninstallAll" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformNativeLibsWithMergeJniLibsForDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles all the Test applications." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="assembleAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processDebugAndroidTestResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preparePUBLISHED_DEXDebugForPublishing" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="packageRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="validateSigningDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugAidl" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeDebugResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preDebugUnitTestBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileLint" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugAndroidTestResValues" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mainApkListPersistenceRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformNativeLibsWithMergeJniLibsForDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeReleaseShaders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the Android dependencies of the project." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="androidDependencies" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugAndroidTestNdk" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugUnitTestSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformNativeLibsWithMergeJniLibsForRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformDexArchiveWithExternalLibsDexMergerForDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeDebugAndroidTestJniLibFolders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="extractProguardFiles" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="assembleDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preparePUBLISHED_JAVA_RESDebugForPublishing" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="objlibClean" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processDebugJavaRes" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="consumeConfigAttr" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugAndroidTestAssets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileReleaseJavaWithJavac" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformResourcesWithMergeJavaResForDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="downloadNeededDrawables" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Run unit tests for all variants." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="test" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformNativeLibsWithStripDebugSymbolForDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugNdk" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeDebugAndroidTestResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preReleaseUnitTestBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugResValues" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs all checks." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="check" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="javaPreCompileDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Run unit tests for the debug build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="testDebugUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Installs and runs instrumentation tests for all flavors on connected devices." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="connectedAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Installs the Debug build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="installDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformResourcesWithMergeJavaResForRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileReleaseSources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileReleaseUnitTestJavaWithJavac" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugShaders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformResourcesWithMergeJavaResForDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileReleaseAidl" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs lint on the Release build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="lintRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles and tests this project and all projects that depend on it." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="buildDependents" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugAssets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformDexArchiveWithDexMergerForDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the dependent components of components in project ':xscreensaver'. [incubating]" />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="dependentComponents" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays all buildscript dependencies declared in project ':xscreensaver'." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="buildEnvironment" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="checkDebugManifest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeDebugJniLibFolders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Prints out all the source sets defined in this project." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="sourceSets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformResourcesWithMergeJavaResForDebugUnitTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="perlBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="bundleDebugResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeReleaseAssets" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugRenderscript" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateReleaseBuildConfig" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preparePUBLISHED_NATIVE_LIBSDebugAndroidTestForPublishing" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="perlClean" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateReleaseResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Runs lint on just the fatal issues in the release build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="lintVitalRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="ndkBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="platformAttrExtractor" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Uninstalls the Debug build." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="uninstallDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the signing info for each variant." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="signingReport" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugAndroidTestAidl" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="mergeDebugAndroidTestShaders" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="bundleAppClassesDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Deletes the build directory." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="clean" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="preDebugBuild" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugBuildConfig" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="transformDexArchiveWithExternalLibsDexMergerForDebug" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles and tests this project." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="build" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Assembles all Release builds." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="assembleRelease" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="resolveConfigAttr" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="compileDebugAndroidTestRenderscript" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateDebugAndroidTestResources" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="processDebugManifest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="writeReleaseApplicationId" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="packageDebugAndroidTest" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="generateReleaseResValues" />
-              </ExternalTaskPojo>
-              <ExternalTaskPojo>
-                <option name="description" value="Displays the properties of project ':xscreensaver'." />
-                <option name="linkedExternalProjectPath" value="$PROJECT_DIR$" />
-                <option name="name" value="properties" />
-              </ExternalTaskPojo>
-            </list>
-          </value>
-        </entry>
-      </map>
-    </option>
-    <option name="projectBuildClasspath">
-      <map>
-        <entry key="$PROJECT_DIR$">
-          <value>
-            <ExternalProjectBuildClasspathPojo>
-              <option name="modulesBuildClasspath">
-                <map>
-                  <entry key="$PROJECT_DIR$/..">
-                    <value>
-                      <ExternalModuleBuildClasspathPojo>
-                        <option name="entries">
-                          <list>
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle/3.1.2/1608fa49add4d13366db7844998c6e59711f7e2a/gradle-3.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-core/3.1.2/ccab33656c1baa6514d88f4d9356db19d0e9823b/gradle-core-3.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/bundletool/0.1.0-alpha01/f7c303e37818223bd98566fcbea29aa0964c4d06/bundletool-0.1.0-alpha01.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder/3.1.2/133b1f665104f0ebf01f71b61e4794385d7b5f1b/builder-3.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-gradle-api/26.1.2/8c54aedfe9da66e64402de04883cee083c127a3b/lint-gradle-api-26.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-api/3.1.2/427e25639a55911cadcf70657c9b2ded2ad6af2b/gradle-api-3.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/compilerCommon/3.1.2/be65c11ded4242932046f23ecfa5c7ccb0e98f46/compilerCommon-3.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-jre8/1.2.0/505f55b9619bbc5f5e26c77427dd24a6a441eef1/kotlin-stdlib-jre8-1.2.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/transform-api/2.0.0-deprecated-use-gradle-api/47f6c56527c42425742fa9b56ffd3fd80763fe03/transform-api-2.0.0-deprecated-use-gradle-api.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm/5.1/5ef31c4fe953b1fd00b8a88fa1d6820e8785bb45/asm-5.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-analysis/5.1/6d1bf8989fc7901f868bee3863c44f21aa63d110/asm-analysis-5.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-commons/5.1/25d8a575034dd9cfcb375a39b5334f0ba9c8474e/asm-commons-5.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-util/5.1/b60e33a6bd0d71831e0c249816d01e6c1dd90a47/asm-util-5.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.sf.jopt-simple/jopt-simple/4.9/ee9e9eaa0a35360dcfeac129ff4923215fd65904/jopt-simple-4.9.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.sf.proguard/proguard-gradle/5.3.3/ad23a0505f58d0dfc95bb1472decc397460406c9/proguard-gradle-5.3.3.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.auto.value/auto-value/1.5.2/1b94ab7ec707e2220a0d1a7517488d1843236345/auto-value-1.5.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.guava/guava/22.0/3564ef3803de51fb0530a8377ec6100b33b0d073/guava-22.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.protobuf/protobuf-java/3.4.0/b32aba0cbe737a4ca953f71688725972e3ee927c/protobuf-java-3.4.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.protobuf/protobuf-java-util/3.4.0/96aba8ab71c16018c6adf66771ce15c6491bc0fe/protobuf-java-util-3.4.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.errorprone/error_prone_annotations/2.1.2/6dcc08f90f678ac33e5ef78c3c752b6f59e63e0c/error_prone_annotations-2.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/aapt2-proto/0.1.0/d1eb93a21a8d3590c3bfac574a8b6dffb2dbd21c/aapt2-proto-0.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-model/3.1.2/4504b655fa8fe72302020ca9a2387f3f23fbfb57/builder-model-3.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-test-api/3.1.2/ffb00b786822df6538377a90df9f2d11c022efc3/builder-test-api-3.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdklib/26.1.2/94697a9dff499b64b6e101bedb89a89825150af/sdklib-26.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdk-common/26.1.2/2cf773af3fb0e1bbd56a80fc6903a9d2a40a248/sdk-common-26.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/common/26.1.2/c31bbd68c51ed0ef3b8d7cdd5615acf762473887/common-26.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/manifest-merger/26.1.2/79f398427650c76f0c66c89f10e4886a1fe68c26/manifest-merger-26.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.ddms/ddmlib/26.1.2/1d423e621fb5c89fed13e41d0ed026cf5d8d7e7b/ddmlib-26.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.analytics-library/protos/26.1.2/ba53bcde9703b2bf9871128952dce844c5d743fa/protos-26.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.analytics-library/shared/26.1.2/bc21fe64fdaa64e59672e7d546d373f430e7557c/shared-26.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.analytics-library/tracker/26.1.2/2d2260da92e50ac072f89d60a596d03aab3a8757/tracker-26.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/apksig/3.1.2/5af360dd30015a9a47c8ab0af0e6b05f64760edc/apksig-3.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.squareup/javawriter/2.5.0/81241ff7078ef14f42ea2a8995fa09c096256e6b/javawriter-2.5.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.bouncycastle/bcpkix-jdk15on/1.56/4648af70268b6fdb24674fb1fd7c1fcc73db1231/bcpkix-jdk15on-1.56.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.bouncycastle/bcprov-jdk15on/1.56/a153c6f9744a3e9dd6feab5e210e1c9861362ec7/bcprov-jdk15on-1.56.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-tree/5.1/87b38c12a0ea645791ead9d3e74ae5268d1d6c34/asm-tree-5.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/it.unimi.dsi/fastutil/7.2.0/5ad3a2bb04143f70aa0765fc29fc29571a7d6b34/fastutil-7.2.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.googlecode.json-simple/json-simple/1.1/5e303a03d04e6788dddfa3655272580ae0fc13bb/json-simple-1.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-reflect/1.2.0/4bbda3b5425aa38a9f6960468a29c5ef3e8a28c9/kotlin-reflect-1.2.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/baseLibrary/3.1.2/1b6a1add6a577708b62737dc31c479549f77750d/baseLibrary-3.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.antlr/antlr4/4.5.3/f35db7e4b2446e4174ba6a73db7bd6b3e6bb5da1/antlr4-4.5.3.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/commons-io/commons-io/2.4/b1b6ea3b7e4aa4f492509a4952029cd8e48019ad/commons-io-2.4.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.googlecode.juniversalchardet/juniversalchardet/1.0.3/cd49678784c46aa8789c060538e0154013bb421b/juniversalchardet-1.0.3.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.squareup/javapoet/1.8.0/e858dc62ef484048540d27d36f3ec2177a3fa9b1/javapoet-1.8.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.code.gson/gson/2.7/751f548c85fa49f330cecbb1875893f971b33c4e/gson-2.7.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/annotations/26.1.2/4f4e0ee71b9ccaa4a70cc86e40fb84ada2ed99a3/annotations-26.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.sf.proguard/proguard-base/5.3.3/988b6b0636ce343d4962b3b37f6319dcc6e99a61/proguard-base-5.3.3.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.layoutlib/layoutlib-api/26.1.2/3697abf628d30042c1082ea846454dfd1e8da3e/layoutlib-api-26.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/dvlib/26.1.2/eb39925fee6e726468fc10344ec988c086301ed7/dvlib-26.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/repository/26.1.2/c8209ccb8ee0e5e3f293fd71d2a827f440ab811c/repository-26.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-compress/1.12/84caa68576e345eb5e7ae61a0e5a9229eb100d7b/commons-compress-1.12.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpclient/4.2.6/e4ca30a6a3a075053a61c6fc850d2432dc012ba7/httpclient-4.2.6.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpmime/4.1/9ba2dcdf94ce35c8a8e9bff242db0618ca932e92/httpmime-4.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.sf.kxml/kxml2/2.3.0/ccbc77a5fd907ef863c29f3596c6f54ffa4e9442/kxml2-2.3.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains/annotations/13.0/919f0dfe192fb4e063e7dacadee7f8bb9a2672a9/annotations-13.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.sun.activation/javax.activation/1.2.0/bf744c1e2776ed1de3c55c8dac1057ec331ef744/javax.activation-1.2.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.glassfish.jaxb/jaxb-runtime/2.2.11/65510afc78679e347b0d774617a97fedac94f8/jaxb-runtime-2.2.11.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.jimfs/jimfs/1.1/8fbd0579dc68aba6186935cc1bee21d2f3e7ec1c/jimfs-1.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpcore/4.2.5/472f0f5f8dba5d1962cb9d7739feed739a31c30d/httpcore-4.2.5.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/commons-logging/commons-logging/1.1.1/5043bfebc3db072ed80fbd362e7caf00e885d8ae/commons-logging-1.1.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/commons-codec/commons-codec/1.6/b7f0fc8f61ecadeb3695f0b9464755eee44374d4/commons-codec-1.6.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.2.0/25eb440d6eeb9fc60299121020fe726eb2100d03/kotlin-stdlib-1.2.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.glassfish.jaxb/jaxb-core/2.2.11/f5745049f5fb9cb9d9b5f513c207727f475983e9/jaxb-core-2.2.11.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jvnet.staxex/stax-ex/1.7.7/18bed5a0da27a6b43efe01282f2dc911b1cb3a72/stax-ex-1.7.7.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.sun.xml.fastinfoset/FastInfoset/1.2.13/98f56b9354e27bd2941cc5d461344e240ae51ae/FastInfoset-1.2.13.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-jre7/1.2.0/ec8b969e26fbcf2265a4d1a1539c4d1d4c5af380/kotlin-stdlib-jre7-1.2.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.code.findbugs/jsr305/1.3.9/40719ea6961c0cb6afaeb6a921eaa1f6afd4cfdf/jsr305-1.3.9.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.j2objc/j2objc-annotations/1.1/976d8d30bebc251db406f2bdb3eb01962b5685b3/j2objc-annotations-1.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.codehaus.mojo/animal-sniffer-annotations/1.14/775b7e22fb10026eed3f86e8dc556dfafe35f2d5/animal-sniffer-annotations-1.14.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/javax.xml.bind/jaxb-api/2.2.12-b140109.1041/7ed0e0d01198614194d56dfb03d9d95aa311824c/jaxb-api-2.2.12-b140109.1041.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.glassfish.jaxb/txw2/2.2.11/2df047d8c187a62f2177bf6013f1f9786cdfc8a2/txw2-2.2.11.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.sun.istack/istack-commons-runtime/2.21/c969d8f15c467f0ef7d7b04889afbe7b5d48e22f/istack-commons-runtime-2.21.jar" />
-                          </list>
-                        </option>
-                        <option name="path" value="$PROJECT_DIR$/.." />
-                      </ExternalModuleBuildClasspathPojo>
-                    </value>
-                  </entry>
-                  <entry key="$PROJECT_DIR$">
-                    <value>
-                      <ExternalModuleBuildClasspathPojo>
-                        <option name="entries">
-                          <list>
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle/3.1.2/1608fa49add4d13366db7844998c6e59711f7e2a/gradle-3.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-core/3.1.2/ccab33656c1baa6514d88f4d9356db19d0e9823b/gradle-core-3.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/bundletool/0.1.0-alpha01/f7c303e37818223bd98566fcbea29aa0964c4d06/bundletool-0.1.0-alpha01.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder/3.1.2/133b1f665104f0ebf01f71b61e4794385d7b5f1b/builder-3.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-gradle-api/26.1.2/8c54aedfe9da66e64402de04883cee083c127a3b/lint-gradle-api-26.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-api/3.1.2/427e25639a55911cadcf70657c9b2ded2ad6af2b/gradle-api-3.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/compilerCommon/3.1.2/be65c11ded4242932046f23ecfa5c7ccb0e98f46/compilerCommon-3.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-jre8/1.2.0/505f55b9619bbc5f5e26c77427dd24a6a441eef1/kotlin-stdlib-jre8-1.2.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/transform-api/2.0.0-deprecated-use-gradle-api/47f6c56527c42425742fa9b56ffd3fd80763fe03/transform-api-2.0.0-deprecated-use-gradle-api.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm/5.1/5ef31c4fe953b1fd00b8a88fa1d6820e8785bb45/asm-5.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-analysis/5.1/6d1bf8989fc7901f868bee3863c44f21aa63d110/asm-analysis-5.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-commons/5.1/25d8a575034dd9cfcb375a39b5334f0ba9c8474e/asm-commons-5.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-util/5.1/b60e33a6bd0d71831e0c249816d01e6c1dd90a47/asm-util-5.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.sf.jopt-simple/jopt-simple/4.9/ee9e9eaa0a35360dcfeac129ff4923215fd65904/jopt-simple-4.9.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.sf.proguard/proguard-gradle/5.3.3/ad23a0505f58d0dfc95bb1472decc397460406c9/proguard-gradle-5.3.3.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.auto.value/auto-value/1.5.2/1b94ab7ec707e2220a0d1a7517488d1843236345/auto-value-1.5.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.guava/guava/22.0/3564ef3803de51fb0530a8377ec6100b33b0d073/guava-22.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.protobuf/protobuf-java/3.4.0/b32aba0cbe737a4ca953f71688725972e3ee927c/protobuf-java-3.4.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.protobuf/protobuf-java-util/3.4.0/96aba8ab71c16018c6adf66771ce15c6491bc0fe/protobuf-java-util-3.4.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.errorprone/error_prone_annotations/2.1.2/6dcc08f90f678ac33e5ef78c3c752b6f59e63e0c/error_prone_annotations-2.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/aapt2-proto/0.1.0/d1eb93a21a8d3590c3bfac574a8b6dffb2dbd21c/aapt2-proto-0.1.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-model/3.1.2/4504b655fa8fe72302020ca9a2387f3f23fbfb57/builder-model-3.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder-test-api/3.1.2/ffb00b786822df6538377a90df9f2d11c022efc3/builder-test-api-3.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdklib/26.1.2/94697a9dff499b64b6e101bedb89a89825150af/sdklib-26.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/sdk-common/26.1.2/2cf773af3fb0e1bbd56a80fc6903a9d2a40a248/sdk-common-26.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/common/26.1.2/c31bbd68c51ed0ef3b8d7cdd5615acf762473887/common-26.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/manifest-merger/26.1.2/79f398427650c76f0c66c89f10e4886a1fe68c26/manifest-merger-26.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.ddms/ddmlib/26.1.2/1d423e621fb5c89fed13e41d0ed026cf5d8d7e7b/ddmlib-26.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.analytics-library/protos/26.1.2/ba53bcde9703b2bf9871128952dce844c5d743fa/protos-26.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.analytics-library/shared/26.1.2/bc21fe64fdaa64e59672e7d546d373f430e7557c/shared-26.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.analytics-library/tracker/26.1.2/2d2260da92e50ac072f89d60a596d03aab3a8757/tracker-26.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/apksig/3.1.2/5af360dd30015a9a47c8ab0af0e6b05f64760edc/apksig-3.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.squareup/javawriter/2.5.0/81241ff7078ef14f42ea2a8995fa09c096256e6b/javawriter-2.5.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.bouncycastle/bcpkix-jdk15on/1.56/4648af70268b6fdb24674fb1fd7c1fcc73db1231/bcpkix-jdk15on-1.56.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.bouncycastle/bcprov-jdk15on/1.56/a153c6f9744a3e9dd6feab5e210e1c9861362ec7/bcprov-jdk15on-1.56.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm-tree/5.1/87b38c12a0ea645791ead9d3e74ae5268d1d6c34/asm-tree-5.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/it.unimi.dsi/fastutil/7.2.0/5ad3a2bb04143f70aa0765fc29fc29571a7d6b34/fastutil-7.2.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.googlecode.json-simple/json-simple/1.1/5e303a03d04e6788dddfa3655272580ae0fc13bb/json-simple-1.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-reflect/1.2.0/4bbda3b5425aa38a9f6960468a29c5ef3e8a28c9/kotlin-reflect-1.2.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.databinding/baseLibrary/3.1.2/1b6a1add6a577708b62737dc31c479549f77750d/baseLibrary-3.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.antlr/antlr4/4.5.3/f35db7e4b2446e4174ba6a73db7bd6b3e6bb5da1/antlr4-4.5.3.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/commons-io/commons-io/2.4/b1b6ea3b7e4aa4f492509a4952029cd8e48019ad/commons-io-2.4.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.googlecode.juniversalchardet/juniversalchardet/1.0.3/cd49678784c46aa8789c060538e0154013bb421b/juniversalchardet-1.0.3.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.squareup/javapoet/1.8.0/e858dc62ef484048540d27d36f3ec2177a3fa9b1/javapoet-1.8.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.code.gson/gson/2.7/751f548c85fa49f330cecbb1875893f971b33c4e/gson-2.7.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/annotations/26.1.2/4f4e0ee71b9ccaa4a70cc86e40fb84ada2ed99a3/annotations-26.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.sf.proguard/proguard-base/5.3.3/988b6b0636ce343d4962b3b37f6319dcc6e99a61/proguard-base-5.3.3.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.layoutlib/layoutlib-api/26.1.2/3697abf628d30042c1082ea846454dfd1e8da3e/layoutlib-api-26.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/dvlib/26.1.2/eb39925fee6e726468fc10344ec988c086301ed7/dvlib-26.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools/repository/26.1.2/c8209ccb8ee0e5e3f293fd71d2a827f440ab811c/repository-26.1.2.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-compress/1.12/84caa68576e345eb5e7ae61a0e5a9229eb100d7b/commons-compress-1.12.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpclient/4.2.6/e4ca30a6a3a075053a61c6fc850d2432dc012ba7/httpclient-4.2.6.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpmime/4.1/9ba2dcdf94ce35c8a8e9bff242db0618ca932e92/httpmime-4.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/net.sf.kxml/kxml2/2.3.0/ccbc77a5fd907ef863c29f3596c6f54ffa4e9442/kxml2-2.3.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains/annotations/13.0/919f0dfe192fb4e063e7dacadee7f8bb9a2672a9/annotations-13.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.sun.activation/javax.activation/1.2.0/bf744c1e2776ed1de3c55c8dac1057ec331ef744/javax.activation-1.2.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.glassfish.jaxb/jaxb-runtime/2.2.11/65510afc78679e347b0d774617a97fedac94f8/jaxb-runtime-2.2.11.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.jimfs/jimfs/1.1/8fbd0579dc68aba6186935cc1bee21d2f3e7ec1c/jimfs-1.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpcore/4.2.5/472f0f5f8dba5d1962cb9d7739feed739a31c30d/httpcore-4.2.5.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/commons-logging/commons-logging/1.1.1/5043bfebc3db072ed80fbd362e7caf00e885d8ae/commons-logging-1.1.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/commons-codec/commons-codec/1.6/b7f0fc8f61ecadeb3695f0b9464755eee44374d4/commons-codec-1.6.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.2.0/25eb440d6eeb9fc60299121020fe726eb2100d03/kotlin-stdlib-1.2.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.glassfish.jaxb/jaxb-core/2.2.11/f5745049f5fb9cb9d9b5f513c207727f475983e9/jaxb-core-2.2.11.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jvnet.staxex/stax-ex/1.7.7/18bed5a0da27a6b43efe01282f2dc911b1cb3a72/stax-ex-1.7.7.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.sun.xml.fastinfoset/FastInfoset/1.2.13/98f56b9354e27bd2941cc5d461344e240ae51ae/FastInfoset-1.2.13.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-jre7/1.2.0/ec8b969e26fbcf2265a4d1a1539c4d1d4c5af380/kotlin-stdlib-jre7-1.2.0.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.code.findbugs/jsr305/1.3.9/40719ea6961c0cb6afaeb6a921eaa1f6afd4cfdf/jsr305-1.3.9.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.j2objc/j2objc-annotations/1.1/976d8d30bebc251db406f2bdb3eb01962b5685b3/j2objc-annotations-1.1.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.codehaus.mojo/animal-sniffer-annotations/1.14/775b7e22fb10026eed3f86e8dc556dfafe35f2d5/animal-sniffer-annotations-1.14.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/javax.xml.bind/jaxb-api/2.2.12-b140109.1041/7ed0e0d01198614194d56dfb03d9d95aa311824c/jaxb-api-2.2.12-b140109.1041.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.glassfish.jaxb/txw2/2.2.11/2df047d8c187a62f2177bf6013f1f9786cdfc8a2/txw2-2.2.11.jar" />
-                            <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.sun.istack/istack-commons-runtime/2.21/c969d8f15c467f0ef7d7b04889afbe7b5d48e22f/istack-commons-runtime-2.21.jar" />
-                          </list>
-                        </option>
-                        <option name="path" value="$PROJECT_DIR$" />
-                      </ExternalModuleBuildClasspathPojo>
-                    </value>
-                  </entry>
-                </map>
-              </option>
-              <option name="name" value="android" />
-              <option name="projectBuildClasspath">
-                <list>
-                  <option value="$PROJECT_DIR$/buildSrc/src/main/java" />
-                  <option value="$PROJECT_DIR$/buildSrc/src/main/groovy" />
-                </list>
-              </option>
-            </ExternalProjectBuildClasspathPojo>
-          </value>
-        </entry>
-      </map>
-    </option>
-  </component>
-  <component name="ProjectFrameBounds">
-    <option name="x" value="105" />
-    <option name="y" value="23" />
-    <option name="width" value="1339" />
-    <option name="height" value="859" />
-  </component>
-  <component name="ProjectView">
-    <navigator currentView="Scope" currentSubView="Project Files" proportions="" version="1">
-      <foldersAlwaysOnTop value="true" />
-    </navigator>
-    <panes>
-      <pane id="ProjectPane" />
-      <pane id="Scope">
-        <subPane subId="Project Files">
-          <expand>
-            <path>
-              <item name="Root" type="cbb8eebc:String" user="Root" />
-              <item name="android" type="cbb8eebc:String" user="android" />
-            </path>
-            <path>
-              <item name="Root" type="cbb8eebc:String" user="Root" />
-              <item name="android" type="cbb8eebc:String" user="android" />
-              <item name="$PROJECT_DIR$/.." type="cbb8eebc:String" user="$PROJECT_DIR$/.." />
-            </path>
-            <path>
-              <item name="Root" type="cbb8eebc:String" user="Root" />
-              <item name="android" type="cbb8eebc:String" user="android" />
-              <item name="$PROJECT_DIR$/.." type="cbb8eebc:String" user="$PROJECT_DIR$/.." />
-              <item name="gradle/wrapper" type="cbb8eebc:String" user="gradle/wrapper" />
-            </path>
-          </expand>
-          <select />
-        </subPane>
-      </pane>
-      <pane id="AndroidView">
-        <subPane>
-          <expand>
-            <path>
-              <item name="xscreensaver" type="1abcf292:AndroidViewProjectNode" />
-              <item name="Gradle Scripts" type="ae0cef3a:AndroidBuildScriptsGroupNode" />
-            </path>
-          </expand>
-          <select />
-        </subPane>
-      </pane>
-      <pane id="PackagesPane" />
-    </panes>
-  </component>
-  <component name="PropertiesComponent">
-    <property name="GoToClass.includeLibraries" value="false" />
-    <property name="GoToClass.toSaveIncludeLibraries" value="false" />
-    <property name="GoToFile.includeJavaFiles" value="false" />
-    <property name="MemberChooser.sorted" value="false" />
-    <property name="MemberChooser.showClasses" value="true" />
-    <property name="MemberChooser.copyJavadoc" value="false" />
-    <property name="settings.editor.selected.configurable" value="android.sdk-updates" />
-    <property name="settings.editor.splitter.proportion" value="0.2" />
-    <property name="SearchEverywhereHistoryKey" value="sdk manager&#9;ACTION&#9;WelcomeScreen.RunAndroidSdkManager" />
-    <property name="last_opened_file_path" value="$PROJECT_DIR$" />
-    <property name="show.do.not.ask.upgrade.gradle.plugin" value="2.1.0" />
-    <property name="com.android.tools.idea.instantapp.provision.ProvisionBeforeRunTaskProvider.myTimeStamp" value="1545885427557" />
-    <property name="device.picker.selection" value="Nexus_5_8.1" />
-    <property name="sync.plugin.last.upgrade.timestamp" value="1538463643381" />
-  </component>
-  <component name="RunDashboard">
-    <option name="ruleStates">
-      <list>
-        <RuleState>
-          <option name="name" value="ConfigurationTypeDashboardGroupingRule" />
-        </RuleState>
-        <RuleState>
-          <option name="name" value="StatusDashboardGroupingRule" />
-        </RuleState>
-      </list>
-    </option>
-  </component>
-  <component name="RunManager">
-    <configuration default="true" type="AndroidJUnit" factoryName="Android JUnit">
-      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
-      <option name="ALTERNATIVE_JRE_PATH" />
-      <option name="PACKAGE_NAME" />
-      <option name="MAIN_CLASS_NAME" />
-      <option name="METHOD_NAME" />
-      <option name="TEST_OBJECT" value="class" />
-      <option name="VM_PARAMETERS" />
-      <option name="PARAMETERS" />
-      <option name="WORKING_DIRECTORY" value="file://$MODULE_DIR$" />
-      <option name="PASS_PARENT_ENVS" value="true" />
-      <option name="TEST_SEARCH_SCOPE">
-        <value defaultName="singleModule" />
-      </option>
-      <patterns />
-      <method>
-        <option name="Make" enabled="false" />
-        <option name="Android.Gradle.BeforeRunTask" enabled="true" />
-      </method>
-    </configuration>
-    <configuration default="true" type="AndroidRunConfigurationType" factoryName="Android App">
-      <option name="DEPLOY" value="true" />
-      <option name="DEPLOY_APK_FROM_BUNDLE" value="false" />
-      <option name="ARTIFACT_NAME" value="" />
-      <option name="PM_INSTALL_OPTIONS" value="" />
-      <option name="DYNAMIC_FEATURES_DISABLED_LIST" value="" />
-      <option name="ACTIVITY_EXTRA_FLAGS" value="" />
-      <option name="MODE" value="default_activity" />
-      <option name="CLEAR_LOGCAT" value="false" />
-      <option name="SHOW_LOGCAT_AUTOMATICALLY" value="false" />
-      <option name="SKIP_NOOP_APK_INSTALLATIONS" value="true" />
-      <option name="FORCE_STOP_RUNNING_APP" value="true" />
-      <option name="TARGET_SELECTION_MODE" value="SHOW_DIALOG" />
-      <option name="USE_LAST_SELECTED_DEVICE" value="false" />
-      <option name="PREFERRED_AVD" value="" />
-      <option name="SELECTED_CLOUD_MATRIX_CONFIGURATION_ID" value="-1" />
-      <option name="SELECTED_CLOUD_MATRIX_PROJECT_ID" value="" />
-      <option name="DEBUGGER_TYPE" value="Auto" />
-      <Auto>
-        <option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
-        <option name="SHOW_STATIC_VARS" value="true" />
-        <option name="WORKING_DIR" value="" />
-        <option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
-        <option name="SHOW_OPTIMIZED_WARNING" value="true" />
-      </Auto>
-      <Hybrid>
-        <option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
-        <option name="SHOW_STATIC_VARS" value="true" />
-        <option name="WORKING_DIR" value="" />
-        <option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
-        <option name="SHOW_OPTIMIZED_WARNING" value="true" />
-      </Hybrid>
-      <Java />
-      <Native>
-        <option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
-        <option name="SHOW_STATIC_VARS" value="true" />
-        <option name="WORKING_DIR" value="" />
-        <option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
-        <option name="SHOW_OPTIMIZED_WARNING" value="true" />
-      </Native>
-      <Profilers>
-        <option name="ADVANCED_PROFILING_ENABLED" value="false" />
-        <option name="STARTUP_CPU_PROFILING_ENABLED" value="false" />
-        <option name="STARTUP_CPU_PROFILING_CONFIGURATION_NAME" value="Sampled (Java)" />
-      </Profilers>
-      <option name="DEEP_LINK" value="" />
-      <option name="ACTIVITY_CLASS" value="" />
-      <method>
-        <option name="Android.Gradle.BeforeRunTask" enabled="true" />
-      </method>
-    </configuration>
-    <configuration name="xscreensaver" type="AndroidRunConfigurationType" factoryName="Android App">
-      <module name="xscreensaver" />
-      <option name="DEPLOY" value="true" />
-      <option name="DEPLOY_APK_FROM_BUNDLE" value="false" />
-      <option name="ARTIFACT_NAME" value="" />
-      <option name="PM_INSTALL_OPTIONS" value="" />
-      <option name="DYNAMIC_FEATURES_DISABLED_LIST" value="" />
-      <option name="ACTIVITY_EXTRA_FLAGS" value="" />
-      <option name="MODE" value="default_activity" />
-      <option name="CLEAR_LOGCAT" value="false" />
-      <option name="SHOW_LOGCAT_AUTOMATICALLY" value="false" />
-      <option name="SKIP_NOOP_APK_INSTALLATIONS" value="true" />
-      <option name="FORCE_STOP_RUNNING_APP" value="true" />
-      <option name="TARGET_SELECTION_MODE" value="SHOW_DIALOG" />
-      <option name="USE_LAST_SELECTED_DEVICE" value="false" />
-      <option name="PREFERRED_AVD" value="" />
-      <option name="SELECTED_CLOUD_MATRIX_CONFIGURATION_ID" value="-1" />
-      <option name="SELECTED_CLOUD_MATRIX_PROJECT_ID" value="" />
-      <option name="DEBUGGER_TYPE" value="Auto" />
-      <Auto>
-        <option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
-        <option name="SHOW_STATIC_VARS" value="true" />
-        <option name="WORKING_DIR" value="" />
-        <option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
-        <option name="SHOW_OPTIMIZED_WARNING" value="true" />
-      </Auto>
-      <Hybrid>
-        <option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
-        <option name="SHOW_STATIC_VARS" value="true" />
-        <option name="WORKING_DIR" value="" />
-        <option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
-        <option name="SHOW_OPTIMIZED_WARNING" value="true" />
-      </Hybrid>
-      <Java />
-      <Native>
-        <option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
-        <option name="SHOW_STATIC_VARS" value="true" />
-        <option name="WORKING_DIR" value="" />
-        <option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
-        <option name="SHOW_OPTIMIZED_WARNING" value="true" />
-      </Native>
-      <Profilers>
-        <option name="ADVANCED_PROFILING_ENABLED" value="false" />
-        <option name="STARTUP_CPU_PROFILING_ENABLED" value="false" />
-        <option name="STARTUP_CPU_PROFILING_CONFIGURATION_NAME" value="Sampled (Java)" />
-      </Profilers>
-      <option name="DEEP_LINK" value="" />
-      <option name="ACTIVITY_CLASS" value="" />
-    </configuration>
-    <configuration default="true" type="Application" factoryName="Application">
-      <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
-    </configuration>
-    <configuration default="true" type="TestNG" factoryName="TestNG">
-      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
-      <option name="ALTERNATIVE_JRE_PATH" />
-      <option name="SUITE_NAME" />
-      <option name="PACKAGE_NAME" />
-      <option name="MAIN_CLASS_NAME" />
-      <option name="METHOD_NAME" />
-      <option name="GROUP_NAME" />
-      <option name="TEST_OBJECT" value="CLASS" />
-      <option name="VM_PARAMETERS" value="-ea" />
-      <option name="PARAMETERS" />
-      <option name="WORKING_DIRECTORY" value="$MODULE_DIR$" />
-      <option name="OUTPUT_DIRECTORY" />
-      <option name="PASS_PARENT_ENVS" value="true" />
-      <option name="TEST_SEARCH_SCOPE">
-        <value defaultName="singleModule" />
-      </option>
-      <option name="USE_DEFAULT_REPORTERS" value="false" />
-      <option name="PROPERTIES_FILE" />
-      <properties />
-      <listeners />
-    </configuration>
-    <configuration name="&lt;template&gt;" type="Applet" default="true" selected="false">
-      <option name="MAIN_CLASS_NAME" />
-      <option name="HTML_FILE_NAME" />
-      <option name="HTML_USED" value="false" />
-      <option name="WIDTH" value="400" />
-      <option name="HEIGHT" value="300" />
-      <option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" />
-      <option name="VM_PARAMETERS" />
-    </configuration>
-    <configuration name="&lt;template&gt;" type="#org.jetbrains.idea.devkit.run.PluginConfigurationType" default="true" selected="false">
-      <option name="VM_PARAMETERS" value="-Xmx512m -Xms256m -XX:MaxPermSize=250m -ea" />
-    </configuration>
-  </component>
-  <component name="SvnConfiguration">
-    <configuration />
-  </component>
-  <component name="TaskManager">
-    <task active="true" id="Default" summary="Default task">
-      <changelist id="41008724-035d-4e24-92b6-6dfb9231c83c" name="Default" comment="" />
-      <created>1475536195508</created>
-      <option name="number" value="Default" />
-      <option name="presentableId" value="Default" />
-      <updated>1475536195508</updated>
-    </task>
-    <servers />
-  </component>
-  <component name="ToolWindowManager">
-    <frame x="105" y="23" width="1339" height="859" extended-state="0" />
-    <layout>
-      <window_info anchor="bottom" id="Android Profiler" order="7" show_stripe_button="false" />
-      <window_info anchor="bottom" id="TODO" order="6" />
-      <window_info anchor="right" id="Palette&#9;" order="3" />
-      <window_info id="Image Layers" order="3" />
-      <window_info id="Build Variants" order="3" side_tool="true" />
-      <window_info anchor="right" id="Capture Analysis" order="3" />
-      <window_info active="true" anchor="bottom" id="Event Log" order="7" sideWeight="0.5188897" side_tool="true" visible="true" weight="0.32882273" />
-      <window_info anchor="bottom" id="Run" order="2" />
-      <window_info anchor="bottom" id="Version Control" order="7" show_stripe_button="false" />
-      <window_info anchor="bottom" id="Terminal" order="7" />
-      <window_info anchor="bottom" id="Logcat" order="7" />
-      <window_info id="Captures" order="2" weight="0.25" />
-      <window_info id="Capture Tool" order="3" />
-      <window_info id="Designer" order="3" />
-      <window_info content_ui="combo" id="Project" order="0" visible="true" weight="0.2544333" />
-      <window_info anchor="right" id="Assistant" visible="true" weight="0.3299923" />
-      <window_info anchor="bottom" id="Build" order="8" sideWeight="0.47185814" weight="0.32928476" />
-      <window_info anchor="bottom" id="Find" order="1" sideWeight="0.48111024" visible="true" weight="0.32882273" />
-      <window_info anchor="right" id="Gradle" order="3" />
-      <window_info id="Structure" order="1" side_tool="true" weight="0.25" />
-      <window_info anchor="right" id="Device File Explorer" order="3" side_tool="true" />
-      <window_info anchor="right" id="Theme Preview" order="3" />
-      <window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
-      <window_info id="Favorites" order="3" side_tool="true" />
-      <window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" />
-      <window_info anchor="bottom" id="Messages" order="7" sideWeight="0.49730146" visible="true" weight="0.32839838" />
-      <window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
-      <window_info anchor="right" id="Android Model" order="3" side_tool="true" />
-      <window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
-      <window_info id="Nl-Palette" order="3" />
-      <window_info anchor="right" id="Properties" order="3" />
-      <window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
-      <window_info anchor="bottom" id="Message" order="0" />
-      <window_info anchor="bottom" id="Gradle Console" order="7" side_tool="true" />
-      <window_info anchor="bottom" id="Android Monitor" order="7" />
-      <window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
-    </layout>
-  </component>
-  <component name="Vcs.Log.UiProperties">
-    <option name="RECENTLY_FILTERED_USER_GROUPS">
-      <collection />
-    </option>
-    <option name="RECENTLY_FILTERED_BRANCH_GROUPS">
-      <collection />
-    </option>
-  </component>
-  <component name="VcsContentAnnotationSettings">
-    <option name="myLimit" value="2678400000" />
-  </component>
-  <component name="VcsManagerConfiguration">
-    <ignored-roots>
-      <path value="$PROJECT_DIR$/../.." />
-    </ignored-roots>
-  </component>
-  <component name="editorHistoryManager">
-    <entry file="file://$PROJECT_DIR$/../gradle/wrapper/gradle-wrapper.properties">
-      <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="90">
-          <caret line="6" selection-start-line="6" selection-end-line="6" />
-        </state>
-      </provider>
-    </entry>
-    <entry file="file://$PROJECT_DIR$/../gradle/wrapper/gradle-wrapper.properties">
-      <provider selected="true" editor-type-id="text-editor">
-        <state />
-      </provider>
-    </entry>
-    <entry file="file://$PROJECT_DIR$/../gradle/wrapper/gradle-wrapper.properties">
-      <provider selected="true" editor-type-id="text-editor">
-        <state />
-      </provider>
-    </entry>
-    <entry file="file://$PROJECT_DIR$/../gradle/wrapper/gradle-wrapper.properties">
-      <provider selected="true" editor-type-id="text-editor">
-        <state />
-      </provider>
-    </entry>
-    <entry file="file://$PROJECT_DIR$/../gradle/wrapper/gradle-wrapper.properties">
-      <provider selected="true" editor-type-id="text-editor">
-        <state />
-      </provider>
-    </entry>
-    <entry file="file://$PROJECT_DIR$/../gradle/wrapper/gradle-wrapper.properties">
-      <provider selected="true" editor-type-id="text-editor">
-        <state />
-      </provider>
-    </entry>
-    <entry file="file://$PROJECT_DIR$/../gradle/wrapper/gradle-wrapper.properties">
-      <provider selected="true" editor-type-id="text-editor">
-        <state />
-      </provider>
-    </entry>
-    <entry file="file://$PROJECT_DIR$/../gradle/wrapper/gradle-wrapper.properties">
-      <provider selected="true" editor-type-id="text-editor">
-        <state />
-      </provider>
-    </entry>
-    <entry file="file://$PROJECT_DIR$/../gradle/wrapper/gradle-wrapper.properties">
-      <provider selected="true" editor-type-id="text-editor">
-        <state />
-      </provider>
-    </entry>
-    <entry file="file://$PROJECT_DIR$/../gradle/wrapper/gradle-wrapper.properties">
-      <provider selected="true" editor-type-id="text-editor">
-        <state />
-      </provider>
-    </entry>
-    <entry file="file://$PROJECT_DIR$/../gradle/wrapper/gradle-wrapper.properties">
-      <provider selected="true" editor-type-id="text-editor">
-        <state />
-      </provider>
-    </entry>
-    <entry file="file://$PROJECT_DIR$/../gradle/wrapper/gradle-wrapper.properties">
-      <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="90">
-          <caret line="6" selection-start-line="6" selection-end-line="6" />
-        </state>
-      </provider>
-    </entry>
-  </component>
-</project>
\ No newline at end of file
index 038e613786c85e5134af9e2b0b9a7ec45e107820..dae6d48e2ca434c49b15061875b3931f3cc21491 100644 (file)
@@ -6,8 +6,8 @@ dependencies {
 }
 
 android {
-    compileSdkVersion 27
-    buildToolsVersion "27.0.3"
+    compileSdkVersion 28
+    buildToolsVersion "28.0.3"
     compileOptions {
         sourceCompatibility JavaVersion.VERSION_1_7
         targetCompatibility JavaVersion.VERSION_1_7
@@ -101,7 +101,7 @@ android {
         // Note that the Java class tree is still "org.jwz.xscreensaver".
         applicationId "org.jwz.android.xscreensaver"
         minSdkVersion 15
-        targetSdkVersion 27
+        targetSdkVersion 28
     }
     productFlavors {
     }
index 3524910be74d6724d0f26d12403fa436f6bc7732..cedd244d58b733c9cca58d6d0302ccce4726eb25 100644 (file)
@@ -1,6 +1,6 @@
-#Sat Feb 10 21:20:31 PST 2018
+#Mon Jan 13 18:13:30 PST 2020
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
diff --git a/android/xscreensaver/local.properties b/android/xscreensaver/local.properties
deleted file mode 100644 (file)
index d530e0d..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-## This file is automatically generated by Android Studio.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must *NOT* be checked into Version Control Systems,
-# as it contains information specific to your local configuration.
-#
-# Location of the SDK. This is only used by Gradle.
-# For customization when using a Version Control System, please read the
-# header note.
-#Mon Oct 03 16:09:56 PDT 2016
-sdk.dir=/Users/jwz/Library/Android/sdk
index 18e9fb05e704da1a7d12429d88d4b59d7347d28e..677133882b4d4d079fdefa368536138941b31c38 100644 (file)
@@ -4,6 +4,8 @@
     <facet type="android-gradle" name="Android-Gradle">
       <configuration>
         <option name="GRADLE_PROJECT_PATH" value=":xscreensaver" />
+        <option name="LAST_SUCCESSFUL_SYNC_AGP_VERSION" value="3.1.2" />
+        <option name="LAST_KNOWN_AGP_VERSION" value="3.1.2" />
       </configuration>
     </facet>
     <facet type="android" name="Android">
@@ -15,7 +17,8 @@
           <task>generateDebugSources</task>
         </afterSyncTasks>
         <option name="ALLOW_USER_CONFIGURATION" value="false" />
-        <option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/res" />
+        <option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/res;file://$MODULE_DIR$/build/generated/res/rs/debug;file://$MODULE_DIR$/build/generated/res/resValues/debug" />
+        <option name="TEST_RES_FOLDERS_RELATIVE_PATH" value="" />
       </configuration>
     </facet>
   </component>
     <exclude-output />
     <content url="file://$MODULE_DIR$">
       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/debug" isTestSource="false" generated="true" />
-      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
-      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" generated="true" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/androidTest/debug" isTestSource="true" generated="true" />
-      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
-      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" generated="true" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/test/debug" isTestSource="true" generated="true" />
       <sourceFolder url="file://$MODULE_DIR$/build-types/debug/res" type="java-resource" />
       <sourceFolder url="file://$MODULE_DIR$/build-types/debug/resources" type="java-resource" />
       <sourceFolder url="file://$MODULE_DIR$/assets" type="java-resource" />
       <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
       <sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
       <sourceFolder url="file://$MODULE_DIR$/tests/res" type="java-test-resource" />
       <sourceFolder url="file://$MODULE_DIR$/tests/resources" type="java-test-resource" />
       <sourceFolder url="file://$MODULE_DIR$/tests/assets" type="java-test-resource" />
       <sourceFolder url="file://$MODULE_DIR$/tests/java" isTestSource="true" />
       <sourceFolder url="file://$MODULE_DIR$/tests/rs" isTestSource="true" />
       <sourceFolder url="file://$MODULE_DIR$/tests/shaders" isTestSource="true" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/check-manifest" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaPrecompile" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/prebuild" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/splits-support" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
-      <excludeFolder url="file://$MODULE_DIR$/build/outputs" />
-      <excludeFolder url="file://$MODULE_DIR$/build/reports" />
-      <excludeFolder url="file://$MODULE_DIR$/build/tmp" />
+      <sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
+      <excludeFolder url="file://$MODULE_DIR$/build" />
     </content>
     <orderEntry type="jdk" jdkName="Android API 27 Platform" jdkType="Android SDK" />
     <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntry type="library" name="Gradle: com.android.support:support-v4-27.1.1" level="project" />
-    <orderEntry type="library" name="Gradle: android.arch.lifecycle:common:1.1.0@jar" level="project" />
-    <orderEntry type="library" name="Gradle: com.android.support:support-fragment-27.1.1" level="project" />
     <orderEntry type="library" name="Gradle: com.android.support:support-annotations:27.1.1@jar" level="project" />
-    <orderEntry type="library" name="Gradle: android.arch.core:runtime-1.1.0" level="project" />
-    <orderEntry type="library" name="Gradle: com.android.support:support-compat-27.1.1" level="project" />
-    <orderEntry type="library" name="Gradle: android.arch.lifecycle:viewmodel-1.1.0" level="project" />
-    <orderEntry type="library" name="Gradle: android.arch.lifecycle:livedata-core-1.1.0" level="project" />
-    <orderEntry type="library" name="Gradle: com.android.support:support-media-compat-27.1.1" level="project" />
-    <orderEntry type="library" name="Gradle: com.android.support:support-core-ui-27.1.1" level="project" />
+    <orderEntry type="library" name="Gradle: android.arch.lifecycle:common:1.1.0@jar" level="project" />
     <orderEntry type="library" name="Gradle: android.arch.core:common:1.1.0@jar" level="project" />
-    <orderEntry type="library" name="Gradle: com.android.support:support-core-utils-27.1.1" level="project" />
-    <orderEntry type="library" name="Gradle: android.arch.lifecycle:runtime-1.1.0" level="project" />
+    <orderEntry type="library" name="Gradle: com.android.support:support-v4:27.1.1@aar" level="project" />
+    <orderEntry type="library" name="Gradle: com.android.support:support-media-compat:27.1.1@aar" level="project" />
+    <orderEntry type="library" name="Gradle: com.android.support:support-fragment:27.1.1@aar" level="project" />
+    <orderEntry type="library" name="Gradle: com.android.support:support-core-ui:27.1.1@aar" level="project" />
+    <orderEntry type="library" name="Gradle: com.android.support:support-core-utils:27.1.1@aar" level="project" />
+    <orderEntry type="library" name="Gradle: com.android.support:support-compat:27.1.1@aar" level="project" />
+    <orderEntry type="library" name="Gradle: android.arch.lifecycle:runtime:1.1.0@aar" level="project" />
+    <orderEntry type="library" name="Gradle: android.arch.lifecycle:livedata-core:1.1.0@aar" level="project" />
+    <orderEntry type="library" name="Gradle: android.arch.lifecycle:viewmodel:1.1.0@aar" level="project" />
+    <orderEntry type="library" name="Gradle: android.arch.core:runtime:1.1.0@aar" level="project" />
   </component>
 </module>
\ No newline at end of file
index 4ca00b68ede57430bbcb554306a026bd9e08f19c..7baf504923284ce708e68619b8a7c00d51491a32 100644 (file)
@@ -301,7 +301,7 @@ install-program: $(EXES)
        echo $$inst xscreensaver $(install_prefix)$(bindir)/xscreensaver ;    \
        $$inst xscreensaver $(install_prefix)$(bindir)/xscreensaver
        @for exe in xscreensaver-command xscreensaver-demo                 \
-                   xscreensaver-getimage @EXES_OSX@ ; do                  \
+                   xscreensaver-getimage @EXES_OSX@ @EXES_SYSTEMD@ ; do   \
          echo $(INSTALL_PROGRAM) $$exe $(install_prefix)$(bindir)/$$exe ; \
               $(INSTALL_PROGRAM) $$exe $(install_prefix)$(bindir)/$$exe ; \
         done
@@ -633,7 +633,9 @@ clean:
 
 distclean: clean
        -rm -f Makefile XScreenSaver.ad \
-       TAGS *~ "#"* screensaver-properties.desktop
+       TAGS *~ "#"* screensaver-properties.desktop \
+       xscreensaver-demo.glade2 \
+       xscreensaver.pam
 
 # Adds all current dependencies to Makefile
 depend: XScreenSaver_ad.h XScreenSaver_Xm_ad.h
@@ -651,9 +653,10 @@ distdepend: check_men update_ad_version XScreenSaver_ad.h XScreenSaver_Xm_ad.h
        $(DEPEND) -w 0 -f -                                                 \
        -s '# DO NOT DELETE: updated by make distdepend' $(DEPEND_FLAGS) -- \
        $(INCLUDES_1) $(DEFS) $(DEPEND_DEFINES) $(CFLAGS) $(X_CFLAGS) --    \
-       $(SAVER_SRCS_1) $(MOTIF_SRCS) $(GTK_SRCS) $(GETIMG_SRCS_1)          \
-       $(PWENT_SRCS) $(LOCK_SRCS_1) $(DEMO_SRCS_1) $(CMD_SRCS)             \
-       $(SYSTEMD_SRCS) $(TEST_SRCS) 2>/dev/null |                          \
+       $(SAVER_SRCS_1) $(SYSTEMD_SRCS) $(MOTIF_SRCS) $(GTK_SRCS)           \
+       $(PWENT_SRCS) $(PWHELPER_SRCS) $(KERBEROS_SRCS) $(PAM_SRCS)         \
+       $(LOCK_SRCS_1) $(DEMO_SRCS_1) $(CMD_SRCS) $(GETIMG_SRCS_1)          \
+       $(PDF2JPEG_SRCS) $(TEST_SRCS) 2>/dev/null |                         \
        sort -d |                                                           \
        (                                                                   \
          awk '/^# .*Makefile.in ---/,/^# DO .*distdepend/' < Makefile.in ; \
@@ -866,7 +869,7 @@ test-mlstring.o: mlstring.c
 test-mlstring: test-mlstring.o
        $(CC) -DTEST $(LDFLAGS) -o $@ test-mlstring.o $(SAVER_LIBS)
 
-TEST_FADE_OBJS = test-fade.o $(UTILS_SRC)/fade.o $(DEMO_UTIL_OBJS)
+TEST_FADE_OBJS = test-fade.o $(UTILS_BIN)/fade.o $(DEMO_UTIL_OBJS)
 test-fade: test-fade.o $(UTILS_BIN)/fade.o
        $(CC) $(LDFLAGS) -o $@ $(TEST_FADE_OBJS) $(SAVER_LIBS)
 
@@ -923,11 +926,19 @@ lock.o: $(srcdir)/types.h
 lock.o: $(UTILS_SRC)/resources.h
 lock.o: $(srcdir)/xscreensaver.h
 mlstring.o: $(srcdir)/mlstring.h
+passwd-helper.o: ../config.h
+passwd-helper.o: $(srcdir)/prefs.h
+passwd-helper.o: $(srcdir)/types.h
+passwd-helper.o: $(srcdir)/xscreensaver.h
+passwd-kerberos.o: ../config.h
 passwd.o: $(srcdir)/auth.h
 passwd.o: ../config.h
 passwd.o: $(srcdir)/prefs.h
 passwd.o: $(srcdir)/types.h
 passwd.o: $(srcdir)/xscreensaver.h
+passwd-pam.o: $(srcdir)/auth.h
+passwd-pam.o: ../config.h
+passwd-pam.o: $(srcdir)/types.h
 passwd-pwent.o: ../config.h
 prefs.o: ../config.h
 prefs.o: $(srcdir)/prefs.h
index 5deb3344b06b85872164680d5b249c4216c2e7c8..cfdd1a239fd129d34049570a7dab8d59cd360c24 100644 (file)
@@ -4,8 +4,8 @@
 !            a screen saver and locker for the X window system
 !                            by Jamie Zawinski
 !
-!                              version 5.43
-!                              09-Jul-2019
+!                              version 5.44
+!                              20-Mar-2020
 !
 ! See "man xscreensaver" for more info.  The latest version is always
 ! available at https://www.jwz.org/xscreensaver/
@@ -323,7 +323,7 @@ XScreenSaver.bourneShell:           /bin/sh
 *passwd.user.label:            Username:
 
 *splash.heading.label:         XScreenSaver %s
-*splash.body.label:            Copyright \251 1991-2019 by
+*splash.body.label:            Copyright \251 1991-2020 by
 *splash.body2.label:           Jamie Zawinski <jwz@jwz.org>
 *splash.demo.label:            Settings
 *splash.help.label:            Help
@@ -445,6 +445,7 @@ XScreenSaver.bourneShell:           /bin/sh
 @GL_KLUDGE@ GL:                                menger -root                                \n\
 @GL_KLUDGE@ GL:                                molecule -root                              \n\
                                rotzoomer -root                             \n\
+                               scooter -root                               \n\
                                speedmine -root                             \n\
 @GL_KLUDGE@ GL:                                starwars -root                              \n\
 @GL_KLUDGE@ GL:                                stonerview -root                            \n\
@@ -577,7 +578,9 @@ XScreenSaver.bourneShell:           /bin/sh
 @GL_KLUDGE@ GL:                                razzledazzle -root                          \n\
                                vfeedback -root                             \n\
 @GL_KLUDGE@ GL:                                deepstars -root                             \n\
-@GL_KLUDGE@ GL:                                gravitywell -root                           \n
+@GL_KLUDGE@ GL:                                gravitywell -root                           \n\
+@GL_KLUDGE@ GL:                                etruscanvenus -root                         \n\
+@GL_KLUDGE@ GL:                                gibson -root                                \n
 
 
 
@@ -613,6 +616,7 @@ XScreenSaver.bourneShell:           /bin/sh
 *hacks.dnalogo.name:        DNA Logo
 *hacks.dymaxionmap.name:    DymaxionMap
 *hacks.energystream.name:   EnergyStream
+*hacks.etruscanvenus.name:  EtruscanVenus
 *hacks.euler2d.name:        Euler2D
 *hacks.fadeplot.name:       FadePlot
 *hacks.filmleader.name:     FilmLeader
index 2b2dab8589fe6e11e7bb75eb1fa0e15e62d36d0f..d9fc3042d38e5e6e346136ee3ab4bb68c72071e9 100644 (file)
@@ -87,7 +87,7 @@
 "*passwd.login.label:          New Login",
 "*passwd.user.label:           Username:",
 "*splash.heading.label:                XScreenSaver %s",
-"*splash.body.label:           Copyright \\251 1991-2019 by",
+"*splash.body.label:           Copyright \\251 1991-2020 by",
 "*splash.body2.label:          Jamie Zawinski <jwz@jwz.org>",
 "*splash.demo.label:           Settings",
 "*splash.help.label:           Help",
   GL:                          menger -root                                \\n\
   GL:                          molecule -root                              \\n\
                                rotzoomer -root                             \\n\
+                               scooter -root                               \\n\
                                speedmine -root                             \\n\
   GL:                          starwars -root                              \\n\
   GL:                          stonerview -root                            \\n\
   GL:                          razzledazzle -root                          \\n\
                                vfeedback -root                             \\n\
   GL:                          deepstars -root                             \\n\
-  GL:                          gravitywell -root                           \\n",
+  GL:                          gravitywell -root                           \\n\
+  GL:                          etruscanvenus -root                         \\n\
+  GL:                          gibson -root                                \\n",
 "*hacks.antinspect.name:     AntInspect",
 "*hacks.antmaze.name:        AntMaze",
 "*hacks.antspotlight.name:   AntSpotlight",
 "*hacks.dnalogo.name:        DNA Logo",
 "*hacks.dymaxionmap.name:    DymaxionMap",
 "*hacks.energystream.name:   EnergyStream",
+"*hacks.etruscanvenus.name:  EtruscanVenus",
 "*hacks.euler2d.name:        Euler2D",
 "*hacks.fadeplot.name:       FadePlot",
 "*hacks.filmleader.name:     FilmLeader",
index be4a2387ef4b5208e5a54c9a53b74f124c08a74b..da98c535e8839efd5b6cdb82fa6eecdf52b6937e 100644 (file)
@@ -1,5 +1,5 @@
 /* demo-Gtk.c --- implements the interactive demo-mode and options dialogs.
- * xscreensaver, Copyright (c) 1993-2019 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1993-2020 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
@@ -550,7 +550,10 @@ warning_dialog (GtkWidget *parent, const char *message,
   if (!parent ||
       !GET_WINDOW (parent)) /* too early to pop up transient dialogs */
     {
-      fprintf (stderr, "%s: too early for dialog?\n", progname);
+      fprintf (stderr,
+               "%s: too early for warning dialog?"
+               "\n\n\t%s\n\n",
+               progname, message);
       free(msg);
       return False;
     }
@@ -1043,7 +1046,9 @@ await_xscreensaver (state *s)
         strcat (buf, STFU
          _("You are running as root.  This usually means that xscreensaver\n"
             "was unable to contact your X server because access control is\n"
-            "turned on.  Try running this command:\n"
+            "turned on."
+/*
+            "  Try running this command:\n"
             "\n"
             "                        xhost +localhost\n"
             "\n"
@@ -1053,9 +1058,10 @@ await_xscreensaver (state *s)
             "on to this machine to access your screen, which might be\n"
             "considered a security problem.  Please read the xscreensaver\n"
             "manual and FAQ for more information.\n"
+ */
             "\n"
             "You shouldn't run X as root. Instead, you should log in as a\n"
-            "normal user, and `su' as necessary."));
+            "normal user, and `sudo' as necessary."));
       else
         strcat (buf, _("Please check your $PATH and permissions."));
 
@@ -4422,7 +4428,8 @@ kde_screensaver_active_p (void)
   FILE *p = popen ("dcop kdesktop KScreensaverIface isEnabled 2>/dev/null",
                    "r");
   char buf[255];
-  fgets (buf, sizeof(buf)-1, p);
+  if (!p) return False;
+  if (!fgets (buf, sizeof(buf)-1, p)) return False;
   pclose (p);
   if (!strcmp (buf, "true\n"))
     return True;
@@ -4433,7 +4440,11 @@ kde_screensaver_active_p (void)
 static void
 kill_kde_screensaver (void)
 {
-  system ("dcop kdesktop KScreensaverIface enable false");
+  /* Use empty body to kill warning from gcc -Wall with
+     "warning: ignoring return value of 'system',
+      declared with attribute warn_unused_result"
+  */
+  if (system ("dcop kdesktop KScreensaverIface enable false")) {}
 }
 
 
index 7696f3015358bf9c9446c46c65195213a82f691c..d36481e1e777e1fb029cf495e69a08b665a886cc 100644 (file)
@@ -1400,6 +1400,8 @@ destroy_passwd_window (saver_info *si)
   memset (pw, 0, sizeof(*pw));
   free (pw);
   si->pw_data = 0;
+
+  si->unlock_dismiss_time = time((time_t *) 0);
 }
 
 
@@ -2216,6 +2218,7 @@ Bool
 unlock_p (saver_info *si)
 {
   saver_preferences *p = &si->prefs;
+  time_t now = time ((time_t *) 0);
 
   if (!si->unlock_cb)
     {
@@ -2225,6 +2228,18 @@ unlock_p (saver_info *si)
 
   raise_window (si, True, True, True);
 
+  /* If your cat is sitting on the return key, don't thrash the window.
+     Only one failed/cancelled unlock per 2 seconds.
+   */
+  if (si->unlock_dismiss_time >= now - 1)
+    {
+      if (p->verbose_p)
+        fprintf (stderr, "%s: unlock: thrashing: RET held down?\n", blurb());
+      XSync (si->dpy, False);
+#     undef sleep
+      sleep (2);    /* This is less than ideal, but fine */
+    }
+
   xss_authenticate(si, p->verbose_p);
 
   return (si->unlock_state == ul_success);
index f4437268d8771b89b5385f44f445db885de14c6b..68e1a0b7c17144a4b4fb56fed2d923f4be081722 100644 (file)
@@ -1,5 +1,5 @@
 /* passwd.c --- verifying typed passwords with the OS.
- * xscreensaver, Copyright (c) 1993-2018 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1993-2019 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -251,7 +251,7 @@ do_syslog (saver_info *si, Bool verbose_p)
 {
 # ifdef HAVE_SYSLOG
   struct passwd *pw = getpwuid (getuid ());
-  char *d = DisplayString (si->dpy);
+  char *d = (si->dpy ? DisplayString (si->dpy) : 0);
   char *u = (pw && pw->pw_name ? pw->pw_name : "???");
   int opt = 0;
   int fac = 0;
@@ -324,8 +324,9 @@ xss_authenticate(saver_info *si, Bool verbose_p)
           si->cached_passwd &&
           !*si->cached_passwd)
         {
-          fprintf (stderr, "%s: assuming null password means cancel.\n",
-                   blurb());
+          if (verbose_p)
+            fprintf (stderr, "%s: assuming null password means cancel.\n",
+                     blurb());
           si->unlock_state = ul_cancel;
         }
 
@@ -354,11 +355,11 @@ xss_authenticate(saver_info *si, Bool verbose_p)
         {
           /* If any auth method gets a cancel or timeout, don't try the
              next auth method!  We're done! */
-          fprintf (stderr,
-                   "%s: authentication via %s %s.\n",
-                       blurb(), methods[i].name,
-                   (si->unlock_state == ul_cancel
-                    ? "cancelled" : "timed out"));
+          if (verbose_p)
+            fprintf (stderr, "%s: authentication via %s %s.\n",
+                     blurb(), methods[i].name,
+                     (si->unlock_state == ul_cancel
+                      ? "cancelled" : "timed out"));
           goto DONE;
         }
     }
index 8fb029eed4bdfa954546ec49158adde45d78720a..94e7a0ceadf98f4c903424582020dd2300e68ba5 100644 (file)
@@ -1,5 +1,5 @@
 /* dotfile.c --- management of the ~/.xscreensaver file.
- * xscreensaver, Copyright (c) 1998-2018 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1998-2020 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
@@ -136,33 +136,34 @@ init_file_name (void)
   if (!file)
     {
       uid_t uid = getuid ();
-      struct passwd *p = getpwuid (uid);
+      const char *home = getenv("HOME");
 
-      if (i_am_a_nobody (uid))
-        /* If we're running as nobody, then use root's .xscreensaver file
-           (since ~root/.xscreensaver and ~nobody/.xscreensaver are likely
-           to be different -- if we didn't do this, then xscreensaver-demo
-           would appear to have no effect when the luser is running as root.)
-         */
-        uid = 0;
-
-      p = getpwuid (uid);
-
-      if (!p || !p->pw_name || !*p->pw_name)
-       {
-         fprintf (stderr, "%s: couldn't get user info of uid %d\n",
-                  blurb(), getuid ());
-         file = "";
-       }
-      else if (!p->pw_dir || !*p->pw_dir)
+      if (i_am_a_nobody (uid) || !home || !*home)
        {
-         fprintf (stderr, "%s: couldn't get home directory of \"%s\"\n",
-                  blurb(), (p->pw_name ? p->pw_name : "???"));
-         file = "";
+         /* If we're running as nobody, then use root's .xscreensaver file
+            (since ~root/.xscreensaver and ~nobody/.xscreensaver are likely
+            to be different -- if we didn't do this, then xscreensaver-demo
+            would appear to have no effect when the luser is running as root.)
+          */
+          struct passwd *p = getpwuid (uid);
+         uid = 0;
+         if (!p || !p->pw_name || !*p->pw_name)
+           {
+             fprintf (stderr, "%s: couldn't get user info of uid %d\n",
+                      blurb(), getuid ());
+           }
+         else if (!p->pw_dir || !*p->pw_dir)
+           {
+             fprintf (stderr, "%s: couldn't get home directory of \"%s\"\n",
+                      blurb(), (p->pw_name ? p->pw_name : "???"));
+           }
+         else
+           {
+             home = p->pw_dir;
+           }
        }
-      else
+      if (home && *home)
        {
-         const char *home = p->pw_dir;
          const char *name = ".xscreensaver";
          file = (char *) malloc(strlen(home) + strlen(name) + 2);
          strcpy(file, home);
@@ -170,6 +171,10 @@ init_file_name (void)
            strcat(file, "/");
          strcat(file, name);
        }
+      else
+       {
+         file = "";
+       }
     }
 
   if (file && *file)
@@ -1653,7 +1658,7 @@ stop_the_insanity (saver_preferences *p)
   if (p->watchdog_timeout > 57000) p->watchdog_timeout = 57000;   /* 57 secs */
 
   if (p->pointer_hysteresis < 0)   p->pointer_hysteresis = 0;
-  if (p->pointer_hysteresis > 100) p->pointer_hysteresis = 100;
+/* if (p->pointer_hysteresis > 100) p->pointer_hysteresis = 100; */
 
   if (p->auth_warning_slack < 0)   p->auth_warning_slack = 0;
   if (p->auth_warning_slack > 300) p->auth_warning_slack = 300;
index d500f70eda56cf5885ff7704843cc153b1890a83..e25184200d9f1d7a0112814d2bcf80208664c13d 100644 (file)
@@ -264,8 +264,8 @@ make_job (pid_t pid, int screen, const char *cmd)
   clean_job_list();
 
  AGAIN:
-  while (isspace(*in)) in++;           /* skip whitespace */
-  while (!isspace(*in) && *in != ':') {
+  while (*in && isspace(*in)) in++;            /* skip whitespace */
+  while (*in && !isspace(*in) && *in != ':') {
     if (*in == '=') got_eq = 1;
     *out++ = *in++;                    /* snarf first token */
   }
@@ -277,7 +277,7 @@ make_job (pid_t pid, int screen, const char *cmd)
       goto AGAIN;
     }
 
-  while (isspace(*in)) in++;           /* skip whitespace */
+  while (*in && isspace(*in)) in++;            /* skip whitespace */
   *out = 0;
 
   job->name = strdup(name);
index ea97f34629cc5b793fd689e953dcbfeac1576fbd..5aa568c17087ec87be4d4f508e0cb800e9ea4e79 100644 (file)
@@ -1,5 +1,5 @@
 /* timers.c --- detecting when the user is idle, and other timer-related tasks.
- * xscreensaver, Copyright (c) 1991-2017 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1991-2019 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -311,6 +311,12 @@ activate_lock_timer (XtPointer closure, XtIntervalId *id)
 
   if (p->verbose_p)
     fprintf (stderr, "%s: timed out; activating lock.\n", blurb());
+
+  if (!si->locked_p)
+    /* So that "xscreensaver-command -watch" reports the time that the
+       screen was locked, instead of duplicating the blank time. */
+    si->blank_time = time ((time_t *) 0);
+
   set_locked_p (si, True);
 }
 
index 35992ae95f3160fd7af98eea067d56177c39477e..ebea9e031a8765e4ed50fa402730a5bb81f84949 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1993-2019 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1993-2020 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
@@ -275,6 +275,7 @@ struct saver_info {
   int unlock_failures;         /* Counts failed login attempts while the
                                   screen is locked. */
   time_t unlock_failure_time;  /* Time of first failed login attempt. */
+  time_t unlock_dismiss_time;  /* Time lock dialog most recently dismissed. */
 
   char *unlock_typeahead;      /* If the screen is locked, and the user types
                                    a character, we assume that it is the first
index b7bea5284e5eb2dc49f308e79a80ed9e3e443182..9e47c4521ff2153f70d47aa363671578fb33ec78 100644 (file)
@@ -1,5 +1,5 @@
 /* windows.c --- turning the screen black; dealing with visuals, virtual roots.
- * xscreensaver, Copyright (c) 1991-2019 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1991-2020 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
@@ -1463,6 +1463,7 @@ resize_screensaver_window (saver_info *si)
           if (ssi->cmap)
             XInstallColormap (si->dpy, ssi->cmap);
           XMapRaised (si->dpy, ssi->screensaver_window);
+          XSync (si->dpy, False);
           if (! ssi->pid)
             spawn_screenhack (ssi);
 
@@ -1586,6 +1587,7 @@ raise_window (saver_info *si,
          if (!dont_clear || ssi->stderr_overlay_window)
            clear_stderr (ssi);
          XMapRaised (si->dpy, ssi->screensaver_window);
+          XSync (si->dpy, False);
 #ifdef HAVE_MIT_SAVER_EXTENSION
          if (ssi->server_mit_saver_window &&
              window_exists_p (si->dpy, ssi->server_mit_saver_window))
@@ -1792,15 +1794,18 @@ unblank_screen (saver_info *si)
   {
     Window focus = 0;
     int revert_to;
+    XSync (si->dpy, False);
     XGetInputFocus (si->dpy, &focus, &revert_to);
     if (focus && focus != PointerRoot && focus != None)
       {
+       XErrorHandler old_handler = XSetErrorHandler (BadWindow_ehandler);
        XWindowAttributes xgwa;
        xgwa.colormap = 0;
-       XGetWindowAttributes (si->dpy, focus, &xgwa);
-       if (xgwa.colormap &&
+       if (XGetWindowAttributes (si->dpy, focus, &xgwa) &&
+           xgwa.colormap &&
            xgwa.colormap != DefaultColormapOfScreen (xgwa.screen))
          XInstallColormap (si->dpy, xgwa.colormap);
+       XSetErrorHandler (old_handler);
       }
   }
 
index ba1ef308ab9d56e3e90d42293123e624a19fc13e..3a5c7f4e05196ada2253ed44e78a3606ac48168b 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/perl -w
-# Copyright © 2001-2018 Jamie Zawinski <jwz@jwz.org>.
+# Copyright © 2001-2020 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
@@ -53,7 +53,7 @@ BEGIN { eval 'use LWP::Simple;' }
 
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my ($version) = ('$Revision: 1.52 $' =~ m/\s(\d[.\d]+)\s/s);
+my ($version) = ('$Revision: 1.53 $' =~ m/\s(\d[.\d]+)\s/s);
 
 my $verbose = 0;
 
@@ -1256,6 +1256,7 @@ sub main() {
     elsif (m/^--?no-spotlight$/s) { $use_spotlight_p = 0; }
     elsif (m/^--?cache$/s)        { $cache_p = 1; }
     elsif (m/^--?no-?cache$/s)    { $cache_p = 0; }
+    elsif (m/^--?flush-?cache$/s) { $feed_max_age = $cache_max_age = 0; }
     elsif (m/^--?cocoa$/)         { $cocoa_id = shift @ARGV; }
     elsif (m/^--?abs(olute)?$/)   { $abs_p = 1; }
     elsif (m/^-./)                { usage; }
index e965bedef3a4b5ea04bb95069d3ee1924a09438c..eca1fbf7537c56d498110539518a3691a15591d9 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/perl -w
-# Copyright © 2005-2017 Jamie Zawinski <jwz@jwz.org>
+# Copyright © 2005-2019 Jamie Zawinski <jwz@jwz.org>
 #
 # Permission to use, copy, modify, distribute, and sell this software and its
 # documentation for any purpose is hereby granted without fee, provided that
@@ -37,7 +37,7 @@ use Text::Wrap qw(wrap);
 #use bytes;  # This breaks shit.
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my ($version) = ('$Revision: 1.46 $' =~ m/\s(\d[.\d]+)\s/s);
+my ($version) = ('$Revision: 1.48 $' =~ m/\s(\d[.\d]+)\s/s);
 
 my $verbose = 0;
 my $http_proxy = undef;
@@ -344,6 +344,11 @@ sub output() {
         last if ($truncate_lines && $lines > $truncate_lines);
       }
       close $pipe;
+
+      # I don't understand why we must do this here, but must not do this
+      # in the 'file' branch above, which reads the file with :raw...
+      utf8::decode ($body);  # Pack multi-byte UTF-8 back into wide chars.
+
       $body = reformat_text ($body);
       print STDOUT $body;
     } else {
@@ -573,9 +578,10 @@ sub reformat_rss($) {
   foreach (@items) {
     $i++;
 
-    my ($title, $body1, $body2, $body3);
+    my ($title, $author, $body1, $body2, $body3);
     
     $title = $3 if (m@<((TITLE)       [^<>\s]*)[^<>]*>\s*(.*?)\s*</\1>@xsi);
+    $author= $3 if (m@<((DC:CREATOR)  [^<>\s]*)[^<>]*>\s*(.*?)\s*</\1>@xsi);
     $body1 = $3 if (m@<((DESCRIPTION) [^<>\s]*)[^<>]*>\s*(.*?)\s*</\1>@xsi);
     $body2 = $3 if (m@<((CONTENT)     [^<>\s]*)[^<>]*>\s*(.*?)\s*</\1>@xsi);
     $body3 = $3 if (m@<((SUMMARY)     [^<>\s]*)[^<>]*>\s*(.*?)\s*</\1>@xsi);
@@ -602,10 +608,19 @@ sub reformat_rss($) {
     }
 
     $title = rss_field_to_html ($title || '');
+    $author= rss_field_to_html ($author || '');
     $body1 = rss_field_to_html ($body1 || '');
 
     $title = '' if ($body1 eq $title);  # Identical in Twitter's atom feed.
 
+    # Omit author if it's in the title or body
+    $author = '' if ($author &&
+                     ($title =~ m/\Q$author\E/si ||
+                      $body1 =~ m/\Q$author\E/si));
+
+    $title = $author if ($author && !$title);
+    $title = "$author: $title" if ($author && $title);
+
     $out .= reformat_html ("$title<P>$body1", $wiki_p ? 'wiki' : 'rss');
     $out .= "\n";
   }
index 2add3b8713c6b9ce5126e145e9ac77f99eb09acd..40f8207f95394788931dfc11457e8bfff52f7037 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1991-2019 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1991-2020 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
@@ -443,6 +443,11 @@ saver_ehandler (Display *dpy, XErrorEvent *error)
 }
 
 
+#ifdef __GNUC__  /* Silence warning */
+static void startup_ehandler (String, String, String, String, String *,
+                              Cardinal *) __attribute__((noreturn));
+#endif /* __GNUC__ */
+
 /* This error handler is used only while the X connection is being set up;
    after we've got a connection, we don't use this handler again.  The only
    reason for having this is so that we can present a more idiot-proof error
@@ -1561,6 +1566,7 @@ main (int argc, char **argv)
       if (ssi->real_screen_p)
         if (ensure_no_screensaver_running (si->dpy, si->screens[i].screen))
           exit (1);
+      ssi->current_hack = -1;
     }
 
   lock_initialization (si, &argc, argv);
@@ -1590,6 +1596,8 @@ main (int argc, char **argv)
   initialize_stderr (si);
   handle_signals (si);
 
+  store_saver_status (si);     /* for xscreensaver-command -status */
+
 # ifdef HAVE_LIBSYSTEMD   /* Launch it in the background */
   si->systemd_pid = fork_and_exec_1 (si, 0, "xscreensaver-systemd");
 # endif
@@ -1904,13 +1912,13 @@ handle_clientmessage (saver_info *si, XEvent *event, Bool until_idle_p)
                              "suspending.");
       si->selection_mode = 0;
       si->demoing_p = False;
-      si->emergency_lock_p = True;
       si->throttled_p = True;
 
       /* When suspending, immediately lock, if locking enabled. */
 # ifndef NO_LOCKING
       if (p->lock_p && !si->locked_p && !si->locking_disabled_p)
         {
+          si->emergency_lock_p = True;
           if (p->verbose_p)
             fprintf (stderr, "%s: locking.\n", blurb());
           set_locked_p (si, True);
index 63e69be24935ed607e9969a210bf4cfaf50b50f7..7acaeb3331a6758d9b11b3253365105e670442a1 100644 (file)
@@ -122,7 +122,7 @@ SRCS                = attraction.c blitspin.c bouboule.c braid.c bubbles.c \
                  boxfit.c interaggregate.c celtic.c cwaves.c m6502.c \
                  asm6502.c abstractile.c lcdscrub.c hexadrop.c \
                  tessellimage.c delaunay.c recanim.c binaryring.c \
-                 glitchpeg.c vfeedback.c webcollage-cocoa.m \
+                 glitchpeg.c vfeedback.c scooter.c webcollage-cocoa.m \
                  webcollage-helper-cocoa.m testx11.c
 SCRIPTS                = vidwhacker webcollage ljlatest
 
@@ -164,7 +164,7 @@ OBJS                = attraction.o blitspin.o bouboule.o braid.o bubbles.o \
                  webcollage-cocoa.o webcollage-helper-cocoa.o m6502.o \
                  asm6502.o abstractile.o lcdscrub.o hexadrop.o \
                  tessellimage.o delaunay.o recanim.o binaryring.o \
-                 glitchpeg.o vfeedback.o testx11.o
+                 glitchpeg.o vfeedback.o scooter.o testx11.o
 
 EXES           = attraction blitspin bouboule braid decayscreen deco \
                  drift flame galaxy grav greynetic halo \
@@ -186,7 +186,7 @@ EXES                = attraction blitspin bouboule braid decayscreen deco \
                  pacman fuzzyflakes anemotaxis memscroller substrate \
                  intermomentary fireworkx fiberlamp boxfit interaggregate \
                  celtic cwaves m6502 abstractile lcdscrub hexadrop \
-                 tessellimage binaryring glitchpeg vfeedback \
+                 tessellimage binaryring glitchpeg vfeedback scooter \
                  @JPEG_EXES@
 JPEG_EXES      = webcollage-helper
 
@@ -245,7 +245,7 @@ MEN         = anemone.man apollonian.man attraction.man \
                  intermomentary.man fireworkx.man fiberlamp.man boxfit.man \
                  interaggregate.man celtic.man cwaves.man abstractile.man \
                  lcdscrub.man hexadrop.man tessellimage.man binaryring.man \
-                 glitchpeg.man vfeedback.man
+                 glitchpeg.man vfeedback.man scooter.man
 
 RETIRED_MEN    = ant.man bubbles.man critical.man flag.man forest.man \
                  laser.man lightning.man lisa.man lissie.man lmorph.man \
@@ -291,7 +291,10 @@ install-program:: $(EXES)
        done
 
 install-scripts: $(SCRIPTS) munge-scripts
-       @for program in $(SCRIPTS); do                                  \
+       @if [ ! -d $(install_prefix)$(HACKDIR) ]; then                  \
+         $(INSTALL_DIRS) $(install_prefix)$(HACKDIR) ;                 \
+        fi ;                                                           \
+       for program in $(SCRIPTS); do                                   \
          if [ -r $$program ] ; then                                    \
            p=$$program ;                                               \
          else                                                          \
@@ -814,8 +817,8 @@ halftone:   halftone.o      $(HACK_OBJS) $(COL)
 metaballs:     metaballs.o     $(HACK_OBJS)
        $(CC_HACK) -o $@ $@.o   $(HACK_OBJS) $(HACK_LIBS)
 
-eruption:      eruption.o      $(HACK_OBJS)
-       $(CC_HACK) -o $@ $@.o   $(HACK_OBJS) $(HACK_LIBS)
+eruption:      eruption.o      $(HACK_OBJS) $(SHM)
+       $(CC_HACK) -o $@ $@.o   $(HACK_OBJS) $(SHM) $(HACK_LIBS) $(THRL)
 
 popsquares:    popsquares.o    $(HACK_OBJS) $(DBE) $(COL)
        $(CC_HACK) -o $@ $@.o   $(HACK_OBJS) $(DBE) $(COL) $(HACK_LIBS)
@@ -1030,6 +1033,9 @@ pacman:           pacman.o        $(PACOBJS) $(XLOCK_OBJS) $(PNG)
 fiberlamp:     fiberlamp.o     $(XLOCK_OBJS)
        $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(HACK_LIBS)
 
+scooter:       scooter.o       $(XLOCK_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(XLOCK_OBJS) $(HACK_LIBS)
+
 # These are not like the others.
 #
 xsublim:       xsublim.o       $(HACK_OBJS_1)
@@ -1655,6 +1661,7 @@ eruption.o: $(UTILS_SRC)/hsv.h
 eruption.o: $(UTILS_SRC)/resources.h
 eruption.o: $(UTILS_SRC)/usleep.h
 eruption.o: $(UTILS_SRC)/visual.h
+eruption.o: $(UTILS_SRC)/xshm.h
 eruption.o: $(UTILS_SRC)/yarandom.h
 euler2d.o: ../config.h
 euler2d.o: $(srcdir)/fps.h
@@ -2711,6 +2718,21 @@ rotzoomer.o: $(UTILS_SRC)/usleep.h
 rotzoomer.o: $(UTILS_SRC)/visual.h
 rotzoomer.o: $(UTILS_SRC)/xshm.h
 rotzoomer.o: $(UTILS_SRC)/yarandom.h
+scooter.o: ../config.h
+scooter.o: $(srcdir)/fps.h
+scooter.o: $(srcdir)/recanim.h
+scooter.o: $(srcdir)/screenhackI.h
+scooter.o: $(UTILS_SRC)/colors.h
+scooter.o: $(UTILS_SRC)/erase.h
+scooter.o: $(UTILS_SRC)/font-retry.h
+scooter.o: $(UTILS_SRC)/grabscreen.h
+scooter.o: $(UTILS_SRC)/hsv.h
+scooter.o: $(UTILS_SRC)/resources.h
+scooter.o: $(UTILS_SRC)/usleep.h
+scooter.o: $(UTILS_SRC)/visual.h
+scooter.o: $(UTILS_SRC)/yarandom.h
+scooter.o: $(srcdir)/xlockmoreI.h
+scooter.o: $(srcdir)/xlockmore.h
 screenhack.o: ../config.h
 screenhack.o: $(srcdir)/fps.h
 screenhack.o: $(srcdir)/recanim.h
index d70db1b6ec1babe6ad982045bd21833f874b03c9..aeec901250c1b5841baa549b47ed24e601bcc10b 100644 (file)
@@ -1,4 +1,4 @@
-/* xanalogtv-cli, Copyright (c) 2018 Jamie Zawinski <jwz@jwz.org>
+/* xanalogtv-cli, Copyright (c) 2018-2019 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -15,7 +15,7 @@
  *    --duration     Length in seconds of MP4.
  *    --powerup      Do the power-on animation at the beginning.
  *    --logo FILE    Small image overlayed onto the colorbars image.
- *    --audio FILE   Add a soundtrack. Must be as long or longer.
+ *    --audio FILE   Add a soundtrack.
  *
  *  Created: 10-Dec-2018 by jwz.
  */
@@ -573,7 +573,8 @@ analogtv_write_mp4 (struct state *st, const char *outfile,
              " -map 0:v:0"
              " -map 1:a:0"
              " -acodec aac"
-             " -shortest",
+             /* Truncate or pad audio to length of video */
+             " -filter_complex '[1:0] apad' -shortest",
              audiofile);
   sprintf (cmd + strlen(cmd),
            " -c:v libx264"
@@ -642,10 +643,11 @@ analogtv_convert (const char *infile, const char *outfile,
   unsigned long curticks = 0;
   time_t lastlog = time((time_t *)0);
   int frames_left;
+  int channel_changes = 0;
   int fps = 30;
 
   if (verbose_p)
-    fprintf (stderr, "%s: progname: loaded %s %dx%d\n", 
+    fprintf (stderr, "%s: loaded %s %dx%d\n", 
              progname, infile, ximage->width, ximage->height);
 
   flip_ximage (ximage);
@@ -663,12 +665,30 @@ analogtv_convert (const char *infile, const char *outfile,
     calloc (st->output_frame->height, st->output_frame->bytes_per_line);
 
   {
-    char *s1, *s2;
-    st->framefile_fmt = malloc (strlen(outfile) + 100);
+    char *s0, *slash, *dot;
+    st->framefile_fmt = calloc (1, strlen(outfile) + 100);
+
+    s0 = st->framefile_fmt;
     strcpy (st->framefile_fmt, outfile);
-    s1 = strrchr (st->framefile_fmt, '/');
-    s2 = strrchr (st->framefile_fmt, '.');
-    if (s2 && s2 > s1) *s2 = 0;
+
+    slash = strrchr (st->framefile_fmt, '/');
+    dot = strrchr (st->framefile_fmt, '.');
+    if (dot && dot > slash) *dot = 0;
+
+    /* Make tmp files be dotfiles */
+    if (slash) {
+      memmove (slash+1, slash, strlen(slash)+1);
+      slash[1] = '.';
+    } else {
+      memmove (s0+1, s0, strlen(s0)+1);
+      s0[0] = '.';
+    }
+
+    /* Can't have percents in the tmp file names */
+    for (s0 = (slash ? slash : s0); *s0; s0++) {
+      if (*s0 == '%') *s0 = '_';
+    }
+
     sprintf (st->framefile_fmt + strlen(st->framefile_fmt),
              ".%08x.%%06d.png", (random() % 0xFFFFFFFF));
   }
@@ -677,7 +697,7 @@ analogtv_convert (const char *infile, const char *outfile,
     int x, y;
     st->logo = file_to_ximage (0, 0, logofile);
     if (verbose_p)
-      fprintf (stderr, "%s: progname: loaded %s %dx%d\n", 
+      fprintf (stderr, "%s: loaded %s %dx%d\n", 
                progname, logofile, st->logo->width, st->logo->height);
     flip_ximage (st->logo);
     /* Pull the alpha out of the logo and make a separate mask ximage. */
@@ -799,6 +819,8 @@ analogtv_convert (const char *infile, const char *outfile,
 
   st->curinputi=0;
   st->cs = &st->chansettings[st->curinputi];
+
+  /* First channel (initial unadulterated image) stays for this long */
   frames_left = fps * (2 + frand(1.5));
 
   st->tv->powerup=0.0;
@@ -832,17 +854,35 @@ analogtv_convert (const char *infile, const char *outfile,
 
     frames_left--;
     if (frames_left <= 0) {
-      frames_left = fps * (0.5 + frand(2.5));
 
-      if (st->curinputi != 0 && !(random() % 3)) {
-        st->curinputi = 0;  /* unadulterated image */
+      channel_changes++;
+
+      if (channel_changes == 1) {
+        /* Second channel has short duration */
+        frames_left = fps * (0.25 + frand(0.5));
       } else {
+        frames_left = fps * (0.5 + frand(2.5));
+      }
+
+      if (channel_changes == 2) {
+        /* Always use the unadulterated image for the third channel:
+           So the effect is, plain, brief blip, plain, then random. */
+        st->curinputi = 0;
+      } else if (st->curinputi != 0 && !(random() % 3)) {
+        /* Use the unadulterated image 1/3 of the time */
+        st->curinputi = 0;
+      } else {
+        /* Otherwise random */
         st->curinputi = 1 + (random() % (N_CHANNELS - 1));
       }
 
       st->cs = &st->chansettings[st->curinputi];
       /* Set channel change noise flag */
       st->tv->channel_change_cycles=200000;
+
+      if (verbose_p)
+        fprintf (stderr, "%s: %.1f: channel %d\n",
+                 progname, curticks/1000.0, st->curinputi);
     }
 
     for (i=0; i<MAX_MULTICHAN; i++) {
index 2ce609e64d961a2ff78db83c5dd5ce27cbfe99b6..1f56013e9fd6a2fe236a75cd8e869b6ac0fb4c28 100644 (file)
@@ -101,14 +101,17 @@ static const char *words[] =
   "abstraction",
   "acid",
   "addiction",
+  "affluenza",
   "alertness",
   "Algeria",
+  "antifa",
   "anxiety",
   "aorta",
   "argyle socks",
   "attrition",
   "axis of evil",
   "bamboo",
+  "banana slug",
   "bangle",
   "bankruptcy",
   "baptism",
@@ -122,6 +125,7 @@ static const char *words[] =
   "boobs",
   "booty",
   "bread",
+  "brogrammers",
   "bubba",
   "burrito",
   "California",
@@ -131,8 +135,10 @@ static const char *words[] =
   "carnage",
   "children",
   "chocolate",
+  "chupacabra",
   "CLONE",
   "cock",
+  "congress",
   "constriction",
   "contrition",
   "cop",
@@ -153,10 +159,10 @@ static const char *words[] =
   "despair",
   "desperation",
   "disease",
-  "disease",
+  "DNA Lounge",
   "doberman",
   "DOOM",
-  "dreams",
+  "dot com",
   "dreams",
   "drugs",
   "easy",
@@ -175,9 +181,10 @@ static const char *words[] =
   "flatulence",
   "fluff",
   "fnord",
+  "followers",
+  "frak",
   "freedom",
   "fruit",
-  "fruit",
   "futility",
   "gerbils",
   "GOD",
@@ -198,8 +205,12 @@ static const char *words[] =
   "icepick",
   "identity",
   "ignorance",
+  "illuminati",
   "importance",
   "individuality",
+  "influence",
+  "influencers",
+  "influenza",
   "inkling",
   "insurrection",
   "intoxicant",
@@ -215,6 +226,7 @@ static const char *words[] =
   "lattice",
   "lawyer",
   "lemming",
+  "likes",
   "liquidation",
   "lobbyist",
   "love",
@@ -224,9 +236,11 @@ static const char *words[] =
   "malfunction",
   "marmot",
   "marshmallow",
+  "measles",
   "merit",
   "merkin",
   "mescaline",
+  "methane",
   "milk",
   "mischief",
   "mistrust",
@@ -281,6 +295,7 @@ static const char *words[] =
   "respect",
   "revolution",
   "roadrunner",
+  "rootkit",
   "rule",
   "savor",
   "scab",
@@ -290,6 +305,7 @@ static const char *words[] =
   "security",
   "sediment",
   "self worth",
+  "shadow profile",
   "sickness",
   "silicone",
   "slack",
@@ -316,17 +332,21 @@ static const char *words[] =
   "terrorism",
   "terrorist",
   "the impossible",
+  "the panopticon",
   "the unknown",
   "toast",
   "topography",
   "truism",
+  "truthiness",
   "turgid",
+  "twits",
   "underbrush",
   "underling",
   "unguent",
   "unusual",
   "uplink",
   "urge",
+  "vaccines",
   "valor",
   "variance",
   "vaudeville",
@@ -334,6 +354,7 @@ static const char *words[] =
   "vegetarian",
   "venom",
   "verifiability",
+  "very fine people",
   "viagra",
   "vibrator",
   "victim",
@@ -351,7 +372,6 @@ static const char *words[] =
   "words",
   "worm",
   "worship",
-  "worship",
   "Xanax",
   "Xerxes",
   "Xhosa",
index 040db542ba2d1a6f5539e8cc650d6561485fccff..ffde1a651fe3685a72fee0465628d987ca67093e 100644 (file)
@@ -1554,7 +1554,7 @@ windows_ransomware (Display *dpy, Window window)
   const time_t stage1_deadline = now + 259200 - advance_deadline; /* 3 days */
   const time_t stage2_deadline = now + 604800 - advance_deadline; /* 7 days */
   char stage1_deadline_str[25], stage2_deadline_str[25];
-  char countdown_str[16];
+  char countdown_str[20];
   int countdown_d, countdown_h, countdown_m, countdown_s, countdown_r;
   int line_height  = bst->font->ascent + bst->font->descent;
   int line_height1 = bst->fontA->ascent + bst->fontA->descent;
@@ -2528,7 +2528,7 @@ macsbug (Display *dpy, Window window)
   if (xoff < 0) xoff = 0;
   if (yoff < 0) yoff = 0;
 
-  BSOD_MARGINS (bst, xoff, yoff);
+  BSOD_MARGINS (bst, xoff, xoff);
 
   BSOD_COLOR (bst, bc, bg);
   BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, bst->xgwa.height);
@@ -2552,7 +2552,9 @@ macsbug (Display *dpy, Window window)
   BSOD_MOVETO (bst,
                xoff + col_right + char_width,
                yoff + body_top + line_height);
-  BSOD_MARGINS (bst, xoff + col_right + char_width, yoff);
+  BSOD_MARGINS (bst,
+                xoff + col_right + char_width,
+                xoff + col_right + char_width);
   BSOD_TEXT (bst, LEFT, body);
 
   BSOD_RECT (bst, False, xoff-2, yoff, page_right+4, page_bottom); /* again */
@@ -3265,28 +3267,21 @@ sparc_solaris (Display *dpy, Window window)
   Pixmap pixmap = image_data_to_pixmap (dpy, window,
                                         sun_png, sizeof(sun_png),
                                         &pix_w, &pix_h, &mask);
-# if 0
-  if (pixmap && 
-      pix_w < bst->xgwa.width / 2 &&
-      pix_h < bst->xgwa.height / 2)
-    {
-      int i, n = 1;
-      if (bst->xgwa.width > 2560) n++;  /* Retina displays */
-      for (i = 0; i < n; i++)
-        {
-          pixmap = double_pixmap (dpy, bst->xgwa.visual,
-                                  bst->xgwa.depth, pixmap, pix_w, pix_h);
-          mask = double_pixmap (dpy, bst->xgwa.visual, 1, mask, pix_w, pix_h);
-          pix_w *= 2;
-          pix_h *= 2;
-        }
-    }
-# endif
 
   char_width = (bst->font->per_char
                ? bst->font->per_char['n'-bst->font->min_char_or_byte2].width
                : bst->font->min_bounds.width);
 
+  if (pixmap)
+    while (pix_w < char_width * 4)
+      {
+        pixmap = double_pixmap (dpy, bst->xgwa.visual,
+                                bst->xgwa.depth, pixmap, pix_w, pix_h);
+        mask = double_pixmap (dpy, bst->xgwa.visual, 1, mask, pix_w, pix_h);
+        pix_w *= 2;
+        pix_h *= 2;
+      }
+
   bst->pixmap = pixmap;
   bst->mask = mask;
 
@@ -3384,13 +3379,13 @@ sparc_solaris (Display *dpy, Window window)
 
   BSOD_PIXMAP (bst, 0, 0, pix_w, pix_h, ~0, ~0);
   BSOD_MARGINS (bst,
-                bst->left_margin + char_width * 12,
-                bst->top_margin);
+                bst->left_margin + pix_w + char_width * 2,
+                bst->left_margin + pix_w + char_width * 2);
   BSOD_TEXT (bst, LEFT,
              "SPARCstation IPC, Keyboard Present\n"
              "ROM Rev. 2.9, 16 MB memory installed, Serial #12648190.\n"
              "Ethernet address 8:0:20:37:1:87, Host ID: 52c0fefe.\n");
-  BSOD_MARGINS (bst, bst->left_margin, bst->top_margin);
+  BSOD_MARGINS (bst, bst->left_margin, bst->left_margin);
 
   BSOD_TEXT (bst, LEFT, "\n\n\033");
   BSOD_PAUSE (bst, 3000000);
@@ -5653,6 +5648,121 @@ dvd (Display *dpy, Window window)
 }
 
 
+static struct bsod_state *
+tivo (Display *dpy, Window window)
+{
+  struct bsod_state *bst = make_bsod_state (dpy, window, "tivo", "Tivo");
+  int char_width =
+    (bst->font->per_char
+     ? bst->font->per_char['n'-bst->font->min_char_or_byte2].width
+     : bst->font->min_bounds.width);
+  int line_height = bst->font->ascent + bst->font->descent;
+
+  int left = (bst->xgwa.width - char_width * 44) / 2;
+  int top = (bst->xgwa.height - line_height * 15) / 2;
+  if (left < 0) left = 0;
+  if (top < 0) top = 0;
+
+  XClearWindow (dpy, window);
+
+  BSOD_MARGINS (bst, left, left);
+  BSOD_MOVETO (bst, left, top);
+
+  BSOD_FONT (bst, 1);
+  BSOD_TEXT (bst, LEFT, "\nA severe error has occurred.\n\n");
+  BSOD_FONT (bst, 0);
+  BSOD_TEXT (bst, LEFT,
+             "Please leave the Receiver plugged in and connected\n"
+             "to the phone line for the next three hours while the\n"
+             "Receiver attempts to repair itself.");
+  BSOD_FONT (bst, 1);
+  BSOD_TEXT (bst, LEFT,
+             "\n\n"
+             "DO NOT UNPLUG OR RESTART\nTHE RECEIVER.\n\n");
+  BSOD_FONT (bst, 0);
+  BSOD_TEXT (bst, LEFT,
+             "If, after three hours, the Receiver does not restart\n"
+             "itself, call Customer Care.");
+
+  BSOD_PAUSE (bst, 1000000 * 60);
+  return bst;
+}
+
+
+/* Error message for corrupted (and therefore presumed bootleg) cartridges.
+ */
+static struct bsod_state *
+nintendo (Display *dpy, Window window)
+{
+  struct bsod_state *bst = make_bsod_state (dpy, window,
+                                            "nintendo", "Nintendo");
+  unsigned long bg = get_pixel_resource (dpy, bst->xgwa.colormap,
+                                         "nintendo.background",
+                                         "Nintendo.Background");
+  unsigned long bg2 = get_pixel_resource (dpy, bst->xgwa.colormap,
+                                          "nintendo.background2",
+                                          "Nintendo.Background");
+  unsigned long fg = get_pixel_resource (dpy, bst->xgwa.colormap,
+                                         "nintendo.foreground",
+                                         "Nintendo.Foreground");
+  int char_width =
+    (bst->font->per_char
+     ? bst->font->per_char['n'-bst->font->min_char_or_byte2].width
+     : bst->font->min_bounds.width);
+  int line_height = bst->font->ascent + bst->font->descent;
+
+  int left = (bst->xgwa.width - char_width * 30) / 2;
+  int top = (bst->xgwa.height - line_height * 9) / 2;
+  int left2 = left - char_width * 4;
+  int top2  = top - line_height;
+  if (left < 0) left = 0;
+  if (top < 0) top = 0;
+  if (left2 < 0) left2 = 0;
+  if (top2 < 0) top2 = 0;
+  if (left2 > char_width * 8) left2 = char_width * 8;
+  if (top2  > line_height * 10) top2 = line_height * 10;
+
+  XClearWindow (dpy, window);
+
+  BSOD_COLOR (bst, bg2, bg);
+  BSOD_RECT (bst, True, left2, top2 - line_height*2,
+             bst->xgwa.width - left2*2, 
+             bst->xgwa.height - top2*2 + line_height*2);
+
+  BSOD_MARGINS (bst, left, left);
+  BSOD_MOVETO (bst, left, top - line_height/2);
+
+  BSOD_FONT (bst, 1);
+  BSOD_COLOR (bst, bg, bg2);
+
+  /* a variant crash has a second box above the English text that says:
+
+                        警告
+         ビデオゲームのコピーは法律で禁じられています。
+         詳しくは取扱説明書をご覧になってください。
+
+     but BSOD_TEXT doesn't do Xft, and more importantly, "PxPlus IBM VGA8"
+     doesn't contain Japanese characters.
+   */
+
+  BSOD_TEXT (bst, CENTER, "WARNING");
+  BSOD_FONT (bst, 0);
+  BSOD_COLOR (bst, fg, bg2);
+  BSOD_TEXT (bst, LEFT,
+             "\n\n"
+             "IT IS A SERIOUS CRIME\n"
+             "TO COPY VIDEO GAMES\n"
+             "ACCORDING TO COPYRIGHT LAW.\n"
+             "PLEASE REFER TO\n"
+             "YOUR NINTENDO GAME\n"
+             "INSTRUCTION BOOKLET\n"
+             "FOR FURTHER INFORMATION.");
+
+  BSOD_PAUSE (bst, 1000000 * 60);
+  return bst;
+}
+
+
 /* An Android phone boot loader, by jwz.
  */
 static struct bsod_state *
@@ -5930,6 +6040,8 @@ static const struct {
   { "VMware",          vmware },
   { "Encom",           encom },
   { "DVD",             dvd },
+  { "Tivo",            tivo },
+  { "Nintendo",                nintendo },
 };
 
 
@@ -6247,10 +6359,12 @@ static const char *bsod_defaults [] = {
   "*doNvidia:             True",
   "*doATM:                True",
   "*doGLaDOS:             True",
-  "*doAndroid:            True",
+  "*doAndroid:            False",
   "*doVMware:             True",
   "*doEncom:              True",
   "*doDVD:                True",
+  "*doTivo:               True",
+  "*doNintendo:                   True",
 
   ".foreground:                   White",
   ".background:                   Black",
@@ -6362,6 +6476,13 @@ static const char *bsod_defaults [] = {
   ".vmware.foreground2:           Yellow",
   ".vmware.background:    #a700a8",    /* purple */
 
+  ".tivo.background:      #339020",
+  ".tivo.foreground:      #B8E6BA",
+
+  ".nintendo.background:   #F76D0A",
+  ".nintendo.background2:  #085C89",
+  ".nintendo.foreground:   #EEAACF",
+
   "*dontClearRoot:         True",
 
   ANALOGTV_DEFAULTS
@@ -6370,6 +6491,8 @@ static const char *bsod_defaults [] = {
   "*useSHM:                True",
 #endif
 
+  ".lowrez: false",  /* This is required on macOS */
+
   "*fontB:                ",
   "*fontC:                ",
 
@@ -6400,6 +6523,11 @@ static const char *bsod_defaults [] = {
   ".ransomware.fontB:        Arial 9, Helvetica 9",
   ".ransomware.fontC:        Arial Bold 11, Arial-BoldMT 11, Helvetica Bold 11",
 
+  ".tivo.font:            Helvetica-Bold 13",
+  ".tivo.fontB:                   Helvetica-Bold 17",
+
+  ".nintendo.font:        PxPlus IBM VGA8 18, Courier-Bold 18",
+
 # elif defined(HAVE_ANDROID)
 
   "*font:                 PxPlus IBM VGA8 16",
@@ -6424,6 +6552,11 @@ static const char *bsod_defaults [] = {
   ".ransomware.fontB:     -*-helvetica-medium-r-*-*-*-80-*-*-*-*-*-*",
   ".ransomware.fontC:     -*-helvetica-bold-r-*-*-*-100-*-*-*-*-*-*",
 
+  ".tivo.font:            -*-helvetica-medium-r-*-*-*-180-*-*-*-*-*-*",
+  ".tivo.fontB:                   -*-helvetica-bold-r-*-*-*-240-*-*-*-*-*-*",
+
+  ".nintendo.font:        PxPlus IBM VGA8 18",
+
 # elif defined(HAVE_COCOA)
 
   "*font:                 PxPlus IBM VGA8 8,  Courier Bold 9",
@@ -6455,10 +6588,16 @@ static const char *bsod_defaults [] = {
   ".win10.fontB:          Arial 100, Helvetica 100",
   ".win10.fontC:          Arial 16, Helvetica 16",
 
-  ".ransomware.font:         Arial 24, Helvetica 24",
-  ".ransomware.bigFont:      Arial 24, Helvetica 24",
-  ".ransomware.fontB:        Arial 16, Helvetica 16",
-  ".ransomware.fontC:        Arial Bold 24, Helvetica Bold 24",
+  ".ransomware.font:       Arial 24, Helvetica 24",
+  ".ransomware.bigFont:    Arial 24, Helvetica 24",
+  ".ransomware.fontB:      Arial 16, Helvetica 16",
+  ".ransomware.fontC:      Arial Bold 24, Helvetica Bold 24",
+
+  ".tivo.font:            Helvetica 36",
+  ".tivo.fontB:                   Helvetica 48",
+
+  ".nintendo.font:        PxPlus IBM VGA8 12, Courier Bold 12",
+  ".nintendo.bigFont:     PxPlus IBM VGA8 48, Courier Bold 48",
 
 # else   /* X11 */
 
@@ -6506,6 +6645,11 @@ static const char *bsod_defaults [] = {
   ".ransomware.fontB:     -*-helvetica-medium-r-*-*-*-140-*-*-*-*-*-*",
   ".ransomware.fontC:     -*-helvetica-bold-r-*-*-*-180-*-*-*-*-*-*",
 
+  ".tivo.font:            -*-helvetica-medium-r-*-*-*-180-*-*-*-*-*-*",
+  ".tivo.fontB:                   -*-helvetica-bold-r-*-*-*-240-*-*-*-*-*-*",
+
+  ".nintendo.font:        -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
+  ".nintendo.bigFont:     -*-courier-bold-r-*-*-*-360-*-*-m-*-*-*",
 
 # endif  /* X11 */
 
@@ -6580,8 +6724,12 @@ static const XrmOptionDescRec bsod_options [] = {
   { "-no-vmware",      ".doVMware",            XrmoptionNoArg,  "False" },
   { "-encom",          ".doEncom",             XrmoptionNoArg,  "True"  },
   { "-no-encom",       ".doEncom",             XrmoptionNoArg,  "False" },
-  { "-dvd",            ".doDVD",               XrmoptionNoArg,  "True"  },
-  { "-no-dvd",         ".doDVD",               XrmoptionNoArg,  "False" },
+  { "-dvd",            ".doDVD",               XrmoptionNoArg,  "True"  },
+  { "-no-dvd",         ".doDVD",               XrmoptionNoArg,  "False" },
+  { "-tivo",           ".doTivo",              XrmoptionNoArg,  "True"  },
+  { "-no-tivo",                ".doTivo",              XrmoptionNoArg,  "False" },
+  { "-nintendo",       ".doNintendo",          XrmoptionNoArg,  "True"  },
+  { "-no-nintendo",    ".doNintendo",          XrmoptionNoArg,  "False" },
   ANALOGTV_OPTIONS
   { 0, 0, 0, 0 }
 };
index 9fab007949d741fddc1f523ee17ef3d4bf3e00bf..caf116c257463a6fe5363743130bda0b3145e377 100644 (file)
@@ -111,6 +111,7 @@ $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) RORSCHACH.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) ROTOR.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) ROTZOOMER.C
+$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) SCOOTER.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) SCREENHACK.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) SHADEBOBS.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) SIERPINSKI.C
index 9fab007949d741fddc1f523ee17ef3d4bf3e00bf..caf116c257463a6fe5363743130bda0b3145e377 100644 (file)
@@ -111,6 +111,7 @@ $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) RORSCHACH.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) ROTOR.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) ROTZOOMER.C
+$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) SCOOTER.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) SCREENHACK.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) SHADEBOBS.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) SIERPINSKI.C
index 58c41953ea650c76feee361eb216bb9236b06d9f..5ba2e7baf2e36862538d33ba92cdc2b4870eee44 100644 (file)
@@ -4,8 +4,8 @@
             a screen saver and locker for the X window system
                             by Jamie Zawinski
 
-                              version 5.43
-                               09-Jul-2019
+                              version 5.44
+                               20-Mar-2020
 
                      https://www.jwz.org/xscreensaver/
 
index 0d18218728209afa3ed2bf96de52ee476c6e2ff2..6a3ac4ac2f14c774f52654986693345e7cec6242 100644 (file)
@@ -24,7 +24,7 @@
   <vgroup>
    <boolean id="amiga"      _label="AmigaDOS"       arg-unset="-no-amiga"/>
    <boolean id="glados"     _label="GLaDOS"         arg-unset="-no-glados"/>
-   <boolean id="android"    _label="Android"        arg-unset="-no-android"/>
+   <boolean id="android"    _label="Android"        arg-set="-android"/>
    <boolean id="apple2"     _label="Apple ]["       arg-unset="-no-apple2"/>
    <boolean id="ransomware" _label="Ransomware"     arg-unset="-no-ransomware"/>
   </vgroup>
    <boolean id="encom"      _label="Encom"          arg-unset="-no-encom"/>
   </vgroup>
   <vgroup>
-   <boolean id="vms"        _label="VMS"            arg-unset="-no-vms"/>
    <boolean id="hvx"        _label="HVX/GCOS6"      arg-unset="-no-hvx"/>
    <boolean id="blitdamage" _label="NCD X Terminal  " arg-unset="-no-blitdamage"/>
    <boolean id="atm"        _label="ATM"            arg-unset="-no-atm"/>
    <boolean id="dvd"        _label="DVD"            arg-unset="-no-dvd"/>
+   <boolean id="nintendo"   _label="Nintendo"       arg-unset="-no-nintendo"/>
   </vgroup>
   <vgroup>
+   <boolean id="tivo"       _label="Tivo"           arg-unset="-no-tivo"/>
+   <boolean id="vms"        _label="VMS"            arg-unset="-no-vms"/>
    <boolean id="bsd"        _label="BSD"            arg-set="-bsd"/>
    <boolean id="linux"      _label="Linux (fsck)"   arg-unset="-no-linux"/>
    <boolean id="sparclinux" _label="Linux (sparc)"  arg-set="-sparclinux"/>
-   <boolean id="hppalinux"  _label="Linux (hppa)"   arg-unset="-no-hppalinux"/>
   </vgroup>
   <vgroup>
+   <boolean id="hppalinux"  _label="Linux (hppa)"   arg-unset="-no-hppalinux"/>
    <boolean id="solaris"    _label="Solaris"        arg-unset="-no-solaris"/>
    <boolean id="sco"        _label="SCO"            arg-unset="-no-sco"/>
    <boolean id="hpux"       _label="HPUX"           arg-unset="-no-hpux"/>
index e1118e27dd6a3df913165e91a4b7416c0f83549c..d690d2de3aa5e27c4397cdbc529c797da0afcbeb 100644 (file)
@@ -19,6 +19,8 @@
           _label="Smear" _low-label="Low" _high-label="High"
           low="0.1" high="5.0" default="1.0"/>
 
+  <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
+
   <xscreensaver-updater />
 
   <_description>
index ac10f15ae9be4c9ba694c3ee4f31cb92769d85e4..48cd2ee6002e273be3f341af1c1964c93ca7633b 100644 (file)
@@ -33,18 +33,6 @@ DNA Lounge
         San Francisco, CA
         94103
 
-Codeword
-
-        Restaurant -- Bar -- Nightclub -- Cafe -- Est. 2015.
-
-        917 Folsom Street
-        San Francisco, CA
-        94107
-
-        https://www.dnalounge.com/
-        http://www.dnapizza.com/
-        https://www.codeword-sf.com/
-
 Written by Jamie Zawinski; 2001.
   </_description>
 </screensaver>
diff --git a/hacks/config/etruscanvenus.xml b/hacks/config/etruscanvenus.xml
new file mode 100644 (file)
index 0000000..090b102
--- /dev/null
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<screensaver name="etruscanvenus" _label="EtruscanVenus" gl="yes">
+
+  <video href="https://www.youtube.com/watch?v=p3MgGyie6-I"/>
+
+  <command arg="-root"/>
+
+  <hgroup>
+    <select id="view-mode">
+      <option id="walk"      _label="Random motion"/>
+      <option id="walk"      _label="Walk"      arg-set="-view-mode walk"/>
+      <option id="turn"      _label="Turn"      arg-set="-view-mode turn"/>
+    </select>
+
+    <boolean id="orientation-marks" _label="Show orientation marks"
+              arg-set="-orientation-marks"/>
+  </hgroup>
+
+  <hgroup>
+    <boolean id="deform" _label="Deform the surface"
+              arg-unset="-no-deform"/>
+
+    <number id="deform-speed" type="slider" arg="-deformation-speed %"
+            _label="Deformation speed"
+            _low-label="1.0" _high-label="100.0"
+            low="1.0" high="100.0" default="10.0"/>
+
+    <number id="init-deform" type="slider" arg="-initial-deformation %"
+            _label="Initial deformation"
+            _low-label="0.0" _high-label="3999.0"
+            low="0.0" high="3999.0" default="0.0"/>
+  </hgroup>
+
+
+  <hgroup>
+
+    <vgroup>
+      <select id="display-mode">
+        <option id="random"      _label="Random surface"/>
+        <option id="wire"        _label="Wireframe mesh"      arg-set="-mode wireframe"/>
+        <option id="surface"     _label="Solid surface"       arg-set="-mode surface"/>
+        <option id="transparent" _label="Transparent surface" arg-set="-mode transparent"/>
+      </select>
+
+      <select id="appearance">
+        <option id="random" _label="Random pattern"/>
+        <option id="solid"  _label="Solid object"    arg-set="-appearance solid"/>
+        <option id="bands"  _label="Distance bands"  arg-set="-appearance distance-bands"/>
+        <option id="bands"  _label="Direction bands" arg-set="-appearance direction-bands"/>
+      </select>
+
+      <select id="colors">
+        <option id="random"   _label="Random coloration"/>
+        <option id="twosided" _label="One-sided"        arg-set="-colors one-sided"/>
+        <option id="twosided" _label="Two-sided"        arg-set="-colors two-sided"/>
+        <option id="rainbow"  _label="Distance colors"  arg-set="-colors distance"/>
+        <option id="rainbow"  _label="Direction colors" arg-set="-colors direction"/>
+      </select>
+
+      <boolean id="change-colors" _label="Change colors"
+                arg-unset="-no-change-colors"/>
+
+      <select id="projection">
+        <option id="random"       _label="Random Projection"/>
+        <option id="perspective"  _label="Perspective"  arg-set="-projection perspective"/>
+        <option id="orthographic" _label="Orthographic" arg-set="-projection orthographic"/>
+      </select>
+    </vgroup>
+
+    <vgroup>
+      <number id="speed-x" type="slider" arg="-speed-x %"
+              _label="X rotation speed"
+              _low-label="-4.0" _high-label="4.0"
+              low="-4.0" high="4.0" default="1.1"/>
+
+      <number id="speed-y" type="slider" arg="-speed-y %"
+              _label="Y rotation speed"
+              _low-label="-4.0" _high-label="4.0"
+              low="-4.0" high="4.0" default="1.3"/>
+
+      <number id="speed-z" type="slider" arg="-speed-z %"
+              _label="Z rotation speed"
+              _low-label="-4.0" _high-label="4.0"
+              low="-4.0" high="4.0" default="1.5"/>
+    </vgroup>
+
+    <vgroup>
+     <number id="walk-direction" type="slider" arg="-walk-direction %"
+             _label="Walking direction"
+             _low-label="-180.0" _high-label="180.0"
+             low="-180.0" high="180.0" default="83.0"/>
+
+     <number id="walk-speed" type="slider" arg="-walk-speed %"
+             _label="Walking speed"
+             _low-label="1.0" _high-label="100.0"
+             low="1.0" high="100.0" default="20.0"/>
+
+     <number id="delay" type="slider" arg="-delay %"
+             _label="Frame rate" _low-label="Low" _high-label="High"
+             low="0" high="100000" default="10000"
+             convert="invert"/>
+    </vgroup>
+
+    <vgroup>
+     <xscreensaver-updater />
+     <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
+    </vgroup>
+
+  </hgroup>
+
+  <_description>
+A 3D immersion of of a Klein bottle that smoothly deforms between the
+Etruscan Venus surface, the Roman surface, the Boy surface, and the
+Ida surface.  Topologically, all surfaces are Klein bottles, even the
+Roman and Boy surfaces, which are doubly covered and therefore appear
+to be an immersed real projective plane.
+
+You can walk on the Klein bottle or rotate it in 3D.  Since all the
+surfaces except the Ida surfaces have points where the surface normal
+is not well defined for some points, walking is performed on the Ida
+surface.  Furthermore, it is possible to smoothly deform the surface
+between the Etruscan Venus surface, the Roman surface, the Boy
+surface, and the Ida surface surface while turning it.
+
+Inspired by George K. Francis's book "A Topological Picturebook",
+Springer, 1987, George K. Francis's paper "The Etruscan Venus" in
+P. Concus, R. Finn, and D. A. Hoffman: "Geometric Analysis and
+Computer Graphics", Springer, 1991, and a video entitled "The Etruscan
+Venus" by Donna J. Cox, George K. Francis, and Raymond L. Idaszak,
+presented at SIGGRAPH 1989.
+
+https://en.wikipedia.org/wiki/Boy%27s_surface
+https://en.wikipedia.org/wiki/Roman_surface
+https://en.wikipedia.org/wiki/Klein_bottle
+http://mathworld.wolfram.com/BoySurface.html
+http://mathworld.wolfram.com/RomanSurface.html
+http://mathworld.wolfram.com/EtruscanVenusSurface.html
+http://mathworld.wolfram.com/IdaSurface.html
+
+Written by Carsten Steger; 2020.
+  </_description>
+</screensaver>
diff --git a/hacks/config/gibson.xml b/hacks/config/gibson.xml
new file mode 100644 (file)
index 0000000..3e69a9c
--- /dev/null
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="gibson" _label="Gibson" gl="yes">
+
+  <command arg="-root"/>
+
+  <video href="https://www.youtube.com/watch?v=_gOhMR3TrHA"/>
+
+  <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="Glyph speed" _low-label="Slow" _high-label="Fast"
+            low="0.1" high="8.0" default="1.0"/>
+   </vgroup>
+   <vgroup>
+    <number id="grid-width" type="spinbutton" arg="-grid-width %"
+            _label="Grid width" low="1" high="20" default="6"/>
+
+    <number id="grid-depth" type="spinbutton" arg="-grid-depth %"
+            _label="Grid depth" low="1" high="20" default="6"/>
+   </vgroup>
+   <vgroup>
+    <number id="grid-height" type="spinbutton" arg="-grid-height %"
+            _label="Tower depth" low="1" high="20" default="7"/>
+
+    <number id="spacing" type="spinbutton" arg="-spacing %"
+            _label="Tower spacing" low="1" high="5" default="2.0"/>
+
+    <number id="columns" type="spinbutton" arg="-columns %"
+            _label="Text columns" low="1" high="20" default="5"/>
+   </vgroup>
+  </hgroup>
+
+  <hgroup>
+   <boolean id="tex"     _label="Textured"  arg-unset="-no-texture"/>
+   <boolean id="wire"    _label="Wireframe"   arg-set="-wireframe"/>
+   <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
+   <xscreensaver-updater />
+  </hgroup>
+
+  <_description>
+Hacking the Gibson, as per the 1995 classic film, HACKERS.
+
+Cereal Killer: "Oh yeah, you want a seriously righteous hack, you score
+one of those Gibsons, man.  You know, supercomputers they use to like,
+do physics, and look for oil and stuff?"
+
+Phantom Phreak: "Ain't no way, man, security's too tight. The big iron?"
+
+Zero Cool: "Maybe. But, if I were gonna hack some heavy metal, I'd, uh,
+work my way back through some low security, and try the back door."
+
+Cereal Killer: "Yeah but oh man, wouldn't you just love to get one of
+those Gibsons, baby? Ooooh!"
+
+Phantom Phreak: "Yo, who ate all of my fries?"
+
+Written by Jamie Zawinski; 2020.
+  </_description>
+</screensaver>
index a82e090afd7e057aa9797372e15689a7e78f4cf7..899d0cbad8efbbbc960d797d937ee684bd11d96d 100644 (file)
     </select>
 
     <select id="colors">
-      <option id="twosided" _label="Two-sided" arg-set="-twosided"/>
+      <option id="onesided"   _label="One-sided" arg-set="-onesided"/>
+      <option id="twosided"   _label="Two-sided" arg-set="-twosided"/>
       <option id="colorwheel" _label="Color wheel"/>
     </select>
 
+    <boolean id="change-colors" _label="Change colors"
+              arg-set="-change-colors"/>
+
     <select id="projection3d">
       <option id="perspective-3d" _label="Perspective 3D"/>
       <option id="orthographic-3d" _label="Orthographic 3D"
index 8a93c9e0e3ba9b81bfea54cad8ab46886a7d28d6..4880eb0bf2cb41ea831318dbaa46ee18b9e07cf1 100644 (file)
@@ -8,10 +8,10 @@
 
   <hgroup>
     <select id="kleinbottle">
-      <option id="random"         _label="Random shape"/>
-      <option id="figure-8"       _label="Figure 8"       arg-set="-klein-bottle figure-8"/>
-      <option id="squeezed-torus" _label="Squeezed torus" arg-set="-klein-bottle squeezed-torus"/>
-      <option id="lawson"         _label="Lawson"         arg-set="-klein-bottle lawson"/>
+      <option id="random"        _label="Random shape"/>
+      <option id="figure-8"      _label="Figure 8"      arg-set="-klein-bottle figure-8"/>
+      <option id="pinched-torus" _label="Pinched torus" arg-set="-klein-bottle pinched-torus"/>
+      <option id="lawson"        _label="Lawson"        arg-set="-klein-bottle lawson"/>
     </select>
 
     <select id="view-mode">
 
     <select id="colors">
       <option id="random"   _label="Random coloration"/>
+      <option id="twosided" _label="One-sided"       arg-set="-colors one-sided"/>
       <option id="twosided" _label="Two-sided"       arg-set="-colors two-sided"/>
       <option id="rainbow"  _label="Rainbow colors"  arg-set="-colors rainbow"/>
       <option id="depth"    _label="4d depth colors" arg-set="-colors depth"/>
     </select>
 
+    <boolean id="change-colors" _label="Change colors"
+              arg-set="-change-colors"/>
+
     <select id="projection3d">
       <option id="random"          _label="Random 3D"/>
       <option id="perspective-3d"  _label="Perspective 3D"  arg-set="-projection-3d perspective"/>
index fa9dfb86c7093a6b013156e85702e9a43d0639cc..996d0107bd7365002ad56084fddb04d69bca97a2 100644 (file)
 
     <select id="colors">
       <option id="random"   _label="Random coloration"/>
+      <option id="twosided" _label="One-sided"        arg-set="-colors one-sided"/>
       <option id="twosided" _label="Two-sided"        arg-set="-colors two-sided"/>
       <option id="rainbow"  _label="Distance colors"  arg-set="-colors distance"/>
       <option id="rainbow"  _label="Direction colors" arg-set="-colors direction"/>
       <option id="depth"    _label="4d depth colors"  arg-set="-colors depth"/>
     </select>
 
+    <boolean id="change-colors" _label="Change colors"
+              arg-set="-change-colors"/>
+
     <select id="projection3d">
       <option id="random"          _label="Random 3D"/>
       <option id="perspective-3d"  _label="Perspective 3D"  arg-set="-projection-3d perspective"/>
index 1af07df0c674bc196264a1a26a31c541d72914a3..043788e4c582fdbcbcaa3114b3e268bce84dc309 100644 (file)
@@ -29,7 +29,7 @@
             low="1.0" high="10.0" default="5.0"/>
 
     <number id="thickness" type="slider" arg="-thickness %"
-            _label="Lines" _low-label="Thick" _high-label="Thin"
+            _label="Lines" _low-label="Thin" _high-label="Thick"
             low="0.05" high="1.0" default="0.1"/>
 
     <select id="object">
index b2f6cb4596686c6f8500b425db20693ad2f1546e..941317c1eb92a4162b3769d8ee564423427d813e 100644 (file)
 
       <select id="colors">
         <option id="random"   _label="Random coloration"/>
+        <option id="twosided" _label="One-sided"        arg-set="-colors one-sided"/>
         <option id="twosided" _label="Two-sided"        arg-set="-colors two-sided"/>
         <option id="rainbow"  _label="Distance colors"  arg-set="-colors distance"/>
         <option id="rainbow"  _label="Direction colors" arg-set="-colors direction"/>
       </select>
 
+      <boolean id="change-colors" _label="Change colors"
+                arg-set="-change-colors"/>
+
       <select id="projection">
         <option id="random"          _label="Random Projection"/>
         <option id="perspective"  _label="Perspective"  arg-set="-projection perspective"/>
diff --git a/hacks/config/scooter.xml b/hacks/config/scooter.xml
new file mode 100644 (file)
index 0000000..72fe9b3
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="scooter" _label="Scooter" gl="no">
+
+  <command arg="-root"/>
+
+  <video href="https://www.youtube.com/watch?v=Qqzk1BldlXg"/>
+
+  <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="cycles" type="slider" arg="-cycles %"
+            _label="Boat Speed" _low-label="Very slow" _high-label="Very fast"
+            low="0" high="1000" default="5"/>
+    <number id="count" type="slider" arg="-count %"
+            _label="Number of doors" _low-label="4" _high-label="40"
+            low="4" high="40" default="24"/>
+   </vgroup>
+   <vgroup>
+    <number id="size" type="slider" arg="-size %"
+            _label="Number of stars" _low-label="1" _high-label="200"
+            low="0" high="200" default="100"/>
+    <number id="ncolors" type="slider" arg="-ncolors %"
+            _label="Number of colors" _low-label="Mono" _high-label="Colorful"
+            low="0" high="200" default="200"/>
+
+    <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
+
+    <xscreensaver-updater />
+   </vgroup>
+  </hgroup>
+
+  <_description>
+Zooming down a tunnel in a star field.  Originally an Amiga hack.
+
+Written by Sven Thoennissen; 2001.
+Ported by EoflaOE; 2019.
+  </_description>
+</screensaver>
index e88986b234fd6c2c8022130f630bb8214b5ca1de..376d9264fb43313cbea31ac816bce918fa5e7585 100644 (file)
@@ -631,7 +631,8 @@ draw_drift(ModeInfo * mi)
                if (dp->total_points++ > dp->fractal_len) {
                        draw_flush(mi, dp, window);
                        if (0 == --dp->nfractals) {
-              dp->erase_countdown = 4 * 1000000 / MI_PAUSE(mi);
+              dp->erase_countdown = 4 * 1000000 / 
+                ((MI_PAUSE(mi) == 0) ? 1 : MI_PAUSE(mi));
                                return;
                        }
                        initfractal(mi);
index 3f68cf7cb0f0b03ad19fedae3e03bf327f7600d4..a4cfc254fe1752f2ca9f22f78261d3d23f852dd9 100644 (file)
  *
  * Module - "eruption.c"
  *
+ * [01-2015] - Dave Odell <dmo2118@gmail.com>: Performance tweaks. Also, click-for-explosion.
  * [02-2003] - W.P. van Paassen: Improvements, added some code of jwz from the pyro hack for a spherical distribution of the particles
  * [01-2003] - W.P. van Paassen: Port to X for use with XScreenSaver, the shadebob hack by Shane Smit was used as a template
  * [04-2002] - W.P. van Paassen: Creation for the Demo Effects Collection (http://demo-effects.sourceforge.net)
  */
 
+#include <assert.h>
 #include <math.h>
 #include "screenhack.h"
+#include "xshm.h"
+
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+typedef unsigned long uint32_t;
+typedef unsigned short uint16_t;
+typedef unsigned char uint8_t;
+#endif
 
 /*#define VERBOSE*/ 
 
@@ -42,7 +53,7 @@ struct state {
 
   PARTICLE *particles;
   unsigned short iWinWidth, iWinHeight;
-  unsigned char **fire;
+  unsigned char *fire;
   unsigned short nParticleCount;
   unsigned char xdelta, ydelta, decay;
   signed char gravity;
@@ -53,6 +64,7 @@ struct state {
   signed short iColorCount;
   unsigned long *aiColorVals;
   XImage *pImage;
+  XShmSegmentInfo shm_info;
 
   int draw_i;
 };
@@ -85,12 +97,18 @@ static void init_particle(struct state *st, PARTICLE* particle, unsigned short x
   particle->dead = 0;
 }
 
+#define X_PAD 1 /* Could be more if anybody wants the blur to fall off the left/right edges. */
+#define Y_PAD 1
+
+
 static void Execute( struct state *st )
 {
+  XImage *img = st->pImage;
   int i, j;
-  unsigned int temp;
+  size_t fire_pitch = st->iWinWidth + X_PAD * 2;
+  unsigned char *line0, *line1, *line2;
 
-  /* move and draw particles into st->fire array */
+  /* move particles */
   
   for (i = 0; i < st->nParticleCount; i++)
     {
@@ -141,74 +159,123 @@ static void Execute( struct state *st )
          
          /* particle cools off */
          st->particles[i].colorindex--;
-         
-         /* draw particle */
-         if (st->iWinHeight <= 2 || st->iWinWidth <= 2) continue;
-         st->fire[st->particles[i].ypos][st->particles[i].xpos] = st->particles[i].colorindex;
-         st->fire[st->particles[i].ypos][st->particles[i].xpos - 1] = st->particles[i].colorindex;
-         st->fire[st->particles[i].ypos + 1][st->particles[i].xpos] = st->particles[i].colorindex;
-         st->fire[st->particles[i].ypos - 1][st->particles[i].xpos] = st->particles[i].colorindex;
-         st->fire[st->particles[i].ypos][st->particles[i].xpos + 1] = st->particles[i].colorindex;
        }
     }
-  
-  /* create st->fire effect */ 
-  for (i = 0; i < st->iWinHeight; i++)
+
+  /* draw particles into st->fire array */
+  for( i = 0; i < st->nParticleCount; i++ )
     {
-      for (j = 0; j < st->iWinWidth; j++)
-       {
-         if (j + 1 >= st->iWinWidth)
-           temp = 0;
-         else
-           temp = st->fire[i][j + 1];
+      PARTICLE *p = &st->particles[i];
+      if( !p->dead && p->ypos >= -Y_PAD + 1 && p->ypos < st->iWinHeight + Y_PAD - 1 )
+        {
+          /* draw particle */
+          unsigned char *center = st->fire + (p->ypos - -Y_PAD) * fire_pitch + (p->xpos + X_PAD);
+          unsigned char color = p->colorindex;
+          *center = color;
+          center[-1] = color;
+          if (p->ypos < st->iWinHeight + Y_PAD - 2)
+            center[fire_pitch] = color;
+          if (p->ypos >= -Y_PAD + 2)
+            center[-fire_pitch] = color;
+          center[1] = color;
+        }
+    }
 
-         if (j - 1 >= 0)  
-           temp += st->fire[i][j - 1];
+  line0 = st->fire + X_PAD;
+  line1 = line0 + fire_pitch;
+  line2 = line1 + fire_pitch;
 
-         if (i - 1 >= 0)
-           {
-             temp += st->fire[i - 1][j];
-             if (j - 1 >= 0)
-               temp += st->fire[i - 1][j - 1];
-             if (j + 1 < st->iWinWidth)
-               temp += st->fire[i - 1][j + 1];
-           }
-         
-         if (i + 1 < st->iWinHeight)
-           {
-             temp += st->fire[i + 1][j];
-             if (j + 1 < st->iWinWidth)
-               temp += st->fire[i + 1][j + 1];
-             if (j - 1 >= 0)
-               temp += st->fire[i + 1][j - 1];
-           }
-         
-         temp >>= 3;
-         
-         if (temp > st->decay)
-           {
-             temp -= st->decay;
-           }
-         else
-           temp = 0;
-         
-         st->fire[i][j] = temp;
-       }
+  /* create st->fire effect */
+
+  switch( img->bits_per_pixel )
+    {
+    case 8:
+    case 16:
+    case 32:
+      break;
+    default:
+      memset( img->data, 0, img->bytes_per_line * img->height );
+      break;
     }
-  
-  memset( st->pImage->data, 0, st->pImage->bytes_per_line * st->pImage->height );
-  
-  /* draw st->fire array to screen */
-  for (i = 0; i < st->iWinHeight; ++i)
+
+  for( i = -Y_PAD + 1; i < st->iWinHeight + Y_PAD - 1; i++ )
     {
-      for (j = 0; j < st->iWinWidth; ++j)
-       {
-         if (st->fire[i][j] > 0)
-           XPutPixel( st->pImage, j, i, st->aiColorVals[ st->fire[i][j] ] );
-       }
+      const int j0 = -X_PAD + 1;
+
+      unsigned
+        t0 = line0[j0 - 1] + line1[j0 - 1] + line2[j0 - 1],
+        t1 = line0[j0] + line1[j0] + line2[j0];
+
+      unsigned j1 = st->iWinWidth + X_PAD;
+
+      /* This is basically like the GIMP's "Convolution Matrix" filter, with
+         the following settings:
+         Matrix:
+         | 1 1 1 |    Divisor = 8
+         | 1 0 1 |    Offset = -eruption.cooloff
+         | 1 1 1 |
+         Except that the effect is applied to each pixel individually, in order
+         from left-to-right, then top-to-bottom, resulting in a slight smear
+         going rightwards and downwards.
+       */
+
+      for( j = j0 + 1; j != j1; j++ )
+        {
+          unsigned t2 = line0[j] + line1[j] + line2[j];
+          unsigned char *px = line1 + j - 1;
+          int temp;
+          t1 -= *px;
+          temp = t0 + t1 + t2 - st->decay;
+          temp = temp >= 0 ? temp >> 3 : 0;
+          *px = temp;
+          t0 = t1 + temp;
+          t1 = t2;
+        }
+
+      if( i >= 0 && i < st->iWinHeight )
+        {
+          /* draw st->fire array to screen */
+          void *out_ptr = img->data + img->bytes_per_line * i;
+
+          switch( img->bits_per_pixel )
+            {
+            case 32:
+              {
+                uint32_t *out = (uint32_t *)out_ptr;
+                for( j = 0; j < st->iWinWidth; ++j )
+                  out[j] = st->aiColorVals[ line1[j] ];
+              }
+              break;
+            case 16:
+              {
+                uint16_t *out = (uint16_t *)out_ptr;
+                for( j = 0; j < st->iWinWidth; ++j )
+                  out[j] = st->aiColorVals[ line1[j] ];
+              }
+              break;
+            case 8:
+              {
+                uint8_t *out = (uint8_t *)out_ptr;
+                for( j = 0; j < st->iWinWidth; ++j )
+                  out[j] = st->aiColorVals[ line1[j] ];
+              }
+              break;
+            default:
+              for( j = 0; j < st->iWinWidth; ++j )
+                {
+                  if( line1[j] )
+                    XPutPixel( img, j, i, st->aiColorVals[ line1[j] ] );
+                }
+              break;
+            }
+        }
+
+      line0 += fire_pitch;
+      line1 += fire_pitch;
+      line2 += fire_pitch;
     }
-  XPutImage( st->dpy, st->window, st->gc, st->pImage,
-            0,0,0,0, st->iWinWidth, st->iWinHeight );
+  put_xshm_image( st->dpy, st->window, st->gc, st->pImage,
+                  0,0,0,0, st->iWinWidth, st->iWinHeight, &st->shm_info );
 }
 
 static unsigned long * SetPalette(struct state *st)
@@ -294,43 +361,41 @@ static unsigned long * SetPalette(struct state *st)
 }
 
 
-static void Initialize( struct state *st )
+static void DestroyImage (struct state *st)
 {
-       XGCValues gcValues;
-       XWindowAttributes XWinAttribs;
-       int /*iBitsPerPixel,*/ i;
+  free (st->fire);
+  destroy_xshm_image (st->dpy, st->pImage, &st->shm_info);
+}
 
-       /* Create the Image for drawing */
-       XGetWindowAttributes( st->dpy, st->window, &XWinAttribs );
+static void CreateImage( struct state *st, XWindowAttributes *XWinAttribs )
+{
+  /* Create the Image for drawing */
 
-       /* Find the preferred bits-per-pixel. (jwz) */
-       {
-               int pfvc = 0;
-               XPixmapFormatValues *pfv = XListPixmapFormats( st->dpy, &pfvc );
-               for( i=0; i<pfvc; i++ )
-                       if( pfv[ i ].depth == XWinAttribs.depth )
-                       {
-                               /*iBitsPerPixel = pfv[ i ].bits_per_pixel;*/
-                               break;
-                       }
-               if( pfv )
-                       XFree (pfv);
-       }
+  /* Must be NULL because of how DestroyImage works. */
+  assert( !st->fire );
 
-       /*  Create the GC. */
-       st->gc = XCreateGC( st->dpy, st->window, 0, &gcValues );
+  st->pImage = create_xshm_image( st->dpy, XWinAttribs->visual,
+                                  XWinAttribs->depth, ZPixmap, &st->shm_info,
+                                  XWinAttribs->width, XWinAttribs->height );
+
+  memset( (st->pImage)->data, 0,
+          (st->pImage)->bytes_per_line * (st->pImage)->height);
 
-       st->pImage = XCreateImage( st->dpy, XWinAttribs.visual, XWinAttribs.depth, ZPixmap, 0, NULL,
-                                                         XWinAttribs.width, XWinAttribs.height, BitmapPad( st->dpy ), 0 );
-       (st->pImage)->data = calloc((st->pImage)->bytes_per_line, (st->pImage)->height);
+  st->iWinWidth = XWinAttribs->width;
+  st->iWinHeight = XWinAttribs->height;
+
+  /* create st->fire array */
+  st->fire = calloc( (st->iWinHeight + Y_PAD * 2) * (st->iWinWidth + X_PAD * 2), sizeof(unsigned char));
+}
 
-       st->iWinWidth = XWinAttribs.width;
-       st->iWinHeight = XWinAttribs.height;
+static void Initialize( struct state *st, XWindowAttributes *XWinAttribs )
+{
+       XGCValues gcValues;
+
+       /*  Create the GC. */
+       st->gc = XCreateGC( st->dpy, st->window, 0, &gcValues );
 
-       /* create st->fire array */
-       st->fire = calloc( st->iWinHeight, sizeof(unsigned char*));
-       for (i = 0; i < st->iWinHeight; ++i)
-         st->fire[i] = calloc( st->iWinWidth, sizeof(unsigned char));
+       CreateImage (st, XWinAttribs);
 
        /*create st->particles */
        st->particles = malloc (st->nParticleCount * sizeof(PARTICLE));
@@ -361,6 +426,7 @@ eruption_init (Display *dpy, Window window)
          st->decay = 0;
        if (st->decay > 10)
          st->decay = 10;
+       st->decay <<= 3;
 
        st->gravity = get_integer_resource(st->dpy,  "gravity", "Integer" );
        if (st->gravity < -5)
@@ -378,7 +444,9 @@ eruption_init (Display *dpy, Window window)
        printf( "%s: Allocated %d st->particles\n", progclass, st->nParticleCount );
 #endif  /*  VERBOSE */
 
-       Initialize( st );
+       XGetWindowAttributes( st->dpy, st->window, &XWinAttribs );
+
+       Initialize( st, &XWinAttribs );
 
        st->ydelta = 0;
        while (sum < (st->iWinHeight >> 1) - SPREAD)
@@ -399,12 +467,10 @@ eruption_init (Display *dpy, Window window)
 
        cache(st);
        
-       XGetWindowAttributes( st->dpy, st->window, &XWinAttribs );
        XFreeColors( st->dpy, XWinAttribs.colormap, st->aiColorVals, st->iColorCount, 0 );
        free( st->aiColorVals );
        st->aiColorVals = SetPalette( st );
        XClearWindow( st->dpy, st->window );
-       memset( st->pImage->data, 0, st->pImage->bytes_per_line * st->pImage->height );
 
         st->draw_i = -1;
 
@@ -412,6 +478,23 @@ eruption_init (Display *dpy, Window window)
 }
 
 
+static void
+new_eruption (struct state *st, unsigned short xcenter, unsigned short ycenter)
+{
+  for (st->draw_i = 0; st->draw_i < st->nParticleCount; st->draw_i++)
+    init_particle(st, st->particles + st->draw_i, xcenter, ycenter);
+  st->draw_i = 0;
+}
+
+
+static void
+random_eruption (struct state *st)
+{
+  /* compute random center */
+  new_eruption (st, random() % st->iWinWidth, random() % st->iWinHeight);
+}
+
+
 static unsigned long
 eruption_draw (Display *dpy, Window window, void *closure)
 {
@@ -419,14 +502,7 @@ eruption_draw (Display *dpy, Window window, void *closure)
            
   if( st->draw_i < 0 || st->draw_i++ >= st->cycles )
     {
-      /* compute random center */
-      unsigned short xcenter, ycenter;
-      xcenter = random() % st->iWinWidth;
-      ycenter = random() % st->iWinHeight;
-               
-      for (st->draw_i = 0; st->draw_i < st->nParticleCount; st->draw_i++)
-        init_particle(st, st->particles + st->draw_i, xcenter, ycenter);
-      st->draw_i = 0;
+      random_eruption (st);
     }
            
   Execute( st );
@@ -451,31 +527,33 @@ eruption_reshape (Display *dpy, Window window, void *closure,
 {
   struct state *st = (struct state *) closure;
   XWindowAttributes XWinAttribs;
-  int i;
 
-  for (i = 0; i < st->iWinHeight; ++i)
-    free (st->fire[i]);
+  DestroyImage (st);
+  st->fire = NULL;
 
-  st->iWinWidth = w;
-  st->iWinHeight = h;
-
-  free (st->fire);
-  st->fire = calloc( st->iWinHeight, sizeof(unsigned char*));
-  for (i = 0; i < st->iWinHeight; ++i)
-    st->fire[i] = calloc( st->iWinWidth, sizeof(unsigned char));
-
-  XDestroyImage( st->pImage );
   XGetWindowAttributes( st->dpy, st->window, &XWinAttribs );
-  st->pImage = XCreateImage( st->dpy, XWinAttribs.visual, XWinAttribs.depth, ZPixmap, 0, NULL,
-                                                         XWinAttribs.width, XWinAttribs.height, BitmapPad( st->dpy ), 0 );
-  (st->pImage)->data = calloc((st->pImage)->bytes_per_line, (st->pImage)->height);
-
+  XWinAttribs.width = w;
+  XWinAttribs.height = h;
+  CreateImage (st, &XWinAttribs);
   st->draw_i = -1;
 }
 
 static Bool
 eruption_event (Display *dpy, Window window, void *closure, XEvent *event)
 {
+  struct state *st = (struct state *) closure;
+
+  if (event->type == ButtonPress)
+    {
+      new_eruption (st, event->xbutton.x, event->xbutton.y);
+      return True;
+    }
+  else if (screenhack_event_helper (dpy, window, event))
+    {
+      random_eruption (st);
+      return True;
+    }
+
   return False;
 }
 
@@ -483,12 +561,8 @@ static void
 eruption_free (Display *dpy, Window window, void *closure)
 {
   struct state *st = (struct state *) closure;
-  int i;
-  XDestroyImage (st->pImage);
+  DestroyImage (st);
   free (st->aiColorVals);
-  for (i = 0; i < st->iWinHeight; ++i)
-    free (st->fire[i]);
-  free (st->fire);
   free (st->particles);
   XFreeGC (dpy, st->gc);
   free (st);
@@ -506,6 +580,8 @@ static const char *eruption_defaults [] = {
   "*cooloff: 2",
   "*gravity: 1",
   "*heat: 256",
+  ".lowrez: true",  /* Too slow on Retina screens otherwise */
+  "*useSHM: True",
   0
 };
 
@@ -517,6 +593,10 @@ static XrmOptionDescRec eruption_options [] = {
   { "-cooloff",  ".cooloff",  XrmoptionSepArg, 0 },
   { "-gravity",  ".gravity",  XrmoptionSepArg, 0 },
   { "-heat",  ".heat",  XrmoptionSepArg, 0 },
+#ifdef HAVE_XSHM_EXTENSION
+  { "-shm", ".useSHM", XrmoptionNoArg, "True" },
+  { "-no-shm",  ".useSHM", XrmoptionNoArg, "False" },
+#endif
   { 0, 0, 0, 0 }
 };
 
index 2aabb9d56641c74797782dea0ede4361c9af9644..c242083b473b3f5e5b7bc77f37fa76a57ec22968 100644 (file)
@@ -546,13 +546,22 @@ static const char *filmleader_defaults [] = {
 
 # endif
 
-# ifdef USE_IPHONE
+  /* Note: these font sizes aren't relative to screen pixels, but to the
+     712 x Y or X x 712 canvas that we draw in, which is then scaled to
+     the size of the screen by analogtv. */
 
+# ifdef USE_IPHONE
   "*numberFont:  Helvetica Bold 120",
   "*numberFont2: Helvetica 36",
   "*numberFont3: Helvetica 28",
 
-# else /* X11, Cocoa or Android */
+# elif defined(HAVE_COCOA)
+  /* Need to double these because ANALOGTV_DEFAULTS sets lowrez: true */
+  "*numberFont:  Helvetica Bold 240",
+  "*numberFont2: Helvetica 72",
+  "*numberFont3: Helvetica 56",
+
+# else /* X11 or Android */
 
   "*numberFont:  -*-helvetica-bold-r-*-*-*-1700-*-*-*-*-*-*",
   "*numberFont2: -*-helvetica-medium-r-*-*-*-500-*-*-*-*-*-*",
index 57ba1280715539dd664bd9dde9d0f5a42a9c3f42..12d9864753339aa002e7fb96a6ba944bea769787 100644 (file)
@@ -862,6 +862,7 @@ static const char *fireworkx_defaults [] =
        "*flash: True",
        "*shoot: False",
        "*verbose: False",
+        ".lowrez: true",  /* Too slow on Retina screens otherwise */
        0
 };
 
index 482bed3dae17f163c0d2128658eab58df1f3ae0a..7ddb223e43af1f506dd1e33a6bdc090e31b80b1f 100644 (file)
@@ -137,7 +137,8 @@ SRCS                = xscreensaver-gl-helper.c normals.c erase-gl.c fps-gl.c \
                  raverhoop.c hydrostat.c discoball.c cubetwist.c cubestack.c \
                  splodesic.c hexstrut.c vigilance.c seccam.c esper.c \
                  razzledazzle.c ships.c peepers.c crumbler.c quickhull.c \
-                 maze3d.c handsy.c handsy_model.c gravitywell.c deepstars.c
+                 maze3d.c handsy.c handsy_model.c gravitywell.c deepstars.c \
+                 gibson.c etruscanvenus.c
 
 OBJS           = xscreensaver-gl-helper.o normals.o erase-gl.o fps-gl.o \
                  atlantis.o b_draw.o b_lockglue.o b_sphere.o bubble3d.o \
@@ -184,7 +185,8 @@ OBJS                = xscreensaver-gl-helper.o normals.o erase-gl.o fps-gl.o \
                  raverhoop.o hydrostat.o discoball.o cubetwist.o cubestack.o \
                  splodesic.o hexstrut.o vigilance.o seccam.o esper.o \
                  razzledazzle.o ships.o peepers.o crumbler.o quickhull.o \
-                 maze3d.o handsy.o handsy_model.o gravitywell.o deepstars.o
+                 maze3d.o handsy.o handsy_model.o gravitywell.o deepstars.o \
+                 gibson.o etruscanvenus.o
 
 GL_EXES                = cage gears moebius pipes sproingies stairs superquadrics \
                  morph3d rubik atlantis lament bubble3d glplanet pulsar \
@@ -205,7 +207,7 @@ GL_EXES             = cage gears moebius pipes sproingies stairs superquadrics \
                  splitflap dymaxionmap unicrud energystream raverhoop \
                  hydrostat discoball cubetwist cubestack splodesic \
                  hexstrut vigilance esper razzledazzle peepers crumbler \
-                 maze3d handsy gravitywell deepstars
+                 maze3d handsy gravitywell deepstars gibson etruscanvenus
 GLE_EXES       = extrusion
 SUID_EXES      = sonar
 SETCAP_EXES    = sonar
@@ -273,7 +275,7 @@ GL_MEN              = atlantis.man boxed.man bubble3d.man cage.man circuit.man \
                  discoball.man cubetwist.man cubestack.man splodesic.man \
                  hexstrut.man vigilance.man esper.man razzledazzle.man \
                  peepers.man crumbler.man maze3d.man handsy.man \
-                 gravitywell.man deepstars.man
+                 gravitywell.man deepstars.man gibson.man etruscanvenus.man
 MEN            = @GL_MEN@
 RETIRED_MEN    = glforestfire.man
 EXTRAS         = README Makefile.in dxf2gl.pl vrml2gl.pl wfront2gl.pl \
@@ -791,6 +793,9 @@ projectiveplane:    projectiveplane.o       $(HACK_TRACK_OBJS)
 romanboy:      romanboy.o      $(HACK_TRACK_OBJS)
        $(CC_HACK) -o $@ $@.o   $(HACK_TRACK_OBJS) $(HACK_LIBS)
 
+etruscanvenus: etruscanvenus.o $(HACK_TRACK_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(HACK_TRACK_OBJS) $(HACK_LIBS)
+
 glmatrix:      glmatrix.o      $(PNG) $(HACK_OBJS)
        $(CC_HACK) -o $@ $@.o   $(PNG) $(HACK_OBJS) $(PNG_LIBS)
 
@@ -1033,6 +1038,9 @@ gravitywell:      gravitywell.o   $(HACK_TRACK_OBJS)
 deepstars:     deepstars.o     $(HACK_TRACK_OBJS)
        $(CC_HACK) -o $@ $@.o   $(HACK_TRACK_OBJS) $(HACK_LIBS)
 
+gibson:                gibson.o        $(PNG) $(HACK_TRACK_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(PNG) $(HACK_TRACK_OBJS) $(PNG_LIBS)
+
 ##############################################################################
 #
 # DO NOT DELETE: updated by make distdepend
@@ -1731,6 +1739,23 @@ esper.o: $(UTILS_SRC)/xshm.h
 esper.o: $(UTILS_SRC)/yarandom.h
 esper.o: $(HACK_SRC)/xlockmoreI.h
 esper.o: $(HACK_SRC)/xlockmore.h
+etruscanvenus.o: ../../config.h
+etruscanvenus.o: $(srcdir)/curlicue.h
+etruscanvenus.o: $(HACK_SRC)/fps.h
+etruscanvenus.o: $(srcdir)/gltrackball.h
+etruscanvenus.o: $(HACK_SRC)/recanim.h
+etruscanvenus.o: $(HACK_SRC)/screenhackI.h
+etruscanvenus.o: $(UTILS_SRC)/colors.h
+etruscanvenus.o: $(UTILS_SRC)/erase.h
+etruscanvenus.o: $(UTILS_SRC)/font-retry.h
+etruscanvenus.o: $(UTILS_SRC)/grabscreen.h
+etruscanvenus.o: $(UTILS_SRC)/hsv.h
+etruscanvenus.o: $(UTILS_SRC)/resources.h
+etruscanvenus.o: $(UTILS_SRC)/usleep.h
+etruscanvenus.o: $(UTILS_SRC)/visual.h
+etruscanvenus.o: $(UTILS_SRC)/yarandom.h
+etruscanvenus.o: $(HACK_SRC)/xlockmoreI.h
+etruscanvenus.o: $(HACK_SRC)/xlockmore.h
 extrusion-helix2.o: ../../config.h
 extrusion-helix2.o: $(srcdir)/extrusion.h
 extrusion-helix3.o: ../../config.h
@@ -1966,6 +1991,23 @@ gflux.o: $(UTILS_SRC)/visual.h
 gflux.o: $(UTILS_SRC)/yarandom.h
 gflux.o: $(HACK_SRC)/xlockmoreI.h
 gflux.o: $(HACK_SRC)/xlockmore.h
+gibson.o: ../../config.h
+gibson.o: $(HACK_SRC)/fps.h
+gibson.o: $(HACK_SRC)/recanim.h
+gibson.o: $(srcdir)/rotator.h
+gibson.o: $(HACK_SRC)/screenhackI.h
+gibson.o: $(srcdir)/texfont.h
+gibson.o: $(UTILS_SRC)/colors.h
+gibson.o: $(UTILS_SRC)/erase.h
+gibson.o: $(UTILS_SRC)/font-retry.h
+gibson.o: $(UTILS_SRC)/grabscreen.h
+gibson.o: $(UTILS_SRC)/hsv.h
+gibson.o: $(UTILS_SRC)/resources.h
+gibson.o: $(UTILS_SRC)/usleep.h
+gibson.o: $(UTILS_SRC)/visual.h
+gibson.o: $(UTILS_SRC)/yarandom.h
+gibson.o: $(HACK_SRC)/xlockmoreI.h
+gibson.o: $(HACK_SRC)/xlockmore.h
 glblur.o: ../../config.h
 glblur.o: $(HACK_SRC)/fps.h
 glblur.o: $(srcdir)/gltrackball.h
index b477e001e0aa84805037537912f2de0183404e00..f415f18fd8f806df0badc7003eadf1fe3a6f285c 100644 (file)
 
 #ifdef STANDALONE
 #define DEFAULTS       "*delay:                        30000   \n"     \
-                                       "*showFPS:                      False   \n" \
-                                       "*suppressRotationAnimation: True\n" \
+                       "*showFPS:                      False   \n" \
+                       "*suppressRotationAnimation: True\n" \
 
 # define release_deepstars 0
-# include "xlockmore.h"                                /* from the xscreensaver distribution */
+# include "xlockmore.h"                        /* from the xscreensaver distribution */
 #else  /* !STANDALONE */
-# include "xlock.h"                                    /* from the xlockmore distribution */
+# include "xlock.h"                    /* from the xlockmore distribution */
 #endif /* !STANDALONE */
 
 #ifdef USE_GL /* whole file */
diff --git a/hacks/glx/etruscanvenus.c b/hacks/glx/etruscanvenus.c
new file mode 100644 (file)
index 0000000..71af80a
--- /dev/null
@@ -0,0 +1,1825 @@
+/* etruscanvenus --- Shows a 3d immersion of a Klein bottle that
+   rotates in 3d or on which you can walk and that can deform smoothly
+   between the Etruscan Venus surface, the Roman surface, the Boy
+   surface surface, and the Ida surface. */
+
+#if 0
+static const char sccsid[] = "@(#)etruscanvenus.c  1.1 05/01/20 xlockmore";
+#endif
+
+/* Copyright (c) 2019-2020 Carsten Steger <carsten@mirsanmir.org>. */
+
+/*
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appear in all copies and that
+ * both that copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * This file is provided AS IS with no warranties of any kind.  The author
+ * shall have no liability with respect to the infringement of copyrights,
+ * trade secrets or any patents by this file or any part thereof.  In no
+ * event will the author be liable for any lost revenue or profits or
+ * other special, indirect and consequential damages.
+ *
+ * REVISION HISTORY:
+ * C. Steger - 05/01/20: Initial version
+ */
+
+/*
+ * This program shows a 3d immersion of a Klein bottle that smoothly
+ * deforms between the Etruscan Venus surface, the Roman surface, the
+ * Boy surface, and the Ida surface.  You can walk on the Klein bottle
+ * or turn it in 3d.  Topologically, all surfaces are Klein bottles,
+ * even the Roman and Boy surfaces, which are doubly covered and
+ * therefore appear to be an immersed real projective plane.  The
+ * smooth deformation between these surfaces was constructed by George
+ * K. Francis.
+ *
+ * The Klein bottle is a non-orientable surface.  To make this
+ * apparent, the two-sided color mode can be used.  Alternatively,
+ * orientation markers (curling arrows) can be drawn as a texture map
+ * on the surface of the Klein bottle.  While walking on the Klein
+ * bottle, you will notice that the orientation of the curling arrows
+ * changes (which it must because the Klein bottle is non-orientable).
+ * Since all the surfaces except the Ida surface have points where the
+ * surface normal is not well defined for some points, walking is only
+ * performed on the Ida surface.
+ *
+ * As mentioned above, the Roman and Boy surfaces are doubly covered
+ * and therefore appear to be an immersed real projective plane.
+ * Since some of the parameter names are based on this interpretation
+ * of the surface, the geometry of the real projective plane will be
+ * briefly disussed.  The real projective plane is a model for the
+ * projective geometry in 2d space.  One point can be singled out as
+ * the origin.  A line can be singled out as the line at infinity,
+ * i.e., a line that lies at an infinite distance to the origin.  The
+ * line at infinity is topologically a circle.  Points on the line at
+ * infinity are also used to model directions in projective geometry.
+ * Direction and distance bands refer to this interpretation of the
+ * surface.  If direction bands are used, the bands extend from the
+ * origin of the projective plane in different directions to the line
+ * at infinity and back to the origin.  If distance bands are used,
+ * the bands lie at constant distances to the origin.  The same
+ * interpretation is used for distance and direction colors.  Although
+ * there is no conceptually equivalent geometric interpretation for
+ * the two Klein bottle surfaces (the Etruscan Venus and Ida
+ * surfaces), the smooth deformation between the surfaces results in a
+ * natural extension of these concepts to the Klein bottle surfaces.
+ *
+ * The immersed surfaces can be projected to the screen either
+ * perspectively or orthographically.  When using the walking mode,
+ * perspective projection to the screen will be used.
+ *
+ * There are three display modes for the Klein bottle: mesh
+ * (wireframe), solid, or transparent.  Furthermore, the appearance of
+ * the surface can be as a solid object or as a set of see-through
+ * bands.  The bands can be distance bands or direction bands, as
+ * explained above.
+ *
+ * The colors with with the Klein bottle is drawn can be set to
+ * one-sided, two-sided, distance, or direction.  In one-sided mode,
+ * the surface is drawn with the same color on both sides of the
+ * underlying triangles.  In two-sided mode, the surface is drawn with
+ * red on one side of the underlying triangles and green on the other
+ * side.  Since the surface actually only has one side, the color
+ * jumps from red to green along a line on the surface.  This mode
+ * enables you to see that the surface is non-orientable.  In distance
+ * mode, the surface is displayed with fully saturated colors that
+ * depend on the distance of the points on the projective plane to the
+ * origin, as described above.  If the surface is displayed as
+ * distance bands, each band will be displayed with a different color.
+ * In direction mode, the surface is displayed with fully saturated
+ * colors that depend on the angle of the points on the projective
+ * plane with respect to the origin (see above for an explanation).
+ * If the surface is displayed as direction bands, each band will be
+ * displayed with a different color.  The colors used to color the
+ * surface can either be static or can be changed dynamically.
+ *
+ * The rotation speed for each of the three coordinate axes around
+ * which the Klein bottle rotates can be chosen.
+ *
+ * Furthermore, in the walking mode the walking direction in the 2d
+ * base square of the surface and the walking speed can be chosen.
+ * The walking direction is measured as an angle in degrees in the 2d
+ * square that forms the coordinate system of the surface.  A value of
+ * 0 or 180 means that the walk is along a circle at a randomly chosen
+ * distance from the origin (parallel to a distance band).  A value of
+ * 90 or 270 means that the walk is directly along a direction band.
+ * Any other value results in a curved path along the surface.  As
+ * noted above, walking is performed only on the Ida surface.
+ *
+ * By default, the immersion of the Klein bottle smoothly deforms
+ * between the Etruscan Venus surface, the Roman surface, the Boy
+ * surface, and the Ida surface.  It is possible to choose the speed
+ * of the deformation.  Furthermore, it is possible to switch the
+ * deformation off.  It is also possible to determine the initial
+ * deformation of the immersion.  This is mostly useful if the
+ * deformation is switched off, in which case it will determine the
+ * appearance of the surface.  A value of 0 corresponds to the
+ * Etruscan Venus surface, a value of 1000 to the Roman surface, a
+ * value of 2000 to the Boy surface, and a value of 3000 to the Ida
+ * surface.
+ *
+ * This program is inspired by George K. Francis's book "A Topological
+ * Picturebook", Springer, 1987, by George K. Francis's paper "The
+ * Etruscan Venus" in P. Concus, R. Finn, and D. A. Hoffman:
+ * "Geometric Analysis and Computer Graphics", Springer, 1991, and by
+ * a video entitled "The Etruscan Venus" by Donna J. Cox, George
+ * K. Francis, and Raymond L. Idaszak, presented at SIGGRAPH 1989.
+ */
+
+#include "curlicue.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+#define DISP_WIREFRAME             0
+#define DISP_SURFACE               1
+#define DISP_TRANSPARENT           2
+#define NUM_DISPLAY_MODES          3
+
+#define APPEARANCE_SOLID           0
+#define APPEARANCE_DISTANCE_BANDS  1
+#define APPEARANCE_DIRECTION_BANDS 2
+#define NUM_APPEARANCES            3
+
+#define COLORS_ONESIDED            0
+#define COLORS_TWOSIDED            1
+#define COLORS_DISTANCE            2
+#define COLORS_DIRECTION           3
+#define NUM_COLORS                 4
+
+#define VIEW_WALK                  0
+#define VIEW_TURN                  1
+#define NUM_VIEW_MODES             2
+
+#define DISP_PERSPECTIVE           0
+#define DISP_ORTHOGRAPHIC          1
+#define NUM_DISP_MODES             2
+
+#define DEF_DISPLAY_MODE           "random"
+#define DEF_APPEARANCE             "random"
+#define DEF_COLORS                 "random"
+#define DEF_VIEW_MODE              "random"
+#define DEF_MARKS                  "False"
+#define DEF_CHANGE_COLORS          "True"
+#define DEF_DEFORM                 "True"
+#define DEF_PROJECTION             "random"
+#define DEF_SPEEDX                 "1.1"
+#define DEF_SPEEDY                 "1.3"
+#define DEF_SPEEDZ                 "1.5"
+#define DEF_WALK_DIRECTION         "83.0"
+#define DEF_WALK_SPEED             "20.0"
+#define DEF_DEFORM_SPEED           "10.0"
+#define DEF_INIT_DEFORM            "0.0"
+
+#ifdef STANDALONE
+# define DEFAULTS           "*delay:      10000 \n" \
+                            "*showFPS:    False \n" \
+
+# define release_etruscanvenus 0
+# include "xlockmore.h"         /* from the xscreensaver distribution */
+#else  /* !STANDALONE */
+# include "xlock.h"             /* from the xlockmore distribution */
+#endif /* !STANDALONE */
+
+#ifdef USE_GL
+
+#ifndef HAVE_JWXYZ
+# include <X11/keysym.h>
+#endif
+
+#include "gltrackball.h"
+
+#include <float.h>
+
+
+#ifdef USE_MODULES
+ModStruct etruscanvenus_description =
+{"etruscanvenus", "init_etruscanvenus", "draw_etruscanvenus",
+ NULL, "draw_etruscanvenus", "change_etruscanvenus",
+ "free_etruscanvenus", &etruscanvenus_opts, 25000, 1, 1, 1, 1.0, 4, "",
+ "Rotate a 3d immersion of a Klein bottle in 3d or walk on it",
+ 0, NULL};
+
+#endif
+
+
+static char *mode;
+static char *appear;
+static char *color_mode;
+static char *view_mode;
+static Bool marks;
+static Bool deform;
+static Bool change_colors;
+static char *proj;
+static float speed_x;
+static float speed_y;
+static float speed_z;
+static float walk_direction;
+static float walk_speed;
+static float deform_speed;
+static float init_deform;
+
+
+static XrmOptionDescRec opts[] =
+{
+  {"-mode",                ".displayMode",   XrmoptionSepArg, 0 },
+  {"-wireframe",           ".displayMode",   XrmoptionNoArg,  "wireframe" },
+  {"-surface",             ".displayMode",   XrmoptionNoArg,  "surface" },
+  {"-transparent",         ".displayMode",   XrmoptionNoArg,  "transparent" },
+  {"-appearance",          ".appearance",    XrmoptionSepArg, 0 },
+  {"-solid",               ".appearance",    XrmoptionNoArg,  "solid" },
+  {"-distance-bands",      ".appearance",    XrmoptionNoArg,  "distance-bands" },
+  {"-direction-bands",     ".appearance",    XrmoptionNoArg,  "direction-bands" },
+  {"-colors",              ".colors",        XrmoptionSepArg, 0 },
+  {"-onesided-colors",     ".colors",        XrmoptionNoArg,  "one-sided" },
+  {"-twosided-colors",     ".colors",        XrmoptionNoArg,  "two-sided" },
+  {"-distance-colors",     ".colors",        XrmoptionNoArg,  "distance" },
+  {"-direction-colors",    ".colors",        XrmoptionNoArg,  "direction" },
+  {"-change-colors",       ".changeColors",  XrmoptionNoArg,  "on"},
+  {"+change-colors",       ".changeColors",  XrmoptionNoArg,  "off"},
+  {"-view-mode",           ".viewMode",      XrmoptionSepArg, 0 },
+  {"-walk",                ".viewMode",      XrmoptionNoArg,  "walk" },
+  {"-turn",                ".viewMode",      XrmoptionNoArg,  "turn" },
+  {"-deform",              ".deform",        XrmoptionNoArg,  "on"},
+  {"+deform",              ".deform",        XrmoptionNoArg,  "off"},
+  {"-orientation-marks",   ".marks",         XrmoptionNoArg,  "on"},
+  {"+orientation-marks",   ".marks",         XrmoptionNoArg,  "off"},
+  {"-projection",          ".projection",    XrmoptionSepArg, 0 },
+  {"-perspective",         ".projection",    XrmoptionNoArg,  "perspective" },
+  {"-orthographic",        ".projection",    XrmoptionNoArg,  "orthographic" },
+  {"-speed-x",             ".speedx",        XrmoptionSepArg, 0 },
+  {"-speed-y",             ".speedy",        XrmoptionSepArg, 0 },
+  {"-speed-z",             ".speedz",        XrmoptionSepArg, 0 },
+  {"-walk-direction",      ".walkDirection", XrmoptionSepArg, 0 },
+  {"-walk-speed",          ".walkSpeed",     XrmoptionSepArg, 0 },
+  {"-deformation-speed",   ".deformSpeed",   XrmoptionSepArg, 0 },
+  {"-initial-deformation", ".initDeform",    XrmoptionSepArg, 0 },
+  {"-etruscan-venus",      ".initDeform",    XrmoptionNoArg,  "0.0" },
+  {"-roman",               ".initDeform",    XrmoptionNoArg,  "1000.0" },
+  {"-boy",                 ".initDeform",    XrmoptionNoArg,  "2000.0" },
+  {"-ida",                 ".initDeform",    XrmoptionNoArg,  "3000.0" },
+};
+
+static argtype vars[] =
+{
+  { &mode,           "displayMode",   "DisplayMode",   DEF_DISPLAY_MODE,   t_String },
+  { &appear,         "appearance",    "Appearance",    DEF_APPEARANCE,     t_String },
+  { &color_mode,     "colors",        "Colors",        DEF_COLORS,         t_String },
+  { &change_colors,  "changeColors",  "ChangeColors",  DEF_CHANGE_COLORS,  t_Bool },
+  { &view_mode,      "viewMode",      "ViewMode",      DEF_VIEW_MODE,      t_String },
+  { &deform,         "deform",        "Deform",        DEF_DEFORM,         t_Bool },
+  { &marks,          "marks",         "Marks",         DEF_MARKS,          t_Bool },
+  { &proj,           "projection",    "Projection",    DEF_PROJECTION,     t_String },
+  { &speed_x,        "speedx",        "Speedx",        DEF_SPEEDX,         t_Float},
+  { &speed_y,        "speedy",        "Speedy",        DEF_SPEEDY,         t_Float},
+  { &speed_z,        "speedz",        "Speedz",        DEF_SPEEDZ,         t_Float},
+  { &walk_direction, "walkDirection", "WalkDirection", DEF_WALK_DIRECTION, t_Float},
+  { &walk_speed,     "walkSpeed",     "WalkSpeed",     DEF_WALK_SPEED,     t_Float},
+  { &deform_speed,   "deformSpeed",   "DeformSpeed",   DEF_DEFORM_SPEED,   t_Float},
+  { &init_deform,    "initDeform",    "InitDeform",    DEF_INIT_DEFORM,    t_Float },
+};
+
+ENTRYPOINT ModeSpecOpt etruscanvenus_opts =
+{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, NULL};
+
+
+/* Offset by which we walk above the surface */
+#define DELTAY  0.01
+
+/* Color change speeds */
+#define DRHO    0.7
+#define DSIGMA  1.1
+#define DTAU    1.7
+
+/* Number of subdivisions of the surface */
+#define NUMU 192
+#define NUMV 128
+
+/* Number of subdivisions per band */
+#define NUMBDIR  8
+#define NUMBDIST 4
+
+/* Constants that are used to calculate the approximate center of the
+   surface in the z direction. */
+#define Z1 (0.8141179221194051)
+#define Z2 (0.1359276851926206)
+#define Z3 (1.1581097545867050)
+#define Z4 (0.7186549129158579)
+#define Z5 (2.5393401559381240)
+
+/* Constants that are used to calculate the approximate radius of the
+   surface. */
+#define R1 (1.308007044714129)
+#define R2 (4.005205981405042)
+#define R3 (-2.893994600199527)
+#define R4 (-1.266709537162707)
+
+
+typedef struct {
+  GLint WindH, WindW;
+  GLXContext *glx_context;
+  /* Options */
+  int display_mode;
+  int appearance;
+  int colors;
+  Bool change_colors;
+  int view;
+  int projection;
+  Bool marks;
+  /* 3D rotation angles */
+  float alpha, beta, delta;
+  /* Color rotation angles */
+  float rho, sigma, tau;
+  /* Movement parameters */
+  float umove, vmove, dumove, dvmove;
+  int side;
+  /* Deformation parameters */
+  float dd;
+  int defdir;
+  /* The viewing offset in 3d */
+  float offset3d[3];
+  /* The 3d coordinates of the surface and their derivatives */
+  float *ev;
+  float *evn;
+  /* The precomputed colors of the surface */
+  float *col;
+  /* The precomputed texture coordinates of the surface */
+  float *tex;
+  /* The "curlicue" texture */
+  GLuint tex_name;
+  /* Aspect ratio of the current window */
+  float aspect;
+  /* Trackball states */
+  trackball_state *trackball;
+  Bool button_pressed;
+  /* A random factor to modify the rotation speeds */
+  float speed_scale;
+} etruscanvenusstruct;
+
+static etruscanvenusstruct *etruscanvenus = (etruscanvenusstruct *) NULL;
+
+
+/* Add a rotation around the x-axis to the matrix m. */
+static void rotatex(float m[3][3], float phi)
+{
+  float c, s, u, v;
+  int i;
+
+  phi *= M_PI/180.0;
+  c = cos(phi);
+  s = sin(phi);
+  for (i=0; i<3; i++)
+  {
+    u = m[i][1];
+    v = m[i][2];
+    m[i][1] = c*u+s*v;
+    m[i][2] = -s*u+c*v;
+  }
+}
+
+
+/* Add a rotation around the y-axis to the matrix m. */
+static void rotatey(float m[3][3], float phi)
+{
+  float c, s, u, v;
+  int i;
+
+  phi *= M_PI/180.0;
+  c = cos(phi);
+  s = sin(phi);
+  for (i=0; i<3; i++)
+  {
+    u = m[i][0];
+    v = m[i][2];
+    m[i][0] = c*u-s*v;
+    m[i][2] = s*u+c*v;
+  }
+}
+
+
+/* Add a rotation around the z-axis to the matrix m. */
+static void rotatez(float m[3][3], float phi)
+{
+  float c, s, u, v;
+  int i;
+
+  phi *= M_PI/180.0;
+  c = cos(phi);
+  s = sin(phi);
+  for (i=0; i<3; i++)
+  {
+    u = m[i][0];
+    v = m[i][1];
+    m[i][0] = c*u+s*v;
+    m[i][1] = -s*u+c*v;
+  }
+}
+
+
+/* Compute the rotation matrix m from the rotation angles. */
+static void rotateall(float al, float be, float de, float m[3][3])
+{
+  int i, j;
+
+  for (i=0; i<3; i++)
+    for (j=0; j<3; j++)
+      m[i][j] = (i==j);
+  rotatex(m,al);
+  rotatey(m,be);
+  rotatez(m,de);
+}
+
+
+/* Multiply two rotation matrices: o=m*n. */
+static void mult_rotmat(float m[3][3], float n[3][3], float o[3][3])
+{
+  int i, j, k;
+
+  for (i=0; i<3; i++)
+  {
+    for (j=0; j<3; j++)
+    {
+      o[i][j] = 0.0;
+      for (k=0; k<3; k++)
+        o[i][j] += m[i][k]*n[k][j];
+    }
+  }
+}
+
+
+/* Compute a 3D rotation matrix from a unit quaternion. */
+static void quat_to_rotmat(float p[4], float m[3][3])
+{
+  double al, be, de;
+  double r00, r01, r02, r12, r22;
+
+  r00 = 1.0-2.0*(p[1]*p[1]+p[2]*p[2]);
+  r01 = 2.0*(p[0]*p[1]+p[2]*p[3]);
+  r02 = 2.0*(p[2]*p[0]-p[1]*p[3]);
+  r12 = 2.0*(p[1]*p[2]+p[0]*p[3]);
+  r22 = 1.0-2.0*(p[1]*p[1]+p[0]*p[0]);
+
+  al = atan2(-r12,r22)*180.0/M_PI;
+  be = atan2(r02,sqrt(r00*r00+r01*r01))*180.0/M_PI;
+  de = atan2(-r01,r00)*180.0/M_PI;
+
+  rotateall(al,be,de,m);
+}
+
+
+/* Compute a fully saturated and bright color based on an angle and,
+   optionally, a color rotation matrix. */
+static void color(etruscanvenusstruct *ev, double angle, float mat[3][3],
+                  float col[4])
+{
+  int s;
+  double t, ca, sa;
+  float m;
+
+  if (!ev->change_colors)
+  {
+    if (ev->colors == COLORS_ONESIDED || ev->colors == COLORS_TWOSIDED)
+      return;
+
+    if (angle >= 0.0)
+      angle = fmod(angle,2.0*M_PI);
+    else
+      angle = fmod(angle,-2.0*M_PI);
+    s = floor(angle/(M_PI/3));
+    t = angle/(M_PI/3)-s;
+    if (s >= 6)
+      s = 0;
+    switch (s)
+    {
+      case 0:
+        col[0] = 1.0;
+        col[1] = t;
+        col[2] = 0.0;
+        break;
+      case 1:
+        col[0] = 1.0-t;
+        col[1] = 1.0;
+        col[2] = 0.0;
+        break;
+      case 2:
+        col[0] = 0.0;
+        col[1] = 1.0;
+        col[2] = t;
+        break;
+      case 3:
+        col[0] = 0.0;
+        col[1] = 1.0-t;
+        col[2] = 1.0;
+        break;
+      case 4:
+        col[0] = t;
+        col[1] = 0.0;
+        col[2] = 1.0;
+        break;
+      case 5:
+        col[0] = 1.0;
+        col[1] = 0.0;
+        col[2] = 1.0-t;
+        break;
+    }
+  }
+  else /* ev->change_colors */
+  {
+    if (ev->colors == COLORS_ONESIDED || ev->colors == COLORS_TWOSIDED)
+    {
+      col[0] = mat[0][2];
+      col[1] = mat[1][2];
+      col[2] = mat[2][2];
+    }
+    else
+    {
+      ca = cos(angle);
+      sa = sin(angle);
+      col[0] = ca*mat[0][0]+sa*mat[0][1];
+      col[1] = ca*mat[1][0]+sa*mat[1][1];
+      col[2] = ca*mat[2][0]+sa*mat[2][1];
+    }
+    m = 0.5f/fmaxf(fmaxf(fabsf(col[0]),fabsf(col[1])),fabsf(col[2]));
+    col[0] = m*col[0]+0.5f;
+    col[1] = m*col[1]+0.5f;
+    col[2] = m*col[2]+0.5f;
+  }
+  if (ev->display_mode == DISP_TRANSPARENT)
+    col[3] = 0.7;
+  else
+    col[3] = 1.0;
+}
+
+
+/* Set up the surface colors and texture. */
+static void setup_etruscan_venus_color_texture(ModeInfo *mi, double umin,
+                                               double umax, double vmin,
+                                               double vmax, int numu, int numv)
+{
+  int i, j, k;
+  double u, v, ur, vr, vc;
+  etruscanvenusstruct *ev = &etruscanvenus[MI_SCREEN(mi)];
+
+  ur = umax-umin;
+  vr = vmax-vmin;
+  for (i=0; i<=numv; i++)
+  {
+    for (j=0; j<=numu; j++)
+    {
+      k = i*(numu+1)+j;
+      u = ur*j/numu+umin;
+      if (ev->appearance == APPEARANCE_DISTANCE_BANDS)
+        v = -vr*i/numv+vmin;
+      else
+        v = vr*i/numv+vmin;
+      if (!ev->change_colors)
+      {
+        if (ev->colors == COLORS_DISTANCE)
+        {
+          if (ev->appearance == APPEARANCE_DISTANCE_BANDS)
+            vc = -4.0*v;
+          else
+            vc = 4.0*v;
+          if (vc >= 4.0*M_PI)
+            vc -= 4.0*M_PI;
+          if (vc >= 2.0*M_PI)
+            vc = 4.0*M_PI-vc;
+          color(ev,vc,NULL,&ev->col[4*k]);
+        }
+        else /* ev->colors == COLORS_DIRECTION */
+        {
+          color(ev,u,NULL,&ev->col[4*k]);
+        }
+      }
+      ev->tex[2*k+0] = 48*u/(2.0*M_PI);
+      if (ev->appearance == APPEARANCE_DISTANCE_BANDS)
+        ev->tex[2*k+1] = 64*v/(2.0*M_PI)-0.5;
+      else
+        ev->tex[2*k+1] = 64*v/(2.0*M_PI);
+    }
+  }
+}
+
+
+/* Draw a 3d immersion of the surface. */
+static int etruscan_venus(ModeInfo *mi, double umin, double umax,
+                          double vmin, double vmax, int numu, int numv)
+{
+  int polys = 0;
+  static const GLfloat mat_diff_red[]           = { 1.0, 0.0, 0.0, 1.0 };
+  static const GLfloat mat_diff_green[]         = { 0.0, 1.0, 0.0, 1.0 };
+  static const GLfloat mat_diff_oneside[]       = { 0.9, 0.4, 0.3, 1.0 };
+  static const GLfloat mat_diff_trans_red[]     = { 1.0, 0.0, 0.0, 0.7 };
+  static const GLfloat mat_diff_trans_green[]   = { 0.0, 1.0, 0.0, 0.7 };
+  static const GLfloat mat_diff_trans_oneside[] = { 0.9, 0.4, 0.3, 0.7 };
+  float mat_diff_dyn[4], mat_diff_dyn_compl[4];
+  float p[3], pu[3], pv[3], pm[3], n[3], b[3], mat[3][3], matc[3][3];
+  int i, j, k, l, m, o;
+  double u, v, ur, vr, oz, vc;
+  double xx[3], xxu[3], xxv[3];
+  double r, s, t;
+  double dd, bb, ll, db, dl, radius;
+  double cv, sv, c2v, s2v, cu, su, c2u, s2u, c3u, s3u;
+  double bosqrt2, b2osqrt2, b3osqrt2, nom, den, nomv, denu, denv, den2;
+  double f, fx, fy, fz, x, y, z;
+  double fu, fv, fxu, fxv, fyu, fyv, fzv, xu, xv, yu, yv, zu, zv;
+  float qu[4], r1[3][3], r2[3][3];
+  etruscanvenusstruct *ev = &etruscanvenus[MI_SCREEN(mi)];
+
+  dd = ev->dd;
+  if (dd < 1.0)
+  {
+    bb = 0.0;
+    ll = dd;
+  }
+  else if (dd < 2.0)
+  {
+    bb = dd-1.0;
+    ll = 1.0;
+  }
+  else if (dd < 3.0)
+  {
+    bb = 1.0;
+    ll = 3.0-dd;
+  }
+  else /* dd < 4.0 */
+  {
+    bb = 4.0-dd;
+    ll = 0.0;
+  }
+  db = ((6.0*bb-15.0)*bb+10.0)*bb*bb*bb;
+  dl = ((6.0*ll-15.0)*ll+10.0)*ll*ll*ll;
+  /* Calculate the approximate center of the surface in the z direction. */
+  oz = (Z1*(sin(0.5*M_PI*pow(dl,Z3))+Z2*sin(1.5*M_PI*pow(dl,Z3)))*
+        exp(Z4*pow(db,Z5)));
+  /* Calculate the approximate radius of the surface. */
+  r = R1+(db-0.5)*(dl-0.5)+R2*exp(R3*(1.0-db))*exp(R4*dl);
+  radius = 0.8/r;
+
+  if (ev->change_colors)
+    rotateall(ev->rho,ev->sigma,ev->tau,matc);
+
+  if (ev->view == VIEW_WALK)
+  {
+    u = ev->umove;
+    v = ev->vmove;
+    u = 0.5*u;
+    bosqrt2 = db/M_SQRT2;
+    b2osqrt2 = 2.0*bosqrt2;
+    b3osqrt2 = 3.0*bosqrt2;
+    cu = cos(u);
+    su = sin(u);
+    c2u = cos(2.0*u);
+    s2u = sin(2.0*u);
+    c3u = cos(3.0*u);
+    s3u = sin(3.0*u);
+    cv = cos(v);
+    sv = sin(v);
+    c2v = cos(2.0*v);
+    s2v = sin(2.0*v);
+    nom = (1.0-dl+dl*cv);
+    den = (1.0-bosqrt2*s3u*s2v);
+    f = nom/den;
+    fx = c2u*cv+cu*sv;
+    fy = s2u*cv-su*sv;
+    fz = M_SQRT2*cv;
+    x = f*fx;
+    y = f*fy;
+    z = f*fz;
+    nomv = -dl*sv;
+    denu = -b3osqrt2*c3u*s2v;
+    denv = -b2osqrt2*s3u*c2v;
+    den2 = 1.0/(den*den);
+    fu = -nom*denu*den2;
+    fv = (den*nomv-nom*denv)*den2;
+    fxu = -su*sv-2.0*s2u*cv;
+    fxv = cu*cv-c2u*sv;
+    fyu = 2.0*c2u*cv-cu*sv;
+    fyv = -s2u*sv-su*cv;
+    fzv = -M_SQRT2*sv;
+    xu = fu*fx+f*fxu;
+    xv = fv*fx+f*fxv;
+    yu = fu*fy+f*fyu;
+    yv = fv*fy+f*fyv;
+    zu = fu*fz;
+    zv = fv*fz+f*fzv;
+    xx[0] = x;
+    xx[1] = y;
+    xx[2] = z-oz;
+    n[0] = yu*zv-zu*yv;
+    n[1] = zu*xv-xu*zv;
+    n[2] = xu*yv-yu*xv;
+    t = n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
+    /* Avoid degenerate tangential plane basis vectors as much as
+       possible. */
+    if (t < FLT_EPSILON)
+    {
+      u += 0.01;
+      v += 0.01;
+      cu = cos(u);
+      su = sin(u);
+      c2u = cos(2.0*u);
+      s2u = sin(2.0*u);
+      c3u = cos(3.0*u);
+      s3u = sin(3.0*u);
+      cv = cos(v);
+      sv = sin(v);
+      c2v = cos(2.0*v);
+      s2v = sin(2.0*v);
+      nom = (1.0-dl+dl*cv);
+      den = (1.0-bosqrt2*s3u*s2v);
+      f = nom/den;
+      fx = c2u*cv+cu*sv;
+      fy = s2u*cv-su*sv;
+      fz = M_SQRT2*cv;
+      nomv = -dl*sv;
+      denu = -b3osqrt2*c3u*s2v;
+      denv = -b2osqrt2*s3u*c2v;
+      den2 = 1.0/(den*den);
+      fu = -nom*denu*den2;
+      fv = (den*nomv-nom*denv)*den2;
+      fxu = -su*sv-2.0*s2u*cv;
+      fxv = cu*cv-c2u*sv;
+      fyu = 2.0*c2u*cv-cu*sv;
+      fyv = -s2u*sv-su*cv;
+      fzv = -M_SQRT2*sv;
+      xu = fu*fx+f*fxu;
+      xv = fv*fx+f*fxv;
+      yu = fu*fy+f*fyu;
+      yv = fv*fy+f*fyv;
+      zu = fu*fz;
+      zv = fv*fz+f*fzv;
+    }
+    xxu[0] = xu;
+    xxu[1] = yu;
+    xxu[2] = zu;
+    xxv[0] = xv;
+    xxv[1] = yv;
+    xxv[2] = zv;
+    for (l=0; l<3; l++)
+    {
+      p[l] = xx[l]*radius;
+      pu[l] = xxu[l]*radius;
+      pv[l] = xxv[l]*radius;
+    }
+    n[0] = pu[1]*pv[2]-pu[2]*pv[1];
+    n[1] = pu[2]*pv[0]-pu[0]*pv[2];
+    n[2] = pu[0]*pv[1]-pu[1]*pv[0];
+    t = 1.0/(ev->side*4.0*sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]));
+    n[0] *= t;
+    n[1] *= t;
+    n[2] *= t;
+    pm[0] = 0.5*pu[0]*ev->dumove+pv[0]*ev->dvmove;
+    pm[1] = 0.5*pu[1]*ev->dumove+pv[1]*ev->dvmove;
+    pm[2] = 0.5*pu[2]*ev->dumove+pv[2]*ev->dvmove;
+    t = 1.0/(4.0*sqrt(pm[0]*pm[0]+pm[1]*pm[1]+pm[2]*pm[2]));
+    pm[0] *= t;
+    pm[1] *= t;
+    pm[2] *= t;
+    b[0] = n[1]*pm[2]-n[2]*pm[1];
+    b[1] = n[2]*pm[0]-n[0]*pm[2];
+    b[2] = n[0]*pm[1]-n[1]*pm[0];
+    t = 1.0/(4.0*sqrt(b[0]*b[0]+b[1]*b[1]+b[2]*b[2]));
+    b[0] *= t;
+    b[1] *= t;
+    b[2] *= t;
+
+    /* Compute alpha, beta, gamma from the three basis vectors.
+           |  -b[0]  -b[1]  -b[2] |
+       m = |   n[0]   n[1]   n[2] |
+           | -pm[0] -pm[1] -pm[2] |
+    */
+    ev->alpha = atan2(-n[2],-pm[2])*180/M_PI;
+    ev->beta = atan2(-b[2],sqrt(b[0]*b[0]+b[1]*b[1]))*180/M_PI;
+    ev->delta = atan2(b[1],-b[0])*180/M_PI;
+
+    /* Compute the rotation that rotates the surface in 3D. */
+    rotateall(ev->alpha,ev->beta,ev->delta,mat);
+
+    u = ev->umove;
+    v = ev->vmove;
+    u = 0.5*u;
+    bosqrt2 = db/M_SQRT2;
+    b2osqrt2 = 2.0*bosqrt2;
+    b3osqrt2 = 3.0*bosqrt2;
+    cu = cos(u);
+    su = sin(u);
+    c2u = cos(2.0*u);
+    s2u = sin(2.0*u);
+    s3u = sin(3.0*u);
+    cv = cos(v);
+    sv = sin(v);
+    s2v = sin(2.0*v);
+    nom = (1.0-dl+dl*cv);
+    den = (1.0-bosqrt2*s3u*s2v);
+    f = nom/den;
+    fx = c2u*cv+cu*sv;
+    fy = s2u*cv-su*sv;
+    fz = M_SQRT2*cv;
+    x = f*fx;
+    y = f*fy;
+    z = f*fz;
+    xx[0] = x;
+    xx[1] = y;
+    xx[2] = z-oz;
+    for (l=0; l<3; l++)
+    {
+      r = 0.0;
+      for (m=0; m<3; m++)
+        r += mat[l][m]*xx[m];
+      p[l] = r*radius;
+    }
+
+    ev->offset3d[0] = -p[0];
+    ev->offset3d[1] = -p[1]-DELTAY;
+    ev->offset3d[2] = -p[2];
+  }
+  else
+  {
+    /* Compute the rotation that rotates the surface in 3D, including the
+       trackball rotations. */
+    rotateall(ev->alpha,ev->beta,ev->delta,r1);
+
+    gltrackball_get_quaternion(ev->trackball,qu);
+    quat_to_rotmat(qu,r2);
+
+    mult_rotmat(r2,r1,mat);
+  }
+
+  if (!ev->change_colors)
+  {
+    if (ev->colors == COLORS_ONESIDED)
+    {
+      glColor3fv(mat_diff_oneside);
+      if (ev->display_mode == DISP_TRANSPARENT)
+      {
+        glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,
+                     mat_diff_trans_oneside);
+      }
+      else
+      {
+        glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,
+                     mat_diff_oneside);
+      }
+    }
+    else if (ev->colors == COLORS_TWOSIDED)
+    {
+      glColor3fv(mat_diff_red);
+      if (ev->display_mode == DISP_TRANSPARENT)
+      {
+        glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_red);
+        glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_green);
+      }
+      else
+      {
+        glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_red);
+        glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_green);
+      }
+    }
+  }
+  else /* ev->change_colors */
+  {
+    color(ev,0.0,matc,mat_diff_dyn);
+    if (ev->colors == COLORS_ONESIDED)
+    {
+      glColor3fv(mat_diff_dyn);
+      glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn);
+    }
+    else if (ev->colors == COLORS_TWOSIDED)
+    {
+      mat_diff_dyn_compl[0] = 1.0f-mat_diff_dyn[0];
+      mat_diff_dyn_compl[1] = 1.0f-mat_diff_dyn[1];
+      mat_diff_dyn_compl[2] = 1.0f-mat_diff_dyn[2];
+      mat_diff_dyn_compl[3] = mat_diff_dyn[3];
+      glColor3fv(mat_diff_dyn);
+      glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn);
+      glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn_compl);
+    }
+  }
+  glBindTexture(GL_TEXTURE_2D,ev->tex_name);
+
+  ur = umax-umin;
+  vr = vmax-vmin;
+
+  /* Set up the surface coordinates and normals. */
+  if (ev->appearance == APPEARANCE_DISTANCE_BANDS)
+  {
+    for (i=0; i<=numv; i++)
+    {
+      if ((i & (NUMBDIST-1)) >= NUMBDIST/4+1 &&
+          (i & (NUMBDIST-1)) < 3*NUMBDIST/4)
+        continue;
+      for (j=0; j<=numu; j++)
+      {
+        o = i*(numu+1)+j;
+        u = ur*j/numu+umin;
+        v = -vr*i/numv+vmin;
+        if (ev->change_colors)
+        {
+          /* Compute the colors dynamically. */
+          if (ev->colors == COLORS_DISTANCE)
+          {
+            vc = -4.0*v;
+            if (vc >= 4.0*M_PI)
+              vc -= 4.0*M_PI;
+            if (vc >= 2.0*M_PI)
+              vc = 4.0*M_PI-vc;
+            color(ev,vc,matc,&ev->col[4*o]);
+          }
+          else if (ev->colors == COLORS_DIRECTION)
+          {
+            color(ev,u,matc,&ev->col[4*o]);
+          }
+        }
+        u = 0.5*u;
+        bosqrt2 = db/M_SQRT2;
+        b2osqrt2 = 2.0*bosqrt2;
+        b3osqrt2 = 3.0*bosqrt2;
+        cu = cos(u);
+        su = sin(u);
+        c2u = cos(2.0*u);
+        s2u = sin(2.0*u);
+        c3u = cos(3.0*u);
+        s3u = sin(3.0*u);
+        cv = cos(v);
+        sv = sin(v);
+        c2v = cos(2.0*v);
+        s2v = sin(2.0*v);
+        nom = (1.0-dl+dl*cv);
+        den = (1.0-bosqrt2*s3u*s2v);
+        f = nom/den;
+        fx = c2u*cv+cu*sv;
+        fy = s2u*cv-su*sv;
+        fz = M_SQRT2*cv;
+        x = f*fx;
+        y = f*fy;
+        z = f*fz;
+        nomv = -dl*sv;
+        denu = -b3osqrt2*c3u*s2v;
+        denv = -b2osqrt2*s3u*c2v;
+        den2 = 1.0/(den*den);
+        fu = -nom*denu*den2;
+        fv = (den*nomv-nom*denv)*den2;
+        fxu = -su*sv-2.0*s2u*cv;
+        fxv = cu*cv-c2u*sv;
+        fyu = 2.0*c2u*cv-cu*sv;
+        fyv = -s2u*sv-su*cv;
+        fzv = -M_SQRT2*sv;
+        xu = fu*fx+f*fxu;
+        xv = fv*fx+f*fxv;
+        yu = fu*fy+f*fyu;
+        yv = fv*fy+f*fyv;
+        zu = fu*fz;
+        zv = fv*fz+f*fzv;
+        xx[0] = x;
+        xx[1] = y;
+        xx[2] = z-oz;
+        n[0] = yu*zv-zu*yv;
+        n[1] = zu*xv-xu*zv;
+        n[2] = xu*yv-yu*xv;
+        t = n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
+        /* Avoid degenerate tangential plane basis vectors as much as
+           possible. */
+        if (t < FLT_EPSILON)
+        {
+          u += 0.01;
+          v += 0.01;
+          cu = cos(u);
+          su = sin(u);
+          c2u = cos(2.0*u);
+          s2u = sin(2.0*u);
+          c3u = cos(3.0*u);
+          s3u = sin(3.0*u);
+          cv = cos(v);
+          sv = sin(v);
+          c2v = cos(2.0*v);
+          s2v = sin(2.0*v);
+          nom = (1.0-dl+dl*cv);
+          den = (1.0-bosqrt2*s3u*s2v);
+          f = nom/den;
+          fx = c2u*cv+cu*sv;
+          fy = s2u*cv-su*sv;
+          fz = M_SQRT2*cv;
+          nomv = -dl*sv;
+          denu = -b3osqrt2*c3u*s2v;
+          denv = -b2osqrt2*s3u*c2v;
+          den2 = 1.0/(den*den);
+          fu = -nom*denu*den2;
+          fv = (den*nomv-nom*denv)*den2;
+          fxu = -su*sv-2.0*s2u*cv;
+          fxv = cu*cv-c2u*sv;
+          fyu = 2.0*c2u*cv-cu*sv;
+          fyv = -s2u*sv-su*cv;
+          fzv = -M_SQRT2*sv;
+          xu = fu*fx+f*fxu;
+          xv = fv*fx+f*fxv;
+          yu = fu*fy+f*fyu;
+          yv = fv*fy+f*fyv;
+          zu = fu*fz;
+          zv = fv*fz+f*fzv;
+        }
+        xxu[0] = xu;
+        xxu[1] = yu;
+        xxu[2] = zu;
+        xxv[0] = xv;
+        xxv[1] = yv;
+        xxv[2] = zv;
+        for (l=0; l<3; l++)
+        {
+          r = 0.0;
+          s = 0.0;
+          t = 0.0;
+          for (m=0; m<3; m++)
+          {
+            r += mat[l][m]*xx[m];
+            s += mat[l][m]*xxu[m];
+            t += mat[l][m]*xxv[m];
+          }
+          p[l] = r*radius+ev->offset3d[l];
+          pu[l] = s*radius;
+          pv[l] = t*radius;
+        }
+        n[0] = pu[1]*pv[2]-pu[2]*pv[1];
+        n[1] = pu[2]*pv[0]-pu[0]*pv[2];
+        n[2] = pu[0]*pv[1]-pu[1]*pv[0];
+        t = 1.0/sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);
+        n[0] *= t;
+        n[1] *= t;
+        n[2] *= t;
+        ev->ev[3*o+0] = p[0];
+        ev->ev[3*o+1] = p[1];
+        ev->ev[3*o+2] = p[2];
+        ev->evn[3*o+0] = n[0];
+        ev->evn[3*o+1] = n[1];
+        ev->evn[3*o+2] = n[2];
+      }
+    }
+  }
+  else /* ev->appearance != APPEARANCE_DISTANCE_BANDS */
+  {
+    for (j=0; j<=numu; j++)
+    {
+      if (ev->appearance == APPEARANCE_DIRECTION_BANDS &&
+          ((j & (NUMBDIR-1)) >= NUMBDIR/2+1))
+        continue;
+      for (i=0; i<=numv; i++)
+      {
+        o = i*(numu+1)+j;
+        u = ur*j/numu+umin;
+        v = vr*i/numv+vmin;
+        if (ev->change_colors)
+        {
+          /* Compute the colors dynamically. */
+          if (ev->colors == COLORS_DISTANCE)
+          {
+            vc = 4.0*v;
+            if (vc >= 4.0*M_PI)
+              vc -= 4.0*M_PI;
+            if (vc >= 2.0*M_PI)
+              vc = 4.0*M_PI-vc;
+            color(ev,vc,matc,&ev->col[4*o]);
+          }
+          else if (ev->colors == COLORS_DIRECTION)
+          {
+            color(ev,u,matc,&ev->col[4*o]);
+          }
+        }
+        u = 0.5*u;
+        bosqrt2 = db/M_SQRT2;
+        b2osqrt2 = 2.0*bosqrt2;
+        b3osqrt2 = 3.0*bosqrt2;
+        cu = cos(u);
+        su = sin(u);
+        c2u = cos(2.0*u);
+        s2u = sin(2.0*u);
+        c3u = cos(3.0*u);
+        s3u = sin(3.0*u);
+        cv = cos(v);
+        sv = sin(v);
+        c2v = cos(2.0*v);
+        s2v = sin(2.0*v);
+        nom = (1.0-dl+dl*cv);
+        den = (1.0-bosqrt2*s3u*s2v);
+        f = nom/den;
+        fx = c2u*cv+cu*sv;
+        fy = s2u*cv-su*sv;
+        fz = M_SQRT2*cv;
+        x = f*fx;
+        y = f*fy;
+        z = f*fz;
+        nomv = -dl*sv;
+        denu = -b3osqrt2*c3u*s2v;
+        denv = -b2osqrt2*s3u*c2v;
+        den2 = 1.0/(den*den);
+        fu = -nom*denu*den2;
+        fv = (den*nomv-nom*denv)*den2;
+        fxu = -su*sv-2.0*s2u*cv;
+        fxv = cu*cv-c2u*sv;
+        fyu = 2.0*c2u*cv-cu*sv;
+        fyv = -s2u*sv-su*cv;
+        fzv = -M_SQRT2*sv;
+        xu = fu*fx+f*fxu;
+        xv = fv*fx+f*fxv;
+        yu = fu*fy+f*fyu;
+        yv = fv*fy+f*fyv;
+        zu = fu*fz;
+        zv = fv*fz+f*fzv;
+        xx[0] = x;
+        xx[1] = y;
+        xx[2] = z-oz;
+        n[0] = yu*zv-zu*yv;
+        n[1] = zu*xv-xu*zv;
+        n[2] = xu*yv-yu*xv;
+        t = n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
+        /* Avoid degenerate tangential plane basis vectors as much as
+           possible. */
+        if (t < FLT_EPSILON)
+        {
+          u += 0.01;
+          v += 0.01;
+          cu = cos(u);
+          su = sin(u);
+          c2u = cos(2.0*u);
+          s2u = sin(2.0*u);
+          c3u = cos(3.0*u);
+          s3u = sin(3.0*u);
+          cv = cos(v);
+          sv = sin(v);
+          c2v = cos(2.0*v);
+          s2v = sin(2.0*v);
+          nom = (1.0-dl+dl*cv);
+          den = (1.0-bosqrt2*s3u*s2v);
+          f = nom/den;
+          fx = c2u*cv+cu*sv;
+          fy = s2u*cv-su*sv;
+          fz = M_SQRT2*cv;
+          nomv = -dl*sv;
+          denu = -b3osqrt2*c3u*s2v;
+          denv = -b2osqrt2*s3u*c2v;
+          den2 = 1.0/(den*den);
+          fu = -nom*denu*den2;
+          fv = (den*nomv-nom*denv)*den2;
+          fxu = -su*sv-2.0*s2u*cv;
+          fxv = cu*cv-c2u*sv;
+          fyu = 2.0*c2u*cv-cu*sv;
+          fyv = -s2u*sv-su*cv;
+          fzv = -M_SQRT2*sv;
+          xu = fu*fx+f*fxu;
+          xv = fv*fx+f*fxv;
+          yu = fu*fy+f*fyu;
+          yv = fv*fy+f*fyv;
+          zu = fu*fz;
+          zv = fv*fz+f*fzv;
+        }
+        xxu[0] = xu;
+        xxu[1] = yu;
+        xxu[2] = zu;
+        xxv[0] = xv;
+        xxv[1] = yv;
+        xxv[2] = zv;
+        for (l=0; l<3; l++)
+        {
+          r = 0.0;
+          s = 0.0;
+          t = 0.0;
+          for (m=0; m<3; m++)
+          {
+            r += mat[l][m]*xx[m];
+            s += mat[l][m]*xxu[m];
+            t += mat[l][m]*xxv[m];
+          }
+          p[l] = r*radius+ev->offset3d[l];
+          pu[l] = s*radius;
+          pv[l] = t*radius;
+        }
+        n[0] = pu[1]*pv[2]-pu[2]*pv[1];
+        n[1] = pu[2]*pv[0]-pu[0]*pv[2];
+        n[2] = pu[0]*pv[1]-pu[1]*pv[0];
+        t = 1.0/sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);
+        n[0] *= t;
+        n[1] *= t;
+        n[2] *= t;
+        ev->ev[3*o+0] = p[0];
+        ev->ev[3*o+1] = p[1];
+        ev->ev[3*o+2] = p[2];
+        ev->evn[3*o+0] = n[0];
+        ev->evn[3*o+1] = n[1];
+        ev->evn[3*o+2] = n[2];
+      }
+    }
+  }
+
+  if (ev->appearance == APPEARANCE_DISTANCE_BANDS)
+  {
+    for (i=0; i<numv; i++)
+    {
+      if ((i & (NUMBDIST-1)) >= NUMBDIST/4 &&
+          (i & (NUMBDIST-1)) < 3*NUMBDIST/4)
+        continue;
+      if (ev->display_mode == DISP_WIREFRAME)
+        glBegin(GL_QUAD_STRIP);
+      else
+        glBegin(GL_TRIANGLE_STRIP);
+      for (j=0; j<=numu; j++)
+      {
+        for (k=0; k<=1; k++)
+        {
+          l = (i+k);
+          m = j;
+          o = l*(numu+1)+m;
+          glTexCoord2fv(&ev->tex[2*o]);
+          if (ev->colors != COLORS_ONESIDED && ev->colors != COLORS_TWOSIDED)
+          {
+            glColor3fv(&ev->col[4*o]);
+            glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,
+                         &ev->col[4*o]);
+          }
+          glNormal3fv(&ev->evn[3*o]);
+          glVertex3fv(&ev->ev[3*o]);
+          polys++;
+        }
+      }
+      glEnd();
+    }
+  }
+  else /* ev->appearance != APPEARANCE_DISTANCE_BANDS */
+  {
+    for (j=0; j<numu; j++)
+    {
+      if (ev->appearance == APPEARANCE_DIRECTION_BANDS &&
+          ((j & (NUMBDIR-1)) >= NUMBDIR/2))
+        continue;
+      if (ev->display_mode == DISP_WIREFRAME)
+        glBegin(GL_QUAD_STRIP);
+      else
+        glBegin(GL_TRIANGLE_STRIP);
+      for (i=0; i<=numv; i++)
+      {
+        for (k=0; k<=1; k++)
+        {
+          l = i;
+          m = (j+k);
+          o = l*(numu+1)+m;
+          glTexCoord2fv(&ev->tex[2*o]);
+          if (ev->colors != COLORS_ONESIDED && ev->colors != COLORS_TWOSIDED)
+          {
+            glColor3fv(&ev->col[4*o]);
+            glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,
+                         &ev->col[4*o]);
+          }
+          glNormal3fv(&ev->evn[3*o]);
+          glVertex3fv(&ev->ev[3*o]);
+          polys++;
+        }
+      }
+      glEnd();
+    }
+  }
+
+  polys /= 2;
+  return polys;
+}
+
+
+/* Generate a texture image that shows the orientation reversal. */
+static void gen_texture(ModeInfo *mi)
+{
+  etruscanvenusstruct *ev = &etruscanvenus[MI_SCREEN(mi)];
+
+  glGenTextures(1,&ev->tex_name);
+  glBindTexture(GL_TEXTURE_2D,ev->tex_name);
+  glPixelStorei(GL_UNPACK_ALIGNMENT,1);
+  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);
+  glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
+  glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,TEX_DIMENSION,TEX_DIMENSION,0,
+               GL_LUMINANCE,GL_UNSIGNED_BYTE,texture);
+}
+
+
+static void init(ModeInfo *mi)
+{
+  static const GLfloat light_ambient[]  = { 0.0, 0.0, 0.0, 1.0 };
+  static const GLfloat light_diffuse[]  = { 1.0, 1.0, 1.0, 1.0 };
+  static const GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
+  static const GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
+  static const GLfloat mat_specular[]   = { 1.0, 1.0, 1.0, 1.0 };
+  etruscanvenusstruct *ev = &etruscanvenus[MI_SCREEN(mi)];
+
+  if (deform_speed == 0.0)
+    deform_speed = 10.0;
+
+  if (init_deform < 0.0)
+    init_deform = 0.0;
+  if (init_deform >= 4000.0)
+    init_deform = 0.0;
+
+  if (walk_speed == 0.0)
+    walk_speed = 20.0;
+
+  if (ev->view == VIEW_TURN)
+  {
+    ev->alpha = frand(360.0);
+    ev->beta = frand(360.0);
+    ev->delta = frand(360.0);
+  }
+  else
+  {
+    ev->alpha = 0.0;
+    ev->beta = 0.0;
+    ev->delta = 0.0;
+  }
+  ev->umove = frand(2.0*M_PI);
+  ev->vmove = frand(2.0*M_PI);
+  ev->dumove = 0.0;
+  ev->dvmove = 0.0;
+  ev->side = 1;
+
+  ev->dd = init_deform*0.001;
+  ev->defdir = 1;
+
+  ev->rho = frand(360.0);
+  ev->sigma = frand(360.0);
+  ev->tau = frand(360.0);
+
+  ev->offset3d[0] = 0.0;
+  ev->offset3d[1] = 0.0;
+  ev->offset3d[2] = -2.0;
+
+  gen_texture(mi);
+  setup_etruscan_venus_color_texture(mi,0.0,2.0*M_PI,0.0,2.0*M_PI,NUMU,NUMV);
+
+  if (ev->marks)
+    glEnable(GL_TEXTURE_2D);
+  else
+    glDisable(GL_TEXTURE_2D);
+
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  if (ev->projection == DISP_PERSPECTIVE || ev->view == VIEW_WALK)
+  {
+    if (ev->view == VIEW_WALK)
+      gluPerspective(60.0,1.0,0.01,10.0);
+    else
+      gluPerspective(60.0,1.0,0.1,10.0);
+  }
+  else
+  {
+    glOrtho(-1.0,1.0,-1.0,1.0,0.1,10.0);
+  }
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+
+# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */
+  if (ev->display_mode == DISP_WIREFRAME)
+    ev->display_mode = DISP_SURFACE;
+# endif
+
+  if (ev->display_mode == DISP_SURFACE)
+  {
+    glEnable(GL_DEPTH_TEST);
+    glDepthFunc(GL_LESS);
+    glShadeModel(GL_SMOOTH);
+    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
+    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
+    glEnable(GL_LIGHTING);
+    glEnable(GL_LIGHT0);
+    glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient);
+    glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse);
+    glLightfv(GL_LIGHT0,GL_SPECULAR,light_specular);
+    glLightfv(GL_LIGHT0,GL_POSITION,light_position);
+    glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,mat_specular);
+    glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,50.0);
+    glDepthMask(GL_TRUE);
+    glDisable(GL_BLEND);
+  }
+  else if (ev->display_mode == DISP_TRANSPARENT)
+  {
+    glDisable(GL_DEPTH_TEST);
+    glShadeModel(GL_SMOOTH);
+    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
+    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
+    glEnable(GL_LIGHTING);
+    glEnable(GL_LIGHT0);
+    glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient);
+    glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse);
+    glLightfv(GL_LIGHT0,GL_SPECULAR,light_specular);
+    glLightfv(GL_LIGHT0,GL_POSITION,light_position);
+    glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,mat_specular);
+    glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,50.0);
+    glDepthMask(GL_FALSE);
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+  }
+  else  /* ev->display_mode == DISP_WIREFRAME */
+  {
+    glDisable(GL_DEPTH_TEST);
+    glShadeModel(GL_FLAT);
+    glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+    glDisable(GL_LIGHTING);
+    glDisable(GL_LIGHT0);
+    glDisable(GL_BLEND);
+  }
+}
+
+
+/* Redisplay the Klein bottle. */
+static void display_etruscanvenus(ModeInfo *mi)
+{
+  etruscanvenusstruct *ev = &etruscanvenus[MI_SCREEN(mi)];
+
+  if (!ev->button_pressed)
+  {
+    if (deform)
+    {
+      ev->dd += ev->defdir*deform_speed*0.001;
+      if (ev->dd < 0.0)
+        ev->dd += 4.0;
+      if (ev->dd >= 4.0)
+        ev->dd -= 4.0;
+      /* Randomly change the deformation direction at one of the four
+         surface types in 10% of the cases. */
+      if (fabs(round(ev->dd)-ev->dd) <= deform_speed*0.0005)
+      {
+        if (LRAND() % 10 == 0)
+          ev->defdir = -ev->defdir;
+      }
+    }
+    if (ev->view == VIEW_TURN)
+    {
+      ev->alpha += speed_x*ev->speed_scale;
+      if (ev->alpha >= 360.0)
+        ev->alpha -= 360.0;
+      ev->beta += speed_y*ev->speed_scale;
+      if (ev->beta >= 360.0)
+        ev->beta -= 360.0;
+      ev->delta += speed_z*ev->speed_scale;
+      if (ev->delta >= 360.0)
+        ev->delta -= 360.0;
+    }
+    if (ev->view == VIEW_WALK)
+    {
+      ev->dumove = cos(walk_direction*M_PI/180.0)*walk_speed*M_PI/4096.0;
+      ev->dvmove = sin(walk_direction*M_PI/180.0)*walk_speed*M_PI/4096.0;
+      ev->umove += ev->dumove;
+      if (ev->umove >= 2.0*M_PI)
+      {
+        ev->umove -= 2.0*M_PI;
+        ev->vmove = 2.0*M_PI-ev->vmove;
+        ev->side = -ev->side;
+      }
+      if (ev->umove < 0.0)
+      {
+        ev->umove += 2.0*M_PI;
+        ev->vmove = 2.0*M_PI-ev->vmove;
+        ev->side = -ev->side;
+      }
+      ev->vmove += ev->dvmove;
+      if (ev->vmove >= 2.0*M_PI)
+        ev->vmove -= 2.0*M_PI;
+      if (ev->vmove < 0.0)
+        ev->vmove += 2.0*M_PI;
+    }
+    if (ev->change_colors)
+    {
+      ev->rho += DRHO;
+      if (ev->rho >= 360.0)
+        ev->rho -= 360.0;
+      ev->sigma += DSIGMA;
+      if (ev->sigma >= 360.0)
+        ev->sigma -= 360.0;
+      ev->tau += DTAU;
+      if (ev->tau >= 360.0)
+        ev->tau -= 360.0;
+    }
+  }
+
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  if (ev->projection == DISP_PERSPECTIVE || ev->view == VIEW_WALK)
+  {
+    if (ev->view == VIEW_WALK)
+      gluPerspective(60.0,ev->aspect,0.01,10.0);
+    else
+      gluPerspective(60.0,ev->aspect,0.1,10.0);
+  }
+  else
+  {
+    if (ev->aspect >= 1.0)
+      glOrtho(-ev->aspect,ev->aspect,-1.0,1.0,0.1,10.0);
+    else
+      glOrtho(-1.0,1.0,-1.0/ev->aspect,1.0/ev->aspect,0.1,10.0);
+  }
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+
+  mi->polygon_count = etruscan_venus(mi,0.0,2.0*M_PI,0.0,2.0*M_PI,NUMU,NUMV);
+}
+
+
+ENTRYPOINT void reshape_etruscanvenus(ModeInfo *mi, int width, int height)
+{
+  etruscanvenusstruct *ev = &etruscanvenus[MI_SCREEN(mi)];
+  int y = 0;
+
+  if (width > height * 5) {   /* tiny window: show middle */
+    height = width;
+    y = -height/2;
+  }
+
+  ev->WindW = (GLint)width;
+  ev->WindH = (GLint)height;
+  glViewport(0,y,width,height);
+  ev->aspect = (GLfloat)width/(GLfloat)height;
+}
+
+
+ENTRYPOINT Bool etruscanvenus_handle_event(ModeInfo *mi, XEvent *event)
+{
+  etruscanvenusstruct *ev = &etruscanvenus[MI_SCREEN(mi)];
+
+  if (event->xany.type == ButtonPress && event->xbutton.button == Button1)
+  {
+    ev->button_pressed = True;
+    gltrackball_start(ev->trackball, event->xbutton.x, event->xbutton.y,
+                      MI_WIDTH(mi), MI_HEIGHT(mi));
+    return True;
+  }
+  else if (event->xany.type == ButtonRelease &&
+           event->xbutton.button == Button1)
+  {
+    ev->button_pressed = False;
+    return True;
+  }
+  else if (event->xany.type == MotionNotify && ev->button_pressed)
+  {
+    gltrackball_track(ev->trackball, event->xmotion.x, event->xmotion.y,
+                      MI_WIDTH(mi), MI_HEIGHT(mi));
+    return True;
+  }
+
+  return False;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *-----------------------------------------------------------------------------
+ *    Xlock hooks.
+ *-----------------------------------------------------------------------------
+ *-----------------------------------------------------------------------------
+ */
+
+/*
+ *-----------------------------------------------------------------------------
+ *    Initialize etruscanvenus.  Called each time the window changes.
+ *-----------------------------------------------------------------------------
+ */
+
+ENTRYPOINT void init_etruscanvenus(ModeInfo *mi)
+{
+  etruscanvenusstruct *ev;
+
+  MI_INIT (mi, etruscanvenus);
+  ev = &etruscanvenus[MI_SCREEN(mi)];
+
+  ev->ev = calloc(3*(NUMU+1)*(NUMV+1),sizeof(float));
+  ev->evn = calloc(3*(NUMU+1)*(NUMV+1),sizeof(float));
+  ev->col = calloc(4*(NUMU+1)*(NUMV+1),sizeof(float));
+  ev->tex = calloc(2*(NUMU+1)*(NUMV+1),sizeof(float));
+
+  ev->trackball = gltrackball_init(True);
+  ev->button_pressed = False;
+
+  /* Set the display mode. */
+  if (!strcasecmp(mode,"random"))
+  {
+    ev->display_mode = random() % NUM_DISPLAY_MODES;
+  }
+  else if (!strcasecmp(mode,"wireframe"))
+  {
+    ev->display_mode = DISP_WIREFRAME;
+  }
+  else if (!strcasecmp(mode,"surface"))
+  {
+    ev->display_mode = DISP_SURFACE;
+  }
+  else if (!strcasecmp(mode,"transparent"))
+  {
+    ev->display_mode = DISP_TRANSPARENT;
+  }
+  else
+  {
+    ev->display_mode = random() % NUM_DISPLAY_MODES;
+  }
+
+  ev->marks = marks;
+
+  /* Orientation marks don't make sense in wireframe mode. */
+  if (ev->display_mode == DISP_WIREFRAME)
+    ev->marks = False;
+
+  /* Set the appearance. */
+  if (!strcasecmp(appear,"random"))
+  {
+    ev->appearance = random() % NUM_APPEARANCES;
+  }
+  else if (!strcasecmp(appear,"solid"))
+  {
+    ev->appearance = APPEARANCE_SOLID;
+  }
+  else if (!strcasecmp(appear,"distance-bands"))
+  {
+    ev->appearance = APPEARANCE_DISTANCE_BANDS;
+  }
+  else if (!strcasecmp(appear,"direction-bands"))
+  {
+    ev->appearance = APPEARANCE_DIRECTION_BANDS;
+  }
+  else
+  {
+    ev->appearance = random() % NUM_APPEARANCES;
+  }
+
+  /* Set the color mode. */
+  if (!strcasecmp(color_mode,"random"))
+  {
+    ev->colors = random() % NUM_COLORS;
+  }
+  else if (!strcasecmp(color_mode,"one-sided"))
+  {
+    ev->colors = COLORS_ONESIDED;
+  }
+  else if (!strcasecmp(color_mode,"two-sided"))
+  {
+    ev->colors = COLORS_TWOSIDED;
+  }
+  else if (!strcasecmp(color_mode,"distance"))
+  {
+    ev->colors = COLORS_DISTANCE;
+  }
+  else if (!strcasecmp(color_mode,"direction"))
+  {
+    ev->colors = COLORS_DIRECTION;
+  }
+  else
+  {
+    ev->colors = random() % NUM_COLORS;
+  }
+
+  ev->change_colors = change_colors;
+
+  /* Set the view mode. */
+  if (!strcasecmp(view_mode,"random"))
+  {
+    /* Select the walking mode only in 10% of the cases. */
+    if (LRAND() % 10 == 0)
+      ev->view = VIEW_WALK;
+    else
+      ev->view = VIEW_TURN;
+  }
+  else if (!strcasecmp(view_mode,"walk"))
+  {
+    ev->view = VIEW_WALK;
+  }
+  else if (!strcasecmp(view_mode,"turn"))
+  {
+    ev->view = VIEW_TURN;
+  }
+  else
+  {
+    /* Select the walking mode only in 10% of the cases. */
+    if (LRAND() % 10 == 0)
+      ev->view = VIEW_WALK;
+    else
+      ev->view = VIEW_TURN;
+  }
+
+  if (ev->view == VIEW_WALK)
+  {
+    /* Walking only works on the Ida surface.  Therefore, set the initial
+       deformation to the Ida surface and switch off the deformation. */
+    init_deform = 3000.0;
+    deform = False;
+  }
+
+  /* Set the 3d projection mode. */
+  if (!strcasecmp(proj,"random"))
+  {
+    /* Orthographic projection only makes sense in turn mode. */
+    if (ev->view == VIEW_TURN)
+      ev->projection = random() % NUM_DISP_MODES;
+    else
+      ev->projection = DISP_PERSPECTIVE;
+  }
+  else if (!strcasecmp(proj,"perspective"))
+  {
+    ev->projection = DISP_PERSPECTIVE;
+  }
+  else if (!strcasecmp(proj,"orthographic"))
+  {
+    ev->projection = DISP_ORTHOGRAPHIC;
+  }
+  else
+  {
+    /* Orthographic projection only makes sense in turn mode. */
+    if (ev->view == VIEW_TURN)
+      ev->projection = random() % NUM_DISP_MODES;
+    else
+      ev->projection = DISP_PERSPECTIVE;
+  }
+
+  /* Make multiple screens rotate at slightly different rates. */
+  ev->speed_scale = 0.9+frand(0.3);
+
+  if ((ev->glx_context = init_GL(mi)) != NULL)
+  {
+    reshape_etruscanvenus(mi,MI_WIDTH(mi),MI_HEIGHT(mi));
+    glDrawBuffer(GL_BACK);
+    init(mi);
+  }
+  else
+  {
+    MI_CLEARWINDOW(mi);
+  }
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *    Called by the mainline code periodically to update the display.
+ *-----------------------------------------------------------------------------
+ */
+ENTRYPOINT void draw_etruscanvenus(ModeInfo *mi)
+{
+  Display *display = MI_DISPLAY(mi);
+  Window window = MI_WINDOW(mi);
+  etruscanvenusstruct *ev;
+
+  if (etruscanvenus == NULL)
+    return;
+  ev = &etruscanvenus[MI_SCREEN(mi)];
+
+  MI_IS_DRAWN(mi) = True;
+  if (!ev->glx_context)
+    return;
+
+  glXMakeCurrent(display, window, *ev->glx_context);
+
+  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+  glLoadIdentity();
+
+  display_etruscanvenus(mi);
+
+  if (MI_IS_FPS(mi))
+    do_fps (mi);
+
+  glFlush();
+
+  glXSwapBuffers(display,window);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *    The display is being taken away from us.  Free up malloc'ed 
+ *      memory and X resources that we've alloc'ed.
+ *-----------------------------------------------------------------------------
+ */
+
+ENTRYPOINT void free_etruscanvenus(ModeInfo *mi)
+{
+  etruscanvenusstruct *ev = &etruscanvenus[MI_SCREEN(mi)];
+
+  if (!ev->glx_context) return;
+  glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *ev->glx_context);
+
+  if (ev->ev) free(ev->ev);
+  if (ev->evn) free(ev->evn);
+  if (ev->col) free(ev->col);
+  if (ev->tex) free(ev->tex);
+  gltrackball_free(ev->trackball);
+  if (ev->tex_name) glDeleteTextures(1, &ev->tex_name);
+}
+
+#ifndef STANDALONE
+ENTRYPOINT void change_etruscanvenus(ModeInfo *mi)
+{
+  etruscanvenusstruct *ev = &etruscanvenus[MI_SCREEN(mi)];
+
+  if (!ev->glx_context)
+    return;
+
+  glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *ev->glx_context);
+  init(mi);
+}
+#endif /* !STANDALONE */
+
+XSCREENSAVER_MODULE ("EtruscanVenus", etruscanvenus)
+
+#endif /* USE_GL */
diff --git a/hacks/glx/etruscanvenus.man b/hacks/glx/etruscanvenus.man
new file mode 100644 (file)
index 0000000..a96bd23
--- /dev/null
@@ -0,0 +1,372 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+etruscanvenus - Draws a 3d immersion of a Klein bottle that smoothly
+deforms between the Etruscan Venus surface, the Roman surface, the Boy
+surface surface, and the Ida surface.
+.SH SYNOPSIS
+.B etruscanvenus
+[\-display \fIhost:display.screen\fP]
+[\-install]
+[\-visual \fIvisual\fP]
+[\-window]
+[\-root]
+[\-delay \fIusecs\fP]
+[\-fps]
+[\-mode \fIdisplay-mode\fP]
+[\-wireframe]
+[\-surface]
+[\-transparent]
+[\-appearance \fIappearance\fP]
+[\-solid]
+[\-distance-bands]
+[\-direction-bands]
+[\-colors \fIcolor-scheme\fP]
+[\-onesided-colors]
+[\-twosided-colors]
+[\-distance-colors]
+[\-direction-colors]
+[\-no-change-colors]
+[\-view-mode \fIview-mode\fP]
+[\-walk]
+[\-turn]
+[\-no-deform]
+[\-deformation-speed \fIfloat\fP]
+[\-initial-deformation \fIfloat\fP]
+[\-etruscan-venus]
+[\-roman]
+[\-boy]
+[\-ida]
+[\-orientation-marks]
+[\-projection \fImode\fP]
+[\-perspective]
+[\-orthographic]
+[\-speed-x \fIfloat\fP]
+[\-speed-y \fIfloat\fP]
+[\-speed-z \fIfloat\fP]
+[\-walk-direction \fIfloat\fP]
+[\-walk-speed \fIfloat\fP]
+.SH DESCRIPTION
+The \fIetruscanvenus\fP program shows a 3d immersion of a Klein bottle
+that smoothly deforms between the Etruscan Venus surface, the Roman
+surface, the Boy surface, and the Ida surface.  You can walk on the
+Klein bottle or turn it in 3d.  Topologically, all surfaces are Klein
+bottles, even the Roman and Boy surfaces, which are doubly covered and
+therefore appear to be an immersed real projective plane.  The smooth
+deformation between these surfaces was constructed by George
+K. Francis.
+.PP
+The Klein bottle is a non-orientable surface.  To make this apparent,
+the two-sided color mode can be used.  Alternatively, orientation
+markers (curling arrows) can be drawn as a texture map on the surface
+of the Klein bottle.  While walking on the Klein bottle, you will
+notice that the orientation of the curling arrows changes (which it
+must because the Klein bottle is non-orientable).  Since all the
+surfaces except the Ida surface have points where the surface normal
+is not well defined for some points, walking is only performed on the
+Ida surface.
+.PP
+As mentioned above, the Roman and Boy surfaces are doubly covered and
+therefore appear to be an immersed real projective plane.  Since some
+of the parameter names are based on this interpretation of the
+surface, the geometry of the real projective plane will be briefly
+disussed.  The real projective plane is a model for the projective
+geometry in 2d space.  One point can be singled out as the origin.  A
+line can be singled out as the line at infinity, i.e., a line that
+lies at an infinite distance to the origin.  The line at infinity is
+topologically a circle.  Points on the line at infinity are also used
+to model directions in projective geometry.  Direction and distance
+bands refer to this interpretation of the surface.  If direction bands
+are used, the bands extend from the origin of the projective plane in
+different directions to the line at infinity and back to the origin.
+If distance bands are used, the bands lie at constant distances to the
+origin.  The same interpretation is used for distance and direction
+colors.  Although there is no conceptually equivalent geometric
+interpretation for the two Klein bottle surfaces (the Etruscan Venus
+and Ida surfaces), the smooth deformation between the surfaces results
+in a natural extension of these concepts to the Klein bottle surfaces.
+.PP
+The immersed surfaces can be projected to the screen either
+perspectively or orthographically.  When using the walking mode,
+perspective projection to the screen will be used.
+.PP
+There are three display modes for the Klein bottle: mesh (wireframe),
+solid, or transparent.  Furthermore, the appearance of the surface can
+be as a solid object or as a set of see-through bands.  The bands can
+be distance bands or direction bands, as explained above.
+.PP
+The colors with with the surface is drawn can be set to one-sided,
+two-sided, distance, or direction.  In one-sided mode, the surface is
+drawn with the same color on both sides of the underlying triangles.
+In two-sided mode, the surface is drawn with one color on one side of
+the underlying triangles and the complementary color on the other
+side.  Since the surface actually only has one side, the color jumps
+from red to green along a line on the surface.  This mode enables you
+to see that the surface is non-orientable.  In distance mode, the
+surface is displayed with fully saturated colors that depend on the
+distance of the points on the projective plane to the origin, as
+described above.  If the surface is displayed as distance bands, each
+band will be displayed with a different color.  In direction mode, the
+surface is displayed with fully saturated colors that depend on the
+angle of the points on the projective plane with respect to the origin
+(see above for an explanation).  If the surface is displayed as
+direction bands, each band will be displayed with a different color.
+The colors used to color the surface can either be static or can be
+changed dynamically.
+.PP
+The rotation speed for each of the three coordinate axes around which
+the Klein bottle rotates can be chosen.
+.PP
+Furthermore, in the walking mode the walking direction in the 2d base
+square of the surface and the walking speed can be chosen.  The
+walking direction is measured as an angle in degrees in the 2d square
+that forms the coordinate system of the surface.  A value of 0 or 180
+means that the walk is along a circle at a randomly chosen distance
+from the origin (parallel to a distance band).  A value of 90 or 270
+means that the walk is directly along a direction band.  Any other
+value results in a curved path along the surface.  As noted above,
+walking is performed only on the Ida surface.
+.PP
+By default, the immersion of the Klein bottle smoothly deforms between
+the Etruscan Venus surface, the Roman surface, the Boy surface, and
+the Ida surface.  It is possible to choose the speed of the
+deformation.  Furthermore, it is possible to switch the deformation
+off.  It is also possible to determine the initial deformation of the
+immersion.  This is mostly useful if the deformation is switched off,
+in which case it will determine the appearance of the surface.  A
+value of 0 corresponds to the Etruscan Venus surface, a value of 1000
+to the Roman surface, a value of 2000 to the Boy surface, and a value
+of 3000 to the Ida surface.
+.PP
+This program is inspired by George K. Francis's book "A Topological
+Picturebook", Springer, 1987, by George K. Francis's paper "The
+Etruscan Venus" in P. Concus, R. Finn, and D. A. Hoffman: "Geometric
+Analysis and Computer Graphics", Springer, 1991, and by a video
+entitled "The Etruscan Venus" by Donna J. Cox, George K. Francis, and
+Raymond L. Idaszak, presented at SIGGRAPH 1989.
+.SH OPTIONS
+.I etruscanvenus
+accepts the following options:
+.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 \-install
+Install a private colormap for the window.
+.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 \-delay \fImicroseconds\fP
+How much of a delay should be introduced between steps of the
+animation.  Default 10000, or 1/100th second.
+.TP 8
+.B \-fps
+Display the current frame rate, CPU load, and polygon count.
+.PP
+The following four options are mutually exclusive.  They determine how
+the Klein bottle is displayed.
+.TP 8
+.B \-mode random
+Display the Klein bottle in a random display mode (default).
+.TP 8
+.B \-mode wireframe \fP(Shortcut: \fB\-wireframe\fP)
+Display the Klein bottle as a wireframe mesh.
+.TP 8
+.B \-mode surface \fP(Shortcut: \fB\-surface\fP)
+Display the Klein bottle as a solid surface.
+.TP 8
+.B \-mode transparent \fP(Shortcut: \fB\-transparent\fP)
+Display the Klein bottle as a transparent surface.
+.PP
+The following four options are mutually exclusive.  They determine the
+appearance of the Klein bottle.
+.TP 8
+.B \-appearance random
+Display the Klein bottle with a random appearance (default).
+.TP 8
+.B \-appearance solid \fP(Shortcut: \fB\-solid\fP)
+Display the Klein bottle as a solid object.
+.TP 8
+.B \-appearance distance-bands \fP(Shortcut: \fB\-distance-bands\fP)
+Display the Klein bottle as see-through bands that lie at increasing
+distances from the origin (see above for an explanation).
+.PP
+.TP 8
+.B \-appearance direction-bands \fP(Shortcut: \fB\-direction-bands\fP)
+Display the Klein bottle as see-through bands that lie at increasing
+angles with respect to the origin (see above for an explanation).
+.PP
+The following five options are mutually exclusive.  They determine how
+to color the Klein bottle.
+.TP 8
+.B \-colors random
+Display the Klein bottle with a random color scheme (default).
+.TP 8
+.B \-colors onesided \fP(Shortcut: \fB\-onesided-colors\fP)
+Display the Klein bottle with a single color.
+.TP 8
+.B \-colors twosided \fP(Shortcut: \fB\-twosided-colors\fP)
+Display the Klein bottle with two colors: one color on one "side" and
+the complementary color on the "other side."
+.TP 8
+.B \-colors distance \fP(Shortcut: \fB\-distance-colors\fP)
+Display the Klein bottle with fully saturated colors that depend on
+the distance of the points on the projective plane to the origin (see
+above for an explanation).  If the Klein bottle is displayed as
+distance bands, each band will be displayed with a different color.
+.TP 8
+.B \-colors direction \fP(Shortcut: \fB\-direction-colors\fP)
+Display the Klein bottle with fully saturated colors that depend on
+the angle of the points on the projective plane with respect to the
+origin (see above for an explanation).  If the Klein bottle is
+displayed as direction bands, each band will be displayed with a
+different color.
+.PP
+The following options determine whether the colors with which the
+Klein bottle are displayed are static or are changing dynamically.
+.TP 8
+.B \-change-colors
+Change the colors with which the Klein bottle is displayed
+dynamically (default).
+.TP 8
+.B \-no-change-colors
+Use static colors to display the Klein bottle.
+.PP
+The following three options are mutually exclusive.  They determine
+how to view the Klein bottle.
+.TP 8
+.B \-view-mode random
+View the Klein bottle in a random view mode (default).  The walking
+mode will be randomly selected in approximately 10% of the cases.
+.TP 8
+.B \-view-mode turn \fP(Shortcut: \fB\-turn\fP)
+View the Klein bottle while it turns in 3d.
+.TP 8
+.B \-view-mode walk \fP(Shortcut: \fB\-walk\fP)
+View the Klein bottle as if walking on its surface.
+.PP
+The following options determine whether the surface is being deformed.
+.TP 8
+.B \-deform
+Deform the surface smoothly between the Etruscan Venus surface, the
+Roman surface, the Boy surface surface, and the Ida surface (default).
+.TP 8
+.B \-no-deform
+Don't deform the surface.
+.PP
+The following option determines the deformation speed.
+.TP 8
+.B \-deformation-speed \fIfloat\fP
+The deformation speed is measured in percent of some sensible maximum
+speed (default: 10.0).
+.PP
+The following options determine the initial deformation of the
+surface.  As described above, this is mostly useful if
+\fB\-no-deform\fP is specified.
+.TP 8
+.B \-initial-deformation \fIfloat\fP
+The initial deformation is specified as a number between 0 and 4000.
+A value of 0 corresponds to the Etruscan Venus surface, a value of
+1000 to the Roman surface, a value of 2000 to the Boy surface, and a
+value of 3000 to the Ida surface.  The default value is 0.
+.TP 8
+.B \-etruscan-venus
+This is a shortcut for \fB\-initial-deformation 0\fP.
+.TP 8
+.B \-roman
+This is a shortcut for \fB\-initial-deformation 1000\fP.
+.TP 8
+.B \-boy
+This is a shortcut for \fB\-initial-deformation 2000\fP.
+.TP 8
+.B \-ida
+This is a shortcut for \fB\-initial-deformation 3000\fP.
+.PP
+The following options determine whether orientation marks are shown on
+the Klein bottle.
+.TP 8
+.B \-orientation-marks
+Display orientation marks on the Klein bottle.
+.TP 8
+.B \-no-orientation-marks
+Don't display orientation marks on the Klein bottle (default).
+.PP
+The following three options are mutually exclusive.  They determine
+how the Klain bottle is projected from 3d to 2d (i.e., to the screen).
+.TP 8
+.B \-projection random
+Project the Klein bottle from 3d to 2d using a random projection mode
+(default).
+.TP 8
+.B \-projection perspective \fP(Shortcut: \fB\-perspective\fP)
+Project the Klein bottle from 3d to 2d using a perspective projection.
+.TP 8
+.B \-projection orthographic \fP(Shortcut: \fB\-orthographic\fP)
+Project the Klein bottle from 3d to 2d using an orthographic
+projection.
+.PP
+The following three options determine the rotation speed of the Klein
+bottle around the three possible axes.  The rotation speed is measured
+in degrees per frame.  The speeds should be set to relatively small
+values, e.g., less than 4 in magnitude.  In walk mode, all speeds are
+ignored.
+.TP 8
+.B \-speed-x \fIfloat\fP
+Rotation speed around the x axis (default: 1.1).
+.TP 8
+.B \-speed-y \fIfloat\fP
+Rotation speed around the y axis (default: 1.3).
+.TP 8
+.B \-speed-z \fIfloat\fP
+Rotation speed around the z axis (default: 1.5).
+.PP
+The following two options determine the walking speed and direction.
+.TP 8
+.B \-walk-direction \fIfloat\fP
+The walking direction is measured as an angle in degrees in the 2d
+square that forms the coordinate system of the surface of the Klein
+bottle (default: 83.0).  A value of 0 or 180 means that the walk is
+along a circle at a randomly chosen distance from the origin (parallel
+to a distance band).  A value of 90 or 270 means that the walk is
+directly along a direction band.  Any other value results in a curved
+path along the surface.  As noted above, walking is performed only on
+the Ida surface.
+.TP 8
+.B \-walk-speed \fIfloat\fP
+The walking speed is measured in percent of some sensible maximum
+speed (default: 20.0).
+.SH INTERACTION
+If you run this program in standalone mode in its turn mode, you can
+rotate the Klein bottle by dragging the mouse while pressing the left
+mouse button.  This rotates the Klein bottle in 3d.  To examine the
+Klein bottle at your leisure, it is best to set all speeds to 0.
+Otherwise, the Klein bottle will rotate while the left mouse button is
+not pressed.  This kind of interaction is not available in the walk
+mode.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 2019-2020 by Carsten Steger.  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
+Carsten Steger <carsten@mirsanmir.org>, 05-jan-2020.
diff --git a/hacks/glx/gibson.c b/hacks/glx/gibson.c
new file mode 100644 (file)
index 0000000..8f99040
--- /dev/null
@@ -0,0 +1,1335 @@
+/* gibson, Copyright (c) 2020 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.
+ *
+ * Hacking the Gibson, as per the 1995 classic film, HACKERS.
+ *
+ * In the movie, this was primarily a practical effect: the towers were
+ * edge-lit etched perspex, each about four feet tall.
+ */
+
+#define TOWER_FONT "-*-helvetica-bold-r-normal-*-*-480-*-*-*-*-*-*"
+
+#define DEFAULTS       "*delay:        20000       \n" \
+                       "*groundColor:  #8A2BE2"   "\n" \
+                       "*towerColor:   #4444FF"   "\n" \
+                       "*towerText:    #DDDDFF"   "\n" \
+                       "*towerText2:   #FF0000"   "\n" \
+                       "*towerFont:  " TOWER_FONT "\n" \
+                       "*showFPS:      False       \n" \
+                       "*wireframe:    False       \n" \
+
+# define release_gibson 0
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+#include "xlockmore.h"
+#include "colors.h"
+#include "rotator.h"
+#include "texfont.h"
+#include <ctype.h>
+
+#ifdef USE_GL /* whole file */
+
+
+#define DEF_SPEED       "1.0"
+#define DEF_TEXTURE      "True"
+#define DEF_GRID_WIDTH  "6"
+#define DEF_GRID_HEIGHT         "7"
+#define DEF_GRID_DEPTH  "6"
+#define DEF_GRID_SPACING "2.0"
+#define DEF_COLUMNS     "5"
+
+#define GROUND_QUAD_SIZE 30
+
+typedef struct {
+  GLfloat x, y, h;
+  GLuint fg_dlists[5], bg_dlists[5];
+  int fg_polys, bg_polys;
+  unsigned int face_mode;   /* 5 bit field */
+} tower;
+
+typedef struct {
+  GLXContext *glx_context;
+  Bool button_down_p;
+  rotator *rot, *rot2;
+  GLfloat xscroll, yscroll;
+  GLfloat oxscroll, oyscroll;
+
+  GLuint ground_dlist;
+  GLuint tower_dlist;
+  int ground_polys, tower_polys;
+  GLfloat ground_y;
+  GLfloat billboard_y;
+  const char *billboard_text;
+
+  int ntowers;
+  tower *towers;
+  GLfloat tower_color[4];
+  GLfloat tower_color2[4];
+  GLfloat edge_color[4];
+  GLfloat bg_color[4];
+  Bool startup_p;
+
+  struct {
+    GLuint texid;
+    XCharStruct metrics;
+    int width, height;
+    texture_font_data *font_data;
+    int ascent, descent, em_width;
+    char *text;
+  } text[2];
+
+} gibson_configuration;
+
+static gibson_configuration *ccs = NULL;
+
+static GLfloat speed;
+static Bool do_tex;
+static int grid_width;
+static int grid_height;
+static int grid_depth;
+static GLfloat grid_spacing;
+static int columns;
+
+static XrmOptionDescRec opts[] = {
+  { "-speed",        ".speed",       XrmoptionSepArg, 0 },
+  { "-texture",      ".texture",     XrmoptionNoArg,  "True" },
+  { "+texture",      ".texture",     XrmoptionNoArg,  "False" },
+  { "-grid-width",   ".gridWidth",   XrmoptionSepArg, 0 },
+  { "-grid-height",  ".gridHeight",  XrmoptionSepArg, 0 },
+  { "-grid-depth",   ".gridDepth",   XrmoptionSepArg, 0 },
+  { "-spacing",      ".gridSpacing", XrmoptionSepArg, 0 },
+  { "-columns",      ".columns",     XrmoptionSepArg, 0 },
+};
+
+static argtype vars[] = {
+  {&speed,        "speed",       "Speed",       DEF_SPEED,        t_Float},
+  {&do_tex,       "texture",     "Texture",     DEF_TEXTURE,      t_Bool},
+  {&grid_width,   "gridWidth",   "GridWidth",   DEF_GRID_WIDTH,   t_Int},
+  {&grid_height,  "gridHeight",  "GridHeight",  DEF_GRID_HEIGHT,  t_Int},
+  {&grid_depth,   "gridDepth",   "GridDepth",   DEF_GRID_DEPTH,   t_Int},
+  {&grid_spacing, "gridSpacing", "GridSpacing", DEF_GRID_SPACING, t_Float},
+  {&columns,      "columns",     "Columns",     DEF_COLUMNS,      t_Int},
+};
+
+ENTRYPOINT ModeSpecOpt gibson_opts = {
+ countof(opts), opts, countof(vars), vars, NULL};
+
+
+ENTRYPOINT void
+reshape_gibson (ModeInfo *mi, int width, int height)
+{
+  GLfloat h = (GLfloat) height / (GLfloat) width;
+  int y = 0;
+
+  glViewport (0, y, (GLint) width, (GLint) height);
+
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+# ifdef DEBUG
+  gluPerspective (30, 1/h, 1, 100);
+# else
+  gluPerspective (100, 1/h/4,
+                  1.0, 
+                  20 * grid_depth * 1.5 * (1 + grid_spacing));
+# endif
+
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+  gluLookAt( 0, 0, 1,
+             0, 0, 0,
+             0, 1, 0);
+
+  glClear(GL_COLOR_BUFFER_BIT);
+}
+
+
+/* Copied from gltrackball.c */
+static void
+adjust_for_device_rotation (double *x, double *y, double *w, double *h)
+{
+  int rot = (int) current_device_rotation();
+  int swap;
+
+  while (rot <= -180) rot += 360;
+  while (rot >   180) rot -= 360;
+
+  if (rot > 135 || rot < -135)         /* 180 */
+    {
+      *x = *w - *x;
+      *y = *h - *y;
+    }
+  else if (rot > 45)                   /* 90 */
+    {
+      swap = *x; *x = *y; *y = swap;
+      swap = *w; *w = *h; *h = swap;
+      *x = *w - *x;
+    }
+  else if (rot < -45)                  /* 270 */
+    {
+      swap = *x; *x = *y; *y = swap;
+      swap = *w; *w = *h; *h = swap;
+      *y = *h - *y;
+    }
+}
+
+
+ENTRYPOINT Bool
+gibson_handle_event (ModeInfo *mi, XEvent *event)
+{
+  gibson_configuration *bp = &ccs[MI_SCREEN(mi)];
+  double w = MI_WIDTH(mi);
+  double h = MI_HEIGHT(mi);
+  double xoff = 0, yoff = 0;
+
+  if (event->xany.type == ButtonPress ||
+      event->xany.type == ButtonRelease)
+    {
+      double x = event->xbutton.x;
+      double y = event->xbutton.y;
+      adjust_for_device_rotation (&x, &y, &w, &h);
+      xoff = (x / w) - 0.5;
+      yoff = (event->xbutton.y / h) - 0.5;
+      bp->button_down_p = (event->xany.type == ButtonPress);
+      bp->oxscroll = xoff;
+      bp->oyscroll = yoff;
+
+      return True;
+    }
+  else if (event->xany.type == MotionNotify)
+    {
+      double x = event->xmotion.x;
+      double y = event->xmotion.y;
+      adjust_for_device_rotation (&x, &y, &w, &h);
+      xoff = (x / w) - 0.5;
+      yoff = (y / h) - 0.5;
+      if (bp->button_down_p)
+        {
+          bp->xscroll += xoff - bp->oxscroll;
+          bp->yscroll += yoff - bp->oyscroll;
+          bp->oxscroll = xoff;
+          bp->oyscroll = yoff;
+        }
+      return True;
+    }
+
+  return False;
+}
+
+
+static void
+parse_color (ModeInfo *mi, char *key, GLfloat color[4])
+{
+  XColor xcolor;
+  char *string = get_string_resource (mi->dpy, key, "Color");
+  if (!XParseColor (mi->dpy, mi->xgwa.colormap, string, &xcolor))
+    {
+      fprintf (stderr, "%s: unparsable color in %s: %s\n", progname,
+               key, string);
+      exit (1);
+    }
+  free (string);
+
+  color[0] = xcolor.red   / 65536.0;
+  color[1] = xcolor.green / 65536.0;
+  color[2] = xcolor.blue  / 65536.0;
+  color[3] = 1;
+}
+
+
+static int
+draw_ground (ModeInfo *mi)
+{
+  int wire = MI_IS_WIREFRAME(mi);
+  int polys = 0;
+  int x, y;
+  int cells = 20;
+  GLfloat color[4];
+  GLfloat color0[4];
+  GLfloat cell_size = 1.0;
+  GLfloat z = -0.005;
+
+  parse_color (mi, "groundColor", color);
+  parse_color (mi, "towerColor", color0);
+  color0[0] *= 0.05;
+  color0[1] *= 0.05;
+  color0[2] *= 0.3;
+  color0[3] = 1;
+
+  if (!wire)
+    {
+      GLfloat fog_color[4] = { 0, 0, 0, 1 };
+
+      glFogi (GL_FOG_MODE, GL_EXP2);
+      glFogfv (GL_FOG_COLOR, fog_color);
+      glFogf (GL_FOG_DENSITY, 0.015);
+      glFogf (GL_FOG_START, -cells/2 * cell_size);
+      glEnable (GL_FOG);
+    }
+
+  glPushMatrix();
+  glScalef (1.0/cells, 1.0/cells, 1);
+  glTranslatef (-cells/2.0, -cells/2.0, 0);
+  glTranslatef (0.5, 0, 0);
+
+  glBegin (GL_QUADS);  /* clipping quad */
+  glColor4fv (color0);
+  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color0);
+
+  glVertex3f (0, 0, z);
+  glVertex3f (cells * cell_size, 0, z);
+  glVertex3f (cells * cell_size, cells * cell_size, z);
+  glVertex3f (0, cells * cell_size, z);
+  glEnd();
+  polys++;
+
+  glColor4fv (color);
+  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
+
+  for (y = 0; y < cells; y++)
+    for (x = 0; x < cells; x++)
+      {
+        GLfloat a = 0;
+        GLfloat b = 1.0/3;
+        GLfloat c = 2.0/3;
+        GLfloat d = 1.0;
+        GLfloat w = 0.02;
+
+        glPushMatrix();
+        glTranslatef (x, y, 0);
+
+        glNormal3f (0, 0, 1);
+
+        switch (random() % 4) {
+        case 0:
+          glRotatef (90, 0, 0, 1);
+          glTranslatef (0, -1, 0);
+          break;
+        case 1:
+          glRotatef (-90, 0, 0, 1);
+          glTranslatef (-1, 0, 0);
+          break;
+        case 2:
+          glRotatef (180, 0, 0, 1);
+          glTranslatef (-1, -1, 0);
+          break;
+        default: break;
+        }
+
+        switch (random() % 2) {
+        case 0:
+          glScalef (-1, -1, 1);
+          glTranslatef (-1, -1, 0);
+          break;
+        default: break;
+        }
+
+        switch (random() % 2) {
+        case 0:
+
+          glBegin (wire ? GL_LINE_LOOP : GL_QUAD_STRIP);
+          glVertex3f (a, b+w, 0);
+          glVertex3f (a, b-w, 0); polys++;
+          glVertex3f (b+w, a, 0); polys++;
+          glVertex3f (b-w, a, 0); polys++;
+          glEnd();
+
+          glBegin (wire ? GL_LINE_LOOP : GL_QUAD_STRIP);
+          glVertex3f (a,   c+w, 0);
+          glVertex3f (a,   c-w, 0); polys++;
+          glVertex3f (b+w, c+w, 0); polys++;
+          glVertex3f (b,   c-w, 0); polys++;
+          glVertex3f (c+w, b+w, 0); polys++;
+          glVertex3f (c-w, b,   0); polys++;
+          glVertex3f (c+w, a,   0); polys++;
+          glVertex3f (c-w, a,   0); polys++;
+          glEnd();
+
+/*
+          glBegin (wire ? GL_LINE_LOOP : GL_QUAD_STRIP);
+          glVertex3f (c+w, d,   0);
+          glVertex3f (c-w, d,   0); polys++;
+          glVertex3f (d,   c+w, 0); polys++;
+          glVertex3f (d,   c-w, 0); polys++;
+          glEnd();
+*/
+          break;
+
+        default:
+          glBegin (wire ? GL_LINE_LOOP : GL_QUAD_STRIP);
+          glVertex3f (a+w, d,   0);
+          glVertex3f (a,   d,   0); polys++;
+          glVertex3f (a+w, d,   0);
+          glVertex3f (a,   d-w, 0); polys++;
+          glVertex3f (b+w, c-w, 0); polys++;
+          glVertex3f (b-w, c-w, 0); polys++;
+          glVertex3f (b+w, a,   0); polys++;
+          glVertex3f (b-w, a,   0); polys++;
+          glEnd();
+
+          glBegin (wire ? GL_LINE_LOOP : GL_QUAD_STRIP);
+          glVertex3f (b+w, d,   0);
+          glVertex3f (b-w, d,   0); polys++;
+          glVertex3f (c+w, c-w, 0); polys++;
+          glVertex3f (c-w, c-w, 0); polys++;
+          glVertex3f (c+w, a,   0); polys++;
+          glVertex3f (c-w, a,   0); polys++;
+          glEnd();
+          break;
+        }
+
+        glPopMatrix();
+      }
+  glPopMatrix();
+
+  if (!wire)
+    {
+      glDisable (GL_BLEND);
+      glDisable (GL_FOG);
+    }
+
+  return polys;
+}
+
+
+/* qsort comparator for sorting towers by y position */
+static int
+cmp_towers (const void *aa, const void *bb)
+{
+  const tower *a = (tower *) aa;
+  const tower *b = (tower *) bb;
+  return ((int) (b->y * 10000) -
+          (int) (a->y * 10000));
+}
+
+
+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.5;
+  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;
+}
+
+
+/* Draws the text quads on the face.
+   First pass is for the small background text, second is for the big block.
+ */
+static int
+draw_tower_face_text (ModeInfo *mi, GLfloat height, Bool which)
+{
+  gibson_configuration *bp = &ccs[MI_SCREEN(mi)];
+  int wire = MI_IS_WIREFRAME(mi);
+  int polys = 0;
+  Bool wire2 = False;   /* Debugging quads */
+  Bool bg_p = (which == 1 && do_tex && !wire);
+
+  glColor4fv (which ? bp->tower_color2 : bp->tower_color);
+  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, 
+                which ? bp->tower_color2 : bp->tower_color);
+
+  /* The texture is a tex_width x tex_height rectangle, of which we 
+     only use the rbearing+lbearing x ascent+descent sub-rectangle.
+     Texture coordinates reference the tex_width x tex_height rectangle
+     as a 0.0 - 1.0 coordinate.
+   */
+  int n = which ? 1 : 0;
+  GLfloat twratio = ((bp->text[n].metrics.rbearing +
+                      bp->text[n].metrics.lbearing) /
+                     (GLfloat) bp->text[n].width);
+  GLfloat thratio = ((bp->text[n].metrics.ascent +
+                      bp->text[n].metrics.descent) /
+                     (GLfloat) bp->text[n].height);
+  GLfloat aspect = ((bp->text[n].ascent + bp->text[n].descent) /
+                    (GLfloat) bp->text[n].em_width);
+
+  GLfloat sx  = 1.0 / (which ? 1 : columns);
+  GLfloat sy  = (which
+                 ? height * 0.8
+                 : sx * 4);  /* Tweaked to match gluPerspective */
+
+  GLfloat lines_in_tex = ((bp->text[n].metrics.ascent +
+                           bp->text[n].metrics.descent) /
+                          (GLfloat)
+                          (bp->text[n].ascent + bp->text[n].descent));
+  GLfloat tex_lines = (which ? 3 : 8);  /* Put this many lines in each quad */
+
+  GLfloat tsx = sx * twratio;
+  GLfloat tsy = sy * thratio * tex_lines / lines_in_tex * aspect;
+  GLfloat x1, tx1;
+  GLfloat margin = 0.2;
+  GLfloat m2 = margin/2 / (which ? 1 : columns);
+  GLfloat m3 = m2 / (which ? 1 : height);
+  GLfloat h2 = height * (which ? 1-margin : 1);
+
+  glBindTexture (GL_TEXTURE_2D, bp->text[n].texid);
+
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+  if (!wire && !wire2 && !bg_p) glBegin (GL_QUADS);
+  for (x1 = 0, tx1 = 0; x1 < 1.0; x1 += sx, tx1 += tsx)
+    {
+      GLfloat x2  = x1 + sx;
+      GLfloat tx2 = tx1 + tsx;
+      GLfloat y2, ty2;
+      GLfloat z = (which ? 0.05 : 0);
+
+      tx1 = 0;
+      tx2 = twratio;
+
+      for (y2 = h2, ty2 = thratio;
+           y2 > 0;
+           y2 -= sy, ty2 -= tsy)
+        {
+          GLfloat y1  = y2 - sy * (1-margin);
+          GLfloat ty1 = ty2 - tsy;
+          GLfloat toff = frand ((bp->text[n].metrics.ascent + 
+                                 bp->text[n].metrics.descent)
+                                * 0.8);
+
+          if (y1 < 0)  /* Clip the panel to the bottom of the tower face */
+            {
+              tsy = y2 / (y2 - y1);
+              y1 = 0;
+            }
+
+          ty1 = toff;
+          ty2 = ty1 + tsy;
+
+          if (wire2 && which) glColor3f (1,0,0);
+          if (wire || wire2 || bg_p)
+            glBegin (!wire && (wire2 || bg_p) ? GL_QUADS : GL_LINE_LOOP);
+          glTexCoord2f(tx1, ty2); glVertex3f (x1+m2, y1+m3, z);
+          glTexCoord2f(tx2, ty2); glVertex3f (x2-m2, y1+m3, z);
+          glTexCoord2f(tx2, ty1); glVertex3f (x2-m2, y2-m3, z);
+          glTexCoord2f(tx1, ty1); glVertex3f (x1+m2, y2-m3, z);
+          if (wire || wire2 || bg_p)
+            glEnd();
+          polys++;
+
+          if (bg_p)
+            {
+              GLfloat bg[4] = { 1, 1, 1, 0.2 };
+              z  -= 0.1;
+              m2 -= 0.03;
+              m3 -= 0.03;
+              glColor4fv (bg);
+              glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, bg);
+            }
+
+          if ((wire2 || bg_p) && !wire)
+            {
+              if (do_tex) glDisable(GL_TEXTURE_2D);
+              glBegin (bg_p ? GL_QUADS : GL_LINE_LOOP);
+              glVertex3f (x1+m2, y1+m3, z);
+              glVertex3f (x2-m2, y1+m3, z);
+              glVertex3f (x2-m2, y2-m3, z);
+              glVertex3f (x1+m2, y2-m3, z);
+              glEnd();
+              polys++;
+              if (do_tex) glEnable(GL_TEXTURE_2D);
+            }
+
+          if (which) break;
+        }
+    }
+  if (!wire && !wire2 && !bg_p) glEnd();
+
+  return polys;
+}
+
+
+/* Draws the wall of the face, and the edges, then the text quads on it.
+ */
+static int
+draw_tower_face (ModeInfo *mi, GLfloat height, int mode)
+{
+  gibson_configuration *bp = &ccs[MI_SCREEN(mi)];
+  int wire = MI_IS_WIREFRAME(mi);
+  int polys = 0;
+
+  switch (mode) {
+  case 0:
+    if (! wire)
+      {
+        GLfloat m =  0.015;
+        GLfloat z = -0.0005;
+        if (do_tex) glDisable (GL_TEXTURE_2D);
+
+        glNormal3f (0, 0, 1);
+
+        glColor4fv (bp->bg_color);
+        glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE,
+                      bp->bg_color);
+
+        glBegin (GL_QUADS);
+        glVertex3f (0, 0, z*2);                        /* background */
+        glVertex3f (1, 0, z*2);
+        glVertex3f (1, height, z*2);
+        glVertex3f (0, height, z*2);
+        polys++;
+        glEnd();
+
+        glColor4fv (bp->edge_color);
+        glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE,
+                      bp->edge_color);
+
+        glBegin (GL_QUADS);
+        glVertex3f (0, 0, z);                  /* left */
+        glVertex3f (m, 0, z);
+        glVertex3f (m, height, z);
+        glVertex3f (0, height, z);
+        polys++;
+
+        glVertex3f (1-m, 0, 0);                        /* right */
+        glVertex3f (1,   0, 0);
+        glVertex3f (1,   height, z);
+        glVertex3f (1-m, height, z);
+        polys++;
+
+        glVertex3f (m,   0, 0);                        /* bottom */
+        glVertex3f (1-m, 0, 0);
+        glVertex3f (1-m, m, 0);
+        glVertex3f (m,   m, 0);
+        polys++;
+
+        glVertex3f (m,   height-m, z);         /* top */
+        glVertex3f (1-m, height-m, z);
+        glVertex3f (1-m, height,   z);
+        glVertex3f (m,   height,   z);
+        polys++;
+        glEnd();
+
+        if (do_tex) glEnable (GL_TEXTURE_2D);
+      }
+    break;
+  case 1:
+    polys += draw_tower_face_text (mi, height, 0);
+    break;
+  case 2:
+    polys += draw_tower_face_text (mi, height * 0.7, 1);
+    break;
+  default:
+    abort();
+    break;
+  }
+
+  return polys;
+}
+
+
+/* Mode 0: draws 5 sides of the box
+   Mode 1: just background text
+   Mode 2: just foreground text
+ */
+static int
+draw_tower (ModeInfo *mi, tower *t, int mode, int face)
+{
+  GLfloat height = grid_height;
+
+  int polys = 0;
+
+  glPushMatrix();
+  glTranslatef (-0.5, 0.5, 0);
+
+  if (face == 0 || face == -1)
+    {
+      glPushMatrix();                          /* top */
+      glTranslatef (0, 0, height);
+      polys += draw_tower_face (mi, 1.0, mode);
+      glPopMatrix();
+    }
+
+  if (face == 1 || face == -1)
+    {
+      glPushMatrix();                          /* left */
+      glRotatef ( 90, 1, 0, 0);
+      glRotatef (-90, 0, 1, 0);
+      glTranslatef (-1, 0, 0);
+      polys += draw_tower_face (mi, height, mode);
+      glPopMatrix();
+    }
+
+  if (face == 2 || face == -1)
+    {
+      glPushMatrix();                          /* back */
+      glRotatef ( 90, 1, 0, 0);
+      glRotatef (180, 0, 1, 0);
+      glTranslatef (-1, 0, 1);
+      polys += draw_tower_face (mi, height, mode);
+      glPopMatrix();
+    }
+
+  if (face == 3 || face == -1)
+    {
+      glPushMatrix();                          /* right */
+      glRotatef ( 90, 1, 0, 0);
+      glRotatef ( 90, 0, 1, 0);
+      glTranslatef (0, 0, 1);
+      polys += draw_tower_face (mi, height, mode);
+      glPopMatrix();
+    }
+
+  if (face == 4 || face == -1)
+    {
+      glPushMatrix();                          /* front */
+      glRotatef ( 90, 1, 0, 0);
+      polys += draw_tower_face (mi, height, mode);
+      glPopMatrix();
+    }
+
+  if (face < -1 || face > 4) abort();
+
+  glPopMatrix();
+  return polys;
+}
+
+
+static void
+animate_towers (ModeInfo *mi)
+{
+  gibson_configuration *bp = &ccs[MI_SCREEN(mi)];
+  int ii;
+  GLfloat min = -3;
+  GLfloat max = grid_depth * (1 + grid_spacing) - grid_spacing - 1;
+  GLfloat yspeed = speed * 0.05;
+
+  for (ii = 0; ii < 20; ii++)
+    {
+      int jj, kk;
+
+      /* randomly trade two towers' fg dlists */
+      if (0 == (random() % 20))
+        {
+          int i = random() % bp->ntowers;
+          int j = random() % bp->ntowers;
+          int k = random() % countof(bp->towers[i].fg_dlists);
+          GLuint d1 = bp->towers[i].bg_dlists[k];
+          GLuint d2 = bp->towers[j].bg_dlists[k];
+          bp->towers[i].bg_dlists[k] = d2;
+          bp->towers[j].bg_dlists[k] = d1;
+        }
+
+      /* randomly trade two towers' bg dlists */
+      if (1) /* (0 == (random() % 3)) */
+        {
+          int i = random() % bp->ntowers;
+          int j = random() % bp->ntowers;
+          int k = random() % countof(bp->towers[i].fg_dlists);
+          GLuint d1 = bp->towers[i].fg_dlists[k];
+          GLuint d2 = bp->towers[j].fg_dlists[k];
+          bp->towers[i].fg_dlists[k] = d2;
+          bp->towers[j].fg_dlists[k] = d1;
+        }
+
+      /* Randomize whether it's displaying fg text or bg text */
+      for (jj = 0; jj < bp->ntowers; jj++)
+        for (kk = 0; kk < countof(bp->towers[jj].fg_dlists); kk++)
+          {
+            /* Re-choose every N frames.  Display fg 1 in M. */
+            int frames = 500;
+            int fg_chance = (kk == 0 ? 100000 : 10);
+            unsigned int o = !!(bp->towers[jj].face_mode & (1 << kk));
+            unsigned int n = !!((random() % frames) ? o : 
+                                (0 == (random() % fg_chance)));
+            bp->towers[jj].face_mode =
+              ((bp->towers[jj].face_mode & ~(1 << kk)) | (n << kk));
+          }
+    }
+
+  for (ii = 0; ii < bp->ntowers; ii++)
+    {
+      tower *t = &bp->towers[ii];
+      t->h += speed * 0.01;
+      if (t->h > 1) t->h = 1;
+
+      t->y -= yspeed;
+
+      if (t->y < min)
+        {
+          t->h = 0;
+          t->y = max;
+        }
+    }
+
+  /* Sorting by depth improves frame rate slightly. */
+  qsort (bp->towers, bp->ntowers, sizeof(*bp->towers), cmp_towers);
+
+  bp->ground_y -= yspeed / GROUND_QUAD_SIZE;
+  if (bp->ground_y < 1)
+    bp->ground_y += 1;
+
+  bp->billboard_y -= yspeed;
+  if (bp->billboard_y < min || !bp->billboard_text)
+    {
+      const char *const ss[] = {
+        "ACCESS GRANTED",
+        "ACCESS GRANTED",
+        "ACCESS DENIED",
+        "ACCESS DENIED",
+        "ACCESS DENIED",
+        "ACCESS DENIED",
+        "ACCESS DENIED",
+        "PASSWORD ACCEPTED",
+        " GIVE ME\nA COOKIE",
+        "MESS WITH THE BEST\n  DIE LIKE THE REST",
+      };
+
+      bp->billboard_y = max * (1 + frand(8));
+      bp->billboard_text = ss[random() % countof(ss)];
+    }
+}
+
+
+static int
+draw_billboard (ModeInfo *mi)
+{
+  gibson_configuration *bp = &ccs[MI_SCREEN(mi)];
+  int polys = 0;
+  int wire = MI_IS_WIREFRAME(mi);
+  GLfloat w, h, s, margin, margin2;
+  XCharStruct metrics;
+  int ascent, descent;
+  texture_font_data *font = bp->text[1].font_data;
+  GLfloat color[4];
+  GLfloat y = grid_height * 0.3;
+
+  texture_string_metrics (font, bp->billboard_text,
+                          &metrics, &ascent, &descent);
+  w = metrics.lbearing + metrics.rbearing;
+  h = metrics.ascent   + metrics.descent;
+  s = 1.0 / w;
+  s *= 0.95;
+
+  margin = w * 0.1;
+  margin2 = margin * 1.7;
+
+  glPushMatrix();
+
+  glTranslatef (-0.5, bp->billboard_y, y);
+  glRotatef (90, 1, 0, 0);
+  glScalef (s, s * 1.5, s);
+
+  memcpy (color, bp->tower_color2, sizeof(color));
+  color[3] = 0.6;
+  glColor4fv (color);
+  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
+
+  if (do_tex && !wire)
+    glDisable (GL_TEXTURE_2D);
+
+  glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
+  glNormal3f (0, 0, 1);
+  glVertex3f (-margin,  -margin2,  0);
+  glVertex3f (-margin,  h+margin2, 0);
+  glVertex3f (w+margin, h+margin2, 0);
+  glVertex3f (w+margin, -margin2,  0);
+  glEnd();
+  polys++;
+
+  if (do_tex && !wire)
+    {
+      color[3] = 1;
+      glColor4fv (color);
+      glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
+      glEnable (GL_TEXTURE_2D);
+      glTranslatef (-metrics.lbearing, metrics.descent, 0);
+      print_texture_string (font, bp->billboard_text);
+      polys++;
+    }
+
+  glPopMatrix();
+  return polys;
+}
+
+
+static void
+init_text (ModeInfo *mi)
+{
+  gibson_configuration *bp = &ccs[MI_SCREEN(mi)];
+  int lines = 20;
+  int i;
+  char *s;
+
+  const char *const ss[] = {
+   "\n"
+   "ACCESS TO THIS COMPUTER AND\n"
+   "ITS DATA IS RESTRICTED TO\n"
+   "AUTHORIZED PERSONNEL ONLY\n"
+   "\n",
+   "\n"
+   "  PASSWORD ACCEPTED\n"
+   "             GOD\n"
+   "\n",
+   "PERSONNEL   >>>\n",
+   "SEA ROUTINGS   >>>\n",
+   "GARBAGE   >>>\n",
+   "COMP. SERVICING   >>>\n",
+   "COMPANY BUDGETS   >>>\n",
+   "SCIENTIFIC BUDGETS   >>>\n",
+   "COMPANY POLICIES   >>>\n",
+   "ANNUAL RETURNS   >>>\n",
+   "MINE RESEARCH   >>>\n",
+   "CENTRAL LIBRARY   >>>\n",
+   "QUANTATIVE SPEC.   >>>\n",
+   "PAYMENT LEVELS   >>>\n",
+   "CENTRAL SERVER   >>>\n",
+   "GARBAGE   >>>\n",
+   "KNMTS. DVPNT.   >>>\n",
+   "LICENSING   >>>\n",
+   "RELATIONS   >>>\n",
+   "TIME SHEET RECS.   >>>\n",
+   "RD. PRT. ROUTINGS   >>>\n",
+   "RECRUITMENT   >>>\n",
+   "TNKR. EXPENDITURE   >>>\n",
+   "MINE DEVELOPMENT   >>>\n",
+   "GARBAGE   >>>\n",
+   "ANNUAL BUDGETS   >>>\n",
+   "OIL LOCATIONS   >>>\n",
+   "TIME SHEET RECS.   >>>\n",
+   "RD. PRT. ROUTINGS   >>>\n",
+   "KINEMATICS   >>>\n",
+   "TPS. REPORTS   >>>\n",
+   "BLAST FRNC. STATUS   >>>\n",
+   "ACCOUNTANTS   >>>\n",
+   "SHIPPING FORCASTS   >>>\n",
+   "INDST. REPORTS   >>>\n",
+   "EXPLOR. DVLT.   >>>\n",
+   "WRHSE. EXPEND.   >>>\n",
+   "GARBAGE   >>>\n",
+   "RELOCATIONS   >>>\n",
+   "AIRFREIGHT STATUS   >>>\n",
+   "TPGC. EXPEND.   >>>\n",
+   "SEA-BOARD LAWS   >>>\n",
+   "COMPOSITE PLANTS   >>>\n",
+   "NUCLEAR RESEARCH   >>>\n",
+   "BALLAST REPORTS   >>>\n",
+   "\n"
+   "CONFIDENTAL\n"
+   "FILES\n"
+   "DO NOT DELETE\n"
+   "BEFORE FINAL\n"
+   "BACKUP IS COMPLETED\n"
+   "\n",
+   "\n"
+   "FILE 1\n"
+   "WAITING FOR BACK-UP\n"
+   "\n"
+   "FILE 2\n"
+   "WAITING FOR BACK-UP\n"
+   "\n"
+   "FILE 3\n"
+   "WAITING FOR BACK-UP\n"
+   "\n"
+   "FILE 4\n"
+   "WAITING FOR BACK-UP\n"
+   "\n"
+   };
+
+
+  bp->text[1].text = s = calloc (countof(ss) * 2 * 40, 1);
+  for (i = 0; i < countof(ss); i++)
+    {
+      int n = random() % countof(ss);
+      strcat (s, ss[n]);
+      s += strlen(s);
+    }
+
+  bp->text[0].text = s = calloc (lines * 40, 1);
+  for (i = 0; i < lines; i++)
+    {
+      switch (random() % 11) {
+      case 0: sprintf (s, "%X\n", random() % 0xFFFFFFFF); break;
+      case 1: sprintf (s, "%X\n", random() % 0xFFFFFF); break;
+      case 2: sprintf (s, "%X\n", random() % 0xFFFF); break;
+      case 3: sprintf (s, "%d\n", random() % 0xFFFFFF); break;
+      case 4: sprintf (s, "%d\n", random() % 0xFFFF); break;
+      case 5: sprintf (s, "%d\n", random() % 0xFFF); break;
+      case 6: strcat (s, "00000000\n"); break;
+      case 7: sprintf (s, "{{{{{{{{\n"); break;
+      case 8: sprintf (s, "[][][][][][]\n"); break;
+      case 9: sprintf (s, "DEFAULT\n"); break;
+      case 10: sprintf (s, "\n"); break;
+      }
+      s += strlen(s);
+    }
+}
+
+
+static void
+init_textures (ModeInfo *mi)
+{
+  gibson_configuration *bp = &ccs[MI_SCREEN(mi)];
+  int i;
+  for (i = 0; i < countof(bp->text); i++)
+    {
+      glGenTextures (1, &bp->text[i].texid);
+      glBindTexture (GL_TEXTURE_2D, bp->text[i].texid);
+      texture_string_metrics (bp->text[i].font_data, " ",
+                              &bp->text[i].metrics,
+                              &bp->text[i].ascent,
+                              &bp->text[i].descent);
+      bp->text[i].em_width = bp->text[i].metrics.width;
+      string_to_texture (bp->text[i].font_data, bp->text[i].text,
+                         &bp->text[i].metrics,
+                         &bp->text[i].width,
+                         &bp->text[i].height);
+    }
+  glBindTexture (GL_TEXTURE_2D, 0);
+}
+
+
+ENTRYPOINT void 
+init_gibson (ModeInfo *mi)
+{
+  gibson_configuration *bp;
+
+  MI_INIT (mi, ccs);
+
+  bp = &ccs[MI_SCREEN(mi)];
+
+  if ((bp->glx_context = init_GL(mi)) != NULL) {
+    reshape_gibson (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+  }
+
+  parse_color (mi, "towerText",  bp->tower_color);
+  parse_color (mi, "towerText2", bp->tower_color2);
+  parse_color (mi, "towerColor", bp->bg_color);
+  memcpy (bp->edge_color, bp->bg_color, sizeof(bp->tower_color));
+  bp->edge_color  [3] = 0.7;
+  bp->bg_color    [3] = 1.0;
+  bp->tower_color [3] = 1.0;
+  bp->tower_color2[3] = 1.0;
+
+  if (grid_spacing < 1) grid_spacing = 1;
+  if (grid_width   < 1) grid_width   = 1;
+  if (grid_height  < 1) grid_height  = 1;
+  if (grid_depth   < 1) grid_depth   = 1;
+  if (columns      < 1) columns      = 1;
+  bp->ntowers = grid_width * grid_depth;
+  bp->towers = (tower *) calloc (sizeof(tower), bp->ntowers);
+  bp->startup_p = True;
+
+  {
+    double wander_speed = 0.007 * speed;
+    double tilt_speed   = 0.01 * speed;
+    bp->rot  = make_rotator (0, 0, 0, 0, wander_speed, True);
+    bp->rot2 = make_rotator (0, 0, 0, 0, tilt_speed,   True);
+  }
+
+  bp->text[0].font_data = load_texture_font (mi->dpy, "towerFont");
+  bp->text[1].font_data = load_texture_font (mi->dpy, "towerFont");
+  init_text (mi);
+  init_textures (mi);
+
+  bp->ground_dlist = glGenLists (1);
+  glNewList (bp->ground_dlist, GL_COMPILE);
+  bp->ground_polys = draw_ground (mi);
+  glEndList ();
+
+  bp->tower_dlist = glGenLists (1);
+  glNewList (bp->tower_dlist, GL_COMPILE);
+  bp->tower_polys = draw_tower (mi, &bp->towers[0], 0, -1);
+  glEndList ();
+
+  {
+    int x, y;
+    GLfloat ww = grid_width * (1 + grid_spacing) - grid_spacing;
+    GLfloat hh = grid_depth * (1 + grid_spacing) - grid_spacing;
+    for (y = 0; y < grid_depth; y++)
+      for (x = 0; x < grid_width; x++)
+        {
+          int i;
+          tower *t = &bp->towers[y * grid_width + x];
+          t->x = (x * ww / (grid_width - 1)) - ww/2;
+          t->y = (y * hh / grid_depth) + 6;
+          t->h = 0 - y / (GLfloat) grid_depth / 2;
+
+          for (i = 0; i < countof(t->fg_dlists); i++)
+            {
+              t->bg_dlists[i] = glGenLists (1);
+              glNewList (t->bg_dlists[i], GL_COMPILE);
+              t->bg_polys = draw_tower (mi, t, 1, i);
+              glEndList ();
+
+              t->fg_dlists[i] = glGenLists (1);
+              glNewList (t->fg_dlists[i], GL_COMPILE);
+              t->fg_polys += draw_tower (mi, t, 2, i);
+              glEndList ();
+            }
+        }
+  }
+
+  animate_towers (mi);
+}
+
+
+ENTRYPOINT void
+draw_gibson (ModeInfo *mi)
+{
+  gibson_configuration *bp = &ccs[MI_SCREEN(mi)];
+  Display *dpy = MI_DISPLAY(mi);
+  Window window = MI_WINDOW(mi);
+  int wire = MI_IS_WIREFRAME(mi);
+  GLfloat s;
+  int i;
+
+  static const GLfloat bspec[4]  = {1.0, 1.0, 1.0, 1.0};
+  static const GLfloat bshiny    = 128.0;
+  GLfloat bcolor[4] = { 0.7, 0.7, 1.0, 1.0 };
+
+  if (!bp->glx_context)
+    return;
+
+  mi->polygon_count = 0;
+  glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *bp->glx_context);
+
+  glShadeModel (GL_SMOOTH);
+  glEnable (GL_NORMALIZE);
+  glEnable (GL_CULL_FACE);
+  glDisable (GL_TEXTURE_2D);
+  glEnable (GL_DEPTH_TEST);
+
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  if (!wire)
+    {
+      GLfloat pos[4] = {0.4, 0.2, 0.4, 0.0};
+      GLfloat amb[4] = {0.2, 0.2, 0.2, 1.0};
+      GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0};
+      GLfloat spc[4] = {1.0, 1.0, 1.0, 1.0};
+
+      glEnable(GL_LIGHTING);
+      glEnable(GL_LIGHT0);
+      glLightfv(GL_LIGHT0, GL_POSITION, pos);
+      glLightfv(GL_LIGHT0, GL_AMBIENT,  amb);
+      glLightfv(GL_LIGHT0, GL_DIFFUSE,  dif);
+      glLightfv(GL_LIGHT0, GL_SPECULAR, spc);
+    }
+
+  glPushMatrix ();
+
+  glRotatef(current_device_rotation(), 0, 0, 1);
+
+# ifdef DEBUG
+  s = 0.02;
+# else
+  s = 10;
+# endif
+
+  glScalef (s, s, s);
+
+  glTranslatef (0, -1, 0);
+
+# ifndef DEBUG
+  glRotatef (-82, 1, 0, 0);
+
+  {
+    double maxx = 40;   /* up/down */
+    double maxy = 1.5;  /* tilt */
+    double maxz = 100;  /* left/right */
+
+    double x, y, z;
+    double minh = -(grid_height / 2.0);
+    double maxh = -(grid_height / 20.0);
+
+    get_position (bp->rot, &x, &y, &z, !bp->button_down_p);
+    x -= 0.5;
+    z = minh + (z * (maxh - minh));
+    glTranslatef(x * grid_spacing * 0.005, 0, z);
+
+    get_position (bp->rot2, &x, &y, &z, !bp->button_down_p);
+
+    z += (bp->xscroll / 2.0);
+    x += (bp->yscroll / 2.0);
+
+    glRotatef (maxx/2 - x*maxx, 1, 0, 0);
+    glRotatef (maxy/2 - y*maxy, 0, 1, 0);
+    glRotatef (maxz/2 - z*maxz, 0, 0, 1);
+  }
+# endif /* DEBUG */
+
+  glPushMatrix();
+  glScalef (GROUND_QUAD_SIZE, GROUND_QUAD_SIZE, 1);
+
+  glTranslatef (0, bp->ground_y - 1.5, 0);
+  glCallList (bp->ground_dlist);
+  mi->polygon_count += bp->ground_polys;
+
+  glTranslatef (0, 1, 0);
+  glCallList (bp->ground_dlist);
+  mi->polygon_count += bp->ground_polys;
+  glPopMatrix();
+
+  glMaterialfv (GL_FRONT, GL_SPECULAR,            bspec);
+  glMateriali  (GL_FRONT, GL_SHININESS,           bshiny);
+  glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, bcolor);
+
+  glPushMatrix();
+
+  if (grid_width & 1)  /* Stay between towers */
+    glTranslatef ((grid_spacing + 1) / 2.0, 0, 0);
+
+
+  if (!wire)
+    {
+      GLfloat fog_color[4] = { 0, 0, 0, 1 };
+      glFogfv (GL_FOG_COLOR, fog_color);
+      /* I so don't understand how to choose the fog parameters. */
+      glFogi (GL_FOG_MODE, GL_LINEAR);
+      glFogf (GL_FOG_START, 0);
+      glFogf (GL_FOG_END, 100);
+      glEnable (GL_FOG);
+    }
+
+  /* Clear the floor under the tower bases */
+
+  {
+    GLfloat color0[4] = { 0, 0, 0, 1 };
+    GLfloat z = 0.01;
+
+    if (do_tex && !wire) glDisable (GL_TEXTURE_2D);
+    glColor4fv (color0);
+    glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color0);
+    glDisable (GL_BLEND);
+    glDisable (GL_DEPTH_TEST);
+
+    for (i = 0; i < bp->ntowers; i++)
+      {
+        tower *t = &bp->towers[i];
+        glPushMatrix();
+        glTranslatef (t->x, t->y, 0);
+
+        glNormal3f (0, 0, 1);
+        glBegin (wire ? GL_LINE_LOOP : GL_QUADS);      /* clipping quad */
+        glVertex3f (-0.5, -0.5, z);
+        glVertex3f ( 0.5, -0.5, z);
+        glVertex3f ( 0.5,  0.5, z);
+        glVertex3f (-0.5,  0.5, z);
+        glEnd();
+        mi->polygon_count++;
+        glPopMatrix();
+      }
+  }
+
+  glEnable (GL_DEPTH_TEST);
+
+  if (!wire)
+    {
+      if (do_tex)
+        {
+          glEnable (GL_TEXTURE_2D);
+          enable_texture_string_parameters();
+        }
+      glEnable (GL_BLEND);
+      glBlendFunc (GL_SRC_ALPHA, GL_ONE);
+      glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+      glDisable (GL_CULL_FACE);
+      if (bp->startup_p)
+        glEnable (GL_DEPTH_TEST);
+      else
+        glDisable (GL_DEPTH_TEST);
+    }
+
+  /* Draw the towers */
+
+  for (i = 0; i < bp->ntowers; i++)
+    {
+      tower *t = &bp->towers[i];
+      glPushMatrix();
+      glTranslatef (t->x, t->y-1, -grid_height * ease_ratio (1 - t->h));
+
+      glCallList (bp->tower_dlist);
+      mi->polygon_count += bp->tower_polys;
+
+      if (wire || do_tex)
+        {
+          int j;
+          for (j = 0; j < countof(t->fg_dlists); j++)
+            {
+              if (! (t->face_mode & (1 << j)))
+                {
+                  glCallList (t->bg_dlists[j]);
+                  mi->polygon_count += t->bg_polys;
+                }
+              else
+                {
+                  glCallList (t->fg_dlists[j]);
+                  mi->polygon_count += t->fg_polys;
+                }
+            }
+        }
+      glPopMatrix();
+    }
+
+  glPopMatrix();
+
+  mi->polygon_count += draw_billboard (mi);
+  glPopMatrix();
+
+  if (!bp->button_down_p)
+    animate_towers (mi);
+
+  if (bp->startup_p && bp->towers[bp->ntowers-1].h >= 1)
+    bp->startup_p = False;
+
+  if (mi->fps_p) do_fps (mi);
+  glFinish();
+
+  glXSwapBuffers(dpy, window);
+}
+
+
+ENTRYPOINT void
+free_gibson (ModeInfo *mi)
+{
+  int i, j;
+  gibson_configuration *bp = &ccs[MI_SCREEN(mi)];
+  if (!bp->glx_context) return;
+  glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *bp->glx_context);
+
+  if (bp->towers) free (bp->towers);
+  if (bp->rot)  free_rotator (bp->rot);
+  if (bp->rot2) free_rotator (bp->rot2);
+  if (glIsList(bp->ground_dlist)) glDeleteLists(bp->ground_dlist, 1);
+  if (glIsList(bp->tower_dlist)) glDeleteLists(bp->tower_dlist, 1);
+  for (i = 0; i < countof(bp->text); i++)
+    {
+      if (bp->text[i].font_data) free_texture_font (bp->text[i].font_data);
+      if (bp->text[i].text) free (bp->text[i].text);
+    }
+  for (i = 0; i < bp->ntowers; i++)
+    {
+      for (j = 0; j < countof(bp->towers[i].fg_dlists); j++)
+        {
+          if (glIsList(bp->towers[i].fg_dlists[j]))
+            glDeleteLists(bp->towers[i].fg_dlists[j], 1);
+          if (glIsList(bp->towers[i].bg_dlists[j]))
+            glDeleteLists(bp->towers[i].bg_dlists[j], 1);
+        }
+    }
+}
+
+
+XSCREENSAVER_MODULE ("Gibson", gibson)
+/* Greets to Crash Override, The Phantom Freak, and also Joey */
+
+#endif /* USE_GL */
diff --git a/hacks/glx/gibson.man b/hacks/glx/gibson.man
new file mode 100644 (file)
index 0000000..a57e018
--- /dev/null
@@ -0,0 +1,88 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+Hacking the Gibson - screen saver.
+.SH SYNOPSIS
+.B gibson
+[\-display \fIhost:display.screen\fP]
+[\-visual \fIvisual\fP]
+[\-window]
+[\-root]
+[\-delay \fInumber\fP]
+[\-speed \fInumber\fP]
+[\-grid-width \fInumber\fP]
+[\-grid-depth \fInumber\fP]
+[\-grid-height \fInumber\fP]
+[\-grid-spacing \fInumber\fP]
+[\-columns \fInumber\fP]
+[\-no-texture]
+[\-wireframe]
+[\-fps]
+.SH DESCRIPTION
+Hacking the Gibson, as per the 1995 classic film, \fIHACKERS\fP.
+
+"Hackers penetrate and ravage delicate public and privately owned
+computer systems, infecting them with viruses, and stealing materials
+for their own ends. These people, they are terrorists."
+.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 \-grid-width \fInumber\fP
+Number of towers across.  1 - 20.  Default: 10.
+.TP 8
+.B \-grid-depth \fInumber\fP
+Number of towers deep.  1 - 20.  Default: 10.
+.TP 8
+.B \-grid-height \fInumber\fP
+Height of the towers.  1 - 20.  Default: 7.
+.TP 8
+.B \-grid-spacing \fInumber\fP
+Space between towers.  1 - 5.  Default: 2.0.
+.TP 8
+.B \-columns \fInumber\fP
+Columns of text on the towers.  1 - 20.        Default: 6.
+.TP 8
+.B \-texture | \-no-texture
+Whether to draw text.  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)
+.SH COPYRIGHT
+Copyright \(co 2020 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 46cdc68e254131b7e02a505549f51c9aa2072091..11ac75ff8baa339d36c8ec0733dc8e63e5c8ada2 100644 (file)
@@ -1424,13 +1424,14 @@ static GLubyte *makeTexture(glhcfg *glhanoi, int x_size, int y_size, int z_size,
                                                                           tex_col_t *), tex_col_t * colours)
 {
        int i, j, k;
-       GLubyte *textureData;
+       GLuint *textureData;
        GLuint *texturePtr;
        double x, y, z;
        double xi, yi, zi;
 
+       /* As we use GL_RGBA format, we must assign 4 bytes per element */
        if((textureData =
-               calloc(x_size * y_size * z_size, sizeof(GLubyte))) == NULL) {
+               calloc(x_size * y_size * z_size, sizeof(*texturePtr))) == NULL) {
                return NULL;
        }
 
@@ -1439,7 +1440,7 @@ static GLubyte *makeTexture(glhcfg *glhanoi, int x_size, int y_size, int z_size,
        zi = 1.0 / z_size;
 
        z = 0.0;
-       texturePtr = (void *)textureData;
+       texturePtr = textureData;
        for(k = 0; k < z_size; k++, z += zi) {
                y = 0.0;
                for(j = 0; j < y_size; j++, y += yi) {
@@ -1450,7 +1451,7 @@ static GLubyte *makeTexture(glhcfg *glhanoi, int x_size, int y_size, int z_size,
                        }
                }
        }
-       return textureData;
+       return (GLubyte *)textureData;
 }
 
 static void freeTexCols(tex_col_t*p)
index 1e1c4f6d004f6998658725ad7d97ffe5a35be3f3..a638583624f708ad2fb5f1e6549237b7ac43729f 100644 (file)
@@ -251,7 +251,7 @@ reset_strip (ModeInfo *mi, strip *s)
     if (do_clock &&
         !time_displayed_p &&
         (i < GRID_SIZE-5) &&   /* display approx. once per 5 strips */
-       !(random() % (GRID_SIZE-5)*5))
+       !(random() % ((GRID_SIZE-5)*5)))
       {
        int j;
        char text[80];
index 70787646a1a952d75124fb1643f8d17f223a020a..90edcf0b7bb4d52806c2b49bb97df094d701f4fa 100644 (file)
@@ -430,6 +430,8 @@ draw_row (ModeInfo *mi, int w, int y, Bool swap)
           polys += 1;
 
           ci = EASE (bp->vtx[vp + 2] / MAX_MASS_COLOR) * bp->ncolors;
+          if (ci < 0) ci = 0;
+          if (ci >= bp->ncolors) ci = bp->ncolors - 1;
           bp->col[cp]   = bp->colors[ci].red   / 65536.0;
           bp->col[cp+1] = bp->colors[ci].green / 65536.0;
           bp->col[cp+2] = bp->colors[ci].blue  / 65536.0;
@@ -452,6 +454,8 @@ draw_row (ModeInfo *mi, int w, int y, Bool swap)
               bp->vtx[vp + 2] = gridp[x * GRID_SEG + i];
 
               ci = EASE (bp->vtx[vp + 2] / MAX_MASS_COLOR) * bp->ncolors;
+              if (ci < 0) ci = 0;
+              if (ci >= bp->ncolors) ci = bp->ncolors - 1;
               bp->col[cp]   = bp->colors[ci].red   / 65536.0;
               bp->col[cp+1] = bp->colors[ci].green / 65536.0;
               bp->col[cp+2] = bp->colors[ci].blue  / 65536.0;
@@ -689,6 +693,8 @@ draw_gw (ModeInfo *mi)
       GLfloat th, color[4];
       int ci;
       ci = EASE (s->depth / MAX_MASS_COLOR) * bp->ncolors;
+      if (ci < 0) ci = 0;
+      if (ci >= bp->ncolors) ci = bp->ncolors - 1;
       color[0] = bp->colors[ci].red   / 65536.0;
       color[1] = bp->colors[ci].green / 65536.0;
       color[2] = bp->colors[ci].blue  / 65536.0;
index 8aa8d4dc593bb5061eb07ebd04bef4e580ca5684..41f4e0aa3b9b4bebf6ec6c342bb0e4da8ccb0b7b 100644 (file)
@@ -1,10 +1,10 @@
 /* hypertorus --- Shows a hypertorus that rotates in 4d */
 
 #if 0
-static const char sccsid[] = "@(#)hypertorus.c  1.2 05/09/28 xlockmore";
+static const char sccsid[] = "@(#)hypertorus.c  1.2 28/09/05 xlockmore";
 #endif
 
-/* Copyright (c) 2003-2009 Carsten Steger <carsten@mirsanmir.org>. */
+/* Copyright (c) 2003-2020 Carsten Steger <carsten@mirsanmir.org>. */
 
 /*
  * Permission to use, copy, modify, and distribute this software and its
@@ -25,30 +25,44 @@ static const char sccsid[] = "@(#)hypertorus.c  1.2 05/09/28 xlockmore";
  *                       and trackball support
  * C. Steger - 07/01/23: Improved 4d trackball support
  * C. Steger - 09/08/22: Removed check-config.pl warnings
+ * C. Steger - 11/01/20: Added the changing colors mode.
  */
 
 /*
- * This program shows the Clifford torus as it rotates in 4d.  The Clifford
- * torus is a torus lies on the "surface" of the hypersphere in 4d.  The
- * program projects the 4d torus to 3d using either a perspective or an
- * orthographic projection.  Of the two alternatives, the perspecitve
- * projection looks much more appealing.  In orthographic projections the
- * torus degenerates into a doubly covered cylinder for some angles.  The
- * projected 3d torus can then be projected to the screen either perspectively
- * or orthographically.  There are three display modes for the torus: mesh
- * (wireframe), solid, or transparent.  Furthermore, the appearance of the
- * torus can be as a solid object or as a set of see-through bands or
- * see-through spirals.  Finally, the colors with with the torus is drawn can
- * be set to either two-sided or to colorwheel.  In the first case, the torus
- * is drawn with red on the outside and green on the inside.  This mode
- * enables you to see that the torus turns inside-out as it rotates in 4d.
- * The second mode draws the torus in a fully saturated color wheel.  This
- * gives a very nice effect when combined with the see-through bands or
- * see-through spirals mode.  The rotation speed for each of the six planes
- * around which the torus rotates can be chosen.  This program is very much
- * inspired by Thomas Banchoff's book "Beyond the Third Dimension: Geometry,
- * Computer Graphics, and Higher Dimensions", Scientific American Library,
- * 1990.
+ * This program shows the Clifford torus as it rotates in 4d.  The
+ * Clifford torus is a torus lies on the "surface" of the hypersphere
+ * in 4d.  The program projects the 4d torus to 3d using either a
+ * perspective or an orthographic projection.  Of the two
+ * alternatives, the perspective projection looks much more appealing.
+ * In orthographic projections the torus degenerates into a doubly
+ * covered cylinder for some angles.  The projected 3d torus can then
+ * be projected to the screen either perspectively or
+ * orthographically.
+ *
+ * There are three display modes for the torus: mesh (wireframe),
+ * solid, or transparent.  Furthermore, the appearance of the torus
+ * can be as a solid object or as a set of see-through bands or
+ * see-through spirals.  Finally, the colors with with the torus is
+ * drawn can be set to one-sided, two-sided, or to a color wheel.  The
+ * colors can be static or changing dynamically.  In one-sided color
+ * mode, the torus is drawn with the same color on the inside and the
+ * outside.  In two-sided color mode, the torus is drawn with red on
+ * the outside and green on the inside if static colors are used.  If
+ * changing colors are used, dynamically varying complementary colors
+ * are used for the two sides.  This mode enables you to see that the
+ * 3d projection of the torus turns inside-out as it rotates in 4d.
+ * The color wheel mode draws the torus with a fully saturated color
+ * wheel.  If changing colors are used, the colors of the color wheel
+ * are varying dynamically.  The color wheel mode gives a very nice
+ * effect when combined with the see-through bands or see-through
+ * spirals mode.
+ *
+ * Finally, the rotation speed for each of the six planes around which
+ * the torus rotates can be chosen.
+ *
+ * This program is inspired by Thomas Banchoff's book "Beyond the
+ * Third Dimension: Geometry, Computer Graphics, and Higher
+ * Dimensions", Scientific American Library, 1990.
  */
 
 #ifndef M_PI
@@ -63,8 +77,9 @@ static const char sccsid[] = "@(#)hypertorus.c  1.2 05/09/28 xlockmore";
 #define APPEARANCE_BANDS           1
 #define APPEARANCE_SPIRALS         2
 
-#define COLORS_TWOSIDED            0
-#define COLORS_COLORWHEEL          1
+#define COLORS_ONESIDED            0
+#define COLORS_TWOSIDED            1
+#define COLORS_COLORWHEEL          2
 
 #define DISP_3D_PERSPECTIVE        0
 #define DISP_3D_ORTHOGRAPHIC       1
@@ -75,6 +90,7 @@ static const char sccsid[] = "@(#)hypertorus.c  1.2 05/09/28 xlockmore";
 #define DEF_DISPLAY_MODE           "surface"
 #define DEF_APPEARANCE             "bands"
 #define DEF_COLORS                 "colorwheel"
+#define DEF_CHANGE_COLORS          "False"
 #define DEF_PROJECTION_3D          "perspective"
 #define DEF_PROJECTION_4D          "perspective"
 #define DEF_SPEEDWX                "1.1"
@@ -117,6 +133,7 @@ static int appearance;
 static int num_spirals;
 static char *color_mode;
 static int colors;
+static Bool change_colors;
 static char *proj_3d;
 static int projection_3d;
 static char *proj_4d;
@@ -146,8 +163,11 @@ static XrmOptionDescRec opts[] =
   {"-spirals-4",       ".appearance",   XrmoptionNoArg,  "spirals-4" },
   {"-spirals-8",       ".appearance",   XrmoptionNoArg,  "spirals-8" },
   {"-spirals-16",      ".appearance",   XrmoptionNoArg,  "spirals-16" },
+  {"-onesided",        ".colors",       XrmoptionNoArg,  "onesided" },
   {"-twosided",        ".colors",       XrmoptionNoArg,  "twosided" },
   {"-colorwheel",      ".colors",       XrmoptionNoArg,  "colorwheel" },
+  {"-change-colors",   ".changeColors", XrmoptionNoArg,  "on"},
+  {"+change-colors",   ".changeColors", XrmoptionNoArg,  "off"},
   {"-perspective-3d",  ".projection3d", XrmoptionNoArg,  "perspective" },
   {"-orthographic-3d", ".projection3d", XrmoptionNoArg,  "orthographic" },
   {"-perspective-4d",  ".projection4d", XrmoptionNoArg,  "perspective" },
@@ -162,43 +182,28 @@ static XrmOptionDescRec opts[] =
 
 static argtype vars[] =
 {
-  { &mode,       "displayMode",  "DisplayMode",  DEF_DISPLAY_MODE,  t_String },
-  { &appear,     "appearance",   "Appearance",   DEF_APPEARANCE,    t_String },
-  { &color_mode, "colors",       "Colors",       DEF_COLORS,        t_String },
-  { &proj_3d,    "projection3d", "Projection3d", DEF_PROJECTION_3D, t_String },
-  { &proj_4d,    "projection4d", "Projection4d", DEF_PROJECTION_4D, t_String },
-  { &speed_wx,   "speedwx",      "Speedwx",      DEF_SPEEDWX,       t_Float},
-  { &speed_wy,   "speedwy",      "Speedwy",      DEF_SPEEDWY,       t_Float},
-  { &speed_wz,   "speedwz",      "Speedwz",      DEF_SPEEDWZ,       t_Float},
-  { &speed_xy,   "speedxy",      "Speedxy",      DEF_SPEEDXY,       t_Float},
-  { &speed_xz,   "speedxz",      "Speedxz",      DEF_SPEEDXZ,       t_Float},
-  { &speed_yz,   "speedyz",      "Speedyz",      DEF_SPEEDYZ,       t_Float}
-};
-
-static OptionStruct desc[] =
-{
-  { "-wireframe",       "display the torus as a wireframe mesh" },
-  { "-surface",         "display the torus as a solid surface" },
-  { "-transparent",     "display the torus as a transparent surface" },
-  { "-solid",           "display the torus as a solid object" },
-  { "-bands",           "display the torus as see-through bands" },
-  { "-spirals-{1,2,4,8,16}", "display the torus as see-through spirals" },
-  { "-twosided",        "display the torus with two colors" },
-  { "-colorwheel",      "display the torus with a smooth color wheel" },
-  { "-perspective-3d",  "project the torus perspectively from 3d to 2d" },
-  { "-orthographic-3d", "project the torus orthographically from 3d to 2d" },
-  { "-perspective-4d",  "project the torus perspectively from 4d to 3d" },
-  { "-orthographic-4d", "project the torus orthographically from 4d to 3d" },
-  { "-speed-wx <arg>",  "rotation speed around the wx plane" },
-  { "-speed-wy <arg>",  "rotation speed around the wy plane" },
-  { "-speed-wz <arg>",  "rotation speed around the wz plane" },
-  { "-speed-xy <arg>",  "rotation speed around the xy plane" },
-  { "-speed-xz <arg>",  "rotation speed around the xz plane" },
-  { "-speed-yz <arg>",  "rotation speed around the yz plane" }
+  { &mode,          "displayMode",  "DisplayMode",  DEF_DISPLAY_MODE,  t_String },
+  { &appear,        "appearance",   "Appearance",   DEF_APPEARANCE,    t_String },
+  { &color_mode,    "colors",       "Colors",       DEF_COLORS,        t_String },
+  { &change_colors, "changeColors", "ChangeColors", DEF_CHANGE_COLORS, t_Bool },
+  { &proj_3d,       "projection3d", "Projection3d", DEF_PROJECTION_3D, t_String },
+  { &proj_4d,       "projection4d", "Projection4d", DEF_PROJECTION_4D, t_String },
+  { &speed_wx,      "speedwx",      "Speedwx",      DEF_SPEEDWX,       t_Float},
+  { &speed_wy,      "speedwy",      "Speedwy",      DEF_SPEEDWY,       t_Float},
+  { &speed_wz,      "speedwz",      "Speedwz",      DEF_SPEEDWZ,       t_Float},
+  { &speed_xy,      "speedxy",      "Speedxy",      DEF_SPEEDXY,       t_Float},
+  { &speed_xz,      "speedxz",      "Speedxz",      DEF_SPEEDXZ,       t_Float},
+  { &speed_yz,      "speedyz",      "Speedyz",      DEF_SPEEDYZ,       t_Float}
 };
 
 ENTRYPOINT ModeSpecOpt hypertorus_opts =
-{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
+{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, NULL};
+
+
+/* Color change speeds */
+#define DRHO    0.7
+#define DSIGMA  1.1
+#define DTAU    1.7
 
 
 typedef struct {
@@ -206,15 +211,15 @@ typedef struct {
   GLXContext *glx_context;
   /* 4D rotation angles */
   float alpha, beta, delta, zeta, eta, theta;
+  /* Color rotation angles */
+  float rho, sigma, tau;
   /* Aspect ratio of the current window */
   float aspect;
   /* Trackball states */
   trackball_state *trackballs[2];
   int current_trackball;
   Bool button_pressed;
-
   float speed_scale;
-
 } hypertorusstruct;
 
 static hypertorusstruct *hyper = (hypertorusstruct *) NULL;
@@ -352,6 +357,77 @@ static void rotateall(float al, float be, float de, float ze, float et,
 }
 
 
+/* Add a rotation around the x-axis to the matrix m. */
+static void rotatex(float m[3][3], float phi)
+{
+  float c, s, u, v;
+  int i;
+
+  phi *= M_PI/180.0;
+  c = cos(phi);
+  s = sin(phi);
+  for (i=0; i<3; i++)
+  {
+    u = m[i][1];
+    v = m[i][2];
+    m[i][1] = c*u+s*v;
+    m[i][2] = -s*u+c*v;
+  }
+}
+
+
+/* Add a rotation around the y-axis to the matrix m. */
+static void rotatey(float m[3][3], float phi)
+{
+  float c, s, u, v;
+  int i;
+
+  phi *= M_PI/180.0;
+  c = cos(phi);
+  s = sin(phi);
+  for (i=0; i<3; i++)
+  {
+    u = m[i][0];
+    v = m[i][2];
+    m[i][0] = c*u-s*v;
+    m[i][2] = s*u+c*v;
+  }
+}
+
+
+/* Add a rotation around the z-axis to the matrix m. */
+static void rotatez(float m[3][3], float phi)
+{
+  float c, s, u, v;
+  int i;
+
+  phi *= M_PI/180.0;
+  c = cos(phi);
+  s = sin(phi);
+  for (i=0; i<3; i++)
+  {
+    u = m[i][0];
+    v = m[i][1];
+    m[i][0] = c*u+s*v;
+    m[i][1] = -s*u+c*v;
+  }
+}
+
+
+/* Compute the 3d rotation matrix m from the 3d rotation angles. */
+static void rotateall3d(float al, float be, float de, float m[3][3])
+{
+  int i, j;
+
+  for (i=0; i<3; i++)
+    for (j=0; j<3; j++)
+      m[i][j] = (i==j);
+  rotatex(m,al);
+  rotatey(m,be);
+  rotatez(m,de);
+}
+
+
 /* Multiply two rotation matrices: o=m*n. */
 static void mult_rotmat(float m[4][4], float n[4][4], float o[4][4])
 {
@@ -400,62 +476,84 @@ static void quats_to_rotmat(float p[4], float q[4], float m[4][4])
 
 
 /* Compute a fully saturated and bright color based on an angle. */
-static void color(double angle)
+static void color(double angle, float mat[3][3], float col[4])
 {
   int s;
-  double t;
-  float color[4];
+  double t, ca, sa;
+  float m;
 
-  if (colors != COLORS_COLORWHEEL)
-    return;
+  if (!change_colors)
+  {
+    if (colors == COLORS_ONESIDED || colors == COLORS_TWOSIDED)
+      return;
 
-  if (angle >= 0.0)
-    angle = fmod(angle,2*M_PI);
-  else
-    angle = fmod(angle,-2*M_PI);
-  s = floor(angle/(M_PI/3));
-  t = angle/(M_PI/3)-s;
-  if (s >= 6)
-    s = 0;
-  switch (s)
+    if (angle >= 0.0)
+      angle = fmod(angle,2*M_PI);
+    else
+      angle = fmod(angle,-2*M_PI);
+    s = floor(angle/(M_PI/3));
+    t = angle/(M_PI/3)-s;
+    if (s >= 6)
+      s = 0;
+    switch (s)
+    {
+      case 0:
+        col[0] = 1.0;
+        col[1] = t;
+        col[2] = 0.0;
+        break;
+      case 1:
+        col[0] = 1.0-t;
+        col[1] = 1.0;
+        col[2] = 0.0;
+        break;
+      case 2:
+        col[0] = 0.0;
+        col[1] = 1.0;
+        col[2] = t;
+        break;
+      case 3:
+        col[0] = 0.0;
+        col[1] = 1.0-t;
+        col[2] = 1.0;
+        break;
+      case 4:
+        col[0] = t;
+        col[1] = 0.0;
+        col[2] = 1.0;
+        break;
+      case 5:
+        col[0] = 1.0;
+        col[1] = 0.0;
+        col[2] = 1.0-t;
+        break;
+    }
+  }
+  else /* change_colors */
   {
-    case 0:
-      color[0] = 1.0;
-      color[1] = t;
-      color[2] = 0.0;
-      break;
-    case 1:
-      color[0] = 1.0-t;
-      color[1] = 1.0;
-      color[2] = 0.0;
-      break;
-    case 2:
-      color[0] = 0.0;
-      color[1] = 1.0;
-      color[2] = t;
-      break;
-    case 3:
-      color[0] = 0.0;
-      color[1] = 1.0-t;
-      color[2] = 1.0;
-      break;
-    case 4:
-      color[0] = t;
-      color[1] = 0.0;
-      color[2] = 1.0;
-      break;
-    case 5:
-      color[0] = 1.0;
-      color[1] = 0.0;
-      color[2] = 1.0-t;
-      break;
+    if (colors == COLORS_ONESIDED || colors == COLORS_TWOSIDED)
+    {
+      col[0] = mat[0][2];
+      col[1] = mat[1][2];
+      col[2] = mat[2][2];
+    }
+    else
+    {
+      ca = cos(angle);
+      sa = sin(angle);
+      col[0] = ca*mat[0][0]+sa*mat[0][1];
+      col[1] = ca*mat[1][0]+sa*mat[1][1];
+      col[2] = ca*mat[2][0]+sa*mat[2][1];
+    }
+    m = 0.5f/fmaxf(fmaxf(fabsf(col[0]),fabsf(col[1])),fabsf(col[2]));
+    col[0] = m*col[0]+0.5f;
+    col[1] = m*col[1]+0.5f;
+    col[2] = m*col[2]+0.5f;
   }
   if (display_mode == DISP_TRANSPARENT)
-    color[3] = 0.7;
+    col[3] = 0.7;
   else
-    color[3] = 1.0;
-  glColor3fv(color);
-  glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,color);
+    col[3] = 1.0;
 }
 
 
@@ -464,14 +562,17 @@ static void color(double angle)
    power of 2.  Similarly, the banded appearance will only work correctly
    if numu and numv are divisible by 4. */
 static int hypertorus(ModeInfo *mi, double umin, double umax, double vmin,
-                       double vmax, int numu, int numv)
+                      double vmax, int numu, int numv)
 {
   int polys = 0;
-  static const GLfloat mat_diff_red[]         = { 1.0, 0.0, 0.0, 1.0 };
-  static const GLfloat mat_diff_green[]       = { 0.0, 1.0, 0.0, 1.0 };
-  static const GLfloat mat_diff_trans_red[]   = { 1.0, 0.0, 0.0, 0.7 };
-  static const GLfloat mat_diff_trans_green[] = { 0.0, 1.0, 0.0, 0.7 };
-  float p[3], pu[3], pv[3], n[3], mat[4][4];
+  static const GLfloat mat_diff_red[]           = { 1.0, 0.0, 0.0, 1.0 };
+  static const GLfloat mat_diff_green[]         = { 0.0, 1.0, 0.0, 1.0 };
+  static const GLfloat mat_diff_oneside[]       = { 0.9, 0.4, 0.3, 1.0 };
+  static const GLfloat mat_diff_trans_red[]     = { 1.0, 0.0, 0.0, 0.7 };
+  static const GLfloat mat_diff_trans_green[]   = { 0.0, 1.0, 0.0, 0.7 };
+  static const GLfloat mat_diff_trans_oneside[] = { 0.9, 0.4, 0.3, 0.7 };
+  float mat_diff_dyn[4], mat_diff_dyn_compl[4];
+  float p[3], pu[3], pv[3], n[3], mat[4][4], matc[3][3], col[4];
   int i, j, k, l, m, b, skew;
   double u, v, ur, vr;
   double cu, su, cv, sv;
@@ -480,6 +581,9 @@ static int hypertorus(ModeInfo *mi, double umin, double umax, double vmin,
   float q1[4], q2[4], r1[4][4], r2[4][4];
   hypertorusstruct *hp = &hyper[MI_SCREEN(mi)];
 
+  if (change_colors)
+    rotateall3d(hp->rho,hp->sigma,hp->tau,matc);
+
   rotateall(hp->alpha,hp->beta,hp->delta,hp->zeta,hp->eta,hp->theta,r1);
 
   gltrackball_get_quaternion(hp->trackballs[0],q1);
@@ -488,31 +592,56 @@ static int hypertorus(ModeInfo *mi, double umin, double umax, double vmin,
 
   mult_rotmat(r2,r1,mat);
 
-  if (colors != COLORS_COLORWHEEL)
+  if (!change_colors)
   {
-    glColor3fv(mat_diff_red);
-    if (display_mode == DISP_TRANSPARENT)
+    if (colors == COLORS_ONESIDED)
     {
-      glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_red);
-      glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_green);
+      glColor3fv(mat_diff_oneside);
+      if (display_mode == DISP_TRANSPARENT)
+      {
+        glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,
+                     mat_diff_trans_oneside);
+      }
+      else
+      {
+        glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,
+                     mat_diff_oneside);
+      }
     }
-    else
+    else if (colors == COLORS_TWOSIDED)
     {
-      glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_red);
-      glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_green);
+      glColor3fv(mat_diff_red);
+      if (display_mode == DISP_TRANSPARENT)
+      {
+        glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_red);
+        glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_green);
+      }
+      else
+      {
+        glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_red);
+        glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_green);
+      }
     }
   }
-
-#if 0 /* #### not working */
-# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  else /* change_colors */
   {
-    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);
+    color(0.0,matc,mat_diff_dyn);
+    if (colors == COLORS_ONESIDED)
+    {
+      glColor3fv(mat_diff_dyn);
+      glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn);
+    }
+    else if (colors == COLORS_TWOSIDED)
+    {
+      mat_diff_dyn_compl[0] = 1.0f-mat_diff_dyn[0];
+      mat_diff_dyn_compl[1] = 1.0f-mat_diff_dyn[1];
+      mat_diff_dyn_compl[2] = 1.0f-mat_diff_dyn[2];
+      mat_diff_dyn_compl[3] = mat_diff_dyn[3];
+      glColor3fv(mat_diff_dyn);
+      glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn);
+      glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn_compl);
+    }
   }
-# endif
-#endif
 
   skew = num_spirals;
   ur = umax-umin;
@@ -538,11 +667,16 @@ static int hypertorus(ModeInfo *mi, double umin, double umax, double vmin,
         {
           u += 4.0*skew/numv*v;
           b = ((i/4)&(skew-1))*(numu/(4*skew));
-          color(ur*4*b/numu+umin);
+          color(ur*4*b/numu+umin,matc,col);
         }
         else
         {
-          color(u);
+          color(u,matc,col);
+        }
+        if (colors == COLORS_COLORWHEEL)
+        {
+          glColor3fv(col);
+          glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,col);
         }
         cu = cos(u);
         su = sin(u);
@@ -631,6 +765,10 @@ static void init(ModeInfo *mi)
   hp->eta = 0.0;
   hp->theta = 0.0;
 
+  hp->rho = frand(360.0);
+  hp->sigma = frand(360.0);
+  hp->tau = frand(360.0);
+
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   if (projection_3d == DISP_3D_PERSPECTIVE)
@@ -718,6 +856,19 @@ static void display_hypertorus(ModeInfo *mi)
     hp->theta += speed_yz * hp->speed_scale;
     if (hp->theta >= 360.0)
       hp->theta -= 360.0;
+
+    if (change_colors)
+    {
+      hp->rho += DRHO;
+      if (hp->rho >= 360.0)
+        hp->rho -= 360.0;
+      hp->sigma += DSIGMA;
+      if (hp->sigma >= 360.0)
+        hp->sigma -= 360.0;
+      hp->tau += DTAU;
+      if (hp->tau >= 360.0)
+        hp->tau -= 360.0;
+    }
   }
 
   glMatrixMode(GL_PROJECTION);
@@ -736,10 +887,6 @@ static void display_hypertorus(ModeInfo *mi)
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
 
-  /* Let's keep a constant aspect ratio rather than stretching with the
-     shape of the window */
-  glScalef (hp->WindH / (GLfloat) hp->WindW, 1, 1);
-
   mi->polygon_count = hypertorus(mi,0.0,2.0*M_PI,0.0,2.0*M_PI,64,64);
 }
 
@@ -747,19 +894,11 @@ static void display_hypertorus(ModeInfo *mi)
 ENTRYPOINT void reshape_hypertorus(ModeInfo *mi, int width, int height)
 {
   hypertorusstruct *hp = &hyper[MI_SCREEN(mi)];
-  double h = (GLfloat) height / (GLfloat) width;  
-  int y = 0;
-
-  if (width > height * 5) {   /* tiny window: show middle */
-    height = width * 9/16;
-    y = -height/2;
-    h = height / (GLfloat) width;
-  }
 
   hp->WindW = (GLint)width;
   hp->WindH = (GLint)height;
-  glViewport(0,y,width,height);
-  hp->aspect = h;
+  glViewport(0,0,width,height);
+  hp->aspect = (GLfloat)width/(GLfloat)height;
 }
 
 
@@ -910,7 +1049,11 @@ ENTRYPOINT void init_hypertorus(ModeInfo *mi)
   }
 
   /* Set the color mode. */
-  if (!strcasecmp(color_mode,"twosided"))
+  if (!strcasecmp(color_mode,"onesided"))
+  {
+    colors = COLORS_ONESIDED;
+  }
+  else if (!strcasecmp(color_mode,"twosided"))
   {
     colors = COLORS_TWOSIDED;
   }
index 8c7075f7821c48a6030d8fa112cb82489b9e66e0..8f0837ed4b9a08e7b52a16074b54a8fab9b9c33f 100644 (file)
@@ -16,8 +16,10 @@ hypertorus - Draws a hypertorus that rotates in 4d
 [\-solid]
 [\-bands]
 [\-spirals-{1,2,4,8,16}]
+[\-onesided]
 [\-twosided]
 [\-colorwheel]
+[\-change-colors]
 [\-perspective-3d]
 [\-orthographic-3d]
 [\-perspective-4d]
@@ -37,18 +39,28 @@ alternatives, the perspective projection looks much more appealing.
 In orthographic projections the torus degenerates into a doubly
 covered cylinder for some angles.  The projected 3d torus can then be
 projected to the screen either perspectively or orthographically.
+.PP
 There are three display modes for the torus: mesh (wireframe), solid,
 or transparent.  Furthermore, the appearance of the torus can be as a
 solid object or as a set of see-through bands or see-through spirals.
-Finally, the colors with with the torus is drawn can be set to either
-two-sided or to a color wheel.  In the first case, the torus is drawn
-with red on the outside and green on the inside.  This mode enables
-you to see that the torus turns inside-out as it rotates in 4d.  The
-second mode draws the torus with a fully saturated color wheel.  This
-gives a very nice effect when combined with the see-through bands or
-see-through spirals mode.  The rotation speed for each of the six
-planes around which the torus rotates can be chosen.  This program is
-very much inspired by Thomas Banchoff's book "Beyond the Third
+Finally, the colors with with the torus is drawn can be set to
+one-sided, two-sided, or to a color wheel.  The colors can be static
+or changing dynamically.  In one-sided color mode, the torus is drawn
+with the same color on the inside and the outside.  In two-sided color
+mode, the torus is drawn with red on the outside and green on the
+inside if static colors are used.  If changing colors are used,
+dynamically varying complementary colors are used for the two sides.
+This mode enables you to see that the 3d projection of the torus turns
+inside-out as it rotates in 4d.  The color wheel mode draws the torus
+with a fully saturated color wheel.  If changing colors are used, the
+colors of the color wheel are varying dynamically.  The color wheel
+mode gives a very nice effect when combined with the see-through bands
+or see-through spirals mode.
+.PP
+Finally, the rotation speed for each of the six planes around which
+the torus rotates can be chosen.
+.PP
+This program is inspired by Thomas Banchoff's book "Beyond the Third
 Dimension: Geometry, Computer Graphics, and Higher Dimensions",
 Scientific American Library, 1990.
 .SH OPTIONS
@@ -97,18 +109,31 @@ Display the torus as see-through bands (default).
 Display the torus as see-through spirals with the indicated number of
 spirals.
 .PP
-The following two options are mutually exclusive.  They determine how
-to color the torus.
+The following three options are mutually exclusive.  They determine
+how to color the torus.
+.TP 8
+.B \-onesided
+Display the torus with a single color.
 .TP 8
 .B \-twosided
-Display the torus with two colors: red on the outside and green on
-the inside.
+Display the torus with two colors: one color on the outside and the
+complementary on the inside.  For static colors, the colors are red
+and green.
 .TP 8
 .B \-colorwheel
 Display the torus with a fully saturated color wheel (default).  If
-the torus is displayed as see-through bands each band will be
+the torus is displayed as see-through bands, each band will be
 displayed with a different color.  Likewise, if the torus is displayed
-as see-through spirals each spiral will receive a different color.
+as see-through spirals, each spiral will receive a different color.
+.PP
+The following options determine whether the colors with which the
+torus is displayed are static or are changing dynamically.
+.TP 8
+.B \-change-colors
+Change the colors with which the torus is displayed dynamically.
+.TP 8
+.B \-no-change-colors
+Use static colors to display the torus (default).
 .PP
 The following two options are mutually exclusive.  They determine how
 the torus is projected from 3d to 2d (i.e., to the screen).
@@ -158,9 +183,9 @@ Display the current frame rate, CPU load, and polygon count.
 .SH INTERACTION
 If you run this program in standalone mode you can rotate the
 hypertorus by dragging the mouse while pressing the left mouse button.
-This rotates the hypertorus in 3D, i.e., around the wx, wy, and wz
+This rotates the hypertorus in 3d, i.e., around the wx, wy, and wz
 planes.  If you press the shift key while dragging the mouse with the
-left button pressed the hypertorus is rotated in 4D, i.e., around the
+left button pressed the hypertorus is rotated in 4d, i.e., around the
 xy, xz, and yz planes.  To examine the hypertorus at your leisure, it
 is best to set all speeds to 0.  Otherwise, the hypertorus will rotate
 while the left mouse button is not pressed.
@@ -177,12 +202,13 @@ stored in the RESOURCE_MANAGER property.
 .BR X (1),
 .BR xscreensaver (1)
 .SH COPYRIGHT
-Copyright \(co 2003-2005 by Carsten Steger.  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.
+Copyright \(co 2003-2020 by Carsten Steger.  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
-Carsten Steger <carsten@mirsanmir.org>, 28-sep-2005.
+Carsten Steger <carsten@mirsanmir.org>, 11-jan-2020.
index 0fac5d299f01e2d54b2696dcbe305bfaacc07c93..7be515745a1e92998f4c7d26abad370d0c205954 100644 (file)
@@ -2,10 +2,10 @@
    can walk */
 
 #if 0
-static const char sccsid[] = "@(#)klein.c  1.1 08/10/04 xlockmore";
+static const char sccsid[] = "@(#)klein.c  1.1 04/10/08 xlockmore";
 #endif
 
-/* Copyright (c) 2005-2014 Carsten Steger <carsten@mirsanmir.org>. */
+/* Copyright (c) 2005-2020 Carsten Steger <carsten@mirsanmir.org>. */
 
 /*
  * Permission to use, copy, modify, and distribute this software and its
@@ -21,61 +21,83 @@ static const char sccsid[] = "@(#)klein.c  1.1 08/10/04 xlockmore";
  * other special, indirect and consequential damages.
  *
  * REVISION HISTORY:
- * C. Steger - 08/10/04: Initial version
- * C. Steger - 09/08/03: Changes to the parameter handling
- * C. Steger - 13/12/25: Added the squeezed torus Klein bottle
- * C. Steger - 14/10/03: Moved the curlicue texture to curlicue.h
+ * C. Steger - 04/10/08: Initial version
+ * C. Steger - 03/08/09: Changes to the parameter handling
+ * C. Steger - 25/12/13: Added the squeezed torus Klein bottle
+ * C. Steger - 03/10/14: Moved the curlicue texture to curlicue.h
+ * C. Steger - 11/01/20: Added the changing colors mode.
  */
 
 /*
- * This program shows three different Klein bottles in 4d: the figure-8 Klein
- * bottle, the squeezed torus Klein bottle, or the Lawson Klein bottle.  You
- * can walk on the Klein bottle, see it turn in 4d, or walk on it while it
- * turns in 4d.  The figure-8 Klein bottle is well known in its 3d form.  The
- * 4d form used in this program is an extension of the 3d form to 4d that
- * does not intersect itself in 4d (which can be seen in the depth colors
- * mode).  The squeezed torus Klein bottle also does not intersect itself in
- * 4d (which can be seen in the depth colors mode).  The Lawson Klein bottle,
- * on the other hand, does intersect itself in 4d.  Its primary use is that
- * it has a nice appearance for walking and for turning in 3d.  The Klein
- * bottle is a non-orientable surface.  To make this apparent, the two-sided
- * color mode can be used.  Alternatively, orientation markers (curling
- * arrows) can be drawn as a texture map on the surface of the Klein bottle.
- * While walking on the Klein bottle, you will notice that the orientation
- * of the curling arrows changes (which it must because the Klein bottle is
- * non-orientable).  The program projects the 4d Klein bottle to 3d using
- * either a perspective or an orthographic projection.  Which of the two
- * alternatives looks more appealing depends on the viewing mode and the
- * Klein bottle.  For example, the Lawson Klein bottle looks nicest when
- * projected perspectively.  The figure-8 Klein bottle, on the other
- * hand, looks nicer while walking when projected orthographically from 4d.
- * For the squeezed torus Klein bottle, both projection modes give equally
- * acceptable projections.  The projected Klein bottle can then be projected
- * to the screen either perspectively or orthographically.  When using the
- * walking modes, perspective projection to the screen should be used.  There
- * are three display modes for the Klein bottle: mesh (wireframe), solid, or
- * transparent.  Furthermore, the appearance of the Klein bottle can be as
- * a solid object or as a set of see-through bands.  Finally, the colors
- * with with the Klein bottle is drawn can be set to two-sided, rainbow, or
- * depth.  In the first case, the Klein bottle is drawn with red on one
- * "side" and green on the "other side".  Of course, the Klein bottle only
- * has one side, so the color jumps from red to green along a curve on the
- * surface of the Klein bottle.  This mode enables you to see that the Klein
- * bottle is non-orientable.  The second mode draws the Klein bottle with
- * fully saturated rainbow colors.  This gives a very nice effect when
- * combined with the see-through bands mode or with the orientation markers
- * drawn.  The third mode draws the Klein bottle with colors that are chosen
- * according to the 4d "depth" of the points.  This mode enables you to see
- * that the figure-8 and squeezed torus Klein bottles do not intersect
- * themselves in 4d, while the Lawson Klein bottle does intersect itself.
- * The rotation speed for each of the six planes around which the Klein
- * bottle rotates can be chosen.  For the walk-and-turn more, only the
- * rotation speeds around the true 4d planes are used (the xy, xz, and yz
- * planes).  Furthermore, in the walking modes the walking direction in the
- * 2d base square of the Klein bottle and the walking speed can be chosen.
- * This program is somewhat inspired by Thomas Banchoff's book "Beyond the
- * Third Dimension: Geometry, Computer Graphics, and Higher Dimensions",
- * Scientific American Library, 1990.
+ * This program shows three different Klein bottles in 4d: the
+ * figure-8 Klein bottle, the pinched torus Klein bottle, or the
+ * Lawson Klein bottle.  You can walk on the Klein bottle, see it turn
+ * in 4d, or walk on it while it turns in 4d.  The figure-8 Klein
+ * bottle is well known in its 3d form.  The 4d form used in this
+ * program is an extension of the 3d form to 4d that does not
+ * intersect itself in 4d (which can be seen in the depth colors mode
+ * when using static colors).  The pinched torus Klein bottle also
+ * does not intersect itself in 4d (which can be seen in the depth
+ * colors mode when using static colors).  The Lawson Klein bottle, on
+ * the other hand, does intersect itself in 4d.  Its primary use is
+ * that it has a nice appearance for walking and for turning in 3d.
+ *
+ * The Klein bottle is a non-orientable surface.  To make this
+ * apparent, the two-sided color mode can be used.  Alternatively,
+ * orientation markers (curling arrows) can be drawn as a texture map
+ * on the surface of the Klein bottle.  While walking on the Klein
+ * bottle, you will notice that the orientation of the curling arrows
+ * changes (which it must because the Klein bottle is non-orientable).
+ *
+ * The program projects the 4d Klein bottle to 3d using either a
+ * perspective or an orthographic projection.  Which of the two
+ * alternatives looks more appealing depends on the viewing mode and
+ * the Klein bottle.  For example, the Lawson Klein bottle looks
+ * nicest when projected perspectively.  The figure-8 Klein bottle, on
+ * the other hand, looks nicer while walking when projected
+ * orthographically from 4d.  For the pinched torus Klein bottle, both
+ * projection modes give equally acceptable projections.
+ *
+ * The projected Klein bottle can then be projected to the screen
+ * either perspectively or orthographically.  When using the walking
+ * modes, perspective projection to the screen should be used.
+ *
+ * There are three display modes for the Klein bottle: mesh
+ * (wireframe), solid, or transparent.  Furthermore, the appearance of
+ * the Klein bottle can be as a solid object or as a set of
+ * see-through bands.  Finally, the colors with with the Klein bottle
+ * is drawn can be set to one-sided, two-sided, rainbow, or depth.  In
+ * one-sided mode, the Klein bottle is drawn with the same color on
+ * both "sides."  In two-sided mode (using static colors), the Klein
+ * bottle is drawn with red on one "side" and green on the "other
+ * side."  Of course, the Klein bottle only has one side, so the color
+ * jumps from red to green along a curve on the surface of the Klein
+ * bottle.  This mode enables you to see that the Klein bottle is
+ * non-orientable.  If changing colors are used in two-sided mode,
+ * changing complementary colors are used on the respective "sides."
+ * The rainbow color mode (using static colors) draws the Klein bottle
+ * with a color wheel of fully saturated rainbow colors.  If changing
+ * colors are used, the color wheel's colors change dynamically.  The
+ * rainbow color mode gives a very nice effect when combined with the
+ * see-through bands mode or with the orientation markers drawn.  The
+ * depth color mode draws the Klein bottle with colors that are chosen
+ * according to the 4d "depth" of the points.  If static colors are
+ * used, this mode enables you to see that the figure-8 and pinched
+ * torus Klein bottles do not intersect themselves in 4d, while the
+ * Lawson Klein bottle does intersect itself.
+ *
+ * The rotation speed for each of the six planes around which the
+ * Klein bottle rotates can be chosen.  For the walk-and-turn mode,
+ * only the rotation speeds around the true 4d planes are used (the
+ * xy, xz, and yz planes).
+ *
+ * Furthermore, in the walking modes the walking direction in the 2d
+ * base square of the Klein bottle and the walking speed can be
+ * chosen.
+ *
+ * This program is somewhat inspired by Thomas Banchoff's book "Beyond
+ * the Third Dimension: Geometry, Computer Graphics, and Higher
+ * Dimensions", Scientific American Library, 1990.
  */
 
 #include "curlicue.h"
@@ -84,54 +106,56 @@ static const char sccsid[] = "@(#)klein.c  1.1 08/10/04 xlockmore";
 #define M_PI 3.14159265358979323846
 #endif
 
-#define KLEIN_BOTTLE_FIGURE_8       0
-#define KLEIN_BOTTLE_SQUEEZED_TORUS 1
-#define KLEIN_BOTTLE_LAWSON         2
-#define NUM_KLEIN_BOTTLES           3
-
-#define DISP_WIREFRAME              0
-#define DISP_SURFACE                1
-#define DISP_TRANSPARENT            2
-#define NUM_DISPLAY_MODES           3
-
-#define APPEARANCE_SOLID            0
-#define APPEARANCE_BANDS            1
-#define NUM_APPEARANCES             2
-
-#define COLORS_TWOSIDED             0
-#define COLORS_RAINBOW              1
-#define COLORS_DEPTH                2
-#define NUM_COLORS                  3
-
-#define VIEW_WALK                   0
-#define VIEW_TURN                   1
-#define VIEW_WALKTURN               2
-#define NUM_VIEW_MODES              3
-
-#define DISP_3D_PERSPECTIVE         0
-#define DISP_3D_ORTHOGRAPHIC        1
-#define NUM_DISP_3D_MODES           2
-
-#define DISP_4D_PERSPECTIVE         0
-#define DISP_4D_ORTHOGRAPHIC        1
-#define NUM_DISP_4D_MODES           2
-
-#define DEF_KLEIN_BOTTLE            "random"
-#define DEF_DISPLAY_MODE            "random"
-#define DEF_APPEARANCE              "random"
-#define DEF_COLORS                  "random"
-#define DEF_VIEW_MODE               "random"
-#define DEF_MARKS                   "False"
-#define DEF_PROJECTION_3D           "random"
-#define DEF_PROJECTION_4D           "random"
-#define DEF_SPEEDWX                 "1.1"
-#define DEF_SPEEDWY                 "1.3"
-#define DEF_SPEEDWZ                 "1.5"
-#define DEF_SPEEDXY                 "1.7"
-#define DEF_SPEEDXZ                 "1.9"
-#define DEF_SPEEDYZ                 "2.1"
-#define DEF_WALK_DIRECTION          "7.0"
-#define DEF_WALK_SPEED              "20.0"
+#define KLEIN_BOTTLE_FIGURE_8      0
+#define KLEIN_BOTTLE_PINCHED_TORUS 1
+#define KLEIN_BOTTLE_LAWSON        2
+#define NUM_KLEIN_BOTTLES          3
+
+#define DISP_WIREFRAME             0
+#define DISP_SURFACE               1
+#define DISP_TRANSPARENT           2
+#define NUM_DISPLAY_MODES          3
+
+#define APPEARANCE_SOLID           0
+#define APPEARANCE_BANDS           1
+#define NUM_APPEARANCES            2
+
+#define COLORS_ONESIDED            0
+#define COLORS_TWOSIDED            1
+#define COLORS_RAINBOW             2
+#define COLORS_DEPTH               3
+#define NUM_COLORS                 4
+
+#define VIEW_WALK                  0
+#define VIEW_TURN                  1
+#define VIEW_WALKTURN              2
+#define NUM_VIEW_MODES             3
+
+#define DISP_3D_PERSPECTIVE        0
+#define DISP_3D_ORTHOGRAPHIC       1
+#define NUM_DISP_3D_MODES          2
+
+#define DISP_4D_PERSPECTIVE        0
+#define DISP_4D_ORTHOGRAPHIC       1
+#define NUM_DISP_4D_MODES          2
+
+#define DEF_KLEIN_BOTTLE           "random"
+#define DEF_DISPLAY_MODE           "random"
+#define DEF_APPEARANCE             "random"
+#define DEF_COLORS                 "random"
+#define DEF_VIEW_MODE              "random"
+#define DEF_MARKS                  "False"
+#define DEF_CHANGE_COLORS          "False"
+#define DEF_PROJECTION_3D          "random"
+#define DEF_PROJECTION_4D          "random"
+#define DEF_SPEEDWX                "1.1"
+#define DEF_SPEEDWY                "1.3"
+#define DEF_SPEEDWZ                "1.5"
+#define DEF_SPEEDXY                "1.7"
+#define DEF_SPEEDXZ                "1.9"
+#define DEF_SPEEDYZ                "2.1"
+#define DEF_WALK_DIRECTION         "7.0"
+#define DEF_WALK_SPEED             "20.0"
 
 #ifdef STANDALONE
 # define DEFAULTS           "*delay:      10000 \n" \
@@ -168,6 +192,7 @@ static char *appear;
 static char *color_mode;
 static char *view_mode;
 static Bool marks;
+static Bool change_colors;
 static char *proj_3d;
 static char *proj_4d;
 static float speed_wx;
@@ -184,7 +209,7 @@ static XrmOptionDescRec opts[] =
 {
   {"-klein-bottle",      ".kleinBottle",   XrmoptionSepArg, 0 },
   {"-figure-8",          ".kleinBottle",   XrmoptionNoArg,  "figure-8" },
-  {"-squeezed-torus",    ".kleinBottle",   XrmoptionNoArg,  "squeezed-torus" },
+  {"-pinched-torus",     ".kleinBottle",   XrmoptionNoArg,  "pinched-torus" },
   {"-lawson",            ".kleinBottle",   XrmoptionNoArg,  "lawson" },
   {"-mode",              ".displayMode",   XrmoptionSepArg, 0 },
   {"-wireframe",         ".displayMode",   XrmoptionNoArg,  "wireframe" },
@@ -194,15 +219,18 @@ static XrmOptionDescRec opts[] =
   {"-solid",             ".appearance",    XrmoptionNoArg,  "solid" },
   {"-bands",             ".appearance",    XrmoptionNoArg,  "bands" },
   {"-colors",            ".colors",        XrmoptionSepArg, 0 },
+  {"-onesided",          ".colors",        XrmoptionNoArg,  "one-sided" },
   {"-twosided",          ".colors",        XrmoptionNoArg,  "two-sided" },
   {"-rainbow",           ".colors",        XrmoptionNoArg,  "rainbow" },
   {"-depth",             ".colors",        XrmoptionNoArg,  "depth" },
+  {"-change-colors",     ".changeColors",  XrmoptionNoArg,  "on"},
+  {"+change-colors",     ".changeColors",  XrmoptionNoArg,  "off"},
   {"-view-mode",         ".viewMode",      XrmoptionSepArg, 0 },
   {"-walk",              ".viewMode",      XrmoptionNoArg,  "walk" },
   {"-turn",              ".viewMode",      XrmoptionNoArg,  "turn" },
   {"-walk-turn",         ".viewMode",      XrmoptionNoArg,  "walk-turn" },
-  {"-orientation-marks", ".marks",         XrmoptionNoArg, "on"},
-  {"+orientation-marks", ".marks",         XrmoptionNoArg, "off"},
+  {"-orientation-marks", ".marks",         XrmoptionNoArg,  "on"},
+  {"+orientation-marks", ".marks",         XrmoptionNoArg,  "off"},
   {"-projection-3d",     ".projection3d",  XrmoptionSepArg, 0 },
   {"-perspective-3d",    ".projection3d",  XrmoptionNoArg,  "perspective" },
   {"-orthographic-3d",   ".projection3d",  XrmoptionNoArg,  "orthographic" },
@@ -225,6 +253,7 @@ static argtype vars[] =
   { &mode,           "displayMode",   "DisplayMode",   DEF_DISPLAY_MODE,   t_String },
   { &appear,         "appearance",    "Appearance",    DEF_APPEARANCE,     t_String },
   { &color_mode,     "colors",        "Colors",        DEF_COLORS,         t_String },
+  { &change_colors,  "changeColors",  "ChangeColors",  DEF_CHANGE_COLORS,  t_Bool },
   { &view_mode,      "viewMode",      "ViewMode",      DEF_VIEW_MODE,      t_String },
   { &marks,          "marks",         "Marks",         DEF_MARKS,          t_Bool },
   { &proj_3d,        "projection3d",  "Projection3d",  DEF_PROJECTION_3D,  t_String },
@@ -246,12 +275,17 @@ ENTRYPOINT ModeSpecOpt klein_opts =
 /* Radius of the figure-8 Klein bottle */
 #define FIGURE_8_RADIUS 2.0
 
-/* Radius of the squeezed torus Klein bottle */
-#define SQUEEZED_TORUS_RADIUS 2.0
+/* Radius of the pinched torus Klein bottle */
+#define PINCHED_TORUS_RADIUS 2.0
 
 /* Offset by which we walk above the Klein bottle */
 #define DELTAY  0.02
 
+/* Color change speeds */
+#define DRHO    0.7
+#define DSIGMA  1.1
+#define DTAU    1.7
+
 /* Number of subdivisions of the Klein bottle */
 #define NUMU 128
 #define NUMV 128
@@ -268,11 +302,14 @@ typedef struct {
   int display_mode;
   int appearance;
   int colors;
+  Bool change_colors;
   int view;
   int projection_3d;
   int projection_4d;
   /* 4D rotation angles */
   float alpha, beta, delta, zeta, eta, theta;
+  /* Color rotation angles */
+  float rho, sigma, tau;
   /* Movement parameters */
   float umove, vmove, dumove, dvmove;
   int side;
@@ -451,6 +488,77 @@ static void rotateall4d(float ze, float et, float th, float m[4][4])
 }
 
 
+/* Add a rotation around the x-axis to the matrix m. */
+static void rotatex(float m[3][3], float phi)
+{
+  float c, s, u, v;
+  int i;
+
+  phi *= M_PI/180.0;
+  c = cos(phi);
+  s = sin(phi);
+  for (i=0; i<3; i++)
+  {
+    u = m[i][1];
+    v = m[i][2];
+    m[i][1] = c*u+s*v;
+    m[i][2] = -s*u+c*v;
+  }
+}
+
+
+/* Add a rotation around the y-axis to the matrix m. */
+static void rotatey(float m[3][3], float phi)
+{
+  float c, s, u, v;
+  int i;
+
+  phi *= M_PI/180.0;
+  c = cos(phi);
+  s = sin(phi);
+  for (i=0; i<3; i++)
+  {
+    u = m[i][0];
+    v = m[i][2];
+    m[i][0] = c*u-s*v;
+    m[i][2] = s*u+c*v;
+  }
+}
+
+
+/* Add a rotation around the z-axis to the matrix m. */
+static void rotatez(float m[3][3], float phi)
+{
+  float c, s, u, v;
+  int i;
+
+  phi *= M_PI/180.0;
+  c = cos(phi);
+  s = sin(phi);
+  for (i=0; i<3; i++)
+  {
+    u = m[i][0];
+    v = m[i][1];
+    m[i][0] = c*u+s*v;
+    m[i][1] = -s*u+c*v;
+  }
+}
+
+
+/* Compute the 3d rotation matrix m from the 3d rotation angles. */
+static void rotateall3d(float al, float be, float de, float m[3][3])
+{
+  int i, j;
+
+  for (i=0; i<3; i++)
+    for (j=0; j<3; j++)
+      m[i][j] = (i==j);
+  rotatex(m,al);
+  rotatey(m,be);
+  rotatez(m,de);
+}
+
+
 /* Multiply two rotation matrices: o=m*n. */
 static void mult_rotmat(float m[4][4], float n[4][4], float o[4][4])
 {
@@ -499,54 +607,79 @@ static void quats_to_rotmat(float p[4], float q[4], float m[4][4])
 
 
 /* Compute a fully saturated and bright color based on an angle. */
-static void color(kleinstruct *kb, double angle, float col[4])
+static void color(kleinstruct *kb, double angle, float mat[3][3], float col[4])
 {
   int s;
-  double t;
+  double t, ca, sa;
+  float m;
 
-  if (kb->colors == COLORS_TWOSIDED)
-    return;
+  if (!kb->change_colors)
+  {
+    if (kb->colors == COLORS_ONESIDED || kb->colors == COLORS_TWOSIDED)
+      return;
 
-  if (angle >= 0.0)
-    angle = fmod(angle,2.0*M_PI);
-  else
-    angle = fmod(angle,-2.0*M_PI);
-  s = floor(angle/(M_PI/3));
-  t = angle/(M_PI/3)-s;
-  if (s >= 6)
-    s = 0;
-  switch (s)
-  {
-    case 0:
-      col[0] = 1.0;
-      col[1] = t;
-      col[2] = 0.0;
-      break;
-    case 1:
-      col[0] = 1.0-t;
-      col[1] = 1.0;
-      col[2] = 0.0;
-      break;
-    case 2:
-      col[0] = 0.0;
-      col[1] = 1.0;
-      col[2] = t;
-      break;
-    case 3:
-      col[0] = 0.0;
-      col[1] = 1.0-t;
-      col[2] = 1.0;
-      break;
-    case 4:
-      col[0] = t;
-      col[1] = 0.0;
-      col[2] = 1.0;
-      break;
-    case 5:
-      col[0] = 1.0;
-      col[1] = 0.0;
-      col[2] = 1.0-t;
-      break;
+    if (angle >= 0.0)
+      angle = fmod(angle,2.0*M_PI);
+    else
+      angle = fmod(angle,-2.0*M_PI);
+    s = floor(angle/(M_PI/3));
+    t = angle/(M_PI/3)-s;
+    if (s >= 6)
+      s = 0;
+    switch (s)
+    {
+      case 0:
+        col[0] = 1.0;
+        col[1] = t;
+        col[2] = 0.0;
+        break;
+      case 1:
+        col[0] = 1.0-t;
+        col[1] = 1.0;
+        col[2] = 0.0;
+        break;
+      case 2:
+        col[0] = 0.0;
+        col[1] = 1.0;
+        col[2] = t;
+        break;
+      case 3:
+        col[0] = 0.0;
+        col[1] = 1.0-t;
+        col[2] = 1.0;
+        break;
+      case 4:
+        col[0] = t;
+        col[1] = 0.0;
+        col[2] = 1.0;
+        break;
+      case 5:
+        col[0] = 1.0;
+        col[1] = 0.0;
+        col[2] = 1.0-t;
+        break;
+    }
+  }
+  else /* kb->change_colors */
+  {
+    if (kb->colors == COLORS_ONESIDED || kb->colors == COLORS_TWOSIDED)
+    {
+      col[0] = mat[0][2];
+      col[1] = mat[1][2];
+      col[2] = mat[2][2];
+    }
+    else
+    {
+      ca = cos(angle);
+      sa = sin(angle);
+      col[0] = ca*mat[0][0]+sa*mat[0][1];
+      col[1] = ca*mat[1][0]+sa*mat[1][1];
+      col[2] = ca*mat[2][0]+sa*mat[2][1];
+    }
+    m = 0.5f/fmaxf(fmaxf(fabsf(col[0]),fabsf(col[1])),fabsf(col[2]));
+    col[0] = m*col[0]+0.5f;
+    col[1] = m*col[1]+0.5f;
+    col[2] = m*col[2]+0.5f;
   }
   if (kb->display_mode == DISP_TRANSPARENT)
     col[3] = 0.7;
@@ -573,10 +706,13 @@ static void setup_figure8(ModeInfo *mi, double umin, double umax, double vmin,
       k = i*(NUMV+1)+j;
       u = -ur*j/NUMU+umin;
       v = vr*i/NUMV+vmin;
-      if (kb->colors == COLORS_DEPTH)
-        color(kb,(cos(u)+1.0)*M_PI*2.0/3.0,kb->col[k]);
-      else
-        color(kb,v,kb->col[k]);
+      if (!kb->change_colors)
+      {
+        if (kb->colors == COLORS_DEPTH)
+          color(kb,(cos(u)+1.0)*M_PI*2.0/3.0,NULL,kb->col[k]);
+        else if (kb->colors == COLORS_RAINBOW)
+          color(kb,v,NULL,kb->col[k]);
+      }
       kb->tex[k][0] = -32*u/(2.0*M_PI);
       kb->tex[k][1] = 32*v/(2.0*M_PI);
       cu = cos(u);
@@ -612,9 +748,9 @@ static void setup_figure8(ModeInfo *mi, double umin, double umax, double vmin,
 }
 
 
-/* Set up the squeezed torus Klein bottle coordinates, colors, and texture. */
-static void setup_squeezed_torus(ModeInfo *mi, double umin, double umax,
-                                 double vmin, double vmax)
+/* Set up the pinched torus Klein bottle coordinates, colors, and texture. */
+static void setup_pinched_torus(ModeInfo *mi, double umin, double umax,
+                                double vmin, double vmax)
 {
   int i, j, k, l;
   double u, v, ur, vr;
@@ -630,10 +766,13 @@ static void setup_squeezed_torus(ModeInfo *mi, double umin, double umax,
       k = i*(NUMV+1)+j;
       u = -ur*j/NUMU+umin;
       v = vr*i/NUMV+vmin;
-      if (kb->colors == COLORS_DEPTH)
-        color(kb,(sin(u)*sin(0.5*v)+1.0)*M_PI*2.0/3.0,kb->col[k]);
-      else
-        color(kb,v,kb->col[k]);
+      if (!kb->change_colors)
+      {
+        if (kb->colors == COLORS_DEPTH)
+          color(kb,(sin(u)*sin(0.5*v)+1.0)*M_PI*2.0/3.0,NULL,kb->col[k]);
+        else if (kb->colors == COLORS_RAINBOW)
+          color(kb,v,NULL,kb->col[k]);
+      }
       kb->tex[k][0] = -32*u/(2.0*M_PI);
       kb->tex[k][1] = 32*v/(2.0*M_PI);
       cu = cos(u);
@@ -642,23 +781,23 @@ static void setup_squeezed_torus(ModeInfo *mi, double umin, double umax,
       sv = sin(v);
       cv2 = cos(0.5*v);
       sv2 = sin(0.5*v);
-      kb->x[k][0] = (SQUEEZED_TORUS_RADIUS+cu)*cv;
-      kb->x[k][1] = (SQUEEZED_TORUS_RADIUS+cu)*sv;
+      kb->x[k][0] = (PINCHED_TORUS_RADIUS+cu)*cv;
+      kb->x[k][1] = (PINCHED_TORUS_RADIUS+cu)*sv;
       kb->x[k][2] = su*cv2;
       kb->x[k][3] = su*sv2;
       kb->xu[k][0] = -su*cv;
       kb->xu[k][1] = -su*sv;
       kb->xu[k][2] = cu*cv2;
       kb->xu[k][3] = cu*sv2;
-      kb->xv[k][0] = -(SQUEEZED_TORUS_RADIUS+cu)*sv;
-      kb->xv[k][1] = (SQUEEZED_TORUS_RADIUS+cu)*cv;
+      kb->xv[k][0] = -(PINCHED_TORUS_RADIUS+cu)*sv;
+      kb->xv[k][1] = (PINCHED_TORUS_RADIUS+cu)*cv;
       kb->xv[k][2] = -0.5*su*sv2;
       kb->xv[k][3] = 0.5*su*cv2;
       for (l=0; l<4; l++)
       {
-        kb->x[k][l] /= SQUEEZED_TORUS_RADIUS+1.25;
-        kb->xu[k][l] /= SQUEEZED_TORUS_RADIUS+1.25;
-        kb->xv[k][l] /= SQUEEZED_TORUS_RADIUS+1.25;
+        kb->x[k][l] /= PINCHED_TORUS_RADIUS+1.25;
+        kb->xu[k][l] /= PINCHED_TORUS_RADIUS+1.25;
+        kb->xv[k][l] /= PINCHED_TORUS_RADIUS+1.25;
       }
     }
   }
@@ -683,10 +822,13 @@ static void setup_lawson(ModeInfo *mi, double umin, double umax, double vmin,
       k = i*(NUMU+1)+j;
       u = -ur*j/NUMU+umin;
       v = vr*i/NUMV+vmin;
-      if (kb->colors == COLORS_DEPTH)
-        color(kb,(sin(u)*cos(0.5*v)+1.0)*M_PI*2.0/3.0,kb->col[k]);
-      else
-        color(kb,v,kb->col[k]);
+      if (!kb->change_colors)
+      {
+        if (kb->colors == COLORS_DEPTH)
+          color(kb,(sin(u)*cos(0.5*v)+1.0)*M_PI*2.0/3.0,NULL,kb->col[k]);
+        else if (kb->colors == COLORS_RAINBOW)
+          color(kb,v,NULL,kb->col[k]);
+      }
       kb->tex[k][0] = -32*u/(2.0*M_PI);
       kb->tex[k][1] = 32*v/(2.0*M_PI);
       cu = cos(u);
@@ -717,19 +859,25 @@ static int figure8(ModeInfo *mi, double umin, double umax, double vmin,
                    double vmax)
 {
   int polys = 0;
-  static const GLfloat mat_diff_red[]         = { 1.0, 0.0, 0.0, 1.0 };
-  static const GLfloat mat_diff_green[]       = { 0.0, 1.0, 0.0, 1.0 };
-  static const GLfloat mat_diff_trans_red[]   = { 1.0, 0.0, 0.0, 0.7 };
-  static const GLfloat mat_diff_trans_green[] = { 0.0, 1.0, 0.0, 0.7 };
-  float p[3], pu[3], pv[3], pm[3], n[3], b[3], mat[4][4];
+  static const GLfloat mat_diff_red[]           = { 1.0, 0.0, 0.0, 1.0 };
+  static const GLfloat mat_diff_green[]         = { 0.0, 1.0, 0.0, 1.0 };
+  static const GLfloat mat_diff_oneside[]       = { 0.9, 0.4, 0.3, 1.0 };
+  static const GLfloat mat_diff_trans_red[]     = { 1.0, 0.0, 0.0, 0.7 };
+  static const GLfloat mat_diff_trans_green[]   = { 0.0, 1.0, 0.0, 0.7 };
+  static const GLfloat mat_diff_trans_oneside[] = { 0.9, 0.4, 0.3, 0.7 };
+  float mat_diff_dyn[4], mat_diff_dyn_compl[4];
+  float p[3], pu[3], pv[3], pm[3], n[3], b[3], mat[4][4], matc[3][3];
   int i, j, k, l, m, o;
-  double u, v;
+  double u, v, ur, vr;
   double xx[4], xxu[4], xxv[4], y[4], yu[4], yv[4];
   double q, r, s, t;
   double cu, su, cv, sv, cv2, sv2, c2u, s2u;
   float q1[4], q2[4], r1[4][4], r2[4][4];
   kleinstruct *kb = &klein[MI_SCREEN(mi)];
 
+  if (kb->change_colors)
+    rotateall3d(kb->rho,kb->sigma,kb->tau,matc);
+
   if (kb->view == VIEW_WALK || kb->view == VIEW_WALKTURN)
   {
     /* Compute the rotation that rotates the Klein bottle in 4D without the
@@ -931,22 +1079,60 @@ static int figure8(ModeInfo *mi, double umin, double umax, double vmin,
     }
   }
 
-  if (kb->colors == COLORS_TWOSIDED)
+  if (!kb->change_colors)
   {
-    glColor3fv(mat_diff_red);
-    if (kb->display_mode == DISP_TRANSPARENT)
+    if (kb->colors == COLORS_ONESIDED)
     {
-      glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_red);
-      glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_green);
+      glColor3fv(mat_diff_oneside);
+      if (kb->display_mode == DISP_TRANSPARENT)
+      {
+        glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,
+                     mat_diff_trans_oneside);
+      }
+      else
+      {
+        glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,
+                     mat_diff_oneside);
+      }
     }
-    else
+    else if (kb->colors == COLORS_TWOSIDED)
     {
-      glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_red);
-      glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_green);
+      glColor3fv(mat_diff_red);
+      if (kb->display_mode == DISP_TRANSPARENT)
+      {
+        glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_red);
+        glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_green);
+      }
+      else
+      {
+        glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_red);
+        glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_green);
+      }
+    }
+  }
+  else /* kb->change_colors */
+  {
+    color(kb,0.0,matc,mat_diff_dyn);
+    if (kb->colors == COLORS_ONESIDED)
+    {
+      glColor3fv(mat_diff_dyn);
+      glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn);
+    }
+    else if (kb->colors == COLORS_TWOSIDED)
+    {
+      mat_diff_dyn_compl[0] = 1.0f-mat_diff_dyn[0];
+      mat_diff_dyn_compl[1] = 1.0f-mat_diff_dyn[1];
+      mat_diff_dyn_compl[2] = 1.0f-mat_diff_dyn[2];
+      mat_diff_dyn_compl[3] = mat_diff_dyn[3];
+      glColor3fv(mat_diff_dyn);
+      glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn);
+      glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn_compl);
     }
   }
   glBindTexture(GL_TEXTURE_2D,kb->tex_name);
 
+  ur = umax-umin;
+  vr = vmax-vmin;
   for (i=0; i<NUMU; i++)
   {
     if (kb->appearance == APPEARANCE_BANDS && ((i & (NUMB-1)) >= NUMB/2))
@@ -964,7 +1150,20 @@ static int figure8(ModeInfo *mi, double umin, double umax, double vmin,
         o = l*(NUMV+1)+m;
         glNormal3fv(kb->pn[o]);
         glTexCoord2fv(kb->tex[o]);
-        if (kb->colors != COLORS_TWOSIDED)
+        if (kb->change_colors)
+        {
+          if (kb->colors == COLORS_DEPTH)
+          {
+            u = -ur*m/NUMU+umin;
+            color(kb,(cos(u)+1.0)*M_PI*2.0/3.0,matc,kb->col[o]);
+          }
+          else if (kb->colors == COLORS_RAINBOW)
+          {
+            v = vr*l/NUMV+vmin;
+            color(kb,v,matc,kb->col[o]);
+          }
+        }
+        if (kb->colors != COLORS_ONESIDED && kb->colors != COLORS_TWOSIDED)
         {
           glColor3fv(kb->col[o]);
           glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,kb->col[o]);
@@ -980,24 +1179,30 @@ static int figure8(ModeInfo *mi, double umin, double umax, double vmin,
 }
 
 
-/* Draw a squeezed torus Klein bottle projected into 3D. */
-static int squeezed_torus(ModeInfo *mi, double umin, double umax, double vmin,
-                          double vmax)
+/* Draw a pinched torus Klein bottle projected into 3D. */
+static int pinched_torus(ModeInfo *mi, double umin, double umax, double vmin,
+                         double vmax)
 {
   int polys = 0;
-  static const GLfloat mat_diff_red[]         = { 1.0, 0.0, 0.0, 1.0 };
-  static const GLfloat mat_diff_green[]       = { 0.0, 1.0, 0.0, 1.0 };
-  static const GLfloat mat_diff_trans_red[]   = { 1.0, 0.0, 0.0, 0.7 };
-  static const GLfloat mat_diff_trans_green[] = { 0.0, 1.0, 0.0, 0.7 };
-  float p[3], pu[3], pv[3], pm[3], n[3], b[3], mat[4][4];
+  static const GLfloat mat_diff_red[]           = { 1.0, 0.0, 0.0, 1.0 };
+  static const GLfloat mat_diff_green[]         = { 0.0, 1.0, 0.0, 1.0 };
+  static const GLfloat mat_diff_oneside[]       = { 0.9, 0.4, 0.3, 1.0 };
+  static const GLfloat mat_diff_trans_red[]     = { 1.0, 0.0, 0.0, 0.7 };
+  static const GLfloat mat_diff_trans_green[]   = { 0.0, 1.0, 0.0, 0.7 };
+  static const GLfloat mat_diff_trans_oneside[] = { 0.9, 0.4, 0.3, 0.7 };
+  float mat_diff_dyn[4], mat_diff_dyn_compl[4];
+  float p[3], pu[3], pv[3], pm[3], n[3], b[3], mat[4][4], matc[3][3];
   int i, j, k, l, m, o;
-  double u, v;
+  double u, v, ur, vr;
   double xx[4], xxu[4], xxv[4], y[4], yu[4], yv[4];
   double q, r, s, t;
   double cu, su, cv, sv, cv2, sv2;
   float q1[4], q2[4], r1[4][4], r2[4][4];
   kleinstruct *kb = &klein[MI_SCREEN(mi)];
 
+  if (kb->change_colors)
+    rotateall3d(kb->rho,kb->sigma,kb->tau,matc);
+
   if (kb->view == VIEW_WALK || kb->view == VIEW_WALKTURN)
   {
     /* Compute the rotation that rotates the Klein bottle in 4D without the
@@ -1012,23 +1217,23 @@ static int squeezed_torus(ModeInfo *mi, double umin, double umax, double vmin,
     sv = sin(v);
     cv2 = cos(0.5*v);
     sv2 = sin(0.5*v);
-    xx[0] = (SQUEEZED_TORUS_RADIUS+cu)*cv;
-    xx[1] = (SQUEEZED_TORUS_RADIUS+cu)*sv;
+    xx[0] = (PINCHED_TORUS_RADIUS+cu)*cv;
+    xx[1] = (PINCHED_TORUS_RADIUS+cu)*sv;
     xx[2] = su*cv2;
     xx[3] = su*sv2;
     xxu[0] = -su*cv;
     xxu[1] = -su*sv;
     xxu[2] = cu*cv2;
     xxu[3] = cu*sv2;
-    xxv[0] = -(SQUEEZED_TORUS_RADIUS+cu)*sv;
-    xxv[1] = (SQUEEZED_TORUS_RADIUS+cu)*cv;
+    xxv[0] = -(PINCHED_TORUS_RADIUS+cu)*sv;
+    xxv[1] = (PINCHED_TORUS_RADIUS+cu)*cv;
     xxv[2] = -0.5*su*sv2;
     xxv[3] = 0.5*su*cv2;
     for (l=0; l<4; l++)
     {
-      xx[l] /= SQUEEZED_TORUS_RADIUS+1.25;
-      xxu[l] /= SQUEEZED_TORUS_RADIUS+1.25;
-      xxv[l] /= SQUEEZED_TORUS_RADIUS+1.25;
+      xx[l] /= PINCHED_TORUS_RADIUS+1.25;
+      xxu[l] /= PINCHED_TORUS_RADIUS+1.25;
+      xxv[l] /= PINCHED_TORUS_RADIUS+1.25;
     }
     for (l=0; l<4; l++)
     {
@@ -1103,12 +1308,12 @@ static int squeezed_torus(ModeInfo *mi, double umin, double umax, double vmin,
     sv = sin(v);
     cv2 = cos(0.5*v);
     sv2 = sin(0.5*v);
-    xx[0] = (SQUEEZED_TORUS_RADIUS+cu)*cv;
-    xx[1] = (SQUEEZED_TORUS_RADIUS+cu)*sv;
+    xx[0] = (PINCHED_TORUS_RADIUS+cu)*cv;
+    xx[1] = (PINCHED_TORUS_RADIUS+cu)*sv;
     xx[2] = su*cv2;
     xx[3] = su*sv2;
     for (l=0; l<4; l++)
-      xx[l] /= SQUEEZED_TORUS_RADIUS+1.25;
+      xx[l] /= PINCHED_TORUS_RADIUS+1.25;
     for (l=0; l<4; l++)
     {
       r = 0.0;
@@ -1193,22 +1398,60 @@ static int squeezed_torus(ModeInfo *mi, double umin, double umax, double vmin,
     }
   }
 
-  if (kb->colors == COLORS_TWOSIDED)
+  if (!kb->change_colors)
   {
-    glColor3fv(mat_diff_red);
-    if (kb->display_mode == DISP_TRANSPARENT)
+    if (kb->colors == COLORS_ONESIDED)
     {
-      glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_red);
-      glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_green);
+      glColor3fv(mat_diff_oneside);
+      if (kb->display_mode == DISP_TRANSPARENT)
+      {
+        glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,
+                     mat_diff_trans_oneside);
+      }
+      else
+      {
+        glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,
+                     mat_diff_oneside);
+      }
     }
-    else
+    else if (kb->colors == COLORS_TWOSIDED)
     {
-      glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_red);
-      glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_green);
+      glColor3fv(mat_diff_red);
+      if (kb->display_mode == DISP_TRANSPARENT)
+      {
+        glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_red);
+        glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_green);
+      }
+      else
+      {
+        glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_red);
+        glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_green);
+      }
+    }
+  }
+  else /* kb->change_colors */
+  {
+    color(kb,0.0,matc,mat_diff_dyn);
+    if (kb->colors == COLORS_ONESIDED)
+    {
+      glColor3fv(mat_diff_dyn);
+      glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn);
+    }
+    else if (kb->colors == COLORS_TWOSIDED)
+    {
+      mat_diff_dyn_compl[0] = 1.0f-mat_diff_dyn[0];
+      mat_diff_dyn_compl[1] = 1.0f-mat_diff_dyn[1];
+      mat_diff_dyn_compl[2] = 1.0f-mat_diff_dyn[2];
+      mat_diff_dyn_compl[3] = mat_diff_dyn[3];
+      glColor3fv(mat_diff_dyn);
+      glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn);
+      glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn_compl);
     }
   }
   glBindTexture(GL_TEXTURE_2D,kb->tex_name);
 
+  ur = umax-umin;
+  vr = vmax-vmin;
   for (i=0; i<NUMU; i++)
   {
     if (kb->appearance == APPEARANCE_BANDS && ((i & (NUMB-1)) >= NUMB/2))
@@ -1226,7 +1469,20 @@ static int squeezed_torus(ModeInfo *mi, double umin, double umax, double vmin,
         o = l*(NUMV+1)+m;
         glNormal3fv(kb->pn[o]);
         glTexCoord2fv(kb->tex[o]);
-        if (kb->colors != COLORS_TWOSIDED)
+        if (kb->change_colors)
+        {
+          v = vr*l/NUMV+vmin;
+          if (kb->colors == COLORS_DEPTH)
+          {
+            u = -ur*m/NUMU+umin;
+            color(kb,(sin(u)*sin(0.5*v)+1.0)*M_PI*2.0/3.0,matc,kb->col[o]);
+          }
+          else if (kb->colors == COLORS_RAINBOW)
+          {
+            color(kb,v,matc,kb->col[o]);
+          }
+        }
+        if (kb->colors != COLORS_ONESIDED && kb->colors != COLORS_TWOSIDED)
         {
           glColor3fv(kb->col[o]);
           glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,kb->col[o]);
@@ -1247,19 +1503,25 @@ static int lawson(ModeInfo *mi, double umin, double umax, double vmin,
                   double vmax)
 {
   int polys = 0;
-  static const GLfloat mat_diff_red[]         = { 1.0, 0.0, 0.0, 1.0 };
-  static const GLfloat mat_diff_green[]       = { 0.0, 1.0, 0.0, 1.0 };
-  static const GLfloat mat_diff_trans_red[]   = { 1.0, 0.0, 0.0, 0.7 };
-  static const GLfloat mat_diff_trans_green[] = { 0.0, 1.0, 0.0, 0.7 };
-  float p[3], pu[3], pv[3], pm[3], n[3], b[3], mat[4][4];
+  static const GLfloat mat_diff_red[]           = { 1.0, 0.0, 0.0, 1.0 };
+  static const GLfloat mat_diff_green[]         = { 0.0, 1.0, 0.0, 1.0 };
+  static const GLfloat mat_diff_oneside[]       = { 0.9, 0.4, 0.3, 1.0 };
+  static const GLfloat mat_diff_trans_red[]     = { 1.0, 0.0, 0.0, 0.7 };
+  static const GLfloat mat_diff_trans_green[]   = { 0.0, 1.0, 0.0, 0.7 };
+  static const GLfloat mat_diff_trans_oneside[] = { 0.9, 0.4, 0.3, 0.7 };
+  float mat_diff_dyn[4], mat_diff_dyn_compl[4];
+  float p[3], pu[3], pv[3], pm[3], n[3], b[3], mat[4][4], matc[3][3];
   int i, j, k, l, m, o;
-  double u, v;
+  double u, v, ur, vr;
   double cu, su, cv, sv, cv2, sv2;
   double xx[4], xxu[4], xxv[4], y[4], yu[4], yv[4];
   double q, r, s, t;
   float q1[4], q2[4], r1[4][4], r2[4][4];
   kleinstruct *kb = &klein[MI_SCREEN(mi)];
 
+  if (kb->change_colors)
+    rotateall3d(kb->rho,kb->sigma,kb->tau,matc);
+
   if (kb->view == VIEW_WALK || kb->view == VIEW_WALKTURN)
   {
     /* Compute the rotation that rotates the Klein bottle in 4D without the
@@ -1447,22 +1709,60 @@ static int lawson(ModeInfo *mi, double umin, double umax, double vmin,
     }
   }
 
-  if (kb->colors == COLORS_TWOSIDED)
+  if (!kb->change_colors)
   {
-    glColor3fv(mat_diff_red);
-    if (kb->display_mode == DISP_TRANSPARENT)
+    if (kb->colors == COLORS_ONESIDED)
     {
-      glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_red);
-      glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_green);
+      glColor3fv(mat_diff_oneside);
+      if (kb->display_mode == DISP_TRANSPARENT)
+      {
+        glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,
+                     mat_diff_trans_oneside);
+      }
+      else
+      {
+        glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,
+                     mat_diff_oneside);
+      }
     }
-    else
+    else if (kb->colors == COLORS_TWOSIDED)
+    {
+      glColor3fv(mat_diff_red);
+      if (kb->display_mode == DISP_TRANSPARENT)
+      {
+        glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_red);
+        glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_green);
+      }
+      else
+      {
+        glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_red);
+        glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_green);
+      }
+    }
+  }
+  else /* kb->change_colors */
+  {
+    color(kb,0.0,matc,mat_diff_dyn);
+    if (kb->colors == COLORS_ONESIDED)
+    {
+      glColor3fv(mat_diff_dyn);
+      glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn);
+    }
+    else if (kb->colors == COLORS_TWOSIDED)
     {
-      glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_red);
-      glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_green);
+      mat_diff_dyn_compl[0] = 1.0f-mat_diff_dyn[0];
+      mat_diff_dyn_compl[1] = 1.0f-mat_diff_dyn[1];
+      mat_diff_dyn_compl[2] = 1.0f-mat_diff_dyn[2];
+      mat_diff_dyn_compl[3] = mat_diff_dyn[3];
+      glColor3fv(mat_diff_dyn);
+      glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn);
+      glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn_compl);
     }
   }
   glBindTexture(GL_TEXTURE_2D,kb->tex_name);
 
+  ur = umax-umin;
+  vr = vmax-vmin;
   for (i=0; i<NUMV; i++)
   {
     if (kb->appearance == APPEARANCE_BANDS && ((i & (NUMB-1)) >= NUMB/2))
@@ -1480,7 +1780,20 @@ static int lawson(ModeInfo *mi, double umin, double umax, double vmin,
         o = l*(NUMU+1)+m;
         glNormal3fv(kb->pn[o]);
         glTexCoord2fv(kb->tex[o]);
-        if (kb->colors != COLORS_TWOSIDED)
+        if (kb->change_colors)
+        {
+          v = vr*l/NUMV+vmin;
+          if (kb->colors == COLORS_DEPTH)
+          {
+            u = -ur*m/NUMU+umin;
+            color(kb,(sin(u)*cos(0.5*v)+1.0)*M_PI*2.0/3.0,matc,kb->col[o]);
+          }
+          else if (kb->colors == COLORS_RAINBOW)
+          {
+            color(kb,v,matc,kb->col[o]);
+          }
+        }
+        if (kb->colors != COLORS_ONESIDED && kb->colors != COLORS_TWOSIDED)
         {
           glColor3fv(kb->col[o]);
           glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,kb->col[o]);
@@ -1509,7 +1822,7 @@ static void gen_texture(ModeInfo *mi)
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
   glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
-  glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,TEX_DIMENSION,TEX_DIMENSION,0,
+  glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,TEX_DIMENSION,TEX_DIMENSION,0,
                GL_LUMINANCE,GL_UNSIGNED_BYTE,texture);
 }
 
@@ -1540,7 +1853,7 @@ static void init(ModeInfo *mi)
   }
   kb->zeta = 0.0;
   if (kb->bottle_type == KLEIN_BOTTLE_FIGURE_8 ||
-      kb->bottle_type == KLEIN_BOTTLE_SQUEEZED_TORUS)
+      kb->bottle_type == KLEIN_BOTTLE_PINCHED_TORUS)
     kb->eta = 0.0;
   else
     kb->eta = 45.0;
@@ -1551,6 +1864,10 @@ static void init(ModeInfo *mi)
   kb->dvmove = 0.0;
   kb->side = 1;
 
+  kb->rho = frand(360.0);
+  kb->sigma = frand(360.0);
+  kb->tau = frand(360.0);
+
   if (kb->bottle_type == KLEIN_BOTTLE_FIGURE_8)
   {
     kb->offset4d[0] = 0.0;
@@ -1565,7 +1882,7 @@ static void init(ModeInfo *mi)
       kb->offset3d[2] = -1.9;
     kb->offset3d[3] = 0.0;
   }
-  else if (kb->bottle_type == KLEIN_BOTTLE_SQUEEZED_TORUS)
+  else if (kb->bottle_type == KLEIN_BOTTLE_PINCHED_TORUS)
   {
     kb->offset4d[0] = 0.0;
     kb->offset4d[1] = 0.0;
@@ -1598,8 +1915,8 @@ static void init(ModeInfo *mi)
   gen_texture(mi);
   if (kb->bottle_type == KLEIN_BOTTLE_FIGURE_8)
     setup_figure8(mi,0.0,2.0*M_PI,0.0,2.0*M_PI);
-  else if (kb->bottle_type == KLEIN_BOTTLE_SQUEEZED_TORUS)
-    setup_squeezed_torus(mi,0.0,2.0*M_PI,0.0,2.0*M_PI);
+  else if (kb->bottle_type == KLEIN_BOTTLE_PINCHED_TORUS)
+    setup_pinched_torus(mi,0.0,2.0*M_PI,0.0,2.0*M_PI);
   else /* kb->bottle_type == KLEIN_BOTTLE_LAWSON */
     setup_lawson(mi,0.0,2.0*M_PI,0.0,2.0*M_PI);
 
@@ -1736,6 +2053,18 @@ static void display_klein(ModeInfo *mi)
       if (kb->umove < 0.0)
         kb->umove += 2.0*M_PI;
     }
+    if (kb->change_colors)
+    {
+      kb->rho += DRHO;
+      if (kb->rho >= 360.0)
+        kb->rho -= 360.0;
+      kb->sigma += DSIGMA;
+      if (kb->sigma >= 360.0)
+        kb->sigma -= 360.0;
+      kb->tau += DTAU;
+      if (kb->tau >= 360.0)
+        kb->tau -= 360.0;
+    }
   }
 
   glMatrixMode(GL_PROJECTION);
@@ -1760,8 +2089,8 @@ static void display_klein(ModeInfo *mi)
 
   if (kb->bottle_type == KLEIN_BOTTLE_FIGURE_8)
     mi->polygon_count = figure8(mi,0.0,2.0*M_PI,0.0,2.0*M_PI);
-  else if (kb->bottle_type == KLEIN_BOTTLE_SQUEEZED_TORUS)
-    mi->polygon_count = squeezed_torus(mi,0.0,2.0*M_PI,0.0,2.0*M_PI);
+  else if (kb->bottle_type == KLEIN_BOTTLE_PINCHED_TORUS)
+    mi->polygon_count = pinched_torus(mi,0.0,2.0*M_PI,0.0,2.0*M_PI);
   else /* kb->bottle_type == KLEIN_BOTTLE_LAWSON */
     mi->polygon_count = lawson(mi,0.0,2.0*M_PI,0.0,2.0*M_PI);
 }
@@ -1874,9 +2203,9 @@ ENTRYPOINT void init_klein(ModeInfo *mi)
   {
     kb->bottle_type = KLEIN_BOTTLE_FIGURE_8;
   }
-  else if (!strcasecmp(klein_bottle,"squeezed-torus"))
+  else if (!strcasecmp(klein_bottle,"pinched-torus"))
   {
-    kb->bottle_type = KLEIN_BOTTLE_SQUEEZED_TORUS;
+    kb->bottle_type = KLEIN_BOTTLE_PINCHED_TORUS;
   }
   else if (!strcasecmp(klein_bottle,"lawson"))
   {
@@ -1936,6 +2265,10 @@ ENTRYPOINT void init_klein(ModeInfo *mi)
   {
     kb->colors = random() % NUM_COLORS;
   }
+  else if (!strcasecmp(color_mode,"one-sided"))
+  {
+    kb->colors = COLORS_ONESIDED;
+  }
   else if (!strcasecmp(color_mode,"two-sided"))
   {
     kb->colors = COLORS_TWOSIDED;
@@ -1953,6 +2286,8 @@ ENTRYPOINT void init_klein(ModeInfo *mi)
     kb->colors = random() % NUM_COLORS;
   }
 
+  kb->change_colors = change_colors;
+
   /* Set the view mode. */
   if (!strcasecmp(view_mode,"random"))
   {
index 1b456bcf3c6a1ff4f2ea1902edc9d7a74a7fe1b7..342c11f110cbb18a192cd001ab4e0c7cb3160b5b 100644 (file)
@@ -12,7 +12,7 @@ klein - Draws a 4d Klein bottle.
 [\-fps]
 [\-klein-bottle \fIbottle-name\fP]
 [-figure-8]
-[-squeezed-torus]
+[-pinched-torus]
 [-lawson]
 [\-mode \fIdisplay-mode\fP]
 [\-wireframe]
@@ -22,9 +22,11 @@ klein - Draws a 4d Klein bottle.
 [\-solid]
 [\-bands]
 [\-colors \fIcolor-scheme\fP]
+[\-onesided]
 [\-twosided]
 [\-rainbow]
 [\-depth]
+[\-change-colors]
 [\-view-mode \fIview-mode\fP]
 [\-walk]
 [\-turn]
@@ -46,56 +48,72 @@ klein - Draws a 4d Klein bottle.
 [\-walk-speed \fIfloat\fP]
 .SH DESCRIPTION
 The \fIklein\fP program shows three different Klein bottles in 4d: the
-figure-8 Klein bottle, the squeezed torus Klein bottle, or the Lawson
+figure-8 Klein bottle, the pinched torus Klein bottle, or the Lawson
 Klein bottle.  You can walk on the Klein bottle, see it turn in 4d, or
 walk on it while it turns in 4d.  The figure-8 Klein bottle is well
 known in its 3d form.  The 4d form used in this program is an
 extension of the 3d form to 4d that does not intersect itself in 4d
-(which can be seen in the depth colors mode).  The squeezed torus
-Klein bottle also does not intersect itself in 4d (which can be seen
-in the depth colors mode).  The Lawson Klein bottle, on the other
-hand, does intersect itself in 4d.  Its primary use is that it has a
-nice appearance for walking and for turning in 3d.  The Klein bottle
-is a non-orientable surface.  To make this apparent, the two-sided
-color mode can be used.  Alternatively, orientation markers (curling
-arrows) can be drawn as a texture map on the surface of the Klein
-bottle.  While walking on the Klein bottle, you will notice that the
-orientation of the curling arrows changes (which it must because the
-Klein bottle is non-orientable).  The program projects the 4d Klein
-bottle to 3d using either a perspective or an orthographic projection.
-Which of the two alternatives looks more appealing depends on the
-viewing mode and the Klein bottle.  For example, the Lawson Klein
-bottle looks nicest when projected perspectively.  The figure-8 Klein
-bottle, on the other hand, looks nicer while walking when projected
-orthographically from 4d.  For the squeezed torus Klein bottle, both
-projection modes give equally acceptable projections.  The projected
-Klein bottle can then be projected to the screen either perspectively
-or orthographically.  When using the walking modes, perspective
-projection to the screen should be used.  There are three display
-modes for the Klein bottle: mesh (wireframe), solid, or transparent.
-Furthermore, the appearance of the Klein bottle can be as a solid
-object or as a set of see-through bands.  Finally, the colors with
-with the Klein bottle is drawn can be set to two-sided, rainbow, or
-depth.  In the first case, the Klein bottle is drawn with red on one
-"side" and green on the "other side".  Of course, the Klein bottle
+(which can be seen in the depth colors mode when using static colors).
+The pinched torus Klein bottle also does not intersect itself in 4d
+(which can be seen in the depth colors mode when using static colors).
+The Lawson Klein bottle, on the other hand, does intersect itself in
+4d.  Its primary use is that it has a nice appearance for walking and
+for turning in 3d.
+.PP
+The Klein bottle is a non-orientable surface.  To make this apparent,
+the two-sided color mode can be used.  Alternatively, orientation
+markers (curling arrows) can be drawn as a texture map on the surface
+of the Klein bottle.  While walking on the Klein bottle, you will
+notice that the orientation of the curling arrows changes (which it
+must because the Klein bottle is non-orientable).
+.PP
+The program projects the 4d Klein bottle to 3d using either a
+perspective or an orthographic projection.  Which of the two
+alternatives looks more appealing depends on the viewing mode and the
+Klein bottle.  For example, the Lawson Klein bottle looks nicest when
+projected perspectively.  The figure-8 Klein bottle, on the other
+hand, looks nicer while walking when projected orthographically from
+4d.  For the pinched torus Klein bottle, both projection modes give
+equally acceptable projections.
+.PP
+The projected Klein bottle can then be projected to the screen either
+perspectively or orthographically.  When using the walking modes,
+perspective projection to the screen should be used.
+.PP
+There are three display modes for the Klein bottle: mesh (wireframe),
+solid, or transparent.  Furthermore, the appearance of the Klein
+bottle can be as a solid object or as a set of see-through bands.
+Finally, the colors with with the Klein bottle is drawn can be set to
+one-sided, two-sided, rainbow, or depth.  In one-sided mode, the Klein
+bottle is drawn with the same color on both "sides."  In two-sided
+mode (using static colors), the Klein bottle is drawn with red on one
+"side" and green on the "other side."  Of course, the Klein bottle
 only has one side, so the color jumps from red to green along a curve
 on the surface of the Klein bottle.  This mode enables you to see that
-the Klein bottle is non-orientable.  The second mode draws the Klein
-bottle with fully saturated rainbow colors.  This gives a very nice
-effect when combined with the see-through bands mode or with the
-orientation markers drawn.  The third mode draws the Klein bottle with
-colors that are chosen according to the 4d "depth" of the points.
-This mode enables you to see that the figure-8 and squeezed torus
-Klein bottles do not intersect themselves in 4d, while the Lawson
-Klein bottle does intersect itself.  The rotation speed for each of
-the six planes around which the Klein bottle rotates can be chosen.
-For the walk-and-turn mode, only the rotation speeds around the true
-4d planes are used (the xy, xz, and yz planes).  Furthermore, in the
-walking modes the walking direction in the 2d base square of the Klein
-bottle and the walking speed can be chosen.  This program is somewhat
-inspired by Thomas Banchoff's book "Beyond the Third Dimension:
-Geometry, Computer Graphics, and Higher Dimensions", Scientific
-American Library, 1990.
+the Klein bottle is non-orientable.  If changing colors are used in
+two-sided mode, changing complementary colors are used on the
+respective "sides."  The rainbow color mode (using static colors)
+draws the Klein bottle with a color wheel of fully saturated rainbow
+colors.  If changing colors are used, the color wheel's colors change
+dynamically.  The rainbow color mode gives a very nice effect when
+combined with the see-through bands mode or with the orientation
+markers drawn.  The depth color mode draws the Klein bottle with
+colors that are chosen according to the 4d "depth" of the points.  If
+static colors are used, this mode enables you to see that the figure-8
+and pinched torus Klein bottles do not intersect themselves in 4d,
+while the Lawson Klein bottle does intersect itself.
+.PP
+The rotation speed for each of the six planes around which the Klein
+bottle rotates can be chosen.  For the walk-and-turn mode, only the
+rotation speeds around the true 4d planes are used (the xy, xz, and yz
+planes).
+.PP
+Furthermore, in the walking modes the walking direction in the 2d base
+square of the Klein bottle and the walking speed can be chosen.
+.PP
+This program is somewhat inspired by Thomas Banchoff's book "Beyond
+the Third Dimension: Geometry, Computer Graphics, and Higher
+Dimensions", Scientific American Library, 1990.
 .SH OPTIONS
 .I klein
 accepts the following options:
@@ -129,8 +147,8 @@ Display a random Klein bottle (default).
 .B \-klein-bottle figure-8 \fP(Shortcut: \fB\-figure-8\fP)
 Display the figure-8 Klein bottle.
 .TP 8
-.B \-klein-bottle squeezed-torus \fP(Shortcut: \fB\-squeezed-torus\fP)
-Display the squeezed torus Klein bottle.
+.B \-klein-bottle pinched-torus \fP(Shortcut: \fB\-pinched-torus\fP)
+Display the pinched torus Klein bottle.
 .TP 8
 .B \-klein-bottle lawson \fP(Shortcut: \fB\-lawson\fP)
 Display the Lawson Klein bottle.
@@ -162,15 +180,19 @@ Display the Klein bottle as a solid object.
 .B \-appearance bands \fP(Shortcut: \fB\-bands\fP)
 Display the Klein bottle as see-through bands.
 .PP
-The following four options are mutually exclusive.  They determine
+The following five options are mutually exclusive.  They determine
 how to color the Klein bottle.
 .TP 8
 .B \-colors random
 Display the Klein bottle with a random color scheme (default).
 .TP 8
-.B \-colors twosided \fP(Shortcut: \fB\-twosided\fP)
-Display the Klein bottle with two colors: red on one "side" and green
-on the "other side".
+.B \-colors one-sided \fP(Shortcut: \fB\-onesided\fP)
+Display the Klein bottle with a single color.
+.TP 8
+.B \-colors two-sided \fP(Shortcut: \fB\-twosided\fP)
+Display the Klein bottle with two colors: one color one "side" and the
+complementary color on the "other side."  For static colors, the
+colors are red and green.
 .TP 8
 .B \-colors rainbow \fP(Shortcut: \fB\-rainbow\fP)
 Display the Klein bottle with fully saturated rainbow colors.  If the
@@ -181,6 +203,16 @@ displayed with a different color.
 Display the Klein bottle with colors chosen depending on the 4d
 "depth" of the points.
 .PP
+The following options determine whether the colors with which the
+Klein bottle is displayed are static or are changing dynamically.
+.TP 8
+.B \-change-colors
+Change the colors with which the Klein bottle is displayed
+dynamically.
+.TP 8
+.B \-no-change-colors
+Use static colors to display the Klein bottle (default).
+.PP
 The following four options are mutually exclusive.  They determine
 how to view the Klein bottle.
 .TP 8
@@ -296,7 +328,7 @@ stored in the RESOURCE_MANAGER property.
 .BR X (1),
 .BR xscreensaver (1)
 .SH COPYRIGHT
-Copyright \(co 2005-2014 by Carsten Steger.  Permission to use, copy,
+Copyright \(co 2005-2020 by Carsten Steger.  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
@@ -305,4 +337,4 @@ 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
-Carsten Steger <carsten@mirsanmir.org>, 03-oct-2014.
+Carsten Steger <carsten@mirsanmir.org>, 11-jan-2020.
index c704722a32d27c47d1a2bfa83996b683a403a7f1..333fcdec9d7b33a9769968f1581ba89cb6726378 100644 (file)
@@ -4,7 +4,7 @@
 static const char sccsid[] = "@(#)polytopes.c  1.2 05/09/28 xlockmore";
 #endif
 
-/* Copyright (c) 2003-2009 Carsten Steger <carsten@mirsanmir.org>. */
+/* Copyright (c) 2003-2019 Carsten Steger <carsten@mirsanmir.org>. */
 
 /*
  * Permission to use, copy, modify, and distribute this software and its
@@ -2862,16 +2862,10 @@ static void display_polytopes(ModeInfo *mi)
 ENTRYPOINT void reshape_polytopes(ModeInfo *mi, int width, int height)
 {
   polytopesstruct *pp = &poly[MI_SCREEN(mi)];
-  int y = 0;
-
-  if (width > height * 5) {   /* tiny window: show middle */
-    height = width;
-    y = -height/2;
-  }
 
   pp->WindW = (GLint)width;
   pp->WindH = (GLint)height;
-  glViewport(0,y,width,height);
+  glViewport(0,0,width,height);
   pp->aspect = (GLfloat)width/(GLfloat)height;
 }
 
index 3a052eae59ffbe0f9de331f7ee570ea9321892b7..5f42d602442f6b5c70b473b9f97feb0adec4a2b2 100644 (file)
@@ -2,10 +2,10 @@
    that rotates in 4d or on which you can walk */
 
 #if 0
-static const char sccsid[] = "@(#)projectiveplane.c  1.1 14/01/01 xlockmore";
+static const char sccsid[] = "@(#)projectiveplane.c  1.1 03/01/14 xlockmore";
 #endif
 
-/* Copyright (c) 2005-2014 Carsten Steger <carsten@mirsanmir.org>. */
+/* Copyright (c) 2013-2020 Carsten Steger <carsten@mirsanmir.org>. */
 
 /*
  * Permission to use, copy, modify, and distribute this software and its
@@ -21,8 +21,9 @@ static const char sccsid[] = "@(#)projectiveplane.c  1.1 14/01/01 xlockmore";
  * other special, indirect and consequential damages.
  *
  * REVISION HISTORY:
- * C. Steger - 14/01/03: Initial version
- * C. Steger - 14/10/03: Moved the curlicue texture to curlicue.h
+ * C. Steger - 03/01/14: Initial version
+ * C. Steger - 03/10/14: Moved the curlicue texture to curlicue.h
+ * C. Steger - 06/01/20: Added the changing colors mode.
  */
 
 /*
@@ -30,12 +31,13 @@ static const char sccsid[] = "@(#)projectiveplane.c  1.1 14/01/01 xlockmore";
  * You can walk on the projective plane, see it turn in 4d, or walk on
  * it while it turns in 4d.  The fact that the surface is an embedding
  * of the real projective plane in 4d can be seen in the depth colors
- * mode: set all rotation speeds to 0 and the projection mode to 4d
- * orthographic projection.  In its default orientation, the embedding
- * of the real projective plane will then project to the Roman
- * surface, which has three lines of self-intersection.  However, at
- * the three lines of self-intersection the parts of the surface that
- * intersect have different colors, i.e., different 4d depths.
+ * mode (using static colors): set all rotation speeds to 0 and the
+ * projection mode to 4d orthographic projection.  In its default
+ * orientation, the embedding of the real projective plane will then
+ * project to the Roman surface, which has three lines of
+ * self-intersection.  However, at the three lines of
+ * self-intersection the parts of the surface that intersect have
+ * different colors, i.e., different 4d depths.
  *
  * The real projective plane is a non-orientable surface.  To make
  * this apparent, the two-sided color mode can be used.
@@ -48,33 +50,35 @@ static const char sccsid[] = "@(#)projectiveplane.c  1.1 14/01/01 xlockmore";
  * The real projective plane is a model for the projective geometry in
  * 2d space.  One point can be singled out as the origin.  A line can
  * be singled out as the line at infinity, i.e., a line that lies at
- * an infinite distance to the origin.  The line at infinity is
- * topologically a circle.  Points on the line at infinity are also
- * used to model directions in projective geometry.  The origin can be
- * visualized in different manners.  When using distance colors, the
+ * an infinite distance to the origin.  The line at infinity, like all
+ * lines in the projective plane, is topologically a circle.  Points
+ * on the line at infinity are also used to model directions in
+ * projective geometry.  The origin can be visualized in different
+ * manners.  When using distance colors (and using static colors), the
  * origin is the point that is displayed as fully saturated red, which
  * is easier to see as the center of the reddish area on the
  * projective plane.  Alternatively, when using distance bands, the
- * origin is the center of the only band that projects to a disc.
+ * origin is the center of the only band that projects to a disk.
  * When using direction bands, the origin is the point where all
  * direction bands collapse to a point.  Finally, when orientation
  * markers are being displayed, the origin the the point where all
  * orientation markers are compressed to a point.  The line at
  * infinity can also be visualized in different ways.  When using
- * distance colors, the line at infinity is the line that is displayed
- * as fully saturated magenta.  When two-sided colors are used, the
- * line at infinity lies at the points where the red and green "sides"
- * of the projective plane meet (of course, the real projective plane
- * only has one side, so this is a design choice of the
- * visualization).  Alternatively, when orientation markers are being
- * displayed, the line at infinity is the place where the orientation
- * markers change their orientation.
+ * distance colors (and using static colors), the line at infinity is
+ * the line that is displayed as fully saturated magenta.  When
+ * two-sided (and static) colors are used, the line at infinity lies
+ * at the points where the red and green "sides" of the projective
+ * plane meet (of course, the real projective plane only has one side,
+ * so this is a design choice of the visualization).  Alternatively,
+ * when orientation markers are being displayed, the line at infinity
+ * is the place where the orientation markers change their
+ * orientation.
  *
  * Note that when the projective plane is displayed with bands, the
  * orientation markers are placed in the middle of the bands.  For
  * distance bands, the bands are chosen in such a way that the band at
  * the origin is only half as wide as the remaining bands, which
- * results in a disc being displayed at the origin that has the same
+ * results in a disk being displayed at the origin that has the same
  * diameter as the remaining bands.  This choice, however, also
  * implies that the band at infinity is half as wide as the other
  * bands.  Since the projective plane is attached to itself (in a
@@ -119,33 +123,37 @@ static const char sccsid[] = "@(#)projectiveplane.c  1.1 14/01/01 xlockmore";
  * projective plane is non-orientable.
  *
  * Finally, the colors with with the projective plane is drawn can be
- * set to two-sided, distance, direction, or depth.  In two-sided
- * mode, the projective plane is drawn with red on one "side" and
- * green on the "other side".  As described above, the projective
- * plane only has one side, so the color jumps from red to green along
- * the line at infinity.  This mode enables you to see that the
- * projective plane is non-orientable.  In distance mode, the
- * projective plane is displayed with fully saturated colors that
- * depend on the distance of the points on the projective plane to the
- * origin.  The origin is displayed in red, the line at infinity is
- * displayed in magenta.  If the projective plane is displayed as
- * distance bands, each band will be displayed with a different color.
- * In direction mode, the projective plane is displayed with fully
+ * set to one-sided, two-sided, distance, direction, or depth.  In
+ * one-sided mode, the projective plane is drawn with the same color
+ * on both "sides."  In two-sided mode (using static colors), the
+ * projective plane is drawn with red on one "side" and green on the
+ * "other side."  As described above, the projective plane only has
+ * one side, so the color jumps from red to green along the line at
+ * infinity.  This mode enables you to see that the projective plane
+ * is non-orientable.  If changing colors are used in two-sided mode,
+ * changing complementary colors are used on the respective "sides."
+ * In distance mode, the projective plane is displayed with fully
+ * saturated colors that depend on the distance of the points on the
+ * projective plane to the origin.  If static colors are used, the
+ * origin is displayed in red, while the line at infinity is displayed
+ * in magenta.  If the projective plane is displayed as distance
+ * bands, each band will be displayed with a different color.  In
+ * direction mode, the projective plane is displayed with fully
  * saturated colors that depend on the angle of the points on the
  * projective plane with respect to the origin.  Angles in opposite
  * directions to the origin (e.g., 15 and 205 degrees) are displayed
  * in the same color since they are projectively equivalent.  If the
  * projective plane is displayed as direction bands, each band will be
  * displayed with a different color.  Finally, in depth mode the
- * projective plane with colors chosen depending on the 4d "depth"
- * (i.e., the w coordinate) of the points on the projective plane at
- * its default orientation in 4d.  As discussed above, this mode
- * enables you to see that the projective plane does not intersect
- * itself in 4d.
+ * projective plane is displayed with colors chosen depending on the
+ * 4d "depth" (i.e., the w coordinate) of the points on the projective
+ * plane at its default orientation in 4d.  As discussed above, this
+ * mode enables you to see that the projective plane does not
+ * intersect itself in 4d.
  *
  * The rotation speed for each of the six planes around which the
  * projective plane rotates can be chosen.  For the walk-and-turn
- * more, only the rotation speeds around the true 4d planes are used
+ * mode, only the rotation speeds around the true 4d planes are used
  * (the xy, xz, and yz planes).
  *
  * Furthermore, in the walking modes the walking direction in the 2d
@@ -180,11 +188,12 @@ static const char sccsid[] = "@(#)projectiveplane.c  1.1 14/01/01 xlockmore";
 #define APPEARANCE_DIRECTION_BANDS 2
 #define NUM_APPEARANCES            3
 
-#define COLORS_TWOSIDED            0
-#define COLORS_DISTANCE            1
-#define COLORS_DIRECTION           2
-#define COLORS_DEPTH               3
-#define NUM_COLORS                 4
+#define COLORS_ONESIDED            0
+#define COLORS_TWOSIDED            1
+#define COLORS_DISTANCE            2
+#define COLORS_DIRECTION           3
+#define COLORS_DEPTH               4
+#define NUM_COLORS                 5
 
 #define VIEW_WALK                  0
 #define VIEW_TURN                  1
@@ -204,6 +213,7 @@ static const char sccsid[] = "@(#)projectiveplane.c  1.1 14/01/01 xlockmore";
 #define DEF_COLORS                 "random"
 #define DEF_VIEW_MODE              "random"
 #define DEF_MARKS                  "False"
+#define DEF_CHANGE_COLORS          "False"
 #define DEF_PROJECTION_3D          "random"
 #define DEF_PROJECTION_4D          "random"
 #define DEF_SPEEDWX                "1.1"
@@ -252,6 +262,7 @@ static char *appear;
 static char *color_mode;
 static char *view_mode;
 static Bool marks;
+static Bool change_colors;
 static char *proj_3d;
 static char *proj_4d;
 static float speed_wx;
@@ -275,16 +286,19 @@ static XrmOptionDescRec opts[] =
   {"-distance-bands",    ".appearance",    XrmoptionNoArg,  "distance-bands" },
   {"-direction-bands",   ".appearance",    XrmoptionNoArg,  "direction-bands" },
   {"-colors",            ".colors",        XrmoptionSepArg, 0 },
+  {"-onesided-colors",   ".colors",        XrmoptionNoArg,  "one-sided" },
   {"-twosided-colors",   ".colors",        XrmoptionNoArg,  "two-sided" },
   {"-distance-colors",   ".colors",        XrmoptionNoArg,  "distance" },
   {"-direction-colors",  ".colors",        XrmoptionNoArg,  "direction" },
   {"-depth-colors",      ".colors",        XrmoptionNoArg,  "depth" },
+  {"-change-colors",     ".changeColors",  XrmoptionNoArg,  "on"},
+  {"+change-colors",     ".changeColors",  XrmoptionNoArg,  "off"},
   {"-view-mode",         ".viewMode",      XrmoptionSepArg, 0 },
   {"-walk",              ".viewMode",      XrmoptionNoArg,  "walk" },
   {"-turn",              ".viewMode",      XrmoptionNoArg,  "turn" },
   {"-walk-turn",         ".viewMode",      XrmoptionNoArg,  "walk-turn" },
-  {"-orientation-marks", ".marks",         XrmoptionNoArg, "on"},
-  {"+orientation-marks", ".marks",         XrmoptionNoArg, "off"},
+  {"-orientation-marks", ".marks",         XrmoptionNoArg,  "on"},
+  {"+orientation-marks", ".marks",         XrmoptionNoArg,  "off"},
   {"-projection-3d",     ".projection3d",  XrmoptionSepArg, 0 },
   {"-perspective-3d",    ".projection3d",  XrmoptionNoArg,  "perspective" },
   {"-orthographic-3d",   ".projection3d",  XrmoptionNoArg,  "orthographic" },
@@ -306,6 +320,7 @@ static argtype vars[] =
   { &mode,           "displayMode",   "DisplayMode",   DEF_DISPLAY_MODE,   t_String },
   { &appear,         "appearance",    "Appearance",    DEF_APPEARANCE,     t_String },
   { &color_mode,     "colors",        "Colors",        DEF_COLORS,         t_String },
+  { &change_colors,  "changeColors",  "ChangeColors",  DEF_CHANGE_COLORS,  t_Bool },
   { &view_mode,      "viewMode",      "ViewMode",      DEF_VIEW_MODE,      t_String },
   { &marks,          "marks",         "Marks",         DEF_MARKS,          t_Bool },
   { &proj_3d,        "projection3d",  "Projection3d",  DEF_PROJECTION_3D,  t_String },
@@ -327,6 +342,11 @@ ENTRYPOINT ModeSpecOpt projectiveplane_opts =
 /* Offset by which we walk above the projective plane */
 #define DELTAY  0.01
 
+/* Color change speeds */
+#define DRHO    0.7
+#define DSIGMA  1.1
+#define DTAU    1.7
+
 /* Number of subdivisions of the projective plane */
 #define NUMU 128
 #define NUMV 128
@@ -342,12 +362,15 @@ typedef struct {
   int display_mode;
   int appearance;
   int colors;
+  Bool change_colors;
   int view;
   Bool marks;
   int projection_3d;
   int projection_4d;
   /* 4D rotation angles */
   float alpha, beta, delta, zeta, eta, theta;
+  /* Color rotation angles */
+  float rho, sigma, tau;
   /* Movement parameters */
   float umove, vmove, dumove, dvmove;
   int side, dir;
@@ -526,6 +549,77 @@ static void rotateall4d(float ze, float et, float th, float m[4][4])
 }
 
 
+/* Add a rotation around the x-axis to the matrix m. */
+static void rotatex(float m[3][3], float phi)
+{
+  float c, s, u, v;
+  int i;
+
+  phi *= M_PI/180.0;
+  c = cos(phi);
+  s = sin(phi);
+  for (i=0; i<3; i++)
+  {
+    u = m[i][1];
+    v = m[i][2];
+    m[i][1] = c*u+s*v;
+    m[i][2] = -s*u+c*v;
+  }
+}
+
+
+/* Add a rotation around the y-axis to the matrix m. */
+static void rotatey(float m[3][3], float phi)
+{
+  float c, s, u, v;
+  int i;
+
+  phi *= M_PI/180.0;
+  c = cos(phi);
+  s = sin(phi);
+  for (i=0; i<3; i++)
+  {
+    u = m[i][0];
+    v = m[i][2];
+    m[i][0] = c*u-s*v;
+    m[i][2] = s*u+c*v;
+  }
+}
+
+
+/* Add a rotation around the z-axis to the matrix m. */
+static void rotatez(float m[3][3], float phi)
+{
+  float c, s, u, v;
+  int i;
+
+  phi *= M_PI/180.0;
+  c = cos(phi);
+  s = sin(phi);
+  for (i=0; i<3; i++)
+  {
+    u = m[i][0];
+    v = m[i][1];
+    m[i][0] = c*u+s*v;
+    m[i][1] = -s*u+c*v;
+  }
+}
+
+
+/* Compute the 3d rotation matrix m from the 3d rotation angles. */
+static void rotateall3d(float al, float be, float de, float m[3][3])
+{
+  int i, j;
+
+  for (i=0; i<3; i++)
+    for (j=0; j<3; j++)
+      m[i][j] = (i==j);
+  rotatex(m,al);
+  rotatey(m,be);
+  rotatez(m,de);
+}
+
+
 /* Multiply two rotation matrices: o=m*n. */
 static void mult_rotmat(float m[4][4], float n[4][4], float o[4][4])
 {
@@ -574,54 +668,80 @@ static void quats_to_rotmat(float p[4], float q[4], float m[4][4])
 
 
 /* Compute a fully saturated and bright color based on an angle. */
-static void color(projectiveplanestruct *pp, double angle, float col[4])
+static void color(projectiveplanestruct *pp, double angle, float mat[3][3],
+                  float col[4])
 {
   int s;
-  double t;
+  double t, ca, sa;
+  float m;
 
-  if (pp->colors == COLORS_TWOSIDED)
-    return;
+  if (!pp->change_colors)
+  {
+    if (pp->colors == COLORS_ONESIDED || pp->colors == COLORS_TWOSIDED)
+      return;
 
-  if (angle >= 0.0)
-    angle = fmod(angle,2.0*M_PI);
-  else
-    angle = fmod(angle,-2.0*M_PI);
-  s = floor(angle/(M_PI/3));
-  t = angle/(M_PI/3)-s;
-  if (s >= 6)
-    s = 0;
-  switch (s)
-  {
-    case 0:
-      col[0] = 1.0;
-      col[1] = t;
-      col[2] = 0.0;
-      break;
-    case 1:
-      col[0] = 1.0-t;
-      col[1] = 1.0;
-      col[2] = 0.0;
-      break;
-    case 2:
-      col[0] = 0.0;
-      col[1] = 1.0;
-      col[2] = t;
-      break;
-    case 3:
-      col[0] = 0.0;
-      col[1] = 1.0-t;
-      col[2] = 1.0;
-      break;
-    case 4:
-      col[0] = t;
-      col[1] = 0.0;
-      col[2] = 1.0;
-      break;
-    case 5:
-      col[0] = 1.0;
-      col[1] = 0.0;
-      col[2] = 1.0-t;
-      break;
+    if (angle >= 0.0)
+      angle = fmod(angle,2.0*M_PI);
+    else
+      angle = fmod(angle,-2.0*M_PI);
+    s = floor(angle/(M_PI/3));
+    t = angle/(M_PI/3)-s;
+    if (s >= 6)
+      s = 0;
+    switch (s)
+    {
+      case 0:
+        col[0] = 1.0;
+        col[1] = t;
+        col[2] = 0.0;
+        break;
+      case 1:
+        col[0] = 1.0-t;
+        col[1] = 1.0;
+        col[2] = 0.0;
+        break;
+      case 2:
+        col[0] = 0.0;
+        col[1] = 1.0;
+        col[2] = t;
+        break;
+      case 3:
+        col[0] = 0.0;
+        col[1] = 1.0-t;
+        col[2] = 1.0;
+        break;
+      case 4:
+        col[0] = t;
+        col[1] = 0.0;
+        col[2] = 1.0;
+        break;
+      case 5:
+        col[0] = 1.0;
+        col[1] = 0.0;
+        col[2] = 1.0-t;
+        break;
+    }
+  }
+  else /* pp->change_colors */
+  {
+    if (pp->colors == COLORS_ONESIDED || pp->colors == COLORS_TWOSIDED)
+    {
+      col[0] = mat[0][2];
+      col[1] = mat[1][2];
+      col[2] = mat[2][2];
+    }
+    else
+    {
+      ca = cos(angle);
+      sa = sin(angle);
+      col[0] = ca*mat[0][0]+sa*mat[0][1];
+      col[1] = ca*mat[1][0]+sa*mat[1][1];
+      col[2] = ca*mat[2][0]+sa*mat[2][1];
+    }
+    m = 0.5f/fmaxf(fmaxf(fabsf(col[0]),fabsf(col[1])),fabsf(col[2]));
+    col[0] = m*col[0]+0.5f;
+    col[1] = m*col[1]+0.5f;
+    col[2] = m*col[2]+0.5f;
   }
   if (pp->display_mode == DISP_TRANSPARENT)
     col[3] = 0.7;
@@ -635,7 +755,7 @@ static void setup_projective_plane(ModeInfo *mi, double umin, double umax,
                                    double vmin, double vmax)
 {
   int i, j, k;
-  double u, v, ur, vr;
+  double u, v, w, ur, vr;
   double cu, su, cv2, sv2, cv4, sv4, c2u, s2u;
   projectiveplanestruct *pp = &projectiveplane[MI_SCREEN(mi)];
 
@@ -658,12 +778,16 @@ static void setup_projective_plane(ModeInfo *mi, double umin, double umax,
       sv2 = sin(0.5*v);
       cv4 = cos(0.25*v);
       sv4 = sin(0.25*v);
-      if (pp->colors == COLORS_DEPTH)
-        color(pp,((su*su*sv4*sv4-cv4*cv4)+1.0)*M_PI*2.0/3.0,pp->col[k]);
-      else if (pp->colors == COLORS_DIRECTION)
-        color(pp,2.0*M_PI+fmod(2.0*u,2.0*M_PI),pp->col[k]);
-      else /* pp->colors == COLORS_DISTANCE */
-        color(pp,v*(5.0/6.0),pp->col[k]);
+      w = 0.5*(su*su*sv4*sv4-cv4*cv4);
+      if (!pp->change_colors)
+      {
+        if (pp->colors == COLORS_DEPTH)
+          color(pp,(2.0*w+1.0)*M_PI*2.0/3.0,NULL,pp->col[k]);
+        else if (pp->colors == COLORS_DIRECTION)
+          color(pp,2.0*M_PI+fmod(2.0*u,2.0*M_PI),NULL,pp->col[k]);
+        else /* pp->colors == COLORS_DISTANCE */
+          color(pp,v*(5.0/6.0),NULL,pp->col[k]);
+      }
       pp->tex[k][0] = -32*u/(2.0*M_PI);
       if (pp->appearance != APPEARANCE_DISTANCE_BANDS)
         pp->tex[k][1] = 32*v/(2.0*M_PI);
@@ -672,7 +796,7 @@ static void setup_projective_plane(ModeInfo *mi, double umin, double umax,
       pp->x[k][0] = 0.5*s2u*sv4*sv4;
       pp->x[k][1] = 0.5*su*sv2;
       pp->x[k][2] = 0.5*cu*sv2;
-      pp->x[k][3] = 0.5*(su*su*sv4*sv4-cv4*cv4);
+      pp->x[k][3] = w;
       /* Avoid degenerate tangential plane basis vectors. */
       if (v < FLT_EPSILON)
         v = FLT_EPSILON;
@@ -697,19 +821,25 @@ static int projective_plane(ModeInfo *mi, double umin, double umax,
                             double vmin, double vmax)
 {
   int polys = 0;
-  static const GLfloat mat_diff_red[]         = { 1.0, 0.0, 0.0, 1.0 };
-  static const GLfloat mat_diff_green[]       = { 0.0, 1.0, 0.0, 1.0 };
-  static const GLfloat mat_diff_trans_red[]   = { 1.0, 0.0, 0.0, 0.7 };
-  static const GLfloat mat_diff_trans_green[] = { 0.0, 1.0, 0.0, 0.7 };
-  float p[3], pu[3], pv[3], pm[3], n[3], b[3], mat[4][4];
+  static const GLfloat mat_diff_red[]           = { 1.0, 0.0, 0.0, 1.0 };
+  static const GLfloat mat_diff_green[]         = { 0.0, 1.0, 0.0, 1.0 };
+  static const GLfloat mat_diff_oneside[]       = { 0.9, 0.4, 0.3, 1.0 };
+  static const GLfloat mat_diff_trans_red[]     = { 1.0, 0.0, 0.0, 0.7 };
+  static const GLfloat mat_diff_trans_green[]   = { 0.0, 1.0, 0.0, 0.7 };
+  static const GLfloat mat_diff_trans_oneside[] = { 0.9, 0.4, 0.3, 0.7 };
+  float mat_diff_dyn[4], mat_diff_dyn_compl[4];
+  float p[3], pu[3], pv[3], pm[3], n[3], b[3], mat[4][4], matc[3][3];
   int i, j, k, l, m, o;
-  double u, v;
+  double u, v, ur, vr;
   double xx[4], xxu[4], xxv[4], y[4], yu[4], yv[4];
   double q, r, s, t;
   double cu, su, cv2, sv2, cv4, sv4, c2u, s2u;
   float q1[4], q2[4], r1[4][4], r2[4][4];
   projectiveplanestruct *pp = &projectiveplane[MI_SCREEN(mi)];
 
+  if (pp->change_colors)
+    rotateall3d(pp->rho,pp->sigma,pp->tau,matc);
+
   if (pp->view == VIEW_WALK || pp->view == VIEW_WALKTURN)
   {
     /* Compute the rotation that rotates the projective plane in 4D without
@@ -904,22 +1034,60 @@ static int projective_plane(ModeInfo *mi, double umin, double umax,
     }
   }
 
-  if (pp->colors == COLORS_TWOSIDED)
+  if (!pp->change_colors)
   {
-    glColor3fv(mat_diff_red);
-    if (pp->display_mode == DISP_TRANSPARENT)
+    if (pp->colors == COLORS_ONESIDED)
     {
-      glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_red);
-      glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_green);
+      glColor3fv(mat_diff_oneside);
+      if (pp->display_mode == DISP_TRANSPARENT)
+      {
+        glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,
+                     mat_diff_trans_oneside);
+      }
+      else
+      {
+        glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,
+                     mat_diff_oneside);
+      }
     }
-    else
+    else if (pp->colors == COLORS_TWOSIDED)
+    {
+      glColor3fv(mat_diff_red);
+      if (pp->display_mode == DISP_TRANSPARENT)
+      {
+        glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_red);
+        glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_green);
+      }
+      else
+      {
+        glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_red);
+        glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_green);
+      }
+    }
+  }
+  else /* pp->change_colors */
+  {
+    color(pp,0.0,matc,mat_diff_dyn);
+    if (pp->colors == COLORS_ONESIDED)
+    {
+      glColor3fv(mat_diff_dyn);
+      glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn);
+    }
+    else if (pp->colors == COLORS_TWOSIDED)
     {
-      glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_red);
-      glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_green);
+      mat_diff_dyn_compl[0] = 1.0f-mat_diff_dyn[0];
+      mat_diff_dyn_compl[1] = 1.0f-mat_diff_dyn[1];
+      mat_diff_dyn_compl[2] = 1.0f-mat_diff_dyn[2];
+      mat_diff_dyn_compl[3] = mat_diff_dyn[3];
+      glColor3fv(mat_diff_dyn);
+      glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn);
+      glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn_compl);
     }
   }
   glBindTexture(GL_TEXTURE_2D,pp->tex_name);
 
+  ur = umax-umin;
+  vr = vmax-vmin;
   if (pp->appearance != APPEARANCE_DIRECTION_BANDS)
   {
     for (i=0; i<NUMV; i++)
@@ -940,7 +1108,24 @@ static int projective_plane(ModeInfo *mi, double umin, double umax,
           o = l*(NUMU+1)+m;
           glNormal3fv(pp->pn[o]);
           glTexCoord2fv(pp->tex[o]);
-          if (pp->colors != COLORS_TWOSIDED)
+          if (pp->change_colors)
+          {
+            if (pp->colors == COLORS_DEPTH)
+            {
+              color(pp,(2.0*pp->x[o][3]+1.0)*M_PI*2.0/3.0,matc,pp->col[o]);
+            }
+            else if (pp->colors == COLORS_DIRECTION)
+            {
+              u = -ur*m/NUMU+umin;
+              color(pp,2.0*M_PI+fmod(2.0*u,2.0*M_PI),matc,pp->col[o]);
+            }
+            else if (pp->colors == COLORS_DISTANCE)
+            {
+              v = vr*l/NUMV+vmin;
+              color(pp,v*(5.0/6.0),matc,pp->col[o]);
+            }
+          }
+          if (pp->colors != COLORS_ONESIDED && pp->colors != COLORS_TWOSIDED)
           {
             glColor3fv(pp->col[o]);
             glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,pp->col[o]);
@@ -971,7 +1156,24 @@ static int projective_plane(ModeInfo *mi, double umin, double umax,
           o = l*(NUMU+1)+m;
           glNormal3fv(pp->pn[o]);
           glTexCoord2fv(pp->tex[o]);
-          if (pp->colors != COLORS_TWOSIDED)
+          if (pp->change_colors)
+          {
+            if (pp->colors == COLORS_DEPTH)
+            {
+              color(pp,(2.0*pp->x[o][3]+1.0)*M_PI*2.0/3.0,matc,pp->col[o]);
+            }
+            else if (pp->colors == COLORS_DIRECTION)
+            {
+              u = ur*m/NUMU+umin;
+              color(pp,2.0*M_PI+fmod(2.0*u,2.0*M_PI),matc,pp->col[o]);
+            }
+            else if (pp->colors == COLORS_DISTANCE)
+            {
+              v = vr*l/NUMV+vmin;
+              color(pp,v*(5.0/6.0),matc,pp->col[o]);
+            }
+          }
+          if (pp->colors != COLORS_ONESIDED && pp->colors != COLORS_TWOSIDED)
           {
             glColor3fv(pp->col[o]);
             glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,pp->col[o]);
@@ -1002,7 +1204,7 @@ static void gen_texture(ModeInfo *mi)
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
   glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
-  glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,TEX_DIMENSION,TEX_DIMENSION,0,
+  glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,TEX_DIMENSION,TEX_DIMENSION,0,
                GL_LUMINANCE,GL_UNSIGNED_BYTE,texture);
 }
 
@@ -1047,6 +1249,10 @@ static void init(ModeInfo *mi)
   else
     pp->dir = -1;
 
+  pp->rho = frand(360.0);
+  pp->sigma = frand(360.0);
+  pp->tau = frand(360.0);
+
   pp->offset4d[0] = 0.0;
   pp->offset4d[1] = 0.0;
   pp->offset4d[2] = 0.0;
@@ -1205,6 +1411,18 @@ static void display_projectiveplane(ModeInfo *mi)
       if (pp->umove < 0.0)
         pp->umove += 2.0*M_PI;
     }
+    if (pp->change_colors)
+    {
+      pp->rho += DRHO;
+      if (pp->rho >= 360.0)
+        pp->rho -= 360.0;
+      pp->sigma += DSIGMA;
+      if (pp->sigma >= 360.0)
+        pp->sigma -= 360.0;
+      pp->tau += DTAU;
+      if (pp->tau >= 360.0)
+        pp->tau -= 360.0;
+    }
   }
 
   glMatrixMode(GL_PROJECTION);
@@ -1383,6 +1601,10 @@ ENTRYPOINT void init_projectiveplane(ModeInfo *mi)
   {
     pp->colors = random() % NUM_COLORS;
   }
+  else if (!strcasecmp(color_mode,"one-sided"))
+  {
+    pp->colors = COLORS_ONESIDED;
+  }
   else if (!strcasecmp(color_mode,"two-sided"))
   {
     pp->colors = COLORS_TWOSIDED;
@@ -1404,6 +1626,8 @@ ENTRYPOINT void init_projectiveplane(ModeInfo *mi)
     pp->colors = random() % NUM_COLORS;
   }
 
+  pp->change_colors = change_colors;
+
   /* Set the view mode. */
   if (!strcasecmp(view_mode,"random"))
   {
index 8adea81b7557e026b6c5dc26b1cb836625ee8703..7df253d45a43fb6b15e995a4e0fcff0111a45840 100644 (file)
@@ -19,9 +19,11 @@ projectiveplane - Draws a 4d embedding of the real projective plane.
 [\-distance-bands]
 [\-direction-bands]
 [\-colors \fIcolor-scheme\fP]
+[\-onesided-colors]
 [\-twosided-colors]
 [\-distance-colors]
 [\-direction-colors]
+[\-change-colors]
 [\-depth-colors]
 [\-view-mode \fIview-mode\fP]
 [\-walk]
@@ -47,12 +49,13 @@ The \fIprojectiveplane\fP program shows a 4d embedding of the real
 projective plane.  You can walk on the projective plane, see it turn
 in 4d, or walk on it while it turns in 4d.  The fact that the surface
 is an embedding of the real projective plane in 4d can be seen in the
-depth colors mode: set all rotation speeds to 0 and the projection
-mode to 4d orthographic projection.  In its default orientation, the
-embedding of the real projective plane will then project to the Roman
-surface, which has three lines of self-intersection.  However, at the
-three lines of self-intersection the parts of the surface that
-intersect have different colors, i.e., different 4d depths.
+depth colors mode (using static colors): set all rotation speeds to 0
+and the projection mode to 4d orthographic projection.  In its default
+orientation, the embedding of the real projective plane will then
+project to the Roman surface, which has three lines of
+self-intersection.  However, at the three lines of self-intersection
+the parts of the surface that intersect have different colors, i.e.,
+different 4d depths.
 .PP
 The real projective plane is a non-orientable surface.  To make this
 apparent, the two-sided color mode can be used.  Alternatively,
@@ -65,26 +68,27 @@ non-orientable).
 The real projective plane is a model for the projective geometry in 2d
 space.  One point can be singled out as the origin.  A line can be
 singled out as the line at infinity, i.e., a line that lies at an
-infinite distance to the origin.  The line at infinity is
-topologically a circle.  Points on the line at infinity are also used
-to model directions in projective geometry.  The origin can be
-visualized in different manners.  When using distance colors, the
-origin is the point that is displayed as fully saturated red, which is
-easier to see as the center of the reddish area on the projective
-plane.  Alternatively, when using distance bands, the origin is the
-center of the only band that projects to a disk.  When using direction
-bands, the origin is the point where all direction bands collapse to a
-point.  Finally, when orientation markers are being displayed, the
-origin the the point where all orientation markers are compressed to a
-point.  The line at infinity can also be visualized in different ways.
-When using distance colors, the line at infinity is the line that is
-displayed as fully saturated magenta.  When two-sided colors are used,
-the line at infinity lies at the points where the red and green
-"sides" of the projective plane meet (of course, the real projective
-plane only has one side, so this is a design choice of the
-visualization).  Alternatively, when orientation markers are being
-displayed, the line at infinity is the place where the orientation
-markers change their orientation.
+infinite distance to the origin.  The line at infinity, like all lines
+in the projective plane, is topologically a circle.  Points on the
+line at infinity are also used to model directions in projective
+geometry.  The origin can be visualized in different manners.  When
+using distance colors (and using static colors), the origin is the
+point that is displayed as fully saturated red, which is easier to see
+as the center of the reddish area on the projective plane.
+Alternatively, when using distance bands, the origin is the center of
+the only band that projects to a disk.  When using direction bands,
+the origin is the point where all direction bands collapse to a point.
+Finally, when orientation markers are being displayed, the origin the
+the point where all orientation markers are compressed to a point.
+The line at infinity can also be visualized in different ways.  When
+using distance colors (and using static colors), the line at infinity
+is the line that is displayed as fully saturated magenta.  When
+two-sided (and static) colors are used, the line at infinity lies at
+the points where the red and green "sides" of the projective plane
+meet (of course, the real projective plane only has one side, so this
+is a design choice of the visualization).  Alternatively, when
+orientation markers are being displayed, the line at infinity is the
+place where the orientation markers change their orientation.
 .PP
 Note that when the projective plane is displayed with bands, the
 orientation markers are placed in the middle of the bands.  For
@@ -134,27 +138,32 @@ origin) is a Moebius strip, which also shows that the projective plane
 is non-orientable.
 .PP
 Finally, the colors with with the projective plane is drawn can be set
-to two-sided, distance, direction, or depth.  In two-sided mode, the
-projective plane is drawn with red on one "side" and green on the
-"other side".  As described above, the projective plane only has one
-side, so the color jumps from red to green along the line at infinity.
-This mode enables you to see that the projective plane is
-non-orientable.  In distance mode, the projective plane is displayed
-with fully saturated colors that depend on the distance of the points
-on the projective plane to the origin.  The origin is displayed in
-red, the line at infinity is displayed in magenta.  If the projective
-plane is displayed as distance bands, each band will be displayed with
-a different color.  In direction mode, the projective plane is
-displayed with fully saturated colors that depend on the angle of the
-points on the projective plane with respect to the origin.  Angles in
-opposite directions to the origin (e.g., 15 and 205 degrees) are
-displayed in the same color since they are projectively equivalent.
-If the projective plane is displayed as direction bands, each band
-will be displayed with a different color.  Finally, in depth mode the
-projective plane with colors chosen depending on the 4d "depth" (i.e.,
-the w coordinate) of the points on the projective plane at its default
-orientation in 4d.  As discussed above, this mode enables you to see
-that the projective plane does not intersect itself in 4d.
+to one-sided, two-sided, distance, direction, or depth.  In one-sided
+mode, the projective plane is drawn with the same color on both
+"sides."  In two-sided mode (using static colors), the projective
+plane is drawn with red on one "side" and green on the "other side."
+As described above, the projective plane only has one side, so the
+color jumps from red to green along the line at infinity.  This mode
+enables you to see that the projective plane is non-orientable.  If
+changing colors are used in two-sided mode, changing complementary
+colors are used on the respective "sides."  In distance mode, the
+projective plane is displayed with fully saturated colors that depend
+on the distance of the points on the projective plane to the origin.
+If static colors are used, the origin is displayed in red, while the
+line at infinity is displayed in magenta.  If the projective plane is
+displayed as distance bands, each band will be displayed with a
+different color.  In direction mode, the projective plane is displayed
+with fully saturated colors that depend on the angle of the points on
+the projective plane with respect to the origin.  Angles in opposite
+directions to the origin (e.g., 15 and 205 degrees) are displayed in
+the same color since they are projectively equivalent.  If the
+projective plane is displayed as direction bands, each band will be
+displayed with a different color.  Finally, in depth mode the
+projective plane is displayed with colors chosen depending on the 4d
+"depth" (i.e., the w coordinate) of the points on the projective plane
+at its default orientation in 4d.  As discussed above, this mode
+enables you to see that the projective plane does not intersect itself
+in 4d.
 .PP
 The rotation speed for each of the six planes around which the
 projective plane rotates can be chosen.  For the walk-and-turn mode,
@@ -238,18 +247,23 @@ to color the projective plane.
 .B \-colors random
 Display the projective plane with a random color scheme (default).
 .TP 8
+.B \-colors onesided \fP(Shortcut: \fB\-onesided-colors\fP)
+Display the projective plane with a single color.
+.TP 8
 .B \-colors twosided \fP(Shortcut: \fB\-twosided-colors\fP)
-Display the projective plane with two colors: red on one "side" and
-green on the "other side."  Note that the line at infinity lies at the
+Display the projective plane with two colors: one color one "side" and
+the complementary color on the "other side."  For static colors, the
+colors are red and green.  Note that the line at infinity lies at the
 points where the red and green "sides" of the projective plane meet,
 i.e., where the orientation of the projective plane reverses.
 .TP 8
 .B \-colors distance \fP(Shortcut: \fB\-distance-colors\fP)
 Display the projective plane with fully saturated colors that depend
 on the distance of the points on the projective plane to the origin.
-The origin is displayed in red, the line at infinity is displayed in
-magenta.  If the projective plane is displayed as distance bands, each
-band will be displayed with a different color.
+For static colors, the origin is displayed in red, while the line at
+infinity is displayed in magenta.  If the projective plane is
+displayed as distance bands, each band will be displayed with a
+different color.
 .TP 8
 .B \-colors direction \fP(Shortcut: \fB\-direction-colors\fP)
 Display the projective plane with fully saturated colors that depend
@@ -264,6 +278,16 @@ Display the projective plane with colors chosen depending on the 4d
 "depth" (i.e., the w coordinate) of the points on the projective plane
 at its default orientation in 4d.
 .PP
+The following options determine whether the colors with which the
+projective plane is displayed are static or are changing dynamically.
+.TP 8
+.B \-change-colors
+Change the colors with which the projective plane is displayed
+dynamically.
+.TP 8
+.B \-no-change-colors
+Use static colors to display the projective plane (default).
+.PP
 The following four options are mutually exclusive.  They determine how
 to view the projective plane.
 .TP 8
@@ -388,7 +412,7 @@ stored in the RESOURCE_MANAGER property.
 .BR X (1),
 .BR xscreensaver (1)
 .SH COPYRIGHT
-Copyright \(co 2005-2014 by Carsten Steger.  Permission to use, copy,
+Copyright \(co 2013-2020 by Carsten Steger.  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
@@ -397,4 +421,4 @@ 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
-Carsten Steger <carsten@mirsanmir.org>, 03-oct-2014.
+Carsten Steger <carsten@mirsanmir.org>, 06-jan-2020.
index e906082141e0faf20d4a35d04d2ba702cfc27d1a..69575564af9061f24d77cdbb70ac5cd32b645d2d 100644 (file)
@@ -3,10 +3,10 @@
    smoothly between the Roman surface and the Boy surface. */
 
 #if 0
-static const char sccsid[] = "@(#)romanboy.c  1.1 14/10/03 xlockmore";
+static const char sccsid[] = "@(#)romanboy.c  1.1 03/10/14 xlockmore";
 #endif
 
-/* Copyright (c) 2013-2014 Carsten Steger <carsten@mirsanmir.org>. */
+/* Copyright (c) 2014-2020 Carsten Steger <carsten@mirsanmir.org>. */
 
 /*
  * Permission to use, copy, modify, and distribute this software and its
@@ -22,15 +22,16 @@ static const char sccsid[] = "@(#)romanboy.c  1.1 14/10/03 xlockmore";
  * other special, indirect and consequential damages.
  *
  * REVISION HISTORY:
- * C. Steger - 14/10/03: Initial version
+ * C. Steger - 03/10/14: Initial version
+ * C. Steger - 06/01/20: Added the changing colors mode.
  */
 
 /*
- * This program shows a 3d immersion of the real projective plane
- * that smoothly deforms between the Roman surface and the Boy
- * surface.  You can walk on the projective plane or turn in 3d.  The
- * smooth deformation (homotopy) between these two famous immersions
- * of the real projective plane was constructed by François Apéry.
+ * This program shows a 3d immersion of the real projective plane that
+ * smoothly deforms between the Roman surface and the Boy surface.
+ * You can walk on the projective plane or turn in 3d.  The smooth
+ * deformation (homotopy) between these two famous immersions of the
+ * real projective plane was constructed by François Apéry.
  *
  * The real projective plane is a non-orientable surface.  To make
  * this apparent, the two-sided color mode can be used.
@@ -43,10 +44,11 @@ static const char sccsid[] = "@(#)romanboy.c  1.1 14/10/03 xlockmore";
  * The real projective plane is a model for the projective geometry in
  * 2d space.  One point can be singled out as the origin.  A line can
  * be singled out as the line at infinity, i.e., a line that lies at
- * an infinite distance to the origin.  The line at infinity is
- * topologically a circle.  Points on the line at infinity are also
- * used to model directions in projective geometry.  The origin can be
- * visualized in different manners.  When using distance colors, the
+ * an infinite distance to the origin.  The line at infinity, like all
+ * lines in the projective plane, is topologically a circle.  Points
+ * on the line at infinity are also used to model directions in
+ * projective geometry.  The origin can be visualized in different
+ * manners.  When using distance colors (and using static colors), the
  * origin is the point that is displayed as fully saturated red, which
  * is easier to see as the center of the reddish area on the
  * projective plane.  Alternatively, when using distance bands, the
@@ -56,14 +58,15 @@ static const char sccsid[] = "@(#)romanboy.c  1.1 14/10/03 xlockmore";
  * markers are being displayed, the origin the the point where all
  * orientation markers are compressed to a point.  The line at
  * infinity can also be visualized in different ways.  When using
- * distance colors, the line at infinity is the line that is displayed
- * as fully saturated magenta.  When two-sided colors are used, the
- * line at infinity lies at the points where the red and green "sides"
- * of the projective plane meet (of course, the real projective plane
- * only has one side, so this is a design choice of the
- * visualization).  Alternatively, when orientation markers are being
- * displayed, the line at infinity is the place where the orientation
- * markers change their orientation.
+ * distance colors (and using static colors), the line at infinity is
+ * the line that is displayed as fully saturated magenta.  When
+ * two-sided (and static) colors are used, the line at infinity lies
+ * at the points where the red and green "sides" of the projective
+ * plane meet (of course, the real projective plane only has one side,
+ * so this is a design choice of the visualization).  Alternatively,
+ * when orientation markers are being displayed, the line at infinity
+ * is the place where the orientation markers change their
+ * orientation.
  *
  * Note that when the projective plane is displayed with bands, the
  * orientation markers are placed in the middle of the bands.  For
@@ -100,24 +103,28 @@ static const char sccsid[] = "@(#)romanboy.c  1.1 14/10/03 xlockmore";
  * projective plane is non-orientable.
  *
  * Finally, the colors with with the projective plane is drawn can be
- * set to two-sided, distance, or direction.  In two-sided mode, the
- * projective plane is drawn with red on one "side" and green on the
- * "other side".  As described above, the projective plane only has
- * one side, so the color jumps from red to green along the line at
- * infinity.  This mode enables you to see that the projective plane
- * is non-orientable.  In distance mode, the projective plane is
- * displayed with fully saturated colors that depend on the distance
- * of the points on the projective plane to the origin.  The origin is
- * displayed in red, the line at infinity is displayed in magenta.  If
- * the projective plane is displayed as distance bands, each band will
- * be displayed with a different color.  In direction mode, the
- * projective plane is displayed with fully saturated colors that
- * depend on the angle of the points on the projective plane with
- * respect to the origin.  Angles in opposite directions to the origin
- * (e.g., 15 and 205 degrees) are displayed in the same color since
- * they are projectively equivalent.  If the projective plane is
- * displayed as direction bands, each band will be displayed with a
- * different color.
+ * set to one-sided, two-sided, distance, or direction.  In one-sided
+ * mode, the projective plane is drawn with the same color on both
+ * "sides."  In two-sided mode (using static colors), the projective
+ * plane is drawn with red on one "side" and green on the "other
+ * side."  As described above, the projective plane only has one side,
+ * so the color jumps from red to green along the line at infinity.
+ * This mode enables you to see that the projective plane is
+ * non-orientable.  If changing colors are used in two-sided mode,
+ * changing complementary colors are used on the respective "sides."
+ * In distance mode, the projective plane is displayed with fully
+ * saturated colors that depend on the distance of the points on the
+ * projective plane to the origin.  If static colors are used, the
+ * origin is displayed in red, while the line at infinity is displayed
+ * in magenta.  If the projective plane is displayed as distance
+ * bands, each band will be displayed with a different color.  In
+ * direction mode, the projective plane is displayed with fully
+ * saturated colors that depend on the angle of the points on the
+ * projective plane with respect to the origin.  Angles in opposite
+ * directions to the origin (e.g., 15 and 205 degrees) are displayed
+ * in the same color since they are projectively equivalent.  If the
+ * projective plane is displayed as direction bands, each band will be
+ * displayed with a different color.
  *
  * The rotation speed for each of the three coordinate axes around
  * which the projective plane rotates can be chosen.
@@ -172,10 +179,11 @@ static const char sccsid[] = "@(#)romanboy.c  1.1 14/10/03 xlockmore";
 #define APPEARANCE_DIRECTION_BANDS 2
 #define NUM_APPEARANCES            3
 
-#define COLORS_TWOSIDED            0
-#define COLORS_DISTANCE            1
-#define COLORS_DIRECTION           2
-#define NUM_COLORS                 3
+#define COLORS_ONESIDED            0
+#define COLORS_TWOSIDED            1
+#define COLORS_DISTANCE            2
+#define COLORS_DIRECTION           3
+#define NUM_COLORS                 4
 
 #define VIEW_WALK                  0
 #define VIEW_TURN                  1
@@ -190,6 +198,7 @@ static const char sccsid[] = "@(#)romanboy.c  1.1 14/10/03 xlockmore";
 #define DEF_COLORS                 "random"
 #define DEF_VIEW_MODE              "random"
 #define DEF_MARKS                  "False"
+#define DEF_CHANGE_COLORS          "False"
 #define DEF_DEFORM                 "True"
 #define DEF_PROJECTION             "random"
 #define DEF_SPEEDX                 "1.1"
@@ -239,6 +248,7 @@ static char *color_mode;
 static char *view_mode;
 static Bool marks;
 static Bool deform;
+static Bool change_colors;
 static char *proj;
 static float speed_x;
 static float speed_y;
@@ -261,16 +271,19 @@ static XrmOptionDescRec opts[] =
   {"-distance-bands",      ".appearance",    XrmoptionNoArg,  "distance-bands" },
   {"-direction-bands",     ".appearance",    XrmoptionNoArg,  "direction-bands" },
   {"-colors",              ".colors",        XrmoptionSepArg, 0 },
+  {"-onesided-colors",     ".colors",        XrmoptionNoArg,  "one-sided" },
   {"-twosided-colors",     ".colors",        XrmoptionNoArg,  "two-sided" },
   {"-distance-colors",     ".colors",        XrmoptionNoArg,  "distance" },
   {"-direction-colors",    ".colors",        XrmoptionNoArg,  "direction" },
+  {"-change-colors",       ".changeColors",  XrmoptionNoArg,  "on"},
+  {"+change-colors",       ".changeColors",  XrmoptionNoArg,  "off"},
   {"-view-mode",           ".viewMode",      XrmoptionSepArg, 0 },
   {"-walk",                ".viewMode",      XrmoptionNoArg,  "walk" },
   {"-turn",                ".viewMode",      XrmoptionNoArg,  "turn" },
-  {"-deform",              ".deform",        XrmoptionNoArg, "on"},
-  {"+deform",              ".deform",        XrmoptionNoArg, "off"},
-  {"-orientation-marks",   ".marks",         XrmoptionNoArg, "on"},
-  {"+orientation-marks",   ".marks",         XrmoptionNoArg, "off"},
+  {"-deform",              ".deform",        XrmoptionNoArg,  "on"},
+  {"+deform",              ".deform",        XrmoptionNoArg,  "off"},
+  {"-orientation-marks",   ".marks",         XrmoptionNoArg,  "on"},
+  {"+orientation-marks",   ".marks",         XrmoptionNoArg,  "off"},
   {"-projection",          ".projection",    XrmoptionSepArg, 0 },
   {"-perspective",         ".projection",    XrmoptionNoArg,  "perspective" },
   {"-orthographic",        ".projection",    XrmoptionNoArg,  "orthographic" },
@@ -291,6 +304,7 @@ static argtype vars[] =
   { &mode,           "displayMode",   "DisplayMode",   DEF_DISPLAY_MODE,   t_String },
   { &appear,         "appearance",    "Appearance",    DEF_APPEARANCE,     t_String },
   { &color_mode,     "colors",        "Colors",        DEF_COLORS,         t_String },
+  { &change_colors,  "changeColors",  "ChangeColors",  DEF_CHANGE_COLORS,  t_Bool },
   { &view_mode,      "viewMode",      "ViewMode",      DEF_VIEW_MODE,      t_String },
   { &deform,         "deform",        "Deform",        DEF_DEFORM,         t_Bool },
   { &marks,          "marks",         "Marks",         DEF_MARKS,          t_Bool },
@@ -312,6 +326,11 @@ ENTRYPOINT ModeSpecOpt romanboy_opts =
 /* Offset by which we walk above the projective plane */
 #define DELTAY  0.01
 
+/* Color change speeds */
+#define DRHO    0.7
+#define DSIGMA  1.1
+#define DTAU    1.7
+
 /* Number of subdivisions of the projective plane */
 #define NUMU 64
 #define NUMV 128
@@ -327,11 +346,14 @@ typedef struct {
   int display_mode;
   int appearance;
   int colors;
+  Bool change_colors;
   int view;
   int projection;
   Bool marks;
   /* 3D rotation angles */
   float alpha, beta, delta;
+  /* Color rotation angles */
+  float rho, sigma, tau;
   /* Movement parameters */
   float umove, vmove, dumove, dvmove;
   int side, dir;
@@ -472,54 +494,80 @@ static void quat_to_rotmat(float p[4], float m[3][3])
 
 
 /* Compute a fully saturated and bright color based on an angle. */
-static void color(romanboystruct *pp, double angle, float col[4])
+static void color(romanboystruct *pp, double angle, float mat[3][3],
+                  float col[4])
 {
   int s;
-  double t;
+  double t, ca, sa;
+  float m;
 
-  if (pp->colors == COLORS_TWOSIDED)
-    return;
+  if (!pp->change_colors)
+  {
+    if (pp->colors == COLORS_ONESIDED || pp->colors == COLORS_TWOSIDED)
+      return;
 
-  if (angle >= 0.0)
-    angle = fmod(angle,2.0*M_PI);
-  else
-    angle = fmod(angle,-2.0*M_PI);
-  s = floor(angle/(M_PI/3));
-  t = angle/(M_PI/3)-s;
-  if (s >= 6)
-    s = 0;
-  switch (s)
+    if (angle >= 0.0)
+      angle = fmod(angle,2.0*M_PI);
+    else
+      angle = fmod(angle,-2.0*M_PI);
+    s = floor(angle/(M_PI/3));
+    t = angle/(M_PI/3)-s;
+    if (s >= 6)
+      s = 0;
+    switch (s)
+    {
+      case 0:
+        col[0] = 1.0;
+        col[1] = t;
+        col[2] = 0.0;
+        break;
+      case 1:
+        col[0] = 1.0-t;
+        col[1] = 1.0;
+        col[2] = 0.0;
+        break;
+      case 2:
+        col[0] = 0.0;
+        col[1] = 1.0;
+        col[2] = t;
+        break;
+      case 3:
+        col[0] = 0.0;
+        col[1] = 1.0-t;
+        col[2] = 1.0;
+        break;
+      case 4:
+        col[0] = t;
+        col[1] = 0.0;
+        col[2] = 1.0;
+        break;
+      case 5:
+        col[0] = 1.0;
+        col[1] = 0.0;
+        col[2] = 1.0-t;
+        break;
+    }
+  }
+  else /* pp->change_colors */
   {
-    case 0:
-      col[0] = 1.0;
-      col[1] = t;
-      col[2] = 0.0;
-      break;
-    case 1:
-      col[0] = 1.0-t;
-      col[1] = 1.0;
-      col[2] = 0.0;
-      break;
-    case 2:
-      col[0] = 0.0;
-      col[1] = 1.0;
-      col[2] = t;
-      break;
-    case 3:
-      col[0] = 0.0;
-      col[1] = 1.0-t;
-      col[2] = 1.0;
-      break;
-    case 4:
-      col[0] = t;
-      col[1] = 0.0;
-      col[2] = 1.0;
-      break;
-    case 5:
-      col[0] = 1.0;
-      col[1] = 0.0;
-      col[2] = 1.0-t;
-      break;
+    if (pp->colors == COLORS_ONESIDED || pp->colors == COLORS_TWOSIDED)
+    {
+      col[0] = mat[0][2];
+      col[1] = mat[1][2];
+      col[2] = mat[2][2];
+    }
+    else
+    {
+      ca = cos(angle);
+      sa = sin(angle);
+      col[0] = ca*mat[0][0]+sa*mat[0][1];
+      col[1] = ca*mat[1][0]+sa*mat[1][1];
+      col[2] = ca*mat[2][0]+sa*mat[2][1];
+    }
+    m = 0.5f/fmaxf(fmaxf(fabsf(col[0]),fabsf(col[1])),fabsf(col[2]));
+    col[0] = m*col[0]+0.5f;
+    col[1] = m*col[1]+0.5f;
+    col[2] = m*col[2]+0.5f;
   }
   if (pp->display_mode == DISP_TRANSPARENT)
     col[3] = 0.7;
@@ -550,10 +598,13 @@ static void setup_roman_boy_color_texture(ModeInfo *mi, double umin,
       else
         u = ur*j/numu+umin;
       v = vr*i/numv+vmin;
-      if (pp->colors == COLORS_DIRECTION)
-        color(pp,2.0*M_PI-fmod(2.0*u,2.0*M_PI),&pp->col[4*k]);
-      else /* pp->colors == COLORS_DISTANCE */
-        color(pp,v*(5.0/6.0),&pp->col[4*k]);
+      if (!pp->change_colors)
+      {
+        if (pp->colors == COLORS_DIRECTION)
+          color(pp,2.0*M_PI-fmod(2.0*u,2.0*M_PI),NULL,&pp->col[4*k]);
+        else /* pp->colors == COLORS_DISTANCE */
+          color(pp,v*(5.0/6.0),NULL,&pp->col[4*k]);
+      }
       pp->tex[2*k+0] = -16*g*u/(2.0*M_PI);
       if (pp->appearance == APPEARANCE_DISTANCE_BANDS)
         pp->tex[2*k+1] = 32*v/(2.0*M_PI)-0.5;
@@ -569,11 +620,14 @@ static int roman_boy(ModeInfo *mi, double umin, double umax,
                      double vmin, double vmax, int numu, int numv)
 {
   int polys = 0;
-  static const GLfloat mat_diff_red[]         = { 1.0, 0.0, 0.0, 1.0 };
-  static const GLfloat mat_diff_green[]       = { 0.0, 1.0, 0.0, 1.0 };
-  static const GLfloat mat_diff_trans_red[]   = { 1.0, 0.0, 0.0, 0.7 };
-  static const GLfloat mat_diff_trans_green[] = { 0.0, 1.0, 0.0, 0.7 };
-  float p[3], pu[3], pv[3], pm[3], n[3], b[3], mat[3][3];
+  static const GLfloat mat_diff_red[]           = { 1.0, 0.0, 0.0, 1.0 };
+  static const GLfloat mat_diff_green[]         = { 0.0, 1.0, 0.0, 1.0 };
+  static const GLfloat mat_diff_oneside[]       = { 0.9, 0.4, 0.3, 1.0 };
+  static const GLfloat mat_diff_trans_red[]     = { 1.0, 0.0, 0.0, 0.7 };
+  static const GLfloat mat_diff_trans_green[]   = { 0.0, 1.0, 0.0, 0.7 };
+  static const GLfloat mat_diff_trans_oneside[] = { 0.9, 0.4, 0.3, 0.7 };
+  float mat_diff_dyn[4], mat_diff_dyn_compl[4];
+  float p[3], pu[3], pv[3], pm[3], n[3], b[3], mat[3][3], matc[3][3];
   int i, j, k, l, m, o, g;
   double u, v, ur, vr, oz;
   double xx[3], xxu[3], xxv[3];
@@ -591,6 +645,10 @@ static int roman_boy(ModeInfo *mi, double umin, double umax,
   r = 1.0+d*d*(1.0/2.0+d*d*(1.0/6.0+d*d*(1.0/3.0)));
   radius = 1.0/r;
   oz = 0.5*r;
+
+  if (pp->change_colors)
+    rotateall(pp->rho,pp->sigma,pp->tau,matc);
+
   if (pp->view == VIEW_WALK)
   {
     u = pp->umove;
@@ -740,18 +798,54 @@ static int roman_boy(ModeInfo *mi, double umin, double umax,
     mult_rotmat(r2,r1,mat);
   }
 
-  if (pp->colors == COLORS_TWOSIDED)
+  if (!pp->change_colors)
   {
-    glColor3fv(mat_diff_red);
-    if (pp->display_mode == DISP_TRANSPARENT)
+    if (pp->colors == COLORS_ONESIDED)
     {
-      glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_red);
-      glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_green);
+      glColor3fv(mat_diff_oneside);
+      if (pp->display_mode == DISP_TRANSPARENT)
+      {
+        glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,
+                     mat_diff_trans_oneside);
+      }
+      else
+      {
+        glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,
+                     mat_diff_oneside);
+      }
     }
-    else
+    else if (pp->colors == COLORS_TWOSIDED)
     {
-      glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_red);
-      glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_green);
+      glColor3fv(mat_diff_red);
+      if (pp->display_mode == DISP_TRANSPARENT)
+      {
+        glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_red);
+        glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_green);
+      }
+      else
+      {
+        glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_red);
+        glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_green);
+      }
+    }
+  }
+  else /* pp->change_colors */
+  {
+    color(pp,0.0,matc,mat_diff_dyn);
+    if (pp->colors == COLORS_ONESIDED)
+    {
+      glColor3fv(mat_diff_dyn);
+      glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn);
+    }
+    else if (pp->colors == COLORS_TWOSIDED)
+    {
+      mat_diff_dyn_compl[0] = 1.0f-mat_diff_dyn[0];
+      mat_diff_dyn_compl[1] = 1.0f-mat_diff_dyn[1];
+      mat_diff_dyn_compl[2] = 1.0f-mat_diff_dyn[2];
+      mat_diff_dyn_compl[3] = mat_diff_dyn[3];
+      glColor3fv(mat_diff_dyn);
+      glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn);
+      glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn_compl);
     }
   }
   glBindTexture(GL_TEXTURE_2D,pp->tex_name);
@@ -772,6 +866,14 @@ static int roman_boy(ModeInfo *mi, double umin, double umax,
         o = i*(numu+1)+j;
         u = ur*j/numu+umin;
         v = vr*i/numv+vmin;
+        if (pp->change_colors)
+        {
+          /* Compute the colors dynamically. */
+          if (pp->colors == COLORS_DIRECTION)
+            color(pp,2.0*M_PI-fmod(2.0*u,2.0*M_PI),matc,&pp->col[4*o]);
+          else if (pp->colors == COLORS_DISTANCE)
+            color(pp,v*(5.0/6.0),matc,&pp->col[4*o]);
+        }
         if (g & 1)
           v = 0.5*M_PI-0.25*v;
         else
@@ -872,6 +974,14 @@ static int roman_boy(ModeInfo *mi, double umin, double umax,
         o = i*(numu+1)+j;
         u = -ur*j/numu+umin;
         v = vr*i/numv+vmin;
+        if (pp->change_colors)
+        {
+          /* Compute the colors dynamically. */
+          if (pp->colors == COLORS_DIRECTION)
+            color(pp,2.0*M_PI-fmod(2.0*u,2.0*M_PI),matc,&pp->col[4*o]);
+          else if (pp->colors == COLORS_DISTANCE)
+            color(pp,v*(5.0/6.0),matc,&pp->col[4*o]);
+        }
         if (g & 1)
           v = 0.5*M_PI-0.25*v;
         else
@@ -981,7 +1091,7 @@ static int roman_boy(ModeInfo *mi, double umin, double umax,
           m = j;
           o = l*(numu+1)+m;
           glTexCoord2fv(&pp->tex[2*o]);
-          if (pp->colors != COLORS_TWOSIDED)
+          if (pp->colors != COLORS_ONESIDED && pp->colors != COLORS_TWOSIDED)
           {
             glColor3fv(&pp->col[4*o]);
             glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,
@@ -1013,7 +1123,7 @@ static int roman_boy(ModeInfo *mi, double umin, double umax,
           m = (j+k);
           o = l*(numu+1)+m;
           glTexCoord2fv(&pp->tex[2*o]);
-          if (pp->colors != COLORS_TWOSIDED)
+          if (pp->colors != COLORS_ONESIDED && pp->colors != COLORS_TWOSIDED)
           {
             glColor3fv(&pp->col[4*o]);
             glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,
@@ -1046,7 +1156,7 @@ static void gen_texture(ModeInfo *mi)
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
   glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
-  glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,TEX_DIMENSION,TEX_DIMENSION,0,
+  glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,TEX_DIMENSION,TEX_DIMENSION,0,
                GL_LUMINANCE,GL_UNSIGNED_BYTE,texture);
 }
 
@@ -1096,6 +1206,10 @@ static void init(ModeInfo *mi)
   pp->dd = init_deform*0.001;
   pp->defdir = -1;
 
+  pp->rho = frand(360.0);
+  pp->sigma = frand(360.0);
+  pp->tau = frand(360.0);
+
   pp->offset3d[0] = 0.0;
   pp->offset3d[1] = 0.0;
   pp->offset3d[2] = -1.8;
@@ -1241,6 +1355,18 @@ static void display_romanboy(ModeInfo *mi)
       if (pp->umove < 0.0)
         pp->umove += 2.0*M_PI;
     }
+    if (pp->change_colors)
+    {
+      pp->rho += DRHO;
+      if (pp->rho >= 360.0)
+        pp->rho -= 360.0;
+      pp->sigma += DSIGMA;
+      if (pp->sigma >= 360.0)
+        pp->sigma -= 360.0;
+      pp->tau += DTAU;
+      if (pp->tau >= 360.0)
+        pp->tau -= 360.0;
+    }
   }
 
   glMatrixMode(GL_PROJECTION);
@@ -1269,16 +1395,10 @@ static void display_romanboy(ModeInfo *mi)
 ENTRYPOINT void reshape_romanboy(ModeInfo *mi, int width, int height)
 {
   romanboystruct *pp = &romanboy[MI_SCREEN(mi)];
-  int y = 0;
-
-  if (width > height * 5) {   /* tiny window: show middle */
-    height = width;
-    y = -height/2;
-  }
 
   pp->WindW = (GLint)width;
   pp->WindH = (GLint)height;
-  glViewport(0,y,width,height);
+  glViewport(0,0,width,height);
   pp->aspect = (GLfloat)width/(GLfloat)height;
 }
 
@@ -1402,6 +1522,10 @@ ENTRYPOINT void init_romanboy(ModeInfo *mi)
   {
     pp->colors = random() % NUM_COLORS;
   }
+  else if (!strcasecmp(color_mode,"one-sided"))
+  {
+    pp->colors = COLORS_ONESIDED;
+  }
   else if (!strcasecmp(color_mode,"two-sided"))
   {
     pp->colors = COLORS_TWOSIDED;
@@ -1419,6 +1543,8 @@ ENTRYPOINT void init_romanboy(ModeInfo *mi)
     pp->colors = random() % NUM_COLORS;
   }
 
+  pp->change_colors = change_colors;
+
   /* Set the view mode. */
   if (!strcasecmp(view_mode,"random"))
   {
index 2957a0ec4b71a1c6423dd35f7464ed38d4eb12cd..e4e947b3b0363adfe7072e68f36c12e3630a8d26 100644 (file)
@@ -20,9 +20,11 @@ smoothly deforms between the Roman surface and the Boy surface.
 [\-distance-bands]
 [\-direction-bands]
 [\-colors \fIcolor-scheme\fP]
+[\-onesided-colors]
 [\-twosided-colors]
 [\-distance-colors]
 [\-direction-colors]
+[\-change-colors]
 [\-view-mode \fIview-mode\fP]
 [\-walk]
 [\-turn]
@@ -59,26 +61,27 @@ non-orientable).
 The real projective plane is a model for the projective geometry in 2d
 space.  One point can be singled out as the origin.  A line can be
 singled out as the line at infinity, i.e., a line that lies at an
-infinite distance to the origin.  The line at infinity is
-topologically a circle.  Points on the line at infinity are also used
-to model directions in projective geometry.  The origin can be
-visualized in different manners.  When using distance colors, the
-origin is the point that is displayed as fully saturated red, which is
-easier to see as the center of the reddish area on the projective
-plane.  Alternatively, when using distance bands, the origin is the
-center of the only band that projects to a disk.  When using direction
-bands, the origin is the point where all direction bands collapse to a
-point.  Finally, when orientation markers are being displayed, the
-origin the the point where all orientation markers are compressed to a
-point.  The line at infinity can also be visualized in different ways.
-When using distance colors, the line at infinity is the line that is
-displayed as fully saturated magenta.  When two-sided colors are used,
-the line at infinity lies at the points where the red and green
-"sides" of the projective plane meet (of course, the real projective
-plane only has one side, so this is a design choice of the
-visualization).  Alternatively, when orientation markers are being
-displayed, the line at infinity is the place where the orientation
-markers change their orientation.
+infinite distance to the origin.  The line at infinity, like all lines
+in the projective plane, is topologically a circle.  Points on the
+line at infinity are also used to model directions in projective
+geometry.  The origin can be visualized in different manners.  When
+using distance colors (and using static colors), the origin is the
+point that is displayed as fully saturated red, which is easier to see
+as the center of the reddish area on the projective plane.
+Alternatively, when using distance bands, the origin is the center of
+the only band that projects to a disk.  When using direction bands,
+the origin is the point where all direction bands collapse to a point.
+Finally, when orientation markers are being displayed, the origin the
+the point where all orientation markers are compressed to a point.
+The line at infinity can also be visualized in different ways.  When
+using distance colors (and using static colors), the line at infinity
+is the line that is displayed as fully saturated magenta.  When
+two-sided (and static) colors are used, the line at infinity lies at
+the points where the red and green "sides" of the projective plane
+meet (of course, the real projective plane only has one side, so this
+is a design choice of the visualization).  Alternatively, when
+orientation markers are being displayed, the line at infinity is the
+place where the orientation markers change their orientation.
 .PP
 Note that when the projective plane is displayed with bands, the
 orientation markers are placed in the middle of the bands.  For
@@ -114,23 +117,27 @@ origin) is a Moebius strip, which also shows that the projective plane
 is non-orientable.
 .PP
 Finally, the colors with with the projective plane is drawn can be set
-to two-sided, distance, or direction.  In two-sided mode, the
-projective plane is drawn with red on one "side" and green on the
-"other side".  As described above, the projective plane only has one
-side, so the color jumps from red to green along the line at infinity.
-This mode enables you to see that the projective plane is
-non-orientable.  In distance mode, the projective plane is displayed
-with fully saturated colors that depend on the distance of the points
-on the projective plane to the origin.  The origin is displayed in
-red, the line at infinity is displayed in magenta.  If the projective
-plane is displayed as distance bands, each band will be displayed with
-a different color.  In direction mode, the projective plane is
-displayed with fully saturated colors that depend on the angle of the
-points on the projective plane with respect to the origin.  Angles in
-opposite directions to the origin (e.g., 15 and 205 degrees) are
-displayed in the same color since they are projectively equivalent.
-If the projective plane is displayed as direction bands, each band
-will be displayed with a different color.
+to one-sided, two-sided, distance, or direction.  In one-sided mode,
+the projective plane is drawn with the same color on both "sides."  In
+two-sided mode (using static colors), the projective plane is drawn
+with red on one "side" and green on the "other side."  As described
+above, the projective plane only has one side, so the color jumps from
+red to green along the line at infinity.  This mode enables you to see
+that the projective plane is non-orientable.  If changing colors are
+used in two-sided mode, changing complementary colors are used on the
+respective "sides."  In distance mode, the projective plane is
+displayed with fully saturated colors that depend on the distance of
+the points on the projective plane to the origin.  If static colors
+are used, the origin is displayed in red, while the line at infinity
+is displayed in magenta.  If the projective plane is displayed as
+distance bands, each band will be displayed with a different color.
+In direction mode, the projective plane is displayed with fully
+saturated colors that depend on the angle of the points on the
+projective plane with respect to the origin.  Angles in opposite
+directions to the origin (e.g., 15 and 205 degrees) are displayed in
+the same color since they are projectively equivalent.  If the
+projective plane is displayed as direction bands, each band will be
+displayed with a different color.
 .PP
 The rotation speed for each of the three coordinate axes around which
 the projective plane rotates can be chosen.
@@ -230,18 +237,23 @@ to color the projective plane.
 .B \-colors random
 Display the projective plane with a random color scheme (default).
 .TP 8
+.B \-colors onesided \fP(Shortcut: \fB\-onesided-colors\fP)
+Display the projective plane with a single color.
+.TP 8
 .B \-colors twosided \fP(Shortcut: \fB\-twosided-colors\fP)
-Display the projective plane with two colors: red on one "side" and
-green on the "other side."  Note that the line at infinity lies at the
+Display the projective plane with two colors: one color one "side" and
+the complementary color on the "other side."  For static colors, the
+colors are red and green.  Note that the line at infinity lies at the
 points where the red and green "sides" of the projective plane meet,
 i.e., where the orientation of the projective plane reverses.
 .TP 8
 .B \-colors distance \fP(Shortcut: \fB\-distance-colors\fP)
 Display the projective plane with fully saturated colors that depend
 on the distance of the points on the projective plane to the origin.
-The origin is displayed in red, the line at infinity is displayed in
-magenta.  If the projective plane is displayed as distance bands, each
-band will be displayed with a different color.
+For static colors, the origin is displayed in red, while the line at
+infinity is displayed in magenta.  If the projective plane is
+displayed as distance bands, each band will be displayed with a
+different color.
 .TP 8
 .B \-colors direction \fP(Shortcut: \fB\-direction-colors\fP)
 Display the projective plane with fully saturated colors that depend
@@ -251,6 +263,16 @@ degrees) are displayed in the same color since they are projectively
 equivalent.  If the projective plane is displayed as direction bands,
 each band will be displayed with a different color.
 .PP
+The following options determine whether the colors with which the
+projective plane is displayed are static or are changing dynamically.
+.TP 8
+.B \-change-colors
+Change the colors with which the projective plane is displayed
+dynamically.
+.TP 8
+.B \-no-change-colors
+Use static colors to display the projective plane (default).
+.PP
 The following three options are mutually exclusive.  They determine
 how to view the projective plane.
 .TP 8
@@ -378,7 +400,7 @@ stored in the RESOURCE_MANAGER property.
 .BR X (1),
 .BR xscreensaver (1)
 .SH COPYRIGHT
-Copyright \(co 2013-2014 by Carsten Steger.  Permission to use, copy,
+Copyright \(co 2013-2020 by Carsten Steger.  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
@@ -387,4 +409,4 @@ 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
-Carsten Steger <carsten@mirsanmir.org>, 03-oct-2014.
+Carsten Steger <carsten@mirsanmir.org>, 06-jan-2020.
index 961dcf50e6b56bb8db73e633c3dd157c8b86070b..658074b5cc0c77a851929f9246e63ea3477a8696 100644 (file)
@@ -1,4 +1,4 @@
-/* sonar, Copyright (c) 1998-2019 Jamie Zawinski and Stephen Martin
+/* sonar, Copyright (c) 1998-2020 Jamie Zawinski and Stephen Martin
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -939,6 +939,7 @@ send_ping (ping_data *pd, const sonar_bogie *b)
   struct ICMP *icmph;
   const char *token = "org.jwz.xscreensaver.sonar";
   char *host_id;
+  struct timeval tval;
 
   unsigned long pcktsiz = (sizeof(struct ICMP) + sizeof(struct timeval) +
                  sizeof(socklen_t) + pb->addrlen +
@@ -956,12 +957,16 @@ send_ping (ping_data *pd, const sonar_bogie *b)
   ICMP_CHECKSUM(icmph) = 0;
   ICMP_ID(icmph) = pd->pid;
   ICMP_SEQ(icmph) = pd->seq++;
+  /* struct timeval needs alignment, so we first use aligned buffer for
+     gettimeofday() and later copy the result to packet buffer
+   */
 # ifdef GETTIMEOFDAY_TWO_ARGS
-  gettimeofday((struct timeval *) &packet[sizeof(struct ICMP)],
+  gettimeofday((struct timeval *) &tval,
                (struct timezone *) 0);
 # else
-  gettimeofday((struct timeval *) &packet[sizeof(struct ICMP)]);
+  gettimeofday((struct timeval *) &tval);
 # endif
+  memcpy(&packet[sizeof(struct ICMP)], &tval, sizeof tval);
 
   /* We store the sockaddr of the host we're pinging in the packet, and parse
      that out of the return packet later (see get_ping() for why).
@@ -1068,7 +1073,7 @@ get_ping (sonar_sensor_data *ssd)
   int result;
   u_char packet[1024];
   struct timeval now;
-  struct timeval *then;
+  struct timeval then;
   struct ip *ip;
   int iphdrlen;
   struct ICMP *icmph;
@@ -1132,7 +1137,10 @@ get_ping (sonar_sensor_data *ssd)
           ip = (struct ip *) packet;
           iphdrlen = IP_HDRLEN(ip) << 2;
           icmph = (struct ICMP *) &packet[iphdrlen];
-          then  = (struct timeval *) &packet[iphdrlen + sizeof(struct ICMP)];
+           /* struct timeval data in packet is not aligned, move the data to
+              the aligned buffer
+             */
+          memcpy(&then, &packet[iphdrlen + sizeof(struct ICMP)], sizeof then);
 
 
           /* Ignore anything but ICMP Replies */
@@ -1221,7 +1229,7 @@ get_ping (sonar_sensor_data *ssd)
           bl = new;
 
           {
-            double msec = delta(then, &now) / 1000.0;
+            double msec = delta(&then, &now) / 1000.0;
 
             if (pd->times_p)
               {
@@ -1694,7 +1702,7 @@ sonar_init_ping (Display *dpy, char **error_ret, char **desc_ret,
     fprintf (stderr, "%s: unable to open icmp socket\n", progname);
 
   /* Disavow privs */
-  setuid(getuid());
+  if (setuid(getuid()) == -1) abort();
 
   pd->pid = getpid() & 0xFFFF;
   pd->seq = 0;
index ddbb79f0b6424749e70d311b0acbfced2bc0a5d5..e4e0b865c33df498ad09de4aa2b88540e0320c2f 100644 (file)
@@ -1,4 +1,4 @@
-/* sonar, Copyright (c) 1998-2018 Jamie Zawinski and Stephen Martin
+/* sonar, Copyright (c) 1998-2020 Jamie Zawinski and Stephen Martin
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -935,7 +935,11 @@ init_sensor (ModeInfo *mi)
                                ping_arg, ping_timeout, resolve_p, times_p,
                                debug_p);
   else
-    setuid(getuid()); /* Disavow privs if not pinging. */
+    { /* Disavow privs if not pinging. */
+      if (setuid(getuid()) == -1) abort();
+    }
+
+    setuid(getuid());
 
   sp->start_time = double_time ();  /* for error message timing */
 
index bccd5682efe5ededc18dcfc14d0fafb4064935fc..0f1457a8461b0cafe2f479c0e6589f34617903d3 100644 (file)
@@ -69,6 +69,7 @@
 #define DEF_LINES      "125"
 #define DEF_STEPS      "35"
 #define DEF_SPIN       "0.03"
+#define DEF_SATURATION "0.3"
 #define DEF_SIZE       "-1"
 #define DEF_COLUMNS    "-1"
 #define DEF_LINE_WRAP  "True"
@@ -130,6 +131,7 @@ static sws_configuration *scs = NULL;
 static int max_lines;
 static int scroll_steps;
 static float star_spin;
+static float star_saturation;
 static float font_size;
 static int target_columns;
 static int wrap_p;
@@ -145,9 +147,11 @@ static XrmOptionDescRec opts[] = {
   {"-lines",       ".lines",     XrmoptionSepArg, 0 },
   {"-steps",       ".steps",     XrmoptionSepArg, 0 },
   {"-spin",        ".spin",      XrmoptionSepArg, 0 },
+  {"-saturation",  ".saturation",XrmoptionSepArg, 0 },
   {"-size",       ".size",      XrmoptionSepArg, 0 },
   {"-columns",    ".columns",   XrmoptionSepArg, 0 },
 /*{"-font",        ".font",      XrmoptionSepArg, 0 },*/
+  {"-program",    ".program",   XrmoptionSepArg, 0 },
   {"-fade",        ".fade",      XrmoptionNoArg,  "True"   },
   {"-no-fade",     ".fade",      XrmoptionNoArg,  "False"  },
   {"-textures",    ".textures",  XrmoptionNoArg,  "True"   },
@@ -170,6 +174,7 @@ static argtype vars[] = {
   {&max_lines,      "lines",     "Integer",    DEF_LINES,     t_Int},
   {&scroll_steps,   "steps",     "Integer",    DEF_STEPS,     t_Int},
   {&star_spin,      "spin",      "Float",      DEF_SPIN,      t_Float},
+  {&star_saturation,"saturation","Float",      DEF_SATURATION,t_Float},
   {&font_size,      "size",      "Float",      DEF_SIZE,      t_Float},
   {&target_columns, "columns",   "Integer",    DEF_COLUMNS,   t_Int},
   {&wrap_p,         "lineWrap",  "Boolean",    DEF_LINE_WRAP, t_Bool},
@@ -587,9 +592,10 @@ init_stars (ModeInfo *mi, int width, int height)
       glBegin (GL_POINTS);
       for (i = 0; i < nstars / steps; i++)
         {
-          glColor3f (0.6 + frand(0.3),
-                     0.6 + frand(0.3),
-                     0.6 + frand(0.3));
+          GLfloat brightness = 0.9 - star_saturation;
+          glColor3f (brightness + frand(star_saturation),
+                     brightness + frand(star_saturation),
+                     brightness + frand(star_saturation));
           glVertex2f (2 * size * (0.5 - frand(1.0)),
                       2 * size * (0.5 - frand(1.0)));
         }
index ecdd84f7e94be03377edbf77886d7c3fbe4b074e..c4e2667036dc253d390ff18aae7bce97b4d536a3 100644 (file)
@@ -387,6 +387,7 @@ static const char *halftone_defaults [] = {
 #ifdef HAVE_MOBILE
   "*ignoreRotation:     True",
 #endif
+  ".lowrez:            true",  /* Too slow on Retina screens otherwise */
   0
 };
 
index c4d5ada6d92b428e488f71f669ed79f755c37a68..c45a99ec4e836d296cd5dcc03ee345cacb9a6ea2 100644 (file)
@@ -409,6 +409,8 @@ static const char *halo_defaults [] = {
 #ifdef HAVE_MOBILE
   "*ignoreRotation:     True",
 #endif
+  ".lowrez:            true",  /* Too slow on Retina screens otherwise */
+                     /* But that looks crappy too. It's bad either way. */
   0
 };
 
index 9f3d47c8b831031ee2e313f6c5dac6f3875da88d..4b0a2393f03d4e036d99be77149712fafe47db74 100644 (file)
@@ -39,6 +39,8 @@ gen/%_png.h: %.png
 clean:
        $(RM) -r gen
 
+distclean:: clean
+
 echo_tarfiles:
        @echo $(TARFILES)
 
index 497ebfcf44602b43553c602105443cfd63cdc7e7..9a0375bdb512fd212564911019524bb2ac506637 100644 (file)
@@ -39,6 +39,8 @@ gen/%_png.h: %.png
 clean:
        $(RM) -r gen
 
+distclean:: clean
+
 echo_tarfiles:
        @echo $(TARFILES)
 
index caf47c330f47f0bb44ef3550b22a8f49c5d9ec1e..e69ad470eb5930e65a1013b2dba6edd24dc828de 100644 (file)
@@ -329,7 +329,7 @@ moire2_free (Display *dpy, Window window, void *closure)
 }
 
 static const char *moire2_defaults [] = {
-  ".lowrez:            true",
+  ".lowrez:            true",  /* Too slow on Retina screens otherwise */
   ".background:                black",
   ".foreground:                white",
   "*delay:             50000",
index fe8f60f07460b1b8050ba26f991725a8ff9924be..c45e37f9ac4a69d11c9a5560181486c9b9e0e225 100644 (file)
@@ -1,6 +1,8 @@
 /* Munching Squares and Mismunch
  *
  * Portions copyright 1992-2014 Jamie Zawinski <jwz@jwz.org>
+ * Portions Copyright 1997, Tim Showalter
+ * Portions Copyright 2004 Steven Hazel <sah@thalassocracy.org>
  *
  *   Permission to use, copy, modify, distribute, and sell this
  *   software and its documentation for any purpose is hereby
  *   representations are made about the suitability of this software
  *   for any purpose.  It is provided "as is" without express or
  *   implied warranty.
- *
- * Portions Copyright 1997, Tim Showalter
- *
- *   Permission is granted to copy, modify, and use this as long
- *   as this notice remains intact.  No warranties are expressed or
- *   implied.  CMU Sucks.
- * 
- * Portions Copyright 2004 Steven Hazel <sah@thalassocracy.org>
- *
- *   (The "mismunch" part).
  * 
  * "munch.c" and "mismunch.c" merged by jwz, 29-Aug-2008.
  *
index 7504d2ce6b39d8904707e92f74e958cb0ba3ec41..8199b2f6e00e166deddf2abd49707b96b9983ee8 100755 (executable)
@@ -57,7 +57,6 @@ my %disable = (
 
 
 # Parse the RETIRED_EXES variable from the Makefiles to populate %disable.
-# Duplicated in ../OSX/build-fntable.pl.
 #
 sub parse_makefiles() {
   foreach my $mf ( "Makefile.in", "glx/Makefile.in" ) {
index 9628619b757155d92369c90b4f0d0bc67230df9b..4b7131d3d38515d77389e6c5ab5c80b7bef4347e 100644 (file)
@@ -489,12 +489,21 @@ rd_draw (Display *dpy, Window win, void *closure)
   struct state *st = (struct state *) closure;
   Bool bump = False;
 
+  /* Let's compute N frames at once. This speeds up the progress of
+     the animation and the seething, but doesn't appreciably affect the
+     frame rate or CPU utilization. */
+  int ii;
+  int chunk = 3;
+  for (ii = 0; ii < chunk; ii++) {
+
   int i, j;
   pixack_frame(st, st->pd);
+  if (ii == chunk-1) {  /* Only need to putimage on the final frame */
   for (i = 0; i < st->array_width; i += st->width)
     for (j = 0; j < st->array_height; j += st->height)
       put_xshm_image(st->dpy, st->window, st->gc, st->image, 0, 0, i+st->array_x, j+st->array_y,
                      st->width, st->height, &st->shm_info);
+  }
 
   st->array_x += st->array_dx;
   st->array_y += st->array_dy;
@@ -526,6 +535,7 @@ rd_draw (Display *dpy, Window win, void *closure)
   }
 
   st->frame++;
+  }
 
   return st->delay;
 }
index 69bf3855acbfde3afc694cfc700addb6b5ffef6b..bd88b4b0467243e52c318c318d54f969b2e412a6 100644 (file)
@@ -1,4 +1,4 @@
-/* recanim, Copyright (c) 2014-2018 Jamie Zawinski <jwz@jwz.org>
+/* recanim, Copyright (c) 2014-2020 Jamie Zawinski <jwz@jwz.org>
  * Record animation frames of the running screenhack.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -427,7 +427,9 @@ screenhack_record_anim_free (record_anim_state *st)
            st->fps, progname, type, st->fps);
   if (soundtrack)
     sprintf (cmd + strlen(cmd),
-             " -i '%s' -map 0:v:0 -map 1:a:0 -acodec aac",
+             " -i '%s' -map 0:v:0 -map 1:a:0 -acodec aac"
+             /* Truncate or pad audio to length of video */
+             " -filter_complex '[1:0] apad' -shortest",
              soundtrack);
   sprintf (cmd + strlen(cmd),
            " -c:v libx264"
@@ -439,7 +441,11 @@ screenhack_record_anim_free (record_anim_state *st)
            /*" 2>&-"*/,
            fn);
   fprintf (stderr, "%s: exec: %s\n", progname, cmd);
-  system (cmd);
+  /* Use empty body to kill warning from gcc -Wall with
+     "warning: ignoring return value of 'system',
+     declared with attribute warn_unused_result"
+   */
+  if (system (cmd)) {}
 
   if (stat (fn, &s))
     {
diff --git a/hacks/scooter.c b/hacks/scooter.c
new file mode 100644 (file)
index 0000000..9a66da6
--- /dev/null
@@ -0,0 +1,957 @@
+/* -*- Mode: C; tab-width: 4 -*- */
+/* scooter -- a journey through space tunnel and stars */
+
+/*
+ *  scooter.c
+ *
+ *  Copyright (c) 2001 Sven Thoennissen <posse@gmx.net>
+ *
+ *  This program is based on the original "scooter", a blanker module from the
+ *  Nightshift screensaver which is part of EGS (Enhanced Graphics System) on
+ *  the Amiga computer. EGS has been developed by VIONA Development.
+ *
+ *
+ *  (now the obligatory stuff)
+ *
+ *  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.
+ *
+ *     Changes:
+ *
+ *     ??/??/2001 (Sven Thoennissen <posse@gmx.net>):    Initial release
+ *     05/08/2019 (EoflaOE <eoflaoevicecity@gmail.com>): Ported to XScreenSaver
+ */
+
+#ifdef STANDALONE
+#define MODE_scooter
+#define PROGCLASS "Scooter"
+#define HACK_INIT init_scooter
+#define HACK_DRAW draw_scooter
+#define scooter_opts xlockmore_opts
+#define DEFAULTS       "*delay: 20000 \n" \
+                                       "*count: 24 \n" \
+                                       "*cycles: 5 \n" \
+                                       "*size: 100 \n" \
+                                       "*ncolors: 200 \n" \
+                                       "*fullrandom: True \n" \
+                                       "*verbose: False \n" \
+                                       "*fpsSolid: true \n" \
+                                   "*lowrez: True \n"
+# define reshape_scooter 0
+# define scooter_handle_event 0
+#include "xlockmore.h"          /* in xscreensaver distribution */
+#else /* STANDALONE */
+#include "xlock.h"              /* in xlockmore distribution */
+#endif /* STANDALONE */
+
+#ifdef MODE_scooter
+
+ModeSpecOpt scooter_opts =
+{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
+
+#ifdef USE_MODULES
+ModStruct scooter_description =
+{"scooter", "init_scooter", "draw_scooter", "release_scooter",
+ "refresh_scooter", "change_scooter", (char *) NULL, &scooter_opts,
+ 20000, 24, 5, 100, 64, 1.0, "",
+ "Shows a journey through space tunnel and stars", 0, NULL};
+/*
+ *  count = number of doors
+ *  cycles = speed (see MIN/MAX_SPEED below)
+ *  size = number of stars
+ *
+ */
+#endif
+
+typedef struct {
+       int x, y, z;
+} Vec3D;
+
+typedef struct {
+       int x, y, z;
+} Angle3D;
+
+typedef struct {
+       int r, g, b;
+} ColorRGB;
+
+typedef struct {
+       XPoint lefttop, rightbottom;
+} Rect;
+
+typedef struct {
+       Vec3D coords[4]; /* lefttop, righttop, rightbottom, leftbottom */
+       int zelement;
+       unsigned long color;
+       char freecolor;
+       char pad;
+} Door;
+
+typedef struct {
+       int xpos, ypos;
+       int width, height;
+       int zelement;
+       short draw;
+} Star;
+
+/* define this to see a pixel for each zelement */
+/*
+#define _DRAW_ZELEMENTS
+*/
+
+typedef struct {
+       Vec3D pos;
+       Angle3D angle;
+} ZElement;
+
+typedef struct {
+       Star *stars;
+       Door *doors;
+       ZElement *zelements;
+       int doorcount, ztotal, speed;
+       int zelements_per_door, zelement_distance, spectator_zelement;
+       int projnorm_z, rotationDuration, rotationStep, starcount;
+       Angle3D currentRotation, rotationDelta;
+
+       /* doors color cycling stuff */
+       ColorRGB begincolor, endcolor;
+       int colorcount, colorsteps;
+
+       /* scale all stars and doors to window dimensions */
+       float aspect_scale;
+
+       Bool halt_scooter;
+} scooterstruct;
+
+static scooterstruct *scooters = (scooterstruct *) NULL;
+
+#define MIN_DOORS 4
+
+#define MIN_SPEED 1
+#define MAX_SPEED 10
+
+#define SPACE_XY_FACTOR 10
+
+#define DOOR_WIDTH  (600*SPACE_XY_FACTOR)
+#define DOOR_HEIGHT (400*SPACE_XY_FACTOR)
+
+/* stars distance from doors center */
+#define STAR_MIN_X  (1000*SPACE_XY_FACTOR)
+#define STAR_MIN_Y  (750*SPACE_XY_FACTOR)
+#define STAR_MAX_X  (10000*SPACE_XY_FACTOR)
+#define STAR_MAX_Y  (7500*SPACE_XY_FACTOR)
+
+/* star size (random) */
+#define STAR_SIZE_MIN (2*SPACE_XY_FACTOR)
+#define STAR_SIZE_MAX (64*SPACE_XY_FACTOR)
+
+/* greater values make scooter run harder curves, smaller values produce calm curves */
+#define DOOR_CURVEDNESS 14
+
+/* 3d->2d projection (greater values create more fish-eye effect) */
+#define PROJECTION_DEGREE 2.4
+
+/*  this is my resolution at which scooter is in its original size, producing a 4:3 aspect ratio.
+ *  all variables in this module are adjusted for this screen size; if scooter is run
+ *  in windows with different size, it knows how to rescale itself.
+ */
+#define ASPECT_SCREENWIDTH 1152
+#define ASPECT_SCREENHEIGHT 864
+
+/* we define our own sin/cos macros to be faaast ;-) (good old Amiga times) */
+#define SINUSTABLE_SIZE 0x8000
+#define SINUSTABLE_MASK 0x7fff
+#define SIN(a) sintable[a & SINUSTABLE_MASK]
+#define COS(a) sintable[(a+(SINUSTABLE_SIZE/4)) & SINUSTABLE_MASK]
+
+/* signum function */
+#define SGN(a) (a < 0 ? -1 : 1)
+
+static float *sintable = (float *) NULL;
+
+static void
+randomcolor(ColorRGB *col)
+{
+       unsigned long n;
+
+/*     col->r = NRAND(65536);
+       col->g = NRAND(65536);
+       col->b = NRAND(65536);
+*/
+/*     col->r = LRAND() & 0xffff;
+       col->g = LRAND() & 0xffff;
+       col->b = LRAND() & 0xffff;
+*/
+       /* this seems best */
+       n = NRAND(0x1000000);
+       col->r = (n>>16)<<8;
+       col->g = ((n>>8) & 0xff)<<8;
+       col->b = (n & 0xff)<<8;
+}
+
+static void
+initdoorcolors(scooterstruct *sp)
+{
+       /* prepare initial values for nextdoorcolor() */
+
+       randomcolor(&sp->endcolor);
+
+       sp->colorcount = 0;
+       sp->colorsteps = 0;
+}
+
+static void nextdoorcolor(ModeInfo *mi, Door *door)
+{
+       scooterstruct *sp = &scooters[MI_SCREEN(mi)];
+       Display *display = MI_DISPLAY(mi);
+       XColor xcol;
+
+/* comment this to color the doors from xlock's palette (created with saturation value) */
+#if 1
+       if (door->freecolor) {
+               XFreeColors(display, MI_COLORMAP(mi), &(door->color), 1, 0);
+               door->freecolor = 0;
+       }
+       if (MI_NPIXELS(mi) <= 2) {
+               door->color = MI_WHITE_PIXEL(mi);
+               return;
+       }
+
+       if (sp->colorcount >= sp->colorsteps) {
+
+               /* init next color ramp */
+
+               sp->colorcount = 0;
+               sp->colorsteps = 8 + NRAND(32);
+               sp->begincolor = sp->endcolor;
+               randomcolor(&sp->endcolor);
+       }
+
+       /* compute next color values */
+
+       xcol.red   = sp->begincolor.r + ((sp-> endcolor.r - sp->begincolor.r) *
+               sp->colorcount / sp->colorsteps);
+       xcol.green = sp->begincolor.g + ((sp-> endcolor.g - sp->begincolor.g) *
+               sp->colorcount / sp->colorsteps);
+       xcol.blue  = sp->begincolor.b + ((sp-> endcolor.b - sp->begincolor.b) *
+               sp->colorcount / sp->colorsteps);
+       xcol.pixel = 0;
+       xcol.flags = DoRed | DoGreen | DoBlue;
+
+       sp->colorcount++;
+
+       if (!XAllocColor(display, MI_COLORMAP(mi), &xcol)) {
+                /* fail safe */
+               door->color = MI_WHITE_PIXEL(mi);
+               door->freecolor = 0;
+       } else {
+               door->color = xcol.pixel;
+               door->freecolor = 1;
+       }
+#else
+       if (MI_NPIXELS(mi) > 2) {
+               if (++colorcount >= MI_NPIXELS(mi))
+                       colorcount = 0;
+               door->color = MI_PIXEL(mi,colorcount);
+       } else
+               door->color = MI_WHITE_PIXEL(mi);
+       return;
+#endif
+}
+
+static void
+free_scooter(scooterstruct *sp)
+{
+       if (sp->doors != NULL) {
+               free(sp->doors);
+               sp->doors = (Door *) NULL;
+       }
+       if (sp->stars != NULL) {
+               free(sp->stars);
+               sp->stars = (Star *) NULL;
+       }
+       if (sp->zelements != NULL) {
+               free(sp->zelements);
+               sp->zelements = (ZElement *) NULL;
+       }
+}
+
+static void release_scooter(ModeInfo *mi)
+{
+    if (scooters != NULL) {
+        int screen;
+
+        for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
+             free_scooter(&scooters[screen]);
+        free(scooters);
+        scooters = (scooterstruct *) NULL;
+    }
+       if (sintable != NULL) {
+               free(sintable);
+               sintable = (float *) NULL;
+       }
+}
+
+static void init_scooter(ModeInfo *mi)
+{
+       int i;
+       scooterstruct *sp;
+
+       if (scooters == NULL) {
+               if ((scooters = (scooterstruct *) calloc(MI_NUM_SCREENS(mi),
+                               sizeof (scooterstruct))) == NULL)
+                       return;
+       }
+       sp = &scooters[MI_SCREEN(mi)];
+       sp->doorcount = MAX(MI_COUNT(mi),MIN_DOORS);
+       sp->speed = MI_CYCLES(mi);
+       sp->starcount = MI_SIZE(mi);
+       if (sp->starcount < 1)
+               sp->starcount = 1;
+       if (sp->speed < MIN_SPEED)
+               sp->speed = MIN_SPEED;
+       if (sp->speed > MAX_SPEED)
+               sp->speed = MAX_SPEED;
+       sp->zelements_per_door = 60;
+       sp->zelement_distance = 300;
+       sp->ztotal = sp->doorcount * sp->zelements_per_door;
+       /* sp->z_maxdepth = sp->ztotal * sp->zelement_distance; */
+       if (sp->starcount > sp->ztotal)
+               sp->starcount = sp->ztotal;
+
+       sp->halt_scooter = False;
+
+       initdoorcolors(sp);
+       free_scooter(sp);
+       if (sintable == NULL) {
+               if ((sintable = (float *) malloc(sizeof(float) *
+                       SINUSTABLE_SIZE)) == NULL) {
+                       release_scooter(mi);
+                       return;
+               }
+       }
+       for (i = 0; i < SINUSTABLE_SIZE; i++) {
+               sintable[i] = SINF(M_PI*2/SINUSTABLE_SIZE*i);
+       }
+
+       if ((sp->doors = (Door *) malloc(sizeof(Door) *
+                       sp->doorcount)) == NULL) {
+               return;
+       }
+
+       if ((sp->zelements = (ZElement *) malloc(sizeof(ZElement) *
+                sp->ztotal)) == NULL) {
+               free_scooter(sp);
+               return;
+       }
+       for (i = 0; i <  sp->doorcount; i++) {
+               sp->doors[i].zelement =
+                       (sp->zelements_per_door * (i + 1)) - 1;
+               sp->doors[i].freecolor = 0;
+               nextdoorcolor(mi, &sp->doors[i]);
+       }
+
+       for (i = 0; i < sp->ztotal; i++) {
+               sp->zelements[i].angle.x = 0;
+               sp->zelements[i].angle.y = 0;
+               sp->zelements[i].angle.z = 0;
+       }
+
+       if ((sp->stars = (Star *) malloc(sizeof(Star) *
+                       sp->starcount)) == NULL) {
+               free_scooter(sp);
+               return;
+       }
+       for (i = 0; i < sp->starcount; i++) {
+               sp->stars[i].zelement = sp->ztotal * i / sp->starcount;
+               sp->stars[i].draw = 0;
+       }
+
+       sp->projnorm_z = 50 * 240;
+       sp->spectator_zelement = sp->zelements_per_door;
+
+       sp->currentRotation.x = 0;
+       sp->currentRotation.y = 0;
+       sp->currentRotation.z = 0;
+
+       sp->rotationDelta.x = 0;
+       sp->rotationDelta.y = 0;
+       sp->rotationDelta.z = 0;
+
+       sp->rotationDuration = 1;
+       sp->rotationStep = 0;
+}
+
+static void cleardoors(ModeInfo *mi)
+{
+       /* MI_CLEARWINDOW(mi);*/
+       XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi));
+}
+
+/* Should be taken care of already... but just in case */
+#if !defined( __GNUC__ ) && !defined(__cplusplus) && !defined(c_plusplus)
+#undef inline
+#define inline                  /* */
+#endif
+static inline float
+projection (scooterstruct *sp, int zval)
+{
+       return (sp->projnorm_z / (PROJECTION_DEGREE * zval));
+/* this is another formula. it is not limited to z>0 but it pulls too strong towards the screen center */
+/*      return (sp->projnorm_z * pow(1.22,-(zval/200*PROJ_CURVEDNESS)))*/
+}
+
+/*
+
+ y
+
+ ^
+ |      z
+ |    .
+ |   /
+ |  /
+ | /
+ |/
+-+------------> x
+/|
+
+  rotation angles:
+         a = alpha (x-rotation), b = beta (y-rotation), c = gamma (z-rotation)
+
+  x-axis rotation:
+       (  z  )'  =  ( cos(a) -sin(a) ) (  z  )
+       (  y  )      ( sin(a)  cos(a) ) (  y  )
+
+  y-axis rotation:
+       (  z  )'  =  ( cos(b) -sin(b) ) (  z  )
+       (  x  )      ( sin(b)  cos(b) ) (  x  )
+
+  z-axis rotation:
+       (  x  )'  =  ( cos(c) -sin(c) ) (  x  )
+       (  y  )      ( sin(c)  cos(c) ) (  y  )
+*/
+
+static void
+rotate_3d(Vec3D *src, Vec3D *dest, Angle3D *angle)
+{
+       Vec3D tmp;
+       float   cosa = COS(angle->x),
+               cosb = COS(angle->y),
+               cosc = COS(angle->z),
+               sina = SIN(angle->x),
+               sinb = SIN(angle->y),
+               sinc = SIN(angle->z);
+
+       /* rotate around X, Y and Z axis (see formulae above) */
+
+       /* X axis */
+       tmp.z = src->z;
+       tmp.y = src->y;
+       dest->z = (int) (tmp.z * cosa - tmp.y * sina);
+       dest->y = (int) (tmp.z * sina + tmp.y * cosa);
+
+       /* Y axis */
+       tmp.z = dest->z;
+       tmp.x = src->x;
+       dest->z = (int) (tmp.z * cosb - tmp.x * sinb);
+       dest->x = (int) (tmp.z * sinb + tmp.x * cosb);
+
+       /* Z axis */
+       tmp.x = dest->x;
+       tmp.y = dest->y;
+       dest->x = (int) (tmp.x * cosc - tmp.y * sinc);
+       dest->y = (int) (tmp.x * sinc + tmp.y * cosc);
+}
+
+static void calc_new_element(ModeInfo *mi)
+{
+       scooterstruct *sp = &scooters[MI_SCREEN(mi)];
+       float rot = SIN((SINUSTABLE_SIZE/2)*
+               sp->rotationStep/sp->rotationDuration);
+
+       /* change current rotation 3D angle */
+
+       if (sp->rotationStep++ >= sp->rotationDuration) {
+
+               int fps = 1000000/MI_DELAY(mi); /* frames per second as timebase */
+
+               /*  one rotation interval takes 10-30 seconds at speed 1.
+                */
+               sp->rotationDuration = 10*fps + NRAND(20*fps);
+
+               /* -DOOR_CURVEDNESS <= delta <= +DOOR_CURVEDNESS */
+               sp->rotationDelta.x =
+                       NRAND(DOOR_CURVEDNESS*2+1) - DOOR_CURVEDNESS;
+               sp->rotationDelta.y =
+                       NRAND(DOOR_CURVEDNESS*2+1) - DOOR_CURVEDNESS;
+               sp->rotationDelta.z =
+                       NRAND(DOOR_CURVEDNESS*2+1) - DOOR_CURVEDNESS;
+
+               sp->rotationStep = 0;
+       }
+
+       sp->currentRotation.x += (int) (rot * sp->rotationDelta.x);
+       sp->currentRotation.y += (int) (rot * sp->rotationDelta.y);
+       sp->currentRotation.z += (int) (rot * sp->rotationDelta.z);
+
+       sp->currentRotation.x &= SINUSTABLE_MASK;
+       sp->currentRotation.y &= SINUSTABLE_MASK;
+       sp->currentRotation.z &= SINUSTABLE_MASK;
+}
+
+static void shift_elements(ModeInfo *mi)
+{
+       scooterstruct *sp = &scooters[MI_SCREEN(mi)];
+       int i, iprev;
+       Vec3D tmpvec;
+       Angle3D tmpangle;
+
+       /* shift angles from zelements */
+
+       for (i = sp->speed; i < sp->ztotal; i++) {
+               sp->zelements[i - sp->speed].angle = sp->zelements[i].angle;
+       }
+       for (i = sp->ztotal - sp->speed; i < sp->ztotal; i++) {
+               calc_new_element(mi);
+               sp->zelements[i].angle = sp->currentRotation;
+       }
+
+       /* calculate new 3D-coords from ALL zelements */
+
+       sp->zelements[sp->spectator_zelement].pos.x = 0;
+       sp->zelements[sp->spectator_zelement].pos.y = 0;
+       sp->zelements[sp->spectator_zelement].pos.z =
+               sp->zelement_distance * sp->spectator_zelement;
+
+       for (i = sp->spectator_zelement - 1; i >= 0; --i) {
+               iprev = i + 1;
+
+               tmpvec.x = 0;
+               tmpvec.y = 0;
+               tmpvec.z = - sp->zelement_distance;
+               tmpangle.x = sp->zelements[i].angle.x -
+                       sp->zelements[sp->spectator_zelement].angle.x;
+               tmpangle.y = sp->zelements[i].angle.y -
+                       sp->zelements[sp->spectator_zelement].angle.y;
+               tmpangle.z = sp->zelements[i].angle.z -
+                       sp->zelements[sp->spectator_zelement].angle.z;
+               rotate_3d(&tmpvec, &(sp->zelements[i].pos), &tmpangle);
+               sp->zelements[i].pos.x += sp->zelements[iprev].pos.x;
+               sp->zelements[i].pos.y += sp->zelements[iprev].pos.y;
+               sp->zelements[i].pos.z += sp->zelements[iprev].pos.z;
+       }
+
+       for (i = sp->spectator_zelement + 1; i < sp->ztotal; i++) {
+               iprev = i - 1;
+
+               tmpvec.x = 0;
+               tmpvec.y = 0;
+               tmpvec.z = sp->zelement_distance;
+               tmpangle.x = sp->zelements[i].angle.x -
+                       sp->zelements[sp->spectator_zelement].angle.x;
+               tmpangle.y = sp->zelements[i].angle.y -
+                       sp->zelements[sp->spectator_zelement].angle.y;
+               tmpangle.z = sp->zelements[i].angle.z -
+                       sp->zelements[sp->spectator_zelement].angle.z;
+               rotate_3d(&tmpvec, &(sp->zelements[i].pos), &tmpangle);
+               sp->zelements[i].pos.x += sp->zelements[iprev].pos.x;
+               sp->zelements[i].pos.y += sp->zelements[iprev].pos.y;
+               sp->zelements[i].pos.z += sp->zelements[iprev].pos.z;
+       }
+
+
+       /* shift doors and wrap around */
+
+       for (i = 0; i < sp->doorcount; i++) {
+               if ((sp->doors[i].zelement -= sp->speed) < 0) {
+                       sp->doors[i].zelement += sp->ztotal;
+                       nextdoorcolor(mi,&sp->doors[i]);
+               }
+       }
+
+       /* shift stars */
+
+       for (i = 0; i < sp->starcount; i++) {
+               if ((sp->stars[i].zelement -= sp->speed) < 0) {
+                       int rnd;
+
+                       sp->stars[i].zelement += sp->ztotal;
+                       sp->stars[i].draw = 1;
+
+                       /* make sure new stars are outside doors */
+
+                       rnd = NRAND(2*(STAR_MAX_X - STAR_MIN_X)) -
+                               (STAR_MAX_X - STAR_MIN_X);
+                       sp->stars[i].xpos = rnd + (STAR_MIN_X * SGN(rnd));
+
+                       rnd = NRAND(2*(STAR_MAX_Y - STAR_MIN_Y)) -
+                               (STAR_MAX_Y - STAR_MIN_Y);
+                       sp->stars[i].ypos = rnd + (STAR_MIN_Y * SGN(rnd));
+
+                       rnd = NRAND(STAR_SIZE_MAX - STAR_SIZE_MIN) +
+                               STAR_SIZE_MIN;
+                       sp->stars[i].width  = rnd;
+                       sp->stars[i].height = rnd * 3 / 4;
+               }
+       }
+}
+
+static void door_3d(scooterstruct *sp, Door *door)
+{
+       ZElement *ze = &sp->zelements[door->zelement];
+       Vec3D src;
+       Angle3D tmpangle;
+
+       tmpangle.x = ze->angle.x -
+               sp->zelements[sp->spectator_zelement].angle.x;
+       tmpangle.y = ze->angle.y -
+               sp->zelements[sp->spectator_zelement].angle.y;
+       tmpangle.z = ze->angle.z -
+               sp->zelements[sp->spectator_zelement].angle.z;
+
+       /* calculate 3d coords of all 4 edges */
+
+       src.x = -DOOR_WIDTH/2;
+       src.y = DOOR_HEIGHT/2;
+       src.z = 0;
+       rotate_3d(&src, &(door->coords[0]), &tmpangle);
+       door->coords[0].x += ze->pos.x;
+       door->coords[0].y += ze->pos.y;
+       door->coords[0].z += ze->pos.z;
+
+       src.x = DOOR_WIDTH/2;
+       rotate_3d(&src, &(door->coords[1]), &tmpangle);
+       door->coords[1].x += ze->pos.x;
+       door->coords[1].y += ze->pos.y;
+       door->coords[1].z += ze->pos.z;
+
+       src.y = -DOOR_HEIGHT/2;
+       rotate_3d(&src, &(door->coords[2]), &tmpangle);
+       door->coords[2].x += ze->pos.x;
+       door->coords[2].y += ze->pos.y;
+       door->coords[2].z += ze->pos.z;
+
+       src.x = -DOOR_WIDTH/2;
+       rotate_3d(&src, &(door->coords[3]), &tmpangle);
+       door->coords[3].x += ze->pos.x;
+       door->coords[3].y += ze->pos.y;
+       door->coords[3].z += ze->pos.z;
+}
+
+/*
+ *  clip the line p1-p2 at the given rectangle
+ *
+ */
+static int clipline(XPoint *p1, XPoint *p2, Rect *rect)
+{
+       XPoint new1, new2, tmp;
+       float m;
+
+       new1 = *p1;
+       new2 = *p2;
+
+       /* entire line may not need clipping */
+
+       if (((new1.x >= rect->lefttop.x) && (new1.x <= rect->rightbottom.x))
+        || ((new1.y >= rect->lefttop.y) && (new1.y <= rect->rightbottom.y))
+        || ((new2.x >= rect->lefttop.x) && (new2.x <= rect->rightbottom.x))
+        || ((new2.y >= rect->lefttop.y) && (new2.y <= rect->rightbottom.y)))
+               return 1;
+
+
+       /* first: clip y dimension */
+
+       /* p1 is above p2 */
+       if (new1.y > new2.y) {
+               tmp = new1;
+               new1 = new2;
+               new2 = tmp;
+       }
+
+       /* line could be totally out of view */
+       if ((new2.y < rect->lefttop.y) || (new1.y > rect->rightbottom.y))
+               return 0;
+
+       m = (new2.x == new1.x) ? 0 :
+               ((float)(new2.y - new1.y) / (new2.x - new1.x));
+
+       if (new1.y < rect->lefttop.y) {
+               if (m)
+                       new1.x += (int) ((rect->lefttop.y - new1.y)/m);
+               new1.y = rect->lefttop.y;
+       }
+       if (new2.y > rect->rightbottom.y) {
+               if (m)
+                       new2.x -= (int) ((new2.y - rect->rightbottom.y)/m);
+               new2.y = rect->rightbottom.y;
+       }
+
+
+       /* clip x dimension */
+
+       /* p1 is left to p2 */
+       if (new1.x > new2.x) {
+               tmp = new1;
+               new1 = new2;
+               new2 = tmp;
+       }
+
+       if ((new2.x < rect->lefttop.x) || (new1.x > rect->rightbottom.x))
+               return 0;
+
+       m = (new2.x == new1.x) ? 0 :
+               ((float)(new2.y - new1.y) / (new2.x - new1.x));
+
+       if (new1.x < rect->lefttop.x) {
+               new1.y += (int) ((rect->lefttop.y - new1.y)*m);
+               new1.x = rect->lefttop.x;
+       }
+       if (new2.y > rect->rightbottom.y) {
+               new2.y -= (int) ((new2.y - rect->rightbottom.y)*m);
+               new2.x = rect->rightbottom.x;
+       }
+
+
+       /* push values */
+
+       *p1 = new1;
+       *p2 = new2;
+
+       return 1;
+}
+
+static void drawdoors(ModeInfo *mi)
+{
+       scooterstruct *sp = &scooters[MI_SCREEN(mi)];
+       Display *display = MI_DISPLAY(mi);
+       Window window = MI_WINDOW(mi);
+       GC gc = MI_GC(mi);
+       int width = MI_WIDTH(mi), height = MI_HEIGHT(mi),
+               midx = width/2, midy = height/2;
+       int i, j;
+       Rect rect = { {0,0}, {0,0} };
+
+        rect.rightbottom.x = width - 1;
+        rect.rightbottom.y = height - 1;
+       XSetLineAttributes(display, gc, 2, LineSolid, CapNotLast, JoinRound);
+
+#ifdef _DRAW_ZELEMENTS
+        XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
+        for (i= sp->spectator_zelement; i<ztotal; i++) {
+                register float proj;
+                XPoint p;
+
+                proj = projection(sp, zelements[i].pos.z) * sp->aspect_scale;
+                p.x = midx + (sp->zelements[i].pos.x * proj / SPACE_XY_FACTOR);
+                p.y = midy - (sp->zelements[i].pos.y * proj / SPACE_XY_FACTOR);
+                XDrawPoint(display, window, gc, p.x, p.y);
+        }
+#endif
+
+       for (i = 0; i < sp->doorcount; i++) {
+
+               register float proj;
+               XPoint lines[4], clip1, clip2;
+
+               door_3d(sp, &sp->doors[i]);
+
+               for (j=0; j<4; j++) {
+                       if (sp->doors[i].coords[j].z <= 0) break;
+
+                       proj = projection(sp, sp->doors[i].coords[j].z) * sp->aspect_scale;
+                       lines[j].x = midx + (int) (sp->doors[i].coords[j].x *
+                               proj / SPACE_XY_FACTOR);
+                       lines[j].y = midy - (int) (sp->doors[i].coords[j].y *
+                               proj / SPACE_XY_FACTOR);
+               }
+               if (j<4) continue;
+
+               XSetForeground(display, gc, sp->doors[i].color);
+
+               for (j=0; j<4; j++) {
+                       clip1 = lines[j];
+                       clip2 = lines[(j+1)%4];
+                       if (clipline(&clip1, &clip2, &rect))
+                               XDrawLine(display, window, gc, clip1.x, clip1.y, clip2.x, clip2.y);
+               }
+       }
+}
+
+ENTRYPOINT void drawstars(ModeInfo *mi)
+{
+       scooterstruct *sp = &scooters[MI_SCREEN(mi)];
+       Display *display = MI_DISPLAY(mi);
+       Window window = MI_WINDOW(mi);
+       GC gc = MI_GC(mi);
+       int width = MI_WIDTH(mi), height = MI_HEIGHT(mi),
+               midx = width/2, midy = height/2;
+       int i;
+
+       for (i = 0; i < sp->starcount; i++) {
+
+               float proj;
+               ZElement *ze = &sp->zelements[sp->stars[i].zelement];
+               Vec3D tmpvec, coords;
+               Angle3D tmpangle;
+               XPoint lefttop, rightbottom;
+
+               if (!sp->stars[i].draw) continue;
+
+
+               /* rotate star around its z-element, then add its position */
+
+               tmpangle.x = ze->angle.x -
+                       sp->zelements[sp->spectator_zelement].angle.x;
+               tmpangle.y = ze->angle.y -
+                       sp->zelements[sp->spectator_zelement].angle.y;
+               tmpangle.z = ze->angle.z -
+                       sp->zelements[sp->spectator_zelement].angle.z;
+
+               tmpvec.x = sp->stars[i].xpos;
+               tmpvec.y = sp->stars[i].ypos;
+               tmpvec.z = 0;
+               rotate_3d(&tmpvec, &coords, &tmpangle);
+               coords.x += ze->pos.x;
+               coords.y += ze->pos.y;
+               coords.z += ze->pos.z;
+
+               if (coords.z <= 0) continue;
+
+
+               /* projection and clipping (trivial for a rectangle) */
+
+               proj = projection(sp, coords.z) * sp->aspect_scale;
+
+               lefttop.x = midx + (int) ((coords.x - sp->stars[i].width/2) *
+                       proj / SPACE_XY_FACTOR);
+               lefttop.y = midy - (int) ((coords.y + sp->stars[i].height/2) *
+                       proj / SPACE_XY_FACTOR);
+               if (lefttop.x < 0)
+                       lefttop.x = 0;
+               else if (lefttop.x >= width)
+                       continue;
+               if (lefttop.y < 0)
+                       lefttop.y = 0;
+               else if (lefttop.y >= height)
+                       continue;
+
+               rightbottom.x = midx + (int) ((coords.x + sp->stars[i].width/2) *
+                        proj / SPACE_XY_FACTOR);
+               rightbottom.y = midy - (int) ((coords.y - sp->stars[i].height/2) *
+                        proj / SPACE_XY_FACTOR);
+               if (rightbottom.x < 0)
+                       continue;
+               else if (rightbottom.x >= width)
+                       rightbottom.x = width - 1;
+               if (rightbottom.y < 0)
+                       continue;
+               else if (rightbottom.y >= height)
+                       rightbottom.y = height - 1;
+
+
+               /* in white color, small stars look darker than big stars */
+
+               XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
+
+               if ((lefttop.x == rightbottom.x) &&
+                               (lefttop.y == rightbottom.y)) {
+                       /* star is exactly 1 pixel */
+                       XDrawPoint(display, window, gc, lefttop.x, lefttop.y);
+               } else if ((rightbottom.x - lefttop.x) +
+                               (rightbottom.y - lefttop.y) == 1) {
+                       /* star is 2 pixels wide or high */
+                       XDrawPoint(display, window, gc,
+                               lefttop.x,     lefttop.y);
+                       XDrawPoint(display, window, gc,
+                               rightbottom.x, rightbottom.y);
+               } else if ((rightbottom.x - lefttop.x == 1) &&
+                               (rightbottom.y - lefttop.y == 1)) {
+
+                       /*  star is exactly 2x2 pixels.
+                        *  a 2x2 rectangle should be drawn faster by plotting all 4 pixels
+                        *  than by filling a rectangle (is this really so under X ?)
+                        */
+
+                       XDrawPoint(display, window, gc,
+                               lefttop.x,     lefttop.y);
+                       XDrawPoint(display, window, gc,
+                               rightbottom.x, lefttop.y);
+                       XDrawPoint(display, window, gc,
+                               lefttop.x,     rightbottom.y);
+                       XDrawPoint(display, window, gc,
+                               rightbottom.x, rightbottom.y);
+               } else {
+                       XFillRectangle(display, window, gc,
+                               lefttop.x, lefttop.y,
+                               rightbottom.x - lefttop.x,
+                               rightbottom.y - lefttop.y);
+               }
+       }
+}
+
+ENTRYPOINT void draw_scooter(ModeInfo *mi)
+{
+       scooterstruct *sp;
+
+       if (scooters == NULL)
+               return;
+       sp = &scooters[MI_SCREEN(mi)];
+       if (sp->doors == NULL)
+               return;
+
+       cleardoors(mi);
+
+       shift_elements(mi);
+
+       /* With these scale factors, all doors are sized correctly for any window dimension.
+        * If aspect ratio is not 4:3, the smaller part of the window is used, e.g.:
+        *      window = 1000x600
+        *      => door scale factor is like in a 800x600 window (not 1000x750)
+        */
+
+       if ((float)MI_WIDTH(mi)/MI_HEIGHT(mi) >=
+                       (float)ASPECT_SCREENWIDTH/ASPECT_SCREENHEIGHT) {
+               /* window is wider than or equal 4:3 */
+               sp->aspect_scale = (float)MI_HEIGHT(mi) / ASPECT_SCREENHEIGHT;
+       } else {
+               /* window is higher than 4:3 */
+               sp->aspect_scale = (float)MI_WIDTH(mi) / ASPECT_SCREENWIDTH;
+       }
+
+       drawstars(mi);
+
+       drawdoors(mi);
+}
+
+#if 0
+ENTRYPOINT void refresh_scooter(ModeInfo *mi)
+{
+       /* MI_CLEARWINDOW(mi); */
+       XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi));
+}
+
+ENTRYPOINT void change_scooter(ModeInfo *mi)
+{
+       scooterstruct *sp;
+
+       if (scooters == NULL)
+               return;
+       sp = &scooters[MI_SCREEN(mi)];
+
+       sp->halt_scooter = !sp->halt_scooter;
+}
+#endif
+
+#define free_scooter 0
+XSCREENSAVER_MODULE ("Scooter", scooter)
+
+#endif /* MODE_scooter */
diff --git a/hacks/scooter.man b/hacks/scooter.man
new file mode 100644 (file)
index 0000000..492eb00
--- /dev/null
@@ -0,0 +1,79 @@
+.TH XScreenSaver 1 "14-Mar-01" "X Version 11"
+.SH NAME
+scooter - shows a journey through space tunnel and stars
+.SH SYNOPSIS
+.B scooter
+[\-display \fIhost:display.screen\fP]
+[\-mono]
+[\-delay \fImillisecs\fP]
+[\-cycles \fIcycles\fP]
+[\-count \fIcount\fP]
+[\-size \fIsize\fP]
+[\-ncolors \fIcolors\fP]
+[\-window] [\-root] [\-install | \-noinstall] [\-visual \fIvisual\fP]
+[\-fps | \-no\-fps]
+[\-pair]
+.SH DESCRIPTION
+\fIscooter\fP is a screensaver that shows endless journey through space tunnel and stars.
+.SH OPTIONS
+.I scooter
+accepts the following options:
+.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 \-install
+Install a private colormap for the window.
+.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 \-delay \fImilliseconds\fP
+How much of a delay should be introduced between steps of the animation.
+Default 10, or about 1/100th second.
+.TP 8
+.B \-cycles \fIcycles\fP
+How fast/slow the screensaver is. \fIcycles\fP takes number of cycles. The default is 5 cycles.
+.TP 8
+.B \-count \fIcount\fP
+Specifies how many doors in a tunnel can be rendered. Minimum is 4. Default is 24.
+.TP 8
+.B \-size \fIsize\fP
+Specifies how many stars outside the tunnel can be rendered. Default is 100.
+.TP 8
+.B \-ncolors \fIcolors\fP
+Specifies number of colors. A number that is less than or equals 2 means monochrome. \-mono achieves the same thing.
+.TP 8
+.B \-pair
+Start screensaver in pairs (Not recommended)
+.TP 8
+.B \-fps
+Display the current frame rate and CPU load.
+.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 xscreensaver\-demo (1),
+.BR xscreensaver\-getimage (1)
+.SH COPYRIGHT
+Copyright \(co 2001 by Sven Thoennissen.  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
+Sven Thoennissen <posse@gmx.net>
index fdd2e4323a73e2bc23fda6e60c7ed8213dbb53de..f2925385a6da856f0c298674032be29d7c1e163a 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1992-2017 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1992-2020 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
@@ -265,7 +265,7 @@ MapNotify_event_p (Display *dpy, XEvent *event, XPointer window)
 }
 
 
-static Atom XA_WM_PROTOCOLS, XA_WM_DELETE_WINDOW;
+static Atom XA_WM_PROTOCOLS, XA_WM_DELETE_WINDOW, XA_NET_WM_PID;
 
 /* Dead-trivial event handling: exits if "q" or "ESC" are typed.
    Exit if the WM_PROTOCOLS WM_DELETE_WINDOW ClientMessage is received.
@@ -691,6 +691,7 @@ init_window (Display *dpy, Widget toplevel, const char *title)
   XWindowAttributes xgwa;
   XtPopup (toplevel, XtGrabNone);
   XtVaSetValues (toplevel, XtNtitle, title, NULL);
+  long pid = getpid();
 
   /* Select KeyPress, and announce that we accept WM_DELETE_WINDOW.
    */
@@ -702,6 +703,8 @@ init_window (Display *dpy, Widget toplevel, const char *title)
   XChangeProperty (dpy, window, XA_WM_PROTOCOLS, XA_ATOM, 32,
                    PropModeReplace,
                    (unsigned char *) &XA_WM_DELETE_WINDOW, 1);
+  XChangeProperty (dpy, window, XA_NET_WM_PID, XA_CARDINAL, 32,
+                   PropModeReplace, (unsigned char *)&pid, 1);
 }
 
 
@@ -767,6 +770,7 @@ main (int argc, char **argv)
 
   XA_WM_PROTOCOLS = XInternAtom (dpy, "WM_PROTOCOLS", False);
   XA_WM_DELETE_WINDOW = XInternAtom (dpy, "WM_DELETE_WINDOW", False);
+  XA_NET_WM_PID = XInternAtom (dpy, "_NET_WM_PID", False);
 
   {
     char *v = (char *) strdup(strchr(screensaver_id, ' '));
index 5cc1196a5f3c0049332a19513fc9814fd9927e31..47f86fe4d633b6017aa1bc5234f2bc045a7425af 100755 (executable)
@@ -3701,6 +3701,7 @@ sub update_imagemap($$$$$$$$) {
  </HEAD>
  <BODY>
   <DIV CLASS="webcollage_frame">
+   <DIV CLASS="webcollage_box"></DIV>
   </DIV>
  </BODY>
 </HTML>
index addfd4c8018a16932a576e387438166f6db89d74..5ddf175e974c354c708202749ff06947b1269876 100644 (file)
@@ -263,6 +263,13 @@ xlockmore_release_screens (ModeInfo *mi)
 }
 
 
+static Bool
+xlockmore_got_init (ModeInfo *mi)
+{
+  return mi->xlmft->got_init & (1ul << mi->screen_number);
+}
+
+
 static void
 xlockmore_free_screens (ModeInfo *mi)
 {
@@ -279,7 +286,8 @@ xlockmore_free_screens (ModeInfo *mi)
     int old_screen = mi->screen_number;
     for (mi->screen_number = 0; mi->screen_number < XLOCKMORE_NUM_SCREENS;
          ++mi->screen_number) {
-      xlmft->hack_free (mi);
+      if (xlockmore_got_init(mi))
+        xlmft->hack_free (mi); /* got_init is reset in xlockmore_release_screens. */
     }
     mi->screen_number = old_screen;
   }
@@ -401,7 +409,7 @@ xlockmore_init (Display *dpy, Window window,
     const int size = XLOCKMORE_NUM_SCREENS;
     int i;
     for (i = 0; i < size; i++) {
-      if (! (xlmft->live_displays & (1 << i)))
+      if (! (xlmft->live_displays & (1ul << i)))
         break;
     }
     if (i >= size) abort();
@@ -571,16 +579,11 @@ xlockmore_clear (ModeInfo *mi)
 static void
 xlockmore_do_init (ModeInfo *mi)
 {
-  mi->xlmft->got_init |= 1 << mi->screen_number;
   xlockmore_clear (mi);
   mi->xlmft->hack_init (mi);
-}
 
-
-static Bool
-xlockmore_got_init (ModeInfo *mi)
-{
-  return mi->xlmft->got_init & (1 << mi->screen_number);
+  /* Do this last, so MI_INIT gets the old got_init. */
+  mi->xlmft->got_init |= 1ul << mi->screen_number;
 }
 
 
@@ -682,10 +685,13 @@ xlockmore_event (Display *dpy, Window window, void *closure, XEvent *event)
 
     if (screenhack_event_helper (mi->dpy, mi->window, event)) {
       /* If a clear is in progress, don't interrupt or restart it. */
-      if (mi->needs_clear)
+      if (mi->needs_clear) {
+        if (mi->xlmft->hack_free)
+          mi->xlmft->hack_free (mi);
         mi->xlmft->got_init &= ~(1ul << mi->screen_number);
-      else
+      } else {
         mi->xlmft->hack_init (mi);
+      }
       return True;
     }
   }
@@ -714,8 +720,10 @@ xlockmore_free (Display *dpy, Window window, void *closure)
      xlockmore_free returns. Thus, hack_free has to happen now, rather than
      after the final screen has been released.
    */
-  if (mi->xlmft->hack_free)
+  if (mi->xlmft->hack_free && xlockmore_got_init(mi)) {
     mi->xlmft->hack_free (mi);
+    mi->xlmft->got_init &= ~(1ul << mi->screen_number);
+  }
 
   /* Find us in live_displays and clear that slot. */
   assert (mi->xlmft->live_displays & (1ul << mi->screen_number));
@@ -761,8 +769,8 @@ xlockmore_mi_init (ModeInfo *mi, size_t state_size, void **state_array)
 
   /* Find the appropriate state object, clear it, and we're done. */
   {
-    if (xlmft->hack_free)
-      xlmft->hack_free (mi);
+    if (xlmft->hack_free && xlockmore_got_init(mi))
+      xlmft->hack_free (mi); /* Don't reset the got_init bit from MI_INIT. */
     memset ((char *)(*xlmft->state_array) + mi->screen_number * state_size, 0,
             state_size);
   }
index 9f1305b9c80449e06a335a253002aa947428777b..4b4ad0c412d0ea304bbd91abf58f1c4b366bdbc9 100644 (file)
@@ -1865,7 +1865,7 @@ xlyap_draw (Display *dpy, Window window, void *closure)
     }
   }
 
-  for (i = 0; i < 1000; i++)
+  for (i = 0; i < 2000; i++)
     if (complyap(st) == TRUE)
       {
         st->run = 0;
index 45c5f9d4277f4d996b93ecd60c8f399b4b6b2a72..70f6516583a5ca6efb4937e1250850f199dcc202 100644 (file)
@@ -1311,7 +1311,7 @@ hack_text (m_state *state)
   /* Stupid iPhone X bezel.
      #### This is the worst of all possible ways to do this!  But how else?
    */
-  if (state->xgwa.width == 2436 || state->xgwa.height == 2436)
+  if (state->xgwa.width == 1218 || state->xgwa.height == 1218)
     switch (state->mode) 
       {
       case TRACE_TEXT_A:
@@ -1319,7 +1319,7 @@ hack_text (m_state *state)
       case KNOCK:
       case NMAP:
         {
-          int off = 5 * (state->small_p ? 2 : 1);
+          int off = 2 * (state->small_p ? 2 : 1);
           if (state->xgwa.width > state->xgwa.height)
             {
               state->typing_left_margin += off;
index 2b74b799160aa10f178660915cecd803151838f0..85ce924635d346d3eb6031c75f345497d1d0afa1 100644 (file)
@@ -1138,8 +1138,9 @@ jwxyz_gl_copy_area (Display *dpy, Drawable src, Drawable dst, GC gc,
     bind_drawable_fbo (rh, dst);
   finish_bind_drawable (dpy, dst);
 
-  jwxyz_gl_copy_area_write_tex_image (dpy, gc, src_x, src_y, width, height,
-                                      dst_x, dst_y);
+  jwxyz_gl_copy_area_write_tex_image (dpy, gc, src_x, src_y,
+                                      jwxyz_drawable_depth (src),
+                                      width, height, dst_x, dst_y);
 
 #else
   // Kumppa: 0.17 FPS
index 369d16fbbc1ff73763668a10cc41f6245d3fcfbd..f1c13da23a66e032374d98e0184a6feaf7db2d17 100644 (file)
@@ -544,7 +544,7 @@ visual (Display *dpy)
  */
 
 static void *
-enqueue (Display *dpy, Drawable d, GC gc, int mode, size_t count,
+enqueue (Display *dpy, Drawable d, GC gc, GLenum mode, size_t count,
          unsigned long pixel)
 {
   if (dpy->queue_size &&
@@ -947,7 +947,8 @@ jwxyz_gl_copy_area_read_tex_image (Display *dpy, unsigned src_height,
 }
 
 void
-jwxyz_gl_copy_area_write_tex_image (Display *dpy, GC gc, int src_x, int src_y,
+jwxyz_gl_copy_area_write_tex_image (Display *dpy, GC gc,
+                                    int src_x, int src_y, int src_depth,
                                     unsigned int width, unsigned int height,
                                     int dst_x, int dst_y)
 {
@@ -964,7 +965,7 @@ jwxyz_gl_copy_area_write_tex_image (Display *dpy, GC gc, int src_x, int src_y,
   glBindTexture (dpy->gl_texture_target, dpy->textures[texture_rgba]);
 
   jwxyz_gl_draw_image (dpy, gc, dpy->gl_texture_target, tex_w, tex_h,
-                       0, 0, gc->depth, width, height, dst_x, dst_y, False);
+                       0, 0, src_depth, width, height, dst_x, dst_y, False);
 
   clear_texture (dpy);
 }
@@ -1291,10 +1292,32 @@ FillPolygon (Display *dpy, Drawable d, GC gc,
 #define degrees(RAD) ((RAD) * 180.0 / M_PI)
 
 static void
-arc_xy(GLfloat *p, double cx, double cy, double w2, double h2, double theta)
+arc_xy (GLfloat *p, GLfloat cx, GLfloat cy, GLfloat w2, GLfloat h2,
+        GLfloat theta)
 {
-  p[0] = cos(theta) * w2 + cx;
-  p[1] = -sin(theta) * h2 + cy;
+  p[0] = cx + cosf(theta) * w2;
+  p[1] = cy - sinf(theta) * h2;
+}
+
+static void
+arc_xy2 (GLfloat *p, GLfloat cx, GLfloat cy, GLfloat w2, GLfloat h2,
+         GLfloat theta, GLfloat gglw)
+{
+  // The inner/outer contour of the stroke of an ellipse is not itself an
+  // ellipse.
+
+  GLfloat ct = cosf(theta), st = sinf(theta);
+
+  GLfloat w2st = w2 * st, h2ct = h2 * ct;
+  GLfloat w2ct = w2 * ct, h2st = h2 * st;
+
+  GLfloat d = gglw / sqrtf(w2st * w2st + h2ct * h2ct);
+  GLfloat dh2ct = d * h2ct, dw2st = d * w2st;
+
+  p[0] = cx +  w2ct + dh2ct;
+  p[1] = cy - (h2st + dw2st);
+  p[2] = cx +  w2ct - dh2ct;
+  p[3] = cy - (h2st - dw2st);
 }
 
 static unsigned
@@ -1306,48 +1329,17 @@ mod_neg(int a, unsigned b)
   return a < 0 ? (b - 1) - (-(a + 1) % b) : a % b;
 }
 
-/* TODO: Fill in arcs with line width > 1 */
 static int
 draw_arc (Display *dpy, Drawable d, GC gc, int x, int y,
           unsigned int width, unsigned int height,
           int angle1, int angle2, Bool fill_p)
 {
-    int gglw = gc->gcv.line_width;
-
-    if (fill_p || gglw <= 1) {
-        draw_arc_gl (dpy, d, gc, x, y, width, height, angle1, angle2, fill_p);
-    }
-    else {
-        int w1, w2, h1, h2, gglwh;
-        w1 = width + gglw;
-        h1 = height + gglw;
-        h2 = height - gglw;
-        w2 = width - gglw;
-        gglwh = gglw / 2;
-        int x1 = x - gglwh;
-        int x2 = x + gglwh;
-        int y1 = y - gglwh;
-        int y2 = y + gglwh;
-        //draw_arc_gl (dpy, d, gc, x, y, width, height, angle1, angle2, fill_p);
-        draw_arc_gl (dpy, d, gc, x1, y1, w1, h1, angle1, angle2, fill_p);
-        draw_arc_gl (dpy, d, gc, x2, y2, w2, h2, angle1, angle2, fill_p);
-    }
-    return 0;
-}
-
-
-int
-draw_arc_gl (Display *dpy, Drawable d, GC gc, int x, int y,
-          unsigned int width, unsigned int height,
-          int angle1, int angle2, Bool fill_p)
-{
-  set_fg_gc(dpy, d, gc);
-
-  /* Let's say the number of line segments needed to make a convincing circle is
-     4*sqrt(radius). (But these arcs aren't necessarily circular arcs...) */
+  /* 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. */
+  GLfloat w2 = width * 0.5f, h2 = height * 0.5f;
+  GLfloat a, b; /* Semi-major/minor axes. */
   if(w2 > h2) {
     a = w2;
     b = h2;
@@ -1355,30 +1347,30 @@ draw_arc_gl (Display *dpy, Drawable d, GC gc, int x, int y,
     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));
+  const GLfloat tau = 2 * M_PI;
+
+  GLfloat amb = a - b, apb = a + b;
+  GLfloat h = (amb * amb) / (apb * apb);
+  GLfloat D_approx = apb * (1 + 3 * h / (10 + sqrtf(4 - 3 * h)));
+  // From Ramanujan, "Modular Equations and Approximations to π".
+  // double C_approx = D_approx * M_PI;
+  GLfloat segments_f = sqrtf(8 * D_approx);
 
   // 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;
+  GLfloat segment_angle = tau / segments_360;
 
   const unsigned deg64 = 360 * 64;
-  const double rad_from_deg64 = two_pi / deg64;
-  
+  const GLfloat rad_from_deg64 = tau / deg64;
+
   if (angle2 < 0) {
     angle1 += angle2;
     angle2 = -angle2;
@@ -1388,79 +1380,128 @@ draw_arc_gl (Display *dpy, Drawable d, GC gc, int x, int y,
 
   if (angle2 > deg64)
     angle2 = deg64; // TODO: Handle circles special.
-  
-  double
+
+  GLfloat
     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;
+  if (angle2_f > tau) // TODO: Move this up.
+    angle2_f = tau;
+
+  GLfloat segment0_angle_part = fmodf(angle1_f, segment_angle);
+
+  unsigned segment0 = ((angle1_f - segment0_angle_part) / segment_angle) + 1.5;
+
+  GLfloat angle_2r = angle2_f - segment0_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;
+  /* TODO: It would probably be better for vertices at the corners of the
+     elliptical sector/arc to be the intersection between a ray extending from
+     the ellipse center along one of the specified angles and one of the line
+     segments following the outline of the 360-degree ellipse, rather than
+     what it is now.
+   */
+
   if (fill_p) {
-    data_ptr[0] = cx;
-    data_ptr[1] = cy;
+    GLfloat *data = enqueue (dpy, d, gc, GL_TRIANGLE_STRIP, segments + 5,
+                             gc->gcv.foreground);
+    GLfloat *data_ptr = data;
+
+    unsigned segment1 = segment0 + segments / 2;
+    unsigned ds = segment1 - segment0 + 1;
+    unsigned ds2 = ds / 2;
+
+    if (ds & 1) {
+      arc_xy (data_ptr, cx, cy, w2, h2, (segment0 + ds2) * segment_angle);
+      data_ptr += 2;
+    }
+
+    unsigned s = ds2;
+    while (s) {
+      --s;
+      arc_xy (data_ptr, cx, cy, w2, h2, (segment0 + s) * segment_angle);
+      arc_xy (data_ptr + 2, cx, cy, w2, h2,
+              (segment1 - s) * segment_angle);
+      data_ptr += 4;
+    }
+
+    arc_xy (data_ptr, cx, cy, w2, h2, angle1_f);
+    data_ptr[2] = cx;
+    data_ptr[3] = cy;
+    data_ptr[4] = cx;
+    data_ptr[5] = cy;
+    arc_xy (data_ptr + 6, cx, cy, w2, h2, angle1_f + angle2_f);
+    data_ptr += 8;
+
+    unsigned segment2 = segment0 + segments;
+    ds = segment2 - segment1;
+    ds2 = ds / 2;
+
+    for (s = 0; s != ds2; ++s) {
+      arc_xy (data_ptr, cx, cy, w2, h2, (segment1 + s) * segment_angle);
+      arc_xy (data_ptr + 2, cx, cy, w2, h2,
+              (segment2 - s - 1) * segment_angle);
+      data_ptr += 4;
+    }
+
+    if (ds & 1) {
+      arc_xy (data_ptr, cx, cy, w2, h2, (segment1 + ds2) * segment_angle);
+      data_ptr += 2;
+    }
+
+    finish_triangle_strip (dpy, data);
+  } else if (!gc->gcv.line_width) {
+    set_fg_gc(dpy, d, gc);
+
+    GLfloat *data = malloc((segments + 2) * sizeof(GLfloat) * 2); // TODO: Check result.
+    GLfloat *data_ptr = data;
+
+    arc_xy (data_ptr, cx, cy, w2, h2, angle1_f);
     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);
+
+    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, (segment0 + s) * segment_angle);
+      data_ptr += 2;
+    }
+
+    arc_xy (data_ptr, cx, cy, w2, h2, angle1_f + angle2_f);
     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);
-  
-  vertex_pointer (dpy, GL_FLOAT, 0, data);
-  glDrawArrays (fill_p ? GL_TRIANGLE_FAN : GL_LINE_STRIP,
-                0,
-                (GLsizei)((data_ptr - data) / 2));
+    glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+    glEnableClientState (GL_VERTEX_ARRAY);
 
-  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;
+    vertex_pointer (dpy, GL_FLOAT, 0, data);
+    glDrawArrays (fill_p ? GL_TRIANGLE_FAN : GL_LINE_STRIP,
+                  0,
+                  (GLsizei)((data_ptr - data) / 2));
+
+    free(data);
+  } else {
+    GLfloat gglw = gc->gcv.line_width * 0.5f;
+
+    GLfloat *data = enqueue (dpy, d, gc, GL_TRIANGLE_STRIP, 2 * segments + 4,
+                             gc->gcv.foreground);
+    GLfloat *data_ptr = data;
+
+    arc_xy2 (data_ptr, cx, cy, w2, h2, angle1_f, gglw);
+    data_ptr += 4;
+
+    for (unsigned s = 0; s != segments; ++s) {
+      arc_xy2 (data_ptr, cx, cy, w2, h2, (segment0 + s) * segment_angle,
+               gglw);
+      data_ptr += 4;
+    }
+
+    arc_xy2 (data_ptr, cx, cy, w2, h2, angle1_f + angle2_f, gglw);
+    data_ptr += 4;
+
+    finish_triangle_strip (dpy, data);
   }
-  
-  glEnd ();
-#endif
-  
+
   return 0;
 }
 
index 6a38d2effdf9b70b0514d6edbd4a7877f1db36d2..f7560f727019da705e46c72f314fa0fb4da7c372 100644 (file)
@@ -165,6 +165,7 @@ extern void jwxyz_gl_copy_area_read_tex_image (Display *dpy,
                                                int dst_x, int dst_y);
 extern void jwxyz_gl_copy_area_write_tex_image (Display *dpy, GC gc,
                                                 int src_x, int src_y,
+                                                int src_depth,
                                                 unsigned int width,
                                                 unsigned int height,
                                                 int dst_x, int dst_y);
index 38a89efc387f0307f8e15b87fff8348000a4d00b..d785843a6afc548876e49cdb1720c17e96da2dbc 100644 (file)
@@ -1,4 +1,4 @@
-# Auto-generated: Tue Jul  9 20:31:29 PDT 2019
+# Auto-generated: Fri Mar 20 18:40:22 PDT 2020
 driver/demo-Gtk-conf.c
 driver/demo-Gtk.c
 driver/screensaver-properties.desktop.in
@@ -71,6 +71,7 @@ hacks/config/engine.xml
 hacks/config/epicycle.xml
 hacks/config/eruption.xml
 hacks/config/esper.xml
+hacks/config/etruscanvenus.xml
 hacks/config/euler2d.xml
 hacks/config/extrusion.xml
 hacks/config/fadeplot.xml
@@ -94,6 +95,7 @@ hacks/config/gears.xml
 hacks/config/geodesic.xml
 hacks/config/geodesicgears.xml
 hacks/config/gflux.xml
+hacks/config/gibson.xml
 hacks/config/glblur.xml
 hacks/config/glcells.xml
 hacks/config/gleidescope.xml
@@ -203,6 +205,7 @@ hacks/config/rotzoomer.xml
 hacks/config/rubik.xml
 hacks/config/rubikblocks.xml
 hacks/config/sballs.xml
+hacks/config/scooter.xml
 hacks/config/shadebobs.xml
 hacks/config/sierpinski.xml
 hacks/config/sierpinski3d.xml
index aee19eef993a96f46150276d6fbdc11dd346346f..39065252c9a936e10a0e6b766c9b5b77c3e0c443 100644 (file)
--- a/setup.com
+++ b/setup.com
@@ -92,6 +92,7 @@ $ ripples     :== $'mydir'ripples
 $ rocks                :== $'mydir'rocks
 $ rorschach    :== $'mydir'rorschach
 $ rotzoomer    :== $'mydir'rotzoomer
+$ scooter      :== $'mydir'scooter
 $ shadebobs    :== $'mydir'shadebobs
 $ sierpinski   :== $'mydir'sierpinski
 $ slidescreen  :== $'mydir'slidescreen
index b01396c2ec6f6e5651dfa3dded8005088187427e..7a20c663102f044bdb040415ade308c9d276d8d3 100644 (file)
@@ -1,2 +1,2 @@
 static const char screensaver_id[] =
-       "@(#)xscreensaver 5.43 (09-Jul-2019), by Jamie Zawinski (jwz@jwz.org)";
+       "@(#)xscreensaver 5.44 (20-Mar-2020), by Jamie Zawinski (jwz@jwz.org)";
index 3fc0527d6370563f166e34d3050c7cd6e706f131..84931b525873334c88f4a744148259be24adc63c 100644 (file)
@@ -1,5 +1,5 @@
 %define        name xscreensaver
-%define        version 5.43
+%define        version 5.44
 
 Summary:       X screen saver and locker
 Name:          %{name}